This QP-nano Tutorial is adapted from Chapter 1 of Practical UML Statecharts in C/C++, Second Edition
by Miro Samek, the founder and president of Quantum Leaps, LLC.
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 ARM-Cortex version, because the application source code is identical in both.
Listing 3-1 shows the 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.
Listing 3-1 The file main.c of the "Fly 'n' Shoot" game application.
(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.In QP-nano, I use every opportunity to place data in ROM rather than in the precious RAM. The QActiveCB structure contains data elements known at compile time, so that these elements can be placed in ROMas opposed to placing them in the active object structure (RAM). That way, I save anywhere from 10 to 80 bytes of RAM, depending on the number of active objects and the pointer size of the target CPU. The Q_ROM macro is necessary on some CPU architecture to enforce placement of constant objects, such as the QF_active[] array, in ROM. On Harvard architecture CPUs (such as 8051 or AVR), the code and data spaces are separate and are accessed through different CPU instructions. The const keyword is not sufficient to place data in ROM, and various compilers often provide specific extended keywords to designate the code space for placing constant data, such as the "__code" extended keyword in the IAR 8051 compiler. The macro Q_ROM hides such non-standard extensions. If you don't define Q_ROM in qepn_port.h, it will be defined to nothing in the qepn.h platform-independent header file. The Q_ROM_VAR macro defines the compiler-specific directive for accessing a constant object in ROM. Many compilers for 8-bit MCUs provide different size pointers for accessing objects in various memories. Constant objects allocated in ROM often mandate the use of specific-size pointers (e.g., far pointers) to get access to ROM objects. The macro Q_ROM_VAR specifies the kind of the pointer to be used to access the ROM objects. An example of valid Q_ROM_VAR macro definition is: __far (Freescale HC(S)08 compiler).
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.In QP-nano, QF_MAX_ACTIVE denotes the exact number of active objects used in the application, as opposed to the full-version QP, where QF_MAX_ACTIVE denotes just the configurable maximum number of active objects.
The macro QF_MAX_ACTIVE must be defined in qpn_port.h header file, because QP-nano uses the macro to optimize the internal algorithms based on the number of active objects. The compile-time assertion in line (12) makes sure that the configured number of active objects indeed matches exactly the number of active object control blocks defined in the QF_active[] array.
main() function must first explicitly calls all active object constructors.QF_run() to pass the control to the QF-nano framework.Overall, the application startup is much simpler in QP-nano than in full-version QP. Neither event pools, nor publish-subscribe lists are supported, so you don't need to initialize them. You also don't start active objects explicitly. The QF-nano framework starts all active objects defined in the QF_active[] array automatically just after it gets control in QF_run().
The 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() (7) #include <stdint.h> /* Exact-width types (WG14/N843 C99 Standard) */ #include <i86.h> /* for _disable()/_enable() */ (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, so I'm using it here. If you work with a pre-standard compiler, you can typedef the six exact-width integer types used in QP (uint8_t, int8_t, uint16_t, int16_t, uint32_t, and int32_t). which I'm using here, is a pre-standard compiler and does not provide 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.Prev: 2. Let's Play
Next: 4. Designing an Event-Driven Application
Copyright © 2002-2010 Quantum Leaps, LLC. All Rights Reserved.
http://www.quantum-leaps.com
1.6.3