AM5728-NOR+eMMC启动-主备分区切换功能实现

一、 方案框图

基于广州创龙TL5728-EasyEVM 开发板,设计了NOR+eMMC启动及升级方案,实现框图如下所示。
在这里插入图片描述

  • eMMC 有三大分区,分别是boot分区、rootfs1分区、rootfs2分区(backup),在创龙提供的demo脚本基础上进行了eMMC分区修改。

  • NOR在调试时,遇到了Spansion 和镁光不同型号的NOR出现读写问题。创龙提供了支持报告,可参考。另外自己编写了NOR烧写脚本。

  • 高端内存读写操作使用了自定义Uboot命令,myhello命令。

  • 分区切换通过修改默认环境变量实现。

  • 使能看门狗配合分区切换。

    软件版本:
    Uboot版本:u-boot-2017.01
    Kernel版本:linux-rt-4.9.65

二、 登陆Linux系统后需做的修改

2.1 设备树修改

路径:kernel\Linux-RT-4.9.65\arch\arm\boot\dts\am57xx-evm-common.dtsi

重新调整了NOR Flash的分区。
在这里插入图片描述
在这里插入图片描述
重新编译设备树文件 tl5728-easy-evm.dtb.

2.2 烧录脚本修改

基于创龙提供的烧录脚本,进行了修改。

1)eMMC烧录脚本
脚本:burn_scripts\mkemmcboot-heat.sh
在这里插入图片描述
分区大小如上所示。分了3个区,bank1用于存放 MLO和u-boot.img,bank2用于存放rootfs1,bank3用于存放rootfs2(备份)。
分区完成后,将SD卡分区的文件拷贝至eMMC 分区中。
在这里插入图片描述
2)NOR烧录脚本
脚本:burn_scripts\mknorboot-heat.sh

将SD卡中的文件,拷贝至NOR相应的分区中。
在这里插入图片描述
MLO - /dev/mtdblock0
u-boot.img - /dev/mtdblock1
image.ub - /dev/mtdblock6
备注:下面章节四有image.ub文件制作过程。

三、 引导启动-MLO和Uboot 修改

3.1 添加对镁光Flash的支持

创龙提供了两种NOR型号的核心板:Spansion 和 镁光。
修改 uboot添加对镁光 flash 的支持,以及不使用 EDMA3 进行拷贝。
在这里插入图片描述
另外Uboot初始化镁光NOR后,也会出现读写镜像错误,需修改spi flash读操作函数。
\u-boot-2017.01-g70d59ba-v2.0\drivers\mtd\spi\spi_flash.c
在这里插入图片描述
在这里插入图片描述

3.2 使能看门狗

参考:
http://e2e.ti.com/support/processors/f/791/t/853613?AM5728-Issues-with-WDT-enabled-in-U-boot

Uboot 2017.01版本u-boot-2017.01-demo\drivers\watchdog 目录下的 Kconfig文件是空的,拷贝了TI 官网SDK 06.02.00.81 版本的u-boot-2019.01 的 Kconfig进行了修改。
下面的Makefile ,有编译 omap_wdt.c的选项。
在这里插入图片描述
照猫画虎,修改了对应的 Kconfig 文件。

在这里插入图片描述

menu "Watchdog Timer Support"

config WATCHDOG
	bool "Enable U-Boot watchdog reset"
	help
	  This option enables U-Boot watchdog support where U-Boot is using
	  watchdog_reset function to service watchdog device in U-Boot. Enable
	  this option if you want to service enabled watchdog by U-Boot. Disable
	  this option if you want U-Boot to start watchdog but never service it.

config HW_WATCHDOG
	bool

config WATCHDOG_RESET_DISABLE
	bool "Disable reset watchdog"
	help
	   Disable reset watchdog, which can let WATCHDOG_RESET invalid, so
	   that the watchdog will not be fed in u-boot.

config OMAP_WATCHDOG
	bool "TI OMAP watchdog driver"
	select HW_WATCHDOG
	default y if AM33XX
	help
	  Say Y here to enable the OMAP3+ watchdog driver.


endmenu

添加Kconfig后,需要 make ARCH=arm menuconfig 打开相应的配置。
在这里插入图片描述
打开配置后,make ARCH=arm编译,报错如下。
在这里插入图片描述
手动在文件 \drivers\watchdog\omap_wdt.c 里定义该宏。
在这里插入图片描述
继续编译,仍有报错。
在这里插入图片描述
报错找不到结构体 struct wd_timer 的定义,需添加相应头文件。
在这里插入图片描述
继续编译,继续报错。重复定义了结构体。
在这里插入图片描述
到相应的头文件中进行修改,屏蔽该结构体的定义。
\arch\arm\include\asm\arch-am33xx\cpu.h
在这里插入图片描述
继续编译,仍有报错。SPL阶段找不到看门狗初始化等操作函数。
在这里插入图片描述
在配置中使能 SPL阶段的看门狗功能。
在这里插入图片描述
在这里插入图片描述
接下来使能Uboot阶段的看门狗功能。
\board\ti\am57xx\board.c
添加看门狗初始化。
在这里插入图片描述
在这里插入图片描述
其他修改:通过grep –nr heat 查看
在这里插入图片描述
在这里插入图片描述

3.3 自定义Uboot命令

在u-boot-2017.01-demo\cmd\目录下添加自己定义的myhello.c。
Makefile添加编译 myhello.c的选项。
在这里插入图片描述
Kconfig文件添加myhello编译选项,其上一层为“Memory commands”。
在这里插入图片描述
在这里插入图片描述
menuconfig查看配置,并将 myhello 勾选上。
在这里插入图片描述
进行编译。

说明:
myhello.c 文件中涉及的高端内存地址。

1) 内存地址及数值定义

Count_flag_addr = 0xFFFFF00 , Count_flag_value = 0xBEEF0000 代表启动次数为0,Count_flag_value = 0xBEEF0001 代表启动次数为1;

Media_flag_addr=0xFFFFFF04,Media_flag_value = 0xDEAD0000 代表文件系统分区为eMMC- rootfs1,Media_flag_value = 0xDEAD0001 代表文件系统分区为eMMC- rootfs2,Media_flag_value = 0xDEAD0002 代表文件系统分区为NOR-Ramdisk;

读取到的Media_flag_value数值可以用于判断当前系统所运行的文件系统分区。

2)内存地址读写接口

高端内存的地址映射采用mmap方式,读写接口封装成了so库。

读写API如下:
读操作:unsigned long high_mem_read(char *addr);
写操作:int high_mem_write(char *addr, char *write_val);

3.4 默认环境变量修改

u-boot-2017.01-demo\include\environment\ti\boot.h

/*
 * Boot related environment variable definitions on TI boards.
 *
 * (C) Copyright 2017 Linaro Ltd.
 * Sam Protsenko <semen.protsenko@linaro.org>
 *
 * SPDX-License-Identifier: GPL-2.0+
 */

#ifndef __TI_BOOT_H
#define __TI_BOOT_H

#ifndef CONSOLEDEV
#define CONSOLEDEV "ttyO2"
#endif

#ifndef PARTS_DEFAULT
#define PARTS_DEFAULT
#endif

#define DEFAULT_COMMON_BOOT_TI_ARGS \
    "console=" CONSOLEDEV ",115200n8\0" \
    "fdtfile=undefined\0" \
    "board_name=tl5728-easy-evm\0" \
    "bootpart=0:2\0" \
    "bootdir=/boot\0" \
    "bootfile=zImage\0" \
    "usbtty=cdc_acm\0" \
    "vram=16M\0" \
    "partitions=" PARTS_DEFAULT "\0" \
    "optargs=\0" \
    "idk_pru1_mii=no\0" \
    "optargs=omapdrm.displays=0,1\0" \
    "dofastboot=0\0" \
    "usbdev=0\0" \
    "usbroot=/dev/sda2\0" \
    "usbrootfstype=ext4 rootwait\0" \
    "count_addr=0xFFFFFF00\0" \
    "media_addr=0xFFFFFF04\0" \
    "norboot=echo norboot\0 " \
    "usbloadimage=load usb ${bootpart} ${loadaddr} ${bootdir}/${bootfile}\0" \
    "usbloadfdt=load usb ${bootpart} ${fdtaddr} ${bootdir}/${fdtfile};\0" \
    "args_usb=setenv bootargs rootfstype=${usbrootfstype} root=${usbroot} rw console=${console} ${optargs};\0" \
    "usbboot=echo usb found on device ${usbdev}; " \
        "run findfdt; " \
        "usb start; " \
        "if run usbloadimage; then " \
            "run usbloadfdt; " \
            "echo Booting from usb${usbdev} ...; " \
            "run args_usb; " \
            "bootz ${loadaddr} - ${fdtaddr}; " \
        "fi;\0" \
    "emmc_linux_boot=" \
        "echo Trying to boot Linux from eMMC ...; " \
        "setenv mmcdev 1; " \
        "if myhello ${count_addr} ; then " \
            "if myhello ${media_addr} ; then " \
                "echo bootpart 1:2;" \
                "setenv bootpart 1:2; " \
            "else " \
                "echo bootpart 1:3;" \
                "setenv bootpart 1:3; " \
            "fi; " \
        "else " \
            "if myhello ${media_addr} ; then " \
                "mw.l ${media_addr} 0xdead0001 1; " \
                "echo bootpart 1:3;" \
                "setenv bootpart 1:3; " \
            "else " \
                "echo Trying to boot Linux from NOR Flash ...; " \
                "mw.l ${media_addr} 0xdead0002 1; " \
                "run ramdiskboot; " \
            "fi; " \
        "fi; " \
        "setenv mmcroot /dev/mmcblk0p2 rw; " \
        "run mmcboot;\0" \
    "emmc_android_boot=" \
        "echo Trying to boot Android from eMMC ...; " \
        "setenv eval_bootargs setenv bootargs $bootargs; " \
        "run eval_bootargs; " \
        "setenv mmcdev 1; " \
        "setenv fdt_part 3; " \
        "setenv boot_part 9; " \
        "setenv machid fe6; " \
        "mmc dev $mmcdev; " \
        "mmc rescan; " \
        "part start mmc ${mmcdev} ${fdt_part} fdt_start; " \
        "part size mmc ${mmcdev} ${fdt_part} fdt_size; " \
        "part start mmc ${mmcdev} ${boot_part} boot_start; " \
        "part size mmc ${mmcdev} ${boot_part} boot_size; " \
        "mmc read ${fdtaddr} ${fdt_start} ${fdt_size}; " \
        "mmc read ${loadaddr} ${boot_start} ${boot_size}; " \
        "bootm $loadaddr $loadaddr $fdtaddr;\0" \
    "uimageaddr=0x9E0000\0" \
    "uimagesize=0x1620000\0" \
    "uimageloadaddr=0xA0000000\0" \
    "ramdiskboot=echo Image is image.ub ...;" \
        "echo  Filesystem is Ramdisk ...; " \
        "sf probe ${spibusno}:0 48000000; " \
        "sf read ${uimageloadaddr} ${uimageaddr} ${uimagesize}; " \
        "bootm ${uimageloadaddr}\0" \

