Interrupt Problems with HAL_UART_Receive_DMA

bueddi wrote on Thursday, December 21, 2017:

Hello,

I’m runnig a STM32L476VGT with FreeRTOS V9.0.0 with serveral tasks. At my GNSS-task I want to receive GNSS-data from a MAX-M8 from ublox in DMA-mode.

The problem is that it works fine in the first loop and it gives the GNSS-data back. But in the second loop of the main-task an undefinded interrupt occure and the code jump into the default-handler in startup_stm32l476xx.s.

HAL_UART_Receive_DMA(huart_gnss, uart_rx_buf, GNSS_UART_BUFSIZE);
“HAL_UART_Receive_DMA” returns a “HAL_OK” and I get my GNSS-data in a correct form. But in the second run an undefined interrupt occurs.

When I use another receive-function like
** HAL_UART_Receive(huart_gnss, uart_rx_buf, GNSS_UART_BUFSIZE, GNSS_UART_REC_TIMEOUT);**
which uses the blocking-mode instead of DMA-mode, the undefined interrupt doesn’t occure.

Why do I post the problem in the freetos-forum?
I work with “Eclipse Oxygen” and use the “FreeRTOS”-plugin, which give me in the “Task List”-window an good overview about the current task-states. When I use “HAL_UART_Receive_DMA” the gnss-task is in “suspend”-state and when I want to wake it with “osThreadResume(gnssTaskHandle);” the undefinded interrupt occure.

So, here are my questions:
Should I pay attention to something special when I use DMA-transfer in a task?
Does FreeRTOS have an other way to handle with DMA?
Can I avoid such problems when I use events instead of interrupts?

Addtionally, here are my important code parts, which don’t working:

void MainTask(void const * argument)
{
    while(1) {
		osThreadResume(gnssTaskHandle);
		modem_init();

		modem_connect_flag = modem_connect();

		if(modem_connect_flag == MODEM_STATE_IS_CONNECTED) {

			gnss.timestamp = entras_get_epoch();

			if (gnss_gga.fix != fix_invalid) {
				gnss.latitude = (double)gnss_gga.latitude/GNSS_PRESERVE_POS;
				gnss.longitude = (double)gnss_gga.longitude/GNSS_PRESERVE_POS;
			}
            
			modem_checkConnection();
		}
		modem_shutdown();

		osDelay(SERVER_SEND_INTERVAL);
	}
}


void StartGnssTask(void const * argument)
{
  /* USER CODE BEGIN StartGnssTask */

    gnss_init();

    while(1) {
        osThreadSuspend(NULL);

		osThreadResume(mainTaskHandle);

        if (gnss_get_data(&gnss_gga) == GNSS_STATUS_FIX) {
            status.gnss_ok++;
        }
        else {
            status.gnss_err++;
            osDelay(GNSS_DELAY_RETRY);
        }
    }
  /* USER CODE END StartGnssTask */
}


gnss_status_t gnss_get_data(gga_data_t *data) {
    uint8_t uart_rx_buf[GNSS_UART_BUFSIZE] = {0};
    char *gga_str = NULL;
    char *zda_str = NULL;
    data->fix = fix_invalid;

    while (1) {
        while (gga_str == NULL) {
            fill_memory(uart_rx_buf, GNSS_UART_BUFSIZE, MEM_FILL_ZERO, 0);

            /* START Receive Function */
            rx_state = HAL_UART_Receive_DMA(huart_gnss, uart_rx_buf, GNSS_UART_BUFSIZE);
            /* END Receive Function */

            if (rx_state == HAL_TIMEOUT || rx_state == HAL_ERROR) {
            	return GNSS_STATUS_NO_COM;
            }
            
            zda_str = strstr((char *)uart_rx_buf, "$GNZDA");
            gga_str = strstr((char *)uart_rx_buf, "$GNGGA");
        }
        
        gga_str = NULL;
        zda_str = NULL;
       
        osDelay(GNSS_TIME_BETWEEN_NEXT_FIX);
        
        return GNSS_STATUS_OK;
    }
}

rtel wrote on Thursday, December 21, 2017:

I’m not sure this is related to FreeRTOS, but could be if you are using
FreeRTOS API functions from inside the interrupts - in which case you
will need to ensure the interrupt priorities are set correctly, and as
this is an STM, also that you ensure all priority bits specify a
preemption priority rather than a sub priority. More information is
available on this page: https://www.freertos.org/RTOS-Cortex-M3-M4.html

osThreadResume() is not a native FreeRTOS function, so I can’t help
there, but is the thread really in the Suspended state? Did you
actually place the task into the Suspended state using vTaskSuspend(),
or whatever the equivalent is in the API abstraction you are using?
Also, don’t use suspending/resuming as a mechanism for synchronising a
task with an interrupt, if that is what you are doing, as per
description on the API documentation page here:
https://www.freertos.org/taskresumefromisr.html