Just for curiosity, I tried to do it in a STM32F411 (A lot more basic that yours).
The main problem here is that you can't do it with a single dma request.
Ex. a single ADC trasnfer (might be 16 or 32bit transfer) needs to be broken into multiple 8-bit transfers for the UART.
And the UART DMA needs a request for each one of these transfers.
So you must do somthing to generate those multiple DMA requests between each ADC transfer. I used timers.
This is how I got it working without any cpu intervention, no buffers, no interrupts:
- Timer 2 TRGO signal drives the ADC DMA request, transfers the adc result into "ADC_VALUE" variable.
- DMA: Circular, peripheral to mem, half-word both, no increase (Updates the same memory variable).
- Timer 3 is configured to run exactly at (n sending bytes) times faster the speed of Timer2, uses the dma stream associated with T3_Update signal.
- DMA: Circular, mem to peripheral, byte size in both, mem increase.รง
- Timer 3 DMA belongs to DMA1, this controller can only access to APB1 peripherals (At least in F4 series), so in this case USART2 was used.
- At 96MHz, the timer period for 25.6KHz is 3750-1.
To send 2 bytes, Timer 3 period is 1875-1, but 4 isn't a clean divisor (You need to have both timers perfectly synced).
So in this example I send 5 bytes for every ADC conversion, Timer 3 period is 750-1
Then:
- Start ADC (Doesn't really start, waits for TRGO signal)
- Clear both timers counters and flags.
- Start DMA channel attached to Timer 3 (Doesn't start until timer3 triggers it)
- Enable Timer3 DMA update signal
- Start Timer2 and Timer 3 (Doesn't need interrupts)
Now you'll get this:
#< -------------- ADC CONVERSION ------------- >#< -------------- ADC CONVERSION ------------- >#
#< TX[4] >|< TX[3] >|< TX[2] >|< TX[1] >|< TX[0] >#< TX[4] >|< TX[3] >|< TX[2] >|< TX[1] >|< TX[0] >#
Pros:
- Absolutely zero cpu intervention, no interrupts required, not even for the DMA (In circular mode, it will reset itself)
- I've tested it using 1.5MBit USART, 25.6Ksps ADC, and sending 5 bytes for sample (5*25.6K=1.28Mbit), worked perfectly fine.
Downsides:
- Transmits in Little-endian (lower bytes first).
- The sync between timers must be perfect, or it will drift and start sending mixed old/new readings.
Your STM32 is a lot more powerful, so it might be able to do it in a better way, it should be pretty easy to adapt the method to your needs.
Attached simple demo as reference.