2025-01-03 04:17 PM
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:
So:
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,
Are the first 256bytes on external OctalSPI flash always never executable?
Why does MPU config "hides" this memory region? (in debug mode with MemoryBrowser)
Solved! Go to Solution.
2025-01-04 04:00 PM
Hi all,
actually, my code execution works (when booting in DEV mode).
No, I do not (yet) flash the code in external octal SPI memory: I want to get familiar with all the features of N6 first.
Later it will come to the issue how to write code for a standalone application (not DEV, not with debugger).
I have seen the Template_FSBL_XIP example. Just for one reason it creates just one sub-project. As I understand it has two parts: the booloader and the external code. Never mind - even with this project code execution works.
With modifying (and testing) project "XSPI_NOR_MemoryMapped_DTR" I can write, read and even execute data and code written to external octal SPI flash. I am not using yet to flash the entire FW into it (still in DEV boot mode).
The external octal SPI flash can be erased, written, read and even execute code. Just to make sure that a Thumb address is needed (+1) in order to call code (my concern was just to see that code execution works - it does!).
All is fine, even starting at 0x70000000: Yes, later when signed code is bootloaded from it - it is important to know that external octal SPI flash starts with signed headers. For now, in DEV mode: the entire SPI flash is available.
Just important to bear in mind that the XSPI must be in MemoryMapped mode (for reading back data or to execute code). Here my test code (without initialization: after writing all and keeping it in MemoryMapped mode):
{
FPTR fptr = (FPTR)TEST;
int i;
if (fptr() == 1)
{
for (i = 0; i < 10; i++)
{
BSP_LED_Toggle(LED_GREEN);
HAL_Delay(200);
}
}
}
{
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);
}
}
}
I write code as instructions to external octal SPI flash. I can read back and execute (it is a simple MOV R0, #1; BX LR).
The (minor) issue just: when enabling the MPU for this 0x70000000 - it "hides" the memory (for debugger). And I cannot launch anymore code at 0x70000000. Without MPU it works fine.
(it is like: MPU configured makes the 0x100 - not 0x400 - first memory address not access-able)
Anyway: it looks to me that debugger (with "MemoryBrowser") cannot see really all memories, e.g.:
Never mind: just playing with the building blocks I would need later... So far OK, just a bit confused what is going on (e.g. the effect of the MPU config). I want to make sure (just) that data and code access to/from external SPI flash works (and it does!). All fine.
2025-01-03 04:28 PM
Here my debug session:
2025-01-04 12:59 AM - edited 2025-01-04 01:12 AM
Isn't it the place where the STM32N6 expects the binary "signature" using STM32_SigningTool_CLI.exe? And the offset shall actually be 0x400 (1kB)? Because that's the size of the signature. So it is maybe unreadable/unusable by design or something like that?
2025-01-04 06:14 AM
Hi @tjaekel
The XSPI_NOR_MemoryMapped_DTR example demonstrates how to erase, write and re-read data in the external NOR Flash.
Normally, for a code execution context from this external XPI Flash memory, you should start from the Template_FSBL_XIP example.
Both FSBL and Appli binaries must be signed before programming (refer to the example readme.html)
Best regards,
Romain,
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2025-01-04 04:00 PM
Hi all,
actually, my code execution works (when booting in DEV mode).
No, I do not (yet) flash the code in external octal SPI memory: I want to get familiar with all the features of N6 first.
Later it will come to the issue how to write code for a standalone application (not DEV, not with debugger).
I have seen the Template_FSBL_XIP example. Just for one reason it creates just one sub-project. As I understand it has two parts: the booloader and the external code. Never mind - even with this project code execution works.
With modifying (and testing) project "XSPI_NOR_MemoryMapped_DTR" I can write, read and even execute data and code written to external octal SPI flash. I am not using yet to flash the entire FW into it (still in DEV boot mode).
The external octal SPI flash can be erased, written, read and even execute code. Just to make sure that a Thumb address is needed (+1) in order to call code (my concern was just to see that code execution works - it does!).
All is fine, even starting at 0x70000000: Yes, later when signed code is bootloaded from it - it is important to know that external octal SPI flash starts with signed headers. For now, in DEV mode: the entire SPI flash is available.
Just important to bear in mind that the XSPI must be in MemoryMapped mode (for reading back data or to execute code). Here my test code (without initialization: after writing all and keeping it in MemoryMapped mode):
{
FPTR fptr = (FPTR)TEST;
int i;
if (fptr() == 1)
{
for (i = 0; i < 10; i++)
{
BSP_LED_Toggle(LED_GREEN);
HAL_Delay(200);
}
}
}
{
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);
}
}
}
I write code as instructions to external octal SPI flash. I can read back and execute (it is a simple MOV R0, #1; BX LR).
The (minor) issue just: when enabling the MPU for this 0x70000000 - it "hides" the memory (for debugger). And I cannot launch anymore code at 0x70000000. Without MPU it works fine.
(it is like: MPU configured makes the 0x100 - not 0x400 - first memory address not access-able)
Anyway: it looks to me that debugger (with "MemoryBrowser") cannot see really all memories, e.g.:
Never mind: just playing with the building blocks I would need later... So far OK, just a bit confused what is going on (e.g. the effect of the MPU config). I want to make sure (just) that data and code access to/from external SPI flash works (and it does!). All fine.