Twice now I have received complaints/issues about reading messages from the CAN driver. The usual issue is that people people that the driver is somehow losing or dropping CAN messages. But in these cases, people discover that they have been using the CAN driver incorrectly and, as is human nature, decide that the driver is the cause of the problem.

When reading from the CAN driver multiple messages may be returned, depending on (1) the size the returned can messages, and (2) the size of the buffer provided to receive CAN messages. Never assume that a single message will be returned... if you do this, you will lose CAN messages under conditions where your read buffer can hold more than one small message. Below is an example about how you should think of the CAN read operation:

#define BUFLEN 128  /* Some arbitrary size for the CAN RX buffer */

FAR struct can_msg_s *msg;
char rxbuffer[BUFLEN];
ssize_t nread;
int nbytes;
int msglen
int i;

/* Read messages into the RX buffer */

nread = read(fd, rxbuffer, BUFLEN);

/* Check for read errors */
...

/* Process each message in the RX buffer */

for (i = 0; i <= nread - CAN_MSGLEN(0); i += msglen)
{
  /* Get the next message from the RX buffer */

  msg    = (FAR struct can_msg_s *)&rxbuffer[i];
  nbytes = can_dlc2bytes(msg->cm_hdr.ch_dlc);
  msglen = CAN_MSGLEN(nbytes);

  DEBUGASSERT(i + msglen < BUFLEN);

  /* Process the next CAN message */
  ...
}
  • No labels