野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 90|回复: 1

[求助] 如何使用杂项设备驱动驱动蜂鸣器工作?

[复制链接]
发表于 2024-4-10 13:46:48 | 显示全部楼层 |阅读模式
跟着北京讯为的视频,使用杂项设备驱动驱动蜂鸣器的工作,根据原理图得知蜂鸣器的驱动IO口为GPIO1_19。将代码内的GPIO5_1替换为GPIO1_19地址无法直接使用。

请问缺了哪些步骤,应当如何操作?
  1. /*
  2. * @Descripttion: 基于杂项设备的蜂鸣器驱动
  3. * @version:
  4. * @Author: Apple
  5. * @Date: 2021-02-23 13:54:49
  6. */
  7. #include <linux/init.h>         //初始化头文件
  8. #include <linux/module.h>       //最基本的文件,支持动态添加和卸载模块。
  9. #include <linux/miscdevice.h>   //包含了miscdevice结构的定义及相关的操作函数。
  10. #include <linux/fs.h>           //文件系统头文件,定义文件表结构(file,buffer_head,m_inode等)
  11. #include <linux/uaccess.h>      //包含了copy_to_user、copy_from_user等内核访问用户进程内存地址的函数定义。
  12. #include <linux/io.h>           //包含了ioremap、iowrite等内核访问IO内存等函数的定义。
  13. #include <linux/kernel.h>                //驱动要写入内核,与内核相关的头文件
  14. #define GPIO5_DR 0x0209C060     //蜂鸣器物理地址,通过查看原理图得知 这里是GPIO1_19 基地址+18*4字节
  15. unsigned int *vir_gpio5_dr;     //存放映射完的虚拟地址的首地址
  16. /**
  17. * @name: misc_read
  18. * @test: 从设备中读取数据,当用户层调用函数read时,对应的,内核驱动就会调用这个函数。
  19. * @msg:
  20. * @param {structfile} *file file结构体
  21. * @param {char__user} *ubuf 这是对应用户层的read函数的第二个参数void *buf
  22. * @param {size_t} size 对应应用层的read函数的第三个参数
  23. * @param {loff_t} *loff_t 这是用于存放文件的偏移量的,回想一下系统编程时,读写文件的操作都会使偏移量往后移。
  24. * [url=home.php?mod=space&uid=82536]@return[/url] {*} 当返回正数时,内核会把值传给应用程序的返回值。一般的,调用成功会返回成功读取的字节数。
  25. 如果返回负数,内核就会认为这是错误,应用程序返回-1
  26. */
  27. ssize_t misc_read (struct file *file, char __user *ubuf, size_t size, loff_t *loff_t)
  28. {
  29.         printk("misc_read\n ");
  30.         return 0;
  31. }
  32. /**
  33. * @name: misc_write
  34. * @test: 往设备写入数据,当用户层调用函数write时,对应的,内核驱动就会调用这个函数。
  35. * @msg:
  36. * @param {structfile} * filefile结构体
  37. * @param {constchar__user} *ubuf 这是对应用户层的write函数的第二个参数const void *buf
  38. * @param {size_t} size 对应用户层的write函数的第三个参数count。
  39. * @param {loff_t} *loff_t 这是用于存放文件的偏移量的,回想一下系统编程时,读写文件的操作都会使偏移量往后移。
  40. * @return {*} 当返回正数时,内核会把值传给应用程序的返回值。一般的,调用成功会返回成功读取的字节数。
  41. 如果返回负数,内核就会认为这是错误,应用程序返回-1。
  42. */
  43. ssize_t misc_write (struct file *file, const char __user *ubuf, size_t size, loff_t *loff_t)
  44. {       
  45.     /*应用程序传入数据到内核空间,然后控制蜂鸣器的逻辑,在此添加*/
  46.         // kbuf保存的是从应用层读取到的数据
  47.     char kbuf[64] = {0};
  48.     // copy_from_user 从应用层传递数据给内核层
  49.         if(copy_from_user(kbuf,ubuf,size)!= 0)
  50.         {
  51.         // copy_from_user 传递失败打印
  52.                 printk("copy_from_user error \n ");
  53.                 return -1;
  54.         }
  55.     //打印传递进内核的数据
  56.     printk("kbuf is %d\n ",kbuf[0]);
  57.         if(kbuf[0]==1) //传入数据为1 ,蜂鸣器响
  58.         {
  59.                 *vir_gpio5_dr |= (1<<1);
  60.         }
  61.         else if(kbuf[0]==0) //传入数据为0,蜂鸣器关闭
  62.                 *vir_gpio5_dr &= ~(1<<1);
  63.         return 0;
  64. }
  65. /**
  66. * @name: misc_release
  67. * @test: 当设备文件被关闭时内核会调用这个操作,当然这也可以不实现,函数默认为NULL。关闭设备永远成功。
  68. * @msg:
  69. * @param {structinode} *inode 设备节点
  70. * @param {structfile} *file filefile结构体
  71. * @return {0}
  72. */
  73. int misc_release(struct inode *inode,struct file *file){
  74.         printk("hello misc_relaease bye bye \n ");
  75.         return 0;
  76. }
  77. /**
  78. * @name: misc_open
  79. * @test: 在操作设备前必须先调用open函数打开文件,可以干一些需要的初始化操作。
  80. * @msg:
  81. * @param {structinode} *inode 设备节点
  82. * @param {structfile} *file filefile结构体
  83. * @return {0}
  84. */
  85. int misc_open(struct inode *inode,struct file *file){
  86.         printk("hello misc_open\n ");
  87.         return 0;
  88. }
  89. //文件操作集
  90. struct file_operations misc_fops={
  91.         .owner = THIS_MODULE,
  92.         .open = misc_open,
  93.         .release = misc_release,
  94.         .read = misc_read,
  95.         .write = misc_write,
  96. };
  97. //miscdevice结构体
  98. struct miscdevice  misc_dev = {
  99.         .minor = MISC_DYNAMIC_MINOR,
  100.         .name = "hello_misc",
  101.         .fops = &misc_fops,
  102. };
  103. static int misc_init(void)
  104. {
  105.         int ret;
  106.     //注册杂项设备
  107.         ret = misc_register(&misc_dev);
  108.         if(ret<0)
  109.         {
  110.                 printk("misc registe is error \n");
  111.         }
  112.         printk("misc registe is succeed \n");
  113.     //将物理地址转化为虚拟地址
  114.         vir_gpio5_dr = ioremap(GPIO5_DR,4);
  115.         if(vir_gpio5_dr == NULL)
  116.         {
  117.         printk("GPIO5_DR ioremap is error \n");
  118.         return EBUSY;
  119.         }
  120.         printk("GPIO5_DR ioremap is ok \n");       
  121.         return 0;
  122. }
  123. static void misc_exit(void){
  124.     //卸载杂项设备
  125.         misc_deregister(&misc_dev);
  126.         iounmap(vir_gpio5_dr);
  127.         printk(" misc gooodbye! \n");
  128. }
  129. module_init(misc_init);
  130. module_exit(misc_exit);
  131. MODULE_LICENSE("GPL");

复制代码


回复

使用道具 举报

发表于 2024-4-10 18:01:02 | 显示全部楼层
https://doc.embedfire.com/linux/ ... aracter_device.html

改个字符设备驱动起来先,然后再去改杂项
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-5-1 22:51 , Processed in 0.112983 second(s), 24 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表