訊為4412蜂鳴器驅動實現
阿新 • • 發佈:2018-12-20
最近在搞訊為開發板的驅動,終於將訊為的蜂鳴器驅動搞定,現在進行一個總結。
編寫流程:
(1)分析硬體原理圖
要控制beep ----> gpd0_0 --->輸出高:響;輸出低:不響。
(2)分析該硬體所需配置的暫存器
實體地址:
con:0x114000a0 [0-3] 0x01(output)
dat:0x114000a4 [0] 1響 0滅
(3)搭建驅動框架
1)模組三要素
2)完成字元裝置相關的操作
3)相關硬體的操作
3.1 完成對映
3.2 配置暫存器
驅動原始碼:
#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/io.h> #define NAME "beep_demo" #define GPD0CON 0x114000a0 #define GPD0DAT 0x114000a4 void __iomem *gpd0con; void __iomem *gpd0dat; int major = 0; int led_open(struct inode *inode, struct file *file) { writel((0x1<<0),gpd0dat); printk("%s,%d\n",__func__,__LINE__); return 0; } int led_release(struct inode *inode, struct file *file) { writel(~(0x1<<0),gpd0dat); printk("%s,%d\n",__func__,__LINE__); return 0; } struct file_operations f_ops = { .owner = THIS_MODULE, .open = led_open, .release = led_release, }; int beep_init(void) { int ret = 0; major = register_chrdev(major,NAME,&f_ops); if(major < 0){ printk("%s,%d register_chrdev fail...\n",__func__,__LINE__); return -EINVAL; } gpd0con = ioremap(GPD0CON,4); if(gpd0con == NULL){ printk("%s,%d ioremap gpd0con fail...\n",__func__,__LINE__); goto ERR_STEP1; } gpd0dat = ioremap(GPD0DAT,4); if(gpd0dat == NULL){ printk("%s,%d ioremap gpd0dat fail...\n",__func__,__LINE__); goto ERR_STEP2; } writel((readl(gpd0con)&~(0xf<<0))|(0x1<<0),gpd0con); printk("%s,%d\n",__func__,__LINE__); return 0; ERR_STEP2: iounmap(gpd0con); ERR_STEP1: unregister_chrdev(major,NAME); return ret; } void beep_exit(void) { iounmap(gpd0con); iounmap(gpd0dat); unregister_chrdev(major,NAME); printk("%s,%d\n",__func__,__LINE__); } module_init(beep_init); module_exit(beep_exit); MODULE_LICENSE("GPL");
編寫Makefile
#!/bin/bash
$(warning KERNELRELEASE = $(KERNELRELEASE))
ifeq ($(KERNELRELEASE),)
#核心的原始碼路徑, ?= 條件賦值, uname -r 得到核心版本號
KERNELDIR ?= /home/skyfall/iTOP4412/kernel/iTop4412_Kernel_3.0
# := 立即賦值, 得到當前的絕對路徑
PWD := $(shell pwd)
# -C 切換工作路徑, $(MAKE) = make
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions Module* modules*
.PHONY: modules clean
else
# 生成模組
obj-m := beep_demo.o
endif
交叉編譯,生成驅動檔案:
(3)編寫上層的應用程式,實現的是響3s後停止。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
int fd;
fd = open("/dev/beep" , O_RDWR);
if(fd < 0){
perror("open");
}
sleep(3);
return 0;
}
交叉編譯,生成可執行檔案:
arm-none-linux-gnueabi-gcc test.c -o test
將驅動檔案與應用層檔案拷貝至開板,首先載入驅動。
insmod beep_demo.ko
檢視生成的裝置號
建立裝置節點
mknod /dev/beep c 248 0
應用層呼叫:
發現蜂鳴器響3s後停止。
最後解除安裝驅動模組:
整個蜂鳴器的驅動全部完成。