Skip to main content
Sergio Fabbrini
Associate
April 5, 2017
Solved

HAL UART DMA RX - variable packet length & counter reset

  • April 5, 2017
  • 4 replies
  • 2318 views
Posted on April 05, 2017 at 12:48

Hello

I'm trying to read data from a GPS module that send packets with different lengths. I connected the rx line to another pin and enabled an interrupt on it, in this way I can 'timeout' the end of packet (packets are one per second, plenty of time between a pair).

I set-up DMA on UART (tried both circular and normal) because I don't need UART interrupt to read data. I would like to read data on timeout, but after the read I need to reset the state of DMA in order to empty the buffer and restart writing from index 0. I need to know the dat tranfered too.

I'm using an STM32F101 device with HAL library version 1.4.0.

No luck with examples from ST nor documentation around internet.

Thanks for your help.

Sergio

    This topic has been closed for replies.
    Best answer by Sergio Fabbrini
    Posted on April 10, 2017 at 14:37

    Thanks for your reply.

    First of all, I'm using a GPS module that send NMEA sentences, net binary one. They are array of chars to be received and parsed.

    I'm pretty sure the interrupt timeout is working well, because I'm counting the number of times I enter the 'packetReady' function and is compatible with 1 pkt per second (running the serial at 38400baud I have a lot of spare time between two transmission).

    UART in IRQ mode want to know the amount of data to be received, but I don't know it in advance. I tried to read the sentences one byte per time, but it's too complex. I set-up a circular DMA buffer and I can read from it.

    The only thing I was not sure to do correctly is e reset of the buffer, but now it seems to work correctly. I'm using

       HAL_UART_DMAStop(&huart1);

    right after the end of packet, then I precess the sentence and call

       if (HAL_UART_Receive_DMA(&huart1, (uint8_t *) dmaRxBuffer, 2048) != HAL_OK) {

          Error_Handler();

       }

    again to start the DMA acquisition again. This seems to work, because DMA over-run error is not fired, so I assume the vector start from index 0 every time.

    I think it should be simpler than that, but at least it works.

    Thnk you all for your contribution.

    Bye.

    4 replies

    Tesla DeLorean
    Guru
    April 5, 2017
    Posted on April 05, 2017 at 16:44

    GPS processing can be done quite effectively via a USART and IRQ.

    If I was using DMA, I'd set up a circular buffer, interrupting on the HT and TC thresholds, have the array holding uint16_t data and marking the values I'd pulled by tagging a high order bit not set by the USART data (USARTx->DR is 16-bit wide). This way a periodic interrupt could the timeout, and determine buffer position.

    Alternatively one might use the 1PPS from the GPS to trigger a one-shot timer to start processing where packet data would be complete.

    Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
    howard n2wx
    Associate III
    April 5, 2017
    Posted on April 05, 2017 at 21:54

    Are the data NMEA formatted (with the leading '$')?

    Tesla DeLorean
    Guru
    April 5, 2017
    Posted on April 05, 2017 at 22:09

    NMEA sentences yes, along with trailing <CR><LF> pairs, but binary packets like UBX or RTCM have neither.

    Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
    Sergio Fabbrini
    Sergio FabbriniAuthorBest answer
    Associate
    April 10, 2017
    Posted on April 10, 2017 at 14:37

    Thanks for your reply.

    First of all, I'm using a GPS module that send NMEA sentences, net binary one. They are array of chars to be received and parsed.

    I'm pretty sure the interrupt timeout is working well, because I'm counting the number of times I enter the 'packetReady' function and is compatible with 1 pkt per second (running the serial at 38400baud I have a lot of spare time between two transmission).

    UART in IRQ mode want to know the amount of data to be received, but I don't know it in advance. I tried to read the sentences one byte per time, but it's too complex. I set-up a circular DMA buffer and I can read from it.

    The only thing I was not sure to do correctly is e reset of the buffer, but now it seems to work correctly. I'm using

       HAL_UART_DMAStop(&huart1);

    right after the end of packet, then I precess the sentence and call

       if (HAL_UART_Receive_DMA(&huart1, (uint8_t *) dmaRxBuffer, 2048) != HAL_OK) {

          Error_Handler();

       }

    again to start the DMA acquisition again. This seems to work, because DMA over-run error is not fired, so I assume the vector start from index 0 every time.

    I think it should be simpler than that, but at least it works.

    Thnk you all for your contribution.

    Bye.

    Ivchenko Dmytro
    Associate
    June 20, 2017
    Posted on June 20, 2017 at 16:31

    can you help me to implement gps on stm32f103 please

    Salih
    Visitor II
    August 23, 2019

    Hi,

    I am Salih. This solution is great.

    I have the same problem. Can you share the code with me to help? the size of the data I receive is uncertain and I need to read it in the array.

    Thanks.