在xilinx zc702开发板上移植完linux和android后,闲来折腾已经发霉的samsung2440,arm移植网上的帖子满天飞,随便搜一个来参考就可跑的很流畅。这里也是参考网上的资料,只mark一下我移植的过程和遇到的一些问题,以便后边查看。
开发板:蓝海微星LJD-E2440,64MB flash上有个坏块。
Linux kernel:Linux2.6.29.6
gcc : arm-linux-gcc 3.4.1
busybox: busybox-1.00-pre10
bootloader: 官方提供,带有uart和usb下载功能
os:i686,Ubuntu12.10,linux3.10.1,gcc 4.7.2
仿真器:mutliICE2.3
移植过程可以分为以下几个部分:
1. 移植环境配置
2. Bootloader修改和烧写
3. Linux kernel 移植
4. cramfs文件系统移植
1.移植环境配置
在安装好Ubuntu后,设置网络和共享文件夹,也可以安装VMware tools,方便和win7拖拉文件。
Sharefolder: /home/yoyo/vmshare
Workspace:/work/arm
安装linux2.6.29.6,arm-linux-gcc 3.4.1
$ cd /work/arm
$ cp –rf /home/yoyo/vmshare/linux-2.6.29.6.tar.gz . /
$ tar –xzf linux-2.6.29.6.tar.gz
$ cp –rf /home/yoyo/vmshare/arm-linux-gcc-3.4.1.tar.bz2 . /
$ bzip2 -d–xzf arm-linux-gcc-3.4.1.tar.bz2
$ tar -xvf arm-linux-gcc-3.4.1.tar
设置环境变量
$ gedit /etc/environment
添加gcc路径/work/arm/arm-linux-gcc/3.4.1/bin,用$ arm-linux-gcc –v 检查是否设置对。Thread model: posix ; gcc version 3.4.1
2. Bootloader修改和烧写
这部分折腾挺长时间,开始不知道坏块的位置,试了几次,后来发现启动linux时,会自动检查坏块,并且报告位置Bad eraseblock 733 at 0x00b74000。用bootloader烧写到坏块处会暂停一下。
原bootloader的nandflash分区如下;
{0, 0x00030000, "boot"}, //192K for bootloader
{0x00030000, 0x001d0000, "kernel"}, //1856k for linux kernel zImage
{0x00200000, 0x01e00000, "rootfs"}, //30M for file system
{0x02000000, 0x0157c000, "NK.bin"}, //22M for wince
{0x0357c000, 0x009c4000, "nandflash"}, //10M for external nandflash
修改后绕开坏块:
{0, 0x00030000, "boot"}, //192K
{0x00030000, 0x001d0000, "kernel"}, //1856k
{0x00c00000, 0x01e00000, "rootfs"}, //30M
{0x02a00000, 0x0157c000, "NK.bin"}, //22M
{0x03f7c000, 0x00084000, "nandflash"}, //2M
rootfs分区有坏块时,启动总是提示文件系统解压失败。板子上的flash已经烧有bootloader程序,能在DNW下擦除和下载程序。
开发板自带的烧写程序是基于并口的SJF2440.exe,本没有并口,这里用自带的bootloader和mutliICE烧写boot分区。
用MutliIce烧写bootloader
先在DNW下用自带的bootloader擦除nandflash第0分区bootloader,再用AXD全速debug跑bootloader程序,小等一段时间,插上usb,选择菜单1,将bootloader.bin下载到sdram的0x32000000,选择菜单4,烧写到nandflash的第0分区,写完断电,从开发板端拔掉MutliIce,重新上电,bootloader烧写成功。
这里需注意,断电后拔掉mutliICE,要从开发板端拔掉,mutliICE用jtag下载,jtag的优先级最高。
3. Linux kernel 移植
Linux kernel 下也需要修改nandflash分区表,对于S3C24XX CPU,NANDFLASH这样的平台设备设置在arch/arm/plat-s3c24xx/common-smdk.c里,打开common-smdk.c修改相应分区为:
static struct mtd_partition smdk_default_nand_part[] = {
[0] = {
.name = "boot",
.offset = 0x00000000,
.size = 0x00030000,
},
[1] = {
.name = "kernel",
.offset = 0x00030000,
.size = 0x001d0000,
},
[2] = {
.name = "rootfs",
.offset = 0x00c00000,
.size = 0x01e00000,
}
};
配置linux kernel
S3c2440的配置完全继承s3c2410,可以用$ make s3c2410_defconfig来配置。或者
$ cp arch/arm/configs/s3c2410_defconfig ./.config ,重新配置可以用
$ make menuconfig
修改boot options
(root=/dev/mtdblock2 ro noinitrd init=/linuxrc console=ttySAC0,115200 rootfstype=cramfs mem=64m
其他可保持默认配置。
这里遇到的一些问题:
a ,问题:
FAT: unable to read boot sector
VFS: Cannot open root device "mtdblock2" or unknown-block(31,2)
Please append a correct "root=" boot option; here are the available
内核代码ECC校验和nandflash里都用hw_ecc
修改nand Flash的校验方式, ECC_HW校验。
在drivers/mtd/nand/s3c2410.c 第669行
将chip->ecc.mode = NAND_ECC_SOFT;
改为 chip->ecc.mode = NAND_ECC_HW;
在内核配置中添加:
Device Drivers --->
<*> Memory Technology Device (MTD) support ---->
<*>NAND DECIVE SUPPORT --->
在2440中要添加NAND_ECC_HW硬件支持才行。
b , /linuxrc
linux启动后自动加载设置,在/linuxrc里添加
/bin/insmod /usr/usbfor2440.ko
/bin/mknod .....
/bin/mount ....
/etc/profile 设置export一些路径,设置usrname
/etc/inittab 设置系统启动首先执行的一些命令,设置shell环境,重启关机命令
/etc/init.d/rcSd定义hostname,在/etc/inittab 中调用首先执行/.bashrc
c , 问题:
clk: version magic '2.6.12-h1940 ARMv4 gcc-3.4' should be '2.6.29.6 mod_unlo
添加了usrname和hostname就没了。
d , 问题
Failed to execute /linuxrc. Attempting defaults...
Kernel panic - not syncing: No init found. Try passing init= option to kernel.
busybox的动态链接库没拷到/lib下
e , 问题
FATAL: kernel too old
Kernel panic - not syncing: Attempted to kill init!
交叉编译版本高,其动态库有最低版本限制。
4. cramfs文件系统移植
安装busybox:
$ cd /work/arm
$ cp –rf /home/yoyo/vmshare/busybox-1.00-pre10.tar.bz2 . /
$ bzip2 -d–xzf busybox-1.00-pre10.tar.bz2
$ tar -xvf busybox-1.00-pre10.tar
$ make menuconfig
a ,执行make menuconfig,然后进行设置,这里借助网上的一片博文:
http://blog.chinaunix.net/uid-20734916-id-1882739.html ,这几张图就是在进行配置时需要重点注意的地方:
(1)在General Configuration中,一定要选择“Support for devfs”选项,现在的Busybox新版本去掉了这个选项,不过应该可以通过修改配置文件加入。
(2)在Build Options选项中,选择使用“静态库”以及设置交叉编译工具的PREFIX。
(3)在Linux System Utilities选项中,“Support loopback mounts”和“Support for the old /etc/mtab file”2个选项应该选中。
(4)在Init Utilities选项中,“Support reading an inittab file”应该选中,这样可以根据自己编写的inittab文件初始化;“Support running commands with a controlling-tty”应该选中,否则会提示非常困扰的“/bin/sh: can't access tty; job control turned off”的提示,尽管可以进入控制台命令行。
(4)在Shell选项中,应该选中默认shell:ash,否则不会生成sh,导致不能解释脚本文件。
(5)其他的选项根据自己的需要设置。
b , 配置完成后,退出保存(最好备份.config文件以供后用),然后开始生成,执行make TARGET_ARCH=arm;此处的TARGET_ARCH是必须的。生成完成后使用qemu-arm测试:qemu-arm ./busybox ls,如果没有错误的话,会显示出 当前目录下的文件列表。
说明:在生成的过程中,提示了“/mnt/extdisk/embedded/busybox-1.1.3/include/bbconfigopts.h:28 hmm, untermina”错误,分析相应的文件,发现应该是一个配置包含文件,在配置后保存在.config文件中,因此这个文件中的内容应该不是关键内容,因此我将此文件清空保存,然后重新执行上面的生成命令,成功。
c , 生成结束后,执行make install,生成一个_install文件夹,内有一个linuxrc文件和bin、sbin、usr三个文件夹,删除linuxrc,将三个文件夹打包。
d , 准备生成cramfs文件系统:
(1)创建一个文件夹,比如rootfs,转到rootfs,执行命令mkdir bin dev etc home lib mnt proc sbin sys tmp var usr,建立相应的文件夹,再建立etc下的init.d文件夹。
(2)准备启动所需的文件:linuxrc、rcS、inittab、fstab四个文件;
linuxrc文件:
----------------------------------
#!/bin/sh
echo "mount /etc as ramfs"
/bin/mount -f -t cramfs -o remount,ro /dev/bon/2 /
/bin/mount -t ramfs ramfs /var
/bin/mkdir -p /var/tmp
/bin/mkdir -p /var/run
/bin/mkdir -p /var/log
/bin/mkdir -p /var/lock
/bin/mkdir -p /var/empty
#/bin/mount -t usbdevfs none /proc/bus/usb
exec /sbin/init
----------------------------------
Linuxrc文件,内核加载后执行的第一个文件,设置内核执行的初始化进程,/bin/mount -t ramfs ramfs /var这句话的作用加载一个ramfs作为/var目录。Ramfs是一个存在于内存中的文件系统,当重启系统后内存上保留的信息就会被擦除。这样/var就被挂载为ramfs文件系统。这样/var就是一个可写目录。cramfs根文件系统,是一个只读文件系统中,这样/var可保存临时文件, linuxrc第一件事情就是将一个ramfs mount 到/var只读目录中,使得/var/*可写。
exec /sbin/init执行根文件系统中的init执行程序,使其成为1号进程。shell正式运行。
rcS文件:(/etc/init.d目录下),在/etc/inittab 脚本中被调用。
-----------------------------------------------------------------------------------
#!/bin/sh
/bin/mount –a #挂载/etc/fstab中指定要挂载的文件系统
-----------------------------------------------------------------------------------
这两个文件生成后,应该使其具有执行的权限,可使用chmod 775 linuxrc rcS来修改,linuxrc应该放在rootfs根目录,rcS应该放在rootfs/etc/init.d/目录。
inittab文件:(/etc目录下),用于控制init进程。
---------------------------------
# This is run first except when booting 系统启动后最先执行
::sysinit:/etc/init.d/rcS#表示rcS只执行一次,而且init进程等待它结束才继续执行其他#动作
# Start an "askfirst" shell on the console
#::askfirst:-/bin/bash
::askfirst:-/bin/sh #“-”表示这个程序是交互的,init进程先输出” 等用户输入回车后才启动子程序。
# Stuff to do when restarting the init process
::restart:/sbin/init #先重新读取、解析/etc/inittab文件,再执行restart程序
::once:/usr/etc/rc.local #once表示只执行一次,init进程不等它结束
# Stuff to do before rebooting
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
-----------------------------------
fstab文件:(/etc目录下),用于指定要挂载的文件系统,在rcS中被调用。
-----------------------------------
none /proc proc defaults 0 0
none /dev/pts devpts mode=0622 0 0
tmpfs /dev/shm tmpfs defaults 0 0
proc 文件系统表示 process information pseudo文件系统,内核用它来提供系统状态信息。
tmpfs是一种虚拟内存文件系统
devpts 文件系统是一个支持Unix98 PTYs的虚拟伪终端文件系统,/dev/pts,即伪终端,逻辑上的终端设备,多用于模拟终端设备。/pts目录下,系统会根据需要自动生成1、2、3等设备文件,这些设备文件是临时的。
--------------------------------
Inittab和fstab这两个文件应该放在rootfs/etc/目录,应该注意其权限问题。
(3)如果使用linux 2.6.xx内核,应该实现创建节点console、null。转到rootfs/dev/目录来创建:
sudo mknod console c 5 1
sudo mknod null c 1 3
否则就会提示“Warning: unable to open an initial console.
Kernel panic - not syncing: Attempted to kill init!”的类似错误。
(4)将刚才在busybox的_install下的三个文件夹的打包文件复制到rootfs目录,解压后删除打包文件。
(5)也可以将一些常用的lib文件复制到rootfs/lib/目录下,比如:ld-2.5.so libc-2.5.so libcrypt.so.1 libgcc_s.so.1 libm.so.6 ld-linux.so.3 libcrypt-2.5.so libc.so.6 libm-2.5.so等文件或符号连接,在复制时应该注意采用图形化的界面复制活打包后解包方式复制。
(6)转到rootfs的上一级目录,使用mkcramfs制作文件系统:./mkcramfs rootfs xxxxx.cramfs,然后下载、少录、启动,成功启动。
遇到的问题;
编译busybox1.00pe10
mconf.c:477: warning: ignoring return value of 'write', declared with attribute
warn_unused_result
解决办法:
$ gedit scripts/config/mconf.c
static char filename[PATH_MAX+1] = ".config";
static int indent = 0;
static struct termios ios_org;
static int rows, cols;
//static struct menu *current_menu; //将此行注释即可
static int child_count;
static int single_menu_mode;
5. 总结
(a), 本版搭配,这里搭配如下
Linux kernel:Linux2.6.29.6
gcc : arm-linux-gcc 3.4.1
busybox: busybox-1.00-pre10
由于在移植xilinx zynq时用到linux3.10.1,arm-linux-gcc-4.4.3.tar.gz,busybox-1.20.2.tar开始想直接用这两个arm-linux-gcc-4.4.3.tar.gz,busybox-1.20.2.tar搭配Linux2.6.29.6,结果提示FATAL: kernel too old
Kernel panic - not syncing: Attempted to kill init!
gcc对内核有最低版本限制,用file查看gcc目录下的lib库文件可知。以后有时间,再试试linux3.10.1,arm-linux-gcc-4.4.3.tar.gz,busybox-1.20.2.tar这个组合。
(b)file system启动/linuxrc文件
这个文件是启动文件系统的关键,可以用busybox生成的,也可以自己配置,暂时参考上边网上写的,由于对内核启动后一些系统配置不清楚,这个地方还有很多不理解的。Cramfs是只读文件系统,需要挂在ram才能读写,由于flash有坏块,容量不够,以后有时间,把坏块前边的空间分出来试试。
文章评论(0条评论)
登录后参与讨论