cancel
Showing results for 
Search instead for 
Did you mean: 

USART and DMA

greg_t
Associate II
Posted on August 02, 2011 at 15:52

I use DMA to write a string to USART2.

After power up I trigger transmittion by pressing down a switch and detect

( oscilloscope ) that the usart transmitted two bytes less than expected - after that every time I trigger the write sequence using DMA it works ok... until next reset or power up  !!!

Any ideas why this strange 

behavior

??

#dma-usart
6 REPLIES 6
Posted on August 02, 2011 at 20:36

The first two bytes, or the last two, or some random ones in the middle?

Sounds like some assumptions about what clocks/registers are set up, and it what order. Or perhaps waiting sufficiently for clocks to come up or synchronize.

Without some concise example to look at, or test, we're just left to guess.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
greg_t
Associate II
Posted on August 03, 2011 at 07:21

Hello Clive1,

    The missing bytes are the last two. If I change the buffer size parameter  

    ( add two )  in DMA initialization the first string comes out ok but 

    all other strings have two bytes more.

void RCC_Configuration(void)

{

  RCC_ClearFlag();

   

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

 

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2 |

                         RCC_APB1Periph_TIM2   | RCC_APB1Periph_TIM3 |

                         RCC_APB1Periph_I2C1   | RCC_APB1Periph_TIM4   ,

                         ENABLE); 

}

void GPIO_Configuration(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;

  ////////////////////////////////////////////////////////////

   /* Configure USART2 Rx as input floating */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Configure USART2 Tx as alternate function push-pull */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /////////////////////////////////////////////////////////

}

/* USART2 configuration */

void USART2_Configuration(void)

{

  /* USART2 configured as follow:

        - BaudRate = ????? baud 

        - Word Length = 8 Bits

        - One Stop Bit

        - No parity

        - Hardware flow control disabled (RTS and CTS signals)

        - Receive and transmit enabled

  */

  USART_InitTypeDef USART_InitStructure;

 

  USART_InitStructure.USART_BaudRate = 9600; 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;

  /* Configure USART */

  USART_Init(USART2, &USART_InitStructure);

 

  USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);

  USART_ITConfig(USART2, USART_IT_ERR , ENABLE);

 

  /* Enable USART2 DMA TX request */

  USART_DMACmd(USART2, USART_DMAReq_Tx, ENABLE);

  

  /* Enable the USART */

  USART_Cmd(USART2, ENABLE);

} void NVIC_Configuration(void)

{

  NVIC_InitTypeDef NVIC_InitStructure;

  

  /* Configure the NVIC Preemption Priority Bits */ 

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

  

  /* Enable USART2 RX Interrupt */

  NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;

  NVIC_Init(&NVIC_InitStructure);

 

  /* TX DMA Interrupt USART2 */

  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel7_IRQn ;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure); 

}

void SendStr(char *s, int lenght )

{

  if (TX_head != NULL)

  {

    struct TX_list* second = TX_head ;

    while ((second)->Next != NULL)

    {

      second = second->Next;

    }

    second->Next = (struct TX_list*)malloc(sizeof(struct TX_list));

    second = second->Next;

    second->Data = s;

    second->lenght = lenght;

    second->Next = NULL;

  }

  else

  {

    TX_head = (struct TX_list*)malloc(sizeof(struct TX_list));

    TX_head->Data = s;

    TX_head->lenght = lenght;

    TX_head->Next = NULL;

  }

  

  /* Load String into DMA1 */

  if (TxBusy == 0)

  {

    TxBusy = 1;

    Start_USART_DMA_TX ( TX_head->Data, TX_head->lenght);

  }

}

/* USART DMA TX */

void Start_USART_DMA_TX ( char *s, int lenght )

