@@ -16,10 +16,12 @@ use core::convert::TryFrom;
1616use heapless:: spsc:: { Consumer , Producer , Queue } ;
1717use rtic:: app;
1818use stm32f0xx_hal:: {
19- gpio:: gpioa:: { PA10 , PA11 , PA12 , PA15 , PA2 , PA3 , PA4 , PA8 , PA9 } ,
19+ adc,
20+ adc:: Adc ,
21+ gpio:: gpioa:: { PA0 , PA10 , PA11 , PA12 , PA15 , PA2 , PA3 , PA4 , PA8 , PA9 } ,
2022 gpio:: gpiob:: { PB0 , PB3 , PB4 , PB5 } ,
2123 gpio:: gpiof:: { PF0 , PF1 } ,
22- gpio:: { Alternate , Floating , Input , Output , PullDown , PullUp , PushPull , AF1 } ,
24+ gpio:: { Alternate , Analog , Floating , Input , Output , PullDown , PullUp , PushPull , AF1 } ,
2325 pac,
2426 prelude:: * ,
2527 rcc, serial,
@@ -170,6 +172,10 @@ mod app {
170172 rcc : Option < rcc:: Rcc > ,
171173 /// IRQ pin
172174 pin_irq : PA8 < Output < PushPull > > ,
175+ /// 3.3V monitor pin
176+ pin_3v3_monitor : PA0 < Analog > ,
177+ /// ADC
178+ adc : Adc ,
173179 }
174180
175181 #[ monotonic( binds = SysTick , default = true ) ]
@@ -204,6 +210,10 @@ mod app {
204210 // Initialize the monotonic timer using the Cortex-M SysTick peripheral
205211 let mono = Systick :: new ( cp. SYST , rcc. clocks . sysclk ( ) . 0 ) ;
206212
213+ 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 ) ;
216+
207217 defmt:: info!( "Creating pins..." ) ;
208218 let gpioa = dp. GPIOA . split ( & mut rcc) ;
209219 let gpiob = dp. GPIOB . split ( & mut rcc) ;
@@ -236,6 +246,8 @@ mod app {
236246 pin_cipo,
237247 pin_copi,
238248 mut pin_irq,
249+ pin_3v3_monitor,
250+ adc,
239251 ) = cortex_m:: interrupt:: free ( |cs| {
240252 (
241253 // uart_tx,
@@ -281,6 +293,10 @@ mod app {
281293 gpioa. pa7 . into_alternate_af0 ( cs) ,
282294 // pin_irq
283295 gpioa. pa8 . into_push_pull_output ( cs) ,
296+ // pin_3v3_monitor
297+ gpioa. pa0 . into_analog ( cs) ,
298+ // ADC
299+ adc,
284300 )
285301 } ) ;
286302
@@ -364,6 +380,8 @@ mod app {
364380 press_button_reset_short : debouncr:: debounce_2 ( false ) ,
365381 rcc : Some ( rcc) ,
366382 pin_irq,
383+ pin_3v3_monitor,
384+ adc,
367385 } ;
368386 let init = init:: Monotonics ( mono) ;
369387 ( shared_resources, local_resources, init)
@@ -372,7 +390,7 @@ mod app {
372390 /// Our idle task.
373391 ///
374392 /// This task is called when there is nothing else to do.
375- #[ idle( shared = [ msg_q_out, msg_q_in, spi, state_dc_power_enabled, pin_dc_on, pin_sys_reset, speaker] , local = [ pin_irq, rcc, speaker_task_handle: Option <speaker_pwm_stop:: MyMono :: SpawnHandle > = None ] ) ]
393+ #[ idle( shared = [ msg_q_out, msg_q_in, spi, state_dc_power_enabled, pin_dc_on, pin_sys_reset, speaker] , local = [ pin_irq, rcc, speaker_task_handle: Option <speaker_pwm_stop:: MyMono :: SpawnHandle > = None , adc , pin_3v3_monitor ] ) ]
376394 fn idle ( mut ctx : idle:: Context ) -> ! {
377395 // TODO: Get this from the VERSION static variable or from PKG_VERSION
378396 let mut register_state = RegisterState {
@@ -420,7 +438,8 @@ mod app {
420438 }
421439 }
422440 Some ( Message :: PowerButtonLongPress ) => {
423- if ctx. shared . state_dc_power_enabled . lock ( |r| * r) == DcPowerState :: On {
441+ let power_state = ctx. shared . state_dc_power_enabled . lock ( |r| * r) ;
442+ if power_state == DcPowerState :: On || power_state == DcPowerState :: Starting {
424443 defmt:: info!( "Power off requested!" ) ;
425444 ctx. shared
426445 . state_dc_power_enabled
@@ -452,26 +471,12 @@ mod app {
452471 ctx. shared . pin_sys_reset . lock ( |pin| pin. set_low ( ) . unwrap ( ) ) ;
453472 // Step 4 - Turn on PSU
454473 ctx. shared . pin_dc_on . set_high ( ) . unwrap ( ) ;
455- // Step 5 - Leave it in reset for a while.
456- // TODO: Start monitoring 3.3V and 5.0V rails here
457- // TODO: Take system out of reset when 3.3V and 5.0V are good
458- // Returns an error if it's already scheduled (but we don't care)
459- let _ = exit_reset:: spawn_after ( RESET_DURATION_MS . millis ( ) ) ;
460- // Set 6 - unmask the IRQ
461- irq_forced_low = false ;
474+ // Step 5 happens below when power is good
475+ defmt:: info!( "Waiting for power-good" ) ;
462476 }
463477 }
464478 Some ( Message :: PowerButtonRelease ) => {
465- if ctx. shared . state_dc_power_enabled . lock ( |r| * r) == DcPowerState :: Starting {
466- defmt:: info!( "Power button released." ) ;
467- // Button released after power on. Change the power
468- // state machine t "On". We were in 'Starting' to ignore
469- // any further button events until the button had been
470- // released.
471- ctx. shared
472- . state_dc_power_enabled
473- . lock ( |r| * r = DcPowerState :: On ) ;
474- }
479+ defmt:: info!( "Power button released." ) ;
475480 }
476481 Some ( Message :: ResetButtonShortPress ) => {
477482 // Is the board powered on? Don't do a reset if it's powered off.
@@ -493,7 +498,7 @@ mod app {
493498 }
494499 }
495500 Some ( Message :: SpiEnable ) => {
496- if ctx. shared . state_dc_power_enabled . lock ( |r| * r) != DcPowerState :: Off {
501+ if ctx. shared . state_dc_power_enabled . lock ( |r| * r) == DcPowerState :: On {
497502 // Turn on the SPI peripheral and expect four bytes (the
498503 // length of a Request).
499504 ctx. shared . spi . lock ( |s| s. start ( 4 ) ) ;
@@ -583,7 +588,37 @@ mod app {
583588 ) ;
584589 }
585590 }
586- // TODO: Read ADC for 3.3V and 5.0V rails and check good
591+ // TODO: Also monitor 5.0V rail
592+
593+ // Wait for power good
594+ if ctx. shared . state_dc_power_enabled . lock ( |r| * r) == DcPowerState :: Starting {
595+ 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) ;
599+ } else {
600+ defmt:: info!(
601+ "Power good. 3v3 at {} mV. Continue with startup sequence." ,
602+ mon_3v3
603+ ) ;
604+ // Change the power state machine to "On". We were in 'Starting' to ignore
605+ // any further button events until the button had been
606+ // released and to wait for power good.
607+ ctx. shared
608+ . state_dc_power_enabled
609+ . 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
614+ // Returns an error if it's already scheduled (but we don't care)
615+ let _ = exit_reset:: spawn_after ( RESET_DURATION_MS . millis ( ) ) ;
616+ // Set 6 - unmask the IRQ
617+ irq_forced_low = false ;
618+ }
619+ }
620+ // TODO: Shutdown system if mon_3v3 falls below threshold
621+ // TODO: Maybe report voltages to CPU?
587622 }
588623 }
589624
@@ -797,7 +832,7 @@ mod app {
797832 #[ task( shared = [ pin_sys_reset, state_dc_power_enabled] ) ]
798833 fn exit_reset ( mut ctx : exit_reset:: Context ) {
799834 defmt:: debug!( "End reset" ) ;
800- if ctx. shared . state_dc_power_enabled . lock ( |r| * r) != DcPowerState :: Off {
835+ if ctx. shared . state_dc_power_enabled . lock ( |r| * r) == DcPowerState :: On {
801836 // Raising the reset line takes the rest of the system out of reset
802837 ctx. shared . pin_sys_reset . lock ( |pin| pin. set_high ( ) . unwrap ( ) ) ;
803838 }
0 commit comments