Skip to main content
Senior III
June 22, 2026
Solved

Deadlock on STM32H7S7L with FreeRTOS and TouchGFX

  • June 22, 2026
  • 5 replies
  • 56 views

I’m using a custom board based 99% on the STM32H7S78-DK (except for the display, which is a 7”).

I’m having a serious deadlock issue (the entire microcontroller freezes, and I can’t connect to the debugger).

My firmware is composed:

  • The bootloader that just checks if an SD card is attached (if so, it mounts, reads it, and, in case, updates the external flash with the firmware).
  • If no SD card is detected, it loads the application.

The bootloader uses I and D caches and sets up the external memory via XSPI (PSRAM and FLASH)

The PSRAM is used for the TouchGFX framebuffer; the FLASH for the TouchGFX assets.

The .icd defines (among other things)

define symbol __ICFEDIT_intvec_start__ = 0x70000000;

define region EXTRAM_region = mem:[from 0x90000000 to 0x91FFFFFF];

define region ROM_region = mem:[from 0x70000000to 0x701FFFFF];

define region EXTROM_region = mem:[from 0x70200000to 0x77FFFFFF];

place in ROM_region { readonly };
place in RAM_region { readwrite };

place in EXTRAM_region { first section TouchGFX_Framebuffer
, section Video_RGB_Buffer
, section Nemagfx_Stencil_Buffer };

place in EXTROM_region { section TextFlashSection
, section FontFlashSection
, section FontSearchFlashSection
, section ExtFlashSection };

The application uses only the I cache, and it has just 3 RTOS tasks:

  • TouchGFX
  • COM (for UART communication over MODBUS protocol)
  • EEPROM read/write (to read and write EEPROM data via I2C)

What I’ve tried so far to avoid this deadlock:

  • increased stack size of every task (8192 for TouchGFX, 4096 for COM and 4096 for EEPROM)
  • increased heap size to 65536 in configTOTAL_HEAP_SIZE in FreeRTOSConfig.h
  • increased configMINIMAL_STACK_SIZE to 256
  • set configTIMER_TASK_PRIORITY to configMAX_PRIORITIES - 1
  • set INCLUDE_vTaskCleanUpResources to 1
  • disabled all tasks and kept just the TouchGFX one
  • removed all the code in Model::tick to avoid overloading the task
  • reduced frequency of XSPI (especially PSRAM) setting  PsramObject.psram_public.FreqMax = 100 * 1000000u; even if max ferquency is 200MHz
  • increased prescaler to hxspi1.Init.ClockPrescaler = 2;
  • enabled   hxspi1.Init.DelayHoldQuarterCycle = HAL_XSPI_DHQC_ENABLE;
  • added   hxspi1.Init.SampleShifting = HAL_XSPI_SAMPLE_SHIFT_HALFCYCLE; instead of None
  • Increased in the .icf file CSTACK = 0x6000; and HEAP   = 0x4000;
  • applied fix for errata 2.2.17
  • checked errata 2.4.2, but I’m not multiplexing XSPI
  • followed this fix https://forums.freertos.org/t/tmr-svc-appears-to-stop-working-and-threads-waiting-for-event-bits-become-non-responsive-how-should-i-debug-this/16324/2 setting configMAX_PRIORITIES 56 and configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1) and #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5

The issue happens after a couple of minutes from startup. After it happens, if I instantly power up the board, it happens after 2-3 seconds (the application always boots from the bootloader). If I wait to power cycle (like 2-3 minutes), the application keeps working for a little more before it crashes.

I’ve no idea how to debug it, as soon as the microcontroller freezes, the debugger basically disconnects, and I can’t find the latest code executed. Any idea, or I’m missing something?

I’m using IAR 9.60 and the J-Link Base

Best answer by nico23

Hi ​@JohanAstrup and ​@Hamady 

I think the issue was the errata in 2.2.15.

My error was to disable entirely the SBS in CubeMX, which has removed the clock configurationa dn other important line of code.

