Hi everyone.
I've implemented kind of simple FW updater.
The purpose is to copy FW from flash (0x0 address, no MBR or SoftDevice) to RAM buffer on node1.
than send this FW to node2 by a couple of packets via ESB.
After receive all FW data, execute FW updater (copy received FW from RAM to 0x0 same address FLASH via RAM function).
Flash copy procedure is ok and works on writing to some other address (0x5000 for example).
But when I execute it on 0x0 address my device becomes bricked...
Here is the source code:
#define FW_FLASH_START 0x0 #define RAM_START 0x20009000 //FW copy function type typedef void (*update_fw_proc)(uint32_t dest, uint8_t *src, uint32_t size); //FW copy function void fw_copy_flash(uint32_t dest, uint8_t *src, uint32_t size) { int i; int pagesNum = FW_DATA_MAX_SIZE / NRF_FICR->CODEPAGESIZE; __disable_irq(); //erase number of pages needed for (i = FW_START_PAGE; i < 80; i++) { // Enable erase. NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een; __ISB(); __DSB(); // Erase the page NRF_NVMC->ERASEPAGE = i * NRF_FICR->CODEPAGESIZE; while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {;} NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren; __ISB(); __DSB(); } //write to flash for (i = 0; i < size; i++) { uint32_t byte_shift = (dest + i) & (uint32_t)0x03; uint32_t address32 = (dest + i) & ~byte_shift; // Address to the word this byte is in. uint32_t value32 = (*(uint32_t*)address32 & ~((uint32_t)0xFF << (byte_shift << (uint32_t)3))); value32 = value32 + ((uint32_t)src[i] << (byte_shift << 3)); // Enable write. NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos); __ISB(); __DSB(); *(uint32_t*)address32 = value32; while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {;} NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos); __ISB(); __DSB(); } //reset board __DSB(); SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | SCB_AIRCR_SYSRESETREQ_Msk ); __DSB(); for(;;) { __NOP(); } } //execute FW update (place FW copy function to RAM and execute it) void execute_fw_update(uint8_t* fwData, uint32_t fwSize) { update_fw_proc updater = (update_fw_proc) (RAM_START + 1); uint32_t src = (uint32_t)fw_copy_flash; memcpy((void*)RAM_START, (void*)(src & ~1), FW_FLASH_FUNC_SIZE); __dsb(0xf); __isb(0xf); (updater)(FW_FLASH_START, fwData, fwSize); }
What am I doing wrong?
Kind regards.
Ivan.