Reputation: 1
So the main question is can I update the program flash while code is running?
I am able to receive a new binary over tcp and save it to the second half of the flash. I want now to copy it to the first half so that it runs after next reboot.
I know this approach has the risk of bricking the board if there are any issues during the copy, and a long term approach should use a 2 stage bootloader or similar, but for now this would be a quick way of doing it.
I found conflicting information regarding if you can or not write over an area of flash that is being executed, but I understood that if the code that does the copy is run from RAM this should be possible.
The following code attempts to do this but only writes two sectors and then freezes. Is there an error in it of this is just not possible due to the reasons mentioned?
The output of the program is:
Position written 0 out of 1048576
Position written 4096 out of 1048576
Edit: read about issues with stopping interrupts when running code in second core, but have disabled that code and result is the same.
Tks
__attribute__((section(".ram_code"))) void copy_flash_to_zero(uint32_t source_address)
{
uint32_t flash_index = 0;
uint8_t led_counter=0;
uint32_t ints;
uint8_t buffer[FLASH_SECTOR_SIZE]; // Buffer to hold data
printf("Starting Flash update\n");
do
{
// Read data from the source address in flash into the buffer
memcpy(buffer, (const void *)(source_address + XIP_BASE + flash_index), FLASH_SECTOR_SIZE);
// Disable interrupts during flash operations to prevent issues
ints = save_and_disable_interrupts();
// Erase the flash sector at address zero plus bootloades offset (256 bytes)
flash_range_erase(flash_index, FLASH_SECTOR_SIZE);
// Write the buffer to flash address zero
flash_range_program(flash_index, buffer, FLASH_SECTOR_SIZE);
// Restore interrupts after flash operations
restore_interrupts(ints);
printf("position written %u out of %u\n", flash_index, FLASH_SIZE_BYTES / 2);
fflush(stdout); // Force flush the buffer
flash_index += FLASH_SECTOR_SIZE;
led_counter++;
} while (flash_index < FLASH_SIZE_BYTES / 2);
printf("Flash update complete. RebootingX\n", source_address, FLASH_ADDRESS_ZERO);
sleep_ms(2000);
watchdog_reboot(0, 0, 0);
}
I expected the code to run, reset the board and start running again. However the "Flash update complete" message never appears and the board hangs indefinitely.
Upvotes: 0
Views: 207
Reputation: 87396
The problem here is that the function you wrote is in RAM, but it calls many other functions (like memcpy
and printf
) which are most likely not in RAM, so your code will malfunction when those functions get overwritten. You also have interrupts enabled, and the interrupt service routines are probably in flash.
Upvotes: 0