What instead worked was to keep SBS active in the Boot, but only disable IO HSLV FOR XSPIM1 e IO HSLV FOR XSPIM2

This removed just the code portion:

  /* The CSI is used by the compensation cells and must be enabled before enabling the
compensation cells.
For more details refer to RM0477 [SBS I/O compensation cell management] chapter.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_CSI;
RCC_OscInitStruct.CSIState = RCC_CSI_ON;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}

/* Configure the compensation cell */
HAL_SBS_ConfigCompensationCell(SBS_IO_XSPI1_CELL, SBS_IO_CELL_CODE, 0U, 0U);
HAL_SBS_ConfigCompensationCell(SBS_IO_XSPI2_CELL, SBS_IO_CELL_CODE, 0U, 0U);

/* Enable compensation cell */
HAL_SBS_EnableCompensationCell(SBS_IO_XSPI1_CELL);
HAL_SBS_EnableCompensationCell(SBS_IO_XSPI2_CELL);

/* wait ready before enabled IO */
while(HAL_SBS_GetCompensationCellReadyStatus(SBS_IO_XSPI1_CELL_READY) != 1U);
while(HAL_SBS_GetCompensationCellReadyStatus(SBS_IO_XSPI2_CELL_READY) != 1U);

/* high speed low voltage config */
HAL_SBS_EnableIOSpeedOptimize(SBS_IO_XSPI1_HSLV);
HAL_SBS_EnableIOSpeedOptimize(SBS_IO_XSPI2_HSLV);

keeping the clock and power enebaled.

Then, I added back as suggested

  /* high speed low voltage config */
HAL_SBS_EnableIOSpeedOptimize(SBS_IO_XSPI1_HSLV);
HAL_SBS_EnableIOSpeedOptimize(SBS_IO_XSPI2_HSLV);

I don’t know if it also helped but, looking into the dev kit source code, I have edited the chip select override which was None in XPS1 and I switched to NCs1 - PORT1 and changed to

hxspi1.Init.ChipSelectBoundary = HAL_XSPI_BONDARYOF_16KB;
hxspi1.Init.Refresh = 400;

At the moment everything seems to work correctly for the past hour; I’m still monitoring but I’m positive it’s a fix

I’ll keep you updated in about 24 hours to mark this as resolved if it’s the case

5 replies

mƎALLEm
ST Technical Moderator
June 22, 2026

Hello ​@nico23 ,

Such kind of questions need to be asked either in TouchGFX or Embedded software forum boards.

I’ll move that post in TouchGFX, if the TouchGFX team estimate that’s not a TouchGFX issue they can move it to Embedded software forum board.

To give better visibility on the answered topics, please click "Best answer" on the reply which solved your issue or answered your question.
nico23Author
Senior III
June 22, 2026

yeah, please move in the correct section; I wans’t sure if it was a FreeRTOS/TouchGFX issue or some hardware/low-level MCU issue

ST Technical Moderator
June 22, 2026

Hello Nico.

Without knowing for sure, it sounds like your issue could be related to section 2.2.15 in the errata sheet.
You can test that by disabling SBS in STM32CubeMX and then adding the following code to the user code section in stm32h7rsxx_hal_msp.c:

/* USER CODE BEGIN MspInit 1 */
/* high speed low voltage config */
HAL_SBS_EnableIOSpeedOptimize(SBS_IO_XSPI1_HSLV);
HAL_SBS_EnableIOSpeedOptimize(SBS_IO_XSPI2_HSLV);
/* USER CODE END MspInit 1 */

This is the fix we have applied to the STM32H7S78-DK TBSs.

Best regards,
Johan

nico23Author
Senior III
June 22, 2026

Doing that I’m seeing the MX_SBS_Init has been removed from Boot (I have SBS active only there) but it was already empty

