1111use cortex_m:: interrupt:: free as disable_interrupts;
1212use rtic:: app;
1313use stm32f0xx_hal:: {
14- gpio:: gpioa:: { PA10 , PA11 , PA12 , PA9 } ,
14+ gpio:: gpioa:: { PA10 , PA11 , PA12 , PA2 , PA3 , PA9 } ,
1515 gpio:: gpiob:: { PB0 , PB1 } ,
1616 gpio:: gpiof:: { PF0 , PF1 } ,
1717 gpio:: { Alternate , Input , Output , PullUp , PushPull , AF1 } ,
@@ -54,19 +54,24 @@ const APP: () = {
5454 /// The FTDI UART header (J105)
5555 serial : serial:: Serial < pac:: USART1 , PA9 < Alternate < AF1 > > , PA10 < Alternate < AF1 > > > ,
5656 /// The Clear-To-Send line on the FTDI UART header (which the serial object can't handle)
57- uart_cts : PA11 < Alternate < AF1 > > ,
57+ pin_uart_cts : PA11 < Alternate < AF1 > > ,
5858 /// The Ready-To-Receive line on the FTDI UART header (which the serial object can't handle)
59- uart_rts : PA12 < Alternate < AF1 > > ,
59+ pin_uart_rts : PA12 < Alternate < AF1 > > ,
6060 /// The power button
6161 button_power : PF0 < Input < PullUp > > ,
6262 /// The reset button
6363 button_reset : PF1 < Input < PullUp > > ,
6464 /// Tracks power button state for short presses. 75ms x 2 = 150ms is a short press
65- button_power_short_press : debouncr:: Debouncer < u8 , debouncr:: Repeat2 > ,
65+ press_button_power_short : debouncr:: Debouncer < u8 , debouncr:: Repeat2 > ,
6666 /// Tracks power button state for long presses. 75ms x 16 = 1200ms is a long press
67- button_power_long_press : debouncr:: Debouncer < u16 , debouncr:: Repeat16 > ,
67+ press_button_power_long : debouncr:: Debouncer < u16 , debouncr:: Repeat16 > ,
6868 /// Tracks DC power state
69- dc_power_enabled : DcPowerState ,
69+ state_dc_power_enabled : DcPowerState ,
70+ /// Controls the DC-DC PSU
71+ pin_dc_on : PA3 < Output < PushPull > > ,
72+ /// Controls the Reset signal across the main board, putting all the
73+ /// chips (except this BMC!) in reset when pulled low.
74+ pin_sys_reset : PA2 < Output < PushPull > > ,
7075 }
7176
7277 /// The entry point to our application.
@@ -100,12 +105,14 @@ const APP: () = {
100105 let (
101106 uart_tx,
102107 uart_rx,
103- uart_cts ,
104- uart_rts ,
108+ pin_uart_cts ,
109+ pin_uart_rts ,
105110 mut led_power,
106111 led_status,
107112 button_power,
108113 button_reset,
114+ mut pin_dc_on,
115+ mut pin_sys_reset,
109116 ) = disable_interrupts ( |cs| {
110117 (
111118 gpioa. pa9 . into_alternate_af1 ( cs) ,
@@ -116,9 +123,14 @@ const APP: () = {
116123 gpiob. pb1 . into_push_pull_output ( cs) ,
117124 gpiof. pf0 . into_pull_up_input ( cs) ,
118125 gpiof. pf1 . into_pull_up_input ( cs) ,
126+ gpioa. pa3 . into_push_pull_output ( cs) ,
127+ gpioa. pa2 . into_push_pull_output ( cs) ,
119128 )
120129 } ) ;
121130
131+ pin_sys_reset. set_low ( ) . unwrap ( ) ;
132+ pin_dc_on. set_low ( ) . unwrap ( ) ;
133+
122134 defmt:: info!( "Creating UART..." ) ;
123135
124136 let mut serial =
@@ -136,15 +148,17 @@ const APP: () = {
136148
137149 init:: LateResources {
138150 serial,
139- uart_cts ,
140- uart_rts ,
151+ pin_uart_cts ,
152+ pin_uart_rts ,
141153 led_power,
142154 led_status,
143155 button_power,
144156 button_reset,
145- button_power_short_press : debouncr:: debounce_2 ( false ) ,
146- button_power_long_press : debouncr:: debounce_16 ( false ) ,
147- dc_power_enabled : DcPowerState :: Off ,
157+ press_button_power_short : debouncr:: debounce_2 ( false ) ,
158+ press_button_power_long : debouncr:: debounce_16 ( false ) ,
159+ state_dc_power_enabled : DcPowerState :: Off ,
160+ pin_dc_on,
161+ pin_sys_reset,
148162 }
149163 }
150164
@@ -204,58 +218,50 @@ const APP: () = {
204218 /// This task polls our power and reset buttons.
205219 ///
206220 /// We poll them rather than setting up an interrupt as we need to debounce them, which involves waiting a short period and checking them again. Given that we have to do that, we might as well not bother with the interrupt.
207- #[ task( schedule = [ button_poll] , resources = [ led_power, button_power, button_power_short_press, button_power_long_press, dc_power_enabled] ) ]
221+ #[ task(
222+ schedule = [ button_poll] ,
223+ resources = [
224+ led_power, button_power, press_button_power_short, press_button_power_long, state_dc_power_enabled,
225+ pin_sys_reset, pin_dc_on
226+ ]
227+ ) ]
208228 fn button_poll ( ctx : button_poll:: Context ) {
209229 // Poll button
210230 let pressed: bool = ctx. resources . button_power . is_low ( ) . unwrap ( ) ;
211231
212232 // Update state
213- let short_edge = ctx. resources . button_power_short_press . update ( pressed) ;
214- let long_edge = ctx. resources . button_power_long_press . update ( pressed) ;
233+ let short_edge = ctx. resources . press_button_power_short . update ( pressed) ;
234+ let long_edge = ctx. resources . press_button_power_long . update ( pressed) ;
215235
216236 // Dispatch event
217- if short_edge == Some ( debouncr:: Edge :: Rising ) {
218- defmt:: trace!(
219- "Power short press in! {}" ,
220- * ctx. resources. dc_power_enabled as u8
221- ) ;
222- if * ctx. resources . dc_power_enabled == DcPowerState :: Off {
223- * ctx. resources . dc_power_enabled = DcPowerState :: Starting ;
237+ match ( long_edge, short_edge, * ctx. resources . state_dc_power_enabled ) {
238+ ( None , Some ( debouncr:: Edge :: Rising ) , DcPowerState :: Off ) => {
239+ defmt:: info!( "Power button pressed whilst off." ) ;
240+ // Button pressed - power on system
241+ * ctx. resources . state_dc_power_enabled = DcPowerState :: Starting ;
224242 ctx. resources . led_power . set_high ( ) . unwrap ( ) ;
225243 defmt:: info!( "Power on!" ) ;
226- // TODO: Enable DC PSU here
244+ ctx . resources . pin_dc_on . set_high ( ) . unwrap ( ) ;
227245 // TODO: Start monitoring 3.3V and 5.0V rails here
228246 // TODO: Take system out of reset when 3.3V and 5.0V are good
247+ ctx. resources . pin_sys_reset . set_high ( ) . unwrap ( ) ;
229248 }
230- } else if short_edge == Some ( debouncr:: Edge :: Falling ) {
231- defmt:: trace!(
232- "Power short press out! {}" ,
233- * ctx. resources. dc_power_enabled as u8
234- ) ;
235- match * ctx. resources . dc_power_enabled {
236- DcPowerState :: Starting => {
237- * ctx. resources . dc_power_enabled = DcPowerState :: On ;
238- }
239- DcPowerState :: On => {
240- // TODO: Tell host that power off was requested
241- }
242- DcPowerState :: Off => {
243- // Ignore
244- }
249+ ( None , Some ( debouncr:: Edge :: Falling ) , DcPowerState :: Starting ) => {
250+ defmt:: info!( "Power button released." ) ;
251+ // Button released after power on
252+ * ctx. resources . state_dc_power_enabled = DcPowerState :: On ;
245253 }
246- }
247-
248- if long_edge == Some ( debouncr:: Edge :: Rising ) {
249- defmt:: trace!(
250- "Power long press in! {}" ,
251- * ctx. resources. dc_power_enabled as u8
252- ) ;
253- if * ctx. resources . dc_power_enabled == DcPowerState :: On {
254- * ctx. resources . dc_power_enabled = DcPowerState :: Off ;
254+ ( Some ( debouncr:: Edge :: Rising ) , None , DcPowerState :: On ) => {
255+ defmt:: info!( "Power button held whilst on." ) ;
256+ * ctx. resources . state_dc_power_enabled = DcPowerState :: Off ;
255257 ctx. resources . led_power . set_low ( ) . unwrap ( ) ;
256258 defmt:: info!( "Power off!" ) ;
257- // TODO: Put system in reset here
258- // TODO: Disable DC PSU here
259+ ctx. resources . pin_sys_reset . set_low ( ) . unwrap ( ) ;
260+ // TODO: Wait for 100ms for chips to stop?
261+ ctx. resources . pin_dc_on . set_low ( ) . unwrap ( ) ;
262+ }
263+ _ => {
264+ // Do nothing
259265 }
260266 }
261267
0 commit comments