This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] CC2642R-Q1:根据 RAM 代码执行任务期间的运行时 BIM/CCFG 复制

Guru**** 2647835 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/1582651/cc2642r-q1-runtime-bim-ccfg-copy-during-task-execution-from-ram-code

器件型号:CC2642R-Q1


大家好:

我希望获得以下运行时闪存复制方法的专家反馈 安全可靠 在上 CC26x2 正常工作条件下的器件系列(假设没有意外复位或功率损耗)。


目标

我们的目标是复制更新的 BIM 映像 CCFG 区域、并进行了更新 证书块 、从闪存0x34000 () 中的临时暂存区域到其最终目的地0x54000–0x57FFF ()、由触发 CAN 消息 至关重要。


系统环境

  • 器件: TI CC26x2 (运行 TI-RTOS)

  • 使用 TI 执行的闪存操作 闪存 API (driverlib)

  • 暂存区0x34000–0x35FFF () 是由之前编写的 OTA 更新 即用型二进制映像。

  • 该结构如下:

    • 0x34000→证书页

    • 0x35000→新的 BIM + CCFG 映像

  • 最终目的地:

    • 0x54000T Ü V→(最终副本)

    • 0x56000→BIM + CCFG(最终副本)

  • 为何种保护 不会 在此过程中为 BIM/CCFG 区域启用。


代码概述

此函数在运行时由 CAN 消息触发。
到目前为止、它已成功运行、没有出现错误或意外行为。

uint8_t res = copyBimToFinal(true);

__attribute__((section(".ti_ram_code")))
bool copyBimToFinal(bool isTaskRunning)
{
    uint8_t* src = (uint8_t*)0x34000;
    uint8_t* dst = (uint8_t*)0x54000;
    uint32_t i;
    uint32_t dataBuf[32]; // 128-byte buffer

    UInt key = Hwi_disable();
    if (isTaskRunning)
        Task_disable();

    // 1. Erase destination pages (including CCFG)
    if (FlashSectorErase(0x54000) != FAPI_STATUS_SUCCESS)
        return false;
    if (FlashSectorErase(0x56000) != FAPI_STATUS_SUCCESS)
        return false;

    // 2. Copy in 128-byte chunks
    for (i = 0; i < 0x4000; i += sizeof(dataBuf))
    {
        uint32_t j;
        for (j = 0; j < sizeof(dataBuf); j++)
        {
            ((uint8_t*)dataBuf)[j] = src[i + j];
        }

        if (FlashProgram((uint8_t*)dataBuf, (uint32_t)(dst + i), sizeof(dataBuf)) != FAPI_STATUS_SUCCESS)
            return false;
    }

    for (i = 0; i < 100000; i++) {} // Small delay

    if (isTaskRunning)
        Task_enable();
    Hwi_restore(key);

    return true;
}

根据将该函数放入 RAM 中:

.ti_ram_code : {
    *(.ti_ram_code)
} > SRAM

设计原理

在擦除和编程操作期间、CC26x2 上的闪存操作会阻止 CPU 访问闪存、因此该函数被显式移动至 RAM 以避免指令提取冲突。

此外:

  • hwi_disable() task_disable () 在编程期间防止闪存访问或抢占系统其他器件。

  • 所有操作都按顺序(擦除→编程)小块完成、以尽可能减少内存使用。


问题

在这些条件下(正常运行,无电源故障场景)、是否考虑了此方法 安全且合规 是否满足 TI 的闪存编程要求?

具体来说:

  1. 有任何问题 隐藏风险 暂时禁用其他任务时、如何在运行时从 RAM 执行此代码?

  2. TI 是否建议使用 额外同步 在多任务 RTOS 环境中从 RAM 执行闪存操作时、是否有预防措施?

  3. 是这样 首选方法 动态更新 BIM 和 CCFG 区域(无需重新启动到专用引导加载程序上下文)?

目前、这种实施在实践中运行良好、没有发现崩溃、验证失败或闪存损坏、但我想从架构的角度确认其正确性和潜在的限制。


感谢您提供任何见解、文档参考或示例。

