diff --git a/301/CO_HBconsumer.c b/301/CO_HBconsumer.c index a851598..e2b09f6 100644 --- a/301/CO_HBconsumer.c +++ b/301/CO_HBconsumer.c @@ -31,6 +31,12 @@ #if (CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_ENABLE +/* Verify HB consumer configuration *******************************************/ +#if (CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_CHANGE \ + && (CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_MULTI +#error CO_CONFIG_HB_CONS_CALLBACK_CHANGE and CO_CONFIG_HB_CONS_CALLBACK_MULTI cannot be set simultaneously! +#endif + /* * Read received message from CAN module. * @@ -137,6 +143,7 @@ CO_ReturnError_t CO_HBconsumer_init( HBcons->monitoredNodes[i].pFunctSignalPre = NULL; #endif #if (CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_MULTI + HBcons->monitoredNodes[i].pFunctSignalNmtChanged = NULL; HBcons->monitoredNodes[i].pFunctSignalHbStarted = NULL; HBcons->monitoredNodes[i].pFunctSignalTimeout = NULL; HBcons->monitoredNodes[i].pFunctSignalRemoteReset = NULL; @@ -185,7 +192,8 @@ CO_ReturnError_t CO_HBconsumer_initEntry( monitoredNode->nodeId = nodeId; monitoredNode->time_us = (int32_t)consumerTime_ms * 1000; monitoredNode->NMTstate = CO_NMT_UNKNOWN; -#if (CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_CHANGE +#if (CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_CHANGE \ + || (CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_MULTI monitoredNode->NMTstatePrev = CO_NMT_UNKNOWN; #endif CO_FLAG_CLEAR(monitoredNode->CANrxNew); @@ -239,7 +247,7 @@ void CO_HBconsumer_initCallbackPre( void CO_HBconsumer_initCallbackNmtChanged( CO_HBconsumer_t *HBcons, void *object, - void (*pFunctSignal)(uint8_t nodeId, + void (*pFunctSignal)(uint8_t nodeId, uint8_t idx, CO_NMT_internalState_t NMTstate, void *object)) { @@ -254,6 +262,25 @@ void CO_HBconsumer_initCallbackNmtChanged( #if (CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_MULTI +/******************************************************************************/ +void CO_HBconsumer_initCallbackNmtChanged( + CO_HBconsumer_t *HBcons, + uint8_t idx, + void *object, + void (*pFunctSignal)(uint8_t nodeId, uint8_t idx, + CO_NMT_internalState_t NMTstate, + void *object)) +{ + if (HBcons==NULL || idx>=HBcons->numberOfMonitoredNodes) { + return; + } + + CO_HBconsNode_t * const monitoredNode = &HBcons->monitoredNodes[idx]; + monitoredNode->pFunctSignalNmtChanged = pFunctSignal; + monitoredNode->pFunctSignalObjectNmtChanged = object; +} + + /******************************************************************************/ void CO_HBconsumer_initCallbackHeartbeatStarted( CO_HBconsumer_t *HBcons, @@ -321,18 +348,16 @@ void CO_HBconsumer_process( { (void)timerNext_us; /* may be unused */ - uint8_t i; bool_t allMonitoredActiveCurrent = true; uint8_t allMonitoredOperationalCurrent = CO_NMT_OPERATIONAL; - CO_HBconsNode_t *monitoredNode = &HBcons->monitoredNodes[0]; if (NMTisPreOrOperational && HBcons->NMTisPreOrOperationalPrev) { - for (i=0; inumberOfMonitoredNodes; i++) { + for (uint8_t i=0; inumberOfMonitoredNodes; i++) { uint32_t timeDifference_us_copy = timeDifference_us; + CO_HBconsNode_t * const monitoredNode = &HBcons->monitoredNodes[i]; if (monitoredNode->HBstate == CO_HBconsumer_UNCONFIGURED) { /* continue, if node is not monitored */ - monitoredNode++; continue; } /* Verify if received message is heartbeat or bootup */ @@ -409,32 +434,40 @@ void CO_HBconsumer_process( if (monitoredNode->NMTstate != CO_NMT_OPERATIONAL) { allMonitoredOperationalCurrent = CO_NMT_UNKNOWN; } -#if (CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_CHANGE +#if (CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_CHANGE \ + || (CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_MULTI /* Verify, if NMT state of monitored node changed */ if(monitoredNode->NMTstate != monitoredNode->NMTstatePrev) { +#if (CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_CHANGE if (HBcons->pFunctSignalNmtChanged != NULL) { HBcons->pFunctSignalNmtChanged( - monitoredNode->nodeId, monitoredNode->NMTstate, + monitoredNode->nodeId, i, monitoredNode->NMTstate, HBcons->pFunctSignalObjectNmtChanged); +#else + if (monitoredNode->pFunctSignalNmtChanged != NULL) { + monitoredNode->pFunctSignalNmtChanged( + monitoredNode->nodeId, i, monitoredNode->NMTstate, + monitoredNode->pFunctSignalObjectNmtChanged); +#endif } monitoredNode->NMTstatePrev = monitoredNode->NMTstate; } #endif - monitoredNode++; } } else if (NMTisPreOrOperational || HBcons->NMTisPreOrOperationalPrev) { /* (pre)operational state changed, clear variables */ - for(i=0; inumberOfMonitoredNodes; i++) { + for(uint8_t i=0; inumberOfMonitoredNodes; i++) { + CO_HBconsNode_t * const monitoredNode = &HBcons->monitoredNodes[i]; monitoredNode->NMTstate = CO_NMT_UNKNOWN; -#if (CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_CHANGE +#if (CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_CHANGE \ + || (CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_MULTI monitoredNode->NMTstatePrev = CO_NMT_UNKNOWN; #endif CO_FLAG_CLEAR(monitoredNode->CANrxNew); if (monitoredNode->HBstate != CO_HBconsumer_UNCONFIGURED) { monitoredNode->HBstate = CO_HBconsumer_UNKNOWN; } - monitoredNode++; } allMonitoredActiveCurrent = false; allMonitoredOperationalCurrent = CO_NMT_UNKNOWN; diff --git a/301/CO_HBconsumer.h b/301/CO_HBconsumer.h index 2a31759..421032f 100644 --- a/301/CO_HBconsumer.h +++ b/301/CO_HBconsumer.h @@ -91,11 +91,20 @@ typedef struct { /** From CO_HBconsumer_initCallbackPre() or NULL */ void *functSignalObjectPre; #endif -#if ((CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_CHANGE) || defined CO_DOXYGEN +#if ((CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_CHANGE) \ + || ((CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_MULTI) \ + || defined CO_DOXYGEN /** Previous value of the remote node (Heartbeat payload) */ CO_NMT_internalState_t NMTstatePrev; #endif #if ((CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_MULTI) || defined CO_DOXYGEN + /** Callback for remote NMT changed event. + * From CO_HBconsumer_initCallbackNmtChanged() or NULL. */ + void (*pFunctSignalNmtChanged)(uint8_t nodeId, uint8_t idx, + CO_NMT_internalState_t state, + void *object); + /** Pointer to object */ + void *pFunctSignalObjectNmtChanged; /** Callback for heartbeat state change to active event. * From CO_HBconsumer_initCallbackHeartbeatStarted() or NULL. */ void (*pFunctSignalHbStarted)(uint8_t nodeId, uint8_t idx, void *object); @@ -138,7 +147,7 @@ typedef struct{ #if ((CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_CHANGE) || defined CO_DOXYGEN /** Callback for remote NMT changed event. * From CO_HBconsumer_initCallbackNmtChanged() or NULL. */ - void (*pFunctSignalNmtChanged)(uint8_t nodeId, + void (*pFunctSignalNmtChanged)(uint8_t nodeId, uint8_t idx, CO_NMT_internalState_t state, void *object); /** Pointer to object */ @@ -214,7 +223,9 @@ void CO_HBconsumer_initCallbackPre( void (*pFunctSignal)(void *object)); #endif -#if ((CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_CHANGE) || defined CO_DOXYGEN +#if ((CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_CHANGE) \ + || ((CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_MULTI) \ + || defined CO_DOXYGEN /** * Initialize Heartbeat consumer NMT changed callback function. * @@ -222,14 +233,19 @@ void CO_HBconsumer_initCallbackPre( * state from the remote node changes. * * @param HBcons This object. + * @param idx index of the node in HBcons object (only when + * CO_CONFIG_HB_CONS_CALLBACK_MULTI is enabled) * @param object Pointer to object, which will be passed to pFunctSignal(). * Can be NULL. * @param pFunctSignal Pointer to the callback function. Not called if NULL. */ void CO_HBconsumer_initCallbackNmtChanged( CO_HBconsumer_t *HBcons, +#if ((CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_MULTI) || defined CO_DOXYGEN + uint8_t idx, +#endif void *object, - void (*pFunctSignal)(uint8_t nodeId, + void (*pFunctSignal)(uint8_t nodeId, uint8_t idx, CO_NMT_internalState_t state, void *object)); #endif @@ -253,7 +269,6 @@ void CO_HBconsumer_initCallbackHeartbeatStarted( void *object, void (*pFunctSignal)(uint8_t nodeId, uint8_t idx, void *object)); - /** * Initialize Heartbeat consumer timeout callback function. * diff --git a/301/CO_config.h b/301/CO_config.h index d455b99..58872e6 100644 --- a/301/CO_config.h +++ b/301/CO_config.h @@ -135,16 +135,19 @@ extern "C" { * - #CO_CONFIG_FLAG_TIMERNEXT - Enable calculation of timerNext_us variable * inside CO_HBconsumer_process(). * - CO_CONFIG_HB_CONS_ENABLE - Enable heartbeat consumer. - * - CO_CONFIG_HB_CONS_CALLBACK_CHANGE - Enable custom callback after NMT + * - CO_CONFIG_HB_CONS_CALLBACK_CHANGE - Enable custom common callback after NMT * state of the monitored node changes. Callback is configured by * CO_HBconsumer_initCallbackNmtChanged(). * - CO_CONFIG_HB_CONS_CALLBACK_MULTI - Enable multiple custom callbacks, which - * can be configured for each monitored node. Callback are configured by + * can be configured individually for each monitored node. Callbacks are + * configured by CO_HBconsumer_initCallbackNmtChanged(), * CO_HBconsumer_initCallbackHeartbeatStarted(), * CO_HBconsumer_initCallbackTimeout() and * CO_HBconsumer_initCallbackRemoteReset() functions. * - CO_CONFIG_HB_CONS_QUERY_FUNCT - Enable functions for query HB state or * NMT state of the specific monitored node. + * Note that CO_CONFIG_HB_CONS_CALLBACK_CHANGE and + * CO_CONFIG_HB_CONS_CALLBACK_MULTI cannot be set simultaneously. */ #ifdef CO_DOXYGEN #define CO_CONFIG_HB_CONS (CO_CONFIG_HB_CONS_ENABLE) diff --git a/example/CO_driver_target.h b/example/CO_driver_target.h index 735ff53..f2dd495 100644 --- a/example/CO_driver_target.h +++ b/example/CO_driver_target.h @@ -53,7 +53,6 @@ extern "C" { #ifndef CO_CONFIG_HB_CONS #define CO_CONFIG_HB_CONS (CO_CONFIG_HB_CONS_ENABLE | \ - CO_CONFIG_HB_CONS_CALLBACK_CHANGE | \ CO_CONFIG_HB_CONS_CALLBACK_MULTI | \ CO_CONFIG_HB_CONS_QUERY_FUNCT | \ CO_CONFIG_FLAG_CALLBACK_PRE | \ diff --git a/socketCAN/CO_error_msgs.h b/socketCAN/CO_error_msgs.h index 7ad1182..ae76d56 100644 --- a/socketCAN/CO_error_msgs.h +++ b/socketCAN/CO_error_msgs.h @@ -70,7 +70,7 @@ extern "C" { /* mainline */ #define DBG_EMERGENCY_RX "CANopen Emergency message from node 0x%02X: errorCode=0x%04X, errorRegister=0x%02X, errorBit=0x%02X, infoCode=0x%08X" #define DBG_NMT_CHANGE "CANopen NMT state changed to: \"%s\" (%d)" -#define DBG_HB_CONS_NMT_CHANGE "CANopen Remote node ID = 0x%02X: NMT state changed to: \"%s\" (%d)" +#define DBG_HB_CONS_NMT_CHANGE "CANopen Remote node ID = 0x%02X (index = %d): NMT state changed to: \"%s\" (%d)" #define DBG_ARGUMENT_UNKNOWN "(%s) Unknown %s argument: \"%s\"", __func__ #define DBG_NOT_TCP_PORT "(%s) -c argument \"%s\" is not a valid tcp port", __func__ #define DBG_WRONG_NODE_ID "(%s) Wrong node ID \"%d\"", __func__ diff --git a/socketCAN/CO_main_basic.c b/socketCAN/CO_main_basic.c index d38c1d1..59494a9 100644 --- a/socketCAN/CO_main_basic.c +++ b/socketCAN/CO_main_basic.c @@ -186,13 +186,13 @@ static void NmtChangedCallback(CO_NMT_internalState_t state) #if (CO_CONFIG_HB_CONS) & CO_CONFIG_HB_CONS_CALLBACK_CHANGE /* callback for monitoring Heartbeat remote NMT state change */ -static void HeartbeatNmtChangedCallback(uint8_t nodeId, +static void HeartbeatNmtChangedCallback(uint8_t nodeId, uint8_t idx, CO_NMT_internalState_t state, void *object) { (void)object; log_printf(LOG_NOTICE, DBG_HB_CONS_NMT_CHANGE, - nodeId, NmtState2Str(state), state); + nodeId, idx, NmtState2Str(state), state); } #endif