• day4驱动开发


    目的:通过字符设备驱动的分步实现编写LED驱动,另外实现特备文件和设备的绑定

    驱动文件 :

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

    应用程序 : 

    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. // 打开第一个设备文件
    13. int fd1 = open("/dev/mychrdev0", O_RDWR);
    14. if (fd1 < 0)
    15. {
    16. printf("打开设备文件失败\n");
    17. exit(-1);
    18. }
    19. // 打开第二个设备文件
    20. int fd2 = open("/dev/mychrdev1", O_RDWR);
    21. if (fd2 < 0)
    22. {
    23. printf("打开设备文件失败\n");
    24. exit(-1);
    25. }
    26. // 打开第三个设备文件
    27. int fd3 = open("/dev/mychrdev2", O_RDWR);
    28. if (fd3 < 0)
    29. {
    30. printf("打开设备文件失败\n");
    31. exit(-1);
    32. }
    33. while (1)
    34. {
    35. int a, b;
    36. // 从终端读取
    37. printf("请输入字符\n");
    38. printf("第一个字符:1(LED1) 2(LED2) 3(LED3)\n");
    39. scanf("%d", &a);
    40. printf("第二个字符:0(关灯) 1(开灯)\n");
    41. printf("请输入>");
    42. scanf("%d", &b);
    43. // 向设备文件中写
    44. switch (b)
    45. {
    46. case 1:
    47. switch (a)
    48. {
    49. case 1: // LED1
    50. ioctl(fd1, LED_ON);
    51. break;
    52. case 2: // LED2
    53. ioctl(fd2, LED_ON);
    54. break;
    55. case 3: // LED3
    56. ioctl(fd3, LED_ON);
    57. break;
    58. }
    59. break;
    60. case 0:
    61. switch (a)
    62. {
    63. case 1: // LED1
    64. ioctl(fd1, LED_OFF);
    65. break;
    66. case 2: // LED2
    67. ioctl(fd2, LED_OFF);
    68. break;
    69. case 3: // LED3
    70. ioctl(fd3, LED_OFF);
    71. break;
    72. }
    73. break;
    74. }
    75. }
    76. close(fd1);
    77. close(fd2);
    78. close(fd3);
    79. return 0;
    80. }

    头文件 :

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

  • 相关阅读:
    【Swift 60秒】60 - Creating your own structs
    人员定位系统如何赋能智慧电厂转型?
    【JVM--StringTable字符串常量池】
    网卡收发包过程
    因果系列文章(10)—— 因果关系发现
    基于正交分解的室外阴影图像恢复
    从2022安洵杯[babyPHP]看Soap+CLRF造成SSRF漏洞
    KingbaseES V8R6集群管理运维案例之---repmgr standby switchover故障
    Python中的HTTP高手:如何玩转requests模块
    在线问诊 Python、FastAPI、Neo4j — 创建药品节点
  • 原文地址:https://blog.csdn.net/m0_64146298/article/details/133997474