第7章 嵌入式uClinux及其应用开发2文档格式.docx
- 文档编号:22589237
- 上传时间:2023-02-04
- 格式:DOCX
- 页数:38
- 大小:151.50KB
第7章 嵌入式uClinux及其应用开发2文档格式.docx
《第7章 嵌入式uClinux及其应用开发2文档格式.docx》由会员分享,可在线阅读,更多相关《第7章 嵌入式uClinux及其应用开发2文档格式.docx(38页珍藏版)》请在冰豆网上搜索。
#defineDSD0(2<
12)/*RAMBank0*/
#defineDSD1(0<
14)
#defineDSD2(0<
16)
#defineDSD3(0<
18)
#defineDSX0(0<
20)/*EXTIO0*/
#defineDSX1(0<
22)
#defineDSX2(0<
24)
#defineDSX3(0<
26)
#definerEXTDBWTH(DSR0|DSR1|DSR2|DSR3|DSR4|DSR5|DSD0|DSD1|DSD2|DSD3|DSX0|DSX1|DSX2|DSX3)
以上定义了系统存储器控制寄存器,按照以上定义,ROM/SRAM/FLASHBank0定义为16位数据宽度(事实上,ROM/SRAM/FLASHBank0的数据宽度由B0SIZE[1:
0]的状态决定),而ROM/SRAM/FLASHBank1~ROM/SRAM/FLASHBank5禁用;
DRAM/SDRAMBank0定义为16位数据宽度,DRAM/SDRAMBank1~DRAM/SDRAMBank3禁用;
外部I/O组全部禁用;
若用户系统的存储器系统配置不同,应在此处修改。
之后还做了其他一些改动,包括对ROM/SRAM/FLASHBank0控制寄存器的设置,Flash容量的设置,DRAM/SDRAMBank0控制寄存器的设置,SDRAM容量的设置等,这些设置均应该与用户系统对应。
7.3.3编译uClinux内核
作为操作系统的核心,uClinux内核负责管理系统的进程、内存、设备驱动程序、文件系统和网络系统,决定着系统的各种性能。
uClinux内核的源代码是完全公开的,任何人只要遵循GPL,就可以对内核加以修改并发布给他人使用,因此,在广大编程人员的支持下,uClinux的内核版本不断更新,新的内核修改了旧的内核的缺陷,并增加了许多新的特性,用户如果想在自己的系统中使用这些新的特性,或想根据自己的系统量身定制更高效、更稳定可靠的内核,就需要重新编译内核。
一般说来,更新的内核版本会支持更多的硬件,具有更好的进程管理能力,运行速度会更快、更稳定,并且一般都会修复旧版本中已发现的缺陷等,因此,经常选择升级更新的系统内核是必要的。
uClinux内核采用模块化的组织结构,通过增减内核模块的方式来增减系统的功能,因此,正确合理的设置内核的功能模块,从而只编译系统所需功能的代码,会对系统的运行进行如下几个方面的优化:
—
用户根据自身硬件系统的实际情况定制编译的内核因为具有更少的代码,一般会获得更高的运行速度。
由于内核代码在系统运行时会常驻内存,因此,更短小的内核会获得更多的用户内存空间。
减少内核中不必要的功能模块,可以减少系统的漏洞,从而增加系统的稳定性和安全性。
uClinux的内核源代码可以从许多网站上免费下载,内核的发布一般有两种形式,一种是完整的内核版本,完整的内核版本一般是.tar.gz文件,使用时需要解压。
另一种是通过对旧的版本发布补丁(patch),达到升级的效果。
本例所采用的在Linux下使用的交叉编译器和uClinux-Samsung-20020318.tar.gz源码均来自网站http:
//mac.os.nctu.edu.tw/。
在准备好uClinux的内核源代码后,利用交叉编译器就可以编译生成运行在硬件目标板上的uClinux内核。
从http:
//mac.os.nctu.edu.tw/上下载uClinux内核源代码uClinux-Samsung-20020318.tar.gz,保存到宿主机的用户目录。
运行解压命令:
tarxzvfuClinux-Samsung-250020318.tar.gz
解压完毕后,就会在用户目录下生成uClinux-Samsung目录,以下命令进入到该目录中:
$cduClinux-Samsung
1.
键入命令:
makemenuconfig
内核配置。
该命令执行完毕后生成文件.config,它保存这个配置信息。
下一次再做makemenuconfig的时候将产生新的.config文件,原来的.config被改名为.config.old。
此时会出现菜单配置对话框,要求进行目标平台的选择,如图7.6所示,输入回车后,出现供选择的具体的供应商和产品列表,在这里我们选择:
Samsung/4510B,如图7.7所示,在库的选择上,我们选择uC-libc,其他选项暂时不用修改,保存好设置后,存盘退出。
图7.6目标平台配置
图7.7选择合适的产品类型
2.键入命令:
makedep
该命令用于寻找依存关系。
3.键入命令:
makeclean
该命令清除以前构造内核时生成的所有目标文件,模块文件和一些临时文件。
1.
makelib_only
该命令编译库文件。
2.
makeuser_only
该命令编译用户应用程序文件。
3.
makeromfs
该命令生成romfs文件系统。
4.
makeimage
注意做到这一步的时候可能会出现错误的信息提示,类似于:
arm-elf-objcopy:
/home/nie/uClinux-Samsung/linux-2.4.x/linux:
Nosuchfileordirectory
make[1]:
***[image]Error1
Leavingdirectory`/home/nie/uClinux-Samsung/vendors/Samsung/4510B'
make:
***[image]Error2
这是因为第一次编译时还没有romfs.o,所以出错,等romfs.o编译好了以后,如果再进行内核的编译,就不会出现这个错误信息了。
它完全不影响内核的编译,可以完全不必理会这个错误信息。
继续进行编译工作。
5.
make
通过各个目录的Makefile文件进行,会在各目录下生成一大堆目标文件。
上述步骤完成后,就完成了对uClinux源码的编译工作。
整个编译过程视计算机运行速度而定,大约需要十几分钟左右。
在编译内核的时,建议在Linux平台下进行。
7.3.4内核的加载运行
当内核的编译工作完成之后,会在/uClinux-Samsung/images目录下看到两个内核文件:
image.ram和image.rom,其中,可将image.rom烧写入ROM/SRAM/FLASHBank0对应的Flash存储器中,当系统复位或上电时,内核自解压到SDRAM,并开始运行。
image.ram可直接在系统的SDRAM中运行,使用ADS(或SDT)集成开发环境将系统的SDRAM映射到起始地址为0x0处,并将image.ram载入从0x8000开始的SDRAM中,加载完毕后,修改PC指针寄存器的值为0x8000并执行。
注意该内核默认串行口COM1为输入输出控制台,波特率为19200,8个数据位,1个停止位,无校验。
7.4在uClinux下开发应用程序
当完成了上述所有工作后,一个嵌入式应用开发平台就已经搭建好了,在这个平台之上,就可以根据不同需要开发嵌入式应用了。
图7.8所示为一个基于uClinux的嵌入式系统典型框架结构,下面将向读者介绍如何将自己开发的应用程序添加到目标板上运行。
图7.8基于uClinux嵌入式系统框图
基于uClinux系统的应用程序的开发通常是在标准Linux平台上(本书已经介绍了适用于Windows环境的交叉编译器,所以也可以在Windows平台)用交叉编译工具来完成。
由于uClinux是为没有内存管理单元(MMU)的处理器和控制器而设计的,并做了较大幅度的精简,所以可能出现这样的情况:
在标准Linux下可以使用的某些函数在uClinux下却用不了,这个时候,就需要用户编写相应的库函数了。
当然绝大多数的函数它们都还是通用的。
除此以外,在x86版本的gcc编译器下编译通过的软件,通常不需要做太大的改动就可以用刚才我们建立的交叉编译工具编译成可以在uClinux上运行的文件格式。
因此开发在uClinux下运行的程序,基本上就和开发在Linux下运行的程序是一样的,关于Linux下的编程,读者可以参考其他更详细的资料,以下就一个简单的例子,描述其基本开发过程。
考虑一个定时中断的例子,文件名为lednxy.c,其源代码如下:
/*******************************************************
*InstituteofAutomation,ChineseAcademyofSciences
*FileName:
lednxy.c
*Description:
timinginterrupt
*Author:
XueyuanNie
*Date:
*******************************************************/
#include<
signal.h>
unistd.h>
#defineIOPMOD(*(volatileunsigned*)0x3ff5000)
#defineIOPDATA(*(volatileunsigned*)0x3ff5008)
inti=0;
staticvoidsig_alarm(intsignumber)
{
if(i==3)i=0;
IOPDATA=i++;
alarm
(2);
}
intmain(void)
IOPMOD=0xff;
if(signal(SIGALRM,sig_alarm)==SIG_ERR)
{
printf(“someerroroccurs\n”);
return1;
}
while
(1);
return0;
在代码中,SIGALRM为系统定义的信号的名字,在头文件里被定义为一个正整数,用户自定义函数sig_alarm()为信号处理函数,系统函数alarm()用来设定一个2秒的定时器,当定时器时间片终止的时候,进程将会产生SIGALRM信号,在程序中用函数signal()实现了信号SIGALRM和信号处理函数sig_alarm()的连接,这样,当用alarm()函数设置时钟的时间段终止时,就会有SIGALRM信号产生,程序就会转而执行函数sig_alarm(),从而实现每隔2秒钟,I/O口数据寄存器的值发生一次变化,达到控制LED等的目的。
有关signal()函数和alarm()函数的使用,读者可以查阅有关在Linux上的C编程方面的内容,本书在此不作详述。
该程序达到的效果就是,让目标硬件上的P0和P1口的两个LED显示器按照P0亮,P1亮,P0、P1全亮的顺序,每隔2秒实现其中的一种状态。
在装有标准Linux的宿主机(或装有Cygwin的windows的PC机)上,用前面已经建立好的交叉编译工具编译源文件,在该程序所在的目录下键入如下命令:
arm-elf-gcc–Wall–O2–Wl,-elf2flt–olednxylednxy.c
仍然在该目录下,键入命令:
ls
可以查看到在该目录下生成了文件名为lednxy的文件。
在键入的编译命令中,选项:
-Wall指定产生全部的警告信息;
-O2是一个二级优化选项,它表示告诉编译器产生尽可能小和尽可能快的代码;
-Wl的一般用法是’’-Wl,option’’就是把它后面的选项传递给链接器,在本命令中就是把’’-elf2flt‘’传给链接器;
-elf2flt指定自动调用elf转换flat格式的工具;
之所以要使用该选项是因为,由于GNU工具本身并不支持flat格式的二进制文件,然而,uClinux目前只支持flat格式的可执行文件,因此必须使用相应的二进制工具进行格式转换。
flat格式是对elf格式的很大的文件头和一些段信息做了简化的文件格式。
编译成功后得到的lednxy就可以在uClinux环境上运行了。
关于如何将生成的可执行代码加入到uClinux,将在后面的章节讲述。
除了以命令行的形式进行代码编译外,我们还可以利用前面提到的makefile的知识,用makefile文件实现代码编译的功能。
下面给出本例相应的makefile文件(该文件名为makefile)。
CFLAGS=-Wall–Os–Dlinux–D__linux__-Dunix–D__uClinux__-DEMBED
LDFLAGS=-Wl,-elf2flt
CC=arm-elf-gcc
LD=arm-elf-gcc
TARGT=lednxy
OBJ=$(TARGT).o
SRC=$(TARGT).c
all:
$(TARGT)
%.o:
%.c
$(CC)$(CFLAGS)–c$<
-o$@
$(TARGT):
$(OBJ)
$(CC)$(CFLAGS)$(LDFLAGS)–o$@$(OBJ)
整个编译过程如下:
[nie@uClinuxusr]$make
arm-elf-gcc–Wall–Os–Dlinux–D__linux__-Dunix–D__uClinux__-DEMBED-clednxy.c–olednxy.o
arm-elf-gcc–Wall–Os–Dlinux–D__linux__-Dunix–D__uClinux__-DEMBED-Wl,-elf2flt–olednxylednxy.o
可以用工具arm-elf-flthdr查看生成的lednxy的格式,它是一个能够操作和显示flat格式文件的头信息的可执行程序。
在生成lednxy的当前路径下键入命令:
arm-elf-flthdrlednxy
后,可以看到以下对该文件头描述的信息,
lednxy
Magic:
bFLT
Rev:
4
BuildDate:
ThuJun1910:
31:
142003
Entry:
0x50
DataStart:
0x1c80
DataEnd:
0x2010
BSSEnd:
0x22a0
StackSize:
0x1000
RelocStart:
RelocCount:
0x4f
Flags:
0x1(Load-to-Ram)
从显示的信息,可以看出文件lednxy的确是一个flat格式的文件,是可以在uClinux环境下运行的。
7.4.1串行通信
所谓串行通信就是在传输数据的时候每次只传输一位,其传输的速率通常用“位/秒”来表示,即通常所说的“波特率”。
Linux对所有各类设备文件的输入输出操作,看上去就像对普通文件的输入输出一样,所以Linux对串口的操作,也是通过设备文件访问的。
为了访问串口,只需要打开相应的设备文件即可。
设备文件/dev/ttyS*是用于挂起Linux终端的文件。
默认地,在Linux下,串行口COM1和COM2对应的设备分别为/dev/ttyS0和/dev/ttyS1。
在程序中,很容易配置串口的属性,这些属性定义在结构体structtermios中。
为在程序中使用该结构体,需要包含文件<
termbits.h>
,该头文件定义了结构体structtermios。
#defineNCCS19
structtermios{
tcflag_tc_iflag;
/*inputmodeflags*/
tcflag_tc_oflag;
/*outputmodeflags*/
tcflag_tc_cflag;
/*controlmodeflags*/
tcflag_tc_lflag;
/*localmodeflags*/
cc_tc_line;
/*linediscipline*/
cc_tc_cc[NCCS];
/*controlcharacters*/
};
下面对结构体中的各个成员做一个简单介绍。
在c_iflag中的输入模式标志符控制所有的输入处理过程,就是说,从设备发送的字符在被read函数读取之前要经过处理。
类似的,成员c_oflag控制输出处理过程,c_cflag包含对端口的设置,如,波特率,字符位数,停止位等。
存储在成员c_lflag的本地模式标志符决定是否显示字符,是否发送信号到应用程序等。
数组c_cc包含了控制字符的定义和超时参数。
成员c_line在POSIX(PortableOperatingSystemInterfaceforUNIX)系统中不使用。
下面结合一个简单的实例,说明如何对串口进行读写操作。
serialcomm.c
communicationwithserial
sys/types.h>
sys/stat.h>
fcntl.h>
termios.h>
stdio.h>
#defineBAUDRATEB19200
#defineSERIALDEVICE"
/dev/ttyS0"
intmain()
intfd,ncount;
structtermiosoldtio,newtio;
charbuf[]="
Thisisasimpleapplicationforserialcommunication\r\n"
;
fd=open(SERIALDEVICE,O_RDWR|O_NOCTTY);
if(fd<
0)
perror(SERIALDEVICE);
exit(-1);
tcgetattr(fd,&
oldtio);
bzero(&
newtio,sizeof(newtio));
newtio.c_cflag=BAUDRATE|CS8|CLOCAL|CREAD;
newtio.c_iflag=IGNPAR|ICRNL;
newtio.c_oflag=0;
newtio.c_lflag=ICANON;
tcflush(fd,TCIFLUSH);
fcntl(fd,F_SETFL,0);
tcsetattr(fd,TCSANOW,&
newtio);
ncount=write(fd,buf,sizeof(buf));
printf("
thebyteswrittentoserialis%d\n"
ncount);
printf("
charactertosendis:
%s\n"
buf);
perror("
write"
);
tcsetattr(fd,TCSANOW,&
close(fd);
return0;
程序首先为波特率常数定义了宏值,为设备文件定义了设备名常数。
有关波特率常数的定义可参见<
(该头文件包含在termios.h中)。
对于普通用户而言,是不允许访问设备文件的,如果要访问,要么以root账号登录,要么需要改变文件的访问属性。
假定设备文件是可以访问的,用open函数打开设备文件,返回一个文件描述符(filedescriptors,fd),通过文件描述符来访问文件。
O_RDWR标志表示对该文件可读可写,O_NOCTTY表示该程序不会成为控制终端,这样就避免了当在键盘输入类似ctrl+c的命令后,终止程序的运行。
然后用tcgetattr保存串口的当前设置,给端口设置新的属性,通过对c_cflag的赋值,设置波特率,字符大小(CS8表示8位数据位,1位停止位,没有奇偶校验位),使能本地连接,使能串行口驱动读取输入数据。
通过设置c_iflag,控制端口对字符的输入处理过程,IGNPAR符号常量表示忽略奇偶性错误的字节,并不对输入数据进行任何校验,ICRNL将回车符映射为换行符。
设置原始数据输出,使能规范输入。
在对structtermios结构体的各个成员赋值完毕
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第7章 嵌入式uClinux及其应用开发2 嵌入式 uClinux 及其 应用 开发