• 华清远见(上海中心)


    日期:11月19日             

     

    一、题目

    1. 在串口工具进行输入:   
        echo 1 > /dev/myled0 ---->led1灯点亮
        echo 0 > /dev/myled0 ---->led1灯熄灭
        echo 1 > /dev/myled1 ---->led1灯点亮
        echo 0 > /dev/myled1 ---->led1灯熄灭
        echo 1 > /dev/myled2 ---->led1灯点亮
        echo 0 > /dev/myled2 ---->led1灯熄灭

    代码实现:

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include "mycdev.h"
    9. #define CNAME "myled"
    10. struct cdev *cdev;
    11. struct class *cls;
    12. struct device *device;
    13. dev_t dev;
    14. int *virt_RCC;
    15. gpio_t *virt_GPIOE;
    16. gpio_t *virt_GPIOF;
    17. unsigned int major;
    18. unsigned int minor = 0;
    19. unsigned int count=3;
    20. char buf[128]={0};
    21. int myc_open(struct inode *inode, struct file *file)
    22. {
    23. minor = MINOR(inode->i_rdev);
    24. file->private_data = (void*)minor;
    25. return 0;
    26. }
    27. ssize_t myc_read(struct file *file, char __user *user, size_t size, loff_t *ft)
    28. {
    29. return 0;
    30. }
    31. ssize_t myc_write(struct file *file, const char __user *user, size_t size, loff_t *ft)
    32. {
    33. int ret;
    34. minor = ((int*)file->private_data);
    35. if(size > sizeof(user)) size = sizeof(buf);
    36. ret = copy_from_user(buf,user,sizeof(user));
    37. if(ret)
    38. {
    39. printk("copy from user is error\n");
    40. return -EIO;
    41. }
    42. switch(minor)
    43. {
    44. case LED1:
    45. if(buf[0]=='1')
    46. {
    47. virt_GPIOE->ODR |=(0x1<<10);
    48. }
    49. else
    50. {
    51. virt_GPIOE->ODR &=(~(0x1<<10));
    52. }
    53. break;
    54. case LED2:
    55. if(buf[0]=='1')
    56. {
    57. virt_GPIOF->ODR |=(0x1<<10);
    58. }
    59. else
    60. {
    61. virt_GPIOF->ODR &=(~(0x1<<10));
    62. }
    63. break;
    64. case LED3:
    65. if(buf[0]=='1')
    66. {
    67. virt_GPIOE->ODR |=(0x1<<8);
    68. }
    69. else
    70. {
    71. virt_GPIOE->ODR &=(~(0x1<<8));
    72. }
    73. break;
    74. }
    75. return 0;
    76. }
    77. int myc_close(struct inode *inode, struct file *file)
    78. {
    79. return 0;
    80. }
    81. const struct file_operations fops ={
    82. .open=myc_open,
    83. .read=myc_read,
    84. .write=myc_write,
    85. .release=myc_close,
    86. };
    87. static int __init mycdev_init(void)
    88. {
    89. int ret;
    90. int i;
    91. //映射虚拟地址
    92. virt_RCC = ioremap(RCC_ENABLE,sizeof(int));
    93. virt_GPIOE = ioremap(GPIOE,sizeof(gpio_t));
    94. virt_GPIOF = ioremap(GPIOF,sizeof(gpio_t));
    95. //1.分配cdev结构体
    96. cdev = cdev_alloc();
    97. if(NULL == cdev)
    98. {
    99. printk("cdev alloc is error\n");
    100. printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    101. ret = -EIO;
    102. goto ERR1;
    103. }
    104. //2.初始化结构体
    105. cdev_init(cdev,&fops);
    106. //3.申请设备号
    107. ret = alloc_chrdev_region(&dev,minor,count,CNAME);
    108. if(ret)
    109. {
    110. printk("alloc chrdev region is filed\n");
    111. printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    112. ret = -ENOMEM;
    113. goto ERR2;
    114. }
    115. //4.驱动的注册
    116. ret = cdev_add(cdev,dev,count);
    117. if(ret)
    118. {
    119. printk("cdev add is filed\n");
    120. printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    121. ret = -ENOMEM;
    122. goto ERR3;
    123. }
    124. //5.自动创建设备节点
    125. //向上层提交目录信息
    126. cls = class_create(THIS_MODULE,CNAME);
    127. if(IS_ERR(cls))
    128. {
    129. printk("class create is failed\n");
    130. ret = PTR_ERR(cls);
    131. goto ERR4;
    132. }
    133. //向上层提交设备节点
    134. major = MAJOR(dev);
    135. minor = MINOR(dev);
    136. for(i=0;i
    137. {
    138. device = device_create(cls,NULL,MKDEV(major,i),NULL,"myled%d",i);
    139. if(IS_ERR(device))
    140. {
    141. printk("device create is error\n");
    142. ret = PTR_ERR(device);
    143. goto ERR5;
    144. }
    145. }
    146. //LED灯初始化
    147. //将PE10引脚初始化
    148. //RCC使能
    149. *virt_RCC |=(0x1<<4);
    150. //将GPIOE_MODER设置为输出模式
    151. virt_GPIOE->MODER &=(~(0x3<<20));
    152. virt_GPIOE->MODER |=(0x1<<20);
    153. //将GPIOE_ODR设置为低电平
    154. virt_GPIOE->ODR &=(~(0x1<<10));
    155. //将PF10引脚初始化
    156. //RCC使能
    157. *virt_RCC |=(0x1<<5);
    158. //将GPIOE_MODER设置为输出模式
    159. virt_GPIOF->MODER &=(~(0x3<<20));
    160. virt_GPIOF->MODER |=(0x1<<20);
    161. //将GPIOE_ODR设置为低电平
    162. virt_GPIOF->ODR &=(~(0x1<<10));
    163. //将PE8引脚初始化
    164. //RCC使能
    165. *virt_RCC |=(0x1<<4);
    166. //将GPIOE_MODER设置为输出模式
    167. virt_GPIOE->MODER &=(~(0x3<<16));
    168. virt_GPIOE->MODER |=(0x1<<16);
    169. //将GPIOE_ODR设置为低电平
    170. virt_GPIOE->ODR &=(~(0x1<<8));
    171. return 0;
    172. ERR5:
    173. for(--i;i>=0;i--)
    174. {
    175. device_destroy(cls,MKDEV(major,i));
    176. }
    177. class_destroy(cls);
    178. ERR4:
    179. cdev_del(cdev);
    180. ERR3:
    181. unregister_chrdev_region(dev,count);
    182. ERR2:
    183. kfree(cdev);
    184. ERR1:
    185. return -EIO;
    186. }
    187. static void __exit mycdev_exit(void)
    188. {
    189. int i;
    190. //取消映射
    191. iounmap(virt_GPIOE);
    192. iounmap(virt_GPIOF);
    193. //1.销毁设备节点信息
    194. for(i=0;i
    195. {
    196. device_destroy(cls,MKDEV(major,i));
    197. }
    198. //2.销毁目录信息
    199. class_destroy(cls);
    200. //3.驱动的注销
    201. cdev_del(cdev);
    202. //4.销毁设备号
    203. unregister_chrdev_region(dev,count);
    204. //5.释放cdev结构体
    205. kfree(cdev);
    206. }
    207. module_init(mycdev_init);
    208. module_exit(mycdev_exit);
    209. MODULE_LICENSE("GPL");
    1. #ifndef __MYCDEV_H__
    2. #define __MYCDEV_H__
    3. typedef struct{
    4. volatile unsigned int MODER;
    5. volatile unsigned int OTYPER;
    6. volatile unsigned int OSPEEDR;
    7. volatile unsigned int PUPDR;
    8. volatile unsigned int IDR;
    9. volatile unsigned int ODR;
    10. }gpio_t;
    11. typedef enum{
    12. LED1,
    13. LED2,
    14. LED3
    15. }led_t;
    16. #define RCC_ENABLE 0x50000A28
    17. #define GPIOE 0x50006000
    18. #define GPIOF 0x50007000
    19. #endif
    1. #指定架构变量名
    2. ARCH?=x86
    3. #指定编译文件名
    4. modname?=demo
    5. ifeq ($(ARCH),arm)
    6. #定义一个变量,存放linux内核源码的路径,编译完成之后,生成ARM架构,在开发板运行
    7. KERNEDIR:=/home/ubuntu/linux-5.10.61
    8. else
    9. #定义一个变量,存放ubuntu中linux内核源码的路径,编译完成之后,生成X86架构,在开发板运行
    10. KERNEDIR:=/lib/modules/$(shell uname -r)/build
    11. endif
    12. #PWD是自己定义的一个变量,$(shell pwd)开启一个终端,执行pwd命令,将执行的结果赋值给PWD变量
    13. PWD:=$(shell pwd)
    14. KBUILD_EXTRA_SYMBOLS:=/home/ubuntu/驱动/drivers/mydriver/02_EXPORT/demoA/Module.symvers
    15. all:
    16. make -C $(KERNEDIR) M=$(PWD) modules
    17. clean:
    18. make -C $(KERNEDIR) M=$(PWD) clean
    19. #指定模块化方式编译的文件
    20. obj-m:=$(modname).o

    现象实现:

    LED1:

     LED2:

     

    LED3:

     

     

     

  • 相关阅读:
    java中String,StringBuilder,StringBuffer实现原理,优化
    STM32F103实现激光测距传感器测距WT-VL53L0 L1
    手把手教你用nodejs+SQL Server2012做增删改查
    Python 推导式
    增速冠军 | 超云AI与信创实践典范,引领IDC中国服务器市场
    adb调试系统app
    蓝/紫/红色光油溶性钙钛矿/近红外发射光油溶性PbS/CdS量子点制备
    【React】表单
    【最佳实践】瀚高数据库企业版v6.0.2在Centos7.8安装过程
    苹果Mac优化清理工具CleanMyMac X2023版本
  • 原文地址:https://blog.csdn.net/qq_58538047/article/details/127936732