I am considering using CANopenNode to create a full SIIS2 stack, but before I jump into someone elses work I like to think through how and why I want CANopen build. Below is a simple UML diagram.
This diagram lack Bootloader and Object Dictionary, but I simply created classes for each bulk of work that needs to be done.
CANbus. I need a driver outside the stack. This will integrate to various HW as well as adapters for Windows etc.
CANopen. We definitely need a CANopen with all main interface functions. A simple class to be used to create a stack and then add CANModules to this as needed. We can createa a CANopenSlave and CANopenMaster, but also provide a custom implementation.
The rest of the CANopen stack is easily divided into groups of work using CANModule as base. CANModule can carry common functions while each of the SDO, PDO, LSS, NMT etc carry their respective messages with Processing, Encoding and Decoding. Some of the blocks like SDO, PDO, LSS and NMT should be sub-classed because Client/Server, Producer/Consumer, Master/Slave have different implementations of the same messages. So can EMCY, SYNC and Time, but as these are smaller I am not sure I bother.
Creating a C++ layer like this also allows for the user to sub-class and easily modify the stack without changing the base code or dealing with nasty #ifdef code.
Heartbeat is actually part of NMT with separate schemes for Master and Slave.
This is how I would like to divide code up in C++ and if you look at CANopenNode you notice that these building blocks more or less exist in C code – this was accidentally.
CANopen Bootloader will need to be created from scratch.
Object Dictionary will need to be re-done. The onle used in CANopenNode is not sufficient for what I want to do.
That said – I am not convinced I will jum onto this train – just toying with the idea for now. Wherever I write my own from scratch or use CANopenNode is of no consequence as I can easily write a C++ wrapper on top of CANopenNode.