ARM的嵌入式Linux移植体验之操作系统.docx
- 文档编号:28395646
- 上传时间:2023-07-13
- 格式:DOCX
- 页数:13
- 大小:50.99KB
ARM的嵌入式Linux移植体验之操作系统.docx
《ARM的嵌入式Linux移植体验之操作系统.docx》由会员分享,可在线阅读,更多相关《ARM的嵌入式Linux移植体验之操作系统.docx(13页珍藏版)》请在冰豆网上搜索。
ARM的嵌入式Linux移植体验之操作系统
ARM的嵌入式Linux移植体验之操作系统
2007-04-2522:
50
2006-08-1308:
00作者:
宋宝华出处:
天极开发
在笔者撰写的《C语言嵌入式系统编程修炼之道》一文中,主要陈诉的软件架构是单任务无操作系统平台的,而本文的侧重点则在于讲述操作系统嵌入的软件架构,二者的区别如下图:
嵌入式操作系统并不总是必须的,因为程序完全可以在裸板上运行。
尽管如此,但对于复杂的系统,为使其具有任务管理、定时器管理、存储器管理、资源管理、事件管理、系统管理、消息管理、队列管理和中断处理的能力,提供多任务处理,更好的分配系统资源的功能,很有必要针对特定的硬件平台和实际应用移植操作系统。
鉴于Linux的源代码开放性,它成为嵌入式操作系统领域的很好选择。
国内外许多知名大学、公司、研究机构都加入了嵌入式Linux的研究行列,推出了一些著名的版本:
·RT-Linux提供了一个精巧的实时内核,把标准的Linux核心作为实时核心的一个进程同用户的实时进程一起调度。
RT-Linux已成功地应用于航天飞机的空间数据采集、科学仪器测控和电影特技图像处理等广泛的应用领域。
如NASA(美国国家宇航局)将装有RT-Linux的设备放在飞机上,以测量Georage咫风的风速;
·uCLinux(Micro-Control-Linux,u表示Micro,C表示Control)去掉了MMU(内存管理)功能,应用于没有虚拟内存管理的微处理器/微控制器,它已经被成功地移植到了很多平台上。
本章涉及的mizi-linux由韩国mizi公司根据Linux2.4内核移植而来,支持S3C2410A处理器。
1.Linux内核要点
和其他操作系统一样,Linux包含进程调度与进程间通信(IPC)、内存管理(MMU)、虚拟文件系统(VFS)、网络接口等,下图给出了Linux的组成及其关系:
Linux内核源代码包括多个目录:
(1)arch:
包括硬件特定的内核代码,如arm、mips、i386等;
(2)drivers:
包含硬件驱动代码,如char、cdrom、scsi、mtd等;
(3)include:
通用头文件及针对不同平台特定的头文件,如asm-i386、asm-arm等;
(4)init:
内核初始化代码;
(5)ipc:
进程间通信代码;
(6)kernel:
内核核心代码;
(7)mm:
内存管理代码;
(8)net:
与网络协议栈相关的代码,如ipv4、ipv6、ethernet等;
(9)fs:
文件系统相关代码,如nfs、vfat等;
(10)lib:
库文件,与平台无关的strlen、strcpy等,如在string.c中包含:
char*strcpy(char*dest,constchar*src)
{
char*tmp=dest;
while((*dest++=*src++)!
='\0')
/*nothing*/;
returntmp;
}
(11)Documentation:
文档
在Linux内核的实现中,有一些数据结构使用非常频繁,对研读内核的人来说至为关键,它们是:
1.task_struct
Linux内核利用task_struct数据结构代表一个进程,用task_struct指针形成一个task数组。
当建立新进程的时候,Linux为新的进程分配一个task_struct结构,然后将指针保存在task数组中。
调度程序维护current指针,它指向当前正在运行的进程。
2.mm_struct
每个进程的虚拟内存由mm_struct结构代表。
该结构中包含了一组指向vm-area_struct结构的指针,vm-area_struct结构描述了虚拟内存的一个区域。
3.inode
Linux虚拟文件系统中的文件、目录等均由对应的索引节点(inode)代表。
2.Linux移植项目
mizi-linux已经根据Linux2.4内核针对S3C2410A这一芯片进行了有针对性的移植工作,包括:
(1)修改根目录下的Makefile文件
a.指定目标平台为ARM:
#ARCH:
=$(shelluname-m|sed-es/i.86/i386/-es/sun4u/sparc64/-es/arm.*/arm/-es/sa110/arm/)
ARCH:
=arm
b.指定交叉编译器:
CROSS_COMPILE=arm-linux-
(2)修改arch目录中的文件
根据本章第一节可知,Linux的arch目录存放硬件相关的内核代码,因此,在Linux内核中增加对S3C2410的支持,最主要就是要修改arch目录中的文件。
a.在arch/arm/Makefile文件中加入:
ifeq($(CONFIG_ARCH_S3C2410),y)
TEXTADDR=0xC0008000
MACHINE=s3c2410
Endif
b.在arch\arm\config.in文件中加入:
if["$CONFIG_ARCH_S3C2410"="y"];then
comment'S3C2410Implementation'
dep_bool'SMDK(MERITECHBOARD)'CONFIG_S3C2410_SMDK$CONFIG_ARCH_S3C2410
dep_bool'changeAIJI'CONFIG_SMDK_AIJI
dep_tristate'S3C2410USBfunctionsupport'CONFIG_S3C2410_USB$CONFIG_ARCH_S3C2100
dep_tristate'SupportforS3C2410USBcharacterdeviceemulation'CONFIG_S3C2410_USB_CHAR$CONFIG_S3C2410_USB
fi#/*CONFIG_ARCH_S3C2410*/
arch\arm\config.in文件还有几处针对S3C2410的修改。
c.在arch/arm/boot/Makefile文件中加入:
ifeq($(CONFIG_ARCH_S3C2410),y)
ZTEXTADDR=0x30008000
ZRELADDR=0x30008000
endif
d.在linux/arch/arm/boot/compressed/Makefile文件中加入:
ifeq($(CONFIG_ARCH_S3C2410),y)
OBJS+=head-s3c2410.o
endif
加入的结果是head-s3c2410.S文件被编译为head-s3c2410.o。
e.加入arch\arm\boot\compressed\head-s3c2410.S文件
#include
#include
#include
.section".start",#alloc,#execinstr
__S3C2410_start:
@Preserver8/r7i.e.kernelentryvalues
@Whatisit?
@Nandy
@Datacache,Intstructioncache,MMUmightbeactive.
@Besuretoflushkernelbinaryoutofthecache,
@whateverstateitis,beforeitisturnedoff.
@Thisisdonebyfetchingthroughcurrentlyexecuted
@memorytobesurewehitthesamecache
bicr2,pc,#0x1f
addr3,r2,#0x4000@16kbisquiteenough...
1:
ldrr0,[r2],#32
teqr2,r3
bne1b
mcrp15,0,r0,c7,c10,4@drainWB
mcrp15,0,r0,c7,c7,0@flushI&Dcaches
#if0
@disablingMMUandcaches
mrcp15,0,r0,c1,c0,0@readcontrolregister
bicr0,r0,#0x05@disableDcacheandMMU
bicr0,r0,#1000@disableIcache
mcrp15,0,r0,c1,c0,0
#endif
/*
*Pauseforashorttimesothatwegiveenoughtime
*forthehosttostartaterminalup.
*/
movr0,#0x00200000
1:
subsr0,r0,#1
bne1b
该文件中的汇编代码完成S3C2410特定硬件相关的初始化。
f.在arch\arm\def-configs目录中增加配置文件
g.在arch\arm\kernel\Makefile中增加对S3C2410的支持
no-irq-arch:
=$(CONFIG_ARCH_INTEGRATOR)$(CONFIG_ARCH_CLPS711X)\
$(CONFIG_FOOTBRIDGE)$(CONFIG_ARCH_EBSA110)\
$(CONFIG_ARCH_SA1100)$(CONFIG_ARCH_CAMELOT)\
$(CONFIG_ARCH_S3C2400)$(CONFIG_ARCH_S3C2410)\
$(CONFIG_ARCH_MX1ADS)$(CONFIG_ARCH_PXA)
obj-$(CONFIG_MIZI)+=event.o
obj-$(CONFIG_APM)+=apm2.o
h.修改arch/arm/kernel/debug-armv.S文件,在适当的位置增加如下关于S3C2410的代码:
#elifdefined(CONFIG_ARCH_S3C2410)
.macroaddruart,rx
mrcp15,0,\rx,c1,c0
tst\rx,#1@MMUenabled?
moveq\rx,#0x50000000@physicalbaseaddress
movne\rx,#0xf0000000@virtualaddress
.endm
.macrosenduart,rd,rx
str\rd,[\rx,#0x20]@UTXH
.endm
.macrowaituart,rd,rx
.endm
.macrobusyuart,rd,rx
1001:
ldr\rd,[\rx,#0x10]@readUTRSTAT
tst\rd,#1<<2@TX_EMPTY?
beq1001b
.endm
i.修改arch/arm/kernel/setup.c文件
此文件中的setup_arch非常关键,用来完成与体系结构相关的初始化:
void__initsetup_arch(char**cmdline_p)
{
structtag*tags=NULL;
structmachine_desc*mdesc;
char*from=default_command_line;
ROOT_DEV=MKDEV(0,255);
setup_processor();
mdesc=setup_machine(machine_arch_type);
machine_name=mdesc->name;
if(mdesc->soft_reboot)
reboot_setup("s");
if(mdesc->param_offset)
tags=phys_to_virt(mdesc->param_offset);
/*
*Dothemachine-specificfixupsbeforeweparsethe
*parametersortags.
*/
if(mdesc->fixup)
mdesc->fixup(mdesc,(structparam_struct*)tags,
&from,&meminfo);
/*
*Ifwehavetheoldstyleparameters,convertthemto
*ataglistbefore.
*/
if(tags&&tags->hdr.tag!
=ATAG_CORE)
convert_to_tag_list((structparam_struct*)tags,
meminfo.nr_banks==0);
if(tags&&tags->hdr.tag==ATAG_CORE)
parse_tags(tags);
if(meminfo.nr_banks==0){
meminfo.nr_banks=1;
meminfo.bank[0].start=PHYS_OFFSET;
meminfo.bank[0].size=MEM_SIZE;
}
init_mm.start_code=(unsignedlong)&_text;
init_mm.end_code=(unsignedlong)&_etext;
init_mm.end_data=(unsignedlong)&_edata;
init_mm.brk=(unsignedlong)&_end;
memcpy(saved_command_line,from,COMMAND_LINE_SIZE);
saved_command_line[COMMAND_LINE_SIZE-1]='\0';
parse_cmdline(&meminfo,cmdline_p,from);
bootmem_init(&meminfo);
paging_init(&meminfo,mdesc);
request_standard_resources(&meminfo,mdesc);
/*
*Setupvariousarchitecture-specificpointers
*/
init_arch_irq=mdesc->init_irq;
#ifdefCONFIG_VT
#ifdefined(CONFIG_VGA_CONSOLE)
conswitchp=&vga_con;
#elifdefined(CONFIG_DUMMY_CONSOLE)
conswitchp=&dummy_con;
#endif
#endif
}
j.修改arch/arm/mm/mm-armv.c文件(arch/arm/mm/目录中的文件完成与ARM相关的MMU处理)
修改
init_maps->bufferable=0;
为
init_maps->bufferable=1;
要轻而易举地进行上述马拉松式的内核移植工作并非一件轻松的事情,需要对Linux内核有很好的掌握,同时掌握硬件特定的知识和相关的汇编。
幸而mizi公司的开发者们已经合力为我们完成了上述工作,这使得小弟们在将mizi-linux移植到自身开发的电路板的过程中只需要关心如下几点:
(1)内核初始化:
Linux内核的入口点是start_kernel()函数。
它初始化内核的其他部分,包括捕获,IRQ通道,调度,设备驱动,标定延迟循环,最重要的是能够fork"init"进程,以启动整个多任务环境。
我们可以在init中加上一些特定的内容。
(2)设备驱动:
设备驱动占据了Linux内核很大部分。
同其他操作系统一样,设备驱动为它们所控制的硬件设备和操作系统提供接口。
本文第四章将单独讲解驱动程序的编写方法。
(3)文件系统:
Linux最重要的特性之一就是对多种文件系统的支持。
这种特性使得Linux很容易地同其他操作系统共存。
文件系统的概念使得用户能够查看存储设备上的文件和路径而无须考虑实际物理设备的文件系统类型。
Linux透明的支持许多不同的文件系统,将各种安装的文件和文件系统以一个完整的虚拟文件系统的形式呈现给用户。
我们可以在K9S1208NANDFLASH上移植cramfs、jfss2、yaffs等FLASH文件系统。
3.init进程
在init函数中"加料",可以使得Linux启动的时候做点什么,例如广州友善之臂公司的demo板在其中加入了公司信息:
staticintinit(void*unused)
{
lock_kernel();
do_basic_setup();
prepare_namespace();
/*
*Ok,wehavecompletedtheinitialbootup,and
*we'reessentiallyupandrunning.Getridofthe
*initmemsegmentsandstarttheuser-modestuff..
*/
free_initmem();
unlock_kernel();
if(open("/dev/console",O_RDWR,0)<0)
printk("Warning:
unabletoopenaninitialconsole.\n");
(void)dup(0);
(void)dup(0);
/*
*Wetryeachoftheseuntilonesucceeds.
*
*TheBourneshellcanbeusedinsteadofinitifweare
*tryingtorecoverareallybrokenmachine.
*/
printk("========================================\n");
printk("=Friendly-ARMTech.Ltd.=\n");
printk("==\n");
printk("==\n");
printk("========================================\n");
if(execute_command)
execve(execute_command,argv_init,envp_init);
execve("/sbin/init",argv_init,envp_init);
execve("/etc/init",argv_init,envp_init);
execve("/bin/init",argv_init,envp_init);
execve("/bin/sh",argv_init,envp_init);
panic("Noinitfound.Trypassinginit=optiontokernel.");
}
这样在Linux的启动过程中,会额外地输出:
========================================
=Friendly-ARMTech.Ltd.=
==
==
========================================
4.文件系统移植
文件系统是基于被划分的存储设备上的逻辑上单位上的一种定义文件的命名、存储、组织及取出的方法。
如果一个Linux没有根文件系统,它是不能被正确的启动的。
因此,我们需要为Linux创建根文件系统,我们将其创建在K9S1208NANDFLASH上。
Linux的根文件系统可能包括如下目录(或更多的目录):
(1)/bin(binary):
包含着所有的标准命令和应用程序;
(2)/dev(device):
包含外设的文件接口,在Linux下,文件和设备采用同种地方法访问的,系统上的每个设备都在/dev里有一个对应的设备文件;
(3)/etc(etcetera):
这个目录包含着系统设置文件和其他的系统文件,例如/etc/fstab(filesystemtable)记录了启动时要mount的filesystem;
(4)/home:
存放用户主目录;
(5)/lib(library):
存放系统最基本的库文件;
(6)/mnt:
用户临时挂载文件系统的地方;
(7)/proc:
linux提供的一个虚拟系统,系统启动时在内存中产生,用户可以直接通过访问这些文件来获得系统信息;
(8)/root:
超级用户主目录;
(9)/sbin:
这个目录存放着系统管理程序,如fsck、mount等;
(10)/tmp(temporary):
存放不同的程序执行时产生的临时文件;
(11)/usr(user):
存放用户应用程序和文件。
采用BusyBox是缩小根文件系统的好办法,因为其中提供了系统的许多基本指令但是其体积很小。
众所周知,瑞士军刀以其小巧轻便、功能众多而闻名世界,成为各国军人的必备工具,并广泛应用于民间,而BusyBox也被称为嵌入式Linux领域的"瑞士军刀"。
此地址可以下载BusyBox:
,当前最新版本为1.1.3。
编译好busybox后,将其放入/bin目录,若要使用其中的命令,只需要建立link,如:
ln-s./busyboxls
ln-s./busyboxmkdir
4.1cramfs
在根文件系统中,为保护系统的基本设置不被更改,可以采用cramfs格式,它是一种只读的闪存文件系统。
制作cramfs文件系统的方法为:
建立一个
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ARM 嵌入式 Linux 移植 体验 操作系统