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.

[参考译文] AM625:UART3接收数据、将会丢失一些数据

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

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1370356/am625-uart3-receive-data-and-it-will-miss-a-few-datas

器件型号:AM625

工具与软件:

嗨、大家好;
  我最近在 AM625上遇到了 ti-processor-sdk-linux-rt-am62xx-evm-08.06.00.42的 UART 问题。
我编写了一个应用程序(catch_rtk.c)、通过 UART3接收 GPS 数据、包括 GSV、GSA 和原始数据。 UART3的波特率为921600。 GPS 模块提供41kb/s 的数据。
也许由于大量的数据,我发现,偶尔会错过一些数据。 而且,我已经排除了 GPS 模块。 我跟踪 UART 8250驱动程序代码。 我在函数 UART_INSERT _CHAR 中发现发生了溢出错误(寄存器 UART_LSR 的位 RX_OE)。

我发现不使用 DMA、而是使用 FIFO。
 up.port.fifosize = 64;
 up.tx_loadsz = 64;

我想修改 RX FIFO 触发电平以避免错误。 如果可以、请告诉我如何修改。

原因是未使用 DMA。 我已尝试 UART DMA。 我在文件中配置 UART3 DTS
arch/arm64/boot/dts/ti/k3-am62-main.dtsi。

main_uart3:串行@2830000{
Compatible ="ti、am64-uart"、"ti、am654-uart";
REG =<0x00 0x02830000 0x00 0x100>;
中断= ;
电源域=<&K3_PDS 154 TI_SCI_PD_Exclusive>;
时钟=<&K3_CLKS 154 0>;
时钟名称="fclk";
DMA =<&MAIN_pktdma 0x4403 0>、<&MAIN_pktdma 0xc403 0>;
DMA-names ="Rx"、"TX";
};

我使用同一个应用程序接收 GPS 数据超过12小时。 不幸的是、我发现有缺失
两个数据在多个地方。 目前我不知道通过 DMA 模式的根模式吗?

我想知道 DMA 模式是否可以优化?

请给我一些建议。

 catch_rtk.c 源代码如下:

#include
#include
#include

#include
#include
#include

#include
#include
#include

#define RTK_DEV_FILE "/dev/ttyS9 "
#define RTK_DATA_FILE "/home/root/rtk_data.txt "

int main (int argc、char * argv[])

INT FD、UART_FD;
struct termios 选项;
结构时间;

Int ret;
int fs_sel、lenth;
FD_SET FS_READ;
char buff[1024];

FD = OPEN (RTK_DATA_FILE、O_RDWR | O_CREAT);
IF (FD < 0)

printf ("打开%s 文件失败\n"、RTK_DATA_FILE);
返回-1;
}

UART_FD = OPEN (RTK_DEV_FILE、O_RDWR);
IF (UART_FD < 0)

printf ("打开%s 文件失败\n"、kkm_dev_file);
关闭(FD);
返回-1;
}

if (tcgetattr (UART_FD、&OPTIONS)!= 0)

perror ("获取 UART 属性\n");
关闭(FD);
关闭(UART_FD);
返回-1;
}

cfsetidspeed (&options、B921600);
cfsetospeed (&options、B921600);

options.c_cflag |= CLOCAL;
options.c_cflag |= CREAD;

options.c_cflag &=~μ s CRTSCTS;
options.c_cflag &=~CSIZE;

options.c_cflag |= CS8;
options.c_cflag &=~PARENB;
options.c_iflag &=~μ s INPCK;
options.c_cflag &=~CSTOPB;

options.c_ofag &=~μ s OPOST;
options.c_lflag &=~(ICANON | ECHO | ECHOE | ISIG);
options.c_iflag &=~(ICRNL | IXON);
options.c_cc[VTIME]= 1;
options.c_cc[Vmin]= 1;

tcflush (UART_FD、TCIFLUSH);

if (tcsetattr (UART_FD、TCSANOW、&OPTIONS)!= 0)

perror ("设置 UART 参数错误!\n");
关闭(FD);
关闭(UART_FD);
返回-1;
}

