Setting GPNVM bits while running from bank 1

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?

I don't see your functions running from SRAM, I am pretty sure they should.

I changed it because I thought that was the problem. It was not. I have returned things to the way they were, like this:

/**
 * @brief Resets the device after setting gpnvm bits.
 * 
 */
__attribute__ ((long_call, section (".ramfunc")))
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 problem still remains.

Post the most basic full sketch that shows the issue.

Unfortunately, I can't share my code, as basic as it is. It basically copies the contents of an exported bin file from the arduino ide over from the upper half of bank 1 to the beginning of bank 0 (after clearing bank 0). It does so successfully, as I have confirmed the contents with a debugger (ATMEL-ICE) and with SHA256 validation post copy, so I know the contents of bank 0 are identical to that exported bin file. Still, it hangs upon clearing gpnvm bit 2 just before resetting.