0
votes

I have a known serial stream format that I am capturing via the DMA. It has header and footer bytes. But sometimes the MCU starts capturing in the middle of the stream and then the sync is out because the DMA is looking for a set number of bytes. I have read of people using circular buffers, but I have struggled to grasp this concept.

Instead, I was thinking of disabling the DMA and enabling the a serial interrupt at the start up of the MCU. Then cycle through each byte that is captured by the interrupt to find the start byte. Then, once I have found the start byte, disable the serial interrupt capturing and enable the DMA to take over the capturing of the stream.

Does this sound feasible? Thanks for any input.

I am using STM32 HAL libs with the new STM32 IDE that includes STM32 CubeMX.

2
DMA is looking for a set number of bytes DMA is not looking for anything. As you do not understand the basics - I advice to drop the async way of handling and stick with single threaded0___________
@P__J__ You are correct, DMA is not looking for anything. But the USART itself may have character recognition and its corresponding interrupt. Another extended feature might be configurable timeout.KIIV
@P__J__, yes, I understand that the DMA itself is not looking for a number of bites. It is one of the definitions that is required when setting u the USART for DMA because it needs to know how much space to reserve in the memory bank.Dylan144GT
Yes, I do know the time between each packet - it is consistent and there is enough time between each packet to ensure that the time out would not allow the interrupt to take data from the next packet. My packet duration is 3ms and the packet is updated every 9ms. So I could set a timeout of 4ms. This was a solution that I wanted to implement but I could not find out how to set a timeout. Would you know?Dylan144GT
Really briefly: CR2 register for enabling it, RTOR for setting the timeout and USART_ITConfig(USART1,USART_IT_RTO,ENABLE); for enabling interrupt + some handlingKIIV

2 Answers

0
votes

If I understand your reference to circular buffers correctly, the concept is simple. You have a large buffer with a write pointer and a read pointer. The write function writes data into the buffer from the write pointer onward, taking care that once it reaches the end of the buffer, it wraps around and dumps the data at the beginning of the buffer and onward. Then you need a reader function that reads the data from the read pointer onward, and again, taking care of wrap around at the end of the buffer.

Both the read and write pointers start at the beginning of the buffer. The two conditions that you have to check are: 1) When the read pointer is at the same location as the write pointer, there is nothing (more) to read. 2) When the write pointer increments and runs into the read pointer location, you have a buffer overflow condition. This should never happen, so either you must use a larger buffer, or have the reader task runs more frequently, or you start throwing things out.

So in your scenario, the DMA just dumps data, and your reader task looks for the header bytes and processes the data until it finds the footer bytes.

0
votes

As the protocol has idle gaps between packets, you can use the idle interrupt feature of the UART to synchronize the receiver.

Enable the UART interrupt, simply start receiving with DMA, and set UARTx->CR1 |= USART_CR1_IDLEIE. Whenever the idle interrupt is triggered, look at the DMA channel, if it's still running, stop the transfer and discard the input buffer (as this means that the receive was started in the middle of the packet) and start receiving the next packet.