ST意法半导体
直播中

吴湛

10年用户 827经验值
擅长:33391
私信 关注
[问答]

HAL_UART_Receive_DMA 随机停止工作怎么处理?

我正在使用 STM32WB5MMG,但我认为这个问题与 MCU 的无线电部分无关,所以我在更一般的社区发帖。我希望没关系。
我正在使用 HAL_UART_Receive_DMA 函数通过 UART 从 GPS 接收器读取数据。数据以 230400 波特率传入。DMA 配置为 512 字节的简单(非循环)缓冲区。在 HAL_UART_RxCpltCallback 处理程序中,我再次调用 HAL_UART_Receive_DMA 以开始新的传输。
我这样做(而不是使用循环模式),以便我可以通过计算 512 字节的完整“帧”数并添加 (512 - CNDTR) 来计算传输的字节总数。我担心的是,如果我使用循环缓冲区,那么相对于 CNDTR 更新的帧数更新时间会有些模糊。
通常,这工作正常。但是在接收数据几分钟后,CNDTR 似乎停止了更新。我已经检查过 GPS 模块仍然有数据传入。奇怪的是,当CNDTR停止更新时,它总是等于511(即比缓冲区长度小1)。
我偶然发现了一种获得类似结果的方法......
  • 在调试模式下运行固件
  • 打破我通常处理传入数据的地方
  • 去掉断点继续执行
  • 再次设置断点
当调试器第二次中断时,同样,CNDTR 停留在 511。这似乎是由于某种溢出,这让我认为对于我遇到的实际问题可能也是如此。
但是,永远不会调用 HAL_UART_ErrorCallback,并且当错误发生时,似乎没有任何寄存器指示溢出(具体查看 DMA2 和 DMAMUX1 SFR)。
粗略地说,这是我的代码结构:
  • #define GNSS_RX_BUF_LEN                512                // Circular buffer for UART
  • #define GNSS_UPDATE_MSEC    10
  • #define GNSS_UPDATE_RATE    (GNSS_UPDATE_MSEC*1000/CFG_TS_tiCK_VAL)
  • uint8_t  gnssRxData[GNSS_RX_BUF_LEN];        // data buffer
  • uint32_t gnssRxIndex = 0;                                // read index
  • void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  • {
  •         // Begin DMA transfer
  •         HAL_UART_Receive_DMA(&huart1, gnssRxData, GNSS_RX_BUF_LEN);
  • }
  • void GNSS_Init(void)
  • {
  •         // Begin DMA transfer
  •         HAL_UART_Receive_DMA(&huart1, gnssRxData, GNSS_RX_BUF_LEN);
  •         // Initialize GNSS task
  •         UTIL_SEQ_RegTask(1<
  •         // Initialize GNSS update timer
  •         HW_TS_Create(CFG_TIM_PROC_ID_ISR, &timer_id, hw_ts_Repeated, GNSS_Timer);
  •         HW_TS_Start(timer_id, GNSS_UPDATE_RATE);
  • }
  • static void GNSS_Timer(void)
  • {
  •         // Call update task
  •         UTIL_SEQ_SetTask(1<}
  • static void GNSS_Update(void)
  • {
  •         uint32_t cndtr = huart1.hdmarx->Instance->CNDTR;
  •         uint32_t writeIndex = GNSS_RX_BUF_LEN - cndtr;
  •         while (gnssRxIndex != writeIndex)
  •         {
  •                 // Handle a byte and increment gnssRxIndex
  •         }
  • }
任何帮助将不胜感激。如果发生超限,我不完全确定我会在哪里捕获它——我认为 SFR 会改变,但也许不会?我希望这个问题对外面的人来说很熟悉。




回帖(1)

李娟

2023-1-9 10:51:45
最有可能的是 UART 溢出,CNDTR 一直低于满意味着这是 DMA 重启不够快的结果(难怪,考虑到 Cube/HAL 膨胀)。坚持循环 DMA,学习处理潜在的 NDTR 环绕。
> 然而,HAL_UART_ErrorCallback 从未被调用,
调试吧,Cube是开源的。溢出不是 DMA/DMAMUX“功能”,而是 UART,所以看那里。RM 是你的朋友。检查,如果底层 UART ISR 被调用,如果是,问题出在 Cube 的 harness 中,如果没有,调试通常中断被调试。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分