Configuration#
Configuration Options#
Application Parameter#
This chapter describes the specification of the parameter groups. The parameter structures are highly application-specific and shall be defined within the application header files.
Example:
typedef struct COM_PARA_MEM_T {
uint16_t Heartbeat_1017_0;
} COM_PARA_MEM;
typedef struct APP_PARA_MEM_T {
uint32_t DemoLong;
uint16_t DemoWord;
uint8_t DemoByte;
} APP_PARA_MEM;
typedef struct ALL_PARA_MEM_T {
COM_PARA_MEM Com;
APP_PARA_MEM App;
} ALL_PARA_MEM;
This example defines multiple parameter groups:
-
a parameter group containing the communication profile parameter (
COM_PARA_MEM
) -
a parameter group containing the application-specific parameter (
APP_PARA_MEM
) -
The third definition collects the previously defined parameter groups to a single parameter group to allow loading and storage of both parameter groups with single access (
ALL_PARA_MEM
)
These structure type definitions are recommended to force the linker to place the corresponding parameter variables in a consecutive memory block. Any other technique to get this result is reasonable, too.
Within the object directory configuration, the parameter group information structures shall be allocated and filled with the corresponding parameter group information settings.
Example:
static const CO_PARA AllParaObj = {
0L, /* placement in non-volatile memory */
sizeof(ALL_PARA_MEM),
(uint8_t *)&Para,
(uint8_t *)&ParaDef,
CO_RESET_NODE,
(void *)"all.txt",
CO_PARA___E
};
static const CO_PARA ComParaObj = {
0L, /* placement in non-volatile memory */
sizeof(COM_PARA_MEM),
(uint8_t *)&Para.Com,
(uint8_t *)&ParaDef.Com,
CO_RESET_COM,
(void *)"com.txt",
CO_PARA___E
};
static const CO_PARA AppParaObj = {
sizeof(COM_PARA_MEM), /* placement in non-volatile memory */
sizeof(APP_PARA_MEM),
(uint8_t *)&Para.App,
(uint8_t *)&ParaDef.App,
CO_RESET_NODE,
(void *)"app.txt",
CO_PARA___E
};
The following descriptions explains the details of the table members:
-
The parameter group size [
uint32_t
] shall be set to the number of bytes within the parameter group memory area -
The start address of the parameter group memory area [
uint8_t *
] shall be set to the first address of the parameter group memory -
The reset type [
CO_NMT_RESET
] shall be set to one of the following values:
Reset Type | Description |
---|---|
CO_RESET_COM |
parameter group shall be set to the stored values on communication reset |
CO_RESET_NODE |
parameter group shall be set to the stored values on node reset |
-
The pointer to the identification [
void *
] of this parameter group is not used by the CANopen stack. This member is intended to identify the different parameter groups within the application callback functions, related to the parameter handling. Any type of identification may be used for this purpose. In the shown example, an identification string is used. -
The parameter group feature indication [
uint32_t
], which is returned on a simple object entry read access, shall be set to one of the following values:
Parameter Feature | Description |
---|---|
CO_PARA____ |
parameter group is disabled |
CO_PARA___E |
parameter group is enabled and will be stored on command |
CO_PARA__A_ |
parameter group is enabled and will be stored autonomously |
CO_PARA__AE |
parameter group is enabled and will be stored on command and autonomously |
Note: "autonomously" means without CANopen network interaction; e.g. the application is responsible for the storage of these parameter groups.
The object entries, handling the saving and restoring of parameters, shall be set for the example to the following values:
{ CO_KEY(0x1010, 0, CO_OBJ_D___R_), CO_TPARA_STORE, (CO_DATA)(0x03) },
{ CO_KEY(0x1010, 1, CO_OBJ_____RW), CO_TPARA_STORE, (CO_DATA)(&AllParaObj) },
{ CO_KEY(0x1010, 2, CO_OBJ_____RW), CO_TPARA_STORE, (CO_DATA)(&ComParaObj) },
{ CO_KEY(0x1010, 3, CO_OBJ_____RW), CO_TPARA_STORE, (CO_DATA)(&AppParaObj) },
{ CO_KEY(0x1011, 0, CO_OBJ_D___R_), CO_TPARA_RESTORE, (CO_DATA)(0x03) },
{ CO_KEY(0x1011, 1, CO_OBJ_____RW), CO_TPARA_RESTORE, (CO_DATA)(&AllParaObj) },
{ CO_KEY(0x1011, 2, CO_OBJ_____RW), CO_TPARA_RESTORE, (CO_DATA)(&ComParaObj) },
{ CO_KEY(0x1011, 3, CO_OBJ_____RW), CO_TPARA_RESTORE, (CO_DATA)(&AppParaObj) },
The single parameters are most likely used within the object directory. The example definition of an object entry is shown for one parameter:
{ CO_KEY(0x1017, 0, CO_OBJ_____RW), CO_TUNSIGNED16, (CO_DATA)(&Para.App.DemoWord) },
Domain Definition#
This chapter describes the specification of an object with the type domain
. The domains are highly application-specific and are usable in a wide range.
Example:
CO_OBJ_DOM AppDomain = {
0,
sizeof(APP_PARA_MEM),
&AppParaObj
};
This example defines a domain information object for the already allocated memory space of the variable AppParaObj (a variable within the application parameter example). This allows access to the complete application parameter set with SDO segmented or block transfers from within the CANopen network.
The following descriptions explains the details of the structure members:
-
The domain offset [
uint32_t
] shall be set to 0 to access the first byte of the domain -
The domain size [
uint32_t
] in bytes shall be set to the number of bytes within the domain memory area -
The start address of the domain memory area [
uint8_t *
] shall be set to the first address of the domain
The object entry, presenting the example domain above to the CANopen network, should be defined within the manufacturer-specific area (e.g. index 0x2500, subindex 0x00) with the following object directory entry definition line:
{ CO_KEY(0x2500, 0, CO_OBJ_____RW), CO_TDOMAIN, (CO_DATA)(&AppDomain) },
Note: The standard type implementation CO_TDOMAIN
assumes, that the domain memory is located in RAM and is direct accessible. For other types of domain, a project-specific domain type shall be implemented.
Heartbeat Consumer Definition#
This chapter describes the specification of a heartbeat consumer object.
Example:
CO_HBCONS AppHbConsumer_1 = { 0 };
/* optional somewhere during startup: */
AppHbConsumer_1.Time = 100; /* heartbeat consumer time of 100ms */
AppHbConsumer_1.NodeId = 42; /* heartbeat consumer for node 42 */
This example defines a heartbeat consumer object. The initialization of all members with 0 is good practice, but not mandatory. The heartbeat consumer object allows the configuration of a heartbeat consumer with SDO transfers from within the CANopen network or during configuration time.
The following descriptions explains the details of the structure members, which should be initialized (via application - or via an SDO write access):
-
The Time [
uint16_t
] shall be set to the heartbeat consumer time in ms. The monitoring of the addressed heartbeat starts after the first reception of the addressed heartbeat. -
The NodeId [
uint8_t
] shall be set to the CANopen Node-ID of the heartbeat producer, which shall be consumed.
The object entry, presenting the example domain above to the CANopen network, should be defined within the heartbeat consumer area (index 0x1016, subindex 0 to 254) with the following object directory entry definition line:
{ CO_KEY(0x1016, 0, CO_OBJ_D___R_), CO_THB_CONS, (CO_DATA)(1) },
{ CO_KEY(0x1016, 1, CO_OBJ_____RW), CO_THB_CONS, (CO_DATA)(&AppHbConsumer_1) },
Note: Even, if the members "Time" and "NodeId" are static, the heartbeat consumer must be placed in RAM. There are multiple internal members for managing the heartbeat consumer included as well.
Emergency Code Definition#
This chapter describes the definition of the Emergency error code table. This table must be in line with the Emergency identifier enumeration.
Example:
const CO_EMCY_TBL AppEmcyCode[CO_EMCY_N] = {
{ CO_EMCY_REG_GENERAL, CO_EMCY_CODE_GEN_ERR + 0x01 }, /* APP_EMCY_1 */
{ CO_EMCY_REG_CURRENT, CO_EMCY_CODE_CUR_ERR + 0x01 }, /* APP_EMCY_2 */
{ CO_EMCY_REG_VOLTAGE, CO_EMCY_CODE_VOL_ERR + 0x01 }, /* APP_EMCY_3 */
{ CO_EMCY_REG_TEMP , CO_EMCY_CODE_TEMP_ERR + 0x01 } /* APP_EMCY_4 */
};
This example defines 4 emergency codes within different error register classes (first entry of each line). The emergency codes itself are based on the standard emergency codes (second entry of each line).
The following descriptions explains the details of the table members:
- The error register bit definition [
uint8_t
] shall be set to one of the following values:
Error Register Bit | Description |
---|---|
CO_EMCY_REG_GENERAL |
general error (includes all other classes) |
CO_EMCY_REG_CURRENT |
error class: current |
CO_EMCY_REG_VOLTAGE |
error class: voltage |
CO_EMCY_REG_TEMP |
error class: temperature |
CO_EMCY_REG_COM |
error class: communication |
CO_EMCY_REG_PROFILE |
error class: profile specific error |
CO_EMCY_REG_MANUFACTURER |
error class: manufacturer specific |
- The emergency error code [
uint16_t
] shall be set to the application-specific error code. This error code should be defined acc. the CANopen specification.
The EMCY handling and object directory manipulations with these definitions is performed by the CANopen stack without further definitions.
The application is able to register, clear, reset, check and count emergency errors with the provided function API. For details on this API, see API Functions.
Example:
status = COEmcyGet(&Node.Emcy, APP_EMCY_1);
This example gets the current status of the Emergency error with the given emergency identifier APP_EMCY_1
.
Object Dictionary#
This chapter describes the configuration table representing the CANopen object dictionary. This is the central element of the CANopen node. This table can be placed in RAM or in ROM. The placement decides, which access type is possible with direct entries. Most likely this table is placed in ROM because RAM is in most cases the limited resource.
const CO_OBJ AppObjDir[] = {
{ <ObjEntryKey_0>, <ObjTypeRef_0>, <ObjData_0> }, /* first object entry */
:
{ <ObjEntryKey_N>, <ObjTypeRef_N>, <ObjData_N> }, /* last object entry */
CO_OBJ_DICT_ENDMARK
};
Each line represents a single object entry definition. The collection of object entries shall be sorted in ascending order in index and subindex.
The following chapters describes the details of the table members.
Object Entry Key#
The object entry key [uint32_t
] shall be constructed with the following macro:
CO_KEY(<index>, <subindex>, <property flags>)
-
The index is a 16bit value with possible range from
0x0000
to0xFFFF
-
The subindex is an 8bit value with the possible range from
0x00
to0xFF
-
The property flags shall be set to a bitwise disjunction of the listed values
Property Flags#
The following table shows the possible property flags. The bitwise disjunction is possible with setting multiple letters in a prepared define (e.g. CO_OBJ__N_PRW
), or using them separately.
Access Mode Flags | Description |
---|---|
CO_OBJ______W |
Write only |
CO_OBJ_____R_ |
Read only |
Note
The access types specifies the possible access types from the CANopen network to that object entry. The application is always able to read and write the object entry.
Type Flags | Description |
---|---|
CO_OBJ____P__ |
PDO mappable object |
CO_OBJ___A___ |
Use asynchronous PDO trigger on change |
CO_OBJ__N____ |
Add Node-ID to object value |
Note
The type flags are used in the communication modules for the basic object types CO_TUNSIGNED8
, CO_TUNSIGNED16
, and CO_TUNSIGNED32
only.
Storage Flags | Description |
---|---|
CO_OBJ_D_____ |
Store the value in data pointer memory |
Important
When using architectures with pointer types lower than 32bit (e.g. 16bit microcontrollers), you can store only values up to the pointer width directly in the object dictionary. For larger values declare a constant variable and place a pointer to this constant into the object dictionary.
Object Type Interface#
The object entry type function interface [CO_OBJ_TYPE *
] shall be set to one of the following values:
Basic types#
Object Type | Description | Data Variable |
---|---|---|
CO_TUNSIGNED8 |
Basic 8bit type | uint8_t |
CO_TUNSIGNED16 |
Basic 16bit type | uint16_t |
CO_TUNSIGNED32 |
Basic 32bit type | uint32_t |
CO_TDOMAIN |
Domain entry | CO_OBJ_DOM |
CO_TSTRING |
Unlimited read-only string | CO_OBJ_STR |
CiA301 Specific Types#
Object Type | Description | Data Variable |
---|---|---|
CO_TEMCY_HIST |
EMCY history entry (subindex 0) | uint8_t |
CO_TEMCY_HIST |
EMCY history entry (subindex 1..254) | uint32_t |
CO_TEMCY_ID |
Dynamic EMCY COB-ID | uint32_t |
CO_TEVENT |
PDO event timer entry | uint16_t |
CO_THB_CONS |
Heartbeat consumer entry | CO_HBCONS |
CO_THB_PROD |
Heartbeat producer entry | uint16_t |
CO_TPARA_STORE |
Parameter group store (subindex 0) | uint8_t |
CO_TPARA_STORE |
Parameter group store (subindex 1..254) | CO_PARA |
CO_TPARA_RESTORE |
Parameter group restore (subindex 0) | uint8_t |
CO_TPARA_RESTORE |
Parameter group restore (subindex 1..254) | CO_PARA |
CO_TPDO_ID |
Dynamic PDO COB-ID entry | uint32_t |
CO_TPDO_MAP |
Dynamic PDO mapping entry | uint32_t |
CO_TPDO_NUM |
Dynamic PDO number of mapping entries | uint8_t |
CO_TPDO_TYPE |
Dynamic PDO transmission type entry | uint8_t |
CO_TSDO_ID |
Dynamic SDO COB-ID entry | uint32_t |
CO_TSYNC_CYCLE |
SYNC producer cycle time | uint32_t |
CO_TSYNC_ID |
Dynamic SYNC COB-ID | uint32_t |
Object Data Reference#
The object data reference [CO_DATA
] shall be set in dependence to the object type to a variable pointer of a specific type. See above for the type specific data variable types.
PDO Mapping Value#
For the PDO mapping object entries, we must encode the object data value in the following way:
You can use the macro CO_LINK
to get the value in a readable way:
CO_LINK(<destination-index>, <destination-subindex>, <mapping-bits>)
For example, when you want to map an object entry with a size of 8 bits from index 0x2100, subindex 0x02 to your PDO, the mapping entry in the object dictionary is:
/* variable for object entry data */
uint8_t MyData = 0u;
/* object dictionary */
const CO_OBJ AppObjDir[] = {
:
/* PDO mapping entry */
{CO_KEY(0x1A00, 1, CO_OBJ_D___R_), CO_TUNSIGNED32, (CO_DATA)(CO_LINK(0x2100, 0x02, 8))},
:
/* mapped object entry */
{CO_KEY(0x2100, 2, CO_OBJ____PR_), CO_TUNSIGNED8, (CO_DATA)(&MyData)},
:
CO_OBJ_DICT_ENDMARK
};
Note: this CANopen stack supports the mapping of 8, 16, 24 or 32bits.
Transmit PDO Communication#
This chapter describes the PDO communication record for a transmit PDO. The object record contains the following object entries:
Index:sub | Static Type | Dynamic Type | Description |
---|---|---|---|
1800h:00 |
CO_TUNSIGNED8 |
CO_TUNSIGNED8 |
Communication Object TPDO #0 |
1800h:01 |
CO_TUNSIGNED32 |
CO_TPDO_ID |
COB-ID used by TPDO |
1800h:02 |
CO_TUNSIGNED8 |
CO_TPDO_TYPE |
Transmission type |
1800h:03 |
CO_TUNSIGNED16 |
CO_TUNSIGNED16 |
Inhibit time with LSB 100us (0=disable) |
1800h:04 |
n/a | n/a | reserved, shall not be implemented |
1800h:05 |
CO_TUNSIGNED16 |
CO_TPDO_EVENT |
Event timer LSB 1ms (0=disable) |
The index identifies which PDO is configured (1800h: TPDO #0, 1801h: TPDO #1, ..., 19ffh: TPDO #511). The object entries are setup with basic types in case of static communication settings. When the communication settings are parameters or dynamic variables, the listed dynamic object types ensures the correct change behavior for these records.
The encoding for the transmission type (subindex 2) is standardized:
Value | Description |
---|---|
00h | acyclic |
01h..F0h | cyclic every n-th SYNC (1..240) |
F1h..FDh | reserved |
FEh | event-driven (manufacturer specific) |
FFh | event-driven (device profile specific) |
Timer Memory Block#
This chapter describes the allocation of the data memory, required by the CANopen timer module. The presented source code lines represent the default and must not be changed. The typical need on changing this memory allocation is to place this memory to a specific place in internal or external RAM.
CO_TMR_MEM AppTmrMem[CO_TMR_N];
SDO Transfer Memory#
This chapter describes the allocation of the data memory, required by the CANopen SDO server module. The presented source code lines represent the default and must not be changed. The typical need on changing this memory allocation is to place this memory to a specific place in internal or external RAM.
uint8_t AppSdoBuf[CO_SSDO_N][CO_SDO_BUF_BYTE];
Note: This memory is used only when support for SDO segmented or block transfers are performed.
Node Specification#
This chapter describes the basic node specification. This table must be existent for each CANopen node, which shall be active within the CANopen device.
Example:
const CO_NODE_SPEC AppSpec = {
(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 */
};
This example specifies the basic node information for the example node. Each entry is a part of the configuration. This structure is only required during the startup of the CANopen stack.
If SDO block and segmented transfer is disabled, e.g. the SDO transfer buffer is not used, the last entry in the node specification can be set to NULL
.
The following example creates a single CANopen node:
extern const CO_NODE_SPEC AppSpec;
CO_NODE AppNode;
void StartNode (void)
{
CONodeInit(&AppNode, (CO_NODE_SPEC *)&AppSpec);
if (CONodeGetErr(&AppNode) != CO_ERR_NONE) {
/* error handling */
}
};