Skip to main content
mogwaifactory
Associate II
November 19, 2015
Question

STM32F407 DMA Transfer Peripheral to Peripheral

  • November 19, 2015
  • 8 replies
  • 7565 views
Posted on November 19, 2015 at 18:32

Hello,

I'm wondering if it is possible like with the pic32 to initiate a DMA transfer from peripheral to peripheral. So far the documentation I've read specifies periph to memory, memory to periph, or memory to memory.

The idea is to forward every bytes from USART2_RX to USART6_TX and vice versa.

I'm currently doing it with interrupts, but I would like to lighten the MCU a little bit because it does a lot of things in background.

Should I use a small buffer in memory and do periph to mem, then mem to periph?

Thanks for your input.

Dan.

#stm32 #stm32f407 #uart #stm32f4

Note: this post was migrated and contained many threaded conversations, some content may be missing.
This topic has been closed for replies.

8 replies

Tesla DeLorean
Guru
November 19, 2015
Posted on November 19, 2015 at 19:49

Memory-to-Memory can cover both peripheral buses, the DMA1 associates internally with APB1 devices, DMA2 w/APB2

If the triggering device is on APB2, you should be able to use it's DMA Channel/Stream to copy to another peripheral or memory location.

I honestly don't see much value in forwarding between two USARTs like that and not having the data in memory. What you're describing can be easily done with bits of wire.

Suggest you experiment.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
mogwaifactory
Associate II
November 20, 2015
Posted on November 20, 2015 at 09:34

Thank you for your input Clive, the only reason I'm passing through the mcu is that the user can change the baudrate from the front panel to the first uart, but from the second uart to the fiber converter, this one is fixed. The mcu serves then as a buffer if the first baudrate is lower (it won't be higher to prevent bottleneck).

I'll take a look at what you said.

Thanks,

Dan.

jpeacock
Associate
November 20, 2015
Posted on November 20, 2015 at 15:17

From the RM:

''

Dual AHB master bus architecture, one dedicated to memory accesses and one

dedicated to peripheral accesses''

There's only one AHB port to peripherals.  Memory to memory works (only on DMA2) because the AHB peripheral port on DMA2 can also access memory.  For a peripheral to peripheral DMA the AHB memory port would have to also support peripherals (according to the RM it doesn't).

  Jack Peacock
AVI-crak
Senior
October 4, 2017
Posted on October 04, 2017 at 07:40

This is part of the truth.

The main thing in working with the periphery is the expectation of readiness, naturally on the hardware level. If you use DMA in memory-memory mode, then the waiting limit is replaced by the priority level. DMA will work at the first space speed, even if the receiver is an absolute brake.

However, if the speed of the receiver is higher than the source - the focus may turn out. For example, start DMA from the timer (does not require confirmation), take data from memory and write to the periphery. Or, to take data from a slow USART and write to a fast one, the slow USART should serve as the starting source.

But the reverse process is impossible, why the meaning of the solution is completely lost.
mogwaifactory
Associate II
November 20, 2015
Posted on November 20, 2015 at 16:50

Hi Jack,

That confirms what I read on the AN4031.

http://www.st.com/web/en/resource/technical/document/application_note/DM00046011.pdf

Thanks,

Dan.

waclawek.jan
Super User
November 20, 2015
Posted on November 20, 2015 at 19:28

I beg to disagree. IMO, you can use the peripheral port of the DMA stream ''assigned'' to slower UART's Rx to read from that one, triggered by that one, and the memory port of that DMA stream to write to the faster UART's Tx. The ''vice versa'' generally can't work, you would experience data loss when going from faster to slower; but I understand that there might be specific circumstances which would throttle the slower enough to get it working.

Why don't you simply try, it's a one hour's fun exercise directly in the debugger, you don't need to write a single line of code. Set up both UARTs (clock, baudrate, enable rx tx), then set up the respective DMA stream, send data to first UART's Rx and watch on debugger (not the UARTs' registers! the DMA registers) what's hapening, and eventually the data coming out the second UART's Tx.

JW

Code Wrangler
Associate II
October 2, 2017
Posted on October 02, 2017 at 22:57

