The open source community doesn't offer much for automotive software
development and even CAN network database parsers and related tools are
barely offered - although CAN communication is a well-established
technology for decades now. One of the few other available packages is
cantools, found at SourceForge (see https://sourceforge.net/projects/cantools/),
too. What are the differences and similarities between cantools and
comFramework's code generator?
Most evidently, the scope of cantools is a bit different; they provide
access to the data exchange formats of several commercial tools, which are
typically used in the automotive environment and this is not an aim of
comFramework. Directly comparable are the facilities of both packages to
access the information in a CAN network database file (*.dbc file) and
to apply this information to de/encoding of raw binary data exchanged on
the lower network protocol layers into/from information meaningful to the
application level code. As their core competence, both provide mechanisms
to compose outbound frames from application provided signals and to
decompose received frames into application usable signals. These
operations are often referred to as pack and unpack functions.
As a major difference, cantools consider the *.dbc parse tree as a
result returned to the user and they offer a set of API functions, which
operate on this tree. The implementation of these API functions is given,
they form a kind of library, which is integrated into the target code. The
API offers the pack/unpack functionality to the user.
In contrast to this, our code generator has the parse tree only as
internal, intermediate results and it evaluates it such, that it generates
suitable pack/unpack functions as C source code. This source code is
integrated into the target code as the API functions of cantools are,
but they don't form a library; they are specific to the given, parsed
network database.
The cantools approach is the conventional design pattern for software
running on a general purpose operating system like Windows, Linux,
Mac OS, etc. A large data structure is built at runtime, which all other
functions operate on. Building the data structure is based on dynamic
memory allocation; each parsed item will become a further little chunk of
heap memory. The design is well suited for these machine, which typically
have a strong focus on interaction with a human. In particular, this
design is essential if we consider an application, which starts its
operation with offering a human machine interface, enabling the user to
select the database file to work with.
However, the embedded world typically behaves differently. Despite of the
incredible decrease of memory costs over the years is RAM still an
expensive and limited resource for embedded computers and there's no
background storage for virtualizing the memory space. Even more important,
the statistical perception of failures and failure handling, which is
appropriate for interactive computers - for improbable errors they may
raise an error message and leave the decision how to proceed to the user -
is unacceptable for most embedded system, which simply must operate under
all circumstances. Therefore, these systems usually forbid the use of
dynamically built data structures, i.e. data structures constructed at
runtime and using heap technologies. Which does not mean that these
systems don't use complex, nested data structures - but they are
constructed at compile time from accordingly complex structured
configuration data. This is what our code generator does. It uses the
*.dbc files plus the StringTemplate V4 templates as configuration data
and prepares everything for the compilation - no chance for configuration
changes after compilation any more.
A cantools application is by principle able to switch to another network
database during operation but a comFramework Code Generator application by
principle isn't.
A cantools application by principle needs a heap and dynamic memory
allocation, whereas a comFramework Code Generator application uses static
memory allocation and has a fixed, guaranteed upper bounds for the memory
consumption.
While the pack/unpack functions have been mainly mentioned here the same
considerations hold for other functionality, e.g. the use and evaluation
of attributes.
A unique characteristic of our code generator is its flexibility and
customizability, which results from the use of application owned
templates. Completely differently designed target code can be got just by
configuration change but without the need for any modification of the
tool. There's even no restriction to the target language C.
As a rule of thumb we can summarize:
Regardless, if you like cantools more than our code generator then you
can still use it on embedded targets. You will have to write a small
application, which runs the cantools parser and renders the returned
parse tree as a const C object. All information in the parse tree is
represented as the constant initializer expression assigned to this
object. Which basically means to implement a tree traversal with text
output. The cantools API functions are integrated into the target code
and operate on this constant data object.