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.

[参考译文] TM4C123GH6PM:UART TX 中断丢失

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/569283/tm4c123gh6pm-uart-tx-interrupt-lost

器件型号:TM4C123GH6PM
主题中讨论的其他器件:TM4C123

您好!


我有一个很大的项目、它包含许多模块。 一个模块负责通过 UART 与主机系统进行通信。 我禁用 FIFO 并为每个发送的字节使用一个中断、我的问题是、当我使用 UARTTxIntModeSet (UART_base、UART_TXINT_MODE_FIFO)时、在某个随机的时间时刻、在消息传输期间不会触发中断。 它可以在数百万次成功的交易之后发生、绝对是随机发生的。 另一方面、当我使用 UARTTxIntModeSet (UART_base、UART_TXINT_MODE_EOT)时、一切都正常、但我对 MODE_FIFO 为什么会出现这样一个奇怪的情况感兴趣、并且我将在我的另一个项目中使用 FIFO 中断。

UART 初始化例程:

void UART_Host_Init (uint32_t 时钟速率)
{
//
//启用 UART 使用的 GPIO 外设。
//
SysCtlPeripheralEnable (UART_HOST_PERIPh_GPIO);

//
//启用 UART 主机时钟
//
SysCtlPeripheralEnable (UART_HOST_CLOCK);

//
//为 UART 模式配置 GPIO 引脚。
//
GPIOPinConfigure (UART_HOST_GPIO_RX);
GPIOPinConfigure (UART_HOST_GPIO_TX);
GPIOPinTypeUART (UART_HOST_GPIO_BASE_PORT、UART_HOST_GPIO_PIN_RX | UART_HOST_GPIO_PIN_TX);

//
//使用内部16MHz 振荡器作为 UART 时钟源。
//
UARTConfigSetExpClk (UART_HOST、时钟速率、UART_HOST_SPEED、(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_Two | UART_CONFIG_PAR_NONE));
UARTFIFODisable (UART_HOST);
//
//如果下面的行未注释,则一切正常
//
// UARTTxIntModeSet (UART_HOST、UART_TXINT_MODE_EOT);


//
//启用 RT -接收超时、TX 和 RX 中断
//
IntEnable (UART_HOST_INT_INDEX);
UARTIntEnable (UART_HOST、UART_INT_RT | UART_INT_TX | UART_INT_RX);
} 

在主循环中:

