|
@@ -1,61 +1,163 @@
|
|
|
#![cfg_attr(test, allow(unused_imports))]
|
|
|
-
|
|
|
#![cfg_attr(not(test), no_std)]
|
|
|
#![cfg_attr(not(test), no_main)]
|
|
|
|
|
|
// pick a panicking behavior
|
|
|
-// #[cfg(not(test))]
|
|
|
-// use panic_halt as _; // you can put a breakpoint on `rust_begin_unwind` to catch panics
|
|
|
-// use panic_abort as _; // requires nightly
|
|
|
-// use panic_itm as _; // logs messages over ITM; requires ITM support
|
|
|
-// use panic_semihosting as _; // logs messages to the host stderr; requires a debugger
|
|
|
+#[cfg(not(test))]
|
|
|
use core::panic::PanicInfo; // custom panic handler
|
|
|
|
|
|
// use cortex_m::asm;
|
|
|
+use core::{cell::RefCell, ops::DerefMut};
|
|
|
+use cortex_m::{interrupt::free, interrupt::Mutex, peripheral::NVIC};
|
|
|
use cortex_m_rt::entry;
|
|
|
-// use stm32l4::stm32l4x2;
|
|
|
-use stm32l4xx_hal::{prelude::*, pac, rcc};
|
|
|
-use cortex_m_semihosting::{debug, hprintln};
|
|
|
+use cortex_m_semihosting::hprintln;
|
|
|
+// use stm32l4::stm32l4x2::interrupt;
|
|
|
+use stm32l4xx_hal::{
|
|
|
+ delay::Delay,
|
|
|
+ gpio::State,
|
|
|
+ gpio::{Edge, Input, Output, PullUp, PushPull, PA3, PC15},
|
|
|
+ interrupt, pac,
|
|
|
+ prelude::*,
|
|
|
+ rcc,
|
|
|
+ stm32::Interrupt,
|
|
|
+};
|
|
|
+
|
|
|
+static FAULT_INT: Mutex<RefCell<Option<PA3<Input<PullUp>>>>> = Mutex::new(RefCell::new(None));
|
|
|
+static FAULT_LED: Mutex<RefCell<Option<PC15<Output<PushPull>>>>> = Mutex::new(RefCell::new(None));
|
|
|
|
|
|
#[cfg(not(test))]
|
|
|
#[entry]
|
|
|
fn main() -> ! {
|
|
|
-
|
|
|
- // asm::nop(); // To not have main optimize to abort in release mode, remove when you add code
|
|
|
hprintln!("Hello, world!").unwrap();
|
|
|
|
|
|
- let peripherals = pac::Peripherals::take().unwrap();
|
|
|
- let _core = cortex_m::Peripherals::take().unwrap();
|
|
|
+ // Acquire a singleton instance for the chip's peripherals
|
|
|
+ let mut dp = pac::Peripherals::take().unwrap();
|
|
|
+ let cp = pac::CorePeripherals::take().unwrap();
|
|
|
+ // let cp = cortex_m::Peripherals::take().unwrap();
|
|
|
+
|
|
|
+ // Consume the raw peripheral and return a new object that implements a higher level API
|
|
|
+ let mut flash = dp.FLASH.constrain();
|
|
|
+ let mut rcc = dp.RCC.constrain();
|
|
|
+ let mut pwr = dp.PWR.constrain(&mut rcc.apb1r1);
|
|
|
+
|
|
|
+ // Configure clocks to run at maximum frequency off internal oscillator
|
|
|
+ let clocks = rcc
|
|
|
+ .cfgr
|
|
|
+ .pll_source(rcc::PllSource::HSI16)
|
|
|
+ .sysclk(80.mhz())
|
|
|
+ .hclk(80.mhz())
|
|
|
+ .pclk1(80.mhz())
|
|
|
+ .pclk2(80.mhz())
|
|
|
+ .freeze(&mut flash.acr, &mut pwr);
|
|
|
+
|
|
|
+ // Split GPIO peripheral into independent pins and registers
|
|
|
+ // let mut gpiob = dp.GPIOB.split(&mut rcc.ahb2);
|
|
|
+ let mut gpioa = dp.GPIOA.split(&mut rcc.ahb2);
|
|
|
+ let mut gpioc = dp.GPIOC.split(&mut rcc.ahb2);
|
|
|
|
|
|
+ // Configure fault LED output on PC15
|
|
|
+ let fault_led = gpioc.pc15.into_push_pull_output_with_state(
|
|
|
+ &mut gpioc.moder,
|
|
|
+ &mut gpioc.otyper,
|
|
|
+ State::Low,
|
|
|
+ );
|
|
|
|
|
|
- let gpioa = &peripherals.GPIOA;
|
|
|
- gpioa.odr.modify(|_, w| w.odr0().set_bit());
|
|
|
+ // Store fault LED in global static variable as it is accessed in interrupts
|
|
|
+ free(|cs| {
|
|
|
+ FAULT_LED.borrow(cs).replace(Some(fault_led));
|
|
|
+ });
|
|
|
|
|
|
- panic!();
|
|
|
+ // Configure fault input interrupt on PA3
|
|
|
+ let mut fault_int = gpioa
|
|
|
+ .pa3
|
|
|
+ .into_pull_up_input(&mut gpioa.moder, &mut gpioa.pupdr);
|
|
|
+ fault_int.make_interrupt_source(&mut dp.SYSCFG, &mut rcc.apb2);
|
|
|
+ fault_int.enable_interrupt(&mut dp.EXTI);
|
|
|
+ fault_int.trigger_on_edge(&mut dp.EXTI, Edge::FALLING);
|
|
|
+
|
|
|
+ // Configure NVIC mask to enable interrupt source
|
|
|
+ unsafe {
|
|
|
+ NVIC::unmask(Interrupt::EXTI3);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Store fault input in global static variable as it is accessed in interrupt
|
|
|
+ free(|cs| {
|
|
|
+ FAULT_INT.borrow(cs).replace(Some(fault_int));
|
|
|
+ });
|
|
|
+
|
|
|
+ // Start with HV PSU disabled (enable pin on PA2)
|
|
|
+ let mut _hv_en =
|
|
|
+ gpioa
|
|
|
+ .pa2
|
|
|
+ .into_push_pull_output_with_state(&mut gpioa.moder, &mut gpioa.otyper, State::Low);
|
|
|
+
|
|
|
+ // Configure abstract timer that operates off systick timer
|
|
|
+ let mut timer = Delay::new(cp.SYST, clocks);
|
|
|
|
|
|
loop {
|
|
|
- // your code goes here
|
|
|
+ timer.delay_ms(1000_u32);
|
|
|
+ set_fault_led(State::High);
|
|
|
+ timer.delay_ms(1000_u32);
|
|
|
+ set_fault_led(State::Low);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-#[panic_handler]
|
|
|
-#[cfg(not(test))]
|
|
|
-fn panic(_info: &PanicInfo) -> ! {
|
|
|
- hprintln!("Panic!").unwrap();
|
|
|
- loop {}
|
|
|
+fn set_fault_led(on: State) {
|
|
|
+ free(|cs| {
|
|
|
+ let mut led_ref = FAULT_LED.borrow(cs).borrow_mut();
|
|
|
+ if let Some(ref mut led) = led_ref.deref_mut() {
|
|
|
+ match on {
|
|
|
+ State::High => led.set_high().unwrap(),
|
|
|
+ State::Low => led.set_low().unwrap(),
|
|
|
+ };
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
-fn add(a: i32, b: i32) -> i32 {
|
|
|
- a + b
|
|
|
+#[interrupt]
|
|
|
+fn EXTI3() {
|
|
|
+ free(|cs| {
|
|
|
+ let mut nfault_ref = FAULT_INT.borrow(cs).borrow_mut();
|
|
|
+ if let Some(ref mut nfault) = nfault_ref.deref_mut() {
|
|
|
+ if nfault.check_interrupt() {
|
|
|
+ hprintln!("Fault pin interrupt triggered!").unwrap();
|
|
|
+ // nfault.clear_interrupt_pending_bit();
|
|
|
+ panic!();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+#[panic_handler]
|
|
|
+#[cfg(not(test))]
|
|
|
+/// Custom panic handler
|
|
|
+fn panic(info: &PanicInfo) -> ! {
|
|
|
+ if let Some(location) = info.location() {
|
|
|
+ hprintln!(
|
|
|
+ "Panic in file '{}' at line {}",
|
|
|
+ location.file(),
|
|
|
+ location.line()
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ } else {
|
|
|
+ hprintln!("Panic'd!").unwrap();
|
|
|
+ }
|
|
|
+ loop {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
#[cfg(test)]
|
|
|
mod test {
|
|
|
- use super::*;
|
|
|
-
|
|
|
- #[test]
|
|
|
- fn foo() {
|
|
|
- println!("tests work!");
|
|
|
- assert!(2 == add(1,1));
|
|
|
- }
|
|
|
-}
|
|
|
+ use super::*;
|
|
|
+
|
|
|
+ fn add(a: i32, b: i32) -> i32 {
|
|
|
+ a + b
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn foo() {
|
|
|
+ println!("tests work!");
|
|
|
+ assert!(2 == add(1, 1));
|
|
|
+ }
|
|
|
+}
|