2023-07-27 05:59 AM
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
SPI
NVIC
Any help would be amazing
2023-07-27 06:27 AM
> 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.
2023-07-27 06:46 AM - edited 2023-07-27 06:47 AM
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();
}
2023-07-27 07:22 AM
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.
2023-07-27 07:27 AM
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
2023-07-27 07:35 AM - edited 2023-07-27 07:38 AM
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.
2023-07-27 10:49 PM
You suggest i moce HAL_SPI_TransmitReceive outside of the EXTI_Rising_Callback? or just an other function entirely
2023-07-28 06:58 AM
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.
2023-07-28 12:14 PM
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.