CO_SYNC.h 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /**
  2. * CANopen Synchronisation protocol.
  3. *
  4. * @file CO_SYNC.h
  5. * @ingroup CO_SYNC
  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_SYNC_H
  26. #define CO_SYNC_H
  27. #include "301/CO_driver.h"
  28. /* default configuration, see CO_config.h */
  29. #ifndef CO_CONFIG_SYNC
  30. #define CO_CONFIG_SYNC (CO_CONFIG_SYNC_ENABLE | CO_CONFIG_SYNC_PRODUCER)
  31. #endif
  32. #if ((CO_CONFIG_SYNC) & CO_CONFIG_SYNC_ENABLE) || defined CO_DOXYGEN
  33. #ifdef __cplusplus
  34. extern "C" {
  35. #endif
  36. /**
  37. * @defgroup CO_SYNC SYNC
  38. * @ingroup CO_CANopen_301
  39. * @{
  40. *
  41. * CANopen Synchronisation protocol.
  42. *
  43. * For CAN identifier see #CO_Default_CAN_ID_t
  44. *
  45. * SYNC message is used for synchronization of the nodes on network. One node
  46. * can be SYNC producer, others can be SYNC consumers. Synchronous TPDOs are
  47. * transmitted after the CANopen SYNC message. Synchronous received PDOs are
  48. * accepted(copied to OD) immediatelly after the reception of the next SYNC
  49. * message.
  50. *
  51. * ####Contents of SYNC message
  52. * By default SYNC message has no data. If _Synchronous counter overflow value_
  53. * from Object dictionary (index 0x1019) is different than 0, SYNC message has
  54. * one data byte: _counter_ incremented by 1 with every SYNC transmission.
  55. *
  56. * ####SYNC in CANopenNode
  57. * According to CANopen, synchronous RPDOs must be processed after reception of
  58. * the next sync messsage. For that reason, there is a double receive buffer
  59. * for each synchronous RPDO. At the moment, when SYNC is received or
  60. * transmitted, internal variable CANrxToggle toggles. That variable is then
  61. * used by synchronous RPDO to determine, which of the two buffers is used for
  62. * RPDO reception and which for RPDO processing.
  63. */
  64. /**
  65. * SYNC producer and consumer object.
  66. */
  67. typedef struct{
  68. CO_EM_t *em; /**< From CO_SYNC_init() */
  69. CO_NMT_internalState_t *operatingState; /**< From CO_SYNC_init() */
  70. /** True, if device is SYNC producer. Calculated from _COB ID SYNC Message_
  71. variable from Object dictionary (index 0x1005). */
  72. bool_t isProducer;
  73. /** COB_ID of SYNC message. Calculated from _COB ID SYNC Message_
  74. variable from Object dictionary (index 0x1005). */
  75. uint16_t COB_ID;
  76. /** Sync period time in [microseconds]. Calculated from _Communication cycle period_
  77. variable from Object dictionary (index 0x1006). */
  78. uint32_t periodTime;
  79. /** Sync period timeout time in [microseconds].
  80. (periodTimeoutTime = periodTime * 1,5) */
  81. uint32_t periodTimeoutTime;
  82. /** Value from _Synchronous counter overflow value_ variable from Object
  83. dictionary (index 0x1019) */
  84. uint8_t counterOverflowValue;
  85. /** True, if current time is inside synchronous window.
  86. In this case synchronous PDO may be sent. */
  87. bool_t curentSyncTimeIsInsideWindow;
  88. /** Indicates, if new SYNC message received from CAN bus */
  89. volatile void *CANrxNew;
  90. /** Variable toggles, if new SYNC message received from CAN bus */
  91. bool_t CANrxToggle;
  92. /** Counter of the SYNC message if counterOverflowValue is different than zero */
  93. uint8_t counter;
  94. /** Timer for the SYNC message in [microseconds].
  95. Set to zero after received or transmitted SYNC message */
  96. uint32_t timer;
  97. /** Set to nonzero value, if SYNC with wrong data length is received from CAN */
  98. uint16_t receiveError;
  99. #if ((CO_CONFIG_SYNC) & CO_CONFIG_FLAG_CALLBACK_PRE) || defined CO_DOXYGEN
  100. /** From CO_SYNC_initCallbackPre() or NULL */
  101. void (*pFunctSignalPre)(void *object);
  102. /** From CO_SYNC_initCallbackPre() or NULL */
  103. void *functSignalObjectPre;
  104. #endif
  105. CO_CANmodule_t *CANdevRx; /**< From CO_SYNC_init() */
  106. uint16_t CANdevRxIdx; /**< From CO_SYNC_init() */
  107. CO_CANmodule_t *CANdevTx; /**< From CO_SYNC_init() */
  108. CO_CANtx_t *CANtxBuff; /**< CAN transmit buffer inside CANdevTx */
  109. uint16_t CANdevTxIdx; /**< From CO_SYNC_init() */
  110. }CO_SYNC_t;
  111. /** Return value for #CO_SYNC_process */
  112. typedef enum {
  113. CO_SYNC_NONE = 0, /**< SYNC not received */
  114. CO_SYNC_RECEIVED = 1, /**< SYNC received */
  115. CO_SYNC_OUTSIDE_WINDOW = 2 /**< SYNC received outside SYNC window */
  116. } CO_SYNC_status_t;
  117. /**
  118. * Initialize SYNC object.
  119. *
  120. * Function must be called in the communication reset section.
  121. *
  122. * @param SYNC This object will be initialized.
  123. * @param em Emergency object.
  124. * @param SDO SDO server object.
  125. * @param operatingState Pointer to variable indicating CANopen device NMT internal state.
  126. * @param COB_ID_SYNCMessage From Object dictionary (index 0x1005).
  127. * @param communicationCyclePeriod From Object dictionary (index 0x1006).
  128. * @param synchronousCounterOverflowValue From Object dictionary (index 0x1019).
  129. * @param CANdevRx CAN device for SYNC reception.
  130. * @param CANdevRxIdx Index of receive buffer in the above CAN device.
  131. * @param CANdevTx CAN device for SYNC transmission.
  132. * @param CANdevTxIdx Index of transmit buffer in the above CAN device.
  133. *
  134. * @return #CO_ReturnError_t: CO_ERROR_NO or CO_ERROR_ILLEGAL_ARGUMENT.
  135. */
  136. CO_ReturnError_t CO_SYNC_init(
  137. CO_SYNC_t *SYNC,
  138. CO_EM_t *em,
  139. CO_SDO_t *SDO,
  140. CO_NMT_internalState_t *operatingState,
  141. uint32_t COB_ID_SYNCMessage,
  142. uint32_t communicationCyclePeriod,
  143. uint8_t synchronousCounterOverflowValue,
  144. CO_CANmodule_t *CANdevRx,
  145. uint16_t CANdevRxIdx,
  146. CO_CANmodule_t *CANdevTx,
  147. uint16_t CANdevTxIdx);
  148. #if ((CO_CONFIG_SYNC) & CO_CONFIG_FLAG_CALLBACK_PRE) || defined CO_DOXYGEN
  149. /**
  150. * Initialize SYNC callback function.
  151. *
  152. * Function initializes optional callback function, which should immediately
  153. * start processing of CO_SYNC_process() function.
  154. * Callback is called after SYNC message is received from the CAN bus.
  155. *
  156. * @param SYNC This object.
  157. * @param object Pointer to object, which will be passed to pFunctSignalPre(). Can be NULL
  158. * @param pFunctSignalPre Pointer to the callback function. Not called if NULL.
  159. */
  160. void CO_SYNC_initCallbackPre(
  161. CO_SYNC_t *SYNC,
  162. void *object,
  163. void (*pFunctSignalPre)(void *object));
  164. #endif
  165. /**
  166. * Send SYNC message.
  167. *
  168. * This function prepares and sends a SYNC object. The application should only
  169. * call this if direct control of SYNC transmission is needed, otherwise use
  170. * CO_SYNC_process().
  171. *
  172. *
  173. * @param SYNC SYNC object.
  174. *
  175. * @return Same as CO_CANsend().
  176. */
  177. CO_ReturnError_t CO_SYNCsend(CO_SYNC_t *SYNC);
  178. /**
  179. * Process SYNC communication.
  180. *
  181. * Function must be called cyclically.
  182. *
  183. * @param SYNC This object.
  184. * @param timeDifference_us Time difference from previous function call in [microseconds].
  185. * @param ObjDict_synchronousWindowLength _Synchronous window length_ variable from
  186. * Object dictionary (index 0x1007).
  187. * @param [out] timerNext_us info to OS - see CO_process_SYNC_PDO().
  188. *
  189. * @return #CO_SYNC_status_t: CO_SYNC_NONE, CO_SYNC_RECEIVED or CO_SYNC_OUTSIDE_WINDOW.
  190. */
  191. CO_SYNC_status_t CO_SYNC_process(
  192. CO_SYNC_t *SYNC,
  193. uint32_t timeDifference_us,
  194. uint32_t ObjDict_synchronousWindowLength,
  195. uint32_t *timerNext_us);
  196. /** @} */ /* CO_SYNC */
  197. #ifdef __cplusplus
  198. }
  199. #endif /*__cplusplus*/
  200. #endif /* (CO_CONFIG_SYNC) & CO_CONFIG_SYNC_ENABLE */
  201. #endif /* CO_SYNC_H */