1. 程式人生 > >訊為4412蜂鳴器驅動實現

訊為4412蜂鳴器驅動實現

最近在搞訊為開發板的驅動,終於將訊為的蜂鳴器驅動搞定,現在進行一個總結。

編寫流程:


(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後停止。

最後解除安裝驅動模組:

 

整個蜂鳴器的驅動全部完成。