Skip to main content
Associate II
October 12, 2026
Solved

ITCM not working.

I’ve tried to include the ITCM for a while w/o sucess only getting a few cells cooperating leaving the lions share as ???????? in the memory view (STM32CubeIDE 2.2.0). Notably, the DTCM works fine after initiation.

 

I start out (from reset) to verify the ICTMCR/DTCMCR as enabled, identifying the size as 256KB (both).

After this I blindly writes 0 (32-bit) all over the place, this makes a very few ITCM cells 0x00000000.

If I only initiates DTCM, a few ITCM cells become visible but what looks like randomized not 0.

As stated earlier the full DTCM is now 0x00000000.

 

The DBGMCU_IDC is

DevID:0x499

RevID:0x2000

 

Somebody sees what I’m doing wrong?

All help appreciated!

/Henrik

 

 

HenrikGladerBest answer
Associate II
October 16, 2026

For completion, if anybody else got stuck on this...

Jiri V. at ST pointed out that ITCM needs 64-bit initialization writes.

This issue is resolved!

Thank you, Jiri 😀

9 replies

LCE
Principal III
October 12, 2026

Using ITCM on H733 here, for vector table and some functions.

 

in linker file *.ld :

MEMORY
{
ITCMRAMVEC (xrw) : ORIGIN = 0x00000000, LENGTH = 1K /* instruction RAM - vector table */
ITCMRAM (xrw) : ORIGIN = 0x00000400, LENGTH = 31K /* instruction RAM */
ITCM_HPST(xrw) : ORIGIN = 0x00008000, LENGTH = 32K /* ITCM heap & stack */
...


/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
/* ITCM SRAM
* for
* - vector table
* - some functions (interrupt handlers)
*/

/* ITCM_RAM VECTOR TABLE section */
.ItcmVecSection (NOLOAD):
{
. = ALIGN(8);
*(.ItcmVecSection)
*(.ItcmVecSection*)
. = ALIGN(8);
} >ITCMRAMVEC

/*
use before function:
__attribute__((section(".ItcmRamFuncSection")))
*/
_siitcmram = LOADADDR(.ItcmRamFuncSection);
/* ITCMRAM function section */
.ItcmRamFuncSection :
{
. = ALIGN(8);
_sitcmram = .; /* start */
*(.ItcmRamFuncSection)
*(.ItcmRamFuncSection*)
. = ALIGN(8);
_eitcmram = .; /* end */
} >ITCMRAM AT> FLASH



in my main.c/h :

main.h :

#define __ATT_SECT_ITCM_VECT __attribute__((section(".ItcmVecSection")))
#define __ATT_SECT_ITCM_FUNC __attribute__((section(".ItcmRamFuncSection")))

main.c :

/* memory section boundaries which are defined in the linker script */
extern uint32_t _siitcmram, _sitcmram, _eitcmram;


+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
/* copy some functions into ITCM SRAM,
* functions preceded by
* __ATT_SECT_ITCM_FUNC
*/
#if ITCM_RAM_FUNCTIONS
static void ItcmCopyFunctions(void)
{
uint8_t *pu8ItcmFlashStart = (uint8_t *)&_siitcmram;
uint8_t *pu8ItcmFuncStart = (uint8_t *)&_sitcmram;
uint8_t *pu8ItcmFuncEnd = (uint8_t *)&_eitcmram;
uint32_t u32Len = (uint32_t)pu8ItcmFuncEnd - (uint32_t)pu8ItcmFuncStart;

for( uint32_t i = 0; i < u32Len; i++ )
{
*(pu8ItcmFuncStart + i) = *(pu8ItcmFlashStart + i);
}
}
#endif /* ITCM_RAM_FUNCTIONS */


at start of main() :

/* #################################################################### */
/* IMPORTANT
* tell CPU that vector table is in APPLICATION section
*/
SCB->VTOR = FLASH_INT_ADDR_START | FLASH_INT_ADDR_OFFS_APP_VECT;

#if ITCM_RAM_VECTORTAB

/* move vector table (interrupts) to ITCM RAM */
uint8_t *pu8OrigVectorTable = (uint8_t *)SCB->VTOR;

/* copy vector table from flash to ITCM */
for( uint32_t i = 0; i < (uint32_t)sizeof(u8NewVectorTable); i++ ) u8NewVectorTable[i] = pu8OrigVectorTable[i];

/* set the new interrupt vector table */
SCB->VTOR = (uint32_t)&u8NewVectorTable[0];

#endif /* ITCM_RAM_VECTORTAB */

/* #################################################################### */

#if ITCM_RAM_FUNCTIONS
/* copy functions to ITCM RAM */
ItcmCopyFunctions();
#endif

...

functions are placed into ITCM this way:

#if ITCM_RAM_FUNCTIONS
__ATT_SECT_ITCM_FUNC
#endif
void SysTick_Handler(void)
{
u32SysTick++;
}

/* HAL_GetTick()
* moved here and into ITCM
*/
#if ITCM_RAM_FUNCTIONS
__ATT_SECT_ITCM_FUNC
#endif
uint32_t HAL_GetTick(void)
{
return u32SysTick;
}

 

That took some fiddling and stealing from the web...

Associate II
October 13, 2026

Yes, I have collected all important interrupthandlers in ITCM but sitting on the fence regarding the NVIC entries.

I’m guessing but placing it in ITCM makes sense as the instruction pipe is parked during take-off.

The handlers corresponding stack is in DTCM so, apart from earlier instructions residuals, the core has full access here.

Place the NVIC table here would mean competition.

But then again, I’m not that knowledged in this matters.

 

Thank you : )

AScha.3
Super User
October 12, 2026

I use almost all memories on H743 :

 

>Somebody sees what I’m doing wrong?

D tcmram is for data - as you tried with success.

I tcmram is for code only ! use for data is nonsense , would be slower than normal ram, if working at all; (access restricted, read rm . or ask Gemini ...)

Just set in linker script, what you want to be in itcmram  area. 

If you feel a post has answered your question, please click on " Best Answer ".
Associate II
October 13, 2026

Yes, indeed.

In the link script only my “.scode” goes into ITCM (“.sdata” and “.sbss” to DTCM respectively).

 

That is, I have not put any data within ITCM, only tried to see what the debugger finds there.

This works perfectly on the STM32H755 but on this newer one, I got no luck (yet).

 

BTW, I get a hard fault when the instruction pointer tries to access the ITCM.

The handler entries are all aligned on a 64-bit boundary.

 

Thank you : )

David Littell
Senior II
October 13, 2026

Just guessing that the MPU’s setup might be an issue?

HenrikGladerAuthorBest answer
Associate II
October 16, 2026

For completion, if anybody else got stuck on this...

Jiri V. at ST pointed out that ITCM needs 64-bit initialization writes.

This issue is resolved!

Thank you, Jiri 😀

LCE
Principal III
October 16, 2026

> Jiri V. at ST pointed out that ITCM needs 64-bit initialization writes.

 

Thanks for posting the solution.

Question to the experts:

So, is the alignment setting ALIGN(8) in the section declaration in the linker file good enough?

 

.ItcmVecSection (NOLOAD):

{

. = ALIGN(8);

*(.ItcmVecSection)

*(.ItcmVecSection*)

. = ALIGN(8);

} >ITCMRAMVEC

Associate II
October 16, 2026

You’d probably need to tell the compiler as well, from Jiri:

 

static void itcm_fill(volatile uint64_t *itcm, bool inverted)
{
  for (uint32_t i = 0; i < ITCM_GRANULE_COUNT; ++i)
  {
    itcm[i] = itcm_pattern(i, inverted);
  }

  __DSB();
}