CANopenNode

Modules

 Stack configuration
 
 Basic definitions
 Target specific basic definitions and data types according to Misra C specification.
 
 Reception of CAN messages
 Target specific definitions and description of CAN message reception.
 
 Transmission of CAN messages
 Target specific definitions and description of CAN message transmission.
 
 Critical sections
 CANopenNode is designed to run in different threads, as described in README.md. Threads are implemented differently in different systems. In microcontrollers threads are interrupts with different priorities, for example. It is necessary to protect sections, where different threads access to the same resource. In simple systems interrupts or scheduler may be temporary disabled between access to the shared resource. Otherwise mutexes or semaphores can be used.
 

Files

file  CO_config.h
 Configuration macros for CANopenNode.
 
file  CO_driver.h
 Interface between CAN hardware and CANopenNode.
 

Data Structures

struct  CO_CANmodule_t
 Complete CAN module object. More...
 

Macros

#define CO_VERSION_MAJOR   4
 Major version number of CANopenNode.
 
#define CO_VERSION_MINOR   0
 Minor version number of CANopenNode.
 
#define CO_errinfo(CANmodule, err)
 Macro for passing additional information about error. More...
 

Enumerations

enum  CO_Default_CAN_ID_t {
  CO_CAN_ID_NMT_SERVICE = 0x000, CO_CAN_ID_GFC = 0x001, CO_CAN_ID_SYNC = 0x080, CO_CAN_ID_EMERGENCY = 0x080,
  CO_CAN_ID_TIME = 0x100, CO_CAN_ID_SRDO_1 = 0x0FF, CO_CAN_ID_TPDO_1 = 0x180, CO_CAN_ID_RPDO_1 = 0x200,
  CO_CAN_ID_TPDO_2 = 0x280, CO_CAN_ID_RPDO_2 = 0x300, CO_CAN_ID_TPDO_3 = 0x380, CO_CAN_ID_RPDO_3 = 0x400,
  CO_CAN_ID_TPDO_4 = 0x480, CO_CAN_ID_RPDO_4 = 0x500, CO_CAN_ID_SDO_SRV = 0x580, CO_CAN_ID_SDO_CLI = 0x600,
  CO_CAN_ID_HEARTBEAT = 0x700, CO_CAN_ID_LSS_SLV = 0x7E4, CO_CAN_ID_LSS_MST = 0x7E5
}
 Default CANopen identifiers. More...
 
enum  CO_CAN_ERR_status_t {
  CO_CAN_ERRTX_WARNING = 0x0001, CO_CAN_ERRTX_PASSIVE = 0x0002, CO_CAN_ERRTX_BUS_OFF = 0x0004, CO_CAN_ERRTX_OVERFLOW = 0x0008,
  CO_CAN_ERRTX_PDO_LATE = 0x0080, CO_CAN_ERRRX_WARNING = 0x0100, CO_CAN_ERRRX_PASSIVE = 0x0200, CO_CAN_ERRRX_OVERFLOW = 0x0800,
  CO_CAN_ERR_WARN_PASSIVE = 0x0303
}
 CAN error status bitmasks. More...
 
enum  CO_ReturnError_t {
  CO_ERROR_NO = 0, CO_ERROR_ILLEGAL_ARGUMENT = -1, CO_ERROR_OUT_OF_MEMORY = -2, CO_ERROR_TIMEOUT = -3,
  CO_ERROR_ILLEGAL_BAUDRATE = -4, CO_ERROR_RX_OVERFLOW = -5, CO_ERROR_RX_PDO_OVERFLOW = -6, CO_ERROR_RX_MSG_LENGTH = -7,
  CO_ERROR_RX_PDO_LENGTH = -8, CO_ERROR_TX_OVERFLOW = -9, CO_ERROR_TX_PDO_WINDOW = -10, CO_ERROR_TX_UNCONFIGURED = -11,
  CO_ERROR_OD_PARAMETERS = -12, CO_ERROR_DATA_CORRUPT = -13, CO_ERROR_CRC = -14, CO_ERROR_TX_BUSY = -15,
  CO_ERROR_WRONG_NMT_STATE = -16, CO_ERROR_SYSCALL = -17, CO_ERROR_INVALID_STATE = -18, CO_ERROR_NODE_ID_UNCONFIGURED_LSS = -19
}
 Return values of some CANopen functions. More...
 

