CANopenNode

The CANopenNode track in Zephy is currently outdated to the latest version of CANopenNode, and the CANopenEditor does not support this legacy version of CANopenNode (it has a legacy exporter, but the generated code lacks some type definitions that it can’t compile).

But CAN open is not that really open as a lot of the specifications are not free. For now I need CiA 302.

However, since the current version of CANopenNode in Zephyr is still operational and provides the necessary features, it’s too good to not use it. Here are some notes for using CANopenNode in Zephyr:

CAN Reception

callbacks

CAN bus driver in Zephyr uses hardware filters to filter out messages, and only messages that pass the filter will be received by the application using callback functions from an interrupt context [1]. Since callbacks are called from ISR, caution must be taken when setting callbacks related to CAN bus reception in CANopenNode. For example, CO_EM_initCallbackRx() and CO_NMT_initCallback() both execute in the ISR context, please investigate the source code to see what context the callback is executed.

Filters

Filters are added using CO_CANrxBufferInit() defined in CO_driver.c. The following is a list of filters added by CANopenNode:

  • CO_EM_init() in CO_Emergency.c

  • CO_HBcons_monitoredNodeConfig() in CO_HBconsumer.c, one for each monitored node

  • CO_LSSmaster_init() in CO_LSSmaster.c number not investigated

  • CO_LSSslave_init() in CO_LSSslave.c number not investigated

  • CO_NMT_init() in CO_NMT_Heartbeat.c

  • CO_RPDO_init() in CO_PDO.c, called once for each RPDO by CO_CANopenInitPDO() in CANopen.c

  • CO_SDO_init() in CO_SDO.c

  • CO_SDOclient_setup() in CO_SDOmaster.c, one for each SDO client

  • CO_SYNC_init() in CO_SYNC.c

  • CO_TIME_init() in CO_TIME.c

Note

Since STM32 only supports up to 28 standard ID filters, caution must be taken when configuring CANopenNode.

Service Data Object (SDO)

Each object dictionary (OD) entry can add additional functionalities by registering a callback function using CO_OD_configure(). And, CANopenNode already registered some common OD entries to provide functionalities according to the CiA 301 standard. The following is a list of registered ODs:

  • 0x1003: Pre-defined error field

  • 0x1005: COB-ID SYNC message

  • 0x1006: Communication cycle period

  • 0x1010: Store parameters

  • 0x1011: Restore default parameters

  • 0x1014: COB-ID EMCY

  • 0x1016: Consumer heartbeat time

  • 0x1019: Synchronous counter overflow value

  • 0x1200: SDO server parameter

  • 0x1400 to 0x15FF: RPDO communication parameter

  • 0x1600 to 0x17FF: RPDO mapping parameter

  • 0x1800 to 0x19FF TPDO communication parameter

  • 0x1A00 to 0x1BFF TPDO mapping parameter

Error Handling

Error status bits

CANopenNode uses an optional OD entry Error status bits of type OCTET_STRING and length more than 12 to store error status. You are responsible for setting it in OD and register it to CANopenNode using CO_EM_init(). The first 6 bytes (and hence the minimum length of 12 of the octet string) is used internally by CANopenNode to store error status, and the rest 26 bytes can be used for manaufacturer specific errors. The definitions of the error status bits can be found in CO_EM_errorStatusBits_t.

Note

The length of Error status bits must grow coorespondingly to the number of manufacturer specific errors.

Error register

CANopenNode also helps mamnge generic, communication and manufacturer-specific bits of Error register at OD 0x1001 [2]. It sets communication bits when internal communication error occurs, and manufacturer-specific bits when any of the manaufacturer specific errors in Error status bits are set. However, it only set generic bit when CO_EM_errorStatusBits_t between 0x28 to 0x2F are set, which does NOT adhere to the standard stating that: “The generic error shall be signaled at any error situation [3].”

EMCY write

In CANopen standard the EMCY write payload has the following format [4]:

  0        1          2         3                              7
+------------+----------------+----------------------------------+
| error code | error register | manufacturer-specific error code |
+------------+----------------+----------------------------------+

CANopenNode uses the first byte of manaufacturer-specific error code to transmit its Error status bits, so the payload becomes:

  0        1         2                  3           4                              7
+------------+----------------+------------------------------------------------------+
| error code | error register | error status bits | manufacturer-specific error code |
+------------+----------------+------------------------------------------------------+

CANopenNode also recognizes the first byte of manaufacturer-specific error code as Error status bits when receiving EMCY messages from other nodes. The callback for receiving EMCY registered using CO_EM_initCallbackRx() has the prototype:

void pFunctSignalRx(const uint16_t ident,
                    const uint16_t errorCode,
                    const uint8_t errorRegister,
                    const uint8_t errorBit,
                    const uint32_t infoCode);

Where errorBit is for Error status bits (and infoCode for the rest of the manufacturer-specific error code).

Pre-defined error fields

CANopenNode also helps to maintain Pre-defined error fields at OD 0x1003 for recording errors that happened [5]. Once an error is reported using CO_errorReport(), it will be recorded to Pre-defined error fields in the following format:

32     24               16           0
+------+----------------+------------+
| 0x00 | error register | error code |
+------+----------------+------------+
MSB                                LSB

where error code is one of the standard error codes defined in CiA 301.

EMCY reception

CANopenNode will receive all EMCY messages from the bus [6] and call the callback registered using CO_EM_initCallbackRx(). It does not provide support for Emergency consumer object at OD 0x1014.

Reference