Skip to main content
Ajay Paul
Associate
January 4, 2017
Question

DMA configuration for USART Reception in STM32L152

  • January 4, 2017
  • 4 replies
  • 1198 views
Posted on January 04, 2017 at 14:41

Hi,

I was trying to configure a DMA for receiving data continuously from USART in STM32L152 Discovery board. I am able to configure the USART TX for DMA. But when i am trying to configure the DMA for RX, even interrupt is also not coming. Can anyone suggest me how to solve this issue . I am  adding the code below.

#include 'stm32l1xx.h'

#include 'stm32l1xx_usart.h'

#include 'stm32l1xx_gpio.h'

#include 'stm32l1xx_rcc.h'

#include 'stm32l1xx_dma.h'

#define USART2_BAUDRATE                 115200  

/**************************************************************************************/

 

void RCC_Configuration(void)

{

  /* --------------------------- System Clocks Configuration -----------------*/

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_DMA1, ENABLE);

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

}

 

/**************************************************************************************/

 

void GPIO_Configuration(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;

 

  /*-------------------------- GPIO Configuration ----------------------------*/

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

 

  /* Connect USART pins to AF */

  GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);

  GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);

}

 

/**************************************************************************************/

 

void USART2_Configuration(void)

{

    USART_InitTypeDef USART_InitStructure;

 

  USART_InitStructure.USART_BaudRate = USART2_BAUDRATE;

  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_Init(USART2, &USART_InitStructure);

 

  USART_Cmd(USART2, ENABLE);

}

 

/**************************************************************************************/

 

uint8_t Buffer[]='shokam';

 

void DMA_Configuration(void)

{

  DMA_InitTypeDef  DMA_InitStructure;

 

  DMA_DeInit(DMA1_Channel7);

 

  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; // Receive

  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Buffer;

  DMA_InitStructure.DMA_BufferSize = (uint16_t)sizeof(Buffer);

  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART2->DR;

  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_High;

  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

 

  DMA_Init(DMA1_Channel7, &DMA_InitStructure);

 

  /* Enable the USART Rx DMA request */

  USART_DMACmd(USART2, USART_DMAReq_Rx, ENABLE);

 

  /* Enable DMA Stream Half Transfer and Transfer Complete interrupt */

  DMA_ITConfig(DMA1_Channel7, DMA_IT_TC, ENABLE);

 

  /* Enable the DMA RX Stream */

  DMA_Cmd(DMA1_Channel7, ENABLE);

 

}

 

/**************************************************************************************/

 

void DMA1_Channel7_IRQHandler(void)

{

  /* Test on DMA Stream Transfer Complete interrupt */

  if (DMA_GetITStatus(DMA1_IT_TC7))

  {

    /* Clear DMA Stream Transfer Complete interrupt pending bit */

    DMA_ClearITPendingBit(DMA1_IT_TC7);

 

    USART_SendData(USART2, 'C');

  }

   

}

 

/**************************************************************************************/

 

void NVIC_Configuration(void)

