Browse Source

Add initial IO support

Kevin Lee 2 years ago
parent
commit
2aff792f17
2 changed files with 135 additions and 37 deletions
  1. 1 5
      Nixie_Firmware_Rust/Cargo.toml
  2. 134 32
      Nixie_Firmware_Rust/src/main.rs

+ 1 - 5
Nixie_Firmware_Rust/Cargo.toml

@@ -24,13 +24,9 @@ cortex-m-semihosting = "0.3.3"
 # features = ["stm32f303", "rt"]
 # version = "0.7.1"
 
-# [dependencies.stm32l4]
-# version = "0.13.0"
-# features = ["stm32l4x2", "rt"]
-
 [dependencies.stm32l4xx-hal]
 version = "0.6.0"
-features = ["stm32l4x2"]
+features = ["stm32l4x2", "rt"]
 
 # this lets you use `cargo fix`!
 # [[bin]]

+ 134 - 32
Nixie_Firmware_Rust/src/main.rs

@@ -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));
+    }
+}