前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >求解:串口DMA STOP模式下唤醒崩了

求解:串口DMA STOP模式下唤醒崩了

作者头像
用户8913398
发布2023-03-05 14:42:27
8470
发布2023-03-05 14:42:27
举报

问题背景

最近开发低功耗产品,工作模式为唤醒情况下正常工作,没什么特别的,没有外部唤醒的时候,MCU进入STOP模式,间隔RTC唤醒(2S一次),或者外部中断唤醒,串口为其中的一种唤醒方式。

问题:

正常工作模式下,串口收发数据帧一直运行几个小时都没问题,但是在低功耗进入STOP模式之后,通讯唤醒,主机通讯,会出现无法通讯的情况,过了几秒又恢复正常,一般5S以内,偶尔较长时间,为何?

目前只是解决了问题,但是出现问题的原因还没有找到,有经验的小伙伴可以一起探讨交流下!!!

问题分析

正常工作模式下既然长时间工作一直不出问题,应用层的数据通讯解析逻辑肯定是没问题的,可以放过了。

重点就放在了跟串口底层相关的部分,因为在进STOP模式之前会把所有的外设处理一下,串口、DMA都会关掉,唤醒之后重新使能,问题可能出在了这里,但是分析完之后也没有发现有什么异常。

既然可能是串口底层出了问题,咱们重点来抓一下串口底层的一些现象,这里HAL库做了很多的回调函数,前面4个是正常的传输回调函数,后面几个是异常回调,既然现在是出现了问题,不妨来监测一下看看:

代码语言:javascript
复制
void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart);
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);
void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart);
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);


void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart);
void HAL_UART_AbortCpltCallback(UART_HandleTypeDef *huart);
void HAL_UART_AbortTransmitCpltCallback(UART_HandleTypeDef *huart);
void HAL_UART_AbortReceiveCpltCallback(UART_HandleTypeDef *huart);

使用这个,别问为啥,想瞎猫碰死耗子~~~:

代码语言:javascript
复制
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart);


/**
  * @brief  UART error callback.
  * @param  huart UART handle.
  * @retval None
  */
__weak void HAL_UART_ErrorCallback(UART_HandleTypeDef *

这个在HAL库中本身是个“弱函数”,什么是“弱函数”,大家动动小手自己百度下了哈,用户可以自己实现一样的名字的函数,供系统回调,打印个提示信息看看:

代码语言:javascript
复制
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
  if(huart->Instance == USART3)
  {
    LOG_E("comm error!!!");
  }
}

测试下看看,会不会出错,从打印的信息来看,瞎猫确实碰到死耗子了..果然有错误,既然有错误了,就继续究根刨底下去:

调用这个回调函数的地方还挺多,那究竟跟哪一个啊?

翻一翻,加上我们是用DMA出现的问题,找找跟DMA相关的,DMA传输错误会调用这个回调,这个DMA错误在串口中断中有调用,这样好像就都联系起来了:

能够进来这个DMA错误回调的条件是下面这个,发生以下通讯错误的时候,会进一步处理:

代码语言:javascript
复制
/** @defgroup UART_Error_Definition   UART Error Definition
  * @{
  */
#define  HAL_UART_ERROR_NONE             (0x00000000U)    /*!< No error*/

#define  HAL_UART_ERROR_PE               (0x00000001U)    /*!< Parity error            */
#define  HAL_UART_ERROR_NE               (0x00000002U)    /*!< Noise error             */
#define  HAL_UART_ERROR_FE               (0x00000004U)    /*!< Frame error             */
#define  HAL_UART_ERROR_ORE              (0x00000008U)    /*!< Overrun error           */
#define  HAL_UART_ERROR_DMA              (0x00000010U)    /*!< DMA transfer error      */
#define  HAL_UART_ERROR_RTO              (0x00000020U)    /*!< Receiver Timeout error  */


接下来检测下发生的错误,每一个错误都打印出来:

有时候也会出现噪声错误

错误对应的是,帧错误,噪声错误:

代码语言:javascript
复制
#define  HAL_UART_ERROR_FE               (0x00000004U)    /*!< Frame error             */

#define  HAL_UART_ERROR_NE               (0x00000002U)    /*!< Noise error             */

定位到问题了,接下来先打个补丁,能够正常使用,在错误回调里面清除标志,重新DMA接收:

代码语言:javascript
复制
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
  if(huart->Instance == USART3)
  {
      LOG_E("comm error!!!");
      __HAL_UART_CLEAR_FLAG(&m_sUartxHandle,UART_CLEAR_FEF);//清除帧错误标志
     __HAL_UART_CLEAR_FLAG(&m_sUartxHandle,USART_ICR_NECF);//清除噪声错误标志

      Bsw_EUART_InitVariables();
      HAL_UART_Receive_DMA(&m_sUartxHandle,m_Uart_DMARX_Frame.rec_buffer,DMA_REC_DATA_LEN);
      Bsw_Uart_ReceviceCfg(ENABLE);                           //接收配置  
  }
}

目前仅仅是问题得到了解决,但是为什么出现这个问题还在研究中,有知道的小伙伴吗?可以交流下!!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-11-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 小飞哥玩嵌入式 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题背景
    • 问题:
    • 问题分析
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档