iMX 处理器上的串行驱动程序限制

Serial driver limitations on iMX processor

我正在使用 ARM iMX6 处理器的嵌入式 Linux 设备上进行开发。主要目的是从外部源读取传入的串行流。

由于串行流的非典型性,我 运行 在使用 imx 处理器的 Linux serial driver 时遇到了一些障碍。但没有什么超出 iMX6 的能力。例如,传入的串行流是反逻辑。 iMX6 有一个特定的寄存器设置来反转 RX 信号。据我所知,Linux 驱动程序没有公开它。

另一个复杂的问题是传入的串行数据以 3 毫秒的脉冲串形式到达。外部源连续传输 3 毫秒,然后 3 毫秒空闲,然后 3 毫秒数据,然后空闲等。为了与每个突发的第一个字节同步,能够检测线路何时空闲非常有用。同样,iMX6 有一个专门用于指示 RX 线空闲的寄存器值,但 Linux 驱动程序没有公开它。

我也很困惑缓冲在驱动程序中是如何工作的。我知道 iMX6 有一个 32 字节的 FIFO 缓冲区,但我不知道驱动程序是使用该缓冲区还是使用外部 RAM 进行缓冲。我 运行 遇到一个问题,当我处于阻塞模式时, read 命令经常挂起一秒钟,这种情况永远不会发生,因为数据流是连续的。

作为参考,以下是我在 C 代码中配置串口并读取 50 个字节的方式(我现在已将其更改为非阻塞):

#include <stropts.h>
#include <asm/termios.h>
#include <unistd.h>
#include <fcntl.h>

int main()
{
  int fd;
  struct termios2 terminal;
  unsigned char v[50];

  fd = open ("/dev/ttymxc2", O_RDONLY | O_NOCTTY | O_NONBLOCK );
  ioctl(fd, TCGETS2, &terminal);
  terminal.c_cflag |= (CLOCAL | CREAD) ;
  terminal.c_cflag |= PARENB ; //enable parity
  terminal.c_cflag &= ~PARODD ; //even parity
  terminal.c_cflag |= CSTOPB ;  //2 stop bits
  terminal.c_cflag &= ~CSIZE ;
  terminal.c_cflag |= CS8 ;
  terminal.c_lflag &= ~(ICANON | IEXTEN | ECHO | ECHOE | ISIG) ;
  terminal.c_oflag &= ~OPOST ;
  terminal.c_cflag &= ~CBAUD;
  terminal.c_cflag |= BOTHER;
  terminal.c_ispeed = 100000;  //100kHz baud
  terminal.c_ospeed = 100000;
  ioctl(fd, TCSETS2, &terminal);
  ...
  for(i=0;i<50;i++)
  {
      read(fd,v+i,1)
  }
  ...
}

所以我有两个问题:

  1. 什么是 "proper" 从处理器可用但驱动程序未公开的串行端口中获取功能的方法?我无法想象我是第一个想要使用处理器如此基本功能的人,但我不想重新发明轮子。我需要开始编写自己的驱动程序吗?

  2. 哪里有关于 iMX 串行驱动程序的综合文档?代码评论很差,我很快就迷失了方向,试图找到解决方法。比如接收连续数据流时导致卡死的缓冲问题,不知道从何入手

我完全放弃了串行驱动程序,而是编写了一些函数来直接访问寄存器内存(仿照 devmem2.c 源代码)。现在我可以直接设置 INVR 位来反转 RX 信号,使用 IDLE 位来检测线路何时空闲,并在传入数据字节到达时立即检索它们而不会延迟。

我在另一个论坛上发现了一些关于 UART DMA 需要 RX 线在服务缓冲区之前至少空闲 8ms 的内容。这显然是我遇到 1 秒延迟的原因。