zoukankan      html  css  js  c++  java
  • AM335X的SD卡更新系统学习记录

    一般利用一张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 "33[9;0]" > /dev/tty0
    
        #echo Bringing lo up
        /sbin/ifconfig lo 127.0.0.1 up 2>/dev/null
        /sbin/route add -net 127.0.0.0 netmask 255.0.0.0 gw 127.0.0.1 dev lo 2>/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 0
            /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=${1:-start}                              #mode等于传入的参数1为start
    if [ $mode = "start" ]                        #如果mode的值等于start,那么运行以下程序
    then
    
    #set sgtl5000 volume 0~127
    amixer cset numid=5 65                        #猜测是设置蜂鸣器音量,还不确定
    
    echo "start format board mmc..."
    echo 1 > /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 0 8
    
            echo "write boot/u-boot.spi.512 ..."
            flashcp /boot/u-boot.spi.512 /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 0 > /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 ]]                #如果传入脚本的参数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=$1                    #DRIVE=/dev/mmcblk1
    
    ##----------End of variables-----------------------##
    
    ## Kill any partition info that might be there
    dd if=/dev/zero of=$DRIVE bs=4k count=1    #猜测是清除设备原有的分区
    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/255/63/512 | 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=1
          for i in $is_mounted; do 
              echo "4k erase on ${DRIVE}p${counter}"; 
              dd if=/dev/zero of=${DRIVE}p${counter} bs=4k count=1;
              counter=$((counter+1));
          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 2 partitions:
    ##  1. FAT, size = 9 cylinders * 255 heads * 63 sectors * 512 bytes/sec = ~70MB
    ##  2. EXT3, size = 223 ($CYLINDERS-[9 for fat]) cylinders * 255 heads * 63 sectors * 512 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 255 -S 63 -C $CYLINDERS $DRIVE << EOF
    ,65,0x0c,*
    65,65,,-
    130,130,,-
    260,,,-
    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 2
    
    ## 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=512 count=1
    
    ## Make sure posted writes are cleaned up
    sync
    sync
    
    ## Format the eMMC into 2 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系统。然后整个系统正常运行。

  • 相关阅读:
    Bootstrap模态框modal的高度和宽度设置
    入门学习Linux常用必会命令实例详解
    Linux 系统中用户切换(su user与 su
    hdu 3549 Flow Problem(最大流模板题)
    第三章 学后心得及总结 【物联网1132-11】
    Find Minimum in Rotated Sorted Array 旋转数组中找最小值 @LeetCode
    面试题4
    Fp关联规则算法计算置信度及MapReduce实现思路
    POJ 1679 The Unique MST 推断最小生成树是否唯一
    论程序猿的社会地位
  • 原文地址:https://www.cnblogs.com/andyfly/p/11017377.html
Copyright © 2011-2022 走看看