2-3 BEEP 驱动程序开发(包含驱动和测试程序)

来源:互联网 发布:java网上订餐系统源码 编辑:程序博客网 时间:2024/06/05 12:42

1、电路图

  

2Linux-2.6.32.2内核重要头文件目录:

linux-2.6.32.2/arch/arm/mach-s3c2410/include/mach/regs-gpio.h

linux-2.6.32.2/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h

linux-2.6. 32.2/arch/arm/plat-s3c24xx/gpio.c

linux-2.6. 32.2/include/linux/asm-generic/io.h

linux-2.6. 32.2/include/linux/wait.h

链接关系。如:出现asm则链接之后的内容

asm --- linux-2.6.32.2/include/linux/asm-generic

mach --- linux-2.6.32.2/arch/arm/mach-s3c2410/include/mach

plat --- linux-2.6.32.2/arch/arm/plat-s3c24xx/include/plat

linux-2.6.32.2/arch/arm/plat-s3c/include/plat

3、代码阅读分析

拿到驱动代码首先看下面这个两个宏:

module_init(beep_init);   /*模块加载时调用beep_init函数进行加载*/

module_exit(beep_cleanup); /*模块卸载时调用beep_cleanup函数进行清除*/

4.源代码beep_drv.c分析:

#include <linux/errno.h>  /*公共的头文*/#include <linux/kernel.h>#include <linux/module.h>#include <linux/slab.h>#include <linux/input.h>#include <linux/init.h>#include <linux/serio.h>#include <linux/delay.h>#include <linux/clk.h>#include <linux/miscdevice.h>#include <linux/gpio.h>#include <asm/io.h>  //平台相关的文件#include <asm/irq.h> /*出现asm 则它会连接到 linux-2.6.32.2/include/linux/asm-generic*/#include <asm/uaccess.h>#include <mach/regs-clock.h>#include <plat/regs-timer.h> #include <mach/regs-gpio.h>//这个文件在inux-2.6.32.2/arch/arm/mach-s3c2410/include/mach/regs-gpio.h中// /opt/linux-2.6.34/arch/arm/mach-s3c2410/include/mach/regs-gpio.h#include <linux/cdev.h>static int beep_major = 0;/*全局主设备号*/module_param(beep_major, int, 0);/*传递参数这里没有到*/MODULE_AUTHOR("Hanson He"); /*声明作者*/MODULE_LICENSE("Dual BSD/GPL");/*指定使用什么协议的*/#define BEEP_MAGIC 'k'#define BEEP_START_CMD _IO (BEEP_MAGIC, 1)#define BEEP_STOP_CMD _IO (BEEP_MAGIC, 2)/*   _IO(type,nr)用于构造无参数的命令编号;*//* * Open the device; in fact, there's nothing to do here. */int beep_open (struct inode *inode, struct file *filp)/*没用到,但必需保持完整性*/{return 0;}ssize_t beep_read(struct file *file, char __user *buff, size_t count, loff_t *offp){return 0;}ssize_t beep_write(struct file *file, const char __user *buff, size_t count, loff_t *offp){return 0;}void beep_stop( void ){//add your src HERE!!!//set GPB0 as outputs3c2410_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPIO_OUTPUT);s3c2410_gpio_setpin(S3C2410_GPB(0),0);}void beep_start( void ){//add your src HERE!!!//set GPB0 as outputs3c2410_gpio_pullup(S3C2410_GPB(0),1);/*上拉电阻*/s3c2410_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPIO_OUTPUT);/*配置*/s3c2410_gpio_setpin(S3C2410_GPB(0),1);/*置位*/}static int beep_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){//add your src HERE!!!switch ( cmd ) {case BEEP_START_CMD: {beep_start(); break;}case BEEP_STOP_CMD: {beep_stop(); break;}default: {break;}}return 0;}static int beep_release(struct inode *node, struct file *file){return 0;}/* * Set up the cdev structure for a device. */static void beep_setup_cdev(struct cdev *dev, int minor,struct file_operations *fops){int err, devno = MKDEV(beep_major, minor);/*由主次设备号生成设备号*/    cdev_init(dev, fops); /* 初始化cdev*/dev->owner = THIS_MODULE;dev->ops = fops;err = cdev_add (dev, devno, 1);/* 注册设备*//* Fail gracefully if need be */if (err)printk (KERN_NOTICE "Error %d adding beep%d", err, minor);}/* * Our various sub-devices. *//* Device 0 uses remap_pfn_range */static struct file_operationKERNELDIR ?=/home/student/linux-2.6.32.2all: beep_test beep_test : beep_test.c#arm-linux-gcc -I$(KERNELDIR) -s -Wl,-warn-common --static -o $@ $^arm-linux-gcc -I$(KERNELDIR) -o $@ $^clean :rm beep_tests beep_remap_ops = { ?*file_operations的对象beep_remap_ops,并对其赋值*/.owner   = THIS_MODULE,  /*指向模块本身*/.open    = beep_open,     /*把open和beep_open函数关联起来,注册*/.release = beep_release,.read    = beep_read,.write   = beep_write,.ioctl   = beep_ioctl,};/* * There's no need for us to maintain any * special housekeeping info, so we just deal with raw cdevs. */static struct cdev BeepDevs;/* * Module housekeeping. */static int beep_init(void)/*模块加载时调用beep_init函数进行加载*/{int result;dev_t dev = MKDEV(beep_major, 0);char dev_name[]="beep";/* Figure out our device number. */if (beep_major)/*设备号的分配*/result = register_chrdev_region(dev, 1, dev_name); /*手工 分配*/else {result = alloc_chrdev_region(&dev, 0, 1, dev_name);/*系统分配一个设备号0:第一个次设备号,1:一个设备*/beep_major = MAJOR(dev);/*取得主设备号*/}if (result < 0) {printk(KERN_WARNING "beep: unable to get major %d\n", beep_major);return result;}if (beep_major == 0)beep_major = result;/* Now set up cdev. */beep_setup_cdev(&BeepDevs, 0, &beep_remap_ops);printk("beep device installed, with major %d\n", beep_major);printk("The device name is: %s\n", dev_name);return 0;}static void beep_cleanup(void)/*模块卸载时调用beep_cleanup函数进行清除*/{cdev_del(&BeepDevs);/*注销设备*/unregister_chrdev_region(MKDEV(beep_major, 0), 1);/*释放占用的设备号*/printk("beep device uninstalled\n");}module_init(beep_init);    /*模块加载时调用beep_init函数进行加载*/module_exit(beep_cleanup); /*模块卸载时调用beep_cleanup函数进行清除*/EXPORT_SYMBOL(beep_major);/*????*/相应的Makefile文件(参考)ifeq ($(KERNELRELEASE),)#KERNELDIR ?= /your/target/source/directory/KERNELDIR ?=/home/lwb/linux-2.6.32.2PWD := $(shell pwd)modules:$(MAKE) -C $(KERNELDIR) M=$(PWD) modulesmodules_install:$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_installclean:rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions.PHONY: modules modules_install cleanelse    obj-m := beep_drv.oendif



 

