0

I'm trying to get a code to work that triggers an interrupt for a variable data size coming to a RX input of a STM32 board (not discovery) in DMA Circular mode. ex.:CONNECTED\r\nDATAREQUEST\r\n

So far so good, I'm being able to receive data and all, while also triggering the DMA interrupt.

I will then create a sub RX message processing buffer breaking down each \r\n to a different char array pointer.

msgProcessingBuffer[0] = "COM_OK"

msgProcessingBuffer[1] = "DATAREQUEST"

msgProcessingBuffer[n] = "BlahBlahBlah"

My problem comes actually from the trigger of the interrupt. I would like to trigger the interrupt from any amount of data and processing any data received.

If I use the interrupt request bellow:

HAL_UART_Receive_DMA(&huart1,uart1RxMsgBuffer, 30);

The input buffer will take 30 bytes to trigger the interrupt, but that's too much time to wait because I would like to process the RX data as soon as a \r\n is found in the string. So I cannot wait for the full buffer to fill to begin processing it.

If I use the interrupt request bellow:

HAL_UART_Receive_DMA(&huart1,uart1RxMsgBuffer, 1;

It will trigger as I want, but there is no point on using DMA in this case because it will trigger the interrupt for every byte and will create a buffer of just 1 byte (duh) just like in "polling mode".

So my question is, how do I trigger the DMA for the first byte received but still receive/process all data that might come after it in a single interrupt? I believe I might be missing some basic concept here.

Best regards, Blukrr

3 Answers3

1

In short: HAL/SPL libraries don't provide such feachures.

Generally some MCUs, for example STM32F091VCT6 have hardware supporting of Modbus and byte flow analysis (interrupt by recieve some control byte) - so if you will use such MCU in you project, you can configure receive by circular DMA with interrupts by receive '\r' or '\n' byte.

And I repeat: HAL or SPL don't support this features, you can use it only throught work with registers (see reference manuals).

imbearr
  • 999
  • 7
  • 22
1

I was taking a look at some other forums and I've found there a work around for this problem.

I'm using a DMA in circular mode and then I monitor the NDTR which updates its value every time a byte is received through the UART interface. Then I cyclically call a function (in while 1 loop or in a cyclic interrupt handler) that break down each message part always looking for /n /r chars. This function also saves the current NDTR value for comparison if it has changed since the last "while 1" cycle. If the NDTR has changed since last cycle I wait a couple milliseconds to receive the remaining message (UART it's too slow to transmit) and then save those received messages in a char buffer array for post processing.

If you create a circular DMA buffer of about 50 bytes (HAL_UART_Receive_DMA(&huart1,uart1RxMsgBuffer, 50)) I think it's enough to compensate any fluctuations in the program cycle.

0

In the mean time I opened a ticket to ST and they confirmed what you just said they also added:

SOLUTION PROPOSED BY SUPPORTER - 14/4/2016 16:45:22 : Hi Gilberto,

The DMA interrupt requests available are listed on Table 50 of the Reference Manual, RM0090, http://www.st.com/web/en/resource/technical/document/reference_manual/DM00031020.pdf. Therefore, basically, the DMA interrupt can only trigger at the end of one of these events.

• Half-transfer reached • Transfer complete • Transfer error • Fifo error (overrun, underrun or FIFO level error) • Direct mode error

Getting a DMA interrupt to trigger upon reception of a specific character in your receive data stream is not possible. You may want to trigger the interrupt when you receive packets of say 30 bytes each and then process the datastring to check if your \r\n chars have arrived so you can process the data block.

Regards, MCU Tech Support