CO_SDOclient.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. /**
  2. * CANopen Service Data Object - client protocol.
  3. *
  4. * @file CO_SDOclient.h
  5. * @ingroup CO_SDOclient
  6. * @author Janez Paternoster
  7. * @author Matej Severkar
  8. * @copyright 2020 Janez Paternoster
  9. *
  10. * This file is part of CANopenNode, an opensource CANopen Stack.
  11. * Project home page is <https://github.com/CANopenNode/CANopenNode>.
  12. * For more information on CANopen see <http://www.can-cia.org/>.
  13. *
  14. * Licensed under the Apache License, Version 2.0 (the "License");
  15. * you may not use this file except in compliance with the License.
  16. * You may obtain a copy of the License at
  17. *
  18. * http://www.apache.org/licenses/LICENSE-2.0
  19. *
  20. * Unless required by applicable law or agreed to in writing, software
  21. * distributed under the License is distributed on an "AS IS" BASIS,
  22. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  23. * See the License for the specific language governing permissions and
  24. * limitations under the License.
  25. */
  26. #ifndef CO_SDO_CLIENT_H
  27. #define CO_SDO_CLIENT_H
  28. #include "301/CO_driver.h"
  29. #include "301/CO_SDOserver.h"
  30. #include "301/CO_fifo.h"
  31. /* default configuration, see CO_config.h */
  32. #ifndef CO_CONFIG_SDO_CLI
  33. #define CO_CONFIG_SDO_CLI (0)
  34. #endif
  35. #ifndef CO_CONFIG_SDO_CLI_BUFFER_SIZE
  36. #if (CO_CONFIG_SDO_CLI) & CO_CONFIG_SDO_CLI_BLOCK
  37. #define CO_CONFIG_SDO_CLI_BUFFER_SIZE 1000
  38. #else
  39. #define CO_CONFIG_SDO_CLI_BUFFER_SIZE 32
  40. #endif
  41. #endif
  42. #if ((CO_CONFIG_SDO_CLI) & CO_CONFIG_SDO_CLI_ENABLE) || defined CO_DOXYGEN
  43. #ifdef __cplusplus
  44. extern "C" {
  45. #endif
  46. /**
  47. * @defgroup CO_SDOclient SDO client
  48. * @ingroup CO_CANopen_301
  49. * @{
  50. *
  51. * CANopen Service Data Object - client protocol (master functionality).
  52. *
  53. * @see @ref CO_SDOserver
  54. */
  55. /**
  56. * SDO Client Parameter. The same as record from Object dictionary
  57. * (index 0x1280+).
  58. */
  59. typedef struct {
  60. /** Equal to 3 */
  61. uint8_t maxSubIndex;
  62. /** Communication object identifier for client transmission.
  63. * Meaning of the specific bits:
  64. - Bit 0...10: 11-bit CAN identifier.
  65. - Bit 11..30: reserved, set to 0.
  66. - Bit 31: if 1, SDO client object is not used. */
  67. uint32_t COB_IDClientToServer;
  68. /** Communication object identifier for message received from server.
  69. * Meaning of the specific bits:
  70. - Bit 0...10: 11-bit CAN identifier.
  71. - Bit 11..30: reserved, set to 0.
  72. - Bit 31: if 1, SDO client object is not used. */
  73. uint32_t COB_IDServerToClient;
  74. /** Node-ID of the SDO server */
  75. uint8_t nodeIDOfTheSDOServer;
  76. } CO_SDOclientPar_t;
  77. /**
  78. * SDO client object
  79. */
  80. typedef struct {
  81. #if ((CO_CONFIG_SDO_CLI) & CO_CONFIG_SDO_CLI_LOCAL) || defined CO_DOXYGEN
  82. /** From CO_SDOclient_init() */
  83. CO_SDO_t *SDO;
  84. #endif
  85. /** From CO_SDOclient_init() */
  86. CO_SDOclientPar_t *SDOClientPar;
  87. /** From CO_SDOclient_init() */
  88. CO_CANmodule_t *CANdevRx;
  89. /** From CO_SDOclient_init() */
  90. uint16_t CANdevRxIdx;
  91. /** From CO_SDOclient_init() */
  92. CO_CANmodule_t *CANdevTx;
  93. /** From CO_SDOclient_init() */
  94. uint16_t CANdevTxIdx;
  95. /** CAN transmit buffer inside CANdevTx for CAN tx message */
  96. CO_CANtx_t *CANtxBuff;
  97. /** Index of current object in Object Dictionary */
  98. uint16_t index;
  99. /** Subindex of current object in Object Dictionary */
  100. uint8_t subIndex;
  101. /* If true, then data transfer is finished */
  102. bool_t finished;
  103. /** Size of data, which will be transferred. It is optionally indicated by
  104. * client in case of download or by server in case of upload. */
  105. size_t sizeInd;
  106. /** Size of data which is actually transferred. */
  107. size_t sizeTran;
  108. /** Internal state of the SDO client */
  109. volatile CO_SDO_state_t state;
  110. /** Maximum timeout time between request and response in microseconds */
  111. uint32_t SDOtimeoutTime_us;
  112. /** Timeout timer for SDO communication */
  113. uint32_t timeoutTimer;
  114. /** CO_fifo_t object for data buffer (not pointer) */
  115. CO_fifo_t bufFifo;
  116. /** Data buffer of usable size @ref CO_CONFIG_SDO_CLI_BUFFER_SIZE, used
  117. * inside bufFifo. Must be one byte larger for fifo usage. */
  118. char buf[CO_CONFIG_SDO_CLI_BUFFER_SIZE + 1];
  119. /** Indicates, if new SDO message received from CAN bus. It is not cleared,
  120. * until received message is completely processed. */
  121. volatile void *CANrxNew;
  122. /** 8 data bytes of the received message */
  123. uint8_t CANrxData[8];
  124. /** Previous value of the COB_IDClientToServer */
  125. uint32_t COB_IDClientToServerPrev;
  126. /** Previous value of the COB_IDServerToClient */
  127. uint32_t COB_IDServerToClientPrev;
  128. #if ((CO_CONFIG_SDO_CLI) & CO_CONFIG_FLAG_CALLBACK_PRE) || defined CO_DOXYGEN
  129. /** From CO_SDOclient_initCallbackPre() or NULL */
  130. void (*pFunctSignal)(void *object);
  131. /** From CO_SDOclient_initCallbackPre() or NULL */
  132. void *functSignalObject;
  133. #endif
  134. #if ((CO_CONFIG_SDO_CLI) & CO_CONFIG_SDO_CLI_SEGMENTED) || defined CO_DOXYGEN
  135. /** Toggle bit toggled in each segment in segmented transfer */
  136. uint8_t toggle;
  137. #endif
  138. #if ((CO_CONFIG_SDO_CLI) & CO_CONFIG_SDO_CLI_BLOCK) || defined CO_DOXYGEN
  139. /** Timeout time for SDO sub-block upload, half of #SDOtimeoutTime_us */
  140. uint32_t block_SDOtimeoutTime_us;
  141. /** Timeout timer for SDO sub-block upload */
  142. uint32_t block_timeoutTimer;
  143. /** Sequence number of segment in block, 1..127 */
  144. uint8_t block_seqno;
  145. /** Number of segments per block, 1..127 */
  146. uint8_t block_blksize;
  147. /** Number of bytes in last segment that do not contain data */
  148. uint8_t block_noData;
  149. /** Server CRC support in block transfer */
  150. bool_t block_crcEnabled;
  151. /** Last 7 bytes of data at block upload */
  152. uint8_t block_dataUploadLast[7];
  153. /** Calculated CRC checksum */
  154. uint16_t block_crc;
  155. #endif
  156. } CO_SDOclient_t;
  157. /**
  158. * Initialize SDO client object.
  159. *
  160. * Function must be called in the communication reset section.
  161. *
  162. * @param SDO_C This object will be initialized.
  163. * @param SDO SDO server object. It is used in case, if client is accessing
  164. * object dictionary from its own device. If NULL, it will be ignored.
  165. * @param SDOClientPar Pointer to _SDO Client Parameter_ record from Object
  166. * dictionary (index 0x1280+). Will be written.
  167. * @param CANdevRx CAN device for SDO client reception.
  168. * @param CANdevRxIdx Index of receive buffer in the above CAN device.
  169. * @param CANdevTx CAN device for SDO client transmission.
  170. * @param CANdevTxIdx Index of transmit buffer in the above CAN device.
  171. *
  172. * @return #CO_ReturnError_t: CO_ERROR_NO or CO_ERROR_ILLEGAL_ARGUMENT.
  173. */
  174. CO_ReturnError_t CO_SDOclient_init(CO_SDOclient_t *SDO_C,
  175. void *SDO,
  176. CO_SDOclientPar_t *SDOClientPar,
  177. CO_CANmodule_t *CANdevRx,
  178. uint16_t CANdevRxIdx,
  179. CO_CANmodule_t *CANdevTx,
  180. uint16_t CANdevTxIdx);
  181. #if ((CO_CONFIG_SDO_CLI) & CO_CONFIG_FLAG_CALLBACK_PRE) || defined CO_DOXYGEN
  182. /**
  183. * Initialize SDOclient callback function.
  184. *
  185. * Function initializes optional callback function, which should immediately
  186. * start processing of CO_SDOclientDownload() or CO_SDOclientUpload() function.
  187. * Callback is called after SDOclient message is received from the CAN bus or
  188. * when new call without delay is necessary (exchange data with own SDO server
  189. * or SDO block transfer is in progress).
  190. *
  191. * @param SDOclient This object.
  192. * @param object Pointer to object, which will be passed to pFunctSignal(). Can
  193. * be NULL.
  194. * @param pFunctSignal Pointer to the callback function. Not called if NULL.
  195. */
  196. void CO_SDOclient_initCallbackPre(CO_SDOclient_t *SDOclient,
  197. void *object,
  198. void (*pFunctSignal)(void *object));
  199. #endif
  200. /**
  201. * Setup SDO client object.
  202. *
  203. * Function must be called before new SDO communication. If previous SDO
  204. * communication was with the same node, function does not need to be called.
  205. *
  206. * @remark If configuring SDO client from network is required, this function
  207. * should be set as callback for the corresponding SDO client parameter OD
  208. * entry.
  209. *
  210. * @param SDO_C This object.
  211. * @param COB_IDClientToServer See CO_SDOclientPar_t. If zero, then
  212. * nodeIDOfTheSDOServer is used with default COB-ID.
  213. * @param COB_IDServerToClient See CO_SDOclientPar_t. If zero, then
  214. * nodeIDOfTheSDOServer is used with default COB-ID.
  215. * @param nodeIDOfTheSDOServer Node-ID of the SDO server. If zero, SDO client
  216. * object is not used. If it is the same as node-ID of this node, then data will
  217. * be exchanged with this node (without CAN communication).
  218. *
  219. * @return #CO_SDO_return_t
  220. */
  221. CO_SDO_return_t CO_SDOclient_setup(CO_SDOclient_t *SDO_C,
  222. uint32_t COB_IDClientToServer,
  223. uint32_t COB_IDServerToClient,
  224. uint8_t nodeIDOfTheSDOServer);
  225. /**
  226. * Initiate SDO download communication.
  227. *
  228. * Function initiates SDO download communication with server specified in
  229. * CO_SDOclient_init() function. Data will be written to remote node.
  230. * Function is non-blocking.
  231. *
  232. * @param SDO_C This object.
  233. * @param index Index of object in object dictionary in remote node.
  234. * @param subIndex Subindex of object in object dictionary in remote node.
  235. * @param sizeIndicated Optionally indicate size of data to be downloaded.
  236. * Actual data are written with one or multiple CO_SDOclientDownloadBufWrite()
  237. * calls.
  238. * - If sizeIndicated is different than 0, then total number of data
  239. * written by CO_SDOclientDownloadBufWrite() will be compared against
  240. * sizeIndicated. Also sizeIndicated info will be passed to the server, which
  241. * will compare actual data size downloaded. In case of mismatch, SDO abort
  242. * message will be generated.
  243. * - If sizeIndicated is 0, then actual data size will not be verified.
  244. * @param SDOtimeoutTime_ms Timeout time for SDO communication in milliseconds.
  245. * @param blockEnable Try to initiate block transfer.
  246. *
  247. * @return #CO_SDO_return_t
  248. */
  249. CO_SDO_return_t CO_SDOclientDownloadInitiate(CO_SDOclient_t *SDO_C,
  250. uint16_t index,
  251. uint8_t subIndex,
  252. size_t sizeIndicated,
  253. uint16_t SDOtimeoutTime_ms,
  254. bool_t blockEnable);
  255. /**
  256. * Initiate SDO download communication - update size.
  257. *
  258. * This is optional function, which updates sizeIndicated, if it was not known
  259. * in the CO_SDOclientDownloadInitiate() function call. This function can be
  260. * used after CO_SDOclientDownloadBufWrite(), but must be used before
  261. * CO_SDOclientDownload().
  262. *
  263. * @param SDO_C This object.
  264. * @param sizeIndicated Same as in CO_SDOclientDownloadInitiate().
  265. */
  266. void CO_SDOclientDownloadInitiateSize(CO_SDOclient_t *SDO_C,
  267. size_t sizeIndicated);
  268. /**
  269. * Write data into SDO client buffer
  270. *
  271. * This function copies data from buf into internal SDO client fifo buffer.
  272. * Function returns number of bytes successfully copied. If there is not enough
  273. * space in destination, not all bytes will be copied. Additional data can be
  274. * copied in next cycles. If there is enough space in destination and
  275. * sizeIndicated is different than zero, then all data must be written at once.
  276. *
  277. * This function is basically a wrapper for CO_fifo_write() function. As
  278. * alternative, other functions from CO_fifo can be used directly, for example
  279. * CO_fifo_cpyTok2U8() or similar.
  280. *
  281. * @param SDO_C This object.
  282. * @param buf Buffer which will be copied
  283. * @param count Number of bytes in buf
  284. *
  285. * @return number of bytes actually written.
  286. */
  287. size_t CO_SDOclientDownloadBufWrite(CO_SDOclient_t *SDO_C,
  288. const char *buf,
  289. size_t count);
  290. /**
  291. * Process SDO download communication.
  292. *
  293. * Function must be called cyclically until it returns <=0. It Proceeds SDO
  294. * download communication initiated with CO_SDOclientDownloadInitiate().
  295. * Function is non-blocking.
  296. *
  297. * If function returns #CO_SDO_RT_blockDownldInProgress and OS has buffer for
  298. * CAN tx messages, then this function may be called multiple times within own
  299. * loop. This can speed-up SDO block transfer.
  300. *
  301. * @param SDO_C This object.
  302. * @param timeDifference_us Time difference from previous function call in
  303. * [microseconds].
  304. * @param abort If true, SDO client will send abort message from SDOabortCode
  305. * and transmission will be aborted.
  306. * @param bufferPartial True indicates, not all data were copied to internal
  307. * buffer yet. Buffer will be refilled later with #CO_SDOclientDownloadBufWrite.
  308. * @param [out] SDOabortCode In case of error in communication, SDO abort code
  309. * contains reason of error. Ignored if NULL.
  310. * @param [out] sizeTransferred Actual size of data transferred. Ignored if NULL
  311. * @param [out] timerNext_us info to OS - see CO_process(). Ignored if NULL.
  312. *
  313. * @return #CO_SDO_return_t. If less than 0, then error occurred,
  314. * SDOabortCode contains reason and state becomes idle. If 0, communication
  315. * ends successfully and state becomes idle. If greater than 0, then
  316. * communication is in progress.
  317. */
  318. CO_SDO_return_t CO_SDOclientDownload(CO_SDOclient_t *SDO_C,
  319. uint32_t timeDifference_us,
  320. bool_t abort,
  321. bool_t bufferPartial,
  322. CO_SDO_abortCode_t *SDOabortCode,
  323. size_t *sizeTransferred,
  324. uint32_t *timerNext_us);
  325. /**
  326. * Initiate SDO upload communication.
  327. *
  328. * Function initiates SDO upload communication with server specified in
  329. * CO_SDOclient_init() function. Data will be read from remote node.
  330. * Function is non-blocking.
  331. *
  332. * @param SDO_C This object.
  333. * @param index Index of object in object dictionary in remote node.
  334. * @param subIndex Subindex of object in object dictionary in remote node.
  335. * @param SDOtimeoutTime_ms Timeout time for SDO communication in milliseconds.
  336. * @param blockEnable Try to initiate block transfer.
  337. *
  338. * @return #CO_SDO_return_t
  339. */
  340. CO_SDO_return_t CO_SDOclientUploadInitiate(CO_SDOclient_t *SDO_C,
  341. uint16_t index,
  342. uint8_t subIndex,
  343. uint16_t SDOtimeoutTime_ms,
  344. bool_t blockEnable);
  345. /**
  346. * Process SDO upload communication.
  347. *
  348. * Function must be called cyclically until it returns <=0. It Proceeds SDO
  349. * upload communication initiated with CO_SDOclientUploadInitiate().
  350. * Function is non-blocking.
  351. *
  352. * If this function returns #CO_SDO_RT_uploadDataBufferFull, then data must be
  353. * read from fifo buffer to make it empty. This function can then be called
  354. * once again immediately to speed-up block transfer. Note also, that remaining
  355. * data must be read after function returns #CO_SDO_RT_ok_communicationEnd.
  356. * Data must not be read, if function returns #CO_SDO_RT_blockUploadInProgress.
  357. *
  358. * @param SDO_C This object.
  359. * @param timeDifference_us Time difference from previous function call in
  360. * [microseconds].
  361. * @param abort If true, SDO client will send abort message from SDOabortCode
  362. * and reception will be aborted.
  363. * @param [out] SDOabortCode In case of error in communication, SDO abort code
  364. * contains reason of error. Ignored if NULL.
  365. * @param [out] sizeIndicated If larger than 0, then SDO server has indicated
  366. * size of data transfer. Ignored if NULL.
  367. * @param [out] sizeTransferred Actual size of data transferred. Ignored if NULL
  368. * @param [out] timerNext_us info to OS - see CO_process(). Ignored if NULL.
  369. *
  370. * @return #CO_SDO_return_t. If less than 0, then error occurred,
  371. * SDOabortCode contains reason and state becomes idle. If 0, communication
  372. * ends successfully and state becomes idle. If greater than 0, then
  373. * communication is in progress.
  374. */
  375. CO_SDO_return_t CO_SDOclientUpload(CO_SDOclient_t *SDO_C,
  376. uint32_t timeDifference_us,
  377. bool_t abort,
  378. CO_SDO_abortCode_t *SDOabortCode,
  379. size_t *sizeIndicated,
  380. size_t *sizeTransferred,
  381. uint32_t *timerNext_us);
  382. /**
  383. * Read data from SDO client buffer.
  384. *
  385. * This function copies data from internal fifo buffer of SDO client into buf.
  386. * Function returns number of bytes successfully copied. It can be called in
  387. * multiple cycles, if data length is large.
  388. *
  389. * This function is basically a wrapper for CO_fifo_read() function. As
  390. * alternative, other functions from CO_fifo can be used directly, for example
  391. * CO_fifo_readU82a() or similar.
  392. *
  393. * @warning This function (or similar) must NOT be called when
  394. * CO_SDOclientUpload() returns #CO_SDO_RT_blockUploadInProgress!
  395. *
  396. * @param SDO_C This object.
  397. * @param buf Buffer into which data will be copied
  398. * @param count Copy up to count bytes into buffer
  399. *
  400. * @return number of bytes actually read.
  401. */
  402. size_t CO_SDOclientUploadBufRead(CO_SDOclient_t *SDO_C,
  403. char *buf,
  404. size_t count);
  405. /**
  406. * Close SDO communication temporary.
  407. *
  408. * Function must be called after finish of each SDO client communication cycle.
  409. * It disables reception of SDO client CAN messages. It is necessary, because
  410. * CO_SDOclient_receive function may otherwise write into undefined SDO buffer.
  411. *
  412. * @param SDO_C This object.
  413. */
  414. void CO_SDOclientClose(CO_SDOclient_t *SDO_C);
  415. /** @} */ /* CO_SDOclient */
  416. #ifdef __cplusplus
  417. }
  418. #endif /*__cplusplus*/
  419. #endif /* (CO_CONFIG_SDO_CLI) & CO_CONFIG_SDO_CLI_ENABLE */
  420. #endif /* CO_SDO_CLIENT_H */