AnsweredAssumed Answered

Stm32F4 dma -> usart int is never called no output on usart

Question asked by mccarty.michael on Jan 9, 2013
Latest reply on Mar 15, 2013 by bean.andrew
Good Morning,
  I'm migrating my code from a stm32f10x based discovery board, to the stm32f407 based discovery board. Everything was going reasonably well until I tried to transmit on usart2 using dma. I have code that transmits dma then in the interrupt for tc it calls that function again to progress the state machine sending the next portion of dma data. 

 I never hit the breakpoint in the DMA1_Stream0_IRQHandler, and the data I receive is none. I have tested just sending data to the port using senddata that works fine. 

 Is there some restriction to which dma stream i can use on the usart ? Is there a certain order to which i have to call the functions ? 

#define zbCom_USART                        USART2
#define zbCom_DRADDR                            (uint32_t)&(USART2->DR)
#define zbCom_USART_CLK                    RCC_APB1Periph_USART2

#define zbCom_USART_TX_PIN                 GPIO_Pin_2
#define zbCom_USART_TX_GPIO_PORT           GPIOA
#define zbCom_USART_TX_GPIO_CLK            RCC_AHB1Periph_GPIOA
#define zbCom_USART_TX_SOURCE              GPIO_PinSource2
#define zbCom_USART_TX_AF                  GPIO_AF_USART2


#define zbCom_USART_RX_PIN                 GPIO_Pin_3
#define zbCom_USART_RX_GPIO_PORT           GPIOA
#define zbCom_USART_RX_GPIO_CLK            RCC_AHB1Periph_GPIOA
#define zbCom_USART_RX_SOURCE              GPIO_PinSource3
#define zbCom_USART_RX_AF                  GPIO_AF_USART2


#define zbCom_USART_IRQn                   USART2_IRQn
#define zbCom_DMA_STREAM_IRQ                   DMA1_Stream0_IRQn


#define zbCom_Usart_DMA_Stream                    DMA1_Stream0
#define zbCom_Usart_DMA_CLK                         RCC_AHB1Periph_DMA1



void initComm()
{
     NVIC_InitTypeDef           NVIC_InitStructure;


     // init clocks
     RCC_APB1PeriphClockCmd(zbCom_USART_TX_GPIO_CLK, ENABLE); 
     RCC_APB1PeriphClockCmd(zbCom_USART_RX_GPIO_CLK, ENABLE); 
     RCC_APB1PeriphClockCmd(zbCom_USART_CLK,ENABLE);
     RCC_AHB1PeriphClockCmd(zbCom_Usart_DMA_CLK, ENABLE);


     // int our vector table
          /* Enable the DMA Stream IRQ Channel */
     NVIC_InitStructure.NVIC_IRQChannel = zbCom_DMA_STREAM_IRQ;
     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
     NVIC_Init(&NVIC_InitStructure); 
          /* Enable the USARTz Interrupt */
     NVIC_InitStructure.NVIC_IRQChannel = zbCom_USART_IRQn;
     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
     NVIC_Init(&NVIC_InitStructure);


     // init circular buffer
     cbInit(&rxUSCBuff);
       // --- config for usart comm


     // init the usart output 
     USART2_Config();


     // init the dma for usart tx
     //initDMA2();
}


void USART2_Config(void)
{
     USART_InitTypeDef           USART_InitStructure;
     GPIO_InitTypeDef GPIO_InitStructure; 
     
     GPIO_InitStructure.GPIO_Pin = zbCom_USART_TX_PIN | zbCom_USART_RX_PIN;
     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_50MHz;
     GPIO_Init(zbCom_USART_TX_GPIO_PORT, &GPIO_InitStructure);


     GPIO_PinAFConfig(zbCom_USART_TX_GPIO_PORT, zbCom_USART_TX_SOURCE, zbCom_USART_TX_AF);
     GPIO_PinAFConfig(zbCom_USART_RX_GPIO_PORT, zbCom_USART_RX_SOURCE, zbCom_USART_RX_AF);
     
     USART_InitStructure.USART_BaudRate = UARTBAUD;
     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(zbCom_USART, &USART_InitStructure);
     
     // hold onto your butts
     USART_Cmd(zbCom_USART, ENABLE);
}

