We can think of DMA as co-processor who can only transfer data between different memories, in our case between peripheral data register UART and temporary DMA buffer we assign to it.
In general, before you start DMA, you have to assign number of bytes DMA should transfer before you say .
As always, there were many more changes to the Rails codebase than we can cover here - if you’re interested, you can check out the full listing of commits from the last two weeks. I will cover the highlights from the last two weeks. 39 people contributed to Rails in the last two weeks, including 9 for the first time! If you’d like to see yourself on that board, why not check out the list of open issues, or get involved in the core discussion list.
Every DMA in STM32 supports half-transfer and transfer complete interrupts, so the only problem is if IDLE line is supported in particular family or not.
This example uses single buffer acting like double buffering.
But we know, in general, UART can receive data at any time.
By UART specifications, we don’t know when and how many of bytes will arrive.
/** * \brief Actually process USART data received over UART * \note Called from \ref check_dma_receive function * \param[in] d: Pointer to data to process * \param[in] len: Length of data in units of bytes *//** * \brief Periodically check for new incoming data from DMA * \note Call this function either in main loop (one thread in RTOS, or main while loop) or from timer interrupt * \note This function must be called faster than time used to fill entire DMA buffer * Frequency of this function call depends on: * - USART baudrate * - USART number of bytes at a time (stream length if exists) * - DMA RX buffer size * * Example uses 921600 baudrate configuration, which means that every byte takes around 10us * If you call this function every 1ms, in worst case you need 1k buffer to be safe.
* This applies if you have a big stream of RX data on USART.
After a nice discussion in comments and possible support for other devices where DMA streams are not available (other DMA structure), here is an implementation without using IDLE line detection and without using any DMA interrupts.
DMA works in circular mode and user is responsible to read the data from DMA buffer periodically otherwise you will have data loss because DMA will overwrite your non-read data. Example was developed on NUCLEO-L073 development board, but concept should work on every STM32.
If we now do our example again by receiving between in this example), we would set DMA to receive 20 bytes.
Since we will only receive 14 bytes, we will get IDLE line detection on UART RX line.
In this case, every received byte is manipulated by CPU by jumping to appropriate UART interrupt service routine.