本帖最后由 yibin_cai 于 2021-3-9 14:25 编辑
Roy_LDH 发表于 2021-3-8 14:18 谢谢你的建议,这个建议我有想到过,但是我的客户想在下位机固件去避免因选错.bin文件的问题; 目前我 ...
在进行真正的固件数据传输之前,
发送端会通过 new image characteristic 发送新固件信息:image base(新固件地址), image size
我们可以判断 image base 所在的区域的标志位,如果是 OTA_VALID_TAG,说明新固件所属区域和本地固件所在区域冲突了,
判断方式如下:
void OTA_Write_Request_CB(uint16_t connection_handle,
uint16_t attr_handle,
uint8_t data_length,
uint8_t *att_data)
{
tBleStatus ret;
uint16_t k;
conn_handle = connection_handle;
if (attr_handle == (btlNewImageCharHandle + 1)){
erase_flash_done = 0;
ota_service_is_disconnected=0;
/* Incoming write characteristic to allow master to specify the base address and size
* of the firmware image it intends to send.
* Get base_address and image size + notification range requested from client.
*/
imageSize = (uint32_t)(att_data[4] << 24) + (uint32_t)(att_data[3] << 16) + (uint32_t)(att_data[2] << 8) + att_data[1];
imageBase = (uint32_t)(att_data[8] << 24) + (uint32_t)(att_data[7] << 16) + (uint32_t)(att_data[6] << 8) + att_data[5];
notification_range = NOTIFICATION_INTERVAL(att_data[0]);
/* Check if the new image already exists */
uint32_t *ota_tag_value = (uint32_t *)(imageBase + OTA_TAG_VECTOR_TABLE_ENTRY_OFFSET);
if (*ota_tag_value == OTA_VALID_TAG)
{
PRINTF("Error! new image exists!\r\n");
}
你可以根据这个判断,选择把设备断开,或反馈错误信息等操作
进一步验证,这个思路不可行。。。
原因在于,image base,是由 firmware 给到 APP 的。再由 APP 下发下来的。并不能作为 fimware_low 和 firmare_high 的标识。即:
假设本地运行的是 firmware_low,则其会告知 APP 有效的升级地址是 firmare_high_address;
固件数据传输完成后,FLASH 两个区域都被填充了 firmare_low 固件。
reset_manager 会跳到 firmare_high_address 去执行 firmware_low,导致死机
firmware_low 和 firmware_high 在链接的时候被分配到了不同的地址
把 firmware_low 放到 flash_high 区域,会因为函数地址错乱导致程序跑飞
本质上,解决该问题的方法是要对 firmware_low 和 firmware_high 的 bin 文件添加一个标识符号,将两者区分开来。
8 楼给出了完整的解决方案