嵌入式系统 驱动程序开发 专题报告 罗晟 2007 年 3 月 20 日

Post on 30-Dec-2015

115 Views

Category:

Documents

9 Downloads

Preview:

Click to see full reader

DESCRIPTION

嵌入式系统 驱动程序开发 专题报告 罗晟 2007 年 3 月 20 日. 第一章 嵌入式系统开发基础 第一节 vivi 、 kernel 和文件系统的下载 1 、 vivi 的下载. 2 、超级终端参数的设置 开启超级终端,设置串口 COM1. 复位开发板,敲入空格键,进入 vivi 环境. 在 vivi 环境中对 flash 进行分区 vivi>bon part 0 192k 1M. 3 、 kernel 的下载 通过超级终端下载内核镜像文件: vivi>load flash kernel x. 4 、文件系统的下载 - PowerPoint PPT Presentation

TRANSCRIPT

嵌入式系统 嵌入式系统 驱动程序开发 驱动程序开发

专题报告专题报告

罗晟罗晟20072007 年年 33 月月 2020 日日

第一章 嵌入式系统开发基础第一章 嵌入式系统开发基础第一节 第一节 vivivivi 、、 kernelkernel 和文件系统的下载和文件系统的下载11 、、 vivivivi 的下载的下载

22 、超级终端参数的设置、超级终端参数的设置•开启超级终端,设置串口开启超级终端,设置串口 COM1COM1

•复位开发板,敲入空格键,进入复位开发板,敲入空格键,进入 vivivivi 环境环境

•在在 vivivivi 环境中对环境中对 flashflash 进行分区进行分区 vivi>bon part 0 192k 1Mvivi>bon part 0 192k 1M

33 、、 kernelkernel 的下载的下载 通过超级终端下载内核镜像文件:通过超级终端下载内核镜像文件: vivi>load flash kernel xvivi>load flash kernel x

44 、文件系统的下载、文件系统的下载 vivi>load flash root xvivi>load flash root x

至此整个嵌入式至此整个嵌入式 LinuxLinux 系统已经建立,按复位系统已经建立,按复位键启动键启动 vivivivi ,然后按回车,,然后按回车, LinuxLinux 将启动将启动

第二节 嵌入式第二节 嵌入式 LinuxLinux 开发环境的建立开发环境的建立11 、交叉编译器的安装、交叉编译器的安装• 在在 /usr/local/usr/local 下建立一个下建立一个 armarm 目录:目录: mkdir /usr/local/armmkdir /usr/local/arm 然后把叫交叉编译包复制到此目录下:然后把叫交叉编译包复制到此目录下: cp –rf cross-2.95.3.tar.bz2cp –rf cross-2.95.3.tar.bz2• 解压缩解压缩 cross-2.95.3.tar.bz2cross-2.95.3.tar.bz2 交叉编译包:交叉编译包: cd /usr/local/armcd /usr/local/arm tar –jxvf cross-2.95.3.tar.bz2tar –jxvf cross-2.95.3.tar.bz2• 为了方便使用交叉编译器,我们修改为了方便使用交叉编译器,我们修改 PATHPATH 变量:变量: cd /etccd /etc vi profile //vi profile // 进入进入 profileprofile 按按 i //inserti //insert 找到找到 pathmunge /usr/local/sbinpathmunge /usr/local/sbin ,在其下面添加一行,在其下面添加一行 pahtmunge /usr/local/arm/2.95.3/binpahtmunge /usr/local/arm/2.95.3/bin ,按,按 ESCESC 退出退出 insertinsert ,再按‘,再按‘ shift’+‘:’shift’+‘:’ ,然后键入‘,然后键入‘ wq!’wq!’

22 、、 minicomminicom 参数设置参数设置 首先进入首先进入 minicomminicom ,然后按,然后按 Ctrl+aCtrl+a ,再按,再按

oo ,, 出现如下界面:出现如下界面:

同超级终端的参数设置,要注意的是同超级终端的参数设置,要注意的是 Serial Serial device device 为为 /dev/ttys0/dev/ttys033 、、 ztelnetztelnet 的安装的安装 rpm –ivh ztelnet-0.9.1-7mz.i386.rpmrpm –ivh ztelnet-0.9.1-7mz.i386.rpm

