Serial port 具有两个USART中断的溢出错误

Serial port 具有两个USART中断的溢出错误,serial-port,embedded,interrupt,stm32,Serial Port,Embedded,Interrupt,Stm32,在STM32F2上使用两个以115200波特运行的USART,一个用于与无线电模块通信,另一个用于从PC串行。时钟速度为120MHz 当同时从两个USART接收数据时,一个USART或另一个USART上可能会发生溢出错误。做一些快速返回信封的计算应该有足够的时间来处理这两个问题,因为中断只是简单地将字节复制到一个循环缓冲区 从理论上和测量上看,将字节推送到缓冲区的中断代码应该/确实以2-4µS的顺序运行,在115200波特时,我们有大约70us的时间来处理每个字符 为什么我们在一个或另一个USA

在STM32F2上使用两个以115200波特运行的USART,一个用于与无线电模块通信,另一个用于从PC串行。时钟速度为120MHz

当同时从两个USART接收数据时,一个USART或另一个USART上可能会发生溢出错误。做一些快速返回信封的计算应该有足够的时间来处理这两个问题,因为中断只是简单地将字节复制到一个循环缓冲区

从理论上和测量上看,将字节推送到缓冲区的中断代码应该/确实以2-4µS的顺序运行,在115200波特时,我们有大约70us的时间来处理每个字符

为什么我们在一个或另一个USART上看到偶然的矿石

更新-其他信息:

  • 目前我们代码中没有其他ISR正在开火
  • 我们正在运行Keil RTX,systick中断配置为每10毫秒触发一次
  • 我们目前没有禁用任何中断
  • 根据这本书(《Cortex-M处理器系列设计师指南》),中断延迟约为12个周期(并非真正致命)
  • 考虑到以上所有70个U在我们清除中断的时间内至少是10倍,所以我不确定这是否很容易解释。我是否应该得出结论,肯定还有其他一些因素我在仔细考虑

    MDK-ARM版本为4.70


    systick中断由RTO使用,因此无法计时,其他ISR每字节运行2-3µS

    几个月前,我在Cortex M4(SAM4S)上遇到了与你类似的问题。我有一个函数,根据定时器中断以100赫兹的频率被调用

    同时,我配置了一个UART来中断字符接收。UART上的预期数据是64字节长的数据包,每个字符上的中断都会导致延迟,因此我的100Hz更新功能在20Hz左右运行。在这个120MHz的处理器上,100Hz的速度相对较慢,但每个字符上的中断都会导致大量延迟

    我决定将UART配置为使用PDC(外围DMA控制器),我的问题立即消失了

    DMA允许UART将数据存储在内存中,而不中断处理器,直到缓冲区已满,从而节省大量开销

    在我的例子中,我告诉PDC将UART数据存储到缓冲区(字节数组)中,并指定了长度。当UART通过PDC填充缓冲区时,PDC发出中断

    在PDC ISR中:

  • 给PDC一个新的空缓冲区
  • 重新启动UART PDC(这样我们可以在isr中执行其他操作时收集数据)
  • memcpy将完整缓冲区转换为环形缓冲区
  • 退出ISR

  • 正如上面swineone所建议的,实施DMA,你就会热爱生活。

    也有类似的问题。短解决方案-将过采样更改为8位,使USART时钟更精确。明智地选择你的MCU时钟

    huart1.Init.OverSampling = UART_OVERSAMPLING_8;
    
    此外,添加USART错误处理程序和机制以检查数据是否有效,例如CRC16。这里是STM32F0xx系列的示例,我假设它在整个系列中应该非常相似

    void UART_flush(void) {
      // Flush UART RX buffer if RXNE is set
      if READ_BIT(huart1.Instance->ISR, USART_ISR_RXNE) {
        SET_BIT(huart1.Instance->RQR, UART_RXDATA_FLUSH_REQUEST);
      }
    
      // Not available on F030xx devices!
      // SET_BIT(huart1.Instance->RQR, UART_TXDATA_FLUSH_REQUEST);
    
      // Clear All Errors (if needed)
      if (READ_BIT(huart1.Instance->ISR, USART_ISR_ORE | USART_ISR_FE | USART_ISR_NE)) {
        SET_BIT(huart1.Instance->ICR, USART_ICR_ORECF | USART_ICR_FECF | USART_ICR_NCF);
      }
    }
    
    // USART Error Handler
    void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) {
      if(huart->Instance==USART1) {
        // See if we have any errors
        if (READ_BIT(huart1.Instance->ISR, USART_ISR_ORE | USART_ISR_FE | USART_ISR_NE | USART_ISR_RXNE)) {
            // Flush errors
            UART_flush();
    
            // Raise Error Handler
            _Error_Handler(__FILE__, __LINE__);
        }
      }
    }
    

    DMA也可能有所帮助。我的问题与USART时钟容差有关,这甚至可能导致DMA实现时的溢出错误。因为这是USART的硬件问题。不管怎样,希望这能帮助别人!干杯

    我最近遇到了这个问题,所以我实现了一个UART_ErrorCallback函数,它还没有被植入(只是_弱版本)。 是这样的:

    void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
    {
         if(huart == &huart1)
         {
             HAL_UART_DeInit(&huart1);
             MX_USART1_UART_Init(); //my initialization code
          ...
    

    这就解决了超支问题。

    你没有提供足够的信息让别人说出你为什么会超支。明显的候选者:在其他地方禁用中断?高优先级中断处理程序太慢?代码中有Bug吗?没有足够的信息来确定哪个.ISR延迟在该芯片上是非常致命的,UART没有fifo缓冲区。你的理论计算已经偏离了2倍。添加ISR占用太多时间的高优先级中断,或者在您不知道的代码中禁用中断,并且溢出很容易解释。感谢您的评论,我为问题添加了更多信息,我不确定还能提供哪些其他信息。RTX(或ARM-MDK)的哪个版本?Cortex-M3的早期版本有缺陷,不完全支持中断优先级分组。如果没有代码,这个问题可能无法回答。我不会放弃一个无法解释的问题,因为以后症状可能会在其他地方出现。尽管如此,在我最近的几个项目中,我一直使用DMA来创建一个循环缓冲区,用于存储从USART接收的数据。实际的硬件(DMA控制器)不会错过最后期限(除非它也过载了,但除非你用它做其他事情,否则以这种速度进行2次使用应该是小菜一碟)。