• 驱动编写LED灯


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

    text.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(开灯)>");
    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. }

    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

    makefile

    1. modname ?= demo
    2. arch ?= arm
    3. ifeq ($(arch),arm)
    4. #KERNELDIR保存开发板内核源码路径
    5. KERNELDIR := /home/ubuntu/linux-5.10.61/
    6. else
    7. #保存UBUNTU内核
    8. KERNELDIR :=/lib/modules/$(shell uname -r)/build
    9. #KERNELDIR :=/lib/modules/5.3.0-28-generic/build
    10. endif
    11. #PWD保存当前内核模块的路径
    12. PWD := $(shell pwd)
    13. #PWD := /home/ubuntu/qudong/day1
    14. all:
    15. #make modules是模块化编译命令
    16. #make -C $(KERNLEDIR)执行make之前先切换到KERNELDIR对应的路径
    17. #M=$(PWD)表示进行模块化编译的路径是PwD保存的路径
    18. make -C $(KERNELDIR) M=$(PWD) modules
    19. clean:
    20. #编译清除
    21. make -C $(KERNELDIR) M=$(PWD) clean
    22. #将obj-m保存的文件单独链接为内核模块
    23. obj-m := $(modname).o

  • 相关阅读:
    UE4 UltraDynamicSky 天气与水体交互
    关于一篇“范式详解”博文的批注
    在Ubuntu中启用root用户登录SSH
    ZEMAX | 如何使用渐晕系数
    Python3 - Docker图像化管理工具之Portainer
    02.OpenWrt-进入开发板系统
    Java Stack 类
    【软件测试】测试人,被裁后已失业大半年该如何破局?
    笔试强训48天——day23
    第七章-项目成本管理
  • 原文地址:https://blog.csdn.net/zky050213/article/details/133953492