cancel
Showing results for 
Search instead for 
Did you mean: 

DMA Memory To UART5

dclark9
Associate II
Posted on June 25, 2012 at 15:38

Hi,

I'm having an issue setting up a DMA to transfer data from a 2 element uint8_t array to UART5. The code works, but the UART only sends out the first byte and having tried lots of different things I don't understand what I need to do to make it push out the whole buffer. Code is as follows :-

uint8_t myBuffer[2] = {0x55, 0x55};
DMA_DeInit(MEZZANINE_DMA_TX);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&UART5->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) myBuffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = 2;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
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_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(MEZZANINE_DMA_TX, &DMA_InitStructure);
DMA_Cmd( MEZZANINE_DMA_TX, ENABLE );

Many thanks in advance for any responses, Dave

#dma #stm32-uart-usart
29 REPLIES 29
georpo
Associate
Posted on December 29, 2012 at 22:31

Hello,

I managed to transmit the buffer thanks to your examples

but I have a silly question.

What I need is to write data to the buffer and then the buffer should flush out

of the USART tx and stop until I write new data to the buffer.

With the above examples, the buffer keeps transmitting for ever

and also it does not leave me do anything else.

My CPU is occupied by this endless transmitting.

Any ideas?

Thanks,

George.

Posted on December 30, 2012 at 00:28

The example tries to minimize the amount of code required to illustrate basic DMA function, however the CPU utilization should be pretty minimal as the DMA is handled off core. Placing a WFI in the while(1) loop should illustrate this.

To handle a more practical implementation you'd need to provide some buffering, either in the form of a ring buffer, or a collection of buffers, which would be feed to the DMA unit at each TC (Transmit Complete) interrupt from the DMA unit, or the DMA could be turned off if no additional buffers were full. Basically you'd want to dispatch each new buffer to the DMA unit, and turn off the circular function. You should only dispatch buffers when output data is available rather than trying to play catch up, as there is no additional flow control.

Providing a full featured buffering demo is beyond the scope of my forum participation, and also tends to wade into to personal implementation preferences which probably won't match your specific needs/requirements.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on October 28, 2013 at 14:32

Was there a question there, or an attempt to post from a mobile device?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
jdcowpland
Associate II
Posted on December 13, 2013 at 17:58

Hi Clive,

This code looks really good and has been really useful in setting up my RX DMA, but just wondering how to go about sending with the TX DMA? Have you got any examples of sending various different strings using it?

Posted on December 13, 2013 at 18:28

This code looks really good and has been really useful in setting up my RX DMA, but just wondering how to go about sending with the TX DMA? Have you got any examples of sending various different strings using it?

 

There is an example at the top end of the thread dealing with TX DMA, and discussion devolved from there.

Do I have a prepacked example, no, but it would just need some slight modification. You'd need to use the DMA in normal rather than circular mode, and at each TC interrupt you'd reprogram the DMA to do the next string.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on December 13, 2013 at 19:11

// STM32 USART6 DMA TX MULTI (Tx PC.6, Rx PC.7) STM32F4DIS-BB - sourcer32@gmail.com
#include ''stm32f4_discovery.h''
#include <
string.h
>
/**************************************************************************************/
void RCC_Configuration(void)
{
/* --------------------------- System Clocks Configuration -----------------*/
/* USART6 clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6, ENABLE);
/* GPIOC clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
/* DMA2 clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
}
/**************************************************************************************/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*-------------------------- GPIO Configuration ----------------------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; // PC.6 USART6_TX, PC.7 USART6_RX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Connect USART pins to AF */
GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_USART6);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_USART6);
}
/**************************************************************************************/
void USART6_Configuration(void)
{
USART_InitTypeDef USART_InitStructure;
/* USARTx configuration ------------------------------------------------------*/
/* USARTx 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 = 115200;
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_Init(USART6, &USART_InitStructure);
USART_Cmd(USART6, ENABLE);
/* Enable the USART Tx DMA request */
USART_DMACmd(USART6, USART_DMAReq_Tx, ENABLE);
}
/**************************************************************************************/
// Output as a series of different length strings in a loop
char StringA[] = ''The quick brown fox jumps over the lazy dog

'';
char StringB[] = ''Danger Zombies Ahead

'';
char StringC[] = ''Do not cross the streams

'';
int StringIndex = 0;
char *StringList[] = { StringA, StringB, StringC, NULL };
void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
char *Buffer;
// USART6_TX DMA Channel 5, DMA2, Stream7 (alt Stream6 potential clash SDIO)
if (StringList[StringIndex] == NULL)
StringIndex = 0;
Buffer = StringList[StringIndex++];
DMA_DeInit(DMA2_Stream7);
DMA_InitStructure.DMA_Channel = DMA_Channel_5;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; // Transmit
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Buffer;
DMA_InitStructure.DMA_BufferSize = (uint16_t)strlen(Buffer);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART6->DR;
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_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream7, &DMA_InitStructure);
/* Enable DMA Stream Transfer Complete interrupt */
DMA_ITConfig(DMA2_Stream7, DMA_IT_TC, ENABLE);
/* Enable the DMA TX Stream */
DMA_Cmd(DMA2_Stream7, ENABLE);
}
/**************************************************************************************/
void DMA2_Stream7_IRQHandler(void) // USART6_TX
{
/* Test on DMA Stream Transfer Complete interrupt */
if (DMA_GetITStatus(DMA2_Stream7, DMA_IT_TCIF7))
{
/* Clear DMA Stream Transfer Complete interrupt pending bit */
DMA_ClearITPendingBit(DMA2_Stream7, DMA_IT_TCIF7);
DMA_Configuration(); // Light off next string
}
}
/**************************************************************************************/
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure the Priority Group to 2 bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* Enable the USART6 TX DMA Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream7_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/**************************************************************************************/
int main(void)
{
RCC_Configuration();
NVIC_Configuration();
GPIO_Configuration();
USART6_Configuration();
DMA_Configuration();
while(1); // Don't want to exit
}
/**************************************************************************************/

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
mucenieks
Associate II
Posted on January 06, 2015 at 15:41

If I understand correctly then you have to reconfigure DMA each time you want to repeat sending. In this example using:

DMA_Configuration(); in DMA2_Stream7_IRQHandler(void)

How would code look like if I wanted to update the data strings from main()?

Posted on January 06, 2015 at 17:11

How would code look like if I wanted to update the data strings from main()?

Not sure I'm up to code your application, but you'd probably want to have some buffering and linked list arrangement, and either chain that in the TC interrupt, or light it off when it's idle.


Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
contactst
Associate II
Posted on June 02, 2016 at 08:36

Thanks for the useful example. But I don't know why the result is 

The quick brown fox jumps over the lazy dog

Danger Zombies Ahead

Do not cross the streams

The quick brown fox jumps over the lazy dog

Danger Zombies Ahead

Do not cross the streams

The quick brown fox jubies Ahead  // error in here

Do not cross the streams

The quick brown fox jumps over the lazy dog

Danger Zombies Ahead

Do not cross the streams

The quick brown fox jumps over the lazy dog

Danger Zombies Ahead

Do not cross the streams

.....

( sorry! i don't know how to upload the imagine)... I use Terminal to see result.... 

Posted on June 02, 2016 at 18:11

Could be for a whole host of reasons, I would tend to suspect the serial dongle being used, perhaps it is losing synchronization. You could increase the stop bit setting, so the inter-symbol gap is larger.

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