From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.



NI-CAN读写队列可以有多大?



硬件: Wireless Sensor Network>>WSN Gateways>>NI 9792>>Switch Controller>>PCI-4021>>CAN

问题:

我想增大NI-CAN对象读写队列的长度,但是我不知道它们的极限值。



解答: 注意: NI-CAN 1.5版本解决了一些关于读写队列极限值的问题。本文假设你使用的是NI-CAN 1.5或更高版本。

每个NI-CAN对象都有一个读队列(FIFO)用于和应用程序交换其接收到的帧,还有一个写队列用于为传输交换帧。这些帧的长度则通过恰当的ncConfig函数来指定。传递给ncConfig的长度值以帧为单位,不是以字节为单位。

下列的队列长度对于大多数NI-CAN的应用来说已经足够:
 网口读队列的长度:100
网口写队列的长度:10
传输数据的CAN对象的读队列的长度:0
传输数据的CAN对象的写队列的长度:10
接收数据的CAN对象的读队列的长度:10
接收数据的CAN对象的写队列的长度:0
除非遇到特殊情况,否则一般推荐使用上述队列长度,因为这些长度满足各种不同应用的限制条件。要想增大队列长度到其最大值,需要理解这些队列在NI-CAN中是如何实现的。本文接下来将概述这个实现。

在最大数据传输率下,每一个读写队列都是在内存(Windows NI-CAN驱动和CAN卡上的嵌入式微处理器共享这个内存)中实现的,所以如果使用2端口的CAN卡,这2个端口的读/写队列(比如CAN0和CAN1)分配的是同一块内存。

每个CAN卡(1端口或2端口)可以分配给读写队列6600个字节。对于一个给定队列,用下面的公式可以计算出可用内存中已用内存的大小:
已用内存 = ((Queue_length + 1) * Entry_size) + 30;
30个字节是头文件的大小。Queue_length是使用ncConfig指定的帧的数量。Entry_size由读写的数据类型所决定:
网口读队列:22个字节
网口写队列:14个字节
CAN对象的读队列:16个字节
CAN对象的写队列:8个字节
由Memory_used的公式可以看到,将队列长度设为0并不意味着没有为队列分配内存。根据NI-CAN用户手册,一个0长度的队列存储最近的数据,因此仍然需要分配内存。一个0长度的队列需要为头文件分配30个字节,再加上一个entry (Entry_size的字节数)。即使配置了对象,情况也还是这样,但是不在应用程序打开(比如只使用CAN对象时的网口).


下面的范例有助于阐明如何计算特定应用程序的最大队列长度。

范例1:单个网口
如果只打开一个网口用于读写,通常将写队列的长度设置为推荐值10,然后使读队列的长度最大化。

写队列的长度10需要:
已用内存 = ((10 + 1) * 14) + 30 = 184字节
这样读队列长度的最大值可以达到(6600 - 184) = 6416字节。30个字节将用于读队列的头文件,还剩(6416 - 30) = 6386字节。该数除以Entry_size得到(6386 / 22) = 290帧,这意味着读队列的长度可设为289。


范例2:2个网口
如果这2个网口属于2个CAN卡,可以使用的读队列长度同范例1。但是如果是在一个2端口的CAN卡上打开这2个网口,每个网口的读队列长度必须是之前的一半(144)。这是由于6600个字节的内存是由CAN卡上的2个端口共享的。


范例3:CAN对象
配置3个CAN对象,其中2个的通信类型是周期性传输数据(Periodic Transmit ),还有1个设置为远程周期性接收数据(Receive Periodic Using Remote)。我们希望数据帧队列(用于传输的写队列、用于接收的读队列)的长度最大化。

我们没有在应用程序中打开网口,但是仍然对网口进行了配置,包括读队列和写队列。为了使分配给网口的内存最小化,我们将队列长度设置为0。

下面列出了未使用的队列的Memory_used:
 网口
读队列长度 = 0
已用内存 = ((0 + 1) * 22) + 30 = 52

网口
写队列长度 = 0
已用内存 = ((0 + 1) * 14) + 30 = 44

CAN对象,周期性传输
读队列长度 = 0
已用内存 = ((0 + 1) * 16) + 30 = 46

CAN对象,周期性传输
写队列长度 = 0
已用内存 = ((0 + 1) * 16) + 30 = 46

CAN对象,周期性接收
写队列长度 = 0
已用内存 = ((0 + 1) * 8) + 30 = 38
这些队列总的已用内存为226个字节,剩下的队列可用字节数为(6600 - 226) = 6374。

简单来说,我们将余下的内存分为3个部分,每个CAN对象占一个部分。这样每个队列可用 (6374 / 3) = 2124字节。

首先我们为周期性接收CAN对象的读队列分配内存,30个字节用于读队列的头文件,剩余(2124 - 30) = 2094字节,该数除以Entry_size得到(2094 / 16) = 130帧,这意味着读队列的长度可设为:129。

接下来我们为2个周期性传输CAN对象分配内存,30个字节用于读队列的头文件,剩余(2124 - 30) = 2094字节,该数除以Entry_size得到(2094 / 8) = 261帧,这意味着每个读队列的长度可设为:260。

注意,如果2个CAN对象是由2端口卡的2个端口所均分(比如在CAN0上传输,在CAN1上接收),我们需要为额外网口分配0长度的读写队列,但是剩下的内存分配是一样的。


可以看到,要想为CAN对象分配理想的队列长度,过程是较为复杂的。对于传输数据的CAN对象, 推荐的写队列长度10适用于大多数应用。向写队列中写入帧直至将其填满,等待一会之后再写,这样就可以方便地在CAN总线上传输大量的波形数据。对于接收数据的CAN对象,推荐的读队列长度10也可满足大多数应用,特别是当周期性传输帧的时候。

总的来说,就是要使用推荐的队列长度(本文一开始的部分有说明),除非你的应用有特别的需要,或者遇到读队列溢出的情况。

相关链接: Drivers and Updates: Latest NI-CAN driver
Product Manuals: Current NI-CAN documentation
KnowledgeBase 1YL9E1RM: What Causes Queue Overflow with NI-CAN?

附件:





报告日期: 06/14/2000
最近更新: 09/15/2007
文档编号: 1YD93QRM