第二章 嵌入式第二章 嵌入式 LinuxLinux 的移植的移植11 、设置、设置 IPIP 地址地址 进入开发板中的进入开发板中的 LinuxLinux 后,我们键入:后,我们键入: #ifconfig eth0 192.168.1.171#ifconfig eth0 192.168.1.171 #inetd#inetd• 修改文件系统中的修改文件系统中的 /usr/etc/rc.local/usr/etc/rc.local ,找到,找到 /sbin/sbin

/ifconfig eth0 192.168.1.XXX/ifconfig eth0 192.168.1.XXX 这一行,把这一行,把 192.16192.168.1.XXX8.1.XXX 修改成为你想用的修改成为你想用的 IPIP 地址地址

然后启动然后启动 PCPC 机上的机上的 LinuxLinux ,键入:,键入: #ping 192.168.1.171#ping 192.168.1.171 查看是否能与开发板通讯查看是否能与开发板通讯

22 、利用、利用 ztelnetztelnet 下载文件系统下载文件系统 首先在首先在 linuxlinux 下建立下建立 /image/image 目录,把远峰资料中的目录,把远峰资料中的 /image/image 里面的所有内容拷贝到该目录下,然后在里面的所有内容拷贝到该目录下,然后在 终端中键入终端中键入 ztelnet 192.168.1.171ztelnet 192.168.1.171 ,会出现如下,会出现如下 信息:信息: Trying 192.168.1.171…Trying 192.168.1.171… Connected to 192.168.1.171.Connected to 192.168.1.171. Escape character is ‘^]’Escape character is ‘^]’ Linux 2.4.18-rmk7-pxa1((none)) (o)Linux 2.4.18-rmk7-pxa1((none)) (o) (none)login: (none)login: 我们用我们用 rootroot 登陆,不需要登陆,不需要 passwordpassword 。然后我们可以。然后我们可以 通过以下步骤来下载文件系统:通过以下步骤来下载文件系统:

#cd /tmp #cd /tmp #PATH=$PATH:/image //#PATH=$PATH:/image // 设置路径设置路径#rz#rz键入键入 rzrz 后会出现后会出现rz ready.To begin transfer,type “sz rz ready.To begin transfer,type “sz file…”to your modem programfile…”to your modem program 的信息,我的信息,我们再键入们再键入 Ctrl+Ctrl+‘]’‘]’ ,然后键入:,然后键入:ztelnet>sz root_china.cramfs imagewriteztelnet>sz root_china.cramfs imagewrite在读取完成后在在读取完成后在 /tmp/tmp 目录下会出现目录下会出现root_china.cramfsroot_china.cramfs 、、 imagewriteimagewrite 文件文件然后在开发板的然后在开发板的 linuxlinux 下键入:下键入:#./imagewrite /dev/mtd/0 root_china.cramfs:1M#./imagewrite /dev/mtd/0 root_china.cramfs:1M来完成文件系统的烧写来完成文件系统的烧写

第三章 嵌入式第三章 嵌入式 LinuxLinux 驱动程序开发驱动程序开发第一节 设备驱动程序简介第一节 设备驱动程序简介11 、驱动程序基本概念、驱动程序基本概念 LinuxLinux 系统中,设备驱动程序是操作系统内系统中,设备驱动程序是操作系统内

核的重要组成部分,在与硬件设备之间 建核的重要组成部分,在与硬件设备之间 建立了标准的抽象接口。通过这个接口,用立了标准的抽象接口。通过这个接口,用户可以像处理普通文件一样,对硬件设备户可以像处理普通文件一样,对硬件设备进行打开进行打开 (open)(open) 、关闭、关闭 (close)(close) 、读写、读写 (re(read/write)ad/write) 等操作。通过分析和设计设备驱等操作。通过分析和设计设备驱动程序,可以深入理解动程序,可以深入理解 LinuxLinux 系统和进行系统和进行系统开发。 系统开发。

