cancel
Showing results for 
Search instead for 
Did you mean: 

UART DMA and SPI DMA problems on STM32G0B0

Hi all,

I have an system that reads data form an external ADC via SPI DMA, i send the StartConversion CMD and when it's done i get and IRQ so i can read the register. 

I also have an UART communication that polls every 2sec for the new data, I have the uart configured in DMA mode with interrupt.

The problem is that i somtime miss a UART message, if i set the UART DMA higher in priority the ADC cannot convert and cant communicate.

UART

 

PieterInHetBos_0-1690462554611.png

PieterInHetBos_5-1690462665926.png

 

SPI

PieterInHetBos_2-1690462602722.png

PieterInHetBos_6-1690462685844.png

 

NVIC

PieterInHetBos_4-1690462642102.png

Any help would be amazing

 

 

 

 

 

8 REPLIES 8
TDK
Guru

> The problem is that i somtime miss a UART message, if i set the UART DMA higher in priority the ADC cannot convert and cant communicate.

If your SPI prescaler is 256, there's no way the DMA is saturating the bus, leading to lost data. And there's no way UART is saturating the bus.

Most like you're doing too much stuff within the DMA IRQ handler which causes the UART handling to miss data. One solution is to do less in the handlers and more in the main loop. This is most likely a coding issue, not a STM32 configuration/setup issue. Hard to know exactly without seeing the code.

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

STM32G0_it.c

 

void EXTI4_15_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI4_15_IRQn 0 */

  /* USER CODE END EXTI4_15_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4);
  /* USER CODE BEGIN EXTI4_15_IRQn 1 */
  HAL_GPIO_TogglePin(GPIOB, LED_BLUE_Pin);
  nextChannel =1;
  /* USER CODE END EXTI4_15_IRQn 1 */
}

/**
  * @brief This function handles DMA1 channel 1 interrupt.
  */
void DMA1_Channel1_IRQHandler(void)
{
  /* USER CODE BEGIN DMA1_Channel1_IRQn 0 */
//  HAL_UART_RxCpltCallback(&huart2);
  /* USER CODE END DMA1_Channel1_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_usart2_rx);
  /* USER CODE BEGIN DMA1_Channel1_IRQn 1 */


  /* USER CODE END DMA1_Channel1_IRQn 1 */
}

/**
  * @brief This function handles DMA1 Ch4 to Ch7, DMA2 Ch1 to Ch5 and DMAMUX1 Overrun Interrupts.
  */
void DMA1_Ch4_7_DMA2_Ch1_5_DMAMUX1_OVR_IRQHandler(void)
{
  /* USER CODE BEGIN DMA1_Ch4_7_DMA2_Ch1_5_DMAMUX1_OVR_IRQn 0 */

  /* USER CODE END DMA1_Ch4_7_DMA2_Ch1_5_DMAMUX1_OVR_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_spi1_rx);
  /* USER CODE BEGIN DMA1_Ch4_7_DMA2_Ch1_5_DMAMUX1_OVR_IRQn 1 */


  /* USER CODE END DMA1_Ch4_7_DMA2_Ch1_5_DMAMUX1_OVR_IRQn 1 */
}

/**
  * @brief This function handles TIM6 global Interrupts.
  */
void TIM6_IRQHandler(void)
{
  /* USER CODE BEGIN TIM6_IRQn 0 */
  TimerInterrupt = 1;
  /* USER CODE END TIM6_IRQn 0 */
  HAL_TIM_IRQHandler(&htim6);
  /* USER CODE BEGIN TIM6_IRQn 1 */

  /* USER CODE END TIM6_IRQn 1 */
}

/**
  * @brief This function handles TIM14 global interrupt.
  */
void TIM14_IRQHandler(void)
{
  /* USER CODE BEGIN TIM14_IRQn 0 */

  /* USER CODE END TIM14_IRQn 0 */
  HAL_TIM_IRQHandler(&htim14);
  /* USER CODE BEGIN TIM14_IRQn 1 */

  /* USER CODE END TIM14_IRQn 1 */
}

/**
  * @brief This function handles TIM17 global interrupt.
  */
