• 嵌入式:驱动开发 Day2


    作业:字符设备驱动,完成三盏LED灯的控制

    驱动代码: mychrdev.c

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include "head.h"
    7. unsigned int major; //保存主设备号
    8. char kbuf[128] = "";
    9. unsigned int *vir_moder_e;
    10. unsigned int *vir_odr_e;
    11. unsigned int *vir_rcc_e;
    12. unsigned int *vir_moder_f;
    13. unsigned int *vir_odr_f;
    14. unsigned int *vir_rcc_f;
    15. //封装操作方法
    16. int mycdev_open(struct inode *inode, struct file *file){
    17. printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    18. return 0;
    19. }
    20. ssize_t mycdev_read(struct file *file, char *ubuf, size_t size, loff_t *lof){
    21. int ret;
    22. ret = copy_to_user(ubuf, kbuf, size);
    23. if(ret){
    24. printk("copy_to_user err\n");
    25. return -EIO;
    26. }
    27. return 0;
    28. }
    29. ssize_t mycdev_write(struct file *file, const char *ubuf, size_t size, loff_t *lof){
    30. int ret;
    31. ret = copy_from_user(kbuf, ubuf, size);
    32. if(ret){
    33. printk("copy_from_user err\n");
    34. return -EIO;
    35. }
    36. if(kbuf[0] == '1') //led1开灯
    37. {
    38. //开灯逻辑
    39. (*vir_odr_e) |= (0x1 << 10);
    40. }else if(kbuf[0] == '2'){ //led1关灯
    41. //关灯逻辑
    42. (*vir_odr_e) &= (~(0x1 << 10));
    43. }else if(kbuf[0] == '3'){ //led2开灯
    44. //开灯逻辑
    45. (*vir_odr_f) |= (0x1 << 10);
    46. }else if(kbuf[0] == '4'){ //led2关灯
    47. //关灯逻辑
    48. (*vir_odr_f) &= (~(0x1 << 10));
    49. }else if(kbuf[0] == '5'){ //led3开灯
    50. //开灯逻辑
    51. (*vir_odr_e) |= (0x1 << 8);
    52. }else if(kbuf[0] == '6'){ //led3关灯
    53. //关灯逻辑
    54. (*vir_odr_e) &= (~(0x1 << 8));
    55. }
    56. return 0;
    57. }
    58. int mycdev_close(struct inode *inode, struct file *file){
    59. printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    60. return 0;
    61. }
    62. //定义一个操作方法结构体对象并初始化
    63. struct file_operations fops = {
    64. .open = mycdev_open,
    65. .read = mycdev_read,
    66. .write = mycdev_write,
    67. .release = mycdev_close,
    68. };
    69. static int __init mycdev_init(void){
    70. //字符设备驱动的注册
    71. major = register_chrdev(0, "mychrdev", &fops);
    72. if(major < 0){
    73. printk("字符设备驱动注册失败\n");
    74. return major;
    75. }
    76. printk("字符设备驱动注册成功 major = %d\n", major);
    77. //进行相关寄存器的内存映射
    78. //GPIOE组寄存器内存映射
    79. vir_odr_e = ioremap(GPIOE_ODR, 4);
    80. if(vir_odr_e == NULL){
    81. printk("物理内存映射失败%d\n", __LINE__);
    82. return -EFAULT;
    83. }
    84. vir_rcc_e = ioremap(GPIOE_RCC, 4);
    85. if(vir_rcc_e == NULL){
    86. printk("物理内存映射失败%d\n", __LINE__);
    87. return -EFAULT;
    88. }
    89. vir_moder_e = ioremap(GPIOE_MODER, 4);
    90. if(vir_moder_e == NULL){
    91. printk("物理内存映射失败%d\n", __LINE__);
    92. return -EFAULT;
    93. }
    94. //GPIOF组寄存器内存映射
    95. vir_odr_f = ioremap(GPIOF_ODR, 4);
    96. if(vir_odr_f == NULL){
    97. printk("物理内存映射失败%d\n", __LINE__);
    98. return -EFAULT;
    99. }
    100. vir_rcc_f = ioremap(GPIOF_RCC, 4);
    101. if(vir_rcc_f == NULL){
    102. printk("物理内存映射失败%d\n", __LINE__);
    103. return -EFAULT;
    104. }
    105. vir_moder_f = ioremap(GPIOF_MODER, 4);
    106. if(vir_moder_f == NULL){
    107. printk("物理内存映射失败%d\n", __LINE__);
    108. return -EFAULT;
    109. }
    110. printk("寄存器内存映射成功\n");
    111. //硬件寄存器的初始化
    112. //RCC使能
    113. (*vir_rcc_e) |= (0x1 << 4); //GPIOE(PE10 PE8)使能
    114. (*vir_rcc_f) |= (0x1 << 5); //GPIOF(PF10)使能
    115. //设置PE10为输出模式 --> LED1
    116. (*vir_moder_e) &= (~(0x3 << 20));
    117. (*vir_moder_e) |= (0x1 << 20);
    118. //设置PF10为输出模式 --> LED2
    119. (*vir_moder_f) &= (~(0x3 << 20));
    120. (*vir_moder_f) |= (0x1 << 20);
    121. //设置PE8为输出模式 --> LED3
    122. (*vir_moder_e) &= (~(0x3 << 16));
    123. (*vir_moder_e) |= (0x1 << 16);
    124. //默认LED1关灯
    125. (*vir_odr_e) &= (~(0x1 << 10));
    126. //默认LED2关灯
    127. (*vir_odr_f) &= (~(0x1 << 10));
    128. //默认LED1关灯
    129. (*vir_odr_e) &= (~(0x1 << 8));
    130. return 0;
    131. }
    132. static void __exit mycdev_exit(void){
    133. //取消物理内存映射
    134. iounmap(vir_moder_e);
    135. iounmap(vir_odr_e);
    136. iounmap(vir_rcc_e);
    137. iounmap(vir_moder_f);
    138. iounmap(vir_odr_f);
    139. iounmap(vir_rcc_f);
    140. //字符设备驱动注销
    141. unregister_chrdev(major, "mychrdev");
    142. }
    143. module_init(mycdev_init);
    144. module_exit(mycdev_exit);
    145. MODULE_LICENSE("GPL");

    应用代码:test.c

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. int main(){
    9. char buf[128] = "";
    10. int fd = open("/dev/mychrdev", O_RDWR);
    11. if(fd < 0){
    12. printf("设备文件打开失败\n");
    13. exit(-1);
    14. }
    15. while(1){
    16. printf("请输入对LED的控制命令:1(LED1开灯) 2(LED1关灯) 3(LED2开灯) 4(LED2关灯) 5(LED3开灯) 6(LED3关灯) >");
    17. fgets(buf, sizeof(buf), stdin); //在终端输入数据传递到buf
    18. buf[strlen(buf) - 1] = '\0'; //替换末尾的'\n'
    19. write(fd, buf, sizeof(buf));
    20. }
    21. close(fd);
    22. return 0;
    23. }

    头文件:head.h

    1. #ifndef __HEAD_H__
    2. #define __HEAD_H__
    3. #define GPIOE_MODER 0x50006000
    4. #define GPIOE_ODR 0x50006014
    5. #define GPIOE_RCC 0x50000A28
    6. #define GPIOF_MODER 0x50007000
    7. #define GPIOF_ODR 0x50007014
    8. #define GPIOF_RCC 0x50000A28
    9. #endif

  • 相关阅读:
    AndroidStudio电脑连接手机后但AndroidStudio识别不到
    第十章:枚举和注解
    Kotlin 中的 apply 函数详解
    使用STM32CubeMX实现按下按键,电平反转
    正点原子linux——BSP工程管理实验-编写通用Makefile
    【AI】量子计算机与人工智能
    玻色量子“天工量子大脑”亮相中关村论坛,大放异彩
    Python数据分析-Numpy
    视频如何拼接?建议收藏这些方法
    Java的IO框架
  • 原文地址:https://blog.csdn.net/jx4252/article/details/132795660