EmbeddedRelated.com
Forums

Problem: Debug ITCM in STM32H7 processor

Started by drmike 1 month ago4 replieslatest reply 1 month ago105 views

 I am attempting to use an ST micro NUCLEO-H7S3L8 board to run code as fast as possible using the ITCM RAM. The problem is I can't use the ST-LINK debugger once the code starts running in ITCM. All the posts on the ST Community forum with exactly the same problem (different processor) are unanswered. Is it possible to use ST-LINK with ITCM? 

For now my options are to get the code running in FLASH, then use the ancient method of toggling GPIO lines to know where I am in the code when it moves to ITCM. Life is just easier if I could use the debugger.

Mike 

Edit: I have managed to get the debugger to step through code after hitting "pause" in the debugger. It's flaky, but at least I can probe processor registers to figure out what was done wrong. So the answer is Yes, it is possible to use ST-LINK with ITCM, it's just not very robust. Until I figure out what else I'm doing wrong!

[ - ]
Reply by satishms_erMay 8, 2026
STMs are tied to configuration done via STM32CubeIDE.

1. Check where the ITCM RAM starts in your linker script if you haven't done it already. 
   It can point to 0x4000. Not 0x0000 - a NULL Pointer. 
2. What is the Debugger Reset Behavior configured as?
   In STM32CubeIDE, navigate to Debug Configuration > Debugger tab > Reset behavior: Set it to None
3. Is it a Debug Build and Not a Release Build?
4. If you are here, make sure you do a Full Chip Erase using STM32CubeProgrammer
5. Single stepping will not allow your code to run.
   Use break points strategically based on your needs. 
6. For the onboard STLink, sometimes USB-C cables are a problem. A - C cables are helpful. 
7. If you change the cable, starting from #4 will help

Would love to hear how things work out for you
[ - ]
Reply by drmikeMay 8, 2026

I have created a copy of the ISR vector table and put it in ITCM from 0 - 0x400, then main starts at 0x400. The map file shows this is what I expect.

I changed it from "connect on reset" to "none", and that makes no difference. At least in terms of stopping at main().

Debug build. I tried full chip erase and after several runs it does seem to be stopping at the break point requested.

F6 does step over most of the time. 

The USB cable doesn't seem to matter - C-C or A-C has same behavior. 

It does seem to behave much, much better - other than not stopping at main(), the debugger is now useful! Hopefully I can do more than flash a few LED's, and see where the bugs are. 

I should check to see how much of the code is in ITCM. It may be the single step works because some is still in FLASH. 

How often is a full chip erase useful? 

Thanks - this is a huge improvement!

Edit: I copied all code into ITCM, now F6 (step over) and F5 (step into) still work - most of the time. And it does halt at break points. So this is really way better than where I was 6 hours ago.

[ - ]
Reply by satishms_erMay 8, 2026

Good to hear.

I forgot to mention that after a Full chip erase, it is a good idea to remove USB cables, power cycle and reconnect the USB cables and download your binary. Ideally, following all these steps should make your experience much smoother.

To your point above, merely "navigate to Debug Configuration > Debugger tab > Reset behavior: Set it to None" was not expected to work.

We need a series of things to happen, for a clean outcome.

A full chip erase is more to start with memory in a clean state.

Good luck!


[ - ]
Reply by drmikeMay 9, 2026

So far so good. On rare occasions it gives the "too many break points" error, but then it stops at a requested break point after hitting go. I just did a GPIO toggle test and the processor runs faster than the I/O pin allows, which is exactly what I want to see.

Finding dumb mistakes is the most important part of a debugger, and it's now doing that really well. In a week I should have everything doing what I want, so this is fantastic. Thanks for the help!

Attempting to change timer code causes the debugger to jump to hard fault instead of the timer init. At least I can put in infinite loops before and after code runs, then pause and check registers. Still better than not working!