STM32N6: MPU config, code execution - why not at 0x70000000?
I try to build a code example where I can execute directly from external OctalSPI flash.
I use HAL project "XSPI_NOR_MemoryMapped_DTR" as reference and starting point:
It works fine: I can write (flash) and read back external QSPI memory. I can also execute code from it.
It looks to me at: the memory region 0x7000_0000...0x7000_00FF on external OctalSPI is a "write and readable" data region but "never an executable region". Code execution is only possible at address 0x7000_0100 (and beyond).
The strange issues I have:
- without MPU configured: I can write (flash) data on 0x7000_0000... It works fine: read back in code seems to be OK.
In debug mode, using the "Memory Browser" : I see this region 0x7000_0000...0x7000_00FF written properly - all written and read back are correct - with MPU enabled (for this region): I can still write and read back - all OK (FW passed on reading it back).
BUT: in debug mode, using the "Memory Browser" : I see this regions 0x7000_0000...0x7000_00FF all as 0xFF.
(even the write and read back via FW code passes) - When I try to call the code written to OctalSPI flash memory (0x7000_0000...0x7000_00FF) - I write data as instructions, a very simple sub-function called with:
movs r0, #1
bx lr
(in hex value as 0x2001 0x4770)
I can never call this code at address 0x7000_0000. But I can this call this code located at address 0x7000_0100.
So:
- enabling MPU makes it impossible to read what was written at 0x7000_0000...0x7000_00FF in Memory Browser (all as 0xFF), but code running seems to see properly written values and able to read it back.
- I can never call the code at 0x7000_0000, never mind if MPU is enabled or not - just code starting at 0x7000_0100 works.
The difference is on main() - with or without calling MPU_Config():
/* Configure the system clock */
SystemClock_Config();
//?? whith this config - the written code not visible at 0x7000_0000 (debugger reads 0xFF...) ??
//?? not possible to execute this code - even writing and reading seems to be OK! ??
////MPU_Config();
Here my MPU config I use:
void MPU_Config(void)
{
MPU_Region_InitTypeDef default_config = {0};
MPU_Attributes_InitTypeDef attr_config = {0};
uint32_t primask_bit = __get_PRIMASK();
__disable_irq();
/* disable the MPU */
HAL_MPU_Disable();
/* create an attribute configuration for the MPU */
attr_config.Attributes = INNER_OUTER(MPU_RW_ALLOCATE); //INNER_OUTER(MPU_NOT_CACHEABLE);
attr_config.Number = MPU_ATTRIBUTES_NUMBER0;
HAL_MPU_ConfigMemoryAttributes(&attr_config);
/* Create a non cacheable region */
/*Normal memory type, code execution allowed */
default_config.Enable = MPU_REGION_ENABLE;
default_config.Number = MPU_REGION_NUMBER0;
default_config.BaseAddress = 0x70000000;
default_config.LimitAddress = 0x70001000;
default_config.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
default_config.AccessPermission = MPU_REGION_ALL_RW;
default_config.IsShareable = MPU_ACCESS_OUTER_SHAREABLE | MPU_ACCESS_INNER_SHAREABLE; //MPU_ACCESS_NOT_SHAREABLE;
default_config.AttributesIndex = MPU_ATTRIBUTES_NUMBER0;
HAL_MPU_ConfigRegion(&default_config);
/* enable the MPU */
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
/* Exit critical section to lock the system and avoid any issue around MPU mechanisme */
__set_PRIMASK(primask_bit);
}
Here the code when I want to jump to this external OctalSPI region (be aware of: the address to jump is odd (+1, due to thumb code):
{
//?? even write and read on address 0x70000000 seems to work/pass
//?? and I can see the memory content - but code execution does NOT work at 0x70000000!
FPTR fptr = (FPTR)0x70000101; //it must be thumb code address! and only this address works!
int i;
if (fptr() == 1)
{
for (i = 0; i < 10; i++)
{
BSP_LED_Toggle(LED_BLUE);
HAL_Delay(200);
}
}
}
So,
- enabling MPU makes it impossible to use debug "Memory Browser" to see the content on OctalSPI 0x7000_0000... (but code running seems to see properly)
- I can never jump to 0x7000_0000 (+1), but jump to 0x7000_0100 (+1) works
Are the first 256bytes on external OctalSPI flash always never executable?
Why does MPU config "hides" this memory region? (in debug mode with MemoryBrowser)
