Skip to content

Commit 715b6f8

Browse files
authored
Merge pull request #12 from Neotron-Compute/feature/use-rtic
Feature/use rtic
2 parents 6428256 + ade0197 commit 715b6f8

4 files changed

Lines changed: 457 additions & 90 deletions

File tree

Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ cortex-m = "0.7.1"
1212
cortex-m-rt = "0.6.13"
1313
defmt = "0.2.0"
1414
defmt-rtt = "0.2.0"
15+
cortex-m-rtic = "0.5"
1516
panic-probe = { version = "0.2.0", features = ["print-defmt"] }
16-
stm32f0xx-hal = { version = "0.17", features = ["stm32f030x6"] }
17+
stm32f0xx-hal = { version = "0.17", features = ["stm32f031", "rt"] }
18+
1719

1820
[features]
1921
# set logging levels here

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ use defmt_rtt as _; // global logger
66
use panic_probe as _;
77
use stm32f0xx_hal as _; // memory layout // panic handler
88

9+
pub mod monotonic;
10+
911
// same panicking *behavior* as `panic-probe` but doesn't print a panic message
1012
// this prevents the panic message being printed *twice* when `defmt::panic` is invoked
1113
#[defmt::panic_handler]

src/main.rs

Lines changed: 129 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -3,108 +3,148 @@
33

44
use neotron_bmc as _;
55

6-
use hal::{i2c, pac, prelude::*, serial, spi};
7-
use stm32f0xx_hal as hal;
6+
use neotron_bmc::monotonic::{Instant, Tim3Monotonic, U16Ext};
87