void DMA_TXPush(void)
{
     DMA_InitTypeDef           DMA_InitStructure;
     u8 *dataPointer = 0;
     u16 len = 0;
     
     if(dmaTX.state == done)
     return;
     if(dmaTX.state == data)
     {
     dmaTX.state = done;
     dataPointer = dmaTX.offset;
     len = dmaTX.count;
     }
     if(dmaTX.state == new)
     {
     dmaTX.state = data;
     dataPointer = dmaTX.txHdr;
     len = hdrSize;
     }
     
     /* USARTy_Tx_DMA_Channel (triggered by USARTy Tx event) Config */
     DMA_DeInit(zbCom_Usart_DMA_Stream);
       /* Check if the DMA Stream is disabled before enabling it.
      Note that this step is useful when the same Stream is used multiple times:
      enabled, then disabled then re-enabled... In this case, the DMA Stream disable
      will be effective only at the end of the ongoing data transfer and it will
      not be possible to re-configure it before making sure that the Enable bit
      has been cleared by hardware. If the Stream is used only once, this step might
      be bypassed. */
     while (DMA_GetCmdStatus(zbCom_Usart_DMA_Stream) != DISABLE)
     {
     }
     DMA_InitStructure.DMA_Channel = DMA_Channel_0;
     DMA_InitStructure.DMA_PeripheralBaseAddr = zbCom_DRADDR;     // usart2 data register
     DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)dataPointer;
     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;     // IS THIS BACKWARDS ? 
     DMA_InitStructure.DMA_BufferSize = len;
     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_MemoryBurst = DMA_MemoryBurst_Single;
     DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
     
     DMA_Init(zbCom_Usart_DMA_Stream, &DMA_InitStructure);
     
     USART_DMACmd(zbCom_USART, USART_DMAReq_Tx, ENABLE);
     
     /* Enable DMA Stream Half Transfer and Transfer Complete interrupt */
     DMA_ITConfig(zbCom_Usart_DMA_Stream, DMA_IT_TC|DMA_IT_TE|DMA_IT_FE, ENABLE);
     
     // start the dma transfer, it will execute now
     DMA_Cmd(zbCom_Usart_DMA_Stream, ENABLE);


}


/**
  * @brief 
  *       
  *         
  * @note   
  * @param  none
  * @retval none
  */
void DMA1_Stream0_IRQHandler(void)
{
     /*
  *            @arg DMA_IT_TCIFx:  Streamx transfer complete interrupt
  *            @arg DMA_IT_HTIFx:  Streamx half transfer complete interrupt
  *            @arg DMA_IT_TEIFx:  Streamx transfer error interrupt
  *            @arg DMA_IT_DMEIFx: Streamx direct mode error interrupt
  *            @arg DMA_IT_FEIFx:  Streamx FIFO error interrupt     */
  if(DMA_GetITStatus(zbCom_Usart_DMA_Stream, DMA_IT_TEIF0|DMA_IT_DMEIF0|DMA_IT_FEIF0))
  {
            printf("USART DMA ERROR");
            return; // fail
  }
  /* Test on DMA Stream Transfer Complete interrupt */
  if(DMA_GetITStatus(zbCom_Usart_DMA_Stream, DMA_FLAG_TCIF0))
  {
    /* Clear DMA Stream Transfer Complete interrupt pending bit */
    DMA_ClearITPendingBit(zbCom_Usart_DMA_Stream, DMA_FLAG_TCIF0);  
    
    // kick off next segment or quit
     DMA_TXPush();
  }
}




Outcomes