Skip to content

Commit c6f2adb

Browse files
committed
Control the DC_ON and SYS_nRESET lines.
1 parent 2bc4ceb commit c6f2adb

2 files changed

Lines changed: 57 additions & 51 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ The NBMC firmware is designed to run on an ST Micro STM32F0 (STM32F031K6T6) micr
3232
| Pin | Name | Signal | Function |
3333
| :--- | :--- | :---------- | :------------------------------------------- |
3434
| 02 | PF0 | BUTTON_nPWR | Power Button Input (active low) |
35-
| 03 | PF1 | HOST_nRST | Reset Output to reset the rest of the system |
35+
| 03 | PF1 | BUTTON_nRST | Reset Button Input (active low) |
3636
| 06 | PA0 | MON_3V3 | 3.3V rail monitor Input (1.65V nominal) |
3737
| 07 | PA1 | MON_5V | 5.0V rail monitor Input (1.65V nominal) |
3838
| 08 | PA2 | nSYS_RESET | System Reset Output (active low) |

src/main.rs

Lines changed: 56 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use cortex_m::interrupt::free as disable_interrupts;
1212
use rtic::app;
1313
use 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

Comments
 (0)