@@ -321,167 +321,165 @@ impl DutPwrThread {
321321 // Spawn a high priority thread that handles the power status
322322 // in a realtimey fashion.
323323 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 ;
346325
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 ( ) ;
354333
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) ;
425338
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 ) ) ;
428341
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+ } ;
439353
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 ( ) ) ;
441374 }
442375
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 {
446381 turn_off_with_reason (
447- OutputState :: OverCurrent ,
382+ OutputState :: RealtimeViolation ,
448383 & pwr_line,
449384 & discharge_line,
450385 & state,
451386 ) ;
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+ }
452392
453- continue ;
393+ if let Ok ( m) = feedback {
394+ break ( m[ 0 ] . value , m[ 1 ] . value ) ;
454395 }
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+ }
455454
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 ) ;
479477 }
480478 }
479+ }
481480
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) ;
485483
486484 Ok ( ( ) )
487485 } ) ?;
0 commit comments