Functions

void CO_CANsetConfigurationMode (void *CANptr)
 Request CAN configuration (stopped) mode and wait until it is set. More...
 
void CO_CANsetNormalMode (CO_CANmodule_t *CANmodule)
 Request CAN normal (operational) mode and wait until it is set. More...
 
CO_ReturnError_t CO_CANmodule_init (CO_CANmodule_t *CANmodule, void *CANptr, CO_CANrx_t rxArray[], uint16_t rxSize, CO_CANtx_t txArray[], uint16_t txSize, uint16_t CANbitRate)
 Initialize CAN module object. More...
 
void CO_CANmodule_disable (CO_CANmodule_t *CANmodule)
 Switch off CANmodule. More...
 
CO_ReturnError_t CO_CANrxBufferInit (CO_CANmodule_t *CANmodule, uint16_t index, uint16_t ident, uint16_t mask, bool_t rtr, void *object, void(*CANrx_callback)(void *object, void *message))
 Configure CAN message receive buffer. More...
 
CO_CANtx_tCO_CANtxBufferInit (CO_CANmodule_t *CANmodule, uint16_t index, uint16_t ident, bool_t rtr, uint8_t noOfBytes, bool_t syncFlag)
 Configure CAN message transmit buffer. More...
 
CO_ReturnError_t CO_CANsend (CO_CANmodule_t *CANmodule, CO_CANtx_t *buffer)
 Send CAN message. More...
 
void CO_CANclearPendingSyncPDOs (CO_CANmodule_t *CANmodule)
 Clear all synchronous TPDOs from CAN module transmit buffers. More...
 
void CO_CANmodule_process (CO_CANmodule_t *CANmodule)
 Process can module - verify CAN errors. More...
 
static uint8_t CO_getUint8 (const void *buf)
 Get uint8_t value from memory buffer. More...
 
static uint16_t CO_getUint16 (const void *buf)
 Get uint16_t value from memory buffer, see CO_getUint8.
 
static uint32_t CO_getUint32 (const void *buf)
 Get uint32_t value from memory buffer, see CO_getUint8.
 
static uint8_t CO_setUint8 (void *buf, uint8_t value)
 Write uint8_t value into memory buffer. More...
 
static uint8_t CO_setUint16 (void *buf, uint16_t value)
 Write uint16_t value into memory buffer, see CO_setUint8.
 
static uint8_t CO_setUint32 (void *buf, uint32_t value)
 Write uint32_t value into memory buffer, see CO_setUint8.
 

Detailed Description

Interface between CAN hardware and CANopenNode.

CANopenNode is designed for speed and portability. It runs efficiently on devices from simple 16-bit microcontrollers to PC computers. It can run in multiple threads. Reception of CAN messages is pre-processed with very fast functions. Time critical objects, such as PDO or SYNC are processed in real-time thread and other objects are processed in normal thread. See Flowchart in README.md for more information.

CANopenNode Object

CANopenNode is implemented as a collection of different objects, for example SDO, SYNC, Emergency, PDO, NMT, Heartbeat, etc. Code is written in C language and tries to be object oriented. So each CANopenNode Object is implemented in a pair of .h/.c files. It basically contains a structure with all necessary variables and some functions which operates on it. CANopenNode Object is usually connected with one or more CAN receive or transmit Message Objects. (CAN message Object is a CAN message with specific 11-bit CAN identifier (usually one fixed or a range).)

Hardware interface of CANopenNode

It consists of minimum three files:

CO_driver_target.h and CO_driver.c files are specific for each different microcontroller and are not part of CANopenNode. There are separate projects for different microcontrollers, which usually include CANopenNode as a git submodule. CANopenNode only includes those two files in the example directory and they are basically empty. It should be possible to compile the CANopenNode/example on any system, however compiled program is not usable. CO_driver.h contains documentation for all necessary macros, types and functions.

