Xyntos | Logo

Overview  |  Quick Start  |  Samples  |  Architecture  |  CoSlave  |  CoMaster  |  Listeners  |  Object Dictionary  |  Configuration  |  Eds2Od


CANoopEn – CANopen Stack C++/OOP

CANoopEn is a CANopen protocol stack written in clean, object-oriented C++17 — designed for portability, testability and readability. The stack is completely target-independent and runs on any hardware architecture; ready-to-build samples are currently available for STM32 (bare-metal and FreeRTOS), with more platforms to follow. CANoopEn is developed and maintained by Xyntos GmbH.

Source code on GitHub

The complete project is available on GitHub under the Apache License 2.0:

Repository Content
CANoopEn The stack — clone it or add it as a git submodule to your project
CANoopEnDemo Ready-to-build sample projects (bare-metal and FreeRTOS, CiA 401 and CiA 417)
CANoopEnTest The unit test suite, running on every commit
CANoopEnTools Eds2Od, the object dictionary generator — download

Why CANoopEn?

  • Modern C++ instead of C macros — the stack is a set of small classes with clear responsibilities. Your device is a class that derives from CoSlave or CoMaster; the object dictionary is a class with typed entry objects; callbacks are virtual methods on listener interfaces.
  • Hardware-agnostic by design — the stack never touches hardware. It talks to your CAN driver through a single method (SendCanMessage) and receives messages and time through two Proceed calls. Porting means implementing three small interfaces.
  • No dynamic memory allocation — all buffers and tables are statically sized at compile time via CoSettings. Object dictionary entries are plain member objects owned by your application.
  • Object dictionary generated from your EDS — the bundled Eds2Od tool turns a standard CANopen EDS file into your object dictionary class. You maintain only the EDS file (for example with free graphical editors such as Vector’s CANeds), regenerate, and access the dictionary from your application in a fully type-safe way — no void*, no casts (details).
  • Scales down — every service can be compiled out via CoConfiguration feature switches (-DCO_ENABLE_LSS=0, …) to fit small flash budgets.
  • Tested — a comprehensive Google Test unit test suite runs on every commit via GitHub Actions.
  • Open source — Apache License 2.0, on GitHub (all repositories).

Supported services and profiles

Area Support
NMT (CiA 301) Slave and master state machines, boot-up, start/stop/reset commands
Heartbeat Producer and consumer with timeout monitoring (objects 1016h/1017h)
SDO server Expedited, segmented and block transfer, multiple channels
SDO client Synchronous read/write of remote object dictionaries, block transfer
PDO Transmit and receive PDOs with mapping parameters, event-driven transmission
MPDO Multiplexed PDOs, source (SAM) and destination (DAM) addressing mode
SYNC / TIME / EMCY Producer and consumer, error history (object 1003h)
LSS (CiA 305) Master and slave role: node-id and bit timing configuration, identity inquiry
Indicators (CiA 303-3) Run/error LED flash patterns computed by the stack
NMT master boot-up (CiA 302-2) Demonstrated in the master samples (“boot NMT slave” process)
CiA 417 (lift application profile) Profile COB-ID mapping and virtual I/O mapping helpers

A slave in a nutshell

class MyDevice : public CANoopEn::CoSlave,
                 public CANoopEn::ICoListener,
                 public CANoopEn::ICoObjectDictionaryListener,
                 public CANoopEn::ICoSendHandlerListener
{
public:
    MyDevice() : CoSlave(*this, _objectDictionary, *this, NodeId, _cobId),
                 _objectDictionary(*this) {}

    // Your CAN driver, called by the stack for every outgoing frame
    bool SendCanMessage(const CANoopEn::CoCanMessage& msg) override;

    // Callbacks you care about (NMT state, EMCY, LEDs, OD writes, ...)
    void OnNmtStateChange(uint16_t nodeId, CANoopEn::CoNmtState state) override;
    // ...

private:
    static constexpr uint16_t NodeId = 10;
    MyDeviceOd _objectDictionary;          // derives CoObjectDictionary
    CANoopEn::CoCobIdCia301 _cobId;        // standard CiA 301 COB-IDs
};

// main loop: feed received frames and call the scheduler periodically
for (;;)
{
    if (canDriver.ReceiveCanMessage(msg))
        device.Proceed(msg);
    if (cycleTimerElapsed)                 // every CoSettings::CoCycleTime ms
        device.Proceed();
}

Getting started

The fastest way to a running CANopen node is the Quick Start Guide — from git clone to a live node on the CAN bus in about half an hour, using the low-cost ST NUCLEO-C092RC board and VS Code.

Ready-to-build sample projects (bare-metal and FreeRTOS) live in the repository CANoopEnDemo — the Samples page describes them in detail.

Documentation

  • Quick Start Guide — hardware, tools, first build, first steps on the bus
  • Samples – the sample matrix: what each sample does, buttons, leds, anatomy
  • Architecture — how the stack is structured and what your application provides
  • API reference (user-facing interface):
  • Eds2Od — the object dictionary generator: usage and downloads for Windows and Linux

License

CANoopEn is licensed under the Apache License, Version 2.0.

Professional support

CANoopEn is developed by Xyntos GmbH, a Swiss engineering company specializing in embedded software. If you need support integrating CANopen into your product — from device firmware to conformance — get in touch.

XYNTOS_Logo_mit_claim_weiss