cancel
Showing results for 
Search instead for 
Did you mean: 

UART DMA usart2 to uart1

marwen_azouzi
Associate II
Posted on May 16, 2012 at 03:40

Hi , i want to transfer the incoming data on uart2 to uart1 using DMA i d'ont know where is the problem with my code

8 REPLIES 8
marwen_azouzi
Associate II
Posted on May 16, 2012 at 03:42

/* Includes ------------------------------------------------------------------*/

#include ''stm32f10x.h''

#include ''stm32f10x_gpio.h''

#include ''stm32f10x_rcc.h''

#include ''stm32f10x_usart.h''

#include ''stm32f10x_dma.h''

/** @addtogroup Examples

  * @{

  */

/* Private typedef -----------------------------------------------------------*/

typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus;

/* Private define ------------------------------------------------------------*/

void RCC_Configuration(void)

{

/* Enable DMA clock */

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

/* Enable GPIO bank clock */

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

/* Enable UART clock */

RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

}

/******************************************************************************/

void GPIO_Configuration(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

/* Configure USART Tx as alternate function push-pull */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;  // PA.09 USART1.TX

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;  // PA.09 USART1.TX

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOA, &GPIO_InitStructure);

/* Configure USART Rx as input floating */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; // PA.10 USART1.RX

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // PA.10 USART1.RX

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

GPIO_Init(GPIOA, &GPIO_InitStructure);

}

/******************************************************************************/

void USART_Configuration(void)

{

USART_InitTypeDef USART_InitStructure;

/* USART resources configuration (Clock, GPIO pins and USART registers) ----*/

/* USART configured as follow:

- BaudRate = 115200 baud

- Word Length = 8 Bits

- One Stop Bit

- No parity

- Hardware flow control disabled (RTS and CTS signals)

- Receive and transmit enabled

*/

USART_InitStructure.USART_BaudRate = 9600;

USART_InitStructure.USART_WordLength = USART_WordLength_8b;

USART_InitStructure.USART_StopBits = USART_StopBits_1;

USART_InitStructure.USART_Parity = USART_Parity_No;

USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

/* USART configuration */

USART_Init(USART2, &USART_InitStructure);

USART_Init(USART1, &USART_InitStructure);

/* Enable the USART1 */

USART_Cmd(USART2, ENABLE);

USART_Cmd(USART1, ENABLE);

}

/******************************************************************************/

void DMA_Configuration(void)

{

// USART1 Channel 4, USART2 Channel 7, USART3 Channel 2

DMA_DeInit(DMA1_Channel7);

DMA_Cmd(DMA1_Channel7, DISABLE);

}

/******************************************************************************/

void DMA_USART()

{

DMA_InitTypeDef DMA_InitStructure;

/* Disable the DMA Controller/Channel */

DMA_DeInit(DMA1_Channel7);

/* USART1_Tx_DMA_Channel (triggered by USART1 Tx event) Config */

DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART2->DR;

DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&USART1->DR;

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;

DMA_InitStructure.DMA_BufferSize = 0x20;

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;

DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

DMA_Init(DMA1_Channel7, &DMA_InitStructure);

/* Enable the DMA Controller/Channel */

DMA_Cmd(DMA1_Channel7, ENABLE);

/* Enable USART1 DMA TX request */

USART_DMACmd(USART2, USART_DMAReq_Tx, ENABLE);

/* Wait of DMA completion */

while(DMA_GetFlagStatus(DMA1_FLAG_TC4) == RESET);

/* Loop until the end of transmit */

while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);

}

/******************************************************************************/

int main(void)

{

RCC_Configuration();

GPIO_Configuration();

USART_Configuration();

DMA_Configuration();

DMA_USART();

/* Infinite loop */

while(1);

/* does not exit - kind of important */

return(1);

}

Posted on May 16, 2012 at 04:19

Hi , i want to transfer the incoming data on uart2 to uart1 using DMA i d'ont know where is the problem with my code

There are a bunch, but the most fatal is I don't think you can do a Peripheral-to-Peripheral in this fashion. You need to Rx DMA into one buffer, and then Tx DMA back out to the other USART. You also need this buffer to provide some elasticity because the USART's aren't synchronous.

You don't want to be incrementing the address.

Actually what you are doing here would be better implemented with a piece of wire, with the added benefit that it wouldn't add ~10 bit times worth of delay into the signal.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
marwen_azouzi
Associate II
Posted on May 16, 2012 at 05:15

In the data sheet as showen  section 9.2

DMA main features

Peripheral-to-memory and memory-to-peripheral, and peripheral-to-peripheral

transfers

�? Access to Flash, SRAM, APB1, APB2 and AHB peripherals as source and destination

�? Programmable number of data to be transferred: up to 65536

I use uart as asynchronous peripheral

frankmeyer9
Associate II
Posted on May 16, 2012 at 14:12

> I use uart as asynchronous peripheral

But one uart is not necessarily synchonious to the other.

I can't see the special advantage of the DMA, compared to the wire clive proposed.

A simple RS232 echo could be done cheaper, and anything else will not work with uart-to-uart DMA.

marwen_azouzi
Associate II
Posted on May 16, 2012 at 14:29

I wanted

a less

cluttered

that's why

I used

DMA

THx for help 

Posted on May 16, 2012 at 15:57

I use uart as asynchronous peripheral

The baud rates have errors (ie +1%, -2%), if the incoming data is slightly faster than the data going out you're going to have issues with tying them together. Using flow control here? Your method has no way to sample the incoming data for processing, and doesn't address parity, framing, or other errors that may occur. The following might work, but I'm skeptical of it's function/usability

/* USART1_Tx_DMA_Channel (triggered by USART1 Tx event) Config */
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART2->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&USART1->DR;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = 0x20;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel7, &DMA_InitStructure);

Honestly, I think you'd want to be doing this via the USART2 RX DMA, not the USART1 TX. As you want the DMA occuring when you have data, not when the transmitter is empty. Like I said, the less cluttered design is to wire the pins together.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
stefan239955_st
Associate
Posted on October 30, 2013 at 17:37

So nethertheless it is not described in the Reference manual Peritheral to Peritheral will work?

We think about to sample some currents and make them available for an FPGA.

I Think about to transfer ADC2->DR to SPI->Transmit Register would that work?

or would it be better to have it transfered to a memory location first?

best regards Stefan

Posted on October 30, 2013 at 19:00

Possibly, you'd have to experiment.

From a DMA perspective the peripheral-to-peripheral is nuanced, a peripheral on a different APB is a memory transfer, on the same bus you're looking at memory-to-memory.

The issue is with plumbing, a peripheral-to-memory transfer could be achieved directly, where-as other modes would require a holding register, and the operation decomposed into two separate operations.

The DMA in your example would be in-attentive to the SPI TXE state, if the periodicity of the transfer was sufficiently long that probably wouldn't matter. The latency would be a lot lower, and would require a lot lower interrupt loading and buffer management.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..