• 驱动开发day4


    head.h

    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 PURDR;
    8. unsigned int IDR;
    9. unsigned int ODR;
    10. }gpio_t;
    11. #define PHY_LED1 0x50006000
    12. #define PHY_LED2 0x50007000
    13. #define PHY_LED3 0x50006000
    14. #define PHY_RCC 0x50000A28
    15. #define LED_ON _IOW('l',1,int)
    16. #define LED_OFF _IOW('l',0,int)
    17. #endif

    demo.c

    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. struct class *cls;
    13. struct device *dev;
    14. dev_t devno;
    15. gpio_t *vir_led1;
    16. gpio_t *vir_led2;
    17. gpio_t *vir_led3;
    18. unsigned int *vir_rcc;
    19. //封装操作方法
    20. int mycdev_open(struct inode *inode,struct file *file)
    21. {
    22. int min=MINOR(inode->i_rdev);
    23. file->private_data=(void *)min;
    24. printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    25. return 0;
    26. }
    27. long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
    28. {
    29. int min=(int)file->private_data;
    30. switch(min)
    31. {
    32. case 0:
    33. switch(cmd)
    34. {
    35. case LED_ON:
    36. (vir_led1->ODR) |= (0x1<<10);
    37. break;
    38. case LED_OFF:
    39. (vir_led1->ODR) &= (~(0x1<<10));
    40. break;
    41. }
    42. break;
    43. case 1:
    44. switch(cmd)
    45. {
    46. case LED_ON:
    47. (vir_led2->ODR) |= (0x1<<10);
    48. break;
    49. case LED_OFF:
    50. (vir_led2->ODR) &= (~(0x1<<10));
    51. break;
    52. }
    53. break;
    54. case 2:
    55. switch(cmd)
    56. {
    57. case LED_ON:
    58. (vir_led3->ODR) |= (0x1<<8);
    59. break;
    60. case LED_OFF:
    61. (vir_led3->ODR) &= (~(0x1<<8));
    62. break;
    63. }
    64. break;
    65. }
    66. printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    67. return 0;
    68. }
    69. int mycdev_close(struct inode *inode,struct file *file)
    70. {
    71. printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    72. return 0;
    73. }
    74. //定义操作方法结构体对象
    75. struct file_operations fops={
    76. .open=mycdev_open,
    77. /*
    78. .read=mycdev_read,
    79. .write=mycdev_write,
    80. */
    81. .unlocked_ioctl = mycdev_ioctl,
    82. .release=mycdev_close,
    83. };
    84. int all_led_init(void)
    85. {
    86. vir_led1=ioremap(PHY_LED1,sizeof(gpio_t));
    87. vir_led2=ioremap(PHY_LED2,sizeof(gpio_t));
    88. vir_led3=vir_led1;
    89. if(vir_led1==NULL||vir_led2==NULL)
    90. {
    91. printk("物理内存地址映射失败%d\n",__LINE__);
    92. return -EFAULT;
    93. }
    94. vir_rcc=ioremap(PHY_RCC,4);
    95. if(vir_rcc==NULL)
    96. {
    97. printk("物理内存地址映射失败%d\n",__LINE__);
    98. return -EFAULT;
    99. }
    100. printk("物理内存地址映射成功\n");
    101. (*vir_rcc) |= (0x1<<4);//GPIOE控制器时钟使能
    102. (*vir_rcc) |= (0x1<<5);
    103. //LED1寄存器初始化
    104. (vir_led1->MODER) &= (~(0x3<<20));
    105. (vir_led1->MODER) |= (0x1<<20);
    106. (vir_led1->ODR) &= (~(0x1<<10));//默认关灯
    107. //LED2寄存器初始化
    108. (vir_led2->MODER) &= (~(0x3<<20));
    109. (vir_led2->MODER) |= (0x1<<20);
    110. (vir_led2->ODR) &= (~(0x1<<10));//默认关灯
    111. //LED3寄存器初始化
    112. (vir_led3->MODER) &= (~(0x3<<16));
    113. (vir_led3->MODER) |= (0x1<<16);
    114. (vir_led3->ODR) &= (~(0x1<<8));//默认关灯
    115. printk("寄存器初始化成功\n");
    116. return 0;
    117. }
    118. static int __init s1(void)
    119. {
    120. //1.申请字符设备驱动对象
    121. int ret;
    122. cdev=cdev_alloc();
    123. if(cdev==NULL)
    124. {
    125. printk("申请字符设备驱动对象失败\n");
    126. ret=-EFAULT;
    127. goto out1;
    128. }
    129. printk("字符设备驱动对象申请成功\n");
    130. //2.字符设备部分初始化
    131. cdev_init(cdev,&fops);
    132. //3.申请设备号
    133. if(major==0)//动态申请
    134. {
    135. ret=alloc_chrdev_region(&devno,minor,3,"mychrdev");
    136. if(ret)
    137. {
    138. printk("动态申请设备号失败");
    139. goto out2;
    140. }
    141. major=MAJOR(devno);
    142. minor=MINOR(devno);
    143. }
    144. else//静态申请设备号
    145. {
    146. ret=register_chrdev_region(MKDEV(major,minor),3,"mychrdev");
    147. if(ret)
    148. {
    149. printk("静态申请设备号失败\n");
    150. goto out2;
    151. }
    152. }
    153. printk("申请设备号成功\n");
    154. //注册字符设备驱动对象
    155. ret=cdev_add(cdev,MKDEV(major,minor),3);
    156. if(ret)
    157. {
    158. printk("注册字符设备驱动对象失败\n");
    159. goto out3;
    160. }
    161. printk("注册字符设备驱动对象成功\n");
    162. //向上提交目录
    163. cls=class_create(THIS_MODULE,"mychredv");
    164. if(IS_ERR(cls))
    165. {
    166. printk("向上提交目录失败\n");
    167. goto out4;
    168. }
    169. printk("向上提交目录成功\n");
    170. //向上提交设备节点信息
    171. int i=0;
    172. for(i=0;i<3;i++)
    173. {
    174. dev=device_create(cls,NULL,MKDEV(major,i),NULL,"myled%d",i);
    175. if(IS_ERR(dev))
    176. {
    177. printk("向上提交设备节点信息失败\n");
    178. goto out5;
    179. }
    180. }
    181. printk("向上提交设备节点信息成功\n");
    182. //寄存器映射以及初始化
    183. all_led_init();
    184. return 0;
    185. out5:
    186. for(--i;i>=0;i--)
    187. {
    188. device_destroy(cls,MKDEV(major,i));
    189. }
    190. class_destroy(cls);
    191. out4:
    192. cdev_del(cdev);
    193. out3:
    194. unregister_chrdev_region(MKDEV(major,minor),3);
    195. out2:
    196. kfree(cdev);
    197. out1:
    198. return ret;
    199. }
    200. static void __exit s2(void)
    201. {
    202. //取消地址映射
    203. iounmap(vir_led1);
    204. iounmap(vir_led2);
    205. iounmap(vir_led3);
    206. iounmap(vir_rcc);
    207. //注销字符设备及驱动
    208. int i;
    209. for(i=0;i<3;i++)
    210. {
    211. device_destroy(cls,MKDEV(major,i));
    212. }
    213. class_destroy(cls);
    214. cdev_del(cdev);
    215. unregister_chrdev_region(MKDEV(major,minor),3);
    216. kfree(cdev);
    217. }
    218. module_init(s1);
    219. module_exit(s2);
    220. 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,char const *argv[])
    11. {
    12. char buf[128]={0};
    13. int a;
    14. int fd=open("/dev/myled0",O_RDWR);
    15. if(fd<0)
    16. {
    17. printf("打开设备文件失败\n");
    18. return -1;
    19. }
    20. printf("打开设备文件成功\n");
    21. while(1)
    22. {
    23. printf("请输入要进行的操作:0(关灯)1(开灯)");
    24. printf("请输入 >");
    25. scanf("%d",&a);
    26. switch(a)
    27. {
    28. case 1:
    29. ioctl(fd,LED_ON);
    30. break;
    31. case 0:
    32. ioctl(fd,LED_OFF);
    33. break;
    34. }
    35. /*
    36. fgets(buf,sizeof(buf),stdin);//从终端读取一个字符串
    37. buf[strlen(buf)-1]='\0';
    38. write(fd,buf,sizeof(buf));
    39. memset(buf,0,sizeof(buf));
    40. */
    41. }
    42. close(fd);
    43. return 0;
    44. }

  • 相关阅读:
    PHP 个人愿望众筹网站系统mysql数据库web结构apache计算机软件工程网页wamp
    JeecgBoot 3.4.0 版本发布,微服务重构版本
    C++ —— Tinyxml2在Vs2017下相关使用2(较文1更复杂,附源码)
    动态规划:总结
    【C++】C++11 ——— 可变参数模板
    食品赛道崛起,舌尖美食走俏礼品市场
    如何找回误删的文件呢?
    磁盘被Docker占满了怎么办?Docker修改默认存储路径/var/lib/docker
    Istio实战(六)- Istio 部署
    Python和SQL server数据同步更新使用
  • 原文地址:https://blog.csdn.net/Koren_fire/article/details/133998742