----------------------- Page 1-----------------------
嵌入式LINUX开发入门
V1.5
1
----------------------- Page 2-----------------------
华恒对社区的贡献
华恒对社区的贡献
本文适用于对嵌入式系统没有概念和经验,
渴望进入嵌入式系统开发的领域,
但又觉得系统太复杂,要学的东西太多,
感觉完全无从学起,无从下手
的
初级开发人员
2
----------------------- Page 3-----------------------
简述
简述
1、嵌入式系统必须以实践入门,所以要学习必须购买嵌入式开发系统
(开发板或实验箱),否则永远只能停留在纸上谈兵的阶段。
2、学习嵌入式LINUX开发,必须注意学习的方式和方法!就把这个嵌
入式开发板当作一台WINDOWS PC,就像用VC一样在上面做开发(只是
开发模式由原来完全的本地开发变成宿主机--目标板的模式了)。
绝对不要去盲目阅读LINUX内核分析之类的书籍,对于初学者一两年内
根本用不到这个!就像在WINDOWS下开发永远不要关心WINDOWS内核一
个道理,不要因为LINUX内核是源代码开放的,就非要去研究LINUX内
核。90%的开发人员关心的还是“外设接口驱动+应用程序(如GUI)”
,所以对于初学者,进入嵌入式LINUX开发的殿堂,必须迈过如下两个
台阶:
嵌入式基本C程序开发及调试方法
基本驱动的概念和开发调试方法
3
----------------------- Page 4-----------------------
嵌入式开发上手学习大纲
嵌入式开发上手学习大纲
* 安装配置一台REDHAT 9的LINUX PC机。宿主机配置(TFTP/NFS)
参见: www.hhcn/chinese/embedlinux-res.html
* 通过终端软件minicom熟悉一下嵌入式系统的基本操作,否则你
根本就不会操作板子!
* 通过NFS mount的方式,学习用C语言开发最基本的嵌入式应用程
序,并熟悉嵌入式的调试方法。(HHARM9-EDU实验1)
* 熟悉掌握嵌入式LINUX下的编译方法和技巧,并进一步掌握调试
复杂嵌入式应用程序的方法和技巧。(HHARM9-EDU实验2、3)
* 通过NFS mount的方式,学习如何使用一个基本的嵌入式LINUX下
的设备驱动(insmod驱动+测试用应用程序),并尝试着改改看
如何发生变化和如何调试。(HHARM9-EDU实验6中断、
14GPIO/key、AD/DA、I2C等)
* 进一步深入学习其它的接口技术。(HHARM9-EDU其它剩余实验)
【注意】
做到这里您一次都不需要烧写FLASH!
4
----------------------- Page 5-----------------------
Tips--再谈学习的方式方法
Tips--再谈学习的方式方法
早早安装一台REDHAT 9 LINUX的PC,下面这些必须熟悉了解(因为它将是我
们 日 后 开 发 最 佳 的 测 试 伙 伴 ) :
telnet/ncftp/tar(xzf/czf)/vi/grep/find/NFS/tftp等常用操作;熟悉了解
LINUX系统的文件目录构成(/bin/sbin/etc/home/dev/usr等的意义,系统搜
索路径PATH<;例如当前路径和WINDOWS不同,不在LINUX的搜索路径里面,必须
指定./才行>因为嵌入式LINUX上和这个完全一样) (关于这些LINUX常用知识
请参见HHARM2410产品技术手册附录B,那里没有无用的抄袭,而是一线研发
人员实际的总结)
大致了解LINUX内核源代码的文件目录的构成(主要就是drivers目录,它是我
们最常打交道的驱动的目录)。因为我们对于LINUX下驱动的开发最重要的工
作学习的方法就是:“搜索+模仿” 。大家都知道LINUX是开放源代码的,但
其实很多人并没有意识到这个对于我们实际的开发有什么意义。就像面前摆
了一座宝库,但却不知如何去寻宝。我们寻宝的手段就是搜索。对于驱动,
LINUX开放的代码(drivers目录+google网络)里面提供了无数常见接口芯片
的驱动代码或模板(如串口serial.c、framebuffer驱动等),我们首先要知道
这些文件在哪个目录下,到后就是大致读一下,出与自己实际硬件的差
异,以此为基础修修改改即可。而修改时一个重要的手段就是模仿现有的代
码!
5
----------------------- Page 6-----------------------
Tips--再谈学习的方式方法
Tips--再谈学习的方式方法
在嵌入式板卡上做任何稍微复杂些的工作,心里没底的话,就一定养成先在
REDHAT LINUX PC上测试的好习惯。无论你做GPRS/CDMA/PPP/ADSL拨号还是做
USB无线网卡驱动,还是做SAMBA/VPN/SNMP等协议软件,都先在REDHAT LINUX
上配置好,测试通过有了感觉之后再到嵌入式上试,因为ARMLINUX跟REDHAT
LINUX对于我们
开发人员而言几乎没有任何区别!切忌冒进!
不要试图去通读CPU的manual,没有用的,就像不要为了做嵌入式LINUX就要
通读LINUX内核源代码分析一个道流。以目前实际的工作为主线,涉及到什么
再去大致了解一下相关内容,例如我们第二步要做MODULES形式的驱动,那么
这时去大致翻翻那本《LINUX驱动开发》一书的几页还是会有些帮助的,但也
没有必要全部通读!
6
----------------------- Page 7-----------------------
嵌入式开发模式
嵌入式开发模式
交换机
网
线
网线
【宿主机】
串口线
HHARM开发板
假设IP为:192.168.2.120
【目标板】
运行Redhat Linux的PC机
假设IP为:192.168.2.2.122
交叉编译
7
----------------------- Page 8-----------------------
第一部分
嵌入式基本C程序开发和调试
8
----------------------- Page 9-----------------------
嵌入式基本C程序开发和调试
嵌入式基本C程序开发和调试
9
----------------------- Page 10-----------------------
关于Makefile
关于Makefile
Makefile就是一个批处理的脚本!通过执行make来调用
EXEC = hello
OBJS = hello1.o #hello2.o hello3.o
LIBS += #-lcrypt -lm
all: $(EXEC)
$(EXEC) : $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) –o $(EXEC) $(OBJS) $(LIBS)
clean:
rm -f $(OBJS) $(EXEC)
#Note
#表示注释,这是个通用的模板,我们的例子里面只用到一个hello1.c,而
且也不需要链接加密库(libcrypt.a)和数学库(libm.a)。hello1.c的
内容就不需要写了吧,就一个printf语句
10
----------------------- Page 11-----------------------
NFS mount调试方法进阶
NFS mount调试方法进阶
前面./hello的方
式用来调试最简单的主动执行的应用程序。还有很多的
应用程序要复杂一些,例如minigui/qt/microwin等GUI系统,它除了
可执行文件外,还涉及自己的动态库libxxx.so;还有另外一些如CGI类
的被动的被其它程序激发执行的程序对于这样的复杂程序调试,可如下
操作: (细节处有一些操作目录的变化)
在REDHAT LINUX PC上执行: 在minicom等终端里执行:
mkdir /2410lib; mount –o nolock
192.168.2.122:/2410lib /lib
gunzip
mount -o nolock 192.168.2.122:/ /mnt
mount –o loop ramdisk.image /tmp
/
mnt/treeview&
cp –f /tmp/lib/* /2410lib #这样就可以NFS调试带动态库的复杂程序了
注意:
从上可见,板子可以多次mount多个目录,或者多个不同IP的PC的不同硬盘目录,甚至可以将
板子上所有的目录都用PC硬盘上的同类目录覆盖掉
同时可以看出这时的目标板就像一台UNIX主机一样可以为多个开发人员提供并行开发的环境。
11
----------------------- Page 12-----------------------
第二部分
基本驱动的概念和开发调试方法
12
-
---------------------- Page 13-----------------------
基本驱动的概念和开发调试方法
基本驱动的概念和开发调试方法
ARMLINUX不同于uClinux,因为启动了MMU,所以应用程序不能直接
读写物理地址(包括CPU寄存器<;含GPIO端口、中断等CPU 内部资源>、
MEMORY、外设芯片内部寄存器等),而必须借助与驱动的形式,切入
内核用ioremap来实现对这些物理地址的访问。
下面以一个最常见的GPIO操作为例来说明:
就是选择S3C2410的GPIO_C6口作为一个输出口线,用户通过一个应用程序调用驱
动程序来控制这个口线输出1或者0,即高低电平。
例子由两部分构成:“驱动(gpio_driv.c)+应用程序(gpio_test.c)”
LINUX下的驱动有两种形式:
MODULES形式的可动态加载的驱动(这是LINUX 内核一个非常重要
的特点),我们测试用建议都用这种形式的,因为它调试就和普通应用
程序一样,可以通过NFS mount 的方式来调试,非常方便。
静态编译到内核里面的驱动
13
----------------------- Page 14-----------------------
基本驱动
的概念和开发调试方法
基本驱动的概念和开发调试方法
样例modules形式驱动的测试用法如下:
NFS mount宿主机后,
insmod gpio_driv.o #在板上嵌入式LINUX 内核已经跑起来之后动态加载驱动module
mknod /dev/gpiotest c 220 0
./gpio_test #执行测试用的应用程序来调用驱动,来驱动IO输出高低电平
0:set ,1:clear,2: quit :
用户输入0,则C6 口输出3.3V高电平;用户输入1,则C6 口输出0低电平。
应用程序如何调用驱动以及驱动要注意的一些细节在下面的详细代码中通过注释
的形式一一说明。
14
----------------------- Page 15-----------------------
驱动MODULE源代码
驱动MODULE源代码
#include <linux/fs.h> //FILE: gpio_driv.c
#include <linux/iobuf.h>
#include <linux/major.h>
#include <linux/blkdev.h>
#include <linux/capability.h>
#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <asm/hardware.h>
#include <asm/arch/cpu_s3c2410.h>
#include <asm/io.h>
#include <linux/vmalloc.h>
#define IOPORT_MAJOR 220 //定义主设备号,和前面的mknod /dev/gpiotest c 220 0匹配
typedef char ioport_device_t; long port_addr;
static ioport_device_t gpio_devices[257];
int gpio_open(struct inode *, struct file *);
int gpio_release(struct inode *, struct file *);
int gpio_ctl_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
15
----------------------- Page 16-----------------------
驱动MODULE源代码
驱动MODULE源代码
static struct file_operations gpio_ctl_fops = {
ioctl: gpio_ctl_ioctl,
嵌入式linux开发书籍open: gpio_open,
release: gpio_release,
};
//所有的操作系统将硬件设备当作文件处理,所有外设的操作就封装在这个file_operations 结构体里面
//就是文件的open/read/write/close等操作,剩余的都放到一个ioctl函数里面做处理。
int __init gpio_init(void)
{
int i;
//可以看到下面这句向操作系统注册的函数里面和前面我们在minicom里面手工创建的设备文件是
/
/要完全匹配的: mknod /dev/gpiotest c 220 0,这表明创建的是一个字符设备(chrdev),
//主设备号220,次设备号0,因为操作系统不理会“gpiotest”这个设备名字符串的,它只认数字的主次
//设备号,而应用程序到时是open(“/
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论