Skip to main content
muhammad
Associate II
June 16, 2012
Question

UART with DMA mode

  • June 16, 2012
  • 22 replies
  • 10120 views
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
This topic has been closed for replies.

22 replies

sh2
Associate
November 17, 2015
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;

Tesla DeLorean
Guru
November 17, 2015
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 (See Profile) Up vote any posts that you find helpful, it shows what's working..
sh2
Associate
November 17, 2015
Posted on November 17, 2015 at 14:31

unfortunately still same behavior after removing

RPI_USART_DMA_TX_IRQn

Tesla DeLorean
Guru
November 17, 2015
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 (See Profile) Up vote any posts that you find helpful, it shows what's working..
sh2
Associate
November 19, 2015
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
December 4, 2015
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
December 27, 2015
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
Visitor II
June 19, 2016
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!

Tesla DeLorean
Guru
June 19, 2016
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 (See Profile) Up vote any posts that you find helpful, it shows what's working..
khandaynial_2000
Associate
July 24, 2016
Posted on July 24, 2016 at 21:12

hi Clive1

I am using DMA on uart4 and code is runing perfectly but there is a problem i can fatch data from dma buffer only when it have filled by 16 bytes . in my application i need to fatch data from buffer byte by byte please help as soon as possible