一般利用一张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、内核、文件系统的烧写在这里执行。

 ::sysinit:/etc/rc.d/rcS
::respawn:/sbin/getty tty1
::ctrlaltdel:/sbin/reboot
::shutdown:/etc/rc.d/rcS stop
::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=${:-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=${:-$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
then
exit #退出
fi
if [ $mode = "start" ] #若mode的值为start,
then
# show all kernel log messages
if [ -x /proc/sys/kernel/printk ] #若/proc/sys/kernel/printk可执行
then
#echo > /proc/sys/kernel/printk
echo > /proc/sys/kernel/printk #清空/proc/sys/kernel/printk
fi # echo set kernel halt time
echo -e "\033[9;0]" > /dev/tty0 #echo Bringing lo up
/sbin/ifconfig lo 127.0.0.1 up >/dev/null
/sbin/route add -net 127.0.0.0 netmask 255.0.0.0 gw 127.0.0.1 dev lo >/dev/null #echo eth0 setting #网卡0设置
if [ -x /etc/eth0-setting ]
then
echo "Found /etc/eth0-setting..."
/etc/rc.d/ifconfig-eth0 /etc/eth0-setting #在/etc/eth0-setting文件中配置IP、MASK、GATEWAY信息
fi #echo eth1 setting #网卡1设置
if [ -x /etc/eth1-setting ]
then
echo "Found /etc/eth1-setting..."
/etc/rc.d/ifconfig-eth1 /etc/eth1-setting #在/etc/eth1-setting文件中配置IP、MASK、GATEWAY信息
fi #echo wlan0 setting #wlan0设置
if [ -x /etc/wlan0-setting ]
then
echo "Found /etc/wlan0-setting..."
wpa_supplicant -B -D wext -c /etc/wpa.conf -i wlan0
wpa_cli add_network
wpa_cli enable_network
/etc/rc.d/ifconfig-wlan0 /etc/wlan0-setting
fi fi # run rc.local if present and executable
if [ -x /etc/rc.d/rc.local ] #如果/etc/rc.d/rc.local可执行
then echo "Found /etc/rc.d/rc.local..."
/etc/rc.d/rc.local $mode #那么,直接执行它。整个启动脚本的重点在这里,后面分析它
fi # run startx if present and executable
if [ -x /usr/bin/startx ]
then
if [ $mode = "start" ]
then
rm /tmp/.X0-lock
startx
fi
fi

/etc/rc.d/rcS脚本可以总结为如下的功能:
a、配置脚本运行的环境变量,文件为/etc/rc.d/rc.conf
b、运行系统服务进程:crond mount-proc-sys hostname depmod modules udev filesystems inetd
c、设置网络IP/etc/rc.d/ifconfig-eth0 /etc/eth0-setting、/etc/rc.d/ifconfig-eth1 /etc/eth1-setting
d、运行/etc/rc.d/rc.local脚本程序

10、分析/etc/rc.d/rc.local start脚本程序

#!/bin/sh
mode=${:-start} #mode等于传入的参数1为start
if [ $mode = "start" ] #如果mode的值等于start,那么运行以下程序
then #set sgtl5000 volume ~
amixer cset numid= #猜测是设置蜂鸣器音量,还不确定 echo "start format board mmc..."
echo > /sys/class/leds/user_buzzer/brightness #打开蜂鸣器,说明开始运行此脚本更新系统 /etc/rc.d/spi.sh #运行/etc/rc.d/spi.sh脚本,把/boot/u-boot.spi.512拷贝到Flash中,以后程序从此处取出u-boot运行
以下为/etc/rc.d/spi.sh脚本内容:
#!/bin/sh echo "****************************************************"
echo "****************************************************"
echo ""
echo " Hua Ming spi Flashing Script - 01/01/2015"
echo "" echo "erase spi flash..."
flash_erase /dev/mtd0 echo "write boot/u-boot.spi.512 ..."
flashcp /boot/u-boot.spi. /dev/mtd0
echo "done" /etc/rc.d/mmc.sh /dev/mmcblk1 #运行/etc/rc.d/mmc.sh脚本对mmc以ext3文件系统格式进行分区,分为4个区分别为sys、opt、user、Reserved。 mount /dev/mmcblk1p1 /mnt #挂接sys分区,将rfs_335x.tar.gz的文件进行解压缩,里面存放了最小根文件系统
cd /mnt
tar -xzvf ../rfs_335x.tar.gz mount /dev/mmcblk1p2 /mnt/opt #挂接opt分区,将HmReader.tar.gz解压缩,里面存放了应用程序
tar -xzvf ../../HmReader.tar.gz cd boot
ln -s boot.scr.mmc1 boot.scr sync echo > /sys/class/leds/user_buzzer/brightness #蜂鸣器关闭
echo "format finished ..." #格式化结束,更新完成 fi

/etc/rc.d/rc.local start脚本程序功能总结如下:
1、将/boot/u-boot.spi.512拷贝到Flash中,在从spi启动时启动u-boot。
2、对MMC1进行分区,分为四个区分别为sys、opt、user、Reserved
3、将最小根文件系统解压缩到sys分区
4、将应用程序解压缩到opt分区

11、对/etc/rc.d/mmc.sh脚本的分析:

#!/bin/sh

echo "****************************************************"
echo "****************************************************"
echo ""
echo " Hua Ming Example Flashing Script - 01/01/2015"
echo "" if [[ -z $ ]] #如果传入脚本的参数1不存在的话
then
echo "mmc.sh Usage:"
echo " mmc.sh <Dev>"
echo " Example: mmc.sh /dev/mmcblk0"
exit #退出脚本
fi STARTTIME=$(date +%s) #获得当前时间 ##---------Start of variables---------------------## ## Declare eMMC device name here
#DRIVE="/dev/mmcblk0"
DRIVE=$ #DRIVE=/dev/mmcblk1 ##----------End of variables-----------------------## ## Kill any partition info that might be there
dd if=/dev/zero of=$DRIVE bs=4k count= #猜测是清除设备原有的分区
sync
sync #马上写入设备 ## Figure out how big the eMMC is in bytes
SIZE=`fdisk -l $DRIVE | grep Disk | awk '{print $5}'` #算出块设备的大小(以字节为单位) ## Translate size into segments, which traditional tools call Cylinders. eMMC is not a spinning disk.
## We are basically ignoring what FDISK and SFDISK are reporting because it is not really accurate.
## we are translating this info to something that makes more sense for eMMC.
CYLINDERS=`echo $SIZE/// | bc` #作数学运算算出一个柱面的大小 ## Check to see if the eMMC partitions have automatically loaded from the old MBR.
## This might have occured during the boot process if the kernel detected a filesystem
## before we killed the MBR. We will need to unmount and kill them by writing 4k zeros to the
## partitions that were found.
#检查是否已经被挂载,并且已经分区。若有,则清除 check_mounted(){
is_mounted=$(grep ${DRIVE}p /proc/mounts | awk '{print $2}') if grep -q ${DRIVE}p /proc/mounts; then
echo "Found mounted partition(s) on " ${DRIVE}": " $is_mounted
umount $is_mounted
counter=
for i in $is_mounted; do \
echo "4k erase on ${DRIVE}p${counter}";
dd if=/dev/zero of=${DRIVE}p${counter} bs=4k count=;
counter=$((counter+));
done
else
echo "No partition found. Continuing."
fi
} check_mounted; ## Partitioning the eMMC using information gathered.
## Here is where you can add/remove partitions.
## We are building partitions:
## . FAT, size = cylinders * heads * sectors * bytes/sec = ~70MB
## . EXT3, size = ($CYLINDERS-[ for fat]) cylinders * heads * sectors * bytes/sec = ~1l.7GB
##
## You will need to change the lines ",9,0c0C,*", "10,,,-" to suit your needs. Adding is similar,
## but you will need to be aware of partition sizes and boundaries. Use the man page for sfdisk.
echo "Partitioning the eMMC..."
sfdisk -D -H -S -C $CYLINDERS $DRIVE << EOF
,,0x0c,*
,,,-
,,,-
,,,-
EOF ## This sleep is necessary as there is a service which attempts
## to automount any filesystems that it finds as soon as sfdisk
## finishes partitioning. We sleep to let it run. May need to
## be lengthened if you have more partitions.
sleep ## Check here if there has been a partition that automounted.
## This will eliminate the old partition that gets
## automatically found after the sfdisk command. It ONLY
## gets found if there was a previous file system on the same
## partition boundary. Happens when running this script more than once.
## To fix, we just unmount and write some zeros to it.
check_mounted; ## Clean up the dos (FAT) partition as recommended by SFDISK
#dd if=/dev/zero of=${DRIVE}p1 bs= count= ## Make sure posted writes are cleaned up
sync
sync ## Format the eMMC into partitions
echo "Formatting the eMMC into 4 partitions..." mkfs.ext3 -L "sys" ${DRIVE}p1
mkfs.ext3 -L "opt" ${DRIVE}p2
mkfs.ext3 -L "user" ${DRIVE}p3
mkfs.ext3 -L "Reserved" ${DRIVE}p4 ## Make sure posted writes are cleaned up
sync
sync
echo "Formatting done." #格式化完成 ## The block below is only necessary if using 'dd'.
## Force check the filesystem for consistency and fix errors if any.
## Resize partition to the length specified by the MBR.
## /sbin/e2fsck -fy ${DRIVE}p2
## /sbin/resize2fs ${DRIVE}p2 ENDTIME=$(date +%s)
echo "It took $(($ENDTIME - $STARTTIME)) seconds to complete this task..." #计算格式化EMMC花了多长时间
## Reboot
echo ""
echo "********************************************"
echo " Hua Ming Example Flash Script is complete."
echo ""

总结为以ext3文件系统格式对MMC进行分区,分为4个区分别为sys、opt、user、Reserved。其中sys存放最小根文件系统,opt存放应用程序,后续可以对它单独进行更新。

12、到这里所有系统更新完成,拔掉SD卡,重新上电后根据Boot Sequence启动配置(LCD0-LCD15引脚,具体可参考TI官方的335X编程手册),从相应的存储设备启动,这里配置的是SPI接口的Flash启动。说启动可能不准确,其实是内部的ROM从SPI的flash中拷贝镜像到RAM中运行。然后启动u-boot,u-boot启动后会从MMC的/sys分区的/boot目录下取出uImage镜像再到RAM中运行,接着Linux系统挂接到/sys系统。然后整个系统正常运行。

AM335X的SD卡更新系统学习记录的更多相关文章

  1. 菜鸟在ubuntu 16.04下制作am335x的SD卡启动盘反思

    以前只在消费电子平台android和rtos上做软件,每次都是公司的环境现成的,根本不用去想启动加载那部分 的事情,最近在做一个工控机的项目时,接触到了TI的arm335x系列的平台,才发现在嵌入式的 ...

  2. [i.MX6q]i.MX6q处理器,linux操作系统平台搭建 从SD卡启动系统

    转自:http://www.07net01.com/linux/2016/02/1232094.html 参照1:http://blog.csdn.net/girlkoo/article/detail ...

  3. 【转载】自制4412底板自动进入SD卡更新模块

    转载自迅为论坛:http://www.topeetboard.com参考平台:迅为iTOP-4412开发板 问题如下:在自制的底板上,当SD卡插在板子上开机时,会自动进入Updating模式,如果SD ...

  4. pcduino通过sd卡刷系统

    1.登录到pcduino的官网,下载相应的文件. 下载第一个kernel和后面那个ubuntu. 2.将SD卡插入到电脑上,运行下面这个软件: 那个盘符就是你的SD卡的盘符,选择卡量产,镜像文件选上面 ...

  5. BoneBlack am335x利用SD卡烧写板卡上的emmc

    参考ti论坛上面的一篇文章: 链接:https://pan.baidu.com/s/1SLSUbCRrIULJJf_BNI3sEQ 密码: hvem 自己稍微修改的debrick.sh 链接: htt ...

  6. 树莓派SD卡安装系统后扩容——实测简单高效

    接上一篇博客安装了树莓派64位的系统,如果需要安装桌面等其他操作会面临文件系统分区空间紧张的局面,扩容方法如下: 在ubuntu上安装 gparted工具可以对SD卡重新分区 $sudo apt-ge ...

  7. PHP实战-文章发布系统学习记录

    跟随大师的步伐,一步一步向前行进,PHP学习之路中的历程. 如果图片不能正常查看请访问云笔记链接 http://note.youdao.com/share/?id=3c25d8c03ef946d9c6 ...

  8. yii验证系统学习记录,基于yiicms(一)写的太长了,再写一篇(二)

    项目地址:https://gitee.com/templi/yiicms 感谢七觞酒大神的付出,和免费分享.当然也感谢yii2的开发团队们. 项目已经安全完毕,不知道后台密码,这种背景下,后台无法进去 ...

  9. yii验证系统学习记录,基于yiicms(二)

    /** * Validates the specified object. * @param \yii\base\Model $model the data model being validated ...

随机推荐

  1. 【python基础语法】第1天作业练习题

    # 1.下面那些不能作为标识符? """ 1.find 2. _num 3.7val 4.add. 5.def 6.pan 7.-print 8.open_file 9. ...

  2. 【47】迁移学习(Transfer Learning)

    迁移学习(Transfer Learning) 如果你要做一个计算机视觉的应用,相比于从头训练权重,或者说从随机初始化权重开始,如果你下载别人已经训练好网络结构的权重,你通常能够进展的相当快,用这个作 ...

  3. PyCharm2019 永久激活(测试通过)

    2019.1.1 专业版 永久期限,需要下载补丁,以及配置文件 补丁地址:https://pan.baidu.com/s/16ALpz_BCXjsRkpS_PtD23A 1,下载安装pycharm程序 ...

  4. NODEJS 中使用二维码 qr-image

    https://www.npmjs.com/package/qr-image npm install qr-image var qr = require('qr-image'); var code = ...

  5. 小白的java学习之路 “ 二重循环”

    二重循环: 1.什么是二重循环: 一个循环体内又包含另一个完整的循环结构 语法: while(循环条件1) { //循环操作1 while(循环条件2) { //循环操作2 } } do { //循环 ...

  6. PHP 实现遍历出目录及其子文件

    手册(有PHP4的实现方式哦):https://www.php.net/manual/zh/function.scandir.php 直接附代码吧PHP5和PHP7 直接有scandir()函数,遍历 ...

  7. 【spring boot】SpringBoot初学(6)– aop与自定义注解

    前言 github: https://github.com/vergilyn/SpringBootDemo 一.AOP 官方demo:https://github.com/spring-project ...

  8. 剑指offer-面试题12-矩阵中的路径-回溯法

    /* 题目: 设计一个函数,判断一个矩阵中是否存在一条包含该字符串所有字符的路径. 路径可从字符串的任意一格开始,每一步可向上.下.左.右移动一格. 如果一条路径经过了矩阵中的某一格,那么该路径不能再 ...

  9. Java开学测试-学生成绩管理系统

    题目: 1.定义 ScoreInformation 类,其中包括七个私有变量(stunumber, name, mathematicsscore, englishiscore,networkscore ...

  10. mysql如何让两个字段数据都不能重复?

    目录 场景 任务(需求) 行动(解决方案) 方案1:从代码层面解决(正确方案) 方案2:设置成两个唯一索引(正确方案) 方案3:删掉中间表,把从表的主键作为主表的外键,并将外键设置成唯一索引(正确方案 ...