1

socketCAN connection: read() not fast enough

Hello,

I use the socket() connection for my CAN communication.

fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);

I'm using 2 threads: one periodic 1ms RT thread to send data and one thread to read the incoming messages. The read function looks like:

void readCan0Socket(void){
   int receivedBytes = 0;
   do
   {
      // set GPIO pin low
      receivedBytes = read(fd ,
                           &receiveCanFrame[recvBufferWritePosition],
                           sizeof(struct can_frame));
      // reset GPIO pin high

      if (receivedBytes != 0)
      {
         if (receivedBytes == sizeof(struct can_frame))
         {
            recvBufferWritePosition++;
            if (recvBufferWritePosition == CAN_MAX_RECEIVE_BUFFER_LENGTH)
            {
               recvBufferWritePosition = 0;
            }
         }
         receivedBytes = 0;
      }

   } while (1);
 }

The socket is configured in blocking mode, so the read function stays open until a message arrived. The current implementation is working, but when I measure the time between reading a message and the next waiting state of the read function (see set/reset GPIO comment) the time varies between 30 us (the mean value) and > 200 us. A value greather than 200us means (CAN has a baud rate of 1000 kBit/s) that packages are not recognized while the read() handles the previous message. The read() function must be ready within 134 us.

How can I accelerate my implementation? I tried to use two threads which are separated with Mutexes (lock before the read() function and unlock after a message reception), but this didn't solve my problem.

Vikash Pandey
  • 5,407
  • 6
  • 41
  • 42
Mjoelnir81
  • 11
  • 2
  • What does "see set/reset GPIO comment" mean ? Are you doing something more than what your code shows ? e.g. are you reading//writing a GPIO pin, which could incur significant latency ? Note that the socket also have a buffer, which will smooth over jitter like you observe - you'll need to figure out if you're losing packets or read to slow *on average*. – nos Jun 03 '16 at 07:21
  • You should drain the buffer every chance you get rather than just reading one frame and then moving on to do other stuff. – David Schwartz Jun 03 '16 at 07:21
  • Yes, at the comment line I set / reset gpio pin. Toggling the gpio is fast enough I think. The average time of the read function is 30us. It is the spike values I'm concerned of. – Mjoelnir81 Jun 03 '16 at 07:32
  • I have never tried, but it should be possible to read many frames at a time by requesting `N*sizeof(struct can_frame)`, then doing your `read` non-blocking – Fusho Oct 05 '17 at 16:32

0 Answers0