{

  NVIC_InitTypeDef NVIC_InitStructure;

 

  /* Configure the Priority Group to 2 bits */

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

 

  /* Enable the UART4 RX DMA Interrupt */

  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel7_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();

 

  USART2_Configuration();

 

  DMA_Configuration();

 

  while(1);

}
    This topic has been closed for replies.

    4 replies

    Oliver Beirne
    Associate II
    January 4, 2017
    Posted on January 04, 2017 at 15:06

    Hi

    ajaypaul2008@gmial.com

    I have moved your post to the

    https://community.st.com/community/stm32-community/stm32-forum?sr=search&ampsearchId=ce1233ef-d5fc-48ea-b8d1-28e9854d529a&ampsearchIndex=0

    which is the best place to ask any product-related STM32 questions.

    Thanks

    Oli

    waclawek.jan
    Super User
    January 4, 2017
    Posted on January 04, 2017 at 15:22

    USART2_Rx is at DMA Channel 6 rather than Channel7, isn't it?

    Also

    - don't look at the UART registers in debugger, reading data register even in debugger clears the RXNE flag

    - don't try to use interrupts and DMA at the same time, they work out of the very same RXNE flag

    Tesla DeLorean
    Guru
    January 4, 2017
    Posted on January 04, 2017 at 16:59

    // STM32 USART2 DMA RX (Tx PA.2, Rx PA.3) STM32L152RE NUCLEO - sourcer32@gmail.com
    #include 'stm32l1xx.h'
    #include <string.h>
    /**************************************************************************************/
    void RCC_Configuration(void)
    {
     /* --------------------------- System Clocks Configuration -----------------*/
     /* USART2 clock enable */
     RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
     /* GPIOA and DMA1 clock enable */
     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_DMA1, ENABLE);
    }
    /**************************************************************************************/
    void GPIO_Configuration(void)
    {
     GPIO_InitTypeDef GPIO_InitStructure;
     /*-------------------------- GPIO Configuration ----------------------------*/
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3; // PA.2 USART2_TX, PA.3 USART2_R
    X GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
     GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
     GPIO_Init(GPIOA, &GPIO_InitStructure);
     /* Connect USART pins to AF */
     GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);
     GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);
    }
    /**************************************************************************************/
    void USART2_Configuration(void)
    {
     USART_InitTypeDef USART_InitStructure;
     /* USARTx configuration ------------------------------------------------------*/
     /* USARTx 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_Init(USART2, &USART_InitStructure);
     USART_Cmd(USART2, ENABLE);
    }
    /**************************************************************************************/
    uint8_t Buffer[] = 'The quick brown fox jumps over the lazy dog';
    void DMA_Configuration(void)
    {
     DMA_InitTypeDef DMA_InitStructure;
     DMA_DeInit(DMA1_Channel6);
     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; // Receive
     DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Buffer;
     DMA_InitStructure.DMA_BufferSize = (uint16_t)sizeof(Buffer);
     DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART2->DR;
     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_High;
     DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
     DMA_Init(DMA1_Channel6, &DMA_InitStructure);
     /* Enable the USART Rx DMA request */
     USART_DMACmd(USART2, USART_DMAReq_Rx, ENABLE);
     /* Enable DMA Stream Transfer Complete interrupt */
     DMA_ITConfig(DMA1_Channel6, DMA_IT_TC, ENABLE);
     
     /* Enable the DMA RX Stream */
     DMA_Cmd(DMA1_Channel6, ENABLE);
    }
    /**************************************************************************************/
    void DMA1_Channel6_IRQHandler(void)
    {
     /* Test on DMA Stream Transfer Complete interrupt */
     if (DMA_GetITStatus(DMA1_IT_TC6))
     {
     /* Clear DMA Stream Transfer Complete interrupt pending bit */
     DMA_ClearITPendingBit(DMA1_IT_TC6);
     USART_SendData(USART2, 'C');
     }
    }
    /**************************************************************************************/
    void NVIC_Configuration(void)
    {
     NVIC_InitTypeDef NVIC_InitStructure;
     /* Configure the Priority Group to 2 bits */
     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
     /* Enable the USART2 RX DMA Interrupt, per RM0038 */
     NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel6_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();
     USART2_Configuration();
     DMA_Configuration();
     while(1); // Don't want to exit
    }
    /**************************************************************************************/
    #ifdef USE_FULL_ASSERT
    /**
     * @brief Reports the name of the source file and the source line number
     * where the assert_param error has occurred.
     * @param file: pointer to the source file name
     * @param line: assert_param error line source number
     * @retval None
     */
    void assert_failed(uint8_t* file, uint32_t line)
    {
     /* User can add his own implementation to report the file name and line number,
     ex: printf('Wrong parameters value: file %s on line %d
    
    ', file, line) */
     while (1)
     {}
    }
    #endif
    /**************************************************************************************/�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Ajay Paul
    Ajay PaulAuthor
    Associate
    January 5, 2017
    Posted on January 05, 2017 at 05:29

    Thanks

    Turvey.Clive.002

    and

    Waclawek.Jan

    for the quick replay. And it is working now. But i am not able to figure out that, what is the significance of Buffer initialization? and Do I need to ensure that, the data which I am sending through uart should be same size as that of initial Buffer size??

    Tesla DeLorean
    Guru
    January 6, 2017
    Posted on January 06, 2017 at 22:05

    You'd really want to pick a buffer that suits your needs, doing DMA RX requires some thought if you are not dealing with a constant stream of data. The case for DMA TX is a lot easier to make, and manage.

    I used initialization because it is a lot easier to see in the debugger's memory viewer, and that other examples from which this was culled do both TX and RX in a loop from the same buffer, so what is received is ultimately sent out in a loop. The goal generally with the examples is to make them as simple and illustrative as possible, rather than to solve a more complex use case. If the fundamental concepts are understood they can be extended/applied to more complete systems.

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