Linux driver-LED Drivers _ 1, linuxled_1
Steps:
1. Framework
2. complete hardware operations:
A. view the principle diagram and pins
B. Check the 2440 manual.
C. write code: ioremap is required for the IO port.
My board sub-circuit is as follows:
1,Configure GPBCON registersConfiguration output is configured in the open function.
2,Configure GPBDAT registersConfigure in the write function
######################################## #################################
Manual Information:
The physical address of the GPBCON register is 0x56000010.
The physical address of the GPBDAT register is 0x56000014.
######################################## #################################
1. Declare global variables first:
volatile unsigned long *gpbcon = NULL;volatile unsigned long *gpbdat = NULL;
2. Pin ing in the entry function
/* Ing physical address */gpbcon = (volatile unsigned long *) ioremap (0x5621310, 16); gpbdat = gpbcon + 1;
3. Cancel the ing in the exit function.
iounmap(gpbcon);
4. Set the pin to output in the open function.
/* Configure GPB 5 6 7 8 as the output */* gpbcon & = ~ (0x3 <(5*2) | (0x3 <(6*2) | (0x3 <(7*2 )) | (0x3 <(8*2); // first clears * gpbcon | = (0x1 <(5*2 )) | (0x1 <(6*2) | (0x1 <(7*2 )) | (0x1 <(8*2); // set it to 1 (output)
5. Simple processing of user space data in writing functions
Int val; copy_from_user (& val, buf, count); // copy data from the user space to the kernel space if (val = 1) {// click the light * gpbdat & = ~ (1 <5) | (1 <6) | (1 <7) | (1 <8 ));} else {// lamp removal * gpbdat | = (1 <5) | (1 <6) | (1 <7) | (1 <8 );}
The complete driver code is as follows:
# Include <linux/init. h> # include <linux/module. h> # include <linux/kernel. h> # include <linux/fs. h> # include <asm/io. h> # include <linux/cdev. h> # include <linux/device. h> # include <asm/uaccess. h> static struct class * firstdrv_class; static struct class_devices * handle; volatile unsigned long * gpbcon = NULL; volatile unsigned long * gpbdat = NULL; MODULE_LICENSE ("Dual BSD/GPL "); static int first_dev_open (Struct inode * inode, struct file * file) {/* configure GPB 5 6 7 8 as output */* gpbcon & = ~ (0x3 <(5*2) | (0x3 <(6*2) | (0x3 <(7*2 )) | (0x3 <(8*2); // first clears * gpbcon | = (0x1 <(5*2 )) | (0x1 <(6*2) | (0x1 <(7*2 )) | (0x1 <(8*2); // set to 1 (output) // printk ("first dev open \ n"); return 0 ;} static ssize_t first_dev_write (struct file * file, const char _ user * buf, size_t count, loff_t * ppos) {int val; copy_from_user (& val, buf, count ); // copy data from the user space to the kernel space if (val = 1) {// click the light * gpbdat & = ~ (1 <5) | (1 <6) | (1 <7) | (1 <8 ));} else {// lamp removal * gpbdat | = (1 <5) | (1 <6) | (1 <7) | (1 <8 );} // printk ("first dev write \ n"); return 0;} static struct file_operations first_sdv_fops = {. owner = THIS_MODULE ,. open = first_dev_open ,. write = first_dev_write,}; int major; int first_drv_init (void) {major = Queue (0, "first_drv", & role); // register firstdrv_class = class_create (THIS_MODULE, "first_drv"); if (IS_ERR (firstdrv_class) return response (firstdrv_class); then = device_create (firstdrv_class, NULL, MKDEV (major, 0), NULL, "wq_device "); if (unlikely (IS_ERR (random) return PTR_ERR (firstdrv_class_dev);/* ing physical address */gpbcon = (volatile unsigned long *) ioremap (0x561_10, 16 ); gpbdat = gpbcon + 1; // printk ("init major = % d \ n", major); return 0;} void first_dev_exit (void) {// printk ("exit \ n"); uninstall (major, "first_drv"); // uninstall device_unregister (firstdrv_class_dev); class_destroy (firstdrv_class); iounmap (gpbcon );} module_init (first_drv_init); module_exit (first_dev_exit );
The complete test code is as follows:
# Include <sys/types. h> # include <sys/stat. h> # include <fcntl. h> # include <stdio. h>/* wq_device on * wq_device off */int main (int argc, char ** argv) {int fd; int val = 1; fd = open ("/dev/wq_device", O_RDWR); if (fd <0) {printf ("can't open \ n");} if (argc! = 2) {printf ("Usage: \ n"); printf ("% s <on | off> \ n", argv [0]); return 0 ;} if (strcmp (argv [1], "on") = 0) {val = 1;} else {val = 0;} write (fd, & val, 4 ); return 0 ;}