/**
* @brief SBS Initialization Function
* @param None
* @retval None
*/
static void MX_SBS_Init(void)
{

/* USER CODE BEGIN SBS_Init 0 */

/* USER CODE END SBS_Init 0 */

/* USER CODE BEGIN SBS_Init 1 */

/* USER CODE END SBS_Init 1 */
/* USER CODE BEGIN SBS_Init 2 */

/* USER CODE END SBS_Init 2 */

}

and it has removed from HAL_MspInit

  __HAL_RCC_SBS_CLK_ENABLE();

/* The CSI is used by the compensation cells and must be enabled before enabling the
compensation cells.
For more details refer to RM0477 [SBS I/O compensation cell management] chapter.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_CSI;
RCC_OscInitStruct.CSIState = RCC_CSI_ON;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}

/* Configure the compensation cell */
HAL_SBS_ConfigCompensationCell(SBS_IO_XSPI1_CELL, SBS_IO_CELL_CODE, 0U, 0U);
HAL_SBS_ConfigCompensationCell(SBS_IO_XSPI2_CELL, SBS_IO_CELL_CODE, 0U, 0U);

/* Enable compensation cell */
HAL_SBS_EnableCompensationCell(SBS_IO_XSPI1_CELL);
HAL_SBS_EnableCompensationCell(SBS_IO_XSPI2_CELL);

/* wait ready before enabled IO */
while(HAL_SBS_GetCompensationCellReadyStatus(SBS_IO_XSPI1_CELL_READY) != 1U);
while(HAL_SBS_GetCompensationCellReadyStatus(SBS_IO_XSPI2_CELL_READY) != 1U);

/* high speed low voltage config */
HAL_SBS_EnableIOSpeedOptimize(SBS_IO_XSPI1_HSLV);
HAL_SBS_EnableIOSpeedOptimize(SBS_IO_XSPI2_HSLV);

I have then added the code you suggested

/* USER CODE BEGIN MspInit 1 */
/* high speed low voltage config */
HAL_SBS_EnableIOSpeedOptimize(SBS_IO_XSPI1_HSLV);
HAL_SBS_EnableIOSpeedOptimize(SBS_IO_XSPI2_HSLV);
/* USER CODE END MspInit 1 */

but now I’m stuck at  HAL_XSPI_GET_FLAG(hxspi, Flag)with XSPI2 (which is the FLASH) in   EXTMEM_Init(EXTMEMORY_1, HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_XSPI2));


XSPI_WaitFlagStateUntilTimeout
HAL_XSPI_Abort
SAL_XSPI_CheckStatusRegister
sfpd_set_dummycycle
SFDP_BuildGenericDriver
EXTMEM_DRIVER_NOR_SFDP_Init
EXTMEM_Init
MX_EXTMEM_MANAGER_Init
main
[_call_main + 0xd]

 

ST Technical Moderator
June 25, 2026

Are your configurations for both the PSRAM and external flash based on the setup in the TBS available for the STM32H7S78-DK in TouchGFX Designer? If not, could you try comparing the configuration?

Of course, this only applies if the two memories are part of the 99% and are therefore identical to the ones mounted on the DK board.

Best regards,
Johan

nico23Author
Senior III
June 23, 2026

What I’ve also tried so for:

  • changed #define  TICK_INT_PRIORITY from 15UL to 4UL
Associate III
June 25, 2026

Hi , maybe you can try create a touch gfx application using DK board (in touch gfx designer) , open the .IOC and all code and check 

→ Clock three same as gfx app

→ sbs enabled 

→ XSPI same settings as gfx app

→ MPU for boot and APP same as gfx app 

→ freertos same settings as gfx app 

→ use  of TIM6 for systick 

→ Linker script same as gfx app 

→ check if you’re schematic is perfect for SMPS config , also check .IOC

ADD this on boot first line 

  FMC_Bank1_R->BTCR[0] = 0x000030D2;//Disable FMC1

try this for memory in msp in boot section 
 

#define NMOS_ADJ  +2
#define PMOS_ADJ -2

