由于不同的UART驱动程序行为将应用程序从基于ARM的旧系统移植到新系统,我遇到了问题。这些是Linux嵌入式系统,一个是内核为2.6.14的Atmel AT91,另一个是内核为3.14.38的飞思卡尔iMX6。我的应用程序是用 c 编写的。
旧的似乎有 10 个 50 字节的接收缓冲区(我在内核源代码中看到了这一点),而新的似乎至少有 1 个 4096(从测试中扣除)。
这意味着当我尝试从端口读取时,在旧系统中,我需要等待 50 次字符时间才能获得一些数据,而在新系统上,我可能需要等待 4096 个字符的时间才能获得任何数据。这是由于 UART 驱动程序中的 DMA 操作造成的。在缓冲区已满或检测到传输结束之前,驱动程序不会传递任何数据。
如果我每次都会收到响应(即传输根据数据量需要什么),这将不是问题,但是当充当主站并与总线上的从站通信时,您可能会向不存在的设备发出请求,因此您不会得到响应。在这种情况下,我的超时配置需要非常不同,旧系统为我提供了更快的超时响应。
我将用一个例子来说明这一点。我有一个从端口读取的函数,直到没有更多数据。"读取"块,直到有任何数据或超时时间过去。
如果传输为 2048 字节:
旧系统的函数读取:50字节20次,然后是48字节。新系统函数读取:2048 字节。
- 在 9600 波特时,50 字节需要 52 毫秒
- 在 9600 波特时,2048 字节需要 2.13 秒
- 在 9600 波特时,4096 字节需要 4.26 秒
因为我不知道我将得到的回复的长度,所以我必须选择最坏的情况,并假设它可以> 4096 字节:
在我的旧系统中,我可以将端口配置为在 ConfiguredTimeoutTime
+ 52 毫秒超时在新的中,我必须将其设置为 ConfiguredTimeoutTime
+ 4260 毫秒
ConfiguredTimeoutTime
是我给奴隶接收我的请求、处理它并创建响应的宽限期。这将取决于总线上的设备类型。
这是一个相当大的差异,这意味着每个无响应的从站在我的轮询时间中引入了近 4 秒的延迟。
问题是:
- 我可以从我的代码中做些什么来获得与旧系统中类似的结果?
- 在构建内核时,我可以要求新系统的提供者更改什么吗?
- 我是否完全错过了重点,并且在两个系统上都有更好的方法可以做到这一点?
抱歉帖子太长,我看不出如何进一步压缩它!谢谢!
尝试将读取超时设置为 100 毫秒,如下所示,以实现不受不同缓冲区大小的限制。当读取返回时,它将有数据或没有数据。
currentconfig.c_cc[VTIME] = 1;
currentconfig.c_cc[VMIN] = 0;
尝试从这个串行端口库中进行一些简单的实验。应用程序文件夹包含许多针对不同方案的读取方法设计。