Skip to content

CANopen Node#

The node component is the central component and includes all other components for a single CANopen node. The node component provides the interface to the node lifecycle operations.

Module Context#

classDiagram
  CO_DICT *-- CO_NODE : Dict
  CO_IF   *-- CO_NODE : If
  CO_EMCY *-- CO_NODE : Emcy
  CO_TMR  *-- CO_NODE : Tmr
  CO_NMT  *-- CO_NODE : Nmt
  CO_SDO  *-- CO_NODE : Sdo
  CO_LSS  *-- CO_NODE : Lss
  CO_ERR   -- CO_NODE : Error
  CO_NODE *-- CO_RPDO : RPdo
  CO_NODE *-- CO_TPDO : TPdo
  CO_NODE *-- CO_TPDO_LINK : TMap
  CO_NODE *-- CO_SYNC : Sync
  CO_NODE  -- CO_NODE_SPEC
  CO_NODE  -- CO_NMT_RESET
  class CO_NODE {
    -uint8_t SdoBuf
    -uint32_t Baudrate
    -uint8_t NodeId
    +CONodeGetErr() CO_ERR
    +CONodeInit(spec)
    +CONodeParaLoad(type) int16_t
    +CONodeProcess()
    +CONodeStart()
    +CONodeStop()
  }
  class CO_ERR {
    <<enumeration>>
  }
  class CO_NMT_RESET {
    <<enumeration>>
  }

Structure Data#

The class CO_NODE is defined within co_core.h and is responsible for the overall node management functions. The node is the central data point of a CANopen device. The following data members are in this class:

Data Member Type Description
Baudrate uint32_t default CAN communication baudrate
Dict CO_DICT object dictionary object
Emcy CO_EMCY node emergency object
Error CO_ERR Internal error indentification code
If CO_IF CAN bus interface object
Lss CO_LSS LSS management object
Nmt CO_NMT node network management object
NodeId uint8_t default CANopen node ID
Sdo CO_SDO SDO server object array
SdoBuf uint8_t* pointer to SDO transfer buffer
Tmr CO_TMR timer manager object
TPdo[] CO_TPDO transmit PDO object array
TMap[] CO_TPDO_LINK transmit PDO mapping link array
RPdo[] CO_RPDO receive PDO object array
Sync CO_SYNC SYNC management object

Info

The data within this structure must never be manipulated without the corresponding class member functions. This can lead to unpredictable behavior of the node.

Member Functions#

During calling a member function of a class, the first parameter must be a reference to a corresponding object. This should be done as shown in the following examples:

CO_NODE AppNode;                   /* allocate application node    */
  :
CONodeInit (&AppNode       ,...);  /* call member of class CO_NODE */
CODirFind  (&(AppNode.Dir) ,...);  /* call member of class CO_DIR  */
COIfCanSend(&(AppNode.If)  ,...);  /* call member of class CO_IF   */
COEmcySet  (&(AppNode.Emcy),...);  /* call member of class CO_EMCY */
COTmrCreate(&(AppNode.Tmr) ,...);  /* call member of class CO_TMR  */
CONmtReset (&(AppNode.Nmt) ,...);  /* call member of class CO_NMT  */
  :

Note, that in all application source files, which needs to call one or more CANopen API functions, the header file co_core.h must be included.

The following table describes the API functions of the CANopen core module. These functions are implemented within the source file: co_core.c/h

CONodeGetErr()#

If an error was detected, the error is cleared with this function call.

Prototype

CO_ERR CONodeGetErr(CO_NODE *node);

Arguments

Parameter Description
node pointer to node object

Returned Value

One of the following error codes:

