Skip to content

Commit

Permalink
Merge branch 'master' into prestonr-add-el5042
Browse files Browse the repository at this point in the history
  • Loading branch information
preston-rogers committed Oct 30, 2024
2 parents 25d6e57 + 7ce3586 commit 40d420b
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 10 deletions.
97 changes: 92 additions & 5 deletions src/jsd.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ void jsd_set_slave_config(jsd_t* self, uint16_t slave_id,
self->slave_configs[slave_id] = slave_config;
}

bool jsd_init(jsd_t* self, const char* ifname, uint8_t enable_autorecovery) {
bool jsd_init(jsd_t* self, const char* ifname, uint8_t enable_autorecovery, int timeout_us) {
assert(self);
self->enable_autorecovery = enable_autorecovery;

Expand Down Expand Up @@ -165,15 +165,36 @@ bool jsd_init(jsd_t* self, const char* ifname, uint8_t enable_autorecovery) {

self->ecx_context.slavelist[0].state = EC_STATE_OPERATIONAL;

struct timespec start_processdata_time;
clock_gettime(CLOCK_REALTIME, &start_processdata_time);
ecx_send_overlap_processdata(&self->ecx_context);
ecx_receive_processdata(&self->ecx_context, EC_TIMEOUTRET);
ecx_receive_processdata(&self->ecx_context, timeout_us);

ecx_writestate(&self->ecx_context, 0);

int attempt = 0;
while (true) {
struct timespec current_time;
clock_gettime(CLOCK_REALTIME, &current_time);
if ((current_time.tv_nsec - start_processdata_time.tv_nsec)/1e3 > timeout_us) {
MSG_DEBUG("Went over the loop period!");
}
else {
struct timespec diff;
diff.tv_sec = current_time.tv_sec - start_processdata_time.tv_sec;
diff.tv_nsec = current_time.tv_nsec - start_processdata_time.tv_nsec;

// Sleep for period defined by timeout_us before attempting to do a receive_processdata.
// LRW packets must be sent at constant interval to encourage a successful transition to OP state/
if (nanosleep(&diff, NULL) < 0) {
perror("nanosleep failed");
return 1;
}
}

clock_gettime(CLOCK_REALTIME, &start_processdata_time);
int sent = ecx_send_overlap_processdata(&self->ecx_context);
int wkc = ecx_receive_processdata(&self->ecx_context, EC_TIMEOUTRET);
int wkc = ecx_receive_processdata(&self->ecx_context, timeout_us);
ec_state actual_state = ecx_statecheck(
&self->ecx_context, 0, EC_STATE_OPERATIONAL, EC_TIMEOUTSTATE);

Expand All @@ -195,6 +216,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;
Expand Down Expand Up @@ -227,6 +250,70 @@ bool jsd_init(jsd_t* self, const char* ifname, uint8_t enable_autorecovery) {
return true;
}

bool jsd_all_slaves_operational(jsd_t* self) {
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 (int 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("We experienced an ECAT error. When this occurs, error information aught to be saved. "
"Errors in error list displayed below:\n");
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);

Expand All @@ -238,7 +325,7 @@ void jsd_read(jsd_t* self, int timeout_us) {
}
if (self->last_wkc != self->expected_wkc && self->wkc == self->expected_wkc) {
if (self->last_wkc != -1) {
MSG("ecx_receive_processdata is not longer reading bad wkc");
MSG("ecx_receive_processdata is no longer reading bad wkc");
}
}
self->last_wkc = self->wkc;
Expand Down Expand Up @@ -610,7 +697,7 @@ void jsd_ecatcheck(jsd_t* self) {

if ((bus_state == EC_STATE_OPERATIONAL && self->wkc < self->expected_wkc) ||
self->ecx_context.grouplist[currentgroup].docheckstate) {
/* one ore more slaves are not responding */
/* one or more slaves are not responding */
self->ecx_context.grouplist[currentgroup].docheckstate = FALSE;
ecx_readstate(&self->ecx_context);
for (slave = 1; slave <= *self->ecx_context.slavecount; slave++) {
Expand Down
1 change: 1 addition & 0 deletions src/jsd.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ extern "C" {
#include "jsd/jsd_pub.h"

#define JSD_PO2OP_MAX_ATTEMPTS 3
#define JSD_ELIST_MAX_READS 20

/**
* @brief converts ec_state int to human-readable string
Expand Down
17 changes: 16 additions & 1 deletion src/jsd_pub.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,22 @@ void jsd_set_slave_config(jsd_t* self, uint16_t slave_id,
* @param enable_autorecovery enables automatic recovery of lost devices
* @return true on successful SOEM initialization
*/
bool jsd_init(jsd_t* self, const char* ifname, uint8_t enable_autorecovery);
bool jsd_init(jsd_t* self, const char* ifname, uint8_t enable_autorecovery, int timeout_us);

/**
* @brief Checks every state individually and reports its EC state.
*
* @param self pointer JSD context
* @return Whether all states are operational or not
*/
bool jsd_all_slaves_operational(jsd_t* self);

/**
* @brief Determines if all slaves are operational. If not, reports errors from error list.
*
* @param self pointer JSD context
*/
void jsd_inspect_context(jsd_t* self);

/**
* @brief Receive data from slave devices and store on local IOmap.
Expand Down
2 changes: 1 addition & 1 deletion test/device/jsd_minimal_example_el3602.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ int main() {
jsd_set_slave_config(jsd, slave_id, my_config);

// Slave configuration must come before initialization
if (!jsd_init(jsd, "eth9", 1)) {
if (!jsd_init(jsd, "eth9", 1, EC_TIMEOUTRET)) {
ERROR("Could not init jsd");
return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion test/jsd_test_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ void sds_run(single_device_server_t* self, char* device_name, char* filename) {

uint32_t sds_iter = 0;

if (!jsd_init(self->jsd, device_name, 1)) {
if (!jsd_init(self->jsd, device_name, 1, EC_TIMEOUTRET)) {
ERROR("Could not init jsd");
return;
}
Expand Down
2 changes: 1 addition & 1 deletion test/unit/jsd_soem_init_close_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ int main(int argc, char* argv[]) {

jsd_t* jsd = jsd_alloc();

if (!jsd_init(jsd, argv[1], 1)) {
if (!jsd_init(jsd, argv[1], 1, EC_TIMEOUTRET)) {
ERROR("Could not init jsd");
return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion tools/jsd_egd_tlc_tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ int main(int argc, char* argv[]) {
jsd_set_slave_config(jsd, slave_id, my_config);

// slave configuration must come before initialization
if (!jsd_init(jsd, ifname, 1)) {
if (!jsd_init(jsd, ifname, 1, EC_TIMEOUTRET)) {
ERROR("Could not init jsd");
return 0;
}
Expand Down

0 comments on commit 40d420b

Please sign in to comment.