使用WCH的BackupUpgrade_OTA例程进行OTA升级时程序始终是在A区运行程序的,B区只是做个中转用来存放升级文件,这样的好处是用于升级的程序好管理,只需要A区起始地址的升级文件即可,若需在B区也可以运行则需B区起始地址的升级文件。

那么下面就讲解下如何实现AB区来回交替升级:

一.BackupUpgrade_JumpIAP例程无需修改,其实现的功能是跳转到BackupUpgrade_IAP;

二.BackupUpgrade_IAP 需做简单的修改,其功能原先是读取dataflash标志为升级标志时将B区文件拷贝到A区然后跳转A区,现在需修改为根据dataflash标志直接跳转A区或B区;

#define jumpApp_imageA    ((void (*)(void))((int *)IMAGE_A_START_ADD))
#define jumpApp_imageB    ((void (*)(void))((int *)IMAGE_B_START_ADD))

void jump_APP(void)
{
    if(CurrImageFlag == IMAGE_A_FLAG)
    {
    jumpApp_imageA();
    }

    if(CurrImageFlag == IMAGE_B_FLAG)
    {
    jumpApp_imageB();
    }
}

三.BackupUpgrade_OTA imageA

1.将例程中的3处地址偏移屏蔽,因为B区升级文件的起始地址为0x37000为220k,hex文件的偏移地址已在OpAdd体现无需偏移,使用bin文件时需收到填入地址0x37000(B区起始地址)或0x1000(A区起始地址)

//OpAdd += IMAGE_A_SIZE;

2.编程程序后原先是修改DataFlash切换至IAP FLAG,需修改为B区FLAG方便IAP进行跳转;

        /* 编程结束 */
        case CMD_IAP_END:
        {
            PRINT("IAP_END \r\n");

            /* 当前的是ImageA */
            /* 关闭当前所有使用中断,或者方便一点直接全部关闭 */
            DisableAllIRQ();

            /* 修改DataFlash,切换至ImageB */
            SwitchImageFlag(IMAGE_B_FLAG);

            /* 等待打印完成 ,复位*/
            mDelaymS(10);
            SYS_ResetExecute();

            break;
        }

3.在手机APP软件获取INFO时默认上报的是send_buf[0] = IMAGE_B_FLAG;此处可根据需求进行修改,决定了手机APP可以从imageA或imageB文件夹选择文件;

        case CMD_IAP_INFO:
        {
            uint8_t send_buf[20];

            PRINT("IAP_INFO \r\n");

            /* IMAGE FLAG */
            send_buf[0] = IMAGE_B_FLAG;

            /* IMAGE_SIZE */
            send_buf[1] = (uint8_t)(IMAGE_SIZE & 0xff);
            send_buf[2] = (uint8_t)((IMAGE_SIZE >> 8) & 0xff);
            send_buf[3] = (uint8_t)((IMAGE_SIZE >> 16) & 0xff);
            send_buf[4] = (uint8_t)((IMAGE_SIZE >> 24) & 0xff);

            /* BLOCK SIZE */
            send_buf[5] = (uint8_t)(FLASH_BLOCK_SIZE & 0xff);
            send_buf[6] = (uint8_t)((FLASH_BLOCK_SIZE >> 8) & 0xff);

            send_buf[7] = CHIP_ID&0xFF;
            send_buf[8] = (CHIP_ID>>8)&0xFF;
            /* 有需要再增加 */

            /* 发送信息 */
            OTA_IAP_SendData(send_buf, 20);

            break;
        }

四.BackupUpgrade_OTA_imageB

1.将例程中的3处地址偏移屏蔽,因为A区升级文件的起始地址为0x1000为4k,hex文件的偏移地址已在OpAdd体现无需偏移,使用bin文件时需收到填入地址0x37000(B区起始地址)或0x1000(A区起始地址)

//OpAdd += IMAGE_A_SIZE;

2.编程程序后原先是修改DataFlash切换至IAP FLAG,需修改为A区FLAG方便IAP进行跳转;

        /* 编程结束 */
        case CMD_IAP_END:
        {
            PRINT("IAP_END \r\n");

            /* 当前的是ImageB */
            /* 关闭当前所有使用中断,或者方便一点直接全部关闭 */
            DisableAllIRQ();

            /* 修改DataFlash,切换至ImageA */
            SwitchImageFlag(IMAGE_A_FLAG);

            /* 等待打印完成 ,复位*/
            mDelaymS(10);
            SYS_ResetExecute();

            break;
        }

3.在手机APP软件获取INFO时默认上报的是send_buf[0] = IMAGE_A_FLAG;此处可根据需求进行修改,决定了手机APP可以从imageA或imageB文件夹选择文件;     

        case CMD_IAP_INFO:
        {
            uint8_t send_buf[20];

            PRINT("IAP_INFO \r\n");

            /* IMAGE FLAG */
            send_buf[0] = IMAGE_A_FLAG;

            /* IMAGE_SIZE */
            send_buf[1] = (uint8_t)(IMAGE_SIZE & 0xff);
            send_buf[2] = (uint8_t)((IMAGE_SIZE >> 8) & 0xff);
            send_buf[3] = (uint8_t)((IMAGE_SIZE >> 16) & 0xff);
            send_buf[4] = (uint8_t)((IMAGE_SIZE >> 24) & 0xff);

            /* BLOCK SIZE */
            send_buf[5] = (uint8_t)(FLASH_BLOCK_SIZE & 0xff);
            send_buf[6] = (uint8_t)((FLASH_BLOCK_SIZE >> 8) & 0xff);

            send_buf[7] = CHIP_ID&0xFF;
            send_buf[8] = (CHIP_ID>>8)&0xFF;
            /* 有需要再增加 */

            /* 发送信息 */
            OTA_IAP_SendData(send_buf, 20);

            break;
        }

4.在B区往A区升级时擦除判断需按照如下修改,因为A区边界和B区边界不同;

        /* 擦除 -- 蓝牙擦除由主机控制 */
        case CMD_IAP_ERASE:
        {
            OpAdd = (uint32_t)(iap_rec_data.erase.addr[0]);
            OpAdd |= ((uint32_t)(iap_rec_data.erase.addr[1]) << 8);
            OpAdd = OpAdd * 16;

            // OpAdd += IMAGE_A_SIZE;

            EraseBlockNum = (uint32_t)(iap_rec_data.erase.block_num[0]);
            EraseBlockNum |= ((uint32_t)(iap_rec_data.erase.block_num[1]) << 8);
            EraseAdd = OpAdd;
            EraseBlockCnt = 0;

            /* 检验就放在擦除里清0 */
            VerifyStatus = 0;

            PRINT("IAP_ERASE start:%08x num:%d\r\n", (int)OpAdd, (int)EraseBlockNum);

            if(EraseAdd < IMAGE_A_START_ADD || (EraseAdd + (EraseBlockNum - 1) * FLASH_BLOCK_SIZE) > IMAGE_B_START_ADD)
            {
                OTA_IAP_SendCMDDealSta(0xFF);
            }
            else
            {
                /* 启动擦除 */
                tmos_set_event(Peripheral_TaskID, OTA_FLASH_ERASE_EVT);
            }
            break;
        }

...

posted on 2026-07-21 14:18  WCH蓝牙应用分享  阅读(4)  评论(0)    收藏  举报