nbh520 发表于 2017-11-7 09:30:43

STM32F411 DMA2 keil调试时,能够使用,不调试,就没有反应

本帖最后由 nbh520 于 2017-11-7 16:58 编辑

STM32F411芯片在使用USART6 RX DMA2时,发现DMA2不能正常工作,经测试发现,在keil调试状态下,DMA2可以正常接收数据,否则不能接收数据。使用环境:其他外设均以关闭,没有进入低功耗,只有USART6处于工作状态,且已验证,在不使用DMA2时,USART6能够正常接收。   USART6的软件配置如下,项目很急,请各路大神,帮帮看看,指点一下。
/******************************UART 6*****************************************/
#define GPS_COMM_USART_6                         USART6
#define GPS_COMM_USART_CLK_ENABLE()            __HAL_RCC_USART6_CLK_ENABLE()
#define DMA2_CLK_ENABLE()                        __HAL_RCC_DMA2_CLK_ENABLE()
#define GPS_COMM_USART_RX_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOC_CLK_ENABLE()
#define GPS_COMM_USART_TX_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOC_CLK_ENABLE()

#define GPS_COMM_USART_FORCE_RESET()             __HAL_RCC_USART6_FORCE_RESET()
#define GPS_COMM_USART_RELEASE_RESET()         __HAL_RCC_USART6_RELEASE_RESET()

/* Definition for USARTx Pins */
#define GPS_COMM_USART_TX_PIN                  GPIO_PIN_6
#define GPS_COMM_USART_TX_GPIO_PORT            GPIOC
#define GPS_COMM_USART_TX_AF                     GPIO_AF8_USART6
#define GPS_COMM_USART_RX_PIN                  GPIO_PIN_7
#define GPS_COMM_USART_RX_GPIO_PORT            GPIOC
#define GPS_COMM_USART_RX_AF                     GPIO_AF8_USART6

/* Definition for USARTx's DMA */
#define GPS_COMM_USART_TX_DMA_CHANNEL            DMA_CHANNEL_5
#define GPS_COMM_USART_RX_DMA_CHANNEL            DMA_CHANNEL_5

/* Definition for USARTx's DMA Request */
#define GPS_COMM_USART_TX_DMA_STREAM             DMA2_Stream6
#define GPS_COMM_USART_RX_DMA_STREAM             DMA2_Stream2

/* Definition for USARTx's NVIC */
#define GPS_COMM_USART_DMA_TX_IRQn               DMA2_Stream6_IRQn
#define GPS_COMM_USART_DMA_RX_IRQn               DMA2_Stream2_IRQn