#ifdef CONFIG_OMAP54XX

#define DEFAULT_FDT_TI_ARGS \
    "findfdt="\
        "if test $board_name = tl5728-easy-evm; then " \
            "setenv fdtfile tl5728-easy-evm.dtb; fi;" \
        "if test $board_name = tl5728-idk; then " \
            "setenv fdtfile tl5728-idk.dtb; fi;" \
        "if test $board_name = tl5728f-evm; then " \
            "setenv fdtfile tl5728f-evm.dtb; fi;" \
        "if test $board_name = tl5728-idk && test $idk_pru1_mii = yes; then " \
            "setenv fdtfile tl5728-idk-pru1-mii.dtb; fi;" \
        "if test $board_name = tl570x-evm; then " \
            "setenv fdtfile tl570x-evm.dtb; fi;" \
        "if test $fdtfile = undefined; then " \
            "echo WARNING: Could not determine device tree to use; fi; \0" \

#define CONFIG_BOOTCOMMAND \
    "if test ${dofastboot} -eq 1; then " \
        "echo Boot fastboot requested, resetting dofastboot ...;" \
        "setenv dofastboot 0; saveenv;" \
        "echo Booting into fastboot ...; " \
        "fastboot " __stringify(CONFIG_FASTBOOT_USB_DEV) "; " \
    "fi;" \
    "if test ${boot_fit} -eq 1; then "  \
        "run update_to_fit;"    \
    "fi;"   \
    "run findfdt; " \
    "run envboot; " \
    "run mmcboot;" \
    "run emmc_linux_boot; " \
    "run emmc_android_boot; " \
    ""

#endif /* CONFIG_OMAP54XX */

#endif /* __TI_BOOT_H */


四、 image.ub镜像文件制作

在这里插入图片描述
its文件配置:
在这里插入图片描述
根文件系统:rootfs

制作image.ub步骤:
1)find ./ | cpio -o -H newc | gzip -9 > …/rootfs.cpio.gz
(压缩生成 rootfs.cpio.gz,在根文件系统目录下执行该命令)

2)mkimage -f fitImage-am5728.its image.ub (制作镜像 image.ub)

在这里插入图片描述
对于rootfs.cpio.gz格式的文件,通过以下命令解压生成根文件系统。
gzip -d rootfs.cpio.gz (解压 rootfs.cpio.gz 生成 rootfs.cpio文件)
cpio -i -F …/rootfs.cpio (解压 rootfs.cpio 文件生成 cpio 虚拟根文件系统)

另外,Uboot支持FIT镜像加载还需配置menuconfig
在这里插入图片描述
在这里插入图片描述

五、 实际操作步骤

操作步骤

  1. 制作SD卡镜像;执行脚本:mksdboot.sh
  2. 主控板拨码开关拨至从SD卡启动;
  3. 使用SD卡启动进入系统;执行脚本:mknorboot-fatri.sh,烧写uboot.img和MLO启动引导镜像 NOR Flash;执行脚本:mkemmcboot-fatri.sh,将SD卡镜像固化到eMMC中。
  4. 主控板拨码开关拨至从NOR启动;
  5. 进入系统查看当前所处的文件系统分区,可以通过读写高端内存查看。具体情况请对照升级启动流程图。

六、 致谢

此方案的整体设计源于我的师傅 Richard.Li,具体功能实现由我来完成的。感谢我的师傅 Richard.Li在工作中对我的帮助和指导!

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

heat.huang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值