以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。
一、驱动部分
1、前言
九鼎移植的内核已经提供了蜂鸣器驱动源码(在SI中搜索关键字buzzer,发现出现有x210-buzzer.c文件;或者在make menuconfig界面搜索buzzer,得到路径信息drivers/char/buzzer,进入该目录发现有x210-buzzer.c文件;或者在内核源码里使用“grep -nr "buzzer" ./”来查找),因此不需要我们编写。
但是该驱动文件不一定被编译。该文件是否被编译,取决于Makefile文件中的宏:obj-$(CONFIG_X210_BUZZER_DRIVER) += x210-buzzer.o;而该宏又取决于Kconfig文件中的项目(X210_BUZZER_DRIVER)是否显示“y”;而Kconfig文件中的项目是否显示“y”,是由make menuconfig时配置的。因此要进行配置,配置之后再进行驱动的测试,以验证该驱动的可行性。
2、测试
步骤1:在make menuconfig界面进行配置以支持buzzer。
Device Drivers ---> Character devices ---> [*] x210 buzzer driver
步骤2:进行编译,即执行make。
步骤3:将新生成的zImage下载到开发板运行,按理开发板系统上应该生成/dev/buzzer这个设备文件,但实际没有。
[root@xjh dev]# ls /dev/buzzer ls: /dev/buzzer: No such file or directory [root@xjh dev]#
经过bug排查,发现九鼎编写的代码中有个bug,drivers/char/buzzer/Makefile中的宏,如果与Kconfig对应的话,需要修改为如下:
#obj-$(CONFIG_BUZZER_DRIVER) += x210-buzzer.o obj-$(CONFIG_X210_BUZZER_DRIVER) += x210-buzzer.o
步骤4:修改之后重新编译与下载内核运行,可以看到 /dev/buzzer这个设备文件。
[root@xjh ]# ls /dev/buzzer -l //设备文件 crw-rw---- 1 root root 10, 61 Jan 1 12:15 /dev/buzzer [root@xjh ]# //主设备10,次设备号61
至此,buzzer的驱动可以使用了,下面通过写应用来测试此驱动。
二、应用部分
1、浏览驱动有哪些操作
通过简单地浏览x210-buzzer.c这个驱动文件,得知其open、close函数都是空的,只有ioctl函数在做事情,于是可以据此编写应用层代码。
//省略部分代码 static struct file_operations dev_fops = {.owner = THIS_MODULE,.open = x210_pwm_open, //空的.release = x210_pwm_close, //空的.ioctl = x210_pwm_ioctl, //干活的 };static struct miscdevice misc = {.minor = MISC_DYNAMIC_MINOR,.name = DEVICE_NAME,.fops = &dev_fops, }; //省略部分代码
x210_pwm_open()与x210_pwm_close()函数如下:
static int x210_pwm_open(struct inode *inode, struct file *file) {if (!down_trylock(&lock))return 0;elsereturn -EBUSY;}static int x210_pwm_close(struct inode *inode, struct file *file) {up(&lock);return 0; }
x210_pwm_ioctl()函数如下:
static int x210_pwm_ioctl(struct inode *inode, struct file *file,\unsigned int cmd, unsigned long arg) {switch (cmd) { //#define PWM_IOCTL_SET_FREQ 1//这个命令打开蜂鸣器并设置频率,需要带参数,参数含义是频率case PWM_IOCTL_SET_FREQ:printk("PWM_IOCTL_SET_FREQ:\r\n");if (arg == 0)return -EINVAL;PWM_Set_Freq(arg);break;//#define PWM_IOCTL_STOP 0//这个命令关闭蜂鸣器并设置频率,不需要带参数case PWM_IOCTL_STOP:default:printk("PWM_IOCTL_STOP:\r\n");PWM_Stop();break;}return 0; }
2、开始编写应用代码
#include <stdio.h> #include <sys/stat.h> //open这些函数所在的头文件 #include <fcntl.h>#define DEVNAME "/dev/buzzer" //蜂鸣器对应的设备文件,这个啥时候创建的? //这些命令来自驱动文件,应用层知道这些宏的含义 //按理应该写成头文件包含形式,这里不规范 #define PWM_IOCTL_SET_FREQ 1 #define PWM_IOCTL_STOP 0 int main(void) {int fd = -1;fd = open(DEVNAME, O_RDWR);if (fd < 0){perror("open");return -1;}//文件描述符 //频率ioctl(fd, PWM_IOCTL_SET_FREQ, 10000);//命令码来自驱动sleep(3);ioctl(fd, PWM_IOCTL_STOP);sleep(3);ioctl(fd, PWM_IOCTL_SET_FREQ, 3000);sleep(3);ioctl(fd, PWM_IOCTL_STOP);sleep(3);close(fd); return 0; }
3、测试实践
(1)将上面的应用程序命名为app.c;
(2)然后使用命令“arm-linux-gcc app.c -o app”进行编译;
(3)将得到的可执行文件下载至开发板进行运行;
[root@xjh mnt]# ls Makefile app app.c driver_test.c [root@xjh mnt]# ./app [ 2115.943865] PWM_IOCTL_SET_FREQ: //有声音 [ 2119.054830] PWM_IOCTL_STOP: [ 2122.056309] PWM_IOCTL_SET_FREQ: //有声音,且和上面频率不一样 [ 2125.058158] PWM_IOCTL_STOP: [root@xjh mnt]#