From 810cd7514051b11eaaf93e3ffcba0c7195a6b89b Mon Sep 17 00:00:00 2001
From: gdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>
Date: Wed, 26 Mar 2008 16:25:26 +0000
Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@247
 35acf78f-673a-0410-8e92-d51de3d6d3f4

---
 readme.txt           |   9 ++
 src/include/events.h |   4 +-
 src/lib/ch.cpp       | 266 +++++++++++++++++++++++++++++++++++++++++++
 src/lib/ch.hpp       | 310 +++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 587 insertions(+), 2 deletions(-)
 create mode 100644 src/lib/ch.cpp
 create mode 100644 src/lib/ch.hpp

diff --git a/readme.txt b/readme.txt
index b748143bc..52554c513 100644
--- a/readme.txt
+++ b/readme.txt
@@ -61,9 +61,18 @@ Win32-MinGW            - ChibiOS/RT simulator and demo into a WIN32 process,
 *****************************************************************************
 
 *** 0.6.2 ***
+- NEW: Added C++ wrapper around the ChibiOS/RT core APIs, now it is possible
+  to use the OS in a fully object oriented application. The wrapper offers
+  classes that encapsulate threads, semaphores, mutexes, timers etc. Normal C
+  APIs are still accessible from C++ code as usual.
+- NEW: Added a new LPC2148 demo using the new C++ wrapper, it is a good
+  example of C++ used for an embedded application. The demo does not use RTTI
+  nor standard libraries so the resulting code is very compact.
 - Fixed a minor problem in the ARM7 port, the extctx structure definition was
   missing one field, the effect was to allocate stacks 4 bytes shorter than
   the declared size.
+- Fixed a compile time error into the chThdSleepUntil() macro.
+- Fixes in various headers to make some macros compatible with both C and C++.
 - More work on the ARM-CM3 port but it is still not complete.
 
 *** 0.6.1 ***
