【发布时间】:2018-04-11 07:28:31
【问题描述】:
我正在使用 ARM iMX6 处理器的嵌入式 Linux 设备上进行开发。主要目的是从外部源读取传入的串行流。
由于串行流的非典型性质,我在使用 imx 处理器的 Linux serial driver 时遇到了一些障碍。但没有什么超出 iMX6 的能力。例如,传入的串行流是反转逻辑。 iMX6 有一个特定的寄存器设置来反转 RX 信号。据我所知,Linux 驱动程序没有公开它。
另一个复杂因素是传入的串行数据以 3 毫秒的突发形式到达。外部源连续传输 3ms,然后是 3ms 空闲,然后是 3ms 数据,然后是空闲等。为了与每个突发的第一个字节同步,能够检测线路何时空闲是非常有用的。同样,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)
}
...
}
所以我有两个问题:
从处理器可用但驱动程序未公开的串行端口中获取功能的“正确”方法是什么?我无法想象我是第一个想要使用处理器的基本功能的人,但我不想重新发明轮子。我需要自己编写驱动程序吗?
关于 iMX 串行驱动程序的综合文档是否存在于任何地方?该代码的注释很差,我很快就迷失了,试图找到解决方法。例如,我不知道从哪里开始调查导致它在接收连续数据流时挂起的缓冲问题。
【问题讨论】:
-
我认为接近投票没有根据,问题实际上是关于 linux 内核中 imx/tty 驱动程序的代码,而不是为什么问题中的代码不起作用。
-
你@grochmal。我只包含代码作为参考(正如我在问题文本中所述)。我的问题是关于 imx Linux 驱动程序的代码。
-
顺便说一句,我粘贴在我的问题中的代码确实有效。但是我必须在代码的其他地方解决驱动程序的缺点,这使我的程序马虎且效率低下。
-
我已经完全放弃了串行驱动程序,而是编写了一些函数来直接访问寄存器内存(仿照 devmem2.c 源代码)。现在我可以直接设置 INVR 位来反转 RX 信号,使用 IDLE 位来检测线路何时空闲,并在输入数据字节到达时立即检索它们。我在另一个论坛上发现了一些关于 UART DMA 需要 RX 线空闲至少 8ms 才能为缓冲区提供服务。这显然是我遇到 1 秒延迟的原因。
标签: drivers serial-port