• 底层驱动day4作业


    分布注册设备,实现文件和设备的绑定

    代码:

    1. //head.h
    2. #ifndef __HEAD_H__
    3. #define __HEAD_H__
    4. #define PHY_RCC 0x50000A28
    5. #define PHY_GPIOE_MODER 0x50006000
    6. #define PHY_GPIOF_MODER 0x50007000
    7. #define PHY_GPIOE_ODR 0x50006014
    8. #define PHY_GPIOF_ODR 0x50007014
    9. typedef struct
    10. {
    11. unsigned int MODER;
    12. unsigned int OTYPER;
    13. unsigned int OSPEEDR;
    14. unsigned int PUPDR;
    15. unsigned int IDR;
    16. unsigned int ODR;
    17. }gpio_t;
    18. #define GPIOE 0x50006000
    19. #define GPIOF 0x50007000
    20. #define PHY_RCC_ADDR 0x50000A28
    21. #define LED_ON _IOW('l',1,int)
    22. #define LED_OFF _IOW('l',0,int)
    23. #endif
    1. //mycdev.c
    2. #include<linux/init.h>
    3. #include<linux/module.h>
    4. #include<linux/io.h>
    5. #include<linux/device.h>
    6. #include<linux/fs.h>
    7. #include<linux/cdev.h>
    8. #include<linux/uaccess.h>
    9. #include<linux/slab.h>
    10. #include"include/head.h"
    11. unsigned int major = 0,minor = 0;
    12. dev_t devno;
    13. struct class *cls;
    14. struct cdev* cdev;
    15. struct device *dev;
    16. gpio_t *vir_led1;
    17. gpio_t *vir_led2;
    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. int all_led_init(void)
    76. {
    77. vir_led1 = ioremap(GPIOE,sizeof(gpio_t));
    78. if(NULL == vir_led1)
    79. {
    80. printk("ioremap failed : %d\n",__LINE__);
    81. return -ENOMEM;
    82. }
    83. vir_led2 = ioremap(GPIOF,sizeof(gpio_t));
    84. if(NULL == vir_led2)
    85. {
    86. printk("ioremap failed : %d\n",__LINE__);
    87. return -ENOMEM;
    88. }
    89. vir_rcc = ioremap(PHY_RCC,4);
    90. if(NULL == vir_rcc)
    91. {
    92. printk("ioremap failed : %d\n",__LINE__);
    93. return -ENOMEM;
    94. }
    95. printk("寄存器内存映射成功\n");
    96. (*vir_rcc) |= (0x1 << 4);
    97. (*vir_rcc) |= (0x1 << 5);
    98. (vir_led1->MODER) &= (~(0x3 << 20)); //led1_moder
    99. (vir_led1->MODER) |= (0x1 << 20);
    100. (vir_led1->MODER) &= (~(0x3 << 16)); //led3_moder
    101. (vir_led1->MODER) |= (0x1 << 16);
    102. (vir_led1->ODR) &= (~(0x1 << 10)); //led1_odr
    103. (vir_led1->ODR) &= (~(0x1 << 8)); //led3_odr
    104. (vir_led2->MODER) &= (~(0x3 << 20)); //led2_moder
    105. (vir_led2->MODER) |= (0x1 << 20);
    106. (vir_led2->ODR) &= (~(0X1 << 10)); //led2_odr
    107. return 0;
    108. }
    109. struct file_operations fops = {
    110. .open = mycdev_open,
    111. .unlocked_ioctl = mycdev_ioctl,
    112. .release = mycdev_close,
    113. };
    114. static int __init mycdev_init(void)
    115. {
    116. int ret;
    117. all_led_init();
    118. //申请对象空间
    119. cdev = cdev_alloc();
    120. if(NULL == cdev)
    121. {
    122. printk("申请字符设备驱动对象空间失败\n");
    123. ret = -EFAULT;
    124. goto out;
    125. }
    126. printk("申请字符设备驱动对象空间成功\n");
    127. //初始化对象
    128. cdev_init(cdev,&fops);
    129. //申请设备号
    130. if(0 == major)
    131. {
    132. ret = alloc_chrdev_region(&devno,0,3,"mychrdev");
    133. if(0 != ret)
    134. {
    135. printk("动态申请设备号失败\n");
    136. goto out2;
    137. }
    138. major = MAJOR(devno);
    139. minor = MINOR(devno);
    140. }
    141. else
    142. {
    143. ret = register_chrdev_region(MKDEV(major,minor),3,"mychrdev");
    144. if(0 != ret)
    145. {
    146. printk("静态申请设备号失败\n");
    147. goto out2;
    148. }
    149. }
    150. printk("申请设备号成功\n");
    151. //注册驱动对象
    152. int ret2 = cdev_add(cdev,devno,3);
    153. if(0 != ret2)
    154. {
    155. printk("注册驱动对象失败\n");
    156. goto out3;
    157. }
    158. printk("注册字符设备驱动对象成功\n");
    159. //向上提交目录
    160. cls = class_create(THIS_MODULE,"mychrdev");
    161. if(IS_ERR(cls))
    162. {
    163. printk("向上提交目录失败\n");
    164. goto out4;
    165. }
    166. printk("向上提交目录成功\n");
    167. //向上提交设备节点信息
    168. int i;
    169. for(i = 0;i < 3;i++)
    170. {
    171. dev = device_create(cls,NULL,MKDEV(major,i),NULL,"mychrdev%d",i);
    172. if(IS_ERR(dev))
    173. {
    174. printk("向上提交设备节点失败\n");
    175. goto out5;
    176. }
    177. }
    178. printk("向上提交设备节点成功\n");
    179. return 0;
    180. out5:
    181. for(--i;i >= 0;i--)
    182. {
    183. device_destroy(cls,MKDEV(major,i));
    184. }
    185. class_destroy(cls);
    186. out4:
    187. cdev_del(cdev);
    188. out3:
    189. unregister_chrdev_region(MKDEV(major,minor),3);
    190. out2:
    191. kfree(cdev);
    192. out:
    193. return ret;
    194. }
    195. static void __exit mycdev_exit(void)
    196. {
    197. //销毁设备节点信息
    198. int i;
    199. for(i = 0;i < 3;i++)
    200. {
    201. device_destroy(cls,MKDEV(major,i));
    202. }
    203. //销毁设备目录
    204. class_destroy(cls);
    205. //销毁字符设备驱动对象
    206. cdev_del(cdev);
    207. //释放设备号
    208. unregister_chrdev_region(MKDEV(major,minor),3);
    209. kfree(cdev);
    210. return;
    211. }
    212. module_init(mycdev_init);
    213. module_exit(mycdev_exit);
    214. MODULE_LICENSE("GPL");

     

    1. //test.c
    2. #include<unistd.h>
    3. #include<fcntl.h>
    4. #include<sys/stat.h>
    5. #include<sys/types.h>
    6. #include<sys/ioctl.h>
    7. #include<stdio.h>
    8. #include<string.h>
    9. #include"include/head.h"
    10. int main(int argc, char const *argv[])
    11. {
    12. char buf[128] = {0};
    13. int led_id,led_state;
    14. fgets(buf,sizeof(buf),stdin);
    15. buf[strlen(buf) - 1] = 0;
    16. int fd = open(buf,O_RDWR);
    17. if(fd < 0)
    18. {
    19. printf("打开设备文件失败\n");
    20. return -1;
    21. }
    22. printf("打开设备文件成功\n");
    23. while(1)
    24. {
    25. // fgets(buf,sizeof(buf),stdin);
    26. // buf[strlen(buf) - 1] = 0;
    27. // write(fd,buf,sizeof(buf));
    28. // scanf("%d",&led_id);
    29. scanf("%d",&led_state);
    30. switch(led_state)
    31. {
    32. case 1:
    33. ioctl(fd,LED_ON);
    34. break;
    35. case 0:
    36. ioctl(fd,LED_OFF);
    37. break;
    38. default:
    39. break;
    40. }
    41. }
    42. //read(fd,buf,sizeof(buf));
    43. // memset(buf,0,sizeof(buf));
    44. // read(fd,buf,sizeof(buf));
    45. // printf("buf:%s\n",buf);
    46. close(fd);
    47. return 0;
    48. }

    实现效果:

  • 相关阅读:
    HTML5七夕情人节表白网页制作【花瓣图片表白】HTML+CSS+JavaScript html生日快乐祝福网页制作
    QT模态窗口与非模态窗口
    代码随想录算法训练营第48天 | ● 198.打家劫舍 ● 213.打家劫舍II ● 337.打家劫舍III
    引用 随笔
    terraform简单的开始-简单分析一下内容
    极客日报:抖音否认进入外卖行业;谷歌发布Android 12硬件门槛;IntelliJ IDEA 2021.3 EAP 4发布
    浏览器截图扩展增加快捷键
    MySQL调优之慢查询日志应用
    Spring Bean
    使用 Sa-Token 完成踢人下线功能
  • 原文地址:https://blog.csdn.net/a136630108/article/details/133996494