2025-01-01 02:20 PM
Hello,
I have a problem with STM32N6. When trying to access any TCM (ITCM/DTCM) the CPU immediately crashes to the Hard_Fault. Do the TCM memories need to be explicitly enabled or something? From my experience from STM32H7, it was never needed. I've looked around RM for N6 but cannot find anything related. I have found in the examples (FLEXMEM_Configurations) that the HardFault shall happen when accesing beyond the configured TCM size, but I'm getting the crash at the base addresses.
uint16_t* _tcmData = (uint16_t*)0x30000000;
int main()
{
... //system init etc..
_tcmData[0] = 0x1234; //Hard_Fault crash here
}
2025-01-03 09:45 PM
VERY INTERESTING (and confusing)!
I play right now also with the STM32N6 - I tried your issue on on my project... and YES: it can crash in HardFault_Handler (but see below: it depends just on how you compile with debug options!)
First, I thought:
A non-secure vs. secure issue (DTCM 0x30000000 is Secure, 0x20000000 is Non-Secure). So, accessing DTCM as secure when main() is launched as non-secure (potentially) could cause such an issue. But it does NOT!
It just depends on:
How you set Optimization level! VERY STRANGE:
I use an STM32N6 project with FSBL build. It really just depends on how I set the debug level!
Secure and non-secure address location does not have an effect! (it crashes with both address locations if not -Og!)
What is this?
(I have realized already: the STM32N6 is very "delicate": sometimes it works, sometimes not - it seems to depend meanwhile on "how" I generate the code (with vs. without debug optimization, FSBL vs. Appli, ...).
Here the details:
I do also in main():
int main(void)
{
int no = 6;
/* USER CODE BEGIN 1 */
XSPI_RegularCmdTypeDef sCommand = {0};
XSPI_MemoryMappedTypeDef sMemMappedCfg = {0};
uint16_t index = 0;
uint16_t res = 0;
uint32_t address = 0;
__IO uint8_t step = 0;
__IO uint8_t *mem_addr;
#if 1
{
uint16_t* _tcmData = (uint16_t*)0x20000000; //0x30000000 is secure memory, 0x20000000 is non-secure
_tcmData[0] = 0x1234;
if (_tcmData[0] == 0x1234)
testVar = 1;
}
#endif
Just toggle debug level for code generation!
This is a debug session with debug level -Og:
This works fine!: I can write and read DTCM as secure and non-secure (0x30000000 vs. 0x20000000).
This is a debug session with none, as -O0:
This CRASHES: both addresses accessed result in a HardFault_Handler.
What is this?
I assume: the debugger has an effect on secure vs. non-secure access permission or system configuration done (by debugger instead of code).
(the system behavior should not not have any effect if generated for debugger and/or using debugger to let execute my code)
I am pretty "shocked" being able to replicate this issue (and I am very confused, losing my confidence in this N6 MCU...)
2025-01-04 12:23 AM - edited 2025-01-04 04:52 AM
Very interesting findings @tjaekel .
I can confirm, if I switch to -O2, then it does not crash into the HardFault when accessing the memory. However, this is far from over.
To address your points:
(I have realized already: the STM32N6 is very "delicate": sometimes it works, sometimes not - it seems to depend meanwhile on "how" I generate the code (with vs. without debug optimization, FSBL vs. Appli, ...).
Same here. The N6 goes wild on me like 50 times a day, when I have to physically reconnect the USB to reset the ST-Link and Power. Reset button does not "fix" things.
(I'm using the N6-Nucleo board)
A non-secure vs. secure issue (DTCM 0x30000000 is Secure, 0x20000000 is Non-Secure). So, accessing DTCM as secure when main() is launched as non-secure (potentially) could cause such an issue. But it does NOT!
I'm no expert in this secure/non-secure thing. Actually, it just bothers me, I don't want it, but it is what it is. But I was thinking, my code and data runs from secure (using the Appli LRUN.ld, which places the code and data into the 0x34000400 AXI SRAM, which is secure. When I was checking addresses of peripherals, they were all in the 0x50000000 range, again, secure. So my thinking was - I'm in secure, I shall use secure.
I hope these are mostly ST-link issue, fixable by FW update of ST-link. It is a new product, it is very complex, so yeah, I'm expecting some newborn pains.
Because - when I move my stack into the DTCM, it works.
What does not work for me is ITCM. I just cannot make it run no matter what. I have my code and approach from STM32H7:
This has always worked for me. But not in N6 case, I just always get a HardFault when calling any func placed at ITCM.
2025-01-04 12:44 AM
Also tried accessing the memory through STM32CubeProgrammer. I can access basically any address:
But, when I try to access 0x00000000 or 0x10000000 or 0x20000000 or 0x30000000 it gives me an error.
So I can't check or confirm, what is in the ITCM (if anything).
Please ST, have a look at this.
2025-01-04 04:57 AM - edited 2025-01-04 05:32 AM
Update: I have also tried to load the ITCM mem "directly", without the intermediate step of loading from ROM/RAM and this works, surprisingly. When debugging, I can see the SP switch to 0x10000000 and executes the code in ITCM normally. Really, really weird and unpredictable behaviour. Also it is useless.
Edit: Even better, when I load the ITCM directly, it looks like the "connection" to the ITCM gets somehow "enabled" and as long as I don't disconnect the power, I can then do the normal approach with loading the contents to the ITCM from RAM/ROM. And it works. But, when I disconnect the power, reconnect and upload exactly the same code again -> HardFault.