• 驱动开发day8


    head.h

    1. #ifndef __HEAD_H__
    2. #define __HEAD_H__
    3. // 构建开灯关灯的功能码
    4. #define LED_ON _IO('l', 1)
    5. #define LED_OFF _IO('l', 0)
    6. #endif

    demo.c

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

    test.c

    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. int a,b;
    13. while(1)
    14. {
    15. char buf[128]="/dev/mycdev";
    16. //从终端读取
    17. printf("请输入要实现的LED灯:");
    18. printf("0(LED1) 1(LED2) 2(LED3)\n");
    19. printf("请输入>");
    20. scanf("%d",&b);
    21. sprintf(buf,"%s%d",buf,b);
    22. int fd=open(buf,O_RDWR);
    23. if(fd<0)
    24. {
    25. printf("打开设备文件失败\n");
    26. exit(-1);
    27. }
    28. //从终端读取
    29. printf("请输入要实现的功能 ");
    30. printf("0(关灯) 1(开灯)\n");
    31. printf("请输入>");
    32. scanf("%d",&a);
    33. switch(a)
    34. {
    35. case 1:
    36. ioctl(fd,LED_ON);
    37. break;
    38. case 0:
    39. ioctl(fd,LED_OFF);
    40. break;
    41. }
    42. close(fd);
    43. }
    44. return 0;

    计时器

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. struct timer_list hw;
    8. void mytime_hello(struct timer_list *timer)
    9. {
    10. printk("hello world\n");
    11. mod_timer(timer, jiffies + 5*HZ);
    12. }
    13. //入口函数,安装内核模块时执行
    14. static int __init mycdev_init(void)
    15. {
    16. timer_setup(&hw, mytime_hello, 0);
    17. hw.expires = jiffies + 5*HZ;
    18. add_timer(&hw);
    19. return 0;
    20. }
    21. //出口函数,卸载内核模块时执行
    22. static void __exit mycdev_exit(void)
    23. {
    24. del_timer(&hw);
    25. }
    26. //用于声明入口函数
    27. module_init(mycdev_init);
    28. //用于声明出口函数
    29. module_exit(mycdev_exit);
    30. //声明当前内核模块遵循GPL协议
    31. MODULE_LICENSE("GPL");

  • 相关阅读:
    简单配置linux防火墙
    VK1056B/C计算器,跑步机,电子秤LCD驱动方案,段码液晶显示芯片IC技术资料
    【2】CH347应用--在OpenOCD添加CH347-JTAG接口
    【操作系统】进程间的通信——消息队列
    公司电脑强制休眠的3种解决方案
    Debian 使用 systemd 自动挂载 Samba
    Jmeter入门
    TI AM335x继任者?AM6254性能解析
    计算机组成原理习题课第一章-3(唐朔飞)
    golang设置socket选项参数SO_LINGER、SO_SNDBUF
  • 原文地址:https://blog.csdn.net/zjt020305/article/details/134088800