New release: v2.2.0
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
andcoapp::BasicSlave
) as well as to drives. Wait operations are handled by the same timer queue that is used for CANopen timeouts.LoopDriver
andFiberDriver
have a pseudo-blockingUSleep()
method similar to UNIXusleep()
. coapp::BasicMaster
now has an overload of theAsyncDeconfig()
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 C11mtx_t
andcnd_t
, while the C++ API in<lely/ev/fiber_exec.hpp>
mimics the C++11std::mutex
andstd::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 toio::CanNet
and is now based on a C implementation (io_can_net_t
).LoopDriver
andFiberDriver
now explicitly requireAsyncMaster
, instead ofBasicMaster
.
Download
You can download the source from GitLab or the Ubuntu packages from our PPA.