4452|6

565

帖子

513

TA的资源

裸片初长成(中级)

楼主
 

华恒工程师谈嵌入式LINUX入门 [复制链接]

看到不错,转载过来与大家分享下

本文适用于对嵌入式系统没有概念和经验,渴望进入嵌入式系统开发的领域,但又觉得系统太复杂,要学的东西太多,感觉完全无从学起,无从下手的初级开发人员

1、嵌入式系统必须以实践入门,所以要学习必须购买嵌入式开发系统(开发板或实验箱),否则永远只能停留在纸上谈兵的阶段。

2、学习嵌入式LINUX开发,必须注意学习的方式和方法!就把这个嵌入式开发板当作一台WINDOWS PC,就像用VC一样在上面做开发(只是开发模式由原来完全的本地开发变成宿主机--目标板的模式了)。绝对不要去盲目阅读LINUX内核分析之类的书籍,对于初学者一两年内根本用不到这个!就像在WINDOWS下开发永远不要关心WINDOWS内核一个道理,不要因为LINUX内核是源代码开放的,就非要去研究LINUX内核。90%的开发人员关心的还是“外设接口驱动+应用程序(如GUI)”,所以对于初学者,进入嵌入式LINUX开发的殿堂,必须迈过如下两个台阶:
..嵌入式基本C程序开发及调试方法
..基本驱动的概念和开发调试方法

嵌入式开发上手学习大纲

.安装配置一台REDHAT 9的LINUX PC机。宿主机配置(TFTP/NFS)参见:http://www.hhcn.com/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!

再谈学习的方式方法
..早早安装一台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驱动等),我们首先要知道这些文件在哪个目录下,找到后就是大致读一下,找出与自己实际硬件的差异,以此为基础修修改改即可。而修改时一个重要的手段就是模仿现有的代码!

..在嵌入式板卡上做任何稍微复杂些的工作,心里没底的话,就一定养成先在REDHAT LINUX PC上测试的好习惯。无论你做GPRS/CDMA/PPP/ADSL拨号还是做
USB无线网卡驱动,还是做SAMBA/VPN/SNMP等协议软件,都先在REDHAT LINUX上配置好,测试通过有了感觉之后再到嵌入式上试,因为ARMLINUX跟REDHAT LINUX对于我们开发人员而言几乎没有任何区别!切忌冒进!

..不要试图去通读CPU的manual,没有用的,就像不要为了做嵌入式LINUX就要通读LINUX内核源代码分析一个道流。以目前实际的工作为主线,涉及到什么再去大致了解一下相关内容,例如我们第二步要做MODULES形式的驱动,那么这时去大致翻翻那本《LINUX驱动开发》一书的几页还是会有些帮助的,但也没有必要全部通读!

嵌入式开发模式

交叉编译
运行RedhatLinux的PC机
假设IP为:192.168.2.2.122
串口线
HHARM开发板
假设IP为:192.168.2.120
【目标板】
【宿主机】

线
网线
交换机

第一部分

嵌入式基本C程序开发和调试

关于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语句..

NFS mount调试方法进阶

前面./hello的方式用来调试最简单的主动执行的应用程序。还有很多的应用程序要复杂一些,例如minigui/qt/microwin等GUI系统,它除了可执行文件外,还涉及自己的动态库libxxx.so;还有另外一些如CGI类的被动的被其它程序激发执行的程序对于这样的复杂程序调试,可如下

操作: (细节处有一些操作目录的变化)

注意:
..从上可见,板子可以多次mount多个目录,或者多个不同IP的PC的不同硬盘目录,甚至可以将板子上所有的目录都用PC硬盘上的同类目录覆盖掉