while (1)
{
//
//正在发生一些事情
//

if (msgSent = true)
{
msgSent = false;
if (UARTCharPutNonBlocking (UART_HOST、MESSAGE[index++])== false)
{
#ifdef debug
while (1){};
#endif
}
}

UART 中断:

UARTIntHandler (void)
{
uint32_t ui32Status;

ui32Status = UARTIntStatus (UART_HOST、TRUE);//获取中断状态
UARTIntClear (UART_HOST、ui32Status);//清除断言的中断

//
接收数据
//
if (ui32Status & UART_uart_host);//清除 UART32+


(UART_uart_uart_uart_uart_uiCommand) while UART+(UART+ uart_uart_uchart_uart_uart_uart+)+)+(uart_uart_uartuart_uart_uart_uart_uart_uart_uartui
//获取接收到的字符
}

//
发送数据
//
if (ui32Status & UART_INT_TX)
{
g_ui32UARTIntTransmit++;
if (index < length)
{
if (UARTCharPutNonBlocking (UART_host、message[index+])= false)
{
#dif debug
while (1)}=





true
;}= dif}= dif};sendent (u_host = false);sf}= true



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

    UART_TXINT_MODE_FIFO 的理念是在 UART 传输期间、FIFO 上的特定数量的空闲字节再次可用时发出中断标志。

    假设您刚刚将15个字节放入 FIFO 中。 UART 硬件开始根据配置的波特率移出字节。 发送7个字节后、中断会进行调用、以告知您" FIFO 上至少有8个字节可用、以防您需要发送其他内容"。
    此示例中8个字节的图是通过 UARTFIFOLevelSet()配置的参数;-您可以使用不同的级别。
    如果您的 FIFO 水平设置为50%(8字节)、并且您只向 FIFO 写入6个字节、则不会收到中断(9个字节的暂挂数据没有向下突破到8个字节)。 传输仍将正常进行。

    另一个选项(EOT)在 FIFO 中没有更多字节要发送时标记 int (从1个字节暂挂到0)。

    通常情况下、在将所有需要的字节放入 FIFO 后、没有理由监控 EOT 或担心空闲 FIFO:UART 硬件将始终为您传输这些字节、您可以相信!

    如果您最初需要传输的 FIFO 空闲字节多于空闲字节、我建议您每次向 FIFO 发送一个字节、直到 FIFO 已满(请检查 UARTCharPutNonBlocking 函数内部以查看其工作原理)。 然后、将中断配置为让您知道何时有可用空间、然后才继续发送另一组字节。

    Rgds

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

    尊敬的 Bruno Saraiva:

    感谢您的回答。 我对 FIFO 和相关中断用法的理解是完全相同的。

    我将用另一种方法提出我的问题:如果您禁用 FIFO (它实际上变成了1字节深的保持寄存器)、那么根据 UARTCTL 寄存器的 EOT 位、TX 中断的触发方式是否有差异?

    正如我看到的、它现在应该以与 EOT 位无关的方式工作:只要你的一个字节和唯一的字节被完全移位、你就会得到你的中断。

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

    [引用 USER="Andrei Gasilovs"]我看到,它现在应该以与 EOT 位无关的同样方式工作:只要您的一个字节和唯一的字节完全移位,就会得到中断。

    您可以查阅数据表/参考手册、但我不同意。 不知道 TM4C UART 的详细信息、而是其他信息。 在这里、一旦 TX 寄存器被复制到移位寄存器、"TX empty"标志就会被置位。 即实际发送刚开始时。 "TX empty"不是"传输结束"(EOT)。

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

    是的、我也经历过这种行为、例如使用 C2000 MCU。

    这是我对 TM4C123的问题。 如果 FIFO 被禁用且 EOT 未被置位、则何时触发 TX 中断? 我无法从数据表和 TRM 中找出它...

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

    好的、我使用计时器对其进行了测试。 它的工作原理如所述。 当 FIFO 被禁用时、当字节被传输到移位寄存器时、中断被触发;当整个字节被发送时、EOT 被触发。

    但现在回到我最初的问题、我为什么在这个配置中有时会丢失 TX 中断?

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

    [引用 user="Andrei Gaislovs">但现在回到我原来的问题、我为什么在这种配置中有时会丢失 TX 中断? [/报价]

    我已经在其他 MCU 上做过如此低级的工作、但仅使用了 TM4C 上的 TivaWare 函数。

    但是、"丢失"中断的常见原因是溢出或意外清除标志。 由于写入 TX 是同步的、因此不应发生溢出。 也许您正在清除另一个中断例程中的 TXE 标志以及其他标志。 这将不会被注意到、直到两个中断同时发生。 对于不太频繁的写入、这会在问题中添加"随机因子"、并使其异步。

    如果我发现时间,我可能会查看代码和标志...

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

    您好!

    一个小的"bemol":UARTFIFODisable()函数只能在 UARTEnable()之后使用,因为这会以静默方式启用 FIFO。 请查看此函数的源代码。

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

    F.米


    我尝试尽可能去耦我的模块。 据我所知、没有其他中断会影响该 UART 寄存器/标志。
    然而、我注意到了一个奇怪的现象:如果降低 MCU 频率、这种情况看起来会更频繁、而且要快得多。

    Petrei

    是的、没错。 但我使用 UARTConfigSetExpClk 函数、该函数在内部调用 UARTEnable、之后才调用 UARTFIFODisable

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    安德烈
    阅读您的帖子很好、并且您分享了有关中断 EOT/FIFO 功能的结论、谢谢!
    某些行为最终会落入"神秘之罐"中-尤其是在它们随机发生时。 但我甚至不应该提及这一点、因为您显然非常能够理解和诊断您的问题上的所有事件。
    当我厌倦了神秘的行为时、他们会使用我的典型方法:无需弄清楚!
    这意味着、您真的需要该中断吗? 您是否无法获得监视 FIFO 级别所需的所有结果(更好的是、利用 FIFO 提供的所有16个字节)? 如果您真的需要注意 EOT、理论上可以预先计算它-您知道系统时钟、您知道波特率、因此您可以设置一个计时器、在该时间过了时提醒您-但仍然 也许您可以管理传输缓冲区、而无需知道最后一个字节已经消失...
    谢谢
    布鲁诺
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我想谈一谈您的第一个问题:是什么让您相信您正在丢失 TX 中断?

    如果您不混淆写入 UART TX 的字节、则不会丢失任何内容。 TX 中断将告诉您 TX 何时再次就绪-它在以后仍然就绪、除非您从其他位置写入 TX。

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

    F.米


    嗯、这是一个合理的问题。 我认为我放宽了中断、因为否则传输永远不会停止。 如果我使用 EOT 中断、它不会。 这是我在代码中所做的唯一改变:切换到 EOT 或 FIFO 中断、程序以不同的方式运行。 EOT 功能运行良好、FIFO 功能可在随机时间停止发送数据。

    Bruno Saraiva


    是的、我完全同意您的想法。 但你知道,当另一件事落入“神秘的锅”时,它会增加世界的熵并带来焦虑。
    目前,这一案件属于 YAGNI 原则,我将离开这一原则。 但是、我将在有更多空闲时间后立即返回、并将消除这个小错误...

    感谢大家的帮助和想法!

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

    [引用 user="Andrei GaisloVs">切换到 EOT 或 FIFO 中断、程序运行方式不同。 通过 EOT、一切运行良好、并且通过 FIFO、它会在随机的时间停止发送数据。

    这就是我避免 UART 使用 FIFO (或 DMA)的原因。 至少在接收时、需要一个特定的填充级别(字节数)来产生一个中断。 这种情况通常会破坏可变长度传输协议、并且通常会破坏应用时序。

    不确定 FIFO 如何准确地工作以进行发送、我将仔细查阅数据表的 UART 部分。