NDK Mcu Boot¶
1. 背景介绍¶
BootLoader是一个硬件系统的引导代码,可以引导系统软件的升级,由于实际产品中 BootLoader 是不可以或者很难更新的,所有确保BootLoader的稳定性和鲁棒性是对一个系统最基本的保证。原则上需要保证BootLoader的功能尽量简单可靠,本文主要介绍ndk mcu 的开发指南,将会从4个方面进行阐述,分别是flash 区域的划分,BootLoader模式,升级的流程和策略
2. flash 区域的划分¶
Area |
size and range |
---|---|
User flash |
28K 0x78000->0x7F000 |
Backup |
220K 0x41000->0x78000 |
Image |
220K 0xA000->0x41000 |
BootLoader |
40K 0x00000->0xA000 |
Image 为应用程序代码,目前 hr_ota 工程代码大小是113K,那么用户逻辑代码可以使用100K。
Backup 为升级代码的备份区,确保升级固件的完整性和安全性过后,再搬运到Image 区域。
User Flash 区域,为用户存储数据的区域。
注意:User Flash 的大小是可以有限制的增大的,这个特性和BootLoader的模式也有很大的关系,详情参考下面 BootLoader 的模式
2.1 BootLoader mode¶
为了更好适配不同的程序和方案,ndk 的 BootLoader 和应用层配合实现了3种 ota 的模式,依次是 bare mode,ota in BootLoader,ota in app
2.1.1 Bare mode¶
bare mode 以为应用程序是裸机程序,适用于开发阶段的调试,或者特使需求的应用,如下图使能 CONFIG_BARE_IMAGE
即可完成工程的选择。
2.1.2 ota in BootLoader¶
该模式表示 ota 的流程和策略完全在 BootLoader 的程序执行的,这意味着 flash backup 区域可以重新分配给 flash image 和 user flash 区域。
使用该功能的步骤
编译下载 BootLoader 的程序,程序位置为
ndk\pan107x_mcu_boot
或者ndk\pan108x_mcu_boot
,选择那个BootLoader 取决于你的芯片版本。修改应用程序的配置 (1)使能
CONFIG_OTA_IN_BOOTLOADER
,如下图所示 (2)修改 image flash 区域的大小或者 user flash 区域的大小(optional),如下图所示
注意:
CONFIG_IMAGE_EXTENDED_SIZE
和 CONFIG_USER_FLASH_EXTENDED_SIZE
扩展 Image 和 User flash 区域的大小,上图配置可以得到下图的公式
image_size = SIZE_FIXED_APP_IMAGE + CONFIG_IMAGE_EXTENDED_SIZE
image_size = 220 + 120 = 340 octets
user_flash_size = SIZE_FIXED_USER_FLASH + CONFIG_USER_FLASH_EXTENDED_SIZE
user_flash_size = 28 + 100 = 128 octets
2.1.2.1 支持的升级的方法¶
USB dfu 模式:107 芯片支持,108 芯片待支持
UART dfu 模式:107 和108 芯片均支持
PRF OTA 模式:待支持
2.1.3 ota in APP¶
默认OTA 的升级流程是在APP 完成的,相比于 ota in BootLoader 他主要兼容 smp 的蓝牙升级,同时意味着付出了 image flash size <= 220K 的代价。
使用该功能的步骤
编译下载 BootLoader 的程序,程序位置为
ndk\pan107x_mcu_boot
或者ndk\pan108x_mcu_boot
,选择那个BootLoader 取决于你的芯片版本。修改应用程序的配置 (1)禁止
CONFIG_OTA_IN_BOOTLOADER
和CONFIG_BARE_IMAGE
,如下图所示 (2)修改 user flash 区域的大小(optional),如下图所示
注意:此时依然可可以通过CONFIG_USER_FLASH_EXTENDED_SIZE
扩张user flash 区域,如果这样做意味着Image 区域也变相的减少了。
2.1.2.1 支持的升级的方法¶
蓝牙 smp 升级,需要应用层支持,详情参考```bleprph_hr_ota` 的demo
3 BootLoader 升级流程和策略¶
BootLoader 启动的时候,会等待很多个信号,然后依次trigger 信号的操作。这儿我们抽象成QT 编程中描述的信号和槽的概念,代码工程ndk\pan107x_mcu_boot
或者 ndk\pan108x_mcu_boot
。
signal:
bool sig_key_push_down(void);
bool sig_special_ram_value_detected(void);
bool sig_ota_start_received(void);
bool sig_back_up_is_completed_image(void);
slots:
void on_usb_dfu_enter(void);
void on_prf_ota_enter(void);
void on_uart_dfu_enter(void);
void on_image_load_enter(void);
连接信号和槽
typedef void (slot_handler_t)(void);
typedef void (signal_handler_t)(void);
void connect(uint8_t priority, signal_handler_t signal, slot_handler_t slot);
事件检测流程
/* when checking backup image is valid, the on_image_load_enter function will be handled */
ss_connect(0, sig_back_up_is_completed_image, on_image_load_enter);
#if BOOT_FROM_UART
/* when detecting key1 down, the on_uart_dfu_enter function will be handled */
ss_connect(1, sig_key1_push_down, on_uart_dfu_enter);
#endif
#if BOOT_FROM_USB
/* when dectecting key2 down, the on_usb_dfu_enter function will be handled */
ss_connect(2, sig_key2_push_down, on_usb_dfu_enter);
#endif
#if BOOT_FROM_PRF_OTA
/* when receive a ota start packet, the on_prf_ota_enter function will be handled */
ss_connect(3, sig_ota_start_received, on_prf_ota_enter);
#endif
/* handle all of events related signal fuction*/
ss_events_handle();
/* recovery gpio status that you used to trigger signal */
sig_hardware_recovery();
事件检测是分为优先级的,这儿巧妙通过数组索引的流程实现了这个功能。之所以要分优先级,是因为流程的需要,例如备份区已经有了完整的代码,可能需要提前处理一下,处理完成过后也许就不需要升级了。
3.4 Backup dfu 模式¶
检测backup 区域固件的完整性, 决定是否搬移到image
4. uart 升级详解¶
升级的固件需要签名校验,默认 keil 编译的时候,在工程的同级目录Images下会自动生成 ndk_app.signed.bin
。 使用该功能依赖系统安装了 python 和 python 的库文件 numpy。如果系统已经安装 python,请执行下面的命令安装 numpy
python -m pip install numpy
4.1 检测并进入uart 升级模式¶
使能 uart dfu 功能,通过
BOOT_FROM_UART
宏进行使能编写 uart dfu 进入的 signal 函数,并将信号和槽连接,槽属于升级流程BootLoader已经支持,用户不需要修改。用户可以修改signal 函数。默认如下
#if BOOT_FROM_UART /* when detecting key1 down, the on_uart_dfu_enter function will be handled */ ss_connect(1, sig_key1_push_down, on_uart_dfu_enter); #endif /* user can implement a custom signal fucntion */ bool sig_key1_push_down(void) { GPIO_SetMode(P2, BIT0, GPIO_MODE_INPUT); GPIO_EnablePullupPath(P2, BIT0); for (uint16_t i = 0; i < 1000; i++) { if (P20 == 1) { return false; } } return true; }
下载BootLoader 和 应用程序,应用层程序需要配置 OTA_in_Bootloader 的模式
4.2 操作流程¶
1、烧录boot,在boot_config.c里面配置
#define BOOT_FROM_UART 1
2、当前工程比如是peripheral_hr的工程,需要使用uart升级到需要的工程,比如ble_central
3、使用工具SecureCRT进行升级
4、打开工具SecureCRT连接设备串口,串口波特率921600
5、把板卡上P20接GND,复位板卡,查看工具SecureCRT上log打印,一直输出CCCCCCCCCC
6、在工具SecureCRT的”传输”界面选择”发送Xmodem(N)”,选择待升级工程的文件,位于image路径下: ndk_app.signed.bin,文件开始传输
7、拔掉GND,复位设备,查看串口log,已经打印升级后的程序log;
5 USB dfu 升级详解¶
升级的固件需要签名校验,默认keil 编译的时候,在工程的同级目录 Images 下会自动生成 ndk_app.signed.bin
。 使用该功能依赖系统安装了 python 和 python 的库文件 numpy。如果系统已经安装 python,请执行下面的命令安装 numpy
python -m pip install numpy
5.1 检测并进入usb 升级模式¶
使能 usb dfu 功能,通过
BOOT_FROM_USB
宏进行使能编写 uart dfu 进入的 signal 函数,并将信号和槽连接,槽属于升级流程BootLoader已经支持,用户不需要修改。用户可以修改signal 函数。默认如下
#if BOOT_FROM_USB /* when dectecting key2 down, the on_usb_dfu_enter function will be handled */ ss_connect(2, sig_key2_push_down, on_usb_dfu_enter); #endif /* user can implement a custom signal fucntion */ bool sig_key2_push_down(void) { GPIO_SetMode(P2, BIT1, GPIO_MODE_INPUT); GPIO_EnablePullupPath(P2, BIT1); for (uint16_t i = 0; i < 1000; i++) { if (P21 == 1) { return false; } } return true; }
下载BootLoader 和应用程序,应用层程序需要配置 OTA_in_Bootloader 的模式
5.2 操作流程¶
1、烧录boot,在boot_config.c里面配置
#define BOOT_FROM_USB 1
2、当前工程比如是peripheral_hr的工程,需要使用USB升级到需要的工程,比如ble_central
3、使用SDK的05_TOOLS里面的工具箱工具pan107xToolBox V0.0.00x进行升级
4、打开工具pan107xToolBox V0.0.00x,选择”显示”>”DFU”,连接设备USB口
5、把板卡上P21接GND,复位设备,查看工具pan107xToolBox V0.0.00x识别USB口
6、在工具程序设置那里选择”添加程序”>”加载程序”,选择待升级工程的文件,位于image路径下:ndk_app.signed.bin,注意地址需要从0x41000开始
7、程序加载好之后,点击”开始下载”即可
8、拔掉GND线,复位设备,查看串口log,已经打印升级后的程序log
6 PRF ota升级详解¶
1、打开工具Panchip 2.4G OTA V0.0.002.exe,选择2.4g dongle对应的串口,具体设置如下图所示:
2、上位机的使用说明参考上位机的帮助文档。
note:多设备升级不进行校验,不能确保每个设备都能升级成功。有些设备如果升级不成功需要重新升级。