ZHDA191 June   2026 TDA4VE-Q1

 

  1.   1
  2.   摘要
  3.   商标
  4. 1简介
  5. 2运行时代码覆盖后台
    1. 2.1 TDA4x 的存储器架构
    2. 2.2 静态代码分配的挑战
    3. 2.3 为什么选择运行时代码覆盖?
  6. 3运行时代码覆盖方法
    1. 3.1 概述
    2. 3.2 驻留运行时
    3. 3.3 覆盖有效载荷包
    4. 3.4 共享 SRAM 覆盖区域
    5. 3.5 运行时覆盖序列
  7. 4运行时代码覆盖架构
    1. 4.1 软件架构
    2. 4.2 覆盖包格式
    3. 4.3 存储器布局
    4. 4.4 运行时映像加载
    5. 4.5 运行时执行
  8. 5演示实现
    1. 5.1 软件组织
    2. 5.2 覆盖 SRAM 配置
    3. 5.3 有效载荷生成
    4. 5.4 有效载荷加载和执行
    5. 5.5 构建配置
  9. 6运行时代码覆盖验证
    1. 6.1 PayloadA 执行
    2. 6.2 PayloadB 执行
    3. 6.3 PayloadC 执行
    4. 6.4 共享 SRAM 覆盖槽重用
    5. 6.5 完整运行时验证
  10. 7总结
  11. 8参考资料

有效载荷加载和执行

运行时覆盖框架将可执行有效载荷从 eMMC FATFS 加载到共享的 SRAM 覆盖槽中。加载过程由 BootApp_emmcOverlayLoadAndRun() 函数实现。

加载器首先读取并验证覆盖包标头。然后,清除共享 SRAM 覆盖槽,并将可执行有效载荷映像从包文件复制到覆盖执行区域。

有效载荷映像加载到 SRAM 后,由 BootApp_emmcOverlayExecute() 函数执行。执行完成后,有效载荷会将控制权交还给驻留的 boot_app 运行时。然后,相同的 SRAM 覆盖槽可重复用于另一个有效载荷包。

下面是一个与有效载荷加载和执行相关的代码片段。

int32_t BootApp_emmcOverlayLoadAndRun(const char *payloadFile,
                                      BootApp_EmmcOverlayCtx *ctx)
{
    BootApp_EmmcOverlayPkgHeader hdr;
    int32_t status;
    void *slotBase = (void *)((uintptr_t)BOOTAPP_EMMC_OVERLAY_SLOT_BASE);

    if ((payloadFile == NULL) || (ctx == NULL))
    {
        return CSL_EBADARGS;
    }

    memset(&hdr, 0, sizeof(hdr));
    status = BootApp_emmcOverlayReadFile(payloadFile, 0U, &hdr, sizeof(hdr));
    if (status != CSL_PASS)
    {
        return status;
    }

    status = BootApp_emmcOverlayValidateHeader(payloadFile, &hdr);
    if (status != CSL_PASS)
    {
        return status;
    }

    memset(slotBase, 0, BOOTAPP_EMMC_OVERLAY_SLOT_SIZE);
    CacheP_wbInv(slotBase, BOOTAPP_EMMC_OVERLAY_SLOT_SIZE);

    status = BootApp_emmcOverlayReadFile(payloadFile,
                                         (uint32_t)sizeof(hdr),
                                         slotBase,
                                         hdr.codeSize);
    if (status != CSL_PASS)
    {
        return status;
    }

    UART_printf("emmc_overlay: loaded %s code=%u entryOffset=%u slot=0x%x\r\n",
                payloadFile,
                hdr.codeSize,
                hdr.entryOffset,
                (uint32_t)((uintptr_t)slotBase));

    status = BootApp_emmcOverlayExecute(slotBase, hdr.codeSize, hdr.entryOffset, ctx);
    return status;
}

static void BootApp_emmcOverlaySyncForExec(void *addr, uint32_t size)
{
    CacheP_wbInv(addr, size);
    CSL_armR5CacheInvalidateAllIcache();
    CSL_armR5Dsb();
    CSL_armR5Isb();
}

int32_t BootApp_emmcOverlayExecute(void *slotBase,
                                   uint32_t codeSize,
                                   uint32_t entryOffset,
                                   BootApp_EmmcOverlayCtx *ctx)
{
    uintptr_t entryAddr;
    BootApp_EmmcOverlayEntry entry;

    if ((slotBase == NULL) || (ctx == NULL) || (codeSize == 0U) || (entryOffset >= codeSize))
    {
        return CSL_EBADARGS;
    }

    BootApp_emmcOverlaySyncForExec(slotBase, codeSize);

    entryAddr = ((uintptr_t)slotBase) + ((uintptr_t)entryOffset);

    /* R5F executes Thumb code. Force bit[0] for function pointer call. */
    entryAddr |= (uintptr_t)0x1U;
    entry = (BootApp_EmmcOverlayEntry)entryAddr;

    UART_printf("emmc_overlay: execute entry=0x%x codeSize=%u entryOffset=%u\r\n",
                (uint32_t)entryAddr,
                codeSize,
                entryOffset);

    entry(ctx);

    CSL_armR5Dsb();
    CSL_armR5Isb();

    return CSL_PASS;
}