linux驱动开发的基本步骤(Linux平台下驱动程序开发举例)
关于Linux平台下的程序开发,与一般的不带操作系统程序开发有较大的区别。我们这里以Linux平台下SPI驱动开发为例,介绍一下Linux平台下驱动程序开发的一般方法。
图像传感器EV76C570
我们在视觉系统的图像采集部分时,选用的是E2V公司的CMOS sensor EV76C570图像传感器。这一块没有现成的驱动程序可以参考,因此,需要独立自主开发。传感器与MCU之间采用SPI通信,那我们先来看一下SPI总线。
SPI总线通信
SPI接口技术是一种高速,高效的串行接口技术,因而SPI设备在数据通信中应用十分方便。设备驱动程序作为操作系统内核和硬件之间的接口,是嵌入式开发的重要组成部分,针对TI的davinci芯片DM6467和嵌入式Linux操作系统构建的开发平台(针对这部分,我前面有文章专门论述过,这里就不再重复说明了),根据DM6467的SPI接口特性,及接口电路的连接特点说明了SPI设备驱动程序的基本开发方法和动态模块加载实现过程。
具体实现步骤
1、包含必要的头文件
#include <linux/config.h>
#include <linux/device.h>
#include <linux/spi/spi.h>
#include <linux/compiler.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/poll.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/unistd.h>
#include <asm/io.h>
2、设置SPI的设备名与主设备号以及相关寄存器
1)注意避开那些已经使用的主设备号
#define DEVICE_NAME "SPI"//设备名#define SPI_MAJOR 240//主设备号
2)指定SPI寄存器的基地址#define DAVINCI_SPI_BASE (0x01C66800)
3)定义SPI寄存器结构体
struct davinci_spi_reg {
volatile __u32 __bitwise SPIGCR0;
volatile __u32 __bitwise SPIGCR1;
volatile __u32 __bitwise SPIINT;
volatile __u32 __bitwise SPILVL;
volatile __u32 __bitwise SPIFLG;
volatile __u32 __bitwise SPIPC0;
volatile __u32 __bitwise SPIPC1;
volatile __u32 __bitwise SPIPC2;
volatile __u32 __bitwise SPIPC3;
volatile __u32 __bitwise SPIPC4;
volatile __u32 __bitwise SPIPC5;
volatile __u32 __bitwise SPIPC6;
volatile __u32 __bitwise SPIPC7;
volatile __u32 __bitwise SPIPC8;
volatile __u32 __bitwise SPIDAT0;
volatile __u32 __bitwise SPIDAT1;
volatile __u32 __bitwise SPIBUF;
volatile __u32 __bitwise SPIEMU;
volatile __u32 __bitwise SPIDELAY;
volatile __u32 __bitwise SPIDEF;
volatile __u32 __bitwise SPIFMT[4];
volatile __u32 __bitwise TGINTVEC[2];
volatile __u8 __bitwise RSVD0[8];
volatile __u32 __bitwise MIBSPIE;
};
3、填充设备文件file_operations结构体
static struct file_operations davinci_z_spi_fops =
{
.owner = THIS_MODULE,
.open = davinci_spi_open,
.write = davinci_spi_write,
.release = davinci_spi_close,
};
分别实现SPI初始化函数open、读写函数write和释放函数release,以及模块初始化函数dev_init和退出函数dev_exit。
4、编写Makefile
ifeq ($(KERNELRELEASE),)KERNELDIR = /opt/ti-davinci_bt1120/linux-2.6.10_mvl401_LSP_01_30_00_082# The current directory is passed to sub-makes as argumentPWD := $(shell pwd)modules:echo "before modules"$(MAKE) -C $(KERNELDIR) M=$(PWD) modulesecho "modules"modules_install:$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_installecho "modules_install"clean:rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versionsecho "clean".PHONY: modules modules_install clean
else# called from kernel build system: just declare what our modules are
obj-m := spi_master_mod.o#echo "else"endif
5、编写E2V的SPI寄存器配置程序
根据E2V数据手册,封装上述通用SPI驱动。需要注意地址位和读写数据位以及数据长度。这跟一般的嵌入式开发区别不大,这里不做累述。
6、编译调试
1)分别编译
配置好内核路径,以及交叉编译器路径,几次make即可。
2)加载模块
insmod spi_master_mod.ko
3)创建设备节点
mknod /dev/SPI c 200 0
4)运行
进入运行路径,执行应用程序,./spi_master
测试方法
在没有从设备时要进行初步的测试,可以启动spi的环路测试模式,即自发自收,这样发出的数据就是接收的数据,对应的寄存器是 spi_reg_davinci->SPIGCR1。
,免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com