Skip to content

Commit 40d420b

Browse files
Merge branch 'master' into prestonr-add-el5042
2 parents 25d6e57 + 7ce3586 commit 40d420b

File tree

7 files changed

+113
-10
lines changed

7 files changed

+113
-10
lines changed

src/jsd.c

Lines changed: 92 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ void jsd_set_slave_config(jsd_t* self, uint16_t slave_id,
8484
self->slave_configs[slave_id] = slave_config;
8585
}
8686

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

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

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

168+
struct timespec start_processdata_time;
169+
clock_gettime(CLOCK_REALTIME, &start_processdata_time);
168170
ecx_send_overlap_processdata(&self->ecx_context);
169-
ecx_receive_processdata(&self->ecx_context, EC_TIMEOUTRET);
171+
ecx_receive_processdata(&self->ecx_context, timeout_us);
170172

171173
ecx_writestate(&self->ecx_context, 0);
172174

173175
int attempt = 0;
174176
while (true) {
177+
struct timespec current_time;
178+
clock_gettime(CLOCK_REALTIME, &current_time);
179+
if ((current_time.tv_nsec - start_processdata_time.tv_nsec)/1e3 > timeout_us) {
180+
MSG_DEBUG("Went over the loop period!");
181+
}
182+
else {
183+
struct timespec diff;
184+
diff.tv_sec = current_time.tv_sec - start_processdata_time.tv_sec;
185+
diff.tv_nsec = current_time.tv_nsec - start_processdata_time.tv_nsec;
186+
187+
// Sleep for period defined by timeout_us before attempting to do a receive_processdata.
188+
// LRW packets must be sent at constant interval to encourage a successful transition to OP state/
189+
if (nanosleep(&diff, NULL) < 0) {
190+
perror("nanosleep failed");
191+
return 1;
192+
}
193+
}
194+
195+
clock_gettime(CLOCK_REALTIME, &start_processdata_time);
175196
int sent = ecx_send_overlap_processdata(&self->ecx_context);
176-
int wkc = ecx_receive_processdata(&self->ecx_context, EC_TIMEOUTRET);
197+
int wkc = ecx_receive_processdata(&self->ecx_context, timeout_us);
177198
ec_state actual_state = ecx_statecheck(
178199
&self->ecx_context, 0, EC_STATE_OPERATIONAL, EC_TIMEOUTSTATE);
179200

@@ -195,6 +216,8 @@ bool jsd_init(jsd_t* self, const char* ifname, uint8_t enable_autorecovery) {
195216
WARNING("Failed OP transition attempt %d of %d", attempt,
196217
JSD_PO2OP_MAX_ATTEMPTS);
197218

219+
jsd_inspect_context(self);
220+
198221
if (attempt >= JSD_PO2OP_MAX_ATTEMPTS) {
199222
ERROR("Max number of attempts to transition to OPERATIONAL exceeded.");
200223
return false;
@@ -227,6 +250,70 @@ bool jsd_init(jsd_t* self, const char* ifname, uint8_t enable_autorecovery) {
227250
return true;
228251
}
229252

253+
bool jsd_all_slaves_operational(jsd_t* self) {
254+
bool all_slaves_operational = true;
255+
uint8_t currentgroup = 0; // only 1 rate group in JSD currently
256+
/* one or more slaves may not be responding */
257+
for (int slave = 1; slave <= *self->ecx_context.slavecount; slave++) {
258+
if (self->ecx_context.slavelist[slave].group != currentgroup) continue;
259+
/* re-check bad slave individually */
260+
ecx_statecheck(&self->ecx_context, slave, EC_STATE_OPERATIONAL, EC_TIMEOUTRET);
261+
if (self->ecx_context.slavelist[slave].state != EC_STATE_OPERATIONAL) {
262+
all_slaves_operational = false;
263+
if (self->ecx_context.slavelist[slave].state ==
264+
(EC_STATE_SAFE_OP + EC_STATE_ERROR)) {
265+
ERROR("slave[%d] is in SAFE_OP + ERROR.", slave);
266+
} else if (self->ecx_context.slavelist[slave].state == EC_STATE_SAFE_OP) {
267+
ERROR("slave[%d] is in SAFE_OP.", slave);
268+
} else if (self->ecx_context.slavelist[slave].state > EC_STATE_NONE) {
269+
ERROR("slave[%d] is in state with hexadecimal: %x", slave, self->ecx_context.slavelist[slave].state);
270+
} else {
271+
ERROR("slave[%d] is lost", slave);
272+
}
273+
}
274+
else {
275+
MSG("slave[%d] is OPERATIONAL.", slave);
276+
}
277+
}
278+
279+
return all_slaves_operational;
280+
}
281+
282+
void jsd_inspect_context(jsd_t* self) {
283+
ec_state bus_state = jsd_get_device_state(self, 0);
284+
285+
/* first check if the jsd bus is operational so we can get more info */
286+
if (bus_state != EC_STATE_OPERATIONAL) {
287+
ERROR("JSD bus is not OPERATIONAL.");
288+
}
289+
290+
if (jsd_all_slaves_operational(self)) {
291+
MSG("All slaves were operational at time of working counter fault.");
292+
}
293+
else {
294+
MSG("Some slaves were not operational.");
295+
if (self->ecx_context.ecaterror) {
296+
MSG("We experienced an ECAT error. When this occurs, error information aught to be saved. "
297+
"Errors in error list displayed below:\n");
298+
uint8_t i = 0;
299+
while(self->ecx_context.ecaterror && i < JSD_ELIST_MAX_READS) {
300+
MSG("%s\n", ecx_elist2string(&self->ecx_context));
301+
i++;
302+
}
303+
if (i == JSD_ELIST_MAX_READS) {
304+
MSG("Maximum number of reads from error list experienced."
305+
" This is likely a result of indefinite polling.");
306+
}
307+
else {
308+
MSG("Finished reporting errors in error list.");
309+
}
310+
}
311+
else {
312+
MSG("Despite some slaves not being operational, an ECAT error was not experienced.");
313+
}
314+
}
315+
}
316+
230317
void jsd_read(jsd_t* self, int timeout_us) {
231318
assert(self);
232319

@@ -238,7 +325,7 @@ void jsd_read(jsd_t* self, int timeout_us) {
238325
}
239326
if (self->last_wkc != self->expected_wkc && self->wkc == self->expected_wkc) {
240327
if (self->last_wkc != -1) {
241-
MSG("ecx_receive_processdata is not longer reading bad wkc");
328+
MSG("ecx_receive_processdata is no longer reading bad wkc");
242329
}
243330
}
244331
self->last_wkc = self->wkc;
@@ -610,7 +697,7 @@ void jsd_ecatcheck(jsd_t* self) {
610697

611698
if ((bus_state == EC_STATE_OPERATIONAL && self->wkc < self->expected_wkc) ||
612699
self->ecx_context.grouplist[currentgroup].docheckstate) {
613-
/* one ore more slaves are not responding */
700+
/* one or more slaves are not responding */
614701
self->ecx_context.grouplist[currentgroup].docheckstate = FALSE;
615702
ecx_readstate(&self->ecx_context);
616703
for (slave = 1; slave <= *self->ecx_context.slavecount; slave++) {

src/jsd.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ extern "C" {
88
#include "jsd/jsd_pub.h"
99

1010
#define JSD_PO2OP_MAX_ATTEMPTS 3
11+
#define JSD_ELIST_MAX_READS 20
1112

1213
/**
1314
* @brief converts ec_state int to human-readable string

src/jsd_pub.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,22 @@ void jsd_set_slave_config(jsd_t* self, uint16_t slave_id,
5151
* @param enable_autorecovery enables automatic recovery of lost devices
5252
* @return true on successful SOEM initialization
5353
*/
54-
bool jsd_init(jsd_t* self, const char* ifname, uint8_t enable_autorecovery);
54+
bool jsd_init(jsd_t* self, const char* ifname, uint8_t enable_autorecovery, int timeout_us);
55+
56+
/**
57+
* @brief Checks every state individually and reports its EC state.
58+
*
59+
* @param self pointer JSD context
60+
* @return Whether all states are operational or not
61+
*/
62+
bool jsd_all_slaves_operational(jsd_t* self);
63+
64+
/**
65+
* @brief Determines if all slaves are operational. If not, reports errors from error list.
66+
*
67+
* @param self pointer JSD context
68+
*/
69+
void jsd_inspect_context(jsd_t* self);
5570

5671
/**
5772
* @brief Receive data from slave devices and store on local IOmap.

test/device/jsd_minimal_example_el3602.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ int main() {
2323
jsd_set_slave_config(jsd, slave_id, my_config);
2424

2525
// Slave configuration must come before initialization
26-
if (!jsd_init(jsd, "eth9", 1)) {
26+
if (!jsd_init(jsd, "eth9", 1, EC_TIMEOUTRET)) {
2727
ERROR("Could not init jsd");
2828
return 0;
2929
}

test/jsd_test_utils.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ void sds_run(single_device_server_t* self, char* device_name, char* filename) {
103103

104104
uint32_t sds_iter = 0;
105105

106-
if (!jsd_init(self->jsd, device_name, 1)) {
106+
if (!jsd_init(self->jsd, device_name, 1, EC_TIMEOUTRET)) {
107107
ERROR("Could not init jsd");
108108
return;
109109
}

test/unit/jsd_soem_init_close_test.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ int main(int argc, char* argv[]) {
1212

1313
jsd_t* jsd = jsd_alloc();
1414

15-
if (!jsd_init(jsd, argv[1], 1)) {
15+
if (!jsd_init(jsd, argv[1], 1, EC_TIMEOUTRET)) {
1616
ERROR("Could not init jsd");
1717
return 0;
1818
}

tools/jsd_egd_tlc_tty.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ int main(int argc, char* argv[]) {
151151
jsd_set_slave_config(jsd, slave_id, my_config);
152152

153153
// slave configuration must come before initialization
154-
if (!jsd_init(jsd, ifname, 1)) {
154+
if (!jsd_init(jsd, ifname, 1, EC_TIMEOUTRET)) {
155155
ERROR("Could not init jsd");
156156
return 0;
157157
}

0 commit comments

Comments
 (0)