一般利用一张SD卡就能进行系统的更新,以前一直不知是什么原理,最近了解了下,对了解到的内容做个记录。使用的是AM335X平台,系统是Linux,文件系统是EXT3:
1、首先需要一张分好分区的SD卡(分区方法这里不做详细介绍,一般可使用TI官方提供的create-sdcard.sh脚本可以进行分区)。其中分区1(FAT32)存放MLO、u-boot.img、uImage三个文件;分区2(EXT3)存放需要从SD卡启动的Linux文件系统。
2、AM335X上电后,根据Boot Sequence启动配置(LCD0-LCD15引脚,具体可参考TI官方的335X参考手册),从相应的存储设备启动,这里配置的是从SD卡启动。
3、AM335X上电后首先执行固化在芯片内部ROM中的代码,我们称之为BLO,BLO的功能很强大,能读取SD卡中的第一个分区(必须是FAT格式)的MLO文件,复制到AM335X内部的RAM中吞下,复制的起始地址为0x402f0400,所以编译MLO时,连接地址必须设置为0x402F0400。
4、一般的,MLO的作用是:禁用中断、关看门狗、设置栈、初始化时钟、初始化DDR3、初始化串口、最后复制S卡中boot(FAT32)分区的u-boot.img到DDR3的0x80000000(内存)处运行。MLO的最大体积可以达到109K,对于简单的逻辑程序绰绰有余了。
5、u-boot的功能主要是启动内核:u-boot从SD卡的boot(FAT32)分区复制uImage到内存运行。
6、启动Linux后挂载SD卡的rootfs分区(EXT3)的文件系统
7、文件系统是利用Busybox工具集创建的,首先内核会启动BusyBox里的Init进程。init进程首先主要对/etc/inittab文件进行解析,然后按照它的指示创建各种子进程。
8、inittab文件的内容主要以下几部分。其中系统运行后最先执行的是/etc/rc.d/rcS进程,并且它只执行一次,其它进程只有等它执行完毕后才能运行,u-boot、内核、文件系统的烧写在这里执行。
1 ::sysinit:/etc/rc.d/rcS 2 ::respawn:/sbin/getty 9600 tty1 3 ::ctrlaltdel:/sbin/reboot 4 ::shutdown:/etc/rc.d/rcS stop 5 ::restart:/sbin/init
9、接着继续看到/etc/rc.d/rcS文件,这是一个脚本文件,下面一一分析它做的工作
#!/bin/sh # minimal startup script, will work with msh (this is best available in # MMUless format). mode=${1:-start} #若第一个参数存在,则mode的值为第一个参数;否则mode等于start # load the configuration information if [ -x /etc/rc.d/rc.conf ] then . /etc/rc.d/rc.conf #不管/etc/rc.d/rc.conf是否可执行,都去执行它,等价于sh /etc/rc.d/rc.conf fi if [ $mode = "start" ] #若mode的值为start, then services=$cfg_services #那么services等于$cfg_services(这个值在/etc/rc.d/rc.conf中定义:"crond mount-proc-sys hostname depmod modules udev filesystems inetd") else services=$cfg_services_r #否则services等于$cfg_services_r (这个值在/etc/rc.d/rc.conf中定义:"inetd filesystems udev modules depmod hostname mount-proc-sys crond") fi cfg_services=${2:-$services} #若第二个参数存在,则cfg_services的值为第二个参数;否则cfg_services等于services # run the configured sequence #按配置的顺序,启动各个进程 for i in $cfg_services do if [ -x /etc/rc.d/init.d/$i ] #如果进程是可执行的,那么 then echo "/etc/rc.d/init.d/"$i $mode #打印进程信息 /etc/rc.d/init.d/$i $mode #挨个执行 fi done if [ $# -ge 2 ] #如果参数个数大于等于2 then exit 0 #退出 fi if [ $mode = "start" ] #若mode的值为start, then # show all kernel log messages if [ -x /proc/sys/kernel/printk ] #若/proc/sys/kernel/printk可执行 then #echo 8 > /proc/sys/kernel/printk echo 0 > /proc/sys/kernel/printk #清空/proc/sys/kernel/printk fi # echo set kernel halt time echo -e "