Dining Philosophers Problem (DPP) example for the QP active object framework. Demonstrates: event-driven programming, hierarchical state machines in C++, modeling and graphical state machine design, code generation, preemptive multitasking, software tracing, power saving mode, direct event posting, publish-subscribe. More information available in the [[/users/QL/notebook|Quantum Leaps Notebook pages]]. See also [[http://www.state-machine.com|state-machine.com]].

Dependencies:   mbed qp

Committer:
QL
Date:
Wed Feb 16 17:12:38 2011 +0000
Revision:
2:2e62e514f323
Parent:
0:efb9ac8d1a88
Child:
3:81ceb3127876
added slight delay to the idle loop to see the LED4 intensity

Who changed what in which revision?

UserRevisionLine numberNew contents of line
QL 0:efb9ac8d1a88 1 //////////////////////////////////////////////////////////////////////////////
QL 0:efb9ac8d1a88 2 // Product: BSP for "Dining Philosophers Problem" example, QK kernel
QL 0:efb9ac8d1a88 3 // Last Updated for Version: 4.1.06
QL 2:2e62e514f323 4 // Date of the Last Update: Feb 16, 2011
QL 0:efb9ac8d1a88 5 //
QL 0:efb9ac8d1a88 6 // Q u a n t u m L e a P s
QL 0:efb9ac8d1a88 7 // ---------------------------
QL 0:efb9ac8d1a88 8 // innovating embedded systems
QL 0:efb9ac8d1a88 9 //
QL 0:efb9ac8d1a88 10 // Copyright (C) 2002-2011 Quantum Leaps, LLC. All rights reserved.
QL 0:efb9ac8d1a88 11 //
QL 0:efb9ac8d1a88 12 // This software may be distributed and modified under the terms of the GNU
QL 0:efb9ac8d1a88 13 // General Public License version 2 (GPL) as published by the Free Software
QL 0:efb9ac8d1a88 14 // Foundation and appearing in the file GPL.TXT included in the packaging of
QL 0:efb9ac8d1a88 15 // this file. Please note that GPL Section 2[b] requires that all works based
QL 0:efb9ac8d1a88 16 // on this software must also be made publicly available under the terms of
QL 0:efb9ac8d1a88 17 // the GPL ("Copyleft").
QL 0:efb9ac8d1a88 18 //
QL 0:efb9ac8d1a88 19 // Alternatively, this software may be distributed and modified under the
QL 0:efb9ac8d1a88 20 // terms of Quantum Leaps commercial licenses, which expressly supersede
QL 0:efb9ac8d1a88 21 // the GPL and are specifically designed for licensees interested in
QL 0:efb9ac8d1a88 22 // retaining the proprietary status of their code.
QL 0:efb9ac8d1a88 23 //
QL 0:efb9ac8d1a88 24 // Contact information:
QL 0:efb9ac8d1a88 25 // Quantum Leaps Web site: http://www.quantum-leaps.com
QL 0:efb9ac8d1a88 26 // e-mail: info@quantum-leaps.com
QL 0:efb9ac8d1a88 27 //////////////////////////////////////////////////////////////////////////////
QL 0:efb9ac8d1a88 28 #include "qp_port.h"
QL 0:efb9ac8d1a88 29 #include "dpp.h"
QL 0:efb9ac8d1a88 30 #include "bsp.h"
QL 0:efb9ac8d1a88 31 #include "LPC17xx.h"
QL 0:efb9ac8d1a88 32
QL 0:efb9ac8d1a88 33 Q_DEFINE_THIS_FILE
QL 0:efb9ac8d1a88 34
QL 0:efb9ac8d1a88 35 // Local-scope objects -------------------------------------------------------
QL 0:efb9ac8d1a88 36 enum ISR_Priorities { // ISR priorities starting from the highest urgency
QL 0:efb9ac8d1a88 37 GPIOPORTA_PRIO,
QL 0:efb9ac8d1a88 38 SYSTICK_PRIO,
QL 0:efb9ac8d1a88 39 // ...
QL 0:efb9ac8d1a88 40 };
QL 0:efb9ac8d1a88 41
QL 0:efb9ac8d1a88 42 #define LED_PORT LPC_GPIO1
QL 0:efb9ac8d1a88 43 #define LED1_BIT (1U << 18)
QL 0:efb9ac8d1a88 44 #define LED2_BIT (1U << 20)
QL 0:efb9ac8d1a88 45 #define LED3_BIT (1U << 21)
QL 0:efb9ac8d1a88 46 #define LED4_BIT (1U << 23)
QL 0:efb9ac8d1a88 47
QL 0:efb9ac8d1a88 48 #ifdef Q_SPY
QL 0:efb9ac8d1a88 49 #include "mbed.h" // mbed is used only for the built-in serial
QL 0:efb9ac8d1a88 50
QL 0:efb9ac8d1a88 51 QSTimeCtr l_tickTime;
QL 0:efb9ac8d1a88 52 QSTimeCtr l_tickPeriod;
QL 0:efb9ac8d1a88 53
QL 0:efb9ac8d1a88 54 #define QSPY_BAUD_RATE 115200
QL 0:efb9ac8d1a88 55
QL 0:efb9ac8d1a88 56 enum AppRecords { // application-specific trace records
QL 0:efb9ac8d1a88 57 PHILO_STAT = QS_USER
QL 0:efb9ac8d1a88 58 };
QL 0:efb9ac8d1a88 59
QL 0:efb9ac8d1a88 60 Serial l_qspy(USBTX, USBRX);
QL 0:efb9ac8d1a88 61 #endif
QL 0:efb9ac8d1a88 62
QL 0:efb9ac8d1a88 63 //............................................................................
QL 0:efb9ac8d1a88 64 extern "C" void SysTick_Handler(void) {
QL 0:efb9ac8d1a88 65 QK_ISR_ENTRY(); // inform the QK kernel of entering the ISR
QL 0:efb9ac8d1a88 66
QL 0:efb9ac8d1a88 67 #ifdef Q_SPY
QL 0:efb9ac8d1a88 68 uint32_t volatile dummy = SysTick->CTRL; // clear the COUNTFLAG in SysTick
QL 0:efb9ac8d1a88 69 l_tickTime += l_tickPeriod; // account for the clock rollover
QL 0:efb9ac8d1a88 70 #endif
QL 0:efb9ac8d1a88 71
QL 0:efb9ac8d1a88 72 QF::tick(); // process all armed time events
QL 0:efb9ac8d1a88 73
QL 0:efb9ac8d1a88 74 QK_ISR_EXIT(); // inform the QK kernel of exiting the ISR
QL 0:efb9ac8d1a88 75 }
QL 0:efb9ac8d1a88 76
QL 0:efb9ac8d1a88 77 //............................................................................
QL 0:efb9ac8d1a88 78 void BSP_init(void) {
QL 0:efb9ac8d1a88 79 SystemInit(); // initialize the clocking system
QL 0:efb9ac8d1a88 80
QL 0:efb9ac8d1a88 81 // set LED port to output
QL 0:efb9ac8d1a88 82 LED_PORT->FIODIR |= (LED1_BIT | LED2_BIT | LED3_BIT | LED4_BIT);
QL 0:efb9ac8d1a88 83
QL 0:efb9ac8d1a88 84 // clear the LEDs
QL 0:efb9ac8d1a88 85 LED_PORT->FIOCLR = (LED1_BIT | LED2_BIT | LED3_BIT | LED4_BIT);
QL 0:efb9ac8d1a88 86
QL 0:efb9ac8d1a88 87 if (QS_INIT((void *)0) == 0) { // initialize the QS software tracing
QL 0:efb9ac8d1a88 88 Q_ERROR();
QL 0:efb9ac8d1a88 89 }
QL 0:efb9ac8d1a88 90 }
QL 0:efb9ac8d1a88 91 //............................................................................
QL 0:efb9ac8d1a88 92 void BSP_displyPhilStat(uint8_t n, char const *stat) {
QL 0:efb9ac8d1a88 93 // represent LEDs in a const array for convenience
QL 0:efb9ac8d1a88 94 static uint32_t const led[] = { LED1_BIT, LED2_BIT, LED3_BIT, LED4_BIT };
QL 0:efb9ac8d1a88 95 if (n < 3) {
QL 0:efb9ac8d1a88 96 if (stat[0] == 'e') {
QL 0:efb9ac8d1a88 97 LED_PORT->FIOSET = led[n];
QL 0:efb9ac8d1a88 98 }
QL 0:efb9ac8d1a88 99 else {
QL 0:efb9ac8d1a88 100 LED_PORT->FIOCLR = led[n];
QL 0:efb9ac8d1a88 101 }
QL 0:efb9ac8d1a88 102 }
QL 0:efb9ac8d1a88 103
QL 0:efb9ac8d1a88 104 QS_BEGIN(PHILO_STAT, AO_Philo[n]) // application-specific record begin
QL 0:efb9ac8d1a88 105 QS_U8(1, n); // Philosopher number
QL 0:efb9ac8d1a88 106 QS_STR(stat); // Philosopher status
QL 0:efb9ac8d1a88 107 QS_END()
QL 0:efb9ac8d1a88 108 }
QL 0:efb9ac8d1a88 109 //............................................................................
QL 0:efb9ac8d1a88 110 void BSP_busyDelay(void) {
QL 0:efb9ac8d1a88 111 uint32_t volatile i = 10;
QL 0:efb9ac8d1a88 112 while (i-- > 0UL) { // busy-wait loop
QL 0:efb9ac8d1a88 113 }
QL 0:efb9ac8d1a88 114 }
QL 0:efb9ac8d1a88 115
QL 0:efb9ac8d1a88 116 //............................................................................
QL 0:efb9ac8d1a88 117 void QF::onStartup(void) {
QL 0:efb9ac8d1a88 118 // set up the SysTick timer to fire at BSP_TICKS_PER_SEC rate
QL 0:efb9ac8d1a88 119 SysTick_Config(SystemCoreClock / BSP_TICKS_PER_SEC);
QL 0:efb9ac8d1a88 120
QL 0:efb9ac8d1a88 121 // set priorities of all interrupts in the system...
QL 0:efb9ac8d1a88 122 NVIC_SetPriority(SysTick_IRQn, SYSTICK_PRIO);
QL 0:efb9ac8d1a88 123 NVIC_SetPriority(EINT0_IRQn, GPIOPORTA_PRIO);
QL 0:efb9ac8d1a88 124
QL 0:efb9ac8d1a88 125 NVIC_EnableIRQ(EINT0_IRQn);
QL 0:efb9ac8d1a88 126 }
QL 0:efb9ac8d1a88 127 //............................................................................
QL 0:efb9ac8d1a88 128 void QF::onCleanup(void) {
QL 0:efb9ac8d1a88 129 }
QL 0:efb9ac8d1a88 130 //............................................................................
QL 0:efb9ac8d1a88 131 void QK::onIdle(void) {
QL 0:efb9ac8d1a88 132
QL 0:efb9ac8d1a88 133 QF_INT_LOCK(dummy);
QL 2:2e62e514f323 134 LED_PORT->FIOSET = LED4_BIT; // turn the LED4 on
QL 2:2e62e514f323 135 __NOP(); // delay a bit to see some light intensity
QL 2:2e62e514f323 136 __NOP();
QL 2:2e62e514f323 137 __NOP();
QL 2:2e62e514f323 138 __NOP();
QL 0:efb9ac8d1a88 139 LED_PORT->FIOCLR = LED4_BIT; // turn the LED4 off
QL 0:efb9ac8d1a88 140 QF_INT_UNLOCK(dummy);
QL 0:efb9ac8d1a88 141
QL 0:efb9ac8d1a88 142 #ifdef Q_SPY
QL 0:efb9ac8d1a88 143 if (l_qspy.writeable()) {
QL 0:efb9ac8d1a88 144 QF_INT_LOCK(dummy);
QL 0:efb9ac8d1a88 145 uint16_t b = QS::getByte();
QL 0:efb9ac8d1a88 146 QF_INT_UNLOCK(dummy);
QL 0:efb9ac8d1a88 147 if (b != QS_EOD) {
QL 0:efb9ac8d1a88 148 l_qspy.putc((uint8_t)b);
QL 0:efb9ac8d1a88 149 }
QL 0:efb9ac8d1a88 150 }
QL 0:efb9ac8d1a88 151 #else
QL 2:2e62e514f323 152 // Put the CPU and peripherals to the low-power mode. You might need to
QL 2:2e62e514f323 153 // customize the clock management for your application, see the datasheet
QL 2:2e62e514f323 154 // for your particular Cortex-M3 MCU.
QL 2:2e62e514f323 155 //
QL 2:2e62e514f323 156 // Specifially for the mbed board, see the articles:
QL 2:2e62e514f323 157 // * "Power Management" http://mbed.org/cookbook/Power-Management; and
QL 2:2e62e514f323 158 // * "Interface Powerdown" at
QL 2:2e62e514f323 159 // http://mbed.org/users/simon/notebook/interface-powerdown/
QL 2:2e62e514f323 160 //
QL 0:efb9ac8d1a88 161 __WFI();
QL 0:efb9ac8d1a88 162 #endif
QL 0:efb9ac8d1a88 163 }
QL 0:efb9ac8d1a88 164
QL 0:efb9ac8d1a88 165 //............................................................................
QL 0:efb9ac8d1a88 166 void Q_onAssert(char const Q_ROM * const Q_ROM_VAR file, int line) {
QL 0:efb9ac8d1a88 167 (void)file; // avoid compiler warning
QL 0:efb9ac8d1a88 168 (void)line; // avoid compiler warning
QL 0:efb9ac8d1a88 169 QF_INT_LOCK(dummy); // make sure that all interrupts are disabled
QL 0:efb9ac8d1a88 170 // light up all LEDs
QL 0:efb9ac8d1a88 171 LED_PORT->FIOSET = (LED1_BIT | LED2_BIT | LED3_BIT | LED4_BIT);
QL 0:efb9ac8d1a88 172
QL 0:efb9ac8d1a88 173 for (;;) { // NOTE: replace the loop with reset for final version
QL 0:efb9ac8d1a88 174 }
QL 0:efb9ac8d1a88 175 }
QL 0:efb9ac8d1a88 176
QL 0:efb9ac8d1a88 177 //----------------------------------------------------------------------------
QL 0:efb9ac8d1a88 178 #ifdef Q_SPY
QL 0:efb9ac8d1a88 179 //............................................................................
QL 0:efb9ac8d1a88 180 uint8_t QS::onStartup(void const *arg) {
QL 0:efb9ac8d1a88 181 static uint8_t qsBuf[6*256]; // buffer for Quantum Spy
QL 0:efb9ac8d1a88 182 initBuf(qsBuf, sizeof(qsBuf));
QL 0:efb9ac8d1a88 183
QL 0:efb9ac8d1a88 184 l_qspy.baud(QSPY_BAUD_RATE);
QL 0:efb9ac8d1a88 185
QL 0:efb9ac8d1a88 186 l_tickPeriod = SystemCoreClock / BSP_TICKS_PER_SEC;
QL 0:efb9ac8d1a88 187 l_tickTime = l_tickPeriod; // to start the timestamp at zero
QL 0:efb9ac8d1a88 188
QL 0:efb9ac8d1a88 189 // setup the QS filters...
QL 0:efb9ac8d1a88 190 QS_FILTER_ON(QS_ALL_RECORDS);
QL 0:efb9ac8d1a88 191
QL 0:efb9ac8d1a88 192 // QS_FILTER_OFF(QS_QEP_STATE_EMPTY);
QL 0:efb9ac8d1a88 193 // QS_FILTER_OFF(QS_QEP_STATE_ENTRY);
QL 0:efb9ac8d1a88 194 // QS_FILTER_OFF(QS_QEP_STATE_EXIT);
QL 0:efb9ac8d1a88 195 // QS_FILTER_OFF(QS_QEP_STATE_INIT);
QL 0:efb9ac8d1a88 196 // QS_FILTER_OFF(QS_QEP_INIT_TRAN);
QL 0:efb9ac8d1a88 197 // QS_FILTER_OFF(QS_QEP_INTERN_TRAN);
QL 0:efb9ac8d1a88 198 // QS_FILTER_OFF(QS_QEP_TRAN);
QL 0:efb9ac8d1a88 199 // QS_FILTER_OFF(QS_QEP_IGNORED);
QL 0:efb9ac8d1a88 200
QL 0:efb9ac8d1a88 201 QS_FILTER_OFF(QS_QF_ACTIVE_ADD);
QL 0:efb9ac8d1a88 202 QS_FILTER_OFF(QS_QF_ACTIVE_REMOVE);
QL 0:efb9ac8d1a88 203 QS_FILTER_OFF(QS_QF_ACTIVE_SUBSCRIBE);
QL 0:efb9ac8d1a88 204 QS_FILTER_OFF(QS_QF_ACTIVE_UNSUBSCRIBE);
QL 0:efb9ac8d1a88 205 QS_FILTER_OFF(QS_QF_ACTIVE_POST_FIFO);
QL 0:efb9ac8d1a88 206 QS_FILTER_OFF(QS_QF_ACTIVE_POST_LIFO);
QL 0:efb9ac8d1a88 207 QS_FILTER_OFF(QS_QF_ACTIVE_GET);
QL 0:efb9ac8d1a88 208 QS_FILTER_OFF(QS_QF_ACTIVE_GET_LAST);
QL 0:efb9ac8d1a88 209 QS_FILTER_OFF(QS_QF_EQUEUE_INIT);
QL 0:efb9ac8d1a88 210 QS_FILTER_OFF(QS_QF_EQUEUE_POST_FIFO);
QL 0:efb9ac8d1a88 211 QS_FILTER_OFF(QS_QF_EQUEUE_POST_LIFO);
QL 0:efb9ac8d1a88 212 QS_FILTER_OFF(QS_QF_EQUEUE_GET);
QL 0:efb9ac8d1a88 213 QS_FILTER_OFF(QS_QF_EQUEUE_GET_LAST);
QL 0:efb9ac8d1a88 214 QS_FILTER_OFF(QS_QF_MPOOL_INIT);
QL 0:efb9ac8d1a88 215 QS_FILTER_OFF(QS_QF_MPOOL_GET);
QL 0:efb9ac8d1a88 216 QS_FILTER_OFF(QS_QF_MPOOL_PUT);
QL 0:efb9ac8d1a88 217 QS_FILTER_OFF(QS_QF_PUBLISH);
QL 0:efb9ac8d1a88 218 QS_FILTER_OFF(QS_QF_NEW);
QL 0:efb9ac8d1a88 219 QS_FILTER_OFF(QS_QF_GC_ATTEMPT);
QL 0:efb9ac8d1a88 220 QS_FILTER_OFF(QS_QF_GC);
QL 0:efb9ac8d1a88 221 // QS_FILTER_OFF(QS_QF_TICK);
QL 0:efb9ac8d1a88 222 QS_FILTER_OFF(QS_QF_TIMEEVT_ARM);
QL 0:efb9ac8d1a88 223 QS_FILTER_OFF(QS_QF_TIMEEVT_AUTO_DISARM);
QL 0:efb9ac8d1a88 224 QS_FILTER_OFF(QS_QF_TIMEEVT_DISARM_ATTEMPT);
QL 0:efb9ac8d1a88 225 QS_FILTER_OFF(QS_QF_TIMEEVT_DISARM);
QL 0:efb9ac8d1a88 226 QS_FILTER_OFF(QS_QF_TIMEEVT_REARM);
QL 0:efb9ac8d1a88 227 QS_FILTER_OFF(QS_QF_TIMEEVT_POST);
QL 0:efb9ac8d1a88 228 QS_FILTER_OFF(QS_QF_INT_LOCK);
QL 0:efb9ac8d1a88 229 QS_FILTER_OFF(QS_QF_INT_UNLOCK);
QL 0:efb9ac8d1a88 230 QS_FILTER_OFF(QS_QF_ISR_ENTRY);
QL 0:efb9ac8d1a88 231 QS_FILTER_OFF(QS_QF_ISR_EXIT);
QL 0:efb9ac8d1a88 232
QL 0:efb9ac8d1a88 233 // QS_FILTER_OFF(QS_QK_MUTEX_LOCK);
QL 0:efb9ac8d1a88 234 // QS_FILTER_OFF(QS_QK_MUTEX_UNLOCK);
QL 0:efb9ac8d1a88 235 // QS_FILTER_OFF(QS_QK_SCHEDULE);
QL 0:efb9ac8d1a88 236
QL 0:efb9ac8d1a88 237 return (uint8_t)1; // return success
QL 0:efb9ac8d1a88 238 }
QL 0:efb9ac8d1a88 239 //............................................................................
QL 0:efb9ac8d1a88 240 void QS::onCleanup(void) {
QL 0:efb9ac8d1a88 241 }
QL 0:efb9ac8d1a88 242 //............................................................................
QL 0:efb9ac8d1a88 243 QSTimeCtr QS::onGetTime(void) { // invoked with interrupts locked
QL 0:efb9ac8d1a88 244 if ((SysTick->CTRL & 0x00000100) == 0) { // COUNTFLAG no set?
QL 0:efb9ac8d1a88 245 return l_tickTime - (QSTimeCtr)SysTick->VAL;
QL 0:efb9ac8d1a88 246 }
QL 0:efb9ac8d1a88 247 else { // the rollover occured, but the SysTick_ISR did not run yet
QL 0:efb9ac8d1a88 248 return l_tickTime + l_tickPeriod - (QSTimeCtr)SysTick->VAL;
QL 0:efb9ac8d1a88 249 }
QL 0:efb9ac8d1a88 250 }
QL 0:efb9ac8d1a88 251 //............................................................................
QL 0:efb9ac8d1a88 252 void QS::onFlush(void) {
QL 0:efb9ac8d1a88 253 uint16_t b;
QL 0:efb9ac8d1a88 254 QF_INT_LOCK(dummy);
QL 0:efb9ac8d1a88 255 while ((b = QS::getByte()) != QS_EOD) {
QL 0:efb9ac8d1a88 256 while (!l_qspy.writeable()) { // wait until serial port is writable
QL 0:efb9ac8d1a88 257 }
QL 0:efb9ac8d1a88 258 l_qspy.putc((uint8_t)b);
QL 0:efb9ac8d1a88 259 }
QL 0:efb9ac8d1a88 260 QF_INT_UNLOCK(dummy);
QL 0:efb9ac8d1a88 261 }
QL 0:efb9ac8d1a88 262 #endif // Q_SPY
QL 0:efb9ac8d1a88 263 //----------------------------------------------------------------------------