@@ -321,167 +321,165 @@ impl DutPwrThread {
321
321
// Spawn a high priority thread that handles the power status
322
322
// in a realtimey fashion.
323
323
wtb. spawn_thread ( "power-thread" , move || {
324
- {
325
- let mut last_ts: Option < Instant > = None ;
326
-
327
- // There may be transients in the measured voltage/current, e.g. due to EMI or
328
- // inrush currents.
329
- // Nothing will break if they are sufficiently short, so the DUT can stay powered.
330
- // Filter out transients by taking the last four values, throwing away the largest
331
- // and smallest and averaging the two remaining ones.
332
- let mut volt_filter = MedianFilter :: < 4 > :: new ( ) ;
333
- let mut curr_filter = MedianFilter :: < 4 > :: new ( ) ;
334
-
335
- let ( tick_weak, request, state) = match realtime_priority ( ) {
336
- Ok ( _) => {
337
- let tick = Arc :: new ( AtomicU32 :: new ( 0 ) ) ;
338
- let tick_weak = Arc :: downgrade ( & tick) ;
339
-
340
- let request = Arc :: new ( AtomicU8 :: new ( OutputRequest :: Idle as u8 ) ) ;
341
- let state = Arc :: new ( AtomicU8 :: new ( OutputState :: Off as u8 ) ) ;
342
-
343
- thread_res_tx
344
- . try_send ( Ok ( ( tick, request. clone ( ) , state. clone ( ) ) ) )
345
- . unwrap ( ) ;
324
+ let mut last_ts: Option < Instant > = None ;
346
325
347
- ( tick_weak , request , state )
348
- }
349
- Err ( e ) => {
350
- thread_res_tx . try_send ( Err ( e ) ) . unwrap ( ) ;
351
- panic ! ( )
352
- }
353
- } ;
326
+ // There may be transients in the measured voltage/current, e.g. due to EMI or
327
+ // inrush currents.
328
+ // Nothing will break if they are sufficiently short, so the DUT can stay powered.
329
+ // Filter out transients by taking the last four values, throwing away the largest
330
+ // and smallest and averaging the two remaining ones.
331
+ let mut volt_filter = MedianFilter :: < 4 > :: new ( ) ;
332
+ let mut curr_filter = MedianFilter :: < 4 > :: new ( ) ;
354
333
355
- // Run as long as there is a strong reference to `tick`.
356
- // As tick is a private member of the struct this is equivalent
357
- // to running as long as the DutPwrThread was not dropped.
358
- while let Some ( tick) = tick_weak. upgrade ( ) {
359
- thread:: sleep ( THREAD_INTERVAL ) ;
360
-
361
- // Get new voltage and current readings while making sure
362
- // that they are not stale
363
- let ( volt, curr) = loop {
364
- let feedback = pwr_volt
365
- . fast
366
- . try_get_multiple ( [ & pwr_volt. fast , & pwr_curr. fast ] ) ;
367
-
368
- // We do not care too much about _why_ we could not get
369
- // a new value from the ADC.
370
- // If we get a new valid value before the timeout we
371
- // are fine.
372
- // If not we are not.
373
- if let Ok ( m) = feedback {
374
- last_ts = Some ( m[ 0 ] . ts . as_instant ( ) ) ;
375
- }
376
-
377
- let too_old = last_ts
378
- . map ( |ts| Instant :: now ( ) . duration_since ( ts) > MAX_AGE )
379
- . unwrap_or ( false ) ;
380
-
381
- if too_old {
382
- turn_off_with_reason (
383
- OutputState :: RealtimeViolation ,
384
- & pwr_line,
385
- & discharge_line,
386
- & state,
387
- ) ;
388
- } else {
389
- // We have a fresh ADC value. Signal "everything is well"
390
- // to the watchdog task.
391
- tick. fetch_add ( 1 , Ordering :: Relaxed ) ;
392
- }
393
-
394
- if let Ok ( m) = feedback {
395
- break ( m[ 0 ] . value , m[ 1 ] . value ) ;
396
- }
397
- } ;
398
-
399
- // The median filter needs some values in it's backlog before it
400
- // starts outputting values.
401
- let ( volt, curr) = match ( volt_filter. step ( volt) , curr_filter. step ( curr) ) {
402
- ( Some ( volt) , Some ( curr) ) => ( volt, curr) ,
403
- _ => continue ,
404
- } ;
405
-
406
- // Take the next pending OutputRequest (if any) even if it
407
- // may not be used due to a pending error condition, as it
408
- // could be quite surprising for the output to turn on
409
- // immediately when a fault is cleared after quite some time
410
- // of the output being off.
411
- let req = request
412
- . swap ( OutputRequest :: Idle as u8 , Ordering :: Relaxed )
413
- . into ( ) ;
414
-
415
- // Don't even look at the requests if there is an ongoing
416
- // overvoltage condition. Instead turn the output off and
417
- // go back to measuring.
418
- if volt > MAX_VOLTAGE {
419
- turn_off_with_reason (
420
- OutputState :: OverVoltage ,
421
- & pwr_line,
422
- & discharge_line,
423
- & state,
424
- ) ;
334
+ let ( tick_weak, request, state) = match realtime_priority ( ) {
335
+ Ok ( _) => {
336
+ let tick = Arc :: new ( AtomicU32 :: new ( 0 ) ) ;
337
+ let tick_weak = Arc :: downgrade ( & tick) ;
425
338
426
- continue ;
427
- }
339
+ let request = Arc :: new ( AtomicU8 :: new ( OutputRequest :: Idle as u8 ) ) ;
340
+ let state = Arc :: new ( AtomicU8 :: new ( OutputState :: Off as u8 ) ) ;
428
341
429
- // Don't even look at the requests if there is an ongoin
430
- // polarity inversion. Turn off, go back to start, do not
431
- // collect $200.
432
- if volt < MIN_VOLTAGE {
433
- turn_off_with_reason (
434
- OutputState :: InvertedPolarity ,
435
- & pwr_line,
436
- & discharge_line,
437
- & state,
438
- ) ;
342
+ thread_res_tx
343
+ . try_send ( Ok ( ( tick, request. clone ( ) , state. clone ( ) ) ) )
344
+ . unwrap ( ) ;
345
+
346
+ ( tick_weak, request, state)
347
+ }
348
+ Err ( e) => {
349
+ thread_res_tx. try_send ( Err ( e) ) . unwrap ( ) ;
350
+ panic ! ( )
351
+ }
352
+ } ;
439
353
440
- continue ;
354
+ // Run as long as there is a strong reference to `tick`.
355
+ // As tick is a private member of the struct this is equivalent
356
+ // to running as long as the DutPwrThread was not dropped.
357
+ while let Some ( tick) = tick_weak. upgrade ( ) {
358
+ thread:: sleep ( THREAD_INTERVAL ) ;
359
+
360
+ // Get new voltage and current readings while making sure
361
+ // that they are not stale
362
+ let ( volt, curr) = loop {
363
+ let feedback = pwr_volt
364
+ . fast
365
+ . try_get_multiple ( [ & pwr_volt. fast , & pwr_curr. fast ] ) ;
366
+
367
+ // We do not care too much about _why_ we could not get
368
+ // a new value from the ADC.
369
+ // If we get a new valid value before the timeout we
370
+ // are fine.
371
+ // If not we are not.
372
+ if let Ok ( m) = feedback {
373
+ last_ts = Some ( m[ 0 ] . ts . as_instant ( ) ) ;
441
374
}
442
375
443
- // Don't even look at the requests if there is an ongoin
444
- // overcurrent condition.
445
- if curr > MAX_CURRENT {
376
+ let too_old = last_ts
377
+ . map ( |ts| Instant :: now ( ) . duration_since ( ts) > MAX_AGE )
378
+ . unwrap_or ( false ) ;
379
+
380
+ if too_old {
446
381
turn_off_with_reason (
447
- OutputState :: OverCurrent ,
382
+ OutputState :: RealtimeViolation ,
448
383
& pwr_line,
449
384
& discharge_line,
450
385
& state,
451
386
) ;
387
+ } else {
388
+ // We have a fresh ADC value. Signal "everything is well"
389
+ // to the watchdog task.
390
+ tick. fetch_add ( 1 , Ordering :: Relaxed ) ;
391
+ }
452
392
453
- continue ;
393
+ if let Ok ( m) = feedback {
394
+ break ( m[ 0 ] . value , m[ 1 ] . value ) ;
454
395
}
396
+ } ;
397
+
398
+ // The median filter needs some values in it's backlog before it
399
+ // starts outputting values.
400
+ let ( volt, curr) = match ( volt_filter. step ( volt) , curr_filter. step ( curr) ) {
401
+ ( Some ( volt) , Some ( curr) ) => ( volt, curr) ,
402
+ _ => continue ,
403
+ } ;
404
+
405
+ // Take the next pending OutputRequest (if any) even if it
406
+ // may not be used due to a pending error condition, as it
407
+ // could be quite surprising for the output to turn on
408
+ // immediately when a fault is cleared after quite some time
409
+ // of the output being off.
410
+ let req = request
411
+ . swap ( OutputRequest :: Idle as u8 , Ordering :: Relaxed )
412
+ . into ( ) ;
413
+
414
+ // Don't even look at the requests if there is an ongoing
415
+ // overvoltage condition. Instead turn the output off and
416
+ // go back to measuring.
417
+ if volt > MAX_VOLTAGE {
418
+ turn_off_with_reason (
419
+ OutputState :: OverVoltage ,
420
+ & pwr_line,
421
+ & discharge_line,
422
+ & state,
423
+ ) ;
424
+
425
+ continue ;
426
+ }
427
+
428
+ // Don't even look at the requests if there is an ongoin
429
+ // polarity inversion. Turn off, go back to start, do not
430
+ // collect $200.
431
+ if volt < MIN_VOLTAGE {
432
+ turn_off_with_reason (
433
+ OutputState :: InvertedPolarity ,
434
+ & pwr_line,
435
+ & discharge_line,
436
+ & state,
437
+ ) ;
438
+
439
+ continue ;
440
+ }
441
+
442
+ // Don't even look at the requests if there is an ongoin
443
+ // overcurrent condition.
444
+ if curr > MAX_CURRENT {
445
+ turn_off_with_reason (
446
+ OutputState :: OverCurrent ,
447
+ & pwr_line,
448
+ & discharge_line,
449
+ & state,
450
+ ) ;
451
+
452
+ continue ;
453
+ }
455
454
456
- // There is no ongoing fault condition, so we could e.g. turn
457
- // the output on if requested.
458
- match req {
459
- OutputRequest :: Idle => { }
460
- OutputRequest :: On => {
461
- discharge_line
462
- . set_value ( 1 - DISCHARGE_LINE_ASSERTED )
463
- . unwrap ( ) ;
464
- pwr_line. set_value ( PWR_LINE_ASSERTED ) . unwrap ( ) ;
465
- state. store ( OutputState :: On as u8 , Ordering :: Relaxed ) ;
466
- }
467
- OutputRequest :: Off => {
468
- discharge_line. set_value ( DISCHARGE_LINE_ASSERTED ) . unwrap ( ) ;
469
- pwr_line. set_value ( 1 - PWR_LINE_ASSERTED ) . unwrap ( ) ;
470
- state. store ( OutputState :: Off as u8 , Ordering :: Relaxed ) ;
471
- }
472
- OutputRequest :: OffFloating => {
473
- discharge_line
474
- . set_value ( 1 - DISCHARGE_LINE_ASSERTED )
475
- . unwrap ( ) ;
476
- pwr_line. set_value ( 1 - PWR_LINE_ASSERTED ) . unwrap ( ) ;
477
- state. store ( OutputState :: OffFloating as u8 , Ordering :: Relaxed ) ;
478
- }
455
+ // There is no ongoing fault condition, so we could e.g. turn
456
+ // the output on if requested.
457
+ match req {
458
+ OutputRequest :: Idle => { }
459
+ OutputRequest :: On => {
460
+ discharge_line
461
+ . set_value ( 1 - DISCHARGE_LINE_ASSERTED )
462
+ . unwrap ( ) ;
463
+ pwr_line. set_value ( PWR_LINE_ASSERTED ) . unwrap ( ) ;
464
+ state. store ( OutputState :: On as u8 , Ordering :: Relaxed ) ;
465
+ }
466
+ OutputRequest :: Off => {
467
+ discharge_line. set_value ( DISCHARGE_LINE_ASSERTED ) . unwrap ( ) ;
468
+ pwr_line. set_value ( 1 - PWR_LINE_ASSERTED ) . unwrap ( ) ;
469
+ state. store ( OutputState :: Off as u8 , Ordering :: Relaxed ) ;
470
+ }
471
+ OutputRequest :: OffFloating => {
472
+ discharge_line
473
+ . set_value ( 1 - DISCHARGE_LINE_ASSERTED )
474
+ . unwrap ( ) ;
475
+ pwr_line. set_value ( 1 - PWR_LINE_ASSERTED ) . unwrap ( ) ;
476
+ state. store ( OutputState :: OffFloating as u8 , Ordering :: Relaxed ) ;
479
477
}
480
478
}
479
+ }
481
480
482
- // Make sure to enter fail safe mode before leaving the thread
483
- turn_off_with_reason ( OutputState :: Off , & pwr_line, & discharge_line, & state) ;
484
- } ;
481
+ // Make sure to enter fail safe mode before leaving the thread
482
+ turn_off_with_reason ( OutputState :: Off , & pwr_line, & discharge_line, & state) ;
485
483
486
484
Ok ( ( ) )
487
485
} ) ?;
0 commit comments