5 minute read

v2.2.0 has just been released. This is a major release containing several new features and a few minor API changes (see below).

DCF tools

Two DCF tools have been added: an EDS/DCF checker and a (master) DCF generator. The tools are available in the python3-dcf-tools Debian package. Documentation for the tools can be found here.

EDS/DCF checker

dcfchk can be used to check an EDS or DCF for errors. It may be useful for checking the validity of a vendor-supplied EDS as well as the DCF generated by dcfgen (see below). Note that although many common errors are checked, the checks are not complete. A successful run of dcfchk is therefore not a guarantee that the file is entirely correct.

In addition to checking for errors, dcfchk can extract and print the PDO mappings of valid RPDOs and TPDOs in more readable format than the EDS/DCF itself.

DCF generator

dcfgen can be used to generate the DCF of a CANopen master from a YAML configuration file and the EDS files of the slaves. This is generally much easier and less error-prone than writing a DCF by hand. Especially in network configurations with multiple instances of the same slave device, where the slave configuration can be easily replicated by using YAML anchors. dcfgen can also generate the remote PDO mappings used by the C++ CANopen application library.

In addition to the text DCF of the master, dcfgen generates binary files (in the concise-DCF format) for each slave containing SDO requests to be executed by the master during the boot process of the slave (right before the OnConfig() method is called). This allows the user to configure, for example, heartbeat production and consumption or PDO mappings and communication parameters of a slave without having to write a single line of code. Custom SDO requests are also supported.

Asynchronous C++ LSS API

An asynchronous C++ API is now available for issuing LSS requests from a master or handling them in a slave. Similar to SDO requests, this API allows the user to queue multiple requests and receive a future which becomes ready once the request completes.

All LSS master requests can be submitted to an LssMaster instance. Because the LSS state machine is nearly but not entirely independent of the NMT state machine, LssMaster needs access to a Node instance corresponding to an NMT master. The virtual OnStart() method is invoked during the NMT startup process of the master at the point where LSS configuration may be needed (before the NMT Reset communication command is sent). Like the OnConfig() method of a driver, the startup process is paused until the user indicates that the LSS configuration is complete.

To handle LSS requests in slaves, the Node class has two new virtual methods:

  • OnSwitchBitrate(): this method is invoked when a node is requested to activate a new bit rate. The node is required to suspend all CAN bus I/O for a specified time to prevent CAN bus errors if not all nodes change the bit rate at the exact same time.
  • OnStore(): this method is invoked when a node is requested to store the pending node-ID and bit rate to non-volatile memory. This is necessary to ensure those parameters survive a reboot.

Logical device drivers

CANopen supports up to eight logical devices per physical device, and each logical device can implement a different device profile (such as 401 for I/O modules and 402 for drives and motion control), even though they all share the same node-ID. Generic reusable drivers for a device profile should therefore target a logical device instead of a physical device.

To this end, a BasicLogicalDriver base class has been added. Instances can be registered with a BasicDriver in the same way a driver can be registered with a master. The BasicLogicalDriver class has a template parameter corresponding to the type of the driver with which is it registered. This allows logical drivers to use, for example, the Wait() function of their corresponding LoopDriver or FiberDriver.

By default, all CANopen events for a driver are forwarded to the callbacks of all registered logical drivers. The exception is OnRpdoWrite(). If an object is received via RPDO that originates from the device profile section in the object dictionary of a slave, the event is forwarded only to the corresponding logical driver.

Other

  • A new suite of unit tests is under development with the aim of achieving 100% code coverage of the C implementation of the CANopen stack and its dependencies. The test suite is based on the CppUTest framework and the first tests have been added to the unit-tests directory.
  • Access functions are now available to get/set the UploadFile/DownloadFile attributes of sub-objects in the object dictionary.
  • An inhibit time has been added to the LSS master service, to support slaves that cannot handle multiple LSS CAN frames at once. The default inhibit time is 1 ms. It can be changed at both compile and runtime.
  • Timer wait operations can now be submitted to a coapp::Node instance (and by extension, coapp::BasicMaster and coapp::BasicSlave) as well as to drives. Wait operations are handled by the same timer queue that is used for CANopen timeouts. LoopDriver and FiberDriver have a pseudo-blocking USleep() method similar to UNIX usleep().
  • coapp::BasicMaster now has an overload of the AsyncDeconfig() method that deconfigures all drivers simultaneously.
  • A fiber mutex and condition variable implementation has been added for use with the fiber executor. The semantics are similar to regular mutexes and condition variables, except that the running fiber task is suspended instead of the running thread. The C API in <lely/ev/fiber_exec.h> mimics that of the C11 mtx_t and cnd_t, while the C++ API in <lely/ev/fiber_exec.hpp> mimics the C++11 std::mutex and std::condition_variable.
  • C++ CANopen nodes allow explicit specification of the executor used for asynchronous tasks.
  • Non-throwing versions of the io::CanController methods have been added.

Bugs

The following bug has been fixed:

  • Trying to cancel an already completed (or not yet submitted) SDO request would abort the ongoing request.

API changes

  • coapp::IoContext has been moved to io::CanNet and is now based on a C implementation (io_can_net_t).
  • LoopDriver and FiberDriver now explicitly require AsyncMaster, instead of BasicMaster.

Download

You can download the source from GitLab or the Ubuntu packages from our PPA.

Categories:

Updated: