Simple "Blinky" example for the QP active object framework

Dependencies:   mbed qp

Fork of qp_dpp by Quantum Leaps

Files at this revision

API Documentation at this revision

Comitter:
QL
Date:
Sat Feb 12 23:22:47 2011 +0000
Child:
1:c7711e751cf6
Commit message:

Changed in this revision

bsp.cpp Show annotated file Show diff for this revision Revisions of this file
bsp.h Show annotated file Show diff for this revision Revisions of this file
dpp.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
philo.cpp Show annotated file Show diff for this revision Revisions of this file
qp.lib Show annotated file Show diff for this revision Revisions of this file
qp_config.h Show annotated file Show diff for this revision Revisions of this file
table.cpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bsp.cpp	Sat Feb 12 23:22:47 2011 +0000
@@ -0,0 +1,253 @@
+//////////////////////////////////////////////////////////////////////////////
+// Product: BSP for "Dining Philosophers Problem" example, QK kernel
+// Last Updated for Version: 4.1.06
+// Date of the Last Update:  Feb 10, 2011
+//
+//                    Q u a n t u m     L e a P s
+//                    ---------------------------
+//                    innovating embedded systems
+//
+// Copyright (C) 2002-2011 Quantum Leaps, LLC. All rights reserved.
+//
+// This software may be distributed and modified under the terms of the GNU
+// General Public License version 2 (GPL) as published by the Free Software
+// Foundation and appearing in the file GPL.TXT included in the packaging of
+// this file. Please note that GPL Section 2[b] requires that all works based
+// on this software must also be made publicly available under the terms of
+// the GPL ("Copyleft").
+//
+// Alternatively, this software may be distributed and modified under the
+// terms of Quantum Leaps commercial licenses, which expressly supersede
+// the GPL and are specifically designed for licensees interested in
+// retaining the proprietary status of their code.
+//
+// Contact information:
+// Quantum Leaps Web site:  http://www.quantum-leaps.com
+// e-mail:                  info@quantum-leaps.com
+//////////////////////////////////////////////////////////////////////////////
+#include "qp_port.h"
+#include "dpp.h"
+#include "bsp.h"
+#include "LPC17xx.h"
+
+Q_DEFINE_THIS_FILE
+
+// Local-scope objects -------------------------------------------------------
+enum ISR_Priorities {      // ISR priorities starting from the highest urgency
+    GPIOPORTA_PRIO,
+    SYSTICK_PRIO,
+    // ...
+};
+
+#define LED_PORT      LPC_GPIO1
+#define LED1_BIT     (1U << 18)
+#define LED2_BIT     (1U << 20)
+#define LED3_BIT     (1U << 21)
+#define LED4_BIT     (1U << 23)
+
+#ifdef Q_SPY
+    #include "mbed.h"             // mbed is used only for the built-in serial
+
+    QSTimeCtr l_tickTime;
+    QSTimeCtr l_tickPeriod;
+
+    #define QSPY_BAUD_RATE          115200
+
+    enum AppRecords {                    // application-specific trace records
+        PHILO_STAT = QS_USER
+    };
+
+    Serial l_qspy(USBTX, USBRX);
+#endif
+
+//............................................................................
+extern "C" void SysTick_Handler(void) {
+    QK_ISR_ENTRY();                // inform the QK kernel of entering the ISR
+
+#ifdef Q_SPY
+    uint32_t volatile dummy = SysTick->CTRL; // clear the COUNTFLAG in SysTick
+    l_tickTime += l_tickPeriod;              // account for the clock rollover
+#endif
+
+    QF::tick();                               // process all armed time events
+
+    QK_ISR_EXIT();                  // inform the QK kernel of exiting the ISR
+}
+
+//............................................................................
+void BSP_init(void) {
+    SystemInit();                            // initialize the clocking system
+
+                                                     // set LED port to output
+    LED_PORT->FIODIR |= (LED1_BIT | LED2_BIT | LED3_BIT | LED4_BIT);
+    
+                                                             // clear the LEDs
+    LED_PORT->FIOCLR  = (LED1_BIT | LED2_BIT | LED3_BIT | LED4_BIT);
+
+    if (QS_INIT((void *)0) == 0) {       // initialize the QS software tracing
+        Q_ERROR();
+    }
+}
+//............................................................................
+void BSP_displyPhilStat(uint8_t n, char const *stat) {
+                            // represent LEDs in a const array for convenience
+    static uint32_t const led[] = { LED1_BIT, LED2_BIT, LED3_BIT, LED4_BIT };
+    if (n < 3) {
+        if (stat[0] == 'e') {
+            LED_PORT->FIOSET = led[n];
+        }
+        else {
+            LED_PORT->FIOCLR = led[n];
+        }
+    }
+    
+    QS_BEGIN(PHILO_STAT, AO_Philo[n])     // application-specific record begin
+        QS_U8(1, n);                                     // Philosopher number
+        QS_STR(stat);                                    // Philosopher status
+    QS_END()
+}
+//............................................................................
+void BSP_busyDelay(void) {
+    uint32_t volatile i = 10;
+    while (i-- > 0UL) {                                      // busy-wait loop
+    }
+}
+
+//............................................................................
+void QF::onStartup(void) {
+                 // set up the SysTick timer to fire at BSP_TICKS_PER_SEC rate
+    SysTick_Config(SystemCoreClock / BSP_TICKS_PER_SEC);
+
+                          // set priorities of all interrupts in the system...
+    NVIC_SetPriority(SysTick_IRQn, SYSTICK_PRIO);
+    NVIC_SetPriority(EINT0_IRQn,   GPIOPORTA_PRIO);
+
+    NVIC_EnableIRQ(EINT0_IRQn);
+}
+//............................................................................
+void QF::onCleanup(void) {
+}
+//............................................................................
+void QK::onIdle(void) {
+
+    QF_INT_LOCK(dummy);
+    LED_PORT->FIOSET = LED4_BIT;                          // turn the LED4 on
+    LED_PORT->FIOCLR = LED4_BIT;                          // turn the LED4 off
+    QF_INT_UNLOCK(dummy);
+
+#ifdef Q_SPY
+    if (l_qspy.writeable()) {
+        QF_INT_LOCK(dummy);
+        uint16_t b = QS::getByte();
+        QF_INT_UNLOCK(dummy);
+        if (b != QS_EOD) {
+            l_qspy.putc((uint8_t)b);
+        }
+    }
+#else    
+    // put the CPU and peripherals to the low-power mode
+    // you might need to customize the clock management for your application,
+    // see the datasheet for your particular Cortex-M3 MCU. 
+    __WFI();
+#endif
+}
+
+//............................................................................
+void Q_onAssert(char const Q_ROM * const Q_ROM_VAR file, int line) {
+    (void)file;                                      // avoid compiler warning
+    (void)line;                                      // avoid compiler warning
+    QF_INT_LOCK(dummy);          // make sure that all interrupts are disabled
+                                                          // light up all LEDs
+    LED_PORT->FIOSET = (LED1_BIT | LED2_BIT | LED3_BIT | LED4_BIT);
+
+    for (;;) {          // NOTE: replace the loop with reset for final version
+    }
+}
+
+//----------------------------------------------------------------------------
+#ifdef Q_SPY
+//............................................................................
+uint8_t QS::onStartup(void const *arg) {
+    static uint8_t qsBuf[6*256];                     // buffer for Quantum Spy
+    initBuf(qsBuf, sizeof(qsBuf));
+    
+    l_qspy.baud(QSPY_BAUD_RATE);
+    
+    l_tickPeriod = SystemCoreClock / BSP_TICKS_PER_SEC;
+    l_tickTime   = l_tickPeriod;             // to start the timestamp at zero
+
+                                                    // setup the QS filters...
+    QS_FILTER_ON(QS_ALL_RECORDS);
+
+//    QS_FILTER_OFF(QS_QEP_STATE_EMPTY);
+//    QS_FILTER_OFF(QS_QEP_STATE_ENTRY);
+//    QS_FILTER_OFF(QS_QEP_STATE_EXIT);
+//    QS_FILTER_OFF(QS_QEP_STATE_INIT);
+//    QS_FILTER_OFF(QS_QEP_INIT_TRAN);
+//    QS_FILTER_OFF(QS_QEP_INTERN_TRAN);
+//    QS_FILTER_OFF(QS_QEP_TRAN);
+//    QS_FILTER_OFF(QS_QEP_IGNORED);
+
+    QS_FILTER_OFF(QS_QF_ACTIVE_ADD);
+    QS_FILTER_OFF(QS_QF_ACTIVE_REMOVE);
+    QS_FILTER_OFF(QS_QF_ACTIVE_SUBSCRIBE);
+    QS_FILTER_OFF(QS_QF_ACTIVE_UNSUBSCRIBE);
+    QS_FILTER_OFF(QS_QF_ACTIVE_POST_FIFO);
+    QS_FILTER_OFF(QS_QF_ACTIVE_POST_LIFO);
+    QS_FILTER_OFF(QS_QF_ACTIVE_GET);
+    QS_FILTER_OFF(QS_QF_ACTIVE_GET_LAST);
+    QS_FILTER_OFF(QS_QF_EQUEUE_INIT);
+    QS_FILTER_OFF(QS_QF_EQUEUE_POST_FIFO);
+    QS_FILTER_OFF(QS_QF_EQUEUE_POST_LIFO);
+    QS_FILTER_OFF(QS_QF_EQUEUE_GET);
+    QS_FILTER_OFF(QS_QF_EQUEUE_GET_LAST);
+    QS_FILTER_OFF(QS_QF_MPOOL_INIT);
+    QS_FILTER_OFF(QS_QF_MPOOL_GET);
+    QS_FILTER_OFF(QS_QF_MPOOL_PUT);
+    QS_FILTER_OFF(QS_QF_PUBLISH);
+    QS_FILTER_OFF(QS_QF_NEW);
+    QS_FILTER_OFF(QS_QF_GC_ATTEMPT);
+    QS_FILTER_OFF(QS_QF_GC);
+//    QS_FILTER_OFF(QS_QF_TICK);
+    QS_FILTER_OFF(QS_QF_TIMEEVT_ARM);
+    QS_FILTER_OFF(QS_QF_TIMEEVT_AUTO_DISARM);
+    QS_FILTER_OFF(QS_QF_TIMEEVT_DISARM_ATTEMPT);
+    QS_FILTER_OFF(QS_QF_TIMEEVT_DISARM);
+    QS_FILTER_OFF(QS_QF_TIMEEVT_REARM);
+    QS_FILTER_OFF(QS_QF_TIMEEVT_POST);
+    QS_FILTER_OFF(QS_QF_INT_LOCK);
+    QS_FILTER_OFF(QS_QF_INT_UNLOCK);
+    QS_FILTER_OFF(QS_QF_ISR_ENTRY);
+    QS_FILTER_OFF(QS_QF_ISR_EXIT);
+
+//    QS_FILTER_OFF(QS_QK_MUTEX_LOCK);
+//    QS_FILTER_OFF(QS_QK_MUTEX_UNLOCK);
+//    QS_FILTER_OFF(QS_QK_SCHEDULE);
+
+    return (uint8_t)1;                                       // return success
+}
+//............................................................................
+void QS::onCleanup(void) {
+}
+//............................................................................
+QSTimeCtr QS::onGetTime(void) {              // invoked with interrupts locked
+    if ((SysTick->CTRL & 0x00000100) == 0) {              // COUNTFLAG no set?
+        return l_tickTime - (QSTimeCtr)SysTick->VAL;
+    }
+    else {        // the rollover occured, but the SysTick_ISR did not run yet
+        return l_tickTime + l_tickPeriod - (QSTimeCtr)SysTick->VAL;
+    }
+}
+//............................................................................
+void QS::onFlush(void) {
+    uint16_t b;
+    QF_INT_LOCK(dummy);
+    while ((b = QS::getByte()) != QS_EOD) {
+        while (!l_qspy.writeable()) {    // wait until serial port is writable
+        }
+        l_qspy.putc((uint8_t)b);
+    }
+    QF_INT_UNLOCK(dummy);
+}
+#endif                                                                // Q_SPY
+//----------------------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bsp.h	Sat Feb 12 23:22:47 2011 +0000
@@ -0,0 +1,39 @@
+//////////////////////////////////////////////////////////////////////////////
+// Product: DPP example, Board Support Package
+// Last Updated for Version: 4.0.01
+// Date of the Last Update:  Jul 29, 2008
+//
+//                    Q u a n t u m     L e a P s
+//                    ---------------------------
+//                    innovating embedded systems
+//
+// Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
+//
+// This software may be distributed and modified under the terms of the GNU
+// General Public License version 2 (GPL) as published by the Free Software
+// Foundation and appearing in the file GPL.TXT included in the packaging of
+// this file. Please note that GPL Section 2[b] requires that all works based
+// on this software must also be made publicly available under the terms of
+// the GPL ("Copyleft").
+//
+// Alternatively, this software may be distributed and modified under the
+// terms of Quantum Leaps commercial licenses, which expressly supersede
+// the GPL and are specifically designed for licensees interested in
+// retaining the proprietary status of their code.
+//
+// Contact information:
+// Quantum Leaps Web site:  http://www.quantum-leaps.com
+// e-mail:                  info@quantum-leaps.com
+//////////////////////////////////////////////////////////////////////////////
+#ifndef bsp_h
+#define bsp_h
+                                                // System clock tick rate [Hz]
+#define BSP_TICKS_PER_SEC 100
+
+void BSP_init(void);
+void BSP_displyPhilStat(uint8_t n, char const *stat);
+void BSP_busyDelay(void);             // to artificially extend RTC processing
+
+#endif                                                                // bsp_h
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dpp.h	Sat Feb 12 23:22:47 2011 +0000
@@ -0,0 +1,50 @@
+//////////////////////////////////////////////////////////////////////////////
+// Product: DPP example
+// Last Updated for Version: 4.0.00
+// Date of the Last Update:  Apr 07, 2008
+//
+//                    Q u a n t u m     L e a P s
+//                    ---------------------------
+//                    innovating embedded systems
+//
+// Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
+//
+// This software may be distributed and modified under the terms of the GNU
+// General Public License version 2 (GPL) as published by the Free Software
+// Foundation and appearing in the file GPL.TXT included in the packaging of
+// this file. Please note that GPL Section 2[b] requires that all works based
+// on this software must also be made publicly available under the terms of
+// the GPL ("Copyleft").
+//
+// Alternatively, this software may be distributed and modified under the
+// terms of Quantum Leaps commercial licenses, which expressly supersede
+// the GPL and are specifically designed for licensees interested in
+// retaining the proprietary status of their code.
+//
+// Contact information:
+// Quantum Leaps Web site:  http://www.quantum-leaps.com
+// e-mail:                  info@quantum-leaps.com
+//////////////////////////////////////////////////////////////////////////////
+#ifndef dpp_h
+#define dpp_h
+
+enum DPPSignals {
+   EAT_SIG = Q_USER_SIG,        // published by Table to let a philosopher eat
+   DONE_SIG,                      // published by Philosopher when done eating
+   TERMINATE_SIG,             // published by BSP to terminate the application
+   MAX_PUB_SIG,                                   // the last published signal
+
+   HUNGRY_SIG,                      // posted from hungry Philosopher to Table
+   MAX_SIG                                                  // the last signal
+};
+
+struct TableEvt : public QEvent {
+    uint8_t philoNum;                                    // philosopher number
+};
+
+enum { N_PHILO = 5 };                                // number of philosophers
+
+extern QActive * const AO_Philo[N_PHILO];     // "opaque" pointers to Philo AO
+extern QActive * const AO_Table;              // "opaque" pointer  to Table AO
+
+#endif                                                                // dpp_h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sat Feb 12 23:22:47 2011 +0000
@@ -0,0 +1,75 @@
+//////////////////////////////////////////////////////////////////////////////
+// Product: DPP example
+// Last Updated for Version: 4.0.00
+// Date of the Last Update:  May 28, 2008
+//
+//                    Q u a n t u m     L e a P s
+//                    ---------------------------
+//                    innovating embedded systems
+//
+// Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
+//
+// This software may be distributed and modified under the terms of the GNU
+// General Public License version 2 (GPL) as published by the Free Software
+// Foundation and appearing in the file GPL.TXT included in the packaging of
+// this file. Please note that GPL Section 2[b] requires that all works based
+// on this software must also be made publicly available under the terms of
+// the GPL ("Copyleft").
+//
+// Alternatively, this software may be distributed and modified under the
+// terms of Quantum Leaps commercial licenses, which expressly supersede
+// the GPL and are specifically designed for licensees interested in
+// retaining the proprietary status of their code.
+//
+// Contact information:
+// Quantum Leaps Web site:  http://www.quantum-leaps.com
+// e-mail:                  info@quantum-leaps.com
+//////////////////////////////////////////////////////////////////////////////
+#include "qp_port.h"
+#include "dpp.h"
+#include "bsp.h"
+
+// Local-scope objects -------------------------------------------------------
+static QEvent const *l_tableQueueSto[N_PHILO];
+static QEvent const *l_philoQueueSto[N_PHILO][N_PHILO];
+static QSubscrList   l_subscrSto[MAX_PUB_SIG];
+
+static union SmallEvents {
+    void *min_size;
+    TableEvt te;
+    // other event types to go into this pool
+} l_smlPoolSto[2*N_PHILO];                 // storage for the small event pool
+
+//............................................................................
+int main(void) {
+    BSP_init();                                          // initialize the BSP
+    QF::init();       // initialize the framework and the underlying RT kernel
+                                                     // object dictionaries...
+    QS_OBJ_DICTIONARY(l_smlPoolSto);
+    QS_OBJ_DICTIONARY(l_tableQueueSto);
+    QS_OBJ_DICTIONARY(l_philoQueueSto[0]);
+    QS_OBJ_DICTIONARY(l_philoQueueSto[1]);
+    QS_OBJ_DICTIONARY(l_philoQueueSto[2]);
+    QS_OBJ_DICTIONARY(l_philoQueueSto[3]);
+    QS_OBJ_DICTIONARY(l_philoQueueSto[4]);
+
+    QF::psInit(l_subscrSto, Q_DIM(l_subscrSto));     // init publish-subscribe
+                                                  // initialize event pools...
+    QF::poolInit(l_smlPoolSto, sizeof(l_smlPoolSto), sizeof(l_smlPoolSto[0]));
+
+                                                // start the active objects...
+    uint8_t n;
+    for (n = 0; n < N_PHILO; ++n) {
+        AO_Philo[n]->start((uint8_t)(n + 1),
+                           l_philoQueueSto[n], Q_DIM(l_philoQueueSto[n]),
+                           (void *)0, 0, (QEvent *)0);
+    }
+    AO_Table->start((uint8_t)(N_PHILO + 1),
+                    l_tableQueueSto, Q_DIM(l_tableQueueSto),
+                    (void *)0, 0, (QEvent *)0);
+
+    QF::run();                                       // run the QF application
+
+    return 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Sat Feb 12 23:22:47 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/9a9732ce53a1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/philo.cpp	Sat Feb 12 23:22:47 2011 +0000
@@ -0,0 +1,173 @@
+//////////////////////////////////////////////////////////////////////////////
+// Product: DPP example
+// Last Updated for Version: 4.0.00
+// Date of the Last Update:  Apr 06, 2008
+//
+//                    Q u a n t u m     L e a P s
+//                    ---------------------------
+//                    innovating embedded systems
+//
+// Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
+//
+// This software may be distributed and modified under the terms of the GNU
+// General Public License version 2 (GPL) as published by the Free Software
+// Foundation and appearing in the file GPL.TXT included in the packaging of
+// this file. Please note that GPL Section 2[b] requires that all works based
+// on this software must also be made publicly available under the terms of
+// the GPL ("Copyleft").
+//
+// Alternatively, this software may be distributed and modified under the
+// terms of Quantum Leaps commercial licenses, which expressly supersede
+// the GPL and are specifically designed for licensees interested in
+// retaining the proprietary status of their code.
+//
+// Contact information:
+// Quantum Leaps Web site:  http://www.quantum-leaps.com
+// e-mail:                  info@quantum-leaps.com
+//////////////////////////////////////////////////////////////////////////////
+#include "qp_port.h"
+#include "dpp.h"
+#include "bsp.h"
+
+Q_DEFINE_THIS_FILE
+
+// Active object class -------------------------------------------------------
+class Philo : public QActive {
+private:
+    QTimeEvt m_timeEvt;                       // to timeout thinking or eating
+
+public:
+    Philo();
+
+private:
+    static QState initial (Philo *me, QEvent const *e);
+    static QState thinking(Philo *me, QEvent const *e);
+    static QState hungry  (Philo *me, QEvent const *e);
+    static QState eating  (Philo *me, QEvent const *e);
+};
+
+// Local objects -------------------------------------------------------------
+static Philo l_philo[N_PHILO];                       // storage for all Philos
+
+#define THINK_TIME  23
+#define EAT_TIME    19
+                              // helper macro to provide the ID of Philo "me_"
+#define PHILO_ID(me_)    ((uint8_t)((me_) - l_philo))
+
+enum InternalSignals {                                     // internal signals
+    TIMEOUT_SIG = MAX_SIG
+};
+// Global objects ------------------------------------------------------------
+QActive * const AO_Philo[N_PHILO] = {        // "opaque" pointers to Philo AOs
+    &l_philo[0],
+    &l_philo[1],
+    &l_philo[2],
+    &l_philo[3],
+    &l_philo[4]
+};
+
+//............................................................................
+Philo::Philo()
+    : QActive((QStateHandler)&Philo::initial),
+      m_timeEvt(TIMEOUT_SIG)
+{}
+//............................................................................
+QState Philo::initial(Philo *me, QEvent const *) {
+    static uint8_t registered;            // starts off with 0, per C-standard
+    if (!registered) {
+        QS_OBJ_DICTIONARY(&l_philo[0]);
+        QS_OBJ_DICTIONARY(&l_philo[0].m_timeEvt);
+        QS_OBJ_DICTIONARY(&l_philo[1]);
+        QS_OBJ_DICTIONARY(&l_philo[1].m_timeEvt);
+        QS_OBJ_DICTIONARY(&l_philo[2]);
+        QS_OBJ_DICTIONARY(&l_philo[2].m_timeEvt);
+        QS_OBJ_DICTIONARY(&l_philo[3]);
+        QS_OBJ_DICTIONARY(&l_philo[3].m_timeEvt);
+        QS_OBJ_DICTIONARY(&l_philo[4]);
+        QS_OBJ_DICTIONARY(&l_philo[4].m_timeEvt);
+
+        QS_FUN_DICTIONARY(&Philo::initial);
+        QS_FUN_DICTIONARY(&Philo::thinking);
+        QS_FUN_DICTIONARY(&Philo::hungry);
+        QS_FUN_DICTIONARY(&Philo::eating);
+
+        registered = (uint8_t)1;
+    }
+    QS_SIG_DICTIONARY(HUNGRY_SIG, me);               // signal for each Philos
+    QS_SIG_DICTIONARY(TIMEOUT_SIG, me);              // signal for each Philos
+
+    me->subscribe(EAT_SIG);
+
+    return Q_TRAN(&Philo::thinking);
+}
+//............................................................................
+QState Philo::thinking(Philo *me, QEvent const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            me->m_timeEvt.postIn(me, THINK_TIME);
+            return Q_HANDLED();
+        }
+        case TIMEOUT_SIG: {
+            BSP_busyDelay();
+            return Q_TRAN(&Philo::hungry);
+        }
+        case EAT_SIG:                            // intentionally fall-through
+        case DONE_SIG: {
+                         // EAT or DONE must be for other Philos than this one
+            Q_ASSERT(((TableEvt const *)e)->philoNum != PHILO_ID(me));
+            return Q_HANDLED();
+        }
+    }
+    return Q_SUPER(&QHsm::top);
+}
+//............................................................................
+QState Philo::hungry(Philo *me, QEvent const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            TableEvt *pe = Q_NEW(TableEvt, HUNGRY_SIG);
+            pe->philoNum = PHILO_ID(me);
+            AO_Table->postFIFO(pe);
+            return Q_HANDLED();
+        }
+        case EAT_SIG: {
+            if (((TableEvt *)e)->philoNum == PHILO_ID(me)) {
+                BSP_busyDelay();
+                return Q_TRAN(&Philo::eating);
+            }
+            break;
+        }
+        case DONE_SIG: {
+                                // DONE must be for other Philos than this one
+            Q_ASSERT(((TableEvt const *)e)->philoNum != PHILO_ID(me));
+            return Q_HANDLED();
+        }
+    }
+    return Q_SUPER(&QHsm::top);
+}
+//............................................................................
+QState Philo::eating(Philo *me, QEvent const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            me->m_timeEvt.postIn(me, EAT_TIME);
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            TableEvt *pe = Q_NEW(TableEvt, DONE_SIG);
+            pe->philoNum = PHILO_ID(me);
+            QF::publish(pe);
+            return Q_HANDLED();
+        }
+        case TIMEOUT_SIG: {
+            BSP_busyDelay();
+            return Q_TRAN(&Philo::thinking);
+        }
+        case EAT_SIG:                            // intentionally fall-through
+        case DONE_SIG: {
+                         // EAT or DONE must be for other Philos than this one
+            Q_ASSERT(((TableEvt const *)e)->philoNum != PHILO_ID(me));
+            return Q_HANDLED();
+        }
+    }
+    return Q_SUPER(&QHsm::top);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qp.lib	Sat Feb 12 23:22:47 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/QL/code/qp/#5c8be45330ab
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qp_config.h	Sat Feb 12 23:22:47 2011 +0000
@@ -0,0 +1,43 @@
+//////////////////////////////////////////////////////////////////////////////
+// Product: QP-mbed configuration file
+// Last Updated for Version: 4.1.06
+// Date of the Last Update:  Feb 10, 2011
+//
+//                    Q u a n t u m     L e a P s
+//                    ---------------------------
+//                    innovating embedded systems
+//
+// Copyright (C) 2002-2011 Quantum Leaps, LLC. All rights reserved.
+//
+// This software may be distributed and modified under the terms of the GNU
+// General Public License version 2 (GPL) as published by the Free Software
+// Foundation and appearing in the file GPL.TXT included in the packaging of
+// this file. Please note that GPL Section 2[b] requires that all works based
+// on this software must also be made publicly available under the terms of
+// the GPL ("Copyleft").
+//
+// Alternatively, this software may be distributed and modified under the
+// terms of Quantum Leaps commercial licenses, which expressly supersede
+// the GPL and are specifically designed for licensees interested in
+// retaining the proprietary status of their code.
+//
+// Contact information:
+// Quantum Leaps Web site:  http://www.quantum-leaps.com
+// e-mail:                  info@quantum-leaps.com
+//////////////////////////////////////////////////////////////////////////////
+#ifndef qp_config_h
+#define qp_config_h
+
+// enable the Q-SPY software tracing instrumentation
+//#define Q_SPY
+
+// enable preemptive QK kernel
+#define QK_PREEMPTIVE
+
+// The maximum number of active objects in the application (could be up to 63)
+#define QF_MAX_ACTIVE      16
+
+// The signal size (1, 2, 4 bytes)
+#define Q_SIGNAL_SIZE      2
+
+#endif                                                          // qp_config_h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/table.cpp	Sat Feb 12 23:22:47 2011 +0000
@@ -0,0 +1,150 @@
+//////////////////////////////////////////////////////////////////////////////
+// Product: DPP example
+// Last Updated for Version: 4.0.00
+// Date of the Last Update:  Apr 06, 2008
+//
+//                    Q u a n t u m     L e a P s
+//                    ---------------------------
+//                    innovating embedded systems
+//
+// Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
+//
+// This software may be distributed and modified under the terms of the GNU
+// General Public License version 2 (GPL) as published by the Free Software
+// Foundation and appearing in the file GPL.TXT included in the packaging of
+// this file. Please note that GPL Section 2[b] requires that all works based
+// on this software must also be made publicly available under the terms of
+// the GPL ("Copyleft").
+//
+// Alternatively, this software may be distributed and modified under the
+// terms of Quantum Leaps commercial licenses, which expressly supersede
+// the GPL and are specifically designed for licensees interested in
+// retaining the proprietary status of their code.
+//
+// Contact information:
+// Quantum Leaps Web site:  http://www.quantum-leaps.com
+// e-mail:                  info@quantum-leaps.com
+//////////////////////////////////////////////////////////////////////////////
+#include "qp_port.h"
+#include "dpp.h"
+#include "bsp.h"
+
+Q_DEFINE_THIS_FILE
+
+// Active object class -------------------------------------------------------
+class Table : public QActive {
+private:
+    uint8_t m_fork[N_PHILO];
+    uint8_t m_isHungry[N_PHILO];
+
+public:
+    Table();
+
+private:
+    static QState initial(Table *me, QEvent const *e);
+    static QState serving(Table *me, QEvent const *e);
+};
+
+#define RIGHT(n_) ((uint8_t)(((n_) + (N_PHILO - 1)) % N_PHILO))
+#define LEFT(n_)  ((uint8_t)(((n_) + 1) % N_PHILO))
+enum ForkState { FREE, USED };
+
+// Local objects -------------------------------------------------------------
+static Table l_table;                                    // local Table object
+
+// Public-scope objects ------------------------------------------------------
+QActive * const AO_Table = &l_table;                    // "opaque" AO pointer
+
+//............................................................................
+Table::Table() : QActive((QStateHandler)&Table::initial) {
+    uint8_t n;
+    for (n = 0; n < N_PHILO; ++n) {
+        m_fork[n] = FREE;
+        m_isHungry[n] = 0;
+    }
+}
+//............................................................................
+QState Table::initial(Table *me, QEvent const *) {
+
+    QS_OBJ_DICTIONARY(&l_table);
+    QS_FUN_DICTIONARY(&QHsm::top);
+    QS_FUN_DICTIONARY(&Table::initial);
+    QS_FUN_DICTIONARY(&Table::serving);
+
+    QS_SIG_DICTIONARY(DONE_SIG,      0);                     // global signals
+    QS_SIG_DICTIONARY(EAT_SIG,       0);
+    QS_SIG_DICTIONARY(TERMINATE_SIG, 0);
+
+    QS_SIG_DICTIONARY(HUNGRY_SIG,    me);             // signal just for Table
+
+    me->subscribe(DONE_SIG);
+    me->subscribe(TERMINATE_SIG);
+
+    return Q_TRAN(&Table::serving);
+}
+//............................................................................
+QState Table::serving(Table *me, QEvent const *e) {
+    uint8_t n, m;
+    TableEvt *pe;
+
+    switch (e->sig) {
+        case HUNGRY_SIG: {
+            BSP_busyDelay();
+            n = ((TableEvt const *)e)->philoNum;
+                         // phil ID must be in range and he must be not hungry
+            Q_ASSERT((n < N_PHILO) && (!me->m_isHungry[n]));
+
+            BSP_displyPhilStat(n, "hungry  ");
+            m = LEFT(n);
+            if ((me->m_fork[m] == FREE) && (me->m_fork[n] == FREE)) {
+                me->m_fork[m] = me->m_fork[n] = USED;
+                pe = Q_NEW(TableEvt, EAT_SIG);
+                pe->philoNum = n;
+                QF::publish(pe);
+                BSP_displyPhilStat(n, "eating  ");
+            }
+            else {
+                me->m_isHungry[n] = 1;
+            }
+            return Q_HANDLED();
+        }
+        case DONE_SIG: {
+            BSP_busyDelay();
+            n = ((TableEvt const *)e)->philoNum;
+                         // phil ID must be in range and he must be not hungry
+            Q_ASSERT((n < N_PHILO) && (!me->m_isHungry[n]));
+
+            BSP_displyPhilStat(n, "thinking");
+            m = LEFT(n);
+                                         // both forks of Phil[n] must be used
+            Q_ASSERT((me->m_fork[n] == USED) && (me->m_fork[m] == USED));
+
+            me->m_fork[m] = me->m_fork[n] = FREE;
+            m = RIGHT(n);                          // check the right neighbor
+            if (me->m_isHungry[m] && (me->m_fork[m] == FREE)) {
+                me->m_fork[n] = me->m_fork[m] = USED;
+                me->m_isHungry[m] = 0;
+                pe = Q_NEW(TableEvt, EAT_SIG);
+                pe->philoNum = m;
+                QF::publish(pe);
+                BSP_displyPhilStat(m, "eating  ");
+            }
+            m = LEFT(n);                            // check the left neighbor
+            n = LEFT(m);                     // left fork of the left neighbor
+            if (me->m_isHungry[m] && (me->m_fork[n] == FREE)) {
+                me->m_fork[m] = me->m_fork[n] = USED;
+                me->m_isHungry[m] = 0;
+                pe = Q_NEW(TableEvt, EAT_SIG);
+                pe->philoNum = m;
+                QF::publish(pe);
+                BSP_displyPhilStat(m, "eating  ");
+            }
+            return Q_HANDLED();
+        }
+        case TERMINATE_SIG: {
+            QF::stop();
+            return Q_HANDLED();
+        }
+    }
+    return Q_SUPER(&QHsm::top);
+}