cortex_m_asyncrt/
os.rs

1extern crate alloc;
2
3use alloc::boxed::Box;
4use core::ptr::addr_of_mut;
5use core::sync::atomic::{AtomicU32, Ordering};
6use core::{
7    future::Future,
8    pin::Pin,
9    task::{Context, Poll},
10};
11use embedded_alloc::LlffHeap as Heap;
12
13#[global_allocator]
14static HEAP: Heap = Heap::empty();
15
16/// Initialize the heap.
17pub fn init_heap() {
18    use core::mem::MaybeUninit;
19    const HEAP_SIZE: usize = 1024;
20    static mut HEAP_MEM: [MaybeUninit<u8>; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE];
21    unsafe { HEAP.init(addr_of_mut!(HEAP_MEM) as usize, HEAP_SIZE) }
22}
23
24/// Task ID type. We use a 32 bit unsigned integer to represent a task ID.
25/// since the cortex-m architecture is 32 bit and does not have support for
26/// atomic 64 bit integers.
27#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
28struct TaskId(u32);
29
30impl TaskId {
31    fn new() -> Self {
32        static NEXT_ID: AtomicU32 = AtomicU32::new(0);
33        TaskId(NEXT_ID.fetch_add(1, Ordering::Relaxed))
34    }
35}
36
37/// Base struct to represent a task.
38pub struct Task {
39    /// A unique identifier for the task.
40    id: TaskId,
41    /// The future representing the task. The Pin<Box<>> wrapper ensures that that the
42    /// future is not moved in memory. The Output type of the future is (), indicating
43    /// that the future does not return a value - it just runs to completion.
44    future: Pin<Box<dyn Future<Output = ()>>>,
45}
46
47impl Task {
48    /// Create a new task from a future.
49    pub fn new(future: impl Future<Output = ()> + 'static) -> Task {
50        Task {
51            id: TaskId::new(),
52            future: Box::pin(future),
53        }
54    }
55
56    /// Poll the task.
57    fn poll(&mut self, context: &mut Context) -> Poll<()> {
58        self.future.as_mut().poll(context)
59    }
60}
61
62pub mod executor;
63pub mod time;