/*
    ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
                 2011,2012,2013 Giovanni Di Sirio.
    This file is part of ChibiOS/RT.
    ChibiOS/RT is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    ChibiOS/RT is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see .
*/
/**
 * @file    ch.hpp
 * @brief   C++ wrapper classes and definitions.
 *
 * @addtogroup cpp_library
 * @{
 */
#include 
#ifndef _CH_HPP_
#define _CH_HPP_
/**
 * @brief   ChibiOS kernel-related classes and interfaces.
 */
namespace chibios_rt {
  /*------------------------------------------------------------------------*
   * chibios_rt::System                                                     *
   *------------------------------------------------------------------------*/
  /**
   * @brief Class encapsulating the base system functionalities.
   */
  class System {
  public:
    /**
     * @brief   ChibiOS/RT initialization.
     * @details After executing this function the current instructions stream
     *          becomes the main thread.
     * @pre     Interrupts must be still disabled when @p chSysInit() is invoked
     *          and are internally enabled.
     * @post    The main thread is created with priority @p NORMALPRIO.
     * @note    This function has special, architecture-dependent, requirements,
     *          see the notes into the various port reference manuals.
     *
     * @special
     */
    static void init(void);
    /**
     * @brief   Enters the kernel lock mode.
     *
     * @special
     */
    static void lock(void);
    /**
     * @brief   Leaves the kernel lock mode.
     *
     * @special
     */
    static void unlock(void);
    /**
     * @brief   Enters the kernel lock mode from within an interrupt handler.
     * @note    This API may do nothing on some architectures, it is required
     *          because on ports that support preemptable interrupt handlers
     *          it is required to raise the interrupt mask to the same level of
     *          the system mutual exclusion zone.
     *          It is good practice to invoke this API before invoking any I-class
     *          syscall from an interrupt handler.
     * @note    This API must be invoked exclusively from interrupt handlers.
     *
     * @special
     */
    static void lockFromIsr(void);
    /**
     * @brief   Leaves the kernel lock mode from within an interrupt handler.
     *
     * @note    This API may do nothing on some architectures, it is required
     *          because on ports that support preemptable interrupt handlers
     *          it is required to raise the interrupt mask to the same level of
     *          the system mutual exclusion zone.
     *          It is good practice to invoke this API after invoking any I-class
     *          syscall from an interrupt handler.
     * @note    This API must be invoked exclusively from interrupt handlers.
     *
     * @special
     */
    static void unlockFromIsr(void);
    /**
     * @brief   Returns the system time as system ticks.
     * @note    The system tick time interval is implementation dependent.
     *
     * @return          The system time.
     *
     * @api
     */
    static systime_t getTime(void);
    /**
     * @brief   Checks if the current system time is within the specified time
     *          window.
     * @note    When start==end then the function returns always true because the
     *          whole time range is specified.
     *
     * @param[in] start     the start of the time window (inclusive)
     * @param[in] end       the end of the time window (non inclusive)
     * @retval true         current time within the specified time window.
     * @retval false        current time not within the specified time window.
     *
     * @api
     */
    static bool isTimeWithin(systime_t start, systime_t end);
  };
  /*------------------------------------------------------------------------*
   * chibios_rt::System                                                     *
   *------------------------------------------------------------------------*/
  /**
   * @brief Class encapsulating the base system functionalities.
   */
  class Core {
  public:
    /**
     * @brief   Allocates a memory block.
     * @details The size of the returned block is aligned to the alignment
     *          type so it is not possible to allocate less
     *          than MEM_ALIGN_SIZE.
     *
     * @param[in] size      the size of the block to be allocated
     * @return              A pointer to the allocated memory block.
     * @retval NULL         allocation failed, core memory exhausted.
     *
     * @api
     */
    static void *alloc(size_t size);
    /**
     * @brief   Allocates a memory block.
     * @details The size of the returned block is aligned to the alignment
     *          type so it is not possible to allocate less than
     *          MEM_ALIGN_SIZE.
     *
     * @param[in] size      the size of the block to be allocated.
     * @return              A pointer to the allocated memory block.
     * @retval NULL         allocation failed, core memory exhausted.
     *
     * @iclass
     */
    static void *allocI(size_t size);
    /**
     * @brief   Core memory status.
     *
     * @return              The size, in bytes, of the free core memory.
     *
     * @api
     */
    static size_t getStatus(void);
  };
  /*------------------------------------------------------------------------*
   * chibios_rt::Timer                                                      *
   *------------------------------------------------------------------------*/
  /**
   * @brief   Timer class.
   */
  class Timer {
  public:
    /**
     * @brief   Embedded @p VirtualTimer structure.
     */
    ::VirtualTimer timer_ref;
    /**
     * @brief   Enables a virtual timer.
     * @note    The associated function is invoked from interrupt context.
     *
     * @param[in] time      the number of ticks before the operation timeouts,
     *                      the special values are handled as follow:
     *                      - @a TIME_INFINITE is allowed but interpreted as a
     *                        normal time specification.
     *                      - @a TIME_IMMEDIATE this value is not allowed.
     *                      .
     * @param[in] vtfunc    the timer callback function. After invoking the
     *                      callback the timer is disabled and the structure
     *                      can be disposed or reused.
     * @param[in] par       a parameter that will be passed to the callback
     *                      function
     *
     * @iclass
     */
    void setI(systime_t time, vtfunc_t vtfunc, void *par);
    /**
     * @brief   Resets the timer, if armed.
     *
     * @iclass
     */
    void resetI();
    /**
     * @brief   Returns the timer status.
     *
     * @retval TRUE         The timer is armed.
     * @retval FALSE        The timer already fired its callback.
     *
     * @iclass
     */
    bool isArmedI(void);
  };
  /*------------------------------------------------------------------------*
   * chibios_rt::ThreadReference                                            *
   *------------------------------------------------------------------------*/
  /**
   * @brief     Thread reference class.
   * @details   This class encapsulates a reference to a system thread. All
   *            operations involving another thread are performed through
   *            an object of this type.
   */
  class ThreadReference {
  public:
    /**
     * @brief   Pointer to the system thread.
     */
    ::Thread *thread_ref;
    /**
     * @brief   Thread reference constructor.
     *
     * @param[in] tp            the target thread. This parameter can be
     *                          @p NULL if the thread is not known at
     *                          creation time.
     *
     * @init
     */
    ThreadReference(Thread *tp) : thread_ref(tp) {
    };
    /**
     * @brief   Stops the thread.
     * @note    The implementation is left to descendant classes and is
     *          optional.
     */
    virtual void stop(void);
    /**
     * @brief   Suspends the current thread on the reference.
     * @details The suspended thread becomes the referenced thread. It is
     *          possible to use this method only if the thread reference
     *          was set to @p NULL.
     *
     * @return                  The incoming message.
     *
     * @api
     */
    msg_t suspend(void);
    /**
     * @brief   Suspends the current thread on the reference.
     * @details The suspended thread becomes the referenced thread. It is
     *          possible to use this method only if the thread reference
     *          was set to @p NULL.
     *
     * @return                  The incoming message.
     *
     * @sclass
     */
    msg_t suspendS(void);
    /**
     * @brief   Resumes the currently referenced thread, if any.
     *
     * @param[in] msg       the wakeup message
     *
     * @api
     */
    void resume(msg_t msg);
    /**
     * @brief   Resumes the currently referenced thread, if any.
     *
     * @param[in] msg       the wakeup message
     *
     * @iclass
     */
    void resumeI(msg_t msg);
    /**
     * @brief   Requests a thread termination.
     * @pre     The target thread must be written to invoke periodically
     *          @p chThdShouldTerminate() and terminate cleanly if it returns
     *          @p TRUE.
     * @post    The specified thread will terminate after detecting the
     *          termination condition.
     *
     * @api
     */
    void requestTerminate(void);
#if CH_USE_WAITEXIT || defined(__DOXYGEN__)
    /**
     * @brief   Blocks the execution of the invoking thread until the specified
     *          thread terminates then the exit code is returned.
     * @details This function waits for the specified thread to terminate then
     *          decrements its reference counter, if the counter reaches zero
     *          then the thread working area is returned to the proper
     *          allocator.
     *          The memory used by the exited thread is handled in different
     *          ways depending on the API that spawned the thread:
     *          - If the thread was spawned by @p chThdCreateStatic() or by
     *            @p chThdCreateI() then nothing happens and the thread working
     *            area is not released or modified in any way. This is the
     *            default, totally static, behavior.
     *          - If the thread was spawned by @p chThdCreateFromHeap() then
     *            the working area is returned to the system heap.
     *          - If the thread was spawned by @p chThdCreateFromMemoryPool()
     *            then the working area is returned to the owning memory pool.
     *          .
     * @pre     The configuration option @p CH_USE_WAITEXIT must be enabled in
     *          order to use this function.
     * @post    Enabling @p chThdWait() requires 2-4 (depending on the
     *          architecture) extra bytes in the @p Thread structure.
     * @post    After invoking @p chThdWait() the thread pointer becomes
     *          invalid and must not be used as parameter for further system
     *          calls.
     * @note    If @p CH_USE_DYNAMIC is not specified this function just waits
     *          for the thread termination, no memory allocators are involved.
     *
     * @return              The exit code from the terminated thread.
     *
     * @api
     */
    msg_t wait(void);
#endif /* CH_USE_WAITEXIT */
#if CH_USE_MESSAGES || defined(__DOXYGEN__)
    /**
     * @brief   Sends a message to the thread and returns the answer.
     *
     * @param[in] msg           the sent message
     * @return                  The returned message.
     *
     * @api
     */
    msg_t sendMessage(msg_t msg);
    /**
     * @brief   Returns true if there is at least one message in queue.
     *
     * @retval true             A message is waiting in queue.
     * @retval false            A message is not waiting in queue.
     *
     * @api
     */
    bool isPendingMessage(void);
    /**
     * @brief   Returns an enqueued message or @p NULL.
     *
     * @return                  The incoming message.
     *
     * @api
     */
    msg_t getMessage(void);
    /**
     * @brief   Releases the next message in queue with a reply.
     *
     * @param[in] msg           the answer message
     *
     * @api
     */
    void releaseMessage(msg_t msg);
#endif /* CH_USE_MESSAGES */
#if CH_USE_EVENTS || defined(__DOXYGEN__)
    /**
     * @brief   Adds a set of event flags directly to specified @p Thread.
     *
     * @param[in] mask      the event flags set to be ORed
     *
     * @api
     */
    void signalEvents(eventmask_t mask);
    /**
     * @brief   Adds a set of event flags directly to specified @p Thread.
     *
     * @param[in] mask      the event flags set to be ORed
     *
     * @iclass
     */
    void signalEventsI(eventmask_t mask);
#endif /* CH_USE_EVENTS */
#if CH_USE_DYNAMIC || defined(__DOXYGEN__)
#endif /* CH_USE_DYNAMIC */
  };
  /*------------------------------------------------------------------------*
   * chibios_rt::BaseThread                                                 *
   *------------------------------------------------------------------------*/
  /**
   * @brief   Abstract base class for a ChibiOS/RT thread.
   * @details The thread body is the virtual function @p Main().
   */
  class BaseThread : public ThreadReference {
  public:
    /**
     * @brief   BaseThread constructor.
     *
     * @init
     */
    BaseThread(void);
    /**
     * @brief   Thread body function.
     *
     * @return                  The exit message.
     *
     * @api
     */
    virtual msg_t main(void);
    /**
     * @brief   Creates and starts a system thread.
     *
     * @param[in] prio          thread priority
     * @return                  A reference to the created thread with
     *                          reference counter set to one.
     *
     * @api
     */
    virtual ThreadReference start(tprio_t prio);
    /**
     * @brief   Sets the current thread name.
     * @pre     This function only stores the pointer to the name if the option
     *          @p CH_USE_REGISTRY is enabled else no action is performed.
     *
     * @param[in] tname         thread name as a zero terminated string
     *
     * @api
     */
    static void setName(const char *tname);
    /**
     * @brief   Changes the running thread priority level then reschedules if
     *          necessary.
     * @note    The function returns the real thread priority regardless of the
     *          current priority that could be higher than the real priority
     *          because the priority inheritance mechanism.
     *
     * @param[in] newprio   the new priority level of the running thread
     * @return              The old priority level.
     *
     * @api
     */
    static tprio_t setPriority(tprio_t newprio);
    /**
     * @brief   Terminates the current thread.
     * @details The thread goes in the @p THD_STATE_FINAL state holding the
     *          specified exit status code, other threads can retrieve the
     *          exit status code by invoking the function @p chThdWait().
     * @post    Eventual code after this function will never be executed,
     *          this function never returns. The compiler has no way to
     *          know this so do not assume that the compiler would remove
     *          the dead code.
     *
     * @param[in] msg       thread exit code
     *
     * @api
     */
    static void exit(msg_t msg);
    /**
     * @brief   Terminates the current thread.
     * @details The thread goes in the @p THD_STATE_FINAL state holding the
     *          specified exit status code, other threads can retrieve the
     *          exit status code by invoking the function @p chThdWait().
     * @post    Eventual code after this function will never be executed,
     *          this function never returns. The compiler has no way to
     *          know this so do not assume that the compiler would remove
     *          the dead code.
     *
     * @param[in] msg       thread exit code
     *
     * @sclass
     */
    static void exitS(msg_t msg);
    /**
     * @brief   Verifies if the current thread has a termination request
     *          pending.
     * @note    Can be invoked in any context.
     *
     * @retval TRUE         termination request pending.
     * @retval FALSE        termination request not pending.
     *
     * @special
     */
    static bool shouldTerminate(void);
    /**
     * @brief   Suspends the invoking thread for the specified time.
     *
     * @param[in] interval  the delay in system ticks, the special values are
     *                      handled as follow:
     *                      - @a TIME_INFINITE the thread enters an infinite
     *                        sleep state.
     *                      - @a TIME_IMMEDIATE this value is not allowed.
     *                      .
     *
     * @api
     */
    static void sleep(systime_t interval);
    /**
     * @brief   Suspends the invoking thread until the system time arrives to
     *          the specified value.
     *
     * @param[in] time      absolute system time
     *
     * @api
     */
    static void sleepUntil(systime_t time);
    /**
     * @brief   Yields the time slot.
     * @details Yields the CPU control to the next thread in the ready list
     *          with equal priority, if any.
     *
     * @api
     */
    static void yield(void);
#if CH_USE_MESSAGES || defined(__DOXYGEN__)
    /**
     * @brief   Waits for a message.
     *
     * @return                  The sender thread.
     *
     * @api
     */
    static ThreadReference waitMessage(void);
#endif /* CH_USE_MESSAGES */
#if CH_USE_EVENTS || defined(__DOXYGEN__)
    /**
     * @brief   Clears the pending events specified in the mask.
     *
     * @param[in] mask      the events to be cleared
     * @return              The pending events that were cleared.
     *
     * @api
     */
    static eventmask_t getAndClearEvents(eventmask_t mask);
    /**
     * @brief   Adds (OR) a set of event flags on the current thread, this is
     *          @b much faster than using @p chEvtBroadcast() or
     *          @p chEvtSignal().
     *
     * @param[in] mask      the event flags to be added
     * @return              The current pending events mask.
     *
     * @api
     */
    static eventmask_t addEvents(eventmask_t mask);
    /**
     * @brief   Waits for a single event.
     * @details A pending event among those specified in @p ewmask is selected,
     *          cleared and its mask returned.
     * @note    One and only one event is served in the function, the one with
     *          the lowest event id. The function is meant to be invoked into
     *          a loop in order to serve all the pending events.
     *          This means that Event Listeners with a lower event identifier
     *          have an higher priority.
     *
     * @param[in] ewmask        mask of the events that the function should
     *                          wait for, @p ALL_EVENTS enables all the events
     * @return                  The mask of the lowest id served and cleared
     *                          event.
     *
     * @api
     */
    static eventmask_t waitOneEvent(eventmask_t ewmask);
    /**
     * @brief   Waits for any of the specified events.
     * @details The function waits for any event among those specified in
     *          @p ewmask to become pending then the events are cleared and
     *          returned.
     *
     * @param[in] ewmask        mask of the events that the function should
     *                          wait for, @p ALL_EVENTS enables all the events
     * @return                  The mask of the served and cleared events.
     *
     * @api
     */
    static eventmask_t waitAnyEvent(eventmask_t ewmask);
    /**
     * @brief   Waits for all the specified event flags then clears them.
     * @details The function waits for all the events specified in @p ewmask
     *          to become pending then the events are cleared and returned.
     *
     * @param[in] ewmask        mask of the event ids that the function should
     *                          wait for
     * @return                  The mask of the served and cleared events.
     *
     * @api
     */
    static eventmask_t waitAllEvents(eventmask_t ewmask);
#if CH_USE_EVENTS_TIMEOUT || defined(__DOXYGEN__)
    /**
     * @brief   Waits for a single event.
     * @details A pending event among those specified in @p ewmask is selected,
     *          cleared and its mask returned.
     * @note    One and only one event is served in the function, the one with
     *          the lowest event id. The function is meant to be invoked into
     *          a loop in order to serve all the pending events.
     *          This means that Event Listeners with a lower event identifier
     *          have an higher priority.
     *
     * @param[in] ewmask        mask of the events that the function should
     *                          wait for, @p ALL_EVENTS enables all the events
     *
     * @param[in] time          the number of ticks before the operation
     *                          timouts
     * @return                  The mask of the lowest id served and cleared
     *                          event.
     * @retval 0                if the specified timeout expired.
     *
     * @api
     */
    static eventmask_t waitOneEventTimeout(eventmask_t ewmask,
                                           systime_t time);
    /**
     * @brief   Waits for any of the specified events.
     * @details The function waits for any event among those specified in
     *          @p ewmask to become pending then the events are cleared and
     *          returned.
     *
     * @param[in] ewmask        mask of the events that the function should
     *                          wait for, @p ALL_EVENTS enables all the events
     * @param[in] time          the number of ticks before the operation
     *                          timouts
     * @return                  The mask of the served and cleared events.
     * @retval 0                if the specified timeout expired.
     *
     * @api
     */
    static eventmask_t waitAnyEventTimeout(eventmask_t ewmask,
                                           systime_t time);
    /**
     * @brief   Waits for all the specified event flags then clears them.
     * @details The function waits for all the events specified in @p ewmask
     *          to become pending then the events are cleared and returned.
     *
     * @param[in] ewmask        mask of the event ids that the function should
     *                          wait for
     * @param[in] time          the number of ticks before the operation
     *                          timouts
     * @return                  The mask of the served and cleared events.
     * @retval 0                if the specified timeout expired.
     *
     * @api
     */
    static eventmask_t waitAllEventsTimeout(eventmask_t ewmask,
                                            systime_t time);
#endif /* CH_USE_EVENTS_TIMEOUT */
    /**
     * @brief   Invokes the event handlers associated to an event flags mask.
     *
     * @param[in] mask      mask of the event flags to be dispatched
     * @param[in] handlers  an array of @p evhandler_t. The array must have
     *                      size equal to the number of bits in eventmask_t.
     *
     * @api
     */
    static void dispatchEvents(const evhandler_t handlers[],
                               eventmask_t mask);
#endif /* CH_USE_EVENTS */
#if CH_USE_MUTEXES || defined(__DOXYGEN__)
    /**
     * @brief   Unlocks the next owned mutex in reverse lock order.
     * @pre     The invoking thread must have at least one owned mutex.
     * @post    The mutex is unlocked and removed from the per-thread stack of
     *          owned mutexes.
     *
     * @return              A pointer to the unlocked mutex.
     *
     * @api
     */
    static void unlockMutex(void);
    /**
     * @brief   Unlocks the next owned mutex in reverse lock order.
     * @pre     The invoking thread must have at least one owned mutex.
     * @post    The mutex is unlocked and removed from the per-thread stack of
     *          owned mutexes.
     * @post    This function does not reschedule so a call to a rescheduling
     *          function must be performed before unlocking the kernel.
     *
     * @return              A pointer to the unlocked mutex.
     *
     * @sclass
     */
    static void unlockMutexS(void);
    /**
     * @brief   Unlocks all the mutexes owned by the invoking thread.
     * @post    The stack of owned mutexes is emptied and all the found
     *          mutexes are unlocked.
     * @note    This function is MUCH MORE efficient than releasing the
     *          mutexes one by one and not just because the call overhead,
     *          this function does not have any overhead related to the
     *          priority inheritance mechanism.
     *
     * @api
     */
    static void unlockAllMutexes(void);
#endif /* CH_USE_MUTEXES */
  };
  /*------------------------------------------------------------------------*
   * chibios_rt::BaseStaticThread                                           *
   *------------------------------------------------------------------------*/
  /**
   * @brief   Static threads template class.
   * @details This class introduces static working area allocation.
   *
   * @param N               the working area size for the thread class
   */
  template 
  class BaseStaticThread : public BaseThread {
  protected:
    WORKING_AREA(wa, N);
  public:
    /**
     * @brief   Thread constructor.
     * @details The thread object is initialized but the thread is not
     *          started here.
     *
     * @init
     */
    BaseStaticThread(void) : BaseThread() {
    }
    /**
     * @brief   Creates and starts a system thread.
     *
     * @param[in] prio          thread priority
     * @return                  A reference to the created thread with
     *                          reference counter set to one.
     *
     * @api
     */
    virtual ThreadReference start(tprio_t prio) {
      msg_t _thd_start(void *arg);
      thread_ref = chThdCreateStatic(wa, sizeof(wa), prio, _thd_start, this);
      return *this;
    }
  };
#if CH_USE_SEMAPHORES || defined(__DOXYGEN__)
  /*------------------------------------------------------------------------*
   * chibios_rt::CounterSemaphore                                           *
   *------------------------------------------------------------------------*/
  /**
   * @brief   Class encapsulating a semaphore.
   */
  class CounterSemaphore {
  public:
    /**
     * @brief   Embedded @p ::Semaphore structure.
     */
    ::Semaphore sem;
    /**
     * @brief   CounterSemaphore constructor.
     * @details The embedded @p ::Semaphore structure is initialized.
     *
     * @param[in] n             the semaphore counter value, must be greater
     *                          or equal to zero
     *
     * @init
     */
    CounterSemaphore(cnt_t n);
    /**
     * @brief   Performs a reset operation on the semaphore.
     * @post    After invoking this function all the threads waiting on the
     *          semaphore, if any, are released and the semaphore counter is
     *          set to the specified, non negative, value.
     * @note    The released threads can recognize they were waked up by a
     *          reset rather than a signal because the @p chSemWait() will
     *          return @p RDY_RESET instead of @p RDY_OK.
     *
     * @param[in] n         the new value of the semaphore counter. The value
     *                      must be non-negative.
     *
     * @api
     */
    void reset(cnt_t n);
    /**
     * @brief   Performs a reset operation on the semaphore.
     * @post    After invoking this function all the threads waiting on the
     *          semaphore, if any, are released and the semaphore counter is
     *          set to the specified, non negative, value.
     * @post    This function does not reschedule so a call to a rescheduling
     *          function must be performed before unlocking the kernel. Note
     *          that interrupt handlers always reschedule on exit so an
     *          explicit reschedule must not be performed in ISRs.
     * @note    The released threads can recognize they were waked up by a
     *          reset rather than a signal because the @p chSemWait() will
     *          return @p RDY_RESET instead of @p RDY_OK.
     *
     * @param[in] n         the new value of the semaphore counter. The value
     *                      must be non-negative.
     *
     * @iclass
     */
    void resetI(cnt_t n);
    /**
     * @brief   Performs a wait operation on a semaphore.
     *
     * @return              A message specifying how the invoking thread has
     *                      been released from the semaphore.
     * @retval RDY_OK       if the thread has not stopped on the semaphore or
     *                      the semaphore has been signaled.
     * @retval RDY_RESET    if the semaphore has been reset using
     *                      @p chSemReset().
     *
     * @api
     */
    msg_t wait(void);
    /**
     * @brief   Performs a wait operation on a semaphore.
     *
     * @return              A message specifying how the invoking thread has
     *                      been released from the semaphore.
     * @retval RDY_OK       if the thread has not stopped on the semaphore or
     *                      the semaphore has been signaled.
     * @retval RDY_RESET    if the semaphore has been reset using
     *                      @p chSemReset().
     *
     * @sclass
     */
    msg_t waitS(void);
    /**
     * @brief   Performs a wait operation on a semaphore with timeout
     *          specification.
     *
     * @param[in] time      the number of ticks before the operation timeouts,
     *                      the following special values are allowed:
     *                      - @a TIME_IMMEDIATE immediate timeout.
     *                      - @a TIME_INFINITE no timeout.
     *                      .
     * @return              A message specifying how the invoking thread has
     *                      been released from the semaphore.
     * @retval RDY_OK       if the thread has not stopped on the semaphore or
     *                      the semaphore has been signaled.
     * @retval RDY_RESET    if the semaphore has been reset using
     *                      @p chSemReset().
     * @retval RDY_TIMEOUT  if the semaphore has not been signaled or reset
     *                      within the specified timeout.
     *
     * @api
     */
    msg_t waitTimeout(systime_t time);
    /**
     * @brief   Performs a wait operation on a semaphore with timeout
     *          specification.
     *
     * @param[in] time      the number of ticks before the operation timeouts,
     *                      the following special values are allowed:
     *                      - @a TIME_IMMEDIATE immediate timeout.
     *                      - @a TIME_INFINITE no timeout.
     *                      .
     * @return              A message specifying how the invoking thread has
     *                      been released from the semaphore.
     * @retval RDY_OK       if the thread has not stopped on the semaphore or
     *                      the semaphore has been signaled.
     * @retval RDY_RESET    if the semaphore has been reset using
     *                      @p chSemReset().
     * @retval RDY_TIMEOUT  if the semaphore has not been signaled or reset
     *                      within the specified timeout.
     *
     * @sclass
     */
    msg_t waitTimeoutS(systime_t time);
    /**
     * @brief   Performs a signal operation on a semaphore.
     *
     * @api
     */
    void signal(void);
    /**
     * @brief   Performs a signal operation on a semaphore.
     * @post    This function does not reschedule so a call to a rescheduling
     *          function must be performed before unlocking the kernel. Note
     *          that interrupt handlers always reschedule on exit so an
     *          explicit reschedule must not be performed in ISRs.
     *
     * @iclass
     */
    void signalI(void);
    /**
     * @brief   Adds the specified value to the semaphore counter.
     * @post    This function does not reschedule so a call to a rescheduling
     *          function must be performed before unlocking the kernel. Note
     *          that interrupt handlers always reschedule on exit so an explicit
     *          reschedule must not be performed in ISRs.
     *
     * @param[in] n         value to be added to the semaphore counter. The
     *                      value must be positive.
     *
     * @iclass
     */
    void addCounterI(cnt_t n);
    /**
     * @brief   Returns the semaphore counter value.
     *
     * @return                  The semaphore counter value.
     *
     * @iclass
     */
    cnt_t getCounterI(void);
#if CH_USE_SEMSW || defined(__DOXYGEN__)
    /**
     * @brief   Atomic signal and wait operations.
     *
     * @param[in] ssem          @p Semaphore object to be signaled
     * @param[in] wsem          @p Semaphore object to wait on
     * @return                  A message specifying how the invoking thread
     *                          has been released from the semaphore.
     * @retval RDY_OK           if the thread has not stopped on the semaphore
     *                          or the semaphore has been signaled.
     * @retval RDY_RESET        if the semaphore has been reset using
     *                          @p chSemReset().
     *
     * @api
     */
    static msg_t signalWait(CounterSemaphore *ssem,
                            CounterSemaphore *wsem);
#endif /* CH_USE_SEMSW */
  };
  /*------------------------------------------------------------------------*
   * chibios_rt::BinarySemaphore                                            *
   *------------------------------------------------------------------------*/
  /**
   * @brief   Class encapsulating a binary semaphore.
   */
  class BinarySemaphore {
  public:
    /**
     * @brief   Embedded @p ::Semaphore structure.
     */
    ::BinarySemaphore bsem;
    /**
     * @brief   BinarySemaphore constructor.
     * @details The embedded @p ::BinarySemaphore structure is initialized.
     *
     * @param[in] taken     initial state of the binary semaphore:
     *                      - @a false, the initial state is not taken.
     *                      - @a true, the initial state is taken.
     *                      .
     *
     * @init
     */
    BinarySemaphore(bool taken);
    /**
     * @brief   Wait operation on the binary semaphore.
     *
     * @return              A message specifying how the invoking thread has
     *                      been released from the semaphore.
     * @retval RDY_OK       if the binary semaphore has been successfully
     *                      taken.
     * @retval RDY_RESET    if the binary semaphore has been reset using
     *                      @p bsemReset().
     *
     * @api
     */
    msg_t wait(void);
    /**
     * @brief   Wait operation on the binary semaphore.
     *
     * @return              A message specifying how the invoking thread has
     *                      been released from the semaphore.
     * @retval RDY_OK       if the binary semaphore has been successfully
     *                      taken.
     * @retval RDY_RESET    if the binary semaphore has been reset using
     *                      @p bsemReset().
     *
     * @sclass
     */
    msg_t waitS(void);
    /**
     * @brief   Wait operation on the binary semaphore.
     *
     * @param[in] time      the number of ticks before the operation timeouts,
     *                      the following special values are allowed:
     *                      - @a TIME_IMMEDIATE immediate timeout.
     *                      - @a TIME_INFINITE no timeout.
     *                      .
     * @return              A message specifying how the invoking thread has
     *                      been released from the semaphore.
     * @retval RDY_OK       if the binary semaphore has been successfully
     *                      taken.
     * @retval RDY_RESET    if the binary semaphore has been reset using
     *                      @p bsemReset().
     * @retval RDY_TIMEOUT  if the binary semaphore has not been signaled
     *                      or reset within the specified timeout.
     *
     * @api
     */
    msg_t waitTimeout(systime_t time);
    /**
     * @brief   Wait operation on the binary semaphore.
     *
     * @param[in] time      the number of ticks before the operation timeouts,
     *                      the following special values are allowed:
     *                      - @a TIME_IMMEDIATE immediate timeout.
     *                      - @a TIME_INFINITE no timeout.
     *                      .
     * @return              A message specifying how the invoking thread has
     *                      been released from the semaphore.
     * @retval RDY_OK       if the binary semaphore has been successfully
     *                      taken.
     * @retval RDY_RESET    if the binary semaphore has been reset using
     *                      @p bsemReset().
     * @retval RDY_TIMEOUT  if the binary semaphore has not been signaled
     *                      or reset within the specified timeout.
     *
     * @sclass
     */
    msg_t waitTimeoutS(systime_t time);
    /**
     * @brief   Reset operation on the binary semaphore.
     * @note    The released threads can recognize they were waked up by a
     *          reset rather than a signal because the @p bsemWait() will
     *          return @p RDY_RESET instead of @p RDY_OK.
     *
     * @param[in] taken     new state of the binary semaphore
     *                      - @a FALSE, the new state is not taken.
     *                      - @a TRUE, the new state is taken.
     *                      .
     *
     * @api
     */
    void reset(bool taken);
    /**
     * @brief   Reset operation on the binary semaphore.
     * @note    The released threads can recognize they were waked up by a
     *          reset rather than a signal because the @p bsemWait() will
     *          return @p RDY_RESET instead of @p RDY_OK.
     * @note    This function does not reschedule.
     *
     * @param[in] taken     new state of the binary semaphore
     *                      - @a FALSE, the new state is not taken.
     *                      - @a TRUE, the new state is taken.
     *                      .
     *
     * @iclass
     */
    void resetI(bool taken);
    /**
     * @brief   Performs a signal operation on a binary semaphore.
     *
     * @api
     */
    void signal(void);
    /**
     * @brief   Performs a signal operation on a binary semaphore.
     * @note    This function does not reschedule.
     *
     * @iclass
     */
    void signalI(void);
    /**
     * @brief   Returns the binary semaphore current state.
     *
     * @return              The binary semaphore current state.
     * @retval false        if the binary semaphore is not taken.
     * @retval true         if the binary semaphore is taken.
     *
     * @iclass
     */
    bool getStateI(void);
};
#endif /* CH_USE_SEMAPHORES */
#if CH_USE_MUTEXES || defined(__DOXYGEN__)
  /*------------------------------------------------------------------------*
   * chibios_rt::Mutex                                                      *
   *------------------------------------------------------------------------*/
  /**
   * @brief   Class encapsulating a mutex.
   */
  class Mutex {
  public:
    /**
     * @brief   Embedded @p ::Mutex structure.
     */
    ::Mutex mutex;
    /**
     * @brief   Mutex object constructor.
     * @details The embedded @p ::Mutex structure is initialized.
     *
     * @init
     */
    Mutex(void);
    /**
     * @brief   Tries to lock a mutex.
     * @details This function attempts to lock a mutex, if the mutex is already
     *          locked by another thread then the function exits without
     *          waiting.
     * @post    The mutex is locked and inserted in the per-thread stack of
     *          owned mutexes.
     * @note    This function does not have any overhead related to the
     *          priority inheritance mechanism because it does not try to
     *          enter a sleep state.
     *
     * @return              The operation status.
     * @retval TRUE         if the mutex has been successfully acquired
     * @retval FALSE        if the lock attempt failed.
     *
     * @api
     */
    bool tryLock(void);
    /**
     * @brief   Tries to lock a mutex.
     * @details This function attempts to lock a mutex, if the mutex is already
     *          taken by another thread then the function exits without
     *          waiting.
     * @post    The mutex is locked and inserted in the per-thread stack of
     *          owned mutexes.
     * @note    This function does not have any overhead related to the
     *          priority inheritance mechanism because it does not try to
     *          enter a sleep state.
     *
     * @return              The operation status.
     * @retval TRUE         if the mutex has been successfully acquired
     * @retval FALSE        if the lock attempt failed.
     *
     * @sclass
     */
    bool tryLockS(void);
    /**
     * @brief   Locks the specified mutex.
     * @post    The mutex is locked and inserted in the per-thread stack of
     *          owned mutexes.
     *
     * @api
     */
    void lock(void);
    /**
     * @brief   Locks the specified mutex.
     * @post    The mutex is locked and inserted in the per-thread stack of
     *          owned mutexes.
     *
     * @sclass
     */
    void lockS(void);
  };
#if CH_USE_CONDVARS || defined(__DOXYGEN__)
  /*------------------------------------------------------------------------*
   * chibios_rt::CondVar                                                    *
   *------------------------------------------------------------------------*/
  /**
   * @brief   Class encapsulating a conditional variable.
   */
  class CondVar {
  public:
    /**
     * @brief   Embedded @p ::CondVar structure.
     */
    ::CondVar condvar;
    /**
     * @brief   CondVar object constructor.
     * @details The embedded @p ::CondVar structure is initialized.
     *
     * @init
     */
    CondVar(void);
    /**
     * @brief   Signals one thread that is waiting on the condition variable.
     *
     * @api
     */
    void signal(void);
    /**
     * @brief   Signals one thread that is waiting on the condition variable.
     * @post    This function does not reschedule so a call to a rescheduling
     *          function must be performed before unlocking the kernel. Note
     *          that interrupt handlers always reschedule on exit so an
     *          explicit reschedule must not be performed in ISRs.
     *
     * @iclass
     */
    void signalI(void);
    /**
     * @brief   Signals all threads that are waiting on the condition variable.
     *
     * @api
     */
    void broadcast(void);
    /**
     * @brief   Signals all threads that are waiting on the condition variable.
     * @post    This function does not reschedule so a call to a rescheduling
     *          function must be performed before unlocking the kernel. Note
     *          that interrupt handlers always reschedule on exit so an
     *          explicit reschedule must not be performed in ISRs.
     *
     * @iclass
     */
    void broadcastI(void);
    /**
     * @brief   Waits on the condition variable releasing the mutex lock.
     * @details Releases the currently owned mutex, waits on the condition
     *          variable, and finally acquires the mutex again. All the
     *          sequence is performed atomically.
     * @pre     The invoking thread must have at least one owned mutex.
     *
     * @return              A message specifying how the invoking thread has
     *                      been released from the condition variable.
     * @retval RDY_OK       if the condvar has been signaled using
     *                      @p chCondSignal().
     * @retval RDY_RESET    if the condvar has been signaled using
     *                      @p chCondBroadcast().
     *
     * @api
     */
    msg_t wait(void);
    /**
     * @brief   Waits on the condition variable releasing the mutex lock.
     * @details Releases the currently owned mutex, waits on the condition
     *          variable, and finally acquires the mutex again. All the
     *          sequence is performed atomically.
     * @pre     The invoking thread must have at least one owned mutex.
     *
     * @return              A message specifying how the invoking thread has
     *                      been released from the condition variable.
     * @retval RDY_OK       if the condvar has been signaled using
     *                      @p chCondSignal().
     * @retval RDY_RESET    if the condvar has been signaled using
     *                      @p chCondBroadcast().
     *
     * @sclass
     */
    msg_t waitS(void);
#if CH_USE_CONDVARS_TIMEOUT || defined(__DOXYGEN__)
    /**
     * @brief   Waits on the CondVar while releasing the controlling mutex.
     *
     * @param[in] time          the number of ticks before the operation fails
     * @return                  The wakep mode.
     * @retval RDY_OK if        the condvar was signaled using
     *                          @p chCondSignal().
     * @retval RDY_RESET        if the condvar was signaled using
     *                          @p chCondBroadcast().
     * @retval RDY_TIMEOUT      if the condvar was not signaled within the
     *                          specified timeout.
     *
     * @api
     */
    msg_t waitTimeout(systime_t time);
#endif /* CH_USE_CONDVARS_TIMEOUT */
  };
#endif /* CH_USE_CONDVARS */
#endif /* CH_USE_MUTEXES */
#if CH_USE_EVENTS || defined(__DOXYGEN__)
  /*------------------------------------------------------------------------*
   * chibios_rt::EvtListener                                                *
   *------------------------------------------------------------------------*/
  /**
   * @brief   Class encapsulating an event listener.
   */
  class EvtListener {
  public:
    /**
     * @brief   Embedded @p ::EventListener structure.
     */
    struct ::EventListener ev_listener;
    /**
     * @brief   Returns the pending flags from the listener and clears them.
     *
     * @return                  The flags added to the listener by the
     *                          associated event source.
     *
     * @api
     */
    flagsmask_t getAndClearFlags(void);
    /**
     * @brief   Returns the flags associated to an @p EventListener.
     * @details The flags are returned and the @p EventListener flags mask is
     *          cleared.
     *
     * @return              The flags added to the listener by the associated
     *                      event source.
     *
     * @iclass
     */
    flagsmask_t getAndClearFlagsI(void);
  };
  /*------------------------------------------------------------------------*
   * chibios_rt::EvtSource                                                  *
   *------------------------------------------------------------------------*/
  /**
   * @brief   Class encapsulating an event source.
   */
  class EvtSource {
  public:
    /**
     * @brief   Embedded @p ::EventSource structure.
     */
    struct ::EventSource ev_source;
    /**
     * @brief   EvtSource object constructor.
     * @details The embedded @p ::EventSource structure is initialized.
     *
     * @init
     */
    EvtSource(void);
    /**
     * @brief   Registers a listener on the event source.
     *
     * @param[in] elp           pointer to the @p EvtListener object
     * @param[in] eid           numeric identifier assigned to the Event
     *                          Listener
     *
     * @api
     */
    void registerOne(chibios_rt::EvtListener *elp, eventid_t eid);
    /**
     * @brief   Registers an Event Listener on an Event Source.
     * @note    Multiple Event Listeners can specify the same bits to be added.
     *
     * @param[in] elp           pointer to the @p EvtListener object
     * @param[in] emask         the mask of event flags to be pended to the
     *                          thread when the event source is broadcasted
     *
     * @api
     */
    void registerMask(chibios_rt::EvtListener *elp, eventmask_t emask);
    /**
     * @brief   Unregisters a listener.
     * @details The specified listeners is no more signaled by the event
     *          source.
     *
     * @param[in] elp           the listener to be unregistered
     *
     * @api
     */
    void unregister(chibios_rt::EvtListener *elp);
    /**
     * @brief   Broadcasts on an event source.
     * @details All the listeners registered on the event source are signaled
     *          and the flags are added to the listener's flags mask.
     *
     * @param[in] flags         the flags set to be added to the listener
     *                          flags mask
     *
     * @api
     */
    void broadcastFlags(flagsmask_t flags);
    /**
     * @brief   Broadcasts on an event source.
     * @details All the listeners registered on the event source are signaled
     *          and the flags are added to the listener's flags mask.
     *
     * @param[in] flags         the flags set to be added to the listener
     *                          flags mask
     *
     * @iclass
     */
    void broadcastFlagsI(flagsmask_t flags);
  };
#endif /* CH_USE_EVENTS */
#if CH_USE_QUEUES || defined(__DOXYGEN__)
  /*------------------------------------------------------------------------*
   * chibios_rt::InQueue                                                    *
   *------------------------------------------------------------------------*/
  /**
   * @brief   Class encapsulating an input queue.
   */
  class InQueue {
  private:
    /**
     * @brief   Embedded @p ::InputQueue structure.
     */
    ::InputQueue iq;
  public:
    /**
     * @brief   InQueue constructor.
     *
     * @param[in] bp        pointer to a memory area allocated as queue buffer
     * @param[in] size      size of the queue buffer
     * @param[in] infy      pointer to a callback function that is invoked when
     *                      data is read from the queue. The value can be
     *                      @p NULL.
     * @param[in] link      application defined pointer
     *
     * @init
     */
    InQueue(uint8_t *bp, size_t size, qnotify_t infy, void *link);
    /**
     * @brief   Returns the filled space into an input queue.
     *
     * @return              The number of full bytes in the queue.
     * @retval 0            if the queue is empty.
     *
     * @iclass
     */
    size_t getFullI(void);
    /**
     * @brief   Returns the empty space into an input queue.
     *
     * @return              The number of empty bytes in the queue.
     * @retval 0            if the queue is full.
     *
     * @iclass
     */
    size_t getEmptyI(void);
    /**
     * @brief   Evaluates to @p TRUE if the specified input queue is empty.
     *
     * @return              The queue status.
     * @retval false        if the queue is not empty.
     * @retval true         if the queue is empty.
     *
     * @iclass
     */
    bool isEmptyI(void);
    /**
     * @brief   Evaluates to @p TRUE if the specified input queue is full.
     *
     * @return              The queue status.
     * @retval FALSE        if the queue is not full.
     * @retval TRUE         if the queue is full.
     *
     * @iclass
     */
    bool isFullI(void);
    /**
     * @brief   Resets an input queue.
     * @details All the data in the input queue is erased and lost, any waiting
     *          thread is resumed with status @p Q_RESET.
     * @note    A reset operation can be used by a low level driver in order to
     *          obtain immediate attention from the high level layers.
     * @iclass
     */
    void resetI(void);
    /**
     * @brief   Input queue write.
     * @details A byte value is written into the low end of an input queue.
     *
     * @param[in] b         the byte value to be written in the queue
     * @return              The operation status.
     * @retval Q_OK         if the operation has been completed with success.
     * @retval Q_FULL       if the queue is full and the operation cannot be
     *                      completed.
     *
     * @iclass
     */
    msg_t putI(uint8_t b);
    /**
     * @brief   Input queue read.
     * @details This function reads a byte value from an input queue. If the
     *          queue is empty then the calling thread is suspended until a
     *          byte arrives in the queue.
     *
     * @return              A byte value from the queue.
     * @retval Q_RESET      if the queue has been reset.
     *
     * @api
     */
    msg_t get();
    /**
     * @brief   Input queue read with timeout.
     * @details This function reads a byte value from an input queue. If the
     *          queue is empty then the calling thread is suspended until a
     *          byte arrives in the queue or a timeout occurs.
     * @note    The callback is invoked before reading the character from the
     *          buffer or before entering the state @p THD_STATE_WTQUEUE.
     *
     * @param[in] time      the number of ticks before the operation timeouts,
     *                      the following special values are allowed:
     *                      - @a TIME_IMMEDIATE immediate timeout.
     *                      - @a TIME_INFINITE no timeout.
     *                      .
     * @return              A byte value from the queue.
     * @retval Q_TIMEOUT    if the specified time expired.
     * @retval Q_RESET      if the queue has been reset.
     *
     * @api
     */
    msg_t getTimeout(systime_t time);
    /**
     * @brief   Input queue read with timeout.
     * @details The function reads data from an input queue into a buffer. The
     *          operation completes when the specified amount of data has been
     *          transferred or after the specified timeout or if the queue has
     *          been reset.
     * @note    The function is not atomic, if you need atomicity it is
     *          suggested to use a semaphore or a mutex for mutual exclusion.
     * @note    The callback is invoked before reading each character from the
     *          buffer or before entering the state @p THD_STATE_WTQUEUE.
     *
     * @param[out] bp       pointer to the data buffer
     * @param[in] n         the maximum amount of data to be transferred, the
     *                      value 0 is reserved
     * @param[in] time      the number of ticks before the operation timeouts,
     *                      the following special values are allowed:
     *                      - @a TIME_IMMEDIATE immediate timeout.
     *                      - @a TIME_INFINITE no timeout.
     *                      .
     * @return              The number of bytes effectively transferred.
     *
     * @api
     */
    size_t readTimeout(uint8_t *bp, size_t n, systime_t time);
  };
  /*------------------------------------------------------------------------*
   * chibios_rt::InQueueBuffer                                              *
   *------------------------------------------------------------------------*/
  /**
   * @brief   Template class encapsulating an input queue and its buffer.
   *
   * @param N                   size of the input queue
   */
  template 
  class InQueueBuffer : public InQueue {
  private:
    uint8_t iq_buf[N];
  public:
    /**
     * @brief   InQueueBuffer constructor.
     *
     * @param[in] infy      input notify callback function
     * @param[in] link      parameter to be passed to the callback
     *
     * @init
     */
    InQueueBuffer(qnotify_t infy, void *link) : InQueue(iq_buf, N,
                                                        infy, link) {
    }
  };
  /*------------------------------------------------------------------------*
   * chibios_rt::OutQueue                                                   *
   *------------------------------------------------------------------------*/
  /**
   * @brief   Class encapsulating an output queue.
   */
  class OutQueue {
  private:
    /**
     * @brief   Embedded @p ::OutputQueue structure.
     */
    ::OutputQueue oq;
  public:
    /**
     * @brief   OutQueue constructor.
     *
     * @param[in] bp        pointer to a memory area allocated as queue buffer
     * @param[in] size      size of the queue buffer
     * @param[in] onfy      pointer to a callback function that is invoked when
     *                      data is written to the queue. The value can be
     *                      @p NULL.
     * @param[in] link      application defined pointer
     *
     * @init
     */
    OutQueue(uint8_t *bp, size_t size, qnotify_t onfy, void *link);
    /**
     * @brief   Returns the filled space into an output queue.
     *
     * @return              The number of full bytes in the queue.
     * @retval 0            if the queue is empty.
     *
     * @iclass
     */
    size_t getFullI(void);
    /**
     * @brief   Returns the empty space into an output queue.
     *
     * @return              The number of empty bytes in the queue.
     * @retval 0            if the queue is full.
     *
     * @iclass
     */
    size_t getEmptyI(void);
    /**
     * @brief   Evaluates to @p TRUE if the specified output queue is empty.
     *
     * @return              The queue status.
     * @retval false        if the queue is not empty.
     * @retval true         if the queue is empty.
     *
     * @iclass
     */
    bool isEmptyI(void);
    /**
     * @brief   Evaluates to @p TRUE if the specified output queue is full.
     *
     * @return              The queue status.
     * @retval FALSE        if the queue is not full.
     * @retval TRUE         if the queue is full.
     *
     * @iclass
     */
    bool isFullI(void);
    /**
     * @brief   Resets an output queue.
     * @details All the data in the output queue is erased and lost, any
     *          waiting thread is resumed with status @p Q_RESET.
     * @note    A reset operation can be used by a low level driver in order
     *          to obtain immediate attention from the high level layers.
     *
     * @iclass
     */
    void resetI(void);
    /**
     * @brief   Output queue write.
     * @details This function writes a byte value to an output queue. If the
     *          queue is full then the calling thread is suspended until there
     *          is space in the queue.
     *
     * @param[in] b         the byte value to be written in the queue
     * @return              The operation status.
     * @retval Q_OK         if the operation succeeded.
     * @retval Q_RESET      if the queue has been reset.
     *
     * @api
     */
    msg_t put(uint8_t b);
    /**
     * @brief   Output queue write with timeout.
     * @details This function writes a byte value to an output queue. If the
     *          queue is full then the calling thread is suspended until there
     *          is space in the queue or a timeout occurs.
     * @note    The callback is invoked after writing the character into the
     *          buffer.
     *
     * @param[in] b         the byte value to be written in the queue
     * @param[in] time      the number of ticks before the operation timeouts,
     *                      the following special values are allowed:
     *                      - @a TIME_IMMEDIATE immediate timeout.
     *                      - @a TIME_INFINITE no timeout.
     *                      .
     * @return              The operation status.
     * @retval Q_OK         if the operation succeeded.
     * @retval Q_TIMEOUT    if the specified time expired.
     * @retval Q_RESET      if the queue has been reset.
     *
     * @api
     */
    msg_t putTimeout(uint8_t b, systime_t time);
    /**
     * @brief   Output queue read.
     * @details A byte value is read from the low end of an output queue.
     *
     * @return              The byte value from the queue.
     * @retval Q_EMPTY      if the queue is empty.
     *
     * @iclass
     */
    msg_t getI(void);
    /**
     * @brief   Output queue write with timeout.
     * @details The function writes data from a buffer to an output queue. The
     *          operation completes when the specified amount of data has been
     *          transferred or after the specified timeout or if the queue has
     *          been reset.
     * @note    The function is not atomic, if you need atomicity it is
     *          suggested to use a semaphore or a mutex for mutual exclusion.
     * @note    The callback is invoked after writing each character into the
     *          buffer.
     *
     * @param[out] bp       pointer to the data buffer
     * @param[in] n         the maximum amount of data to be transferred, the
     *                      value 0 is reserved
     * @param[in] time      the number of ticks before the operation timeouts,
     *                      the following special values are allowed:
     *                      - @a TIME_IMMEDIATE immediate timeout.
     *                      - @a TIME_INFINITE no timeout.
     *                      .
     * @return              The number of bytes effectively transferred.
     *
     * @api
     */
    size_t writeTimeout(const uint8_t *bp, size_t n, systime_t time);
};
  /*------------------------------------------------------------------------*
   * chibios_rt::OutQueueBuffer                                             *
   *------------------------------------------------------------------------*/
  /**
   * @brief   Template class encapsulating an output queue and its buffer.
   *
   * @param N                   size of the output queue
   */
  template 
  class OutQueueBuffer : public OutQueue {
  private:
    uint8_t oq_buf[N];
  public:
    /**
     * @brief   OutQueueBuffer constructor.
     *
     * @param[in] onfy      output notify callback function
     * @param[in] link      parameter to be passed to the callback
     *
     * @init
     */
    OutQueueBuffer(qnotify_t onfy, void *link) : OutQueue(oq_buf, N,
                                                          onfy, link) {
    }
  };
#endif /* CH_USE_QUEUES */
#if CH_USE_MAILBOXES || defined(__DOXYGEN__)
  /*------------------------------------------------------------------------*
   * chibios_rt::Mailbox                                                    *
   *------------------------------------------------------------------------*/
  /**
   * @brief   Class encapsulating a mailbox.
   */
  class Mailbox {
  public:
    /**
     * @brief   Embedded @p ::Mailbox structure.
     */
    ::Mailbox mb;
    /**
     * @brief   Mailbox constructor.
     * @details The embedded @p ::Mailbox structure is initialized.
     *
     * @param[in] buf           pointer to the messages buffer as an array of
     *                          @p msg_t
     * @param[in] n             number of elements in the buffer array
     *
     * @init
     */
    Mailbox(msg_t *buf, cnt_t n);
    /**
     * @brief   Resets a Mailbox object.
     * @details All the waiting threads are resumed with status @p RDY_RESET
     *          and the queued messages are lost.
     *
     * @api
     */
    void reset(void);
    /**
     * @brief   Posts a message into a mailbox.
     * @details The invoking thread waits until a empty slot in the mailbox
     *          becomes available or the specified time runs out.
     *
     * @param[in] msg       the message to be posted on the mailbox
     * @param[in] time      the number of ticks before the operation timeouts,
     *                      the following special values are allowed:
     *                      - @a TIME_IMMEDIATE immediate timeout.
     *                      - @a TIME_INFINITE no timeout.
     *                      .
     * @return              The operation status.
     * @retval RDY_OK       if a message has been correctly posted.
     * @retval RDY_RESET    if the mailbox has been reset while waiting.
     * @retval RDY_TIMEOUT  if the operation has timed out.
     *
     * @api
     */
    msg_t post(msg_t msg, systime_t time);
    /**
     * @brief   Posts a message into a mailbox.
     * @details The invoking thread waits until a empty slot in the mailbox
     *          becomes available or the specified time runs out.
     *
     * @param[in] msg       the message to be posted on the mailbox
     * @param[in] time      the number of ticks before the operation timeouts,
     *                      the following special values are allowed:
     *                      - @a TIME_IMMEDIATE immediate timeout.
     *                      - @a TIME_INFINITE no timeout.
     *                      .
     * @return              The operation status.
     * @retval RDY_OK       if a message has been correctly posted.
     * @retval RDY_RESET    if the mailbox has been reset while waiting.
     * @retval RDY_TIMEOUT  if the operation has timed out.
     *
     * @sclass
     */
    msg_t postS(msg_t msg, systime_t time);
    /**
     * @brief   Posts a message into a mailbox.
     * @details This variant is non-blocking, the function returns a timeout
     *          condition if the queue is full.
     *
     * @param[in] msg       the message to be posted on the mailbox
     * @return              The operation status.
     * @retval RDY_OK       if a message has been correctly posted.
     * @retval RDY_TIMEOUT  if the mailbox is full and the message cannot be
     *                      posted.
     *
     * @iclass
     */
    msg_t postI(msg_t msg);
    /**
     * @brief   Posts an high priority message into a mailbox.
     * @details The invoking thread waits until a empty slot in the mailbox
     *          becomes available or the specified time runs out.
     *
     * @param[in] msg       the message to be posted on the mailbox
     * @param[in] time      the number of ticks before the operation timeouts,
     *                      the following special values are allowed:
     *                      - @a TIME_IMMEDIATE immediate timeout.
     *                      - @a TIME_INFINITE no timeout.
     *                      .
     * @return              The operation status.
     * @retval RDY_OK       if a message has been correctly posted.
     * @retval RDY_RESET    if the mailbox has been reset while waiting.
     * @retval RDY_TIMEOUT  if the operation has timed out.
     *
     * @api
     */
    msg_t postAhead(msg_t msg, systime_t time);
    /**
     * @brief   Posts an high priority message into a mailbox.
     * @details The invoking thread waits until a empty slot in the mailbox
     *          becomes available or the specified time runs out.
     *
     * @param[in] msg       the message to be posted on the mailbox
     * @param[in] time      the number of ticks before the operation timeouts,
     *                      the following special values are allowed:
     *                      - @a TIME_IMMEDIATE immediate timeout.
     *                      - @a TIME_INFINITE no timeout.
     *                      .
     * @return              The operation status.
     * @retval RDY_OK       if a message has been correctly posted.
     * @retval RDY_RESET    if the mailbox has been reset while waiting.
     * @retval RDY_TIMEOUT  if the operation has timed out.
     *
     * @sclass
     */
    msg_t postAheadS(msg_t msg, systime_t time);
    /**
     * @brief   Posts an high priority message into a mailbox.
     * @details This variant is non-blocking, the function returns a timeout
     *          condition if the queue is full.
     *
     * @param[in] msg       the message to be posted on the mailbox
     * @return              The operation status.
     * @retval RDY_OK       if a message has been correctly posted.
     * @retval RDY_TIMEOUT  if the mailbox is full and the message cannot be
     *                      posted.
     *
     * @iclass
     */
    msg_t postAheadI(msg_t msg);
    /**
     * @brief   Retrieves a message from a mailbox.
     * @details The invoking thread waits until a message is posted in the
     *          mailbox or the specified time runs out.
     *
     * @param[out] msgp     pointer to a message variable for the received
     * @param[in] time      message the number of ticks before the operation
     *                      timeouts, the following special values are allowed:
     *                      - @a TIME_IMMEDIATE immediate timeout.
     *                      - @a TIME_INFINITE no timeout.
     *                      .
     * @return              The operation status.
     * @retval RDY_OK       if a message has been correctly fetched.
     * @retval RDY_RESET    if the mailbox has been reset while waiting.
     * @retval RDY_TIMEOUT  if the operation has timed out.
     *
     * @api
     */
    msg_t fetch(msg_t *msgp, systime_t time);
    /**
     * @brief   Retrieves a message from a mailbox.
     * @details The invoking thread waits until a message is posted in the
     *          mailbox or the specified time runs out.
     *
     * @param[out] msgp     pointer to a message variable for the received
     * @param[in] time      message the number of ticks before the operation
     *                      timeouts, the following special values are allowed:
     *                      - @a TIME_IMMEDIATE immediate timeout.
     *                      - @a TIME_INFINITE no timeout.
     *                      .
     * @return              The operation status.
     * @retval RDY_OK       if a message has been correctly fetched.
     * @retval RDY_RESET    if the mailbox has been reset while waiting.
     * @retval RDY_TIMEOUT  if the operation has timed out.
     *
     * @sclass
     */
    msg_t fetchS(msg_t *msgp, systime_t time);
    /**
     * @brief   Retrieves a message from a mailbox.
     * @details This variant is non-blocking, the function returns a timeout
     *          condition if the queue is empty.
     *
     * @param[out] msgp     pointer to a message variable for the received
     *                      message
     * @return              The operation status.
     * @retval RDY_OK       if a message has been correctly fetched.
     * @retval RDY_TIMEOUT  if the mailbox is empty and a message cannot be
     *                      fetched.
     *
     * @iclass
     */
    msg_t fetchI(msg_t *msgp);
    /**
     * @brief   Returns the number of free message slots into a mailbox.
     * @note    Can be invoked in any system state but if invoked out of a
     *          locked state then the returned value may change after reading.
     * @note    The returned value can be less than zero when there are waiting
     *          threads on the internal semaphore.
     *
     * @return              The number of empty message slots.
     *
     * @iclass
     */
    cnt_t getFreeCountI(void);
    /**
     * @brief   Returns the number of used message slots into a mailbox.
     * @note    Can be invoked in any system state but if invoked out of a
     *          locked state then the returned value may change after reading.
     * @note    The returned value can be less than zero when there are waiting
     *          threads on the internal semaphore.
     *
     * @return              The number of queued messages.
     *
     * @iclass
     */
    cnt_t getUsedCountI(void);
  };
  /*------------------------------------------------------------------------*
   * chibios_rt::MailboxBuffer                                              *
   *------------------------------------------------------------------------*/
  /**
   * @brief   Template class encapsulating a mailbox and its messages buffer.
   *
   * @param N                   size of the mailbox
   */
  template 
  class MailboxBuffer : public Mailbox {
  private:
    msg_t   mb_buf[N];
  public:
    /**
     * @brief   BufferMailbox constructor.
     *
     * @init
     */
    MailboxBuffer(void) : Mailbox(mb_buf,
                                  (cnt_t)(sizeof mb_buf / sizeof (msg_t))) {
    }
  };
#endif /* CH_USE_MAILBOXES */
#if CH_USE_MEMPOOLS || defined(__DOXYGEN__)
  /*------------------------------------------------------------------------*
   * chibios_rt::MemoryPool                                                 *
   *------------------------------------------------------------------------*/
  /**
   * @brief   Class encapsulating a mailbox.
   */
  class MemoryPool {
  public:
    /**
     * @brief   Embedded @p ::MemoryPool structure.
     */
    ::MemoryPool pool;
    /**
     * @brief   MemoryPool constructor.
     *
     * @param[in] size      the size of the objects contained in this memory
     *                      pool, the minimum accepted size is the size of
     *                      a pointer to void.
     * @param[in] provider  memory provider function for the memory pool or
     *                      @p NULL if the pool is not allowed to grow
     *                      automatically
     *
     * @init
     */
    MemoryPool(size_t size, memgetfunc_t provider);
    /**
     * @brief   MemoryPool constructor.
     *
     * @param[in] size      the size of the objects contained in this memory
     *                      pool, the minimum accepted size is the size of
     *                      a pointer to void.
     * @param[in] provider  memory provider function for the memory pool or
     *                      @p NULL if the pool is not allowed to grow
     *                      automatically
     * @param[in] p         pointer to the array first element
     * @param[in] n         number of elements in the array
     *
     * @init
     */
    MemoryPool(size_t size, memgetfunc_t provider, void* p, size_t n);
    /**
     * @brief   Loads a memory pool with an array of static objects.
     * @pre     The memory pool must be already been initialized.
     * @pre     The array elements must be of the right size for the specified
     *          memory pool.
     * @post    The memory pool contains the elements of the input array.
     *
     * @param[in] p         pointer to the array first element
     * @param[in] n         number of elements in the array
     *
     * @api
     */
    void loadArray(void *p, size_t n);
    /**
     * @brief   Allocates an object from a memory pool.
     * @pre     The memory pool must be already been initialized.
     *
     * @return              The pointer to the allocated object.
     * @retval NULL         if pool is empty.
     *
     * @iclass
     */
    void *allocI(void);
    /**
     * @brief   Allocates an object from a memory pool.
     * @pre     The memory pool must be already been initialized.
     *
     * @return              The pointer to the allocated object.
     * @retval NULL         if pool is empty.
     *
     * @api
     */
    void *alloc(void);
    /**
     * @brief   Releases an object into a memory pool.
     * @pre     The memory pool must be already been initialized.
     * @pre     The freed object must be of the right size for the specified
     *          memory pool.
     * @pre     The object must be properly aligned to contain a pointer to
     *          void.
     *
     * @param[in] objp      the pointer to the object to be released
     *
     * @iclass
     */
    void free(void *objp);
    /**
     * @brief   Adds an object to a memory pool.
     * @pre     The memory pool must be already been initialized.
     * @pre     The added object must be of the right size for the specified
     *          memory pool.
     * @pre     The added object must be memory aligned to the size of
     *          @p stkalign_t type.
     * @note    This function is just an alias for @p chPoolFree() and has been
     *          added for clarity.
     *
     * @param[in] objp      the pointer to the object to be added
     *
     * @iclass
     */
    void freeI(void *objp);
  };
  /*------------------------------------------------------------------------*
   * chibios_rt::ObjectsPool                                                *
   *------------------------------------------------------------------------*/
  /**
   * @brief   Template class encapsulating a memory pool and its elements.
   */
  template
  class ObjectsPool : public MemoryPool {
  private:
    /* The buffer is declared as an array of pointers to void for two
       reasons:
       1) The objects must be properly aligned to hold a pointer as
          first field.
       2) There is no need to invoke constructors for object that are
          into the pool.*/
    void *pool_buf[(N * sizeof (T)) / sizeof (void *)];
  public:
    /**
     * @brief   ObjectsPool constructor.
     *
     * @init
     */
    ObjectsPool(void) : MemoryPool(sizeof (T), NULL) {
      loadArray(pool_buf, N);
    }
  };
#endif /* CH_USE_MEMPOOLS */
  /*------------------------------------------------------------------------*
   * chibios_rt::BaseSequentialStreamInterface                              *
   *------------------------------------------------------------------------*/
  /**
   * @brief   Interface of a ::BaseSequentialStream.
   * @note    You can cast a ::BaseSequentialStream to this interface and use
   *          it, the memory layout is the same.
   */
  class BaseSequentialStreamInterface {
  public:
    /**
     * @brief   Sequential Stream write.
     * @details The function writes data from a buffer to a stream.
     *
     * @param[in] bp        pointer to the data buffer
     * @param[in] n         the maximum amount of data to be transferred
     * @return              The number of bytes transferred. The return value
     *                      can be less than the specified number of bytes if
     *                      an end-of-file condition has been met.
     *
     * @api
     */
    virtual size_t write(const uint8_t *bp, size_t n) = 0;
    /**
     * @brief   Sequential Stream read.
     * @details The function reads data from a stream into a buffer.
     *
     * @param[out] bp       pointer to the data buffer
     * @param[in] n         the maximum amount of data to be transferred
     * @return              The number of bytes transferred. The return value
     *                      can be less than the specified number of bytes if
     *                      an end-of-file condition has been met.
     *
     * @api
     */
    virtual size_t read(uint8_t *bp, size_t n) = 0;
    /**
     * @brief   Sequential Stream blocking byte write.
     * @details This function writes a byte value to a channel. If the channel
     *          is not ready to accept data then the calling thread is
     *          suspended.
     *
     * @param[in] b         the byte value to be written to the channel
     *
     * @return              The operation status.
     * @retval Q_OK         if the operation succeeded.
     * @retval Q_RESET      if an end-of-file condition has been met.
     *
     * @api
     */
    virtual msg_t put(uint8_t b) = 0;
    /**
     * @brief   Sequential Stream blocking byte read.
     * @details This function reads a byte value from a channel. If the data
     *          is not available then the calling thread is suspended.
     *
     * @return              A byte value from the queue.
     * @retval Q_RESET      if an end-of-file condition has been met.
     *
     * @api
     */
    virtual msg_t get(void) = 0;
  };
}
#endif /* _CH_HPP_ */
/** @} */