forked from CANopenNode/CANopenNode
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCANopen.h
482 lines (435 loc) · 15.3 KB
/
CANopen.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
/**
* Main CANopenNode file.
*
* @file CANopen.h
* @ingroup CO_CANopen
* @author Janez Paternoster
* @author Uwe Kindler
* @copyright 2010 - 2020 Janez Paternoster
*
* This file is part of CANopenNode, an opensource CANopen Stack.
* Project home page is <https://github.com/CANopenNode/CANopenNode>.
* For more information on CANopen see <http://www.can-cia.org/>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef CANopen_H
#define CANopen_H
#include "301/CO_driver.h"
#include "301/CO_SDOserver.h"
#include "301/CO_SDOclient.h"
#include "301/CO_Emergency.h"
#include "301/CO_NMT_Heartbeat.h"
#include "301/CO_TIME.h"
#include "301/CO_SYNC.h"
#include "301/CO_PDO.h"
#include "301/CO_HBconsumer.h"
#include "303/CO_LEDs.h"
#include "304/CO_GFC.h"
#include "304/CO_SRDO.h"
#include "305/CO_LSSslave.h"
#include "305/CO_LSSmaster.h"
#include "309/CO_gateway_ascii.h"
#include "extra/CO_trace.h"
#include "CO_OD.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup CO_CANopen CANopen
* @{
*
* CANopenNode is free and open source implementation of CANopen communication
* protocol.
*
* CANopen is the internationally standardized (EN 50325-4) (CiA DS-301)
* CAN-based higher-layer protocol for embedded control system. For more
* information on CANopen see http://www.can-cia.org/
*
* CANopenNode homepage is https://github.com/CANopenNode/CANopenNode
*
* CANopen.h file combines Object dictionary (CO_OD) and all other CANopen
* source files. Configuration information are read from CO_OD.h file.
* CO_OD.h/.c files defines CANopen Object Dictionary and are generated by
* external tool.
* CANopen.h file contains most common configuration of CANopenNode objects
* and can also be a template for custom, more complex configurations.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* @}
*/
/**
* @defgroup CO_CANopen_301 CANopen_301
* @{
*
* CANopen application layer and communication profile (CiA 301 v4.2.0)
*
* Definitions of data types, encoding rules, object dictionary objects and
* CANopen communication services and protocols.
* @}
*/
/**
* @defgroup CO_CANopen_303 CANopen_303
* @{
*
* CANopen recommendation for indicator specification (CiA 303-3 v1.4.0)
*
* Description of communication related indicators - green and red LED diodes.
* @}
*/
/**
* @defgroup CO_CANopen_304 CANopen_304
* @{
*
* CANopen Safety (EN 50325-5:2010 (formerly CiA 304))
*
* Standard defines the usage of Safety Related Data Objects (SRDO) and the GFC.
* This is an additional protocol (to SDO, PDO) to exchange data.
* The meaning of "security" here refers not to security (crypto) but to data consistency.
* @}
*/
/**
* @defgroup CO_CANopen_305 CANopen_305
* @{
*
* CANopen layer setting services (LSS) and protocols (CiA 305 DSP v3.0.0)
*
* Inquire or change three parameters on a CANopen device with LSS slave
* capability by a CANopen device with LSS master capability via the CAN
* network: the settings of Node-ID of the CANopen device, bit timing
* parameters of the physical layer (bit rate) or LSS address compliant to the
* identity object (1018h).
* @}
*/
/**
* @defgroup CO_CANopen_309 CANopen_309
* @{
*
* CANopen access from other networks (CiA 309)
*
* Standard defines the services and protocols to interface CANopen networks to
* other networks. Standard is organized as follows:
* - Part 1: General principles and services
* - Part 2: Modbus/TCP mapping
* - Part 3: ASCII mapping
* - Part 4: Amendment 7 to Fieldbus Integration into PROFINET IO
* @}
*/
/**
* @defgroup CO_CANopen_extra CANopen_extra
* @{
*
* Additional non-standard objects related to CANopenNode.
* @}
*/
/**
* @addtogroup CO_CANopen
* @{
*/
#ifdef CO_DOXYGEN
/**
* @defgroup CO_NO_OBJ CANopen configuration
*
* Definitions specify, which and how many CANopenNode communication objects
* will be used in current configuration. Usage of some objects is mandatory and
* is fixed. Others are defined in CO_OD.h.
* @{
*/
/* Definitions valid only for documentation. */
/** Number of NMT objects, fixed to 1 slave(CANrx) */
#define CO_NO_NMT (1)
/** Number of NMT master objects, 0 or 1 master(CANtx). It depends on
* @ref CO_CONFIG_NMT setting. */
#define CO_NO_NMT_MST (0 - 1)
/** Number of SYNC objects, 0 or 1 (consumer(CANrx) + producer(CANtx)) */
#define CO_NO_SYNC (0 - 1)
/** Number of Emergency producer objects, fixed to 1 producer(CANtx) */
#define CO_NO_EMERGENCY (1)
/** Number of Emergency consumer objects, 0 or 1 consumer(CANrx). It depends on
* @ref CO_CONFIG_EM setting. */
#define CO_NO_EM_CONS (0 - 1)
/** Number of Time-stamp objects, 0 or 1 (consumer(CANrx) + producer(CANtx)) */
#define CO_NO_TIME (0 - 1)
/** Number of GFC objects, 0 or 1 (consumer(CANrx) + producer(CANtx)) */
#define CO_NO_GFC (0 - 1)
/** Number of SRDO objects, 0 to 64 (consumer(CANrx) + producer(CANtx)) */
#define CO_NO_RPDO (0 - 64)
/** Number of RPDO objects, 1 to 512 consumers (CANrx) */
#define CO_NO_RPDO (1 - 512)
/** Number of TPDO objects, 1 to 512 producers (CANtx) */
#define CO_NO_TPDO (1 - 512)
/** Number of SDO server objects, from 1 to 128 (CANrx + CANtx) */
#define CO_NO_SDO_SERVER (1 - 128)
/** Number of SDO client objects, from 0 to 128 (CANrx + CANtx) */
#define CO_NO_SDO_CLIENT (0 - 128)
/** Number of HB producer objects, fixed to 1 producer(CANtx) */
#define CO_NO_HB_PROD (1)
/** Number of HB consumer objects, from 0 to 127 consumers(CANrx) */
#define CO_NO_HB_CONS (0 - 127)
/** Number of LSS slave objects, 0 or 1 (CANrx + CANtx). It depends on
* @ref CO_CONFIG_LSS setting. */
#define CO_NO_LSS_SLAVE (0 - 1)
/** Number of LSS master objects, 0 or 1 (CANrx + CANtx). It depends on
* @ref CO_CONFIG_LSS setting. */
#define CO_NO_LSS_MASTER (0 - 1)
/** Number of Trace objects, 0 to many */
#define CO_NO_TRACE (0 - )
/** @} */
#else /* CO_DOXYGEN */
/* Valid Definitions for program. */
/* NMT slave count (fixed) */
#define CO_NO_NMT 1
/* NMT master count depends on stack configuration */
#if (CO_CONFIG_NMT) & CO_CONFIG_NMT_MASTER
#define CO_NO_NMT_MST 1
#else
#define CO_NO_NMT_MST 0
#endif
/* Emergency consumer depends on stack configuration */
#if (CO_CONFIG_EM) & CO_CONFIG_EM_CONSUMER
#define CO_NO_EM_CONS 1
#else
#define CO_NO_EM_CONS 0
#endif
/* Heartbeat producer count (fixed) */
#define CO_NO_HB_PROD 1
/* Heartbeat consumer count depends on Object Dictionary configuration */
#ifdef ODL_consumerHeartbeatTime_arrayLength
#define CO_NO_HB_CONS ODL_consumerHeartbeatTime_arrayLength
#else
#define CO_NO_HB_CONS 0
#endif
/* LSS slave count depends on stack configuration */
#if (CO_CONFIG_LSS) & CO_CONFIG_LSS_SLAVE
#define CO_NO_LSS_SLAVE 1
#else
#define CO_NO_LSS_SLAVE 0
#endif
/* LSS master count depends on stack configuration */
#if (CO_CONFIG_LSS) & CO_CONFIG_LSS_MASTER
#define CO_NO_LSS_MASTER 1
#else
#define CO_NO_LSS_MASTER 0
#endif
#endif /* CO_DOXYGEN */
/**
* CANopen object with pointers to all CANopenNode objects.
*/
typedef struct {
bool_t nodeIdUnconfigured; /**< True in unconfigured LSS slave */
CO_CANmodule_t *CANmodule[1]; /**< CAN module objects */
CO_SDO_t *SDO[CO_NO_SDO_SERVER]; /**< SDO object */
CO_EM_t *em; /**< Emergency report object */
CO_EMpr_t *emPr; /**< Emergency process object */
CO_NMT_t *NMT; /**< NMT object */
#if CO_NO_SYNC == 1 || defined CO_DOXYGEN
CO_SYNC_t *SYNC; /**< SYNC object */
#endif
#if CO_NO_TIME == 1 || defined CO_DOXYGEN
CO_TIME_t *TIME; /**< TIME object */
#endif
CO_RPDO_t *RPDO[CO_NO_RPDO]; /**< RPDO objects */
CO_TPDO_t *TPDO[CO_NO_TPDO]; /**< TPDO objects */
CO_HBconsumer_t *HBcons; /**< Heartbeat consumer object*/
#if CO_NO_SDO_CLIENT != 0 || defined CO_DOXYGEN
CO_SDOclient_t *SDOclient[CO_NO_SDO_CLIENT]; /**< SDO client object */
#endif
#if ((CO_CONFIG_LEDS) & CO_CONFIG_LEDS_ENABLE) || defined CO_DOXYGEN
CO_LEDs_t *LEDs; /**< LEDs object */
#endif
#if CO_NO_GFC != 0 || defined CO_DOXYGEN
CO_GFC_t *GFC; /**< GFC objects */
#endif
#if CO_NO_SRDO != 0 || defined CO_DOXYGEN
CO_SRDOGuard_t *SRDOGuard; /**< SRDO objects */
CO_SRDO_t *SRDO[CO_NO_SRDO]; /**< SRDO objects */
#endif
#if CO_NO_LSS_SLAVE == 1 || defined CO_DOXYGEN
CO_LSSslave_t *LSSslave; /**< LSS slave object */
#endif
#if CO_NO_LSS_MASTER == 1 || defined CO_DOXYGEN
CO_LSSmaster_t *LSSmaster; /**< LSS master object */
#endif
#if ((CO_CONFIG_GTW) & CO_CONFIG_GTW_ASCII) || defined CO_DOXYGEN
CO_GTWA_t *gtwa; /**< Gateway-ascii object (CiA309-3) */
#endif
#if CO_NO_TRACE > 0 || defined CO_DOXYGEN
CO_trace_t *trace[CO_NO_TRACE]; /**< Trace object for recording variables */
#endif
} CO_t;
/** CANopen object */
extern CO_t *CO;
/**
* Allocate and initialize memory for CANopen object
*
* Function must be called the first time, after program starts.
*
* @remark
* With some microcontrollers it is necessary to specify Heap size within
* linker configuration.
*
* @param [out] heapMemoryUsed Information about heap memory used. Ignored if
* NULL.
*
* @return #CO_ReturnError_t: CO_ERROR_NO, CO_ERROR_ILLEGAL_ARGUMENT,
* CO_ERROR_OUT_OF_MEMORY
*/
CO_ReturnError_t CO_new(uint32_t *heapMemoryUsed);
/**
* Delete CANopen object and free memory. Must be called at program exit.
*
* @param CANptr Pointer to the user-defined CAN base structure, passed to
* CO_CANmodule_init().
*/
void CO_delete(void *CANptr);
/**
* Initialize CAN driver
*
* Function must be called in the communication reset section.
*
* @param CANptr Pointer to the user-defined CAN base structure, passed to
* CO_CANmodule_init().
* @param bitRate CAN bit rate.
* @return #CO_ReturnError_t: CO_ERROR_NO, CO_ERROR_ILLEGAL_ARGUMENT,
* CO_ERROR_ILLEGAL_BAUDRATE, CO_ERROR_OUT_OF_MEMORY
*/
CO_ReturnError_t CO_CANinit(void *CANptr,
uint16_t bitRate);
#if CO_NO_LSS_SLAVE == 1 || defined CO_DOXYGEN
/**
* Initialize CANopen LSS slave
*
* Function must be called before CO_CANopenInit.
*
* See #CO_LSSslave_init() for description of parameters.
*
* @param [in,out] pendingNodeID Pending node ID or 0xFF(unconfigured)
* @param [in,out] pendingBitRate Pending bit rate of the CAN interface
* @return #CO_ReturnError_t: CO_ERROR_NO, CO_ERROR_ILLEGAL_ARGUMENT
*/
CO_ReturnError_t CO_LSSinit(uint8_t *pendingNodeID,
uint16_t *pendingBitRate);
#endif /* CO_NO_LSS_SLAVE == 1 */
/**
* Initialize CANopenNode.
*
* Function must be called in the communication reset section.
*
* @param nodeId CANopen Node ID (1 ... 127) or 0xFF(unconfigured). In the
* CANopen initialization it is the same as pendingBitRate from CO_LSSinit().
* If it is unconfigured, then some CANopen objects will not be initialized nor
* processed.
* @return #CO_ReturnError_t: CO_ERROR_NO, CO_ERROR_ILLEGAL_ARGUMENT
*/
CO_ReturnError_t CO_CANopenInit(uint8_t nodeId);
/**
* Process CANopen objects.
*
* Function must be called cyclically. It processes all "asynchronous" CANopen
* objects.
*
* @param co CANopen object.
* @param timeDifference_us Time difference from previous function call in
* microseconds.
* @param [out] timerNext_us info to OS - maximum delay time after this function
* should be called next time in [microseconds]. Value can be used for OS
* sleep time. Initial value must be set to maximum interval time.
* Output will be equal or lower to initial value. Calculation is based
* on various timers which expire in known time. Parameter should be
* used in combination with callbacks configured with
* CO_***_initCallbackPre() functions. Those callbacks should also
* trigger calling of CO_process() function. Parameter is ignored if
* NULL. See also @ref CO_CONFIG_FLAG_CALLBACK_PRE configuration macro.
*
* @return #CO_NMT_reset_cmd_t from CO_NMT_process().
*/
CO_NMT_reset_cmd_t CO_process(CO_t *co,
uint32_t timeDifference_us,
uint32_t *timerNext_us);
#if CO_NO_SYNC == 1 || defined CO_DOXYGEN
/**
* Process CANopen SYNC objects.
*
* Function must be called cyclically from real time thread with constant
* interval (1ms typically). It processes SYNC CANopen objects.
*
* @param co CANopen object.
* @param timeDifference_us Time difference from previous function call in
* microseconds.
* @param [out] timerNext_us info to OS - see CO_process().
*
* @return True, if CANopen SYNC message was just received or transmitted.
*/
bool_t CO_process_SYNC(CO_t *co,
uint32_t timeDifference_us,
uint32_t *timerNext_us);
#endif /* CO_NO_SYNC == 1 */
/**
* Process CANopen RPDO objects.
*
* Function must be called cyclically from real time thread with constant.
* interval (1ms typically). It processes receive PDO CANopen objects.
*
* @param co CANopen object.
* @param syncWas True, if CANopen SYNC message was just received or
* transmitted.
*/
void CO_process_RPDO(CO_t *co, bool_t syncWas);
/**
* Process CANopen TPDO objects.
*
* Function must be called cyclically from real time thread with constant.
* interval (1ms typically). It processes transmit PDO CANopen objects.
*
* @param co CANopen object.
* @param syncWas True, if CANopen SYNC message was just received or
* transmitted.
* @param timeDifference_us Time difference from previous function call in
* microseconds.
* @param [out] timerNext_us info to OS - see CO_process().
*/
void CO_process_TPDO(CO_t *co,
bool_t syncWas,
uint32_t timeDifference_us,
uint32_t *timerNext_us);
#if CO_NO_SRDO != 0 || defined CO_DOXYGEN
/**
* Process CANopen SRDO objects.
*
* Function must be called cyclically from real time thread with constant.
* interval (1ms typically). It processes receive SRDO CANopen objects.
*
* @param co CANopen object.
* @param timeDifference_us Time difference from previous function call in
* microseconds.
* @param [out] timerNext_us info to OS - see CO_process().
*/
void CO_process_SRDO(CO_t *co,
uint32_t timeDifference_us,
uint32_t *timerNext_us);
#endif /* CO_NO_SRDO != 0 */
/** @} */ /* CO_CANopen */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* CANopen_H */