CO_TIME.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /**
  2. * CANopen Time-stamp protocol.
  3. *
  4. * @file CO_TIME.h
  5. * @ingroup CO_TIME
  6. * @author Julien PEYREGNE
  7. * @copyright 2019 - 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_TIME_H
  26. #define CO_TIME_H
  27. #include "301/CO_driver.h"
  28. /* default configuration, see CO_config.h */
  29. #ifndef CO_CONFIG_TIME
  30. #define CO_CONFIG_TIME (0)
  31. #endif
  32. #if ((CO_CONFIG_TIME) & CO_CONFIG_TIME_ENABLE) || defined CO_DOXYGEN
  33. #ifdef __cplusplus
  34. extern "C" {
  35. #endif
  36. /**
  37. * @defgroup CO_TIME TIME
  38. * @ingroup CO_CANopen_301
  39. * @{
  40. *
  41. * CANopen Time-stamp protocol.
  42. *
  43. * For CAN identifier see #CO_Default_CAN_ID_t
  44. *
  45. * TIME message is used for time synchronization of the nodes on network. One node
  46. * should be TIME producer, others can be TIME consumers. This is configured with
  47. * COB_ID_TIME object 0x1012 :
  48. *
  49. * - bit 31 should be set for a consumer
  50. * - bit 30 should be set for a producer
  51. *
  52. *
  53. * ###TIME CONSUMER
  54. *
  55. * CO_TIME_init() configuration :
  56. * - COB_ID_TIME : 0x80000100L -> TIME consumer with TIME_COB_ID = 0x100
  57. * - TIMECyclePeriod :
  58. * - 0 -> no EMCY will be transmitted in case of TIME timeout
  59. * - X -> an EMCY will be transmitted in case of TIME timeout (X * 1.5) ms
  60. *
  61. * Latest time value is stored in \p CO->TIME->Time variable.
  62. *
  63. *
  64. * ###TIME PRODUCER
  65. *
  66. * CO_TIME_init() configuration :
  67. * - COB_ID_TIME : 0x40000100L -> TIME producer with TIME_COB_ID = 0x100
  68. * - TIMECyclePeriod : Time transmit period in ms
  69. *
  70. * Write time value in \p CO->TIME->Time variable, this will be sent at TIMECyclePeriod.
  71. */
  72. #define TIME_MSG_LENGTH 6U
  73. #ifndef timeOfDay_t
  74. typedef union {
  75. unsigned long long ullValue;
  76. struct {
  77. unsigned long ms:28;
  78. unsigned reserved:4;
  79. unsigned days:16;
  80. unsigned reserved2:16;
  81. };
  82. } timeOfDay_t;
  83. #endif
  84. typedef timeOfDay_t TIME_OF_DAY;
  85. typedef timeOfDay_t TIME_DIFFERENCE;
  86. /**
  87. * TIME producer and consumer object.
  88. */
  89. typedef struct{
  90. CO_EM_t *em; /**< From CO_TIME_init() */
  91. CO_NMT_internalState_t *operatingState; /**< From CO_TIME_init() */
  92. /** True, if device is TIME consumer. Calculated from _COB ID TIME Message_
  93. variable from Object dictionary (index 0x1012). */
  94. bool_t isConsumer;
  95. /** True, if device is TIME producer. Calculated from _COB ID TIME Message_
  96. variable from Object dictionary (index 0x1012). */
  97. bool_t isProducer;
  98. uint16_t COB_ID; /**< From CO_TIME_init() */
  99. /** TIME period time in [milliseconds]. Set to TIME period to enable
  100. timeout detection */
  101. uint32_t periodTime;
  102. /** TIME period timeout time in [milliseconds].
  103. (periodTimeoutTime = periodTime * 1,5) */
  104. uint32_t periodTimeoutTime;
  105. /** Variable indicates, if new TIME message received from CAN bus */
  106. volatile void *CANrxNew;
  107. /** Timer for the TIME message in [microseconds].
  108. Set to zero after received or transmitted TIME message */
  109. uint32_t timer;
  110. /** Set to nonzero value, if TIME with wrong data length is received from CAN */
  111. uint16_t receiveError;
  112. #if ((CO_CONFIG_TIME) & CO_CONFIG_FLAG_CALLBACK_PRE) || defined CO_DOXYGEN
  113. /** From CO_TIME_initCallbackPre() or NULL */
  114. void (*pFunctSignalPre)(void *object);
  115. /** From CO_TIME_initCallbackPre() or NULL */
  116. void *functSignalObjectPre;
  117. #endif
  118. CO_CANmodule_t *CANdevRx; /**< From CO_TIME_init() */
  119. uint16_t CANdevRxIdx; /**< From CO_TIME_init() */
  120. CO_CANmodule_t *CANdevTx; /**< From CO_TIME_init() */
  121. uint16_t CANdevTxIdx; /**< From CO_TIME_init() */
  122. CO_CANtx_t *TXbuff; /**< CAN transmit buffer */
  123. TIME_OF_DAY Time;
  124. }CO_TIME_t;
  125. /**
  126. * Initialize TIME object.
  127. *
  128. * Function must be called in the communication reset section.
  129. *
  130. * @param TIME This object will be initialized.
  131. * @param em Emergency object.
  132. * @param SDO SDO server object.
  133. * @param operatingState Pointer to variable indicating CANopen device NMT internal state.
  134. * @param COB_ID_TIMEMessage Should be intialized with CO_CAN_ID_TIME_STAMP
  135. * @param TIMECyclePeriod TIME period in ms (may also be used in consumer mode for timeout detection (1.5x period)).
  136. * @param CANdevRx CAN device for TIME reception.
  137. * @param CANdevRxIdx Index of receive buffer in the above CAN device.
  138. * @param CANdevTx CAN device for TIME transmission.
  139. * @param CANdevTxIdx Index of transmit buffer in the above CAN device.
  140. *
  141. * @return #CO_ReturnError_t: CO_ERROR_NO or CO_ERROR_ILLEGAL_ARGUMENT.
  142. */
  143. CO_ReturnError_t CO_TIME_init(
  144. CO_TIME_t *TIME,
  145. CO_EM_t *em,
  146. CO_SDO_t *SDO,
  147. CO_NMT_internalState_t *operatingState,
  148. uint32_t COB_ID_TIMEMessage,
  149. uint32_t TIMECyclePeriod,
  150. CO_CANmodule_t *CANdevRx,
  151. uint16_t CANdevRxIdx,
  152. CO_CANmodule_t *CANdevTx,
  153. uint16_t CANdevTxIdx);
  154. #if ((CO_CONFIG_TIME) & CO_CONFIG_FLAG_CALLBACK_PRE) || defined CO_DOXYGEN
  155. /**
  156. * Initialize TIME callback function.
  157. *
  158. * Function initializes optional callback function, which should immediately
  159. * start processing of CO_TIME_process() function.
  160. * Callback is called after TIME message is received from the CAN bus.
  161. *
  162. * @param TIME This object.
  163. * @param object Pointer to object, which will be passed to pFunctSignalPre(). Can be NULL
  164. * @param pFunctSignalPre Pointer to the callback function. Not called if NULL.
  165. */
  166. void CO_TIME_initCallbackPre(
  167. CO_TIME_t *TIME,
  168. void *object,
  169. void (*pFunctSignalPre)(void *object));
  170. #endif
  171. /**
  172. * Process TIME communication.
  173. *
  174. * Function must be called cyclically.
  175. *
  176. * @param TIME This object.
  177. * @param timeDifference_us Time difference from previous function call in [microseconds].
  178. *
  179. * @return 0: No special meaning.
  180. * @return 1: New TIME message recently received (consumer) / transmited (producer).
  181. */
  182. uint8_t CO_TIME_process(
  183. CO_TIME_t *TIME,
  184. uint32_t timeDifference_us);
  185. /** @} */ /* CO_TIME */
  186. #ifdef __cplusplus
  187. }
  188. #endif /*__cplusplus*/
  189. #endif /* (CO_CONFIG_TIME) & CO_CONFIG_TIME_ENABLE */
  190. #endif /* CO_TIME_H */