Skip to main content
Graduate
April 4, 2025
Solved

While(1) loop stops executing

  • April 4, 2025
  • 3 replies
  • 459 views

Hello,

For my project Im checking on a data request by using DMA and UART Idle interrupt. After a few minutes my while loop just stops executing. The code keeps executing the USART1_IRQHandler and doesn't return to the main code anymore. If Im not using DMA this doesn't happen. Does anyone know how this happens and if it can be fixed?

Here a few code snippets:

static void MX_USART1_UART_Init(void)
{

/* USER CODE BEGIN USART1_Init 0 */

/* USER CODE END USART1_Init 0 */

/* USER CODE BEGIN USART1_Init 1 */

/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 230400;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_RS485Ex_Init(&huart1, UART_DE_POLARITY_HIGH, 10, 0) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
HAL_UART_Receive_DMA(&huart1, uart_rx_buffer, 50);
/* USER CODE END USART1_Init 2 */

}


static void MX_DMA_Init(void)
{

/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();

/* DMA interrupt init */
/* DMA1_Channel2_3_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel2_3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);

}


void USART1_IRQHandler(void) {
if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE)) {
__HAL_UART_CLEAR_FLAG(&huart1, UART_FLAG_IDLE);

HAL_GPIO_WritePin(GPIOA,LEDR_Pin,GPIO_PIN_RESET);

HAL_UART_DMAStop(&huart1);

for (uint8_t i = 0; i < 50 - 1; i++) {
if (uart_rx_buffer[i] == 0xAA && uart_rx_buffer[i + 1] == ID) {
TransmitDistance();
uart_rx_buffer[i]=0;
uart_rx_buffer[i+1]=0;
break;
}
}

HAL_UART_Receive_DMA(&huart1, uart_rx_buffer, 50);
}
}


int main(void)
{

 /* USER CODE BEGIN 1 */

 /* USER CODE END 1 */

 /* MCU Configuration--------------------------------------------------------*/

 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
 HAL_Init();

 /* USER CODE BEGIN Init */

 /* USER CODE END Init */

 /* Configure the system clock */
 SystemClock_Config();

 /* USER CODE BEGIN SysInit */

 /* USER CODE END SysInit */

 /* Initialize all configured peripherals */
 MX_GPIO_Init();
 MX_DMA_Init();
 MX_I2C1_Init();
 MX_USART1_UART_Init();
 MX_TIM2_Init();
 /* USER CODE BEGIN 2 */
 HAL_TIM_Base_Start(&htim2);

 uint16_t last=0;
 int32_t distance=0;
 int32_t distancemm=0;
 //uint32_t meter=0;
 //uint16_t decimaal=0;
 uint16_t startwaarde=0;
 //uint32_t i=0;

 //Status();

 startwaarde = Init();
 /* USER CODE END 2 */

 /* Infinite loop */
 /* USER CODE BEGIN WHILE */

 while (1)
 {
CalculateDistance(&distance, &distancemm, &last, startwaarde);
HAL_GPIO_WritePin(GPIOA,LEDR_Pin,GPIO_PIN_SET);
/*if(RequestData()){
//i++;
//DelayUS(150);
//if(i>20)
TransmitDistance(meter, decimaal);
}*/

 /* USER CODE END WHILE */

 /* USER CODE BEGIN 3 */
 }
 /* USER CODE END 3 */
}
    This topic has been closed for replies.
    Best answer by Karl Yamashita

    Don't write code in the USART1_IRQHandler but instead in HAL_UARTEx_RxEventCallback.

     

    By the time HAL_UARTEx_RxEventCallback is called, all the flags are cleared. So all need to do is copy the data to another buffer. Then you parse the data in the while loop.

    If you use DMA in Circular mode, then there is no need to stop the DMA and enable it again. Make use of the HT, TC.

     

    See this project https://github.com/karlyamashita/Nucleo-G071RB_UART_DMA_Idle_Circular/wiki

     

     

     

     

    3 replies

    Graduate II
    April 4, 2025

    Check the UART status register, what is flagging?

    IRQ will keep tail chaining if you don't clear the source. If TXE interrupting need to send something or disable it.

    Check for error status flagging.

    Graduate II
    April 5, 2025

    Don't write code in the USART1_IRQHandler but instead in HAL_UARTEx_RxEventCallback.

     

    By the time HAL_UARTEx_RxEventCallback is called, all the flags are cleared. So all need to do is copy the data to another buffer. Then you parse the data in the while loop.

    If you use DMA in Circular mode, then there is no need to stop the DMA and enable it again. Make use of the HT, TC.

     

    See this project https://github.com/karlyamashita/Nucleo-G071RB_UART_DMA_Idle_Circular/wiki

     

     

     

     

    Super User
    April 5, 2025

    Looks like a possible out-of-bounds read in line 56 and out-of-bounds write in line 59.

    hth

    KnarfB