cancel
Showing results for 
Search instead for 
Did you mean: 

UART with DMA mode

muhammad
Associate II
Posted on June 16, 2012 at 15:32

hi 

everyone

need help regarding UART with DMA mode,

i am using STM32F407 Discovery Board,

i want to configure UART4 with DMA, and want it to generate interrupt when DMA completes filling the memory. 

so should i configure the UART4's interrupt initializations also or only DMA interrupt initializations. I've attached my code. 

any help will be appreciated a lot. 

#selective-cut-n-paste #uart-usart-dma-interrupt
22 REPLIES 22
Posted on September 24, 2013 at 23:19

3.5.0 is for the F1 series parts, this thread was about the F4 series parts, as were most of the other examples referred to. Which part are you using?

Here's an example blind ported to the VL-Discovery board which uses the STM32F100

// STM32 USART1 DMA TX/RX (Tx PA.09, Rx PA.10) VLDiscovery - sourcer32@gmail.com
#include ''stm32F10x.h''
#include ''STM32vldiscovery.h''
/**************************************************************************************/
void RCC_Configuration(void)
{
/* Enable DMA clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* Enable GPIO clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* Enable UART clock */
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_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_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 = 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 configuration */
USART_Init(USART1, &USART_InitStructure);
/* Enable the USART1 */
USART_Cmd(USART1, ENABLE);
}
/**************************************************************************************/
volatile char Buffer[] = ''The quick brown fox jumps over the lazy dog

'';
void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
/* USART1_TX DMA1 Channel 4 (See RM0008) */
DMA_DeInit(DMA1_Channel4);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Buffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = sizeof(Buffer) - 1;
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_Low;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel4, &DMA_InitStructure);
USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
/* Enable DMA Stream Transfer Complete interrupt */
DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE);
/* USART1_RX DMA1 Channel 5 (See RM0008) */
DMA_DeInit(DMA1_Channel5);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Buffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = sizeof(Buffer) - 1;
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_Low;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel5, &DMA_InitStructure);
USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
/* Enable DMA Stream Transfer Complete interrupt */
DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);
DMA_Cmd(DMA1_Channel4, ENABLE);
DMA_Cmd(DMA1_Channel5, ENABLE);
}
/**************************************************************************************/
void DMA1_Channel4_IRQHandler(void) // USART1_TX
{
/* Test on DMA Transfer Complete interrupt */
if (DMA_GetITStatus(DMA1_IT_TC4))
{
/* Clear DMA Transfer Complete interrupt pending bit */
DMA_ClearITPendingBit(DMA1_IT_TC4);
/* ... */
}
}
/**************************************************************************************/
void DMA1_Channel5_IRQHandler(void) // USART1_RX
{
/* Test on DMA Transfer Complete interrupt */
if (DMA_GetITStatus(DMA1_IT_TC5))
{
/* Clear DMA Transfer Complete interrupt pending bit */
DMA_ClearITPendingBit(DMA1_IT_TC5);
/* ... */
}
}
/**************************************************************************************/
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure the Priority Group to 2 bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* Enable the USART1 TX DMA Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Enable the USART1 RX DMA Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_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();
USART_Configuration();
DMA_Configuration();
while(1);
}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
sh2
Associate II
Posted on November 17, 2015 at 11:28

Hello,

I try to make stm32f4 discovery communicate with a raspberry pi using USART1 and DMA2. I want to have a rx ring buffer storing the incoming messages from the RPI. For this purpose i configure the DMA2 Streem5 and USART1 as shown in the code below. When i send a byte from the RPi to the discovery it is received in the USART1->DR but a get nothing in my receive buffer and also no interrupt. Thank you for your help! Stefan

