cancel
Showing results for 
Search instead for 
Did you mean: 

NUCLEOH7S3L8(STM32H7S3L8H6X) + FreeRTOS: HAL_TIM_IC_Start_DMA Halts Inside Task, but Works Before Scheduler Starts

htxy
Associate III

Hello everyone,

I'm working on a project using a NUCLEO-H7S3L8 board, and I have run into a very persistent and unusual problem involving FreeRTOS and a HAL function that I hope the community can provide some insight into.

My aim is to build an event-driven data acquisition system. The application uses multiple peripherals (ADC, SPI, UART, I2C, and TIM3 for PWM Input Capture) running in DMA mode. A central FreeRTOS task (StartOSScheduler) waits on an event group for any peripheral DMA to complete. When an event occurs, it collects data from all sources, aggregates it, and sends it as a UDP packet using LwIP.

Hardware and Software Setup

  • Board: NUCLEO-H7S3L8
  • MCU: STM32H7S3L8Hx
  • Toolchain: STM32CubeIDE
  • Firmware: STM32Cube FW_H7RS V1.2.0
  • Middleware: FreeRTOS (CMSIS-V2 Interface) and LwIP

The Problem: A Halt Inside a FreeRTOS Task

My application halts without any fault or error when calling HAL_TIM_IC_Start_DMA() inside my main scheduler task (StartOSScheduler).

The Critical Clue: The Most Important Piece of Information Is This:

  • If I call HAL_TIM_IC_Start_DMA(&htim3, TIM_CHANNEL_1, ...) from main.c before osKernelStart() is called, it works perfectly.
  • If the exact same function call is made from within my FreeRTOS task after the scheduler is running, the entire system halts instantly.

This proves that the peripheral clocks, GPIOs, timer configuration, and DMA configuration are all fundamentally correct. The issue is strictly related to the FreeRTOS task execution context.

Summary of Debugging Steps Taken

I have spent a significant amount of time debugging this and have ruled out all the common causes. Here is what has been tried and confirmed:

FreeRTOS Interrupt Priority Conflict (Solved):

  • Initial Symptom: The entire scheduler was stalled (osDelay would not work).
  • Cause: My peripheral interrupt preemption priorities were set to 5, which conflicted with LIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY (also set to 5).
  • Fix: All peripheral interrupt priorities have been changed to 6, which is a lower logical priority. This fixed the scheduler, and tasks now run correctly until the HAL call.

DMA Configuration Conflicts (Solved):

  • Cause: At one point, CubeMX had generated code where multiple GPDMA1 channels were assigned to the same TIM3 request (e.g., two channels for TIM3_CH1).
  • Fix: The GPDMA1 configuration has been corrected to ensure each timer channel (TIM3_CH1, TIM3_CH2, TIM3_CH3) has one, and only one, unique DMA channel assigned to it.

Hardware Errata (Solved):

  • Cause: I checked the STM32H7S errata sheet (es0596) and found issue 2.18.1, which states the timer's "Reset Mode" slave controller might not work correctly. My TIM3 was configured in this mode.
  • Fix: The TIM3 Slave Mode has been changed to Disabled in CubeMX to apply the workaround. The halt still occurs.

Relevant Codesnippet:

Note: LED_GREEN turns on before the MCU gets stuck, LED_BLUE never turns on. 

/*INSIDE FREERTOS.c*/

void MX_FREERTOS_Init(void) {
  periodicADCTimerHandle = osTimerNew(PeriodicADCTimerCallback, osTimerPeriodic, NULL, &periodicADCTimer_attributes);
  OSSchedulerHandle = osThreadNew(StartOSScheduler, NULL, &OSScheduler_attributes);
  sysAliveHandle = osThreadNew(StartSysAlive, NULL, &sysAlive_attributes);
  peripheralEventGroupHandle = osEventFlagsNew(&peripheralEventGroup_attributes);
}

void StartOSScheduler(void *argument)
{
  MX_LWIP_Init();
  osTimerStart(periodicADCTimerHandle, 60000U);
  BSP_LED_On(LED_GREEN);
  HAL_TIM_IC_Start_DMA(&htim3, TIM_CHANNEL_1, (uint32_t *)pwm_ch1_dma_buffer, PWM_DMA_BUFFER_SIZE);
  BSP_LED_On(LED_BLUE);
  HAL_TIM_IC_Start_DMA(&htim3, TIM_CHANNEL_2, (uint32_t *)pwm_ch2_dma_buffer, PWM_DMA_BUFFER_SIZE);
  HAL_TIM_IC_Start_DMA(&htim3, TIM_CHANNEL_3, (uint32_t *)pwm_ch3_dma_buffer, PWM_DMA_BUFFER_SIZE);
  HAL_SPI_Receive_DMA(&hspi1, (uint8_t*)spi1_dma_buffer, SPI_DMA_BUFFER_SIZE);
  HAL_SPI_Receive_DMA(&hspi2, (uint8_t*)spi2_dma_buffer, SPI_DMA_BUFFER_SIZE);
  HAL_UART_Receive_DMA(&huart4, (uint8_t*)uart4_dma_buffer, UART_DMA_BUFFER_SIZE);
  HAL_UART_Receive_DMA(&huart5, (uint8_t*)uart5_dma_buffer, UART_DMA_BUFFER_SIZE);
  HAL_UART_Receive_DMA(&huart7, (uint8_t*)uart7_dma_buffer, UART_DMA_BUFFER_SIZE);
  HAL_I2C_Slave_Receive_DMA(&hi2c2, (uint8_t*)i2c2_dma_buffer, I2C_DMA_BUFFER_SIZE);
  HAL_I2C_Slave_Receive_DMA(&hi2c3, (uint8_t*)i2c3_dma_buffer, I2C_DMA_BUFFER_SIZE);


....


Question:

Did anyone encounter this behaivior before or found a workaround? I inclluded the IOC as well as documentation about my config as appendix. 

 

1 REPLY 1
TDK
Super User

> My application halts without any fault or error

Where does execution stop? Show a stack trace. Hit run, let it encounter the problem, then hit pause. Probably it's stuck within interrupts somewhere.

If you feel a post has answered your question, please click "Accept as Solution".