★ Overall Introduction
LED driver mainly realizes the hardware drive of 4 LED lights on the TQ2440 Development Board, realizes the Pin GPIOB5, GPIOB6, GPIOB7, The high and low level setting of the GPIOB8 (the configuration of the PIN is already implemented in the COMMON-SMDK.C), the driver is called by the test program, and the LED light is illuminated by command.
★ Specific Introduction 1, Driver code: MY_LED.C
#include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/init.h > #include <linux/delay.h> #include <asm/irq.h> #include <mach/regs-gpio.h> #include <mach/ hardware.h> #include <linux/device.h> #define DEVICE_NAME "my_led"/** the device name you see in cat/proc/devices after loading the module **/# Define LED_MAJOR 103/** main device number **/#define LED_ON 1#define led_off 0/**led control pin **/static Unsigne D Long led_table[] ={s3c2410_gpb5, s3c2410_gpb6,s3c2410_gpb7,s3c2410_gpb8,};static int my_led_open (struct inode *i Node,struct file *file) {PRINTK ("my_led open\n"); return 0;} static int My_led_ioctl (struct inode * inode, struct file * file,unsigned int cmd,unsigned long arg) {if (Arg > 4) {return -1; }switch (cmd) {case Led_on:s3c2410_gpio_setpin (Led_table[arg], 0);//Set the specified PIN to the output level of 0 return 0; Case Led_off:s3c2410_gpio_setpin (Led_table[arg], 1);//Set the specified PIN to the output level of 1 return 0; default:return-1;}} static struct file_operations my_led_fops ={.owner = This_module,.open = My_led_open,.ioctl = My_led_ioctl,};static Struc T class *led_class;static int __init my_led_init (void) {int ret;printk ("my_led start\n"),/** register character device driver **//** number of references to the main device number, Device name, file_operations structure **//** so the main device number is associated with file_operations **/ret = Register_chrdev (Led_major, Device_name, &my_ Led_fops); if (Ret < 0) {PRINTK ("can ' t register major number\n"); return ret;} Register a class. Enables Mdev to establish device nodes under the/dev/folder Led_class = Class_create (This_module, Device_name), if (Is_err (Led_class)) {PRINTK ("failed In my_led class.\n "); return-1;} Device_create (Led_class, NULL, MKDEV (led_major,0), NULL, device_name);p rintk (device_name "initialized\n"); return 0;} static void __exit my_led_exit (void) {Unregister_chrdev (led_major, device_name); Device_destroy (Led_class, MKDEV (led_major,0));//Unregister the device node Class_destroy (led_class);//Unregister Class}module_init (My_led_init); Module_exit (My_led_exit); Module_license ("GPL");
2. Macro definition
#define DEVICE_NAME "my_led"//Load module to run the device name seen in Cat/proc/devices
#define LED_MAJOR 103//main device number
#define LED_ON 1
#define Led_off 0 My_led_ioctl function to enter the parameters of the command, LED_ON will run the command to turn on the lights, Led_off run off the lights command
3, LED lamp pin control
Defines a led_table[] array. It is more convenient to call later.
Specify what S3C2410_GPB5 means:
As you can see. It's all about S3C2410_GPB5-related code.
The above code can conclude that S3C2410_GPB5 is 37. Actually S3C2410_GPB5 is the number of the port. Bank is the base number of the grouping, offset is the amount of offsets within the group.
The value of this calculated S3c2410_gpb5 is 37, and his role is to represent the fifth pin of the B-group port in s3c2440.
4. My_led_ioctl () function
This function is primarily responsible for responding to commands related to the application. Then run the relevant code according to the command. The cmd command contains the led_on, Led_off, and macro definitions.
S3c2410_gpio_setpin () function
I think this is the most important function of this driver, its function is: set the specified pin to low or high level.
This driver only uses the interface provided by the kernel to achieve the control of the pin. Now let's analyze this function.
◇ Function of functions
This function is to set the high and low levels of the pins in the s3c2440.
Its first parameter is some of the macros in the Linux system about PIN definitions. For example, S3C2410_GPB5, S3C2410_GPB6, etc. represent the port pin of the chip, and one of the parameters is a value to. This value represents 0 or 1.
◇ This function is how to set the high and low level
The definition of this function is first posted in the kernel version number LINUX2.6.30.4/ARCH/ARM/PLAT-S3C24XX/GPIO.C
void S3c2410_gpio_setpin (unsigned int pin, unsigned int to) {void __iomem *base = S3c24xx_gpio_base (PIN); unsigned long offs = S3c2410_gpio_offset (PIN); unsigned long flags;unsigned long dat;local_irq_save (flags);d at = __raw_readl (base + 0x04); DAT &= ~ (1 << offs);d at |= to << offs;__raw_writel (DAT, base + 0x04); Local_irq_restore (flags);}
The first function s3c24xx_gpio_base (PIN) is analyzed first
5, the registration of a class
Assuming this class is not registered, one thing to do after mounting the driver on the board is to manually "generate the device node". is to use the Mknod command. However, the driver starts with the execution of the operating system, so build the device node to make it self-generated. Instead of manually. That's why we're going to register such a class, after the driver is mounted, the device node is generated on its own initiative. The core code of the brochure class:
Led_class = Class_create (This_module, Device_name), if (Is_err (Led_class)) {PRINTK ("failed in my_led class.\n"), Return- 1;} Device_create (Led_class, NULL, MKDEV (led_major,0), NULL, device_name);
6. Test procedure
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #in Clude <sys/stat.h> #include <fcntl.h> int main () {int fd,i,cmd; Fd=open ("/dev/my_led", 0); if (fd<0) {printf ("Open led_driver error"); Exit (1); } while (1) {scanf ("%d", &cmd); Switch (CMD) {case 0:printf ("All off\n"); for (i = 0;i < 4;i + +) IOCTL (fd,0,i); Break;case 1:printf ("Light First led\n"); IOCTL (fd,1,0); Break;case 2:printf ("Light Second led\n"); IOCTL (fd,0,0); IOCTL (fd,1,1); Break;case 3:printf ("Light third led\n"); IOCTL (fd,0,1); IOCTL (fd,1,2); Break;case 4:printf ("Light Fourth led\n"); IOCTL (fd,0,2); IOCTL (fd,1,3); Break;case 5:printf ("All light \ n"); for (i = 0;i < 4;i + +) IOCTL (fd,1,i); BREAK;DEFAULT:I = 10; Break; } if (i = = ten) break; } return 0; }
★ Errors encountered
1. File not Found
The main reason for this error is that the kernel has a different version number. The path of the header files of different kernels is not the same. Therefore, when compiling the driver error "File not found", check the path of the header file is correct
2. Makefile file specifies cross compiler
The following is a makefile file for the driver
#LED_makefileKERNELDIR: =/home/xg/linux_arm/linux-2.6.30.4/pwd: =$ (Shell PWD) all:make-c $ (kerneldir) m=$ (PWD) Modules Arch=arm cross_compile=/opt/opt/embedsky/4.3.3/bin/arm-linux-test:/opt/opt/embedsky/4.3.3/bin/ Arm-linux-gcc-o Test TEST.CCLEAN:RM-RF *.o *koobj-m: =MY_LED.O
The error was that the path of the compiler was not clear.
"Linux driver" TQ2440 led driver