SDAA362 June   2026 TDA4VE-Q1

 

  1.   1
  2.   Abstract
  3.   Trademarks
  4. 1Introduction
  5. 2Runtime Code Overlay Background
    1. 2.1 Memory Architecture of TDA4x
    2. 2.2 Challenges of Static Code Allocation
    3. 2.3 Why Runtime Code Overlay?
  6. 3Runtime Code Overlay Methodology
    1. 3.1 Overview
    2. 3.2 Resident Runtime
    3. 3.3 Overlay Payload package
    4. 3.4 Shared SRAM Overlay Region
    5. 3.5 Runtime Overlay Sequence
  7. 4Runtime Code Overlay Architecture
    1. 4.1 Software Architecture
    2. 4.2 Overlay Package Format
    3. 4.3 Memory Layout
    4. 4.4 Runtime Image Loading
    5. 4.5 Runtime Execution
  8. 5Demo Implementation
    1. 5.1 Software Organization
    2. 5.2 Overlay SRAM Configuration
    3. 5.3 Payload Generation
    4. 5.4 Payload Loading and Execution
    5. 5.5 Build Configuration
  9. 6Runtime Code Overlay Verification
    1. 6.1 PayloadA Execution
    2. 6.2 PayloadB Execution
    3. 6.3 PayloadC Execution
    4. 6.4 Shared SRAM Overlay Slot Reuse
    5. 6.5 Complete Runtime Verification
  10. 7Summary
  11. 8References

Payload Loading and Execution

The runtime overlay framework loads executable payloads from eMMC FATFS into a shared SRAM overlay slot. The loading process is implemented by the BootApp_emmcOverlayLoadAndRun() function.

The loader first reads and validates the overlay package header. The shared SRAM overlay slot is then cleared and the executable payload image is copied from the package file into the overlay execution region.

After the payload image has been loaded into SRAM, execution is performed by the BootApp_emmcOverlayExecute() function. Once execution is complete, the payload returns control to the resident boot_app runtime. The same SRAM overlay slot can then be reused for another payload package.

Below is a code snippet related to payload loading and execution.

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;
}