diff --git a/Cargo.toml b/Cargo.toml index 7225880..6e13cd9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ cortex-m-rt = "0.6.5" cortex-m-semihosting = "0.3.2" panic-halt = "0.2.0" panic-semihosting = "0.5.1" +heapless = "0.4.2" [dependencies.cortex-m-rtfm] version = "0.4.2" diff --git a/src/main.rs b/src/main.rs index 5f929e1..5f30d2d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,13 +5,19 @@ extern crate panic_semihosting; -//use cortex_m_semihosting::hprintln; +use core::fmt::Write; +use cortex_m_semihosting::hprintln; use hal::gpio::{Edge, ExtiPin, Floating, Input, Output, PushPull}; use hal::prelude::*; -use hal::stm32::EXTI; +use hal::serial::{self, config::Config as SerialConfig, Serial}; +use hal::stm32::{EXTI, USART1}; +use heapless::consts::U8; +use heapless::Vec; use rtfm::app; type Led = hal::gpio::gpiod::PD>; +type SerialTx = hal::serial::Tx; +type SerialRx = hal::serial::Rx; type UserButton = hal::gpio::gpioa::PA0>; pub enum LedDirection { @@ -87,8 +93,11 @@ impl LedCycle { #[app(device = hal::stm32)] const APP: () = { static mut button: UserButton = (); + static mut buffer: Vec = (); static mut led_cycle: LedCycle = (); static mut exti: EXTI = (); + static mut serial_rx: SerialRx = (); + static mut serial_tx: SerialTx = (); #[init(spawn = [switch_leds])] fn init() -> init::LateResources { @@ -110,7 +119,27 @@ const APP: () = { button.enable_interrupt(&mut exti); button.trigger_on_edge(&mut exti, Edge::RISING); - init::LateResources { button, exti, led_cycle } + // Set up the serial interface. + let tx = gpioa.pa9.into_alternate_af7(); + let rx = gpioa.pa10.into_alternate_af7(); + let config = SerialConfig::default(); + let rcc = device.RCC.constrain(); + let clocks = rcc.cfgr.freeze(); + let mut serial = Serial::usart1(device.USART1, (tx, rx), config, clocks).unwrap(); + serial.listen(serial::Event::Rxne); + let (serial_tx, serial_rx) = serial.split(); + + // Set up the serial interface command buffer. + let buffer = Vec::new(); + + init::LateResources { + button, + buffer, + exti, + led_cycle, + serial_tx, + serial_rx, + } } #[task(schedule = [switch_leds], resources = [led_cycle])] @@ -130,6 +159,53 @@ const APP: () = { resources.button.clear_interrupt_pending_bit(resources.exti); } + #[interrupt( + binds = USART1, + priority = 2, + resources = [buffer, led_cycle, serial_rx, serial_tx], + spawn = [switch_leds] + )] + fn handle_serial() { + let buffer = resources.buffer; + + // Read a byte from the serial port and write it back. + let byte = resources.serial_rx.read().unwrap(); + resources.serial_tx.write(byte).unwrap(); + //hprintln!("serial: {}", byte).unwrap(); + + // Handle the command in the buffer for newline, otherwise append to the buffer. + if byte == b'\r' { + match &buffer[..] { + b"flip" => { + resources.led_cycle.reverse(); + } + b"stop" => { + resources.led_cycle.disable(); + } + b"start" => { + resources.led_cycle.enable(); + spawn.switch_leds().unwrap(); + } + b"off" => { + resources.led_cycle.disable(); + resources.led_cycle.all_off(); + } + b"on" => { + resources.led_cycle.disable(); + resources.led_cycle.all_on(); + } + _ => {} + } + + buffer.clear(); + } else { + if buffer.push(byte).is_err() { + hprintln!("Serial read buffer full!").unwrap(); + } + //hprintln!("buffer: {:?}", buffer).unwrap(); + } + } + extern "C" { fn TIM2(); }