• 注册字符设备使用gpio设备树节点控制led三盏灯的亮灭


    head.h

    1. #define LED_ON _IOW('l',1,int *)
    2. #define LED_OFF _IOW('l',0,int *)

    text.c

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

    demo.c

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

  • 相关阅读:
    Windowns编译OpenSSL
    帆软 多条件参数动态查询,有参数查没参数为空
    vue.js生命周期函数
    MES在流程和离散制造企业的15个差别(上)
    10快速入门Query函数使用的Pandas的查询示例
    【开发心得】Jaxb使用珠玑
    Kotlin 使用vararg可变参数
    【Java并发编程】——线程池
    在 uni-app 中选中奇偶子元素
    Python列表:灵活与高效的数据结构
  • 原文地址:https://blog.csdn.net/fh2331/article/details/134088732