当前文档版本为 NDK-v0.7.0,您可以访问当前页面的 开发中 版本以获取最近可能的更新。

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 区域。

使用该功能的步骤

  1. 编译下载 BootLoader 的程序,程序位置为 ndk\pan107x_mcu_boot 或者 ndk\pan108x_mcu_boot,选择那个BootLoader 取决于你的芯片版本。

  2. 修改应用程序的配置 (1)使能CONFIG_OTA_IN_BOOTLOADER,如下图所示 (2)修改 image flash 区域的大小或者 user flash 区域的大小(optional),如下图所示

注意:

CONFIG_IMAGE_EXTENDED_SIZECONFIG_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 支持的升级的方法

  1. USB dfu 模式:107 芯片支持,108 芯片待支持

  2. UART dfu 模式:107 和108 芯片均支持

  3. PRF OTA 模式:待支持

2.1.3 ota in APP

默认OTA 的升级流程是在APP 完成的,相比于 ota in BootLoader 他主要兼容 smp 的蓝牙升级,同时意味着付出了 image flash size <= 220K 的代价。

使用该功能的步骤

  1. 编译下载 BootLoader 的程序,程序位置为 ndk\pan107x_mcu_boot 或者 ndk\pan108x_mcu_boot,选择那个BootLoader 取决于你的芯片版本。

  2. 修改应用程序的配置 (1)禁止CONFIG_OTA_IN_BOOTLOADERCONFIG_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.1 USB dfu 模式

void on_usb_dfu_enter(void);

进入 dfu 过后,107写寄存器进入 ROM 模式,108 需要自己实现

3.2 UART dfu 模式

void on_uart_dfu_enter(void);

进入 dfu 过后,会采用xmodem 协议进行OTA升级

3.3 PRF OTA 模式

void on_prf_ota_enter(void);

待ota设备复位进入 ota状态,firmware通过2.4g dongle发送给待ota设备

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 升级模式

  1. 使能 uart dfu 功能,通过BOOT_FROM_UART宏进行使能

  2. 编写 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;
    }
    
  3. 下载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

img

PAN107x UART DFU进入升级模式

6、在工具SecureCRT的”传输”界面选择”发送Xmodem(N)”,选择待升级工程的文件,位于image路径下: ndk_app.signed.bin,文件开始传输

img

PAN107x UART DFU传输文件

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 升级模式

  1. 使能 usb dfu 功能,通过BOOT_FROM_USB宏进行使能

  2. 编写 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;
    }
    
  3. 下载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口

img

PAN107x USB DFU识别usb口

6、在工具程序设置那里选择”添加程序”>”加载程序”,选择待升级工程的文件,位于image路径下:ndk_app.signed.bin,注意地址需要从0x41000开始

7、程序加载好之后,点击”开始下载”即可

img

PAN107x USB DFU升级成功

8、拔掉GND线,复位设备,查看串口log,已经打印升级后的程序log

6 PRF ota升级详解

1、打开工具Panchip 2.4G OTA V0.0.002.exe,选择2.4g dongle对应的串口,具体设置如下图所示:

image

PAN107x PRF OTA上位机

2、2.4g dongle通过j-flash烧录固件“prf_ota_client.hex”,固件在上位机的帮助里可以下载。2.4g dongle可以向我司业务申请。

3、上位机的使用说明参考上位机的帮助文档。

note:多设备升级不进行校验,不能确保每个设备都能升级成功。有些设备如果升级不成功需要重新升级。