diff --git a/CANopen.c b/CANopen.c index 358f358..695e18d 100644 --- a/CANopen.c +++ b/CANopen.c @@ -525,6 +525,7 @@ CO_ReturnError_t CO_CANopenInit( CO_OD_NoOfElements, CO_SDO_ODExtensions, nodeId, + 1000, CO->CANmodule[0], CO_RXCAN_SDO_SRV+i, CO->CANmodule[0], @@ -815,63 +816,52 @@ void CO_delete(void *CANptr){ /******************************************************************************/ CO_NMT_reset_cmd_t CO_process( CO_t *co, - uint16_t timeDifference_ms, - uint16_t *timerNext_ms) + uint32_t timeDifference_us, + uint32_t *timerNext_us) { uint8_t i; bool_t NMTisPreOrOperational = false; CO_NMT_reset_cmd_t reset = CO_RESET_NOT; -#ifdef CO_USE_LEDS - static uint16_t ms50 = 0; -#endif /* CO_USE_LEDS */ if(co->NMT->operatingState == CO_NMT_PRE_OPERATIONAL || co->NMT->operatingState == CO_NMT_OPERATIONAL) NMTisPreOrOperational = true; -#ifdef CO_USE_LEDS - ms50 += timeDifference_ms; - if(ms50 >= 50){ - ms50 -= 50; - CO_NMT_blinkingProcess50ms(co->NMT); - } -#endif /* CO_USE_LEDS */ - for(i=0; iSDO[i], NMTisPreOrOperational, - timeDifference_ms, - 1000, - timerNext_ms); + timeDifference_us, + timerNext_us); } CO_EM_process( co->emPr, NMTisPreOrOperational, - timeDifference_ms * 10, + timeDifference_us, OD_inhibitTimeEMCY, - timerNext_ms); + timerNext_us); reset = CO_NMT_process( co->NMT, - timeDifference_ms, + timeDifference_us, OD_producerHeartbeatTime, OD_NMTStartup, OD_errorRegister, OD_errorBehavior, - timerNext_ms); + timerNext_us); CO_HBconsumer_process( co->HBcons, NMTisPreOrOperational, - timeDifference_ms); + timeDifference_us, + timerNext_us); #if CO_NO_TIME == 1 CO_TIME_process( co->TIME, - timeDifference_ms); + timeDifference_us); #endif return reset; diff --git a/CANopen.h b/CANopen.h index d7dc413..2f6e794 100644 --- a/CANopen.h +++ b/CANopen.h @@ -200,10 +200,10 @@ void CO_delete(void *CANptr); * objects. * * @param co CANopen object. - * @param timeDifference_ms Time difference from previous function call in [milliseconds]. - * @param timerNext_ms Return value - info to OS - maximum delay after function - * should be called next time in [milliseconds]. Value can be used for OS - * sleep time. Initial value must be set to something, 50ms typically. + * @param timeDifference_us Time difference from previous function call in [microseconds]. + * @param timerNext_us [out] info to OS - maximum delay after function + * should be called next time in [microseconds]. Value can be used for OS + * sleep time. Initial value must be set to something, 50000us typically. * Output will be equal or lower to initial value. If there is new object * to process, delay should be suspended and this function should be * called immediately. Parameter is ignored if NULL. @@ -212,8 +212,8 @@ void CO_delete(void *CANptr); */ CO_NMT_reset_cmd_t CO_process( CO_t *co, - uint16_t timeDifference_ms, - uint16_t *timerNext_ms); + uint32_t timeDifference_us, + uint32_t *timerNext_us); #if CO_NO_SYNC == 1 @@ -271,7 +271,7 @@ void CO_process_TPDO( * * @param CO This object. * @param timeDifference_us Time difference from previous function call in [microseconds]. - * @param timerNext_us Return value - info to OS - maximum delay after function + * @param timerNext_us [out] info to OS - maximum delay after function * should be called next time in [microseconds]. Value can be used for OS * sleep time. Initial value must be set to something, 1000us typically. * Output will be equal or lower to initial value. If there is new object diff --git a/socketCAN/CO_driver.c b/socketCAN/CO_driver.c index 3218fcb..9b3d6d4 100644 --- a/socketCAN/CO_driver.c +++ b/socketCAN/CO_driver.c @@ -1,7 +1,5 @@ /* - * CAN module object for Linux socketCAN. - * - * This file is a template for other microcontrollers. + * Linux socketCAN interface for CANopenNode. * * @file CO_driver.c * @ingroup CO_driver diff --git a/socketCAN/CO_notify_pipe.h b/socketCAN/CO_notify_pipe.h index b7bea17..52a46cc 100644 --- a/socketCAN/CO_notify_pipe.h +++ b/socketCAN/CO_notify_pipe.h @@ -1,7 +1,5 @@ /** - * CAN module object for Linux socketCAN. - * - * This file is a template for other microcontrollers. + * Notify pipe for Linux threads. * * @file CO_notify_pipe.h * @ingroup CO_driver diff --git a/stack/CO_Emergency.c b/stack/CO_Emergency.c index 4ee75b5..60366bd 100644 --- a/stack/CO_Emergency.c +++ b/stack/CO_Emergency.c @@ -232,15 +232,16 @@ void CO_EM_initCallbackRx( void CO_EM_process( CO_EMpr_t *emPr, bool_t NMTisPreOrOperational, - uint16_t timeDifference_100us, - uint16_t emInhTime, - uint16_t *timerNext_ms) + uint32_t timeDifference_us, + uint16_t emInhTime_100us, + uint32_t *timerNext_us) { CO_EM_t *em = emPr->em; uint8_t errorRegister; uint8_t errorMask; uint8_t i; + uint32_t emInhTime_us = (uint32_t)emInhTime_100us * 100; /* verify errors from driver and other */ CO_CANverifyErrors(emPr->CANdev); @@ -270,8 +271,8 @@ void CO_EM_process( *emPr->errorRegister = (*emPr->errorRegister & errorMask) | errorRegister; /* inhibit time */ - if(emPr->inhibitEmTimer < emInhTime){ - emPr->inhibitEmTimer += timeDifference_100us; + if (emPr->inhibitEmTimer < emInhTime_us) { + emPr->inhibitEmTimer += timeDifference_us; } /* send Emergency message. */ @@ -282,7 +283,7 @@ void CO_EM_process( uint32_t preDEF; /* preDefinedErrorField */ uint16_t diff; - if (emPr->inhibitEmTimer >= emInhTime) { + if (emPr->inhibitEmTimer >= emInhTime_us) { /* inhibit time elapsed, send message */ /* add error register */ @@ -323,11 +324,12 @@ void CO_EM_process( /* send CAN message */ CO_CANsend(emPr->CANdev, emPr->CANtxBuff); } - - /* check again after inhibit time elapsed */ - diff = (emInhTime + 9) / 10; /* time difference in ms, always round up */ - if (timerNext_ms != NULL && *timerNext_ms > diff) { - *timerNext_ms = diff; + else if (timerNext_us != NULL) { + /* check again after inhibit time elapsed */ + diff = emInhTime_us - emPr->inhibitEmTimer; + if (*timerNext_us > diff) { + *timerNext_us = diff; + } } } diff --git a/stack/CO_Emergency.h b/stack/CO_Emergency.h index 40bb9ae..4bb3d85 100644 --- a/stack/CO_Emergency.h +++ b/stack/CO_Emergency.h @@ -339,7 +339,7 @@ typedef struct{ uint32_t *preDefErr; /**< From CO_EM_init() */ uint8_t preDefErrSize; /**< From CO_EM_init() */ uint8_t preDefErrNoOfErrors;/**< Number of active errors in preDefErr */ - uint16_t inhibitEmTimer; /**< Internal timer for emergency message */ + uint32_t inhibitEmTimer; /**< Internal timer for emergency message */ CO_EM_t *em; /**< CO_EM_t sub object is included here */ CO_CANmodule_t *CANdev; /**< From CO_EM_init() */ CO_CANtx_t *CANtxBuff; /**< CAN transmit buffer */ @@ -432,16 +432,16 @@ void CO_EM_initCallbackRx( * * @param emPr This object. * @param NMTisPreOrOperational True if this node is NMT_PRE_OPERATIONAL or NMT_OPERATIONAL. - * @param timeDifference_100us Time difference from previous function call in [100 * microseconds]. - * @param emInhTime _Inhibit time EMCY_ (object dictionary, index 0x1015). - * @param timerNext_ms Return value - info to OS - see CO_process(). + * @param timeDifference_us Time difference from previous function call in [microseconds]. + * @param emInhTime _Inhibit time EMCY_ in [100*us] (object dictionary, index 0x1015). + * @param timerNext_us [out] info to OS - see CO_process(). */ void CO_EM_process( CO_EMpr_t *emPr, bool_t NMTisPreOrOperational, - uint16_t timeDifference_100us, + uint32_t timeDifference_us, uint16_t emInhTime, - uint16_t *timerNext_ms); + uint32_t *timerNext_us); #endif diff --git a/stack/CO_HBconsumer.c b/stack/CO_HBconsumer.c index 725910b..b320445 100644 --- a/stack/CO_HBconsumer.c +++ b/stack/CO_HBconsumer.c @@ -52,52 +52,6 @@ static void CO_HBcons_receive(void *object, void *msg){ } -/* - * Configure one monitored node. - */ -static void CO_HBcons_monitoredNodeConfig( - CO_HBconsumer_t *HBcons, - uint8_t idx, - uint8_t nodeId, - uint16_t time) -{ - uint16_t COB_ID; - CO_HBconsNode_t *monitoredNode; - - if(idx >= HBcons->numberOfMonitoredNodes) return; - - monitoredNode = &HBcons->monitoredNodes[idx]; - monitoredNode->nodeId = nodeId; - monitoredNode->time = time; - monitoredNode->NMTstate = CO_NMT_INITIALIZING; - monitoredNode->HBstate = CO_HBconsumer_UNCONFIGURED; - CO_CANrxNew_CLEAR(monitoredNode->CANrxNew); - - /* is channel used */ - if(monitoredNode->nodeId && monitoredNode->time){ - COB_ID = monitoredNode->nodeId + CO_CAN_ID_HEARTBEAT; - monitoredNode->HBstate = CO_HBconsumer_UNKNOWN; - - } - else{ - COB_ID = 0; - monitoredNode->time = 0; - } - - /* configure Heartbeat consumer CAN reception */ - if (monitoredNode->HBstate != CO_HBconsumer_UNCONFIGURED) { - CO_CANrxBufferInit( - HBcons->CANdevRx, - HBcons->CANdevRxIdxStart + idx, - COB_ID, - 0x7FF, - 0, - (void*)&HBcons->monitoredNodes[idx], - CO_HBcons_receive); - } -} - - /* * OD function for accessing _Consumer Heartbeat Time_ (index 0x1016) from SDO server. * @@ -156,7 +110,9 @@ CO_ReturnError_t CO_HBconsumer_init( HBcons->HBconsTime = HBconsTime; HBcons->monitoredNodes = monitoredNodes; HBcons->numberOfMonitoredNodes = numberOfMonitoredNodes; - HBcons->allMonitoredOperational = 0; + HBcons->allMonitoredActive = false; + HBcons->allMonitoredOperational = CO_NMT_INITIALIZING; + HBcons->NMTisPreOrOperationalPrev = false; HBcons->CANdevRx = CANdevRx; HBcons->CANdevRxIdxStart = CANdevRxIdxStart; @@ -178,7 +134,7 @@ CO_ReturnError_t CO_HBconsumer_initEntry( CO_HBconsumer_t *HBcons, uint8_t idx, uint8_t nodeId, - uint16_t consumerTime) + uint16_t consumerTime_ms) { CO_ReturnError_t ret = CO_ERROR_NO; @@ -187,7 +143,7 @@ CO_ReturnError_t CO_HBconsumer_initEntry( return CO_ERROR_ILLEGAL_ARGUMENT; } - if((consumerTime != 0) && (nodeId != 0)){ + if((consumerTime_ms != 0) && (nodeId != 0)){ uint8_t i; /* there must not be more entries with same index and time different than zero */ for(i = 0U; inumberOfMonitoredNodes; i++){ @@ -200,9 +156,37 @@ CO_ReturnError_t CO_HBconsumer_initEntry( } } - /* Configure */ - if(ret == CO_ERROR_NO){ - CO_HBcons_monitoredNodeConfig(HBcons, idx, nodeId, consumerTime); + /* Configure one monitored node */ + if (ret == CO_ERROR_NO && idx < HBcons->numberOfMonitoredNodes ) { + uint16_t COB_ID; + + CO_HBconsNode_t * monitoredNode = &HBcons->monitoredNodes[idx]; + monitoredNode->nodeId = nodeId; + monitoredNode->time_us = (int32_t)consumerTime_ms * 1000; + monitoredNode->NMTstate = CO_NMT_INITIALIZING; + CO_CANrxNew_CLEAR(monitoredNode->CANrxNew); + + /* is channel used */ + if (monitoredNode->nodeId && monitoredNode->time_us) { + COB_ID = monitoredNode->nodeId + CO_CAN_ID_HEARTBEAT; + monitoredNode->HBstate = CO_HBconsumer_UNKNOWN; + } + else { + COB_ID = 0; + monitoredNode->time_us = 0; + monitoredNode->HBstate = CO_HBconsumer_UNCONFIGURED; + } + + /* configure Heartbeat consumer CAN reception */ + if (monitoredNode->HBstate != CO_HBconsumer_UNCONFIGURED) { + CO_CANrxBufferInit(HBcons->CANdevRx, + HBcons->CANdevRxIdxStart + idx, + COB_ID, + 0x7FF, + 0, + (void*)&HBcons->monitoredNodes[idx], + CO_HBcons_receive); + } } return ret; } @@ -264,102 +248,120 @@ void CO_HBconsumer_initCallbackRemoteReset( monitoredNode->functSignalObjectRemoteReset = object; } + /******************************************************************************/ void CO_HBconsumer_process( CO_HBconsumer_t *HBcons, bool_t NMTisPreOrOperational, - uint16_t timeDifference_ms) + uint32_t timeDifference_us, + uint32_t *timerNext_us) { uint8_t i; - uint8_t emcyHeartbeatTimeoutActive = 0; - uint8_t emcyRemoteResetActive = 0; - uint8_t AllMonitoredOperationalCopy; - CO_HBconsNode_t *monitoredNode; + bool_t allMonitoredActiveCurrent = true; + uint8_t allMonitoredOperationalCurrent = CO_NMT_OPERATIONAL; + CO_HBconsNode_t *monitoredNode = &HBcons->monitoredNodes[0]; - AllMonitoredOperationalCopy = 5; - monitoredNode = &HBcons->monitoredNodes[0]; + if (NMTisPreOrOperational && HBcons->NMTisPreOrOperationalPrev) { + for (i=0; inumberOfMonitoredNodes; i++) { + uint32_t timeDifference_us_copy = timeDifference_us; - if(NMTisPreOrOperational){ - for(i=0; inumberOfMonitoredNodes; i++){ - if(monitoredNode->time > 0){/* is node monitored */ - /* Verify if received message is heartbeat or bootup */ - if(CO_CANrxNew_READ(monitoredNode->CANrxNew)){ - if(monitoredNode->NMTstate == CO_NMT_INITIALIZING){ - /* bootup message, call callback */ - if (monitoredNode->pFunctSignalRemoteReset != NULL) { - monitoredNode->pFunctSignalRemoteReset(monitoredNode->nodeId, i, - monitoredNode->functSignalObjectRemoteReset); - } + if (monitoredNode->HBstate == CO_HBconsumer_UNCONFIGURED) { + /* continue, if node is not monitored */ + continue; + } + /* Verify if received message is heartbeat or bootup */ + if (CO_CANrxNew_READ(monitoredNode->CANrxNew)) { + if (monitoredNode->NMTstate == CO_NMT_INITIALIZING) { + /* bootup message, call callback */ + if (monitoredNode->pFunctSignalRemoteReset != NULL) { + monitoredNode->pFunctSignalRemoteReset( + monitoredNode->nodeId, i, + monitoredNode->functSignalObjectRemoteReset); } - else { - /* heartbeat message */ - if (monitoredNode->HBstate!=CO_HBconsumer_ACTIVE && - monitoredNode->pFunctSignalHbStarted!=NULL) { - monitoredNode->pFunctSignalHbStarted(monitoredNode->nodeId, i, - monitoredNode->functSignalObjectHbStarted); - } - monitoredNode->HBstate = CO_HBconsumer_ACTIVE; - monitoredNode->timeoutTimer = 0; /* reset timer */ - timeDifference_ms = 0; + if (monitoredNode->HBstate == CO_HBconsumer_ACTIVE) { + CO_errorReport(HBcons->em, + CO_EM_HB_CONSUMER_REMOTE_RESET, + CO_EMC_HEARTBEAT, i); } - CO_CANrxNew_CLEAR(monitoredNode->CANrxNew); + monitoredNode->HBstate = CO_HBconsumer_UNKNOWN; + + } + else { + /* heartbeat message, call callback */ + if (monitoredNode->HBstate != CO_HBconsumer_ACTIVE && + monitoredNode->pFunctSignalHbStarted != NULL) { + monitoredNode->pFunctSignalHbStarted( + monitoredNode->nodeId, i, + monitoredNode->functSignalObjectHbStarted); + } + monitoredNode->HBstate = CO_HBconsumer_ACTIVE; + /* reset timer */ + monitoredNode->timeoutTimer = 0; + timeDifference_us_copy = 0; + } + CO_CANrxNew_CLEAR(monitoredNode->CANrxNew); + } + + /* Verify timeout */ + if (monitoredNode->HBstate == CO_HBconsumer_ACTIVE) { + monitoredNode->timeoutTimer += timeDifference_us_copy; + + if (monitoredNode->timeoutTimer >= monitoredNode->time_us) { + /* timeout expired, call callback */ + if (monitoredNode->pFunctSignalTimeout!=NULL) { + monitoredNode->pFunctSignalTimeout( + monitoredNode->nodeId, i, + monitoredNode->functSignalObjectTimeout); + } + CO_errorReport(HBcons->em, CO_EM_HEARTBEAT_CONSUMER, + CO_EMC_HEARTBEAT, i); + monitoredNode->NMTstate = CO_NMT_INITIALIZING; + monitoredNode->HBstate = CO_HBconsumer_TIMEOUT; } - /* Verify timeout */ - if(monitoredNode->timeoutTimer < monitoredNode->time) { - monitoredNode->timeoutTimer += timeDifference_ms; - } - if(monitoredNode->HBstate!=CO_HBconsumer_UNCONFIGURED && - monitoredNode->HBstate!=CO_HBconsumer_UNKNOWN) { - if(monitoredNode->timeoutTimer >= monitoredNode->time){ - /* timeout expired */ - CO_errorReport(HBcons->em, CO_EM_HEARTBEAT_CONSUMER, CO_EMC_HEARTBEAT, i); - emcyHeartbeatTimeoutActive = 1; - - monitoredNode->NMTstate = CO_NMT_INITIALIZING; - if (monitoredNode->HBstate!=CO_HBconsumer_TIMEOUT && - monitoredNode->pFunctSignalTimeout!=NULL) { - monitoredNode->pFunctSignalTimeout(monitoredNode->nodeId, i, - monitoredNode->functSignalObjectTimeout); - } - monitoredNode->HBstate = CO_HBconsumer_TIMEOUT; - } - else if(monitoredNode->NMTstate == CO_NMT_INITIALIZING){ - /* there was a bootup message */ - CO_errorReport(HBcons->em, CO_EM_HB_CONSUMER_REMOTE_RESET, CO_EMC_HEARTBEAT, i); - emcyRemoteResetActive = 1; - - monitoredNode->HBstate = CO_HBconsumer_UNKNOWN; + else if (timerNext_us != NULL) { + /* Calculate timerNext_us for next timeout checking. */ + uint32_t diff = monitoredNode->time_us + - monitoredNode->timeoutTimer; + if (*timerNext_us > diff) { + *timerNext_us = diff; } } - if(monitoredNode->NMTstate != CO_NMT_OPERATIONAL) { - AllMonitoredOperationalCopy = 0; - } + } + + if(monitoredNode->HBstate != CO_HBconsumer_ACTIVE) { + allMonitoredActiveCurrent = false; + } + if (monitoredNode->NMTstate != CO_NMT_OPERATIONAL) { + allMonitoredOperationalCurrent = CO_NMT_INITIALIZING; } monitoredNode++; } } - else{ /* not in (pre)operational state */ - for(i=0; inumberOfMonitoredNodes; i++){ + else if (NMTisPreOrOperational || HBcons->NMTisPreOrOperationalPrev) { + /* (pre)operational state changed, clear variables */ + for(i=0; inumberOfMonitoredNodes; i++) { monitoredNode->NMTstate = CO_NMT_INITIALIZING; CO_CANrxNew_CLEAR(monitoredNode->CANrxNew); - if(monitoredNode->HBstate != CO_HBconsumer_UNCONFIGURED){ + if (monitoredNode->HBstate != CO_HBconsumer_UNCONFIGURED) { monitoredNode->HBstate = CO_HBconsumer_UNKNOWN; } monitoredNode++; } - AllMonitoredOperationalCopy = 0; + allMonitoredActiveCurrent = false; + allMonitoredOperationalCurrent = CO_NMT_INITIALIZING; } - /* clear emergencies. We only have one emergency index for all - * monitored nodes! */ - if ( ! emcyHeartbeatTimeoutActive) { + + /* Clear emergencies when all monitored nodes becomes active. + * We only have one emergency index for all monitored nodes! */ + if (!HBcons->allMonitoredActive && allMonitoredActiveCurrent) { CO_errorReset(HBcons->em, CO_EM_HEARTBEAT_CONSUMER, 0); - } - if ( ! emcyRemoteResetActive) { CO_errorReset(HBcons->em, CO_EM_HB_CONSUMER_REMOTE_RESET, 0); } - HBcons->allMonitoredOperational = AllMonitoredOperationalCopy; + HBcons->allMonitoredActive = allMonitoredActiveCurrent; + HBcons->allMonitoredOperational = allMonitoredOperationalCurrent; + HBcons->NMTisPreOrOperationalPrev = NMTisPreOrOperational; } diff --git a/stack/CO_HBconsumer.h b/stack/CO_HBconsumer.h index d4b2171..37bb2f0 100644 --- a/stack/CO_HBconsumer.h +++ b/stack/CO_HBconsumer.h @@ -68,8 +68,8 @@ typedef struct{ uint8_t nodeId; /**< Node Id of the monitored node */ CO_NMT_internalState_t NMTstate; /**< Of the remote node (Heartbeat payload) */ CO_HBconsumer_state_t HBstate; /**< Current heartbeat state */ - uint16_t timeoutTimer; /**< Time since last heartbeat received */ - uint16_t time; /**< Consumer heartbeat time from OD */ + uint32_t timeoutTimer; /**< Time since last heartbeat received */ + uint32_t time_us; /**< Consumer heartbeat time from OD */ volatile void *CANrxNew; /**< Indication if new Heartbeat message received from the CAN bus */ /** Callback for heartbeat state change to active event */ void (*pFunctSignalHbStarted)(uint8_t nodeId, uint8_t idx, void *object); /**< From CO_HBconsumer_initTimeoutCallback() or NULL */ @@ -94,9 +94,13 @@ typedef struct{ const uint32_t *HBconsTime; /**< From CO_HBconsumer_init() */ CO_HBconsNode_t *monitoredNodes; /**< From CO_HBconsumer_init() */ uint8_t numberOfMonitoredNodes; /**< From CO_HBconsumer_init() */ + /** True, if all monitored nodes are active or no node is + monitored. Can be read by the application */ + bool_t allMonitoredActive; /** True, if all monitored nodes are NMT operational or no node is monitored. Can be read by the application */ uint8_t allMonitoredOperational; + bool_t NMTisPreOrOperationalPrev; /**< previous state of var */ CO_CANmodule_t *CANdevRx; /**< From CO_HBconsumer_init() */ uint16_t CANdevRxIdxStart; /**< From CO_HBconsumer_init() */ }CO_HBconsumer_t; @@ -142,14 +146,14 @@ CO_ReturnError_t CO_HBconsumer_init( * @param HBcons This object. * @param idx index of the node in HBcons object * @param nodeId see OD 0x1016 description - * @param consumerTime see OD 0x1016 description + * @param consumerTime in milliseconds. see OD 0x1016 description * @return */ CO_ReturnError_t CO_HBconsumer_initEntry( CO_HBconsumer_t *HBcons, uint8_t idx, uint8_t nodeId, - uint16_t consumerTime); + uint16_t consumerTime_ms); /** * Initialize Heartbeat consumer started callback function. @@ -213,12 +217,14 @@ void CO_HBconsumer_initCallbackRemoteReset( * * @param HBcons This object. * @param NMTisPreOrOperational True if this node is NMT_PRE_OPERATIONAL or NMT_OPERATIONAL. - * @param timeDifference_ms Time difference from previous function call in [milliseconds]. + * @param timeDifference_us Time difference from previous function call in [microseconds]. + * @param timerNext_us [out] info to OS - see CO_process(). */ void CO_HBconsumer_process( CO_HBconsumer_t *HBcons, bool_t NMTisPreOrOperational, - uint16_t timeDifference_ms); + uint32_t timeDifference_us, + uint32_t *timerNext_us); /** * Get the heartbeat producer object index by node ID diff --git a/stack/CO_LSSmaster.c b/stack/CO_LSSmaster.c index 0819e1b..87553a3 100644 --- a/stack/CO_LSSmaster.c +++ b/stack/CO_LSSmaster.c @@ -112,12 +112,12 @@ static void CO_LSSmaster_receive(void *object, void *msg) */ static CO_LSSmaster_return_t CO_LSSmaster_check_timeout( CO_LSSmaster_t *LSSmaster, - uint16_t timeDifference_ms) + uint32_t timeDifference_us) { CO_LSSmaster_return_t ret = CO_LSSmaster_WAIT_SLAVE; - LSSmaster->timeoutTimer += timeDifference_ms; - if (LSSmaster->timeoutTimer >= LSSmaster->timeout) { + LSSmaster->timeoutTimer += timeDifference_us; + if (LSSmaster->timeoutTimer >= LSSmaster->timeout_us) { LSSmaster->timeoutTimer = 0; ret = CO_LSSmaster_TIMEOUT; } @@ -142,7 +142,7 @@ CO_ReturnError_t CO_LSSmaster_init( return CO_ERROR_ILLEGAL_ARGUMENT; } - LSSmaster->timeout = timeout_ms; + LSSmaster->timeout_us = (uint32_t)timeout_ms * 1000; LSSmaster->state = CO_LSSmaster_STATE_WAITING; LSSmaster->command = CO_LSSmaster_COMMAND_WAITING; LSSmaster->timeoutTimer = 0; @@ -181,7 +181,7 @@ void CO_LSSmaster_changeTimeout( uint16_t timeout_ms) { if (LSSmaster != NULL) { - LSSmaster->timeout = timeout_ms; + LSSmaster->timeout_us = (uint32_t)timeout_ms * 1000; } } @@ -251,7 +251,7 @@ static CO_LSSmaster_return_t CO_LSSmaster_switchStateSelectInitiate( */ static CO_LSSmaster_return_t CO_LSSmaster_switchStateSelectWait( CO_LSSmaster_t *LSSmaster, - uint16_t timeDifference_ms) + uint32_t timeDifference_us) { CO_LSSmaster_return_t ret; @@ -264,11 +264,11 @@ static CO_LSSmaster_return_t CO_LSSmaster_switchStateSelectWait( ret = CO_LSSmaster_OK; } else { - ret = CO_LSSmaster_check_timeout(LSSmaster, timeDifference_ms); + ret = CO_LSSmaster_check_timeout(LSSmaster, timeDifference_us); } } else { - ret = CO_LSSmaster_check_timeout(LSSmaster, timeDifference_ms); + ret = CO_LSSmaster_check_timeout(LSSmaster, timeDifference_us); } return ret; @@ -277,7 +277,7 @@ static CO_LSSmaster_return_t CO_LSSmaster_switchStateSelectWait( /******************************************************************************/ CO_LSSmaster_return_t CO_LSSmaster_switchStateSelect( CO_LSSmaster_t *LSSmaster, - uint16_t timeDifference_ms, + uint32_t timeDifference_us, CO_LSS_address_t *lssAddress) { CO_LSSmaster_return_t ret = CO_LSSmaster_INVALID_STATE; @@ -294,7 +294,7 @@ CO_LSSmaster_return_t CO_LSSmaster_switchStateSelect( } /* Wait for confirmation */ else if (LSSmaster->command == CO_LSSmaster_COMMAND_SWITCH_STATE) { - ret = CO_LSSmaster_switchStateSelectWait(LSSmaster, timeDifference_ms); + ret = CO_LSSmaster_switchStateSelectWait(LSSmaster, timeDifference_us); } if (ret!=CO_LSSmaster_INVALID_STATE && ret!=CO_LSSmaster_WAIT_SLAVE) { @@ -360,7 +360,7 @@ CO_LSSmaster_return_t CO_LSSmaster_switchStateDeselect( */ static CO_LSSmaster_return_t CO_LSSmaster_configureCheckWait( CO_LSSmaster_t *LSSmaster, - uint16_t timeDifference_ms, + uint32_t timeDifference_us, uint8_t csWait) { CO_LSSmaster_return_t ret; @@ -382,11 +382,11 @@ static CO_LSSmaster_return_t CO_LSSmaster_configureCheckWait( } } else { - ret = CO_LSSmaster_check_timeout(LSSmaster, timeDifference_ms); + ret = CO_LSSmaster_check_timeout(LSSmaster, timeDifference_us); } } else { - ret = CO_LSSmaster_check_timeout(LSSmaster, timeDifference_ms); + ret = CO_LSSmaster_check_timeout(LSSmaster, timeDifference_us); } if (ret!=CO_LSSmaster_INVALID_STATE && ret!=CO_LSSmaster_WAIT_SLAVE) { @@ -400,7 +400,7 @@ static CO_LSSmaster_return_t CO_LSSmaster_configureCheckWait( /******************************************************************************/ CO_LSSmaster_return_t CO_LSSmaster_configureBitTiming( CO_LSSmaster_t *LSSmaster, - uint16_t timeDifference_ms, + uint32_t timeDifference_us, uint16_t bit) { CO_LSSmaster_return_t ret = CO_LSSmaster_INVALID_STATE; @@ -442,7 +442,7 @@ CO_LSSmaster_return_t CO_LSSmaster_configureBitTiming( /* Wait for confirmation */ else if (LSSmaster->command == CO_LSSmaster_COMMAND_CFG_BIT_TIMING) { - ret = CO_LSSmaster_configureCheckWait(LSSmaster, timeDifference_ms, + ret = CO_LSSmaster_configureCheckWait(LSSmaster, timeDifference_us, CO_LSS_CFG_BIT_TIMING); } @@ -457,7 +457,7 @@ CO_LSSmaster_return_t CO_LSSmaster_configureBitTiming( /******************************************************************************/ CO_LSSmaster_return_t CO_LSSmaster_configureNodeId( CO_LSSmaster_t *LSSmaster, - uint16_t timeDifference_ms, + uint32_t timeDifference_us, uint8_t nodeId) { CO_LSSmaster_return_t ret = CO_LSSmaster_INVALID_STATE; @@ -487,7 +487,7 @@ CO_LSSmaster_return_t CO_LSSmaster_configureNodeId( /* Wait for confirmation */ else if (LSSmaster->command == CO_LSSmaster_COMMAND_CFG_NODE_ID) { - ret = CO_LSSmaster_configureCheckWait(LSSmaster, timeDifference_ms, + ret = CO_LSSmaster_configureCheckWait(LSSmaster, timeDifference_us, CO_LSS_CFG_NODE_ID); } @@ -502,7 +502,7 @@ CO_LSSmaster_return_t CO_LSSmaster_configureNodeId( /******************************************************************************/ CO_LSSmaster_return_t CO_LSSmaster_configureStore( CO_LSSmaster_t *LSSmaster, - uint16_t timeDifference_ms) + uint32_t timeDifference_us) { CO_LSSmaster_return_t ret = CO_LSSmaster_INVALID_STATE; @@ -527,7 +527,7 @@ CO_LSSmaster_return_t CO_LSSmaster_configureStore( /* Wait for confirmation */ else if (LSSmaster->command == CO_LSSmaster_COMMAND_CFG_STORE) { - ret = CO_LSSmaster_configureCheckWait(LSSmaster, timeDifference_ms, + ret = CO_LSSmaster_configureCheckWait(LSSmaster, timeDifference_us, CO_LSS_CFG_STORE); } @@ -588,7 +588,7 @@ static CO_LSSmaster_return_t CO_LSSmaster_inquireInitiate( */ static CO_LSSmaster_return_t CO_LSSmaster_inquireCheckWait( CO_LSSmaster_t *LSSmaster, - uint16_t timeDifference_ms, + uint32_t timeDifference_us, uint8_t csWait, uint32_t *value) { @@ -603,11 +603,11 @@ static CO_LSSmaster_return_t CO_LSSmaster_inquireCheckWait( ret = CO_LSSmaster_OK; } else { - ret = CO_LSSmaster_check_timeout(LSSmaster, timeDifference_ms); + ret = CO_LSSmaster_check_timeout(LSSmaster, timeDifference_us); } } else { - ret = CO_LSSmaster_check_timeout(LSSmaster, timeDifference_ms); + ret = CO_LSSmaster_check_timeout(LSSmaster, timeDifference_us); } return ret; @@ -616,7 +616,7 @@ static CO_LSSmaster_return_t CO_LSSmaster_inquireCheckWait( /******************************************************************************/ CO_LSSmaster_return_t CO_LSSmaster_InquireLssAddress( CO_LSSmaster_t *LSSmaster, - uint16_t timeDifference_ms, + uint32_t timeDifference_us, CO_LSS_address_t *lssAddress) { CO_LSSmaster_return_t ret = CO_LSSmaster_INVALID_STATE; @@ -629,7 +629,7 @@ CO_LSSmaster_return_t CO_LSSmaster_InquireLssAddress( /* Check for reply */ if (LSSmaster->command == CO_LSSmaster_COMMAND_INQUIRE_VENDOR) { - ret = CO_LSSmaster_inquireCheckWait(LSSmaster, timeDifference_ms, + ret = CO_LSSmaster_inquireCheckWait(LSSmaster, timeDifference_us, CO_LSS_INQUIRE_VENDOR, &lssAddress->identity.vendorID); if (ret == CO_LSSmaster_OK) { /* Start next request */ @@ -639,7 +639,7 @@ CO_LSSmaster_return_t CO_LSSmaster_InquireLssAddress( } else if (LSSmaster->command == CO_LSSmaster_COMMAND_INQUIRE_PRODUCT) { - ret = CO_LSSmaster_inquireCheckWait(LSSmaster, timeDifference_ms, + ret = CO_LSSmaster_inquireCheckWait(LSSmaster, timeDifference_us, CO_LSS_INQUIRE_PRODUCT, &lssAddress->identity.productCode); if (ret == CO_LSSmaster_OK) { /* Start next request */ @@ -649,7 +649,7 @@ CO_LSSmaster_return_t CO_LSSmaster_InquireLssAddress( } else if (LSSmaster->command == CO_LSSmaster_COMMAND_INQUIRE_REV) { - ret = CO_LSSmaster_inquireCheckWait(LSSmaster, timeDifference_ms, + ret = CO_LSSmaster_inquireCheckWait(LSSmaster, timeDifference_us, CO_LSS_INQUIRE_REV, &lssAddress->identity.revisionNumber); if (ret == CO_LSSmaster_OK) { /* Start next request */ @@ -659,7 +659,7 @@ CO_LSSmaster_return_t CO_LSSmaster_InquireLssAddress( } else if (LSSmaster->command == CO_LSSmaster_COMMAND_INQUIRE_SERIAL) { - ret = CO_LSSmaster_inquireCheckWait(LSSmaster, timeDifference_ms, + ret = CO_LSSmaster_inquireCheckWait(LSSmaster, timeDifference_us, CO_LSS_INQUIRE_SERIAL, &lssAddress->identity.serialNumber); } /* Check for next request */ @@ -703,7 +703,7 @@ CO_LSSmaster_return_t CO_LSSmaster_InquireLssAddress( /******************************************************************************/ CO_LSSmaster_return_t CO_LSSmaster_InquireNodeId( CO_LSSmaster_t *LSSmaster, - uint16_t timeDifference_ms, + uint32_t timeDifference_us, uint8_t *nodeId) { CO_LSSmaster_return_t ret = CO_LSSmaster_INVALID_STATE; @@ -726,7 +726,7 @@ CO_LSSmaster_return_t CO_LSSmaster_InquireNodeId( else if (LSSmaster->command == CO_LSSmaster_COMMAND_INQUIRE_NODE_ID) { uint32_t tmp = 0; - ret = CO_LSSmaster_inquireCheckWait(LSSmaster, timeDifference_ms, + ret = CO_LSSmaster_inquireCheckWait(LSSmaster, timeDifference_us, CO_LSS_INQUIRE_NODE_ID, &tmp); *nodeId = tmp & 0xff; @@ -765,11 +765,11 @@ static void CO_LSSmaster_FsSendMsg( */ static CO_LSSmaster_return_t CO_LSSmaster_FsCheckWait( CO_LSSmaster_t *LSSmaster, - uint16_t timeDifference_ms) + uint32_t timeDifference_us) { CO_LSSmaster_return_t ret; - ret = CO_LSSmaster_check_timeout(LSSmaster, timeDifference_ms); + ret = CO_LSSmaster_check_timeout(LSSmaster, timeDifference_us); if (ret == CO_LSSmaster_TIMEOUT) { ret = CO_LSSmaster_SCAN_NOACK; @@ -792,7 +792,7 @@ static CO_LSSmaster_return_t CO_LSSmaster_FsCheckWait( */ static CO_LSSmaster_return_t CO_LSSmaster_FsScanInitiate( CO_LSSmaster_t *LSSmaster, - uint16_t timeDifference_ms, + uint32_t timeDifference_us, CO_LSSmaster_scantype_t scan, CO_LSS_fastscan_lss_sub_next lssSub) { @@ -824,7 +824,7 @@ static CO_LSSmaster_return_t CO_LSSmaster_FsScanInitiate( */ static CO_LSSmaster_return_t CO_LSSmaster_FsScanWait( CO_LSSmaster_t *LSSmaster, - uint16_t timeDifference_ms, + uint32_t timeDifference_us, CO_LSSmaster_scantype_t scan) { CO_LSSmaster_return_t ret; @@ -840,7 +840,7 @@ static CO_LSSmaster_return_t CO_LSSmaster_FsScanWait( return CO_LSSmaster_SCAN_FAILED; } - ret = CO_LSSmaster_check_timeout(LSSmaster, timeDifference_ms); + ret = CO_LSSmaster_check_timeout(LSSmaster, timeDifference_us); if (ret == CO_LSSmaster_TIMEOUT) { ret = CO_LSSmaster_WAIT_SLAVE; @@ -880,7 +880,7 @@ static CO_LSSmaster_return_t CO_LSSmaster_FsScanWait( */ static CO_LSSmaster_return_t CO_LSSmaster_FsVerifyInitiate( CO_LSSmaster_t *LSSmaster, - uint16_t timeDifference_ms, + uint32_t timeDifference_us, CO_LSSmaster_scantype_t scan, uint32_t idNumberCheck, CO_LSS_fastscan_lss_sub_next lssNext) @@ -913,7 +913,7 @@ static CO_LSSmaster_return_t CO_LSSmaster_FsVerifyInitiate( */ static CO_LSSmaster_return_t CO_LSSmaster_FsVerifyWait( CO_LSSmaster_t *LSSmaster, - uint16_t timeDifference_ms, + uint32_t timeDifference_us, CO_LSSmaster_scantype_t scan, uint32_t *idNumberRet) { @@ -923,7 +923,7 @@ static CO_LSSmaster_return_t CO_LSSmaster_FsVerifyWait( return CO_LSSmaster_SCAN_FAILED; } - ret = CO_LSSmaster_check_timeout(LSSmaster, timeDifference_ms); + ret = CO_LSSmaster_check_timeout(LSSmaster, timeDifference_us); if (ret == CO_LSSmaster_TIMEOUT) { *idNumberRet = 0; @@ -970,7 +970,7 @@ static CO_LSS_fastscan_lss_sub_next CO_LSSmaster_FsSearchNext( /******************************************************************************/ CO_LSSmaster_return_t CO_LSSmaster_IdentifyFastscan( CO_LSSmaster_t *LSSmaster, - uint16_t timeDifference_ms, + uint32_t timeDifference_us, CO_LSSmaster_fastscan_t *fastscan) { uint8_t i; @@ -1036,12 +1036,12 @@ CO_LSSmaster_return_t CO_LSSmaster_IdentifyFastscan( * and the correspondign error is returned. */ switch (LSSmaster->fsState) { case CO_LSSmaster_FS_STATE_CHECK: - ret = CO_LSSmaster_FsCheckWait(LSSmaster, timeDifference_ms); + ret = CO_LSSmaster_FsCheckWait(LSSmaster, timeDifference_us); if (ret == CO_LSSmaster_SCAN_FINISHED) { CO_memset((uint8_t*)&fastscan->found, 0, sizeof(fastscan->found)); /* start scanning procedure by triggering vendor ID scan */ - CO_LSSmaster_FsScanInitiate(LSSmaster, timeDifference_ms, + CO_LSSmaster_FsScanInitiate(LSSmaster, timeDifference_us, fastscan->scan[CO_LSS_FASTSCAN_VENDOR_ID], CO_LSS_FASTSCAN_VENDOR_ID); ret = CO_LSSmaster_WAIT_SLAVE; @@ -1050,14 +1050,14 @@ CO_LSSmaster_return_t CO_LSSmaster_IdentifyFastscan( } break; case CO_LSSmaster_FS_STATE_SCAN: - ret = CO_LSSmaster_FsScanWait(LSSmaster, timeDifference_ms, + ret = CO_LSSmaster_FsScanWait(LSSmaster, timeDifference_us, fastscan->scan[LSSmaster->fsLssSub]); if (ret == CO_LSSmaster_SCAN_FINISHED) { /* scanning finished, initiate verifcation. The verification * message also contains the node state machine "switch to * next state" request */ next = CO_LSSmaster_FsSearchNext(LSSmaster, fastscan); - ret = CO_LSSmaster_FsVerifyInitiate(LSSmaster, timeDifference_ms, + ret = CO_LSSmaster_FsVerifyInitiate(LSSmaster, timeDifference_us, fastscan->scan[LSSmaster->fsLssSub], fastscan->match.addr[LSSmaster->fsLssSub], next); @@ -1065,7 +1065,7 @@ CO_LSSmaster_return_t CO_LSSmaster_IdentifyFastscan( } break; case CO_LSSmaster_FS_STATE_VERIFY: - ret = CO_LSSmaster_FsVerifyWait(LSSmaster, timeDifference_ms, + ret = CO_LSSmaster_FsVerifyWait(LSSmaster, timeDifference_us, fastscan->scan[LSSmaster->fsLssSub], &fastscan->found.addr[LSSmaster->fsLssSub]); if (ret == CO_LSSmaster_SCAN_FINISHED) { @@ -1082,7 +1082,7 @@ CO_LSSmaster_return_t CO_LSSmaster_IdentifyFastscan( else { /* initiate scan for next part of LSS address */ ret = CO_LSSmaster_FsScanInitiate(LSSmaster, - timeDifference_ms, fastscan->scan[next], next); + timeDifference_us, fastscan->scan[next], next); if (ret == CO_LSSmaster_SCAN_FINISHED) { /* Scanning is not requested. Initiate verification * step in next function call */ diff --git a/stack/CO_LSSmaster.h b/stack/CO_LSSmaster.h index b1c7239..5c6150f 100644 --- a/stack/CO_LSSmaster.h +++ b/stack/CO_LSSmaster.h @@ -105,11 +105,11 @@ typedef enum { * LSS master object. */ typedef struct{ - uint16_t timeout; /**< LSS response timeout in ms */ + uint16_t timeout_us; /**< LSS response timeout in us */ uint8_t state; /**< Node is currently selected */ uint8_t command; /**< Active command */ - uint16_t timeoutTimer; /**< Timeout timer for LSS communication */ + uint32_t timeoutTimer; /**< Timeout timer for LSS communication */ uint8_t fsState; /**< Current state of fastscan master state machine */ uint8_t fsLssSub; /**< Current state of node state machine */ @@ -212,15 +212,15 @@ void CO_LSSmaster_initCallback( * @remark Only one selection can be active at any time. * * @param LSSmaster This object. - * @param timeDifference_ms Time difference from previous function call in - * [milliseconds]. Zero when request is started. + * @param timeDifference_us Time difference from previous function call in + * [microseconds]. Zero when request is started. * @param lssAddress LSS target address. If NULL, all nodes are selected * @return #CO_LSSmaster_ILLEGAL_ARGUMENT, #CO_LSSmaster_INVALID_STATE, * #CO_LSSmaster_WAIT_SLAVE, #CO_LSSmaster_OK, #CO_LSSmaster_TIMEOUT */ CO_LSSmaster_return_t CO_LSSmaster_switchStateSelect( CO_LSSmaster_t *LSSmaster, - uint16_t timeDifference_ms, + uint32_t timeDifference_us, CO_LSS_address_t *lssAddress); @@ -251,8 +251,8 @@ CO_LSSmaster_return_t CO_LSSmaster_switchStateDeselect( * Function is non-blocking. * * @param LSSmaster This object. - * @param timeDifference_ms Time difference from previous function call in - * [milliseconds]. Zero when request is started. + * @param timeDifference_us Time difference from previous function call in + * [microseconds]. Zero when request is started. * @param bit new bit rate * @return #CO_LSSmaster_ILLEGAL_ARGUMENT, #CO_LSSmaster_INVALID_STATE, * #CO_LSSmaster_WAIT_SLAVE, #CO_LSSmaster_OK, #CO_LSSmaster_TIMEOUT, @@ -260,7 +260,7 @@ CO_LSSmaster_return_t CO_LSSmaster_switchStateDeselect( */ CO_LSSmaster_return_t CO_LSSmaster_configureBitTiming( CO_LSSmaster_t *LSSmaster, - uint16_t timeDifference_ms, + uint32_t timeDifference_us, uint16_t bit); @@ -275,8 +275,8 @@ CO_LSSmaster_return_t CO_LSSmaster_configureBitTiming( * Function is non-blocking. * * @param LSSmaster This object. - * @param timeDifference_ms Time difference from previous function call in - * [milliseconds]. Zero when request is started. + * @param timeDifference_us Time difference from previous function call in + * [microseconds]. Zero when request is started. * @param nodeId new node ID. Special value #CO_LSS_NODE_ID_ASSIGNMENT can be * used to invalidate node ID. * @return #CO_LSSmaster_ILLEGAL_ARGUMENT, #CO_LSSmaster_INVALID_STATE, @@ -285,7 +285,7 @@ CO_LSSmaster_return_t CO_LSSmaster_configureBitTiming( */ CO_LSSmaster_return_t CO_LSSmaster_configureNodeId( CO_LSSmaster_t *LSSmaster, - uint16_t timeDifference_ms, + uint32_t timeDifference_us, uint8_t nodeId); @@ -301,15 +301,15 @@ CO_LSSmaster_return_t CO_LSSmaster_configureNodeId( * Function is non-blocking. * * @param LSSmaster This object. - * @param timeDifference_ms Time difference from previous function call in - * [milliseconds]. Zero when request is started. + * @param timeDifference_us Time difference from previous function call in + * [microseconds]. Zero when request is started. * @return #CO_LSSmaster_ILLEGAL_ARGUMENT, #CO_LSSmaster_INVALID_STATE, * #CO_LSSmaster_WAIT_SLAVE, #CO_LSSmaster_OK, #CO_LSSmaster_TIMEOUT, * #CO_LSSmaster_OK_MANUFACTURER, #CO_LSSmaster_OK_ILLEGAL_ARGUMENT */ CO_LSSmaster_return_t CO_LSSmaster_configureStore( CO_LSSmaster_t *LSSmaster, - uint16_t timeDifference_ms); + uint32_t timeDifference_us); /** @@ -348,15 +348,15 @@ CO_LSSmaster_return_t CO_LSSmaster_ActivateBit( * Function is non-blocking. * * @param LSSmaster This object. - * @param timeDifference_ms Time difference from previous function call in - * [milliseconds]. Zero when request is started. + * @param timeDifference_us Time difference from previous function call in + * [microseconds]. Zero when request is started. * @param lssAddress [out] read result when function returns successfully * @return #CO_LSSmaster_ILLEGAL_ARGUMENT, #CO_LSSmaster_INVALID_STATE, * #CO_LSSmaster_WAIT_SLAVE, #CO_LSSmaster_OK, #CO_LSSmaster_TIMEOUT */ CO_LSSmaster_return_t CO_LSSmaster_InquireLssAddress( CO_LSSmaster_t *LSSmaster, - uint16_t timeDifference_ms, + uint32_t timeDifference_us, CO_LSS_address_t *lssAddress); @@ -371,15 +371,15 @@ CO_LSSmaster_return_t CO_LSSmaster_InquireLssAddress( * Function is non-blocking. * * @param LSSmaster This object. - * @param timeDifference_ms Time difference from previous function call in - * [milliseconds]. Zero when request is started. + * @param timeDifference_us Time difference from previous function call in + * [microseconds]. Zero when request is started. * @param nodeId [out] read result when function returns successfully * @return #CO_LSSmaster_ILLEGAL_ARGUMENT, #CO_LSSmaster_INVALID_STATE, * #CO_LSSmaster_WAIT_SLAVE, #CO_LSSmaster_OK, #CO_LSSmaster_TIMEOUT */ CO_LSSmaster_return_t CO_LSSmaster_InquireNodeId( CO_LSSmaster_t *LSSmaster, - uint16_t timeDifference_ms, + uint32_t timeDifference_us, uint8_t *nodeId); @@ -448,8 +448,8 @@ fastscan.scan[CO_LSS_FASTSCAN_SERIAL] = CO_LSSmaster_FS_SCAN; * Function is non-blocking. * * @param LSSmaster This object. - * @param timeDifference_ms Time difference from previous function call in - * [milliseconds]. Zero when request is started. + * @param timeDifference_us Time difference from previous function call in + * [microseconds]. Zero when request is started. * @param fastscan struct according to #CO_LSSmaster_fastscan_t. * @return #CO_LSSmaster_ILLEGAL_ARGUMENT, #CO_LSSmaster_INVALID_STATE, * #CO_LSSmaster_WAIT_SLAVE, #CO_LSSmaster_SCAN_FINISHED, #CO_LSSmaster_SCAN_NOACK, @@ -457,7 +457,7 @@ fastscan.scan[CO_LSS_FASTSCAN_SERIAL] = CO_LSSmaster_FS_SCAN; */ CO_LSSmaster_return_t CO_LSSmaster_IdentifyFastscan( CO_LSSmaster_t *LSSmaster, - uint16_t timeDifference_ms, + uint32_t timeDifference_us, CO_LSSmaster_fastscan_t *fastscan); /** @} */ /*@defgroup CO_LSSmaster*/ diff --git a/stack/CO_LSSslave.c b/stack/CO_LSSslave.c index cb4bb1b..c6c7418 100644 --- a/stack/CO_LSSslave.c +++ b/stack/CO_LSSslave.c @@ -498,17 +498,17 @@ CO_LSS_state_t CO_LSSslave_getState( /******************************************************************************/ bool_t CO_LSSslave_LEDprocess( CO_LSSslave_t *LSSslave, - uint16_t timeDifference_ms, + uint32_t timeDifference_us, bool_t *LEDon) { - static uint16_t ms50 = 0; + static uint32_t ms50 = 0; static int8_t flash1, flash2; if (LSSslave == NULL || LEDon == NULL) return false; - ms50 += timeDifference_ms; - if(ms50 >= 50) { - ms50 -= 50; + ms50 += timeDifference_us; + if(ms50 >= 50000) { + ms50 -= 50000; /* 4 cycles on, 50 cycles off */ if(++flash1 >= 4) flash1 = -50; diff --git a/stack/CO_LSSslave.h b/stack/CO_LSSslave.h index 1add481..ca14dee 100644 --- a/stack/CO_LSSslave.h +++ b/stack/CO_LSSslave.h @@ -332,14 +332,14 @@ CO_LSS_state_t CO_LSSslave_getState( * If none of above conditions apply, returns false. * * @param LSSslave This object. - * @param timeDifference_ms The amount of time elapsed since the last call + * @param timeDifference_us The amount of time elapsed since the last call * @param LEDon [out] LED state * * @return true if LSS is involved (unconfigured node or selected node) */ bool_t CO_LSSslave_LEDprocess( CO_LSSslave_t *LSSslave, - uint16_t timeDifference_ms, + uint32_t timeDifference_us, bool_t *LEDon); /** diff --git a/stack/CO_NMT_Heartbeat.c b/stack/CO_NMT_Heartbeat.c index 2b5365a..b704a8c 100644 --- a/stack/CO_NMT_Heartbeat.c +++ b/stack/CO_NMT_Heartbeat.c @@ -84,7 +84,7 @@ CO_ReturnError_t CO_NMT_init( CO_NMT_t *NMT, CO_EMpr_t *emPr, uint8_t nodeId, - uint16_t firstHBTime, + uint16_t firstHBTime_ms, CO_CANmodule_t *NMT_CANdev, uint16_t NMT_rxIdx, uint16_t CANidRxNMT, @@ -97,26 +97,25 @@ CO_ReturnError_t CO_NMT_init( return CO_ERROR_ILLEGAL_ARGUMENT; } - /* blinking bytes */ + /* blinking bytes and LEDS */ #ifdef CO_USE_LEDS + NMT->LEDtimer = 0; NMT->LEDflickering = 0; NMT->LEDblinking = 0; NMT->LEDsingleFlash = 0; NMT->LEDdoubleFlash = 0; NMT->LEDtripleFlash = 0; NMT->LEDquadrupleFlash = 0; + NMT->LEDgreenRun = -1; + NMT->LEDredError = 1; #endif /* CO_USE_LEDS */ /* Configure object variables */ NMT->operatingState = CO_NMT_INITIALIZING; -#ifdef CO_USE_LEDS - NMT->LEDgreenRun = -1; - NMT->LEDredError = 1; -#endif /* CO_USE_LEDS */ NMT->nodeId = nodeId; - NMT->firstHBTime = firstHBTime; + NMT->firstHBTime = (int32_t)firstHBTime_ms * 1000; NMT->resetCommand = 0; - NMT->HBproducerTimer = 0xFFFF; + NMT->HBproducerTimer = 0; NMT->emPr = emPr; NMT->pFunctNMT = NULL; @@ -158,64 +157,25 @@ void CO_NMT_initCallback( } -/******************************************************************************/ -#ifdef CO_USE_LEDS -void CO_NMT_blinkingProcess50ms(CO_NMT_t *NMT){ - - if(++NMT->LEDflickering >= 1) NMT->LEDflickering = -1; - - if(++NMT->LEDblinking >= 4) NMT->LEDblinking = -4; - - if(++NMT->LEDsingleFlash >= 4) NMT->LEDsingleFlash = -20; - - switch(++NMT->LEDdoubleFlash){ - case 4: NMT->LEDdoubleFlash = -104; break; - case -100: NMT->LEDdoubleFlash = 100; break; - case 104: NMT->LEDdoubleFlash = -20; break; - default: break; - } - - switch(++NMT->LEDtripleFlash){ - case 4: NMT->LEDtripleFlash = -104; break; - case -100: NMT->LEDtripleFlash = 100; break; - case 104: NMT->LEDtripleFlash = -114; break; - case -110: NMT->LEDtripleFlash = 110; break; - case 114: NMT->LEDtripleFlash = -20; break; - default: break; - } - - switch(++NMT->LEDquadrupleFlash){ - case 4: NMT->LEDquadrupleFlash = -104; break; - case -100: NMT->LEDquadrupleFlash = 100; break; - case 104: NMT->LEDquadrupleFlash = -114; break; - case -110: NMT->LEDquadrupleFlash = 110; break; - case 114: NMT->LEDquadrupleFlash = -124; break; - case -120: NMT->LEDquadrupleFlash = 120; break; - case 124: NMT->LEDquadrupleFlash = -20; break; - default: break; - } -} -#endif /* CO_USE_LEDS */ - - /******************************************************************************/ CO_NMT_reset_cmd_t CO_NMT_process( CO_NMT_t *NMT, - uint16_t timeDifference_ms, - uint16_t HBtime, + uint32_t timeDifference_us, + uint16_t HBtime_ms, uint32_t NMTstartup, uint8_t errorRegister, const uint8_t errorBehavior[], - uint16_t *timerNext_ms) + uint32_t *timerNext_us) { uint8_t CANpassive; uint8_t currentOperatingState = NMT->operatingState; + uint32_t HBtime = (uint32_t)HBtime_ms * 1000; - NMT->HBproducerTimer += timeDifference_ms; + NMT->HBproducerTimer += timeDifference_us; /* Heartbeat producer message & Bootup message */ - if((HBtime != 0 && NMT->HBproducerTimer >= HBtime) || NMT->operatingState == CO_NMT_INITIALIZING){ + if ((HBtime != 0 && NMT->HBproducerTimer >= HBtime) || NMT->operatingState == CO_NMT_INITIALIZING) { /* Start from the beginning. If OS is slow, time sliding may occur. However, heartbeat is * not for synchronization, it is for health report. */ @@ -224,10 +184,12 @@ CO_NMT_reset_cmd_t CO_NMT_process( NMT->HB_TXbuff->data[0] = NMT->operatingState; CO_CANsend(NMT->HB_CANdev, NMT->HB_TXbuff); - if(NMT->operatingState == CO_NMT_INITIALIZING){ - if(HBtime > NMT->firstHBTime) NMT->HBproducerTimer = HBtime - NMT->firstHBTime; - else NMT->HBproducerTimer = 0; - + if (NMT->operatingState == CO_NMT_INITIALIZING) { + /* After bootup messages send first heartbeat earlier */ + if (HBtime > NMT->firstHBTime) { + NMT->HBproducerTimer = HBtime - NMT->firstHBTime; + } + /* NMT slave self starting */ if (NMTstartup == 0x00000008U) NMT->operatingState = CO_NMT_OPERATIONAL; else NMT->operatingState = CO_NMT_PRE_OPERATIONAL; @@ -235,19 +197,6 @@ CO_NMT_reset_cmd_t CO_NMT_process( } - /* Calculate, when next Heartbeat needs to be send and lower timerNext_ms if necessary. */ - if(HBtime != 0 && timerNext_ms != NULL){ - if(NMT->HBproducerTimer < HBtime){ - uint16_t diff = HBtime - NMT->HBproducerTimer; - if(*timerNext_ms > diff){ - *timerNext_ms = diff; - } - }else{ - *timerNext_ms = 0; - } - } - - /* CAN passive flag */ CANpassive = 0; if(CO_isError(NMT->emPr->em, CO_EM_CAN_TX_BUS_PASSIVE) || CO_isError(NMT->emPr->em, CO_EM_CAN_RX_BUS_PASSIVE)) @@ -255,6 +204,51 @@ CO_NMT_reset_cmd_t CO_NMT_process( #ifdef CO_USE_LEDS + NMT->LEDtimer += timeDifference_us; + if (NMT->LEDtimer >= 50000) { + NMT->LEDtimer -= 50000; + + if (timerNext_us != NULL) { + uint32_t diff = 50000 - NMT->LEDtimer; + if (*timerNext_us > diff) { + *timerNext_us = diff; + } + } + + if (++NMT->LEDflickering >= 1) NMT->LEDflickering = -1; + + if (++NMT->LEDblinking >= 4) NMT->LEDblinking = -4; + + if (++NMT->LEDsingleFlash >= 4) NMT->LEDsingleFlash = -20; + + switch (++NMT->LEDdoubleFlash) { + case 4: NMT->LEDdoubleFlash = -104; break; + case -100: NMT->LEDdoubleFlash = 100; break; + case 104: NMT->LEDdoubleFlash = -20; break; + default: break; + } + + switch (++NMT->LEDtripleFlash) { + case 4: NMT->LEDtripleFlash = -104; break; + case -100: NMT->LEDtripleFlash = 100; break; + case 104: NMT->LEDtripleFlash = -114; break; + case -110: NMT->LEDtripleFlash = 110; break; + case 114: NMT->LEDtripleFlash = -20; break; + default: break; + } + + switch (++NMT->LEDquadrupleFlash) { + case 4: NMT->LEDquadrupleFlash = -104; break; + case -100: NMT->LEDquadrupleFlash = 100; break; + case 104: NMT->LEDquadrupleFlash = -114; break; + case -110: NMT->LEDquadrupleFlash = 110; break; + case 114: NMT->LEDquadrupleFlash = -124; break; + case -120: NMT->LEDquadrupleFlash = 120; break; + case 124: NMT->LEDquadrupleFlash = -20; break; + default: break; + } + } + /* CANopen green RUN LED (DR 303-3) */ switch(NMT->operatingState){ case CO_NMT_STOPPED: NMT->LEDgreenRun = NMT->LEDsingleFlash; break; @@ -335,8 +329,26 @@ CO_NMT_reset_cmd_t CO_NMT_process( } } - if(NMT->pFunctNMT!=NULL && currentOperatingState!=NMT->operatingState){ - NMT->pFunctNMT((CO_NMT_internalState_t) NMT->operatingState); + if (currentOperatingState != NMT->operatingState) { + if (NMT->pFunctNMT != NULL) { + NMT->pFunctNMT((CO_NMT_internalState_t) NMT->operatingState); + } + /* execute next CANopen processing immediately */ + if (timerNext_us != NULL) { + *timerNext_us = 0; + } + } + + /* Calculate, when next Heartbeat needs to be send and lower timerNext_us if necessary. */ + if (HBtime != 0 && timerNext_us != NULL) { + if (NMT->HBproducerTimer < HBtime) { + uint32_t diff = HBtime - NMT->HBproducerTimer; + if (*timerNext_us > diff) { + *timerNext_us = diff; + } + } else { + *timerNext_us = 0; + } } return (CO_NMT_reset_cmd_t) NMT->resetCommand; @@ -352,4 +364,3 @@ CO_NMT_internalState_t CO_NMT_getInternalState( } return CO_NMT_INITIALIZING; } - diff --git a/stack/CO_NMT_Heartbeat.h b/stack/CO_NMT_Heartbeat.h index 9199fde..652f4cf 100644 --- a/stack/CO_NMT_Heartbeat.h +++ b/stack/CO_NMT_Heartbeat.h @@ -129,8 +129,8 @@ typedef enum{ * @ref CO_NMT_statusLEDdiodes. Object is initialized by CO_NMT_init(). */ typedef struct{ - uint8_t operatingState; /**< See @ref CO_NMT_internalState_t */ #ifdef CO_USE_LEDS + uint32_t LEDtimer; /**< 50ms led timer */ int8_t LEDflickering; /**< See @ref CO_NMT_statusLEDdiodes */ int8_t LEDblinking; /**< See @ref CO_NMT_statusLEDdiodes */ int8_t LEDsingleFlash; /**< See @ref CO_NMT_statusLEDdiodes */ @@ -141,10 +141,11 @@ typedef struct{ int8_t LEDredError; /**< See @ref CO_NMT_statusLEDdiodes */ #endif /* CO_USE_LEDS */ + uint8_t operatingState; /**< See @ref CO_NMT_internalState_t */ uint8_t resetCommand; /**< If different than zero, device will reset */ uint8_t nodeId; /**< CANopen Node ID of this device */ - uint16_t HBproducerTimer;/**< Internal timer for HB producer */ - uint16_t firstHBTime; /**< From CO_NMT_init() */ + uint32_t HBproducerTimer;/**< Internal timer for HB producer */ + uint32_t firstHBTime; /**< From CO_NMT_init() */ CO_EMpr_t *emPr; /**< From CO_NMT_init() */ CO_CANmodule_t *HB_CANdev; /**< From CO_NMT_init() */ void (*pFunctNMT)(CO_NMT_internalState_t state); /**< From CO_NMT_initCallback() or NULL */ @@ -176,7 +177,7 @@ CO_ReturnError_t CO_NMT_init( CO_NMT_t *NMT, CO_EMpr_t *emPr, uint8_t nodeId, - uint16_t firstHBTime, + uint16_t firstHBTime_ms, CO_CANmodule_t *NMT_CANdev, uint16_t NMT_rxIdx, uint16_t CANidRxNMT, @@ -203,43 +204,31 @@ void CO_NMT_initCallback( void (*pFunctNMT)(CO_NMT_internalState_t state)); -/** - * Calculate blinking bytes. - * - * Function must be called cyclically every 50 milliseconds. See @ref CO_NMT_statusLEDdiodes. - * - * @param NMT NMT object. - */ -#ifdef CO_USE_LEDS -void CO_NMT_blinkingProcess50ms(CO_NMT_t *NMT); -#endif /* CO_USE_LEDS */ - - /** * Process received NMT and produce Heartbeat messages. * * Function must be called cyclically. * * @param NMT This object. - * @param timeDifference_ms Time difference from previous function call in [milliseconds]. + * @param timeDifference_us Time difference from previous function call in [microseconds]. * @param HBtime _Producer Heartbeat time_ (object dictionary, index 0x1017). * @param NMTstartup _NMT startup behavior_ (object dictionary, index 0x1F80). * @param errorRegister _Error register_ (object dictionary, index 0x1001). * @param errorBehavior pointer to _Error behavior_ array (object dictionary, index 0x1029). * Object controls, if device should leave NMT operational state. * Length of array must be 6. If pointer is NULL, no calculation is made. - * @param timerNext_ms Return value - info to OS - see CO_process(). + * @param timerNext_us [out] info to OS - see CO_process(). * * @return #CO_NMT_reset_cmd_t */ CO_NMT_reset_cmd_t CO_NMT_process( CO_NMT_t *NMT, - uint16_t timeDifference_ms, - uint16_t HBtime, + uint32_t timeDifference_us, + uint16_t HBtime_ms, uint32_t NMTstartup, uint8_t errorRegister, const uint8_t errorBehavior[], - uint16_t *timerNext_ms); + uint32_t *timerNext_us); /** diff --git a/stack/CO_PDO.h b/stack/CO_PDO.h index b76d47e..a2e6440 100644 --- a/stack/CO_PDO.h +++ b/stack/CO_PDO.h @@ -374,7 +374,7 @@ void CO_RPDO_process(CO_RPDO_t *RPDO, bool_t syncWas); * @param TPDO This object. * @param syncWas True, if CANopen SYNC message was just received or transmitted. * @param timeDifference_us Time difference from previous function call in [microseconds]. - * @param timerNext_us Return value - info to OS - see CO_process_SYNC_PDO(). + * @param timerNext_us [out] info to OS - see CO_process_SYNC_PDO(). */ void CO_TPDO_process( CO_TPDO_t *TPDO, diff --git a/stack/CO_SDO.c b/stack/CO_SDO.c index 7579e79..da92a76 100644 --- a/stack/CO_SDO.c +++ b/stack/CO_SDO.c @@ -281,6 +281,7 @@ CO_ReturnError_t CO_SDO_init( uint16_t ODSize, CO_OD_extension_t *ODExtensions, uint8_t nodeId, + uint16_t SDOtimeoutTime_ms, CO_CANmodule_t *CANdevRx, uint16_t CANdevRxIdx, CO_CANmodule_t *CANdevTx, @@ -317,6 +318,7 @@ CO_ReturnError_t CO_SDO_init( /* Configure object variables */ SDO->nodeId = nodeId; + SDO->SDOtimeoutTime_us = (uint32_t)SDOtimeoutTime_ms * 1000; SDO->state = CO_SDO_ST_IDLE; CO_CANrxNew_CLEAR(SDO->CANrxNew); SDO->pFunctSignal = NULL; @@ -768,9 +770,8 @@ static void CO_SDO_abort(CO_SDO_t *SDO, uint32_t code){ int8_t CO_SDO_process( CO_SDO_t *SDO, bool_t NMTisPreOrOperational, - uint16_t timeDifference_ms, - uint16_t SDOtimeoutTime, - uint16_t *timerNext_ms) + uint32_t timeDifference_us, + uint32_t *timerNext_us) { CO_SDO_state_t state = CO_SDO_ST_IDLE; bool_t timeoutSubblockDownolad = false; @@ -867,10 +868,10 @@ int8_t CO_SDO_process( } /* verify SDO timeout */ - if(SDO->timeoutTimer < SDOtimeoutTime){ - SDO->timeoutTimer += timeDifference_ms; + if (SDO->timeoutTimer < SDO->SDOtimeoutTime_us) { + SDO->timeoutTimer += timeDifference_us; } - if(SDO->timeoutTimer >= SDOtimeoutTime){ + if (SDO->timeoutTimer >= SDO->SDOtimeoutTime_us) { if((SDO->state == CO_SDO_ST_DOWNLOAD_BL_SUBBLOCK) && (SDO->sequence != 0) && (!SDO->CANtxBuff->bufferFull)){ timeoutSubblockDownolad = true; state = CO_SDO_ST_DOWNLOAD_BL_SUB_RESP; @@ -1434,9 +1435,9 @@ int8_t CO_SDO_process( /* send response */ CO_CANsend(SDO->CANdevTx, SDO->CANtxBuff); - /* Set timerNext_ms to 0 to inform OS to call this function again without delay. */ - if(timerNext_ms != NULL){ - *timerNext_ms = 0; + /* Set timerNext_us to 0 to inform OS to call this function again without delay. */ + if (timerNext_us != NULL) { + *timerNext_us = 0; } /* don't call CO_CANrxNew_CLEAR, so return directly */ @@ -1453,7 +1454,7 @@ int8_t CO_SDO_process( SDO->state = CO_SDO_ST_IDLE; break; } - + case CO_SDO_ST_IDLE: { /* Nothing to do it seems */ diff --git a/stack/CO_SDO.h b/stack/CO_SDO.h index 20bffee..875696e 100644 --- a/stack/CO_SDO.h +++ b/stack/CO_SDO.h @@ -613,8 +613,10 @@ typedef struct{ CO_SDO_state_t state; /** Toggle bit in segmented transfer or block sequence in block transfer */ uint8_t sequence; + /** Maximum timeout time between request and response in microseconds. */ + uint32_t SDOtimeoutTime_us; /** Timeout timer for SDO communication */ - uint16_t timeoutTimer; + uint32_t timeoutTimer; /** Number of segments per block with 1 <= blksize <= 127 */ uint8_t blksize; /** True, if CRC calculation by block transfer is enabled */ @@ -753,6 +755,7 @@ void CO_memcpySwap8(void* dest, const void* src); * @param ODExtensions Pointer to the externally defined array of the same size * as ODSize. * @param nodeId CANopen Node ID of this device. + * @param SDOtimeoutTime_ms Timeout time for SDO communication in milliseconds. * @param CANdevRx CAN device for SDO server reception. * @param CANdevRxIdx Index of receive buffer in the above CAN device. * @param CANdevTx CAN device for SDO server transmission. @@ -770,6 +773,7 @@ CO_ReturnError_t CO_SDO_init( uint16_t ODSize, CO_OD_extension_t ODExtensions[], uint8_t nodeId, + uint16_t SDOtimeoutTime_ms, CO_CANmodule_t *CANdevRx, uint16_t CANdevRxIdx, CO_CANmodule_t *CANdevTx, @@ -799,9 +803,8 @@ void CO_SDO_initCallback( * @param SDO This object. * @param NMTisPreOrOperational Different than zero, if #CO_NMT_internalState_t is * NMT_PRE_OPERATIONAL or NMT_OPERATIONAL. - * @param timeDifference_ms Time difference from previous function call in [milliseconds]. - * @param SDOtimeoutTime Timeout time for SDO communication in milliseconds. - * @param timerNext_ms Return value - info to OS - see CO_process(). + * @param timeDifference_us Time difference from previous function call in [microseconds]. + * @param timerNext_us [out] info to OS - see CO_process(). * * @return 0: SDO server is idle. * @return 1: SDO server is in transfer state. @@ -810,9 +813,8 @@ void CO_SDO_initCallback( int8_t CO_SDO_process( CO_SDO_t *SDO, bool_t NMTisPreOrOperational, - uint16_t timeDifference_ms, - uint16_t SDOtimeoutTime, - uint16_t *timerNext_ms); + uint32_t timeDifference_us, + uint32_t *timerNext_us); /** diff --git a/stack/CO_SDOmaster.c b/stack/CO_SDOmaster.c index e33bbce..c716ce2 100644 --- a/stack/CO_SDOmaster.c +++ b/stack/CO_SDOmaster.c @@ -330,6 +330,7 @@ CO_SDOclient_return_t CO_SDOclientDownloadInitiate( uint8_t subIndex, uint8_t *dataTx, uint32_t dataSize, + uint16_t SDOtimeoutTime_ms, uint8_t blockEnable) { /* verify parameters */ @@ -340,6 +341,8 @@ CO_SDOclient_return_t CO_SDOclientDownloadInitiate( /* save parameters */ SDO_C->buffer = dataTx; SDO_C->bufferSize = dataSize; + SDO_C->SDOtimeoutTimeHalf_us = (uint32_t)SDOtimeoutTime_ms * 500; + SDO_C->SDOtimeoutTime_us = SDO_C->SDOtimeoutTimeHalf_us * 2; SDO_C->state = SDO_STATE_DOWNLOAD_INITIATE; @@ -409,9 +412,9 @@ CO_SDOclient_return_t CO_SDOclientDownloadInitiate( /******************************************************************************/ CO_SDOclient_return_t CO_SDOclientDownload( CO_SDOclient_t *SDO_C, - uint16_t timeDifference_ms, - uint16_t SDOtimeoutTime, - uint32_t *pSDOabortCode) + uint32_t timeDifference_us, + uint32_t *pSDOabortCode, + uint32_t *timerNext_us) { CO_SDOclient_return_t ret = CO_SDOcli_waitingServerResponse; @@ -614,14 +617,23 @@ CO_SDOclient_return_t CO_SDOclientDownload( } /* TMO *********************************************************************************************** */ - if(SDO_C->timeoutTimer < SDOtimeoutTime){ - SDO_C->timeoutTimer += timeDifference_ms; + if (SDO_C->timeoutTimer < SDO_C->SDOtimeoutTime_us) { + SDO_C->timeoutTimer += timeDifference_us; } - if(SDO_C->timeoutTimer >= SDOtimeoutTime){ /* communication TMO */ + + /* communication TMO */ + if (SDO_C->timeoutTimer >= SDO_C->SDOtimeoutTime_us) { *pSDOabortCode = CO_SDO_AB_TIMEOUT; CO_SDOclient_abort(SDO_C, *pSDOabortCode); return CO_SDOcli_endedWithTimeout; } + else if (timerNext_us != NULL) { + /* check again after inhibit time elapsed */ + uint32_t diff = SDO_C->SDOtimeoutTime_us - SDO_C->timeoutTimer; + if (*timerNext_us > diff) { + *timerNext_us = diff; + } + } /* TX data ******************************************************************************************* */ if(SDO_C->CANtxBuff->bufferFull) { @@ -670,9 +682,6 @@ CO_SDOclient_return_t CO_SDOclientDownload( SDO_C->block_seqno += 1; SDO_C->CANtxBuff->data[0] = SDO_C->block_seqno; - if(SDO_C->block_seqno >= SDO_C->block_blksize){ - SDO_C->state = SDO_STATE_BLOCKDOWNLOAD_BLOCK_ACK; - } /* set data */ SDO_C->block_noData = 0; @@ -693,6 +702,13 @@ CO_SDOclient_return_t CO_SDOclientDownload( SDO_C->block_blksize = SDO_C->block_seqno; SDO_C->state = SDO_STATE_BLOCKDOWNLOAD_BLOCK_ACK; } + else if (SDO_C->block_seqno >= SDO_C->block_blksize) { + SDO_C->state = SDO_STATE_BLOCKDOWNLOAD_BLOCK_ACK; + } + else if (timerNext_us != NULL) { + /* Set timerNext_us to 0 to inform OS to call this function again without delay. */ + *timerNext_us = 0; + } /* tx data */ SDO_C->timeoutTimer = 0; @@ -742,6 +758,7 @@ CO_SDOclient_return_t CO_SDOclientUploadInitiate( uint8_t subIndex, uint8_t *dataRx, uint32_t dataRxSize, + uint16_t SDOtimeoutTime_ms, uint8_t blockEnable) { /* verify parameters */ @@ -752,6 +769,8 @@ CO_SDOclient_return_t CO_SDOclientUploadInitiate( /* save parameters */ SDO_C->buffer = dataRx; SDO_C->bufferSize = dataRxSize; + SDO_C->SDOtimeoutTimeHalf_us = (uint32_t)SDOtimeoutTime_ms * 500; + SDO_C->SDOtimeoutTime_us = SDO_C->SDOtimeoutTimeHalf_us * 2; /* prepare CAN tx message */ CO_SDOTxBufferClear(SDO_C); @@ -814,10 +833,10 @@ CO_SDOclient_return_t CO_SDOclientUploadInitiate( /******************************************************************************/ CO_SDOclient_return_t CO_SDOclientUpload( CO_SDOclient_t *SDO_C, - uint16_t timeDifference_ms, - uint16_t SDOtimeoutTime, + uint32_t timeDifference_us, uint32_t *pDataSize, - uint32_t *pSDOabortCode) + uint32_t *pSDOabortCode, + uint32_t *timerNext_us) { uint16_t indexTmp; uint32_t tmp32; @@ -1106,19 +1125,37 @@ CO_SDOclient_return_t CO_SDOclientUpload( } /* TMO *************************************************************************************************** */ - if(SDO_C->timeoutTimer < SDOtimeoutTime){ - SDO_C->timeoutTimer += timeDifference_ms; + if (SDO_C->timeoutTimer < SDO_C->SDOtimeoutTime_us) { + SDO_C->timeoutTimer += timeDifference_us; if (SDO_C->state == SDO_STATE_BLOCKUPLOAD_INPROGRES) - SDO_C->timeoutTimerBLOCK += timeDifference_ms; + SDO_C->timeoutTimerBLOCK += timeDifference_us; } - if(SDO_C->timeoutTimer >= SDOtimeoutTime){ /* communication TMO */ + + /* communication TMO */ + if (SDO_C->timeoutTimer >= SDO_C->SDOtimeoutTime_us) { *pSDOabortCode = CO_SDO_AB_TIMEOUT; CO_SDOclient_abort(SDO_C, *pSDOabortCode); return CO_SDOcli_endedWithTimeout; } - if(SDO_C->timeoutTimerBLOCK >= (SDOtimeoutTime/2)){ /* block TMO */ + else if (timerNext_us != NULL) { + /* check again after inhibit time elapsed */ + uint32_t diff = SDO_C->SDOtimeoutTime_us - SDO_C->timeoutTimer; + if (*timerNext_us > diff) { + *timerNext_us = diff; + } + } + + /* block TMO */ + if (SDO_C->timeoutTimerBLOCK >= SDO_C->SDOtimeoutTimeHalf_us) { SDO_C->state = SDO_STATE_BLOCKUPLOAD_BLOCK_ACK; } + else if (timerNext_us != NULL) { + /* check again after inhibit time elapsed */ + uint32_t diff = SDO_C->SDOtimeoutTimeHalf_us - SDO_C->timeoutTimerBLOCK; + if (*timerNext_us > diff) { + *timerNext_us = diff; + } + } /* TX data ******************************************************************************** */ diff --git a/stack/CO_SDOmaster.h b/stack/CO_SDOmaster.h index bf59214..95f4da7 100644 --- a/stack/CO_SDOmaster.h +++ b/stack/CO_SDOmaster.h @@ -112,10 +112,14 @@ typedef struct{ uint32_t dataSize; /** Data length transferred in block transfer */ uint32_t dataSizeTransfered; + /** Maximum timeout time between request and response in microseconds. */ + uint32_t SDOtimeoutTime_us; + /** Half of maximum timeout time between request and response. */ + uint32_t SDOtimeoutTimeHalf_us; /** Timeout timer for SDO communication */ - uint16_t timeoutTimer; + uint32_t timeoutTimer; /** Timeout timer for SDO block transfer */ - uint16_t timeoutTimerBLOCK; + uint32_t timeoutTimerBLOCK; /** Index of current object in Object Dictionary */ uint16_t index; /** Subindex of current object in Object Dictionary */ @@ -246,6 +250,7 @@ CO_SDOclient_return_t CO_SDOclient_setup( * format, because CANopen itself uses little-endian. Take care, * when using processors with big-endian. * @param dataSize Size of data in dataTx. + * @param SDOtimeoutTime_ms Timeout time for SDO communication in milliseconds. * @param blockEnable Try to initiate block transfer. * * @return #CO_SDOclient_return_t @@ -256,6 +261,7 @@ CO_SDOclient_return_t CO_SDOclientDownloadInitiate( uint8_t subIndex, uint8_t *dataTx, uint32_t dataSize, + uint16_t SDOtimeoutTime_ms, uint8_t blockEnable); @@ -267,18 +273,18 @@ CO_SDOclient_return_t CO_SDOclientDownloadInitiate( * Function is non-blocking. * * @param SDO_C This object. - * @param timeDifference_ms Time difference from previous function call in [milliseconds]. - * @param SDOtimeoutTime Timeout time for SDO communication in milliseconds. + * @param timeDifference_us Time difference from previous function call in [microseconds]. * @param pSDOabortCode Pointer to external variable written by this function * in case of error in communication. + * @param timerNext_us [out] info to OS - see CO_process(). * * @return #CO_SDOclient_return_t */ CO_SDOclient_return_t CO_SDOclientDownload( CO_SDOclient_t *SDO_C, - uint16_t timeDifference_ms, - uint16_t SDOtimeoutTime, - uint32_t *pSDOabortCode); + uint32_t timeDifference_us, + uint32_t *pSDOabortCode, + uint32_t *timerNext_us); /** @@ -296,6 +302,7 @@ CO_SDOclient_return_t CO_SDOclientDownload( * in little-endian format, because CANopen itself uses * little-endian. Take care, when using processors with big-endian. * @param dataRxSize Size of dataRx. + * @param SDOtimeoutTime_ms Timeout time for SDO communication in milliseconds. * @param blockEnable Try to initiate block transfer. * * @return #CO_SDOclient_return_t @@ -306,6 +313,7 @@ CO_SDOclient_return_t CO_SDOclientUploadInitiate( uint8_t subIndex, uint8_t *dataRx, uint32_t dataRxSize, + uint16_t SDOtimeoutTime_ms, uint8_t blockEnable); @@ -317,21 +325,21 @@ CO_SDOclient_return_t CO_SDOclientUploadInitiate( * Function is non-blocking. * * @param SDO_C This object. - * @param timeDifference_ms Time difference from previous function call in [milliseconds]. - * @param SDOtimeoutTime Timeout time for SDO communication in milliseconds. + * @param timeDifference_us Time difference from previous function call in [microseconds]. * @param pDataSize pointer to external variable, where size of received * data will be written. * @param pSDOabortCode Pointer to external variable written by this function * in case of error in communication. + * @param timerNext_us [out] info to OS - see CO_process(). * * @return #CO_SDOclient_return_t */ CO_SDOclient_return_t CO_SDOclientUpload( CO_SDOclient_t *SDO_C, - uint16_t timeDifference_ms, - uint16_t SDOtimeoutTime, + uint32_t timeDifference_us, uint32_t *pDataSize, - uint32_t *pSDOabortCode); + uint32_t *pSDOabortCode, + uint32_t *timerNext_us); /** diff --git a/stack/CO_SYNC.h b/stack/CO_SYNC.h index 80e4449..5a88940 100644 --- a/stack/CO_SYNC.h +++ b/stack/CO_SYNC.h @@ -146,7 +146,7 @@ CO_ReturnError_t CO_SYNC_init( * @param timeDifference_us Time difference from previous function call in [microseconds]. * @param ObjDict_synchronousWindowLength _Synchronous window length_ variable from * Object dictionary (index 0x1007). - * @param timerNext_us Return value - info to OS - see CO_process_SYNC_PDO(). + * @param timerNext_us [out] info to OS - see CO_process_SYNC_PDO(). * * @return 0: No special meaning. * @return 1: New SYNC message recently received or was just transmitted. diff --git a/stack/CO_TIME.c b/stack/CO_TIME.c index aa55022..3482ae1 100644 --- a/stack/CO_TIME.c +++ b/stack/CO_TIME.c @@ -125,13 +125,14 @@ CO_ReturnError_t CO_TIME_init( /******************************************************************************/ uint8_t CO_TIME_process( CO_TIME_t *TIME, - uint32_t timeDifference_ms) + uint32_t timeDifference_us) { uint8_t ret = 0; uint32_t timerNew; if(*TIME->operatingState == CO_NMT_OPERATIONAL || *TIME->operatingState == CO_NMT_PRE_OPERATIONAL){ /* update TIME timer, no overflow */ + uint32_t timeDifference_ms = (timeDifference_us+500) / 1000; //this should be optimized timerNew = TIME->timer + timeDifference_ms; if(timerNew > TIME->timer) TIME->timer = timerNew; diff --git a/stack/CO_TIME.h b/stack/CO_TIME.h index 0884a6f..a3eea4c 100644 --- a/stack/CO_TIME.h +++ b/stack/CO_TIME.h @@ -143,14 +143,14 @@ CO_ReturnError_t CO_TIME_init( * Function must be called cyclically. * * @param TIME This object. - * @param timeDifference_ms Time difference from previous function call in [milliseconds]. + * @param timeDifference_us Time difference from previous function call in [microseconds]. * * @return 0: No special meaning. * @return 1: New TIME message recently received (consumer) / transmited (producer). */ uint8_t CO_TIME_process( CO_TIME_t *TIME, - uint32_t timeDifference_ms); + uint32_t timeDifference_us); #ifdef __cplusplus }