• 22071.11.20作业


    串口工具进行输入:   
        echo 1 > /dev/myled0 ---->led1灯点亮
        echo 0 > /dev/myled0 ---->led1灯熄灭
        echo 1 > /dev/myled1 ---->led2灯点亮
        echo 0 > /dev/myled1 ---->led2灯熄灭
        echo 1 > /dev/myled2 ---->led3灯点亮
        echo 0 > /dev/myled2 ---->led3灯熄灭
    要求:
        1)分部实现注册字符设备驱动
        2)自动创建设备节点
        3)通过结构体对led灯地址进行映射
        4)次设备号完成私有数据传参

    1. #ifndef __LED_H__
    2. #define __LED_H__
    3. #define CNAME "myled"
    4. typedef struct
    5. {
    6. volatile unsigned int MODER;
    7. volatile unsigned int OTYPER;
    8. volatile unsigned int OSPEEDR;
    9. volatile unsigned int PUPDR;
    10. volatile unsigned int IDR;
    11. volatile unsigned int ODR;
    12. }gpio_t;
    13. #define GPIOE (0x50006000)
    14. #define GPIOF (0x50007000)
    15. #define RCC (0x50000A28)
    16. #endif
    1. #include <linux/init.h>
    2. #include <linux/module.h>
    3. #include <linux/cdev.h>
    4. #include <linux/fs.h>
    5. #include <linux/device.h>
    6. #include <linux/slab.h>
    7. #include <linux/uaccess.h>
    8. #include <linux/io.h>
    9. #include "led.h"
    10. struct cdev *cdev;
    11. struct class *cls;
    12. struct device *dev;
    13. #if 1
    14. unsigned int major=0;
    15. #else
    16. unsigned int major=500;
    17. #endif
    18. int minor = 0;
    19. const int count = 3;
    20. volatile unsigned int* vir_rcc;
    21. volatile gpio_t* vir_gpioe;
    22. volatile gpio_t* vir_gpiof;
    23. int mycdev_open(struct inode *inode,struct file *file)
    24. {
    25. file->private_data = (void*)(MINOR(inode->i_rdev));
    26. printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    27. return 0;
    28. }
    29. ssize_t mycdev_read(struct file *file,char __user *ubuf,size_t size,loff_t *loffs)
    30. {
    31. printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    32. return 0;
    33. }
    34. ssize_t mycdev_write(struct file *file,const char __user *ubuf,size_t size,loff_t *loffs)
    35. {
    36. char kbuf;
    37. int ret;
    38. int a;
    39. a = (int)file->private_data;
    40. ret = copy_from_user(&kbuf,ubuf,sizeof(char));
    41. if(ret)
    42. {
    43. printk("copy from user is error...\n");
    44. return -EIO;
    45. }
    46. if(kbuf=='1')
    47. {
    48. switch (a)
    49. {
    50. case 0:
    51. vir_gpioe->ODR |= (0x1<<10);
    52. break;
    53. case 1:
    54. vir_gpiof->ODR |= (0x1<<10);
    55. break;
    56. case 2:
    57. vir_gpioe->ODR |= (0x1<<8);
    58. break;
    59. default:
    60. break;
    61. }
    62. }
    63. else
    64. {
    65. switch (a)
    66. {
    67. case 0:
    68. vir_gpioe->ODR &= (~(0x1<<10));
    69. break;
    70. case 1:
    71. vir_gpiof->ODR &= (~(0x1<<10));
    72. break;
    73. case 2:
    74. vir_gpioe->ODR &= (~(0x1<<8));
    75. break;
    76. default:
    77. break;
    78. }
    79. }
    80. printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    81. return 0;
    82. }
    83. int mycdev_close(struct inode *inode,struct file *file)
    84. {
    85. printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    86. return 0;
    87. }
    88. const struct file_operations fops = {
    89. .open=mycdev_open,
    90. .write=mycdev_write,
    91. .read=mycdev_read,
    92. .release=mycdev_close,
    93. };
    94. static int __init mycdev_init(void)
    95. {
    96. int i;
    97. int ret;
    98. dev_t devt;
    99. //分步实现字符设备驱动
    100. cdev = cdev_alloc();
    101. if(NULL==cdev)
    102. {
    103. printk("cdev alloc is error...\n");
    104. goto ERR1;
    105. }
    106. cdev_init(cdev,&fops);
    107. if(major>0)
    108. {
    109. ret = register_chrdev_region(MKDEV(major,minor),count,CNAME);
    110. if(ret)
    111. {
    112. printk("register chrdev region is error...\n");
    113. goto ERR2;
    114. }
    115. }
    116. else
    117. {
    118. ret = alloc_chrdev_region(&devt,0,count,CNAME);
    119. if(ret)
    120. {
    121. printk("alloc chrdev region is error\n");
    122. goto ERR2;
    123. }
    124. major=MAJOR(devt);
    125. minor=MINOR(devt);
    126. }
    127. ret = cdev_add(cdev,MKDEV(major,minor),count);
    128. if(ret)
    129. {
    130. printk("cdev add is error...\n");
    131. goto ERR3;
    132. }
    133. //自动创建设备节点
    134. cls = class_create(THIS_MODULE,CNAME);
    135. if(IS_ERR(cls))
    136. {
    137. printk("class create is error...\n");
    138. ret = PTR_ERR(cls);
    139. goto ERR4;
    140. }
    141. for(i=0;i<count;i++)
    142. {
    143. dev = device_create(cls,NULL,MKDEV(major,i),NULL,"myled%d",i);
    144. if(IS_ERR(dev))
    145. {
    146. printk("device create is error...\n");
    147. goto ERR5;
    148. }
    149. }
    150. //对LED灯地址进行映射
    151. vir_rcc = ioremap(RCC,4);
    152. if(NULL==vir_rcc)
    153. {
    154. printk("rcc ioremap is error\n");
    155. return -ENOMEM;
    156. }
    157. vir_gpioe = ioremap(GPIOE,sizeof(GPIOE));
    158. if(NULL==vir_gpioe)
    159. {
    160. printk("gpioe ioremap is error\n");
    161. return -ENOMEM;
    162. }
    163. vir_gpiof = ioremap(GPIOF,sizeof(GPIOF));
    164. if(NULL==vir_gpiof)
    165. {
    166. printk("gpiof ioremap is error\n");
    167. return -ENOMEM;
    168. }
    169. *vir_rcc |= (0x3<<4);
    170. vir_gpioe->MODER &= (~(0x3<<20));
    171. vir_gpioe->MODER |= (0x1<<20);
    172. vir_gpiof->MODER &= (~(0x3<<20));
    173. vir_gpiof->MODER |= (0x1<<20);
    174. vir_gpioe->MODER &= (~(0x3<<16));
    175. vir_gpioe->MODER |= (0x1<<16);
    176. return 0;
    177. ERR5:
    178. for(--i;i>=0;i--)
    179. {
    180. device_destroy(cls,MKDEV(major,i));
    181. }
    182. class_destroy(cls);
    183. ERR4:
    184. cdev_del(cdev);
    185. ERR3:
    186. unregister_chrdev_region(MKDEV(major,minor),count);
    187. ERR2:
    188. kfree(cdev);
    189. ERR1:
    190. return -EIO;
    191. }
    192. static void __exit mycdev_exit(void)
    193. {
    194. int i;
    195. for(i=0;i<count;i++)
    196. {
    197. device_destroy(cls,MKDEV(major,i));
    198. }
    199. class_destroy(cls);
    200. cdev_del(cdev);
    201. unregister_chrdev_region(MKDEV(major,minor),count);
    202. kfree(cdev);
    203. //取消映射
    204. iounmap(vir_rcc);
    205. iounmap(vir_gpioe);
    206. iounmap(vir_gpiof);
    207. }
    208. module_init(mycdev_init);
    209. module_exit(mycdev_exit);
    210. MODULE_LICENSE("GPL");

    现象:

     

     

  • 相关阅读:
    [BJDCTF2020]EasySearch
    【python】list 删除列表中某个元素的3种方法;附加删除numpy数组中的指定索引元素的方法
    2024北京护眼产品展/北京眼视光展/北京叶黄素展/中国眼博会
    多智能体强化学习(MARL)研究汇总:行为分析、通信学习、协作学习、智能体建模
    【网络】HTTP协议详解
    jmeter
    FlinkSQL自定义函数开发
    linux删除软件
    配置Jenkins
    适合弱电行业用的项目管理系统,找企智汇项目管理系统!
  • 原文地址:https://blog.csdn.net/brightmante/article/details/127951077