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

发布时间:2023-09-05  

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" 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 }


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>