Hello all,
I have two separate programs, on bank 0 and bank 1.
When setting the GPNVM bits 1 and 2 from bank 0, I can successfully boot to bank 1 after resetting.
But when I set bit 1 and clear bit 2 of GPNVM while running from bank 1 the Arduino hangs, instead of moving to bank 0 again when resetting.
This mechanism is important for the OTA update of my system.
Here is the relevant code:
void setupForReboot()
{
__disable_irq();
flash_set_gpnvm(1);
flash_clear_gpnvm(2);
// Force a hard reset
const int RSTC_KEY = 0xA5;
RSTC->RSTC_CR =
RSTC_CR_KEY(RSTC_KEY) |
RSTC_CR_PROCRST |
RSTC_CR_PERRST;
while (true); //bye cruel world!
}
The same method above works when called from bank 0, with 2 set calls instead of one set and one clear.
Digging deeper into the method calls, I can't see where my program fails:
//flash_efc.cpp
/**
* \brief Clear the given GPNVM bit.
*
* \param ul_gpnvm GPNVM bit index.
*
* \return 0 if successful; otherwise returns an error code.
*/
uint32_t flash_clear_gpnvm(uint32_t ul_gpnvm)
{
if (ul_gpnvm >= GPNVM_NUM_MAX) {
return FLASH_RC_INVALID;
}
if (FLASH_RC_NO == flash_is_gpnvm_set(ul_gpnvm)) {
return FLASH_RC_OK;
}
if (EFC_RC_OK == efc_perform_command(EFC, EFC_FCMD_CGPB, ul_gpnvm)) {
return FLASH_RC_OK;
}
return FLASH_RC_ERROR;
}
//efc.cpp
/**
* \brief Perform the given command and wait until its completion (or an error).
*
* \note Unique ID commands are not supported, use efc_read_unique_id.
*
* \param p_efc Pointer to an EFC instance.
* \param ul_command Command to perform.
* \param ul_argument Optional command argument.
*
* \note This function will automatically choose to use IAP function.
*
* \return 0 if successful, otherwise returns an error code.
*/
uint32_t efc_perform_command(Efc *p_efc, uint32_t ul_command,
uint32_t ul_argument)
{
/* Unique ID commands are not supported. */
if (ul_command == EFC_FCMD_STUI || ul_command == EFC_FCMD_SPUI) {
return EFC_RC_NOT_SUPPORT;
}
/* Use IAP function with 2 parameters in ROM. */
static uint32_t(*iap_perform_command) (uint32_t, uint32_t);
uint32_t ul_efc_nb = (p_efc == EFC0) ? 0 : 1;
iap_perform_command =
(uint32_t(*)(uint32_t, uint32_t))
*((uint32_t *) CHIP_FLASH_IAP_ADDRESS);
iap_perform_command(ul_efc_nb,
EEFC_FCR_FKEY(FWP_KEY) | EEFC_FCR_FARG(ul_argument) |
EEFC_FCR_FCMD(ul_command));
return (p_efc->EEFC_FSR & EEFC_ERROR_FLAGS);
}
The above 2 methods are from DueFlashStorage library.
How can I properly move to bank 0 after reset?