SSD_SD BOOT环境搭建
1. SD boot方案介绍¶
SD boot方案是只通过SD卡从rom启动到rootfs,即IPL, CUST, UBOOT, ENV, KERNEL, ROOTFS等image都存放在SD卡中。分区设计和image存放位置如下图所示:
如图,分区采用dos分区系统,分区1为fat32文件系统的用户分区,里面可以存放IPL, CUST, UBOOT等启动文件和SigmastarSDUpgrade.bin等升级包,同SD upgrade做法。
表头MBR与分区1之间会保留1M(0x800 block)的保留空间,env就存放在这段空间中,0x278~0x478。
kernel,rootfs等image各单独创建一个分区,以二进制数据保存在对应的分区的首地址处。
2. SD boot编译¶
2.1. 准备工作¶
P3开发板、SDHC卡(支持sd2.0协议,容量不小于2G),读卡器
工具链:
export ARCH=arm; export CROSS_COMPILE=arm-linux-gnueabihf-; export PATH=/tools/toolchain/gcc-sigmastar-9.1.0-2020.07-x86_64_arm-linux-gnueabihf/bin/:$PATH;
2.2. project¶
选择使用名字中与sdmmc相关的defconfig,以dispcam_p3_sdmmc.glibc-9.1.0-ext4fs.s01a.64.qfn128_defconfig为例:
cd ${alkaid_path}/project make dispcam_p3_sdmmc.glibc-9.1.0-ext4fs.s01a.64.qfn128_defconfig make clean; make image-nocheck -j32 ls image/output/images/
default编译方案的设定是:SD卡容量为4GB、kernel分区size为10M,rootfs--200M,miserver--300M,customer--2G。
编辑image/configs/p3/sdmmc.ext4fs.partition.config
根据实际情况,可自行调整相关信息参数。
2.3. uboot¶
选择使用名字中与sdmmc相关的defconfig, 以pioneer3_sdmmc_defconfig为例:
cd ${alkaid_path}/boot make pioneer3_sdmmc_defconfig make clean; make -j32 cp ./u-boot.xz.img.bin ${alkaid_path}/project/image/output/images/boot/UBOOT #和SD相关的配置如下 make menuconfig # Device Drivers ---> # [*] MStar drivers ---> # [*] MSTAR SDMMC # [*] Save environment to SDMMC (要确保关闭Save env to ISP NOR FLASH和 Save env to NAND FLASH,否则会编译失败) # [*] Fake cdz, always detect SD is true (fake cdz脚,忽略卡存在检测,贴片式sd需要开启)
2.4. kernel¶
选择使用名字中与sdmmc相关的defconfig,以pioneer3_ssc020a_s01a_str_sdmmc_defconfig为例:
cd ${alkaid_path}/kernel make pioneer3_ssc020a_s01a_str_sdmmc_defconfig make clean; make -j32 cp ./arch/arm/boot/uImage.xz ${alkaid_path}/project/image/output/images/kernel #和SD相关的配置如下 make menuconfig # Enable the block layer --> # [*]Support for large (2TB+) block devices and files (ext4 fs需要) # Device Drivers --> # [*]MMC/SD/SDIO card support --> # <*>HW reset support for eMMC # <*>Simple HW reset support for MMC # <*>MMC block device driver # [*]SStar SoC platform drivers --> # < >EMMC driver (emmc与sd共pad,不要选中) # <*>SStar SD/MMC Card Interface Support # File systems --> # <*>The Extended 4 (ext4) filesystem(emmc启动时需要,子选项保持默认)
3. SD boot烧录¶
3.1. 通过网络自动升级烧录¶
-
将images/boot目录下的IPL, IPL_CUST, UBOOT用读卡器拷贝到SD卡根目录下。
-
插上SD卡,将板子的启动方式切位不spinand/nor启动不skip SD,上电,这时候板子就会优先从SD卡启动,进到UBOOT了。
-
在uboot命令行下设置好网络信息后,敲estar,等待烧录完成。
-
reset,SD卡能boot成功boot到rootfs。
3.2. 通过USB烧录¶
3.3. 烧录器烧录¶
3.3.1 工具准备¶
使用shell脚本将整套启动数据制作sd disk image,然后使用烧录器将该母片烧录到SD卡0地址处,即可完成烧录。
工具:
脚本工具放在images-package包下。脚本运行环境是linux,有losetup、fdisk、mkfs.vfat、mount、umount、dd、rm、cp命令的root权限。
3.3.2 环境变量镜像¶
把需要设置的环境变量按照uboot printenv命令打印出来的格式写入到一个txt文件,例如:
$ cd ${alkaid_path}/boot $ vi ./env.txt autoestart=0 baudrate=115200 bootargs=console=ttyS0,115200 root=/dev/mmcblk0p3 rootwait rootfstype=ext4 rw init=/linuxrc LX_MEM=0x3FE0000 mma_heap=mma_heap_name0,miu=0,sz=0x1E00000 cma=2M highres=off mmap_reserved=fb,miu=0,sz=0x300000,max_start_off=0x3300000,max_end_off=0x3600000 bootcmd=fdisk -r 0:2 0x22000000 0 0x5000; dcache on ; bootm 0x22000000; bootdelay=0 ethact=sstar_emac fileaddr=239c14d0 sstar_bbm=off stderr=serial stdin=serial stdout=serial
uboot编译后在tools目录下有一个mkenvimage工具,使用该工具制作env.bin:
$ ./tools/mkenvimage -s 0x20000 -o ./env.bin ./env.txt
将该env.bin放在images-package包下:
$ cp ./env.bin ${alkaid_path}/project/image/output/images/
3.3.3. 制作母片¶
$ sh mk_sddisk.sh -h
Usage: sh mk_sddisk.sh [option]
Support burn the disk image according to the iamges-package
[option]
-s The path of the source images-package
-o Output filename
-l Virtual block device
键入命令制作sd_disk.img,参数使用默认值,source为.,output filename为sd_disk.img,virtual block device是/dev/loop0
$ sh mk_sddisk.sh
注意:如果提示找不到src file,检查是-s 后面的path是否正确,且path最后不能以'/'结尾。
4. UBOOT下新增命令介绍¶
-
fatformat
将分区格式化为fat32文件系统。举例:fatformat mmc 0:1
-
fdisk
dos分区操作命令,可支持创建/删除/查看分区,读/写/擦除分区数据。
5. Alkaid下修改分区设计方法¶
SD启动方案的分区方案固定写在${alkaid_path}/project/image/configs/p3/sdmmc.ext4fs.partition.config
文件中,default设定如下:
# FAT_IMAGE_LIST中的文件将存放在被格式化为FAT32fs的分区1中 FAT_IMAGE_LIST = ipl ipl_cust uboot # SYS_IMAGE_LIST标识所有需要烧录的image,需要为这些image单独创建对应的分区 SYS_IMAGE_LIST = kernel rootfs miservice customer misc # SD capacity,SD卡的实际总容量大小,以block(512bytes)为单位。 2GB:0x400000 | 4GB:0x800000 | 8GB:0x1000000 | 16GB:0x2000000 | 32GB:0x4000000 | 64GB:0x8000000 # SD卡的实际容量可能比理论容量小,因此该项值最好填小一点。 FLASH_BLK_CNT = 0x800000 # rootfs起来后会自动挂载的image对应的分区 USR_MOUNT_BLOCKS:=miservice customer misc ... kernel$(RESOUCE) = $(PROJ_ROOT)/kbuild/$(KERNEL_VERSION)/arch/arm/boot/uImage.xz kernel$(BOOTCMD) = fdisk -r 0:$(kernel$(INDEX)) $(KERNELBOOTADDR) 0 $(kernel$(CNT))\; kernel$(BOOTENV) = $(KERNEL_BOOT_ENV) # kernel分区的容量,以block(512bytes)为单位 kernel$(CNT) = 0xA000 # kernel分区编号 kernel$(INDEX) = 2 rootfs$(RESOUCE) = $(OUTPUTDIR)/rootfs rootfs$(FSTYPE) = ext4 # ext4fs格式的image的size,以byte为单位,需不小于resouce。 rootfs$(PATSIZE) = 0x1400000 rootfs$(BOOTENV) = console=ttyS0,115200 root=/dev/mmcblk0p3 rootwait rootfstype=ext4 rw init=/linuxrc # rootfs分区的容量,以block(512bytes)为单位 rootfs$(CNT) = 0x64000 # rootfs分区编号 rootfs$(INDEX) = 3 miservice$(RESOUCE) = $(OUTPUTDIR)/miservice/config miservice$(FSTYPE) = ext4 miservice$(PATSIZE) = 0x1400000 miservice$(MOUNTTG) = /config miservice$(MOUNTPT) = /dev/mmcblk0p5 miservice$(OPTIONS) = ro miservice$(CNT) = 0x96000 # 注意,分区4是扩展分区mbr,需要跳过。下面的分区编号要与上面的mount dev一致。 miservice$(INDEX) = 5 # skip ext partition 4 ... # 计算SD卡剩余容量,创建P1分区。若不想把P1分区当作User分区来用,可固定该分区size为0x10000(32MB,FAT32分区size最小值) user-fat$(CNT) = $(shell ((cnt=$(FLASH_BLK_CNT)-$(FLASH_BLK_CNT_RESV)-$(kernel$(CNT))-$(rootfs$(CNT))-$(miservice$(CNT))-$(customer$(CNT))-$(misc$(CNT)))); printf 0x%X $$cnt) user-fat$(TYPE) = FAT32 # 分区1,格式化为fat32文件系统,存放IPL, CUST, UBOOT用于启动 user-fat$(INDEX) = 1 # fat partition have to be part1
注意:在烧录完成后,查看分区表可能发现分区实际size与预设值不符(偏大),这是正常现象。因为小于8GB的SD卡使用CHS mode,其要求分区的起始地址和结束地址要满足units对齐导致的。
6. 常见问题分析¶
-
超SD卡容量问题,如下所示,当SD卡容量不够时会报该问题,可根据log信息中的sd max block count数,重新规划调整分区。
>> fdisk -c 0 0x400000 MMC: block number 0x765a63 exceeds max(0x764000) ** Can't read partition table on 0:7756386 **
-
分区表被破坏,因为误操作,分区表可能会被破坏。
Part Start Sector Num Sectors UUID Type 1 7582 7742049 ffffffff-01 0c 2 7756386 -6755 ffffffff-02 83 3 7756386 -6755 ffffffff-03 83 4 7756386 -6920 ffffffff-04 05 Extd MMC: block number 0x765a63 exceeds max(0x764000) ** Can't read partition table on 0:7756386 **
此时可以使用
mmc erase 0 0x2000
将分区信息全擦除掉,然后再重建分区。示例命令中0代表的是sd卡的起始擦除位置,以block(512byte)为单位,0x2000是size,同样以block为单位,可根据实际情况调整。 -
识别分区失败。刚创建好了的分区,却报获取分区失败。
[UFU runcmd] fdisk -c 0 0xA9667 [UFU runcmd] fdisk -c 0 0x5000 [UFU runcmd] fdisk -c 0 0xb000 [UFU runcmd] fdisk -c 0 0xb000 [UFU runcmd] fdisk -c 0 0x18000 [UFU runcmd] fdisk -c 0 0xA000 [UFU runcmd] fatformat mmc 0:1 Start format MMC0 partition1 .... ERROR: v7_dcache_inval_range - start address is not aligned - 0x239bf168 ERROR: v7_dcache_inval_range - stop address is not aligned - 0x239bf368 ** Partition 1 not valid on device 0 ** Format failure!!! [UFU runcmd] fdisk -e 0:2 ** No partition table - mmc 0 **
这大概率是因为此时sw识别该device的分区type异常,这是由于在空片状态下执行
mmc rescan
导致的,规避方法烧录前不用擦除sd为空片,或者擦完后,烧录前执行fdisk -c 0 0x200
创建一个测试分区用于确保重识别卡为dos分区系统。 -
编译报错
[[customer_sdmmc_ext4_fsimage]] mke2fs -d /home/jz.xiang/workspace/master_branch/project/image/output/customer -t ext4 /home/jz.xiang/workspace/master_branch/project/image/output/images/customer.ext4 $((0x1600000/1024/1024))M mke2fs 1.44.1 (24-Mar-2018) Creating regular file /home/jz.xiang/workspace/master_branch/project/image/output/images/customer.ext4 Creating filesystem with 22528 1k blocks and 5640 inodes Filesystem UUID: 186d8272-6e05-4029-a692-e4ede64fdebd Superblock backups stored on blocks: 8193 Allocating group tables: done Writing inode tables: done Creating journal (1024 blocks): done Copying files into the device: __populate_fs: Could not allocate block in ext2 filesystem while writing file "prog_dla_classify" mke2fs: Could not allocate block in ext2 filesystem while populating file system image.mk:24: recipe for target 'customer_sdmmc_ext4_fsimage' failed
这是设定的image size不够大导致的,修改
sdmmc.ext4fs.partition.config
中对应项即可customer$(RESOUCE) = $(OUTPUTDIR)/customer customer$(FSTYPE) = ext4 customer$(PATSIZE) = 0x3600000 # image size, need to larger than root-directory customer$(MOUNTTG) = /customer