• 驱动开发day2


    通过物理内存映射为虚拟内存 实现三盏LED灯亮灯灭

    head.h

    1. #ifndef __HEAD_H__
    2. #define __HEAD_H__
    3. #define PHY_LED1_MODER 0X50006000
    4. #define PHY_LED1_ODR 0X50006014
    5. #define PHY_RCC 0x50000A28
    6. #define PHY_LED2_MODER 0X50007000
    7. #define PHY_LED2_ODR 0X50007014
    8. #define PHY_LED3_MODER 0X50006000
    9. #define PHY_LED3_ODR 0X50006014
    10. #endif

    test.c

    1. #include <stdio.h>
    2. #include <sys/types.h>
    3. #include <sys/stat.h>
    4. #include <fcntl.h>
    5. #include <unistd.h>
    6. #include <string.h>
    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. close(fd);
    25. return 0;
    26. }

    demo.c

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

  • 相关阅读:
    【Redis】数据结构---String
    岩土工程监测中无线振弦采集仪的高精度高稳定性的重要性
    U-Net 模型改进和应用场景研究性综述
    07_整合spring boot
    作业错题一
    [黑马程序员Pandas教程]——Pandas常用计算函数
    java计算机毕业设计京东仓库管理系统源码+mysql数据库+系统+lw文档+部署
    OTN网络技术—(OTUk、ODUk、OPUk)OTN速率解析
    基于北方苍鹰优化算法的函数寻优算法
    第一章 基础算法
  • 原文地址:https://blog.csdn.net/Meng_fighting/article/details/133953547