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: Runtime BIM/CCFG Copy During Task Execution from RAM Code

Part Number: CC2642R-Q1

 

Hello everyone,

 

I’d like to get expert feedback on whether the following runtime flash-copy approach is **safe and reliable** on the **CC26x2** device family under normal operating conditions (assuming no unexpected reset or power loss).

 

---

 

### **Goal**
We aim to copy an updated **BIM image** and **CCFG** region, as well as an updated **certificate block**, from a temporary staging area in flash (`0x34000`) to their final destinations (`0x54000–0x57FFF`), triggered by a **CAN message** during runtime.

 

---

 

### **System Context**
- Device: **TI CC26x2** (running TI-RTOS)
- Flash operations performed using TI **Flash API (driverlib)**
- The staging area (`0x34000–0x35FFF`) is written earlier by **OTA update** as a ready-to-run binary image.
- The structure is as follows:
  - `0x34000` → Certificate page  
  - `0x35000` → New BIM + CCFG image  
- Final destinations:
  - `0x54000` → Certificate (final copy)
  - `0x56000` → BIM + CCFG (final copy)
- Write protection is **not** enabled for BIM/CCFG regions during this procedure.

 

---

 

### **Code Overview**

 

This function is triggered at runtime by a CAN message.  
It runs successfully so far without errors or unexpected behavior.

 

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

 

The function is placed into RAM using:

 

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

 

---

 

### **Design Rationale**
Because flash operations on CC26x2 block CPU access to flash memory during erase and program operations, this function is explicitly moved to **RAM** to avoid instruction fetch conflicts.

 

Additionally:
- **Hwi_disable()** and **Task_disable()** prevent flash access or preemption from other parts of the system during programming.
- All operations are done sequentially (erase → program) in small chunks to minimize memory use.

 

---

 

### **Question**
Under these conditions (normal operation, no power failure scenarios), is this approach considered **safe and compliant** with TI’s flash programming requirements?

 

Specifically:
1. Are there any **hidden risks** with executing this code from RAM during runtime while other tasks are temporarily disabled?
2. Does TI recommend any **additional synchronization** or precautions when performing flash operations from RAM in a multitasking RTOS environment?
3. Is this the **preferred approach** to update BIM and CCFG regions dynamically (without rebooting into a dedicated bootloader context)?

 

At present, this implementation works perfectly in practice — no crashes, verification failures, or flash corruption observed — but I would like to confirm its correctness and potential limitations from an architectural standpoint.

 

---

 

Thank you for any insights, documentation references, or examples you can provide.

 

Best regards,  
**Yusuf Ünlü**  


  • Hello,

    ### **Question**
    Under these conditions (normal operation, no power failure scenarios), is this approach considered **safe and compliant** with TI’s flash programming requirements?

     

    Specifically:
    1. Are there any **hidden risks** with executing this code from RAM during runtime while other tasks are temporarily disabled?
    2. Does TI recommend any **additional synchronization** or precautions when performing flash operations from RAM in a multitasking RTOS environment?
    3. Is this the **preferred approach** to update BIM and CCFG regions dynamically (without rebooting into a dedicated bootloader context)?

    I have reviewed your approach, but I must clarify that TI will not offer any guarantee in that what you have written. In other words, I can offer suggestions, recommendations, and some review, but as far as a statement as "This should and will work 100%" or "I have verified your approach, and it meets all requirements" is not something I'm comfortable stating. 

    Having said that, I can answer your questions to the best of my ability, as well as offer a few suggestions. I still recommend thorough testing of your implementation before using it in production (of course) and that you have verified that your solution behaves the way that you expect and any risks are identified and mitigated/accepted.

    Under these conditions (normal operation, no power failure scenarios), is this approach considered **safe and compliant** with TI’s flash programming requirements?

    Based on your code, I believe that the implementation is fine. I see that you are disabling hardware interrupts and disabling task preemption via Task_Disable, so that should disable software interrupts as well. You would not want to interrupt in the middle of a flashing sequence, especially for an OTA update. I believe the precautions you've taken in your implementation are fine. (I would double check that Task_Disable does disable software interrupts and suspends the scheduler though).

    1. Are there any **hidden risks** with executing this code from RAM during runtime while other tasks are temporarily disabled?

    No, there shouldn't be any hidden risks. 

    2. Does TI recommend any **additional synchronization** or precautions when performing flash operations from RAM in a multitasking RTOS environment?

    By disabling the task preemption, software interrupts, and hardware interrupts, then there should be no issues or additional synchronization needed. As long as nothing preempts this task and care is taken not be interrupted, then I think the implementation is fine.

    3. Is this the **preferred approach** to update BIM and CCFG regions dynamically (without rebooting into a dedicated bootloader context)?

    Modifying the CCFG regions dynamically should be avoided. However, you recognized that risk already:

    Under these conditions (normal operation, no power failure scenarios)

    The reason is that if there is a power loss scenario and you are in the middle of writing the CCFG to it's location in memory, you may potentially brick the device. Typically it would be better to have a static CCFG, or use the bootloader in order to make that change. Additionally, not write/erase protecting the CCFG has security implications that should be recognized.

    In summary, I believe the implementation is fine, but I still believe that thorough testing is required and that non-normal operations should be handled (power-loss scenario) or recognized. 

    Hope that helps!

    Best,

    Nima Behmanesh

  • Thank you for the detailed explanation and suggestions.

  • I updated my code it seems fine. it only updates the bim/ccfg area, the cert area is updated via keyrotation. Thank you for your support.


    __attribute__((section(".ti_ram_code")))
    bimUpdateFail_e copyBimToFinal(void)
    {
    bimUpdateFail_e ret = BIM_UPDATE_SUCCESS;

    uint8_t* src = (uint8_t*)0x34000;
    uint8_t* dst = (uint8_t*)0x56000;
    uint32_t i;
    uint32_t dataBuf[32];

    UInt hwKey = Hwi_disable();
    UInt taskKey = Task_disable();
    UInt swKey = Swi_disable();

    if (FlashSectorErase((uint32_t)dst) != FAPI_STATUS_SUCCESS)
    {
    ret = BIM_UPDATE_ERASE_FAIL;
    }
    else
    {
    for (i = 0; i < 0x2000; i += sizeof(dataBuf))
    {
    memcpy(dataBuf, src + i, sizeof(dataBuf));

    if (FlashProgram((uint8_t*)dataBuf, (uint32_t)(dst + i), sizeof(dataBuf)) != FAPI_STATUS_SUCCESS)
    {
    ret = BIM_UPDATE_PROGRAM_FAIL;
    break;
    }
    }

    if (ret == BIM_UPDATE_SUCCESS)
    {
    for (i = 0; i < 0x2000; i += sizeof(dataBuf))
    {
    if (memcmp(dst + i, src + i, sizeof(dataBuf)))
    {
    ret = BIM_UPDATE_VERFICATION_FAIL;
    break;
    }
    }
    }
    }
    Swi_restore(swKey);
    Task_enable();
    Hwi_restore(hwKey);
    return ret;
    }