22 、、 LinuxLinux 设备分类设备分类 LinuxLinux 系统将设备分成系统将设备分成 33种类型。种类型。•字符设备:能够像字节流(比如文件)一样字符设备:能够像字节流(比如文件)一样被访问的设备,例如串口、被访问的设备,例如串口、 SPISPI接口等。接口等。

•块设备:对信息的存取以块为单位的设备,块设备:对信息的存取以块为单位的设备,例如硬盘等。例如硬盘等。

•网络接口:负责发送与接收数据包。网络接口:负责发送与接收数据包。

第二节 驱动程序开发实例第二节 驱动程序开发实例#ifndef __KERNEL__ #ifndef __KERNEL__

#define __KERNEL__ #define __KERNEL__ ////没有这个符号,模块就不能使用内核头文件中 没有这个符号,模块就不能使用内核头文件中

针对内核的特殊内容针对内核的特殊内容 #endif#endif

#ifndef MODULE #ifndef MODULE

#define MODULE #define MODULE //// 重要的符号 重要的符号 #endif#endif

#include <linux/module.h> #include <linux/module.h> ////最基本的内核模块头文件最基本的内核模块头文件 #include <linux/config.h>#include <linux/config.h> // // 最基本的内核模块头文件最基本的内核模块头文件 #include <linux/kernel.h>#include <linux/kernel.h> // // 最基本的内核模块头文件最基本的内核模块头文件#include <linux/sched.h>#include <linux/sched.h> // // 这里包含了进行正确性检查的宏 这里包含了进行正确性检查的宏 #include <linux/fs.h>#include <linux/fs.h> // // 文件系统所必需的头文件文件系统所必需的头文件#include <asm/uaccess.h> //#include <asm/uaccess.h> // 包含内核空间与用户空间进行数据交换时的函数包含内核空间与用户空间进行数据交换时的函数宏 宏

#include <asm/io.h>#include <asm/io.h> // // I/OI/O访问访问

//// 文件被操作时的回调功能文件被操作时的回调功能static int spi_open(struct inode *inode, struct file *file);static int spi_open(struct inode *inode, struct file *file);

static int spi_release(struct inode *inode, struct file *filp);static int spi_release(struct inode *inode, struct file *filp);

static ssize_t spi_write(struct file *filp, const char *buf, size_t count);static ssize_t spi_write(struct file *filp, const char *buf, size_t count);

static ssize_t spi_read(struct file *filp, char *buf, size_t count);static ssize_t spi_read(struct file *filp, char *buf, size_t count);

////申请主设备号时用的结构申请主设备号时用的结构static struct file_operations spi_fops = static struct file_operations spi_fops =

{{

owner: THIS_MODULE,owner: THIS_MODULE,

write: spi_write,write: spi_write,

read: spi_read,read: spi_read,

open: spi_open,open: spi_open,

release: spi_release,release: spi_release,

};};

#define DEVICE_NAME "SPI"#define DEVICE_NAME "SPI"

#define SPI_MAJOR 201#define SPI_MAJOR 201

int result; //int result; // 保存主设备号保存主设备号

//// 在系统中注册设备在系统中注册设备static int __init spi_init(void)static int __init spi_init(void)

{ {

result = register_chrdev(201, "SPI", &spi_fops); //result = register_chrdev(201, "SPI", &spi_fops); // 申请主设备号申请主设备号 if (result < 0) if (result < 0)

{{

cleanup_module();cleanup_module();

return result;return result;

}}

elseelse

{{

printk("The major is:%d\n",result); //printk("The major is:%d\n",result); // 显示主设备号显示主设备号 return 0;return 0;

}}

}}

//// 注销设备注销设备static void __exit spi_cleanup(void)static void __exit spi_cleanup(void)

{{

unregister_chrdev(SPI_MAJOR, "SPI");unregister_chrdev(SPI_MAJOR, "SPI");

printk(DEVICE_NAME " unloaded\n");printk(DEVICE_NAME " unloaded\n");

}}

static int spi_open(struct inode *inode, struct file *file)static int spi_open(struct inode *inode, struct file *file)

{{

MOD_INC_USE_COUNT; //MOD_INC_USE_COUNT; // 当前模块计数加当前模块计数加 11

…… …… //// 对设备进行初始化对设备进行初始化 return 0;return 0;

}}

