• 驱动开发LED灯绑定设备文件


    头文件

    1. #ifndef __HEAD_H__
    2. #define __HEAD_H__
    3. typedef struct
    4. {
    5. unsigned int MODER;
    6. unsigned int OTYPER;
    7. unsigned int OSPEEDR;
    8. unsigned int PUPDR;
    9. unsigned int IDR;
    10. unsigned int ODR;
    11. }gpio_t;
    12. #define PHY_LED1_ADDR 0x50006000
    13. #define PHY_LED2_ADDR 0x50007000
    14. #define PHY_LED3_ADDR 0x50006000
    15. #define PHY_RCC_ADDR 0x50000A28
    16. #define LED_ON _IOW('l',1,int)
    17. #define LED_OFF _IOW('l',0,int)
    18. #endif

    应用程序

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include "head.h"
    10. int main(int argc,char const *argv[])
    11. {
    12. char buf[128]={0};
    13. int a,b;
    14. int fd=open("/dev/demo0",O_RDWR);
    15. if(fd<0)
    16. {
    17. printf("打开设备文件失败\n");
    18. exit(-1);
    19. }
    20. while(1)
    21. {
    22. //从终端读取
    23. printf("请输入要实现的功能 ");
    24. printf("0(关灯) 1(开灯)\n");
    25. printf("请输入>");
    26. scanf("%d",&a);
    27. printf("请选择要控制的灯:1(LED1)2(LED2) 3(LED3)\n");
    28. printf("请输入>");
    29. scanf("%d",&b);
    30. switch(a)
    31. {
    32. case 1:
    33. ioctl(fd,LED_ON,&b);
    34. break;
    35. case 0:
    36. ioctl(fd,LED_OFF,&b);
    37. break;
    38. }
    39. }
    40. close(fd);
    41. return 0;
    42. }

    驱动程序

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include "head.h"
    10. unsigned int major=0;
    11. unsigned int minor=0;
    12. char kbuf[128]={};
    13. gpio_t *vir_led1;
    14. gpio_t *vir_led2;
    15. gpio_t *vir_led3;
    16. unsigned int *vir_rcc;
    17. struct cdev *cdev;
    18. dev_t devno;
    19. struct class *cls;
    20. struct device *dev;
    21. int mycdev_open(struct inode *inode, struct file *file)
    22. {
    23. int min=MINOR(inode->i_rdev);
    24. file->private_data=(void *)min;
    25. printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    26. return 0;
    27. }
    28. long mycdev_ioctl(struct file *file,unsigned int cmd,unsigned long arg)
    29. {
    30. int min=(int)file->private_data;
    31. switch (min)
    32. {
    33. case 0: // 操作LED1
    34. switch (cmd)
    35. {
    36. case LED_ON: //开灯
    37. vir_led1->ODR |= (0x1<<10);
    38. break;
    39. case LED_OFF://关灯
    40. vir_led1->ODR &= (~(0x1<<10));
    41. break;
    42. }
    43. break;
    44. case 1: // 操作LED2
    45. switch (cmd)
    46. {
    47. case LED_ON: //开灯
    48. vir_led2->ODR |= (0x1<<10);
    49. break;
    50. case LED_OFF://关灯
    51. vir_led2->ODR &= (~(0x1<<10));
    52. break;
    53. }
    54. break;
    55. case 2: // 操作LED3
    56. switch (cmd)
    57. {
    58. case LED_ON: //开灯
    59. vir_led3->ODR |= (0x1<<8);
    60. break;
    61. case LED_OFF://关灯
    62. vir_led3->ODR &= (~(0x1<<8));
    63. break;
    64. }
    65. break;
    66. }
    67. printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    68. return 0;
    69. }
    70. int mycdev_close(struct inode *inode, struct file *file)
    71. {
    72. printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    73. return 0;
    74. }
    75. struct file_operations fops =
    76. {
    77. .open=mycdev_open,
    78. .unlocked_ioctl=mycdev_ioctl,
    79. .release=mycdev_close,
    80. };
    81. int all_led_init(void)
    82. {
    83. //寄存器地址的映射
    84. vir_led1=ioremap(PHY_LED1_ADDR,sizeof(gpio_t));
    85. if(vir_led1==NULL)
    86. {
    87. printk("ioremap filed:%d\n",__LINE__);
    88. return -ENOMEM;
    89. }
    90. vir_led2=ioremap(PHY_LED2_ADDR,sizeof(gpio_t));
    91. if(vir_led2==NULL)
    92. {
    93. printk("ioremap filed:%d\n",__LINE__);
    94. return -ENOMEM;
    95. }
    96. vir_led3=vir_led1;
    97. vir_rcc=ioremap(PHY_RCC_ADDR,4);
    98. if(vir_rcc==NULL)
    99. {
    100. printk("ioremap filed:%d\n",__LINE__);
    101. return -ENOMEM;
    102. }
    103. printk("物理地址映射成功\n");
    104. //寄存器的初始化
    105. //rcc
    106. (*vir_rcc) |= (3<<4);
    107. //led1
    108. vir_led1->MODER &= (~(3<<20));
    109. vir_led1->MODER |= (1<<20);
    110. vir_led1->ODR &= (~(1<<10));
    111. //led2
    112. vir_led2->MODER &= (~(3<<20));
    113. vir_led2->MODER |= (1<<20);
    114. vir_led2->ODR &= (~(1<<10));
    115. //led3
    116. vir_led3->MODER &= (~(3<<16));
    117. vir_led1->MODER |= (1<<16);
    118. vir_led1->ODR &= (~(1<<8));
    119. printk("寄存器初始化成功\n");
    120. return 0;
    121. }
    122. static int __init mycdev_init(void)
    123. {
    124. //1.申请一个对象空间cdev_alloc
    125. int ret;
    126. cdev= cdev_alloc();
    127. if(cdev==NULL)
    128. {
    129. printk("申请字符设备驱动对象失败\n");
    130. ret=-EFAULT;
    131. goto out1;
    132. }
    133. printk("字符设备驱动对象申请成功\n");
    134. //2.初始化对象cdev_init
    135. cdev_init(cdev,&fops);
    136. //3.申请设备号 register_chrdev_region()/alloc_chrdev_region()
    137. if(major==0)//动态申请
    138. {
    139. ret=alloc_chrdev_region(&devno,minor,3,"demo");
    140. if(ret)
    141. {
    142. printk("动态申请设备号失败\n");
    143. goto out2;
    144. }
    145. major=MAJOR(devno);//根据设备号获取主设备号
    146. minor=MINOR(devno);//根据设备号获取次设备号
    147. }
    148. else
    149. {
    150. ret=register_chrdev_region(MKDEV(major,minor),3,"demo");
    151. if(ret)
    152. {
    153. printk("静态指定设备号失败\n");
    154. goto out2;
    155. }
    156. }
    157. printk("设备号申请成功\n");
    158. //4.注册驱动对象 cdev_add
    159. ret=cdev_add(cdev,MKDEV(major,minor),3);
    160. if(ret)
    161. {
    162. printk("注册字符设备驱动对象失败\n");
    163. goto out3;
    164. }
    165. printk("注册字符设备驱动对象成功\n");
    166. //5.向上提交目录 class_create
    167. cls=class_create(THIS_MODULE,"demo");
    168. if(IS_ERR(cls))
    169. {
    170. printk("向上提交目录失败\n");
    171. goto out4;
    172. }
    173. printk("向上提交目录成功\n");
    174. //6.向上提交设备节点信息 device_create
    175. int i;
    176. for(i=0;i<3;i++)
    177. {
    178. dev=device_create(cls,NULL,MKDEV(major,i),NULL,"demo%d",i);
    179. if(IS_ERR(dev))
    180. {
    181. printk("向上提交设备节点失败\n");
    182. goto out5;
    183. }
    184. }
    185. printk("向上提交设备节点信息成功\n");
    186. all_led_init();
    187. return 0;
    188. out5:
    189. //将提交成功的节点信息释放
    190. for(--i;i>=0;i--)
    191. {
    192. device_destroy(cls,MKDEV(major,i));
    193. }
    194. //销毁目录
    195. class_destroy(cls);
    196. out4:
    197. cdev_del(cdev);
    198. out3:
    199. unregister_chrdev_region(MKDEV(major,minor),3);
    200. out2:
    201. kfree(cdev);
    202. out1:
    203. return ret;
    204. }
    205. static void __exit mycdev_exit(void)
    206. {
    207. iounmap(vir_led1);
    208. iounmap(vir_led2);
    209. iounmap(vir_rcc);
    210. //1.销毁设备节点信息
    211. int i;
    212. for(i=0;i<3;i++)
    213. {
    214. device_destroy(cls,MKDEV(major,i));
    215. }
    216. //2.销毁目录
    217. class_destroy(cls);
    218. //3.注销字符设备驱动对象
    219. cdev_del(cdev);
    220. //4.释放设备号
    221. unregister_chrdev_region(MKDEV(major,minor),3);
    222. //5.释放申请到的字符设备驱动对象空间
    223. kfree(cdev);
    224. }
    225. module_init(mycdev_init);
    226. module_exit(mycdev_exit);
    227. MODULE_LICENSE("GPL");

  • 相关阅读:
    设计海报,这7个工具网站就够了!
    [附源码]计算机毕业设计JAVA音乐交流平台
    基因检测,如何帮助患者对抗疾病?
    Spring Cloud Gateway3.x自定义Spring Cloud Loadbalancer负载均衡策略以及实现动态负载均衡策略的方案
    c语言练习77:公因⼦的数⽬
    WebFlux异常处理:onErrorReturn和onErrorResume
    基于JAVA模拟考试系统计算机毕业设计源码+数据库+lw文档+系统+部署
    analog IC layout-Design for reliability
    步力宝品牌鞋业商业规划如何迭代升级
    整体记录一下asp.net core 认证和授权
  • 原文地址:https://blog.csdn.net/weixin_53373681/article/details/133997687