@@ -84,7 +84,7 @@ void jsd_set_slave_config(jsd_t* self, uint16_t slave_id,
84
84
self -> slave_configs [slave_id ] = slave_config ;
85
85
}
86
86
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 ) {
88
88
assert (self );
89
89
self -> enable_autorecovery = enable_autorecovery ;
90
90
@@ -165,15 +165,36 @@ bool jsd_init(jsd_t* self, const char* ifname, uint8_t enable_autorecovery) {
165
165
166
166
self -> ecx_context .slavelist [0 ].state = EC_STATE_OPERATIONAL ;
167
167
168
+ struct timespec start_processdata_time ;
169
+ clock_gettime (CLOCK_REALTIME , & start_processdata_time );
168
170
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 );
170
172
171
173
ecx_writestate (& self -> ecx_context , 0 );
172
174
173
175
int attempt = 0 ;
174
176
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 );
175
196
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 );
177
198
ec_state actual_state = ecx_statecheck (
178
199
& self -> ecx_context , 0 , EC_STATE_OPERATIONAL , EC_TIMEOUTSTATE );
179
200
@@ -195,6 +216,8 @@ bool jsd_init(jsd_t* self, const char* ifname, uint8_t enable_autorecovery) {
195
216
WARNING ("Failed OP transition attempt %d of %d" , attempt ,
196
217
JSD_PO2OP_MAX_ATTEMPTS );
197
218
219
+ jsd_inspect_context (self );
220
+
198
221
if (attempt >= JSD_PO2OP_MAX_ATTEMPTS ) {
199
222
ERROR ("Max number of attempts to transition to OPERATIONAL exceeded." );
200
223
return false;
@@ -227,6 +250,70 @@ bool jsd_init(jsd_t* self, const char* ifname, uint8_t enable_autorecovery) {
227
250
return true;
228
251
}
229
252
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
+
230
317
void jsd_read (jsd_t * self , int timeout_us ) {
231
318
assert (self );
232
319
@@ -238,7 +325,7 @@ void jsd_read(jsd_t* self, int timeout_us) {
238
325
}
239
326
if (self -> last_wkc != self -> expected_wkc && self -> wkc == self -> expected_wkc ) {
240
327
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" );
242
329
}
243
330
}
244
331
self -> last_wkc = self -> wkc ;
@@ -610,7 +697,7 @@ void jsd_ecatcheck(jsd_t* self) {
610
697
611
698
if ((bus_state == EC_STATE_OPERATIONAL && self -> wkc < self -> expected_wkc ) ||
612
699
self -> ecx_context .grouplist [currentgroup ].docheckstate ) {
613
- /* one ore more slaves are not responding */
700
+ /* one or more slaves are not responding */
614
701
self -> ecx_context .grouplist [currentgroup ].docheckstate = FALSE;
615
702
ecx_readstate (& self -> ecx_context );
616
703
for (slave = 1 ; slave <= * self -> ecx_context .slavecount ; slave ++ ) {
0 commit comments