/**
* @brief UART MSP Initialization
*      This function configures the hardware resources used in this example:
*         - Peripheral's clock enable
*         - Peripheral's GPIO Configuration
* @param huart: UART handle pointer
* @retval None
*/
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
    GPIO_InitTypeDefGPIO_InitStruct;      

    if(huart->Instance == GPS_COMM_USART_6)
    {
      /*##-1- Enable peripherals and GPIO Clocks #################################*/
       GPS_COMM_USART_TX_GPIO_CLK_ENABLE();
       GPS_COMM_USART_RX_GPIO_CLK_ENABLE();
               
       GPS_COMM_USART_CLK_ENABLE();
      
       DMA2_CLK_ENABLE();
      
       /*##-2- Configure peripheral GPIO ##########################################*/
      GPIO_InitStruct.Pin       = GPS_COMM_USART_TX_PIN;
      GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
      GPIO_InitStruct.Pull      = GPIO_PULLUP;
      GPIO_InitStruct.Speed   = GPIO_SPEED_FREQ_VERY_HIGH;
      GPIO_InitStruct.Alternate = GPS_COMM_USART_TX_AF;
      
      HAL_GPIO_Init(GPS_COMM_USART_TX_GPIO_PORT, &GPIO_InitStruct);
      
      GPIO_InitStruct.Pin = GPS_COMM_USART_RX_PIN;
      GPIO_InitStruct.Alternate = GPS_COMM_USART_RX_AF;
      
      HAL_GPIO_Init(GPS_COMM_USART_RX_GPIO_PORT, &GPIO_InitStruct);
      
      /*##-3- Configure the DMA ##################################################*/
   gps_comm_hdma_rx.Instance               = GPS_COMM_USART_RX_DMA_STREAM;
   gps_comm_hdma_rx.Init.Channel             = GPS_COMM_USART_RX_DMA_CHANNEL;      
   gps_comm_hdma_rx.Init.Direction         = DMA_PERIPH_TO_MEMORY;
   gps_comm_hdma_rx.Init.PeriphInc         = DMA_PINC_DISABLE;
   gps_comm_hdma_rx.Init.MemInc            = DMA_MINC_ENABLE;
   gps_comm_hdma_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
   gps_comm_hdma_rx.Init.MemDataAlignment    = DMA_MDATAALIGN_BYTE;
   gps_comm_hdma_rx.Init.Mode                = DMA_NORMAL;
   gps_comm_hdma_rx.Init.Priority            = DMA_PRIORITY_HIGH;
   gps_comm_hdma_rx.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;         
   gps_comm_hdma_rx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
   gps_comm_hdma_rx.Init.MemBurst            = DMA_MBURST_INC4;
   gps_comm_hdma_rx.Init.PeriphBurst         = DMA_PBURST_INC4;
      
   HAL_DMA_Init(&gps_comm_hdma_rx);
      
   /* Associate the initialized DMA handle to the the UART handle */
   __HAL_LINKDMA(huart, hdmarx, gps_comm_hdma_rx);
      
   /*##-4- Configure the NVIC for DMA #########################################*/
   //HAL_NVIC_SetPriority(USART5_DMA_TX_IRQn, 2, 1);
   //HAL_NVIC_EnableIRQ(USART5_DMA_TX_IRQn);
      
      HAL_NVIC_SetPriority(GPS_COMM_USART_DMA_RX_IRQn, GPS_COMM_USART_DMA_RX_IRQn_PRE_PRIORITY,               DEFAULT_IRQ_SUB_PRIORITY);
   HAL_NVIC_EnableIRQ(GPS_COMM_USART_DMA_RX_IRQn);      

   /*##-3- Configure the NVIC for UART ########################################*/
   //HAL_NVIC_SetPriority(GPS_COMM_USART_IRQn, GPS_COMM_USART_DMA_RX_IRQn_PRE_PRIORITY, DEFAULT_IRQ_SUB_PRIORITY);
    //HAL_NVIC_EnableIRQ(GPS_COMM_USART_IRQn);            
    }
}

/*************************************************************************   
**      function name:      gps_comm_init
**      description:                        
**      input para:               
**                        
**      return:                                                               
**************************************************************************/
void gps_comm_init(void)
{
    UartHandle.Instance      = GPS_COMM_USART_6;
   
    UartHandle.Init.BaudRate   = 9600;
    UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
    UartHandle.Init.StopBits   = UART_STOPBITS_1;
    UartHandle.Init.Parity   = UART_PARITY_NONE;
    UartHandle.Init.HwFlowCtl= UART_HWCONTROL_NONE;
    UartHandle.Init.Mode       = UART_MODE_TX_RX;
    UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;
   
    if (HAL_UART_Init(&UartHandle) != HAL_OK)
    {
      /* Initialization Error */
      GPS_COMM_DRIVER_DEBUG("** MY DEBUG INTERFACE FAILED. ** \r\n");
    }
    else
    {
      //MY_DEBUG("** MY DEBUG INTERFACE successfully. ** \r\n");
    }
}


nbh520 发表于 2017-11-7 16:57:49

