================================================================================ esd SocketCAN Plugin for NTCAN library ================================================================================ The information in this document has been carefully checked and is believed to be entirely reliable. esd makes no warranty of any kind with regard to the material in this document, and assumes no responsibility for any errors that may appear in this document. esd reserves the right to make changes without notice to this, or any of its products, to improve reliability, performance or design. esd assumes no responsibility for the use of any circuitry other than circuitry which is part of a product of esd gmbh. esd does not convey to the purchaser of the product described herein any license under the patent rights of esd gmbh nor the rights of others. The use of this software component (esd SocketCAN plugin for NTCAN library) is only allowed with esd CAN interface devices. Any use with other hardware devices is explicitly forbidden. 1 Overview ---------------------------------------- This NTCAN plugin allows to use the esd NTCAN API with esd CAN devices that are supported by SocketCAN. For that purpose it tries to rebuild the esd NTCAN API functionality over the SocketCAN API. This should allow most applications that use esd's NTCAN API to run with SocketCAN. See next chapter for restrictions. The libntcan.so provided in this archive is built with the plugin interface enabled which is needed to support the SocketCAN plugin (libntcanSckPlugin.so). A NTCAN library delivered with an esdcan CAN driver is built with the plugin interface disabled and is therefore overwritten by the install script. The summary information displayed by the install script shows the installed NTCAN libraries and whether they provide the plugin interface. 1.1 Additional requirements ---------------------------------------- I SocketCAN Please see https://github.com/linux-can/ and https://github.com/linux-can/can-utils/ for more information. The user level library libsocketcan can be obtained from http://www.pengutronix.de/software/libsocketcan/download/. Most distributions nowadays provide a package with it. It is named libsocketcan2 under Debian. II "ip"-tool supporting can The install script tries to detected if an 'ip' tool is installed and if it supports the CAN link type (looking for 'can' or 'vcan' as supported type). It complains if a suitable 'ip' tool is not found. Possibly you need to install the package that provides the 'ip' tool. It is named 'iproute2' on Debian. 1.2 Installation ---------------------------------------- I Make sure SocketCAN is available and a device driver is loaded, etc., e.g. by "ls /sys/class/net/". When there is an entry "can0" everything should be fine, else don't try to install this NTCAN plugin before the SocketCAN interface is running properly. II Extract the archive, e.g. by "tar xvfz ntcanSckPlugin32-2.0.8-ntcan-3.3.6.tgz". III Change into the newly created directory and run the install script as *root* user, e.g. by "sudo ./install.sh". The install script provides a test mode (--dry-run) to see in advance what it will do. For usage information call "./install.sh -h". See chapter "Test" for how to verify installation success. The resulting tree of libraries and binaries after an installation with the default PREFIX=/usr/local will look like shown below: / ├── etc │   └── esd-plugin └── usr └── local ├── bin │   └── cantest ├── include │   └── ntcan.h └── lib ├── libntcanSckPlugin.so -> libntcanSckPlugin.so.2 ├── libntcanSckPlugin.so.2 -> libntcanSckPlugin.so.2.3.1 ├── libntcanSckPlugin.so.2.3.1 ├── libntcan.so -> libntcan.so.4 ├── libntcan.so.4 -> libntcan.so.4.0.1 ├── libntcan.so.4.0.1 ├── libsocketcan.so.2 -> libsocketcan.so.2.2.1 └── libsocketcan.so.2.2.1 2 Differences/Restrictions to NTCAN API ---------------------------------------- (See NTCAN API documentation if terms used here are unclear. Also keep in mind that SocketCAN is under development and usage might have changed and therefore some hints here became obsolete/wrong) * Lost counter "lost_msg" in CMSG/CMSG_T structs is supported but behaves a little bit different from an esdcan CAN driver's behaviour. This counter tells you how many frames have been lost since the last read on the handle level. For information about lost frames on the interface level you can use the content of "sys/class/net/can0/statistics". To show the difference in behaviour imagine the following experiment. First open a handle with a RX queue length of 5 and enable the needed CAN Ids. Then a burst of 20 frames is received with the frame number as data content (mark ) which overflows the RX queue. After that 20 calls of canTake() are done on the handle and the received frames are printed (canTake() with "len" == 0 return not printed) which purges the RX queue completely. This is then mark . Another 2 frames are received from the CAN bus and after that (bus traffic completed) the next two canTake() calls deliver two CAN frames. Then the printout looks different if the driver the NTCAN API is based on is either an esdcan driver or via the wrapper is SocketCAN based. The first column marked with # counts the canTake() calls. esdcan based printout: # lost_msg CAN-ID DLC data (hex) 1 lost 0 0x00000080 0x04 01 00 00 00 2 lost 0 0x00000080 0x04 02 00 00 00 3 lost 0 0x00000080 0x04 03 00 00 00 4 lost 0 0x00000080 0x04 04 00 00 00 5 lost 15 0x00000080 0x04 14 00 00 00 21 lost 0 0x00000080 0x04 15 00 00 00 22 lost 0 0x00000080 0x04 16 00 00 00 Observe that the RX queue has the exact length of 5. With canTake() call #5 you get the most recent (!) received frame and the announcement of 15 lost frames. SocketCAN based printout: # lost_msg CAN-ID DLC data (hex) 1 lost 0 0x00000080 0x04 01 00 00 00 2 lost 0 0x00000080 0x04 02 00 00 00 3 lost 0 0x00000080 0x04 03 00 00 00 4 lost 0 0x00000080 0x04 04 00 00 00 5 lost 0 0x00000080 0x04 05 00 00 00 6 lost 0 0x00000080 0x04 06 00 00 00 7 lost 0 0x00000080 0x04 07 00 00 00 8 lost 0 0x00000080 0x04 08 00 00 00 9 lost 0 0x00000080 0x04 09 00 00 00 10 lost 0 0x00000080 0x04 0A 00 00 00 11 lost 0 0x00000080 0x04 0B 00 00 00 21 lost 9 0x00000080 0x04 15 00 00 00 22 lost 0 0x00000080 0x04 16 00 00 00 Observe that the length of the RX queue is not exact of 5. When you purge the RX queue there is no indication of any lost frames. With canTake() call #11 you only get the last frame that fit into the RX queue. After you have purged the RX queue you only get on the next canTake() call (#21) the indication for lost frames. * Events: NTCAN_EV_CAN_ERROR is the only event supported. And within that event's data byte one ("error") is the only supported byte. * Only these I/O controls are supported (See NTCAN docs "canIoctl"): NTCAN_IOCTL_GET_BAUDRATE, NTCAN_IOCTL_SET_BAUDRATE, NTCAN_IOCTL_FLUSH_RX_FIFO, NTCAN_IOCTL_SET_20B_HND_FILTER, NTCAN_IOCTL_GET_TIMESTAMP, NTCAN_IOCTL_GET_TIMESTAMP_FREQ, NTCAN_IOCTL_GET_RX_TIMEOUT, NTCAN_IOCTL_GET_TX_TIMEOUT, NTCAN_IOCTL_SET_TX_TIMEOUT, NTCAN_IOCTL_SET_RX_TIMEOUT, NTCAN_IOCTL_TX_OBJ_CREATE, NTCAN_IOCTL_TX_OBJ_DESTROY, NTCAN_IOCTL_TX_OBJ_UPDATE, NTCAN_IOCTL_TX_OBJ_AUTOANSWER_ON, NTCAN_IOCTL_TX_OBJ_AUTOANSWER_OFF, NTCAN_IOCTL_TX_OBJ_SCHEDULE_START, NTCAN_IOCTL_TX_OBJ_SCHEDULE_STOP, NTCAN_IOCTL_TX_OBJ_SCHEDULE * Bus-OFF handling Current SocketCAN's default is to stay off bus then. The application is usually helpless in that case. To avoid this, set SocketCAN to automatically restart the device then. Currently this can be done with the "ip" command as *root*: e.g.: "ip link set can0 type can restart-ms 1000". (Manual restart possible as *root* by "ip link set can0 type can restart") This is also done automatically. See chapter Configuration for infos about how to avoid that. * canStatus() Resulting CAN_IF_STATUS struct members: "hardware" and "firmware" as described or 0 when they couldn't be determined. "driver" is the wrapper plugin version number. "dll" is set by NTCAN library. "boardstatus" is one of enum "can_state" defined in netlink.h (or 0xffffffff if it couldn't be determined) "boardid" is "SocketCAN". "features" is NTCAN_FEATURE_BASIC_20B | NTCAN_FEATURE_TIMESTAMP Where it is not guaranteed that the underlying hardware really supports CAN 2.0B or hardware timestamps. (Else timestamps will be set by software) * canOpen() The txqueuesize and txtout parameters are ignored! Only some of the open flags are supported: NTCAN_MODE_MARK_INTERACTION NTCAN_MODE_NO_INTERACTION (limited support / incompatible) NTCAN_MODE_LOCAL_ECHO SocketCAN's TX queue size can be set with the ip tool, e.g.: "ip link set can0 txqueuelen 1000" but that is an interface wide setting. The receive buffer size depends on the given rxqueuesize value. But does not match exactly that number of frames. Also it is limited by "rmem_max" value, which can be increased with e.g. "echo 1048576 >/proc/sys/net/core/rmem_max" These example values are also written automatically. See chapter Configuration for infos about how to avoid that. * canSetBaudrate() Only "Pre-defined bit rate table" and "User Bit Rate Numerical" are allowed. Usually only possible as "superuser". (e.g. when app is started with "sudo") Also (re)starts the SocketCAN net interface if it was down or controller was Bus-OFF. Stops the SocketCAN net interface with baud param NTCAN_NO_BAUDRATE. To change the baud rate the Socket-CAN interface must be brought down and then up again. The next IO operation on all open Socket-CAN sockets will then return with error and set to "ENETDOWN". This will then be translated to NTCAN_WRONG_DEVICE_STATE. * canGetBaudrate() Returns NTCAN_NO_BAUDRATE when controller is Bus-OFF or SocketCAN net interface is down. * canRead()/canReadT() When function is waiting for a message, it is not interrupted when another thread closes the same NTCAN handle. * canWrite()/canWriteT()/NTCAN_IOCTL_SET_TX_TIMEOUT The TX timeout is ignored. It is blocking until message is written to the socket buffer! While this is fine for safely sending more messages than the buffer could hold, it is still no guarantee they really went on the bus. (As we're only waiting till they're in the buffer/queue) Does not return NTCAN_CONTR_OFF_BUS/NTCAN_CONTR_WARN. It will return NTCAN_SUCCESS even when controller is Bus-OFF! To avoid this use the error events and stop sending when controller goes off bus. * CAN frame data length counter > 8 SocketCAN does not allow this, so when CMSG/CMSG_T member "len" is set to a value between 9 and 15 it is treated as 8. In receive direction any frames DLC is also limited to 8 by SocketCAN. * NTCAN_IOCTL_GET_TIMESTAMP_FREQ Currently always returns 1000000, regardless of actual frequency. (Timestamps are based on gettimeofday()) * NTCAN_IOCTL_TX_OBJ_SCHEDULE Only time_interval and flags members of CSCHED struct is supported. And the only supported flag is NTCAN_SCHED_FLAG_DIS. (So the cyclic TX always starts with NTCAN_IOCTL_TX_OBJ_SCHEDULE_START and cannot be delayed to a later time) 3 Configuration ---------------------------------------- Configuration is done with the file "/etc/esd-plugin" (see also comments in that file). By default 3 nets are configured: SocketCAN device "can0" is configured as NTCAN net 60, "can1" as net 61, and so on. Just edit the corresponding lines in the file: "libntcanSckPlugin.0.Net=60" "libntcanSckPlugin.1.Net=61" "libntcanSckPlugin.2.Net=62" Other settings in that file: Verbosity level (Text output to "stdout" of the program): "libntcanSckPlugin.verbose=0" Prints nothing "libntcanSckPlugin.verbose=1" Only errors "libntcanSckPlugin.verbose=2" Errors and warnings "libntcanSckPlugin.verbose=3" Errors, warnings and Infos Automatically adapting SocketCAN settings: "libntcanSckPlugin.noscc=1" To disable the use of the settings below. Set a minimum TX queue of "minTXQueue" bytes for the Socket-CAN interface: "libntcanSckPlugin.minTXQueue=1000" Set a RX queue size of "minRMem" bytes for the Socket-CAN interface: "libntcanSckPlugin.minRMem=1048576" Set the Socket-CAN interface's "restart-ms" parameter to the value of "defRestartMs": "libntcanSckPlugin.defRestartMs=1000" 4 Test ---------------------------------------- When the .tar is extracted the test application "cantest" is in the sub folder "cantest" there. Just run it without parameters to see a short help and a list of available CAN nets. (The source and a Makefile is also included for cantest) You should see one or more entries similar to this: Net 60: ID=SocketCAN Serial no.: GN002267 Versions (hex): Lib=4.0.01 Drv=2.3.00 HW=1.0.00 FW=1.1.01 (0.0.00) Baudrate=00000000 (1000 KBit/s) Status=0000 Features=00000462 Ctrl=NXP LPC2xxx MCU @ 60 MHz (Error Active / REC:0 / TEC:0) Transceiver=NXP PCA82C251 TimestampFreq=1.000000 MHz Timestamp=00055825741D5B01 5 History ---------------------------------------- Version 1.0.0/2.0.0, 2010/01/06 BETA1. Tested with SocketCAN SVN Revision 1095 Version 1.0.1/2.0.1, 2010/01/15 Tested with SocketCAN SVN Revision 1107 - More text output, currently set to verbose, see chapter configuration - Enabled loopback - Automatically adapting some SocketCAN settings Version 1.0.2/2.0.2, 2010/01/19 - Minor changes only Version 1.0.3/2.0.3, 2010/03/22 - Also as 64bit version - canOpen() uses "txqueuesize" parameter to change SocketCAN's rx buffer size - Renamed library, now with "lib" prefix (also changed in "esd-plugin") Version 1.0.4/2.0.4, 2011/04/11 - First version for ARM - Changes to build/installation scripts - Updated NTCAN library and cantest.c - Format of /etc/esd-plugin changed Version 1.0.5/2.0.5, 2011/11 - Using original version number for libsocketcan.so - More output when verbose level set to 3 - Updated NTCAN library and cantest.c Version 1.0.6/2.0.6, 2011/11 - canRead() now waits forever with rx timeout of 0 Version 2.0.7, 2013/04 - Removed SYSFS branch - Updated libsocketcan.so to 0.0.9 - When unable to change/get some SocketCAN settings it's now shown as warning only and the wrapper does not abort Version 2.0.8, 2013/09 - Added support for several IOCTLs (TX Scheduling and RTR Auto-Answer) Version 2.0.9, 2014/10 - Added basic support for two more IOCTLs (..._GET_CTRL_STATUS and ..._GET_BITRATE_DETAILS) Version 2.1.0, 2014/11 - Using NTCAN library 3.5.1 Version 2.2.0, 2016/02 - Removed NTCAN API documentation from release archive. Please download it from www.esd.eu (registration needed). Use https://esd.eu/en/content/support-center and in "Downloads" section select "Manuals". Then a search form for the manuals shows up. Enter "NTCAN-API" in the search bar to get the manuals. - Using NTCAN library 4.0.1 - Updated libsocketcan.so to 0.0.10 Version 2.2.3, 2016/07 - Fixed bug with internal handling of NTCAN library's handle context data. - Forces changed behaviour of canSetBaudrate(): To change the baud rate the Socket-CAN interface must be brought down and then up again. The next IO operation on all open Socket-CAN sockets will then return with error and set to "ENETDOWN". To hide this error previous plugin versions used a workaround but that broke the context data handling as described before. Also the workaround was only effective for the NTCAN handle used to set the baud rate. All TX jobs on other NTCAN handles returned with TX_ERROR. Instead of using the workaround canWrite()/canSend() were changed to return NTCAN_WRONG_DEVICE_STATE on =="ENETDOWN" like it was already happening with canRead()/canTake(). Version 2.2.4, 2016/08 - Added support for the NTCAN mode flags NTCAN_MODE_LOCAL_ECHO and NTCAN_MODE_NO_INTERACTION. Version 2.2.5, 2016/09 - Added a workaround for the canCalClient*load() RX timeout problem: Setting a minimum RX buffer size of 4k is a workaround for the problem that is happening if you want to receive only a single CAN Id (like for canCalClient*load()) but between your request and the slave's response is a lot of CAN traffic. Then the SDO response may not fit into the RX buffer and is missed. This happens because the CAN frames are filtered by software on the SocketCAN wrapper level AFTER passing the RX buffer. Version 2.2.6, 2016/09 - Speed up the canIdAdd() and canIdDelete() calls by counting the open 2.0-A RX ids incrementally in preparation for the pending update to do an exact filtering with only 1 (or 2) ids enabled. Version 2.2.7, 2016/09 - Optimization of canIdAdd() and canIdDelete() calls in two aspects: * Save the current SocketCAN RX id filter mode internally to avoid one setsockopt() call if the SocketCAN filter doesn't need to be changed. * Save the current SocketCAN error filter mode internally to avoid another setsockopt() call if it doesn't need to be changed (almost never). - Save code runtime on user level by setting up an exact filtering if only a single 2.0-A id is enabled. This makes sense for canCal SDO handles which also avoids a socket buffer overflow which had been worked around with in version 2.2.5 by increasing the socket's RX buffer. Version 2.2.8, 2016/09 - Fix the incorrect handling for error events generated on the SocketCAN level that could lead to a lock up situation. After returning from a select() with the CAN handle the next canRead() still would block if the SocketCAN error event frame contained a CAN_ERR_CRTL condition with a CAN_ERR_CRTL_RX_OVERFLOW only. That frame was not fully decoded and then ignored which lead to the fact to be stuck in canRead() then. Now the SocketCAN error frame is only enabled if NTCAN_EV_ERROR is enabled with canIdAdd(). - Optimisation for canIoctl(NTCAN_GET_CTRL_STATUS) to only call the code to guess the controller once in canOpen(). - Fixed the in the result structure of canStatus() to contain the controller type. Version 2.2.9, 2016/11 - canStatus() and canIoctl(IOCTL_GET_CTRL_STATE,...) now return correct controller types for the esd USB devices. - The first canOpen() on a CAN interface already set up using the "ip" tool brought the interface unconditionally down to change the parameters "defRestartMs" or "minTXQueue". Now the previous state (up/down) is restored again. With the old behaviour a canGetBaudrate() on the interface would have returned NTCAN_NO_BAUDRATE even with a valid baudrate previously set. Because an interface that is down is regarded to have NTCAN_NO_BAUDRATE by canGetBaudrate(). The new behaviour makes sure that after you set a baud rate and brought the interface up with the "ip" tool then after the (first) canOpen() a following canGetBaudrate() will return your configured baud rate. Version 2.2.10, 2017/08 - Now request a sample point of 87.5% when sending a set bit rate request to the SocketCAN layer (e.g. in canSetBaudrate()). This brings the sample point of some bit rates closer (or making it equal) to the CiA recommended sample point of 87.5%. Before, with the unspecified sample point, the Linux bit rate calculation code preferred sometimes other sample points (e.g. 75% for CAN-USB2 @1MBit). Version 2.3.0, 2017/09 - Switch to use recvmsg() internally instead of read(). This had to be done to be able to mark own sent frames properly with NTCAN_MODE_LOCAL_ECHO enabled. Therefore NTCAN_MODE_MARK_INTERACTION can be supported, too. This change gives also direct access to the SocketCAN time stamps without using an additional ioctl() call. - Fixed the CMSG->len to return the SocketCAN DLC value also for RTR frames instead of a fixed value of NTCAN_RTR (0x10). This seemed to be workaround for a buggy CAN-USB2 Socket-CAN driver (esd_usb2.ko) that returns always a length of 0x08 on Socket-CAN level for RTR frames. - Some internal source code cleanup. Version 2.3.1, 2017/09 - Fixed time stamp support that broke by the switch to use recvmsg(). - Completed the evaluation of per socket dropped frames. This way now the "msg_lost" member of CMSG* is supported. But it is not behaving completely the same because the SocketCAN layer reports dropped frames later than an esdcan CAN driver. - Switched the installation scheme of the NTCAN library to fit to the installation scheme for the NTCAN library delivered by an esdcan driver. Version 2.3.1, 2020/06 - No functional change intended regarding to the last release. - Don't provide an iproute2 source archive any more because the iproute package is standard on most distributions today. Therefore we don't try to build and install an iproute2 package during installation any more.