1 /**
2  * CANopen Emergency protocol.
3  *
4  * @file        CO_Emergency.h
5  * @ingroup     CO_Emergency
6  * @author      Janez Paternoster
7  * @copyright   2004 - 2020 Janez Paternoster
8  *
9  * This file is part of CANopenNode, an opensource CANopen Stack.
10  * Project home page is <https://github.com/CANopenNode/CANopenNode>.
11  * For more information on CANopen see <http://www.can-cia.org/>.
12  *
13  * Licensed under the Apache License, Version 2.0 (the "License");
14  * you may not use this file except in compliance with the License.
15  * You may obtain a copy of the License at
16  *
17  *     http://www.apache.org/licenses/LICENSE-2.0
18  *
19  * Unless required by applicable law or agreed to in writing, software
20  * distributed under the License is distributed on an "AS IS" BASIS,
21  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22  * See the License for the specific language governing permissions and
23  * limitations under the License.
24  */
25 
26 
27 #ifndef CO_EMERGENCY_H
28 #define CO_EMERGENCY_H
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
34 /**
35  * @defgroup CO_Emergency Emergency
36  * @ingroup CO_CANopen
37  * @{
38  *
39  * CANopen Emergency protocol.
40  *
41  * Error control and Emergency is used for control internal error state
42  * and for sending a CANopen Emergency message.
43  *
44  * In case of error condition stack or application calls CO_errorReport()
45  * function with indication of the error. Specific error condition is reported
46  * (with CANopen Emergency message) only the first time after it occurs.
47  * Internal state of the error condition is controlled with
48  * @ref CO_EM_errorStatusBits. Specific error condition can also be reset by
49  * CO_errorReset() function. If so, Emergency message is sent with
50  * CO_EM_NO_ERROR indication.
51  *
52  * Some error conditions are informative and some are critical. Critical error
53  * conditions sets the #CO_errorRegisterBitmask_t.
54  *
55  * Latest errors can be read from _Pre Defined Error Field_ (object dictionary,
56  * index 0x1003). @ref CO_EM_errorStatusBits can also be read form CANopen
57  * object dictionary.
58  *
59  * ###Emergency message contents:
60  *
61  *   Byte | Description
62  *   -----|-----------------------------------------------------------
63  *   0..1 | @ref CO_EM_errorCodes.
64  *   2    | #CO_errorRegisterBitmask_t.
65  *   3    | Index of error condition (see @ref CO_EM_errorStatusBits).
66  *   4..7 | Additional argument informative to CO_errorReport() function.
67  *
68  * ####Contents of _Pre Defined Error Field_ (object dictionary, index 0x1003):
69  * bytes 0..3 are equal to bytes 0..3 in the Emergency message.
70  *
71  * @see #CO_Default_CAN_ID_t
72  */
73 
74 
75 /**
76  * CANopen Error register.
77  *
78  * In object dictionary on index 0x1001.
79  *
80  * Error register is calculated from critical internal @ref CO_EM_errorStatusBits.
81  * Generic and communication bits are calculated in CO_EM_process
82  * function, device profile or manufacturer specific bits may be calculated
83  * inside the application.
84  *
85  * Internal errors may prevent device to stay in NMT Operational state. Details
86  * are described in _Error Behavior_ object in Object Dictionary at index 0x1029.
87  */
88 typedef enum{
89     CO_ERR_REG_GENERIC_ERR  = 0x01U, /**< bit 0, generic error */
90     CO_ERR_REG_CURRENT      = 0x02U, /**< bit 1, current */
91     CO_ERR_REG_VOLTAGE      = 0x04U, /**< bit 2, voltage */
92     CO_ERR_REG_TEMPERATURE  = 0x08U, /**< bit 3, temperature */
93     CO_ERR_REG_COMM_ERR     = 0x10U, /**< bit 4, communication error (overrun, error state) */
94     CO_ERR_REG_DEV_PROFILE  = 0x20U, /**< bit 5, device profile specific */
95     CO_ERR_REG_RESERVED     = 0x40U, /**< bit 6, reserved (always 0) */
96     CO_ERR_REG_MANUFACTURER = 0x80U  /**< bit 7, manufacturer specific */
97 }CO_errorRegisterBitmask_t;
98 
99 
100 /**
101  * @defgroup CO_EM_errorCodes CANopen Error codes
102  * @{
103  *
104  * Standard error codes according to CiA DS-301 and DS-401.
105  */
106 #define CO_EMC_NO_ERROR                 0x0000U /**< 0x00xx, error Reset or No Error */
107 #define CO_EMC_GENERIC                  0x1000U /**< 0x10xx, Generic Error */
108 #define CO_EMC_CURRENT                  0x2000U /**< 0x20xx, Current */
109 #define CO_EMC_CURRENT_INPUT            0x2100U /**< 0x21xx, Current, device input side */
110 #define CO_EMC_CURRENT_INSIDE           0x2200U /**< 0x22xx, Current inside the device */
111 #define CO_EMC_CURRENT_OUTPUT           0x2300U /**< 0x23xx, Current, device output side */
112 #define CO_EMC_VOLTAGE                  0x3000U /**< 0x30xx, Voltage */
113 #define CO_EMC_VOLTAGE_MAINS            0x3100U /**< 0x31xx, Mains Voltage */
114 #define CO_EMC_VOLTAGE_INSIDE           0x3200U /**< 0x32xx, Voltage inside the device */
115 #define CO_EMC_VOLTAGE_OUTPUT           0x3300U /**< 0x33xx, Output Voltage */
116 #define CO_EMC_TEMPERATURE              0x4000U /**< 0x40xx, Temperature */
117 #define CO_EMC_TEMP_AMBIENT             0x4100U /**< 0x41xx, Ambient Temperature */
118 #define CO_EMC_TEMP_DEVICE              0x4200U /**< 0x42xx, Device Temperature */
119 #define CO_EMC_HARDWARE                 0x5000U /**< 0x50xx, Device Hardware */
120 #define CO_EMC_SOFTWARE_DEVICE          0x6000U /**< 0x60xx, Device Software */
121 #define CO_EMC_SOFTWARE_INTERNAL        0x6100U /**< 0x61xx, Internal Software */
122 #define CO_EMC_SOFTWARE_USER            0x6200U /**< 0x62xx, User Software */
123 #define CO_EMC_DATA_SET                 0x6300U /**< 0x63xx, Data Set */
124 #define CO_EMC_ADDITIONAL_MODUL         0x7000U /**< 0x70xx, Additional Modules */
125 #define CO_EMC_MONITORING               0x8000U /**< 0x80xx, Monitoring */
126 #define CO_EMC_COMMUNICATION            0x8100U /**< 0x81xx, Communication */
127 #define CO_EMC_CAN_OVERRUN              0x8110U /**< 0x8110, CAN Overrun (Objects lost) */
128 #define CO_EMC_CAN_PASSIVE              0x8120U /**< 0x8120, CAN in Error Passive Mode */
129 #define CO_EMC_HEARTBEAT                0x8130U /**< 0x8130, Life Guard Error or Heartbeat Error */
130 #define CO_EMC_BUS_OFF_RECOVERED        0x8140U /**< 0x8140, recovered from bus off */
131 #define CO_EMC_CAN_ID_COLLISION         0x8150U /**< 0x8150, CAN-ID collision */
132 #define CO_EMC_PROTOCOL_ERROR           0x8200U /**< 0x82xx, Protocol Error */
133 #define CO_EMC_PDO_LENGTH               0x8210U /**< 0x8210, PDO not processed due to length error */
134 #define CO_EMC_PDO_LENGTH_EXC           0x8220U /**< 0x8220, PDO length exceeded */
135 #define CO_EMC_DAM_MPDO                 0x8230U /**< 0x8230, DAM MPDO not processed, destination object not available */
136 #define CO_EMC_SYNC_DATA_LENGTH         0x8240U /**< 0x8240, Unexpected SYNC data length */
137 #define CO_EMC_RPDO_TIMEOUT             0x8250U /**< 0x8250, RPDO timeout */
138 #define CO_EMC_TIME_DATA_LENGTH         0x8260U /**< 0x8260, Unexpected TIME data length */
139 #define CO_EMC_EXTERNAL_ERROR           0x9000U /**< 0x90xx, External Error */
140 #define CO_EMC_ADDITIONAL_FUNC          0xF000U /**< 0xF0xx, Additional Functions */
141 #define CO_EMC_DEVICE_SPECIFIC          0xFF00U /**< 0xFFxx, Device specific */
142 
143 #define CO_EMC401_OUT_CUR_HI            0x2310U /**< 0x2310, DS401, Current at outputs too high (overload) */
144 #define CO_EMC401_OUT_SHORTED           0x2320U /**< 0x2320, DS401, Short circuit at outputs */
145 #define CO_EMC401_OUT_LOAD_DUMP         0x2330U /**< 0x2330, DS401, Load dump at outputs */
146 #define CO_EMC401_IN_VOLT_HI            0x3110U /**< 0x3110, DS401, Input voltage too high */
147 #define CO_EMC401_IN_VOLT_LOW           0x3120U /**< 0x3120, DS401, Input voltage too low */
148 #define CO_EMC401_INTERN_VOLT_HI        0x3210U /**< 0x3210, DS401, Internal voltage too high */
149 #define CO_EMC401_INTERN_VOLT_LO        0x3220U /**< 0x3220, DS401, Internal voltage too low */
150 #define CO_EMC401_OUT_VOLT_HIGH         0x3310U /**< 0x3310, DS401, Output voltage too high */
151 #define CO_EMC401_OUT_VOLT_LOW          0x3320U /**< 0x3320, DS401, Output voltage too low */
152 /** @} */
153 
154 
155 /**
156  * @defgroup CO_EM_errorStatusBits Error status bits
157  * @{
158  *
159  * Internal indication of the error condition.
160  *
161  * Each error condition is specified by unique index from 0x00 up to 0xFF.
162  * Variable  (from manufacturer section in the Object
163  * Dictionary) contains up to 0xFF bits (32bytes) for the identification of the
164  * specific error condition. (Type of the variable is CANopen OCTET_STRING.)
165  *
166  * If specific error occurs in the stack or in the application, CO_errorReport()
167  * sets specific bit in the _Error Status Bits_ variable. If bit was already
168  * set, function returns without any action. Otherwise it prepares emergency
169  * message.
170  *
171  * CO_errorReport(), CO_errorReset() or CO_isError() functions are called
172  * with unique index as an argument. (However CO_errorReport(), for example, may
173  * be used with the same index on multiple places in the code.)
174  *
175  * Macros defined below are combination of two constants: index and
176  * @ref CO_EM_errorCodes. They represents specific error conditions. They are
177  * used as double argument for CO_errorReport(), CO_errorReset() and
178  * CO_isError() functions.
179  *
180  * Stack uses first 6 bytes of the _Error Status Bits_ variable. Device profile
181  * or application may define own macros for Error status bits using
182  * @ref CO_EM_MANUFACTURER_START and @ref CO_EM_MANUFACTURER_END values. Note that
183  * _Error Status Bits_ must be large enough (up to 32 bytes).
184  */
185 #define CO_EM_NO_ERROR                  0x00U /**< 0x00, Error Reset or No Error */
186 #define CO_EM_CAN_BUS_WARNING           0x01U /**< 0x01, communication, info, CAN bus warning limit reached */
187 #define CO_EM_RXMSG_WRONG_LENGTH        0x02U /**< 0x02, communication, info, Wrong data length of the received CAN message */
188 #define CO_EM_RXMSG_OVERFLOW            0x03U /**< 0x03, communication, info, Previous received CAN message wasn't processed yet */
189 #define CO_EM_RPDO_WRONG_LENGTH         0x04U /**< 0x04, communication, info, Wrong data length of received PDO */
190 #define CO_EM_RPDO_OVERFLOW             0x05U /**< 0x05, communication, info, Previous received PDO wasn't processed yet */
191 #define CO_EM_CAN_RX_BUS_PASSIVE        0x06U /**< 0x06, communication, info, CAN receive bus is passive */
192 #define CO_EM_CAN_TX_BUS_PASSIVE        0x07U /**< 0x07, communication, info, CAN transmit bus is passive */
193 #define CO_EM_NMT_WRONG_COMMAND         0x08U /**< 0x08, communication, info, Wrong NMT command received */
194 #define CO_EM_TIME_TIMEOUT              0x09U /**< 0x09, communication, info, TIME message timeout */
195 #define CO_EM_TIME_LENGTH               0x0AU /**< 0x0A, communication, info, Unexpected TIME data length */
196 #define CO_EM_0B_unused                 0x0BU /**< 0x0B, (unused) */
197 #define CO_EM_0C_unused                 0x0CU /**< 0x0C, (unused) */
198 #define CO_EM_0D_unused                 0x0DU /**< 0x0D, (unused) */
199 #define CO_EM_0E_unused                 0x0EU /**< 0x0E, (unused) */
200 #define CO_EM_0F_unused                 0x0FU /**< 0x0F, (unused) */
201 
202 #define CO_EM_10_unused                 0x10U /**< 0x10, (unused) */
203 #define CO_EM_11_unused                 0x11U /**< 0x11, (unused) */
204 #define CO_EM_CAN_TX_BUS_OFF            0x12U /**< 0x12, communication, critical, CAN transmit bus is off */
205 #define CO_EM_CAN_RXB_OVERFLOW          0x13U /**< 0x13, communication, critical, CAN module receive buffer has overflowed */
206 #define CO_EM_CAN_TX_OVERFLOW           0x14U /**< 0x14, communication, critical, CAN transmit buffer has overflowed */
207 #define CO_EM_TPDO_OUTSIDE_WINDOW       0x15U /**< 0x15, communication, critical, TPDO is outside SYNC window */
208 #define CO_EM_16_unused                 0x16U /**< 0x16, (unused) */
209 #define CO_EM_17_unused                 0x17U /**< 0x17, (unused) */
210 #define CO_EM_SYNC_TIME_OUT             0x18U /**< 0x18, communication, critical, SYNC message timeout */
211 #define CO_EM_SYNC_LENGTH               0x19U /**< 0x19, communication, critical, Unexpected SYNC data length */
212 #define CO_EM_PDO_WRONG_MAPPING         0x1AU /**< 0x1A, communication, critical, Error with PDO mapping */
213 #define CO_EM_HEARTBEAT_CONSUMER        0x1BU /**< 0x1B, communication, critical, Heartbeat consumer timeout */
214 #define CO_EM_HB_CONSUMER_REMOTE_RESET  0x1CU /**< 0x1C, communication, critical, Heartbeat consumer detected remote node reset */
215 #define CO_EM_1D_unused                 0x1DU /**< 0x1D, (unused) */
216 #define CO_EM_1E_unused                 0x1EU /**< 0x1E, (unused) */
217 #define CO_EM_1F_unused                 0x1FU /**< 0x1F, (unused) */
218 
219 #define CO_EM_EMERGENCY_BUFFER_FULL     0x20U /**< 0x20, generic, info, Emergency buffer is full, Emergency message wasn't sent */
220 #define CO_EM_21_unused                 0x21U /**< 0x21, (unused) */
221 #define CO_EM_MICROCONTROLLER_RESET     0x22U /**< 0x22, generic, info, Microcontroller has just started */
222 #define CO_EM_23_unused                 0x23U /**< 0x23, (unused) */
223 #define CO_EM_24_unused                 0x24U /**< 0x24, (unused) */
224 #define CO_EM_25_unused                 0x25U /**< 0x25, (unused) */
225 #define CO_EM_26_unused                 0x26U /**< 0x26, (unused) */
226 #define CO_EM_27_unused                 0x27U /**< 0x27, (unused) */
227 
228 #define CO_EM_WRONG_ERROR_REPORT        0x28U /**< 0x28, generic, critical, Wrong parameters to CO_errorReport() function */
229 #define CO_EM_ISR_TIMER_OVERFLOW        0x29U /**< 0x29, generic, critical, Timer task has overflowed */
230 #define CO_EM_MEMORY_ALLOCATION_ERROR   0x2AU /**< 0x2A, generic, critical, Unable to allocate memory for objects */
231 #define CO_EM_GENERIC_ERROR             0x2BU /**< 0x2B, generic, critical, Generic error, test usage */
232 #define CO_EM_GENERIC_SOFTWARE_ERROR    0x2CU /**< 0x2C, generic, critical, Software error */
233 #define CO_EM_INCONSISTENT_OBJECT_DICT  0x2DU /**< 0x2D, generic, critical, Object dictionary does not match the software */
234 #define CO_EM_CALCULATION_OF_PARAMETERS 0x2EU /**< 0x2E, generic, critical, Error in calculation of device parameters */
235 #define CO_EM_NON_VOLATILE_MEMORY       0x2FU /**< 0x2F, generic, critical, Error with access to non volatile device memory */
236 
237 #define CO_EM_MANUFACTURER_START        0x30U /**< 0x30, manufacturer, info, This can be used by macros to calculate error codes */
238 #define CO_EM_MANUFACTURER_END          0xFFU /**< 0xFF, manufacturer, info, This can be used by macros to check error codes */
239 /** @} */
240 
241 
242 /**
243  * Size of internal buffer, whwre emergencies are stored after CO_errorReport().
244  * Buffer is cleared by CO_EM_process().
245  */
246 #define CO_EM_INTERNAL_BUFFER_SIZE      10
247 
248 
249 /**
250  * Emergerncy object for CO_errorReport(). It contains error buffer, to which new emergency
251  * messages are written, when CO_errorReport() is called. This object is included in
252  * CO_EMpr_t object.
253  */
254 typedef struct{
255     uint8_t            *errorStatusBits;        /**< From CO_EM_init() */
256     uint8_t             errorStatusBitsSize;    /**< From CO_EM_init() */
257 
258     /** Internal buffer for storing unsent emergency messages.*/
259     uint8_t             buf[CO_EM_INTERNAL_BUFFER_SIZE * 8];
260     uint8_t            *bufEnd;             /**< End+1 address of the above buffer */
261     uint8_t            *bufWritePtr;        /**< Write pointer in the above buffer */
262     uint8_t            *bufReadPtr;         /**< Read pointer in the above buffer */
263     uint8_t             bufFull;            /**< True if above buffer is full */
264     uint8_t             wrongErrorReport;   /**< Error in arguments to CO_errorReport() */
265 
266     /** From CO_EM_initCallback() or NULL */
267     void              (*pFunctSignal)(void);
268     /** From CO_EM_initCallbackRx() or NULL */
269     void              (*pFunctSignalRx)(const uint16_t ident,
270                                         const uint16_t errorCode,
271                                         const uint8_t errorRegister,
272                                         const uint8_t errorBit,
273                                         const uint32_t infoCode);
274 }CO_EM_t;
275 
276 
277 /**
278  * Report error condition.
279  *
280  * Function is called on any error condition inside CANopen stack and may also
281  * be called by application on custom error condition. Emergency message is sent
282  * after the first occurance of specific error. In case of critical error, device
283  * will not be able to stay in NMT_OPERATIONAL state.
284  *
285  * Function is short and may be used form any task or interrupt.
286  *
287  * @param em Emergency object.
288  * @param errorBit from @ref CO_EM_errorStatusBits.
289  * @param errorCode from @ref CO_EM_errorCodes.
290  * @param infoCode 32 bit value is passed to bytes 4...7 of the Emergency message.
291  * It contains optional additional information inside emergency message.
292  */
293 void CO_errorReport(CO_EM_t *em, const uint8_t errorBit, const uint16_t errorCode, const uint32_t infoCode);
294 
295 
296 /**
297  * Reset error condition.
298  *
299  * Function is called if any error condition is solved. Emergency message is sent
300  * with @ref CO_EM_errorCodes 0x0000.
301  *
302  * Function is short and may be used form any task or interrupt.
303  *
304  * @param em Emergency object.
305  * @param errorBit from @ref CO_EM_errorStatusBits.
306  * @param infoCode 32 bit value is passed to bytes 4...7 of the Emergency message.
307  */
308 void CO_errorReset(CO_EM_t *em, const uint8_t errorBit, const uint32_t infoCode);
309 
310 
311 /**
312  * Check specific error condition.
313  *
314  * Function returns 1, if specific internal error is present. Otherwise it returns 0.
315  *
316  * @param em Emergency object.
317  * @param errorBit from @ref CO_EM_errorStatusBits.
318  *
319  * @return false: Error is not present.
320  * @return true: Error is present.
321  */
322 bool_t CO_isError(CO_EM_t *em, const uint8_t errorBit);
323 
324 
325 #ifdef CO_DOXYGEN
326 /** Skip section, if CO_SDO.h is not included */
327     #define CO_SDO_H
328 #endif
329 #ifdef CO_SDO_H
330 
331 
332 /**
333  * Error control and Emergency object. It controls internal error state and
334  * sends emergency message, if error condition was reported. Object is initialized
335  * by CO_EM_init(). It contains CO_EM_t object.
336  */
337 typedef struct{
338     uint8_t            *errorRegister;  /**< From CO_EM_init() */
339     uint32_t           *preDefErr;      /**< From CO_EM_init() */
340     uint8_t             preDefErrSize;  /**< From CO_EM_init() */
341     uint8_t             preDefErrNoOfErrors;/**< Number of active errors in preDefErr */
342     uint16_t            inhibitEmTimer; /**< Internal timer for emergency message */
343     CO_EM_t            *em;             /**< CO_EM_t sub object is included here */
344     CO_CANmodule_t     *CANdev;         /**< From CO_EM_init() */
345     CO_CANtx_t         *CANtxBuff;      /**< CAN transmit buffer */
346 }CO_EMpr_t;
347 
348 
349 /**
350  * Initialize Error control and Emergency object.
351  *
352  * Function must be called in the communication reset section.
353  *
354  * @param emPr This object will be initialized.
355  * @param em Emergency object defined separately. Will be included in emPr and
356  * initialized too.
357  * @param SDO SDO server object.
358  * @param errorStatusBits Pointer to _Error Status Bits_ array from Object Dictionary
359  * (manufacturer specific section). See @ref CO_EM_errorStatusBits.
360  * @param errorStatusBitsSize Total size of the above array. Must be >= 6.
361  * @param errorRegister Pointer to _Error Register_ (Object dictionary, index 0x1001).
362  * @param preDefErr Pointer to _Pre defined error field_ array from Object
363  * dictionary, index 0x1003.
364  * @param preDefErrSize Size of the above array.
365  * @param CANdevRx CAN device for Emergency reception.
366  * @param CANdevRxIdx Index of receive buffer in the above CAN device.
367  * @param CANdevTx CAN device for Emergency transmission.
368  * @param CANdevTxIdx Index of transmit buffer in the above CAN device.
369  * @param CANidTxEM CAN identifier for Emergency message.
370  *
371  * @return #CO_ReturnError_t CO_ERROR_NO or CO_ERROR_ILLEGAL_ARGUMENT.
372  */
373 CO_ReturnError_t CO_EM_init(
374         CO_EM_t                *em,
375         CO_EMpr_t              *emPr,
376         CO_SDO_t               *SDO,
377         uint8_t                *errorStatusBits,
378         uint8_t                 errorStatusBitsSize,
379         uint8_t                *errorRegister,
380         uint32_t               *preDefErr,
381         uint8_t                 preDefErrSize,
382         CO_CANmodule_t         *CANdevRx,
383         uint16_t                CANdevRxIdx,
384         CO_CANmodule_t         *CANdevTx,
385         uint16_t                CANdevTxIdx,
386         uint16_t                CANidTxEM);
387 
388 
389 /**
390  * Initialize Emergency callback function.
391  *
392  * Function initializes optional callback function, which executes after
393  * error condition is changed. Function may wake up external task,
394  * which processes mainline CANopen functions.
395  *
396  * @param em This object.
397  * @param pFunctSignal Pointer to the callback function. Not called if NULL.
398  */
399 void CO_EM_initCallback(
400         CO_EM_t               *em,
401         void                  (*pFunctSignal)(void));
402 
403 
404 /**
405  * Initialize Emergency received callback function.
406  *
407  * Function initializes optional callback function, which executes after
408  * error condition is received. Function may wake up external task,
409  * which processes mainline CANopen functions.
410  *
411  * @remark Depending on the CAN driver implementation, this function is called
412  * inside an ISR
413  *
414  * @param em This object.
415  * @param pFunctSignal Pointer to the callback function. Not called if NULL.
416  */
417 void CO_EM_initCallbackRx(
418         CO_EM_t                *em,
419         void                  (*pFunctSignalRx)(const uint16_t ident,
420                                                 const uint16_t errorCode,
421                                                 const uint8_t errorRegister,
422                                                 const uint8_t errorBit,
423                                                 const uint32_t infoCode));
424 
425 
426 /**
427  * Process Error control and Emergency object.
428  *
429  * Function must be called cyclically. It verifies some communication errors,
430  * calculates bit 0 and bit 4 from _Error register_ and sends emergency message
431  * if necessary.
432  *
433  * @param emPr This object.
434  * @param NMTisPreOrOperational True if this node is NMT_PRE_OPERATIONAL or NMT_OPERATIONAL.
435  * @param timeDifference_100us Time difference from previous function call in [100 * microseconds].
436  * @param emInhTime _Inhibit time EMCY_ (object dictionary, index 0x1015).
437  * @param timerNext_ms Return value - info to OS - see CO_process().
438  */
439 void CO_EM_process(
440         CO_EMpr_t              *emPr,
441         bool_t                  NMTisPreOrOperational,
442         uint16_t                timeDifference_100us,
443         uint16_t                emInhTime,
444         uint16_t               *timerNext_ms);
445 
446 
447 #endif
448 
449 #ifdef __cplusplus
450 }
451 #endif /*__cplusplus*/
452 
453 /** @} */
454 #endif
455