..同时可以看出这时的目标板就像一台UNIX主机一样可以为多个开发人员提供并行开发的环境。在REDHAT LINUX PC上执行:mkdir /2410lib; gunzip ramdisk.image.gzmount –o loop ramdisk.image /tmpcp –f /tmp/lib/* /2410lib在minicom等终端里执行:
mount –o nolock
192.168.2.122:/2410lib /libmount -o nolock 192.168.2.122:/ /mnt/mnt/treeview&
#这样就可以NFS调试带动态库的复杂程序了

第二部分

基本驱动的概念和开发调试方法
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的方式来调试,非常方便。
..静态编译到内核里面的驱动

基本驱动的概念和开发调试方法
样例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低电平。
应用程序如何调用驱动以及驱动要注意的一些细节在下面的详细代码中通过注释
的形式一一说明。

驱动MODULE源代码
#include //FILE: gpio_driv.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define IOPORT_MAJOR 220 //定义主设备号,和前面的mknod/dev/gpiotestc 220 0匹配
typedefchar ioport_device_t; long port_addr;
static ioport_device_t gpio_devices[257];
int gpio_open(struct inode*, structfile *);
int gpio_release(struct inode*, structfile *);
int gpio_ctl_ioctl(struct inode *, struct file *, unsigned int, unsigned long);

驱动MODULE源代码
..±..ò: static struct file_operations gpio_ctl_fops = {
ioctl: gpio_ctl_ioctl,
open: gpio_o
驱动MODULE源代码
int gpio_open(struct inode*inode, structfile *filp)
{
intminor;
minor = MINOR(inode->i_rdev);
#if 0 //这里是通常的做法,因为S3C2410的LINUX内核提供了set_gpio_ctrl专用函数,所以不要下面
这样做了
(void *)(port_addr) = ioremap(0x56000020,0x8);
*(volatile unsigned int*)(port_addr)|=0x00008000;
#endif
//驱动里面在open这个设备的时候设置这个口为输出(因为GPIO必须设置方向,做输入还是输出)
set_gpio_ctrl(GPIO_MODE_OUT | GPIO_C6);
gpio_devices[minor]++;
return 0;
}

驱动MODULE源代码
int gpio_release(struct inode*inode, structfile *filp)
{ intminor;
minor = MINOR(inode->i_rdev);
if (gpio_devices[minor])
gpio_devices[minor]--;
return 0;
}
int gpio_ctl_ioctl(struct inode*inode,structfile *flip,unsigned intcommand,unsigned long arg)
{
interr = 0;
intminor = MINOR(inode->i_rdev);
switch (command) {
case IOWRITE:
write_gpio_bit(GPIO_MODE_OUT | GPIO_C6,1); //输出3.3V电平
return 0;
case IOCLEAR:
write_gpio_bit(GPIO_MODE_OUT | GPIO_C6,0); //输出0电平
return 0;
}
return err;
}

[ 本帖最后由 绿茶 于 2009-6-3 16:41 编辑 ]

最新回复

顶了.不错.  详情 回复 发表于 2009-6-28 21:33
点赞 关注

回复
举报

565

帖子

513

TA的资源

裸片初长成(中级)

沙发
 
基本驱动MODULE的MakefileCC = /opt/host/armv4l/bin/armv4l-unknown-linux-gcc
LD = /opt/host/armv4l/bin/armv4l-unknown-linux-ld
CFLAGS = -D__KERNEL__ -I/HHARM2410-R3/kernel/include/linux-I/HHARM2410-R3/kernel/include -Wall -Wstrict-prototypes -Wno-trigraphs-
Os -mapcs-fno-strict-aliasing-fno-common -fno-common -pipe -mapcs-32
-march=armv4 -mtune=arm9tdmi -mshort-load-bytes -msoft-float
-DKBUILD_BASENAME= gpio_driv
-I/opt/host/armv4l/src/linux/include -DMODULE
gpio_driv.o: gpio_driv.c
$(CC) $(CFLAGS) -c $^ -o $@
cp gpio_driv.o / -f
clean:
-rm-f *.o
注意!驱动程序的Makefile和应用程序的参数不同!

测试驱动的应用程序
#include //FILE: gpio_test.c
#include
#include …//省略一些头文件
#include
#define DEVICE_GPIOTEST "/dev/gpiotest"
intmain()
{
int fd; int val=-1;
if((fd=open(DEVICE_ GPIOTEST,O_RDONLY | O_NONBLOCK))<0)//应用程序就是这样调用驱动的
{ perror("can not open device"); exit(1); }
while(1){
printf("0:set ,1:clear,2: quit :");
scanf("%d",&val);
if(val==0)
ioctl(fd,IOWRITE,0);//应用程序就是这样调用驱动的
else if(val==1)
ioctl(fd,IOCLEAR,0);//应用程序就是这样调用驱动的
else if(val==2){
close(fd); …
}
}

最后可试试烧写FLASH了
完成自己的小驱动和测试用应用程序后,您可以将自己的初步成就烧写到板子里去了,具体的烧
写可参见我们产品手册或者HHARM FAQ
如何加入到板子的文件系统里?
文件系统就是用来存放用户应用程序的集合。
HHARM9系列嵌入式LINUX开发系统的根文件系统采用的是ramdisk。
下面举例说明用户如何把自己的hello程序烧写到板子上去:
先把ramdisk.image.gz解压后mount -o loop 到一个目录上,这样就可以看到ramdisk里面的文
件及目录内容,这时再把你编译号的hello这个可执行文件复制到这个目录的bin目录下面,再
umount这个目录,再gzip压缩,这样你所作的改动就被带到这个新生成的ramdisk.image.gz文件
里面了,然后你烧写这个文件就可以在板子上看到你的hello了。
简单命令序列:注意要自己调整目录路径,所有操作均在REDHAT LINUX PC机上完成:
gunzip ramdisk.image.gz
mkdir tmnt
mount -o loop ramdisk.image tmnt
cp -f busybox tmnt/bin
umount tmnt
gzip ramdisk.image
cp -f ramdisk.image.gz /tftpboot ;再后面的烧写步骤这里就不再赘述,参见HHARM FAQ或者我们手册即可
 
 

回复

65

帖子

0

TA的资源

纯净的硅(初级)

板凳
 
顶一顶。。 总是没错的。
 
 
 

回复

2131

帖子

0

TA的资源

至上芯片

4
 
你应该给我讲一下,linux移植的过程!
 
个人签名处处留心皆学问!
 
 

回复

77

帖子

0

TA的资源

五彩晶圆(初级)

5
 

好东西

我也觉得应该多讲一下移植过程
 
 
 

回复

11

帖子

0

TA的资源

一粒金砂(中级)

6
 
顶起呀!!!!
 
 
 

回复

30

帖子

0

TA的资源

一粒金砂(中级)

7
 
顶了.不错.
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表