rttrust/
lib.rs

1//! # rttrust
2//!
3//! Rust wrapper for [rt-thread](https://github.com/RT-Thread/rt-thread/tree/master)
4
5//! ### TODO
6//! 1. communication
7//!     1. rt_mailbox
8//!     1. rt_messagequeue
9//!     1. rt_signal
10//!
11
12#![cfg_attr(not(test), no_std)]
13#![feature(clamp)]
14#![feature(alloc_error_handler)]
15#![feature(negative_impls)]
16#![cfg_attr(test, feature(proc_macro_hygiene))]
17
18#[cfg(test)]
19#[macro_use]
20extern crate std;
21
22#[cfg(feature = "alloc")]
23#[cfg_attr(feature = "alloc", macro_use)]
24extern crate alloc;
25
26#[macro_use]
27extern crate bitflags;
28
29#[macro_use]
30extern crate cfg_if;
31
32#[cfg(test)]
33extern crate mockall;
34
35#[cfg(all(not(test), feature = "alloc"))]
36pub mod allocator;
37#[cfg(feature = "alloc")]
38pub mod callback;
39pub mod cmd;
40pub mod cstr;
41pub mod device;
42pub mod ffi;
43pub mod fmt;
44pub mod ipc;
45pub mod object;
46pub mod sync;
47pub mod thread;
48pub mod timer;
49
50#[cfg(test)]
51pub(crate) mod mock;
52
53#[cfg(feature = "alloc")]
54pub use alloc::{boxed::Box, rc::Rc, vec::Vec};
55
56#[cfg(feature = "io")]
57pub mod io;
58
59#[cfg(all(not(test), not(feature = "custom-panic")))]
60use core::{fmt::Write, panic::PanicInfo};
61use ffi::rt_err_t;
62
63#[macro_export]
64macro_rules! println {
65    ($fmt:expr) => (print!(concat!($fmt, "\n")));
66    ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
67}
68
69#[macro_export]
70macro_rules! print {
71    ($($arg:tt)*) => ({
72        use core::fmt::Write;
73        let mut writer = $crate::fmt::Console {};
74        writer.write_fmt(format_args!($($arg)*)).unwrap();
75    });
76}
77
78#[cfg(all(not(test), not(feature = "custom-panic")))]
79#[cfg_attr(not(test), panic_handler)]
80fn panic(panic: &PanicInfo<'_>) -> ! {
81    let mut writer = fmt::Console {};
82    writeln!(writer, "{}", panic).ok();
83    loop {}
84}
85
86#[cfg(all(not(test), feature = "alloc"))]
87#[cfg_attr(not(test), alloc_error_handler)]
88fn alloc_error_handler(layout: alloc::alloc::Layout) -> ! {
89    panic!("allocation error: {:?}", layout)
90}
91
92/// RT-Thread error code definitions
93#[derive(Debug)]
94pub enum RtError {
95    /// A generic error happens
96    Error,
97    /// Timed out
98    TimeOut,
99    /// The resource is full
100    Full,
101    /// The resource is empty
102    Empty,
103    /// No memory
104    NoMem,
105    /// No system
106    NoSys,
107    /// Busy
108    Busy,
109    /// IO error
110    IO,
111    /// Interrupted system call
112    Intr,
113    /// Invalid argument
114    Inval,
115    /// Unknown error
116    Unknown,
117}
118
119pub type Result<R> = core::result::Result<R, RtError>;
120
121impl RtError {
122    pub fn from_code(err: rt_err_t) -> Option<Self> {
123        let err = err.abs() as u32;
124        match err {
125            ffi::RT_EOK => None,
126            ffi::RT_ETIMEOUT => Some(RtError::TimeOut),
127            ffi::RT_EFULL => Some(RtError::Full),
128            ffi::RT_EEMPTY => Some(RtError::Empty),
129            ffi::RT_ENOMEM => Some(RtError::NoMem),
130            ffi::RT_ENOSYS => Some(RtError::NoSys),
131            ffi::RT_EBUSY => Some(RtError::Busy),
132            ffi::RT_EIO => Some(RtError::IO),
133            ffi::RT_EINTR => Some(RtError::Intr),
134            ffi::RT_EINVAL => Some(RtError::Inval),
135            _ => Some(RtError::Unknown),
136        }
137    }
138    pub fn from_code_none<R>(err: rt_err_t, ok: R) -> Result<R> {
139        Self::from_code(err).map_or(Ok(ok), |e| Err(e))
140    }
141    pub fn from_code_none_then<F, R>(err: rt_err_t, ok: F) -> Result<R>
142    where
143        F: FnOnce() -> R,
144    {
145        Self::from_code(err).map_or_else(|| Ok(ok()), |e| Err(e))
146    }
147
148    pub fn to_code(&self) -> rt_err_t {
149        let code = match self {
150            RtError::Error => ffi::RT_EOK,
151            RtError::TimeOut => ffi::RT_ETIMEOUT,
152            RtError::Full => ffi::RT_EFULL,
153            RtError::Empty => ffi::RT_EEMPTY,
154            RtError::NoMem => ffi::RT_ENOMEM,
155            RtError::NoSys => ffi::RT_ENOSYS,
156            RtError::Busy => ffi::RT_EBUSY,
157            RtError::IO => ffi::RT_EIO,
158            RtError::Intr => ffi::RT_EINTR,
159            RtError::Inval => ffi::RT_EINVAL,
160            RtError::Unknown => ffi::RT_EINVAL + 1,
161        };
162        -(code as rt_err_t)
163    }
164}