Skip to content
Snippets Groups Projects
Commit 6d34a1f5 authored by Astro's avatar Astro :gear:
Browse files

Merge branch 'task/add_bhi160_error_handling' into 'master'

Add erorr handling for BHI160  sensors.

See merge request !8
parents b313cf15 77f2e073
Branches
No related tags found
No related merge requests found
#![no_std] #![no_std]
#![no_main] #![no_main]
use core::fmt::Write;
use card10_l0dable::*; use card10_l0dable::*;
use core::fmt::{self, Write};
main!(main); main!(main);
fn main() { fn main() {
writeln!(UART, "Hello from Rust\r").unwrap(); let result = run();
if let Err(error) = result {
writeln!(UART, "error: {}\r", error).unwrap();
}
}
fn run() -> Result<(), Error> {
writeln!(UART, "Hello from Rust\r")?;
let bme = BME680::start(); let bme = BME680::start();
let a = BHI160::<Accelerometer>::start(); let a = BHI160::<Accelerometer>::start()?;
let g = BHI160::<Gyroscope>::start(); let g = BHI160::<Gyroscope>::start()?;
let o = BHI160::<Orientation>::start(); let o = BHI160::<Orientation>::start()?;
let display = Display::open(); let display = Display::open();
let light = LightSensor::start(); let light = LightSensor::start();
for t in 0..Display::W { for t in 0..Display::W {
writeln!(UART, "BME: {:?}\r", bme.read()).unwrap(); writeln!(UART, "BME: {:?}\r", bme.read())?;
writeln!(UART, "A:\r").unwrap(); writeln!(UART, "A:\r")?;
for d in &a.read() {
writeln!(UART, " - {:?}\r", d).unwrap(); for d in &a.read()? {
writeln!(UART, " - {:?}\r", d)?;
} }
writeln!(UART, "O:\r").unwrap();
for d in &o.read() { writeln!(UART, "O:\r")?;
writeln!(UART, " - {:?}\r", d).unwrap(); for d in &o.read()? {
writeln!(UART, " - {:?}\r", d)?;
} }
writeln!(UART, "G:\r").unwrap();
for d in &g.read() { writeln!(UART, "G:\r")?;
writeln!(UART, " - {:?}\r", d).unwrap(); for d in &g.read()? {
writeln!(UART, " - {:?}\r", d)?;
} }
display.clear(Color::yellow()); display.clear(Color::yellow());
display.print(160 - t, 10, b"Hello Rust\0", Color::white(), Color::black()); display.print(160 - t, 10, b"Hello Rust\0", Color::white(), Color::black());
...@@ -49,8 +62,41 @@ fn main() { ...@@ -49,8 +62,41 @@ fn main() {
if b.right_top() { if b.right_top() {
display.print(80, 30, b"Reset\0", Color::red(), Color::black()); display.print(80, 30, b"Reset\0", Color::red(), Color::black());
} }
writeln!(UART, "Light: {:?}\r", light.get()).unwrap(); writeln!(UART, "Light: {:?}\r", light.get())?;
display.update(); display.update();
} }
Ok(())
}
// -----------------------------------------------------------------------------
// Error
// -----------------------------------------------------------------------------
#[derive(Debug)]
pub enum Error {
UartWriteFailed(fmt::Error),
SensorInteractionFailed(BHI160Error),
}
impl From<fmt::Error> for Error {
fn from(error: fmt::Error) -> Self {
Error::UartWriteFailed(error)
}
}
impl From<BHI160Error> for Error {
fn from(error: BHI160Error) -> Self {
Error::SensorInteractionFailed(error)
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Error::UartWriteFailed(error) => error.fmt(f),
Error::SensorInteractionFailed(error) => error.fmt(f),
}
}
} }
use core::mem::uninitialized; use core::{
use core::marker::PhantomData; fmt::{self, Display, Write},
use super::bindings::*; marker::PhantomData,
mem::MaybeUninit,
};
use core::fmt::Write; use crate::{bindings::*, errno};
pub trait SensorType { pub trait SensorType {
/// sensor_type in C, sensor_id in Python /// sensor_type in C, sensor_id in Python
...@@ -48,43 +50,64 @@ pub struct Sensor<S: SensorType> { ...@@ -48,43 +50,64 @@ pub struct Sensor<S: SensorType> {
} }
impl<S: SensorType> Sensor<S> { impl<S: SensorType> Sensor<S> {
pub fn start() -> Self { fn new(stream_id: i32) -> Self {
Self {
stream_id,
_kind: PhantomData,
}
}
pub fn start() -> Result<Self, Error> {
let mut cfg = bhi160_sensor_config { let mut cfg = bhi160_sensor_config {
sample_buffer_len: 200, sample_buffer_len: 200,
sample_rate: 4, sample_rate: 4,
dynamic_range: 2, dynamic_range: 2,
_padding: [0u8; 8], _padding: [0u8; 8],
}; };
let stream_id = unsafe {
epic_bhi160_enable_sensor(S::sensor_type(), &mut cfg) let stream_id = unsafe { epic_bhi160_enable_sensor(S::sensor_type(), &mut cfg) };
if stream_id < 0 {
let error = match -stream_id {
errno::EBUSY => Error::DriverBusy,
_ => Error::Unknown(stream_id),
}; };
Sensor {
stream_id, return Err(error);
_kind: PhantomData,
} }
Ok(Sensor::new(stream_id))
} }
pub fn read(&self) -> SensorData<S> { pub fn read(&self) -> Result<SensorData<S>, Error> {
let mut buf: [bhi160_data_vector; DATA_MAX] = unsafe { let mut buffer = MaybeUninit::<[bhi160_data_vector; DATA_MAX]>::zeroed();
uninitialized() let buffer_pointer = buffer.as_mut_ptr() as *mut _;
};
let n = unsafe { let packet_count = unsafe { epic_stream_read(self.stream_id, buffer_pointer, DATA_MAX) };
epic_stream_read(self.stream_id, buf.as_mut_ptr() as *mut _, buf.len()) if packet_count < 0 {
let error = match -packet_count {
errno::ENODEV => Error::SensorUnavailable,
errno::EBADF => Error::SensorDescriptorUnknown,
errno::EINVAL => Error::InvalidSampleCount,
errno::EBUSY => Error::CouldNotAcquireLock,
_ => Error::Unknown(packet_count),
}; };
if n < 0 {
panic!("epic_stream_read fail"); return Err(error);
} }
let n = n as usize;
SensorData { Ok(SensorData {
buf, n, buf: unsafe { buffer.assume_init() },
n: packet_count as usize,
_kind: PhantomData, _kind: PhantomData,
} })
} }
} }
impl<S: SensorType> Drop for Sensor<S> { impl<S: SensorType> Drop for Sensor<S> {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { epic_bhi160_disable_sensor(S::sensor_type()); } unsafe {
epic_bhi160_disable_sensor(S::sensor_type());
}
} }
} }
...@@ -97,11 +120,9 @@ pub struct SensorData<S> { ...@@ -97,11 +120,9 @@ pub struct SensorData<S> {
impl<'a, S: SensorType> IntoIterator for &'a SensorData<S> { impl<'a, S: SensorType> IntoIterator for &'a SensorData<S> {
type Item = SensorDataItem; type Item = SensorDataItem;
type IntoIter = SensorDataIter<'a, S>; type IntoIter = SensorDataIter<'a, S>;
fn into_iter(self) -> Self::IntoIter { fn into_iter(self) -> Self::IntoIter {
SensorDataIter { SensorDataIter { data: self, pos: 0 }
data: self,
pos: 0,
}
} }
} }
...@@ -112,22 +133,27 @@ pub struct SensorDataIter<'a, S> { ...@@ -112,22 +133,27 @@ pub struct SensorDataIter<'a, S> {
impl<'a, S: SensorType> Iterator for SensorDataIter<'a, S> { impl<'a, S: SensorType> Iterator for SensorDataIter<'a, S> {
type Item = SensorDataItem; type Item = SensorDataItem;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
while self.pos < self.data.n { while self.pos < self.data.n {
let vec = &self.data.buf[self.pos];
self.pos += 1; self.pos += 1;
if vec.data_type == DATA_TYPE_VECTOR {
let vec = &self.data.buf[self.pos];
if vec.data_type != DATA_TYPE_VECTOR {
writeln!(crate::UART, "Sensor: skip type {}\r", vec.data_type).ok();
continue;
}
let item = SensorDataItem { let item = SensorDataItem {
x: S::convert_single(vec.x), x: S::convert_single(vec.x),
y: S::convert_single(vec.y), y: S::convert_single(vec.y),
z: S::convert_single(vec.z), z: S::convert_single(vec.z),
status: vec.status, status: vec.status,
}; };
return Some(item); return Some(item);
} else {
writeln!(crate::UART, "Sensor: skip type {}\r", vec.data_type).unwrap();
}
} }
None None
} }
} }
...@@ -152,3 +178,38 @@ pub struct bhi160_data_vector { ...@@ -152,3 +178,38 @@ pub struct bhi160_data_vector {
} }
const DATA_TYPE_VECTOR: u8 = 0; const DATA_TYPE_VECTOR: u8 = 0;
// -----------------------------------------------------------------------------
// BHI160 Error
// -----------------------------------------------------------------------------
#[derive(Debug)]
pub enum Error {
/// The descriptor table lock could not be acquired.
CouldNotAcquireLock,
/// The BHI160 driver is currently busy with other tasks and could not be
/// acquired for enabling a sensor.
DriverBusy,
/// The requested sample `count` is not a multiple of the sensor's sample
/// size.
InvalidSampleCount,
/// The given sensor descriptor is unknown.
SensorDescriptorUnknown,
/// Sensor is not currently available.
SensorUnavailable,
/// Not yet documented and therefore unknown error types.
Unknown(i32),
}
impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::CouldNotAcquireLock => writeln!(f, "Could not acquire BHI160 lock."),
Error::DriverBusy => writeln!(f, "The BHI160 Driver is busy."),
Error::InvalidSampleCount => writeln!(f, "Sample couldn't invalid."),
Error::SensorDescriptorUnknown => writeln!(f, "Unknown BHI160 sensor descriptor."),
Error::SensorUnavailable => writeln!(f, "The BHI160 sensor is currently unavailable."),
Error::Unknown(id) => writeln!(f, "Unknown error id: {}", id),
}
}
}
...@@ -58,6 +58,50 @@ pub mod ctypes { ...@@ -58,6 +58,50 @@ pub mod ctypes {
pub use core::ffi::c_void; pub use core::ffi::c_void;
} }
pub mod errno {
#![allow(non_snake_case)]
use crate::ctypes::c_int;
pub const EPERM: c_int = 1; // Operation not permitted
pub const ENOENT: c_int = 2; // No such file or directory
pub const ESRCH: c_int = 3; // No such process
pub const EINTR: c_int = 4; // Interrupted system call
pub const EIO: c_int = 5; // I/O error
pub const ENXIO: c_int = 6; // No such device or address
pub const E2BIG: c_int = 7; // Argument list too long
pub const ENOEXEC: c_int = 8; // Exec format error
pub const EBADF: c_int = 9; // Bad file number
pub const ECHILD: c_int = 10; // No child processes
pub const EAGAIN: c_int = 11; // Try again
pub const ENOMEM: c_int = 12; //Out of memory
pub const EACCES: c_int = 13; //Permission denied
pub const EFAULT: c_int = 14; //Bad address
pub const ENOTBLK: c_int = 15; //Block device required
pub const EBUSY: c_int = 16; //Device or resource busy
pub const EEXIST: c_int = 17; //File exists
pub const EXDEV: c_int = 18; //Cross-device link
pub const ENODEV: c_int = 19; //No such device
pub const ENOTDIR: c_int = 20; //Not a directory
pub const EISDIR: c_int = 21; //Is a directory
pub const EINVAL: c_int = 22; //Invalid argument
pub const ENFILE: c_int = 23; //File table overflow
pub const EMFILE: c_int = 24; //Too many open files
pub const ENOTTY: c_int = 25; //Not a typewriter
pub const ETXTBSY: c_int = 26; //Text file busy
pub const EFBIG: c_int = 27; //File too large
pub const ENOSPC: c_int = 28; //No space left on device
pub const ESPIPE: c_int = 29; //Illegal seek
pub const EROFS: c_int = 30; //Read-only file system
pub const EMLINK: c_int = 31; //Too many links
pub const EPIPE: c_int = 32; //Broken pipe
pub const EDOM: c_int = 33; //Math argument out of domain of func
pub const ERANGE: c_int = 34; //Math result not representable
pub const EAFNOSUPPORT: c_int = 97; //Address family not supported by protocol
pub const ECONNRESET: c_int = 104; //Connection timed out
pub const ETIMEDOUT: c_int = 110; //Connection timed out
pub const EINPROGRESS: c_int = 115; //Operation now in progress
}
pub mod bindings { pub mod bindings {
#![allow(non_upper_case_globals)] #![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)] #![allow(non_camel_case_types)]
...@@ -86,5 +130,8 @@ pub use fmt_buffer::{FmtBuffer, str_to_cstr}; ...@@ -86,5 +130,8 @@ pub use fmt_buffer::{FmtBuffer, str_to_cstr};
mod bme680; mod bme680;
pub use bme680::BME680; pub use bme680::BME680;
mod bhi160; mod bhi160;
pub use bhi160::{Sensor as BHI160, Accelerometer, Orientation, Gyroscope, SensorData as BHI160Data}; pub use bhi160::{
Accelerometer, Error as BHI160Error, Gyroscope, Orientation, Sensor as BHI160,
SensorData as BHI160Data,
};
pub mod fs; pub mod fs;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment