|
3 | 3 |
|
4 | 4 | use neotron_bmc as _; |
5 | 5 |
|
6 | | -use hal::{i2c, pac, prelude::*, serial, spi}; |
7 | | -use stm32f0xx_hal as hal; |
| 6 | +use neotron_bmc::monotonic::{Instant, Tim3Monotonic, U16Ext}; |
8 | 7 |
|
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; |
68 | 9 |
|
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; |
76 | 11 |
|
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 | +}; |
78 | 20 |
|
79 | | - loop { |
80 | | - serial.write_str("Hello, world!\r\n").unwrap(); |
| 21 | +use cortex_m::interrupt::free as disable_interrupts; |
81 | 22 |
|
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")); |
88 | 24 |
|
89 | | - defmt::info!("Off On"); |
| 25 | +const PERIOD_MS: u16 = 1000; |
90 | 26 |
|
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 | + } |
93 | 36 |
|
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 | + } |
95 | 91 |
|
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 | + } |
97 | 100 |
|
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 | + } |
100 | 113 |
|
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; |
102 | 118 |
|
103 | | - defmt::info!("On On"); |
| 119 | + defmt::info!("blink time {}", ctx.scheduled.counts()); |
104 | 120 |
|
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 | + } |
107 | 132 |
|
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(); |
109 | 136 | } |
| 137 | +}; |
| 138 | + |
| 139 | +#[exception] |
| 140 | +unsafe fn DefaultHandler(value: i16) { |
| 141 | + defmt::panic!("DefaultHandler({})", value); |
110 | 142 | } |
| 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