• 驱动 DAY4


    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include "head.h"
    9. struct cdev *cdev;
    10. unsigned int major = 0;
    11. unsigned int minor = 0;
    12. dev_t devno;
    13. struct class *cls;
    14. struct device *dev;
    15. gpio_t *vir_led1;
    16. gpio_t *vir_led2;
    17. gpio_t *vir_led3;
    18. unsigned int *vir_rcc;
    19. int mycdev_open(struct inode *inode, struct file *file)
    20. {
    21. int min = MINOR(inode->i_rdev); // 获取打开的的文件的次设备号
    22. file->private_data = (void *)min;
    23. printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    24. return 0;
    25. }
    26. long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
    27. {
    28. int min = (int)file->private_data; // 获取到文件的次设备号
    29. switch (min)
    30. {
    31. case 0:
    32. switch (cmd)
    33. {
    34. case LED_OFF:
    35. vir_led1->ODR &= (~(0x1 << 10));
    36. break;
    37. case LED_ON:
    38. vir_led1->ODR |= (0x1 << 10);
    39. break;
    40. }
    41. break;
    42. case 1:
    43. switch (cmd)
    44. {
    45. case LED_OFF:
    46. vir_led2->ODR &= (~(0x1 << 10));
    47. break;
    48. case LED_ON:
    49. vir_led2->ODR |= (0x1 << 10);
    50. break;
    51. }
    52. break;
    53. case 2:
    54. switch (cmd)
    55. {
    56. case LED_OFF:
    57. vir_led1->ODR &= (~(0x1 << 8));
    58. break;
    59. case LED_ON:
    60. vir_led1->ODR |= (0x1 << 8);
    61. break;
    62. }
    63. break;
    64. default:
    65. break;
    66. }
    67. printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    68. return 0;
    69. }
    70. int mycdev_close(struct inode *inode, struct file *file)
    71. {
    72. printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    73. return 0;
    74. }
    75. // 定义操作方法结构体变量并赋值
    76. struct file_operations fops = {
    77. .open = mycdev_open,
    78. .unlocked_ioctl = mycdev_ioctl,
    79. .release = mycdev_close,
    80. };
    81. int all_led_init(void)
    82. {
    83. // 寄存器地址的映射
    84. vir_led1 = ioremap(PHY_LED1_ADDR, sizeof(gpio_t));
    85. if (vir_led1 == NULL)
    86. {
    87. printk("ioremap filed:%d\n", __LINE__);
    88. return -ENOMEM;
    89. }
    90. vir_led2 = ioremap(PHY_LED2_ADDR, sizeof(gpio_t));
    91. if (vir_led2 == NULL)
    92. {
    93. printk("ioremap filed:%d\n", __LINE__);
    94. return -ENOMEM;
    95. }
    96. vir_led3 = vir_led1;
    97. vir_rcc = ioremap(PHY_RCC_ADDR, 4);
    98. if (vir_rcc == NULL)
    99. {
    100. printk("ioremap filed:%d\n", __LINE__);
    101. return -ENOMEM;
    102. }
    103. printk("物理地址映射成功\n");
    104. // 寄存器的初始化
    105. // rcc
    106. (*vir_rcc) |= (3 << 4);
    107. // led1
    108. vir_led1->MODER &= (~(3 << 20));
    109. vir_led1->MODER |= (1 << 20);
    110. vir_led1->ODR &= (~(1 << 10));
    111. // led2
    112. vir_led2->MODER &= (~(3 << 20));
    113. vir_led2->MODER |= (1 << 20);
    114. vir_led2->ODR &= (~(1 << 10));
    115. // led3
    116. vir_led3->MODER &= (~(3 << 16));
    117. vir_led1->MODER |= (1 << 16);
    118. vir_led1->ODR &= (~(1 << 8));
    119. printk("寄存器初始化成功\n");
    120. return 0;
    121. }
    122. static int __init mycdev_init(void)
    123. {
    124. all_led_init();
    125. // 1.申请一个对象空间cdev_alloc
    126. int ret;
    127. cdev = cdev_alloc();
    128. if (cdev == NULL)
    129. {
    130. printk("申请字符设备驱动对象失败\n");
    131. ret = -EFAULT;
    132. goto out1;
    133. }
    134. printk("字符设备驱动对象申请成功\n");
    135. // 2.初始化对象cdev_init
    136. cdev_init(cdev, &fops);
    137. // 3.申请设备号 register_chrdev_region()/alloc_chrdev_region()
    138. if (major == 0) // 动态申请
    139. {
    140. ret = alloc_chrdev_region(&devno, minor, 3, "mychrdev");
    141. if (ret)
    142. {
    143. printk("动态申请设备号失败\n");
    144. goto out2;
    145. }
    146. major = MAJOR(devno); // 根据设备号获取主设备号
    147. minor = MINOR(devno); // 根据设备号获取次设备号
    148. }
    149. else
    150. {
    151. ret = register_chrdev_region(MKDEV(major, minor), 3, "mychrdev");
    152. if (ret)
    153. {
    154. printk("静态指定设备号失败\n");
    155. goto out2;
    156. }
    157. }
    158. printk("设备号申请成功\n");
    159. // 4.注册驱动对象 cdev_add
    160. ret = cdev_add(cdev, MKDEV(major, minor), 3);
    161. if (ret)
    162. {
    163. printk("注册字符设备驱动对象失败\n");
    164. goto out3;
    165. }
    166. printk("注册字符设备驱动对象成功\n");
    167. // 5.向上提交目录 class_create
    168. cls = class_create(THIS_MODULE, "mychrdev");
    169. if (IS_ERR(cls))
    170. {
    171. printk("向上提交目录失败\n");
    172. goto out4;
    173. }
    174. printk("向上提交目录成功\n");
    175. // 6.向上提交设备节点信息 device_create
    176. int i;
    177. for (i = 0; i < 3; i++)
    178. {
    179. dev = device_create(cls, NULL, MKDEV(major, i), NULL, "mycdev%d", i);
    180. if (IS_ERR(dev))
    181. {
    182. printk("向上提交设备节点失败\n");
    183. goto out5;
    184. }
    185. }
    186. printk("向上提交设备节点信息成功\n");
    187. return 0;
    188. out5:
    189. // 将提交成功的节点信息释放
    190. for (--i; i >= 0; i--)
    191. {
    192. device_destroy(cls, MKDEV(major, i));
    193. }
    194. // 销毁目录
    195. class_destroy(cls);
    196. out4:
    197. cdev_del(cdev);
    198. out3:
    199. unregister_chrdev_region(MKDEV(major, minor), 3);
    200. out2:
    201. kfree(cdev);
    202. out1:
    203. return ret;
    204. }
    205. static void __exit mycdev_exit(void)
    206. {
    207. // 1.销毁设备节点信息
    208. int i;
    209. for (i = 0; i < 3; i++)
    210. {
    211. device_destroy(cls, MKDEV(major, i));
    212. }
    213. // 2.销毁目录
    214. class_destroy(cls);
    215. // 3.注销字符设备驱动对象
    216. cdev_del(cdev);
    217. // 4.释放设备号
    218. unregister_chrdev_region(MKDEV(major, minor), 3);
    219. // 5.释放申请到的字符设备驱动对象空间
    220. kfree(cdev);
    221. }
    222. module_init(mycdev_init);
    223. module_exit(mycdev_exit);
    224. MODULE_LICENSE("GPL");
    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include"head.h"
    9. int main(int argc, char const *argv[])
    10. {
    11. char buf[128] = {0};
    12. int led_id,led_state;
    13. fgets(buf,sizeof(buf),stdin);
    14. buf[strlen(buf) - 1] = 0;
    15. int fd = open(buf,O_RDWR);
    16. if(fd < 0)
    17. {
    18. printf("打开设备文件失败\n");
    19. return -1;
    20. }
    21. printf("打开设备文件成功\n");
    22. while(1)
    23. {
    24. scanf("%d",&led_state);
    25. switch(led_state)
    26. {
    27. case 1:
    28. ioctl(fd,LED_ON);
    29. break;
    30. case 0:
    31. ioctl(fd,LED_OFF);
    32. break;
    33. default:
    34. break;
    35. }
    36. }
    37. close(fd);
    38. return 0;
    39. }
    1. #ifndef __HEAD_H__
    2. #define __HEAD_H__
    3. typedef struct
    4. {
    5. unsigned int MODER;
    6. unsigned int OTYPER;
    7. unsigned int OSPEEDR;
    8. unsigned int PUPDR;
    9. unsigned int IDR;
    10. unsigned int ODR;
    11. } gpio_t;
    12. #define PHY_LED1_ADDR 0X50006000
    13. #define PHY_LED2_ADDR 0X50007000
    14. #define PHY_LED3_ADDR 0X50006000
    15. #define PHY_RCC_ADDR 0X50000A28
    16. // 构建开灯关灯的功能码
    17. #define LED_ON _IOW('l', 1,int)
    18. #define LED_OFF _IOW('l', 0,int)
    19. #endif

  • 相关阅读:
    国内多位架构大牛强烈推荐的大型分布式手册
    机器学习之随机森林
    超星面试题
    使用verdaccio+docker搭建npm私有仓库以及使用
    Binder 域
    RocketMQ源码阅读(十)消息消费-—消息队列负载均衡
    年年出妖事,一例由JSON解析导致的"薛定谔BUG"排查过程记录
    微信小程序
    【虹科干货】Redis Enterprise vs ElastiCache——如何选择缓存解决方案?
    【运维】永久关闭selinux不当,导致无法启动
  • 原文地址:https://blog.csdn.net/weixin_69028524/article/details/133998616