{

  /* USART2_Tx_DMA_Channel (triggered by USART2 Tx event) Config */

  DMA_InitTypeDef DMA_InitStructure1;

  DMA_DeInit ( DMA1_Channel7);

  DMA_InitStructure1.DMA_PeripheralBaseAddr = 0x40004404;

  DMA_InitStructure1.DMA_MemoryBaseAddr = (uint32_t)(s);

  DMA_InitStructure1.DMA_DIR = DMA_DIR_PeripheralDST;

  DMA_InitStructure1.DMA_BufferSize = lenght;

  DMA_InitStructure1.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

  DMA_InitStructure1.DMA_MemoryInc = DMA_MemoryInc_Enable;

  DMA_InitStructure1.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

  DMA_InitStructure1.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;

  DMA_InitStructure1.DMA_Mode = DMA_Mode_Normal;

  DMA_InitStructure1.DMA_Priority = DMA_Priority_VeryHigh;

  DMA_InitStructure1.DMA_M2M = DMA_M2M_Disable;

  DMA_Init(DMA1_Channel7, &DMA_InitStructure1);

  DMA_ITConfig (DMA1_Channel7, DMA_IT_TC, ENABLE);

  DMA_Cmd(DMA1_Channel7, ENABLE);

}

Posted on August 03, 2011 at 13:49

At a quick scan, I'd suggest you move the following to a point after you've configured the DMA transfer. Or at the very least after USART_Init()

/* Enable USART2 DMA TX request */

  USART_DMACmd(USART2, USART_DMAReq_Tx, ENABLE);
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
greg_t
Associate II
Posted on August 04, 2011 at 18:58

Did not helped ... 

Posted on August 05, 2011 at 17:55

Not seeing any junk/truncation here on USART1. You might also want to fix the race condition in your queuing routine.

void RCC_Configuration(void)

{

  /* Enable DMA clock */

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

  /* Enable GPIO bank clock */

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

  /* Enable UART clock */

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

}

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

void GPIO_Configuration(void)

{

    GPIO_InitTypeDef GPIO_InitStructure;

  /* Configure USART Tx as alternate function push-pull */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;  // PA.09 USART1.TX

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Configure USART Rx as input floating */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // PA.10 USART1.RX

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

}

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

void USART_Configuration(void)

{

  USART_InitTypeDef USART_InitStructure;

  /* USART resources configuration (Clock, GPIO pins and USART registers) ----*/

  /* USART 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 configuration */

  USART_Init(USART1, &USART_InitStructure);

  /* Enable the USART1 */

  USART_Cmd(USART1, ENABLE);

}

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

void DMA_Configuration(void)

{

  // USART1 Channel 4, USART2 Channel 7, USART3 Channel 2

  DMA_DeInit(DMA1_Channel4);

  DMA_Cmd(DMA1_Channel4, DISABLE);

}

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

void DMA_USART_String(char *s)

{

  DMA_InitTypeDef DMA_InitStructure;

    /* Disable the DMA Controller/Channel */

    DMA_DeInit(DMA1_Channel4);

  /* USART1_Tx_DMA_Channel (triggered by USART1 Tx event) Config */

  DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;

  DMA_InitStructure.DMA_MemoryBaseAddr = (u32)s;

  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;

  DMA_InitStructure.DMA_BufferSize = strlen(s);

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

  DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;

  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

  DMA_Init(DMA1_Channel4, &DMA_InitStructure);

    /* Enable the DMA Controller/Channel */

  DMA_Cmd(DMA1_Channel4, ENABLE);

  /* Enable USART1 DMA TX request */

  USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);

    /* Wait of DMA completion */

    while(DMA_GetFlagStatus(DMA1_FLAG_TC4) == RESET);

  /* Loop until the end of transmit */

  while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);

}

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

int main(void)

{

    char str[] = ''Welcome to wherever you are...'';

  int i;

  RCC_Configuration();

  GPIO_Configuration();

  USART_Configuration();

  DMA_Configuration();

  for(i=0; i<10; i++)

    {

    DMA_USART_String(str);

    }

  /* Infinite loop */

    while(1);

  /* does not exit - kind of important */

  return(1);

}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
greg_t
Associate II
Posted on August 12, 2011 at 09:42

You will see the problem if you change the loop

for(i=0; i<10; i++)

{

DMA_USART_String(str);

    }

to 

for(i=0; i<1; i++)

{

DMA_USART_String(str);

}