See CANopenNode/Wiki for a known list of available implementations of CANopenNode on different systems and microcontrollers. Everybody is welcome to extend the list with a link to his own implementation.

Implementation of the hardware interface for specific microcontroller is not always an easy task. For reliable and efficient operation it is necessary to know some parts of the target microcontroller in detail (for example threads (or interrupts), CAN module, etc.).

Macro Definition Documentation

◆ CO_errinfo

#define CO_errinfo (   CANmodule,
  err 
)

Macro for passing additional information about error.

This macro is called from several CANopen init functions, which returns CO_ReturnError_t.

CO_driver_target.h may implement this macro. Usually macro only sets CANmodule->errinfo to err. Application may then use CANmodule->errinfo to determine the reason of failure. errinfo must be type of int32_t. By default macro does not record anything.

CO_errinfo is called in following CO_ReturnError_t reasons:

  • 'CO_ERROR_OD_PARAMETERS' - Index of erroneous OD parameter.

Enumeration Type Documentation

◆ CO_Default_CAN_ID_t

Default CANopen identifiers.

Default CANopen identifiers for CANopen communication objects. Same as 11-bit addresses of CAN messages. These are default identifiers and can be changed in CANopen. Especially PDO identifiers are configured in PDO linking phase of the CANopen network configuration.

Enumerator
CO_CAN_ID_NMT_SERVICE 

0x000, Network management

CO_CAN_ID_GFC 

0x001, Global fail-safe command

CO_CAN_ID_SYNC 

0x080, Synchronous message

CO_CAN_ID_EMERGENCY 

0x080, Emergency messages (+nodeID)

CO_CAN_ID_TIME 

0x100, Time message

CO_CAN_ID_SRDO_1 

0x0FF, Default SRDO1 (+2*nodeID)

CO_CAN_ID_TPDO_1 

0x180, Default TPDO1 (+nodeID)

CO_CAN_ID_RPDO_1 

0x200, Default RPDO1 (+nodeID)

CO_CAN_ID_TPDO_2 

0x280, Default TPDO2 (+nodeID)

CO_CAN_ID_RPDO_2 

0x300, Default RPDO2 (+nodeID)

CO_CAN_ID_TPDO_3 

0x380, Default TPDO3 (+nodeID)

CO_CAN_ID_RPDO_3 

0x400, Default RPDO3 (+nodeID)

CO_CAN_ID_TPDO_4 

0x480, Default TPDO4 (+nodeID)

CO_CAN_ID_RPDO_4 

0x500, Default RPDO5 (+nodeID)

CO_CAN_ID_SDO_SRV 

0x580, SDO response from server (+nodeID)

CO_CAN_ID_SDO_CLI 

0x600, SDO request from client (+nodeID)

CO_CAN_ID_HEARTBEAT 

0x700, Heartbeat message

CO_CAN_ID_LSS_SLV 

0x7E4, LSS response from slave

CO_CAN_ID_LSS_MST 

0x7E5, LSS request from master

◆ CO_CAN_ERR_status_t

CAN error status bitmasks.

CAN warning level is reached, if CAN transmit or receive error counter is more or equal to 96. CAN passive level is reached, if counters are more or equal to 128. Transmitter goes in error state 'bus off' if transmit error counter is more or equal to 256.

Enumerator
CO_CAN_ERRTX_WARNING 

0x0001, CAN transmitter warning

CO_CAN_ERRTX_PASSIVE 

0x0002, CAN transmitter passive

CO_CAN_ERRTX_BUS_OFF 

0x0004, CAN transmitter bus off

CO_CAN_ERRTX_OVERFLOW 

0x0008, CAN transmitter overflow

CO_CAN_ERRTX_PDO_LATE 

0x0080, TPDO is outside sync window

CO_CAN_ERRRX_WARNING 

0x0100, CAN receiver warning

CO_CAN_ERRRX_PASSIVE 

0x0200, CAN receiver passive

CO_CAN_ERRRX_OVERFLOW 

0x0800, CAN receiver overflow

