Resolve "Setup basic scheduler"
This commit is contained in:
parent
8b55888ad0
commit
3af8031387
26
Cargo.toml
26
Cargo.toml
@ -6,34 +6,17 @@ name = "fan_monitor"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
embedded-hal = "0.2.6"
|
||||||
|
nb = "0.1.2"
|
||||||
cortex-m = "0.6.0"
|
cortex-m = "0.6.0"
|
||||||
cortex-m-rt = "0.6.10"
|
cortex-m-rt = "0.6.10"
|
||||||
cortex-m-semihosting = "0.3.3"
|
cortex-m-semihosting = "0.3.3"
|
||||||
panic-halt = "0.2.0"
|
panic-halt = "0.2.0"
|
||||||
embedded-hal = "0.2.3"
|
|
||||||
hd44780-driver = "0.3.0"
|
hd44780-driver = "0.3.0"
|
||||||
nb = "0.1.1"
|
|
||||||
|
|
||||||
[dependencies.stm32f1]
|
|
||||||
version = "0.8.0"
|
|
||||||
features = ["stm32f103", "rt"]
|
|
||||||
|
|
||||||
[dependencies.stm32f1xx-hal]
|
[dependencies.stm32f1xx-hal]
|
||||||
version = "0.4.0"
|
version = "0.7.0"
|
||||||
features = ["stm32f103", "rt"]
|
features = ["stm32f103", "rt", "medium"]
|
||||||
|
|
||||||
# Uncomment for the panic example.
|
|
||||||
# panic-itm = "0.4.1"
|
|
||||||
|
|
||||||
# Uncomment for the allocator example.
|
|
||||||
# alloc-cortex-m = "0.3.5"
|
|
||||||
|
|
||||||
# Uncomment for the device example.
|
|
||||||
# Update `memory.x`, set target to `thumbv7em-none-eabihf` in `.cargo/config`,
|
|
||||||
# and then use `cargo build --examples device` to build it.
|
|
||||||
# [dependencies.stm32f3]
|
|
||||||
# features = ["stm32f303", "rt"]
|
|
||||||
# version = "0.7.1"
|
|
||||||
|
|
||||||
# this lets you use `cargo fix`!
|
# this lets you use `cargo fix`!
|
||||||
[[bin]]
|
[[bin]]
|
||||||
@ -45,3 +28,4 @@ bench = false
|
|||||||
codegen-units = 1 # better optimizations
|
codegen-units = 1 # better optimizations
|
||||||
debug = true # symbols are nice and they don't increase the size on Flash
|
debug = true # symbols are nice and they don't increase the size on Flash
|
||||||
lto = true # better optimizations
|
lto = true # better optimizations
|
||||||
|
|
||||||
|
|||||||
40
openocd.gdb
Normal file
40
openocd.gdb
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
target extended-remote :3333
|
||||||
|
|
||||||
|
# print demangled symbols
|
||||||
|
set print asm-demangle on
|
||||||
|
|
||||||
|
# set backtrace limit to not have infinite backtrace loops
|
||||||
|
set backtrace limit 32
|
||||||
|
|
||||||
|
# detect unhandled exceptions, hard faults and panics
|
||||||
|
break DefaultHandler
|
||||||
|
break HardFault
|
||||||
|
break rust_begin_unwind
|
||||||
|
# # run the next few lines so the panic message is printed immediately
|
||||||
|
# # the number needs to be adjusted for your panic handler
|
||||||
|
# commands $bpnum
|
||||||
|
# next 4
|
||||||
|
# end
|
||||||
|
|
||||||
|
# *try* to stop at the user entry point (it might be gone due to inlining)
|
||||||
|
break main
|
||||||
|
|
||||||
|
monitor arm semihosting enable
|
||||||
|
|
||||||
|
# # send captured ITM to the file itm.fifo
|
||||||
|
# # (the microcontroller SWO pin must be connected to the programmer SWO pin)
|
||||||
|
# # 8000000 must match the core clock frequency
|
||||||
|
# monitor tpiu config internal itm.txt uart off 8000000
|
||||||
|
|
||||||
|
# # OR: make the microcontroller SWO pin output compatible with UART (8N1)
|
||||||
|
# # 8000000 must match the core clock frequency
|
||||||
|
# # 2000000 is the frequency of the SWO pin
|
||||||
|
# monitor tpiu config external uart off 8000000 2000000
|
||||||
|
|
||||||
|
# # enable ITM port 0
|
||||||
|
# monitor itm port 0 on
|
||||||
|
|
||||||
|
load
|
||||||
|
|
||||||
|
# start the process but immediately halt the processor
|
||||||
|
stepi
|
||||||
110
src/lcd_gui.rs
Normal file
110
src/lcd_gui.rs
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
use core::{sync::atomic::{AtomicBool, Ordering}};
|
||||||
|
|
||||||
|
use embedded_hal::{
|
||||||
|
//digital::v1_compat::OldOutputPin,
|
||||||
|
digital::v2::OutputPin,
|
||||||
|
Qei,
|
||||||
|
blocking::delay::{DelayUs, DelayMs},
|
||||||
|
};
|
||||||
|
|
||||||
|
use hd44780_driver::{
|
||||||
|
HD44780,
|
||||||
|
display_mode::DisplayMode,
|
||||||
|
bus::DataBus,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct LCDGui<L, Q, B>
|
||||||
|
where
|
||||||
|
L: LCDScreen,
|
||||||
|
Q: Qei<Count = u16>,
|
||||||
|
B: OutputPin,
|
||||||
|
{
|
||||||
|
lcd: L,
|
||||||
|
qei: Q,
|
||||||
|
button: &'static AtomicBool,
|
||||||
|
backlight: Option<B>,
|
||||||
|
count: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<L, Q, B> LCDGui<L, Q, B>
|
||||||
|
where
|
||||||
|
L: LCDScreen,
|
||||||
|
Q: Qei<Count = u16>,
|
||||||
|
B: OutputPin,
|
||||||
|
{
|
||||||
|
|
||||||
|
pub fn new(lcd: L, qei: Q, button: &'static AtomicBool, backlight: Option<B>)
|
||||||
|
-> LCDGui<L, Q, B> {
|
||||||
|
use hd44780_driver::{Cursor, CursorBlink, Display};
|
||||||
|
|
||||||
|
let count = qei.count();
|
||||||
|
let mut gui = LCDGui {lcd, qei, button, backlight, count};
|
||||||
|
|
||||||
|
if let Some(bl) = &mut gui.backlight { let _ = bl.set_high(); };
|
||||||
|
|
||||||
|
gui.lcd.reset();
|
||||||
|
gui.lcd.clear();
|
||||||
|
gui.lcd.set_display_mode(
|
||||||
|
DisplayMode {
|
||||||
|
display: Display::On,
|
||||||
|
cursor_visibility: Cursor::Visible,
|
||||||
|
cursor_blink: CursorBlink::On,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
let _ = gui.lcd.write_str("Hello world!");
|
||||||
|
|
||||||
|
gui
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run(&mut self) -> ! {
|
||||||
|
loop {
|
||||||
|
//TODO deduplicate button detection
|
||||||
|
if self.button.swap(false, Ordering::AcqRel) {
|
||||||
|
self.lcd.write_str("paf").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.count != self.qei.count() {
|
||||||
|
self.count = self.qei.count();
|
||||||
|
self.lcd.set_cursor_pos(0x40);
|
||||||
|
self.lcd.write_str(" ").unwrap();
|
||||||
|
self.lcd.set_cursor_pos(0x40);
|
||||||
|
write!(self.lcd, "{}", self.qei.count()/2).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
// put device in sleep mode until next interrupt (button or timer)
|
||||||
|
cortex_m::asm::wfi();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait LCDScreen: core::fmt::Write {
|
||||||
|
|
||||||
|
fn reset(&mut self);
|
||||||
|
fn clear(&mut self);
|
||||||
|
fn set_display_mode(&mut self, mode: DisplayMode);
|
||||||
|
fn set_cursor_pos(&mut self, positions: u8);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D, DB> LCDScreen for HD44780<D, DB>
|
||||||
|
where
|
||||||
|
D: DelayUs<u16> + DelayMs<u8>,
|
||||||
|
DB: DataBus,
|
||||||
|
{
|
||||||
|
|
||||||
|
fn reset(&mut self) {
|
||||||
|
self.reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clear(&mut self) {
|
||||||
|
self.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_display_mode(&mut self, mode: DisplayMode) {
|
||||||
|
self.set_display_mode(mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_cursor_pos(&mut self, position: u8) {
|
||||||
|
self.set_cursor_pos(position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
230
src/main.rs
230
src/main.rs
@ -1,11 +1,15 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
|
mod lcd_gui;
|
||||||
|
|
||||||
|
use lcd_gui::LCDGui;
|
||||||
|
|
||||||
extern crate panic_halt;
|
extern crate panic_halt;
|
||||||
|
|
||||||
use core::{
|
use core::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
fmt::Write,
|
sync::atomic::{AtomicBool, Ordering},
|
||||||
};
|
};
|
||||||
|
|
||||||
use cortex_m::interrupt::Mutex;
|
use cortex_m::interrupt::Mutex;
|
||||||
@ -17,63 +21,108 @@ use embedded_hal::digital::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use stm32f1xx_hal::{
|
use stm32f1xx_hal::{
|
||||||
delay::Delay,
|
gpio::*,
|
||||||
gpio::{gpioc, gpiob, Output, PushPull},
|
|
||||||
pac,
|
pac,
|
||||||
pac::{interrupt, Interrupt},
|
pac::{interrupt, Interrupt, EXTI},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
timer::{Event, Timer},
|
timer::{Timer, CountDownTimer, Event},
|
||||||
qei::Qei,
|
qei::{QeiOptions, SlaveMode},
|
||||||
|
rtc::Rtc,
|
||||||
};
|
};
|
||||||
|
|
||||||
use hd44780_driver::{Cursor, CursorBlink, Display, DisplayMode, HD44780};
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
/* system config */
|
||||||
|
|
||||||
|
const GUI_TICK_SEC: f32 = 0.2;
|
||||||
|
const HEARTBEAT_SEC: f32 = 1.0;
|
||||||
|
|
||||||
|
const TEMPS_TICK_SEC: u32 = 5;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
/* interrupt variables */
|
||||||
|
|
||||||
|
// tick/heartbeat timer
|
||||||
static PCB_LED: Mutex<RefCell<Option<gpioc::PC13<Output<PushPull>>>>>
|
static PCB_LED: Mutex<RefCell<Option<gpioc::PC13<Output<PushPull>>>>>
|
||||||
= Mutex::new(RefCell::new(None));
|
= Mutex::new(RefCell::new(None));
|
||||||
|
static TICK_TIMER: Mutex<RefCell<Option<CountDownTimer<pac::TIM2>>>>
|
||||||
|
= Mutex::new(RefCell::new(None));
|
||||||
|
|
||||||
|
// button interrupt
|
||||||
|
static BUTTON_PIN: Mutex<RefCell<Option<gpiob::PB8<Input<PullUp>>>>>
|
||||||
|
= Mutex::new(RefCell::new(None));
|
||||||
|
static BUTTON_FLAG: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
||||||
|
// temps interrupt
|
||||||
static RED_LED: Mutex<RefCell<Option<gpiob::PB11<Output<PushPull>>>>>
|
static RED_LED: Mutex<RefCell<Option<gpiob::PB11<Output<PushPull>>>>>
|
||||||
= Mutex::new(RefCell::new(None));
|
= Mutex::new(RefCell::new(None));
|
||||||
static TIMER: Mutex<RefCell<Option<Timer<pac::TIM2>>>> = Mutex::new(RefCell::new(None));
|
static RTC: Mutex<RefCell<Option<Rtc>>> = Mutex::new(RefCell::new(None));
|
||||||
static TIMER2: Mutex<RefCell<Option<Timer<pac::TIM3>>>> = Mutex::new(RefCell::new(None));
|
static G_EXTI: Mutex<RefCell<Option<EXTI>>> = Mutex::new(RefCell::new(None));
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
/* interrupt service routines */
|
||||||
#[interrupt]
|
#[interrupt]
|
||||||
fn TIM2() {
|
fn TIM2() {
|
||||||
|
|
||||||
|
static mut TICK_DIVIDER: u32 = 0;
|
||||||
|
|
||||||
|
cortex_m::interrupt::free(|cs| {
|
||||||
|
let _ = TICK_TIMER.borrow(cs).borrow_mut().as_mut().unwrap().clear_update_interrupt_flag();
|
||||||
|
});
|
||||||
|
|
||||||
|
*TICK_DIVIDER += 1;
|
||||||
|
if *TICK_DIVIDER >= (HEARTBEAT_SEC / GUI_TICK_SEC) as u32 {
|
||||||
|
*TICK_DIVIDER = 0;
|
||||||
cortex_m::interrupt::free(|cs| {
|
cortex_m::interrupt::free(|cs| {
|
||||||
let _ = PCB_LED.borrow(cs).borrow_mut().as_mut().unwrap().toggle();
|
let _ = PCB_LED.borrow(cs).borrow_mut().as_mut().unwrap().toggle();
|
||||||
});
|
});
|
||||||
|
}
|
||||||
cortex_m::interrupt::free(|cs| {
|
|
||||||
let _ = TIMER.borrow(cs).borrow_mut().as_mut().unwrap().clear_update_interrupt_flag();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[interrupt]
|
#[interrupt]
|
||||||
fn TIM3() {
|
fn EXTI9_5() {
|
||||||
|
|
||||||
|
cortex_m::interrupt::free(|cs| {
|
||||||
|
let _ = BUTTON_PIN.borrow(cs).borrow_mut().as_mut().unwrap().clear_interrupt_pending_bit();
|
||||||
|
});
|
||||||
|
|
||||||
|
BUTTON_FLAG.store(true, Ordering::Release);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[interrupt]
|
||||||
|
fn RTCALARM() {
|
||||||
|
|
||||||
|
cortex_m::interrupt::free(|cs| {
|
||||||
|
let _ = G_EXTI.borrow(cs).borrow_mut().as_mut().unwrap().pr.write(|w| w.pr17().set_bit());
|
||||||
|
});
|
||||||
|
|
||||||
|
cortex_m::interrupt::free(|cs| {
|
||||||
|
let mut rtc = RTC.borrow(cs).borrow_mut();
|
||||||
|
let time = rtc.as_mut().unwrap().current_time();
|
||||||
|
rtc.as_mut().unwrap().set_alarm(time + TEMPS_TICK_SEC); //also clears the flag
|
||||||
|
});
|
||||||
|
|
||||||
cortex_m::interrupt::free(|cs| {
|
cortex_m::interrupt::free(|cs| {
|
||||||
let _ = RED_LED.borrow(cs).borrow_mut().as_mut().unwrap().toggle();
|
let _ = RED_LED.borrow(cs).borrow_mut().as_mut().unwrap().toggle();
|
||||||
});
|
});
|
||||||
|
|
||||||
cortex_m::interrupt::free(|cs| {
|
|
||||||
let _ = TIMER2.borrow(cs).borrow_mut().as_mut().unwrap().clear_update_interrupt_flag();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
/* main function */
|
||||||
#[entry]
|
#[entry]
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
// Get access to the core peripherals from the cortex-m crate
|
|
||||||
let cp = cortex_m::Peripherals::take().unwrap();
|
|
||||||
// Get access to the device specific peripherals from the peripheral access crate
|
|
||||||
let dp = pac::Peripherals::take().unwrap();
|
|
||||||
|
|
||||||
// Take ownership over the raw flash and rcc devices and convert them into the corresponding
|
/* setup */
|
||||||
// HAL structs
|
|
||||||
let mut flash = dp.FLASH.constrain();
|
// basic setup
|
||||||
|
let mut cp = cortex_m::Peripherals::take().unwrap();
|
||||||
|
let mut dp = pac::Peripherals::take().unwrap();
|
||||||
|
|
||||||
|
// clocks config
|
||||||
let mut rcc = dp.RCC.constrain();
|
let mut rcc = dp.RCC.constrain();
|
||||||
|
let mut flash = dp.FLASH.constrain();
|
||||||
// Freeze the configuration of all the clocks in the system and store the frozen frequencies in
|
let clocks = rcc.cfgr
|
||||||
// `clocks`
|
.use_hse(8.mhz())
|
||||||
let clocks = rcc.cfgr.freeze(&mut flash.acr);
|
.freeze(&mut flash.acr);
|
||||||
|
|
||||||
// GPIOs
|
// GPIOs
|
||||||
let mut gpioa = dp.GPIOA.split(&mut rcc.apb2);
|
let mut gpioa = dp.GPIOA.split(&mut rcc.apb2);
|
||||||
@ -83,45 +132,49 @@ fn main() -> ! {
|
|||||||
// setup LED
|
// setup LED
|
||||||
let mut led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh);
|
let mut led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh);
|
||||||
let _ = led.set_high();
|
let _ = led.set_high();
|
||||||
|
|
||||||
cortex_m::interrupt::free(|cs| {
|
cortex_m::interrupt::free(|cs| {
|
||||||
PCB_LED.borrow(cs).borrow_mut().replace(led)
|
PCB_LED.borrow(cs).borrow_mut().replace(led)
|
||||||
});
|
});
|
||||||
|
|
||||||
// Configure the syst timer to trigger an update every second
|
// Configure the timer 2 as tick timer
|
||||||
let mut timer = Timer::tim2(dp.TIM2, 1.hz(), clocks, &mut rcc.apb1);
|
let mut timer = Timer::tim2(dp.TIM2, &clocks, &mut rcc.apb1)
|
||||||
|
.start_count_down(((1.0/GUI_TICK_SEC) as u32).hz());
|
||||||
timer.listen(Event::Update);
|
timer.listen(Event::Update);
|
||||||
|
|
||||||
cortex_m::interrupt::free(|cs| {
|
cortex_m::interrupt::free(|cs| {
|
||||||
TIMER.borrow(cs).borrow_mut().replace(timer)
|
TICK_TIMER.borrow(cs).borrow_mut().replace(timer)
|
||||||
});
|
});
|
||||||
|
|
||||||
// setup LED
|
// setup LED
|
||||||
let mut led = gpiob.pb11.into_push_pull_output(&mut gpiob.crh);
|
let mut red_led = gpiob.pb11.into_push_pull_output(&mut gpiob.crh);
|
||||||
let _ = led.set_high();
|
let _ = red_led.set_high();
|
||||||
|
|
||||||
cortex_m::interrupt::free(|cs| {
|
cortex_m::interrupt::free(|cs| {
|
||||||
RED_LED.borrow(cs).borrow_mut().replace(led)
|
RED_LED.borrow(cs).borrow_mut().replace(red_led)
|
||||||
});
|
});
|
||||||
|
|
||||||
// Configure the syst timer to trigger an update every second
|
// set EXTI 17 (see note in 18.4.2, in short : needed for rtc ISR to trigger)
|
||||||
let mut timer = Timer::tim3(dp.TIM3, 5.hz(), clocks, &mut rcc.apb1);
|
dp.EXTI.ftsr.write(|w| w.tr17().set_bit());
|
||||||
timer.listen(Event::Update);
|
dp.EXTI.imr.write(|w| w.mr17().set_bit());
|
||||||
cortex_m::interrupt::free(|cs| {
|
|
||||||
TIMER2.borrow(cs).borrow_mut().replace(timer)
|
|
||||||
});
|
|
||||||
|
|
||||||
// Enable timer interrupts
|
// setup RTC
|
||||||
unsafe {
|
let mut backup_domain = rcc.bkp.constrain(dp.BKP, &mut rcc.apb1, &mut dp.PWR);
|
||||||
cortex_m::peripheral::NVIC::unmask(Interrupt::TIM2);
|
let mut rtc = Rtc::rtc(dp.RTC, &mut backup_domain);
|
||||||
cortex_m::peripheral::NVIC::unmask(Interrupt::TIM3);
|
rtc.set_alarm(rtc.current_time() + TEMPS_TICK_SEC);
|
||||||
}
|
rtc.listen_alarm();
|
||||||
|
|
||||||
|
cortex_m::interrupt::free(|cs| {
|
||||||
|
RTC.borrow(cs).borrow_mut().replace(rtc)
|
||||||
|
});
|
||||||
|
|
||||||
let mut afio = dp.AFIO.constrain(&mut rcc.apb2);
|
let mut afio = dp.AFIO.constrain(&mut rcc.apb2);
|
||||||
|
|
||||||
// Setup display
|
// Setup display
|
||||||
let mut lcd = {
|
let mut gui = {
|
||||||
|
use stm32f1xx_hal::{gpio::*, delay::Delay};
|
||||||
|
|
||||||
// Set backlight
|
use hd44780_driver::HD44780;
|
||||||
let mut backlight_pin = gpiob.pb9.into_push_pull_output(&mut gpiob.crh);
|
|
||||||
let _ = backlight_pin.set_high();
|
|
||||||
|
|
||||||
// Disable JTAG to free pins
|
// Disable JTAG to free pins
|
||||||
let (d3_pin, d5_pin, d7_pin) = afio.mapr.disable_jtag(gpioa.pa15, gpiob.pb3, gpiob.pb4);
|
let (d3_pin, d5_pin, d7_pin) = afio.mapr.disable_jtag(gpioa.pa15, gpiob.pb3, gpiob.pb4);
|
||||||
@ -140,9 +193,9 @@ fn main() -> ! {
|
|||||||
|
|
||||||
// Force write mode
|
// Force write mode
|
||||||
let mut rw_pin = gpioa.pa9.into_push_pull_output(&mut gpioa.crh);
|
let mut rw_pin = gpioa.pa9.into_push_pull_output(&mut gpioa.crh);
|
||||||
rw_pin.set_low();
|
rw_pin.set_low().unwrap();
|
||||||
|
|
||||||
HD44780::new_8bit(
|
let lcd = HD44780::new_8bit(
|
||||||
OldOutputPin::new(rs_pin),
|
OldOutputPin::new(rs_pin),
|
||||||
OldOutputPin::new(en_pin),
|
OldOutputPin::new(en_pin),
|
||||||
OldOutputPin::new(d0_pin),
|
OldOutputPin::new(d0_pin),
|
||||||
@ -154,39 +207,56 @@ fn main() -> ! {
|
|||||||
OldOutputPin::new(d6_pin),
|
OldOutputPin::new(d6_pin),
|
||||||
OldOutputPin::new(d7_pin),
|
OldOutputPin::new(d7_pin),
|
||||||
Delay::new(cp.SYST, clocks)
|
Delay::new(cp.SYST, clocks)
|
||||||
)};
|
);
|
||||||
|
|
||||||
|
// setup button (interrupt)
|
||||||
|
let mut but_pin = gpiob.pb8.into_pull_up_input(&mut gpiob.crh);
|
||||||
|
but_pin.make_interrupt_source(&mut afio);
|
||||||
|
but_pin.trigger_on_edge(&dp.EXTI, Edge::RISING);
|
||||||
|
but_pin.enable_interrupt(&dp.EXTI);
|
||||||
|
|
||||||
|
cortex_m::interrupt::free(|cs| {
|
||||||
|
BUTTON_PIN.borrow(cs).borrow_mut().replace(but_pin);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set backlight
|
||||||
|
let backlight_pin = gpiob.pb9.into_push_pull_output(&mut gpiob.crh);
|
||||||
|
|
||||||
// setup encoder
|
// setup encoder
|
||||||
let enc = Qei::tim4(dp.TIM4, (gpiob.pb6, gpiob.pb7), &mut afio.mapr, &mut rcc.apb1);
|
let enc = Timer::tim4(dp.TIM4, &clocks, &mut rcc.apb1)
|
||||||
|
.qei((gpiob.pb6, gpiob.pb7), &mut afio.mapr,
|
||||||
|
QeiOptions {
|
||||||
|
slave_mode:SlaveMode::EncoderMode2,
|
||||||
|
auto_reload_value: 200
|
||||||
|
});
|
||||||
|
|
||||||
lcd.reset();
|
LCDGui::new(lcd, enc, &BUTTON_FLAG, Some(backlight_pin))
|
||||||
lcd.clear();
|
};
|
||||||
lcd.set_display_mode(
|
|
||||||
DisplayMode {
|
|
||||||
display: Display::On,
|
|
||||||
cursor_visibility: Cursor::Visible,
|
|
||||||
cursor_blink: CursorBlink::On,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
let _ = lcd.write_str("Hello world!");
|
|
||||||
|
|
||||||
lcd.set_cursor_pos(0x40);
|
let exti = dp.EXTI;
|
||||||
write!(lcd, "{}", enc.count()/4).unwrap();
|
cortex_m::interrupt::free(|cs| {
|
||||||
let mut old_count = enc.count();
|
G_EXTI.borrow(cs).borrow_mut().replace(exti);
|
||||||
|
});
|
||||||
|
|
||||||
loop {
|
// Enable interrupts
|
||||||
if enc.count() != old_count {
|
unsafe {
|
||||||
old_count = enc.count();
|
cortex_m::peripheral::NVIC::unmask(Interrupt::TIM2);
|
||||||
lcd.set_cursor_pos(0x40);
|
cortex_m::peripheral::NVIC::unmask(Interrupt::EXTI9_5);
|
||||||
lcd.write_str(" ");
|
cortex_m::peripheral::NVIC::unmask(Interrupt::RTCALARM);
|
||||||
lcd.set_cursor_pos(0x40);
|
|
||||||
write!(lcd, "{}", enc.count()/4).unwrap();
|
|
||||||
}
|
|
||||||
for i in 0..10000 {
|
|
||||||
cortex_m::asm::nop;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// allow the debugging to continue in sleep and stop modes
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
dp.DBGMCU.cr.write(|w| w.dbg_sleep().set_bit());
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
dp.DBGMCU.cr.write(|w| w.dbg_stop().set_bit());
|
||||||
|
|
||||||
|
// configure stop mode (not working yet, probably due to fake chip)
|
||||||
|
//dp.PWR.cr.write(|w| w.pdds().stop_mode());
|
||||||
|
//dp.PWR.cr.write(|w| w.lpds().set_bit());
|
||||||
|
cp.SCB.set_sleepdeep();
|
||||||
|
|
||||||
|
/* run */
|
||||||
|
gui.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user