• 驱动day8


    基于GPIO子系统编写LED驱动,编写应用程序进行测试,设置定时器,5秒钟打印一次hello world

    驱动代码

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. struct device_node *dnode;
    8. struct gpio_desc *gpiono1;
    9. struct gpio_desc *gpiono2;
    10. struct gpio_desc *gpiono3;
    11. struct timer_list mytimer;
    12. struct class *cls;
    13. struct device *dev;
    14. int major;
    15. char kbuf[128]={0};
    16. //定时器处理函数
    17. void mytimer_funtion(struct timer_list *timer)
    18. {
    19. printk("hello world");
    20. mod_timer(timer,jiffies+5*HZ);
    21. }
    22. int mycdev_open(struct inode *inode,struct file *file)
    23. {
    24. printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    25. return 0;
    26. }
    27. ssize_t mycdev_read(struct file *file,char *ubuf,size_t size,loff_t *lof)
    28. {
    29. printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    30. int ret=copy_to_user(ubuf,kbuf,size);
    31. if(ret)
    32. {
    33. printk("copy_to_user filed\n");
    34. return -EIO;
    35. }
    36. return 0;
    37. }
    38. ssize_t mycdev_write(struct file *file,const char *ubuf,size_t size,loff_t *lof)
    39. {
    40. printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    41. int ret=copy_from_user(kbuf,ubuf,size);
    42. if(ret)
    43. {
    44. printk("copy_from_user filed\n");
    45. return -EIO;
    46. }
    47. //设定该GPIO管脚的输出值
    48. if(kbuf[0]=='0')
    49. {
    50. gpiod_set_value(gpiono1,0);
    51. gpiod_set_value(gpiono2,0);
    52. gpiod_set_value(gpiono3,0);
    53. }
    54. else if(kbuf[0]=='1')
    55. {
    56. gpiod_set_value(gpiono1,1);
    57. gpiod_set_value(gpiono2,1);
    58. gpiod_set_value(gpiono3,1);
    59. }
    60. return 0;
    61. }
    62. int mycdev_close(struct inode *inode,struct file *file)
    63. {
    64. printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    65. return 0;
    66. }
    67. struct file_operations fops ={
    68. .open=mycdev_open,
    69. .read=mycdev_read,
    70. .write=mycdev_write,
    71. .release=mycdev_close,
    72. };
    73. static int __init mycdev_init(void)
    74. {
    75. // 字符设备驱动注册
    76. major = register_chrdev(0, "mychrdev", &fops);
    77. if (major < 0)
    78. {
    79. printk("字符设备驱动注册失败\n");
    80. return major;
    81. }
    82. printk("字符设备驱动注册成功:major=%d\n", major);
    83. // 向上提交目录
    84. cls = class_create(THIS_MODULE, "mychrdev");
    85. if (IS_ERR(cls))
    86. {
    87. printk("向上提交目录失败\n");
    88. return -PTR_ERR(cls);
    89. }
    90. printk("向上提交目录成功\n");
    91. // 向上提交设备节点信息
    92. int i; // 向上提交三次设备节点信息
    93. for (i = 0; i < 3; i++)
    94. {
    95. dev = device_create(cls, NULL, MKDEV(major, i), NULL, "myled%d", i);
    96. if (IS_ERR(dev))
    97. {
    98. printk("向上提交设备节点失败\n");
    99. return -PTR_ERR(dev);
    100. }
    101. }
    102. printk("向上提交设备节点成功\n");
    103. //解析设备树节点信息
    104. dnode=of_find_node_by_path("/myled");
    105. if(dnode==NULL)
    106. {
    107. printk("解析设备树节点失败\n");
    108. return -ENXIO;
    109. }
    110. //获取LED1 GPIO编号
    111. gpiono1=gpiod_get_from_of_node(dnode,"led1-gpio",0,GPIOD_OUT_LOW,NULL);
    112. if(IS_ERR(gpiono1))
    113. {
    114. printk("申请gpiono1信息失败\n");
    115. return -PTR_ERR(gpiono1);
    116. }
    117. gpiono2=gpiod_get_from_of_node(dnode,"led2-gpio",0,GPIOD_OUT_LOW,NULL);
    118. if(IS_ERR(gpiono2))
    119. {
    120. printk("申请gpiono3信息失败\n");
    121. return -PTR_ERR(gpiono2);
    122. }
    123. gpiono3=gpiod_get_from_of_node(dnode,"led3-gpio",0,GPIOD_OUT_LOW,NULL);
    124. if(IS_ERR(gpiono3))
    125. {
    126. printk("申请gpiono3信息失败\n");
    127. return -PTR_ERR(gpiono3);
    128. }
    129. //初始化定时器对象
    130. timer_setup(&mytimer,mytimer_funtion,0);
    131. mytimer.expires=jiffies+HZ;
    132. //注册定时器
    133. add_timer(&mytimer);
    134. return 0;
    135. }
    136. static void __exit mycdev_exit(void)
    137. {
    138. del_timer(&mytimer);
    139. gpiod_set_value(gpiono3,0);
    140. gpiod_put(gpiono3);
    141. gpiod_set_value(gpiono3,0);
    142. gpiod_put(gpiono3);
    143. gpiod_set_value(gpiono3,0);
    144. gpiod_put(gpiono3);
    145. // 销毁设备节点信息
    146. int i;
    147. for (i = 0; i < 3; i++)
    148. {
    149. device_destroy(cls, MKDEV(major, i));
    150. }
    151. // 销毁目录
    152. class_destroy(cls);
    153. // 注销字符设备驱动
    154. unregister_chrdev(major, "mychrdev");
    155. }
    156. module_init(mycdev_init);
    157. module_exit(mycdev_exit);
    158. MODULE_LICENSE("GPL");

    应用代码

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. /* According to earlier standards */
    13. #include
    14. int fd1,fd2,fd3;
    15. char buf[128] ={0};
    16. int main(int argc, char const *argv[])
    17. {
    18. fd1 = open("/dev/myled0", O_RDWR);
    19. if (fd1 < 0)
    20. {
    21. printf("打开设备文件失败\n");
    22. exit(-1);
    23. }
    24. while (1)
    25. {
    26. printf("请输入0(关灯),1(开灯):");
    27. fgets(buf,sizeof(buf),stdin);
    28. //write(fd2,buf,1);
    29. //write(fd3,buf,1);
    30. buf[strlen(buf)-1]='\0';
    31. write(fd1,buf,sizeof(buf));
    32. }
    33. close(fd1);
    34. return 0;
    35. }

    现象:

  • 相关阅读:
    可视化规则引擎
    ios CI/CD 持续集成 组件化专题三 IOS打包Bundle与加载Bundle中的图片
    C++STL——string类
    java高级篇 Mybatis-Plus
    Redis BitMap+SpringBoot 实现签到与统计功能
    【C++】初识STL
    JAVAWeb笔记
    Vue3的异步组件使用
    论文阅读笔记 | 三维目标检测——AVOD算法
    交通标志识别-YOLO-数据集TT100
  • 原文地址:https://blog.csdn.net/weixin_53373681/article/details/134092069