CO_CAN_ERR_WARN_PASSIVE 

0x0303, combination

◆ CO_ReturnError_t

Return values of some CANopen functions.

If function was executed successfully it returns 0 otherwise it returns <0.

Enumerator
CO_ERROR_NO 

Operation completed successfully.

CO_ERROR_ILLEGAL_ARGUMENT 

Error in function arguments.

CO_ERROR_OUT_OF_MEMORY 

Memory allocation failed.

CO_ERROR_TIMEOUT 

Function timeout.

CO_ERROR_ILLEGAL_BAUDRATE 

Illegal baudrate passed to function CO_CANmodule_init()

CO_ERROR_RX_OVERFLOW 

Previous message was not processed yet.

CO_ERROR_RX_PDO_OVERFLOW 

previous PDO was not processed yet

CO_ERROR_RX_MSG_LENGTH 

Wrong receive message length.

CO_ERROR_RX_PDO_LENGTH 

Wrong receive PDO length.

CO_ERROR_TX_OVERFLOW 

Previous message is still waiting, buffer full.

CO_ERROR_TX_PDO_WINDOW 

Synchronous TPDO is outside window.

CO_ERROR_TX_UNCONFIGURED 

Transmit buffer was not configured properly.

CO_ERROR_OD_PARAMETERS 

Error in Object Dictionary parameters.

CO_ERROR_DATA_CORRUPT 

Stored data are corrupt.

CO_ERROR_CRC 

CRC does not match.

CO_ERROR_TX_BUSY 

Sending rejected because driver is busy.

Try again

CO_ERROR_WRONG_NMT_STATE 

Command can't be processed in current state.

CO_ERROR_SYSCALL 

Syscall failed.

CO_ERROR_INVALID_STATE 

Driver not ready.

CO_ERROR_NODE_ID_UNCONFIGURED_LSS 

Node-id is in LSS unconfigured state.

If objects are handled properly, this may not be an error.

Function Documentation

◆ CO_CANsetConfigurationMode()

void CO_CANsetConfigurationMode ( void *  CANptr)

Request CAN configuration (stopped) mode and wait until it is set.

Parameters
CANptrPointer to CAN device

◆ CO_CANsetNormalMode()

void CO_CANsetNormalMode ( CO_CANmodule_t CANmodule)

Request CAN normal (operational) mode and wait until it is set.

Parameters
CANmoduleCO_CANmodule_t object.

◆ CO_CANmodule_init()

CO_ReturnError_t CO_CANmodule_init ( CO_CANmodule_t CANmodule,
void *  CANptr,
CO_CANrx_t  rxArray[],
uint16_t  rxSize,
CO_CANtx_t  txArray[],
uint16_t  txSize,
uint16_t  CANbitRate 
)

Initialize CAN module object.

Function must be called in the communication reset section. CAN module must be in Configuration Mode before.

Parameters
CANmoduleThis object will be initialized.
CANptrPointer to CAN device.
rxArrayArray for handling received CAN messages
rxSizeSize of the above array. Must be equal to number of receiving CAN objects.
txArrayArray for handling transmitting CAN messages
txSizeSize of the above array. Must be equal to number of transmitting CAN objects.
CANbitRateValid values are (in kbps): 10, 20, 50, 125, 250, 500, 800,
  1. If value is illegal, bitrate defaults to 125.

Return CO_ReturnError_t: CO_ERROR_NO or CO_ERROR_ILLEGAL_ARGUMENT.

◆ CO_CANmodule_disable()

void CO_CANmodule_disable ( CO_CANmodule_t CANmodule)

Switch off CANmodule.

Call at program exit.

Parameters
CANmoduleCAN module object.

◆ CO_CANrxBufferInit()

CO_ReturnError_t CO_CANrxBufferInit ( CO_CANmodule_t CANmodule,
uint16_t  index,
uint16_t  ident,
uint16_t  mask,
bool_t  rtr,
void *  object,
void(*)(void *object, void *message)  CANrx_callback 
)

Configure CAN message receive buffer.