// Macro générique pour ajuster une valeur et la clamp sur une plage [0, 15]
#define ADJUST_AND_CLAMP(val, adj) ( ((int32_t)(val) + (adj) < 0) ? 0 : \
(((int32_t)(val) + (adj) > 15) ? 15 : ((int32_t)(val) + (adj))) )

void configure_XPSI(){
RCC_OscInitTypeDef RCC_OscInitStruct = {0};

__HAL_RCC_SBS_CLK_ENABLE();

/* System interrupt init*/

/* Enable the XSPIM_P1 interface */
HAL_PWREx_EnableXSPIM1();

/* Enable the XSPIM_P2 interface */
HAL_PWREx_EnableXSPIM2();

/* The CSI is used by the compensation cells and must be enabled before enabling the
compensation cells.
For more details refer to RM0477 [SBS I/O compensation cell management] chapter.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_CSI;
RCC_OscInitStruct.CSIState = RCC_CSI_ON;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}


/* Configure the compensation cell */
HAL_SBS_ConfigCompensationCell(SBS_IO_XSPI1_CELL, SBS_IO_CELL_CODE, 0U, 0U);
HAL_SBS_ConfigCompensationCell(SBS_IO_XSPI2_CELL, SBS_IO_CELL_CODE, 0U, 0U);

/* Enable compensation cell */
HAL_SBS_EnableCompensationCell(SBS_IO_XSPI1_CELL);
HAL_SBS_EnableCompensationCell(SBS_IO_XSPI2_CELL);

/* wait ready before enabled IO */
while(HAL_SBS_GetCompensationCellReadyStatus(SBS_IO_XSPI1_CELL_READY) != 1U);
while(HAL_SBS_GetCompensationCellReadyStatus(SBS_IO_XSPI2_CELL_READY) != 1U);

uint32_t code1, code2, nmos1, nmos2, pmos1, pmos2;

HAL_SBS_GetCompensationCell(SBS_IO_XSPI1_CELL, &code1, &nmos1, &pmos1);
HAL_SBS_GetCompensationCell(SBS_IO_XSPI2_CELL, &code2, &nmos2, &pmos2);

// Appliquer ajustement + clamp
nmos1 = ADJUST_AND_CLAMP(nmos1, NMOS_ADJ);
nmos2 = ADJUST_AND_CLAMP(nmos2, NMOS_ADJ);
pmos1 = ADJUST_AND_CLAMP(pmos1, PMOS_ADJ);
pmos2 = ADJUST_AND_CLAMP(pmos2, PMOS_ADJ);

HAL_SBS_ConfigCompensationCell(SBS_IO_XSPI1_CELL, SBS_IO_REGISTER_CODE, nmos1, pmos1);
HAL_SBS_ConfigCompensationCell(SBS_IO_XSPI2_CELL, SBS_IO_REGISTER_CODE, nmos2, pmos2);

/* high speed low voltage config */
HAL_SBS_EnableIOSpeedOptimize(SBS_IO_XSPI1_HSLV);
HAL_SBS_EnableIOSpeedOptimize(SBS_IO_XSPI2_HSLV);

}
/* USER CODE END 0 */

void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);
/**
* Initializes the Global MSP.
*/
void HAL_MspInit(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};

/* Configure the system Power Supply */

if (HAL_PWREx_ConfigSupply(PWR_DIRECT_SMPS_SUPPLY) != HAL_OK)
{
/* Initialization error */
Error_Handler();
}

/* USER CODE BEGIN MspInit 0 */
configure_XPSI();
return;
/* USER CODE END MspInit 0 */

__HAL_RCC_SBS_CLK_ENABLE();

/* System interrupt init*/

/* Enable the XSPIM_P1 interface */
HAL_PWREx_EnableXSPIM1();

/* Enable the XSPIM_P2 interface */
HAL_PWREx_EnableXSPIM2();

