STM32F4 using DMA2 for USART1
I am using a STM32F407, and I would like to use DMA to receive data from USART1 and store in a buffer.
HAL is not being used.
USART1 is configured and is receiving the first byte of the message correctly. That is, the data shows up in USART1->DR.
Here is the DMA configuration.
//**********************************************************************
// Configure DMA2 controller for USART1_RX data transfer to memory.
// (DMA2-Stream2-Channel 4)
// PAR = Address of USART1 data register (DR)
// M0AR = Address of UART ReceiverBuf
// PSIZE = Byte size data transfers
// MSIZE set to same value as PSIZE for single transfers
// NDTR = 16 bytes to transfer.
// CR, By default, FIFO is disabled, and direct mode enabled
// CR, MINC = 1, Increment memory address pointer
// CR, PINC = 0, Peripheral address pointer remains fixed (default)
// CR, DIR = 00, Data transfer direction peripheral to memory (default)
// CR, PL = 11, Very high priority
// CR, CHSEL = 4, DMA2 Stream 2, channel 4
// CR, MBURST = 00, Single, (default)
// CR, PBURST = 00, Single, (default)
// Burst transfer modes set to "single", (default)
// We will not use interrupts to signal transfer complete.
// Instead, we will poll.
//***********************************************************************
DMA2_Stream2->PAR = &USART1->DR;
DMA2_Stream2->M0AR = &UART_ReceiveBuf[0];
DMA2_Stream2->NDTR = 16;
DMA2_Stream2->CR = \
4 << DMA_SxCR_CHSEL_BITPOS | \
DMA_SxCR_PL_VERY_HIGH | \
DMA_SxCR_PSIZE_BYTE | \
DMA_SxCR_MINC;Here is a screen snapshot of the DMA registers.
To me, this appears to be setup correctly, and is ENabled.
USART1 registers when program was stopped.
Received data is 0x5A, but was never transferred to memory.
DMA doesn't ever appear to transfer data from USART1->DR to buffer memory in RAM.
Here is the code for a simple test loop to receive the 16 bytes of data through DMA transfer, then reconfigure and setup to receive again.
while(1)
{
DMA2_Stream2->CR |= DMA_SxCR_EN;
while( !(DMA2->LISR & DMA_LISR_TCIF2) ); // wait until data has been received
DMA2_Stream2->CR &= ~DMA_SxCR_EN; // temporarily disable this DMA stream to setup for next packet
while( (DMA2_Stream2->CR & DMA_SxCR_EN) ); // wait until EN bit is clear (xfr finished)
DMA2->LIFCR |= DMA_LIFCR_CTCIF2; // clear transfer complete interrupt flag
DMA2_Stream2->M0AR = &UART_ReceiveBuf[0]; // reset receive buffer pointer to start
DMA2_Stream2->NDTR = 16; // reload number of bytes to receive
}I've seen a few posts that seem to suggest that USART1 interrupts have to be turned on. Is that correct ??? That doesn't seem right to me because that defeats the whole intent behind DMA. I don't want an ISR to handle the data, that is DMA's job. Shouldn't the DMA use the USART1->SR RXNE bit to trigger the receive DMA transfer ?
In any case, I seem to be stuck. Any help would be appreciated.
Thanks.
