Maximum Size for Read and Write Queues for NI-CAN

Updated May 3, 2023

Reported In

Driver

  • NI-CAN

Issue Details

I want to increase the length of my read and write queues for NI-CAN objects, but I don't know the limits. How large can I make the read and write queues for NI-CAN?

Solution

Note: NI-CAN version 1.5 fixed some problems related to the limits for read and write queues. This article assumes that you are using NI-CAN 1.5 or higher.

Every NI-CAN object uses a read queue (FIFO) to exchange received frames with your application and a write queue to exchange frames for transmission. The lengths of these queues are specified using the appropriate ncConfig function. The lengths that you pass to ncConfig are specified in frames, not in bytes.

The following queue lengths are sufficient for most NI-CAN applications:
   Network Interface read queue length:                 100
   Network Interface write queue length:                 10
   CAN Object that transmits data, read queue length:     0
   CAN Object that transmits data, write queue length:   10
   CAN Object that receives data, read queue length:     10
   CAN Object that receives data, write queue length:     0
Unless you are encountering problems, it is recommended that you use the queue lengths specified above as these lengths will remain within limits for a variety of applications. Increasing queue lengths to the maximum requires an understanding of how these queues are implemented within NI-CAN. The remaining text of this article outlines this implementation.

For maximum speed of data transfer, every read and write queue is implemented in the memory that is shared between the Windows NI-CAN driver and the embedded microprocessor on the CAN card. This memory is used for all ports on the CAN card so if you are using a 2-port card, all read/write queues for both ports (such as CAN0 and CAN1) are allocated from the same pool of memory.

Each CAN card (1 or 2 port) has 5972 bytes available for read and write queues. For a given queue, the following formula determines the amount used from available memory:
   Memory_used = ((Queue_length + 1) * Entry_size) + 30;
The 30 bytes are used for a header. Queue_length is the number of frames that you specify using ncConfigEntry_size is determined by the datatype used with each read/write, as follows:
   Network Interface read queue:    22 bytes
   Network Interface write queue:   14 bytes
   CAN Object read queue:            8 bytes
   CAN Object write queue:          16 bytes
As you can see from the formula for Memory_used, setting the queue length to zero does not mean that the queue is not allocated. As described in the NI-CAN manuals, a zero-length queue provides most-recent data, and therefore memory is still required. A zero-length queue allocates 30 bytes for a header, plus one entry (Entry_size bytes). This is true even if the object is configured, but not opened by your application (such as the Network Interface when only CAN Objects are used).


The following examples help to illustrate how to calculate maximum queue lengths for specific applications.

Example 1: Single Network Interface
If you only open one Network Interface for reading and writing, you normally set the write queue length to the recommended value of 10, then try to maximize the read queue length.

The write queue length of 10 requires:
   Memory_used = ((10 + 1) * 14) + 30 = 184 bytes
This leaves (5972 - 184) = 5608 bytes for the read queue. 30 bytes will be used for the read queue's header, leaving (5608 - 30) = 5578 bytes. Dividing this number by the Entry_size gives us (5578 / 22) = 253 frames, which means that we can set the read queue length to one less: 252.


Example 2: Two Network Interfaces
If each Network Interface is on its own CAN card, you can use the same read queue length as in Example 1. If you are opening both ports on a 2-port CAN card, the read queue length of each Network Interface must be half (2986). This is due to the fact that the 5972 bytes of memory is shared among both ports on the CAN card.


Example 3: CAN Objects
We configure 3 CAN Objects, 2 with communication type Periodic Transmit (transmt data), and 1 with type Receive Periodic Using Remote (receive data). We wish to maximize the queues used for data frames (write queue for transmit, read queue for receive).

We do not open the Network Interface in the application. Nevertheless, the Network Interface must still be configured, including the read and write queue. To minimize the memory allocated to the Network Interface, we set its queue lengths to zero.

The following lists the Memory_used for unused queues:
   Network Interface
           Read Q length = 0
           Memory_used = ((0 + 1) * 22) + 30 = 52
	
   Network Interface
           Write Q length = 0
           Memory_used = ((0 + 1) * 14) + 30 = 44
	
   CAN Obj, Periodic Transmit
           Read Q length = 0
           Memory_used = ((0 + 1) * 16) + 30 = 46
	
   CAN Obj, Periodic Transmit
           Read Q length = 0
           Memory_used = ((0 + 1) * 16) + 30 = 46
	
   CAN Obj, Receive Periodic
           Write Q length = 0
           Memory_used = ((0 + 1) * 8) + 30 = 38
The total Memory_used for these queues is 226 bytes, leaving (5972 - 226) = 5746 for the remaining queues.

For simplicity, we divide the remaining memory into 3 parts, one for each CAN Object. This provides (5746 / 3) = 1915 bytes for each queue.

First we allocate the read queue for the Receive Periodic CAN Object. 30 bytes will be used for the read queue's header, leaving (1915 - 30) = 1885 bytes. Dividing this number by the Entry_size gives us (1885 / 8) = 235 frames, which means that we can set the read queue length to one less: 234.

Next we allocate the write queue for the 2 Periodic Transmit CAN Objects. 30 bytes will be used for the read queue's header, leaving (1915 - 30) = 1885 bytes. Dividing this number by the Entry_size gives us (1885 / 16) = 117 frames, which means that we can set each write queue length to one less: 116.

Note that if the CAN Objects are split between both ports of a 2-port card (such as transmit on CAN0, and receive on CAN1), we need to allocate zero-length read and write queues for the extra Network Interface, but the remaining allocations are the same.

As you can see, determining optimal queue lengths for CAN Objects is a relatively complex process. For CAN Objects that transmit data, the recommended write queue length of 10 is adequate for most applications. By filling the write queue with frames until full, then waiting and writing again, you can easily transmit large waveforms of data onto the CAN bus. For CAN Objects that receive data, the recommended read queue length of 10 is also adequate for most applications, especially when each frame is arriving periodically.

The overall guideline is to use the recommended queue lengths (at the top of this article) unless your application has specific needs or is encountering read queue overflows.