• 驱动开发DAY4


    驱动代码

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include "head.h"
    10. dev_t devno;//存放申请的到的设备号的空间首地址
    11. unsigned baseminor;//次设备号的起始值
    12. unsigned count;//申请的设备资源数量
    13. struct cdev *cdev;//申请的字符设备驱动对象指针
    14. char kbuf[128] = {0};//内核空间首地址
    15. unsigned int major=0;
    16. unsigned int minor=0;
    17. struct class *cls;
    18. struct device *dev;
    19. module_param(major,uint,0664);
    20. gpio_t *vir_led1;
    21. gpio_t *vir_led2;
    22. gpio_t *vir_led3;
    23. unsigned int *vir_rcc;
    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. //开灯
    41. vir_led1->ODR |= 1 << 10;
    42. break;
    43. case LED_OFF:
    44. //关灯
    45. vir_led1->ODR &= (~(1 << 10));
    46. break;
    47. }
    48. break;
    49. case 1://控制LED2
    50. switch (cmd)
    51. {
    52. case LED_ON:
    53. //开灯
    54. vir_led2->ODR |= 1 << 10;
    55. break;
    56. case LED_OFF:
    57. //关灯
    58. vir_led2->ODR &= (~(1 << 10));
    59. break;
    60. }
    61. break;
    62. case 2://控制LED3
    63. switch (cmd)
    64. {
    65. case LED_ON:
    66. //开灯
    67. vir_led3->ODR |= 1 << 8;
    68. break;
    69. case LED_OFF:
    70. //关灯
    71. vir_led3->ODR &= (~(1 << 8));
    72. break;
    73. }
    74. break;
    75. }
    76. return 0;
    77. }
    78. ssize_t mycdev_read(struct file *file,char *ubuf,size_t size,loff_t *lof)
    79. {
    80. int ret;
    81. ret=copy_to_user(ubuf,kbuf,size);
    82. if (ret)
    83. {
    84. printk("copy_to_user err\n");
    85. return -EIO;
    86. }
    87. printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    88. return 0;
    89. }
    90. ssize_t mycdev_write(struct file *file,const char *ubuf,size_t size,loff_t *lof)
    91. {
    92. int ret;
    93. //从用户拷贝
    94. ret=copy_from_user(kbuf,ubuf,size);
    95. if (ret)
    96. {
    97. printk("copy_from_user err\n");
    98. return -EIO;
    99. }
    100. return 0;
    101. }
    102. int mycdev_close(struct inode *inode,struct file *file)
    103. {
    104. printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    105. return 0;
    106. }
    107. //定义一个操作方法结构体对象并且初始化
    108. struct file_operations fops = {
    109. .open=mycdev_open,
    110. .read=mycdev_read,
    111. .write=mycdev_write,
    112. .release=mycdev_close,
    113. .unlocked_ioctl = mycdev_ioctl,
    114. };
    115. int all_led_init(void)
    116. {
    117. // 寄存器地址的映射
    118. vir_led1 = ioremap(PHY_LED1_ADDR, sizeof(gpio_t));
    119. if (vir_led1 == NULL)
    120. {
    121. printk("ioremap filed:%d\n", __LINE__);
    122. return -ENOMEM;
    123. }
    124. vir_led2 = ioremap(PHY_LED2_ADDR, sizeof(gpio_t));
    125. if (vir_led2 == NULL)
    126. {
    127. printk("ioremap filed:%d\n", __LINE__);
    128. return -ENOMEM;
    129. }
    130. vir_led3 = vir_led1;
    131. vir_rcc = ioremap(PHY_RCC_ADDR, 4);
    132. if (vir_rcc == NULL)
    133. {
    134. printk("ioremap filed:%d\n", __LINE__);
    135. return -ENOMEM;
    136. }
    137. printk("物理地址映射成功\n");
    138. // 寄存器的初始化
    139. // rcc
    140. (*vir_rcc) |= (0X3 << 4);
    141. // led1
    142. vir_led1->MODER &= (~(3 << 20));
    143. vir_led1->MODER |= (1 << 20);
    144. vir_led1->ODR &= (~(1 << 10));
    145. // led2
    146. vir_led2->MODER &= (~(3 << 20));
    147. vir_led2->MODER |= (1 << 20);
    148. vir_led2->ODR &= (~(1 << 10));
    149. // led3
    150. vir_led3->MODER &= (~(3 << 16));
    151. vir_led1->MODER |= (1 << 16);
    152. vir_led1->ODR &= (~(1 << 8));
    153. printk("寄存器初始化成功\n");
    154. return 0;
    155. }
    156. static int __init mycdev_init(void)
    157. {
    158. int ret;
    159. //申请一个字符设备驱动对象空间
    160. cdev = cdev_alloc();
    161. if (cdev == NULL)
    162. {
    163. printk("申请字符设备对象驱动空间失败\n");
    164. ret = -EFAULT;
    165. goto out1;
    166. }
    167. printk("字符设备驱动对象成功\n");
    168. //字符设备设备驱动对象初始化
    169. cdev_init(cdev,&fops);
    170. //申请设备号
    171. if (major > 0)//静态指定设备号
    172. {
    173. ret=register_chrdev_region(MKDEV(major,minor),3,"myled");
    174. if (ret)
    175. {
    176. printk("静态申请设备号失败\n");
    177. goto out2;
    178. }
    179. }else if(major == 0)
    180. {
    181. int ret= alloc_chrdev_region(&devno,minor,3,"myled");
    182. if (ret!=0)
    183. {
    184. //释放申请的字符设备对象空间
    185. printk("动态申请设备号失败\n");
    186. goto out2;
    187. }
    188. major=MAJOR(devno);//获取主设备号
    189. minor=MINOR(devno);//获取次设备号
    190. }
    191. printk("申请设备号成功\n");
    192. //根据申请到的设备号和驱动对象注册驱动
    193. ret=cdev_add(cdev,MKDEV(major,minor),3);
    194. if (ret != 0)
    195. {
    196. printk("驱动对象注册失败\n");
    197. goto out3;
    198. }
    199. printk("字符设备驱动对象注册成功\n");
    200. // 寄存器映射以及初始化
    201. all_led_init();
    202. //向上提交目录信息
    203. cls=class_create(THIS_MODULE,"myled");
    204. if (IS_ERR(cls))
    205. {
    206. printk("向上提交目录失败\n");
    207. ret = -PTR_ERR(cls);
    208. goto out4;
    209. }
    210. printk("向上提交目录成功\n");
    211. //向上提交设备节点信息
    212. int i;
    213. for(i=0;i<3;i++)
    214. {
    215. dev=device_create(cls,NULL,MKDEV(major,i),NULL,"myled%d",i);
    216. if(IS_ERR(dev))
    217. {
    218. printk("向上提交设备节点信息失败\n");
    219. ret=-PTR_ERR(dev);
    220. goto out5;
    221. }
    222. }
    223. printk("向上提交设备节点信息成功\n");
    224. return 0;
    225. out5:
    226. //释放前一次提交成功的设备信息
    227. for(--i;i>=0;i--)
    228. {
    229. device_destroy(cls,MKDEV(major,i));
    230. }
    231. class_destroy(cls);//释放目录
    232. out4:
    233. cdev_del(cdev);
    234. out3:
    235. unregister_chrdev_region(MKDEV(major,minor),3);
    236. out2:
    237. kfree(cdev);
    238. out1:
    239. return ret;
    240. }
    241. static void __exit mycdev_exit(void)
    242. {
    243. //释放节点信息
    244. int i;
    245. for(i=0;i<3;i++)
    246. {
    247. device_destroy(cls,MKDEV(major,i));
    248. }
    249. //销毁目录
    250. class_destroy(cls);
    251. // 取消地址映射
    252. iounmap(vir_led1);
    253. iounmap(vir_led2);
    254. iounmap(vir_rcc);
    255. //注销驱动对象
    256. cdev_del(cdev);
    257. //释放设备号
    258. unregister_chrdev_region(MKDEV(major,minor),3);
    259. //释放设备空间
    260. kfree(cdev);
    261. }
    262. module_init(mycdev_init);
    263. module_exit(mycdev_exit);
    264. MODULE_LICENSE("GPL");

    头文件

    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. //构建LED开关的功能码,添加ioctl第三个参数int
    16. #define LED_ON _IOW('l',1,int)
    17. #define LED_OFF _IOW('l',0,int)
    18. #endif

    应用代码

    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. int c;
    14. char buf[128] = {0};
    15. int fd,fd1,fd2;
    16. while (1)
    17. {
    18. // 从终端读取
    19. printf("请输入要控制的灯:0(LED1) 1(LED2) 2(LED3)>");
    20. scanf("%d",&a);
    21. switch (a)
    22. {
    23. case 0:
    24. fd = open("/dev/myled0", O_RDWR);
    25. printf("请输入开灯(1) 关灯(0)>");
    26. scanf("%d",&b);
    27. switch (b)
    28. {
    29. case 1:
    30. ioctl(fd, LED_ON,c); // 开灯
    31. close(fd);
    32. break;
    33. case 0:
    34. ioctl(fd, LED_OFF,c); // 关灯
    35. break;
    36. close(fd);
    37. }
    38. break;
    39. case 1:
    40. fd1 = open("/dev/myled1", O_RDWR);
    41. printf("请输入开灯(1) 关灯(0)>");
    42. scanf("%d",&b);
    43. switch(b)
    44. {
    45. case 1:
    46. ioctl(fd1, LED_ON,c); // 开灯
    47. close(fd1);
    48. break;
    49. case 0:
    50. ioctl(fd1, LED_OFF,c); // 关灯
    51. close(fd1);
    52. break;
    53. }
    54. break;
    55. case 2:
    56. fd2 = open("/dev/myled2", O_RDWR);
    57. printf("请输入开灯(1) 关灯(0)>");
    58. scanf("%d",&b);
    59. switch(b)
    60. {
    61. case 1:
    62. ioctl(fd2, LED_ON,c); // 开灯
    63. close(fd2);
    64. break;
    65. case 0:
    66. ioctl(fd2, LED_OFF,c); // 关灯
    67. close(fd2);
    68. break;
    69. }
    70. break;
    71. }
    72. }
    73. return 0;
    74. }

  • 相关阅读:
    【idea】 java: 找不到符号
    postman打开后,以前的接口记录不在,问题解决
    竞赛 基于情感分析的网络舆情热点分析系统
    C Primer Plus(6) 中文版 第7章 C控制语句:分支和跳转 7.1 if语句
    Git 使用教程
    武汉新时标文化传媒有限公司:如何做好短视频直播间的流量?
    基于Java的个性化旅游攻略系统设计与实现(源码+lw+ppt+部署文档+视频讲解等)
    2.6 PE结构:导出表详细解析
    爆款小游戏用的都是什么游戏开发引擎?
    面试素材-结构化
  • 原文地址:https://blog.csdn.net/qq_62504624/article/details/132863880