diff --git a/finny/Cargo.toml b/finny/Cargo.toml index c098aa1..c395288 100644 --- a/finny/Cargo.toml +++ b/finny/Cargo.toml @@ -14,12 +14,12 @@ readme = "../README.md" derive_more = "0.99.11" finny_derive = { path = "../finny_derive", version = "0.2.0" } arraydeque = { version = "0.4", default-features = false } -slog = { version = "2.7.0", optional = true } - +slog = { version = "2.7.0", optional = true, default-features = false } +heapless = { version = "0.7" } [features] default = ["std", "inspect_slog", "timers_std"] -std = ["arraydeque/std"] +std = ["arraydeque/std", "timers_std", "slog/std", "finny_derive/std"] inspect_slog = ["slog"] timers_std = [] generate_plantuml = ["finny_derive/generate_plantuml"] \ No newline at end of file diff --git a/finny/src/fsm/queue.rs b/finny/src/fsm/queue.rs index 32f39f0..9d75db7 100644 --- a/finny/src/fsm/queue.rs +++ b/finny/src/fsm/queue.rs @@ -171,6 +171,79 @@ mod queue_array { pub use self::queue_array::*; + +pub mod heapless_shared { + //! A heapless queue with Clone and Arc support. + + use core::sync::atomic::{AtomicUsize, Ordering}; + + use crate::FsmError; + + use super::*; + + extern crate alloc; + use alloc::sync::Arc; + use heapless::mpmc::Q64; + +/// An unbound event queue that uses `VecDeque`. + pub struct FsmEventQueueHeaplessShared { + inner: Arc> + } + + impl Clone for FsmEventQueueHeaplessShared where F: FsmBackend { + fn clone(&self) -> Self { + Self { inner: self.inner.clone() } + } + } + + struct Inner { + queue: Q64<::Events>, + len: AtomicUsize + } + + impl FsmEventQueueHeaplessShared { + pub fn new() -> Self { + let q = Q64::new(); + let inner = Inner { + queue: q, + len: AtomicUsize::new(0) + }; + FsmEventQueueHeaplessShared { + inner: Arc::new(inner) + } + } + } + + impl FsmEventQueue for FsmEventQueueHeaplessShared { + fn dequeue(&mut self) -> Option<::Events> { + match self.inner.queue.dequeue() { + Some(e) => { + self.inner.len.fetch_sub(1, Ordering::SeqCst); + Some(e) + }, + None => None + } + } + + fn len(&self) -> usize { + self.inner.len.load(Ordering::SeqCst) + } + } + + impl FsmEventQueueSender for FsmEventQueueHeaplessShared { + fn enqueue::Events>>(&mut self, event: E) -> FsmResult<()> { + match self.inner.queue.enqueue(event.into()) { + Ok(_) => { + self.inner.len.fetch_add(1, Ordering::SeqCst); + Ok(()) + }, + Err(_) => Err(FsmError::QueueOverCapacity) + } + } + } + +} + pub struct FsmEventQueueNull { _ty: PhantomData } @@ -260,6 +333,13 @@ fn test_dequeue_vec_shared() { test_queue(queue); } +#[test] +fn test_heapless_shared() { + use self::heapless_shared::FsmEventQueueHeaplessShared; + let queue = FsmEventQueueHeaplessShared::::new(); + test_queue(queue); +} + #[cfg(test)] fn test_queue>(mut queue: Q) { use super::tests_fsm::{Events, EventA}; diff --git a/finny/src/inspect/slog.rs b/finny/src/inspect/slog.rs index cc04cba..3a11756 100644 --- a/finny/src/inspect/slog.rs +++ b/finny/src/inspect/slog.rs @@ -1,9 +1,13 @@ +extern crate alloc; + use slog::{info, o, error}; use crate::{FsmBackend, FsmBackendImpl, FsmEvent, Inspect, InspectEvent, InspectFsmEvent}; use crate::lib::*; use AsRef; use core::fmt::Debug; use core::any::Any; +use alloc::string::ToString; +use alloc::format; pub struct InspectSlog { pub logger: slog::Logger diff --git a/finny_derive/Cargo.toml b/finny_derive/Cargo.toml index 81e8929..a0a0ae8 100644 --- a/finny_derive/Cargo.toml +++ b/finny_derive/Cargo.toml @@ -12,7 +12,8 @@ keywords = ["fsm", "state"] proc-macro = true [features] -default = [] +default = ["std"] +std = [] generate_plantuml = [] [dependencies] diff --git a/finny_derive/src/codegen.rs b/finny_derive/src/codegen.rs index f943cc0..ee65b22 100644 --- a/finny_derive/src/codegen.rs +++ b/finny_derive/src/codegen.rs @@ -544,10 +544,10 @@ pub fn generate_fsm_code(fsm: &FsmFnInput, _attr: TokenStream, _input: TokenStre let mut timers_enter = TokenStream::new(); let state = match &transition.ty { - FsmTransitionType::SelfTransition(FsmStateAction { state: FsmTransitionState::State(st @ FsmState { kind: FsmStateKind::Normal, .. }), .. }) => { + FsmTransitionType::SelfTransition(FsmStateAction { state: FsmTransitionState::State(st @ FsmState { .. }), .. }) => { Some(st) }, - FsmTransitionType::StateTransition(FsmStateTransition { state_to: FsmTransitionState::State(st @ FsmState { kind: FsmStateKind::Normal, .. }), .. }) => { + FsmTransitionType::StateTransition(FsmStateTransition { state_to: FsmTransitionState::State(st @ FsmState { .. }), .. }) => { Some(st) }, _ => None @@ -574,10 +574,10 @@ pub fn generate_fsm_code(fsm: &FsmFnInput, _attr: TokenStream, _input: TokenStre let mut timers_exit = TokenStream::new(); let state = match &transition.ty { - FsmTransitionType::SelfTransition(FsmStateAction { state: FsmTransitionState::State(st @ FsmState { kind: FsmStateKind::Normal, .. }), .. }) => { + FsmTransitionType::SelfTransition(FsmStateAction { state: FsmTransitionState::State(st @ FsmState { .. }), .. }) => { Some(st) }, - FsmTransitionType::StateTransition(FsmStateTransition { state_from: FsmTransitionState::State(st @ FsmState { kind: FsmStateKind::Normal, .. }), .. }) => { + FsmTransitionType::StateTransition(FsmStateTransition { state_from: FsmTransitionState::State(st @ FsmState { .. }), .. }) => { Some(st) }, _ => None diff --git a/finny_nostd_tests/src/main.rs b/finny_nostd_tests/src/main.rs index 10f5b72..bd34be9 100644 --- a/finny_nostd_tests/src/main.rs +++ b/finny_nostd_tests/src/main.rs @@ -1,12 +1,11 @@ -#![no_std] -#![no_main] +// disabling until no_std + alloc becomes stable +// #![no_std] use finny::{finny_fsm, FsmFactory, FsmEventQueueArray, inspect::null::InspectNull, FsmTimersNull}; use finny::decl::{FsmBuilder, BuiltFsm}; use heapless::consts::*; -#[no_mangle] -pub extern "C" fn main(_argc: isize, _argv: *const *const u8) -> isize { +pub fn main() { // Since we are passing a C string the final null character is mandatory const HELLO: &'static str = "Hello, world!\n\0"; unsafe { @@ -21,16 +20,8 @@ pub extern "C" fn main(_argc: isize, _argv: *const *const u8) -> isize { let mut fsm = StateMachine::new_with(ctx, queue, inspect, timers).unwrap(); fsm.start().unwrap(); } - - 0 -} - -#[panic_handler] -fn my_panic(_info: &core::panic::PanicInfo) -> ! { - loop {} } - /////////////////////////////////////////////////// #[derive(Debug, Default)]