Skip to content

Controlling the Node#

CANopen Node#

The CANopen network is organized in a mix of master/slave and producer/consumer communication architecture. One single CANopen device (a master or a slave) is represented within the software with a data structure, called node. This structure is the central entry point of the application into the specific CANopen node.

The following source line is essential to create a new instance of the node:

CO_NODE demo;   /* create the node instance 'demo' */

The service functions starting with CONode…() are provided for initializing and controlling the node-specific aspects. These service functions are requesting the corresponding node pointer as the first argument.

For example reading the internal error state of the CANopen Node:

err = CONodeGetErr(&demo); /* get error state of node 'demo'  */

The same naming convention is realized with several modules. The following table shows the names of the provided modules and their corresponding arguments:

Service Group Argument Example
CODir…() &demo.Dir CODirFind(&demo.Dir, CO_DEV(0x1234,0x56));
COEmcy…() &demo.Emcy COEmcyCnt(&demo.Emcy);
COIf…() &demo.If COIfCanSend(&demo.If, &frm);
CONmt…() &demo.Nmt CONmtGetMode(&demo.Nmt);
CONode…() &demo CONodeGetErr(&demo);
COTmr…() &demo.Tmr COTmrCreate(&demo.Tmr, 0, 10, MyFunc, 0);
COTPdo…() &demo.TPdo COTPdoTrigPdo(&demo.TPdo, 1);

Node Start#

The start of a node needs to have some additional information about memory allocation, the object directory, and more. This information is collected to a single structure, called node specification.

The following source lines show a typical node specification:

const CO_NODE_SPEC DemoSpec = {
  (uint8_t      ) 0x01,              /* pre-defined Node-ID            */
  (uint32_t     ) Baudrate,          /* default baudrate               */
  (CO_OBJ      *)&AppObjDir,         /* start of object directory      */
  (uint16_t     ) APP_OBJ_N,         /* number of objects in directory */
  (CO_EMCY_TBL *)&AppEmcyCode,       /* start of emergency code table  */
  (CO_TMR_MEM  *)&AppTmrMem,         /* start of timer manager memory  */
  (uint16_t     ) APP_TMR_N,         /* max. number of timers/actions  */
  (uint32_t     ) APP_TICKS_PER_SEC, /* timer clock frequency in Hz    */
  (CO_IF_DRV    )&AppDrv,            /* hardware interface drivers     */
  (uint8_t     *)&AppSdoBuf          /* start of SDO transfer buffer   */
};

The service function CONodeInit() initializes the given node with the data and memory of the given node specification:

CONodeInit (&demo, (CO_NODE_SPEC *)&DemoSpec);

The internal behavior of the CANopen stack is shown in the following diagram:

sequenceDiagram
  participant A as Application
  participant S as demo
  participant N as demo.Nmt
  Note over S,N: NMT State = CO_INVALID
  A->>+S: CONodeInit()
  S->>+N: initialize NMT
  N-->>-S: ok
  S-->>-A: ok
  Note over S,N: NMT State = CO_INIT
  A->>+S: CONodeStart()
  S->>+N: NMT bootup
  N-->>-S: ok
  S-->>-A: ok
  Note over S,N: NMT State = CO_PREOP

The CANopen network state machine state is still in CO_INIT after the node initialization, because there may be several additional actions necessary before setting the node in the pre-operational state. With the second function call CONodeStart() the bootup message is sent and the node is in pre-operational mode. The node is now able to perform network communications.

Node Processing#

For processing a single CANopen network message, the CANopen stack provides a service function. The following line processes the latest received CAN message:

CONodeProcess(&demo);

The internal behavior of the CANopen stack is shown in the following diagram:

sequenceDiagram
  participant A as Application
  participant S as demo
  participant I as demo.If
  A->>+S: CONodeProcess()
  S->>+I: get received CAN frame
  I-->>-S: CAN frame
  S-->>-A: ok

Node Stop#

Stopping a node is typically performed by the CAN network with autonomous requests. Nevertheless, the CANopen stack provides a service function to switch the NMT modes by the application. The following line switches the node into the NMT mode CO_STOP.

CONmtSetMode(&demo.Nmt, CO_STOP);

The internal behavior of the CANopen stack is shown in the following diagram:

sequenceDiagram
  participant A as Application
  participant S as demo
  participant N as demo.Nmt
  Note over S,N: NMT State = <any>
  A->>+N: CONmtSetMode()
  N-->>-A: ok
  Note over S,N: NMT State = CO_STOP

Note: After this activity, the interface and all resources are still locked and must not be used by other components.

Node Reset#

Resetting a node is typically performed by the CANopen master via NMT protocol messages. This is done by the CANopen stack without any necessary actions by the application.

The CANopen stack provides a service function to reset the node by the application. The following line initiates the reset of the node.

CONmtReset(&demo.Nmt, CO_RESET_NODE);

There are two different kinds of resets possible: - Reset Communication and Application (this is called "Reset Node") - Reset Communication

The internal behavior of the CANopen stack is shown in the following diagram:

sequenceDiagram
  participant A as Application
  participant N as demo.Nmt
  participant S as demo
  participant I as demo.If
  Note over N: NMT State = <any>
  A->>+N: CONmtReset()
  Note over N: NMT State = CO_INIT
  opt application reset
  N->>+S: load parameters in [2000h to 9FFFh]
  S-->>-N: ok
  end
  N->>+S: load parameters in [1000h to 1FFFh]
  S-->>-N: ok
  N->>+I: COIfCanReset()
  I-->>-N: ok
  N-->>-A: ok

Node Shutdown#

Shutting down a node is typically not used by real embedded CANopen applications. This function is provided to delete all dynamically created objects and free the used memory areas.

CONodeStop(&demo);

The internal behavior of the CANopen stack is shown in the following diagram:

sequenceDiagram
  participant A as Application
  participant S as demo
  participant N as demo.Nmt
  Note over S,N: NMT State = <any>
  A->>+S: CONodeStop()
  S->>+N: CONmtSetMode()
  N-->>-S: ok
  S-->>-A: ok
  Note over S,N: NMT State = CO_STOP

Note: After this activity, the interface and all resources are free to use by other components.