CO_LSSmaster.c 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116
  1. /*
  2. * CANopen LSS Master protocol.
  3. *
  4. * @file CO_LSSmaster.c
  5. * @ingroup CO_LSS
  6. * @author Martin Wagner
  7. * @copyright 2017 - 2020 Neuberger Gebaeudeautomation GmbH
  8. *
  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. #include "305/CO_LSSmaster.h"
  27. #if (CO_CONFIG_LSS) & CO_CONFIG_LSS_MASTER
  28. #include <string.h>
  29. /*
  30. * LSS master slave select state machine. Compared to #CO_LSS_state_t this
  31. * has information if we currently have selected one or all slaves. This
  32. * allows for some basic error checking.
  33. */
  34. typedef enum {
  35. CO_LSSmaster_STATE_WAITING = 0,
  36. CO_LSSmaster_STATE_CFG_SLECTIVE,
  37. CO_LSSmaster_STATE_CFG_GLOBAL,
  38. } CO_LSSmaster_state_t;
  39. /*
  40. * LSS master slave command state machine
  41. */
  42. typedef enum {
  43. CO_LSSmaster_COMMAND_WAITING = 0,
  44. CO_LSSmaster_COMMAND_SWITCH_STATE,
  45. CO_LSSmaster_COMMAND_CFG_BIT_TIMING,
  46. CO_LSSmaster_COMMAND_CFG_NODE_ID,
  47. CO_LSSmaster_COMMAND_CFG_STORE,
  48. CO_LSSmaster_COMMAND_INQUIRE_VENDOR,
  49. CO_LSSmaster_COMMAND_INQUIRE_PRODUCT,
  50. CO_LSSmaster_COMMAND_INQUIRE_REV,
  51. CO_LSSmaster_COMMAND_INQUIRE_SERIAL,
  52. CO_LSSmaster_COMMAND_INQUIRE,
  53. CO_LSSmaster_COMMAND_IDENTIFY_FASTSCAN,
  54. } CO_LSSmaster_command_t;
  55. /*
  56. * LSS master fastscan state machine
  57. */
  58. typedef enum {
  59. CO_LSSmaster_FS_STATE_CHECK,
  60. CO_LSSmaster_FS_STATE_SCAN,
  61. CO_LSSmaster_FS_STATE_VERIFY
  62. } CO_LSSmaster_fs_t;
  63. /*
  64. * Read received message from CAN module.
  65. *
  66. * Function will be called (by CAN receive interrupt) every time, when CAN
  67. * message with correct identifier will be received. For more information and
  68. * description of parameters see file CO_driver.h.
  69. */
  70. static void CO_LSSmaster_receive(void *object, void *msg)
  71. {
  72. CO_LSSmaster_t *LSSmaster;
  73. uint8_t DLC = CO_CANrxMsg_readDLC(msg);
  74. uint8_t *data = CO_CANrxMsg_readData(msg);
  75. LSSmaster = (CO_LSSmaster_t*)object; /* this is the correct pointer type of the first argument */
  76. /* verify message length and message overflow (previous message was not processed yet) */
  77. if (DLC==8 && !CO_FLAG_READ(LSSmaster->CANrxNew) &&
  78. LSSmaster->command!=CO_LSSmaster_COMMAND_WAITING){
  79. /* copy data and set 'new message' flag */
  80. memcpy(LSSmaster->CANrxData, data, sizeof(LSSmaster->CANrxData));
  81. CO_FLAG_SET(LSSmaster->CANrxNew);
  82. #if (CO_CONFIG_LSS) & CO_CONFIG_FLAG_CALLBACK_PRE
  83. /* Optional signal to RTOS, which can resume task, which handles further processing. */
  84. if (LSSmaster->pFunctSignal != NULL) {
  85. LSSmaster->pFunctSignal(LSSmaster->functSignalObject);
  86. }
  87. #endif
  88. }
  89. }
  90. /*
  91. * Check LSS timeout.
  92. *
  93. * Generally, we do not really care if the message has been received before
  94. * or after the timeout expired. Only if no message has been received we have
  95. * to check for timeouts
  96. */
  97. static inline CO_LSSmaster_return_t CO_LSSmaster_check_timeout(
  98. CO_LSSmaster_t *LSSmaster,
  99. uint32_t timeDifference_us)
  100. {
  101. CO_LSSmaster_return_t ret = CO_LSSmaster_WAIT_SLAVE;
  102. LSSmaster->timeoutTimer += timeDifference_us;
  103. if (LSSmaster->timeoutTimer >= LSSmaster->timeout_us) {
  104. LSSmaster->timeoutTimer = 0;
  105. ret = CO_LSSmaster_TIMEOUT;
  106. }
  107. return ret;
  108. }
  109. /******************************************************************************/
  110. CO_ReturnError_t CO_LSSmaster_init(
  111. CO_LSSmaster_t *LSSmaster,
  112. uint16_t timeout_ms,
  113. CO_CANmodule_t *CANdevRx,
  114. uint16_t CANdevRxIdx,
  115. uint32_t CANidLssSlave,
  116. CO_CANmodule_t *CANdevTx,
  117. uint16_t CANdevTxIdx,
  118. uint32_t CANidLssMaster)
  119. {
  120. CO_ReturnError_t ret = CO_ERROR_NO;
  121. /* verify arguments */
  122. if (LSSmaster==NULL || CANdevRx==NULL || CANdevTx==NULL){
  123. return CO_ERROR_ILLEGAL_ARGUMENT;
  124. }
  125. LSSmaster->timeout_us = (uint32_t)timeout_ms * 1000;
  126. LSSmaster->state = CO_LSSmaster_STATE_WAITING;
  127. LSSmaster->command = CO_LSSmaster_COMMAND_WAITING;
  128. LSSmaster->timeoutTimer = 0;
  129. CO_FLAG_CLEAR(LSSmaster->CANrxNew);
  130. memset(LSSmaster->CANrxData, 0, sizeof(LSSmaster->CANrxData));
  131. #if (CO_CONFIG_LSS) & CO_CONFIG_FLAG_CALLBACK_PRE
  132. LSSmaster->pFunctSignal = NULL;
  133. LSSmaster->functSignalObject = NULL;
  134. #endif
  135. /* configure LSS CAN Slave response message reception */
  136. ret = CO_CANrxBufferInit(
  137. CANdevRx, /* CAN device */
  138. CANdevRxIdx, /* rx buffer index */
  139. CANidLssSlave, /* CAN identifier */
  140. 0x7FF, /* mask */
  141. 0, /* rtr */
  142. (void*)LSSmaster, /* object passed to receive function */
  143. CO_LSSmaster_receive);/* this function will process received message */
  144. /* configure LSS CAN Master message transmission */
  145. LSSmaster->CANdevTx = CANdevTx;
  146. LSSmaster->TXbuff = CO_CANtxBufferInit(
  147. CANdevTx, /* CAN device */
  148. CANdevTxIdx, /* index of specific buffer inside CAN module */
  149. CANidLssMaster, /* CAN identifier */
  150. 0, /* rtr */
  151. 8, /* number of data bytes */
  152. 0); /* synchronous message flag bit */
  153. if (LSSmaster->TXbuff == NULL) {
  154. ret = CO_ERROR_ILLEGAL_ARGUMENT;
  155. }
  156. return ret;
  157. }
  158. /******************************************************************************/
  159. void CO_LSSmaster_changeTimeout(
  160. CO_LSSmaster_t *LSSmaster,
  161. uint16_t timeout_ms)
  162. {
  163. if (LSSmaster != NULL) {
  164. LSSmaster->timeout_us = (uint32_t)timeout_ms * 1000;
  165. }
  166. }
  167. #if (CO_CONFIG_LSS) & CO_CONFIG_FLAG_CALLBACK_PRE
  168. /******************************************************************************/
  169. void CO_LSSmaster_initCallbackPre(
  170. CO_LSSmaster_t *LSSmaster,
  171. void *object,
  172. void (*pFunctSignal)(void *object))
  173. {
  174. if (LSSmaster != NULL){
  175. LSSmaster->functSignalObject = object;
  176. LSSmaster->pFunctSignal = pFunctSignal;
  177. }
  178. }
  179. #endif
  180. /*
  181. * Helper function - initiate switch state
  182. */
  183. static CO_LSSmaster_return_t CO_LSSmaster_switchStateSelectInitiate(
  184. CO_LSSmaster_t *LSSmaster,
  185. CO_LSS_address_t *lssAddress)
  186. {
  187. CO_LSSmaster_return_t ret;
  188. if (lssAddress != NULL) {
  189. /* switch state select specific using LSS address */
  190. LSSmaster->state = CO_LSSmaster_STATE_CFG_SLECTIVE;
  191. LSSmaster->command = CO_LSSmaster_COMMAND_SWITCH_STATE;
  192. LSSmaster->timeoutTimer = 0;
  193. CO_FLAG_CLEAR(LSSmaster->CANrxNew);
  194. memset(&LSSmaster->TXbuff->data[6], 0, sizeof(LSSmaster->TXbuff->data) - 6);
  195. LSSmaster->TXbuff->data[0] = CO_LSS_SWITCH_STATE_SEL_VENDOR;
  196. CO_setUint32(&LSSmaster->TXbuff->data[1], lssAddress->identity.vendorID);
  197. CO_CANsend(LSSmaster->CANdevTx, LSSmaster->TXbuff);
  198. LSSmaster->TXbuff->data[0] = CO_LSS_SWITCH_STATE_SEL_PRODUCT;
  199. CO_setUint32(&LSSmaster->TXbuff->data[1], lssAddress->identity.productCode);
  200. CO_CANsend(LSSmaster->CANdevTx, LSSmaster->TXbuff);
  201. LSSmaster->TXbuff->data[0] = CO_LSS_SWITCH_STATE_SEL_REV;
  202. CO_setUint32(&LSSmaster->TXbuff->data[1], lssAddress->identity.revisionNumber);
  203. CO_CANsend(LSSmaster->CANdevTx, LSSmaster->TXbuff);
  204. LSSmaster->TXbuff->data[0] = CO_LSS_SWITCH_STATE_SEL_SERIAL;
  205. CO_setUint32(&LSSmaster->TXbuff->data[1], lssAddress->identity.serialNumber);
  206. CO_CANsend(LSSmaster->CANdevTx, LSSmaster->TXbuff);
  207. ret = CO_LSSmaster_WAIT_SLAVE;
  208. }
  209. else {
  210. /* switch state global */
  211. LSSmaster->state = CO_LSSmaster_STATE_CFG_GLOBAL;
  212. CO_FLAG_CLEAR(LSSmaster->CANrxNew);
  213. LSSmaster->TXbuff->data[0] = CO_LSS_SWITCH_STATE_GLOBAL;
  214. LSSmaster->TXbuff->data[1] = CO_LSS_STATE_CONFIGURATION;
  215. memset(&LSSmaster->TXbuff->data[2], 0, sizeof(LSSmaster->TXbuff->data) - 2);
  216. CO_CANsend(LSSmaster->CANdevTx, LSSmaster->TXbuff);
  217. /* This is non-confirmed service! */
  218. ret = CO_LSSmaster_OK;
  219. }
  220. return ret;
  221. }
  222. /*
  223. * Helper function - wait for confirmation
  224. */
  225. static CO_LSSmaster_return_t CO_LSSmaster_switchStateSelectWait(
  226. CO_LSSmaster_t *LSSmaster,
  227. uint32_t timeDifference_us)
  228. {
  229. CO_LSSmaster_return_t ret;
  230. if (CO_FLAG_READ(LSSmaster->CANrxNew)) {
  231. uint8_t cs = LSSmaster->CANrxData[0];
  232. CO_FLAG_CLEAR(LSSmaster->CANrxNew);
  233. if (cs == CO_LSS_SWITCH_STATE_SEL) {
  234. /* confirmation received */
  235. ret = CO_LSSmaster_OK;
  236. }
  237. else {
  238. ret = CO_LSSmaster_check_timeout(LSSmaster, timeDifference_us);
  239. }
  240. }
  241. else {
  242. ret = CO_LSSmaster_check_timeout(LSSmaster, timeDifference_us);
  243. }
  244. return ret;
  245. }
  246. /******************************************************************************/
  247. CO_LSSmaster_return_t CO_LSSmaster_switchStateSelect(
  248. CO_LSSmaster_t *LSSmaster,
  249. uint32_t timeDifference_us,
  250. CO_LSS_address_t *lssAddress)
  251. {
  252. CO_LSSmaster_return_t ret = CO_LSSmaster_INVALID_STATE;
  253. if (LSSmaster == NULL){
  254. return CO_LSSmaster_ILLEGAL_ARGUMENT;
  255. }
  256. /* Initiate select */
  257. if (LSSmaster->state==CO_LSSmaster_STATE_WAITING &&
  258. LSSmaster->command==CO_LSSmaster_COMMAND_WAITING){
  259. ret = CO_LSSmaster_switchStateSelectInitiate(LSSmaster, lssAddress);
  260. }
  261. /* Wait for confirmation */
  262. else if (LSSmaster->command == CO_LSSmaster_COMMAND_SWITCH_STATE) {
  263. ret = CO_LSSmaster_switchStateSelectWait(LSSmaster, timeDifference_us);
  264. }
  265. if (ret!=CO_LSSmaster_INVALID_STATE && ret!=CO_LSSmaster_WAIT_SLAVE) {
  266. /* finished */
  267. LSSmaster->command = CO_LSSmaster_COMMAND_WAITING;
  268. }
  269. if (ret < CO_LSSmaster_OK) {
  270. /* switching failed, go back to waiting */
  271. LSSmaster->state=CO_LSSmaster_STATE_WAITING;
  272. LSSmaster->command = CO_LSSmaster_COMMAND_WAITING;
  273. }
  274. return ret;
  275. }
  276. /******************************************************************************/
  277. CO_LSSmaster_return_t CO_LSSmaster_switchStateDeselect(
  278. CO_LSSmaster_t *LSSmaster)
  279. {
  280. CO_LSSmaster_return_t ret = CO_LSSmaster_INVALID_STATE;
  281. if (LSSmaster == NULL){
  282. return CO_LSSmaster_ILLEGAL_ARGUMENT;
  283. }
  284. /* We can always send this command to get into a clean state on the network.
  285. * If no slave is selected, this command is ignored. */
  286. LSSmaster->state = CO_LSSmaster_STATE_WAITING;
  287. LSSmaster->command = CO_LSSmaster_COMMAND_WAITING;
  288. LSSmaster->timeoutTimer = 0;
  289. /* switch state global */
  290. CO_FLAG_CLEAR(LSSmaster->CANrxNew);
  291. LSSmaster->TXbuff->data[0] = CO_LSS_SWITCH_STATE_GLOBAL;
  292. LSSmaster->TXbuff->data[1] = CO_LSS_STATE_WAITING;
  293. memset(&LSSmaster->TXbuff->data[2], 0, sizeof(LSSmaster->TXbuff->data) - 2);
  294. CO_CANsend(LSSmaster->CANdevTx, LSSmaster->TXbuff);
  295. /* This is non-confirmed service! */
  296. ret = CO_LSSmaster_OK;
  297. return ret;
  298. }
  299. /*
  300. * Helper function - wait for confirmation, check for returned error code
  301. *
  302. * This uses the nature of the configure confirmation message design:
  303. * - byte 0 -> cs
  304. * - byte 1 -> Error Code, where
  305. * - 0 = OK
  306. * - 1 .. FE = Values defined by CiA. All currently defined values
  307. * are slave rejects. No further distinction on why the
  308. * slave did reject the request.
  309. * - FF = Manufacturer Error Code in byte 2
  310. * - byte 2 -> Manufacturer Error, currently not used
  311. *
  312. * enums for the errorCode are
  313. * - CO_LSS_cfgNodeId_t
  314. * - CO_LSS_cfgBitTiming_t
  315. * - CO_LSS_cfgStore_t
  316. */
  317. static CO_LSSmaster_return_t CO_LSSmaster_configureCheckWait(
  318. CO_LSSmaster_t *LSSmaster,
  319. uint32_t timeDifference_us,
  320. uint8_t csWait)
  321. {
  322. CO_LSSmaster_return_t ret;
  323. if (CO_FLAG_READ(LSSmaster->CANrxNew)) {
  324. uint8_t cs = LSSmaster->CANrxData[0];
  325. uint8_t errorCode = LSSmaster->CANrxData[1];
  326. CO_FLAG_CLEAR(LSSmaster->CANrxNew);
  327. if (cs == csWait) {
  328. if (errorCode == 0) {
  329. ret = CO_LSSmaster_OK;
  330. }
  331. else if (errorCode == 0xff) {
  332. ret = CO_LSSmaster_OK_MANUFACTURER;
  333. }
  334. else {
  335. ret = CO_LSSmaster_OK_ILLEGAL_ARGUMENT;
  336. }
  337. }
  338. else {
  339. ret = CO_LSSmaster_check_timeout(LSSmaster, timeDifference_us);
  340. }
  341. }
  342. else {
  343. ret = CO_LSSmaster_check_timeout(LSSmaster, timeDifference_us);
  344. }
  345. if (ret!=CO_LSSmaster_INVALID_STATE && ret!=CO_LSSmaster_WAIT_SLAVE) {
  346. /* finished */
  347. LSSmaster->command = CO_LSSmaster_COMMAND_WAITING;
  348. }
  349. return ret;
  350. }
  351. /******************************************************************************/
  352. CO_LSSmaster_return_t CO_LSSmaster_configureBitTiming(
  353. CO_LSSmaster_t *LSSmaster,
  354. uint32_t timeDifference_us,
  355. uint16_t bit)
  356. {
  357. CO_LSSmaster_return_t ret = CO_LSSmaster_INVALID_STATE;
  358. uint8_t bitTiming;
  359. if (LSSmaster == NULL){
  360. return CO_LSSmaster_ILLEGAL_ARGUMENT;
  361. }
  362. switch (bit) {
  363. case 1000: bitTiming = CO_LSS_BIT_TIMING_1000; break;
  364. case 800: bitTiming = CO_LSS_BIT_TIMING_800; break;
  365. case 500: bitTiming = CO_LSS_BIT_TIMING_500; break;
  366. case 250: bitTiming = CO_LSS_BIT_TIMING_250; break;
  367. case 125: bitTiming = CO_LSS_BIT_TIMING_125; break;
  368. case 50: bitTiming = CO_LSS_BIT_TIMING_50; break;
  369. case 20: bitTiming = CO_LSS_BIT_TIMING_20; break;
  370. case 10: bitTiming = CO_LSS_BIT_TIMING_10; break;
  371. case 0: bitTiming = CO_LSS_BIT_TIMING_AUTO; break;
  372. default: return CO_LSSmaster_ILLEGAL_ARGUMENT;
  373. }
  374. /* Initiate config bit */
  375. if (LSSmaster->state==CO_LSSmaster_STATE_CFG_SLECTIVE &&
  376. LSSmaster->command==CO_LSSmaster_COMMAND_WAITING){
  377. LSSmaster->command = CO_LSSmaster_COMMAND_CFG_BIT_TIMING;
  378. LSSmaster->timeoutTimer = 0;
  379. CO_FLAG_CLEAR(LSSmaster->CANrxNew);
  380. LSSmaster->TXbuff->data[0] = CO_LSS_CFG_BIT_TIMING;
  381. LSSmaster->TXbuff->data[1] = 0;
  382. LSSmaster->TXbuff->data[2] = bitTiming;
  383. memset(&LSSmaster->TXbuff->data[3], 0, sizeof(LSSmaster->TXbuff->data) - 3);
  384. CO_CANsend(LSSmaster->CANdevTx, LSSmaster->TXbuff);
  385. ret = CO_LSSmaster_WAIT_SLAVE;
  386. }
  387. /* Wait for confirmation */
  388. else if (LSSmaster->command == CO_LSSmaster_COMMAND_CFG_BIT_TIMING) {
  389. ret = CO_LSSmaster_configureCheckWait(LSSmaster, timeDifference_us,
  390. CO_LSS_CFG_BIT_TIMING);
  391. }
  392. if (ret!=CO_LSSmaster_INVALID_STATE && ret!=CO_LSSmaster_WAIT_SLAVE) {
  393. /* finished */
  394. LSSmaster->command = CO_LSSmaster_COMMAND_WAITING;
  395. }
  396. return ret;
  397. }
  398. /******************************************************************************/
  399. CO_LSSmaster_return_t CO_LSSmaster_configureNodeId(
  400. CO_LSSmaster_t *LSSmaster,
  401. uint32_t timeDifference_us,
  402. uint8_t nodeId)
  403. {
  404. CO_LSSmaster_return_t ret = CO_LSSmaster_INVALID_STATE;
  405. if (LSSmaster==NULL || !CO_LSS_NODE_ID_VALID(nodeId)){
  406. return CO_LSSmaster_ILLEGAL_ARGUMENT;
  407. }
  408. /* Initiate config node ID */
  409. if ((LSSmaster->state==CO_LSSmaster_STATE_CFG_SLECTIVE ||
  410. /* Let un-config node ID also be run in global mode for unconfiguring all nodes */
  411. (LSSmaster->state==CO_LSSmaster_STATE_CFG_GLOBAL &&
  412. nodeId == CO_LSS_NODE_ID_ASSIGNMENT)) &&
  413. LSSmaster->command==CO_LSSmaster_COMMAND_WAITING) {
  414. LSSmaster->command = CO_LSSmaster_COMMAND_CFG_NODE_ID;
  415. LSSmaster->timeoutTimer = 0;
  416. CO_FLAG_CLEAR(LSSmaster->CANrxNew);
  417. LSSmaster->TXbuff->data[0] = CO_LSS_CFG_NODE_ID;
  418. LSSmaster->TXbuff->data[1] = nodeId;
  419. memset(&LSSmaster->TXbuff->data[2], 0, sizeof(LSSmaster->TXbuff->data) - 2);
  420. CO_CANsend(LSSmaster->CANdevTx, LSSmaster->TXbuff);
  421. ret = CO_LSSmaster_WAIT_SLAVE;
  422. }
  423. /* Wait for confirmation */
  424. else if (LSSmaster->command == CO_LSSmaster_COMMAND_CFG_NODE_ID) {
  425. ret = CO_LSSmaster_configureCheckWait(LSSmaster, timeDifference_us,
  426. CO_LSS_CFG_NODE_ID);
  427. }
  428. if (ret!=CO_LSSmaster_INVALID_STATE && ret!=CO_LSSmaster_WAIT_SLAVE) {
  429. /* finished */
  430. LSSmaster->command = CO_LSSmaster_COMMAND_WAITING;
  431. }
  432. return ret;
  433. }
  434. /******************************************************************************/
  435. CO_LSSmaster_return_t CO_LSSmaster_configureStore(
  436. CO_LSSmaster_t *LSSmaster,
  437. uint32_t timeDifference_us)
  438. {
  439. CO_LSSmaster_return_t ret = CO_LSSmaster_INVALID_STATE;
  440. if (LSSmaster == NULL){
  441. return CO_LSSmaster_ILLEGAL_ARGUMENT;
  442. }
  443. /* Initiate config store */
  444. if (LSSmaster->state==CO_LSSmaster_STATE_CFG_SLECTIVE &&
  445. LSSmaster->command==CO_LSSmaster_COMMAND_WAITING){
  446. LSSmaster->command = CO_LSSmaster_COMMAND_CFG_STORE;
  447. LSSmaster->timeoutTimer = 0;
  448. CO_FLAG_CLEAR(LSSmaster->CANrxNew);
  449. LSSmaster->TXbuff->data[0] = CO_LSS_CFG_STORE;
  450. memset(&LSSmaster->TXbuff->data[1], 0, sizeof(LSSmaster->TXbuff->data) - 1);
  451. CO_CANsend(LSSmaster->CANdevTx, LSSmaster->TXbuff);
  452. ret = CO_LSSmaster_WAIT_SLAVE;
  453. }
  454. /* Wait for confirmation */
  455. else if (LSSmaster->command == CO_LSSmaster_COMMAND_CFG_STORE) {
  456. ret = CO_LSSmaster_configureCheckWait(LSSmaster, timeDifference_us,
  457. CO_LSS_CFG_STORE);
  458. }
  459. if (ret!=CO_LSSmaster_INVALID_STATE && ret!=CO_LSSmaster_WAIT_SLAVE) {
  460. /* finished */
  461. LSSmaster->command = CO_LSSmaster_COMMAND_WAITING;
  462. }
  463. return ret;
  464. }
  465. /******************************************************************************/
  466. CO_LSSmaster_return_t CO_LSSmaster_ActivateBit(
  467. CO_LSSmaster_t *LSSmaster,
  468. uint16_t switchDelay_ms)
  469. {
  470. CO_LSSmaster_return_t ret = CO_LSSmaster_INVALID_STATE;
  471. if (LSSmaster == NULL){
  472. return CO_LSSmaster_ILLEGAL_ARGUMENT;
  473. }
  474. /* for activating bit timing, we need to have all slaves set to config
  475. * state. This check makes it a bit harder to shoot ourselves in the foot */
  476. if (LSSmaster->state==CO_LSSmaster_STATE_CFG_GLOBAL &&
  477. LSSmaster->command==CO_LSSmaster_COMMAND_WAITING){
  478. CO_FLAG_CLEAR(LSSmaster->CANrxNew);
  479. LSSmaster->TXbuff->data[0] = CO_LSS_CFG_ACTIVATE_BIT_TIMING;
  480. CO_setUint16(&LSSmaster->TXbuff->data[1], switchDelay_ms);
  481. memset(&LSSmaster->TXbuff->data[3], 0, sizeof(LSSmaster->TXbuff->data) - 3);
  482. CO_CANsend(LSSmaster->CANdevTx, LSSmaster->TXbuff);
  483. /* This is non-confirmed service! */
  484. ret = CO_LSSmaster_OK;
  485. }
  486. return ret;
  487. }
  488. /*
  489. * Helper function - send request
  490. */
  491. static CO_LSSmaster_return_t CO_LSSmaster_inquireInitiate(
  492. CO_LSSmaster_t *LSSmaster,
  493. uint8_t cs)
  494. {
  495. CO_FLAG_CLEAR(LSSmaster->CANrxNew);
  496. LSSmaster->TXbuff->data[0] = cs;
  497. memset(&LSSmaster->TXbuff->data[1], 0, sizeof(LSSmaster->TXbuff->data) - 1);
  498. CO_CANsend(LSSmaster->CANdevTx, LSSmaster->TXbuff);
  499. return CO_LSSmaster_WAIT_SLAVE;
  500. }
  501. /*
  502. * Helper function - wait for confirmation
  503. */
  504. static CO_LSSmaster_return_t CO_LSSmaster_inquireCheckWait(
  505. CO_LSSmaster_t *LSSmaster,
  506. uint32_t timeDifference_us,
  507. uint8_t csWait,
  508. uint32_t *value)
  509. {
  510. CO_LSSmaster_return_t ret;
  511. if (CO_FLAG_READ(LSSmaster->CANrxNew)) {
  512. uint8_t cs = LSSmaster->CANrxData[0];
  513. *value = CO_getUint32(&LSSmaster->CANrxData[1]);
  514. CO_FLAG_CLEAR(LSSmaster->CANrxNew);
  515. if (cs == csWait) {
  516. ret = CO_LSSmaster_OK;
  517. }
  518. else {
  519. ret = CO_LSSmaster_check_timeout(LSSmaster, timeDifference_us);
  520. }
  521. }
  522. else {
  523. ret = CO_LSSmaster_check_timeout(LSSmaster, timeDifference_us);
  524. }
  525. return ret;
  526. }
  527. /******************************************************************************/
  528. CO_LSSmaster_return_t CO_LSSmaster_InquireLssAddress(
  529. CO_LSSmaster_t *LSSmaster,
  530. uint32_t timeDifference_us,
  531. CO_LSS_address_t *lssAddress)
  532. {
  533. CO_LSSmaster_return_t ret = CO_LSSmaster_INVALID_STATE;
  534. CO_LSSmaster_command_t next = CO_LSSmaster_COMMAND_WAITING;
  535. if (LSSmaster==NULL || lssAddress==NULL){
  536. return CO_LSSmaster_ILLEGAL_ARGUMENT;
  537. }
  538. /* Check for reply */
  539. if (LSSmaster->command == CO_LSSmaster_COMMAND_INQUIRE_VENDOR) {
  540. ret = CO_LSSmaster_inquireCheckWait(LSSmaster, timeDifference_us,
  541. CO_LSS_INQUIRE_VENDOR, &lssAddress->identity.vendorID);
  542. if (ret == CO_LSSmaster_OK) {
  543. /* Start next request */
  544. next = CO_LSSmaster_COMMAND_INQUIRE_PRODUCT;
  545. ret = CO_LSSmaster_WAIT_SLAVE;
  546. }
  547. }
  548. else if (LSSmaster->command == CO_LSSmaster_COMMAND_INQUIRE_PRODUCT) {
  549. ret = CO_LSSmaster_inquireCheckWait(LSSmaster, timeDifference_us,
  550. CO_LSS_INQUIRE_PRODUCT, &lssAddress->identity.productCode);
  551. if (ret == CO_LSSmaster_OK) {
  552. /* Start next request */
  553. next = CO_LSSmaster_COMMAND_INQUIRE_REV;
  554. ret = CO_LSSmaster_WAIT_SLAVE;
  555. }
  556. }
  557. else if (LSSmaster->command == CO_LSSmaster_COMMAND_INQUIRE_REV) {
  558. ret = CO_LSSmaster_inquireCheckWait(LSSmaster, timeDifference_us,
  559. CO_LSS_INQUIRE_REV, &lssAddress->identity.revisionNumber);
  560. if (ret == CO_LSSmaster_OK) {
  561. /* Start next request */
  562. next = CO_LSSmaster_COMMAND_INQUIRE_SERIAL;
  563. ret = CO_LSSmaster_WAIT_SLAVE;
  564. }
  565. }
  566. else if (LSSmaster->command == CO_LSSmaster_COMMAND_INQUIRE_SERIAL) {
  567. ret = CO_LSSmaster_inquireCheckWait(LSSmaster, timeDifference_us,
  568. CO_LSS_INQUIRE_SERIAL, &lssAddress->identity.serialNumber);
  569. }
  570. /* Check for next request */
  571. if (LSSmaster->state == CO_LSSmaster_STATE_CFG_SLECTIVE ||
  572. LSSmaster->state == CO_LSSmaster_STATE_CFG_GLOBAL) {
  573. if (LSSmaster->command == CO_LSSmaster_COMMAND_WAITING) {
  574. LSSmaster->command = CO_LSSmaster_COMMAND_INQUIRE_VENDOR;
  575. LSSmaster->timeoutTimer = 0;
  576. ret = CO_LSSmaster_inquireInitiate(LSSmaster, CO_LSS_INQUIRE_VENDOR);
  577. }
  578. else if (next == CO_LSSmaster_COMMAND_INQUIRE_PRODUCT) {
  579. LSSmaster->command = CO_LSSmaster_COMMAND_INQUIRE_PRODUCT;
  580. LSSmaster->timeoutTimer = 0;
  581. ret = CO_LSSmaster_inquireInitiate(LSSmaster, CO_LSS_INQUIRE_PRODUCT);
  582. }
  583. else if (next == CO_LSSmaster_COMMAND_INQUIRE_REV) {
  584. LSSmaster->command = CO_LSSmaster_COMMAND_INQUIRE_REV;
  585. LSSmaster->timeoutTimer = 0;
  586. ret = CO_LSSmaster_inquireInitiate(LSSmaster, CO_LSS_INQUIRE_REV);
  587. }
  588. else if (next == CO_LSSmaster_COMMAND_INQUIRE_SERIAL) {
  589. LSSmaster->command = CO_LSSmaster_COMMAND_INQUIRE_SERIAL;
  590. LSSmaster->timeoutTimer = 0;
  591. ret = CO_LSSmaster_inquireInitiate(LSSmaster, CO_LSS_INQUIRE_SERIAL);
  592. }
  593. }
  594. if (ret!=CO_LSSmaster_INVALID_STATE && ret!=CO_LSSmaster_WAIT_SLAVE) {
  595. /* finished */
  596. LSSmaster->command = CO_LSSmaster_COMMAND_WAITING;
  597. }
  598. return ret;
  599. }
  600. /******************************************************************************/
  601. CO_LSSmaster_return_t CO_LSSmaster_Inquire(
  602. CO_LSSmaster_t *LSSmaster,
  603. uint32_t timeDifference_us,
  604. CO_LSS_cs_t lssInquireCs,
  605. uint32_t *value)
  606. {
  607. CO_LSSmaster_return_t ret = CO_LSSmaster_INVALID_STATE;
  608. if (LSSmaster==NULL || value==NULL){
  609. return CO_LSSmaster_ILLEGAL_ARGUMENT;
  610. }
  611. /* send request */
  612. if ((LSSmaster->state==CO_LSSmaster_STATE_CFG_SLECTIVE ||
  613. LSSmaster->state==CO_LSSmaster_STATE_CFG_GLOBAL) &&
  614. LSSmaster->command == CO_LSSmaster_COMMAND_WAITING) {
  615. LSSmaster->command = CO_LSSmaster_COMMAND_INQUIRE;
  616. LSSmaster->timeoutTimer = 0;
  617. ret = CO_LSSmaster_inquireInitiate(LSSmaster, lssInquireCs);
  618. }
  619. /* Check for reply */
  620. else if (LSSmaster->command == CO_LSSmaster_COMMAND_INQUIRE) {
  621. ret = CO_LSSmaster_inquireCheckWait(LSSmaster, timeDifference_us,
  622. lssInquireCs, value);
  623. }
  624. if (ret != CO_LSSmaster_WAIT_SLAVE) {
  625. LSSmaster->command = CO_LSSmaster_COMMAND_WAITING;
  626. }
  627. return ret;
  628. }
  629. /*
  630. * Helper function - send request
  631. */
  632. static void CO_LSSmaster_FsSendMsg(
  633. CO_LSSmaster_t *LSSmaster,
  634. uint32_t idNumber,
  635. uint8_t bitCheck,
  636. uint8_t lssSub,
  637. uint8_t lssNext)
  638. {
  639. LSSmaster->timeoutTimer = 0;
  640. CO_FLAG_CLEAR(LSSmaster->CANrxNew);
  641. LSSmaster->TXbuff->data[0] = CO_LSS_IDENT_FASTSCAN;
  642. CO_setUint32(&LSSmaster->TXbuff->data[1], idNumber);
  643. LSSmaster->TXbuff->data[5] = bitCheck;
  644. LSSmaster->TXbuff->data[6] = lssSub;
  645. LSSmaster->TXbuff->data[7] = lssNext;
  646. CO_CANsend(LSSmaster->CANdevTx, LSSmaster->TXbuff);
  647. }
  648. /*
  649. * Helper function - wait for confirmation
  650. */
  651. static CO_LSSmaster_return_t CO_LSSmaster_FsCheckWait(
  652. CO_LSSmaster_t *LSSmaster,
  653. uint32_t timeDifference_us)
  654. {
  655. CO_LSSmaster_return_t ret;
  656. ret = CO_LSSmaster_check_timeout(LSSmaster, timeDifference_us);
  657. if (ret == CO_LSSmaster_TIMEOUT) {
  658. ret = CO_LSSmaster_SCAN_NOACK;
  659. if (CO_FLAG_READ(LSSmaster->CANrxNew)) {
  660. uint8_t cs = LSSmaster->CANrxData[0];
  661. CO_FLAG_CLEAR(LSSmaster->CANrxNew);
  662. if (cs == CO_LSS_IDENT_SLAVE) {
  663. /* At least one node is waiting for fastscan */
  664. ret = CO_LSSmaster_SCAN_FINISHED;
  665. }
  666. }
  667. }
  668. return ret;
  669. }
  670. /*
  671. * Helper function - initiate scan for 32 bit part of LSS address
  672. */
  673. static CO_LSSmaster_return_t CO_LSSmaster_FsScanInitiate(
  674. CO_LSSmaster_t *LSSmaster,
  675. uint32_t timeDifference_us,
  676. CO_LSSmaster_scantype_t scan,
  677. CO_LSS_fastscan_lss_sub_next lssSub)
  678. {
  679. (void)timeDifference_us; /* unused */
  680. LSSmaster->fsLssSub = lssSub;
  681. LSSmaster->fsIdNumber = 0;
  682. switch (scan) {
  683. case CO_LSSmaster_FS_SCAN:
  684. break;
  685. case CO_LSSmaster_FS_MATCH:
  686. /* No scanning requested */
  687. return CO_LSSmaster_SCAN_FINISHED;
  688. case CO_LSSmaster_FS_SKIP:
  689. default:
  690. return CO_LSSmaster_SCAN_FAILED;
  691. }
  692. LSSmaster->fsBitChecked = CO_LSS_FASTSCAN_BIT31;
  693. /* trigger scan procedure by sending first message */
  694. CO_LSSmaster_FsSendMsg(LSSmaster, LSSmaster->fsIdNumber,
  695. LSSmaster->fsBitChecked, LSSmaster->fsLssSub, LSSmaster->fsLssSub);
  696. return CO_LSSmaster_WAIT_SLAVE;
  697. }
  698. /*
  699. * Helper function - scan for 32 bits of LSS address, one by one
  700. */
  701. static CO_LSSmaster_return_t CO_LSSmaster_FsScanWait(
  702. CO_LSSmaster_t *LSSmaster,
  703. uint32_t timeDifference_us,
  704. CO_LSSmaster_scantype_t scan)
  705. {
  706. CO_LSSmaster_return_t ret;
  707. switch (scan) {
  708. case CO_LSSmaster_FS_SCAN:
  709. break;
  710. case CO_LSSmaster_FS_MATCH:
  711. /* No scanning requested */
  712. return CO_LSSmaster_SCAN_FINISHED;
  713. case CO_LSSmaster_FS_SKIP:
  714. default:
  715. return CO_LSSmaster_SCAN_FAILED;
  716. }
  717. ret = CO_LSSmaster_check_timeout(LSSmaster, timeDifference_us);
  718. if (ret == CO_LSSmaster_TIMEOUT) {
  719. ret = CO_LSSmaster_WAIT_SLAVE;
  720. if (CO_FLAG_READ(LSSmaster->CANrxNew)) {
  721. uint8_t cs = LSSmaster->CANrxData[0];
  722. CO_FLAG_CLEAR(LSSmaster->CANrxNew);
  723. if (cs != CO_LSS_IDENT_SLAVE) {
  724. /* wrong response received. Can not continue */
  725. return CO_LSSmaster_SCAN_FAILED;
  726. }
  727. }
  728. else {
  729. /* no response received, assumption is wrong */
  730. LSSmaster->fsIdNumber |= 1UL << LSSmaster->fsBitChecked;
  731. }
  732. if (LSSmaster->fsBitChecked == CO_LSS_FASTSCAN_BIT0) {
  733. /* Scanning cycle is finished, we now have 32 bit address data */
  734. ret = CO_LSSmaster_SCAN_FINISHED;
  735. }
  736. else {
  737. LSSmaster->fsBitChecked --;
  738. CO_LSSmaster_FsSendMsg(LSSmaster,
  739. LSSmaster->fsIdNumber, LSSmaster->fsBitChecked,
  740. LSSmaster->fsLssSub, LSSmaster->fsLssSub);
  741. }
  742. }
  743. return ret;
  744. }
  745. /*
  746. * Helper function - initiate check for 32 bit part of LSS address
  747. */
  748. static CO_LSSmaster_return_t CO_LSSmaster_FsVerifyInitiate(
  749. CO_LSSmaster_t *LSSmaster,
  750. uint32_t timeDifference_us,
  751. CO_LSSmaster_scantype_t scan,
  752. uint32_t idNumberCheck,
  753. CO_LSS_fastscan_lss_sub_next lssNext)
  754. {
  755. (void)timeDifference_us; /* unused */
  756. switch (scan) {
  757. case CO_LSSmaster_FS_SCAN:
  758. /* ID obtained by scan */
  759. break;
  760. case CO_LSSmaster_FS_MATCH:
  761. /* ID given by user */
  762. LSSmaster->fsIdNumber = idNumberCheck;
  763. break;
  764. case CO_LSSmaster_FS_SKIP:
  765. default:
  766. return CO_LSSmaster_SCAN_FAILED;
  767. }
  768. LSSmaster->fsBitChecked = CO_LSS_FASTSCAN_BIT0;
  769. /* send request */
  770. CO_LSSmaster_FsSendMsg(LSSmaster, LSSmaster->fsIdNumber,
  771. LSSmaster->fsBitChecked, LSSmaster->fsLssSub, lssNext);
  772. return CO_LSSmaster_WAIT_SLAVE;
  773. }
  774. /*
  775. * Helper function - verify 32 bit LSS address, request node(s) to switch
  776. * their state machine to the next state
  777. */
  778. static CO_LSSmaster_return_t CO_LSSmaster_FsVerifyWait(
  779. CO_LSSmaster_t *LSSmaster,
  780. uint32_t timeDifference_us,
  781. CO_LSSmaster_scantype_t scan,
  782. uint32_t *idNumberRet)
  783. {
  784. CO_LSSmaster_return_t ret;
  785. if (scan == CO_LSSmaster_FS_SKIP) {
  786. return CO_LSSmaster_SCAN_FAILED;
  787. }
  788. ret = CO_LSSmaster_check_timeout(LSSmaster, timeDifference_us);
  789. if (ret == CO_LSSmaster_TIMEOUT) {
  790. *idNumberRet = 0;
  791. ret = CO_LSSmaster_SCAN_NOACK;
  792. if (CO_FLAG_READ(LSSmaster->CANrxNew)) {
  793. uint8_t cs = LSSmaster->CANrxData[0];
  794. CO_FLAG_CLEAR(LSSmaster->CANrxNew);
  795. if (cs == CO_LSS_IDENT_SLAVE) {
  796. *idNumberRet = LSSmaster->fsIdNumber;
  797. ret = CO_LSSmaster_SCAN_FINISHED;
  798. } else {
  799. ret = CO_LSSmaster_SCAN_FAILED;
  800. }
  801. }
  802. }
  803. return ret;
  804. }
  805. /*
  806. * Helper function - check which 32 bit to scan for next, if any
  807. */
  808. static CO_LSS_fastscan_lss_sub_next CO_LSSmaster_FsSearchNext(
  809. CO_LSSmaster_t *LSSmaster,
  810. const CO_LSSmaster_fastscan_t *fastscan)
  811. {
  812. int i;
  813. /* we search for the next LSS address part to scan for, beginning with the
  814. * one after the current one. If there is none remaining, scanning is
  815. * finished */
  816. for (i = LSSmaster->fsLssSub + 1; i <= CO_LSS_FASTSCAN_SERIAL; i++) {
  817. if (fastscan->scan[i] != CO_LSSmaster_FS_SKIP) {
  818. return (CO_LSS_fastscan_lss_sub_next)i;
  819. }
  820. }
  821. /* node selection is triggered by switching node state machine back
  822. * to initial state */
  823. return CO_LSS_FASTSCAN_VENDOR_ID;
  824. }
  825. /******************************************************************************/
  826. CO_LSSmaster_return_t CO_LSSmaster_IdentifyFastscan(
  827. CO_LSSmaster_t *LSSmaster,
  828. uint32_t timeDifference_us,
  829. CO_LSSmaster_fastscan_t *fastscan)
  830. {
  831. uint8_t i;
  832. uint8_t count;
  833. CO_LSSmaster_return_t ret = CO_LSSmaster_INVALID_STATE;
  834. CO_LSS_fastscan_lss_sub_next next;
  835. /* parameter validation */
  836. if (LSSmaster==NULL || fastscan==NULL){
  837. return CO_LSSmaster_ILLEGAL_ARGUMENT;
  838. }
  839. if (fastscan->scan[0] == CO_LSSmaster_FS_SKIP) {
  840. /* vendor ID scan cannot be skipped */
  841. return CO_LSSmaster_ILLEGAL_ARGUMENT;
  842. }
  843. count = 0;
  844. for (i = 0; i < (sizeof(fastscan->scan) / sizeof(fastscan->scan[0])); i++) {
  845. if (fastscan->scan[i] == CO_LSSmaster_FS_SKIP) {
  846. count ++;
  847. }
  848. if (count > 2) {
  849. /* Node selection needs the Vendor ID and at least one other value */
  850. return CO_LSSmaster_ILLEGAL_ARGUMENT;
  851. }
  852. }
  853. /* state machine validation */
  854. if (LSSmaster->state!=CO_LSSmaster_STATE_WAITING ||
  855. (LSSmaster->command!=CO_LSSmaster_COMMAND_WAITING &&
  856. LSSmaster->command!=CO_LSSmaster_COMMAND_IDENTIFY_FASTSCAN)) {
  857. /* state machine not ready, other command is already processed */
  858. return CO_LSSmaster_INVALID_STATE;
  859. }
  860. /* evaluate LSS state machine */
  861. switch (LSSmaster->command) {
  862. case CO_LSSmaster_COMMAND_WAITING:
  863. /* start fastscan */
  864. LSSmaster->command = CO_LSSmaster_COMMAND_IDENTIFY_FASTSCAN;
  865. /* check if any nodes are waiting, if yes fastscan is reset */
  866. LSSmaster->fsState = CO_LSSmaster_FS_STATE_CHECK;
  867. CO_LSSmaster_FsSendMsg(LSSmaster, 0, CO_LSS_FASTSCAN_CONFIRM, 0, 0);
  868. return CO_LSSmaster_WAIT_SLAVE;
  869. default:
  870. /* continue with evaluating fastscan state machine */
  871. break;
  872. }
  873. /* evaluate fastscan state machine. The state machine is evaluated as following
  874. * - check for non-configured nodes
  875. * - scan for vendor ID
  876. * - verify vendor ID, switch node state
  877. * - scan for product code
  878. * - verify product code, switch node state
  879. * - scan for revision number
  880. * - verify revision number, switch node state
  881. * - scan for serial number
  882. * - verify serial number, switch node to LSS configuration mode
  883. * Certain steps can be skipped as mentioned in the function description.
  884. * If one step is not ack'ed by a node, the scanning process is terminated
  885. * and the correspondign error is returned. */
  886. switch (LSSmaster->fsState) {
  887. case CO_LSSmaster_FS_STATE_CHECK:
  888. ret = CO_LSSmaster_FsCheckWait(LSSmaster, timeDifference_us);
  889. if (ret == CO_LSSmaster_SCAN_FINISHED) {
  890. memset(&fastscan->found, 0, sizeof(fastscan->found));
  891. /* start scanning procedure by triggering vendor ID scan */
  892. CO_LSSmaster_FsScanInitiate(LSSmaster, timeDifference_us,
  893. fastscan->scan[CO_LSS_FASTSCAN_VENDOR_ID],
  894. CO_LSS_FASTSCAN_VENDOR_ID);
  895. ret = CO_LSSmaster_WAIT_SLAVE;
  896. LSSmaster->fsState = CO_LSSmaster_FS_STATE_SCAN;
  897. }
  898. break;
  899. case CO_LSSmaster_FS_STATE_SCAN:
  900. ret = CO_LSSmaster_FsScanWait(LSSmaster, timeDifference_us,
  901. fastscan->scan[LSSmaster->fsLssSub]);
  902. if (ret == CO_LSSmaster_SCAN_FINISHED) {
  903. /* scanning finished, initiate verifcation. The verification
  904. * message also contains the node state machine "switch to
  905. * next state" request */
  906. next = CO_LSSmaster_FsSearchNext(LSSmaster, fastscan);
  907. ret = CO_LSSmaster_FsVerifyInitiate(LSSmaster, timeDifference_us,
  908. fastscan->scan[LSSmaster->fsLssSub],
  909. fastscan->match.addr[LSSmaster->fsLssSub], next);
  910. LSSmaster->fsState = CO_LSSmaster_FS_STATE_VERIFY;
  911. }
  912. break;
  913. case CO_LSSmaster_FS_STATE_VERIFY:
  914. ret = CO_LSSmaster_FsVerifyWait(LSSmaster, timeDifference_us,
  915. fastscan->scan[LSSmaster->fsLssSub],
  916. &fastscan->found.addr[LSSmaster->fsLssSub]);
  917. if (ret == CO_LSSmaster_SCAN_FINISHED) {
  918. /* verification successful:
  919. * - assumed node id is correct
  920. * - node state machine has switched to the requested state,
  921. * mirror that in the local copy */
  922. next = CO_LSSmaster_FsSearchNext(LSSmaster, fastscan);
  923. if (next == CO_LSS_FASTSCAN_VENDOR_ID) {
  924. /* fastscan finished, one node is now in LSS configuration
  925. * mode */
  926. LSSmaster->state = CO_LSSmaster_STATE_CFG_SLECTIVE;
  927. }
  928. else {
  929. /* initiate scan for next part of LSS address */
  930. ret = CO_LSSmaster_FsScanInitiate(LSSmaster,
  931. timeDifference_us, fastscan->scan[next], next);
  932. if (ret == CO_LSSmaster_SCAN_FINISHED) {
  933. /* Scanning is not requested. Initiate verification
  934. * step in next function call */
  935. ret = CO_LSSmaster_WAIT_SLAVE;
  936. }
  937. LSSmaster->fsState = CO_LSSmaster_FS_STATE_SCAN;
  938. }
  939. }
  940. break;
  941. default:
  942. break;
  943. }
  944. if (ret != CO_LSSmaster_WAIT_SLAVE) {
  945. /* finished */
  946. LSSmaster->command = CO_LSSmaster_COMMAND_WAITING;
  947. }
  948. return ret;
  949. }
  950. #endif /* (CO_CONFIG_LSS) & CO_CONFIG_LSS_MASTER */