Flash 分区说明
目前 TuyaOS BLE SDK V3.9.0 For nRF52840 的 Flash 分区图如下:
上图中:
0x27000 ~ 0x77000 共 320KB 的区域是应用代码存储区。
0x77000 ~ 0xC7000 共 320KB 的区域是OTA代码存储区。
0xC7000 ~ 0xF4000 共 180KB 的区域是未使用区域,可以用于应用层数据存储。
0xF4000 ~ 0xF8000 共 16KB 的区域是涂鸦授权和配网信息存储区,不允许其他程序进行修改和占用。
其他黄色区域是 Nordic 官方 SDK 分配好的区域,其中包含:
4KB 的 MBR(Master Boot Record)程序引导区;
152KB 的 softdevice(蓝牙协议栈)区域;
8KB 的 bootloader 区域;
4KB 的 MBR 信息存储区域;
4KB 的 bootloader 信息存储区域;
Flash 分区调整方法
如果预分配的 application 区域不能满足应用开发需求,可以调整 application 区域的空间,由于 OTA 固件的可能大小跟 application 固件的可能大小是一样的,所以也需要同时调整 OTA 区域的空间。
从分区图中可以看到:unused 区域刚好位于 OTA 区域上方,所以我们只需要将 OTA 区域的起始地址和结束地址向后偏移即可。
具体操作步骤如下(假设将 application 区域由原来的 320KB 扩充到 400 KB):
(1)将 “\software\TuyaOS\vendor\nrf52840_ble\tuyaos\include\board.h” 文件中的
Code: Select all
#ifndef BOARD_FLASH_OTA_START_ADDR
#define BOARD_FLASH_OTA_START_ADDR (0x77000)
#endif
#ifndef BOARD_FLASH_OTA_END_ADDR
#define BOARD_FLASH_OTA_END_ADDR (0xC7000)
#endif
修改为:
Code: Select all
#ifndef BOARD_FLASH_OTA_START_ADDR
#define BOARD_FLASH_OTA_START_ADDR (0x8B000) // (0x77000)
#endif
#ifndef BOARD_FLASH_OTA_END_ADDR
#define BOARD_FLASH_OTA_END_ADDR (0xEF000) // (0xC7000)
#endif
(2)将 “\software\TuyaOS\vendor\nrf52840_ble\tuyaos\drivers\tkl_flash.c” 文件中的
Code: Select all
NRF_FSTORAGE_DEF(nrf_fstorage_t tkl_flash_fstorage) =
{
.evt_handler = ty_flash_fstorage_evt_handler,
.start_addr = (0x77000),
.end_addr = 0xF8000,
};
修改为:
Code: Select all
NRF_FSTORAGE_DEF(nrf_fstorage_t tkl_flash_fstorage) =
{
.evt_handler = ty_flash_fstorage_evt_handler,
.start_addr = (0x8B000), // 0x77000,
.end_addr = 0xF8000,
};
该步骤非必须,但是非常推荐修改,防止 Flash 相关接口修改 application 区域的代码。
(3)修改后的 Flash 分区图为:
(4)基于 TuyaOS BLE SDK V3.9.0 For nRF52840 修改完成后使用以下方式已经测试成功
测试使用的步骤如下:
a. 烧录 3.9.0 版本的固件,固件运行成功;
b. 将固件版本从 3.9.0 OTA 升级到 3.9.1(文件名和固件实际版本 “FIRMWARE_VERSION” 都为 3.9.1),OTA 成功,固件运行成功,检测固件版本号为 3.9.1;
c. 将固件版本从 3.9.1 OTA 升级到 9.9.9(文件名修改为9.9.9,用于触发手机 App 启动 OTA 过程,固件实际版本 “FIRMWARE_VERSION” 为 3.9.0),OTA 成功,固件运行成功,检测固件版本号为 3.9.0,该方法可用于循环 OTA 测试;
其他说明
bootloader 不需要修改的原因:
查看 “\software\TuyaOS\vendor\nrf52840_ble\tuyaos\drivers\tkl_ota.c” 文件中的:
Code: Select all
OPERATE_RET tkl_ota_end_notify(BOOL_T reset)
{
OPERATE_RET ret = OPRT_OK;
if (sg_firmware_len > BOARD_FLASH_OTA_SIZE) {
return 1;
}
if ((sg_data_crc32 != tkl_ota_get_crc32_in_flash(sg_firmware_len))
|| (sg_data_crc32 != *(tkl_ota_pri_param->p_firmware_crc32))) {
return 2;
}
if (reset == TRUE) {
memset(&s_dfu_settings, 0, SIZEOF(nrf_dfu_settings_t));
s_dfu_settings.bank_1.image_crc = sg_data_crc32;
s_dfu_settings.bank_1.image_size = sg_firmware_len;
s_dfu_settings.bank_1.bank_code = NRF_DFU_BANK_VALID_APP;
memset(&s_dfu_settings.progress, 0, SIZEOF(dfu_progress_t));
s_dfu_settings.write_offset = 0;
s_dfu_settings.progress.update_start_address = BOARD_FLASH_OTA_START_ADDR; // Here
nrf_dfu_settings_write_and_backup((nrf_dfu_flash_callback_t)tkl_ota_setting_write_complete_cb);
} else {
s_dfu_settings.bank_1.image_crc = 0;
s_dfu_settings.bank_1.image_size = 0;
s_dfu_settings.bank_1.bank_code = 0;
memset(&s_dfu_settings.progress, 0, SIZEOF(dfu_progress_t));
s_dfu_settings.write_offset = 0;
s_dfu_settings.progress.update_start_address = 0;
// memset(&s_dfu_settings, 0, SIZEOF(nrf_dfu_settings_t));
nrf_dfu_settings_write_and_backup(NULL);
}
return ret;
}
可知:
修改后的 “BOARD_FLASH_OTA_START_ADDR” 的值通过 nrf_dfu_settings_write_and_backup 接口存储到 “bootloader settings” 区域,当下一次 bootloader 运行时会获取到该值,就可以找到 OTA 固件的位置;