• 驱动开发课程LED点亮


    head.h

    1. #ifndef __HEAD_H__
    2. #define __HEAD_H__
    3. #define PHY_LED1_MODER 0X50006000
    4. #define PHY_LED2_MODER 0x50007000
    5. #define PHY_LED1_ODR 0X50006014
    6. #define PHY_LED2_ODR 0x50007014
    7. #define PHY_RCC 0X50000A28
    8. #endif

    test.c

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. int main(int argc, char const *argv[])
    8. {
    9. char buf[128] = {0};
    10. int fd = open("/dev/mychrdev", O_RDWR);
    11. if (fd < 0)
    12. {
    13. printf("打开设备文件失败\n");
    14. return -1;
    15. }
    16. printf("打开设备文件成功\n");
    17. while (1)
    18. {
    19. printf("请输入要进行的操作:0(关灯)1(LED1开)2(LED2开)3(LED3开)>");
    20. fgets(buf, sizeof(buf), stdin); // 在终端读一个字符串
    21. buf[strlen(buf) - 1] = '\0';
    22. write(fd, buf, sizeof(buf)); // 将数据传递给内核
    23. }
    24. close(fd);
    25. return 0;
    26. }

    demo.c

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include "head.h"
    7. unsigned int major;
    8. char kbuf[128] = {};
    9. // 定义三个指针指向映射后的虚拟内存
    10. unsigned int *vir_moder;
    11. unsigned int *vir_moder2;
    12. unsigned int *vir_odr;
    13. unsigned int *vir_odr2;
    14. unsigned int *vir_rcc;
    15. // 封装操作方法
    16. int mycdev_open(struct inode *inode, struct file *file)
    17. {
    18. printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    19. return 0;
    20. }
    21. ssize_t mycdev_read(struct file *file, char *ubuf, size_t size, loff_t *lof)
    22. {
    23. printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    24. int ret;
    25. ret = copy_to_user(ubuf, kbuf, size);
    26. if (ret)
    27. {
    28. printk("copy_to_user filed\n");
    29. return -EIO;
    30. }
    31. return 0;
    32. }
    33. ssize_t mycdev_write(struct file *file, const char *ubuf, size_t size, loff_t *lof)
    34. {
    35. printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    36. int ret;
    37. ret = copy_from_user(kbuf, ubuf, size);
    38. if (ret)
    39. {
    40. printk("copy_from_user filed\n");
    41. return -EIO;
    42. }
    43. if (kbuf[0] == '0') // 关灯
    44. {
    45. // 关灯逻辑
    46. (*vir_odr) &= (~(0X1<<10));//默认关灯
    47. (*vir_odr2) &= (~(0X1<<10));//默认关灯
    48. (*vir_odr) &= (~(0X1<<8));//默认关灯
    49. }
    50. else if (kbuf[0] == '1')
    51. {
    52. // 开灯逻辑
    53. (*vir_odr) |= (0X1<<10);
    54. }
    55. else if (kbuf[0] == '2')
    56. {
    57. // 开灯逻辑
    58. (*vir_odr2) |= (0X1<<10);
    59. }
    60. else if (kbuf[0] == '3')
    61. {
    62. // 开灯逻辑
    63. (*vir_odr) |= (0X1<<8);
    64. }
    65. return 0;
    66. }
    67. int mycdev_close(struct inode *inode, struct file *file)
    68. {
    69. printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    70. return 0;
    71. }
    72. // 定义操作方法结构体对象
    73. struct file_operations fops = {
    74. .open = mycdev_open,
    75. .read = mycdev_read,
    76. .write = mycdev_write,
    77. .release = mycdev_close,
    78. };
    79. static int __init mycdev_init(void)
    80. {
    81. // 注册字符设备驱动
    82. major = register_chrdev(0, "mychrdev", &fops);
    83. if (major < 0)
    84. {
    85. printk("字符设备驱动注册失败\n");
    86. return major;
    87. }
    88. printk("注册字符设备驱动成功major=%d\n", major);
    89. // 进行寄存器的地址映射
    90. vir_moder = ioremap(PHY_LED1_MODER, 4);
    91. if (vir_moder == NULL)
    92. {
    93. printk("物理内存地址映射失败%d\n", __LINE__);
    94. return -EFAULT;
    95. }
    96. vir_moder2 = ioremap(PHY_LED2_MODER, 4);
    97. if (vir_moder == NULL)
    98. {
    99. printk("物理内存地址映射失败%d\n", __LINE__);
    100. return -EFAULT;
    101. }
    102. vir_odr = ioremap(PHY_LED1_ODR, 4);
    103. if (vir_odr == NULL)
    104. {
    105. printk("物理内存地址映射失败%d\n", __LINE__);
    106. return -EFAULT;
    107. }
    108. vir_odr2 = ioremap(PHY_LED2_ODR, 4);
    109. if (vir_odr == NULL)
    110. {
    111. printk("物理内存地址映射失败%d\n", __LINE__);
    112. return -EFAULT;
    113. }
    114. vir_rcc = ioremap(PHY_RCC, 4);
    115. if (vir_rcc == NULL)
    116. {
    117. printk("物理内存地址映射失败%d\n", __LINE__);
    118. return -EFAULT;
    119. }
    120. printk("寄存器内存映射成功\n");
    121. //LED1寄存器初始化
    122. (*vir_rcc) |= (0X1<<4);//GPIOE控制器时钟使能
    123. (*vir_rcc) |= (0X1<<5);//GPIOE控制器时钟使能
    124. (*vir_moder) &= (~(0X3<<20));//MODER[21:20]->00
    125. (*vir_moder) |= (0X1<<20);//MODER[21:20]->01
    126. (*vir_moder) &= (~(0X3<<16));//MODER[21:20]->00
    127. (*vir_moder) |= (0X1<<16);//MODER[21:20]->01
    128. (*vir_moder2) &= (~(0X3<<20));//MODER[21:20]->00
    129. (*vir_moder2) |= (0X1<<20);//MODER[21:20]->01
    130. (*vir_odr) &= (~(0X1<<10));//默认关灯
    131. (*vir_odr) &= (~(0X1<<8));//默认关灯
    132. (*vir_odr2) &= (~(0X1<<10));//默认关灯
    133. return 0;
    134. }
    135. static void __exit mycdev_exit(void)
    136. {
    137. //取消内存映射
    138. iounmap(vir_moder);
    139. iounmap(vir_odr);
    140. iounmap(vir_rcc);
    141. iounmap(vir_moder2);
    142. iounmap(vir_odr2);
    143. // 注销字符设备驱动
    144. unregister_chrdev(major, "mychrdev");
    145. }
    146. module_init(mycdev_init);
    147. module_exit(mycdev_exit);
    148. MODULE_LICENSE("GPL");

    现象:

  • 相关阅读:
    系统提示缺少或找不到msvcp140.dll文件的解决方法
    ipad下载的文件在哪里可以找到
    简单的人脸识别实战
    状态模式详解
    大数据之LibrA数据库系统服务部署原则及运行环境要求
    Node.js学习篇(三)安装express编写get和post请求及安装nodemon
    Redis为什么快?
    ArrayUtils使用
    Set集合
    AD教程 (十)Value值的核对
  • 原文地址:https://blog.csdn.net/CenZywush/article/details/133953132