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.

[参考译文] MSPM0G3519:如何清空 UART Tx 和 Rx FIFO?

Guru**** 2528160 points
Other Parts Discussed in Thread: MSPM0G3519

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1545485/mspm0g3519-how-to-flush-the-uart-tx-and-rx-fifo

器件型号:MSPM0G3519


工具/软件:

我们将 在应用中使用单线 UART 通信、因此应尝试在传输期间禁用 Rx、反之亦然。

在其中一个线程中、建议在发送期间将 Rx 引脚配置为 GPIO 输入、反之亦然、以隔离通信、建议也刷写 FIFO。

但我不确定如何在此微控制器中清除 FIFO、没有任何寄存器根据 TRM 清除数据、如何清除 FIFO?

目前、我们正在将 Rx 引脚重新配置为 GPIO、但仍面临一些问题。  我们是否 为 MSPM0G3519 微型推荐不同的方法?

我共享了一个线程、在该线程下、我被用作参考、

MSPM0G1507:UART0 半双工 IrDA 问题 — 基于 Arm 的微控制器论坛 — 基于 Arm 的微控制器 — TI E2E 支持论坛

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

    可以通过设置 CTL0:FEN=0 然后= 1 [Ref TRM (SLAU846B) Sec 来清空 Tx FIFO  18.3.28.由于您可以控制 Tx FIFO 的内容、因此也可以等到 STAT:TXFE=1。

    清除 Rx FIFO 的方法是读取(并丢弃)RXDATA 直到 STAT:RXFE=1 [请参阅 TRM 表 18-43]。 (一旦将引脚与 UART 断开连接、就不会获得任何新的 Rx FIFO 条目。)

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    刷新 Rx FIFO 的方法是读取(丢弃)RXDATA、直到 STAT:RXFE=1 [Ref TRM 表 18-43]。 (一旦将 PIN 与 UART 断开连接、您将不会获得任何新的 Rx FIFO 条目。)

    将端口配置更改为 GPIO 时、将设置帧错误和中断错误、并且在将其改回 UART 后没有获得 RX 中断。 它会发生超限、然后错误会被清除。 之后、Rx 正在为我工作。

    有时在发送期间不会接收到 Tx 中断、此时设置了 BUSY 位、Tx FIFO 也为空、但没有中断、因此它一直等待该中断。

    您能提出一个解决方案吗?

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

    如果您想实际发送 Tx 数据(而不是丢弃)、您可能不应刷新 Tx FIFO、而是等待(旋转?) 直至 STAT:TXFE=1 和 STAT:BUSY=0。 (STAT:BUSY 应该足够了、但我不知道字节之间是否存在 BUSY = 0 时的任何时刻。)  

    如果断开引脚(中间 Rx 字节)会导致成帧错误、我不会太惊讶、但我不会预期 UART 会因此卡住(因为错误与字节一起存储)。 您使用的顺序是什么? 在执行此操作之前、您是否有办法判断 Rx(来自另一端)是否处于空闲状态?

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

    是的、另一端的 Rx 为空闲。 现在、我只是使用一个终端在另一端发送/接收数据

    所以,另一端没有数据

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

    有时在发送期间、当我们 对 GPIO 输入进行端口配置时、会设置 BUSY 位并且它不会被清除。

    调用发送后、没有触发 Tx 中断、因此 UART 卡滞、此时数据没有发送或接收、此时如何进行恢复?

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

    我不确定我是否了解您使用的顺序。 是否根据需要设置/清除 CTL0:RXE/TXE?

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

    此外、您使用什么终端仿真器? 我还没有找到一个采用单线技术的器件。

    -----

    我尝试了一份 uart_echo_interrupts 副本的天真黑客来动态连接引脚、并且我没有看到任何异常症状。  

    .c

    // UART IOMUX experiment.
    // Author: Bruce McKenney, 2025. No warranty, no support. I may not even exist.
    // Started life as TI example uart_echo_interrupts, which is
    // Copyright (c) 2020, Texas Instruments Incorporated
    
    #include "ti_msp_dl_config.h"
    
    #define IOMUX_PF_GPIO   1
    volatile uint8_t gEchoData = ':';
    uint8_t dummy[1];       // bit-bucket
    
    inline void
    switch_iomux(uint32_t IOPIN, uint32_t PF)
    {
        IOMUX->SECCFG.PINCM[IOPIN] = (IOMUX->SECCFG.PINCM[IOPIN] & ~IOMUX_PINCM_PF_MASK)
                                       | IOMUX_PINCM_INENA_ENABLE | PF;
        return;
    }
    
    int
    main(void)
    {
        SYSCFG_DL_init();
    
        NVIC_ClearPendingIRQ(UART_0_INST_INT_IRQN);
        NVIC_EnableIRQ(UART_0_INST_INT_IRQN);
        switch_iomux(GPIO_UART_0_IOMUX_RX, IOMUX_PF_GPIO);  // Disconnect Rx
        switch_iomux(GPIO_UART_0_IOMUX_TX, IOMUX_PINCM21_PF_UART0_TX);  // Connect Tx
        DL_UART_Main_transmitData(UART_0_INST, gEchoData);  // Tell 'em we're here
    
        while (1) {
            __WFI();
        }
    }
    
    void UART_0_INST_IRQHandler(void)
    {
        switch (DL_UART_Main_getPendingInterrupt(UART_0_INST)) {
        case DL_UART_MAIN_IIDX_EOT_DONE:
            switch_iomux(GPIO_UART_0_IOMUX_TX, IOMUX_PF_GPIO);              // Disconnect Tx
            while (DL_UART_receiveDataCheck(UART_0_INST, &dummy[0])) {/*EMPTY*/;} // Drain Rx FIFO
            switch_iomux(GPIO_UART_0_IOMUX_RX, IOMUX_PINCM22_PF_UART0_RX);  // Connect Rx
            break;
        case DL_UART_MAIN_IIDX_RX:
            DL_GPIO_togglePins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN | GPIO_LEDS_USER_TEST_PIN);
            gEchoData = DL_UART_Main_receiveData(UART_0_INST);
            switch_iomux(GPIO_UART_0_IOMUX_RX, IOMUX_PF_GPIO);              // Disconnect Rx
            //  We know the Tx FIFO is empty
            switch_iomux(GPIO_UART_0_IOMUX_TX, IOMUX_PINCM21_PF_UART0_TX);  // Connect Tx
            DL_UART_Main_transmitData(UART_0_INST, gEchoData);
            break;
         default:
            break;
        }
    }
    

    .syscfg

    /**
     * These arguments were used when this file was generated. They will be automatically applied on subsequent loads
     * via the GUI or CLI. Run CLI with '--help' for additional information on how to override these arguments.
     * @cliArgs --device "MSPM0G350X" --part "Default" --package "LQFP-64(PM)" --product "mspm0_sdk@2.04.00.06"
     * @v2CliArgs --device "MSPM0G3507" --package "LQFP-64(PM)" --product "mspm0_sdk@2.04.00.06"
     * @versions {"tool":"1.21.0+3721"}
     */
    
    /**
     * Import the modules used in this configuration.
     */
    const GPIO   = scripting.addModule("/ti/driverlib/GPIO", {}, false);
    const GPIO1  = GPIO.addInstance();
    const SYSCTL = scripting.addModule("/ti/driverlib/SYSCTL");
    const UART   = scripting.addModule("/ti/driverlib/UART", {}, false);
    const UART1  = UART.addInstance();
    
    /**
     * Write custom configuration values to the imported modules.
     */
    GPIO1.$name                          = "GPIO_LEDS";
    GPIO1.associatedPins.create(2);
    GPIO1.associatedPins[0].$name        = "USER_LED_1";
    GPIO1.associatedPins[0].assignedPort = "PORTA";
    GPIO1.associatedPins[0].initialValue = "SET";
    GPIO1.associatedPins[0].assignedPin  = "0";
    GPIO1.associatedPins[0].pin.$assign  = "PA0";
    GPIO1.associatedPins[1].$name        = "USER_TEST";
    GPIO1.associatedPins[1].assignedPort = "PORTA";
    GPIO1.associatedPins[1].assignedPin  = "15";
    GPIO1.associatedPins[1].initialValue = "SET";
    
    const Board           = scripting.addModule("/ti/driverlib/Board", {}, false);
    Board.configureUnused = true;
    
    SYSCTL.forceDefaultClkConfig = true;
    SYSCTL.clockTreeEn           = true;
    
    UART1.$name                        = "UART_0";
    UART1.rxFifoThreshold              = "DL_UART_RX_FIFO_LEVEL_ONE_ENTRY";
    UART1.enableDMARX                  = false;
    UART1.enableDMATX                  = false;
    UART1.uartClkSrc                   = "LFCLK";
    UART1.ovsRate                      = "3";
    UART1.enabledInterrupts            = ["EOT_DONE","RX"];
    UART1.peripheral.$assign           = "UART0";
    UART1.peripheral.rxPin.$assign     = "PA11";
    UART1.peripheral.txPin.$assign     = "PA10";
    UART1.txPinConfig.$name            = "ti_driverlib_gpio_GPIOPinGeneric0";
    UART1.txPinConfig.enableConfig     = true;
    UART1.txPinConfig.internalResistor = "PULL_UP";
    UART1.rxPinConfig.$name            = "ti_driverlib_gpio_GPIOPinGeneric1";
    UART1.rxPinConfig.enableConfig     = true;
    UART1.rxPinConfig.internalResistor = "PULL_UP";
    
    /**
     * Pinmux solution for unlocked pins/peripherals. This ensures that minor changes to the automatic solver in a future
     * version of the tool will not impact the pinmux you originally saw.  These lines can be completely deleted in order to
     * re-solve from scratch.
     */
    GPIO1.associatedPins[1].pin.$suggestSolution = "PA15";
    Board.peripheral.$suggestSolution            = "DEBUGSS";
    Board.peripheral.swclkPin.$suggestSolution   = "PA20";
    Board.peripheral.swdioPin.$suggestSolution   = "PA19";
    

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

    否、我们不在 CTL0 寄存器上做任何事情。

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

    是否要我们相应地启用和禁用 Rx 和 Tx。?

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

    我们正在使用 Docklight。

    单线通过外部电路处理、我们有一个在两端将 2 线转换为 1 线、反之亦然的电路。

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

    下面是  单线 UART 的序列、

    最初、UART 将处于接收模式 (Tx INT 被禁用、仅启用 Rx INT)。 这是一个请求和发送数据流、因此 UART 将始终处于接收状态、只有在 接收到数据时才会进行发送。 根据命令、响应会有所不同。

    通过 UART 接收到命令时、Rx INT 将被禁用、下一个端口模式将更改为 GPIO、然后调用发送 API。

    同样在 UART Tx 中断中、将提供回调 、端口模式将再次更改为 UART、Tx 中断将被禁用、然后启用 Rx INT 以接收下一条命令。

    此流程会针对每个命令继续执行。

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

    处理 RXE/TXE 似乎是一个可能的答案、直到 I (1) 尝试了上述代码(对 RXE/TXE 没有任何作用)并一直发现 RXE/TXE=1 不会产生不良影响;(2) 注意到勘误表 UART_ERR_02 [Ref 勘误表 (SLAZ758B) 第 18 页]、其中、如果 RXE=0、EOT 停止工作。

    我(现在)建议您不要更改 TXE/RXE。

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

    我不熟悉 Docklight。 丝锥是否会反转电方向? (我正在想象像 RS RS-485 芯片这样的芯片。)

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

    1)“下一个端口模式将更改为 GPIO“:这是否意味着 (1) Rx 引脚设置为 GPIO、然后 (2) Tx 引脚设置为 UART? (如上所示。)

    2)“在 UART Tx 中断中、 [...]端口 模式将更改为 UART“。 当将该字节移动到移位寄存器时、Tx 中断发生、可能为时过早。 EOT(或 BUSY)指示 FIFO 和移位寄存器何时均为空。

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

    1) 是的、Rx 引脚 设置为 GPIO、Tx 引脚 始终设置为 UART。  我们正在尝试消除环回数据、Tx 仅在收到命令后发生、因此 未重新配置 Tx 引脚。

    2) 回调中的端口模式再次更改为 UART、只有在回调之前发送了所有数据并禁用了 Tx 中断时、才会触发回调。

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

    如果您始终保持 Tx 引脚连接、什么因素会阻止它在空闲时驱动(共享)线? 线路周转是如何发生的?

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

    我们正在禁用 Tx 中断、不允许在 Rx 正在进行时发送、这是通过 BUSY 位实现完成的。

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

    我们能够通过启用帧和中断错误中断并在帧/中断错误中断中刷新 FIFO(读取 Rx FIFO 直到其为空)来解决此问题。 在发送之前、将 pinmode 设置为 GPIO 后、也会清除帧中断和错误中断。

    感谢您对 布鲁斯·麦肯尼的支持