linux 内核写led的驱动如图所示:
按照图 的方式我们发现我们需要写两个部分 一个是APP,一个是底层的驱动。其中APP是通过C库和系统层最后调用到底层的驱动的。
linux系统首先会把底层驱动以文件的形式挂载到dev文件夹内,然后APP利用文件写或者读的方式对底层的代码进行操作。
所以程序会分为两部分1. 写驱动并且挂载到linux内核2. 写APP程序去按照文件的方式调用linux挂载的内核。
1. 首先是写驱动的程序。
主要的程序有:
static int first_drv_open(struct inode *inode, struct file *file)
这个是led初始化的函数 其中函数名字可以随便起 但是参数要按照 static struct file_operations first_drv_fops 里面的参数去做写。
static ssize_t first_drv_write(struct file *file, const char __user *buf, size_t count, loff_t* ppos)
这个函数是led的写状态函数, 其中函数的名字可以随便起 但是参数要按照 static struct file_operations first_drv_fops 里面的参数去做写。
static struct file_operations first_drv_fops
这个是linux内核里面的结构体,我们app驱动都是以文件的形式读写,所以我们写的驱动最后必须挂载到这些结构体上面。
int first_drv_init(void)
这个函数里面 major = register_chrdev(0, "first_drv", &first_drv_fops); 是让系统自己去给驱动分配一个设备号,
firstdrv_class = class_create(THIS_MODULE, "firstdrv"); 建立一个led驱动的类
firstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz");
利用上面建立的类我们建立一个驱动 这个驱动将会返回一个驱动设备号。
module_init(first_drv_init);这个函数我们把led初始化驱动注册到内核里面
module_exit(first_drv_exit); 把led从内核中去除。
first_drv_exit 取消注册
1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include 10 #include 11 12 static struct class *firstdrv_class; 13 static struct class_device *firstdrv_class_dev; 14 15 volatile unsigned long *gpfcon = NULL; 16 volatile unsigned long *gpfdat = NULL; 17 18 static int first_drv_open(struct inode *inode, struct file *file) 19 { 20 // printk("first_drv_openrn"); 21 /* ÅäÖÃGPF4,5,6 ΪÊä³ö*/ 22 *gpfcon &= ~((0x3 << (4*2)) | (0x3 << (6*2)) | (0x03 << (5*2))); 23 *gpfcon |= ((0x1 << (4*2)) | (0x1 << (6*2)) | (0x01 << (5*2))); 24 return 0; 25 26 } 27 static ssize_t first_drv_write(struct file *file, const char __user *buf, size_t count, loff_t* ppos) 28 { 29 // printk("first_drv_writern"); 30 int val ; 31 copy_from_user(&val, buf, count); //from user to kernel 32 33 // copy_to_user from kernel to app 34 if(val == 1) 35 { 36 *gpfdat |= (1<<4) | (1<<5) | (1<<6); 37 38 } 39 else 40 { 41 42 *gpfdat &= ~((1<<4) | (1<<5) | (1 << 6)); 43 44 } 45 46 47 return 0; 48 } 49 50 static struct file_operations first_drv_fops = { //¶¨ÒåÒ»¸öfile operation ½Ó¿Ú 51 52 .owner = THIS_MODULE, 53 .open = first_drv_open, 54 .write = first_drv_write, 55 56 57 }; 58 59 int major = 0; 60 int first_drv_init(void) //Èë¿Úº¯Êý 61 { 62 major = register_chrdev(0, "first_drv", &first_drv_fops);//×¢²áÇý¶¯³ÌÐò 63 //major ÊÇÖ÷É豸ºÅ 64 firstdrv_class = class_create(THIS_MODULE, "firstdrv"); //create a class of first drive 65 66 gpfcon = (volatile unsigned long *)ioremap(0x56000050, 16); 67 68 gpfdat = gpfcon + 1; //ÕâÀïµØÖ·ÊÇ+4 µÄ ÒòΪÎÒÃÇÿһ´Î¶ÁÈ¡µÄÊÇ4¸ö×Ö½Ú© 69 //unsigned long ÊÇ4¸ö×Ö½Ú 70 71 if(IS_ERR(firstdrv_class)) 72 return PTR_ERR(firstdrv_class); 73 74 //and create a new device according to the new class eshtablished above 75 firstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz"); 76 return 0; 77 } 78 79 //ÐÞÊÎÈë¿Úº¯Êý 80 module_init(first_drv_init); //Äں˻áµ÷ÓÃÕâ¸ö½á¹¹Ìå 81 82 //³ö¿Úº¯Êý 83 84 int first_drv_exit(void) //Èë¿Úº¯Êý 85 { 86 unregister_chrdev(major , "first_drv");//×¢²áÇý¶¯³ÌÐò 87 //major ÊÇÖ÷É豸ºÅ 88 class_device_unregister(firstdrv_class_dev); //dismount the dev from kernel 89 class_destroy(firstdrv_class); //remove registed class 90 iounmap(gpfcon); 91 return 0; 92 } 93 94 module_exit(first_drv_exit); 95 96 97 98 /*the code below discribe some info for kernel not necessary but can fix some bugs*/ 99 MODULE_AUTHOR("WWW.GOOGLE.COM"); 100 MODULE_VERSION("v1.0"); 101 MODULE_DESCRIPTION("FIRST DRIVER TEST CODE"); 102 MODULE_LICENSE("GPL"); //MUST BE INCLUDED 2. 第二部分是APP我们这里的APP是很简短的 现在仅供测试: 1 #include 2 #include 3 #include 4 #include 5 6 int main(int argc, char** argv) 7 { 8 int fd; 9 int val = 1; 10 fd = open("/dev/xyz", O_RDWR); 11 if(argc != 2) 12 { 13 printf("Usage : n"); 14 printf("%s" 15 16 } 17 18 if(fd < 0) 19 printf("can't open!n"); 20 if(strcmp(argv[1], "on") == 0) 21 val = 1; 22 else 23 val = 0; 24 25 write(fd, &val, 4); 26 return 0; 27 28 }