LED lamp driver tiny6410

Source: Internet
Author: User

This is an LED Driver Under tiny6410. In order to explain the details, do not paste the Code directly. The Code is available on the tiny6410 CD, and this article also posts the code at the end.

Motivation for writing: This is the first and simplest hardware driver, and the Development Board does not seem to have enough comments.

Knowledge points not involved: Driver basics and hybrid devices. If you do not understand them, check them yourself.

The driver only has 10 lines in short, and the annotations and analysis are more detailed.

/*

This code is in the source code ldev/Char of the tiny6410 disc, but I added comments and images for your convenience.

Reference: Samsung s36410 User Manual (Chinese version) download link: http://download.csdn.net/download/qq363692146/5077985

Tiny6410 Manual

Note:
C Xiong and netizens
*/

# Include <Linux/miscdevice. h>
# Include <Linux/delay. h>
# Include <ASM/IRQ. h>
// # Include <Mach/regs-gpio.h>
# Include <Mach/hardware. h>
# Include <Linux/kernel. h>
# Include <Linux/module. h>
# Include <Linux/init. h>
# Include <Linux/mm. h>
# Include <Linux/fs. h>
# Include <Linux/types. h>
# Include <Linux/delay. h>
# Include <Linux/moduleparam. h>
# Include <Linux/slab. h>
# Include <Linux/errno. h>
# Include <Linux/IOCTL. h>
# Include <Linux/cdev. h>
# Include <Linux/string. h>
# Include <Linux/list. h>
# Include <Linux/PCI. h>
# Include <ASM/uaccess. h>
# Include <ASM/Atomic. h>
# Include <ASM/unistd. h>
# Include <Mach/map. h>
# Include <Mach/regs-clock.h>
# Include <Mach/regs-gpio.h>
# Include <plat/gpio-cfg.h>
# Include <Mach/gpio-bank-e.h>
# Include <Mach/gpio-bank-k.h>

# Define device_name "LEDs"

