CO_HBconsumer.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. /**
  2. * CANopen Heartbeat consumer protocol.
  3. *
  4. * @file CO_HBconsumer.h
  5. * @ingroup CO_HBconsumer
  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. #ifndef CO_HB_CONS_H
  26. #define CO_HB_CONS_H
  27. #include "301/CO_driver.h"
  28. /* default configuration, see CO_config.h */
  29. #ifndef CO_CONFIG_HB_CONS
  30. #define CO_CONFIG_HB_CONS (CO_CONFIG_HB_CONS_ENABLE)
  31. #endif
  32. #if ((CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_ENABLE) || defined CO_DOXYGEN
  33. #ifdef __cplusplus
  34. extern "C" {
  35. #endif
  36. /**
  37. * @defgroup CO_HBconsumer Heartbeat consumer
  38. * @ingroup CO_CANopen_301
  39. * @{
  40. *
  41. * CANopen Heartbeat consumer protocol.
  42. *
  43. * Heartbeat consumer monitors Heartbeat messages from remote nodes. If any
  44. * monitored node don't send his Heartbeat in specified time, Heartbeat consumer
  45. * sends emergency message. If all monitored nodes are operational, then
  46. * variable _allMonitoredOperational_ inside CO_HBconsumer_t is set to true.
  47. * Monitoring starts after the reception of the first HeartBeat (not bootup).
  48. *
  49. * Heartbeat set up is done by writing to the OD registers 0x1016 or by using
  50. * the function _CO_HBconsumer_initEntry()_
  51. *
  52. * @see @ref CO_NMT_Heartbeat
  53. */
  54. /**
  55. * Heartbeat state of a node
  56. */
  57. typedef enum {
  58. CO_HBconsumer_UNCONFIGURED = 0x00U, /**< Consumer entry inactive */
  59. CO_HBconsumer_UNKNOWN = 0x01U, /**< Consumer enabled, but no heartbeat received yet */
  60. CO_HBconsumer_ACTIVE = 0x02U, /**< Heartbeat received within set time */
  61. CO_HBconsumer_TIMEOUT = 0x03U, /**< No heatbeat received for set time */
  62. } CO_HBconsumer_state_t;
  63. /**
  64. * One monitored node inside CO_HBconsumer_t.
  65. */
  66. typedef struct {
  67. /** Node Id of the monitored node */
  68. uint8_t nodeId;
  69. /** Of the remote node (Heartbeat payload) */
  70. CO_NMT_internalState_t NMTstate;
  71. /** Current heartbeat state */
  72. CO_HBconsumer_state_t HBstate;
  73. /** Time since last heartbeat received */
  74. uint32_t timeoutTimer;
  75. /** Consumer heartbeat time from OD */
  76. uint32_t time_us;
  77. /** Indication if new Heartbeat message received from the CAN bus */
  78. volatile void *CANrxNew;
  79. #if ((CO_CONFIG_HB_CONS) & CO_CONFIG_FLAG_CALLBACK_PRE) || defined CO_DOXYGEN
  80. /** From CO_HBconsumer_initCallbackPre() or NULL */
  81. void (*pFunctSignalPre)(void *object);
  82. /** From CO_HBconsumer_initCallbackPre() or NULL */
  83. void *functSignalObjectPre;
  84. #endif
  85. #if ((CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_CHANGE) \
  86. || ((CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_MULTI) \
  87. || defined CO_DOXYGEN
  88. /** Previous value of the remote node (Heartbeat payload) */
  89. CO_NMT_internalState_t NMTstatePrev;
  90. #endif
  91. #if ((CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_MULTI) || defined CO_DOXYGEN
  92. /** Callback for remote NMT changed event.
  93. * From CO_HBconsumer_initCallbackNmtChanged() or NULL. */
  94. void (*pFunctSignalNmtChanged)(uint8_t nodeId, uint8_t idx,
  95. CO_NMT_internalState_t state,
  96. void *object);
  97. /** Pointer to object */
  98. void *pFunctSignalObjectNmtChanged;
  99. /** Callback for heartbeat state change to active event.
  100. * From CO_HBconsumer_initCallbackHeartbeatStarted() or NULL. */
  101. void (*pFunctSignalHbStarted)(uint8_t nodeId, uint8_t idx, void *object);
  102. /** Pointer to object */
  103. void *functSignalObjectHbStarted;
  104. /** Callback for consumer timeout event.
  105. * From CO_HBconsumer_initCallbackTimeout() or NULL. */
  106. void (*pFunctSignalTimeout)(uint8_t nodeId, uint8_t idx, void *object);
  107. /** Pointer to object */
  108. void *functSignalObjectTimeout;
  109. /** Callback for remote reset event.
  110. * From CO_HBconsumer_initCallbackRemoteReset() or NULL. */
  111. void (*pFunctSignalRemoteReset)(uint8_t nodeId, uint8_t idx, void *object);
  112. /** Pointer to object */
  113. void *functSignalObjectRemoteReset;
  114. #endif
  115. } CO_HBconsNode_t;
  116. /**
  117. * Heartbeat consumer object.
  118. *
  119. * Object is initilaized by CO_HBconsumer_init(). It contains an array of
  120. * CO_HBconsNode_t objects.
  121. */
  122. typedef struct{
  123. CO_EM_t *em; /**< From CO_HBconsumer_init() */
  124. const uint32_t *HBconsTime; /**< From CO_HBconsumer_init() */
  125. CO_HBconsNode_t *monitoredNodes; /**< From CO_HBconsumer_init() */
  126. uint8_t numberOfMonitoredNodes; /**< From CO_HBconsumer_init() */
  127. /** True, if all monitored nodes are active or no node is
  128. monitored. Can be read by the application */
  129. bool_t allMonitoredActive;
  130. /** True, if all monitored nodes are NMT operational or no node is
  131. monitored. Can be read by the application */
  132. uint8_t allMonitoredOperational;
  133. bool_t NMTisPreOrOperationalPrev; /**< previous state of var */
  134. CO_CANmodule_t *CANdevRx; /**< From CO_HBconsumer_init() */
  135. uint16_t CANdevRxIdxStart; /**< From CO_HBconsumer_init() */
  136. #if ((CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_CHANGE) || defined CO_DOXYGEN
  137. /** Callback for remote NMT changed event.
  138. * From CO_HBconsumer_initCallbackNmtChanged() or NULL. */
  139. void (*pFunctSignalNmtChanged)(uint8_t nodeId, uint8_t idx,
  140. CO_NMT_internalState_t state,
  141. void *object);
  142. /** Pointer to object */
  143. void *pFunctSignalObjectNmtChanged;
  144. #endif
  145. }CO_HBconsumer_t;
  146. /**
  147. * Initialize Heartbeat consumer object.
  148. *
  149. * Function must be called in the communication reset section.
  150. *
  151. * @param HBcons This object will be initialized.
  152. * @param em Emergency object.
  153. * @param SDO SDO server object.
  154. * @param HBconsTime Pointer to _Consumer Heartbeat Time_ array
  155. * from Object Dictionary (index 0x1016). Size of array is equal to numberOfMonitoredNodes.
  156. * @param monitoredNodes Pointer to the externaly defined array of the same size
  157. * as numberOfMonitoredNodes.
  158. * @param numberOfMonitoredNodes Total size of the above arrays.
  159. * @param CANdevRx CAN device for Heartbeat reception.
  160. * @param CANdevRxIdxStart Starting index of receive buffer in the above CAN device.
  161. * Number of used indexes is equal to numberOfMonitoredNodes.
  162. *
  163. * @return #CO_ReturnError_t CO_ERROR_NO or CO_ERROR_ILLEGAL_ARGUMENT.
  164. */
  165. CO_ReturnError_t CO_HBconsumer_init(
  166. CO_HBconsumer_t *HBcons,
  167. CO_EM_t *em,
  168. CO_SDO_t *SDO,
  169. const uint32_t HBconsTime[],
  170. CO_HBconsNode_t monitoredNodes[],
  171. uint8_t numberOfMonitoredNodes,
  172. CO_CANmodule_t *CANdevRx,
  173. uint16_t CANdevRxIdxStart);
  174. /**
  175. * Initialize one Heartbeat consumer entry
  176. *
  177. * Calling this function has the same affect as writing to the corresponding
  178. * entries in the Object Dictionary (index 0x1016)
  179. * @remark The values in the Object Dictionary must be set manually by the
  180. * calling function so that heartbeat consumer behaviour matches the OD value.
  181. *
  182. * @param HBcons This object.
  183. * @param idx index of the node in HBcons object
  184. * @param nodeId see OD 0x1016 description
  185. * @param consumerTime_ms in milliseconds. see OD 0x1016 description
  186. * @return
  187. */
  188. CO_ReturnError_t CO_HBconsumer_initEntry(
  189. CO_HBconsumer_t *HBcons,
  190. uint8_t idx,
  191. uint8_t nodeId,
  192. uint16_t consumerTime_ms);
  193. #if ((CO_CONFIG_HB_CONS) & CO_CONFIG_FLAG_CALLBACK_PRE) || defined CO_DOXYGEN
  194. /**
  195. * Initialize Heartbeat consumer callback function.
  196. *
  197. * Function initializes optional callback function, which should immediately
  198. * start processing of CO_HBconsumer_process() function.
  199. * Callback is called after HBconsumer message is received from the CAN bus.
  200. *
  201. * @param HBcons This object.
  202. * @param object Pointer to object, which will be passed to pFunctSignal(). Can be NULL
  203. * @param pFunctSignal Pointer to the callback function. Not called if NULL.
  204. */
  205. void CO_HBconsumer_initCallbackPre(
  206. CO_HBconsumer_t *HBcons,
  207. void *object,
  208. void (*pFunctSignal)(void *object));
  209. #endif
  210. #if ((CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_CHANGE) \
  211. || ((CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_MULTI) \
  212. || defined CO_DOXYGEN
  213. /**
  214. * Initialize Heartbeat consumer NMT changed callback function.
  215. *
  216. * Function initializes optional callback function, which is called when NMT
  217. * state from the remote node changes.
  218. *
  219. * @param HBcons This object.
  220. * @param idx index of the node in HBcons object (only when
  221. * CO_CONFIG_HB_CONS_CALLBACK_MULTI is enabled)
  222. * @param object Pointer to object, which will be passed to pFunctSignal().
  223. * Can be NULL.
  224. * @param pFunctSignal Pointer to the callback function. Not called if NULL.
  225. */
  226. void CO_HBconsumer_initCallbackNmtChanged(
  227. CO_HBconsumer_t *HBcons,
  228. #if ((CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_MULTI) || defined CO_DOXYGEN
  229. uint8_t idx,
  230. #endif
  231. void *object,
  232. void (*pFunctSignal)(uint8_t nodeId, uint8_t idx,
  233. CO_NMT_internalState_t state,
  234. void *object));
  235. #endif
  236. #if ((CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_MULTI) || defined CO_DOXYGEN
  237. /**
  238. * Initialize Heartbeat consumer started callback function.
  239. *
  240. * Function initializes optional callback function, which is called for the
  241. * first received heartbeat after activating hb consumer or timeout.
  242. * Function may wake up external task, which handles this event.
  243. *
  244. * @param HBcons This object.
  245. * @param idx index of the node in HBcons object
  246. * @param object Pointer to object, which will be passed to pFunctSignal(). Can be NULL
  247. * @param pFunctSignal Pointer to the callback function. Not called if NULL.
  248. */
  249. void CO_HBconsumer_initCallbackHeartbeatStarted(
  250. CO_HBconsumer_t *HBcons,
  251. uint8_t idx,
  252. void *object,
  253. void (*pFunctSignal)(uint8_t nodeId, uint8_t idx, void *object));
  254. /**
  255. * Initialize Heartbeat consumer timeout callback function.
  256. *
  257. * Function initializes optional callback function, which is called when the node
  258. * state changes from active to timeout. Function may wake up external task,
  259. * which handles this event.
  260. *
  261. * @param HBcons This object.
  262. * @param idx index of the node in HBcons object
  263. * @param object Pointer to object, which will be passed to pFunctSignal(). Can be NULL
  264. * @param pFunctSignal Pointer to the callback function. Not called if NULL.
  265. */
  266. void CO_HBconsumer_initCallbackTimeout(
  267. CO_HBconsumer_t *HBcons,
  268. uint8_t idx,
  269. void *object,
  270. void (*pFunctSignal)(uint8_t nodeId, uint8_t idx, void *object));
  271. /**
  272. * Initialize Heartbeat consumer remote reset detected callback function.
  273. *
  274. * Function initializes optional callback function, which is called when a bootup
  275. * message is received from the remote node. Function may wake up external task,
  276. * which handles this event.
  277. *
  278. * @param HBcons This object.
  279. * @param idx index of the node in HBcons object
  280. * @param object Pointer to object, which will be passed to pFunctSignal(). Can be NULL
  281. * @param pFunctSignal Pointer to the callback function. Not called if NULL.
  282. */
  283. void CO_HBconsumer_initCallbackRemoteReset(
  284. CO_HBconsumer_t *HBcons,
  285. uint8_t idx,
  286. void *object,
  287. void (*pFunctSignal)(uint8_t nodeId, uint8_t idx, void *object));
  288. #endif /* (CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_MULTI */
  289. /**
  290. * Process Heartbeat consumer object.
  291. *
  292. * Function must be called cyclically.
  293. *
  294. * @param HBcons This object.
  295. * @param NMTisPreOrOperational True if this node is NMT_PRE_OPERATIONAL or NMT_OPERATIONAL.
  296. * @param timeDifference_us Time difference from previous function call in [microseconds].
  297. * @param [out] timerNext_us info to OS - see CO_process().
  298. */
  299. void CO_HBconsumer_process(
  300. CO_HBconsumer_t *HBcons,
  301. bool_t NMTisPreOrOperational,
  302. uint32_t timeDifference_us,
  303. uint32_t *timerNext_us);
  304. #if ((CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_QUERY_FUNCT) || defined CO_DOXYGEN
  305. /**
  306. * Get the heartbeat producer object index by node ID
  307. *
  308. * @param HBcons This object.
  309. * @param nodeId producer node ID
  310. * @return index. -1 if not found
  311. */
  312. int8_t CO_HBconsumer_getIdxByNodeId(
  313. CO_HBconsumer_t *HBcons,
  314. uint8_t nodeId);
  315. /**
  316. * Get the current state of a heartbeat producer by the index in OD 0x1016
  317. *
  318. * @param HBcons This object.
  319. * @param idx object sub index
  320. * @return #CO_HBconsumer_state_t
  321. */
  322. CO_HBconsumer_state_t CO_HBconsumer_getState(
  323. CO_HBconsumer_t *HBcons,
  324. uint8_t idx);
  325. /**
  326. * Get the current NMT state of a heartbeat producer by the index in OD 0x1016
  327. *
  328. * NMT state is only available when heartbeat is enabled for this index!
  329. *
  330. * @param HBcons This object.
  331. * @param idx object sub index
  332. * @param [out] nmtState of this index
  333. * @retval 0 NMT state has been received and is valid
  334. * @retval -1 not valid
  335. */
  336. int8_t CO_HBconsumer_getNmtState(
  337. CO_HBconsumer_t *HBcons,
  338. uint8_t idx,
  339. CO_NMT_internalState_t *nmtState);
  340. #endif /* (CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_QUERY_FUNCT */
  341. /** @} */ /* CO_HBconsumer */
  342. #ifdef __cplusplus
  343. }
  344. #endif /*__cplusplus*/
  345. #endif /* (CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_ENABLE */
  346. #endif /* CO_HB_CONS_H */