diff --git a/src/jsd.c b/src/jsd.c index 3b0e9b4..d1257a1 100644 --- a/src/jsd.c +++ b/src/jsd.c @@ -194,6 +194,8 @@ bool jsd_init(jsd_t* self, const char* ifname, uint8_t enable_autorecovery) { WARNING("Failed OP transition attempt %d of %d", attempt, JSD_PO2OP_MAX_ATTEMPTS); + jsd_inspect_context(self); + if (attempt >= JSD_PO2OP_MAX_ATTEMPTS) { ERROR("Max number of attempts to transition to OPERATIONAL exceeded."); return false; @@ -226,6 +228,71 @@ bool jsd_init(jsd_t* self, const char* ifname, uint8_t enable_autorecovery) { return true; } +bool jsd_all_slaves_operational(jsd_t* self) { + int slave; + bool all_slaves_operational = true; + uint8_t currentgroup = 0; // only 1 rate group in JSD currently + /* one or more slaves may not be responding */ + for (slave = 1; slave <= *self->ecx_context.slavecount; slave++) { + if (self->ecx_context.slavelist[slave].group != currentgroup) continue; + + /* re-check bad slave individually */ + ecx_statecheck(&self->ecx_context, slave, EC_STATE_OPERATIONAL, EC_TIMEOUTRET); + if (self->ecx_context.slavelist[slave].state != EC_STATE_OPERATIONAL) { + all_slaves_operational = false; + if (self->ecx_context.slavelist[slave].state == + (EC_STATE_SAFE_OP + EC_STATE_ERROR)) { + ERROR("slave[%d] is in SAFE_OP + ERROR.", slave); + } else if (self->ecx_context.slavelist[slave].state == EC_STATE_SAFE_OP) { + ERROR("slave[%d] is in SAFE_OP.", slave); + } else if (self->ecx_context.slavelist[slave].state > EC_STATE_NONE) { + ERROR("slave[%d] is in state with hexadecimal: %x", slave, self->ecx_context.slavelist[slave].state); + } else { + ERROR("slave[%d] is lost", slave); + } + } + else { + MSG("slave[%d] is OPERATIONAL.", slave); + } + } + + return all_slaves_operational; +} + +void jsd_inspect_context(jsd_t* self) { + ec_state bus_state = jsd_get_device_state(self, 0); + + /* first check if the jsd bus is operational so we can get more info */ + if (bus_state != EC_STATE_OPERATIONAL) { + ERROR("JSD bus is not OPERATIONAL."); + } + + if (jsd_all_slaves_operational(self)) { + MSG("All slaves were operational at time of working counter fault."); + } + else { + MSG("Some slaves were not operational."); + if (self->ecx_context.ecaterror) { + MSG("An ECAT error occurred; the error list is displayed below:"); + uint8_t i = 0; + while(self->ecx_context.ecaterror && i < JSD_ELIST_MAX_READS) { + MSG("%s\n", ecx_elist2string(&self->ecx_context)); + i++; + } + if (i == JSD_ELIST_MAX_READS) { + MSG("Maximum number of reads from error list experienced." + " This is likely a result of indefinite polling."); + } + else { + MSG("Finished reporting errors in error list."); + } + } + else { + MSG("Despite some slaves not being operational, an ECAT error was not experienced."); + } + } +} + void jsd_read(jsd_t* self, int timeout_us) { assert(self); diff --git a/src/jsd.h b/src/jsd.h index 5d3f92c..b2156fd 100644 --- a/src/jsd.h +++ b/src/jsd.h @@ -8,6 +8,7 @@ extern "C" { #include "jsd/jsd_pub.h" #define JSD_PO2OP_MAX_ATTEMPTS 3 +#define JSD_ELIST_MAX_READS 100 /** * @brief converts ec_state int to human-readable string diff --git a/src/jsd_pub.h b/src/jsd_pub.h index c69959d..547f12c 100644 --- a/src/jsd_pub.h +++ b/src/jsd_pub.h @@ -53,6 +53,21 @@ void jsd_set_slave_config(jsd_t* self, uint16_t slave_id, */ bool jsd_init(jsd_t* self, const char* ifname, uint8_t enable_autorecovery); +/** + * @brief Determines if all slaves are operational via individual slave queries + * + * @param self pointer JSD context + */ +bool jsd_all_slaves_operational(jsd_t* self); + +/** + * @brief After experiencing a bad working counter it is advised to check the + * context to discover which devices were problematic (if any). + * + * @param self pointer JSD context + */ +void jsd_inspect_context(jsd_t* self); + /** * @brief Receive data from slave devices and store on local IOmap. *