1 /**
2  * Main CANopen stack file.
3  *
4  * It combines Object dictionary (CO_OD) and all other CANopen source files.
5  * Configuration information are read from CO_OD.h file. This file uses one
6  * CAN module. If multiple CAN modules are to be used, then this file may be
7  * customized for different CANopen configuration. (One or multiple CANopen
8  * device on one or multiple CAN modules.)
9  *
10  * @file        CANopen.h
11  * @ingroup     CO_CANopen
12  * @author      Janez Paternoster
13  * @author      Uwe Kindler
14  * @copyright   2010 - 2020 Janez Paternoster
15  *
16  * This file is part of CANopenNode, an opensource CANopen Stack.
17  * Project home page is <https://github.com/CANopenNode/CANopenNode>.
18  * For more information on CANopen see <http://www.can-cia.org/>.
19  *
20  * Licensed under the Apache License, Version 2.0 (the "License");
21  * you may not use this file except in compliance with the License.
22  * You may obtain a copy of the License at
23  *
24  *     http://www.apache.org/licenses/LICENSE-2.0
25  *
26  * Unless required by applicable law or agreed to in writing, software
27  * distributed under the License is distributed on an "AS IS" BASIS,
28  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29  * See the License for the specific language governing permissions and
30  * limitations under the License.
31  */
32 
33 
34 #ifndef CANopen_H
35 #define CANopen_H
36 
37 #ifdef __cplusplus
38 extern "C" {
39 #endif
40 
41 /**
42  * @defgroup CO_CANopen CANopen stack
43  * @{
44  *
45  * CANopenNode is free and open source CANopen Stack.
46  *
47  * CANopen is the internationally standardized (EN 50325-4) (CiA DS-301)
48  * CAN-based higher-layer protocol for embedded control system. For more
49  * information on CANopen see http://www.can-cia.org/
50  *
51  * CANopenNode homepage is https://github.com/CANopenNode/CANopenNode
52  *
53  * Licensed under the Apache License, Version 2.0 (the "License");
54  * you may not use this file except in compliance with the License.
55  * You may obtain a copy of the License at
56  *
57  *     http://www.apache.org/licenses/LICENSE-2.0
58  *
59  * Unless required by applicable law or agreed to in writing, software
60  * distributed under the License is distributed on an "AS IS" BASIS,
61  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
62  * See the License for the specific language governing permissions and
63  * limitations under the License.
64  */
65 
66 
67     #include "CO_driver.h"
68     #include "CO_OD.h"
69     #include "CO_SDO.h"
70     #include "CO_Emergency.h"
71     #include "CO_NMT_Heartbeat.h"
72     #include "CO_SYNC.h"
73     #include "CO_TIME.h"
74     #include "CO_PDO.h"
75     #include "CO_HBconsumer.h"
76 #if CO_NO_SDO_CLIENT != 0
77     #include "CO_SDOmaster.h"
78 #endif
79 #if CO_NO_TRACE > 0
80     #include "CO_trace.h"
81 #endif
82 #if CO_NO_LSS_SERVER == 1
83     #include "CO_LSSslave.h"
84 #endif
85 #if CO_NO_LSS_CLIENT == 1
86     #include "CO_LSSmaster.h"
87 #endif
88 
89 /**
90  * Default CANopen identifiers.
91  *
92  * Default CANopen identifiers for CANopen communication objects. Same as
93  * 11-bit addresses of CAN messages. These are default identifiers and
94  * can be changed in CANopen. Especially PDO identifiers are confgured
95  * in PDO linking phase of the CANopen network configuration.
96  */
97 typedef enum{
98      CO_CAN_ID_NMT_SERVICE       = 0x000,   /**< 0x000, Network management */
99      CO_CAN_ID_SYNC              = 0x080,   /**< 0x080, Synchronous message */
100      CO_CAN_ID_EMERGENCY         = 0x080,   /**< 0x080, Emergency messages (+nodeID) */
101 	 CO_CAN_ID_TIME        		 = 0x100,   /**< 0x100, Time message */
102      CO_CAN_ID_TPDO_1            = 0x180,   /**< 0x180, Default TPDO1 (+nodeID) */
103      CO_CAN_ID_RPDO_1            = 0x200,   /**< 0x200, Default RPDO1 (+nodeID) */
104      CO_CAN_ID_TPDO_2            = 0x280,   /**< 0x280, Default TPDO2 (+nodeID) */
105      CO_CAN_ID_RPDO_2            = 0x300,   /**< 0x300, Default RPDO2 (+nodeID) */
106      CO_CAN_ID_TPDO_3            = 0x380,   /**< 0x380, Default TPDO3 (+nodeID) */
107      CO_CAN_ID_RPDO_3            = 0x400,   /**< 0x400, Default RPDO3 (+nodeID) */
108      CO_CAN_ID_TPDO_4            = 0x480,   /**< 0x480, Default TPDO4 (+nodeID) */
109      CO_CAN_ID_RPDO_4            = 0x500,   /**< 0x500, Default RPDO5 (+nodeID) */
110      CO_CAN_ID_TSDO              = 0x580,   /**< 0x580, SDO response from server (+nodeID) */
111      CO_CAN_ID_RSDO              = 0x600,   /**< 0x600, SDO request from client (+nodeID) */
112      CO_CAN_ID_HEARTBEAT         = 0x700,   /**< 0x700, Heartbeat message */
113      CO_CAN_ID_LSS_CLI           = 0x7E4,   /**< 0x7E4, LSS response from server to client */
114      CO_CAN_ID_LSS_SRV           = 0x7E5    /**< 0x7E5, LSS request from client to server */
115 }CO_Default_CAN_ID_t;
116 
117 
118 /**
119  * CANopen stack object combines pointers to all CANopen objects.
120  */
121 typedef struct{
122     CO_CANmodule_t     *CANmodule[1];   /**< CAN module objects */
123     CO_SDO_t           *SDO[CO_NO_SDO_SERVER]; /**< SDO object */
124     CO_EM_t            *em;             /**< Emergency report object */
125     CO_EMpr_t          *emPr;           /**< Emergency process object */
126     CO_NMT_t           *NMT;            /**< NMT object */
127     CO_SYNC_t          *SYNC;           /**< SYNC object */
128     CO_TIME_t          *TIME;           /**< TIME object */
129     CO_RPDO_t          *RPDO[CO_NO_RPDO];/**< RPDO objects */
130     CO_TPDO_t          *TPDO[CO_NO_TPDO];/**< TPDO objects */
131     CO_HBconsumer_t    *HBcons;         /**<  Heartbeat consumer object*/
132 #if CO_NO_LSS_SERVER == 1
133     CO_LSSslave_t      *LSSslave;       /**< LSS server/slave object */
134 #endif
135 #if CO_NO_LSS_CLIENT == 1
136     CO_LSSmaster_t     *LSSmaster;      /**< LSS master/client object */
137 #endif
138 #if CO_NO_SDO_CLIENT != 0
139     CO_SDOclient_t     *SDOclient[CO_NO_SDO_CLIENT]; /**< SDO client object */
140 #endif
141 #if CO_NO_TRACE > 0
142     CO_trace_t         *trace[CO_NO_TRACE]; /**< Trace object for monitoring variables */
143 #endif
144 }CO_t;
145 
146 
147 /** CANopen object */
148     extern CO_t *CO;
149 
150 
151 /**
152  * Function CO_sendNMTcommand() is simple function, which sends CANopen message.
153  * This part of code is an example of custom definition of simple CANopen
154  * object. Follow the code in CANopen.c file. If macro CO_NO_NMT_MASTER is 1,
155  * function CO_sendNMTcommand can be used to send NMT master message.
156  *
157  * @param co CANopen object.
158  * @param command NMT command.
159  * @param nodeID Node ID.
160  *
161  * @return 0: Operation completed successfully.
162  * @return other: same as CO_CANsend().
163  */
164 #if CO_NO_NMT_MASTER == 1
165     CO_ReturnError_t CO_sendNMTcommand(CO_t *co, uint8_t command, uint8_t nodeID);
166 #endif
167 
168 
169 #if CO_NO_LSS_SERVER == 1
170 /**
171  * Allocate and initialize memory for CANopen object
172  *
173  * Function must be called in the communication reset section.
174  *
175  * @return #CO_ReturnError_t: CO_ERROR_NO, CO_ERROR_ILLEGAL_ARGUMENT,
176  * CO_ERROR_OUT_OF_MEMORY
177  */
178 CO_ReturnError_t CO_new(void);
179 
180 
181 /**
182  * Initialize CAN driver
183  *
184  * Function must be called in the communication reset section.
185  *
186  * @param CANdriverState Pointer to the CAN module, passed to CO_CANmodule_init().
187  * @param bitRate CAN bit rate.
188  * @return #CO_ReturnError_t: CO_ERROR_NO, CO_ERROR_ILLEGAL_ARGUMENT,
189  * CO_ERROR_ILLEGAL_BAUDRATE, CO_ERROR_OUT_OF_MEMORY
190  */
191 CO_ReturnError_t CO_CANinit(
192         void                   *CANdriverState,
193         uint16_t                bitRate);
194 
195 
196 /**
197  * Initialize CANopen LSS slave
198  *
199  * Function must be called in the communication reset section.
200  *
201  * @param nodeId Node ID of the CANopen device (1 ... 127) or CO_LSS_NODE_ID_ASSIGNMENT
202  * @param bitRate CAN bit rate.
203  * @return #CO_ReturnError_t: CO_ERROR_NO, CO_ERROR_ILLEGAL_ARGUMENT
204  */
205 CO_ReturnError_t CO_LSSinit(
206         uint8_t                 nodeId,
207         uint16_t                bitRate);
208 
209 
210 /**
211  * Initialize CANopen stack.
212  *
213  * Function must be called in the communication reset section.
214  *
215  * @param nodeId Node ID of the CANopen device (1 ... 127).
216  * @return #CO_ReturnError_t: CO_ERROR_NO, CO_ERROR_ILLEGAL_ARGUMENT
217  */
218 CO_ReturnError_t CO_CANopenInit(
219         uint8_t                 nodeId);
220 
221 
222 #else /* CO_NO_LSS_SERVER == 1 */
223 /**
224  * Initialize CANopen stack.
225  *
226  * Function must be called in the communication reset section.
227  *
228  * @param CANdriverState Pointer to the user-defined CAN base structure, passed to CO_CANmodule_init().
229  * @param nodeId Node ID of the CANopen device (1 ... 127).
230  * @param bitRate CAN bit rate.
231  *
232  * @return #CO_ReturnError_t: CO_ERROR_NO, CO_ERROR_ILLEGAL_ARGUMENT,
233  * CO_ERROR_OUT_OF_MEMORY, CO_ERROR_ILLEGAL_BAUDRATE
234  */
235 CO_ReturnError_t CO_init(
236         void                   *CANdriverState,
237         uint8_t                 nodeId,
238         uint16_t                bitRate);
239 
240 #endif /* CO_NO_LSS_SERVER == 1 */
241 
242 
243 /**
244  * Delete CANopen object and free memory. Must be called at program exit.
245  *
246  * @param CANdriverState Pointer to the user-defined CAN base structure, passed to CO_CANmodule_init().
247  */
248 void CO_delete(void *CANdriverState);
249 
250 
251 /**
252  * Process CANopen objects.
253  *
254  * Function must be called cyclically. It processes all "asynchronous" CANopen
255  * objects.
256  *
257  * @param co CANopen object.
258  * @param timeDifference_ms Time difference from previous function call in [milliseconds].
259  * @param timerNext_ms Return value - info to OS - maximum delay after function
260  *        should be called next time in [milliseconds]. Value can be used for OS
261  *        sleep time. Initial value must be set to something, 50ms typically.
262  *        Output will be equal or lower to initial value. If there is new object
263  *        to process, delay should be suspended and this function should be
264  *        called immediately. Parameter is ignored if NULL.
265  *
266  * @return #CO_NMT_reset_cmd_t from CO_NMT_process().
267  */
268 CO_NMT_reset_cmd_t CO_process(
269         CO_t                   *co,
270         uint16_t                timeDifference_ms,
271         uint16_t               *timerNext_ms);
272 
273 
274 #if CO_NO_SYNC == 1
275 /**
276  * Process CANopen SYNC objects.
277  *
278  * Function must be called cyclically from real time thread with constant
279  * interval (1ms typically). It processes SYNC CANopen objects.
280  *
281  * @param co CANopen object.
282  * @param timeDifference_us Time difference from previous function call in [microseconds].
283  *
284  * @return True, if CANopen SYNC message was just received or transmitted.
285  */
286 bool_t CO_process_SYNC(
287         CO_t                   *co,
288         uint32_t                timeDifference_us);
289 #endif
290 
291 /**
292  * Process CANopen RPDO objects.
293  *
294  * Function must be called cyclically from real time thread with constant.
295  * interval (1ms typically). It processes receive PDO CANopen objects.
296  *
297  * @param co CANopen object.
298  * @param syncWas True, if CANopen SYNC message was just received or transmitted.
299  */
300 void CO_process_RPDO(
301         CO_t                   *co,
302         bool_t                  syncWas);
303 
304 /**
305  * Process CANopen TPDO objects.
306  *
307  * Function must be called cyclically from real time thread with constant.
308  * interval (1ms typically). It processes transmit PDO CANopen objects.
309  *
310  * @param co CANopen object.
311  * @param syncWas True, if CANopen SYNC message was just received or transmitted.
312  * @param timeDifference_us Time difference from previous function call in [microseconds].
313  */
314 void CO_process_TPDO(
315         CO_t                   *co,
316         bool_t                  syncWas,
317         uint32_t                timeDifference_us);
318 
319 #ifdef __cplusplus
320 }
321 #endif /*__cplusplus*/
322 
323 /** @} */
324 #endif
325