250 likes | 426 Views
嵌入式系统 驱动程序开发 专题报告 罗晟 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 、文件系统的下载
E N D
嵌入式系统 驱动程序开发 专题报告 罗晟 2007年3月20日
第一章 嵌入式系统开发基础 第一节 vivi、kernel和文件系统的下载 1、vivi的下载
2、超级终端参数的设置 • 开启超级终端,设置串口COM1
在vivi环境中对flash进行分区 vivi>bon part 0 192k 1M
3、kernel的下载 通过超级终端下载内核镜像文件: vivi>load flash kernel x
4、文件系统的下载 vivi>load flash root x
至此整个嵌入式Linux系统已经建立,按复位 键启动vivi,然后按回车,Linux将启动
第二节 嵌入式Linux开发环境的建立 1、交叉编译器的安装 • 在/usr/local下建立一个arm目录: mkdir /usr/local/arm 然后把叫交叉编译包复制到此目录下: cp –rf cross-2.95.3.tar.bz2 • 解压缩cross-2.95.3.tar.bz2交叉编译包: cd /usr/local/arm tar –jxvf cross-2.95.3.tar.bz2 • 为了方便使用交叉编译器,我们修改PATH变量: cd /etc vi profile //进入profile 按i //insert 找到pathmunge /usr/local/sbin,在其下面添加一行 pahtmunge /usr/local/arm/2.95.3/bin,按ESC退出 insert,再按‘shift’+‘:’,然后键入‘wq!’
2、minicom参数设置 首先进入minicom,然后按Ctrl+a,再按o, 出现如下界面:
同超级终端的参数设置,要注意的是Serial device 为/dev/ttys0 3、ztelnet的安装 rpm –ivh ztelnet-0.9.1-7mz.i386.rpm
第二章 嵌入式Linux的移植 1、设置IP地址 进入开发板中的Linux后,我们键入: #ifconfig eth0 192.168.1.171 #inetd • 修改文件系统中的/usr/etc/rc.local,找到/sbin/ifconfig eth0 192.168.1.XXX这一行,把192.168.1.XXX修改成为你想用的IP地址 然后启动PC机上的Linux,键入: #ping 192.168.1.171 查看是否能与开发板通讯
2、利用ztelnet下载文件系统 首先在linux下建立/image目录,把远峰资料中的 /image里面的所有内容拷贝到该目录下,然后在 终端中键入ztelnet 192.168.1.171,会出现如下 信息: Trying 192.168.1.171… Connected to 192.168.1.171. Escape character is ‘^]’ Linux 2.4.18-rmk7-pxa1((none)) (o) (none)login: 我们用root登陆,不需要password。然后我们可以 通过以下步骤来下载文件系统:
#cd /tmp #PATH=$PATH:/image //设置路径 #rz 键入rz后会出现 rz ready.To begin transfer,type “sz file…”to your modem program的信息,我 们再键入Ctrl+‘]’,然后键入: ztelnet>sz root_china.cramfs imagewrite 在读取完成后在/tmp目录下会出现 root_china.cramfs、imagewrite文件 然后在开发板的linux下键入: #./imagewrite /dev/mtd/0 root_china.cramfs:1M 来完成文件系统的烧写
第三章 嵌入式Linux驱动程序开发 第一节 设备驱动程序简介 1、驱动程序基本概念 Linux系统中,设备驱动程序是操作系统内核的重要组成部分,在与硬件设备之间 建立了标准的抽象接口。通过这个接口,用户可以像处理普通文件一样,对硬件设备进行打开(open)、关闭(close)、读写(read/write)等操作。通过分析和设计设备驱动程序,可以深入理解Linux系统和进行系统开发。
2、Linux设备分类 Linux系统将设备分成3种类型。 • 字符设备:能够像字节流(比如文件)一样被访问的设备,例如串口、SPI接口等。 • 块设备:对信息的存取以块为单位的设备,例如硬盘等。 • 网络接口:负责发送与接收数据包。
第二节 驱动程序开发实例 #ifndef __KERNEL__ #define __KERNEL__ //没有这个符号,模块就不能使用内核头文件中 针对内核的特殊内容 #endif #ifndef MODULE #define MODULE //重要的符号 #endif #include <linux/module.h> //最基本的内核模块头文件 #include <linux/config.h> //最基本的内核模块头文件 #include <linux/kernel.h> //最基本的内核模块头文件 #include <linux/sched.h> //这里包含了进行正确性检查的宏 #include <linux/fs.h> //文件系统所必需的头文件 #include <asm/uaccess.h> //包含内核空间与用户空间进行数据交换时的函数宏 #include <asm/io.h> // I/O访问
//文件被操作时的回调功能 static int spi_open(struct inode *inode, struct file *file); 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_read(struct file *filp, char *buf, size_t count); //申请主设备号时用的结构 static struct file_operations spi_fops = { owner: THIS_MODULE, write: spi_write, read: spi_read, open: spi_open, release: spi_release, }; #define DEVICE_NAME "SPI" #define SPI_MAJOR 201 int result; //保存主设备号
//在系统中注册设备 static int __init spi_init(void) { result = register_chrdev(201, "SPI", &spi_fops); //申请主设备号 if (result < 0) { cleanup_module(); return result; } else { printk("The major is:%d\n",result); //显示主设备号 return 0; } }
//注销设备 static void __exit spi_cleanup(void) { unregister_chrdev(SPI_MAJOR, "SPI"); printk(DEVICE_NAME " unloaded\n"); } static int spi_open(struct inode *inode, struct file *file) { MOD_INC_USE_COUNT; //当前模块计数加1 …… //对设备进行初始化 return 0; } static int spi_release(struct inode *inode, struct file *filp) { MOD_DEC_USE_COUNT; //当前模块计数减1 return 0; }
//写方法 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) { …… } module_init(spi_init); //每当装配设备驱动程序时,系统自动调用此函数 module_exit(spi_cleanup); //每当卸载设备驱动程序时,系统自动调用此函数
第三节 Linux设备驱动模块的加载与卸载 1、编写Makefile文件编译驱动程序: CC=arm-linux-gcc //指定交叉编译器为arm-linux-gcc LD=arm-linux-ld CFLAGS=-DMODULE -D__KERNEL__ -Wall -O LDFLAGS=-r INCDIR=-I/linuette/target/box/usr/src/kernel/include TARGET=spii.o OBJS=spi.o $(TARGET):$(OBJS) $(LD) $(LDFLAGS) -o $@ $(OBJS) xxd.o:xxd.c $(CC) $(CFLAGS) $(INCDIR) -c $< -o $@ clean: rm *.o 然后运行make对驱动程序进行编译,编译后生成的spi.o即为SPI驱动模块
2、对驱动模块的加载与卸载 • 与windows系统不同,Linux允许随意动态地加载与卸载操作系统部件。所以,驱动开发调试的方法除了可将驱动直接编译到内核,还可以将驱动编译为模块,使用insmod插入内核并进行调试,如果遇到故障又可以使用rmmod从内核中卸载它,无须重新启动内核。第一种方法需要修改内核源文件和Makefile文件,而且把驱动直接加入内核重新编译会增加内核的大小,还不能动态卸载,不利于调试。比较而言,第二种方法使用更方便,调试效率更高,所以一般情况下都使用模块加载的方式进行调试。 # insmod spi.o //加载模块 # mknod /dev/SPI c 201 0 //创建设备入口点 # rmmod spi.o //卸载模块