Error code Description
CO_ERR_NONE no error
CO_ERR_BAD_ARG invalid argument
CO_ERR_OBJ_NOT_FOUND searched object not found in directory
CO_ERR_OBJ_READ error during reading an object entry
CO_ERR_OBJ_WRITE error during writing an object entry
CO_ERR_OBJ_SIZE read/write with a wrong size to object
CO_ERR_OBJ_MAP_LEN invalid mapping length
CO_ERR_OBJ_MAP_TYPE invalid mapping type
CO_ERR_OBJ_ACC unsupported access
CO_ERR_OBJ_RANGE value range of parameter exceeded
CO_ERR_OBJ_INCOMPATIBLE incompatible parameter value
CO_ERR_PARA_IDX wrong index for parameter type
CO_ERR_PARA_STORE error during storing parameter
CO_ERR_PARA_RESTORE error during restoring parameter
CO_ERR_PARA_LOAD error during loading parameter
CO_ERR_CFG_1001_0 entry 1001:0 is bad/not existing
CO_ERR_CFG_1003_0 entry 1003:0 is bad/not existing
CO_ERR_CFG_1003_1 entry 1003:1 is bad/not existing
CO_ERR_CFG_1005_0 entry 1005:0 is bad/not existing
CO_ERR_CFG_1010_0 entry 1010:0 is bad/not existing
CO_ERR_CFG_1011_0 entry 1011:0 is bad/not existing
CO_ERR_CFG_1014_0 entry 1014:0 is bad/not existing
CO_ERR_CFG_1016 entry in 1016 is bad/not existing
CO_ERR_CFG_1017_0 entry 1017:0 is bad/not existing
CO_ERR_CFG_1018 entry in 1018 is bad/not existing
CO_ERR_TMR_NO_ACT no action available while creating
CO_ERR_TMR_INSERT error during insert action in tmr-list
CO_ERR_TMR_CREATE error during creating a timed action
CO_ERR_TMR_DELETE error during deleting a timed action
CO_ERR_NMT_INIT error during initializing NMT slave
CO_ERR_NMT_APP_RESET error in resetting application
CO_ERR_NMT_COM_RESET error in resetting communication
CO_ERR_NMT_MODE action not allowed in current NMT mode
CO_ERR_LSS_LOAD error during loading the LSS configuration
CO_ERR_LSS_STORE error during writing the LSS configuration
CO_ERR_EMCY_BAD_ROOT error in emcy structure, member: Root
CO_ERR_TPDO_COM_OBJ config error in TPDO communication
CO_ERR_TPDO_MAP_OBJ config error in TPDO mapping
CO_ERR_TPDO_OBJ_TRIGGER error during trigger via an object
CO_ERR_TPDO_NUM_TRIGGER error during trigger via a PDO number
CO_ERR_TPDO_INHIBIT error during inhibit timer creation
CO_ERR_TPDO_EVENT error during event timer creation
CO_ERR_RPDO_COM_OBJ config error in RPDO communication
CO_ERR_RPDO_MAP_OBJ config error in RPDO mapping
CO_ERR_SDO_READ error during in SDO block reading
CO_ERR_SDO_WRITE error during in SDO block writing
CO_ERR_SYNC_MSG error during receive synchronous PDO
CO_ERR_IF_INIT error during initialization
CO_ERR_IF_ENABLE error during enabling the interface
CO_ERR_IF_FLUSH_RX error during flushing RX interface
CO_ERR_IF_FLUSH_TX error during flushing TX interface
CO_ERR_IF_RESET error during resetting interface
CO_ERR_IF_CLOSE error during closing the interface
CO_ERR_IF_READ error during reading from interface
CO_ERR_IF_SEND error during sending to interface
CO_ERR_SIG_INIT error during initializing CAN signals
CO_ERR_SIG_CREATE error during creating a needed signal
CO_ERR_MSG_INIT error during message initialization
CO_ERR_MSG_CREATE error during creating a message
CO_ERR_MSG_READ error during reading a message
CO_ERR_TYPE_RD error during reading type
CO_ERR_TYPE_CTRL error during type control
CO_ERR_TYPE_WR error during writing type

Example

The following example demonstrates a diagnostic section of a CANopen startup sequence:

  :
CONodeInit(&AppNode, (CO_NODE_SPEC *)&AppSpec);

err = CONodeGetErr(&AppNode);
if (err == CO_ERR_NONE) {
  CONodeStart(&AppNode);
} else {

  /* handle detected error according to your application */

}
  :

CONodeInit()#

