AnsweredAssumed Answered

TIM triggered DMA to USART2 fires only once.

Question asked by sohail on Oct 26, 2015
Latest reply on Oct 27, 2015 by sohail
On an stm32f411 Nucleo, I'm trying to generate a DMA request to transfer data from memory to the USART2 data register at every compare event (when CCR1 matches TIM3_CNT). To this end, I have, in order:

       
  1. Configured the NVIC, enabled the TIM3_IRQ
  2.    
  3. Configured the GPIO pins for the user LED and USART2
  4.    
  5. Configured the USART2.
  6.    
  7. Configured the DMA1, Stream 4, Channel 5 (for accepting DMA requests from TIM3_CH1 as per the ref. manual).
  8.    
  9. Configured the TIM3 and OC1 so that a compare yields true every 1 second.
  10.    
  11. Enabled the interrupt and DMA requests at every compare TRUE event.
  12.    
  13. Enabled the timer.

The main function is as under:

001.int main(void)
002.{
003.  /*!< At this stage the microcontroller clock setting is already configured,
004.       this is done through SystemInit() function which is called from startup
005.       files before to branch to application main.
006.       To reconfigure the default setting of SystemInit() function,
007.       refer to system_stm32f4xx.c file */
008.        
009.  /* SysTick end of count event each 10ms */
010.  RCC_GetClocksFreq(&RCC_Clocks);
011.  SystemCoreClockUpdate();
012.  SysTick_Config(RCC_Clocks.HCLK_Frequency / 100);
013.   
014.  /* Add your application code here */
015.  userLedInit(LED_DIMMING_DISABLE);
016.  const uint8_t datum[7] = "NUCLEO ";
017.   
018.  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
019.  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
020.  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
021.  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
022.   
023.  /* IRQ configuration */
024.  NVIC_SetPriorityGrouping(0x4);
025.  NVIC_InitTypeDef NVIC_InitStructure;
026.  NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
027.  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
028.  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
029.  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
030.  NVIC_Init(&NVIC_InitStructure);
031. 
032.  /* GPIO Configuration for USART2 through STLink VCP COM3 on Nucleo 411 */
033.  GPIO_InitTypeDef GPIO_InitStructure;
034.  GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);
035.  GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);
036.  GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_TIM3);
037.  GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_6);
038.  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
039.  GPIO_InitStructure.GPIO_Speed = GPIO_Medium_Speed;
040.  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
041.  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
042.  GPIO_Init(GPIOA, &GPIO_InitStructure);
043.   
044.  /* USART2 Initialization */
045.  USART_InitTypeDef USART_InitStructure;
046.  USART_InitStructure.USART_BaudRate = 115200;
047.  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
048.  USART_InitStructure.USART_StopBits = USART_StopBits_1;
049.  USART_InitStructure.USART_Parity = USART_Parity_No;
050.  USART_InitStructure.USART_Mode = (USART_Mode_Tx | USART_Mode_Rx);
051.  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
052.  USART_OverSampling8Cmd(USART2, DISABLE);
053.  USART_Init(USART2, &USART_InitStructure);
054.  USART_Cmd(USART2, ENABLE);
055.   
056.  /* DMA Configuration */
057.  DMA_DeInit(DMA1_Stream4);
058.  DMA_InitTypeDef DMA_InitStructure;
059.  DMA_InitStructure.DMA_Channel = DMA_Channel_5;
060.  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART2->DR;
061.  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&datum;
062.  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
063.  DMA_InitStructure.DMA_BufferSize = 1;
064.  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
065.  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
066.  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
067.  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
068.  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
069.  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
070.  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
071.  DMA_Init(DMA1_Stream4, &DMA_InitStructure);
072.  DMA_Cmd(DMA1_Stream4, ENABLE);
073.   
074.  /* Configure TIM3 at 1 Hz */
075.  TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
076.  TIM_TimeBaseInitStructure.TIM_Prescaler = 49999;
077.  TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
078.  TIM_TimeBaseInitStructure.TIM_Period = 1000;
079.  TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
080.  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
081.  TIM_UpdateRequestConfig(TIM3, TIM_UpdateSource_Regular);
082.   
083.  /* OC Configuration */
084.  TIM_OCInitTypeDef TIM_OCInitStructure;
085.  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
086.  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
087.  TIM_OCInitStructure.TIM_Pulse = 0;
088.  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
089.  TIM_OC1Init(TIM3, &TIM_OCInitStructure);
090.  TIM_DMACmd(TIM3, TIM_DMA_CC1, ENABLE);
091.  TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE);
092.   
093.  TIM_Cmd(TIM3, ENABLE);
094.   
095.  cliPrintf("Greetings from USART2.");
096.   
097.  /* Infinite loop */
098.  while (1)
099.  {
100.      ;
101.  }
102.}
And the interrupt handler like this:
1.void TIM3_IRQHandler(void)
2.{
3.    TIM_ClearFlag(TIM3, TIM_FLAG_CC1);
4.     
5.    userLedToggle();
6.}

The LED toggles fine every one second but the DMA doesn't seem to work beyond one character. The USART is working since I get the greeting from line 95 above on Realterm, but after that, I just get one character and nothing afterwards while the LED continues to blink at 1 second.

What could be wrong? What should I try next? Thanks...

Outcomes