9-
static VERSION: &'static str = include_str!(concat!(env!("OUT_DIR"), "/version.txt"));
10-
11-
/// Holds all the I/O pins in our system
12-
#[allow(unused)]
13-
struct Pins {
14-
// spi_clk: hal::gpio::gpioa::PA5<hal::gpio::Alternate<hal::gpio::AF0>>,
15-
// spi_cipo: hal::gpio::gpioa::PA6<hal::gpio::Alternate<hal::gpio::AF0>>,
16-
// spi_copi: hal::gpio::gpioa::PA7<hal::gpio::Alternate<hal::gpio::AF0>>,
17-
// i2c_scl: hal::gpio::gpiob::PB6<hal::gpio::Alternate<hal::gpio::AF4>>,
18-
// i2c_sda: hal::gpio::gpiob::PB7<hal::gpio::Alternate<hal::gpio::AF4>>,
19-
uart_tx: hal::gpio::gpioa::PA9<hal::gpio::Alternate<hal::gpio::AF1>>,
20-
uart_rx: hal::gpio::gpioa::PA10<hal::gpio::Alternate<hal::gpio::AF1>>,
21-
uart_cts: hal::gpio::gpioa::PA11<hal::gpio::Alternate<hal::gpio::AF1>>,
22-
uart_rts: hal::gpio::gpioa::PA12<hal::gpio::Alternate<hal::gpio::AF1>>,
23-
led_power: hal::gpio::gpiob::PB0<hal::gpio::Output<hal::gpio::PushPull>>,
24-
led_status: hal::gpio::gpiob::PB1<hal::gpio::Output<hal::gpio::PushPull>>,
25-
}
26-
27-
#[cortex_m_rt::entry]
28-
fn main() -> ! {
29-
defmt::info!("Neotron BMC version {:?} booting", VERSION);
30-
31-
let p = pac::Peripherals::take().unwrap();
32-
33-
// Configure the clocks.
34-
// We have no external crystal, and instead run from the High Speed Internal Oscillator.
35-
let mut flash = p.FLASH;
36-
let mut rcc = p
37-
.RCC
38-
.configure()
39-
.hclk(48.mhz())
40-
.pclk(48.mhz())
41-
.sysclk(48.mhz())
42-
.freeze(&mut flash);
43-
44-
defmt::info!("Clocks are clocked");
45-
46-
let gpioa = p.GPIOA.split(&mut rcc);
47-
let gpiob = p.GPIOB.split(&mut rcc);
48-
49-
let mut pins: Pins = cortex_m::interrupt::free(move |cs| {
50-
Pins {
51-
// SPI pins
52-
// spi_clk: gpioa.pa5.into_alternate_af0(cs),
53-
// spi_cipo: gpioa.pa6.into_alternate_af0(cs),
54-
// spi_copi: gpioa.pa7.into_alternate_af0(cs),
55-
// I²C pins
56-
// i2c_scl: gpiob.pb6.into_alternate_af4(cs),
57-
// i2c_sda: gpiob.pb7.into_alternate_af4(cs),
58-
// USART pins
59-
uart_tx: gpioa.pa9.into_alternate_af1(cs),
60-
uart_rx: gpioa.pa10.into_alternate_af1(cs),
61-
uart_cts: gpioa.pa11.into_alternate_af1(cs),
62-
uart_rts: gpioa.pa12.into_alternate_af1(cs),
63-
// LED pins
64-
led_power: gpiob.pb0.into_push_pull_output(cs),
65-
led_status: gpiob.pb1.into_push_pull_output(cs),
66-
}
67-
});
8+
use cortex_m_rt::exception;
689

69-
// // Configure UART. Pick some default baud rate - we can change it later
70-
let mut serial = serial::Serial::usart1(
71-
p.USART1,
72-
(pins.uart_tx, pins.uart_rx),
73-
115_200.bps(),
74-
&mut rcc,
75-
);
10+
use rtic::app;
7611

77-
use core::fmt::Write;
12+
use stm32f0xx_hal::{
13+
gpio::gpioa::{PA10, PA11, PA12, PA9},
14+
gpio::gpiob::{PB0, PB1},
15+
gpio::{Alternate, Output, PushPull, AF1},
16+
pac,
17+
prelude::*,
18+
serial,
19+
};
7820

79-
loop {
80-
serial.write_str("Hello, world!\r\n").unwrap();
21+
use cortex_m::interrupt::free as disable_interrupts;
8122

82-
defmt::info!("Off Off");
83-
84-
pins.led_power.set_low().unwrap();
85-
pins.led_status.set_low().unwrap();
86-
87-
cortex_m::asm::delay(6_000_000);
23+
static VERSION: &'static str = include_str!(concat!(env!("OUT_DIR"), "/version.txt"));
8824

89-
defmt::info!("Off On");
25+
const PERIOD_MS: u16 = 1000;
9026

91-
pins.led_power.set_low().unwrap();
92-
pins.led_status.set_high().unwrap();
27+
#[app(device = crate::pac, peripherals = true, monotonic = crate::Tim3Monotonic)]
28+
const APP: () = {
29+
struct Resources {
30+
uart_cts: PA11<Alternate<AF1>>,
31+
uart_rts: PA12<Alternate<AF1>>,
32+
led_power: PB0<Output<PushPull>>,
33+
led_status: PB1<Output<PushPull>>,
34+
serial: serial::Serial<pac::USART1, PA9<Alternate<AF1>>, PA10<Alternate<AF1>>>,
35+
}
9336

94-
cortex_m::asm::delay(6_000_000);
37+
#[init(spawn = [led_status_blink])]
38+
fn init(ctx: init::Context) -> init::LateResources {
39+
defmt::info!("Neotron BMC version {:?} booting", VERSION);
40+
41+
let dp: pac::Peripherals = ctx.device;
42+
43+
let mut flash = dp.FLASH;
44+
let mut rcc = dp
45+
.RCC
46+
.configure()
47+
.hclk(48.mhz())
48+
.pclk(48.mhz())
49+
.sysclk(48.mhz())
50+
.freeze(&mut flash);
51+
52+
defmt::info!("Configuring TIM3 at 7.8125 kHz...");
53+
crate::Tim3Monotonic::initialize(dp.TIM3);
54+
55+
defmt::info!("Creating pins...");
56+
let gpioa = dp.GPIOA.split(&mut rcc);
57+
let gpiob = dp.GPIOB.split(&mut rcc);
58+
let (uart_tx, uart_rx, uart_cts, uart_rts, mut led_power, led_status) =
59+
disable_interrupts(|cs| {
60+
(
61+
gpioa.pa9.into_alternate_af1(cs),
62+
gpioa.pa10.into_alternate_af1(cs),
63+
gpioa.pa11.into_alternate_af1(cs),
64+
gpioa.pa12.into_alternate_af1(cs),
65+
gpiob.pb0.into_push_pull_output(cs),
66+
gpiob.pb1.into_push_pull_output(cs),
67+
)
68+
});
69+
70+
defmt::info!("Creating UART...");
71+
72+
let mut serial =
73+
serial::Serial::usart1(dp.USART1, (uart_tx, uart_rx), 115_200.bps(), &mut rcc);
74+
75+
serial.listen(serial::Event::Rxne);
76+
77+
ctx.spawn.led_status_blink().unwrap();
78+
79+
led_power.set_high().unwrap();
80+
81+
defmt::info!("Init complete!");
82+
83+
init::LateResources {
84+
serial,
85+
uart_cts,
86+
uart_rts,
87+
led_power,
88+
led_status,
89+
}
90+
}
9591

96-
defmt::info!("On Off");
92+
#[idle(resources = [])]
93+
fn idle(_: idle::Context) -> ! {
94+
defmt::info!("Idle is running...");
95+
loop {
96+
cortex_m::asm::wfi();
97+
defmt::info!("It is now {}", crate::Instant::now().counts());
98+
}
99+
}
97100

98-
pins.led_power.set_high().unwrap();
99-
pins.led_status.set_low().unwrap();
101+
#[task(binds = USART1, resources=[serial])]
102+
fn usart1_interrupt(ctx: usart1_interrupt::Context) {
103+
// Reading the register clears the RX-Not-Empty-Interrupt flag.
104+
match ctx.resources.serial.read() {
105+
Ok(b) => {
106+
defmt::info!("<< UART {:x}", b);
107+
}
108+
Err(_) => {
109+
defmt::warn!("<< UART None?");
110+
}
111+
}
112+
}
100113

101-
cortex_m::asm::delay(6_000_000);
114+
#[task(schedule = [led_status_blink], resources = [led_status])]
115+
fn led_status_blink(ctx: led_status_blink::Context) {
116+
// Use the safe local `static mut` of RTIC
117+
static mut LED_STATE: bool = false;
102118

103-
defmt::info!("On On");
119+
defmt::info!("blink time {}", ctx.scheduled.counts());
104120

105-
pins.led_power.set_high().unwrap();
106-
pins.led_status.set_high().unwrap();
121+
if *LED_STATE {
122+
ctx.resources.led_status.set_low().unwrap();
123+
*LED_STATE = false;
124+
} else {
125+
ctx.resources.led_status.set_high().unwrap();
126+
*LED_STATE = true;
127+
}
128+
let next = ctx.scheduled + PERIOD_MS.millis();
129+
defmt::info!("Next blink at {}", next.counts());
130+
ctx.schedule.led_status_blink(next).unwrap();
131+
}
107132

108-
cortex_m::asm::delay(6_000_000);
133+
// Let it use the USB interrupt as a generic software interrupt.
134+
extern "C" {
135+
fn USB();
109136
}
137+
};
138+
139+
#[exception]
140+
unsafe fn DefaultHandler(value: i16) {
141+
defmt::panic!("DefaultHandler({})", value);
110142
}
143+
144+
// SPI pins
145+
// spi_clk: gpioa.pa5.into_alternate_af0(cs),
146+
// spi_cipo: gpioa.pa6.into_alternate_af0(cs),
147+
// spi_copi: gpioa.pa7.into_alternate_af0(cs),
148+
// I²C pins
149+
// i2c_scl: gpiob.pb6.into_alternate_af4(cs),
150+
// i2c_sda: gpiob.pb7.into_alternate_af4(cs),

0 commit comments

Comments
 (0)