• 驱动day4作业


    通过字符设备驱动的分步实现编写LED驱动,另外实现特备文件和设备的绑定

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

    demo1.c

    1. #include <linux/init.h>
    2. #include <linux/module.h>
    3. #include <linux/fs.h>
    4. #include <linux/io.h>
    5. #include <linux/device.h>
    6. #include <linux/slab.h>
    7. #include <linux/cdev.h>
    8. #include "head.h"
    9. char kbuf[128]={0};
    10. gpio_t *vir_led1;
    11. gpio_t *vir_led2;
    12. gpio_t *vir_led3;
    13. unsigned int *vir_rcc;
    14. struct cdev *cdev;
    15. dev_t devno;
    16. unsigned int major=0;
    17. unsigned int minor=0;
    18. struct class *cls;
    19. struct device *dev;
    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. return 0;
    67. }
    68. int mycdev_close(struct inode *inode, struct file *file)
    69. {
    70. printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    71. return 0;
    72. }
    73. //定义操作方法结构体变量并赋值
    74. struct file_operations fops={
    75. .open=mycdev_open,
    76. .unlocked_ioctl=mycdev_ioctl,
    77. .release=mycdev_close,
    78. };
    79. int all_led_init(void)
    80. {
    81. //寄存器地址的映射
    82. vir_led1=ioremap(PHY_LED1_ADDR,sizeof(gpio_t));
    83. if(vir_led1==NULL)
    84. {
    85. printk("ioremap filed:%d\n",__LINE__);
    86. return -ENOMEM;
    87. }
    88. vir_led2=ioremap(PHY_LED2_ADDR,sizeof(gpio_t));
    89. if(vir_led2==NULL)
    90. {
    91. printk("ioremap filed:%d\n",__LINE__);
    92. return -ENOMEM;
    93. }
    94. vir_led3=vir_led1;
    95. vir_rcc=ioremap(PHY_RCC_ADDR,4);
    96. if(vir_rcc==NULL)
    97. {
    98. printk("ioremap filed:%d\n",__LINE__);
    99. return -ENOMEM;
    100. }
    101. printk("物理地址映射成功\n");
    102. //寄存器的初始化
    103. //rcc
    104. (*vir_rcc) |= (3<<4);
    105. //led1
    106. vir_led1->MODER &= (~(3<<20));
    107. vir_led1->MODER |= (1<<20);
    108. vir_led1->ODR &= (~(1<<10));
    109. //led2
    110. vir_led2->MODER &= (~(3<<20));
    111. vir_led2->MODER |= (1<<20);
    112. vir_led2->ODR &= (~(1<<10));
    113. //led3
    114. vir_led3->MODER &= (~(3<<16));
    115. vir_led1->MODER |= (1<<16);
    116. vir_led1->ODR &= (~(1<<8));
    117. printk("寄存器初始化成功\n");
    118. return 0;
    119. }
    120. static int __init mycdev_init(void)
    121. {
    122. //字符设备驱动注册
    123. int ret;
    124. cdev=cdev_alloc();
    125. if(cdev == NULL)
    126. {
    127. printk("申请对象失败\n");
    128. ret=-EFAULT;
    129. goto out1;
    130. }
    131. printk("申请对象成功\n");
    132. cdev_init(cdev,&fops);
    133. if(major == 0)
    134. {
    135. ret = alloc_chrdev_region(&devno,minor,3,"mychrdev");
    136. if(ret)
    137. {
    138. printk("申请设备号失败\n");
    139. goto out2;
    140. }
    141. printk("申请设备号成功\n");
    142. major=MAJOR(devno);
    143. minor=MINOR(devno);
    144. }
    145. ret=cdev_add(cdev,MKDEV(major,minor),3);
    146. if(ret)
    147. {
    148. printk("注册对象失败\n");
    149. goto out3;
    150. }
    151. printk("注册对象成功\n");
    152. cls=class_create(THIS_MODULE,"mychrdev");
    153. if(IS_ERR(cls))
    154. {
    155. printk("向上提交目录失败\n");
    156. goto out4;
    157. }
    158. printk("向上提交目录成功\n");
    159. int i;
    160. for(i=0;i<3;i++)
    161. {
    162. dev=device_create(cls,NULL,MKDEV(major,i),NULL,"myled%d",i);
    163. if(IS_ERR(dev))
    164. {
    165. printk("向上提交设备节点失败\n");
    166. goto out5;
    167. }
    168. }
    169. printk("向上提交设备节点成功\n");
    170. //寄存器映射以及初始化
    171. all_led_init();
    172. return 0;
    173. out5:
    174. for(--i;i>=0;i++)
    175. {
    176. device_destroy(cls,MKDEV(major,i));
    177. }
    178. class_destroy(cls);
    179. out4:
    180. cdev_del(cdev);
    181. out3:
    182. unregister_chrdev_region(MKDEV(major,minor),3);
    183. out2:
    184. kfree(cdev);
    185. out1:
    186. return ret;
    187. }
    188. static void __exit mycdev_exit(void)
    189. {
    190. //取消地址映射
    191. iounmap(vir_led1);
    192. iounmap(vir_led2);
    193. iounmap(vir_rcc);
    194. int i;
    195. for(i=0;i<3;i++)
    196. {
    197. device_destroy(cls,MKDEV(major,i));
    198. }
    199. class_destroy(cls);
    200. //注销字符设备驱动
    201. cdev_del(cdev);
    202. unregister_chrdev_region(MKDEV(major,minor),3);
    203. kfree(cdev);
    204. }
    205. module_init(mycdev_init);
    206. module_exit(mycdev_exit);
    207. MODULE_LICENSE("GPL");

    text.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. int fd;
    13. char name[20]={0};
    14. int a,b;
    15. while(1)
    16. {
    17. printf("请选择要控制的灯:1(LED1)2(LED2) 3(LED3)\n");
    18. printf("请输入>");
    19. scanf("%d",&b);
    20. switch(b)
    21. {
    22. case 1:
    23. strcpy(name,"/dev/myled0");
    24. break;
    25. case 2:
    26. strcpy(name,"/dev/myled1");
    27. break;
    28. case 3:
    29. strcpy(name,"/dev/myled2");
    30. break;
    31. }
    32. fd=open(name,O_RDWR);
    33. if(fd<0)
    34. {
    35. printf("打开设备文件失败\n");
    36. exit(-1);
    37. }
    38. //从终端读取
    39. printf("请输入要实现的功能:0(关灯) 1(开灯)\n");
    40. printf("请输入>");
    41. scanf("%d",&a);
    42. switch(a)
    43. {
    44. case 1:
    45. ioctl(fd,LED_ON);
    46. break;
    47. case 0:
    48. ioctl(fd,LED_OFF);
    49. break;
    50. }
    51. }
    52. close(fd);
    53. return 0;
    54. }

  • 相关阅读:
    axios详解以及完整封装方法
    20231008工作心得:sql
    探索 Java 8 中的 Stream 流:构建流的多种方式
    Authing 入选长城战略咨询《中国哪吒企业发展报告 2022》
    CountDownLatch
    初探亚马逊 AI 编程助手 CodeWhisperer
    【web安全】Nodejs原型链污染分析
    【机器学习基础】集成学习回顾及总结
    每日汇评:黄金形态确认牛市,再次尝试上行2000美元
    07 Spring事务
  • 原文地址:https://blog.csdn.net/xiaohuoxingdezhu/article/details/133997734