• 驱动day4


    head.h

    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. #define LED_ON _IOW('l',1,int)
    17. #define LED_OFF _IOW('l',0,int)
    18. #endif

    mycdev.c

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include"head.h"
    10. char kbuf[128]={0};
    11. gpio_t *vir_led1;
    12. gpio_t *vir_led2;
    13. gpio_t *vir_led3;
    14. unsigned int *vir_rcc;
    15. struct cdev *cdev;
    16. unsigned int major=0;
    17. unsigned int minor=0;
    18. dev_t devno;
    19. struct class *cls;
    20. struct device *dev;
    21. int mycdev_open(struct inode *inode, struct file *file)
    22. {
    23. int min=MINOR(inode->i_rdev);//获取打开的的文件的次设备号
    24. file->private_data= (void *)min;
    25. printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    26. return 0;
    27. }
    28. long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
    29. {
    30. int min=(int)file->private_data;//获取到文件的次设备号
    31. switch(min)
    32. {
    33. case 0://操作LED1
    34. switch(cmd)
    35. {
    36. case LED_ON://开灯
    37. vir_led1->ODR |= (0X1<<10);
    38. break;
    39. case LED_OFF: //关灯
    40. vir_led1->ODR &= (~(0X1<<10));
    41. break;
    42. }
    43. break;
    44. case 1://操作LED2
    45. switch(cmd)
    46. {
    47. case LED_ON://开灯
    48. vir_led2->ODR |= (0X1<<10);
    49. break;
    50. case LED_OFF: //关灯
    51. vir_led2->ODR &= (~(0X1<<10));
    52. break;
    53. }
    54. break;
    55. case 2://操作LED3
    56. switch(cmd)
    57. {
    58. case LED_ON://开灯
    59. vir_led3->ODR |= (0X1<<10);
    60. break;
    61. case LED_OFF://关灯
    62. vir_led3->ODR &= (~(0X1<<10));
    63. break;
    64. }
    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. int ret;
    125. //申请一个对象空间 cdev_alloc
    126. cdev=cdev_alloc();
    127. if(cdev==NULL)
    128. {
    129. printk("申请对象空间失败\n");
    130. ret=-EFAULT;
    131. goto out1;
    132. }
    133. printk("申请对象空间成功\n");
    134. //初始化对象 cdev_init
    135. cdev_init(cdev, &fops);
    136. //申请设备号
    137. if (major==0)
    138. {
    139. ret=alloc_chrdev_region(&devno, minor, 3,"mychrdev");
    140. if(ret)
    141. {
    142. printk("动态申请设备号失败\n");
    143. goto out2;
    144. }
    145. major=MAJOR(devno);//根据设备获取主设备号
    146. minor=MINOR(devno);//根据设备获取次设备号
    147. printk("字符主设备驱动注册成功:major=%d\n",major);
    148. printk("字符次设备驱动注册成功:minor=%d\n",minor);
    149. }
    150. else
    151. {
    152. ret=register_chrdev_region(MKDEV(major,minor),3,"mychrdev");
    153. if(ret)
    154. {
    155. printk("静态申请设备号失败\n");
    156. goto out2;
    157. }
    158. }
    159. printk("设备号申请成功\n");
    160. //注册驱动对象
    161. ret=cdev_add(cdev,MKDEV(major,minor),3);
    162. if(ret)
    163. {
    164. printk("注册设备驱动对象失败\n");
    165. goto out3;
    166. }
    167. printk("注册设备驱动对象成功\n");
    168. //向上提交目录
    169. cls=class_create(THIS_MODULE,"mychrdev");
    170. if(IS_ERR(cls))
    171. {
    172. printk("向上提交目录失败\n");
    173. goto out4;
    174. }
    175. printk("向上提交目录成功\n");
    176. //向上提交设备节点信息
    177. int i;
    178. for(i=0;i<3;i++)
    179. {
    180. dev=device_create(cls,NULL,MKDEV(major,i),NULL,"mycdev%d",i);
    181. if(IS_ERR(dev))
    182. {
    183. printk("向上提交设备节点失败\n");
    184. goto out5;
    185. }
    186. }
    187. printk("向上提交设备节点成功\n");
    188. all_led_init();
    189. return 0;
    190. out5:
    191. //将提交成功的信息释放
    192. for(--i;i>=0;i--)
    193. {
    194. device_destroy(cls,MKDEV(major,i));
    195. }
    196. //将提交失败的信息销毁
    197. class_destroy(cls);
    198. out4:
    199. cdev_del(cdev);
    200. out3:
    201. unregister_chrdev_region(MKDEV(major,minor),3);
    202. out2:
    203. kfree(cdev);
    204. out1:
    205. return ret;
    206. }
    207. static void __exit mycdev_exit(void)
    208. {
    209. //销毁设备节点信息
    210. int i;
    211. iounmap(vir_led1);
    212. iounmap(vir_led2);
    213. iounmap(vir_led3);
    214. iounmap(vir_rcc);
    215. for(i=0;i<3;i++)
    216. {
    217. device_destroy(cls,MKDEV(major,i));
    218. }
    219. //销毁目录
    220. class_destroy(cls);
    221. //注销字符设备驱动对象空间
    222. cdev_del(cdev);
    223. //释放设备号
    224. unregister_chrdev_region(MKDEV(major,minor),3);
    225. //释放申请到的字符设备驱动对象空间
    226. kfree(cdev);
    227. }
    228. module_init(mycdev_init);
    229. module_exit(mycdev_exit);
    230. 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,const char * argv[])
    11. {
    12. char buf[128]={0};
    13. int a,b;
    14. printf("打开设备文件成功\n");
    15. while(1)
    16. {
    17. //从终端读取
    18. int fd;
    19. printf("请选择要控制的灯:1(LED1)2(LED2)3(LED3)\n");
    20. printf("请输入>");
    21. scanf("%d",&a);
    22. printf("请输入要实现的功能 ");
    23. printf("0(关灯) 1(开灯)\n");
    24. printf("请输入>");
    25. scanf("%d",&b);
    26. switch(a)
    27. {
    28. case 1:
    29. fd=open("/dev/mycdev0",O_RDWR);
    30. if(fd < 0)
    31. {
    32. printf("打开设备文件失败\n");
    33. return -1;
    34. }
    35. if(b==1)
    36. ioctl(fd,LED_ON,&b);
    37. else if(b==0)
    38. ioctl(fd,LED_OFF,&b);
    39. else
    40. b=0;
    41. break;
    42. case 2:
    43. fd=open("/dev/mycdev1",O_RDWR);
    44. if(fd < 0)
    45. {
    46. printf("打开设备文件失败\n");
    47. return -1;
    48. }
    49. if(b==1)
    50. ioctl(fd,LED_ON,&b);
    51. else if(b==0)
    52. ioctl(fd,LED_OFF,&b);
    53. else
    54. b=0;
    55. break;
    56. case 3:
    57. fd=open("/dev/mycdev2",O_RDWR);
    58. if(fd < 0)
    59. {
    60. printf("打开设备文件失败\n");
    61. return -1;
    62. }
    63. if(b==1)
    64. ioctl(fd,LED_ON,&b);
    65. else if(b==0)
    66. ioctl(fd,LED_OFF,&b);
    67. else
    68. b=0;
    69. break;
    70. }
    71. close(fd);
    72. }
    73. return 0;
    74. }

  • 相关阅读:
    PHP数组输出为xml的两种常见方法
    Access — 偏移注入
    论文笔记:Universal Value Function Approximators
    java-net-php-python-jspm家教信息管理系统演示录像(1)计算机毕业设计程序
    vue ref和$refs获取dom元素
    靠着这份1600多页的“Java面试突击核心”手册,我成功拿下了3个大厂offer
    再聊Java Stream的一些实战技能与注意点
    LeetCode-146. LRU 缓存【设计 哈希表 链表 双向链表】
    站长工具综合查询 iis7站长之家SEO综合查询工具
    JavaWeb JSTL标签库
  • 原文地址:https://blog.csdn.net/zky050213/article/details/133998859