diff --git a/src/include/events.h b/src/include/events.h
index 5bcb70e84..30fa50ccb 100644
--- a/src/include/events.h
+++ b/src/include/events.h
@@ -61,7 +61,7 @@ typedef struct EventSource {
  * @note Can be called with interrupts disabled or enabled.
  */
 #define chEvtInit(esp) \
-        ((esp)->es_next = (void *)(esp))
+        ((esp)->es_next = (EventListener *)(void *)(esp))
 
 /**
  * Verifies if there is at least one \p EventListener registered on the
@@ -70,7 +70,7 @@ typedef struct EventSource {
  * @note Can be called with interrupts disabled or enabled.
  */
 #define chEvtIsListening(esp) \
-                ((esp) != (void *)(esp)->es_next)
+                ((esp) != (EventListener *)(void *)(esp)->es_next)
 
 
 /** Event Handler callback function.*/
diff --git a/src/lib/ch.cpp b/src/lib/ch.cpp
new file mode 100644
index 000000000..ad4be5f4d
--- /dev/null
+++ b/src/lib/ch.cpp
@@ -0,0 +1,266 @@
+/*
+    ChibiOS/RT - Copyright (C) 2006-2007 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 <http://www.gnu.org/licenses/>.
+*/
+
+#include <ch.hpp>
+
+namespace chibios_rt {
+
+  /*------------------------------------------------------------------------*
+   * chibios_rt::System                                                     *
+   *------------------------------------------------------------------------*/
+  void System::Init(void) {
+
+    chSysInit();
+  }
+
+  void Lock(void) {
+
+    chSysLock();
+  }
+
+  void Unlock(void) {
+
+    chSysUnlock();
+  }
+
+#ifdef CH_USE_SYSTEMTIME
+  systime_t System::GetTime(void) {
+
+    return chSysGetTime();
+  }
+#endif /* CH_USE_SYSTEMTIME */
+
+#ifdef CH_USE_VIRTUAL_TIMERS
+  /*------------------------------------------------------------------------*
+   * chibios_rt::Timer                                                      *
+   *------------------------------------------------------------------------*/
+  void Timer::Set(systime_t time, vtfunc_t vtfunc, void *par) {
+
+    chVTSetI(&timer, time, vtfunc, par);
+  }
+
+  void Timer::Reset() {
+
+    chVTResetI(&timer);
+  }
+
+  bool Timer::IsArmed(void) {
+
+    return chVTIsArmedI(&timer);
+  }
+#endif /* CH_USE_VIRTUAL_TIMER */
+
+  /*------------------------------------------------------------------------*
+   * chibios_rt::BaseThread                                                 *
+   *------------------------------------------------------------------------*/
+  static msg_t thdstart(void *arg) {
+    BaseThread *btp = (BaseThread *)arg;
+
+    return btp->Main();
+  }
+
+  BaseThread::BaseThread(tprio_t prio, tmode_t mode, void *workspace, size_t wsize) {
+    msg_t thdstart(void *arg);
+
+    thread_ref = chThdCreate(prio, mode, workspace, wsize, thdstart, this);
+  }
+
+  void BaseThread::Exit(msg_t msg) {
+
+    chThdExit(msg);
+  }
+
+#ifdef CH_USE_WAITEXIT
+  msg_t BaseThread::Wait(void) {
+
+    return chThdWait(thread_ref);
+  }
+#endif /* CH_USE_WAITEXIT */
+
+  void BaseThread::SetPriority(tprio_t newprio) {
+
+    chThdSetPriority(newprio);
+  }
+
+#ifdef CH_USE_RESUME
+  void BaseThread::Resume(void) {
+
+    chThdResume(thread_ref);
+  }
+#endif /* CH_USE_RESUME */
+
+#ifdef CH_USE_TERMINATE
+  void BaseThread::Terminate(void) {
+
+    chThdTerminate(thread_ref);
+  }
+#endif /* CH_USE_TERMINATE */
+
+#ifdef CH_USE_SLEEP
+  void BaseThread::Sleep(systime_t n) {
+
+    chThdSleep(n);
+  }
+
+#ifdef CH_USE_SYSTEMTIME
+  void BaseThread::SleepUntil(systime_t time) {
+
+    chThdSleepUntil(time);
+  }
+#endif /* CH_USE_SYSTEMTIME */
+#endif /* CH_USE_SLEEP */
+
+#ifdef CH_USE_MESSAGES
+  msg_t BaseThread::SendMessage(msg_t msg) {
+
+    return chMsgSend(thread_ref, msg);
+  }
+
+  msg_t BaseThread::WaitMessage(void) {
+
+    return chMsgWait();
+  }
+
+  msg_t BaseThread::GetMessage(void) {
+
+    return chMsgGet();
+  }
+
+  void BaseThread::ReleaseMessage(msg_t msg) {
+
+    chMsgRelease(msg);
+  }
+
+  bool BaseThread::IsPendingMessage(void) {
+
+    return chMsgIsPendingI(thread_ref);
+  }
+#endif /* CH_USE_MESSAGES */
+
+  msg_t BaseThread::Main(void) {
+
+    return 0;
+  }
+
+#ifdef CH_USE_SEMAPHORES
+  /*------------------------------------------------------------------------*
+   * chibios_rt::Semaphore                                                  *
+   *------------------------------------------------------------------------*/
+  Semaphore::Semaphore(cnt_t n) {
+
+    chSemInit(&sem, n);
+  }
+
+  void Semaphore::Reset(cnt_t n) {
+
+    chSemReset(&sem, n);
+  }
+
+  msg_t Semaphore::Wait(void) {
+
+    return chSemWait(&sem);
+  }
+
+#ifdef CH_USE_SEMAPHORES_TIMEOUT
+  msg_t Semaphore::WaitTimeout(systime_t time) {
+
+    return chSemWaitTimeout(&sem, time);
+  }
+#endif /* CH_USE_SEMAPHORES_TIMEOUT */
+
+  void Semaphore::Signal(void) {
+
+    chSemSignal(&sem);
+  }
+#endif /* CH_USE_SEMAPHORES */
+
+#ifdef CH_USE_MUTEXES
+  /*------------------------------------------------------------------------*
+   * chibios_rt::Mutex                                                      *
+   *------------------------------------------------------------------------*/
+  Mutex::Mutex(void) {
+
+    chMtxInit(&mutex);
+  }
+
+  bool Mutex::TryLock(void) {
+
+    return chMtxTryLock(&mutex);
+  }
+
+  void Mutex::Lock(void) {
+
+    chMtxLock(&mutex);
+  }
+
+  void Mutex::Unlock(void) {
+
+    chMtxUnlock();
+  }
+
+  void UnlockAll(void) {
+
+    chMtxUnlockAll();
+  }
+#endif /* CH_USE_MUTEXES */
+
+#ifdef CH_USE_EVENTS
+  /*------------------------------------------------------------------------*
+   * chibios_rt::Event                                                      *
+   *------------------------------------------------------------------------*/
+  Event::Event(void) {
+
+    chEvtInit(&event);
+  }
+
+  void Event::Register(EventListener *elp, eventid_t eid) {
+
+    chEvtRegister(&event,elp, eid);
+  }
+
+  void Event::Unregister(EventListener *elp) {
+
+    chEvtUnregister(&event, elp);
+  }
+
+  void Event::Send(void) {
+
+    chEvtSend(&event);
+  }
+
+  void Event::Clear(eventmask_t mask) {
+
+    chEvtClear(mask);
+  }
+
+  eventid_t Event::Wait(eventmask_t ewmask, const evhandler_t handlers[]) {
+
+    return chEvtWait(ewmask, handlers);
+  }
+
+#ifdef CH_USE_EVENTS_TIMEOUT
+  eventid_t Event::WaitTimeout(eventmask_t ewmask,
+                               const evhandler_t handlers[],
+                               systime_t time) {
+
+    return chEvtWaitTimeout(ewmask, handlers, time);
+  }
+#endif /* CH_USE_EVENTS_TIMEOUT */
+#endif /* CH_USE_EVENTS */
+}
diff --git a/src/lib/ch.hpp b/src/lib/ch.hpp
new file mode 100644
index 000000000..9f46b757b
--- /dev/null
+++ b/src/lib/ch.hpp
@@ -0,0 +1,310 @@
+/*
+    ChibiOS/RT - Copyright (C) 2006-2007 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 <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @addtogroup CPlusPlusLibrary
+ * @{
+ */
+
+#include <ch.h>
+
+#ifndef _CH_HPP_
+#define _CH_HPP_
+
+namespace chibios_rt {
+
+  /**
+   * Class encapsulating the base system functionalities.
+   */
+  class System {
+  public:
+    /**
+     * ChibiOS/RT initialization.
+     */
+    static void Init(void);
+
+    /**
+     * Disables interrupts.
+     * @note On some ports it is faster to invoke chSysLock() directly.
+     */
+    static void Lock(void);
+    /**
+     * Enables interrupts.
+     * @note On some ports it is faster to invoke chSysUnlock() directly.
+     */
+    static void Unlock(void);
+
+#ifdef CH_USE_SYSTEMTIME
+    /**
+     * Returns the system time as system ticks.
+     */
+    static systime_t GetTime(void);
+#endif /* CH_USE_SYSTEMTIME */
+  };
+
+#ifdef CH_USE_VIRTUAL_TIMERS
+  /**
+   * Timer class.
+   */
+  class Timer {
+  public:
+    ::VirtualTimer timer;
+
+    /**
+     * Starts the timer.
+     * @note It must be called with the interrupts disabled.
+     * @note The associated function is invoked by an interrupt handler.
+     */
+    void Set(systime_t time, vtfunc_t vtfunc, void *par);
+
+    /**
+     * Resets the timer.
+     * @note It must be called with the interrupts disabled.
+     * @note The timer MUST be active when this function is invoked.
+     */
+    void Reset();
+
+    /**
+     * Returns true if the timer is armed.
+     */
+    bool IsArmed(void);
+  };
+#endif /* CH_USE_VIRTUAL_TIMER */
+
+  /**
+   * Base class for a ChibiOS/RT thread, the thread body is the virtual
+   * function /p Main().
+   */
+  class BaseThread {
+  protected:
+    /**
+     * Thread exit.
+     */
+//    __attribute__((noreturn))
+    void Exit(msg_t msg);
+
+    /**
+     * Change thread priority.
+     */
+    void SetPriority(tprio_t newprio);
+
+#ifdef CH_USE_MESSAGES
+    /**
+     * Waits for a message and returns it.
+     */
+    msg_t WaitMessage(void);
+
+    /**
+     * Returns an enqueued message or /p NULL.
+     */
+    msg_t GetMessage(void);
+
+    /**
+     * Releases the next message in queue with a reply.
+     */
+    void ReleaseMessage(msg_t msg);
+
+    /**
+     * Returns true if there is at least one message in queue.
+     */
+    bool IsPendingMessage(void);
+#endif /* CH_USE_MESSAGES */
+
+  public:
+    ::Thread *thread_ref;
+
+    /**
+     * Thread constructor.
+     */
+    BaseThread(tprio_t prio, tmode_t mode, void *workspace, size_t wsize);
+
+#ifdef CH_USE_WAITEXIT
+    /**
+     * Synchronization on Thread exit.
+     */
+    msg_t Wait(void);
+#endif /* CH_USE_WAITEXIT */
+
+#ifdef CH_USE_RESUME
+    /**
+     * Resumes thread.
+     */
+    void Resume(void);
+#endif /* CH_USE_RESUME */
+
+#ifdef CH_USE_TERMINATE
+    /**
+     * Requests thread termination.
+     */
+    void Terminate(void);
+#endif /* CH_USE_TERMINATE */
+
+#ifdef CH_USE_SLEEP
+    /**
+     * Suspends the thread execution for the specified number of system ticks.
+     */
+    void Sleep(systime_t n);
+
+#ifdef CH_USE_SYSTEMTIME
+    /**
+     * Suspends the thread execution until the specified time arrives.
+     */
+    void SleepUntil(systime_t time);
+#endif /* CH_USE_SYSTEMTIME */
+#endif /* CH_USE_SLEEP */
+
+#ifdef CH_USE_MESSAGES
+    /**
+     * Sends a message to the thread and returns the answer.
+     */
+    msg_t SendMessage(msg_t msg);
+#endif /* CH_USE_MESSAGES */
+
+    /**
+     * Thread body function.
+     */
+//    __attribute__((naked))
+    virtual msg_t Main(void);
+  };
+
+#ifdef CH_USE_SEMAPHORES
+  /**
+   * Class encapsulating a /p Semaphore.
+   */
+  class Semaphore {
+  public:
+    ::Semaphore sem;
+
+    /**
+     * Semaphore constructor.
+     */
+    Semaphore(cnt_t n);
+
+    /**
+     * Resets a semaphore to a given positive value.
+     */
+    void Reset(cnt_t n);
+
+    /**
+     * Wait operation on the semaphore.
+     */
+    msg_t Wait(void);
+
+#ifdef CH_USE_SEMAPHORES_TIMEOUT
+    /**
+     * Wait operation on the semaphore with timeout.
+     */
+    msg_t WaitTimeout(systime_t time);
+#endif /* CH_USE_SEMAPHORES_TIMEOUT */
+
+    /**
+     * Signal operation on the semaphore.
+     */
+    void Signal(void);
+  };
+#endif /* CH_USE_SEMAPHORES */
+
+#ifdef CH_USE_MUTEXES
+  /**
+   * Class encapsulating a /p Mutex.
+   */
+  class Mutex {
+  public:
+    ::Mutex mutex;
+
+    /**
+     * Mutex constructor.
+     */
+    Mutex(void);
+
+    /**
+     * Tries a lock operation on the mutex.
+     */
+    bool TryLock(void);
+
+    /**
+     * Lock operation on the mutex.
+     */
+    void Lock(void);
+
+    /**
+     * Unlock operation on the most recently locked mutex.
+     */
+    static void Unlock(void);
+
+    /**
+     * Unlocks all the mutexes owned by the invoking thread.
+     */
+    static void UnlockAll(void);
+  };
+#endif /* CH_USE_MUTEXES */
+
+#ifdef CH_USE_EVENTS
+  /**
+   * Class encapsulating an /p EventSource.
+   */
+  class Event {
+  public:
+    EventSource event;
+
+    /**
+     * Event constructor.
+     */
+    Event(void);
+
+    /**
+     * Registers a listener on the event source.
+     */
+    void Register(EventListener *elp, eventid_t eid);
+
+    /**
+     * Unregisters a listener from the event source.
+     */
+    void Unregister(EventListener *elp);
+
+    /**
+     * Sends an event.
+     */
+    void Send(void);
+
+    /**
+     * Clears specified events from the pending events mask.
+     */
+    static void Clear(eventmask_t mask);
+
+    /**
+     * Waits and dispatchs events.
+     */
+    static eventid_t Wait(eventmask_t ewmask, const evhandler_t handlers[]);
+
+#ifdef CH_USE_EVENTS_TIMEOUT
+    /**
+     * Waits and dispatchs events with timeout specification.
+     */
+    static eventid_t WaitTimeout(eventmask_t ewmask,
+                                 const evhandler_t handlers[],
+                                 systime_t time);
+#endif /* CH_USE_EVENTS_TIMEOUT */
+  };
+#endif /* CH_USE_EVENTS */
+}
+
+#endif /* _CH_HPP_ */
+
+/** @} */
-- 
cgit v1.2.3