使用DMA做串口接收时,在启动DMA后需要将串口溢出标志清除(有些应用场景,串口接收端是一直有数据存在的),才能正常接收。
这个问题之前在使用STM32L072时,就已经发现解决了,但由于F4平台和L0平台在清除溢出标志方式略有不同。
为了避免有人出现同样的问题,下面给大家描述一下,两者的不同之处:STM32L0清除USART标志直接调用__HAL_USART_CLEAR_IT()即可
STM32F4 __HAL_UART_CLEAR_FLAG()能够清除的标志只有UART_FLAG_CTS、UART_FLAG_LBD、UART_FLAG_TC、UART_FLAG_RXNE,而PE (Parity error), FE (Framing error), NE (Noise error), ORE (Overrun error) and IDLE (Idle line detected) flags 等标志的清除需要读取USART_SR register才行。
STM32L0
/** @briefClears the specified USART ISR flag, in setting the proper ICR register flag.
* @param__HANDLE__: specifies the USART Handle which can be USART1 or USART2.
* @param__IT_CLEAR__: specifies the interrupt clear register flag that needs to be set
*                     to clear the corresponding interrupt
*          This parameter can be one of the following values:
*            @arg USART_CLEAR_PEF: Parity Error Clear Flag
*            @arg USART_CLEAR_FEF: Framing Error Clear Flag
*            @arg USART_CLEAR_NEF: Noise detected Clear Flag
*            @arg USART_CLEAR_OREF: OverRun Error Clear Flag
*            @arg USART_CLEAR_IDLEF: IDLE line detected Clear Flag
*            @arg USART_CLEAR_TCF: Transmission Complete Clear Flag
*            @arg USART_CLEAR_CTSF: CTS Interrupt Clear Flag
* @retval None
*/
#define __HAL_USART_CLEAR_IT(__HANDLE__, __IT_CLEAR__) ((__HANDLE__)->Instance->ICR = (uint32_t)(__IT_CLEAR__))

STM32F4
/** @briefClears the specified UART pending flag.
* @param__HANDLE__: specifies the UART Handle.
*         This parameter can be UARTx where x: 1, 2, 3, 4, 5, 6, 7 or 8 to select the USART or
*         UART peripheral.
* @param__FLAG__: specifies the flag to check.
*          This parameter can be any combination of the following values:
*            @arg UART_FLAG_CTS:CTS Change flag (not available for UART4 and UART5).
*            @arg UART_FLAG_LBD:LIN Break detection flag.
*            @arg UART_FLAG_TC:   Transmission Complete flag.
*            @arg UART_FLAG_RXNE: Receive data register not empty flag.
*   
* @note   PE (Parity error), FE (Framing error), NE (Noise error), ORE (Overrun
*          error) and IDLE (Idle line detected) flags are cleared by software
*          sequence: a read operation to USART_SR register followed by a read
*          operation to USART_DR register.
* @note   RXNE flag can be also cleared by a read to the USART_DR register.
* @note   TC flag can be also cleared by software sequence: a read operation to
*          USART_SR register followed by a write operation to USART_DR register.
* @note   TXE flag is cleared only by a write to the USART_DR register.
*   
* @retval None
*/
#define __HAL_UART_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->SR = ~(__FLAG__))



MrJiu 发表于 2017-11-7 11:23:45

现在都使用的Cube一键配置了。。。。。现在能够帮你看出问题来的人,估计只有cube了!!!

nbh520 发表于 2017-11-7 14:45:11

MrJiu 发表于 2017-11-7 11:23
现在都使用的Cube一键配置了。。。。。现在能够帮你看出问题来的人,估计只有cube了!!! ...

cube配置的代码,我也对比看了,没什么问题。本来想用keil断点调试看看,问题出在哪,结果就发现调试的时候,DMA2能够正常接收,吐血啊。

卖男孩的小火柴 发表于 2018-3-19 11:59:57

nbh520 发表于 2017-11-7 16:57
使用DMA做串口接收时,在启动DMA后需要将串口溢出标志清除(有些应用场景,串口接收端是一直有数据存在的), ...

你好!在论坛里看到你说用stm32L072做过DMA串口接收。我也在用DMA+串口空闲中断做任意长度数据的接收。现在遇到一个问题,如下:
假设DMA缓冲区长度为N,当数据长度≥N+1时,DMA接收中断能接收到前N个,串口空闲中断能接收到第N+1个,无论数据多长,串口空闲中断也只能接到1个。发现是串口溢出,我在串口中断中把溢出标志清除了,仍是如此。求指教。谢谢。
页: [1]
查看完整版本: STM32F411 DMA2 keil调试时,能够使用,不调试,就没有反应