关注、星标公众号,直达精彩内容
最近开发低功耗产品,工作模式为唤醒情况下正常工作,没什么特别的,没有外部唤醒的时候,MCU进入STOP模式,间隔RTC唤醒(2S一次),或者外部中断唤醒,串口为其中的一种唤醒方式。
正常工作模式下,串口收发数据帧一直运行几个小时都没问题,但是在低功耗进入STOP模式之后,通讯唤醒,主机通讯,会出现无法通讯的情况,过了几秒又恢复正常,一般5S以内,偶尔较长时间,为何?
目前只是解决了问题,但是出现问题的原因还没有找到,有经验的小伙伴可以一起探讨交流下!!!
正常工作模式下既然长时间工作一直不出问题,应用层的数据通讯解析逻辑肯定是没问题的,可以放过了。
重点就放在了跟串口底层相关的部分,因为在进STOP模式之前会把所有的外设处理一下,串口、DMA都会关掉,唤醒之后重新使能,问题可能出在了这里,但是分析完之后也没有发现有什么异常。
既然可能是串口底层出了问题,咱们重点来抓一下串口底层的一些现象,这里HAL库做了很多的回调函数,前面4个是正常的传输回调函数,后面几个是异常回调,既然现在是出现了问题,不妨来监测一下看看:
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);
使用这个,别问为啥,想瞎猫碰死耗子~~~:
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库中本身是个“弱函数”,什么是“弱函数”,大家动动小手自己百度下了哈,用户可以自己实现一样的名字的函数,供系统回调,打印个提示信息看看:
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART3)
{
LOG_E("comm error!!!");
}
}
测试下看看,会不会出错,从打印的信息来看,瞎猫确实碰到死耗子了..果然有错误,既然有错误了,就继续究根刨底下去:
调用这个回调函数的地方还挺多,那究竟跟哪一个啊?
翻一翻,加上我们是用DMA出现的问题,找找跟DMA相关的,DMA传输错误会调用这个回调,这个DMA错误在串口中断中有调用,这样好像就都联系起来了:
能够进来这个DMA错误回调的条件是下面这个,发生以下通讯错误的时候,会进一步处理:
/** @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 */
接下来检测下发生的错误,每一个错误都打印出来:
有时候也会出现噪声错误
错误对应的是,帧错误,噪声错误:
#define HAL_UART_ERROR_FE (0x00000004U) /*!< Frame error */
#define HAL_UART_ERROR_NE (0x00000002U) /*!< Noise error */
定位到问题了,接下来先打个补丁,能够正常使用,在错误回调里面清除标志,重新DMA接收:
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); //接收配置
}
}
目前仅仅是问题得到了解决,但是为什么出现这个问题还在研究中,有知道的小伙伴吗?可以交流下!!