In this lesson, you will learn how to prevent system crashes by properly managing CPU interrupts while performing sensitive In-Application Programming (IAP) flash memory writes.
The Collision Problem
When your processor is busy executing a flash write operation, the flash memory controller is often "locked." During this state, the memory is typically inaccessible for instruction fetches. If a hardware interrupt occurs during this time, the CPU will attempt to jump to the Interrupt Service Routine (ISR) defined in the vector table. If that vector table or the ISR code itself resides in the same flash bank being modified—or if the flash controller is in a state where it cannot serve fetch requests—the CPU will trigger a hard fault, crashing the system.
Implementing Critical Sections
To avoid this, you must treat flash programming as a "critical section." Before triggering the write, you must disable interrupts to ensure the CPU remains exclusively focused on the programming sequence.
Here is a conceptual implementation of how to wrap your flash write operation:
void write_flash_safely(uint32_t address, uint8_t *data) {
// 1. Disable interrupts to prevent context switching
uint32_t primask = __get_PRIMASK();
__disable_irq();
// 2. Perform the sensitive write operation
// This function should ideally be executed from RAM
flash_controller_write(address, data);
// 3. Restore previous interrupt state
if (!primask) {
__enable_irq();
}
}
Critical Best Practices
- Execute from RAM: Even with interrupts disabled, the CPU still needs to fetch the instructions for the write operation. If your flash controller blocks all access during a write, you must use a linker attribute to place your flash-writing functions into RAM (e.g.,
__attribute__((section(".ramfunc")))). - Minimize Latency: Because you have disabled interrupts, your system is effectively "blind" to external events. Keep your flash write routines as short as possible, or use a background polling mechanism if the hardware supports it.
- Vector Relocation: Ensure your vector table is relocated to RAM if the programming process modifies the sector containing the original vector table.
Key Takeaway: To ensure stability during IAP, you must disable interrupts and ensure the execution code resides in RAM to prevent the CPU from attempting to fetch instructions from a locked flash memory bank.