Serial port Ada-使用ttyUSB设备(FTDI芯片)时的定时问题

Serial port Ada-使用ttyUSB设备(FTDI芯片)时的定时问题,serial-port,ada,timing,Serial Port,Ada,Timing,我对使用“GNAT.Serial_Communications”包的简单Ada程序有一个奇怪的问题 该程序通过串行端口设备(8,N,115200波特时为1)发送七个字节(126,1,0,0,0,0,254),我已验证使用直接连接到串行端口引脚的逻辑分析仪是否正确执行该操作 奇怪的是,在发送的前三个字节之间有两个很大的间隔(介于0.6毫秒和2.4毫秒之间)。其余的字节将以预期的最大速度发送。每个字节的格式都很完美,并以正确的速率发送。字节之间的空闲时间是变化的部分。换言之,时间是这样的 [126]

我对使用“GNAT.Serial_Communications”包的简单Ada程序有一个奇怪的问题

该程序通过串行端口设备(8,N,115200波特时为1)发送七个字节(126,1,0,0,0,0,254),我已验证使用直接连接到串行端口引脚的逻辑分析仪是否正确执行该操作

奇怪的是,在发送的前三个字节之间有两个很大的间隔(介于0.6毫秒和2.4毫秒之间)。其余的字节将以预期的最大速度发送。每个字节的格式都很完美,并以正确的速率发送。字节之间的空闲时间是变化的部分。换言之,时间是这样的

[126]..........(big gap)..........[1]..........(big gap)..........[0][0][0][0][254]
我有一个C版本的程序,它没有表现出这种行为,所有字节都在一次突发中发送,没有间隔

同样地,
cat
将相同的数据直接从Bash发送到串行端口,前三个字节之间也没有这么大的间隙

这样看来,艾达库/运行时有一些方面在我的字节流中间引入了这个可变延迟。 对于我的项目来说,这是一个可以容忍的问题,但我想尝试找出为什么会发生这种情况

从串行端口读取字节显然没有问题,它正确地接收所有内容

带接口;使用接口;
使用Ada.Text_IO;使用Ada.Text\u IO;
与Ada.Streams;使用Ada.Streams;
与GNAT.Serial_通信;
主要程序是
SP:GNAT.Serial_Communications.Serial_Port;
In_Data:String(1..6):=“~ddddS”此字符串文字仅用于说明
在缓冲区中:流元素数组(1..6);
长度:流元素偏移量;
Propo_八位组类型为mod(2**8);
类型PropIO_数据包是PropIO_八位字节的数组(1..4);
数据包开始:常量八位字节:=16#7E#;
数据包逃逸标记:常量八位字节:=16#7D#;
数据包逃逸异或:常量八位字节:=16#20#;
命令硬复位:常量八位字节:=16#00#;
命令看门狗:常量八位字节:=16#01#;
程序TX_八位组(八位组:在Propo_八位组中;允许转义:在布尔值中)为
输出缓冲区:流元素数组(1..1);
温度八分位:=八分位;
开始
如果允许你逃跑的话
如果(临时Oct=数据包启动)或(临时Oct=数据包退出标记),则
输出缓冲区(流元素偏移量(1)):=Character'Pos(Character'Val(数据包转义标记));
GNAT.Serial_Communications.Write(SP,输出缓冲区);
Temp\u Oct:=Temp\u Oct xor数据包\u Escape\u xor;
如果结束;
如果结束;
输出缓冲区(流元素偏移量(1))
:=字符“Pos”(字符“Val(Temp_Oct));
GNAT.Serial_Communications.Write(SP,输出缓冲区);
结束TX_八位组;
程序TX_数据包(
命令:在PropIO_八位字节中;
数据:在Propo_数据包中
)是
CS:Propo#u八位组:=16#00#;
开始
TX_八位字节(数据包开始,错误);
TX_八位字节(命令,真);
CS:=CS-xor命令;
数据循环的D
TX_八位组(D,真);
CS:=CS-xor-D;
端环;
CS:=16#FF#-CS;
TX_八位组(CS,真);
结束发送数据包;
开始
GNAT.Serial_Communications.Open(SP,“/dev/ttyUSB0”);
GNAT.Serial_Communications.Set(
端口=>SP,
速率=>GNAT.Serial_Communications.B115200,
Bits=>GNAT.Serial_Communications.CS8,
停止\u位=>GNAT.Serial\u Communications.One,
奇偶校验=>GNAT.Serial_Communications.None
);
因为我在1。。10圈
TX_数据包(命令_看门狗,(0,0,0,0));
延迟1.0;
GNAT.Serial_Communications.Read(SP,缓冲区中,长度);
因为我在1。。长度环
In_数据(整数(i)):=字符'Val(In_缓冲区(i));
端环;
输入行(“响应:&输入数据(1..(整数(长度)));
端环;
GNAT.Serial_Communications.Close(SP);
端干管;
我在Ubuntu 19.10(最新更新)和Gnat 8.3.0下运行这段代码。通过USB连接的串行设备是合法的FTDI设备


有什么想法可能导致这种情况吗?

这不是问题的实际答案(我猜答案已经在注释中了),只是关于示例代码的提示。由于类型
GNAT.Serial\u Communications.Serial\u Port
源自
Ada.Streams.Root\u Stream\u type
,您还可以使用面向流的属性
'Read
'Write
读取和写入串行端口。例如:

main.adb

with Ada.Text_IO;
with GNAT.Serial_Communications;

procedure Main is

   package SC renames GNAT.Serial_Communications;

   type Byte is mod 2**8;
   type Byte_Array is array (Natural range <>) of Byte;

   package Byte_IO is
      new Ada.Text_IO.Modular_IO (Byte);

   Port_1 : aliased SC.Serial_Port;
   Port_2 : aliased SC.Serial_Port;

   End_Token : constant := 16#FF#;

   Buffer_Out : Byte_Array (0 .. 5) := (0, 1, 2, 3, 4, End_Token);
   Buffer_In  : Byte;

begin

   --  Open the ports.
   SC.Open (Port_1, "/dev/ttyS98");
   SC.Open (Port_2, "/dev/ttyS99");

   --  Write the byte array (packet) to port 1 in one go.
   Byte_Array'Write (Port_1'Access, Buffer_Out); 

   --  Read the byte array (packet) back from port 2, byte-by-byte.
   loop

      Byte'Read (Port_2'Access, Buffer_In);
      exit when Buffer_In = End_Token;

      Byte_IO.Put (Buffer_In);

   end loop;

   Ada.Text_IO.New_Line;

   --  Close the ports.
   SC.Close (Port_1);
   SC.Close (Port_2);

end Main;
控制台2(运行示例程序)


注意:
sudo
是创建和访问模拟设备所必需的。

您可能希望首先尝试用完整的数据包数据填充流缓冲区(数组),然后
一次性将该缓冲区写入串行端口。延迟可能是由逐字节发送消息造成的。操作系统可能不会立即响应单个写入请求。波特率仅适用于组成字符帧的位的传输。帧的定时是异步的;这就是UART中的“A”的意思。您在字符帧之间看到的时间间隔表明应用程序没有足够快地“写入”(实际上是通过syscall请求)数据,以使UART忙于传输。处理器和UART之间的USB数据包接口增加了一层额外的低效性,并可能加剧低效的用户代码,即逐字节写入。您的代码比我想出来的要容易理解得多,谢谢您,我将在我的程序中改进其中一些。我找不到任何关于GNAT.Serial_通信包的连贯文档,所以我不得不基本上打开“g-sercom.ads”文件,并试图找出其中的难点
$ sudo socat -d -d pty,raw,echo=0,link=/dev/ttyS98 pty,raw,echo=0,link=/dev/ttyS99
2020/01/14 20:23:04 socat[2540] N PTY is /dev/pts/1
2020/01/14 20:23:04 socat[2540] N PTY is /dev/pts/2
2020/01/14 20:23:04 socat[2540] N starting data transfer loop with FDs [5,5] and [7,7]
$ sudo ./main 
   0   1   2   3   4