• 驱动day4


    头文件

    1. #ifndef __HEAD_H__
    2. #define __HEAD_H__
    3. typedef struct{
    4. unsigned int MODER;
    5. unsigned int OTYPER;
    6. unsigned int OSPEEDR;
    7. unsigned int PUPDR;
    8. unsigned int IDR;
    9. unsigned int ODR;
    10. }gpio_t;
    11. #define PHY_LED1_ADDR 0X50006000
    12. #define PHY_LED2_ADDR 0X50007000
    13. #define PHY_LED3_ADDR 0X50006000
    14. #define PHY_RCC_ADDR 0X50000A28
    15. // 构建开灯关灯的功能码
    16. #define LED_ON _IOW('l', 1,int)
    17. #define LED_OFF _IOW('l', 0,int)
    18. #endif

    运行代码

    1. #include<stdlib.h>
    2. #include<stdio.h>
    3. #include <sys/types.h>
    4. #include <sys/stat.h>
    5. #include <sys/ioctl.h>
    6. #include <fcntl.h>
    7. #include<unistd.h>
    8. #include<string.h>
    9. #include "head.h"
    10. int main(int argc, char const *argv[])
    11. {
    12. char buf[128]={0};
    13. int a,b,fd;
    14. if(fd<0)
    15. {
    16. printf("打开设备文件失败\n");
    17. exit(-1);
    18. }
    19. while(1)
    20. {
    21. fd=-1;
    22. //从终端读取
    23. printf("请输入要实现的功能 ");
    24. printf("0(关灯) 1(开灯)\n");
    25. printf("请输入>");
    26. scanf("%d",&a);
    27. printf("请选择要控制的灯:1(LED1)2(LED2) 3(LED3)\n");
    28. printf("请输入>");
    29. scanf("%d",&b);
    30. switch(b)
    31. {
    32. case 1:
    33. fd=open("/dev/burger0",O_RDWR);
    34. if(a == 0)
    35. {
    36. ioctl(fd,LED_ON,&b);
    37. break;
    38. }
    39. else
    40. {
    41. ioctl(fd,LED_OFF,&b);
    42. break;
    43. }
    44. case 2:
    45. fd=open("/dev/burger1",O_RDWR);
    46. if(a == 0)
    47. {
    48. ioctl(fd,LED_ON,&b);
    49. break;
    50. }
    51. else
    52. {
    53. ioctl(fd,LED_OFF,&b);
    54. break;
    55. }
    56. case 3:
    57. fd=open("/dev/burger2",O_RDWR);
    58. if(a == 0)
    59. {
    60. ioctl(fd,LED_ON,&b);
    61. break;
    62. }
    63. else
    64. {
    65. ioctl(fd,LED_OFF,&b);
    66. break;
    67. }
    68. }
    69. close(fd);
    70. }
    71. close(fd);
    72. return 0;
    73. }

    驱动代码

    1. #include <linux/init.h>
    2. #include <linux/module.h>
    3. #include<linux/fs.h>
    4. #include<linux/io.h>
    5. #include <linux/uaccess.h>
    6. #include <linux/device.h>
    7. #include <linux/cdev.h>
    8. #include <linux/slab.h>
    9. #include"head.h"
    10. char kbuf[128]={0};
    11. gpio_t *vir_led1;
    12. gpio_t *vir_led2;
    13. gpio_t *vir_led3;
    14. unsigned int *vir_rcc;
    15. unsigned int major=0;
    16. unsigned int minor=0;
    17. struct cdev *mychdev;
    18. struct class *cls;
    19. struct device *dev;
    20. dev_t devno;
    21. int mycdev_open(struct inode *inode, struct file *file)
    22. {
    23. int min=MINOR(inode->i_rdev);//获取打开的的文件的次设备号
    24. file->private_data= (void *)min;
    25. printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    26. return 0;
    27. }
    28. long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
    29. {
    30. int min=(int)file->private_data;//获取到文件的次设备号
    31. switch(min)
    32. {
    33. case 0: //控制LED1
    34. switch(cmd)
    35. {
    36. case LED_ON: //开灯
    37. vir_led1->ODR |= 1<<10;
    38. break;
    39. case LED_OFF: //关灯
    40. vir_led1->ODR &= (~(1<<10));
    41. break;
    42. }
    43. break;
    44. case 1: //控制LED2
    45. switch(cmd)
    46. {
    47. case LED_ON: //开灯
    48. vir_led2->ODR |= 1<<10;
    49. break;
    50. case LED_OFF: //关灯
    51. vir_led2->ODR &= (~(1<<10));
    52. break;
    53. }
    54. break;
    55. case 2: //控制LED3
    56. switch(cmd)
    57. {
    58. case LED_ON: //开灯
    59. vir_led3->ODR |= 1<<8;
    60. break;
    61. case LED_OFF: //关灯
    62. vir_led3->ODR &= (~(1<<8));
    63. break;
    64. }
    65. break;
    66. }
    67. printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    68. return 0;
    69. }
    70. int mycdev_close(struct inode *inode, struct file *file)
    71. {
    72. printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    73. return 0;
    74. }
    75. //定义操作方法结构体变量并赋值
    76. struct file_operations fops = {
    77. .open = mycdev_open,
    78. .unlocked_ioctl = mycdev_ioctl,
    79. .release = mycdev_close,
    80. };
    81. int all_led_init(void)
    82. {
    83. //寄存器地址的映射
    84. vir_led1=ioremap(PHY_LED1_ADDR,sizeof(gpio_t));
    85. if(vir_led1==NULL)
    86. {
    87. printk("ioremap filed:%d\n",__LINE__);
    88. return -ENOMEM;
    89. }
    90. vir_led2=ioremap(PHY_LED2_ADDR,sizeof(gpio_t));
    91. if(vir_led2==NULL)
    92. {
    93. printk("ioremap filed:%d\n",__LINE__);
    94. return -ENOMEM;
    95. }
    96. vir_led3=vir_led1;
    97. vir_rcc=ioremap(PHY_RCC_ADDR,4);
    98. if(vir_rcc==NULL)
    99. {
    100. printk("ioremap filed:%d\n",__LINE__);
    101. return -ENOMEM;
    102. }
    103. printk("物理地址映射成功\n");
    104. //寄存器的初始化
    105. //rcc
    106. (*vir_rcc) |= (3<<4);
    107. //led1
    108. vir_led1->MODER &= (~(3<<20));
    109. vir_led1->MODER |= (1<<20);
    110. vir_led1->ODR &= (~(1<<10));
    111. //led2
    112. vir_led2->MODER &= (~(3<<20));
    113. vir_led2->MODER |= (1<<20);
    114. vir_led2->ODR &= (~(1<<10));
    115. //led3
    116. vir_led3->MODER &= (~(3<<16));
    117. vir_led1->MODER |= (1<<16);
    118. vir_led1->ODR &= (~(1<<8));
    119. printk("寄存器初始化成功\n");
    120. return 0;
    121. }
    122. static int __init mycdev_init(void)
    123. {
    124. int ret;
    125. //1.申请一个对象空间cdev_alloc
    126. mychdev=cdev_alloc();
    127. if(mychdev == NULL)
    128. {
    129. printk("申请字符设备驱动对象失败\n");
    130. ret = -EFAULT;
    131. goto out1;
    132. }
    133. printk("申请字符设备驱动对象成功\n");
    134. //2.初始化对象cdev_init
    135. cdev_init(mychdev,&fops);
    136. //3.申请设备号 register_chrdev_region()/alloc_chrdev_region()
    137. if(major == 0)
    138. {
    139. ret = alloc_chrdev_region(&devno,minor,3,"burger");
    140. if(ret)
    141. {
    142. printk("动态申请设备号失败\n");
    143. goto out2;
    144. }
    145. major=MAJOR(devno);
    146. minor=MINOR(devno);
    147. }
    148. else
    149. {
    150. ret = register_chrdev_region(MKDEV(major,minor),3,"burger");
    151. if(ret)
    152. {
    153. printk("静态申请设备号失败\n");
    154. goto out2;
    155. }
    156. }
    157. printk("申请设备号成功\n");
    158. //4.注册驱动对象 cdev_add
    159. ret = cdev_add(mychdev,MKDEV(major,minor),3);
    160. if(ret)
    161. {
    162. printk("注册字符设备驱动对象失败\n");
    163. goto out3;
    164. }
    165. printk("注册字符设备驱动对象成功\n");
    166. //5.向上提交目录 class_create
    167. cls=class_create(THIS_MODULE,"burger");
    168. if(IS_ERR(cls))
    169. {
    170. printk("向上提交目录失败\n");
    171. goto out4;
    172. }
    173. printk("向上提交目录成功\n");
    174. //6.向上提交设备节点信息 device_create
    175. int i; //向上提交三次设备节点信息
    176. for(i=0;i<3;i++)
    177. {
    178. dev=device_create(cls,NULL,MKDEV(major,i),NULL,"burger%d",i);
    179. if(IS_ERR(dev))
    180. {
    181. printk("向上提交节点失败\n");
    182. goto out5;
    183. }
    184. }
    185. printk("向上提交节点成功\n");
    186. return 0;
    187. out5:
    188. for(--i;i>=0;i--)
    189. {
    190. device_destroy(cls,MKDEV(major,i));
    191. }
    192. class_destroy(cls);
    193. out4:
    194. cdev_del(mychdev);
    195. out3:
    196. unregister_chrdev_region(MKDEV(major,minor),3);
    197. out2:
    198. kfree(mychdev);
    199. out1:
    200. return ret;
    201. }
    202. static void __exit mycdev_exit(void)
    203. {
    204. //取消地址映射
    205. iounmap(vir_led1);
    206. iounmap(vir_led2);
    207. iounmap(vir_rcc);
    208. //注销字符设备驱动
    209. int i;
    210. for(i=0;i<3;i++)
    211. {
    212. device_destroy(cls,MKDEV(major,i));
    213. }
    214. class_destroy(cls);
    215. cdev_del(mychdev);
    216. unregister_chrdev_region(MKDEV(major,minor),3);
    217. kfree(mychdev);
    218. }
    219. module_init(mycdev_init);
    220. module_exit(mycdev_exit);
    221. MODULE_LICENSE("GPL");

  • 相关阅读:
    实验31:温湿度传感器实验
    数据库字段,对应java对象属性
    学习SpringSecurity这一篇就够了
    MySQL的内置函数
    python:bottle + eel 模仿 mdict 查英汉词典
    celery命令参数详解及在django中的用法
    链路追踪Skywalking快速入门
    redis删除缓存
    备忘录模式:对象状态的保存与恢复
    微信小程序ios页面没有滚动下拉也会出现黑色背景
  • 原文地址:https://blog.csdn.net/cecillq/article/details/133998366