所以主要问题是我可以在代码运行时更新程序闪存吗?
我能够通过 TCP 接收新的二进制文件并将其保存到闪存的后半部分。我现在想将其复制到前半部分,以便它在下次重新启动后运行。
我知道如果复制过程中出现任何问题,这种方法存在使电路板变砖的风险,长期方法应该使用 2 阶段引导加载程序或类似的方法,但就目前而言,这是一种快速的方法。
我发现关于是否可以写入正在执行的闪存区域的冲突信息,但我明白,如果执行复制的代码是从 RAM 运行,这应该是可能的。
以下代码尝试执行此操作,但仅写入两个扇区,然后冻结。由于上述原因,这是否是不可能的?
程序的输出是:
已写入 0 个位置(共 1048576 个)
已写入 4096 个位置(共 1048576 个)
编辑:阅读有关在第二个核心中运行代码时停止中断的问题,但已禁用该代码并且结果是相同的。
谢谢
__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);
}
我希望代码能够运行,重置开发板并再次开始运行。但是,“Flash 更新完成”消息永远不会出现,并且开发板无限期挂起。
这里的问题是,您编写的函数位于 RAM 中,但它调用了许多其他函数(如
memcpy
和 printf
),这些函数很可能不在 RAM 中,因此当这些函数被覆盖时,您的代码将出现故障。 您还启用了中断,并且中断服务例程可能位于闪存中。