This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TM4C1294NCPDT:较高波特率下 UART RX 丢失数据

Guru**** 2535750 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1232425/tm4c1294ncpdt-uart-rx-missing-data-at-higher-baud-rate

器件型号:TM4C1294NCPDT

我需要定期接收一串长度约为45字节且波特率为115200的 RS-232数据、但 在该字符串的后面部分会丢失。

如果我接收到的字符串是"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"、我将始终获得前16个字符、这是有道理的、因为 UART FIFO 是16个字节、但我会错过许多后面的字节、例如、我可能只会从 字母的中到后部分得到几个字符。

我将执行长度  操作、以确保我尽快调用 UARTGetChar、而不会在调用时让中断发生-请查看下面的代码-但我仍然错过了数据。  如果我将速度减至9600、我似乎 不会错过任何数据、但这对于我的需求来说太慢了。

我想知道在115200不丢失数据的情况下执行此操作的唯一方法是将 DMA 与 UART 配合使用吗?

我已按如下方式配置 UART:

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

// Configure the GPIO Pin Mux for RX
GPIOPinConfigure(GPIO_PA0_U0RX);
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0);

// Configure the GPIO Pin Mux for TX
GPIOPinConfigure(GPIO_PA1_U0TX);
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_1);

// Enable the UART module
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
while(!SysCtlPeripheralReady(SYSCTL_PERIPH_UART0));

// Configure the given serial IO port for the given baud rate and, 8-N-1 operation.
UARTConfigSetExpClk(UART0_BASE, sysClockFreq, 115200, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));

UARTFIFOLevelSet(UART0_BASE, UART_FIFO_TX1_8, UART_FIFO_RX1_8);

// Enable the RX UART interrupt.
IntEnable(INT_UART0);
UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT);        

此外、中断处理程序:

   
void SerialCommIntHandler(enum SERIAL_COMM_NUM serialCommNum)
{
     // Get the interrupt status
    uint32_t status = UARTIntStatus(UART0_BASE, true);

    // Clear the asserted interrupts
    UARTIntClear(UART0_BASE, status);

    IntMasterDisable();
            
    // Loop while there are characters in the receive FIFO
    while(UARTCharsAvail(UART0_BASE))
    {
        LogInfo("%c", UARTCharGetNonBlocking(UART0_BASE));
    }
        
    IntMasterEnable();
}

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

     我有几个建议供您尝试。  

     -首先检查您是否在 UARTDR 寄存器中获得了 OE 标志(UART 溢出错误)。 如果存在溢出错误、系统会确认 FIFO 是否被新数据覆盖、然后处理器才能够处理未读数据。

     -我不知道你花了多少时间在 ISR 由于 LogInfo。 通常、我们建议在 ISR 外部处理数据。 您可以在进入 ISR 时设置标志。 如果标志被置位,请读取 main ()中的 RXFIFO。 完成 RXFIFO 读取后、您可以再次清除此标志。 原因是当您使用 LogInfo()处理数据时,可能会出现更多的字符。 将 FIFO 级别设置为1/8、这意味着2个字符。 接下来的两个字符应该会生成 RXFIFO 中断、但您仍在 ISR 中。 新的中断可能会丢失。  

     -如上所述,LogInfo 应在外部完成。 我不知道您是如何实现 LogInfo 的。 看起来好像重新设置数据格式(例如 usprintf)、并且可能会花费许多周期。 它与 UARTPrintf()类似,我们通常尝试避免在任何 ISR 内调用。 ISR 应快速退出。  

     -尝试将 FIFO 级别中断从1/8增加到更高(如1/2),以便在生成中断之前接收到更多数据。 查看这是否对情况有帮助。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您 发送编修 。  要回复上一封邮件中的要点:

    • 是的、我已经确认我遇到过运行错误。  请查看 下面的 screenshot。
    • 同意在中断中使用 LogInfo()是不好的。  我已将其替换为一个简单的缓冲区 、将字符复制到该缓冲区中、您将在下图中看到该缓冲区。
    • 我已经按照您的建议、使用 UART_FIFO_RX4_8将 FIFO 中断增加到1/2、问题仍然存在。

    经过进一步的调查、我认为发生的情况是 SysTick 中断阻止或中断 UART RX 中断。  SysTick 中断花费了很多时间。  遗憾的是、这是必要的、因为 SysTick 中每10毫秒发生一次重要的 I2C 通信。

    我认为、由于 SysTick 具有更高的优先级、因此它要么阻断要么中断 UART RX 中断。

    我认为、如果我将 DMA 与 UART 一起使用、这应该可以解决问题。   DMA 将在 UART 控制器和 DMA 控制器之间的后台发生、填充一个缓冲区、然后我可以在 SysTick 中断后处理这个缓冲区。  你同意吗?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Terence:

     是的、UDMA 应该可以解决该问题。 有一个 udma_demo 示例 使用乒乓模式在 SRAM 和 UART 之间进行传输。 我不知道您的应用与 SysTick 中断的使用相关。 当处于 UART 中断内部时、您可以考虑禁用 NVIC 中断、以便它不会被 SysTick 中断抢先。 但是、如果您的 SysTick 中断至关重要、则该选项可能不可行。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    非常感谢 。   是、 我已经考虑在 UART 中断处理程序内部禁用 中断、但我认为、如果 SysTick 中断当前被触发、并且已接收到 UART RX 中断、但在接收数据时缓冲区溢出仍然会出现问题 而导致的中断。  你不同意吗?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    但我认为 如果当前触发 SysTick 中断并且已接收 UART RX 中断但由于 SysTick 中断而长时间被阻止,接收数据时缓冲区溢出仍会出现问题。  您不同意吗?

    我同意、如果 SysTick 在 ISR 中花费了大量时间、由于 SysTick 具有更高的优先级、它会阻止向 UART 中断提供服务。 你可以更改 UART 与 SysTick 的优先级、但这可能会对 SysTick 端产生影响。 使用 UDMA 可以缓解这一问题。   

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    好的、我来试一下。  非常感谢 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    -感谢您的帮助。  我已经实现了 DMA、看上去运行良好。