gaston feng |
May 11, 2008 2:33:19 PM
|
.PHONY: images |
上述语句将在make image的时候生成压缩的映像文件(image)。
首先,找到语句
genromfs -v -V "ROMdisk" -f $(ROMFSIMG) -d $(ROMFSDIR) |
在其下方加入:
arm-elf-ld -r -o $(ROOTDIR)/$(LINUXDIR)/romfs.o \ |
此语句的作用是产生 romfs.o 供后续生成整体的映像文件使用。
同时,在此 Makefile 的最后加入:
images: |
上述语句将在交叉编译的最后将所有生成的目标文件 Dump 到可以下载到开发板中的映像文件中(注意,这里提供两种形式:ROM 启动的 uclinux_rom.bin 和 RAM 启动的 uclinux_ram.bin)
将此文件中的下列语句:
$(LD) $(ZLDFLAGS) $(HEAD) $(OBJS) piggy.o -o $(LINUX) |
修改为:
$(LD) $(ZLDFLAGS) $(HEAD) $(OBJS) piggy.o $(LIBGCC) -o $(LINUX) |
此语句将 arm-elf-tools 库的 libgcc 链接入 uClinux 的 kernel 中。
Step 3:配置操作系统地址转换
由于 S3C4510B 不含 MMU (Memory Management Unit), 因此其物理地址和虚拟地址是相同的。在../linux-2.4.x/include/asm/mmu.h 中需要加入下列代码以完成此转换:
#define __virt_to_phys__is_a_macro |
Step 4:配置romfs
由于uClinux缺省使用romfs作为根文件系统,因此需要对此进行配置:
在*(.got) /* Global offset table */语句后加入下列语句,从而将上文Step 2 (2) 中生成的romfs.o包含到.text段中:
romfs_data = .; |
此文件是romfs的配置文件,找到“arena[] = {”语句,在其花括号中加入下列3行:
#ifdef CONFIG_ARCH_SAMSUNG |
Step 5:其他修改
此文件中有一个错误语句:
mov r0, #0 |
将其修改为:
#ifdef CONFIG_CPU_WITH_CACHE |
至此,经过修改的uClinux内核已经可以在开发主机上使用make dep, make lib_only, make user_only, make romfs, make image和make 生成 uclinux_rom.bin 和uclinux_ram.bin 映像文件 并在开发板上顺利运行至uClinux欢迎界面和等待命令输入提示符。需要注意的是, uclinux_ram.bin是压缩过的内核映像,可以使用调试器直接烧写至SDRAM中运行,而 uclinux_rom.bin是没有压缩过的内核映像,需要烧写入FLASH中运行。因此,在调试过程中,一般将待调试的内核映像uclinux_ram.bin通过调试器或Bootlaoder(Redboot等)写入SDRAM中进行调试,待完全调试好之后再将最终uclinux_rom.bin版本烧写入FLASH中固化。
Step 1:下载内核压缩包和交叉编译工具包
对于2.6内核的uClinux,需要下载uClinux-dist-20051014.tar.gz内核压缩包以及Linux 2.6版本内核及补丁:linux-2.6.9.tar.bz2、linux-2.6.9-hsc0.patch.gz;同时还需要下载交叉编译工具并进行安装:arm-uclinux-tools-base-gcc3.4.0-20040713.sh。
Step 2:为uClinux更新标准Linux 2.6版本内核
执行下列命令将uClinux-dist-20051014的内核替换为标准Linux的2.6内核:
tar -zxvf uClinux-dist-20051014.tar.gz |
Step 3:配置内核中S3C4510B的参数设置
由于Step 2 中的补丁并没有包括专门针对S3C4510B的内核配置,因此我们只能使用现有的 espd-4510的内核配置文件:
$cp ../linux-2.6.x/arch/armnommu/configs/espd_4510b_defconfig \ |
同时,由于没有特别针对Linux 2.6内核的S3C4510B vendor配置文件因此只能使用现有2.4版本 的vendor配置文件:
$cp ../linux-2.6.x/vendor/Samsung/4510B/config.vendor-2.4.x \ |
Step 4:修改Makefile文件
由于现有的Makefile当中并没有包含编译可烧写至嵌入式存储系统中的映像文件的相应命令,因此需要在此Makefile中添加:
image: |
Step 5:配置romfs
与移植uClinux 2.4内核相同,需要修改下列文件以对romfs进行支持:
在*(.got) /* Global offset table */语句后加入下列语句,从而romfs.o包含到.text段中。
romfs_data = .; |
添加变量romfs_start和romfs_end:
extern int _stext, _text, _etext, _edata, _end; |
同时,对内核启动时的default command line进行设置:
char *from = default_command_line; |
至此,uClinux 2.6版本的内核移植完成,可以通过make dep, make lib_only, make user_only, make romfs, make image和make编译出可以烧写入SDRAM或FLASH的内核映像文件。
|
在嵌入式开发和调试中,最常用的网络服务是使用Telnet登录嵌入式开发板以及使用NFS文件系统。本文下面将根据笔者的实际经验对uClinux 2.4环境下这些网络服务的配置进行说明。
由于Telnet使用串口建立终端进行通信,因此为了在嵌入式开发板上架设Telnet服务器,首先需要修改uClinux的内核配置。具体来说,需要在make menuconfig时进行下列配置:
由于在上面的内核配置中选择了对虚拟终端的支持,因此需要手动在../linux-2.4-x/.config中加入CONFIG_DUMMY_KEYB=y,否则编译时会出现编译错误。
同时,由于uClinux内核自身的问题,按照上述方式配置的Telnet在连接时总是出现login用户名和密码验证错误的问题。此问题可以通过修改../linux-2.4-x/user/tinylogin/login.c,省略Telnet连接时的用户名/密码验证来解决:
extern int login_main(int argc, char **argv) |
重新编译按照上述方法进行修改的内核并将编译好的映像文件烧写入FLASH,系统上电启动后完成后运行:
/bin> inetd & |
开发人员便可以通过Telnet访问嵌入式开发板了。
为了在S3C4510B嵌入式开发板上使用NFS文件系统,需要按照如下的方法修改uClinux内核:运行内核配置程序make menuconfig,选中Customized Kernel Settings和Customized Vendor/User Settings,然后在接下来的配置中按照如下方式进行设置:
选中NFS file system support和Provide NFSv3 client support。
选中portmap,提供端口映射功能。
选中mount和mount: support NFS mounts。
完成上述配置之后,重新编译内核,新内核便可提供NFS Server和Client的支持。在通常情况下, 一般会使用S3C4510B嵌入式开发板作为NFS Client,而开发主机作为NFS Server。例如,开发主机(192.168.0.8)通过配置/etc/exports文件已将/nfs_mount目录设置为NFS目录,则在 S3C4510B嵌入式开发板即可通过下列命令将开发主机的NFS目录挂载至本地/var目录:
/bin > portmap & |
|
uClinux目前并不支持使用insmod动态加载驱动程序,因此S3C4510B嵌入式平台上的驱动程序都需要编译进入内核在启动时自动加载。下面分别对S3C4510B嵌入式平台上的字符驱动程序和网络驱动程序的开发进行一些论述。
开发人员在编写完所需的字符类型驱动程序之后,需要将驱动程序源代码置于
../linux-2.4.x/driver/char目录下,同时修改同级目录下的Makefile。例如,笔者完成了一个S3C4510B的LCD驱动程序(lcd.c),则需要将lcd.c置于../linux-2.4.x/driver/char目录,同时在../linux-2.4.x/driver/char/Makefile中加入:
obj_y += lcd.o |
同时,为了能够在uClinux启动时自动初始化此设备,还需要修改../linux-2.4.x/driver/char/mem.c文件,在其中加入:
extern void lcd_init(void); |
int __init chr_dev_init(void)中调用新设备的初始化函数。例如上面提到的LCD的例子,需要在函数int __init chr_dev_init(void)中加入语句:
lcd_init(); |
函数int __init chr_dev_init(void)中,字符设备的初始化函数将统一被调用,并完成各个字符驱动file_operations数据结构的注册。初始化好之后就可以使用这些字符设备了。
在uClinux中加入网络驱动设备比较简单,只需将编写好的网络驱动程序置于../linux-2.4.x/driver/net,再修改../linux-2.4.x/driver/net/Makefile即可。例如,笔者编写了HDLC的驱动程序
s3c4510b_hdlc.c,只需将其置于../linux-2.4.x/driver/net目录下,然后修改../linux-2.4.x/driver/net/Makefile,在其中加入:
obj-y += s3c4510b_hdlc.o |
uClinux执行make时会根据此Makefile产生新的驱动模块,并将其链接入net.o,系统启动时将会统一加载所有的网络驱动程序。
由于嵌入式应用中往往会对网络应用有特别的需求,因而需要在嵌入式开发板中支持一些不太常用的网络设备(如HDLC设备等)。对此感兴趣的读者可以参考笔者的另外一篇论文《基于 S3C4510B 和 uClinux 的 HDLC 接口的设计与实现》。
|
除了驱动程序,开发人员还需要在S3C4510B嵌入式平台上进行用户空间应用程序的开发,具体步骤如下:
Step 1:在../linux-2.4.x/user目录中为应用程序建立相应目录树结构
例如,笔者在开发中需要开发一个在S3C4510B自带的LCD上显示消息的用户程序(write_lcd.c),则首先需要在../linux-2.4.x/user下新建一个目录(如lcd),然后将应用程序置于此目录下
(../linux-2.4.x/user/lcd/write_lcd.c)。
Step 2:修改2级Makefile文件
由于在../linux-2.4.x/user目录下加入了新的目录树结构,因此需要修改../linux-2.4.x/user/Makefile文件,使运行make时能够进入新目录进行编译。在上面的例子中,需要在
../linux-2.4.x/user/Makefile中加入:
dir_y += lcd |
以指示系统在编译时进入lcd目录。
新建目录中必须提供一个Makefile供make时使用,下面是笔者在实际开发中使用的此处Makefile模板,不同的应用程序只需更改模板中的EXEC和OBJS宏即可:
EXEC = write_lcd |
完成上述步骤之后,运行make user_only编译命令时,将会对../linux-2.4.x/user/目录下的用户程序进行编译,并将编译出的可执行文件置于romfs中的bin目录下。
|
本文根据笔者在实际工作中的经验,对uClinux在S3C4510B嵌入式平台上的移植和开发等主题进行了总结。本文给出了移植uClinux 2.4和2.6版本至S3C4510B平台、配置常用网络服务、各种驱动程序以及用户程序开发的详细步骤,相信能够帮助进行类似工作的开发人员加快开发速度;同时,也能够对开发其他类型的嵌入式系统提供有益的借鉴。
|
刘朋,男,云南昆明人,北京大学“通信与信息系统”硕士。现供职于IBM中国开发中心,主要研究兴趣为无线网络通信协议、Linux 嵌入式系统以及HPC(High Performance Computing)。 |
||
建议? |
||||||
|
Comment:
(no reply)