Example program for the lwIP TCP/IP stack (library lwip_1_4_0_rc2) and the QP state machine framework (library qp). This program demonstrates use of lwIP in hard real-time applications, in which the TCP/IP stack is used to monitor and configure the embedded device as well as to provide remote user interface (e.g., by means of a web browser). In particular, the lwIP stack, which is not reentrant, is strictly encapsulated inside a dedicated QP state machine object (active object in QP), so interrupt locking around calls to lwIP is unnecessary. Also, the Ethernet interrupt service routine (ISR) runs very fast without performing any lengthy copy operations. All this means that hard-real-time processing can be done at the task level, especially when you use the preemptive QK kernel built into QP for executing your application. No external RTOS component is needed to achieve fully deterministic real-time response of active object tasks prioritized above the lwiP task. The lwIP-QP integration uses exclusively the event-driven lwIP API. The heavyweight Berkeley-like socket API requiring a blocking RTOS and is not used, which results in much better performance of the lwIP stack and less memory consumption. NOTE: This example compiles cleanly, but does not run just yet because the low-level Ethernet driver in the lwIP library needs to be completed. See comments in the lwip_1_4_0_rc2 library for more information.

Dependencies:   mbed

Committer:
QL
Date:
Sun Mar 27 16:50:21 2011 +0000
Revision:
0:84f3d3d7e5d9
0.9

Who changed what in which revision?

