RTCan missing frames

Johannes Holtz johannes.holtz at compador.de
Mon Feb 11 16:12:44 CET 2019


Am 11.02.19 um 16:07 schrieb Wolfgang Grandegger:
> Hello,
>
> at a first glance, your code looks good, but you are using the native
> api.. more inline...
>
> Am 11.02.19 um 14:13 schrieb Johannes Holtz:
>> Am 11.02.19 um 13:40 schrieb Wolfgang Grandegger:
>>> Hello,
>>>
>>> Am 11.02.19 um 12:55 schrieb Johannes Holtz:
>>>> Am 11.02.19 um 12:26 schrieb Wolfgang Grandegger:
>>>>> Hello,
>>>>>
>>>>> Am 11.02.19 um 10:16 schrieb Johannes Holtz via Xenomai:
>>>>>> Hi,
>>>>>>
>>>>>> In my application i set up a RTCAN socket and a pair of rt-threads.
>>>>>> One
>>>>>> to read and one to write. Writing works perfectly and I receive
>>>>>> answers
>>>>>> in the initial phase of the program.
>>>>>>
>>>>>> In particular I send CANopen NMT messages out and receive the
>>>>>> responses
>>>>>> from the other Nodes in the Network.
>>>>>>
>>>>>> 2019-02-11 09:52:13.309[       500][    CAN TX] > NMT Node 0:0:
>>>>>> CAN ID 0x000 FC 0x0 DLC 2
>>>>>>            0       82 00
>>>>>> 2019-02-11 09:52:13.310[       503][    CAN RX] > NMT Error Control
>>>>>> Node
>>>>>> 0:8:
>>>>>> CAN ID 0x708 FC 0xe DLC 1
>>>>>>            0       00
>>>>>> 2019-02-11 09:52:13.311[       503][    CAN RX] > NMT Error Control
>>>>>> Node
>>>>>> 0:9:
>>>>>> CAN ID 0x709 FC 0xe DLC 1
>>>>>>            0       00
>>>>>> 2019-02-11 09:52:13.317[       509][    CAN RX] > NMT Error Control
>>>>>> Node
>>>>>> 0:3:
>>>>>> CAN ID 0x703 FC 0xe DLC 1
>>>>>>            0       00
>>>>>> 2019-02-11 09:52:13.317[       509][    CAN RX] > NMT Error Control
>>>>>> Node
>>>>>> 0:4:
>>>>>> CAN ID 0x704 FC 0xe DLC 1
>>>>>>            0       00
>>>>>> 2019-02-11 09:52:13.317[       509][    CAN RX] > NMT Error Control
>>>>>> Node
>>>>>> 0:5:
>>>>>> CAN ID 0x705 FC 0xe DLC 7
>>>>>>            0       00 06 07 00
>>>>>>            4       00 01 01
>>>>>> 2019-02-11 09:52:13.317[       509][    CAN RX] > NMT Node 0:0:
>>>>>> CAN ID 0x000 FC 0x0 DLC 3
>>>>>>            0       07 00 00
>>>>>> 2019-02-11 09:52:13.326[       519][    CAN RX] > TIME Node 0:1:
>>>>>> CAN ID 0x101 FC 0x2 DLC 0
>>>>>>
>>>>>> As you can see, I capture 7 frames. However, the RX count from
>>>>>> /proc/rtcan/devices is 10.
>>>>>>
>>>>>> If I send specific SDO requests to one of the node which have
>>>>>> answered I
>>>>>> don't capture a response but the RX count increases and rtcanrecv
>>>>>> program captures the correct response. Only my application's read
>>>>>> doesn't return.
> What do you mean with "doesn't return". rt_can_recv(MSG_DONTWAIT) should
> not block. What does it return?
It only returns EAGAIN like there is nothing to read.
>
>>>>> Then there seem to be a problem with the read in you application. Can
>>>>> you show use the related code?
>>>>>
>>>>> Wolfgang.
>>>> Here is the main function of the rx thread. This will be executed every
>>>> 1ms.
>>>>
>>>> void can_rx_run(rt_thread_data_t *rt_data) {
>>>>       can_thread_data_t *data = (can_thread_data_t *) rt_data->data;
>>>>       data->time++;
>>>>       static can_frame_t frame_buffer[RX_BUF_SZ];
>>>>       static can_frame_t *frame   = NULL;
>>>>       static can_bus_t *bus       = NULL;
>>>>       int bytes = 1, ret, buf_i = 0;
>>>>       uint32_t bus_idx = 0;
>>>>       if ((data->time > 10)&& (data->time%2)) {
>>>>           bytes       = 1;
>>>>           for (bus_idx = 0; bus_idx < data->n_buses; bus_idx++) {
>>>>               bus     = &data->buses[bus_idx];
>>>>               if(!bus->ready) continue;
>>>>               while (bytes > 0 && (buf_i<2)) {
>>>>                   frame   = &frame_buffer[buf_i];
>>>>                   memset(frame, 0, sizeof (*frame));
>>>>                   bytes   = rt_dev_recv(bus->socket, frame, sizeof
>>>> (*frame), MSG_DONTWAIT);
>>>>                   if (bytes < 0) {
>>>>                       if ((bytes != -ETIMEDOUT) && (bytes != -EAGAIN)) {
>>>>                           rtlog(data->log, data->time, LOG_TAG_ERROR,
>>>> "Connection ended unexpected ret %d errno %d", bytes);
>>>>                       }else{
>>>>                           bytes = 1;
>>>>                       }
>>>>                       break;
>>>>                   } else if (bytes == 0) {
>>>>                       rtlog(data->log, data->time, LOG_TAG_ERROR, "CAN
>>>> Bus
>>>> Connection closed by peer");
>>>>                       break;
>>>>                   }
>>>>                   // move pointer forward for the next frame
>>>>                   buf_i = (buf_i + 1) % RX_BUF_SZ;
>>>>
>>>>                   log_frame(data->log, data->time, frame, bus_idx);
>>>>                   ret = check_frame_integrity(data->log, data->time,
>>>> frame);
>>>>                   if (ret) {
>>>>                       rtlog(data->log, data->time, LOG_TAG_ERROR,
>>>>                             "Frame didn't pass integrity check %d", ret);
>>>>                       continue;
>>>>                   }
>>>>                   ret = process_frame(data->ipc_socket, frame, bus_idx);
>>>>                   if (ret < 0) {
>>>>                       rtlog(data->log, data->time, LOG_TAG_ERROR,
>>>>                             "failed to accept RX CAN frame %d from
>>>> Node %u",
>>>>                             ret);
>>>>                   }
>>>>               }
>>>>           }
>>>>       }
>>>> }
>>> And the code setting up the socket?
>>>
>>> Wolfgang.
>> static int set_bus_mode(can_bus_t* bus, int mode) {
>>      uint32_t *new_mode = (can_mode_t *) &bus->device.ifr_ifru;
>>      *new_mode = mode;
>>      int res = rt_dev_ioctl(bus->socket, SIOCSCANMODE, &bus->device);
>>      if(res) {
>>          return CAN_BUS_INIT_ERROR_MODESET;
>>      }
>>      return 0;
>> }
>>
>> void bus_shutdown (can_bus_t *bus) {
>>
>>      set_bus_mode(bus, CAN_MODE_STOP);
>>
>>      if (bus->socket < 0)
>>          return;
>>
>>      rt_dev_close (bus->socket);
>>      bus->socket = -1;
>>
>>      printf("shutdown bus %d\n", bus->bus_index);
>>      return;
>> }
>>
>> int bus_init (can_bus_t *bus, const int BUS, const uint32_t BAUDRATE,
>> const int64_t TIMEOUT_SEND, const int64_t TIMEOUT_RECV) {
>>      struct sockaddr_can addr;
>>      bus->bus_index = BUS;
>>      int res;
>>      static unsigned int err_mask = CAN_ERR_MASK;
>>      /*
>>      static unsigned int err_mask =  CAN_ERR_CRTL         // Controller
>> Problems (see data[1])
>>                                      | CAN_ERR_BUSOFF            // Bus Off
>>                                      | CAN_ERR_RESTARTED     //
>> Controller Restarted
>>                                      | CAN_ERR_TX_TIMEOUT    // TX
>> timeout (netdevice driver).
>>                                      | CAN_ERR_LOSTARB           // Lost
>> arbitration (see data[0]).
>>                                      | CAN_ERR_PROT        // Protocol
>> violations (see data[2], data[3]).
>>                                      | CAN_ERR_TRX        // Transceiver
>> status (see data[4]).
>>                                      | CAN_ERR_ACK        // Received no
>> ACK on transmission.
>>                                      //| CAN_ERR_BUSERROR        // Bus
>> error (may flood!).
>>                                      //| CAN_ERR_MASK            // All
>> error flags.
>>                                      ;
>>      */
>>      // create socket
>>      bus->socket = rt_dev_socket (PF_CAN, SOCK_RAW, CAN_RAW);
>>      if (bus->socket < 0) {
>>          printf("%s > failed to get socket %d\n",__func__, bus->socket);
>>          return CAN_BUS_INIT_ERROR_RT_DEV_SOCKET;
>>      }
>>
>>      // device index
>>      snprintf (bus->device.ifr_ifrn.ifrn_name, IF_NAMESIZE, "rtcan%d",
>> bus->bus_index);
>>      res = rt_dev_ioctl (bus->socket, SIOCGIFINDEX, &bus->device);
>>      if (res) {
>>          printf("%s > failed to set IF name %s error %d\n", __func__,
>> bus->device.ifr_ifrn.ifrn_name, res);
>>          bus_shutdown (bus);
>>          return CAN_BUS_INIT_ERROR_SIOCGIFINDEX;
>>      }
>>
>>      // receive CAN error frames (also pseudo frames)
>>      res = rt_dev_setsockopt (bus->socket, SOL_CAN_RAW,
>> CAN_RAW_ERR_FILTER, &err_mask, sizeof (err_mask));
>>      if (res) {
>>          bus_shutdown (bus);
>>          return CAN_BUS_INIT_ERROR_SETSOCKOPT;
>>      }
>>
>>      // bind recv
>>      addr.can_family     = AF_CAN;
>>      addr.can_ifindex    = bus->device.ifr_ifindex;
>>      res = rt_dev_bind (bus->socket, (struct sockaddr *) &addr, sizeof
>> (addr));
>>      if (res < 0) {
>>          printf("%s > rt_dev_bind failed with %d\n", __func__, res);
>>          bus_shutdown (bus);
>>          return CAN_BUS_INIT_ERROR_BIND;
>>      }
>>
>>      // baudrate
>>      can_baudrate_t *baudrate = (can_baudrate_t *) &bus->device.ifr_ifru;
>>      *baudrate = BAUDRATE;
>>      res = rt_dev_ioctl (bus->socket, SIOCSCANBAUDRATE, &bus->device);
>>      if (res) {
>>          bus_shutdown (bus);
>>          return CAN_BUS_INIT_ERROR_BAUDRATE;
>>      }
>>
>>      // timeout send
>>      if (TIMEOUT_SEND) {
>>          res = rt_dev_ioctl (bus->socket, RTCAN_RTIOC_SND_TIMEOUT,
>> &TIMEOUT_SEND);
>>          if (res) {
>>              bus_shutdown (bus);
>>              return CAN_BUS_INIT_ERROR_TIMEOUT_SEND;
>>          }
>>      }
>>
>>      // timeout recv
>>      if (TIMEOUT_RECV) {
>>          res = rt_dev_ioctl (bus->socket, RTCAN_RTIOC_RCV_TIMEOUT,
>> &TIMEOUT_RECV);
>>          if (res) {
>>              bus_shutdown (bus);
>>              return CAN_BUS_INIT_ERROR_TIMEOUT_RECV;
>>          }
>>      }
>>
>>      bus->ready = true;
>>      return set_bus_mode(bus, CAN_MODE_START);
>> }
>>
>>
>>





More information about the Xenomai mailing list