void TIM17_IRQHandler(void)
{
  /* USER CODE BEGIN TIM17_IRQn 0 */

  /* USER CODE END TIM17_IRQn 0 */
  HAL_TIM_IRQHandler(&htim17);
  /* USER CODE BEGIN TIM17_IRQn 1 */

  /* USER CODE END TIM17_IRQn 1 */
}

/**
  * @brief This function handles SPI1/I2S1 Interrupt.
  */
void SPI1_IRQHandler(void)
{
  /* USER CODE BEGIN SPI1_IRQn 0 */

  /* USER CODE END SPI1_IRQn 0 */
  HAL_SPI_IRQHandler(&hspi1);
  /* USER CODE BEGIN SPI1_IRQn 1 */

  /* USER CODE END SPI1_IRQn 1 */
}

/**
  * @brief This function handles USART2 Interrupt.
  */
void USART2_IRQHandler(void)
{
  /* USER CODE BEGIN USART2_IRQn 0 */
  //HAL_UART_RxCpltCallback(&huart2);
  /* USER CODE END USART2_IRQn 0 */
  HAL_UART_IRQHandler(&huart2);
  /* USER CODE BEGIN USART2_IRQn 1 */


  /* USER CODE END USART2_IRQn 1 */
}

 

Callback EXTI

 

void HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin) { //non standard function see https://github.com/STMicroelectronics/STM32CubeG0/issues/7

	if(setup_done == true){
		if (GPIO_Pin == ADC_IRQ_MDAT_Pin) {
			uint32_t adc_val2 = 0;
			conversie_done=false;
			uint8_t val[5] = { 0, 0, 0, 0, 0 };
			uint8_t cmd[5] = { 0, 0, 0, 0, 0 };
			cmd[0] = MCP3561_SREAD_DATA_COMMAND;

			HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, 0);
			HAL_SPI_TransmitReceive(&hspi1, &cmd[0], &val[0], 5, 10);
			HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, 1);

			adc_val2 = ((val[2] << 16) | (val[3] << 8 | val[4]) & 0x7FFFFF; 
			adc_val = adc_val2;
			conversie_done=true;

		}else{
			uiGlobalError = GLOBAL_ERR_ADC;
		}
	}
}

 

UART Callback

 

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(rx_buffer[0] == '+' || data_received >= TOLNET_RX_BUFFER_LENGTH){

		data_received = 0;
	}
	rs485_data[data_received] = rx_buffer[0];							// Implement message
	data_received++;
	HAL_UART_Receive_DMA(&huart2, (uint8_t *)rx_buffer, 1); //rx_buffer
	readTolnet();
}

 

 

 

TDK said:

> Most like you're doing too much stuff within the DMA IRQ handler which causes the UART handling to miss data.

so why do you show us all IRQs *except* the DMA IRQ...?

JW

PS: this

HAL_UART_Receive_DMA(&huart2, (uint8_t *)rx_buffer, 1); //rx_buffer

makes little to no sense.

 

This is de only code i wrote, so i guess no DMA IRQ? 

there is no callback after the DMA.

 

What you said makes no sense i dont get really. What makes no sense? 

what i am trying to do i receive 1 byte in the dma because all the messages are diffrend length and when i find the correct fist byte it needs to get the correct message

TDK
Guru

DMA on 1 byte isn't the most efficient solution. What does readTolnet do?

I still don't think you're showing the code causing the problem. I don't see any SPI-related functions here and it sounds like that's the cause of the original issue.

Calling HAL_SPI_TransmitReceive (a blocking function) within HAL_GPIO_EXTI_Rising_Callback could be the reason. But changing DMA priority wouldn't change this.

Edit: Actually, yes, that last thing would explain the problem.

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

You suggest i moce HAL_SPI_TransmitReceive outside of the EXTI_Rising_Callback? or just an other function entirely

 

TDK
Guru

I would suggest moving it outside the IRQ handler. General philosophy is that IRQ handlers should be quick. If you need to respond to something in them, use a flag and do that in the main thread instead.

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

Check also the interrupt priorities. If reaction to the EXTI can wait, make it lower priority than the UART, then the UART interrupt can preempt it. Others already wrote about UART DMA with size 1.