• 驱动day8


    驱动代码

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

    应用程序代码

    1. #include <stdlib.h>
    2. #include <stdio.h>
    3. #include <sys/types.h>
    4. #include <sys/stat.h>
    5. #include <sys/ioctl.h>
    6. #include <fcntl.h>
    7. #include <unistd.h>
    8. #include <string.h>
    9. #include "head.h"
    10. int main(int argc, char const *argv[])
    11. {
    12. int a,b,fd;
    13. while(1)
    14. {
    15. fd=-1;
    16. //从终端读取
    17. printf("请输入要实现的功能 ");
    18. printf("1(关灯) 0(开灯)\n");
    19. printf("请输入>");
    20. scanf("%d",&a);
    21. printf("请选择要控制的灯:1(LED1)2(LED2) 3(LED3)\n");
    22. printf("请输入>");
    23. scanf("%d",&b);
    24. switch(b)
    25. {
    26. case 1:
    27. fd=open("/dev/burger0",O_RDWR);
    28. if(a == 0)
    29. {
    30. ioctl(fd,LED_ON,&b);
    31. break;
    32. }
    33. else
    34. {
    35. ioctl(fd,LED_OFF,&b);
    36. break;
    37. }
    38. case 2:
    39. fd=open("/dev/burger1",O_RDWR);
    40. if(a == 0)
    41. {
    42. ioctl(fd,LED_ON,&b);
    43. break;
    44. }
    45. else
    46. {
    47. ioctl(fd,LED_OFF,&b);
    48. break;
    49. }
    50. case 3:
    51. fd=open("/dev/burger2",O_RDWR);
    52. if(a == 0)
    53. {
    54. ioctl(fd,LED_ON,&b);
    55. break;
    56. }
    57. else
    58. {
    59. ioctl(fd,LED_OFF,&b);
    60. break;
    61. }
    62. }
    63. close(fd);
    64. }
    65. close(fd);
    66. return 0;
    67. }

    头文件

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

    实验结果:

  • 相关阅读:
    【周末读书】认知驱动:做成一件对他人很有用的事
    文件传输协议
    使用 Helm3 部署 Loki
    autodl服务器中YOLOx训练自己数据集
    动态SQL+分页
    差分约束学习笔记
    Shell脚本中2>&1、>、>>等符号到底是什么含义
    haproxy
    PostgreSql学习(基于菜鸟课程)
    4核16G服务器价格腾讯云PK阿里云
  • 原文地址:https://blog.csdn.net/cecillq/article/details/134088973