I just did this experiment and unfortunately, Mr. Peacock is right - It cannot be done [EDIT: It can be done. See Jan's post below]. Here is a brief overview of my experiment (chip is STM32F429):

USART6 (APB2 bus / DMA2) Rx & Tx externally connected via loopback wire

USART6 Tx transmits a buffer via DMA

USART6 Rx receives via DMA

Results:

USART6 Rx - Peripheral -> Memory - MINC (Memory Increment) Enabled - Points to SRAM address - Works

USART6 Rx - Peripheral -> Memory - MINC (Memory Increment) Disabled - Points to SRAM address - Works

USART6 Rx - Peripheral -> Memory - MINC (Memory Increment) Disabled - Points to GPIOE->ODR - No output

USART6 Rx - Peripheral -> Memory - MINC (Memory Increment) Disabled - Points to DAC1->DHR8R1 - No output

Both GPIOE & DAC1 enabled before the start of DMA and manually tested by writing to output register and seeing the results on a scope

waclawek.jan
Super User
October 3, 2017
Posted on October 03, 2017 at 23:07

In attachment is a simple program, which does what you outlined above: one DMA2 stream transfers some bytes from memory to USART6, USART6's Tx is externally looped back to Rx, another DMA2 stream transfers the received byte to GPIOx_ODR. If run on a DISCO-F4, the LEDs will blink according to the data pattern in RAM (provided jumper is installed between USART6 RX-TX. i.e. PC6-PC7).

JW

________________

Attachments :

cw.zip : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HyOc&d=%2Fa%2F0X0000000b72%2FmUCrYYPDfWGD_EXJ9yje9OahOMABf7bovLyQtoZA9.w&asPdf=false

cw.zip : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HyOh&d=%2Fa%2F0X0000000b73%2FeJ7PYtsKf9yUTnmra8XdbcDwfZkJR3DUasB9E8Ql0Ac&asPdf=false
mogwaifactory
Associate II
November 20, 2015
Posted on November 20, 2015 at 20:29

I Jan,

I was about to try it this weekend when I'm finished with another more urgent project.

I think the vice versa would work in my case because most of the time, both uarts will be at the same baudrate, it's a very rare case where the board would buffer a slower baudrate. And if that happens, I have a rolling buffer ready. Plus the data exchanged are just ascii lines to drive a highspeed camera, so no continuous stream that will bottleneck.

Thanks for your input,

Dan.

waclawek.jan
Super User
November 21, 2015
Posted on November 21, 2015 at 11:46

> I think the vice versa would work in my case because most of the time, both uarts will be at the

> same baudrate, it's a very rare case where the board would buffer a slower baudrate. And if

> that happens, I have a rolling buffer ready.

''rolling buffer'' and ''periheral to peripheral DMA'' are two contradictory things.

You still can handle the incoming faster data using DMA but storing into RAM; you need to handle the outgoing slower data in software though.

JW

Rostyslav S
Associate II
November 22, 2017
Posted on November 22, 2017 at 15:34

Implemented the same using STM32Cube.

I am working on the same task to forward data between two UARTs using DMA. In my case two devices are connected to central device via UARTs. Central device acts like a bridge between them.

In my case, DMA was enabled for UART4_RX with Peripheral to memory direction. Mode is set to Circular, priority high.

The same settings applies to UART5_RX DMA. See screenshot below.0690X00000608wHQAQ.png

UART4 and UART5 are configured as 115200bits/s, 8bit word length, no parity and one stop bit.

In source code I have added two lines of code:

HAL_UART_Receive_DMA(&huart4, (uint8_t *) &(USART5->TDR), 1);

HAL_UART_Receive_DMA(&huart5, (uint8_t *) &(USART4->TDR), 1);

This task appeared to be easier than I expected, so I am double checking if everything is set upped correctly.

Questions:

- DMA is configured to transfer one byte from ingress UART4 register to egress UART5 register.

UART4 is configured as 8bit word length + 1 stop bit. So I assumed that stop bit will be validated and then skipped by UART controller and exactly 8bits will be placed in UART4 RDR register. Afterwards RDR content will be placed directly to UART5 TDR.

Right?

- There will be no data loss as when any byte arrives to UART it will be immediately forward to another UART.

Is it possible that DMA will not be able to serve next request if previous DMA transfer is in progress?

waclawek.jan
Super User
November 22, 2017
Posted on November 22, 2017 at 21:39

Is it possible that DMA will not be able to serve next request if previous DMA transfer is in progress?

If the receiving USART's baudrate is higher than the transmitting one, then DMA will simply shovel the incoming bytes onto the still working USART and they will get lost.

JW

Rostyslav S
Associate II
November 23, 2017
Posted on November 23, 2017 at 08:43

Agree, I assume both baud rates are always equal