Open vibnwis opened 3 years ago
You have an inline comment as below.
tv.tv_usec = m_read_timeout_ms * 1000; // Not init'ing this can cause strange errors
Can you elaborate what strange errors were those, please?
I suspect it is what I am experiencing.
When I succeeded setup the following timeout, it causes reading "CAN2 read error: Resource temporarily unavailable CAN2 - read error ". However, if I did not set the timeout or the setting failed. I got the "segmentation faults". Appreciate your comments, please?
if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(timeout)) < 0) { perror("Setting timeout failed"); return STATUS_SOCKET_CREATE_ERROR; }
Hi @vibnwis
My open() is slightly different as I use on classic CAN, not FD_CAN. See below.
I think you don't need to change anything, because you can control the can mode by setting the mode parameter of the open function
SocketCanStatus open(const std::string & can_interface, int32_t read_timeout_ms = 3, SocketMode mode = MODE_CAN_MTU)
, the default value is the classic can.Why did you implement FDCAN? does it SocketCAN support FDCAN by default?
We used can in FD mode, because there were messages on the canbus which used it. I think it depends on the interface driver if it supports or not.
If you only need CAN classic, what would you change your code or how iyour code would look like?
I don't think one need to change anything, it should work out of the box, if you specify the correct opening mode, see my comment above.
You have an inline comment as below.
tv.tv_usec = m_read_timeout_ms * 1000; // Not init'ing this can cause strange errors
Can you elaborate what strange errors were those, please?
This just means if you do not initialize this variable, than it will get some random value and it will cause error.
Unfortunately, I am not an expert on this topic, this is just a minimal implementation what we needed, to read and write can messages. My implementation based on https://github.com/linux-can/can-utils, especially https://github.com/linux-can/can-utils/blob/master/cansend.c. Here you can find lots of information, and people who understands the protocol much better then I am. Sorry, that I cannot help you more. If I will have time I will try to set up a virtual can and test it.
Best Regards, Csaba
Hi there, I experience "segmentation fault" after the very first read. You can see messages below that it received the first frame, and when reading or in the read(), it failed consistently. I can't see any wrong with it. I have tried all solutions, but still no avails. It would be appreciate if you could share your expertise, please.
CAN2Agent::recv_message() entered SocketCAN:: Read() - About to read from CAN interface can0 SocketCAN:: Read() - read from CAN interface can0 completed with num_bytes 16 SocketCAN: Read() frame.can_dlc= 8, frame.can_id = 291 data[170]data[1]data[2]data[3]data[4]data[5]data[6]data[7] SocketCAN: Read() ended len 8 byte, id: 291 data[0]: aa data[1]: 01 data[2]: 02 data[3]: 03 data[4]: 04 data[5]: 05 data[6]: 06 data[7]: 07 write frame_id to source of input_packet write frame_len to source of input_packet write frame_data to source of input_packet set_data()- len 8 set_data()- ended CAN2Agent::recv_message() exited CAN2Agent::recv_message() entered SocketCAN:: Read() - About to read from CAN interface can0 Segmentation fault (core dumped)
My open() is slightly different as I use on classic CAN, not FD_CAN. See below.
SocketCanStatus SocketCan::open(const std::string & can_interface, int32_t read_timeout_ms, SocketMode mode) { m_interface = can_interface; m_socket_mode = mode; m_read_timeout_ms = read_timeout_ms;
/*
retrieve index of the interface name / ifr.ifr_ifindex = if_nametoindex(ifr.ifr_name); /
index of the interface name */ if (!ifr.ifr_ifindex) { perror("if_nametoindex"); printf("Interface name %s",ifr.ifr_name); return STATUS_INTERFACE_NAME_TO_IDX_ERROR; }
/*
retrieve the interface index for the interface name (can0, can1, vcan0 etc) we wish to use. */
if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { perror("SIOCGIFINDEX"); return STATUS_CAN_OP_ERROR; }
/* const int timestamping_flags = (SOF_TIMESTAMPING_SOFTWARE | \ SOF_TIMESTAMPING_RX_SOFTWARE | \ SOF_TIMESTAMPING_RAW_HARDWARE);
} */
/*
*/
/*
define CAN_SFF_MASK 0x000007FFU / Standard frame format (SFF) /
define CAN_EFF_MASK 0x1FFFFFFFU / Extended frame format (EFF) /
define CAN_ERR_MASK 0x1FFFFFFFU / Ignore EFF, RTR, ERR flags /
*/
/ 12 Nov 20 Lim - Re-open the default receive filter on this RAW socket / //setsockopt(m_socket, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0); // Disable frame reception /*
if 0
else
endif
if 1
endif
// LINUX struct sockaddr_can addr;
}
There is one more thing I puzzle and hopefully you could shed some light as well. It is about struct timeval tv; tv.tv_sec = 0; // tv.tv_usec = 1100; As soon as I uncomment tv.tv_usec = 1100, it will cause the auto num_bytes = ::read(s, &frame, int(sizeof(struct can_frame))); to fail. So now, I keep it commented out.
Also, you can see that the read is somewhat different from yours. i.e auto num_bytes = ::read(m_socket, &frame, CANFD_MTU);
I was wondering does yours read() work?
If you only need CAN classic, what would you change your code or how iyour code would look like?
Why did you implement FDCAN? does it SocketCAN support FDCAN by default?
Very appreciate your comments, please?