> This should be OK and I almost prefer it. Get a JTAG or SWD adapter, learn how to use GDB and the self test hardware
I'd really like to write a test that e.g. confirms that if PB13 goes high for longer than 10ms, and event is triggered. Yes, I can run that code on my MCU - but actually testing it requires pressing buttons. With an emulator, I could easily write code to mock out the behavior of external hardware and confirm that my code is handling that input correctly.
> Related to my first point
I'm actually talking about a constraint of Rust - not the HAL or PAC.
Per https://docs.rust-embedded.org/book/concurrency/index.html the canonical way to use a GPIO from an interrupt is something like:
static G_LED: Mutex<RefCell<Option<LEDPIN>>> = Mutex::new(RefCell::new(None));
fn main() {
// get the gpio and pass off to mutex
let mut led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh);
// Move the pin into our global storage
cortex_m::interrupt::free(|cs| *G_LED.borrow(cs).borrow_mut() = Some(led));
}
fn interrupt() {
static mut LED: Option<LEDPIN> = None;
// load the led from the global mutex
let led = LED.get_or_insert_with(|| {
cortex_m::interrupt::free(|cs| {
// Move LED pin here, leaving a None in its place
G_LED.borrow(cs).replace(None).unwrap()
})
});
// actually use the led gpio here
}
If we were genuinely using G_LED from main and from the interrupt, the mutex song-and-dance makes sense, since we want to be careful about how we share use of this resource. But since we just want to set it up in main and use it in the interrupt it's a LOT of confusing overhead/abstraction.