if (fcntl (UART_FD、F_SETFL、0)< 0)

printf ("fcntl UART 失败!\n");
关闭(FD);
关闭(UART_FD);

返回-1;
}

while (1)

fd_zero (&FS_READ);
FD_SET (UART_FD、&FS_READ);

//FS_SEL = SELECT (UART_FD+1、&FS_READ、NULL、NULL 和 TIME);
FS_SEL = SELECT (UART_FD + 1、&FS_READ、NULL、NULL、NULL);
IF (FS_SEL)

memset (buff、"\0"、sizeof (buff));
lenth =读取(UART_FD、buff、sizeof (buff));
if (lenth > 0)

RET =写入(fd、buff、lenth);
if (ret!= lenth)

printf ("将数据写入%s 文件失败\n"、RTK_DATA_FILE);
}
}
}
设计

printf ("UART recv data failure!\n");
关闭(FD);
关闭(UART_FD);
返回-1;
}
}

关闭(UART_FD);
返回0;
}

   此致!

Johnny

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

    尊敬的 Johnny:

    您可以应用下面的内核补丁来查看是否解决数据丢失问题、而不是在 UART 上使用 DMA 吗? 该修补程序基本上会删除" uart_RX_timeout_quirk "标志。

    diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
    index 2bc6b982238f..842f3c19192e 100644
    --- a/drivers/tty/serial/8250/8250_omap.c
    +++ b/drivers/tty/serial/8250/8250_omap.c
    @@ -1337,7 +1337,7 @@ static struct omap8250_dma_params am33xx_dma = {
     static struct omap8250_platdata am654_platdata = {
            .dma_params     = &am654_dma,
            .habit          = UART_HAS_EFR2 | UART_HAS_RHR_IT_DIS |
    -                         UART_RX_TIMEOUT_QUIRK | UART_HAS_NATIVE_RS485,
    +                         UART_HAS_NATIVE_RS485,
     };
     
     static struct omap8250_platdata am33xx_platdata = {

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

    嗨、Bin、

       我已经尝试了您对 UART FIFO 的建议。 我通过同一个应用程序将 GPS 模块连接了6小时。 我发现仍缺少约2个字节的数据、并且在函数 UART_INSERT _CHAR 中发生了溢出错误(寄存器 UART_LSR 的 RX_OE 位)。 此问题与上一个问题相同。

       我已经检查了8250驱动程序和您的补丁。 我发现 它只影响中断函数(omap8250_irq)中的以下代码。

        if (priv->pstay & uart_rx_timeout_quirk &&
          (IIR & UART_IIR_RX_TIMEOUT)=UART_IIR_RX_TIMEOUT &&
          serial_port_in (port、UART_OMAP_RX_LVL)= 0){
          serial_port_in (port、UART_RX);
        }

      谢谢!

    此致!

    Johnny Liu

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

    您好、Bin、

       运行应用程序以获取 GPS 模块数据时的样子。 我使用"devmem2"命令来读取 UART3寄存器。例如:

        devmem2 0x2830008
       /dev/mem 打开。
       存储器映射在地址0xffa8bca000处。
       在地址0x02830008 (0xffa8bca008)处读取:0x000000C1

        devmem2 0x2830040
       /dev/mem 打开。
       内存映射在地址0xff85199000。
       在地址0x02830040 (0xffffff85199040)处读取:0x000000C8

       AM62x 手册的描述如下:

        

       寄存器   UART_SCR 的位7为1。  寄存器   UART_FCR 的位6和位7为 RX_FIFO_TRIG 是触发级别[6位上1-63 ]的2LSB、粒度为1。 我想 知道哪一个是触发电平的4 MSB [6位上1-63 ] 。 如果它是 UART_RXFIFO_LVL? 因为我想降低 RX FIFO 触发电平。

      Johnny Liu

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

    尊敬的 Johnny:

    RXFIFO 触发电平在宏中定义 RX_TRIGGER (默认为48个字节)。 请参阅内核文件 drivers/tty/serial/8250/8250_omap.c 第92行。

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

    嗨、Bin、

      我修改了 RX_TRIGGER  从48改为32。 经过长时间的测试、我发现问题仍然存在。  您有什么好建议吗?

      Johnny Liu

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

    尊敬的 Johnny:

    您能否像在上述原始 DTS 中所做的那样启用 DMA、并应用以下内核补丁、以查看是否仍然存在启用 DMA 的 RX 问题?

    diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
    index 15e50fe40e4b..7f7057131c9a 100644
    --- a/drivers/tty/serial/8250/8250_omap.c
    +++ b/drivers/tty/serial/8250/8250_omap.c
    @@ -1042,6 +1042,10 @@ static int omap_8250_tx_dma(struct uart_8250_port *p)
            unsigned int    skip_byte = 0;
            int ret;
     
    +       /* HACK: do not use DMA for TX */
    +       ret = -EINVAL;
    +       goto err;
    +
            if (dma->tx_running)
                    return 0;
            if (uart_tx_stopped(&p->port) || uart_circ_empty(xmit)) {
    

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

    嗨、Bin、

       感谢您的建议。

       在我看来、由于你们的修改、 UART3并未使用 DMA 来发送数据。 目前、UART3仅接收 GPS 模块的数据、不向 GPS 模块发送数据。 那么、我认为它是无效的。

    Johnny Liu

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

    尊敬的 Johnny:

    在我的测试中、禁用 TX DMA 可解决 RX DMA 数据丢失问题。

    因为在您的用例中、UART 主要接收数据、而不是发送。 因此、禁用 TX DMA 非常好。

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

    您好、Bin、

      太棒了!

       我将测试一个数天。

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

    嗨、Bin、

      我尝试了您的建议、即仅启用 Rx DMA。 仍然是 数据丢失。

    main_uart3:串行@2830000{
    Compatible ="ti、am64-uart"、"ti、am654-uart";
    REG =<0x00 0x02830000 0x00 0x100>;
    中断= ;
    电源域=<&K3_PDS 154 TI_SCI_PD_Exclusive>;
    时钟=<&K3_CLKS 154 0>;
    时钟名称="fclk";
    DMA =<&MAIN_pktdma 0x4403 0>、<&MAIN_pktdma 0xc403 0>;
    DMA-names ="Rx"、"TX";
    };

       我使用上述补丁。

       diff -- git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
    索引15e50fe40e4b..7f7057131c9a 100644
    ---a/drivers/tty/serial/8250/8250_omap.c
    ++ b/drivers/tty/serial/8250/8250_omap.c
    @@-1042、6 +1042、10 @@静态 int OMAP_8250_TX_DMA (结构 UART_8250_PORT * p)
    unsigned int skip_BYTE = 0;
    Int ret;

    +/*黑客:不要为 TX 使用 DMA */
    + ret =-EINVAL;
    + goto err;
    +
    如果(DMA->TX_RUNNING)
    返回0;
    if (UART_TX_STOPPED (&P -> PORT)|| UART_CIRC_EMPTY (发送)){

       但数据丢失的情况比不使用 DMA 更为严重。 我很 好奇为什么会发生这种情况?

       并将"Rx_TRIGGER = 1"修改为"Rx_TRIGGER = 16"、尝试使用  

       静态结构 omap8250_dma_params am654_dma ={
          rx_size = SZ_2K、
          rx_trigger = 16、
          .tx_trigger = TX_TRIGGER、
    };

       但结果是相同的。

      太棒了!

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

    您好!

    请不要使用您的应用、而是使用下面链接中提到的串行检查或 Linux-serial-test 程序来测试您的 UART、以查看您是否仍然看到数据丢失。

    https://dev.ti.com/tirex/explore/node?node=A__AaoTgeq5bZLef17lYvUnsw__AM62-ACADEMY__uiYMDcq__LATEST&placeholder=true

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

    嗨、Bin、

       抱歉、我无法访问 Linux-serial-test

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

    我将其源代码附加到这里。 这可能不是 github.com 上提供的最新版本、但它是我一直使用的版本。

    e2e.ti.com/.../1072.README.md

    e2e.ti.com/.../linux_2D00_serial_2D00_test.c