Simple "Blinky" example for the QP active object framework
Fork of qp_dpp by
Revision 0:efb9ac8d1a88, committed 2011-02-12
- Comitter:
- QL
- Date:
- Sat Feb 12 23:22:47 2011 +0000
- Child:
- 1:c7711e751cf6
- Commit message:
Changed in this revision
--- /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); +}