2020-09-16 05:16 AM
Hello, I am trying to use DMA with USART to transmit and receive data to buffers in internal RAM.
I setup my DMA1_Stream4 as USART3_TX. However, after setting DMA control register, Peripheral address, memory address, number of data to transfer, Enabling DMA causes FEIF4 to set. I cannot transmit anything.
I shared my whole code below.
#include "main.h"
#include "SysClkConfiguration.h"
uint8_t USART3_Transmit_Buffer1[4] = {"Test"};
uint8_t USART3_Receive_Buffer[3];
void Initialization()
{
//----------RCC Configuration----------//
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN; //Enable GPIOC Clock
RCC->APB1ENR |= RCC_APB1ENR_USART3EN; //Enable USART Peripheral Clock
RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN; //Enable DMA1 Clock
//----------GPIO Configuration----------//
GPIOC->MODER |= (0b10<<GPIO_MODER_MODE10_Pos) | (0b10<<GPIO_MODER_MODE11_Pos); //Set PC11/10 as Alternate Function
GPIOC->OSPEEDR |= (0b10<<GPIO_OSPEEDR_OSPEED10_Pos) | (0b10<<GPIO_OSPEEDR_OSPEED10_Pos); //Set PC10/11 Output Speed as High Speed
GPIOC->AFR[1] |= (0b0111<<GPIO_AFRH_AFSEL10_Pos) | (0b0111<<GPIO_AFRH_AFSEL11_Pos); //Set PC10/11 as USART3 RX/TX
//----------USART Configuration----------//
USART3->CR1 &= ~(USART_CR1_UE); //USART Disabled
USART3->BRR = 0x0020; //Baudrate is set 2Mbps
USART3->CR1 |= USART_CR1_OVER8 | USART_CR1_TE | USART_CR1_RE; //Oversampling Mode, Transmit Enable, Receive Enable
USART3->CR3 |= USART_CR3_DMAT | USART_CR3_DMAR; //DMA Enable Transmitter, DMA Enable Receiver
//----------DMA Configuration----------//
DMA1_Stream1-> CR &= ~(DMA_SxCR_EN); //Disable DMA1_Stream1
// Channel 4 High Priority Memory Inc. Circular Transmit Comp. Interrupt
DMA1_Stream1-> CR |= (4<<DMA_SxCR_CHSEL_Pos) | (0b10<<DMA_SxCR_PL_Pos) | DMA_SxCR_MINC | DMA_SxCR_CIRC | DMA_SxCR_TCIE;
DMA1_Stream1-> PAR = (uint32_t) &USART3->DR;
DMA1_Stream1-> M0AR = (uint32_t) USART3_Receive_Buffer;
DMA1_Stream1-> NDTR = 3;
DMA1_Stream1-> CR |= DMA_SxCR_EN; //Enable DMA1_Stream1
DMA1_Stream4-> CR &= ~(DMA_SxCR_EN); //Disable DMA1_Stream4
// Channel 7 Medium Priority Memory Inc. Memory-to-peripheral Transmit Comp. Interrupt
DMA1_Stream4-> CR |= (7<<DMA_SxCR_CHSEL_Pos) | (0b01<<DMA_SxCR_PL_Pos) | DMA_SxCR_MINC | (0b01<<DMA_SxCR_DIR_Pos) | DMA_SxCR_TCIE;
DMA1_Stream4-> PAR = (uint32_t) &USART3->DR;
DMA1_Stream4-> M0AR = (uint32_t) USART3_Transmit_Buffer1;
DMA1_Stream4-> NDTR = 4;
DMA1_Stream4-> CR |= DMA_SxCR_EN; //Enable DMA1_Stream4 (Transmit Buffer through USART3)
//----------NVIC Configuration----------//
NVIC_EnableIRQ(DMA1_Stream1_IRQn); //Enable DMA1 Stream1
NVIC_EnableIRQ(DMA1_Stream4_IRQn); //Enable DMA1 Stream4
//----------Peripheral Activation----------//
USART3->CR1 |= USART_CR1_UE; //USART Enabled
}
void DummyDelay(uint32_t x)
{
while(x)
{
x--;
}
}
int main(void)
{
HAL_Init();
SystemClock_Config();
Initialization();
while (1)
{
DMA1_Stream4-> CR |= DMA_SxCR_EN; //Enable DMA1_Stream4 (Transmit Buffer through USART3)
DummyDelay(1000000);
DMA1_Stream4-> CR |= DMA_SxCR_EN; //Enable DMA1_Stream4 (Transmit Buffer through USART3)
DummyDelay(1000000);
}
}
void DMA1_Stream1_IRQHandler()
{
if(DMA1->LISR & DMA_LISR_TCIF1)
{
DMA1->LIFCR |= DMA_LIFCR_CTCIF1; //Clear Transmission Complete Flag
}
}
void DMA1_Stream4_IRQHandler()
{
if(DMA1->HISR & DMA_HISR_TCIF4)
{
DMA1->HIFCR |= DMA_HIFCR_CTCIF4; //Clear Transmission Complete Flag
}
}
What could be the problem? What am I setting wrong?
2020-09-16 06:18 AM
One typo here:
> GPIOC->OSPEEDR |= (0b10<<GPIO_OSPEEDR_OSPEED10_Pos) | (0b10<<GPIO_OSPEEDR_OSPEED10_Pos); //Set PC10/11 Output Speed as High Speed
Are the two pins connected to each other? How do you know data is being received?
The compiler is allowed to completely optimize out your DummyDelay function. You can make the variable volatile, or (better) use an actual delay such as HAL_Delay or similar.
2020-09-16 02:53 PM
> Enabling DMA causes FEIF4 to set. I cannot transmit anything.
Why? Your setup ignores FIFO error - and rightly so, in Direct mode you are using.
You can avoid it by setting USART_CR3_DMAT *after* you enable the respective DMA.
For explanation, see AN4031, chapter 4.3 Software sequence to enable DMA.
JW