讯为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后停止。

最后卸载驱动模块:

整个蜂鸣器的驱动全部完成。

猜你喜欢

转载自blog.csdn.net/zxy131072/article/details/84845178
今日推荐