@@ -43,6 +43,10 @@ const DEBOUNCE_POLL_INTERVAL_MS: u64 = 75;
4343/// Length of a reset pulse, in milliseconds
4444const RESET_DURATION_MS : u64 = 250 ;
4545
46+ /// Minimum voltage level of the 3.3V rail before we start
47+ /// driving the IRQ pin high, to avoid back-powering.
48+ const POWER_GOOD_THRESHOLD_MV : u16 = 3200 ;
49+
4650/// The states we can be in controlling the DC power
4751#[ derive( Copy , Clone , PartialEq , Eq ) ]
4852#[ repr( u8 ) ]
@@ -211,8 +215,12 @@ mod app {
211215 let mono = Systick :: new ( cp. SYST , rcc. clocks . sysclk ( ) . 0 ) ;
212216
213217 let mut adc = Adc :: new ( dp. ADC , & mut rcc) ;
214- adc. set_sample_time ( adc:: AdcSampleTime :: T_1 ) ;
215- adc. set_precision ( adc:: AdcPrecision :: B_6 ) ;
218+ // 8 bit precision should be plenty for our use case
219+ adc. set_precision ( adc:: AdcPrecision :: B_8 ) ;
220+ // Approx. sampling time required to charge the 8pF sample & hold
221+ // capacitor through the 10kΩ resistor and to get a reading with 8 bit accuracy:
222+ // 8pF * 10kΩ * ln(2^8) ≈ 440ns ≈ 6 ADC clock cycles
223+ adc. set_sample_time ( adc:: AdcSampleTime :: T_7 ) ;
216224
217225 defmt:: info!( "Creating pins..." ) ;
218226 let gpioa = dp. GPIOA . split ( & mut rcc) ;
@@ -471,7 +479,8 @@ mod app {
471479 ctx. shared . pin_sys_reset . lock ( |pin| pin. set_low ( ) . unwrap ( ) ) ;
472480 // Step 4 - Turn on PSU
473481 ctx. shared . pin_dc_on . set_high ( ) . unwrap ( ) ;
474- // Step 5 happens below when power is good
482+ // Taking the system out of reset and enabling the IRQ line happens
483+ // later, when the power rail is settled
475484 defmt:: info!( "Waiting for power-good" ) ;
476485 }
477486 }
@@ -590,15 +599,32 @@ mod app {
590599 }
591600 // TODO: Also monitor 5.0V rail
592601
593- // Wait for power good
602+ // Wait for power- good
594603 if ctx. shared . state_dc_power_enabled . lock ( |r| * r) == DcPowerState :: Starting {
604+ // Reads the absolute voltage of the mon_3v3 line in mV.
605+ // This line is connected to the 3v3 supply through a 50% voltage divider,
606+ // so it should read 1650[mV] nominally.
607+ //
608+ // Note that read_abs_mv is relatively slow, as it internally reads
609+ // ADC values from both the pin and an internal voltage reference, and
610+ // does calculations including integer divisions.
611+ //
612+ // As we do not really require an accurate absolute voltage, but only
613+ // need to be sure that the 3v3 rail is reasonably close to the 3.3VP
614+ // rail (the permanent power rail supplying the BMC), this could be
615+ // rewritten using `ctx.local.adc.read(ctx.local.pin_3v3_monitor)`
616+ // in case performance becomes an issue.
595617 let mon_3v3 = ctx. local . adc . read_abs_mv ( ctx. local . pin_3v3_monitor ) ;
596- defmt:: trace!( "3v3 reading: {}" , mon_3v3) ;
597- if mon_3v3 < 1600 {
598- defmt:: info!( "3v3 below threshold: {} mv" , mon_3v3) ;
618+ defmt:: trace!( "mon_3v3 reading: {} mV" , mon_3v3) ;
619+ if mon_3v3 < POWER_GOOD_THRESHOLD_MV / 2 {
620+ defmt:: info!(
621+ "mon_3v3 below threshold of {} mV: {} mV" ,
622+ POWER_GOOD_THRESHOLD_MV / 2 ,
623+ mon_3v3
624+ ) ;
599625 } else {
600626 defmt:: info!(
601- "Power good. 3v3 at {} mV. Continue with startup sequence." ,
627+ "Power good. Mon_3v3 at {} mV. Continue with startup sequence." ,
602628 mon_3v3
603629 ) ;
604630 // Change the power state machine to "On". We were in 'Starting' to ignore
@@ -607,13 +633,10 @@ mod app {
607633 ctx. shared
608634 . state_dc_power_enabled
609635 . lock ( |r| * r = DcPowerState :: On ) ;
610- // Steps 1 - 4 happened above, in the button press handler
611- // Step 5 - Leave it in reset for a while.
612- // TODO: Start monitoring 3.3V and 5.0V rails here
613- // TODO: Take system out of reset when 3.3V and 5.0V are good
636+ // Wait a bit before taking system out of reset.
614637 // Returns an error if it's already scheduled (but we don't care)
615638 let _ = exit_reset:: spawn_after ( RESET_DURATION_MS . millis ( ) ) ;
616- // Set 6 - unmask the IRQ
639+ // Unmask the IRQ
617640 irq_forced_low = false ;
618641 }
619642 }
0 commit comments