static void init_RPI_usart(void) {
USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
/* Peripheral Clock Enable -------------------------------------------------*/
//Enable GPIO clock
RPI_USART_GPIO_CLK_INIT(RPI_USART_TX_GPIO_CLK | RPI_USART_RX_GPIO_CLK,
ENABLE);
//Enable USART clock
RPI_USART_CLK_INIT(RPI_USART_CLK, ENABLE);
/* RPI_USART GPIO configuration -----------------------------------------------*/
/* Connect USART pins to AF7 */
GPIO_PinAFConfig(RPI_USART_TX_GPIO_PORT, RPI_USART_TX_SOURCE,
RPI_USART_TX_AF);
GPIO_PinAFConfig(RPI_USART_RX_GPIO_PORT, RPI_USART_RX_SOURCE,
RPI_USART_RX_AF);
/* Configure USART Tx and Rx as alternate function push-pull */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Pin = RPI_USART_TX_PIN;
GPIO_Init(RPI_USART_TX_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = RPI_USART_RX_PIN;
GPIO_Init(RPI_USART_RX_GPIO_PORT, &GPIO_InitStructure);
/* RPI_USART configuration ----------------------------------------------------*/
/* Enable the USART OverSampling by 8 */
USART_OverSampling8Cmd(RPI_USART, ENABLE);
/* RPI_USART configured as follow:
- BaudRate = 5250000 baud
- Maximum BaudRate that can be achieved when using the Oversampling by 8
is: (USART APB Clock / 8)
Example:
- (USART3 APB1 Clock / 8) = (42 MHz / 8) = 5250000 baud
- (USART1 APB2 Clock / 8) = (84 MHz / 8) = 10500000 baud
- Maximum BaudRate that can be achieved when using the Oversampling by 16
is: (USART APB Clock / 16)
Example: (USART3 APB1 Clock / 16) = (42 MHz / 16) = 2625000 baud
Example: (USART1 APB2 Clock / 16) = (84 MHz / 16) = 5250000 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;
/* When using Parity the word length must be configured to 9 bits */
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(RPI_USART, &USART_InitStructure);
/* Enable USART */
USART_Cmd(RPI_USART, ENABLE);
}
/**
*
*/
static void init_RPI_dma(void) {
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//Enable the DMA clock
RPI_DMA_CLK_INIT(RPI_USART_DMA_CLK, ENABLE);
/* Configure DMA controller to manage USART TX and RX DMA request ----------*/
DMA_InitStructure.DMA_Channel = RPI_USART_RX_DMA_CHANNEL;
DMA_InitStructure.DMA_PeripheralBaseAddr = RPI_USART_DR_ADDRESS;
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_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_InitStructure.DMA_BufferSize = (uint16_t) TX_RX_QUEUE_SIZE;
//TX configuration
// DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
// DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) tx_queue.buff;
//
// DMA_Init(RPI_USART_TX_DMA_STREAM, &DMA_InitStructure);
//RX configuration
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) &rx_queue.buff[0];
DMA_Init(RPI_USART_RX_DMA_STREAM, &DMA_InitStructure);
//interrupt configuration-------------------------------------------------------------
NVIC_InitStructure.NVIC_IRQChannel = RPI_USART_DMA_TX_IRQn
| RPI_USART_DMA_RX_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// /* Enable the USART DMA requests */
// USART_DMACmd(RPI_USART, USART_DMAReq_Tx, ENABLE);
//
// /* Clear the TC bit in the SR register by writing 0 to it */
// USART_ClearFlag(RPI_USART, USART_FLAG_TC);
//
// /* Enable the DMA TX Stream, USART will start sending */
// DMA_Cmd(USARTx_TX_DMA_STREAM, ENABLE);
/* Enable the USART Rx DMA request */
USART_DMACmd(RPI_USART, USART_DMAReq_Rx, ENABLE);
/* Enable DMA Stream Transfer Complete interrupt */
DMA_ITConfig(RPI_USART_RX_DMA_STREAM, DMA_IT_TC | DMA_IT_HT | DMA_IT_TE | DMA_IT_DME | DMA_IT_FE, ENABLE);
/* Enable the DMA RX Stream */
DMA_Cmd(RPI_USART_RX_DMA_STREAM, ENABLE);

 }

 //defines------------------------------------------------------------------------------