The specification of the CANopen node, and the CANopen node object itself is given as a parameter.

Prototype

void CONodeInit(CO_NODE *node, CO_NODE_SPEC *spec);

Arguments

Parameter Description
node pointer to node object
spec pointer to node specification object

Returned Value

  • none

Example

The following example shows the external reference to the node specification AppSpec which is typically allocated within a configuration file and the allocation of the CANopen node memory AppNode.

extern const CO_NODE_SPEC AppSpec;
             CO_NODE      AppNode;

With these objects, the CANopen node can be initialized and started:

  :
CONodeInit(&AppNode, (CO_NODE_SPEC *)&AppSpec);
  :

CONodeParaLoad()#

A single parameter group will be loaded from NVM by calling the nvm driver function for reading data.

This function considers all parameter groups, which are linked to the parameter store index (1010h) within the object dictionary. Every not linked parameter group is not the scope of this function and must be handled within the application.

Prototype

int16_t CONodeParaLoad(CO_NODE *node, CO_NMT_RESET type);

Arguments

Parameter Description
node pointer to node object
type reset type, e.g. CO_RESET_COM or CO_RESET_NODE

Returned Value

  • =0 : loading successful
  • <0 : an error is detected and function aborted

Example

The function CONodeParaLoad() is rarely called from within the applications. Typically the CANopen master requests the parameter loading via NMT command. In some special cases it is useful to initiate a reset from the slave application. The following example shows the sequence to load all parameters, which are linked to the object directory entries related to the communication profile (index 1000h to 1FFFh).

  :
success = CONodeParaLoad(&AppNode, CO_RESET_COM);
if (success < 0) {
  err = CONodeGetErr(&AppNode);

  /* handle error during parameter loading */

}
  :

CONodeProcess()#

This function is responsible for performing the necessary response to a received CAN frame.

Prototype

void CONodeProcess(CO_NODE *node);

Arguments

Parameter Description
node pointer to node object

Returned Value

  • none

Example

The function CONodeProcess() is most likely called in the background function loop. When using an RTOS, the CANopen node processing from within a separate task is possible, too. In this case, the blocking mode is suitable for most applications:

void CanRxTask(void *arg_p)
{
  CO_NODE *node = (CO_NODE *)arg_p;   /* task parameter is a ptr to   */
                                      /* CANopen node object          */

  while(1) {                          /* endless RTOS task loop       */
    CONodeProcess(node);              /* wait and process CAN frames  */
  }
}

CONodeStart()#

The node will change into the PRE-OPERATIONAL state and is ready for communication.

Prototype

void CONodeStart(CO_NODE *node);

Arguments

Parameter Description
node pointer to node object

Returned Value

  • none

Example

The following example shows the typical startup of a CANopen node AppNode with the specification AppSpec:

CO_ERR err;
  :
CONodeInit(&AppNode, (CO_NODE_SPEC *)&AppSpec);

err = CONodeGetErr(&AppNode);
if (err == CO_ERR_NONE) {
  CONodeStart(&AppNode);
} else {

  /* error handling and diagnostics */

}
  :

CONodeStop()#

This function removes the CANopen node from the CAN bus interface.

To reactivate a stopped CANopen node, the functions CONodeInit() and CONodeStart() must be called again.

Prototype

void CONodeStop(CO_NODE *node);

Arguments

Parameter Description
node pointer to node object

Returned Value

  • none

Example

The following example shows the sequence for restarting a CANopen node AppNode. Assuming the CANopen stack is initialized and started before, we can stop and re-initialize the stack to reset the node completely.

  :
CONodeStop(&AppNode);
  :
/* do something with stopped CANopen node */
  :
CONodeInit(&AppNode, (CO_NODE_SPEC *)&AppSpec);

err = CONodeGetErr(&AppNode);
if (err == CO_ERR_NONE) {
  CONodeStart(&AppNode);
} else {

  /* error handling and diagnostics */

}
  :

Attention

The shown example is NOT identical to the standard node reset which can be requested from the CANopen master or via the API function CONmtReset(). The difference is: the example will transmit the boot-up message.