linux内核驱动 第一个led的 程序思想过程

linux 内核写led的驱动如图所示:

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 <linux/module.h>
  2 #include <linux/kernel.h>
  3 #include <linux/fs.h>
  4 #include <linux/init.h>
  5 #include <linux/delay.h>
  6 #include <asm/uaccess.h>
  7 #include <asm/irq.h>
  8 #include <asm/io.h>
  9 #include <asm/arch/regs-gpio.h>
 10 #include <asm/hardware.h>
 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_open\r\n");
 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_write\r\n");
 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 <sys/types.h>
 2 #include <sys/stat.h>
 3 #include <fcntl.h>
 4 #include <stdio.h>
 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" <on|off>\n"); 
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 }

 

linux内核驱动 第一个led的 程序思想过程

上一篇:Linux命令行操作——使用Shell命令


下一篇:给Linux小白的CentOS8.1基本安装说明