CO_LSSslave.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. /**
  2. * CANopen Layer Setting Service - slave protocol.
  3. *
  4. * @file CO_LSSslave.h
  5. * @ingroup CO_LSS
  6. * @author Martin Wagner
  7. * @author Janez Paternoster
  8. * @copyright 2017 - 2020 Neuberger Gebaeudeautomation GmbH
  9. *
  10. *
  11. * This file is part of CANopenNode, an opensource CANopen Stack.
  12. * Project home page is <https://github.com/CANopenNode/CANopenNode>.
  13. * For more information on CANopen see <http://www.can-cia.org/>.
  14. *
  15. * Licensed under the Apache License, Version 2.0 (the "License");
  16. * you may not use this file except in compliance with the License.
  17. * You may obtain a copy of the License at
  18. *
  19. * http://www.apache.org/licenses/LICENSE-2.0
  20. *
  21. * Unless required by applicable law or agreed to in writing, software
  22. * distributed under the License is distributed on an "AS IS" BASIS,
  23. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  24. * See the License for the specific language governing permissions and
  25. * limitations under the License.
  26. */
  27. #ifndef CO_LSSslave_H
  28. #define CO_LSSslave_H
  29. #include "305/CO_LSS.h"
  30. #if ((CO_CONFIG_LSS) & CO_CONFIG_LSS_SLAVE) || defined CO_DOXYGEN
  31. #ifdef __cplusplus
  32. extern "C" {
  33. #endif
  34. /**
  35. * @defgroup CO_LSSslave LSS Slave
  36. * @ingroup CO_CANopen_305
  37. * @{
  38. *
  39. * CANopen Layer Setting Service - slave protocol.
  40. *
  41. * The slave provides the following services
  42. * - node selection via LSS address
  43. * - node selection via LSS fastscan
  44. * - Inquire LSS address of currently selected node
  45. * - Inquire node ID
  46. * - Configure bit timing
  47. * - Configure node ID
  48. * - Activate bit timing parameters
  49. * - Store configuration (bit rate and node ID)
  50. *
  51. * After CAN module start, the LSS slave and NMT slave are started and then
  52. * coexist alongside each other. To achieve this behaviour, the CANopen node
  53. * startup process has to be controlled more detailed. Therefore, CO_LSSinit()
  54. * must be invoked between CO_CANinit() and CO_CANopenInit() in the
  55. * communication reset section.
  56. *
  57. * Moreover, the LSS slave needs to pause the NMT slave initialization in case
  58. * no valid node ID is available at start up. In that case CO_CANopenInit()
  59. * skips initialization of other CANopen modules and CO_process() skips
  60. * processing of other modules than LSS slave automatically.
  61. *
  62. * Variables for CAN-bitrate and CANopen node-id must be initialized by
  63. * application from non-volatile memory or dip switches. Pointers to them are
  64. * passed to CO_LSSinit() function. Those variables represents pending values.
  65. * If node-id is valid in the moment it enters CO_LSSinit(), it also becomes
  66. * active node-id and the stack initialises normally. Otherwise, node-id must be
  67. * configured by lss and after successful configuration stack passes reset
  68. * communication autonomously.
  69. *
  70. * Device with all threads can be normally initialized and running despite that
  71. * node-id is not valid. Application must take care, because CANopen is not
  72. * initialized. In that case CO_CANopenInit() returns error condition
  73. * CO_ERROR_NODE_ID_UNCONFIGURED_LSS which must be handled properly. Status can
  74. * also be checked with CO->nodeIdUnconfigured variable.
  75. *
  76. * Some callback functions may be initialized by application with
  77. * CO_LSSslave_initCheckBitRateCallback(),
  78. * CO_LSSslave_initActivateBitRateCallback() and
  79. * CO_LSSslave_initCfgStoreCallback().
  80. */
  81. /**
  82. * LSS slave object.
  83. */
  84. typedef struct{
  85. CO_LSS_address_t lssAddress; /**< From #CO_LSSslave_init */
  86. CO_LSS_state_t lssState; /**< #CO_LSS_state_t */
  87. CO_LSS_address_t lssSelect; /**< Received LSS Address by select */
  88. CO_LSS_address_t lssFastscan; /**< Received LSS Address by fastscan */
  89. uint8_t fastscanPos; /**< Current state of fastscan */
  90. uint16_t *pendingBitRate; /**< Bit rate value that is temporarily configured */
  91. uint8_t *pendingNodeID; /**< Node ID that is temporarily configured */
  92. uint8_t activeNodeID; /**< Node ID used at the CAN interface */
  93. volatile void *sendResponse; /**< Variable indicates, if LSS response has to be sent by mainline processing function */
  94. CO_LSS_cs_t service; /**< Service, which will have to be processed by mainline processing function */
  95. uint8_t CANdata[8]; /**< Received CAN data, which will be processed by mainline processing function */
  96. #if ((CO_CONFIG_LSS) & CO_CONFIG_FLAG_CALLBACK_PRE) || defined CO_DOXYGEN
  97. void (*pFunctSignalPre)(void *object); /**< From CO_LSSslave_initCallbackPre() or NULL */
  98. void *functSignalObjectPre;/**< Pointer to object */
  99. #endif
  100. bool_t (*pFunctLSScheckBitRate)(void *object, uint16_t bitRate); /**< From CO_LSSslave_initCheckBitRateCallback() or NULL */
  101. void *functLSScheckBitRateObject; /** Pointer to object */
  102. void (*pFunctLSSactivateBitRate)(void *object, uint16_t delay); /**< From CO_LSSslave_initActivateBitRateCallback() or NULL. Delay is in ms */
  103. void *functLSSactivateBitRateObject; /** Pointer to object */
  104. bool_t (*pFunctLSScfgStore)(void *object, uint8_t id, uint16_t bitRate); /**< From CO_LSSslave_initCfgStoreCallback() or NULL */
  105. void *functLSScfgStoreObject; /** Pointer to object */
  106. CO_CANmodule_t *CANdevTx; /**< From #CO_LSSslave_init() */
  107. CO_CANtx_t *TXbuff; /**< CAN transmit buffer */
  108. }CO_LSSslave_t;
  109. /**
  110. * Initialize LSS object.
  111. *
  112. * Function must be called in the communication reset section.
  113. *
  114. * pendingBitRate and pendingNodeID must be pointers to external variables. Both
  115. * variables must be initialized on program startup (after #CO_NMT_RESET_NODE)
  116. * from non-volatile memory, dip switches or similar. They must not change
  117. * during #CO_NMT_RESET_COMMUNICATION. Both variables can be changed by
  118. * CO_LSSslave_process(), depending on commands from the LSS master.
  119. *
  120. * If pendingNodeID is valid (1 <= pendingNodeID <= 0x7F), then this becomes
  121. * valid active nodeId just after exit of this function. In that case all other
  122. * CANopen objects may be initialized and processed in run time.
  123. *
  124. * If pendingNodeID is not valid (pendingNodeID == 0xFF), then only LSS slave is
  125. * initialized and processed in run time. In that state pendingNodeID can be
  126. * configured and after successful configuration reset communication with all
  127. * CANopen object is activated automatically.
  128. *
  129. * @remark The LSS address needs to be unique on the network. For this, the 128
  130. * bit wide identity object (1018h) is used. Therefore, this object has to be
  131. * fully initialized before passing it to this function (vendorID, product
  132. * code, revisionNo, serialNo are set to 0 by default). Otherwise, if
  133. * non-configured devices are present on CANopen network, LSS configuration may
  134. * behave unpredictable.
  135. *
  136. * @param LSSslave This object will be initialized.
  137. * @param lssAddress LSS address
  138. * @param [in,out] pendingBitRate Pending bit rate of the CAN interface
  139. * @param [in,out] pendingNodeID Pending node ID or 0xFF - invalid
  140. * @param CANdevRx CAN device for LSS slave reception.
  141. * @param CANdevRxIdx Index of receive buffer in the above CAN device.
  142. * @param CANidLssMaster COB ID for reception.
  143. * @param CANdevTx CAN device for LSS slave transmission.
  144. * @param CANdevTxIdx Index of transmit buffer in the above CAN device.
  145. * @param CANidLssSlave COB ID for transmission.
  146. * @return #CO_ReturnError_t: CO_ERROR_NO or CO_ERROR_ILLEGAL_ARGUMENT.
  147. */
  148. CO_ReturnError_t CO_LSSslave_init(
  149. CO_LSSslave_t *LSSslave,
  150. CO_LSS_address_t *lssAddress,
  151. uint16_t *pendingBitRate,
  152. uint8_t *pendingNodeID,
  153. CO_CANmodule_t *CANdevRx,
  154. uint16_t CANdevRxIdx,
  155. uint32_t CANidLssMaster,
  156. CO_CANmodule_t *CANdevTx,
  157. uint16_t CANdevTxIdx,
  158. uint32_t CANidLssSlave);
  159. /**
  160. * Process LSS communication
  161. *
  162. * Object is partially pre-processed after LSS message received. Further
  163. * processing is inside this function.
  164. *
  165. * In case that Node-Id is unconfigured, then this function may request CANopen
  166. * communication reset. This happens, when valid node-id is configured by LSS
  167. * master.
  168. *
  169. * @param LSSslave This object.
  170. * @return True, if #CO_NMT_RESET_COMMUNICATION is requested
  171. */
  172. bool_t CO_LSSslave_process(CO_LSSslave_t *LSSslave);
  173. /**
  174. * Get current LSS state
  175. *
  176. * @param LSSslave This object.
  177. * @return #CO_LSS_state_t
  178. */
  179. static inline CO_LSS_state_t CO_LSSslave_getState(CO_LSSslave_t *LSSslave) {
  180. return (LSSslave == NULL) ? CO_LSS_STATE_WAITING : LSSslave->lssState;
  181. }
  182. #if ((CO_CONFIG_LSS) & CO_CONFIG_FLAG_CALLBACK_PRE) || defined CO_DOXYGEN
  183. /**
  184. * Initialize LSSslaveRx callback function.
  185. *
  186. * Function initializes optional callback function, which should immediately
  187. * start further LSS processing. Callback is called after LSS message is
  188. * received from the CAN bus. It should signal the RTOS to resume corresponding
  189. * task.
  190. *
  191. * @param LSSslave This object.
  192. * @param object Pointer to object, which will be passed to pFunctSignal(). Can be NULL
  193. * @param pFunctSignalPre Pointer to the callback function. Not called if NULL.
  194. */
  195. void CO_LSSslave_initCallbackPre(
  196. CO_LSSslave_t *LSSslave,
  197. void *object,
  198. void (*pFunctSignalPre)(void *object));
  199. #endif
  200. /**
  201. * Initialize verify bit rate callback
  202. *
  203. * Function initializes callback function, which is called when "config bit
  204. * timing parameters" is used. The callback function needs to check if the new bit
  205. * rate is supported by the CANopen device. Callback returns "true" if supported.
  206. * When no callback is set the LSS slave will no-ack the request, indicating to
  207. * the master that bit rate change is not supported.
  208. *
  209. * @param LSSslave This object.
  210. * @param object Pointer to object, which will be passed to pFunctLSScheckBitRate(). Can be NULL
  211. * @param pFunctLSScheckBitRate Pointer to the callback function. Not called if NULL.
  212. */
  213. void CO_LSSslave_initCheckBitRateCallback(
  214. CO_LSSslave_t *LSSslave,
  215. void *object,
  216. bool_t (*pFunctLSScheckBitRate)(void *object, uint16_t bitRate));
  217. /**
  218. * Initialize activate bit rate callback
  219. *
  220. * Function initializes callback function, which is called when "activate bit
  221. * timing parameters" is used. The callback function gives the user an event to
  222. * allow setting a timer or do calculations based on the exact time the request
  223. * arrived.
  224. * According to DSP 305 6.4.4, the delay has to be applied once before and once after
  225. * switching bit rates. During this time, a device mustn't send any messages.
  226. *
  227. * @param LSSslave This object.
  228. * @param object Pointer to object, which will be passed to pFunctLSSactivateBitRate(). Can be NULL
  229. * @param pFunctLSSactivateBitRate Pointer to the callback function. Not called if NULL.
  230. */
  231. void CO_LSSslave_initActivateBitRateCallback(
  232. CO_LSSslave_t *LSSslave,
  233. void *object,
  234. void (*pFunctLSSactivateBitRate)(void *object, uint16_t delay));
  235. /**
  236. * Store configuration callback
  237. *
  238. * Function initializes callback function, which is called when "store configuration" is used.
  239. * The callback function gives the user an event to store the corresponding node id and bit rate
  240. * to NVM. Those values have to be supplied to the init function as "persistent values"
  241. * after reset. If callback returns "true", success is send to the LSS master. When no
  242. * callback is set the LSS slave will no-ack the request, indicating to the master
  243. * that storing is not supported.
  244. *
  245. * @param LSSslave This object.
  246. * @param object Pointer to object, which will be passed to pFunctLSScfgStore(). Can be NULL
  247. * @param pFunctLSScfgStore Pointer to the callback function. Not called if NULL.
  248. */
  249. void CO_LSSslave_initCfgStoreCallback(
  250. CO_LSSslave_t *LSSslave,
  251. void *object,
  252. bool_t (*pFunctLSScfgStore)(void *object, uint8_t id, uint16_t bitRate));
  253. /** @} */ /*@defgroup CO_LSSslave*/
  254. #ifdef __cplusplus
  255. }
  256. #endif /*__cplusplus*/
  257. #endif /* (CO_CONFIG_LSS) & CO_CONFIG_LSS_SLAVE */
  258. #endif /*CO_LSSslave_H*/