1 /** 2 * CANopen LSS Master/Slave protocol. 3 * 4 * @file CO_LSSmaster.h 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 27 28 #ifndef CO_LSSmaster_H 29 #define CO_LSSmaster_H 30 31 #ifdef __cplusplus 32 extern "C" { 33 #endif 34 35 #if CO_NO_LSS_CLIENT == 1 36 37 #include "CO_LSS.h" 38 39 /** 40 * @addtogroup CO_LSS 41 * @defgroup CO_LSSmaster LSS Master 42 * @ingroup CO_LSS 43 * @{ 44 * 45 * CANopen Layer Setting Service - client protocol 46 * 47 * The client/master can use the following services 48 * - node selection via LSS address 49 * - node selection via LSS fastscan 50 * - Inquire LSS address of currently selected node 51 * - Inquire node ID 52 * - Configure bit timing 53 * - Configure node ID 54 * - Activate bit timing parameters 55 * - Store configuration 56 * 57 * The LSS master is initalized during the CANopenNode initialization process. 58 * Except for enabling the LSS master in the configurator, no further 59 * run-time configuration is needed for basic operation. 60 * The LSS master does basic checking of commands and command sequence. 61 * 62 * ###Usage 63 * 64 * Usage of the CANopen LSS master is demonstrated in CANopenSocket application, 65 * see CO_LSS_master.c / CO_LSS_master.h files. 66 * 67 * It essentially is always as following: 68 * - select node(s) 69 * - call master command(s) 70 * - evaluate return value 71 * - deselect nodes 72 * 73 * All commands need to be run cyclically, e.g. like this 74 * \code{.c} 75 76 interval = 0; 77 do { 78 ret = CO_LSSmaster_InquireNodeId(LSSmaster, interval, &outval); 79 80 interval = 1; ms 81 sleep(interval); 82 } while (ret == CO_LSSmaster_WAIT_SLAVE); 83 84 * \endcode 85 * 86 * A more advanced implementation can make use of the callback function to 87 * shorten waiting times. 88 */ 89 90 /** 91 * Return values of LSS master functions. 92 */ 93 typedef enum { 94 CO_LSSmaster_SCAN_FINISHED = 2, /**< Scanning finished successful */ 95 CO_LSSmaster_WAIT_SLAVE = 1, /**< No response arrived from server yet */ 96 CO_LSSmaster_OK = 0, /**< Success, end of communication */ 97 CO_LSSmaster_TIMEOUT = -1, /**< No reply received */ 98 CO_LSSmaster_ILLEGAL_ARGUMENT = -2, /**< Invalid argument */ 99 CO_LSSmaster_INVALID_STATE = -3, /**< State machine not ready or already processing a request */ 100 CO_LSSmaster_SCAN_NOACK = -4, /**< No node found that matches scan request */ 101 CO_LSSmaster_SCAN_FAILED = -5, /**< An error occurred while scanning. Try again */ 102 CO_LSSmaster_OK_ILLEGAL_ARGUMENT = -101, /**< LSS success, node rejected argument because of non-supported value */ 103 CO_LSSmaster_OK_MANUFACTURER = -102, /**< LSS success, node rejected argument with manufacturer error code */ 104 } CO_LSSmaster_return_t; 105 106 107 /** 108 * LSS master object. 109 */ 110 typedef struct{ 111 uint16_t timeout; /**< LSS response timeout in ms */ 112 113 uint8_t state; /**< Node is currently selected */ 114 uint8_t command; /**< Active command */ 115 uint16_t timeoutTimer; /**< Timeout timer for LSS communication */ 116 117 uint8_t fsState; /**< Current state of fastscan master state machine */ 118 uint8_t fsLssSub; /**< Current state of node state machine */ 119 uint8_t fsBitChecked; /**< Current scan bit position */ 120 uint32_t fsIdNumber; /**< Current scan result */ 121 122 volatile void *CANrxNew; /**< Indication if new LSS message is received from CAN bus. It needs to be cleared when received message is completely processed. */ 123 uint8_t CANrxData[8]; /**< 8 data bytes of the received message */ 124 125 void (*pFunctSignal)(void *object); /**< From CO_LSSmaster_initCallback() or NULL */ 126 void *functSignalObject;/**< Pointer to object */ 127 128 CO_CANmodule_t *CANdevTx; /**< From #CO_LSSslave_init() */ 129 CO_CANtx_t *TXbuff; /**< CAN transmit buffer */ 130 }CO_LSSmaster_t; 131 132 133 /** 134 * Default timeout for LSS slave in ms. This is the same as for SDO. For more 135 * info about LSS timeout see #CO_LSSmaster_changeTimeout() 136 */ 137 #define CO_LSSmaster_DEFAULT_TIMEOUT 1000U /* ms */ 138 139 140 /** 141 * Initialize LSS object. 142 * 143 * Function must be called in the communication reset section. 144 * 145 * @param LSSmaster This object will be initialized. 146 * @param timeout_ms slave response timeout in ms, for more detail see 147 * #CO_LSSmaster_changeTimeout() 148 * @param CANdevRx CAN device for LSS master reception. 149 * @param CANdevRxIdx Index of receive buffer in the above CAN device. 150 * @param CANidLssSlave COB ID for reception. 151 * @param CANdevTx CAN device for LSS master transmission. 152 * @param CANdevTxIdx Index of transmit buffer in the above CAN device. 153 * @param CANidLssMaster COB ID for transmission. 154 * @return #CO_ReturnError_t: CO_ERROR_NO or CO_ERROR_ILLEGAL_ARGUMENT. 155 */ 156 CO_ReturnError_t CO_LSSmaster_init( 157 CO_LSSmaster_t *LSSmaster, 158 uint16_t timeout_ms, 159 CO_CANmodule_t *CANdevRx, 160 uint16_t CANdevRxIdx, 161 uint32_t CANidLssSlave, 162 CO_CANmodule_t *CANdevTx, 163 uint16_t CANdevTxIdx, 164 uint32_t CANidLssMaster); 165 166 /** 167 * Change LSS master timeout 168 * 169 * On LSS, a "negative ack" is signaled by the slave not answering. Because of 170 * that, a low timeout value can significantly increase protocol speed in some 171 * cases (e.g. fastscan). However, as soon as there is activity on the bus, 172 * LSS messages can be delayed because of their low CAN network priority (see 173 * #CO_Default_CAN_ID_t). 174 * 175 * @remark Be aware that a "late response" will seriously mess up LSS, so this 176 * value must be selected "as high as necessary and as low as possible". CiA does 177 * neither specify nor recommend a value. 178 * 179 * @remark This timeout is per-transfer. If a command internally needs multiple 180 * transfers to complete, this timeout is applied on each transfer. 181 * 182 * @param LSSmaster This object. 183 * @param timeout_ms timeout value in ms 184 */ 185 void CO_LSSmaster_changeTimeout( 186 CO_LSSmaster_t *LSSmaster, 187 uint16_t timeout_ms); 188 189 190 /** 191 * Initialize LSSserverRx callback function. 192 * 193 * Function initializes optional callback function, which is called after new 194 * message is received from the CAN bus. Function may wake up external task, 195 * which processes mainline CANopen functions. 196 * 197 * @param LSSmaster This object. 198 * @param object Pointer to object, which will be passed to pFunctSignal(). Can be NULL 199 * @param pFunctSignal Pointer to the callback function. Not called if NULL. 200 */ 201 void CO_LSSmaster_initCallback( 202 CO_LSSmaster_t *LSSmaster, 203 void *object, 204 void (*pFunctSignal)(void *object)); 205 206 207 /** 208 * Request LSS switch state select 209 * 210 * This function can select one specific or all nodes. 211 * 212 * Function must be called cyclically until it returns != #CO_LSSmaster_WAIT_SLAVE 213 * Function is non-blocking. 214 * 215 * @remark Only one selection can be active at any time. 216 * 217 * @param LSSmaster This object. 218 * @param timeDifference_ms Time difference from previous function call in 219 * [milliseconds]. Zero when request is started. 220 * @param lssAddress LSS target address. If NULL, all nodes are selected 221 * @return #CO_LSSmaster_ILLEGAL_ARGUMENT, #CO_LSSmaster_INVALID_STATE, 222 * #CO_LSSmaster_WAIT_SLAVE, #CO_LSSmaster_OK, #CO_LSSmaster_TIMEOUT 223 */ 224 CO_LSSmaster_return_t CO_LSSmaster_switchStateSelect( 225 CO_LSSmaster_t *LSSmaster, 226 uint16_t timeDifference_ms, 227 CO_LSS_address_t *lssAddress); 228 229 230 /** 231 * Request LSS switch state deselect 232 * 233 * This function deselects all nodes, so it doesn't matter if a specific 234 * node is selected. 235 * 236 * This function also resets the LSS master state machine to a clean state 237 * 238 * @param LSSmaster This object. 239 * @return #CO_LSSmaster_ILLEGAL_ARGUMENT, #CO_LSSmaster_INVALID_STATE, 240 * #CO_LSSmaster_OK 241 */ 242 CO_LSSmaster_return_t CO_LSSmaster_switchStateDeselect( 243 CO_LSSmaster_t *LSSmaster); 244 245 246 /** 247 * Request LSS configure Bit Timing 248 * 249 * The new bit rate is set as new pending value. 250 * 251 * This function needs one specific node to be selected. 252 * 253 * Function must be called cyclically until it returns != #CO_LSSmaster_WAIT_SLAVE. 254 * Function is non-blocking. 255 * 256 * @param LSSmaster This object. 257 * @param timeDifference_ms Time difference from previous function call in 258 * [milliseconds]. Zero when request is started. 259 * @param bit new bit rate 260 * @return #CO_LSSmaster_ILLEGAL_ARGUMENT, #CO_LSSmaster_INVALID_STATE, 261 * #CO_LSSmaster_WAIT_SLAVE, #CO_LSSmaster_OK, #CO_LSSmaster_TIMEOUT, 262 * #CO_LSSmaster_OK_MANUFACTURER, #CO_LSSmaster_OK_ILLEGAL_ARGUMENT 263 */ 264 CO_LSSmaster_return_t CO_LSSmaster_configureBitTiming( 265 CO_LSSmaster_t *LSSmaster, 266 uint16_t timeDifference_ms, 267 uint16_t bit); 268 269 270 /** 271 * Request LSS configure node ID 272 * 273 * The new node id is set as new pending node ID. 274 * 275 * This function needs one specific node to be selected. 276 * 277 * Function must be called cyclically until it returns != #CO_LSSmaster_WAIT_SLAVE. 278 * Function is non-blocking. 279 * 280 * @param LSSmaster This object. 281 * @param timeDifference_ms Time difference from previous function call in 282 * [milliseconds]. Zero when request is started. 283 * @param nodeId new node ID. Special value #CO_LSS_NODE_ID_ASSIGNMENT can be 284 * used to invalidate node ID. 285 * @return #CO_LSSmaster_ILLEGAL_ARGUMENT, #CO_LSSmaster_INVALID_STATE, 286 * #CO_LSSmaster_WAIT_SLAVE, #CO_LSSmaster_OK, #CO_LSSmaster_TIMEOUT, 287 * #CO_LSSmaster_OK_MANUFACTURER, #CO_LSSmaster_OK_ILLEGAL_ARGUMENT 288 */ 289 CO_LSSmaster_return_t CO_LSSmaster_configureNodeId( 290 CO_LSSmaster_t *LSSmaster, 291 uint16_t timeDifference_ms, 292 uint8_t nodeId); 293 294 295 /** 296 * Request LSS store configuration 297 * 298 * The current "pending" values for bit rate and node ID in LSS slave are 299 * stored as "permanent" values. 300 * 301 * This function needs one specific node to be selected. 302 * 303 * Function must be called cyclically until it returns != #CO_LSSmaster_WAIT_SLAVE. 304 * Function is non-blocking. 305 * 306 * @param LSSmaster This object. 307 * @param timeDifference_ms Time difference from previous function call in 308 * [milliseconds]. Zero when request is started. 309 * @return #CO_LSSmaster_ILLEGAL_ARGUMENT, #CO_LSSmaster_INVALID_STATE, 310 * #CO_LSSmaster_WAIT_SLAVE, #CO_LSSmaster_OK, #CO_LSSmaster_TIMEOUT, 311 * #CO_LSSmaster_OK_MANUFACTURER, #CO_LSSmaster_OK_ILLEGAL_ARGUMENT 312 */ 313 CO_LSSmaster_return_t CO_LSSmaster_configureStore( 314 CO_LSSmaster_t *LSSmaster, 315 uint16_t timeDifference_ms); 316 317 318 /** 319 * Request LSS activate bit timing 320 * 321 * The current "pending" bit rate in LSS slave is applied. 322 * 323 * Be aware that changing the bit rate is a critical step for the network. A 324 * failure will render the network unusable! Therefore, this function only 325 * should be called if the following conditions are met: 326 * - all nodes support changing bit timing 327 * - new bit timing is successfully set as "pending" in all nodes 328 * - all nodes have to activate the new bit timing roughly at the same time. 329 * Therefore this function needs all nodes to be selected. 330 * 331 * @param LSSmaster This object. 332 * @param switchDelay_ms delay that is applied by the slave once before and 333 * once after switching in ms. 334 * @return #CO_LSSmaster_ILLEGAL_ARGUMENT, #CO_LSSmaster_INVALID_STATE, 335 * #CO_LSSmaster_OK 336 */ 337 CO_LSSmaster_return_t CO_LSSmaster_ActivateBit( 338 CO_LSSmaster_t *LSSmaster, 339 uint16_t switchDelay_ms); 340 341 342 /** 343 * Request LSS inquire LSS address 344 * 345 * The LSS address value is read from the node. This is useful when the node 346 * was selected by fastscan. 347 * 348 * This function needs one specific node to be selected. 349 * 350 * Function must be called cyclically until it returns != #CO_LSSmaster_WAIT_SLAVE. 351 * Function is non-blocking. 352 * 353 * @param LSSmaster This object. 354 * @param timeDifference_ms Time difference from previous function call in 355 * [milliseconds]. Zero when request is started. 356 * @param lssAddress [out] read result when function returns successfully 357 * @return #CO_LSSmaster_ILLEGAL_ARGUMENT, #CO_LSSmaster_INVALID_STATE, 358 * #CO_LSSmaster_WAIT_SLAVE, #CO_LSSmaster_OK, #CO_LSSmaster_TIMEOUT 359 */ 360 CO_LSSmaster_return_t CO_LSSmaster_InquireLssAddress( 361 CO_LSSmaster_t *LSSmaster, 362 uint16_t timeDifference_ms, 363 CO_LSS_address_t *lssAddress); 364 365 366 /** 367 * Request LSS inquire node ID 368 * 369 * The node ID value is read from the node. 370 * 371 * This function needs one specific node to be selected. 372 * 373 * Function must be called cyclically until it returns != #CO_LSSmaster_WAIT_SLAVE. 374 * Function is non-blocking. 375 * 376 * @param LSSmaster This object. 377 * @param timeDifference_ms Time difference from previous function call in 378 * [milliseconds]. Zero when request is started. 379 * @param nodeId [out] read result when function returns successfully 380 * @return #CO_LSSmaster_ILLEGAL_ARGUMENT, #CO_LSSmaster_INVALID_STATE, 381 * #CO_LSSmaster_WAIT_SLAVE, #CO_LSSmaster_OK, #CO_LSSmaster_TIMEOUT 382 */ 383 CO_LSSmaster_return_t CO_LSSmaster_InquireNodeId( 384 CO_LSSmaster_t *LSSmaster, 385 uint16_t timeDifference_ms, 386 uint8_t *nodeId); 387 388 389 /** 390 * Scan type for #CO_LSSmaster_fastscan_t scan 391 */ 392 typedef enum { 393 CO_LSSmaster_FS_SCAN = 0, /**< Do full 32 bit scan */ 394 CO_LSSmaster_FS_SKIP = 1, /**< Skip this value */ 395 CO_LSSmaster_FS_MATCH = 2, /**< Full 32 bit value is given as argument, just verify */ 396 } CO_LSSmaster_scantype_t; 397 398 /** 399 * Parameters for LSS fastscan #CO_LSSmaster_IdentifyFastscan 400 */ 401 typedef struct{ 402 CO_LSSmaster_scantype_t scan[4]; /**< Scan type for each part of the LSS address */ 403 CO_LSS_address_t match; /**< Value to match in case of #CO_LSSmaster_FS_MATCH */ 404 CO_LSS_address_t found; /**< Scan result */ 405 } CO_LSSmaster_fastscan_t; 406 407 /** 408 * Select a node by LSS identify fastscan 409 * 410 * This initiates searching for a unconfigured node by the means of LSS fastscan 411 * mechanism. When this function is finished 412 * - a (more or less) arbitrary node is selected and ready for node ID assingment 413 * - no node is selected because the given criteria do not match a node 414 * - no node is selected because all nodes are already configured 415 * 416 * There are multiple ways to scan for a node. Depending on those, the scan 417 * will take different amounts of time: 418 * - full scan 419 * - partial scan 420 * - verification 421 * 422 * Most of the time, those are used in combination. Consider the following example: 423 * - Vendor ID and product code are known 424 * - Software version doesn't matter 425 * - Serial number is unknown 426 * 427 * In this case, the fastscan structure should be set up as following: 428 * \code{.c} 429 CO_LSSmaster_fastscan_t fastscan; 430 fastscan.scan[CO_LSS_FASTSCAN_VENDOR_ID] = CO_LSSmaster_FS_MATCH; 431 fastscan.match.vendorID = YOUR_VENDOR_ID; 432 fastscan.scan[CO_LSS_FASTSCAN_PRODUCT] = CO_LSSmaster_FS_MATCH; 433 fastscan.match.productCode = YOUR_PRODUCT_CODE; 434 fastscan.scan[CO_LSS_FASTSCAN_REV] = CO_LSSmaster_FS_SKIP; 435 fastscan.scan[CO_LSS_FASTSCAN_SERIAL] = CO_LSSmaster_FS_SCAN; 436 * \endcode 437 * 438 * This example will take 2 scan cyles for verifying vendor ID and product code 439 * and 33 scan cycles to find the serial number. 440 * 441 * For scanning, the following limitations apply: 442 * - No more than two values can be skipped 443 * - Vendor ID cannot be skipped 444 * 445 * @remark When doing partial scans, it is in the responsibility of the user 446 * that the LSS address is unique. 447 * 448 * This function needs that no node is selected when starting the scan process. 449 * 450 * Function must be called cyclically until it returns != #CO_LSSmaster_WAIT_SLAVE. 451 * Function is non-blocking. 452 * 453 * @param LSSmaster This object. 454 * @param timeDifference_ms Time difference from previous function call in 455 * [milliseconds]. Zero when request is started. 456 * @param fastscan struct according to #CO_LSSmaster_fastscan_t. 457 * @return #CO_LSSmaster_ILLEGAL_ARGUMENT, #CO_LSSmaster_INVALID_STATE, 458 * #CO_LSSmaster_WAIT_SLAVE, #CO_LSSmaster_SCAN_FINISHED, #CO_LSSmaster_SCAN_NOACK, 459 * #CO_LSSmaster_SCAN_FAILED 460 */ 461 CO_LSSmaster_return_t CO_LSSmaster_IdentifyFastscan( 462 CO_LSSmaster_t *LSSmaster, 463 uint16_t timeDifference_ms, 464 CO_LSSmaster_fastscan_t *fastscan); 465 466 467 #else /* CO_NO_LSS_CLIENT == 1 */ 468 469 /** 470 * @addtogroup CO_LSS 471 * @{ 472 * If you need documetation for LSS master usage, add "CO_NO_LSS_CLIENT=1" to doxygen 473 * "PREDEFINED" variable. 474 * 475 */ 476 477 #endif /* CO_NO_LSS_CLIENT == 1 */ 478 479 #ifdef __cplusplus 480 } 481 #endif /*__cplusplus*/ 482 483 /** @} */ 484 #endif 485