avr-oxide 0.0.6

An extremely simple Rusty operating system for AVR microcontrollers
/* oxide.rs
 *
 * Developed by Tim Walls <tim.walls@snowgoons.com>
 * Copyright (c) All Rights Reserved, Tim Walls
 */
//! A very basic "operating system" (ha!) for our embedded devices, that
//! essentially comprises an event loop that executes a provided closure
//! whenever something happens.  "Something happens" is indicated by
//! sending events to the supervisor.

// Imports ===================================================================
use crate::private::ringq::RingQ;
use crate::event::{OxideEvent, EventSink};
use crate::mut_singleton;
use crate::hal::concurrency::interrupt;

// Declarations ==============================================================

pub struct OxideSupervisor
{
  event_q: RingQ<OxideEvent, 16>
}

mut_singleton!(OxideSupervisor, INSTANCE, instance,
  OxideSupervisor {
    event_q: RingQ::new_with(OxideEvent::Initialise)
  });

// Code ======================================================================
impl OxideSupervisor {
  /**
   * Enter the event loop - and never return (*evil cackle*)
   */
  pub fn run<F: FnMut(OxideEvent)>(&mut self, mut handler: F) -> ! {
    loop {
      interrupt::wait();

      // We use the no-locking event Q.  This is safe as long as I am
      // the only consumer, and any producers are running in an interrupt-secure
      // context.
      while let Some(event) = self.event_q.consume_nolock() {
        handler(event);
      }
    }
  }
}

impl EventSink for OxideSupervisor {
  fn event(event: OxideEvent) {
    match instance().event_q.append_nolock(event) {
      Ok(_) => {
        // Do nothing
      }
      Err(_) => {
        // Also do nothing...  If we can't add events, we will just discard
      }
    }
  }
}


// Tests =====================================================================