/* Definition for RPI_USART resources ********************************************/
#define RPI_USART USART1
#define RPI_USART_CLK RCC_APB2Periph_USART1
#define RPI_USART_CLK_INIT RCC_APB2PeriphClockCmd
#define RPI_USART_IRQHandler USART1_IRQHandler
#define RPI_USART_GPIO_CLK_INIT RCC_AHB1PeriphClockCmd
#define RPI_USART_TX_PIN GPIO_Pin_6
#define RPI_USART_TX_GPIO_PORT GPIOB
#define RPI_USART_TX_GPIO_CLK RCC_AHB1Periph_GPIOB
#define RPI_USART_TX_SOURCE GPIO_PinSource6
#define RPI_USART_TX_AF GPIO_AF_USART1
#define RPI_USART_RX_PIN GPIO_Pin_7
#define RPI_USART_RX_GPIO_PORT GPIOB
#define RPI_USART_RX_GPIO_CLK RCC_AHB1Periph_GPIOB
#define RPI_USART_RX_SOURCE GPIO_PinSource7
#define RPI_USART_RX_AF GPIO_AF_USART1
/* Definition for DMAx resources **********************************************/
#define RPI_USART_DR_ADDRESS ((uint32_t) &RPI_USART->DR)
#define RPI_USART_DMA DMA2
#define RPI_USART_DMA_CLK RCC_AHB1Periph_DMA2
#define RPI_DMA_CLK_INIT RCC_AHB1PeriphClockCmd
#define RPI_USART_TX_DMA_CHANNEL DMA_Channel_4
#define RPI_USART_TX_DMA_STREAM DMA2_Stream7
#define RPI_USART_TX_DMA_FLAG_FEIF DMA_FLAG_FEIF7
#define RPI_USART_TX_DMA_FLAG_DMEIF DMA_FLAG_DMEIF7
#define RPI_USART_TX_DMA_FLAG_TEIF DMA_FLAG_TEIF7
#define RPI_USART_TX_DMA_FLAG_HTIF DMA_FLAG_HTIF7
#define RPI_USART_TX_DMA_FLAG_TCIF DMA_FLAG_TCIF7
#define RPI_USART_RX_DMA_CHANNEL DMA_Channel_4
#define RPI_USART_RX_DMA_STREAM DMA2_Stream5
#define RPI_USART_RX_DMA_FLAG_FEIF DMA_FLAG_FEIF5
#define RPI_USART_RX_DMA_FLAG_DMEIF DMA_FLAG_DMEIF5
#define RPI_USART_RX_DMA_FLAG_TEIF DMA_FLAG_TEIF5
#define RPI_USART_RX_DMA_FLAG_HTIF DMA_FLAG_HTIF5
#define RPI_USART_RX_DMA_FLAG_TCIF DMA_FLAG_TCIF5
#define RPI_USART_DMA_TX_IRQn DMA2_Stream7_IRQn
#define RPI_USART_DMA_RX_IRQn DMA2_Stream5_IRQn
#define RPI_USART_DMA_TX_IRQHandler DMA2_Stream7_IRQHandler
#define RPI_USART_DMA_RX_IRQHandler DMA2_Stream5_IRQHandler
#define TX_RX_QUEUE_SIZE 5
//typedefs-----------------------------------------------------------------------------
typedef struct {
uint8_t buff[TX_RX_QUEUE_SIZE];
uint16_t ri;
uint16_t wi;
} queue_t;

Posted on November 17, 2015 at 14:14

You can't OR indexes together like this

NVIC_InitStructure.NVIC_IRQChannel = RPI_USART_DMA_TX_IRQn
| RPI_USART_DMA_RX_IRQn;

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
sh2
Associate II
Posted on November 17, 2015 at 14:31

unfortunately still same behavior after removing

RPI_USART_DMA_TX_IRQn

Posted on November 17, 2015 at 19:13

Ok, but I can only skim over the code, I'm not writing a framework to test this. You'll need to provide a concise stand-alone example.

Perhaps you should watch the order you run these functions, or move the clock initialization up one level, so all of the them are running.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
sh2
Associate II
Posted on November 19, 2015 at 16:24

Thank you for the response. I change the order of the execution and it works. But now I have another question.

My application receives data blocks of 3 Bytes over the USART1.

I want to put several of those blocks on a circular buffer and get a DMA interrupt each time a new data block was put on the buffer.

This is pretty the same as shown in figure 316 in RM0090.

How to cause a DMA interrupt after exactly 3 byte transfer from UART to RAM if my RAM buffer is bigger then 3 byte?

Now I managed it so far that I can get interrupt only after receiving the byte number specified in DMA_InitStructure.DMA_BufferSize.

If DMA_InitStructure.DMA_BufferSize is equal 3 a get interrupt after a data block but my buffer is also full.

hariprasad
Associate III
Posted on December 04, 2015 at 08:17

Hi Clive,

 I used your code and gave the buffer size to 10, but when I'm trnasferring 10 I'm not getting Transfer Complete every time.

Is it because of the DMA_SxNDTR = Multiple of ((Mburst beat) × (Msize)/(Psize))

inconsistency

When I checked MBURST, MSIZE, and PSIZE all are configured for byte, so it should give me DMA_TC on reception of every 10 byte .

What am I missing?

marko239955_st
Associate II
Posted on December 27, 2015 at 14:11

Is there any example how to implement UART transmit trough circular DMA with use of MxCube?

phvtinh2712
Associate
Posted on June 19, 2016 at 16:20

Hi everyone,

I try to communication with peripherals by USARTx with Keilc 5.13v and stm32f4 discovery. But I can't handle USARTx interrupt through HAL libraries. I don't know what happen? Therefore who can show me how to use HAL libraries to configurate for STM32f4 Discovery kit to get data from PC. Thanks!

Posted on June 19, 2016 at 19:18

I'm not sure where the HAL/Cube protagonists go when people need their help..

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