UserRevisionLine numberNew contents of line
QL 0:84f3d3d7e5d9 1 //////////////////////////////////////////////////////////////////////////////
QL 0:84f3d3d7e5d9 2 // Product: DPP example
QL 0:84f3d3d7e5d9 3 // Last Updated for Version: 4.0.03
QL 0:84f3d3d7e5d9 4 // Date of the Last Update: Mar 16, 2009
QL 0:84f3d3d7e5d9 5 //
QL 0:84f3d3d7e5d9 6 // Q u a n t u m L e a P s
QL 0:84f3d3d7e5d9 7 // ---------------------------
QL 0:84f3d3d7e5d9 8 // innovating embedded systems
QL 0:84f3d3d7e5d9 9 //
QL 0:84f3d3d7e5d9 10 // Copyright (C) 2002-2009 Quantum Leaps, LLC. All rights reserved.
QL 0:84f3d3d7e5d9 11 //
QL 0:84f3d3d7e5d9 12 // This software may be distributed and modified under the terms of the GNU
QL 0:84f3d3d7e5d9 13 // General Public License version 2 (GPL) as published by the Free Software
QL 0:84f3d3d7e5d9 14 // Foundation and appearing in the file GPL.TXT included in the packaging of
QL 0:84f3d3d7e5d9 15 // this file. Please note that GPL Section 2[b] requires that all works based
QL 0:84f3d3d7e5d9 16 // on this software must also be made publicly available under the terms of
QL 0:84f3d3d7e5d9 17 // the GPL ("Copyleft").
QL 0:84f3d3d7e5d9 18 //
QL 0:84f3d3d7e5d9 19 // Alternatively, this software may be distributed and modified under the
QL 0:84f3d3d7e5d9 20 // terms of Quantum Leaps commercial licenses, which expressly supersede
QL 0:84f3d3d7e5d9 21 // the GPL and are specifically designed for licensees interested in
QL 0:84f3d3d7e5d9 22 // retaining the proprietary status of their code.
QL 0:84f3d3d7e5d9 23 //
QL 0:84f3d3d7e5d9 24 // Contact information:
QL 0:84f3d3d7e5d9 25 // Quantum Leaps Web site: http://www.quantum-leaps.com
QL 0:84f3d3d7e5d9 26 // e-mail: info@quantum-leaps.com
QL 0:84f3d3d7e5d9 27 //////////////////////////////////////////////////////////////////////////////
QL 0:84f3d3d7e5d9 28 #include "qp_port.h"
QL 0:84f3d3d7e5d9 29 #include "dpp.h"
QL 0:84f3d3d7e5d9 30 #include "bsp.h"
QL 0:84f3d3d7e5d9 31
QL 0:84f3d3d7e5d9 32 Q_DEFINE_THIS_FILE
QL 0:84f3d3d7e5d9 33
QL 0:84f3d3d7e5d9 34 // Active object class -------------------------------------------------------
QL 0:84f3d3d7e5d9 35 class Philo : public QActive {
QL 0:84f3d3d7e5d9 36 private:
QL 0:84f3d3d7e5d9 37 QTimeEvt m_timeEvt; // to timeout thinking or eating
QL 0:84f3d3d7e5d9 38
QL 0:84f3d3d7e5d9 39 public:
QL 0:84f3d3d7e5d9 40 Philo();
QL 0:84f3d3d7e5d9 41
QL 0:84f3d3d7e5d9 42 private:
QL 0:84f3d3d7e5d9 43 static QState initial (Philo *me, QEvent const *e);
QL 0:84f3d3d7e5d9 44 static QState thinking(Philo *me, QEvent const *e);
QL 0:84f3d3d7e5d9 45 static QState hungry (Philo *me, QEvent const *e);
QL 0:84f3d3d7e5d9 46 static QState eating (Philo *me, QEvent const *e);
QL 0:84f3d3d7e5d9 47 };
QL 0:84f3d3d7e5d9 48
QL 0:84f3d3d7e5d9 49 // Local objects -------------------------------------------------------------
QL 0:84f3d3d7e5d9 50 static Philo l_philo[N_PHILO]; // storage for all Philos
QL 0:84f3d3d7e5d9 51
QL 0:84f3d3d7e5d9 52 #define THINK_TIME 17
QL 0:84f3d3d7e5d9 53 #define EAT_TIME 13
QL 0:84f3d3d7e5d9 54 // helper macro to provide the ID of Philo "me_"
QL 0:84f3d3d7e5d9 55 #define PHILO_ID(me_) ((uint8_t)((me_) - l_philo))
QL 0:84f3d3d7e5d9 56
QL 0:84f3d3d7e5d9 57 enum InternalSignals { // internal signals
QL 0:84f3d3d7e5d9 58 TIMEOUT_SIG = MAX_SIG
QL 0:84f3d3d7e5d9 59 };
QL 0:84f3d3d7e5d9 60 // Global objects ------------------------------------------------------------
QL 0:84f3d3d7e5d9 61 QActive * const AO_Philo[N_PHILO] = { // "opaque" pointers to Philo AOs
QL 0:84f3d3d7e5d9 62 &l_philo[0],
QL 0:84f3d3d7e5d9 63 &l_philo[1],
QL 0:84f3d3d7e5d9 64 &l_philo[2],
QL 0:84f3d3d7e5d9 65 &l_philo[3],
QL 0:84f3d3d7e5d9 66 &l_philo[4]
QL 0:84f3d3d7e5d9 67 };
QL 0:84f3d3d7e5d9 68
QL 0:84f3d3d7e5d9 69 //............................................................................
QL 0:84f3d3d7e5d9 70 Philo::Philo()
QL 0:84f3d3d7e5d9 71 : QActive((QStateHandler)&Philo::initial),
QL 0:84f3d3d7e5d9 72 m_timeEvt(TIMEOUT_SIG)
QL 0:84f3d3d7e5d9 73 {}
QL 0:84f3d3d7e5d9 74 //............................................................................
QL 0:84f3d3d7e5d9 75 QState Philo::initial(Philo *me, QEvent const *) {
QL 0:84f3d3d7e5d9 76 static uint8_t registered; // starts off with 0, per C-standard
QL 0:84f3d3d7e5d9 77 if (!registered) {
QL 0:84f3d3d7e5d9 78 QS_OBJ_DICTIONARY(&l_philo[0]);
QL 0:84f3d3d7e5d9 79 QS_OBJ_DICTIONARY(&l_philo[0].m_timeEvt);
QL 0:84f3d3d7e5d9 80 QS_OBJ_DICTIONARY(&l_philo[1]);
QL 0:84f3d3d7e5d9 81 QS_OBJ_DICTIONARY(&l_philo[1].m_timeEvt);
QL 0:84f3d3d7e5d9 82 QS_OBJ_DICTIONARY(&l_philo[2]);
QL 0:84f3d3d7e5d9 83 QS_OBJ_DICTIONARY(&l_philo[2].m_timeEvt);
QL 0:84f3d3d7e5d9 84 QS_OBJ_DICTIONARY(&l_philo[3]);
QL 0:84f3d3d7e5d9 85 QS_OBJ_DICTIONARY(&l_philo[3].m_timeEvt);
QL 0:84f3d3d7e5d9 86 QS_OBJ_DICTIONARY(&l_philo[4]);
QL 0:84f3d3d7e5d9 87 QS_OBJ_DICTIONARY(&l_philo[4].m_timeEvt);
QL 0:84f3d3d7e5d9 88
QL 0:84f3d3d7e5d9 89 QS_FUN_DICTIONARY(&Philo::initial);
QL 0:84f3d3d7e5d9 90 QS_FUN_DICTIONARY(&Philo::thinking);
QL 0:84f3d3d7e5d9 91 QS_FUN_DICTIONARY(&Philo::hungry);
QL 0:84f3d3d7e5d9 92 QS_FUN_DICTIONARY(&Philo::eating);
QL 0:84f3d3d7e5d9 93
QL 0:84f3d3d7e5d9 94 registered = (uint8_t)1;
QL 0:84f3d3d7e5d9 95 }
QL 0:84f3d3d7e5d9 96 QS_SIG_DICTIONARY(HUNGRY_SIG, me); // signal for each Philos
QL 0:84f3d3d7e5d9 97 QS_SIG_DICTIONARY(TIMEOUT_SIG, me); // signal for each Philos
QL 0:84f3d3d7e5d9 98
QL 0:84f3d3d7e5d9 99 me->subscribe(EAT_SIG);
QL 0:84f3d3d7e5d9 100
QL 0:84f3d3d7e5d9 101 return Q_TRAN(&Philo::thinking);
QL 0:84f3d3d7e5d9 102 }
QL 0:84f3d3d7e5d9 103 //............................................................................
QL 0:84f3d3d7e5d9 104 QState Philo::thinking(Philo *me, QEvent const *e) {
QL 0:84f3d3d7e5d9 105 switch (e->sig) {
QL 0:84f3d3d7e5d9 106 case Q_ENTRY_SIG: {
QL 0:84f3d3d7e5d9 107 me->m_timeEvt.postIn(me, THINK_TIME);
QL 0:84f3d3d7e5d9 108 return Q_HANDLED();
QL 0:84f3d3d7e5d9 109 }
QL 0:84f3d3d7e5d9 110 case TIMEOUT_SIG: {
QL 0:84f3d3d7e5d9 111 return Q_TRAN(&Philo::hungry);
QL 0:84f3d3d7e5d9 112 }
QL 0:84f3d3d7e5d9 113 case EAT_SIG: // intentionally fall-through
QL 0:84f3d3d7e5d9 114 case DONE_SIG: {
QL 0:84f3d3d7e5d9 115 // EAT or DONE must be for other Philos than this one
QL 0:84f3d3d7e5d9 116 Q_ASSERT(((TableEvt const *)e)->philoNum != PHILO_ID(me));
QL 0:84f3d3d7e5d9 117 return Q_HANDLED();
QL 0:84f3d3d7e5d9 118 }
QL 0:84f3d3d7e5d9 119 }
QL 0:84f3d3d7e5d9 120 return Q_SUPER(&QHsm::top);
QL 0:84f3d3d7e5d9 121 }
QL 0:84f3d3d7e5d9 122 //............................................................................
QL 0:84f3d3d7e5d9 123 QState Philo::hungry(Philo *me, QEvent const *e) {
QL 0:84f3d3d7e5d9 124 switch (e->sig) {
QL 0:84f3d3d7e5d9 125 case Q_ENTRY_SIG: {
QL 0:84f3d3d7e5d9 126 TableEvt *pe = Q_NEW(TableEvt, HUNGRY_SIG);
QL 0:84f3d3d7e5d9 127 pe->philoNum = PHILO_ID(me);
QL 0:84f3d3d7e5d9 128 AO_Table->postFIFO(pe);
QL 0:84f3d3d7e5d9 129 return Q_HANDLED();
QL 0:84f3d3d7e5d9 130 }
QL 0:84f3d3d7e5d9 131 case EAT_SIG: {
QL 0:84f3d3d7e5d9 132 if (((TableEvt *)e)->philoNum == PHILO_ID(me)) {
QL 0:84f3d3d7e5d9 133 return Q_TRAN(&Philo::eating);
QL 0:84f3d3d7e5d9 134 }
QL 0:84f3d3d7e5d9 135 break;
QL 0:84f3d3d7e5d9 136 }
QL 0:84f3d3d7e5d9 137 case DONE_SIG: {
QL 0:84f3d3d7e5d9 138 // DONE must be for other Philos than this one
QL 0:84f3d3d7e5d9 139 Q_ASSERT(((TableEvt const *)e)->philoNum != PHILO_ID(me));
QL 0:84f3d3d7e5d9 140 return Q_HANDLED();
QL 0:84f3d3d7e5d9 141 }
QL 0:84f3d3d7e5d9 142 }
QL 0:84f3d3d7e5d9 143 return Q_SUPER(&QHsm::top);
QL 0:84f3d3d7e5d9 144 }
QL 0:84f3d3d7e5d9 145 //............................................................................
QL 0:84f3d3d7e5d9 146 QState Philo::eating(Philo *me, QEvent const *e) {
QL 0:84f3d3d7e5d9 147 switch (e->sig) {
QL 0:84f3d3d7e5d9 148 case Q_ENTRY_SIG: {
QL 0:84f3d3d7e5d9 149 me->m_timeEvt.postIn(me, EAT_TIME);
QL 0:84f3d3d7e5d9 150 return Q_HANDLED();
QL 0:84f3d3d7e5d9 151 }
QL 0:84f3d3d7e5d9 152 case Q_EXIT_SIG: {
QL 0:84f3d3d7e5d9 153 TableEvt *pe = Q_NEW(TableEvt, DONE_SIG);
QL 0:84f3d3d7e5d9 154 pe->philoNum = PHILO_ID(me);
QL 0:84f3d3d7e5d9 155 QF::publish(pe);
QL 0:84f3d3d7e5d9 156 return Q_HANDLED();
QL 0:84f3d3d7e5d9 157 }
QL 0:84f3d3d7e5d9 158 case TIMEOUT_SIG: {
QL 0:84f3d3d7e5d9 159 return Q_TRAN(&Philo::thinking);
QL 0:84f3d3d7e5d9 160 }
QL 0:84f3d3d7e5d9 161 case EAT_SIG: // intentionally fall-through
QL 0:84f3d3d7e5d9 162 case DONE_SIG: {
QL 0:84f3d3d7e5d9 163 // EAT or DONE must be for other Philos than this one
QL 0:84f3d3d7e5d9 164 Q_ASSERT(((TableEvt const *)e)->philoNum != PHILO_ID(me));
QL 0:84f3d3d7e5d9 165 return Q_HANDLED();
QL 0:84f3d3d7e5d9 166 }
QL 0:84f3d3d7e5d9 167 }
QL 0:84f3d3d7e5d9 168 return Q_SUPER(&QHsm::top);
QL 0:84f3d3d7e5d9 169 }
QL 0:84f3d3d7e5d9 170