2025-08-13 1:09 AM
We have a working production firmware for the STM32H7B3 that uses a Winbond W25Q01JVZEIM external flash using QSPI in memory-mapped mode to store data and assets for a TouchGFX and other applications.
Now, due to internal flash limitations, we are attempting to execute some code directly from the same external flash. As a starting point, we created a simple test function to run from external flash:
__attribute__((section("ExtFlashSection")))
void test_ext_flash_func(void) {
volatile int x = 1;
x++;
}
The rest of the application continues to run from internal flash. However, when this function is called, the MCU enters a continuous reboot loop. We have added Hard fault handler but couldn't see any prints for different register values.
Current Configuration
MEMORY
{
...
OSPI (xr) : ORIGIN = 0x93170000, LENGTH = 32M
}
SECTIONS
{
...
ExtFlashSection :
{
*(ExtFlashSection ExtFlashSection.*)
*(.gnu.linkonce.r.*)
. = ALIGN(0x4);
} > OSPI
}
void MPU_Config(void)
{
// Disable MPU
MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
// Configure Region 0 for QSPI external flash
MPU->RNR = 0; // Select Region 0
MPU->RBAR = 0x93170000; // Base address of QSPI flash
// Region size = 32MB → log2(32MB) = 25 → 0x19 << 1 = 0x32
MPU->RASR = (0x19 << MPU_RASR_SIZE_Pos) | // Size = 32MB
(0 << MPU_RASR_TEX_Pos) | // TEX = 0
(1 << MPU_RASR_C_Pos) | // Cacheable
(0 << MPU_RASR_B_Pos) | // Not bufferable
(0 << MPU_RASR_S_Pos) | // Not shareable
(3 << MPU_RASR_AP_Pos) | // Full access
(0 << MPU_RASR_XN_Pos) | // Executable
(1 << MPU_RASR_ENABLE_Pos); // Enable region
// Enable MPU with default memory map for privileged access
MPU->CTRL = MPU_CTRL_ENABLE_Msk | MPU_CTRL_PRIVDEFENA_Msk;
// Ensure MPU settings take effect
__DSB();
__ISB();
}
static void enableMemoryMappedMode( void ) // QPI mode only
{
OCTOSPI1->CR &= (~(OCTOSPI_CR_FMODE | OCTOSPI_CR_FTHRES));
OCTOSPI1->CR |= (OCTOSPI_CR_FMODE_1 | OCTOSPI_CR_FMODE_0);
OCTOSPI1->CCR = OSPI_COMM_CFG_CMD_ADDR_DATA;
OCTOSPI1->TCR = (FLASH_CFG_QPI_NO_OF_DUMMY_CLK << OCTOSPI_TCR_DCYC_Pos) | OCTOSPI_TCR_SSHIFT;
OCTOSPI1->IR = FLASH_CMD_FAST_READ_QPI;
}
OSPIDriverinit()
{
flashSendCMDNoData( FLASH_CMD_ENABLE_4B_ADDR_WB, true ); // Enable the 4 byte addressing mode for all commands
flashReadChipData( FLASH_CMD_READ_SR2_REG_WB, &tmpSRData.statusReg2, 1, 0, true );
if( (tmpSRData.statusReg2 & FLASH_SR2_QE_MASK_WB) == 0 )
{
tmpSRData.statusReg2 |= FLASH_SR2_QE_MASK_WB;
flashSendCMDNoData( FLASH_CMD_WRITE_ENABLE, true );
flashWriteChipData( FLASH_CMD_WRITE_SR2_REG_WB, &tmpSRData.statusReg2, 1, true );
do
{
flashReadChipData( FLASH_CMD_READ_SR1, &tmpSRData.statusReg1, 1, 0, true );
} while( (tmpSRData.statusReg1 & FLASH_SR1_BUSY) != 0 );
}
// Enable QPI mode
flashSendCMDNoData( FLASH_CMD_ENABLE_QPI_WB, true );
// Configure the number of dummy cycles for 100 MHz operation
tmpData = FLASH_CFG_QPI_RD_CFG_REG_WB;
flashWriteChipData( FLASH_CMD_WRITE_RD_CFG_WB, &tmpData, 1, false );
selectedDie = 0;
isDualDieStatReg = true;
flashWriteChipData( FLASH_CMD_SELECT_DIE_WB, &selectedDie, 1, false );
}
__NVIC_DisableIRQ( OCTOSPI1_IRQn );
__NVIC_SetPriority( OCTOSPI1_IRQn, OCTOSPI1_PRIO );
enableMemoryMappedMode();
}
int main(void){
SystemClockConfig();
MPU_Config();
// Enable I-Cache
SCB_EnableICache();
// Enable D-Cache
SCB_EnableDCache();
....
OSPIDriverinit()
....
test_ext_flash_func() // Inside a thread
….
}
Issue
Calling test_ext_flash_func() causes the MCU to reboot continuously. We suspect this is due to executing code from external flash, but need help identifying the root cause and resolving it.