嵌入式linux/鸿蒙开发板(IMX6ULL)开发(二十五)最简单的LED驱动程序 ...

打印 上一主题 下一主题

主题 652|帖子 652|积分 1956

文章目录



怎么根据芯片手册去写一个点亮led驱动程序。
1.写LED驱动程序

1.1第一步 先看原理图


1.2第二步 再看芯片手册:使能GPIO


1.3 第三步 设置引脚是GPIO功能


1.4 第四步 设置引脚是输出


1.5 第五步 设置输出电平


2.最简单的LED驱动程序

后面的LED驱动程序为了容易扩展,引入了很多数据结构。对C语言的要求有点高,所以我们基于Hello驱动程序先写出最简单的LED驱动程序。
2A.1 LED操作方法_基于IMX6ULL

视频中的文档,放在GIT仓库中:
  1. 01_all_series_quickstart\
  2. 05_嵌入式Linux驱动开发基础知识\doc_pic\pic\6A.最简单的LED驱动程序\
  3.     03_IMX6ULL的LED操作方法.pptx
复制代码
2A.2 最简单的LED驱动程序编程_基于IMX6ULL

视频中的源码文档,放在GIT仓库中:
  1. 01_all_series_quickstart\
  2. 05_嵌入式Linux驱动开发基础知识\source\
  3.     02_led_drv\
  4. 00_led_simple\imx6ull
复制代码
2A.2.1 字符设备驱动程序框架

   字符设备驱动程序的框架:
  
   编写驱动程序的套路:
① 确定主设备号,也可以让内核分配
② 定义自己的file_operations结构体
③实现对应的drv_open/drv_read/drv_write等函数,填入file_operations结构体
④把file_operations结构体告诉内核:register_chrdev
⑤谁来注册驱动程序啊?得有一个入口函数:安装驱动程序时,就会去调用这个入口函数
⑥有入口函数就应该有出口函数:卸载驱动程序时,出口函数调用unregister_chrdev
⑦其他完善:提供设备信息,自动创建设备节点:class_create, device_create
    驱动怎么操作硬件?通过ioremap映射寄存器的物理地址得到虚拟地址,读写虚拟地址。
驱动怎么和APP传输数据?通过copy_to_user、copy_from_user这2个函数。
  下面就是写驱动程序的模板!!
  1. ********************************************************
  2. //这个是驱动程序的框架,以后可以直接套用,在上面添加和修改
  3. #include <linux/kernel.h>
  4. #include <linux/module.h>
  5. #include <linux/slab.h>
  6. #include <linux/init.h>
  7. #include <linux/fs.h>
  8. #include <linux/delay.h>
  9. #include <linux/poll.h>
  10. #include <linux/mutex.h>
  11. #include <linux/wait.h>
  12. #include <linux/uaccess.h>
  13. #include <asm/io.h>
  14. /*定义主设备号*/
  15. static struct major;
  16. /*定义led class类*/
  17. static struct class *led_class;
  18. /*结构体中led_open函数*/
  19. static int led_open(struct inode *inode, struct file *file)
  20. {
  21.         /*
  22.         *enable gpio
  23.         *configure pin as gpio
  24.         *configure gpio as output
  25.         */
  26.         return 0;
  27. }
  28. /*结构体中led_write函数*/       
  29. static ssize_t led_write(struct file *file ,const char __user * buf, size_t count, loff_t *ppos)
  30. {
  31.         char val;//val来自内核定义
  32.         /*copy_from_user:get data from app,会涉及到寄存器,那么涉及到物理层,需要用到虚拟地址*/
  33.         copy_from_user(&val, buf, 1);//把app(buf)中的数据拷贝至内核空间(val),拷贝一个字节。
  34.        
  35.         /*to set gpio register :out 1/0,会涉及到寄存器,那么涉及到物理层,需要用到虚拟地址*/
  36.         if(val)
  37.         {
  38.                 /*set gpio to let led on */       
  39.         }
  40.         else
  41.         {
  42.                 /*set gpio to let led off */       
  43.         }
  44.         return 0;
  45. }
  46. /*定义结构体*/
  47. static struct file_operations led_fops ={
  48.         .owner = THIS_MODULE,
  49.     .open = led_open,
  50.         .write = led_write,
  51. };
  52.        
  53. /*入口函数*/
  54. static int __init  led_init(void)
  55. {
  56.         printk("%s %s %d \n",_File_,_FUNCTION_,_LINE_);
  57.         major=register_chrdev(0, "100ask_led", &led_fops);//unsigned int major;设置为0.const char * name设置为“100ask_led”
  58.         /*ioremap*/
  59.         led_class=class_create(THIS_MODULE, "myled");//这个变量的结构体名字被称为class,给这个模块创造一个名字为class类的结构。
  60.         device_create(led_class, NULL, MKDEV(major, 0),NULL, "myled");/**设备就会给我们创建一个/dev/myled设备结点。*/
  61.        
  62.         return 0;       
  63. }
  64. /*出口函数*/
  65. static void  led_exit(void)
  66. {
  67.         device_destroy(led_class, NULL);
  68.         class_destroy(led_class);
  69.         unregister_chrdev(major,"100ask_led" )
  70. }
  71. /*完善入口函数*/
  72. module_init(led_init);
  73. /*完善出口函数*/
  74. module_exit(led_init);
  75. /*设置为GPL协议*/
  76. MODULE_LICENSE("GPL");//指定GPL协议
复制代码
2A.2.2 实现什么功能

   先编写驱动程序:
实现led_open函数,在里面初始化LED引脚。 实现led_write函数,在里面根据APP传来的值控制LED。
  [code]#include #include #include #include #include #include #include #include #include #include #include /*定义主设备号*/static struct major; /*定义led class类*/static struct class *led_class;/*registers*/// IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3地址:0x02290000 + 0x14static volatile unsigned int*IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3;// GPIO5_GDIR地址:0x020AC004static volatile unsigned int*GPIO5_GDIR;//GPIO5_DR地址:0x020AC000static volatile unsigned int*GPIO5_DR;/*结构体中led_open函数*/static int led_open(struct inode *inode, struct file *file) {        /*        *enable gpio        *configure gpio5_3 as gpio        *configure gpio5_3 as output        */        //把引脚配置成gpio        *IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 &= ~0xf;        *IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 |= ~0x05;        //把引脚配置成输出        *GPIO5_GDIR |=(1

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

卖不甜枣

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表