Message Mailboxes

Some other CAN driver libraries in the market feature what usually is called "mailboxes", "message objects", "user buffers" etc. CANlib, on the other hand, focuses on message queues because we feel this imposes fewer restrictions on the CAN system.

For example, a higher layer protocol that uses a sequence of CAN messages with the same identifier is hard to implement using mailboxes: when the next message arrives it overwrites the previous one. You can, in a way, simulate the behavior of mailboxes by using canReadSpecific(). You will have to call canRead() periodically in order to clear out messages not read by canReadSpecific().

Example. How to simulate a mailbox-style CAN interface.

Assume you take special interest in CAN messages with identifiers 530, 540 and 550. Your message-handling loop could then look something like this:

while (..) {
if (canReadSpecific(hnd, 530, buf, ...) == canOK) {
// Process msg 530
}
if (canReadSpecific(hnd, 540, buf, ...) == canOK) {
// Process msg 540
}
if (canReadSpecific(hnd, 550, buf, ...) == canOK) {
// Process msg 550
}
while (canRead(hnd, &id, buf, ...) == canOK) {
// Handle other messages
}
}

You can call this message-processing routine from your WM__CANLIB handler or make it the main routine in your program.

Message Queue and Buffer Sizes

Incoming and outgoing CAN messages can be buffered in three different places:

  • In the CAN controller
  • On the CAN board
  • In the CAN driver (i.e. CANlib)

The sizes of the first two buffers are clearly hardware dependent. You might find the following information useful.

Many CAN boards from KVASER uses the SJA1000 CAN controller. This chip can buffer somewhere between 5 and 19 incoming messages. It does not buffer outgoing messages.

CAN boards with an on-board microcontroller (LAPcan, LAPcan II, USBcan) typically buffer something like 500 incoming and outgoing messages.

CAN boards using the M16C microcontroller (USBcan Rugged, USBcan II, PCIcan II) typically buffer some 100 incoming messages and around 50 outgoing messages.

CANlib drivers will, by default, buffer 256 outgoing messages per channel and 1024 incoming messages per channel. You can use canIoCtl() to adjust the size of the receive buffer.

Different CAN Frame Types

Remote Requests

You can send remote requests by passing the canMSG_RTR flag to canWrite(). Received remote frames are reported by canRead et al using the same flag.

Error Frames

Nearly all hardware platforms support detection of error frames. If an error frame arrives, the flag canMSG_ERROR_FRAME is set in the flag argument of canRead(). The identifier is garbage if an error frame is received, but for LAPcan it happens to be 2048 plus the error code from the SJA1000.

Many platforms (for example, LAPcan, Leaf, and USBcan II) support transmission of error frames as well. To send error frames, set the canMSG_ERROR_FRAME flag in the flag argument to canWrite().

Overload Frames

These aren't used nowadays. Certain old CAN controllers (Intel 82526) used them to delay frame processing in certain cases.

Other frame features of interest

  • You can send wakeup frames (used for Single-Wire CAN) if your hardware supports it, for example, a LAPcan plus a DRVcan S. Just set the canMSG_WAKEUP flag when calling canWrite().
  • For "low-speed CAN" (1053/1054 type transceivers), the canMSG_NERR flag is set if a frame is received in "fault-tolerant" mode.