s3c2440 雜項驅動實現蜂鳴器
阿新 • • 發佈:2019-02-04
這個驅動本來是非常簡單的,但是我就是想做個雜項驅動。
Linux驅動中把無法歸類的五花八門的裝置定義為混雜裝置(用miscdevice結構體表述)。miscdevice共享一個主裝置號MISC_MAJOR(即10),但次裝置號不同。
蜂鳴器控制原理
先來看下蜂鳴器的電路圖:
其實做了前面的LED點燈驅動,那做這個驅動就是分分鐘鐘的事。從上面的電路圖可以知道控制蜂鳴器的引腳就是GPB0;這樣就非常簡單了,需要操作的就是。
1、初始化
s3c2410_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPIO_OUTPUT);// 設定GPBCON
s3c2410_gpio_setpiin(S3C2410_GPB(0), 1); // 設定GPBDAT
2、根據引數開關蜂鳴器
s3c2410_gpio_setpin(S3C2410_GPB(0), flag); // 根據flag來開關蜂鳴器;
雜項裝置知識
雜項裝置結構體(雜項裝置的主裝置號固定為10,不同的雜項裝置是通過次裝置號來區分的)其實從上面的結構體可以知道,雜項裝置驅動只能驅動一個裝置,因為雜項驅動主裝置號固定為10(不同雜項裝置通過次裝置號來區分),而結構體中只有一個次裝置號,所以可以看出雜項驅動只能驅動一個裝置;如果要驅動多個裝置,則不能用雜項驅動;(同類裝置要靠次裝置來區分) 下面要說的兩個雜項驅動操作函式都在:/devices/char/Misc.c;建立和初始化雜項驅動:int misc_register(struct miscdevice * misc);這個函式就大概相當於:字元驅動中的裝置號建立,字元裝置的申請和初始化等(alloc_chrdev_region()裝置號申請;cdevp = cdev_alloc()申請字元結構;cdev_init(cdevp, &fops)讓字元結構和操作函式繫結;cdev_add(cdevp, devNum, 1)繫結主裝置號;) 當然和建立初始化相反的就是:int misc_deregister(struct miscdevice *misc);函數了,該函式的功能和上面的建立函式相反;struct miscdevice { int minor; // 次裝置號 const char *name;// 裝置名稱 const struct file_operations *fops; // 關聯的操作函式 struct list_head list; struct device *parent; struct device *this_device; const char *nodename; mode_t mode; };
驅動程式碼
#include<linux/init.h>
#include<linux/module.h>
#include<linux/fs.h>
#include<linux/miscdevice.h>
#include<linux/gpio.h>
#include<mach/regs-gpio.h>
#define DEV_NAME "yzhBuzzer"
ssize_t myOpen(struct inode *inode, struct file *file)
{
printk(KERN_INFO"in myOpen!\n");
s3c2410_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPIO_OUTPUT);
s3c2410_gpio_setpin(S3C2410_GPB(0), 1);
return 0;
}
int myIoctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
printk(KERN_INFO"in myIoctl cmd:%u, arg:%ld\n", cmd, arg);
if (!cmd)
s3c2410_gpio_setpin(S3C2410_GPB(0), 0);
else
s3c2410_gpio_setpin(S3C2410_GPB(0), 1);
return 0;
}
struct file_operations fop =
{
.owner = THIS_MODULE,
.ioctl = myIoctl,
.open = myOpen,
};
static struct miscdevice misc =
{
.minor = MISC_DYNAMIC_MINOR,
.name = DEV_NAME,
.fops = &fop,
};
static int __init buzzer_init(void)
{
int ret;
printk(KERN_INFO"buzzer init!\n");
ret = misc_register(&misc);
return ret;
}
static void __exit buzzer_exit(void)
{
printk(KERN_INFO"buzzer exit!\n");
misc_deregister(&misc);
}
module_init(buzzer_init);
module_exit(buzzer_exit);
MODULE_LICENSE("Dual BSD/GPL");
附上一個Makefile,現在寫的驅動都是非常簡單的,所以Makefile基本是可以通用的:
obj-m:=buzzer.o
CC=arm-linux-gcc
#KERDIR=/lib/modules/$(shell uname -r)/build
KERDIR=/home/kernel/linux-2.6.32.2
CURDIR=$(shell pwd)
all:
make -C $(KERDIR) M=$(CURDIR) modules
clean:
make -C $(KERDIR) M=$(CURDIR) clean
測試程式碼
測試程式碼非常簡單,這個驅動載入進去後會自動在dev下面建立裝置檔案。直接操作這個檔案就可以了;因為只有一個蜂鳴器,所以用ioctl函式實現有個引數是多餘的。 #include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<fcntl.h>
int main(int argc, char *argv[])
{
int flag = 0;
int fd = open("/dev/yzhBuzzer", O_RDWR);
if(fd < 0)
printf("int open error:%d\n", errno);
if (argc > 1)
flag = 1;
if(ioctl(fd, flag, 0) < 0)
printf("int ioctl error:%d", errno);
return 0;
}