• 驱动day2:LED灯实现三盏灯的亮灭


    head.h

    1. #ifndef __HEAD_H__
    2. #define __HEAD_H__
    3. #define PHY_PE_MODER 0x50006000
    4. #define PHY_PF_MODER 0x50007000
    5. #define PHY_PE_ODR 0x50006014
    6. #define PHY_PF_ODR 0x50007014
    7. #define PHY_RCC 0x50000A28
    8. #endif

    应用程序

    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 (开灯)>");
    20. fgets(buf,sizeof(buf),stdin); //在终端读一个字符串
    21. buf[strlen(buf) - 1] = '\0';
    22. write(fd,buf,sizeof(buf));//将数据传递给内核
    23. }
    24. /*
    25. fgets(buf,sizeof(buf),stdin); //在终端读一个字符串
    26. buf[strlen(buf) - 1] = '\0';
    27. write(fd,buf,sizeof(buf));//将数据传递给内核
    28. memset(buf, 0, sizeof(buf)); //清空数组
    29. read(fd,buf,sizeof(buf)); //将内核数据传递给用户
    30. printf("buf: %s\n", buf);
    31. */
    32. close(fd);
    33. return 0;
    34. }

    驱动程序

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

    实现效果

  • 相关阅读:
    猿创征文 | 基于H5实现跨文档通信 & websocket
    泰山OFFICE技术讲座:文字边框高度研究
    Lock锁:ReentrantLock的可打断和可重入特性
    2023下半年软考各地区准考证打印时间汇总
    aws lakeformation工作流程和权限管理逻辑
    【数据库07】后端开发必备的大数据知识指南
    【PWN · heap | Off-By-One】Asis CTF 2016 b00ks
    面向对象(类/继承/封装/多态)详解
    企业数据流动安全管理软件(深度解析文章)
    C++桶排序算法的应用:存在重复元素 III
  • 原文地址:https://blog.csdn.net/m0_64588047/article/details/133953992