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.00
QL 0:84f3d3d7e5d9 4 // Date of the Last Update: Apr 06, 2008
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-2008 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 Table : public QActive {
QL 0:84f3d3d7e5d9 36 private:
QL 0:84f3d3d7e5d9 37 uint8_t m_fork[N_PHILO];
QL 0:84f3d3d7e5d9 38 uint8_t m_isHungry[N_PHILO];
QL 0:84f3d3d7e5d9 39
QL 0:84f3d3d7e5d9 40 public:
QL 0:84f3d3d7e5d9 41 Table();
QL 0:84f3d3d7e5d9 42
QL 0:84f3d3d7e5d9 43 private:
QL 0:84f3d3d7e5d9 44 static QState initial(Table *me, QEvent const *e);
QL 0:84f3d3d7e5d9 45 static QState serving(Table *me, QEvent const *e);
QL 0:84f3d3d7e5d9 46 };
QL 0:84f3d3d7e5d9 47
QL 0:84f3d3d7e5d9 48 #define RIGHT(n_) ((uint8_t)(((n_) + (N_PHILO - 1)) % N_PHILO))
QL 0:84f3d3d7e5d9 49 #define LEFT(n_) ((uint8_t)(((n_) + 1) % N_PHILO))
QL 0:84f3d3d7e5d9 50 enum ForkState { FREE, USED };
QL 0:84f3d3d7e5d9 51
QL 0:84f3d3d7e5d9 52 // Local objects -------------------------------------------------------------
QL 0:84f3d3d7e5d9 53 static Table l_table; // local Table object
QL 0:84f3d3d7e5d9 54
QL 0:84f3d3d7e5d9 55 // Public-scope objects ------------------------------------------------------
QL 0:84f3d3d7e5d9 56 QActive * const AO_Table = &l_table; // "opaque" AO pointer
QL 0:84f3d3d7e5d9 57
QL 0:84f3d3d7e5d9 58 //............................................................................
QL 0:84f3d3d7e5d9 59 Table::Table() : QActive((QStateHandler)&Table::initial) {
QL 0:84f3d3d7e5d9 60 uint8_t n;
QL 0:84f3d3d7e5d9 61 for (n = 0; n < N_PHILO; ++n) {
QL 0:84f3d3d7e5d9 62 m_fork[n] = FREE;
QL 0:84f3d3d7e5d9 63 m_isHungry[n] = 0;
QL 0:84f3d3d7e5d9 64 }
QL 0:84f3d3d7e5d9 65 }
QL 0:84f3d3d7e5d9 66 //............................................................................
QL 0:84f3d3d7e5d9 67 QState Table::initial(Table *me, QEvent const *) {
QL 0:84f3d3d7e5d9 68
QL 0:84f3d3d7e5d9 69 QS_OBJ_DICTIONARY(&l_table);
QL 0:84f3d3d7e5d9 70 QS_FUN_DICTIONARY(&QHsm::top);
QL 0:84f3d3d7e5d9 71 QS_FUN_DICTIONARY(&Table::initial);
QL 0:84f3d3d7e5d9 72 QS_FUN_DICTIONARY(&Table::serving);
QL 0:84f3d3d7e5d9 73
QL 0:84f3d3d7e5d9 74 QS_SIG_DICTIONARY(DONE_SIG, 0); // global signals
QL 0:84f3d3d7e5d9 75 QS_SIG_DICTIONARY(EAT_SIG, 0);
QL 0:84f3d3d7e5d9 76 QS_SIG_DICTIONARY(TERMINATE_SIG, 0);
QL 0:84f3d3d7e5d9 77
QL 0:84f3d3d7e5d9 78 QS_SIG_DICTIONARY(HUNGRY_SIG, me); // signal just for Table
QL 0:84f3d3d7e5d9 79
QL 0:84f3d3d7e5d9 80 me->subscribe(DONE_SIG);
QL 0:84f3d3d7e5d9 81 me->subscribe(TERMINATE_SIG);
QL 0:84f3d3d7e5d9 82
QL 0:84f3d3d7e5d9 83 return Q_TRAN(&Table::serving);
QL 0:84f3d3d7e5d9 84 }
QL 0:84f3d3d7e5d9 85 //............................................................................
QL 0:84f3d3d7e5d9 86 QState Table::serving(Table *me, QEvent const *e) {
QL 0:84f3d3d7e5d9 87 uint8_t n, m;
QL 0:84f3d3d7e5d9 88 TableEvt *pe;
QL 0:84f3d3d7e5d9 89
QL 0:84f3d3d7e5d9 90 switch (e->sig) {
QL 0:84f3d3d7e5d9 91 case HUNGRY_SIG: {
QL 0:84f3d3d7e5d9 92 n = ((TableEvt const *)e)->philoNum;
QL 0:84f3d3d7e5d9 93 // phil ID must be in range and he must be not hungry
QL 0:84f3d3d7e5d9 94 Q_ASSERT((n < N_PHILO) && (!me->m_isHungry[n]));
QL 0:84f3d3d7e5d9 95
QL 0:84f3d3d7e5d9 96 BSP_displyPhilStat(n, "hungry ");
QL 0:84f3d3d7e5d9 97 m = LEFT(n);
QL 0:84f3d3d7e5d9 98 if ((me->m_fork[m] == FREE) && (me->m_fork[n] == FREE)) {
QL 0:84f3d3d7e5d9 99 me->m_fork[m] = me->m_fork[n] = USED;
QL 0:84f3d3d7e5d9 100 pe = Q_NEW(TableEvt, EAT_SIG);
QL 0:84f3d3d7e5d9 101 pe->philoNum = n;
QL 0:84f3d3d7e5d9 102 QF::publish(pe);
QL 0:84f3d3d7e5d9 103 BSP_displyPhilStat(n, "eating ");
QL 0:84f3d3d7e5d9 104 }
QL 0:84f3d3d7e5d9 105 else {
QL 0:84f3d3d7e5d9 106 me->m_isHungry[n] = 1;
QL 0:84f3d3d7e5d9 107 }
QL 0:84f3d3d7e5d9 108 return Q_HANDLED();
QL 0:84f3d3d7e5d9 109 }
QL 0:84f3d3d7e5d9 110 case DONE_SIG: {
QL 0:84f3d3d7e5d9 111 n = ((TableEvt const *)e)->philoNum;
QL 0:84f3d3d7e5d9 112 // phil ID must be in range and he must be not hungry
QL 0:84f3d3d7e5d9 113 Q_ASSERT((n < N_PHILO) && (!me->m_isHungry[n]));
QL 0:84f3d3d7e5d9 114
QL 0:84f3d3d7e5d9 115 BSP_displyPhilStat(n, "thinking");
QL 0:84f3d3d7e5d9 116 m = LEFT(n);
QL 0:84f3d3d7e5d9 117 // both forks of Phil[n] must be used
QL 0:84f3d3d7e5d9 118 Q_ASSERT((me->m_fork[n] == USED) && (me->m_fork[m] == USED));
QL 0:84f3d3d7e5d9 119
QL 0:84f3d3d7e5d9 120 me->m_fork[m] = me->m_fork[n] = FREE;
QL 0:84f3d3d7e5d9 121 m = RIGHT(n); // check the right neighbor
QL 0:84f3d3d7e5d9 122 if (me->m_isHungry[m] && (me->m_fork[m] == FREE)) {
QL 0:84f3d3d7e5d9 123 me->m_fork[n] = me->m_fork[m] = USED;
QL 0:84f3d3d7e5d9 124 me->m_isHungry[m] = 0;
QL 0:84f3d3d7e5d9 125 pe = Q_NEW(TableEvt, EAT_SIG);
QL 0:84f3d3d7e5d9 126 pe->philoNum = m;
QL 0:84f3d3d7e5d9 127 QF::publish(pe);
QL 0:84f3d3d7e5d9 128 BSP_displyPhilStat(m, "eating ");
QL 0:84f3d3d7e5d9 129 }
QL 0:84f3d3d7e5d9 130 m = LEFT(n); // check the left neighbor
QL 0:84f3d3d7e5d9 131 n = LEFT(m); // left fork of the left neighbor
QL 0:84f3d3d7e5d9 132 if (me->m_isHungry[m] && (me->m_fork[n] == FREE)) {
QL 0:84f3d3d7e5d9 133 me->m_fork[m] = me->m_fork[n] = USED;
QL 0:84f3d3d7e5d9 134 me->m_isHungry[m] = 0;
QL 0:84f3d3d7e5d9 135 pe = Q_NEW(TableEvt, EAT_SIG);
QL 0:84f3d3d7e5d9 136 pe->philoNum = m;
QL 0:84f3d3d7e5d9 137 QF::publish(pe);
QL 0:84f3d3d7e5d9 138 BSP_displyPhilStat(m, "eating ");
QL 0:84f3d3d7e5d9 139 }
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 }