此致、
Yusuf Ünlü ó n

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [quote userid=“567097" url="“ url="~“~/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/1582651/cc2642r-q1-runtime-bim-ccfg-copy-during-task-execution-from-ram-code
    • 暂存区0x34000–0x35FFF () 是由之前编写的 OTA 更新 即用型二进制映像。

    • 该结构如下:

      • 0x34000→证书页

      • 0x35000→新的 BIM + CCFG 映像

    [/报价]

    中的分段区域 0x34000 至 0x37FFF OTA 更新提前准备为准备好运行的二进制映像。

    存储器布局如下:

    • 0x34000–0x35FFF: 证书页面

    • 0x36000–0x37FFF: BIM 和 CCFG 映像

    注意:原始对 0x35000 的引用不正确;BIM + CCFG 区域从 0x36000 开始。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好:

    感谢您对问题的详细解释。

    我有几个建议。

    FlashProgram API 为低级、NVS【非易失性存储驱动程序接口】为高级/线程安全 API。

    NVS 在内部管理必要的闪存操作、NVS API 也使用 FlashProgram API。

    在我们的示例中、如果系统使用 RTOS、我们使用 NVS;对于非 RTOS 系统、我们使用 FlashProgram API。

    在本例中、可以运行 flash_init->flash_open->write_flash->flash_close

    这也将验证写入的字节。 否则,块处理看起来对我很好。

    在 syscfg->NVS->Add flash regions 和 size 中

    静态 bool isOpen = false;
    静态 NVS_handle nvsHandle;
    静态 NVS_Attrs regionAttrs;
    静态 NVS_Params nvsParams;

    void flash_init(void)
    {
    NVS_init();
    NVS_Params_init(&nvsParams);
    }

    bool flash_open(void)
    {
    if (!isOpen)
    {
        nvsHandle = NVS_open(CONFIG_NVSINTERNAL1, &nvsParams);
        if (nvsHandle != NULL)
        {
            isOpen = true;
            // Also read the region's attribute
            NVS_getAttrs(nvsHandle, &regionAttrs);
        }
    }
    
    return (isOpen);
    }

    void flash_close(void)
    {
    if (isOpen)
    {
    NVS_close(nvsHandle);
    isOpen = false;
    }
    }

    uint8_t writeFlash(uint_least32_t addr, uint8_t *pBuf, size_t len)
    {
    uint8_t flashStat = FLASH_FAILURE;
    if(isOpen)
    {
    if(NVS_write(nvsHandle, addr, pBuf, len, NVS_WRITE_PRE_VERIFY | NVS_WRITE_POST_VERIFY)
    == NVS_STATUS_SUCCESS)
    {
    flashStat = FLASH_SUCCESS;
    }
    }
    return (flashStat);
    }

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好:

    感谢您的详细说明和建议。

    实际上,我最初尝试使用基于 NVS 的方法,如你所描述的—调用flash_init -> flash_open -> write_flash -> flash_close.
    它非常适合我系统中的其他闪存区域、但出于某种原因、每当我尝试使用此方法修改 BIM/CCFG 区域时、电路板都会冻结并无响应。

    我尚未确定这种行为的根本原因,因此我实施了问题中所述的当前方法 — 将复制函数完全移动到 RAM 中并直接执行闪存 API 操作。

    从您的角度来看、除了缺少的“验证写入字节“步骤之外、此基于 RAM 的实现中是否存在任何技术风险或错误?
    到目前为止、它在我的所有测试中都稳定可靠、但我想确保它在架构上合理并符合 TI 的最佳实践。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我可以看到、在您的情况下、似乎使用的闪存 API 是合理的。

    另一个良好的做法可以是处理潜在的 erros。

    例如、将 malloc 用于 dataBuf、   

     size_t bufferSize = 32 * sizeof(uint32_t);
    
        // 2. Allocate the memory using malloc.
        // The result is cast to a pointer of the correct type (uint32_t*).
        uint32_t* dataBuf = (uint32_t*)malloc(bufferSize);
    
        // 3. Check if the allocation was successful.
        if (dataBuf == NULL) {
            // If malloc fails, it returns NULL.
            fprintf(stderr, "Memory allocation failed!\n");
            return 1; // Exit with an error code
        }


    Use memcpy_s instead of for(j) loop and check memcpy_s return on each iteration.