Skip to content

Commit

Permalink
uart: Add initial wrappers
Browse files Browse the repository at this point in the history
  • Loading branch information
Teufelchen1 committed Oct 28, 2024
1 parent 71e854e commit 3a4e6f6
Show file tree
Hide file tree
Showing 7 changed files with 173 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ license = "MIT OR Apache-2.0"
[dependencies]
embedded-hal-0-2 = { package = "embedded-hal", version = "0.2.4", features = ["unproven"] }
embedded-hal = "1"
embedded-io = "0.6.1"
switch-hal = "0.4.0"
nb = "0.1.1"
riot-sys = "0.7.13"
Expand Down
1 change: 1 addition & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ fn main() {
"periph_gpio",
"periph_i2c",
"periph_spi",
"periph_uart",
"prng_shaxprng",
"pthread",
"random",
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ pub mod adc;
#[cfg(riot_module_periph_dac)]
pub mod dac;

#[cfg(riot_module_periph_uart)]
pub mod uart;

#[cfg(riot_module_ztimer)]
pub mod ztimer;

Expand Down
99 changes: 99 additions & 0 deletions src/uart/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
//! Wrapper for using the UART
use crate::error::{NegativeErrorExt, NumericError};
use embedded_io;
use embedded_io::ErrorKind;
use riot_sys::libc::c_void;
use riot_sys::macro_UART_DEV;
use riot_sys::uart_init;
use riot_sys::uart_t;
use riot_sys::uart_write;

pub struct UARTDevice {
dev: uart_t,
}

impl embedded_io::Error for NumericError {
fn kind(&self) -> ErrorKind {
match -self.number() as _ {
riot_sys::ENODEV => ErrorKind::NotFound,
riot_sys::ENOTSUP => ErrorKind::Unsupported,
_ => ErrorKind::Other,
}
}
}

impl embedded_io::ErrorType for UARTDevice {
type Error = NumericError;
}

impl UARTDevice {
/// Create a new UARTDevice from a RIOT descriptor
pub fn from_c(dev: uart_t) -> Self {
UARTDevice { dev }
}

/// Create a new UARTDevice from device number
pub fn from_port(dev: u32) -> Self {
UARTDevice {
dev: unsafe { macro_UART_DEV(dev) },
}
}

unsafe extern "C" fn cb<F: FnMut(u8) + Send + 'static>(ctx: *mut c_void, byte: u8) {
let real_cb: &'static mut F = unsafe { &mut *(ctx as *mut _) };
(real_cb)(byte);
}

pub fn init_with_fn<F: FnMut(u8) + Send + 'static>(
&mut self,
baudrate: u32,
callback: &'static mut F,
) -> Result<(), NumericError> {
let result = {
unsafe {
uart_init(
self.dev,
baudrate,
Some(UARTDevice::cb::<F>),
callback as *const _ as *mut _,
)
}
};

result
.negative_to_error()
.map_or_else(|err| Err(NumericError::from(err)), |_| Ok(()))
}

pub fn init_with_closure<F: FnMut(u8) + Send + 'static>(
&mut self,
baudrate: u32,
callback: F,
) -> Result<(), NumericError> {
let result = {
unsafe {
uart_init(
self.dev,
baudrate,
Some(UARTDevice::cb::<F>),
&callback as *const _ as *mut _,
)
}
};

result
.negative_to_error()
.map_or_else(|err| Err(NumericError::from(err)), |_| Ok(()))
}
}

impl embedded_io::Write for UARTDevice {
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
unsafe { uart_write(self.dev, buf.as_ptr(), buf.len() as u32) };
Ok(buf.len())
}

fn flush(&mut self) -> Result<(), Self::Error> {
Ok(())
}
}
20 changes: 20 additions & 0 deletions tests/uart/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[package]
name = "riot-wrappers-test-uart"
version = "0.1.0"
authors = ["Bennet Hattesen <[email protected]>"]
edition = "2021"
publish = false

[lib]
crate-type = ["staticlib"]

[profile.release]
panic = "abort"

[dependencies]
riot-wrappers = { path = "../..", features = [
"set_panic_handler",
"panic_handler_format",
] }
embedded-io = "0.6.1"
static_cell = "2.1.0"
8 changes: 8 additions & 0 deletions tests/uart/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# name of your application
APPLICATION = riot-wrappers-test-uart
APPLICATION_RUST_MODULE = riot_wrappers_test_uart
BASELIBS += $(APPLICATION_RUST_MODULE).module
FEATURES_REQUIRED += rust_target
FEATURES_REQUIRED += periph_uart

include $(RIOTBASE)/Makefile.include
41 changes: 41 additions & 0 deletions tests/uart/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#![no_std]
use embedded_io::{Error, Write};
use riot_wrappers::println;
use riot_wrappers::riot_main;
use riot_wrappers::uart::UARTDevice;
use static_cell::StaticCell;

riot_main!(main);

fn main() {
let mut uart = UARTDevice::from_port(0);
fn echo_writer(byte: u8) {
static mut COUNT: u8 = 0;
let mut _count = unsafe { COUNT };
let character = byte as char;
if character.is_ascii_lowercase() {
println!("{:}:{:}", _count, character.to_ascii_uppercase());
} else if character.is_ascii_uppercase() {
println!("{:}:{:}", _count, character.to_ascii_lowercase());
} else {
println!("{:}:{:}", _count, character);
}
_count += 1;
unsafe { COUNT = _count };
}
static CB: StaticCell<fn(u8)> = StaticCell::new();
let cb = CB.init(echo_writer);
let res = uart.init_with_fn(115200, cb);

// Alternatively, you can use a closure:
// let res = uart.init_with_closure(115200, |mem: u8| {
// println!("Hello frome closure!");

Check warning on line 32 in tests/uart/src/lib.rs

View workflow job for this annotation

GitHub Actions / typos

"frome" should be "from".
// echo_writer(mem);
// });
match res {
Ok(_) => {
let _ = uart.write(b"Uart initialised, type something in!\n");
}
Err(err) => println!("Error: {:?}", err.kind()),
}
}

0 comments on commit 3a4e6f6

Please sign in to comment.