Static long sbc2440_leds_ioctl (struct file * filp, unsigned int cmd, unsigned long Arg)
// CMD is 0 | 1, Arg is 1 ~ 4 (call method in your application: IOCTL (FD, on, led_no); FD is the driver file; on is 0 on or 1 off; led_no is 1 ~ 4 values represent led1 ~ Led4)
{
Switch (CMD ){
Unsigned TMP;
Case 0:
Case 1:
If (Arg> 4 ){
Return-einval;
}
TMP = readl (initi64xx_gpkdat); // read 32-bit data from the memory-mapped I/O space (initi64xx_gpkdat is an I/O address). The led belongs to gpk4 ~ 7, so use gpkdat to read

(The image is from tiny6410hardware album -20110805.pdf)

TMP & = ~ (1 <(4 + Arg); // If Arg = 3, get 01111111, Arg = 2, get 10111111, Arg = 1,11011111, Arg = 11101111 (low ), obviously, it means the one you control (in 4 ~ Between 7 digits), will change to 0
TMP | = ((! CMD) <(4 + Arg); // If CMD is 0, then the value of one digit is 1, otherwise it will not change (so in the user application, 0 indicates that this bit is 1, 1 indicates that this bit is 0)

(The image is from tiny6410hardware album -20110805.pdf)

I have learned a single-chip microcomputer or understand the possibility of this circuit. From this figure, we can see that when the arm6410 pin output 0 is bright, 1 is dark (but in the user program in turn)


Writel (TMP, initi64xx_gpkdat); // write 32-bit data to the I/O address
// Printk (device_name ": % d \ n", ARG, CMD );
Return 0;
Default:
Return-einval;
}
}

Static struct file_operations dev_fops = {
. Owner
= This_module,
. Unlocked_ioctl = sbc2440_leds_ioctl,
};

// MISC device: a special character device with a master device number of 10.
Static struct miscdevice MISC = {
// Number of sub-devices. do not conflict with the number of sub-devices in/proc/Misc.

// Misc_dynamic_minor
. Minor = misc_dynamic_minor,
// Device name
. Name = device_name,
. Fops = & dev_fops,
};

Static int _ init dev_init (void)
{
Int ret;

{
Unsigned TMP;
TMP = readl (89c64xx_gpkcon); // read data from the beginning, corresponding to gpkcon0 in the figure

/* Configure gpk4 to gpk7 in gpkcon0 to output 0001 */
TMP = (TMP &~ (0 xffffu <16) | (0x1111u <16 );//&~ (0 xffffu <16) = 0x0000ffff indicates to clear the GPXCON16-31, | 0x1111u <16 = 0x11110000 becomes to set four gpxcon as the output mode, binary 0001 indicates the output

// Assume that the original read TMP is 0x ???? XXXX will change to 0x1111xxxx now (change the height of 16 to 1111)

Why do we need to do this? This operation is readl (initi64xx_gpkcon), that is, gpkcon0. After the operation, the LED will be changed to the output status.

(The image is from the Chinese version of the user's manual)

You can see gpk4, gpk5, gpk6, and gpk7 (corresponding to 16 ~ 31 digits). Well, they are used to control the LEDs. If you don't know what they are, flip the picture up.

Writel (TMP, 89c64xx_gpkcon );

// Initialize the control register
TMP = readl (89c64xx_gpkdat );
TMP | = (0xf <4); // = 0xf0; 4 ~ 7-bit. It is initialization.
Writel (TMP, 89c64xx_gpkdat );
}

Ret = misc_register (& MISC); // apply for and create a Hybrid device driver File

Printk (device_name "\ tinitialized \ n ");

Return ret;
}

Static void _ exit dev_exit (void)
{
Misc_deregister (& MISC );
}

Module_init (dev_init );
Module_exit (dev_exit );
Module_license ("GPL ");
Module_author ("friendlyarm Inc. & C Bear (aiqqqqqqq@qq.com )");

Finally, I will post the source code to respect the friendly arm and the netizens:

Application:

#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/ioctl.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>int main(int argc, char **argv){int on;int led_no;int fd;if (argc != 3 || sscanf(argv[1], "%d", &led_no) != 1 || sscanf(argv[2],"%d", &on) != 1 ||on < 0 || on > 1 || led_no < 0 || led_no > 3) {fprintf(stderr, "Usage: leds led_no 0|1\n");exit(1);}fd = open("/dev/leds0", 0);if (fd < 0) {fd = open("/dev/leds", 0);}if (fd < 0) {perror("open device leds");exit(1);}ioctl(fd, on, led_no);close(fd);return 0;}

Driver:

#include <linux/miscdevice.h>#include <linux/delay.h>#include <asm/irq.h>//#include <mach/regs-gpio.h>#include <mach/hardware.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/init.h>#include <linux/mm.h>#include <linux/fs.h>#include <linux/types.h>#include <linux/delay.h>#include <linux/moduleparam.h>#include <linux/slab.h>#include <linux/errno.h>#include <linux/ioctl.h>#include <linux/cdev.h>#include <linux/string.h>#include <linux/list.h>#include <linux/pci.h>#include <asm/uaccess.h>#include <asm/atomic.h>#include <asm/unistd.h>#include <mach/map.h>#include <mach/regs-clock.h>#include <mach/regs-gpio.h>#include <plat/gpio-cfg.h>#include <mach/gpio-bank-e.h>#include <mach/gpio-bank-k.h>#define DEVICE_NAME "leds"static long sbc2440_leds_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){switch(cmd) {unsigned tmp;case 0:case 1:if (arg > 4) {return -EINVAL;}tmp = readl(S3C64XX_GPKDAT);tmp &= ~(1 << (4 + arg));tmp |= ( (!cmd) << (4 + arg) );writel(tmp, S3C64XX_GPKDAT);//printk (DEVICE_NAME": %d %d\n", arg, cmd);return 0;default:return -EINVAL;}}static struct file_operations dev_fops = {.owner= THIS_MODULE,.unlocked_ioctl= sbc2440_leds_ioctl,};static struct miscdevice misc = {.minor = MISC_DYNAMIC_MINOR,.name = DEVICE_NAME,.fops = &dev_fops,};static int __init dev_init(void){int ret;{unsigned tmp;tmp = readl(S3C64XX_GPKCON);tmp = (tmp & ~(0xffffU<<16))|(0x1111U<<16);writel(tmp, S3C64XX_GPKCON);tmp = readl(S3C64XX_GPKDAT);tmp |= (0xF << 4);writel(tmp, S3C64XX_GPKDAT);}ret = misc_register(&misc);printk (DEVICE_NAME"\tinitialized\n");return ret;}static void __exit dev_exit(void){misc_deregister(&misc);}module_init(dev_init);module_exit(dev_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("FriendlyARM Inc.");

Annotated driver code

/* Yjx: the code is stored in the source file DEV/char */# include <Linux/miscdevice. h> # include <Linux/delay. h> # include <ASM/IRQ. h> // # include <Mach/regs-gpio.h> # include <Mach/hardware. h> # include <Linux/kernel. h> # include <Linux/module. h> # include <Linux/init. h> # include <Linux/mm. h> # include <Linux/Fs. h> # include <Linux/types. h> # include <Linux/delay. h> # include <Linux/moduleparam. h> # include <Linux/slab. h> # include <Linux/errno. h> # inclu De <Linux/IOCTL. h> # include <Linux/cdev. h> # include <Linux/string. h> # include <Linux/list. h> # include <Linux/PCI. h> # include <ASM/uaccess. h> # include <ASM/atomic. h> # include <ASM/unistd. h> # include <Mach/map. h> # include <Mach/regs-clock.h> # include <Mach/regs-gpio.h> # include <plat/gpio-cfg.h> # include <Mach/gpio-bank-e.h> # include <Mach/gpio-bank-k.h> # define device_name "LEDs" static long sbc2440_leds_ioctl (St Ruct file * filp, unsigned int cmd, unsigned long Arg) // CMD is 0 | 1, Arg is 0 ~ 3 {Switch (CMD) {unsigned TMP; Case 0: Case 1: If (Arg> 4) {return-einval;} TMP = readl (89c64xx_gpkdat ); // read 32-bit data from the memory-mapped I/O space (with an I/O address as the gpk_gpkdat). The led belongs to gpk4 ~ 7 TMP & = ~ (1 <(4 + Arg); // If Arg = 3, get 01111111, Arg = 2, get 10111111, Arg = 1,11011111, Arg = 11101111 (low) TMP | = ((! CMD) <(4 + Arg); // Arg = 3, writel (TMP, 89c64xx_gpkdat ); // write 32-bit data to the I/O address // printk (device_name ": % d \ n", ARG, CMD); Return 0; default: return-einval ;}} static struct file_operations dev_fops = {. owner = this_module ,. unlocked_ioctl = sbc2440_leds_ioctl,}; // MISC device: Miscellaneous device, static struct miscdevice MISC = {// device No, do not conflict with the number of sub-devices that already exist in/proc/MISC/// misc_dynamic_minor to dynamically obtain the device number. minor = misc_dynam Ic_minor, // device name. name = device_name ,. foPs = & dev_fops,}; static int _ init dev_init (void) {int ret; {unsigned TMP; TMP = readl (s364xx_gpkcon); // read data from the beginning, configure gpk4 to gpk7 in the corresponding figure gpkcon0/* gpkcon0 to 0001 output */tmp = (TMP &~ (0 xffffu <16) | (0x1111u <16 );//&~ (0 xffffu <16) = 0x0000ffff indicates to clear the GPXCON16-31, | 0x1111u <16 = 0x11110000 becomes to set four gpxcon as the output mode, binary 0001 indicates the output writel (TMP, 89c64xx_gpkcon); // initialization control register TMP = readl (89c64xx_gpkdat); TMP |=( 0xf <4); // = 0xf0 4 ~ 7-bit writel (TMP, initi64xx_gpkdat);} ret = misc_register (& MISC); // apply for and create the printk (device_name "\ tinitialized \ n") driver file of the Hybrid device "); return ret;} static void _ exit dev_exit (void) {misc_deregister (& MISC);} module_init (dev_init); module_exit (dev_exit); module_license ("GPL "); module_author ("friendlyarm Inc. & C Bear (aiqqqqqqq@qq.com )");

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.