5、 应该编译驱动、下载到板子上、注册。

6、 创建设备节点

    $mknod /dev/node_name c major minor  //char dev_name[]="beep";这里node_namebeep

7、 测试程序代码

  

#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <fcntl.h>#include <linux/ioctl.h>#define BEEP_MAGIC 'k'   /*宏是跟驱动里一样的*/#define BEEP_START_CMD _IO (BEEP_MAGIC, 1)#define BEEP_STOP_CMD _IO (BEEP_MAGIC, 2)int main(){ int i = 0; int dev_fd; dev_fd = open("/dev/beep",O_RDWR | O_NONBLOCK);/*打开设备文件可读可写、非阻塞*/ if ( dev_fd == -1 ) {  printf("Cann't open file /dev/beep\n");  exit(1); } printf("Start beep\n"); ioctl (dev_fd, BEEP_START_CMD,0); getchar();   ioctl (dev_fd, BEEP_STOP_CMD,0); printf("Stop beep and Close device\n"); close(dev_fd); /*关闭设备文件*/ return 0;}
相应的Makefile文件KERNELDIR ?=/home/lwb/linux-2.6.32.2all: beep_test beep_test : beep_test.c#arm-linux-gcc -I$(KERNELDIR) -s -Wl,-warn-common --static -o $@ $^arm-linux-gcc -I$(KERNELDIR) -o $@ $^clean :rm beep_test



8、  编写Makefile

KERNELKDIR?=/opt/linux-2.6.32.2/include

all:test

test:test.c

  arm-linux-gcc–I $(KERNELDIR) –o S@ S^ //–I $(KERNELDIR)包含头文件

clean:

rm –rf test

9、举例:编写BEEP测试程序

9.1编写BEEP测试程序beep_drv.c,编译生成beep_drv.ko

9.2上电开发板,运行uImage内核

9.3下载模块文件到开发板

9.4动态加载模块文件insmod beep_drv.ko

9.5查看BEEP驱动系统自动分配的主设备号cat /proc/devices |grep beep

9.6制作BEEP对应的设备文件节点 mknod /dev/beep c major 0

9.7将编译生成的beep_test,下载到开发板,测试BEEP驱动

 

原创粉丝点击