/* The CSI is used by the compensation cells and must be enabled before enabling the
compensation cells.
For more details refer to RM0477 [SBS I/O compensation cell management] chapter.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_CSI;
RCC_OscInitStruct.CSIState = RCC_CSI_ON;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}

/* Configure the compensation cell */
HAL_SBS_ConfigCompensationCell(SBS_IO_XSPI1_CELL, SBS_IO_CELL_CODE, 0U, 0U);
HAL_SBS_ConfigCompensationCell(SBS_IO_XSPI2_CELL, SBS_IO_CELL_CODE, 0U, 0U);

/* Enable compensation cell */
HAL_SBS_EnableCompensationCell(SBS_IO_XSPI1_CELL);
HAL_SBS_EnableCompensationCell(SBS_IO_XSPI2_CELL);

/* wait ready before enabled IO */
while(HAL_SBS_GetCompensationCellReadyStatus(SBS_IO_XSPI1_CELL_READY) != 1U);
while(HAL_SBS_GetCompensationCellReadyStatus(SBS_IO_XSPI2_CELL_READY) != 1U);

/* high speed low voltage config */
HAL_SBS_EnableIOSpeedOptimize(SBS_IO_XSPI1_HSLV);
HAL_SBS_EnableIOSpeedOptimize(SBS_IO_XSPI2_HSLV);

/* USER CODE BEGIN MspInit 1 */

/* USER CODE END MspInit 1 */
}

 

nico23AuthorBest answer
Senior III
June 25, 2026

Hi ​@JohanAstrup and ​@Hamady 

I think the issue was the errata in 2.2.15.

My error was to disable entirely the SBS in CubeMX, which has removed the clock configurationa dn other important line of code.

What instead worked was to keep SBS active in the Boot, but only disable IO HSLV FOR XSPIM1 e IO HSLV FOR XSPIM2

This removed just the code portion:

  /* The CSI is used by the compensation cells and must be enabled before enabling the
compensation cells.
For more details refer to RM0477 [SBS I/O compensation cell management] chapter.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_CSI;
RCC_OscInitStruct.CSIState = RCC_CSI_ON;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}

/* Configure the compensation cell */
HAL_SBS_ConfigCompensationCell(SBS_IO_XSPI1_CELL, SBS_IO_CELL_CODE, 0U, 0U);
HAL_SBS_ConfigCompensationCell(SBS_IO_XSPI2_CELL, SBS_IO_CELL_CODE, 0U, 0U);

/* Enable compensation cell */
HAL_SBS_EnableCompensationCell(SBS_IO_XSPI1_CELL);
HAL_SBS_EnableCompensationCell(SBS_IO_XSPI2_CELL);

/* wait ready before enabled IO */
while(HAL_SBS_GetCompensationCellReadyStatus(SBS_IO_XSPI1_CELL_READY) != 1U);
while(HAL_SBS_GetCompensationCellReadyStatus(SBS_IO_XSPI2_CELL_READY) != 1U);

/* high speed low voltage config */
HAL_SBS_EnableIOSpeedOptimize(SBS_IO_XSPI1_HSLV);
HAL_SBS_EnableIOSpeedOptimize(SBS_IO_XSPI2_HSLV);

keeping the clock and power enebaled.

Then, I added back as suggested

  /* high speed low voltage config */
HAL_SBS_EnableIOSpeedOptimize(SBS_IO_XSPI1_HSLV);
HAL_SBS_EnableIOSpeedOptimize(SBS_IO_XSPI2_HSLV);

I don’t know if it also helped but, looking into the dev kit source code, I have edited the chip select override which was None in XPS1 and I switched to NCs1 - PORT1 and changed to

hxspi1.Init.ChipSelectBoundary = HAL_XSPI_BONDARYOF_16KB;
hxspi1.Init.Refresh = 400;

At the moment everything seems to work correctly for the past hour; I’m still monitoring but I’m positive it’s a fix

I’ll keep you updated in about 24 hours to mark this as resolved if it’s the case