static int spi_release(struct inode *inode, struct file *filp)static int spi_release(struct inode *inode, struct file *filp)

{{

MOD_DEC_USE_COUNT; //MOD_DEC_USE_COUNT; // 当前模块计数减当前模块计数减 11

return 0;return 0;

}}

//// 写方法写方法static ssize_t spi_write(struct file *filp, const char *buf, size_t count)static ssize_t spi_write(struct file *filp, const char *buf, size_t count)

{{

…… ……

}}

//// 读方法读方法static ssize_t spi_read(struct file *filp, char *buf, size_t count)static ssize_t spi_read(struct file *filp, char *buf, size_t count)

{{

…… ……

}}

module_init(spi_init); module_init(spi_init); ////每当装配设备驱动程序时,系统自动调用此函数每当装配设备驱动程序时,系统自动调用此函数module_exit(spi_cleanup); module_exit(spi_cleanup); ////每当卸载设备驱动程序时,系统自动调用此函数每当卸载设备驱动程序时,系统自动调用此函数

第三节 第三节 LinuxLinux 设备驱动模块的加载与卸载设备驱动模块的加载与卸载11 、编写、编写 MakefileMakefile 文件编译驱动程序:文件编译驱动程序:CC=arm-linux-gcc //CC=arm-linux-gcc // 指定交叉编译器为指定交叉编译器为 arm-linux-gccarm-linux-gcc

LD=arm-linux-ldLD=arm-linux-ld

CFLAGS=-DMODULE -D__KERNEL__ -Wall -OCFLAGS=-DMODULE -D__KERNEL__ -Wall -O

LDFLAGS=-rLDFLAGS=-r

INCDIR=-I/linuette/target/box/usr/src/kernel/includeINCDIR=-I/linuette/target/box/usr/src/kernel/include

TARGET=spii.oTARGET=spii.o

OBJS=spi.oOBJS=spi.o

$(TARGET):$(OBJS) $(TARGET):$(OBJS)

$(LD) $(LDFLAGS) -o $@ $(OBJS) $(LD) $(LDFLAGS) -o $@ $(OBJS)

xxd.o:xxd.c xxd.o:xxd.c

$(CC) $(CFLAGS) $(INCDIR) -c $< -o $@ $(CC) $(CFLAGS) $(INCDIR) -c $< -o $@

clean:clean:

rm *.orm *.o

然后运行然后运行 makemake 对驱动程序进行编译,编译后生成的对驱动程序进行编译,编译后生成的 spi.ospi.o 即为即为 SPISPI 驱动模驱动模块块

22 、对驱动模块的加载与卸载、对驱动模块的加载与卸载• 与与 windowswindows 系统不同,系统不同, LinuxLinux允许随意动态地加载与卸允许随意动态地加载与卸

载操作系统部件。所以,驱动开发调试的方法除了可将驱载操作系统部件。所以,驱动开发调试的方法除了可将驱动直接编译到内核,还可以将驱动编译为模块,使用动直接编译到内核,还可以将驱动编译为模块,使用 insinsmodmod插入内核并进行调试,如果遇到故障又可以使用插入内核并进行调试,如果遇到故障又可以使用 rmrmmodmod从内核中卸载它,无须重新启动内核。第一种方法从内核中卸载它,无须重新启动内核。第一种方法需要修改内核源文件和需要修改内核源文件和 MakefileMakefile 文件,而且把驱动直接文件,而且把驱动直接加入内核重新编译会增加内核的大小,还不能动态卸载,加入内核重新编译会增加内核的大小,还不能动态卸载,不利于调试。比较而言,第二种方法使用更方便,调试效不利于调试。比较而言,第二种方法使用更方便,调试效率更高,所以一般情况下都使用模块加载的方式进行调试。率更高,所以一般情况下都使用模块加载的方式进行调试。

# insmod spi.o //# insmod spi.o // 加载模块加载模块 # mknod /dev/SPI c 201 0 //# mknod /dev/SPI c 201 0 // 创建设备入口点创建设备入口点 # rmmod spi.o //# rmmod spi.o // 卸载模块卸载模块

谢谢大家!谢谢大家!

top related