i.MX8M Mini OTA方案介紹
參考收集中的資料,介紹SWupdate 和 Mender 的區別,以及應用場景
代碼下載
- 代碼下載
repo init -u https://source.codeaurora.org/external/imx/imx-manifest -b imx-linux-sumo -m imx-4.14.98-2.0.0_demo_mender.xml
- 編譯
MACHINE=imx8mmevk DISTRO=fsl-imx-xwayland source ./fsl-setup-mender.sh -b bld-xwayland
bitbake core-image-base
- 燒錄的固件介紹
//升級固件
core-image-base-imx8mmevk-20191111104651.mender
//燒錄固件
core-image-base-imx8mmevk-20191111104651.sdimg
和之前的 core-image-minimal-imx8mmevk-20190521120542.rootfs.sdcard 區別, 這部分了解了很久,走了不少彎路.
sudo ./uuu -b emmc_all imx-boot-imx8mmevk-sd.bin-flash_evk core-image-base-imx8mmevk.sdimg
彎路1 : 第一次編譯出的固件,沒發現可以整體燒錄的固件(sdcard) , 發出查找是不是代碼出現問題
彎路2: 找到對應的代碼, 反覆琢磨,最終編譯出路的固件燒錄成功無法啓動
解決方案:最終通過 dd if=core-image-base-imx8mmevk.sdimg of=/dev/sdc bs=1M && sync 寫入sd卡,發現可以成功啓動
- 燒錄固件提示
boot_fdt=try
bootcmd=mmc dev ${mmcdev}; if mmc rescan; then if run loadbootscript; then run bootscript; else run mender_setup; if run loadimage; then run mmcboot; run mender_try_to_recover; else run mender_try_to_recover; run netboot; fi; fi; else booti ${loadaddr} - ${fdt_addr}; fi
bootcmd_mfg=run mfgtool_args;if iminfo ${initrd_addr}; then if test ${tee} = yes; then bootm ${tee_addr} ${initrd_addr} ${fdt_addr}; else booti ${loadaddr} ${initrd_addr} ${fdt_addr}; fi; else echo "Run fastboot ..."; fastboot 0; fi;
bootcount=1
bootdelay=2
bootlimit=1
bootscript=echo Running bootscript from mmc ...; source
console=ttymxc1,115200 earlycon=ec_imx6q,0x30890000,115200
emmc_dev=1
ethaddr=00:04:9f:05:d1:93
ethprime=FEC
fastboot_dev=mmc1
fdt_addr=0x43000000
fdt_file=boot/fsl-imx8mm-evk.dtb
fdt_high=0xffffffffffffffff
fdtcontroladdr=bc906500
image=boot/Image
initrd_addr=0x43800000
initrd_high=0xffffffffffffffff
jh_clk=
jh_mmcboot=mw 0x303d0518 0xff; setenv fdt_file fsl-imx8mm-evk-root.dtb;setenv jh_clk clk_ignore_unused; if run loadimage; then run mmcboot; else run jh_netboot; fi;
jh_netboot=mw 0x303d0518 0xff; setenv fdt_file fsl-imx8mm-evk-root.dtb; setenv jh_clk clk_ignore_unused; run netboot;
kboot=booti
loadaddr=0x40480000
loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};
loadfdt=ext4load ${mender_uboot_root} ${fdt_addr} ${fdt_file}
loadimage=ext4load ${mender_uboot_root} ${loadaddr} ${image}
mender_altbootcmd=if test ${mender_boot_part} = 2; then setenv mender_boot_part 3; setenv mender_boot_part_hex 3; else setenv mender_boot_part 2; setenv mender_boot_part_hex 2; fi; setenv upgrade_available 0; saveenv; run mender_setup
mender_boot_kernel_type=booti
mender_boot_part=2
mender_boot_part_hex=2
mender_check_saveenv_canary=1
mender_dtb_name=fsl-imx8mm-evk-inmate.dtb
mender_kernel_name=Image
mender_saveenv_canary=1
mender_setup=if test "${mender_saveenv_canary}" != "1"; then setenv mender_saveenv_canary 1; saveenv; fi; if test "${mender_pre_setup_commands}" != ""; then run mender_pre_setup_commands; fi; setenv mender_kernel_root /dev/mmcblk1p${mender_boot_part}; if test ${mender_boot_part} = 2; then setenv mender_boot_part_name /dev/mmcblk1p2; else setenv mender_boot_part_name /dev/mmcblk1p3; fi; setenv mender_kernel_root_name ${mender_boot_part_name}; setenv mender_uboot_root mmc 0:${mender_boot_part_hex}; setenv mender_uboot_root_name ${mender_boot_part_name}; setenv expand_bootargs "setenv bootargs \\"${bootargs}\\""; run expand_bootargs; setenv expand_bootargs; if test "${mender_post_setup_commands}" != ""; then run mender_post_setup_commands; fi
mender_try_to_recover=if test ${upgrade_available} = 1; then reset; fi
mender_uboot_boot=mmc 0:1
mender_uboot_dev=0
mender_uboot_if=mmc
mfgtool_args=setenv bootargs console=${console},${baudrate} rdinit=/linuxrc clk_ignore_unused
mmcargs=setenv bootargs ${jh_clk} console=${console} root=${mender_kernel_root}
mmcautodetect=yes
mmcboot=echo Booting from mmc ...; run mmcargs; if test ${boot_fdt} = yes || test ${boot_fdt} = try; then if run loadfdt; then booti ${loadaddr} - ${fdt_addr}; else echo WARN: Cannot load the DT; fi; else echo wait for boot; fi;
mmcdev=1
mmcpart=1
mmcroot=/dev/mmcblk2p2 rootwait rw
netargs=setenv bootargs ${jh_clk} console=${console} root=/dev/nfs ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp
netboot=echo Booting from net ...; run netargs; if test ${ip_dyn} = yes; then setenv get_cmd dhcp; else setenv get_cmd tftp; fi; ${get_cmd} ${loadaddr} ${image}; if test ${boot_fdt} = yes || test ${boot_fdt} = try; then if ${get_cmd} ${fdt_addr} ${fdt_file}; then booti ${loadaddr} - ${fdt_addr}; else echo WARN: Cannot load the DT; fi; else booti; fi;
script=boot.scr
sd_dev=0
soc_type=imx8mm
upgrade_available=0
Environment size: 3925/4091 bytes
Card did not respond to voltage select!
** Bad device mmc 0 **
排查問題定位於 啓動引導出現問題.嘗試用sd卡製作鏡像,啓動成功
官方提供的mender-demo編譯出的可以從SD卡啓動, 無法從emmc啓動
主要原因在於:
setenv mender_kernel_root /dev/mmcblk1p${mender_boot_part}; //這裏參數是寫死的
對應的
對應代碼中
"setenv mender_kernel_root " MENDER_STORAGE_DEVICE_BASE "${mender_boot_part};
從而找到編譯代碼中
meta-mender-community/meta-mender-imx/templates/local.conf.append:8:MENDER_STORAGE_DEVICE_imx8mqevk = "/dev/mmcblk1"
修改之後結果發現還是無法啓動, 提示:
Fastboot: Normal
Normal Boot
Hit any key to stop autoboot: 0
switch to partitions #0, OK
mmc1(part 0) is current device
** Unable to read file boot.scr **
Card did not respond to voltage select!
** Bad device mmc 0 **
Booting from net ...
ethernet@30be0000 Waiting for PHY auto negotiation to complete......... TIMEOUT !
Could not initialize PHY ethernet@30be0000
BOOTP broadcast 1
BOOTP broadcast 2
BOOTP broadcast 3
BOOTP broadcast 4
BOOTP broadcast 5
注意到其中的: Card did not respond to voltage select! , ** Bad device mmc 0 ** , 馬上根據關鍵詞,定位到源碼中相關位置, 查找時候沒有重大發現,繼續搜索關鍵詞: Booting from net … , 發現:
//代碼位置: include/configs/imx8mm_evk.h
"if run loadimage; then " \
"run mmcboot; " \
"run mender_try_to_recover; " \
"else " \
"run mender_try_to_recover; " \
"run netboot; " \
"fi; " \
"netboot=echo Booting from net ...; " \
應該是啓動loadimage失敗,導致else走netboot, 繼續分析:
"loadimage=ext4load ${mender_uboot_root} ${loadaddr} ${image}\0" \ 找到對應的環境變量值
loadimage=ext4load mmc 0:2 0x40480000 boot/Image , 可以分析下ext4load後面字段的意思:
ext4load mmc 0:2 0x40480000 boot/Image //從第0個存儲設備的第2個分區的boot目錄讀出Image文件到內存地址0x40008000
但是根據實際的情況,目前用的是第1個存儲設備,第0個設備是SD卡
u-boot=> mmc list
FSL_SDHC: 0
FSL_SDHC: 1 (eMMC)
可以在uboot 中運行: ext4load mmc 0:2 0x40480000 boot/Image 得到結果一樣的
Card did not respond to voltage select!
** Bad device mmc 0 **
改爲第1個存儲設備之後, 運行正常
u-boot=> ext4load mmc 1:2 0x40480000 boot/Image
23163392 bytes read in 448 ms (49.3 MiB/s)
//找到對應的問題,據悉分析在源碼中應該怎麼改動
include/env_mender.h 中的L91中設置了該變量
"setenv mender_uboot_root " MENDER_UBOOT_STORAGE_INTERFACE " " __stringify(MENDER_UBOOT_STORAGE_DEVICE) ":${mender_boot_part_hex}; " \
其中MENDER_UBOOT_STORAGE_DEVICE主要設置第幾個存儲設備, 這個宏的值是Yocto編譯層面傳進來的, 對應於
sources/meta-mender-community/meta-mender-imx/recipes-bsp/u-boot/u-boot-imx_%.bbappend 其中的MENDER_UBOOT_STORAGE_DEVICE_imx8mmevk改爲1
10 # Set machine-specific variables per the definitions found in include/configs/MACHINE.h
11 # | VARIABLE | DEFINITION |
12 # | MENDER_UBOOT_ENV_STORAGE_DEVICE_OFFSET_1 | CONFIG_ENV_OFFSET |
13 # | BOOTENV_SIZE | CONFIG_ENV_SIZE |
14 # | MENDER_UBOOT_STORAGE_DEVICE | CONFIG_SYS_MMC_ENV_DEV |
17 MENDER_UBOOT_STORAGE_DEVICE_imx8mmevk = "0"
18 MENDER_UBOOT_ENV_STORAGE_DEVICE_OFFSET_1_imx8mqevk = "0x400000"
修改之後代碼編譯出錯提示:
include/config_mender.h
72:# if CONFIG_SYS_MMC_ENV_DEV != MENDER_UBOOT_STORAGE_DEVICE
73:# error CONFIG_SYS_MMC_ENV_DEV is not the same as MENDER_UBOOT_STORAGE_DEVICE. Either set it to the same value (check for example in the defconfig file), or make sure it is not defined at all. Make sure that: 1) All the instructions at docs.mender.io/devices/integrating-with-u-boot have been followed. 2) All required layers are included in bblayers.conf, including any board specific layers such as meta-mender-<board>
意思是 CONFIG_SYS_MMC_ENV_DEV 相等 MENDER_UBOOT_STORAGE_DEVICE纔行,CONFIG_SYS_MMC_ENV_DEV的值位於
include/configs/imx8mm_evk.h -> #define CONFIG_SYS_MMC_ENV_DEV>->---1 /* USDHC2 */
//修改源碼之後,Yocto中編譯需要注意一下
bitbake core-image-base -c compile -f
修改之後在此進行編譯正常啓動
- 升級過程
root@imx8mmevk:~# mender -rootfs /mnt/core.mender
INFO[0000] Configuration file does not exist: /var/lib/mender/mender.conf module=config
INFO[0000] Loaded configuration file: /etc/mender/mender.conf module=config
INFO[0000] Mender running on partition: /dev/mmcblk1p2 module=main
INFO[0000] Start updating from local image file: [/mnt/core.mender] module=rootfs
Installing update from the artifact of size 51602432
INFO[0000] no public key was provided for authenticating the artifact module=installer
INFO[0000] opening device /dev/mmcblk1p3 for writing module=block_device
INFO[0000] partition /dev/mmcblk1p3 size: 218103808 module=block_device
................................ 2% 1024 KiB
................................
................................ 99% 50176 KiB
......INFO[0047] wrote 218103808/218103808 bytes of update to device /dev/mmcblk1p3 module=device
100% 50393 KiB
INFO[0056] Enabling partition with new image installed to be a boot candidate: 3 module=device
- 是否升級成功主要看:
Kernel command line: console=ttymxc1,115200 earlycon=ec_imx6q,0x30890000,115200 root=/dev/mmcblk1p3
固件掛載
sudo mount -t ext4 -o loop core-image-base-imx8mmevk-xxxx.ext4 core-image-base
OTA Mender 升級
- 閱讀文檔
記錄文檔中的注意事項
mender -rootfs 與 mender -install 的疑惑? / 只是版本的區別
- USB升級
fdisk -l 羅列出設備,
mount /dev/sda1 /mnt 掛載U盤
mender -rootfs /mnt/core.mender 進行升級
- 在線升級
1. 配置文件介紹
2. 重點修改TenantToken
OTA Mender 升級
- 閱讀文檔
記錄文檔中的注意事項
mender -rootfs 與 mender -install 的疑惑? / 只是版本的區別
- USB升級
fdisk -l 羅列出設備,
mount /dev/sda1 /mnt 掛載U盤
mender -rootfs /mnt/core.mender 進行升級
- 在線升級
1. 配置文件介紹
2. 重點修改TenantToken
- 雲端Mender部署