Function configures specific CAN receive buffer. It sets CAN identifier and connects buffer with specific object. Function must be called for each member in rxArray from CO_CANmodule_t.

Parameters
CANmoduleThis object.
indexIndex of the specific buffer in rxArray.
ident11-bit standard CAN Identifier. If two or more CANrx buffers have the same ident, then buffer with lowest index has precedence and other CANrx buffers will be ignored.
mask11-bit mask for identifier. Most usually set to 0x7FF. Received message (rcvMsg) will be accepted if the following condition is true: (((rcvMsgId ^ ident) & mask) == 0).
rtrIf true, 'Remote Transmit Request' messages will be accepted.
objectCANopen object, to which buffer is connected. It will be used as an argument to CANrx_callback. Its type is (void), CANrx_callback will change its type back to the correct object type.
CANrx_callbackPointer to function, which will be called, if received CAN message matches the identifier. It must be fast function.

Return CO_ReturnError_t: CO_ERROR_NO CO_ERROR_ILLEGAL_ARGUMENT or CO_ERROR_OUT_OF_MEMORY (not enough masks for configuration).

◆ CO_CANtxBufferInit()

CO_CANtx_t* CO_CANtxBufferInit ( CO_CANmodule_t CANmodule,
uint16_t  index,
uint16_t  ident,
bool_t  rtr,
uint8_t  noOfBytes,
bool_t  syncFlag 
)

Configure CAN message transmit buffer.

Function configures specific CAN transmit buffer. Function must be called for each member in txArray from CO_CANmodule_t.

Parameters
CANmoduleThis object.
indexIndex of the specific buffer in txArray.
ident11-bit standard CAN Identifier.
rtrIf true, 'Remote Transmit Request' messages will be transmitted.
noOfBytesLength of CAN message in bytes (0 to 8 bytes).
syncFlagThis flag bit is used for synchronous TPDO messages. If it is set, message will not be sent, if current time is outside synchronous window.
Returns
Pointer to CAN transmit message buffer. 8 bytes data array inside buffer should be written, before CO_CANsend() function is called. Zero is returned in case of wrong arguments.

◆ CO_CANsend()

CO_ReturnError_t CO_CANsend ( CO_CANmodule_t CANmodule,
CO_CANtx_t buffer 
)

Send CAN message.

Parameters
CANmoduleThis object.
bufferPointer to transmit buffer, returned by CO_CANtxBufferInit(). Data bytes must be written in buffer before function call.
Returns
CO_ReturnError_t: CO_ERROR_NO, CO_ERROR_TX_OVERFLOW or CO_ERROR_TX_PDO_WINDOW (Synchronous TPDO is outside window).

◆ CO_CANclearPendingSyncPDOs()

void CO_CANclearPendingSyncPDOs ( CO_CANmodule_t CANmodule)

Clear all synchronous TPDOs from CAN module transmit buffers.

CANopen allows synchronous PDO communication only inside time between SYNC message and SYNC Window. If time is outside this window, new synchronous PDOs must not be sent and all pending sync TPDOs, which may be on CAN TX buffers, may optionally be cleared.

This function checks (and aborts transmission if necessary) CAN TX buffers when it is called. Function should be called by the stack in the moment, when SYNC time was just passed out of synchronous window.

Parameters
CANmoduleThis object.

◆ CO_CANmodule_process()

void CO_CANmodule_process ( CO_CANmodule_t CANmodule)

Process can module - verify CAN errors.

Function must be called cyclically. It should calculate CANerrorStatus bitfield for CAN errors defined in CO_CAN_ERR_status_t.

Parameters
CANmoduleThis object.

◆ CO_getUint8()

static uint8_t CO_getUint8 ( const void *  buf)
inlinestatic

Get uint8_t value from memory buffer.

Parameters
bufMemory buffer to get value from.
Returns
Value

◆ CO_setUint8()

static uint8_t CO_setUint8 ( void *  buf,
uint8_t  value 
)
inlinestatic

Write uint8_t value into memory buffer.

Parameters
bufMemory buffer.
valueValue to be written into buf.
Returns
number of bytes written.