-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create new SocketCAN-capable device #251
Comments
I'd like to retrieve certain information on the CAN-enabled sockets, such as current state (BUSOFF, errors...) and bitrate. This can be achieved via command line with See https://www.kernel.org/doc/html/latest/networking/can.html (text version). Edit: answered below at #251 (comment). |
For now, I'm just giving up on providing bitrate information to CanBusSocket users. In this scenario, the CAN bus brokers should be configured to not instantiate a bus load monitor by either not providing a Edit: nah, let's keep that window open. Clients still can pass a bitrate value via config options and retrieve it later through the interface's getter. The setter is disabled, of course. |
Regarding socket buffers: https://stackoverflow.com/q/1803215/10404307. Regarding block-with-timeout socket R/W: https://stackoverflow.com/q/47425873/10404307 and https://ubuntuforums.org/showthread.php?t=1565651&p=9794579#post9794579 (from #146 (comment)). |
CAN ID filtering implemented following the advices at https://stackoverflow.com/q/57790381/10404307. I'm assuming that each In any case, we are not using filters in CanBusControlboard. Edit: tested on a virtual CAN interface and working nicely. I'm actually prone to re-enable filters in CanBusControlboard. |
Thankfully, virtual CAN interfaces are a thing (docs)! Maybe I can test this device from my own home PC. To start such an interface, type:
In fact,
I'm using the previous commands to redirect traffic from vcan1 to vcan0 (so vcan1 here plays the role of a CAN node, while vcan0 is the master), then listen to it via |
Blocking and non-blocking reads and writes successfully tested with the following sample application (see previous comment regarding how to initiate two virtual CAN networks and bind them together): #include <yarp/conf/numeric.h>
#include <yarp/os/LogStream.h>
#include <yarp/os/Property.h>
#include <yarp/os/SystemClock.h>
#include <yarp/dev/CanBusInterface.h>
#include <yarp/dev/PolyDriver.h>
int main()
{
constexpr auto id = 25;
constexpr auto block = false;
constexpr auto BUFFER_SIZE = 10;
yarp::os::Property options = {
{"device", yarp::os::Value("CanBusSocket")},
{"blockingMode", yarp::os::Value(block)},
{"port", yarp::os::Value("vcan0")}
};
yarp::dev::PolyDriver device;
if (!device.open(options))
{
yError() << "Cannot open";
return 1;
}
yarp::dev::ICanBus * iCanBus;
yarp::dev::ICanBufferFactory * iCanBufferFactory;
if (!device.view(iCanBus) || !device.view(iCanBufferFactory))
{
yError() << "Cannot view";
return 1;
}
yInfo() << "canIdAdd()" << iCanBus->canIdAdd(id);
auto sendBuffer = iCanBufferFactory->createBuffer(BUFFER_SIZE);
unsigned int sent;
for (auto i = 0; i < BUFFER_SIZE; i++)
{
sendBuffer[i].setId(id);
sendBuffer[i].setLen(2);
unsigned char data[] = {0x01, 0x02};
std::memcpy(sendBuffer[i].getData(), data, sizeof(data));
}
yInfo() << "canWrite():" << iCanBus->canWrite(sendBuffer, BUFFER_SIZE, &sent, block);
yInfo() << "Sent" << sent << "messages";
auto readBuffer = iCanBufferFactory->createBuffer(BUFFER_SIZE);
unsigned int read = 0;
do
{
iCanBus->canRead(readBuffer, BUFFER_SIZE, &read, block);
yarp::os::SystemClock::delaySystem(0.005);
}
while (!block && read == 0);
yInfo() << "Got" << read << "messages";
for (auto i = 0; i < read; i++)
{
auto && log = yInfo();
log << "id:" << readBuffer[i].getId() << "len:" << readBuffer[i].getLen() << "data:";
for (auto j = 0; j < readBuffer[i].getLen(); j++)
{
log << yarp::conf::numeric::to_hex_string(readBuffer[i].getData()[j]);
}
}
iCanBufferFactory->destroyBuffer(sendBuffer);
iCanBufferFactory->destroyBuffer(readBuffer);
yInfo() << "canIdDelete()" << iCanBus->canIdDelete(id);
return 0;
} |
Moar links found by @jgvictores, mostly referring to VCAN+sniffing (Wireshark): |
According to https://stackoverflow.com/q/13021796/10404307, sockets are full-duplex and bi-directional, therefore lock mechanisms (e.g. a mutex) should not be necessary. In any case, reads and writes are carried out by separate CanBusControlboard threads. |
Regarding error handling:
PEAK also provides a deprecated netdev implementation (link), look for driver/src/pcan_netdev.c. |
Mainline kernel implementations for PEAK hardware (ref, see sources in previous comment):
In TEO, we'd use peak_pciefd according to that. |
CAN bus states along with the error count thresholds (ref): /*
* CAN operational and error states
*/
enum can_state {
CAN_STATE_ERROR_ACTIVE = 0, /* RX/TX error count < 96 */
CAN_STATE_ERROR_WARNING, /* RX/TX error count < 128 */
CAN_STATE_ERROR_PASSIVE, /* RX/TX error count < 256 */
CAN_STATE_BUS_OFF, /* RX/TX error count >= 256 */
CAN_STATE_STOPPED, /* Device is stopped */
CAN_STATE_SLEEPING, /* Device is sleeping */
CAN_STATE_MAX
}; |
The previous enumeration originates from More info:
NIce thing is: we would not need to type (or configure on start) |
My findings on netlink and libsocketcan:
Is libsocketcan worth it? I am mostly interested in solving #246, which might be doable through other means. I just need to monitor the bus-off condition, I don't care about overflow and error counts stored along with that single Boolean in For future reference (maybe I decide to ditch this idea), I have written a find module for libsocketcan at 46818a8. |
Current non-netlink WIP implementation reaches error-passive state on TX upon pressing the emergency button. This fires up at exactly 128 TX errors (#251 (comment)). The output is as follows:
Then, all subsequent CAN writes fail with:
Bus statistics can be obtained via
It never goes beyond those 128 TX errors, which means bus-off state (256 errors) is never reached. We need it to prevent spurious writes from happening, see #246 and: yarp-devices/libraries/YarpPlugins/CanBusControlboard/CanRxTxThreads.cpp Lines 158 to 164 in 5b8dd5e
Output of
Note the We can conclude that netlink/libsocketcan would have made no difference since it returns the same information as |
Done at c86fc25. Configuration files have been not prepared yet, but it's a trivial task. I'm going to consider a migration from CanBusPeak to CanBusSocket as the default CAN device in September. The commands that need to be added on start for each canX interface are:
Prior to that, if proprietary PCAN chardev drivers are decided to be kept, the mainline "peak_pciefd" module must be un-blacklisted (commented out) from |
SocketCAN bus interfaces can be enabled via systemd using this config file located at
Replace
Discarded solutions:
If you want to disable PeakCAN and enable SocketCAN:
If you want to disable SocketCAN and enable PeakCAN:
Step 1 and |
For future reference, left arm (7 nodes) CAN bus usage at 2 ms is 75% (or 68% according to I have merged roboticslab-uc3m/teo-configuration-files@3627e52. The default CAN bus device was switched from CanBusPeak to CanBusSocket on both manipulation and locomotion PCs. See above comment for instructions on how to easily switch between CAN devices and networks. Mind that the proprietary PEAK module might become obsolete due to Linux header upgrades and thus require a rebuild. Also, launch files need to be tweaked in order to pick the correct device implementation (replace In order to keep the workspace clean, it is best to use YARP's resource finder system and locally installed files (as opposed to copy-pasting lots of .ini files in |
In my process of working on a new PCAN-based YARP device at #146, I considered the creation of a more generic SocketCAN device as well. It did not prosper at the time (beyond some preliminary work on the fix-146-CanBusSocket branch), although it's definitely on my radar as the currently empty CanBusSocket directory suggests.
I'm tagging this as low priority given that it's not a pressing matter for our work on TEO; note we are currently fine with the CanBusPeak device. However, it is definitely worth exploring the non-vendor widespread solution that most Linux kernels support nowadays.
See also:
can-utils
suite (apt package)The text was updated successfully, but these errors were encountered: