Skip to content

Commit

Permalink
Use nb crate for cleaner error handling on serial tx busy
Browse files Browse the repository at this point in the history
  • Loading branch information
ah- committed Feb 27, 2018
1 parent b32922d commit dba2073
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 55 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ bare-metal = "0.1.1"
cortex-m = "0.4.3"
cortex-m-semihosting = "0.2.0"
cortex-m-rtfm = "0.3.1"
nb = "0.1.1"
vcell = "0.1.0"

[features]
default = ["use_semihosting"]
default = []
use_semihosting = []

[dependencies.cortex-m-rt]
Expand Down
1 change: 1 addition & 0 deletions src/action.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use keycodes::KeyCode;

#[allow(dead_code)]
#[derive(Copy, Clone, PartialEq)]
pub enum Action {
Nop,
Expand Down
41 changes: 20 additions & 21 deletions src/bluetooth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

use core::fmt::Write;
use cortex_m_semihosting::hio;
use nb;
use rtfm::Threshold;
use super::hidreport::HidReport;
use super::protocol::{Message, MsgType, BleOp, KeyboardOp, SystemOp};
use super::protocol::{Message, MsgType, BleOp, KeyboardOp};
use super::serial::Serial;
use super::serial::bluetooth_usart::BluetoothUsart;

Expand All @@ -21,46 +22,44 @@ impl<'a> Bluetooth<'a> {
}
}

pub fn on(&mut self) {
// TODO: check arguments
// unused?
self.serial.send(MsgType::Ble, BleOp::On as u8, &[]);
pub fn on(&mut self) -> nb::Result<(), !> {
self.serial.send(MsgType::Ble, BleOp::On as u8, &[])
}

pub fn off(&mut self) {
self.serial.send(MsgType::Ble, BleOp::Off as u8, &[]);
pub fn off(&mut self) -> nb::Result<(), !> {
self.serial.send(MsgType::Ble, BleOp::Off as u8, &[])
}

pub fn save_host(&mut self, host: u8) {
pub fn save_host(&mut self, host: u8) -> nb::Result<(), !> {
// TODO: host < 4?
self.serial.send(MsgType::Ble, BleOp::SaveHost as u8, &[host]);
self.serial.send(MsgType::Ble, BleOp::SaveHost as u8, &[host])
}

pub fn connect_host(&mut self, host: u8) {
self.serial.send(MsgType::Ble, BleOp::ConnectHost as u8, &[host]);
pub fn connect_host(&mut self, host: u8) -> nb::Result<(), !> {
self.serial.send(MsgType::Ble, BleOp::ConnectHost as u8, &[host])
}

pub fn delete_host(&mut self, host: u8) {
self.serial.send(MsgType::Ble, BleOp::DeleteHost as u8, &[host]);
pub fn delete_host(&mut self, host: u8) -> nb::Result<(), !> {
self.serial.send(MsgType::Ble, BleOp::DeleteHost as u8, &[host])
}

pub fn broadcast(&mut self) {
self.serial.send(MsgType::Ble, BleOp::Broadcast as u8, &[]);
pub fn broadcast(&mut self) -> nb::Result<(), !> {
self.serial.send(MsgType::Ble, BleOp::Broadcast as u8, &[])
}

pub fn enable_compatibility_mode(&mut self, enabled: bool) {
pub fn enable_compatibility_mode(&mut self, enabled: bool) -> nb::Result<(), !> {
let on = if enabled { 1 } else { 0 };
self.serial.send(MsgType::Ble, BleOp::CompatibilityMode as u8, &[on]);
self.serial.send(MsgType::Ble, BleOp::CompatibilityMode as u8, &[on])
}

pub fn host_list_query(&mut self) {
self.serial.send(MsgType::Ble, BleOp::HostListQuery as u8, &[]);
pub fn host_list_query(&mut self) -> nb::Result<(), !> {
self.serial.send(MsgType::Ble, BleOp::HostListQuery as u8, &[])
}

pub fn send_report(&mut self, report: &HidReport) {
pub fn send_report(&mut self, report: &HidReport) -> nb::Result<(), !> {
self.serial.send(MsgType::Keyboard,
KeyboardOp::KeyReport as u8,
report.as_bytes());
report.as_bytes())
}

pub fn receive(message: &Message) {
Expand Down
19 changes: 19 additions & 0 deletions src/debug.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
// TODO: install exception handler to deal with hio semihosting not being available
// and just ignore bkpts if no debugger attached

use core::fmt;
use core::fmt::Write;
use cortex_m_semihosting::hio;

#[cfg(feature = "use_semihosting")]
#[macro_export]
macro_rules! debug {
Expand All @@ -22,3 +26,18 @@ macro_rules! debug {
}
}
}

pub trait UnwrapLog {
fn log_error(self);
}

impl<E: fmt::Debug> UnwrapLog for Result<(), E>
{
#[inline]
fn log_error(self) {
match self {
Err(e) => { debug!("{:?}", e).unwrap() },
_ => {},
}
}
}
21 changes: 12 additions & 9 deletions src/keyboard.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use action::Action;
use bluetooth::Bluetooth;
use debug::UnwrapLog;
use hidreport::HidReport;
use keycodes::KeyCode;
use keymatrix::KeyState;
use layout::{Layout, LAYERS};
use layout::LAYERS;
use led::Led;

pub struct Keyboard {
Expand Down Expand Up @@ -61,8 +62,8 @@ impl Keyboard {
// TODO: need to comment this out for now for setup msgs to go through
// probably needs a buffer / or not send this when setup got sent
// or not send this if nothing changed
bluetooth.send_report(&hid.report);
led.send_keys(state);
bluetooth.send_report(&hid.report).log_error();
led.send_keys(state).log_error();
self.layers.finish();

self.previous_state = *state;
Expand Down Expand Up @@ -143,23 +144,24 @@ impl EventProcessor for HidProcessor {
impl<'a> EventProcessor for Led<'a> {
fn process(&mut self, action: &Action, pressed: bool, changed: bool) {
if changed && pressed {
match action {
let result = match action {
&Action::LedOn => self.on(),
&Action::LedOff => self.off(),
&Action::LedNextTheme => self.next_theme(),
&Action::LedNextBrightness => self.next_brightness(),
&Action::LedNextAnimationSpeed => self.next_animation_speed(),
&Action::LedTheme(theme_id) => self.set_theme(theme_id),
_ => {}
}
_ => Ok(())
};
result.log_error()
}
}
}

impl<'a> EventProcessor for Bluetooth<'a> {
fn process(&mut self, action: &Action, pressed: bool, changed: bool) {
if changed && pressed {
match action {
let result = match action {
&Action::BtOn => self.on(),
&Action::BtOff => self.off(),
&Action::BtSaveHost(host) => self.save_host(host),
Expand All @@ -168,8 +170,9 @@ impl<'a> EventProcessor for Bluetooth<'a> {
&Action::BtBroadcast => self.broadcast(),
&Action::BtCompatibilityMode(on) => self.enable_compatibility_mode(on),
&Action::BtHostListQuery => self.host_list_query(),
_ => {}
}
_ => Ok(())
};
result.log_error()
}
}
}
1 change: 0 additions & 1 deletion src/layout.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use action::Action;
use action::Action::*;
use keycodes::KeyCode;
use keycodes::KeyCode::*;

/*
Expand Down
35 changes: 19 additions & 16 deletions src/led.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use embedded_hal::digital::OutputPin;
use rtfm::Threshold;
use hal::gpio::{Input, Output};
use hal::gpio::gpioc::PC15;
use nb;
use super::protocol::{Message, MsgType, LedOp};
use super::serial::Serial;
use super::serial::led_usart::LedUsart;
Expand All @@ -23,43 +24,45 @@ impl<'a> Led<'a> {
}
}

pub fn on(&mut self) {
pub fn on(&mut self) -> nb::Result<(), !> {
self.pc15.set_high();
Ok(())
}

pub fn off(&mut self) {
pub fn off(&mut self) -> nb::Result<(), !> {
self.pc15.set_low();
Ok(())
}

// next_* cycles through themes/brightness/speed
pub fn next_theme(&mut self) {
self.serial.send(MsgType::Led, LedOp::ConfigCmd as u8, &[1, 0, 0]);
pub fn next_theme(&mut self) -> nb::Result<(), !> {
self.serial.send(MsgType::Led, LedOp::ConfigCmd as u8, &[1, 0, 0])
}

pub fn next_brightness(&mut self) {
self.serial.send(MsgType::Led, LedOp::ConfigCmd as u8, &[0, 1, 0]);
pub fn next_brightness(&mut self) -> nb::Result<(), !> {
self.serial.send(MsgType::Led, LedOp::ConfigCmd as u8, &[0, 1, 0])
}

pub fn next_animation_speed(&mut self) {
self.serial.send(MsgType::Led, LedOp::ConfigCmd as u8, &[0, 0, 1]);
pub fn next_animation_speed(&mut self) -> nb::Result<(), !> {
self.serial.send(MsgType::Led, LedOp::ConfigCmd as u8, &[0, 0, 1])
}

pub fn set_theme(&mut self, theme: u8) {
self.serial.send(MsgType::Led, LedOp::ThemeMode as u8, &[theme]);
pub fn set_theme(&mut self, theme: u8) -> nb::Result<(), !> {
self.serial.send(MsgType::Led, LedOp::ThemeMode as u8, &[theme])
}

pub fn send_keys(&mut self, state: &KeyState) {
pub fn send_keys(&mut self, state: &KeyState) -> nb::Result<(), !> {
let packed = to_packed_bits(state);
self.serial.send(MsgType::Led, LedOp::Key as u8, &packed.bytes);
self.serial.send(MsgType::Led, LedOp::Key as u8, &packed.bytes)
}

pub fn send_music(&mut self, keys: &[u8]) {
self.serial.send(MsgType::Led, LedOp::Music as u8, keys);
pub fn send_music(&mut self, keys: &[u8]) -> nb::Result<(), !> {
self.serial.send(MsgType::Led, LedOp::Music as u8, keys)
}

pub fn get_theme_id(&mut self) {
pub fn get_theme_id(&mut self) -> nb::Result<(), !> {
// responds with with [ThemeId]
self.serial.send(MsgType::Led, LedOp::GetThemeId as u8, &[]);
self.serial.send(MsgType::Led, LedOp::GetThemeId as u8, &[])
}

pub fn receive(message: &Message) {
Expand Down
2 changes: 2 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#![feature(const_fn)]
#![feature(proc_macro)]
#![feature(never_type)]
#![feature(non_exhaustive)]
#![no_std]

Expand All @@ -8,6 +9,7 @@ extern crate cortex_m;
extern crate cortex_m_rtfm as rtfm;
extern crate cortex_m_semihosting;
extern crate embedded_hal;
extern crate nb;
extern crate stm32l151;
extern crate stm32l151_hal as hal;

Expand Down
12 changes: 5 additions & 7 deletions src/serial/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
pub mod bluetooth_usart;
pub mod led_usart;

use core::fmt::Write;
use cortex_m_semihosting::hio;
use nb;
use super::protocol::{Message, MsgType};


Expand Down Expand Up @@ -89,7 +88,7 @@ impl<'a, USART> Serial<'a, USART>
&mut self,
message_type: MsgType,
operation: u8, // TODO: make this typed?
data: &[u8]) {
data: &[u8]) -> nb::Result<(), !> {
if self.usart.is_send_ready() {
self.send_buffer[0] = message_type as u8;
self.send_buffer[1] = 1 + data.len() as u8;
Expand All @@ -98,11 +97,10 @@ impl<'a, USART> Serial<'a, USART>

self.usart.send(self.send_buffer.as_mut_ptr() as u32, 3 + data.len() as u16);
self.receive_stage = ReceiveStage::Header;

return Ok(())
} else {
// TODO: return an error instead
// saying we're busy
// using https://docs.rs/nb/0.1.1/nb/
debug!("tx busy").ok();
return Err(nb::Error::WouldBlock)
}
}

Expand Down

0 comments on commit dba2073

Please sign in to comment.