AnsweredAssumed Answered

STM32F3 USART1 RX DMA

Question asked by f-stop on Apr 24, 2014
Latest reply on Apr 26, 2014 by f-stop
Hi all,

Hoping to get a second pair of eyes on this code. I'm trying to capture large amounts of data from USART1 using DMA on an F30x series MCU.

So far no luck - feels like I'm looking past an obvious error here 'cause this shouldn't be as complicated as it seems.

Any feedback appreciated.

#include "stm32f30x.h"
// ----------------------------------------------------------------------------
// USART1 DMA Buffer
#define RXBUFFERSIZE 0xFFF
uint8_t RxBuffer[RXBUFFERSIZE];
// ----------------------------------------------------------------------------
#define Loiter() uint8_t loitervar = 0; loitervar++;
 
void DMA1_Channel5IRQHandler(void)
{
    if (DMA_GetITStatus(DMA1_IT_TC5))
    {
        // Transfer complete.
        DMA_ClearITPendingBit(DMA1_IT_TC5);
        GPIO_SetBits(GPIOE, GPIO_Pin_9);
    }
    else if (DMA_GetITStatus(DMA1_IT_HT5))
    {
        // Half transfer.
        DMA_ClearITPendingBit(DMA1_IT_HT5);
    }
    else if (DMA_GetITStatus(DMA1_IT_TE5))
    {
        // Transfer error.
        DMA_ClearITPendingBit(DMA1_IT_TE5);
    }
 
    // This line must be after clearing of interrupts to avoid immediate re-entry when interrupt is not TC.
    Loiter();
}
 
void GPIO_Configuration()
{
    // Enable GPIO Clocks.
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOE, ENABLE);
 
    // Configure PA9 & PA10 AF PP.
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;                   // Alternate function.
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;                 // Push pull.
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;        // GPIOA TX & RX for USART1.
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;               // Not required.
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStruct);
 
    // Connect PA9 & PA10 to USART1.
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_7);        // Tx Line
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_7);       // Rx Line
 
    // Configure PE9 & PE12 Status LED's.
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
    GPIO_Init(GPIOE, &GPIO_InitStruct);
}
 
void USART_Configuration()
{
    // Enable USART1 Clock.
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
 
    // Initialize USART1: 9600,8N1.
    USART_InitTypeDef USART_InitStruct;
    USART_StructInit(&USART_InitStruct);
    USART_Init(USART1, &USART_InitStruct);
 
    // Enable USART1.
    USART_Cmd(USART1, ENABLE);
 
    // Enable RX DMA Transfers from USART1.
    USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
}
 
void DMA_Configuration()
{
    // Enable DMA1 Controller.
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
 
    // Clear USART1 RX DMA Channel config.
    DMA_DeInit(DMA1_Channel5);
 
    // Initialize USART1 RX DMA Channel:
    DMA_InitTypeDef DMA_InitStruct;
    DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&USART1->RDR;         // USART1 RX Data Register.
    DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)RxBuffer;                 // Copy data to RxBuffer.
    DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;                         // Peripheral as source, memory as destination.
    DMA_InitStruct.DMA_BufferSize = RXBUFFERSIZE;                           // Defined above.
    DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;           // No increment on RDR address.
    DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;                    // Increment memory address.
    DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;    // Byte-wise copy.
    DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;            // Byte-wise copy.
    DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;                            // Ring buffer - don't interrupt when at end of memory region.
    DMA_InitStruct.DMA_Priority = DMA_Priority_High;                        // High priority.
    DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;                               // Peripheral to memory, not M2M.
 
    // Initialize USART1 RX DMA Channel.
    DMA_Init(DMA1_Channel5, &DMA_InitStruct);
 
    // Enable Transfer Complete, Half Transfer and Transfer Error interrupts.
    DMA_ITConfig(DMA1_Channel5, DMA_IT_TC | DMA_IT_HT | DMA_IT_TE, ENABLE);
 
    // Enable USART1 RX DMA Channel.
    DMA_Cmd(DMA1_Channel5, ENABLE);
}
 
void NVIC_Configuration()
{
    // We only want to use preemption.
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
 
    // Configure USART1 RX DMA Channel Interrupts.
    NVIC_InitTypeDef NVIC_InitStruct;
    NVIC_InitStruct.NVIC_IRQChannel = DMA1_Channel5_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
    NVIC_Init(&NVIC_InitStruct);
}
 
int main(void)
{
  GPIO_Configuration();
  USART_Configuration();
  DMA_Configuration();
  NVIC_Configuration();
 
  while (1);
}

Outcomes