Prev: 2. Let's Play
Next: 4. Designing an Event-Driven Application
Perhaps the best place to start the explanation of the "Fly 'n' Shoot" application code is the main() function, located in the file main.c. Unless indicated otherwise in this Tutorial, you can browse the code either in the DOS version, or the Cortex-M3 version, because the application source code is identical in both.
main.c source file for the “Fly ‘n’ Shoot” application, which contains the main() function along with some important data structures required by QP-nano.
(1) #include "qpn_port.h" /* QP-nano port */ (2) #include "bsp.h" /* Board Support Package (BSP) */ (3) #include "game.h" /* application interface */ /*..........................................................................*/ (4) static QEvent l_tunnelQueue[GAME_MINES_MAX + 4]; (5) static QEvent l_shipQueue[2]; (6) static QEvent l_missileQueue[2]; /* QF_active[] array defines all active object control blocks --------------*/ (7) QActiveCB const Q_ROM Q_ROM_VAR QF_active[] = { (8) { (QActive *)0, (QEvent *)0, 0 }, (9) { (QActive *)&AO_tunnel, l_tunnelQueue, Q_DIM(l_tunnelQueue) }, (10) { (QActive *)&AO_ship, l_shipQueue, Q_DIM(l_shipQueue) }, (11) { (QActive *)&AO_missile, l_missileQueue, Q_DIM(l_missileQueue) } }; /* make sure that the QF_active[] array matches QF_MAX_ACTIVE in qpn_port.h */ (12) Q_ASSERT_COMPILE(QF_MAX_ACTIVE == Q_DIM(QF_active) - 1); /*..........................................................................*/ void main (void) { (13) Tunnel_ctor (); (14) Ship_ctor (); (15) Missile_ctor(GAME_MISSILE_SPEED_X); (16) BSP_init(); /* initialize the board */ (17) QF_run(); /* transfer control to QF-nano */ }
qpn_port.h header file. This header file contains the specific adaptation of QP-nano to the given processor and compiler, which is called a port. The QP port is typically located in the application directory.bsp.h header file contains the interface to the Board Support Package and is located in the application directory.game.h header file contains the declarations of events and other facilities shared among the components of the "Fly 'n' Shoot" game. This header file is located in the application directory.<qpn>\include\qepn.h header file, included from qpn_port.h. Each event queue of an active object can have a different length and you need to decide this length based on your knowledge of the application. Please refer to Chapters 6 and 7 in Practical UML Statecharts in C/C++, Second Edition for the discussion of sizing event queues.QF_active[], which defines all active object control blocks in the application. The control block QActiveCB structure groups together: (1) the pointer to the corresponding active object instance, (2) the pointer to the event queue buffer of the active object, and (3) the length of the queue buffer.
QF_active[0]) corresponds to active object priority of zero, which is reserved for the idle task and cannot be used for any active object.QF_active[] entries starting from one define the active object control blocks in the order of their relative priorities. The maximum number of active objects in QP-nano cannot exceed 8.QF_active[] array defines the priorities of active objects. This is the only place in the code where you assign active object priorities.qpn_port.h header file.
QF_active[] array.
main() function must first explicitly calls all active object constructors.QF_run() to pass the control to the QF-nano framework.QF_active[] array automatically just after it gets control in QF_run().qpn_port.h header file defines the QP-nano port and all configuration parameters for the particular application. Unlike in the full-version QP, QP-nano ports are typically defined at the application level. Typically also, the whole QP-nano port consists of just the qpn_port.h header file. Listing 3-2 shows the complete qpn_port.h file for the DOS version of the “Fly ‘n’ Shoot” game.Listing 3-2 The qpn_port.h header file for the “Fly ‘n’ Shoot” game.
#ifndef qpn_port_h #define qpn_port_h (1) #define Q_PARAM_SIZE 4 (2) #define QF_TIMEEVT_CTR_SIZE 2 (3) #define Q_NFSM /* maximum # active objects--must match EXACTLY the QF_active[] definition */ (4) #define QF_MAX_ACTIVE 3 /* interrupt locking policy for task level */ (5) #define QF_INT_LOCK() disable() (6) #define QF_INT_UNLOCK() enable() /* Exact-width types (WG14/N843 C99 Standard) for Turbo C++/large model */ (7) typedef signed char int8_t; typedef signed int int16_t; typedef signed long int32_t; typedef unsigned char uint8_t; typedef unsigned int uint16_t; typedef unsigned long uint32_t; #include <dos.h> /* DOS API */ #undef outportb /*don't use the macro because it has a bug in Turbo C++ 1.01*/ (8) #include "qepn.h" /* QEP-nano platform-independent header file */ (9) #include "qfn.h" /* QF-nano platform-independent header file */ #endif /* qpn_port_h */
QF_active[] array (see Listing 3-1(12)).<stdint.h> header file. In this case I just typedef the six exact-width integer types used in QP-nano.qpn_port.h must include the QEP-nano event processor interface qepn.h.The qpn_port.h must include the QF-nano real-time framework interface qfn.h.qpn_port.h header file in Listing 3-2 implicitly configures QP-nano to use the built-in cooperative "vanilla" kernel. The other alternative, which is the preemptive QK-nano kernel, is configured automatically when you include the qkn.h QK-nano interface in the qpn_port.h header file.
1.5.4