STM32L053调试LPUART+DMA+空闲中断收不定长数据时出现帧错误的解决办法

现象

程序仿真正常跑没问题,串口一发数程序就会死在串口错误中断回调函数中

void HAL_UART_ErrorCallback(UART_HandleTypeDef *UartHandle)
{
  while(1)
  {
  }
}

单步调试发现是在

void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)

中的

if (((huart->ErrorCode & HAL_UART_ERROR_ORE) != RESET) ||
          (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)))

条件不满足,跳入了

else
      {
        /* Non Blocking error : transfer could go on. 
           Error is notified to user through user error callback */
        HAL_UART_ErrorCallback(huart);
        huart->ErrorCode = HAL_UART_ERROR_NONE;
      }

此时ErrorCode 中值为4,即发生了frame error ;
关于frame error在参考手册中有如下描述:

帧错误 (Framing error)
如果接收数据时未在预期时间内识别出停止位,从而出现同步失效或过度的噪声,则会检测
到帧错误。
检测到帧错误时:
 FE 位由硬件置 1。
 无效数据从移位寄存器传送到 LPUART_RDR 寄存器。
 单字节通信时无中断产生。然而,在 RXNE 位产生中断时,该位出现上升沿。多缓冲区
通信时,LPUART_CR3 寄存器中的 EIE 位置 1 时将发出中断。
通过将 1 写入 LPUART_ICR 寄存器中的 FECF 位来复位 FE 位。

继续仿真,观察在错误发生前后的寄存器状态变化,发现ORE位置1,RXNE有0-1-0的变化,RDR寄存器中数据为发送数据中的一个,参考以下描述:

上溢错误
如果在 RXNE 未复位时接收到字符,则会发生上溢错误。RXNE 位清零前,数据无法从移位
寄存器传送到 RDR 寄存器。
每接收到一个字节后,RXNE 标志位都将置 1。当 RXNE 标志位是 1 时,如果在接收到下一个
数据或尚未处理上一个 DMA 请求时,则会发生上溢错误。发生上溢错误时:
 ORE 位置 1。
 RDR 中的内容不会丢失。对 LPUART_RDR 执行读操作时可使用先前的数据。
 移位寄存器将被覆盖。之后,上溢期间接收到的任何数据都将丢失。
 如果 RXNEIE 位置 1 或 EIE 位置 1,则会生成中断。
 通过设置 ICR 寄存器中的 ORECF 位复位 ORE 位。

产生了DMA没有正确打开,RDR中数据没有及时取出而导致了问题的出现,仔细排查代码发现DMA通道正确,但request写错了。提醒:参考手册的图中REQ数字与通道数字不对应
STM32L053调试LPUART+DMA+空闲中断收不定长数据时出现帧错误的解决办法