QP/C++: QP/C++ Reference Manual

QP/C++
  • Main Page
  • Related Pages
  • Classes
  • Files

QP/C++ Reference Manual

  • QP Overview
  • Getting Started with QP/C++
  • Practical UML Statecharts in C/C++, Second Edition
  • Licensing Policy for QP
  • Contact Information
  • Directories and Files in the QP/C++ Distribution
  • QP/C++ Revision History

QP Overview

Quantum Platform (QP) is a family of very lightweight, open source, state machine-based frameworks for embedded systems. QP enables developing well-structured embedded applications as a set of concurrently executing hierarchical state machines (UML statecharts). With QP, coding of modern state machines directly in C or C++ is a non-issue. No big tools are needed.

  • QEP Hierarchical Event Processor
  • QF Real-Time Framework
  • QK Preemptive Run-To-Completion Kernel
  • QS Software Tracing Instrumentation (Target Component)
  • QSPY Host Application Reference Manual

Current versions of QP include: QP/C and QP/C++, which require 3-4KB of code and a few hundred bytes of RAM, and the ultra-lightweight QP-nano, which requires only 1-2KB of code and just several bytes of RAM.

QP can work with or without a traditional OS/RTOS. In the simplest configuration, QP can completely replace a traditional RTOS. QP includes a simple non-preemptive scheduler and a fully preemptive kernel (QK), which have been ported to several popular CPUs and compilers including: ARM7/ARM9, ARM Cortex-M3, 80x86, Nios-II, MSP430, M16C, AVR, 80251, and others (see http://www.state-machine.com/downloads/).

QP/C and QP/C++ can also work with a traditional OS/RTOS to take advantage of existing device drivers, communication stacks, and other middleware. QP has been ported to Linux/BSD, Windows, VxWorks, uC/OS-II, and other popular OS/RTOS (see http://www.state-machine.com/downloads/).

The QP Datasheet (see http://www.state-machine.com/products/QP_datasheet.pdf) provides a concise summary of QP features and benefits.

Since its publication in 2002, hundreds of projects around the world have been using QP in all kinds of applications, such as consumer, medical, industrial, wireless, networking, research, defense, robotics, automotive, space exploration, and many others.

QP is available for download from the following websites:

  • Quantum Leaps website: http://www.state-machine.com/downloads - SourceForge.net webiste: https://sourceforge.net/projects/qpc

Getting Started with QP/C++

QP/C++ is distributed in a simple platform-independent ZIP file or in a self-extracing Windows executable. Either way, installing QP/C++ requires simply decompressing the provided archive into a directory of your choice (e.g., qpcpp for QP/C++). The Section Directories and Files in the QP/C++ Distribution describes the content of the standard QP/C++ distribution.

The QP/C++ Tutorial explains all steps necessary to develop a non-trivial QP/C++ application. The Tutorial is based on Chapter 1 of Practical UML Statecharts in C/C++, Second Edition.

  • QP/C++ Tutorial
    • 1. Installing QP/C++ and Building QP Libraries and Applications
    • 2. Let's Play
    • 3. The main() Function
    • 4. Designing an Event-Driven Application
    • 5. Elaborating State Machines of Active Objects
    • 6. Defining Event Signals and Event Parameters
    • 7. Coding Hierarchical State Machines
    • 8. Using the Built-in Real-Time Kernels and Third-Party RTOSes
    • 9. Using Software Tracing for Testing and Debugging
    • 10. Comparison to the Traditional Approach
    • 11. Summary

Practical UML Statecharts in C/C++, Second Edition

All versions of QP are described in detail in the book Practical UML Statecharts in C/C++, Second Edition: Event-Driven Programming for Embedded Systems, Newnes 2008 (ISBN-10: 0750687061, ISBN-13: 978-0750687065).

The book bridges the gap between high-level abstract concepts of the Unified Modeling Language (UML) and the actual programming aspects of modern hierarchical state machines (UML statecharts).

This book is presented in two parts. In Part I, you get a practical description of the relevant state machine concepts starting from traditional finite state automata to modern UML state machines followed by state machine coding techniques with the QEP hierarchical event processor as well as several state-machine design patterns, all illustrated with executable examples.

In Part II, you find a detailed design study of the QF real-time framework, QK preemptive kernel, and QS software tracing, which are indispensable for combining concurrent, event-driven state machines into robust systems. In addition to its value as a reference to the QP event-driven platform, Part II explans the key event-driven programming concepts such as inversion of control ("Hollywood Principle"), blocking versus non-blocking code, run-to-completion (RTC) execution semantics, the importance of event queues, dealing with time, and the role of state machines to maintain the context from one event to the next. This background is designed to help software developers in making the transition from the traditional sequential to the modern event-driven programming, which can be one of the trickiest paradigm shifts.

  • Visit the accompanying website to the book at http://www.state-machine.com/psicc2/ - Order the book from Amazon.com at http://www.amazon.com/exec/obidos/ASIN/0750687061/quantumleap06-20

Licensing Policy for QP

All versions of the QP software are available under dual licensing model, in which both the open source software distribution mechanism and traditional closed source software licensing models are combined.

Open Source Licensing

All versions of the QP software are available under the GNU GENERAL PUBLIC LICENSE Version 2 (GPL2), as published by the Free Software Foundation and included in every distribution of the QP software. The GPL2 license is probably the best known and most established open source license. It is fully compatible with the Open Source Definition, is endorsed by the Free Software Foundation, and has been approved by the Open Source Initiative.

Please note that GPL2 applies to software based not upon how it is used but upon how it is distributed. In this respect GPL2 can be restrictive, because GPL2 Section 2(b) requires that if you distribute the original software or any derivative works based on the software under copyright law, you must release all such derivative works also under the terms of the GPL2 open source license. GPL2 clearly specifies that distributing the original software or any derivative works based upon it in binary form (e.g., embedded inside devices) also represents distribution of the software.

To read more about open source licensing for QP or QP-nano, or to contribute work to the open source community, please visit the following website:

  • http://www.state-machine.com/licensing/open.php - GNU GENERAL PUBLIC LICENSE Version 2

or please contact Quantum Leaps, LLC via the following e-mail address:

  • info@quantum-leaps.com

Closed Source Licensing

If you are developing and distributing traditional closed source applications, you might purchase one of the Quantum Leaps commercial licenses, which are specifically designed for users interested in retaining the proprietary status of their code. This alternative licensing is possible, because Quantum Leaps, LLC owns all intellectual property in the QP and QP-nano software and as the copyright owner can license the software any number of ways. The Quantum Leaps commercial licenses expressly supersede the GNU GENERAL PUBLIC LICENSE Version 2 open source license. This means that when you license the software under a commercial license, you specifically do not use the software under the open source license and therefore you are not subject to any of its terms.

To read more about the commercial licensing options, pricing, technical support, and to request a commercial license, please visit the following website:

  • http://www.state-machine.com/licensing

or please contact Quantum Leaps, LLC via the following e-mail address:

  • info@quantum-leaps.com

Contact Information

  • Quantum Leaps Web site: http://www.state-machine.com - Quantum Leaps licensing: http://www.state-machine.com/licensing - Quantum Leaps downloads: http://www.state-machine.com/downloads - e-mail: info@quantum-leaps.com - Skype: quantum-leaps (US Eastern Standard Time) - Toll-free: 1-866-450-LEAP (US Eastern Standard Time)

Copyright © 2002-2011 Quantum Leaps, LLC. All Rights Reserved.
http://www.state-machine.com

Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: QEP Hierarchical Event Processor

  • Classes
  • Files
  • QP/C++ Reference Manual

QEP Hierarchical Event Processor

Quantum Event Processor™ (QEP) is a generic, portable, and reusable hierarchical event processor that processes events according to the general semantics of UML state machines [UML document ptc/03-08-02]. QEP™ allows you to map UML state diagrams directly and clearly to code without the assistance of complex tools. It allows you to create better designs because you can think in terms of events, states, and transitions directly at the level of the C or C++ programming language. The resulting code is smaller, cleaner, more robust, and simpler to understand and maintain. The testing is faster, more rigorous, and more complete because state machine approach cleanly defines a limited state space for the system and constraints the possible transitions among the states.

QEP™ provides facilities for executing Hierarchical State Machines (HSMs) as well as the simpler traditional Finite State Machines (FSMs). QEP can operate with almost any event queuing and dispatching mechanisms, which are also necessary components of a hypothetical state machine [ptc/03-08-02]. For example, QEP can be used with virtually any event-driven environment, such as any Graphical User Interface system. When used in the domain of real-time embedded (RTE) systems, QEP can be combined with other QP components designed specifically for RTE systems. QEP has been used in hundreds of event-driven applications worldwide and is described in Part 1 of the book Practical UML Statecharts in C/C++, Second Edition, Newnes 2008.

Please refer to Section 7. Coding Hierarchical State Machines in the QP/C++ Tutorial for information on coding UML-compliant hierarchical state machines with QEP.

Copyright © 2002-2011 Quantum Leaps, LLC. All Rights Reserved.
http://www.state-machine.com

Generated on Fri Jan 7 2011 21:37:30 for QP/C++ by doxygen 1.7.3


QP/C++: QF Real-Time Framework

  • QP/C++ Reference Manual

QF Real-Time Framework

Quantum Frameowrk™ (QF) is a reusable event-driven application framework for executing concurrent state machines specifically designed for real-time embedded (RTE) systems. The use of QF generally simplifies the design of event-driven software by allowing the application to be divided into multiple active objects that the framework manages. Active objects in QF are encapsulated tasks (each embedding a state machine and an event queue) that communicate with one another asynchronously by sending and receiving events. Within an active object, events are processed sequentially in a run-to-completion (RTC) fashion, while QF encapsulates all the details of thread-safe event exchange and queuing.

Most of QF™ is written in portable ANSI-C, with microprocessor-specific, compiler-specific, or op-erating system-specific code kept to a minimum for ease of portability. QF is designed to work with Quantum Event Processor (QEP) and a Real Time Operating System (RTOS) of your choice, or even with just "main+ISRs" configuration. The framework is very compact, typically taking up about 4KB of code and data (including the QEP Hierarchical Event Processor). QF has been used in hundreds of event-driven applications worldwide and is described in Part 2 of the book Practical UML Statecharts in C/C++, Second Edition, Newnes 2008.

Please refer to the QP/C++ Tutorial for information on implementing event-driven applications with the QF real-time framework and other components of the QP event-driven platform.

Copyright © 2002-2011 Quantum Leaps, LLC. All Rights Reserved.
http://www.state-machine.com


QP/C++: QK Preemptive Run-To-Completion Kernel

  • QP/C++ Reference Manual

QK Preemptive Run-To-Completion Kernel

Quantum Kernel™ (QK) is a tiny preemptive real-time kernel specifically designed for executing independent tasks in a run-to-completion (RTC) fashion. As it turns out, the RTC-style processing universally applied in the QF Real-Time Framework, and no need for blocking of active objects, allow QK to be extremely simple and utilize only a single stack for all tasks and interrupts.

QK™ is not a standalone product but rather it requires a compatible version of QF. QK doesn't provide event queues, active objects, or even lookup tables used by the scheduler, because these elements are already part of the QF. QK is described in Chapter 10 of the book Practical UML Statecharts in C/C++, Second Edition, Newnes 2008.

Part 8.of the QP/C++ Tutorial describes how to use the QK kernel in an example.

Copyright © 2002-2011 Quantum Leaps, LLC. All Rights Reserved.
http://www.state-machine.com


QP/C++: QS Software Tracing Instrumentation (Target Component)

  • QP/C++ Reference Manual

QS Software Tracing Instrumentation (Target Component)

Quantum Spy™ (QS) is a real-time tracing instrumentation built into the QEP Hierarchical Event Processor, the QF Real-Time Framework, and the QK Preemptive Run-To-Completion Kernel components and also available to the Application code. QS allows you to gain unprecedented visibility into your application by selectively logging almost all interesting events occurring within state machines, the framework, the kernel, and your application code. QS event logging is minimally intrusive, offers precise time-stamping, sophisticated runtime filtering of events, and good data compression. QS can be configured to send the real-time data out of the serial or Ethernet port of the target device, or even write the data to a file. QS is described in Chapter 11 of the book Practical UML Statecharts in C/C++, Second Edition, Newnes 2008.

Every software tracing system consists of a target component and a host component. Section 8. Using the Built-in Real-Time Kernels and Third-Party RTOSes of the QP/C++ Tutorial describes how to enable the QS target component in an example. The host component for the QS software tracing system is the QSPY host application. Section QSPY Host Application Reference Manual describes how to use the QSPY host application.

Copyright © 2002-2011 Quantum Leaps, LLC. All Rights Reserved.
http://www.state-machine.com


QP/C++: QSPY Host Application Reference Manual

  • QP/C++ Reference Manual

QSPY Host Application Reference Manual

  • Introduction
  • QSPY Command-Line Parameters
  • Human-Readable QSPY Output
  • QSPY MATLAB Inteface

Introduction

Quantum Spy™ (QS) is a real-time tracing instrumentation built into the QP event-driven platform. QS allows you to gain unprecedented visibility into your application by selectively logging almost all interesting events occurring within state machines, the framework, the kernel, and your application code. QS event logging is minimally intrusive, offers precise time-stamping, sophisticated runtime filtering of events, and good data compression. QS can be configured to send the real-time data out of the serial or Ethernet port of the target device, or even write the data to a file. QS is described in Chapter 11 of the book Practical UML Statecharts in C/C++, Second Edition, Newnes 2008.

Every software tracing system consists of a target component and a host component. The host component for the Quantum Spy software tracing system is the QSPY host application. QSPY is a simple console application without any fancy GUI because its purpose is to provide only the QS data parsing, storing,and exporting to such powerful tools as MATLAB. QSPY has been designed from the ground up to be platform-neutral. The application is written in portable C++, and ports to Linux and Windows with various compilers are provided.

A typical setup for collecting software trace data with QSPY

QSPY is easily adaptable to various target-host communication links. Out of the box, the QSPY host application supports serial (RS232), TCP/IP, and file communication links. Adding other communication links is easy, because the data link layer is clearly abstracted in a Hardware Abstraction Layer (HAL). The QSPY application accepts several command-line parameters to configure all target dependencies, such as pointer sizes, signal sizes, etc. This means that the single QSPY host application can process data from any target 8-, 16-, or 32-bit.

QSPY provides a simple consolidated, human-readable textual output to the screen. If the QS trace data contains dictionary trace records, QSPY applies this symbolic information to output the provided identifiers for objects, signals, and states. Otherwise, QSPY outputs the hexadecimal values of various pointers and signals. (See Section Human-Readable QSPY Output).

Finally, QSPY can export the trace data in the matrix format readable by MATLAB. Special MATLAB script to import QSPY trace data to MATLAB is provided. Once the data is available in MATLAB matrices, it can be conveniently manipulated and visualized with this powerful tool. (See Section QSPY MATLAB Inteface).

QSPY Command-Line Parameters

The QSPY host application is designed to work with all possible target CPUs and data links, which requires a wide range of configurability. For example, for any given target CPU the QSPY application must "know" the size of object pointers, function pointers, event signals, timestamp size and so on. You provide this information to QSPY by means of command-line parameters, which are summarized in the following table:

Option | Example | Default | Must match QP macro (QP port header file) | Comments
-h | -h |  |  | Help. Prints the summary of options
-q | -q |  |  | Quiet mode (no stdout output)
-o | -o qs.txt |  |  | Produce output to the specified file
-s | -s qs.spy |  |  | Save the binary input to the specified file. Not compatible with -f
-m | -m qs.mat |  |  | Generates MATLAB output to the specified file
-c | -c COM2 | COM1 |  | COM port selection. Not compatible with -t, -p, -f
-b | -b 115200 | 38400 |  | Baud rate selection. Not compatible with -t, -p, -f
-t | -t |  |  | TCP/IP input selection. Not compatible with -c, -b, -f
-p | -p 6602 | 6601 |  | TCP/IP server port number. Not compatible with -c, -b, -f
-f | -f qs.spy |  |  | File input selection. Not compatible with -c, -b, -t, -p
-T | -T 2 | 4 | QS_TIME_SIZE (qs_port.h) | Time stamp size in bytes. Valid values: 1, 2, 4
-O | -O 2 | 4 | QS_OBJ_PTR_SIZE (qs_port.h) | Object pointer size in bytes. Valid values: 1, 2, 4
-F | -F 2 | 4 | #QS_FUN_PTR_SIZE (qs_port.h) | Function pointer size in bytes. Valid values: 1, 2, 4
-S | -S 2 | 1 | Q_SIGNAL_SIZE (qep_port.h) | Signal size in bytes. Valid values: 1, 2, 4
-E | -E 1 | 2 | QF_EVENT_SIZ_SIZE (qf_port.h) | Event-size size in bytes (i.e., the size of variables that hold event size). Valid values: 1, 2, 4
-Q | -Q 1 | 2 | QF_EQUEUE_CTR_SIZE (qf_port.h) | Queue counter size in bytes. Valid values 1, 2, 4
-P | -P 4 | 2 | QF_MPOOL_CTR_SIZE (qf_port.h) | Pool counter size in bytes. Valid values: 1, 2, 4
-B | -B 1 | 2 | QF_MPOOL_SIZ_SIZE (qf_port.h) | Block size size in bytes. (i.e., the size of variables that hold memory block size). Valid values 1, 2, 4
-C | -C 4 | 2 | QF_TIMEEVT_CTR_SIZE (qf_port.h) | Time event counter size. Valid values: 1, 2, 4

The QSPY host application is designed to work with all possible target CPUs and data links, which requires a wide range of configurability. For example, for any given target CPU the QSPY application must "know" the size of object pointers, function pointers, event signals, timestamp size and so on. You provide this information to QSPY by means of command-line parameters, which are summarized in table above. Please note that the options are case sensitive.

Your main concern when invoking QSPY is to match exactly the target system you are using. The fourth column of the table above lists the configuration macros used by the target system as well as the platform-specific QP header files where those macros are defined. You need to use the corresponding QSPY command-line option only when the QP macro differs from the default. The default values assumed by QSPY are consistent with the defaults used in QP.

Note:
When you do not match the QSPY host application with the QS target component, the QSPY application will be unable to parse correctly the mismatched trace records and will start generating the following errors:
     ********** 028: Error xx bytes unparsed
     ********** 014: Error -yy bytes unparsed

The number in front of the error indicates the Record ID of the trace record that could not be parsed.

Licensing QSPY

The QSPY host application is licensed the same way as all other components of the QP event-driven platform. See Section Licensing Policy for QP.

Copyright © 2002-2008 Quantum Leaps, LLC. All Rights Reserved.
http://www.quantum-leaps.com

Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: Human-Readable QSPY Output

  • QP/C++ Reference Manual
  • QSPY Host Application Reference Manual

Human-Readable QSPY Output

The QSPY host application is just a simple console-type program without any fancy user interface. QSPY application displays the trace data in a human-readable textual format. The following listing shows fragments of such a data log generated from the DOS/QK version of the DPP application.

Note:
The QSPY host application supports also exporting data to the powerful MATLAB environment, as described in Section QSPY MATLAB Inteface.
qspy host application 3.5.00
Copyright (c) Quantum Leaps, LLC.
Mon Feb 25 12:20:13 2008

-T 4
-O 4
-F 4
-S 1
-E 2
-Q 1
-P 2
-B 2
-C 2

           Obj Dic: 16CA18D8->l_smlPoolSto
           Obj Dic: 16CA1900->l_tableQueueSto
           Obj Dic: 16CA1914->l_philoQueueSto[0]
. . . . . .
           EQ.INIT: Obj=l_tableQueueSto Len= 5
0000000000 AO.ADD : Active=16CA1CB8 Prio= 6
           Obj Dic: 16CA1CB8->&l_table
           Fun Dic: 141E0006->&QHsm_top
           Fun Dic: 12DA00C9->&Table_initial
           Fun Dic: 12DA020B->&Table_serving
           Sig Dic: 00000008,Obj=16CA1CB8 ->HUNGRY_SIG
0000000000 AO.SUB : Active=l_table Sig=DONE_SIG
0000000000 AO.SUB : Active=l_table Sig=TERMINATE_SIG
           Q_INIT : Obj=l_table Source=QHsm_top Target=Table_serving
0000000000 ==>Init: Obj=l_table New=Table_serving
0000070346 QF_isrE: IsrNest= 1, CurrPrio=255
           TICK   : Ctr=         1
0000070367 QF_isrX: IsrNest= 1, CurrPrio=255
0000135566 QF_isrE: IsrNest= 1, CurrPrio=255
           TICK   : Ctr=         2
0000135581 QF_isrX: IsrNest= 1, CurrPrio=255
. . . . .
0000461783 QF_isrE: IsrNest= 1, CurrPrio=255
           TICK   : Ctr=         7
           TE.ADRM: Obj=l_philo[1].timeEvt Act=l_philo[1]
0000461797 TE.POST: Obj=l_philo[1].timeEvt Sig=TIMEOUT_SIG Act=l_philo[1]
0000461808 AO.FIFO: Obj=l_philo[1] Evt(Sig=TIMEOUT_SIG, Pool=0, Ref= 0)
>          Queue(nUsed=  5, nMax=  5)
0000461824 QF_isrX: IsrNest= 1, CurrPrio=255
0000461836 AO.GETL: Active= l_philo[1] Evt(Sig=TIMEOUT_SIG, Pool=0, Ref= 0)
0000461850 NEW    : Evt(Sig=HUNGRY_SIG, size=    3)
0000461862 MP.GET : Obj=l_smlPoolSto nFree=   9 nMin=   9
0000461874 AO.FIFO: Obj=l_table Evt(Sig=HUNGRY_SIG, Pool=1, Ref= 0)
>          Queue(nUsed=  5, nMax=  5)
0000461886 AO.GETL: Active= l_table Evt(Sig=HUNGRY_SIG, Pool=1, Ref= 1)
0000461906 NEW    : Evt(Sig=EAT_SIG, size=    3)

The QS trace log shown in the listing above contains quite detailed information, because most QS records are enabled (are not blocked in the QS filters). The following bullet items highlight the most interesting parts of the trace and illustrate how you can interpret the trace data:

  • The QS log always contains the QSPY application version number, the date and time of the run, and all the options explicitly provided to the QSPY host application.
  • A log typically starts with the dictionary records that provide a mapping between addresses of various objects in memory and their symbolic names. The dictionary entries don't have timestamps.
  • After the dictionaries, you see the active object initialization. For example, the EQ.INIT record indicates event queue initialization with the l_tableQueueSto buffer. After this the AO.ADD trace record you see adding the Table object with priority 6. At this point, the time tick interrupt is not configured, so all timestamps are 0000000000 (timestamps are always placed in the first 8 columns).
  • Active object initialization can contain dictionary entries for items that are encapsulated within the active object. For example initialization of Table inserts an object dictionary entry for l_table object and three function dictionary entries for state handlers QHsm_top, Table_initial and Table_serving. Finally, the top-most initial transition is taken from QHsm_top to Table_serving.
  • After the active object initialization, interrupts are enabled, and the first Tick interrupt arrives at the timestamp 0000070346. You can find out the type of the interrupt by the unique priority number. For example, the priority of the Tick interrupt is 0xFF == 255.

QEP Trace Records

Rec. Num. | Rec. Enum. | QSPY Abbrev. | Comment
0 | #QS_QEP_STATE_EMPTY |  |
1 | QS_QEP_STATE_ENTRY | Q_ENTRY | a state was entered
2 | QS_QEP_STATE_EXIT | Q_EXIT | a state was exited
3 | QS_QEP_STATE_INIT | Q_INIT | an intial transition was taken in a state
4 | QS_QEP_INIT_TRAN | ==>Init | the top-most initial transition was taken
5 | QS_QEP_INTERN_TRAN | Intern | an internal transition was taken
6 | QS_QEP_TRAN | ==>Tran | a regular transition was taken
7 | QS_QEP_IGNORED | Ignored | an event was ignored (silently discarded)
8 | QS_QEP_DISPATCH | Dispatch | an event was dispatched (begin of RTC step)

QF Trace Records

Rec. Num. | Rec. Enum. | QSPY Abbrev. | Comment
10 | QS_QF_ACTIVE_ADD | ADD | an AO has been added to QF (started)
11 | QS_QF_ACTIVE_REMOVE | REM | an AO has been removed from QF (stopped)
12 | QS_QF_ACTIVE_SUBSCRIBE | SUB | an AO subscribed to an event
13 | QS_QF_ACTIVE_UNSUBSCRIBE | USUB | an AO unsubscribed to an event
14 | QS_QF_ACTIVE_POST_FIFO | AO.FIFO | an event was posted (FIFO) directly to AO
15 | QS_QF_ACTIVE_POST_LIFO | AO.LIFO | an event was posted (LIFO) directly to AO
16 | QS_QF_ACTIVE_GET | AO.GET | AO got an event and its queue is still not empty
17 | QS_QF_ACTIVE_GET_LAST | AO.GETL | AO got an event and its queue is empty
18 | QS_QF_EQUEUE_INIT | EQ.INIT | an event queue was initialized
19 | QS_QF_EQUEUE_POST_FIFO | EQ.FIFO | an event was posted (FIFO) to a raw queue
20 | QS_QF_EQUEUE_POST_LIFO | EQ.LIFO | an event was posted (LIFO) to a raw queue
21 | QS_QF_EQUEUE_GET | EQ.GET | get an event and queue still not empty
22 | QS_QF_EQUEUE_GET_LAST | EQ.GETL | get the last event from the queue
23 | QS_QF_MPOOL_INIT | MP.INIT | a memory pool was initialized
24 | QS_QF_MPOOL_GET | MP.GET | a memory block was removed from a memory pool
25 | QS_QF_MPOOL_PUT | MP.PUT | a memory block was returned to a memory pool
26 | QS_QF_PUBLISH | PUBLISH | an event was published
27 | #reserved |  |
28 | QS_QF_NEW | NEW | new event creation
29 | QS_QF_GC_ATTEMPT | GC-ATT | garbage collection attempt
30 | QS_QF_GC | GC | garbage collection performed
31 | QS_QF_TICK | TICK | QF_tick() was called
32 | QS_QF_TIMEEVT_ARM | TE.ARM | a time event was armed
33 | QS_QF_TIMEEVT_AUTO_DISARM | TE.ADRM | a time event expired and was disarmed
34 | QS_QF_TIMEEVT_DISARM_ATTEMPT | TE.DATT | attempt to disarmed a disarmed tevent
35 | QS_QF_TIMEEVT_DISARM | TE.DARM | true disarming of an armed time event
36 | QS_QF_TIMEEVT_REARM | TE.RARM | rearming of a time event
37 | QS_QF_TIMEEVT_POST | TE.POST | a time event posted itself directly to an AO
38 | #reserved |  |
39 | QS_QF_INT_LOCK | QF_intL | interrupts were locked
40 | QS_QF_INT_UNLOCK | QF_intU | interrupts were unlocked
42 | QS_QF_ISR_ENTRY | QF_isrE | an ISR was entered
42 | QS_QF_ISR_EXIT | QF_isrX | an ISR was exited

QK Trace Records

Rec. Num. | Rec. Enum. | QSPY Abbrev. | Comment
50 | QS_QK_MUTEX_LOCK | QK_muxL | the QK mutex was locked
51 | QS_QK_MUTEX_UNLOCK | QK_muxU | the QK mutex was unlocked
52 | QS_QK_SCHEDULE | QK_sche | the QK scheduled a new task to execute

Miscellaneous Trace Records

Rec. Num. | Rec. Enum. | QSPY Abbrev. | Comment
60 | QS_SIG_DICTIONARY | Sig Dic | signal dictionary entry
61 | QS_OBJ_DICTIONARY | Obj Dic | object dictionary entry
62 | QS_FUN_DICTIONARY | Fun Dic | function dictionary entry
63 | QS_ASSERT | !ASSERT | Assertion fired
... |  |  |
70 | QS_USER | UserXXX | the first record available for user QS records

Copyright © 2002-2008 Quantum Leaps, LLC. All Rights Reserved.
http://www.quantum-leaps.com

Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: QSPY MATLAB Inteface

  • QP/C++ Reference Manual
  • QSPY Host Application Reference Manual

QSPY MATLAB Inteface

The QSPY host application can also export trace data to MATLAB®, which is a popular numerical computing environment and a high-level technical programming language. Created by The MathWorks, Inc., MATLAB allows easy manipulation and plotting of data represented as matrices.

The following sections provide a reference manual for all 11 the MATLAB matrices generated by the qspy.m script. By MATLAB convention, the different variables are put into columns, allowing observations to vary down through the rows. Therefore, a data set consisting of twenty four time samples of six variables is stored in a matrix of size 24-by-6. The pound sign '#' in a given cell of the matrix represents data available from the target. Other values, represent data added by the qspy.m script to allow unambiguous identification of the trace records.

  • Q_STATE Matrix
  • Q_ACTIVE Matrix
  • Q_EQUEUE Matrix
  • Q_MPOOL Matrix
  • Q_NEW Matrix
  • Q_PUB Matrix
  • Q_TIME Matrix
  • Q_INT Matrix
  • Q_ISR Matrix
  • Q_MUTEX Matrix
  • Q_SCHED Matrix

Q_STATE Matrix

The N-by-6 Q_STATE matrix stores all QS records generated by the QEP hierarchical event processor and pertaining to all the state machines in the system. The following table summarizes how the QS records are stored in the matrix:

MATLAB index --> | 1 | 2 | 3 | 4 | 5 | 6
QS Record | V | Time Stamp | Signal | State Machine Object | Source State | New State | Event Hanlder
QS_QEP_STATE_ENTRY | NaN | 1 | #(2) | # | NaN | 1
QS_QEP_STATE_EXIT | NaN | 2 | #(2) | # | NaN | 1
QS_QEP_STATE_INIT | NaN | 3 | # | # | # | 1
QS_QEP_INIT_TRAN | # | 3 | #(2) | NaN | # | 1
QS_QEP_INTERN_TRAN | # | #(1) | #(2) | # | NaN | 1
QS_QEP_TRAN | # | #(1) | #(2) | # | # | 1
QS_QEP_IGNORED | # | #(1) | #(2) | # | NaN | 0
QS_QEP_DISPATCH | # | #(1) | #(2) | # | NaN | 0

(1) The valid USER signal is > 3

(2) Per inheritance, an active object is a state machine object as well

The following criteria (index matrices in MATLAB) unambiguously select the QS records from the Q_STATE matrix:

QS Record | MATLAB Index Matrix
QS_QEP_STATE_ENTRY | Q_STATE(:,2) == 1
QS_QEP_STATE_EXIT | Q_STATE(:,2) == 2
QS_QEP_STATE_INIT | Q_STATE(:,2) == 3
QS_QEP_INIT_TRAN | isnan(Q_STATE(:,4))
QS_QEP_INTERN_TRAN | Q_STATE(:,2) > 3 & isnan(Q_STATE(:,5))
QS_QEP_TRAN | Q_STATE(:,2) > > & ~isnan(Q_STATE(:,5))
QS_QEP_IGNORED | ~Q_STATE(:,6)

For example, the following MATLAB plot shows the timing diagrams for all Philo state machines in the DPP example application made by the philo_timing.m script located in the directory \tools\qspy\matlab\ (see Section Directories and Files in the QP/C++ Distribution). The vertical axis represents states "thinking" (lowest), "hungry" (middle) and "eating" (top) states.

Timing diagrams for all Philo state machines.

Q_ACTIVE Matrix

The N-by-5 Q_ACTIVE matrix stores QS records pertaining to adding/removing active objects and subscribing/unsubscribing to events from active objects. The following table summarizes how the QS records are stored in the matrix:

MATLAB index --> | 1 | 2 | 3 | 4 | 5
QS Record | V | Time Stamp | Signal | Active Object | QF Priority | Delta
QS_QF_ACTIVE_ADD | # | NaN | # | # | +1
QS_QF_ACTIVE_REMOVE | # | NaN | # | # | -1
QS_QF_ACTIVE_SUBSCRIBE | # | # | # | NaN | +1
QS_QF_ACTIVE_UNSUBSCRIBE | # | # | # | NaN | -1

The following criteria (index matrices in MATLAB) unambiguously select the QS records from the Q_ACTIVE matrix:

QS Record | MATLAB Index Matrix
QS_QF_ACTIVE_ADD | isnan(Q_ACTIVE(:,2)) & Q_ACTIVE(:,5) > 0
QS_QF_ACTIVE_REMOVE | isnan(Q_ACTIVE(:,2)) & Q_ACTIVE(:,5) < 0
QS_QF_ACTIVE_SUBSCRIBE | isnan(Q_ACTIVE(:,4)) & Q_ACTIVE(:,5) > 0
QS_QF_ACTIVE_UNSUBSCRIBE | isnan(Q_ACTIVE(:,4)) & Q_ACTIVE(:,5) < 0

Q_EQUEUE Matrix

The N-by-9 Q_EQUEUE matrix stores QS records pertaining to queuing events in the QF. Both the active object event queues and the "raw" thread-safe queues are included. The 'nUsed' field denotes the current number of used entries in the queue. The 'Maximum nUsed' filed denotes the maximum number of used entries since initialization (high watermark). Both fields contain the number of used entries in the queues ring-buffer plus one, to account for the extra location at the front of the queue. The following table summarizes how the QS records are stored in the matrix:

MATLAB index --> | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
QS Record | V | Time Stamp | Event Queue (1) | nFree | Minimum Used | Signal | Pool ID | Ref. Count | LIFO | Delta
QS_QF_EQUEUE_INIT | NaN | # | NaN | 0 | NaN | NaN | NaN | 0 | 0
QS_QF_ACTIVE_POST_FIFO | # | # | # | # | # | # | # | 0 | +1
QS_QF_ACTIVE_POST_LIFO | # | # | # | # | # | # | # | 1 | +1
QS_QF_ACTIVE_GET | # | # | # | NaN | # | # | # | 0 | -1
QS_QF_ACTIVE_GET_LAST | # | # | NaN | NaN | # | # | # | 0 | -1
QS_QF_EQUEUE_POST_FIFO | # | # | # | # | # | 1 | # | 0 | +1
QS_QF_EQUEUE_POST_LIFO | # | # | # | # | # | # | # | 1 | +1
QS_QF_EQUEUE_GET | # | # | # | # | # | # | # | 0 | -1
QS_QF_EQUEUE_GET_LAST | # | # | NaN | NaN | # | # | # | 0 | -1

(1) This field (index 2) is actually the pointer to the ring buffer of the queue.

The following criteria (index matrices in MATLAB) unambiguously select the QS records from the Q_EQUEUE matrix:

QS Record | MATLAB Index Matrix
QS_QF_EQUEUE_INIT | Q_EQUEUE(:,9) == 0
QS_QF_ACTIVE_POST_FIFO | Q_EQUEUE(:,2) == <active obj> & ~Q_EQUEUE(:,8) & Q_EQUEUE(:,9) > 0
QS_QF_ACTIVE_POST_LIFO | Q_EQUEUE(:,2) == <active obj> & Q_EQUEUE(:,8) & Q_EQUEUE(:,9) > 0
QS_QF_ACTIVE_GET | Q_EQUEUE(:,2) == <active obj> & ~isnan(Q_EQUEUE(:,3) & Q_EQUEUE(:,9) < 0
QS_QF_ACTIVE_GET_LAST | Q_EQUEUE(:,2) == <active obj> & isnan(Q_EQUEUE(:,3) & Q_EQUEUE(:,9) < 0
QS_QF_EQUEUE_POST_FIFO | Q_EQUEUE(:,2) == <raw queue> & ~Q_EQUEUE(:,8) & Q_EQUEUE(:,9) > 0
QS_QF_EQUEUE_POST_LIFO | Q_EQUEUE(:,2) == <raw queue> & Q_EQUEUE(:,8) & Q_EQUEUE(:,9) > 0
QS_QF_EQUEUE_GET | Q_EQUEUE(:,2) == <raw queue> & ~isnan(Q_EQUEUE(:,3) & Q_EQUEUE(:,9) < 0
QS_QF_EQUEUE_GET_LAST | Q_EQUEUE(:,2) == <raw queue> & isnan(Q_EQUEUE(:,3) & Q_EQUEUE(:,9) < 0

Q_MPOOL Matrix

The N-by-5 Q_MPOOL matrix stores QS records pertaining to memory pools in the QF. The 'nFree' field denotes the current number of free blocks in the event pool. The 'Minimum nFree' filed denotes the minimal number of free blocks since initialization (low watermark). The following table summarizes how the QS records are stored in the matrix:

MATLAB index --> | 1 | 2 | 3 | 4 | 5
QS Record | V | Time Stamp | Pool Object | nFree | Minimal nFree | Delta
QS_QF_MPOOL_INIT | NaN | # | # | NaN | 0
QS_QF_MPOOL_GET | # | # | # | # | -1
QS_QF_MPOOL_PUT | # | # | # | NaN | +1

The cumulative sum over the 'Delta' column should not have any long-time trends, because this would indicate a leak from the pool. The following picture shows the plot for the test data.

Plot stairs(Q_MPOOL(:,1), cumsum(Q_MPOOL(:,5)))

The following criteria (index matrices in MATLAB) unambiguously select the QS records from the Q_MPOOL matrix:

QS Record | MATLAB Index Matrix
QS_QF_MPOOL_INIT | Q_MPOOL(:,5) == 0
QS_QF_MPOOL_GET | Q_MPOOL(:,5) < 0
QS_QF_MPOOL_PUT | Q_MPOOL(:,5) > 0

Q_NEW Matrix

The N-by-6 Q_NEW matrix stores QS records pertaining to dynamic event allocation and automatic event recycling (garbage collection) in the QF. The following table summarizes how the QS records are stored in the matrix:

MATLAB index --> | 1 | 2 | 3 | 4 | 5 | 6
QS Record | V | Time Stamp | Signal | PoolID | Ref. Count | Event Size | Delta
QS_QF_NEW | # | # | NaN | NaN | # | +1
QS_QF_GC_ATTEMPT | # | # | # | # | NaN | 0
QS_QF_GC | # | # | # | NaN | NaN | -1

The cumulative sum over the 'Delta' column should not have any long-time trends, because this would indicate event leak. The following picture shows the plot for the test data.

Plot stairs(Q_NEW(:,1), cumsum(Q_NEW(:,6)))

The following criteria (index matrices in MATLAB) unambiguously select the QS records from the Q_NEW matrix:

QS Record | MATLAB Index Matrix
QS_QF_NEW | Q_NEW(:,6) > 0
QS_QF_GC_ATTEMPT | Q_NEW(:,6) == 0
QS_QF_GC | Q_NEW(:,6) < 0

Q_PUB Matrix

The N-by-6 Q_PUB matrix stores QS records pertaining to publishing events in QF. The following table summarizes how the QS records are stored in the matrix:

MATLAB index --> | 1 | 2 | 3 | 4 | 5 | 6
QS Record | V | Time Stamp | Signal | PoolID | Ref. Count | # Events Multicast | Delta
QS_QF_PUBLISH | # | # | # | # | # | #

The following criteria (index matrices in MATLAB) unambiguously select the QS records from the Q_PUB matrix:

QS Record | MATLAB Index Matrix
QS_QF_PUBLISH | Q_PUB(:,6) > 0

Q_TIME Matrix

The N-by-7 Q_TIME matrix stores QS records pertaining to time events in QF. The following table summarizes how the QS records are stored in the matrix:

MATLAB index --> | 1 | 2 | 3 | 4 | 5 | 6 | 7
QS Record | V | Time Stamp | QTimeEvt Object | Signal | QActive Object | QTimeEvt Counter | QTimeEvt Interval | QTimeEvt Delta
QS_QF_TICK | NaN | NaN | NaN | NaN | #(1) | NaN | 0
QS_QF_TIMEEVT_ARM | # | # | NaN | # | # | # | +1
QS_QF_TIMEEVT_DISARM | # | # | NaN | # | # | # | -1
QS_QF_TIMEEVT_AUTO_DISARM | NaN | # | NaN | # | NaN | NaN | -1
QS_QF_TIMEEVT_DISARM_ATTEMPT | # | # | NaN | # | NaN | NaN | 0
QS_QF_TIMEEVT_REARM | # | # | NaN | # | # | # | #(2)
QS_QF_TIMEEVT_POST | # | # | # | # | NaN | NaN | 0

(1) For QS_QF_TICK record this matrix element contains the Tick Counter.

(2) For QS_QF_TIMEEVT_REARM event this matrix element is 0 if the time event was disarmed and rearmed again, and 1 if the time event was only armed.

The cumulative sum over the 'Delta' column indicates the total number of armed time events at any given time. The following picture shows the plot for the test data:

Plot stairs(Q_TIME(:,1), cumsum(Q_TIME(:,7)))

The following criteria (index matrices in MATLAB) unambiguously select the QS records from the Q_TIME matrix:

QS Record | MATLAB Index Matrix
QS_QF_TICK | isnan(Q_TIME(:,2))
QS_QF_TIMEEVT_ARM | Q_TIME(:,7) > 0
QS_QF_TIMEEVT_DISARM | ~isnan(Q_TIME(:,1)) & Q_TIME(:,7) < 0
QS_QF_TIMEEVT_AUTO_DISARM | isnan(Q_TIME(:,1)) & Q_TIME(:,7) < 0
QS_QF_TIMEEVT_DISARM_ATTEMPT | isnan(Q_TIME(:,3)) & isnan(Q_TIME(:,5)) & Q_TIME(:,7) == 0
QS_QF_TIMEEVT_REARM | isnan(Q_TIME(:,3)) & ~isnan(Q_TIME(:,5))
QS_QF_TIMEEVT_POST | ~isnan(Q_TIME(:,3)) & ~isnan(Q_TIME(:,4))

Q_INT Matrix

The N-by-3 Q_INT matrix stores QS records pertaining to interrupt locking and unlocking. The following table summarizes how the QS records are stored in the matrix:

MATLAB index --> | 1 | 2 | 3
QS Record | V | Time Stamp | Interrupt Nesting | Nesting Delta
QS_QF_INT_LOCK | # | # | +1
QS_QF_INT_UNLOCK | # | # | -1

The cumulative sum over the 'Delta' column indicates interrupt lock nesting and should closely follow column 2.

The following criteria (index matrices in MATLAB) unambiguously select the QS records from the Q_INT matrix:

QS Record | MATLAB Index Matrix
QS_QF_INT_LOCK | Q_INT(:,3) > 0
QS_QF_INT_UNLOCK | Q_INT(:,3) < 0

Q_ISR Matrix

The N-by-4 Q_ISR matrix stores QS records pertaining to interrupt entry and exit. The following table summarizes how the QS records are stored in the matrix:

MATLAB index --> | 1 | 2 | 3 | 4
QS Record | V | Time Stamp | Interrupt Nesting | ISR Priority | Nesting Delta
QS_QF_ISR_ENTRY | # | # | # | +1
QS_QF_ISR_EXIT | # | # | # | -1

The cumulative sum over the 'Delta' column indicates interrupt nesting level and should closely follow column 2.

The following criteria (index matrices in MATLAB) unambiguously select the QS records from the Q_ISR matrix:

QS Record | MATLAB Index Matrix
QS_QF_ISR_ENTRY | Q_ISR(:,4) > 0
QS_QF_ISR_EXIT | Q_ISR(:,4) < 0

Q_MUTEX Matrix

The N-by-4 Q_MUTEX matrix stores QS records pertaining to the priority-ceiling mutex activity in QK. The following table summarizes how the QS records are stored in the matrix:

MATLAB index --> | 1 | 2 | 3 | 4
QS Record | V | Time Stamp | Original Priority | Priority Ceiling | Nesting Delta
QS_QK_MUTEX_LOCK | # | # | # | +1
QS_QK_MUTEX_UNLOCK | # | # | # | -1

The cumulative sum over the 'Delta' column indicates QK scheduler lock nesting level.

Plot stairs(Q_MUTEX(:,1), cumsum(Q_MUTEX(:,4)), 'r') (red)

The following criteria (index matrices in MATLAB) unambiguously select the QS records from the Q_ISR matrix:

QS Record | MATLAB Index Matrix
QS_QK_MUTEX_LOCK | Q_MUTEX(:,4) > 0
QS_QK_MUTEX_UNLOCK | Q_MUTEX(:,4) < 0

Q_SCHED Matrix

The N-by-3 Q_SCHED matrix stores QS records pertaining to scheduling next task in QK. The following table summarizes how the QS records are stored in the matrix:

MATLAB index --> | 1 | 2 | 3
QS Record | V | Time Stamp | Preempted Priority | New Priority
QS_QK_SCHEDULE | # | # | #

Copyright © 2002-2008 Quantum Leaps, LLC. All Rights Reserved.
http://www.quantum-leaps.com

Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: QP/C++ Tutorial

  • QP/C++ Reference Manual

QP/C++ Tutorial

This QP/C++ 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.

This Tutorial presents an example project implemented entirely with the QP/C event-driven platform using UML state machines and the event-driven paradigm. The example application is an interactive "Fly 'n' Shoot"-type game. My aim in this section is to show the essential elements of the method in a real, nontrivial program, but without getting bogged down in details, rules, and exceptions. At this point, I am not trying to be complete or even precise, although this example is meant to show a good design and the recommended coding style. I don't assume that you know much about UML state machines, the UML notation, or the event-driven programming. I will either briefly introduce the concepts, as needed, or refer you to the the Practical UML Statecharts in C/C++, Second Edition book for more details. The example "Fly 'n' Shoot" game is based on the "Quickstart" application provided in source code with the ARM Cortex-M3 LM3S811 evaluation kit (see Figure 2-2) from Luminary Micro (http://www.luminarymicro.com). I was trying to make the "Fly 'n' Shoot" example behave quite similarly to the original Luminary Micro "Quickstart" application, so that you can directly compare the event-driven approach with the traditional solution to essentially the same problem specification.

  • 1. Installing QP/C++ and Building QP Libraries and Applications
  • 2. Let's Play
  • 3. The main() Function
  • 4. Designing an Event-Driven Application
  • 5. Elaborating State Machines of Active Objects
  • 6. Defining Event Signals and Event Parameters
  • 7. Coding Hierarchical State Machines
  • 8. Using the Built-in Real-Time Kernels and Third-Party RTOSes
  • 9. Using Software Tracing for Testing and Debugging
  • 10. Comparison to the Traditional Approach
  • 11. Summary
Note:
The standard QP/C distribution contains two versions of the game. A DOS version is provided for the standard Windows-based PC so that you don't need any special embedded board to play the game and experiment with the code. Also provided is an embedded version for the inexpensive ARM Corterx-M3-based LM3S811 evaluation kit from Luminary Micro. Both the PC and the ARM-Cortex versions use the exact same source code for all application components and differ only in the Board Support Package (BSP).

Next: 1. Installing QP/C++ and Building QP Libraries and Applications

Copyright © 2002-2011 Quantum Leaps, LLC. All Rights Reserved.
http://www.state-machine.com

Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: 1. Installing QP/C++ and Building QP Libraries and Applications

  • QP/C++ Reference Manual
  • QP/C++ Tutorial

1. Installing QP/C++ and Building QP Libraries and Applications

This QP/C++ 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: QP/C++ Tutorial
Next: 2. Let's Play

QP/C++ is distributed in a simple platform-independent ZIP file, or in a self-extracting Windows executable. Either way, installing QP requires simply decompressing the provided archive into a directory of your choice (e.g., <qpcpp> for QP/C++). The Section Directories and Files in the QP/C++ Distribution describes the directories and files included in the standard QP/C++ distribution.

Specifically to the "Fly 'n' Shoot" example, the companion code contains two versions of the game. I provide a DOS version for the standard Windows-based PC (see Figure 2-1) so that you don't need any special embedded board to play the game and experiment with the code.

Note:
I've chosen the legacy 16-bit DOS platform because it allows programming a standard PC at the bare-metal level. Without leaving your desktop, you can work with interrupts, directly manipulate CPU registers, and directly access the I/O space. No other modern 32-bit development environment for the standard PC allows this much so easily. The ubiquitous PC running under DOS (or a DOS console within any variant of Windows) is as close as it gets to emulate embedded software development on the commodity 80x86 hardware. Additionally, you can use free, mature tools, such as the Open Watcom C/C++ compiler.

I also provide an embedded version for the inexpensive ARM Corterx-M3-based LM3S811 evaluation kit from Luminary Micro (see Figure 2-2). Both the PC and ARM-Cortex versions use the exact same source code for all application components and differ only in the Board Support Package (BSP).

1.1 Building QP Libraries

Note:
The pre-compiled QP libraries are provided in the standard QP distribution (see Directories and Files in the QP/C++ Distribution), so you can start experimenting with all examples without building the QP libraries. However, if you want to re-build the QP libraries, this section provides the details.

Figure 1-1 illustrates the steps required to build the QF library. The process of building other QP components, such as QEP or QK, is essentially identical. The key point of the design is that all platform-independent QF source files include the same qf_port.h header file as the application source files (see Figure 1-1). At this point you can clearly see that the Platfrom Abstraction Layer (PAL) provided in QP plays the dual role of facilitating the porting of QP as well as using it in the applications. Figure 1-1 shows also that every QP component, such as QF, can contain a platform-specific source file (qf_port.cpp in this case). The platform-specific source file is optional and many ports don't require it.

Figure 1-1 Building the QF library.

The standard QP ports often contain a simple make.bat script or a Makefile for building all the QP libraries for the port. You typically can choose the build configuration by providing a target to the make.bat script or to the Makefile. The default target is "dbg". Other possible targets are "rel", and "spy". The following table summarizes the targets accepted by the make.bat scripts or the Makefiles.

Build Configuration | Build Command
Debug | make
Release | make rel
Spy | make spy
Note:
All QP components are designed to be deployed in fine-granularity object libraries. QP libraries allow the linker to eliminate any unreferenced QP code at link time, which results in automatic scaling of every QP component for a wide range of applications. This approach eliminates the need to manually configure and recompile the QP source code for each application at hand.

1.2 Building QP Applications

Note:
The standard QP distribution contains pre-compiled examples (see Directories and Files in the QP/C++ Distribution), so you can start experimenting with all examples without building them. However, if you want to re-build the QP examples, this section provides the details.

Figure 1-2 shows the process of building a QP application. Each QP component requires inclusion of only one platform-specific header file and linking one platform-specific library. For example, to use the QF real-time framework, you need to include the qf_port.h header file and you need to link the qf.lib library file from the specific QP port directory. It really doesn't get any simpler than that.

Figure 1-2 Building a QP-based Application.

The QP port you are using is determined by the directory branch in which the qf_port.h header file and the QF library file are located. Section Directories and Files in the QP/C++ Distribution shows some examples of such port directories. Typically you need to instruct the C/C++ compiler to include header files from the specific QP port directory and also from the platform-independent include directory <qpcpp>\include\. I strongly discourage hard-coding full path-names of the include files in your source code. You should simply include the QP port header file (#include "qf_port.h") without any path. Then you specify to the compiler to search the QP port directory for include files, typically through the -I option.

Prev: QP/C++ Tutorial
Next: 2. Let's Play

Copyright © 2002-2011 Quantum Leaps, LLC. All Rights Reserved.
http://www.state-machine.com

Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: 2. Let's Play

  • QP/C++ Reference Manual
  • QP/C++ Tutorial

2. Let's Play

This QP/C++ 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: 1. Installing QP/C++ and Building QP Libraries and Applications
Next: 3. The main() Function

The following description of the "Fly 'n' Shoot" game serves the dual purpose of explaining how to play the game and as the problem specification for the purpose of designing and implementing the software later in this Tutorial. To accomplish these two goals I need to be quite detailed, so please bear with me.

Your objective in the game is to navigate a space ship through an endless horizontal tunnel with mines. Any collision with the tunnel or the mine destroys the ship. You can move the ship up and down with UP-arrow and DOWN-arrow keys on the PC (see Figure 2-1) or the potentiometer wheel on the LM3S811 board (see Figure 2-2). You can also fire a missile to destroy the mines in the tunnel by pressing the SPACE-bar on the PC or the User button on the LM3S811 board. Score accumulates for survival (at the rate of 30 points per second) and destroying the mines.

The game lasts for only one ship. The game starts in a demo mode, where the tunnel walls scroll at the normal pace from right to left and the "Press Button" text flashes in the middle of the screen. You need to generate the "fire missile" event for the game to begin (press SPACE-bar on the PC and the User Button on the LM3S811 board). You can have only one missile in flight at a time, so trying to fire a missile while it is already flying has no effect. Hitting the tunnel wall with the missile brings you no points, but you earn extra points for destroying the mines.

The game has two types of mines with different behavior. In the original Luminary "Quickstart" application both types of mines behave the same, but I wanted to demonstrate how state machines can elegantly handle differently behaving mines.

Mine type-1 is small, but can be destroyed by hitting any of its pixels with the missile. You earn 25 points for destroying a mine type- Mine type-2 is bigger, but is nastier in that the missile can destroy it only by hitting its center, not any of the "tentacles". Of course, the ship is vulnerable to the whole mine. You earn 45 points for destroying a mine type 2.

When your crash the ship, either by hitting a wall or a mine, the game ends and displays the flashing "Game Over" text as well as your final score. After 5 seconds of flashing, the "Game Over" screen changes back to the demo screen, where the game waits to be started again.

Additionally the application contains a screen saver because the OLED display of the original LM3S811 board has burn-in characteristics similar to a CRT. The screen saver only becomes active if 20 seconds elapse in the demo mode without starting the game (i.e., the screen saver never appears during game play). The screen saver is a simple random-pixel-type, rather than the "Game of Life" algorithm used in the original Luminary "Quickstart" application. I've decided to simplify this aspect of the implementation, because the more elaborate pixel-mixing algorithm does not contribute any new or interesting behavior. After a minute of running the screen saver, the display turns blank and only a single random pixel shows on the screen. Again, this is a little difference from the original "Quickstart" application, which instead blanks the screen and starts flashing the User LED. I've changed this behavior because I have a better purpose for the User LED (to visualize the activity of the idle loop).

Running the DOS Version

The "Fly 'n' Shoot" sample code for the DOS version (in C++) is located in <qpcpp>\examples\80x86\dos\watcom\l\game\, directory, where <qpcpp> stands for the installation directory you chose to install the QP/C++ software.

The compiled executable is provided, so you can run the game on any Windows-based PC by simply double-clicking on the executable game.exe located in the directory <qpcpp>\examples\80x86\dos\watcom\l\game\dbg\.

Figure 2-1 The Fly 'n' Shoot game running in a DOS window under Windows XP.

The first screen you see is the game running in the demo mode with the text "Push Button" flashing in the middle of the display. At the top of the display you see a legend of keystrokes recognized by the application. You need to hit the SPACE key to start playing the game. Please press the ESC key to cleanly exit the application.

If you run "Fly 'n' Shoot" in a window under Microsoft Windows, the animation effects in the game might appear a little jumpy, especially when compared to the ARM-Cortex version of the same game. You can make the application execute significantly smoother if you switch to the full-screen mode by pressing and holding the Alt key and then pressing the Enter key. You go back to the window mode by the same Alt-Enter key combination.

As you can see in Figure 2-1, the DOS version uses simply the standard VGA text mode to emulate the OLED display of the LM3S811 board. The lower part of the DOS screen is used as a matrix of 80x16 character-wide "pixels", which is a little less than the 96x16 pixels of the OLED display, but is still good enough to play the game. I specifically avoid employing any fancier graphics in this early example because I have a bigger fish to fry for you than to worry about the irrelevant complexities of programming graphics. My main goal is to make it easy for you to understand the event-driven code and experiment with it.

To this end, I chose the Open Watcom toolset to build this example as well as several other examples in this book. Open Watcom it is available under a OSI-certified open source license that permits free commercial and non-commercial use. You can download Open Watcom C/C++ toolset for DOS from ftp://ftp.openwatcom.org/. Please select the open-watcom-c-dos-1.8.exe installer. Ready to print documentation in PDF format is also available from http://www.openwatcom.org/index.php/Manuals.

The Open Watcom C/C++ toolset for DOS is distributed as a Windows installer. After you download the open-watcom-c-dos-1.8.exe file, please launch the installer and follow the instructions it provides.

Note:
I strongly recommend that you install the Open Watcom toolset into the directory C:\tools\watcom\. That way, you will be able to use directly the provided make scripts. If you choose to install Open Watcom into a different location, you can still use the make scripts supplied with the QP distribution, but you need to define the WATCOM environment variable. You should not install Open Watcom in the standard "Prgram Files" directory or any directory name with a space.

To experinment with the "Fly 'n' Shoot" game code you can use any code editor to modify the source code. Then you re-build the application by means of the supplied make.bat script, which is located in the directory <qpcpp>\examples\80x86\dos\watcom\l\game\.

In the next section, I describe briefly how to run the embedded version of the game. If you are not interested in the ARM-Cortex version, please feel free to skip to the following Section 3. The main() Function, where I start explaining the application code.

Running the ARM-Cortex Version

In contrast to the "Fly 'n' Shoot" version for DOS running in the ancient real mode of the 80x86 processor, the exact same source code runs on one of the most modern processors in the industry: the ARM-Cortex.

Figure 2-2 The Fly 'n' Shoot game running on the ARM Cortex-M3 LM3S811 evaluation board.

The sample code for the ARM Cortex-M3 LM3S811 board is located in <qpcpp>\examples\arm-cortex\vanilla\iar\game-ev-lm3s811\ directory, where <qpcpp> stands for the root directory you chose to install the accompanying software. The code for the ARM-Cortex kit has been compiled with the 32KB-limited Kickstart edition of the IAR Embedded Workbench for ARM (IAR EWARM) v 5.40, which is provided with the ARM Cortex-M3 EKI-LM3S811 kit. You can also download this software free of charge directly from IAR Systems (http://www.iar.com), after filling out an online registration.

The installation of IAR EWARM is quite straightforward, as the software comes with the installation utility. You also need to install the USB drivers for the hardware debugger built into the LM3S811 board, as described in the documentation of the ARM Cortex-M3 LM3S811 kit.

Note:
I strongly recommend that you install the IAR EWARM toolset into the directory C:\tools\iar\arm_ks_5.40 That way, you will be able to use directly the provided EWARM workspace files and make scripts.

Before you program the "Fly 'n' Shoot" game to the LM3S811 board, you might want to play a little with the original "Quickstart" application that comes pre-programmed with the LM3S811 kit.

To program the "Fly 'n' Shoot" game to the flash memory of the LM3S811 board, you first connect the LM3S811 board to your PC with the USB cable provided in the kit and make sure that the Power LED is on (see Figure 2-2). Next, you need to launch the IAR Embedded Workbench and open the workspace game-ev-lm3s81eww located in <qpcpp>\examples\arm-cortex\vanilla\iar\game-ev-lm3s811\ directory. At this point your screen should look similar to the screenshot shown in Figure 2-3. The game-ev-lm3s811 project is set up to use the LMI FTDI debugger, which is the piece of hardware integrated on the LM3S811 board (see Figure 2-2). You can verify this setup by opening the "Options" dialog box via the Project->Options menu. Within the "Options" dialog box, you need to select the Debugger category in the panel on the left. While you are at it, you could also verify that the flash loading is enabled by selecting the "Download" tab. The checked "Use flash loader(s)" checkbox means that the flash loader application provided by IAR will be first loaded to the RAM of the MCU, and this application will program the flash with the image of your application. To start the flash programming process, select the Project->Debug menu, or simply click on the Debug button (see Figure 2-3) in the toolbar. The IAR Workbench should respond by showing the flash programming progress bar for several seconds, as shown in Figure 2-3. Once the flash programming completes, the IAR EWARM switches to the IAR C-Spy debugger and the program should stop at the entry to main(). You can start playing the game either by hitting the "Go" button in the debugger, or you can close the debugger and reset the board by pressing the Reset button. Either way, "Fly 'n' Shoot" game is now permanently programmed into the LM3S811 board and will start automatically upon every power up.

Figure 2-3 Loading the Fly 'n' Shoot game into the flash of LM3S811 MCU with IAR EWARM IDE

The IAR Embedded Workbench environment allows you to experiment with the "Fly 'n' Shoot" code very easily. You can edit the files and recompile the application at a click of a button (F7). The only caveat is that the first time after the installation of the IAR toolset you need to build the Luminary Micro driver library for the LM3S811 MCU from the sources. You accomplish this by loading the workspace ek-lm3s81eww located in the directory <IAR-EWARM>\ARM\examples\Luminary\Cortex-M3\boards\ek-lm3s811, where <IAR-EWARM> stands for the directory name where you've installed the IAR toolset. In the ev-lm3s81eww workspace, you select the "driverlib - Debug" project from the drop-down list at the top of the Workspace panel, and then press F7 to build the library.

Prev: 1. Installing QP/C++ and Building QP Libraries and Applications
Next: 3. The main() Function

Copyright © 2002-2011 Quantum Leaps, LLC. All Rights Reserved.
http://www.state-machine.com

Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: 3. The main() Function

  • QP/C++ Reference Manual
  • QP/C++ Tutorial

3. The main() Function

This QP/C++ 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.cpp. 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. The complete main.cpp file is shown in Listing 3-1.

Note:
To explain code listings, I place numbers in parentheses at the interesting lines in the left margin of the listing. I then use these labels in the left margin of the explanation section that immediately follows the listing. Occasionally, to unambiguously refer to a line of a particular listing from sections of text other than the explanation section, I use the full reference consisting of the listing number followed by the label. For example, Listing 3-1(18) refers to the label (18) in Listing 3-1

Listing 3-1 The file main.cpp of the "Fly 'n' Shoot" game application.

 (1) #include "qp_port.h"
 (2) #include "bsp.h"
 (3) #include "game.h"

     // Local-scope objects -------------------------------------------------------
 (4) static QEvent const * l_missileQueueSto[2];
 (5) static QEvent const * l_shipQueueSto[3];
 (6) static QEvent const * l_tunnelQueueSto[GAME_MINES_MAX + 5];
 (7) static ObjectPosEvt   l_smlPoolSto[GAME_MINES_MAX + 5];    // small event pool
 (8) static ObjectImageEvt l_medPoolSto[GAME_MINES_MAX + 5];   // medium event pool
 (9) static QSubscrList    l_subscrSto[MAX_PUB_SIG];

     //............................................................................
     void main(int argc, char *argv[]) {

(10)     BSP_init(argc, argv);              // initialize the Board Support Package

(11)     QF::init();       // initialize the framework and the underlying RT kernel

                                                   // initialize the event pools...
(12)     QF::poolInit(l_smlPoolSto, sizeof(l_smlPoolSto), sizeof(l_smlPoolSto[0]));
(13)     QF::poolInit(l_medPoolSto, sizeof(l_medPoolSto), sizeof(l_medPoolSto[0]));

(14)     QF::psInit(l_subscrSto, Q_DIM(l_subscrSto));     // init publish-subscribe

                                                     // start the active objects...
(15)     AO_Missile->start(1,                                           // priority
                           l_missileQueueSto, Q_DIM(l_missileQueueSto),// evt queue
                           (void *)0, 0,                     // no per-thread stack
                           (QEvent *)0);                 // no initialization event
(16)     AO_Ship   ->start(2,                                           // priority
                           l_shipQueueSto, Q_DIM(l_shipQueueSto),      // evt queue
                           (void *)0, 0,                     // no per-thread stack
                           (QEvent *)0);                 // no initialization event
(17)     AO_Tunnel ->start(3,                                           // priority
                           l_tunnelQueueSto, Q_DIM(l_tunnelQueueSto),  // evt queue
                           (void *)0, 0,                     // no per-thread stack
                           (QEvent *)0);                 // no initialization event

(18)     QF::run();                                       // run the QF application
     }
  • (1) The "Fly 'n' Shoot" game is an example of an application implemented with the QP event-driven platform. Every application C-file that uses QP must include the qp_port.h header file. This header file contains the specific adaptation of QP to the given processor, operating system, and compiler, which is called a port. Each QP port is located in a separate directory and the C compiler finds the right qp_port.h header file through the include search path provided to the compiler (typically via the -I compiler option). That way I don't need to change the application source code to recompile it for a different processor or compiler. I only need to instruct the compiler to look in a different QP port directory for the qp_port.h header file. For example, the DOS version includes the qp_port.h header file from the directory <qpcpp>\ports\80x86\dos\watcom\l\, and the ARM-Cortex version from the directory <qpcpp>\ports\arm-cortex\vanilla\iar\.
  • (2) The bsp.h header file contains the interface to the Board Support Package and is located in the application directory.
  • (3) The game.h header file contains the declarations of events and other facilities shared among the components of the application. I will discuss this header file in the upcoming Section 6. Defining Event Signals and Event Parameters. This header file is located in the application directory.

The QP event-driven platform is a collection of components, such as the QEP event processor that executes state machines according to the UML semantics and the QF real-time framework that implements the active object computing model. Active objects in QF are encapsulated state machines (each with an event queue, a separate task context, and a unique priority) that communicate with one another asynchronously by sending and receiving events, while QF handles all the details of thread-safe event exchange and queuing. Within an active object, the events are processed by the QEP event processor sequentially in a run-to-completion (RTC) fashion, meaning that processing of one event must necessarily complete before processing the next event.

  • (4-6) The application must provide storage for the event queues of all active objects used in the application. Here the storage is provided at compile time through the statically allocated arrays of immutable (const) pointers to events, because QF event queues hold just pointers to events, not events themselves. Events are represented as instances of the QEvent structure declared in the qp_port.h header file. Each event queue of an active object can have a different size and you need to decide this size based on your knowledge of the application. I discuss the event queues in Chapters 6 and 7 of Practical UML Statecharts in C/C++, Second Edition.
  • (7-8) The application must also provide storage for event pools that the framework uses for fast and deterministic dynamic allocation of events. Each event pool manages can provide only fixed-size memory blocks. To avoid wasting memory by using oversized blocks for small events, the QF framework can manage up to three event pools of different block sizes (for small, medium, and large events). The "Fly 'n' Shoot" application uses only two out of the three possible event pools (the small and medium pools).

The QF real-time framework supports two event delivery mechanisms: the simple direct event posting to active objects, and the more advanced mechanism called publish-subscribe that decouples event producers from the consumers. In the publish-subscribe mechanism, active objects subscribe to events by the framework. Event producers publish the events to the framework. Upon each publication request, the framework delivers the event to all active objects that had subscribed to that event type. One obvious implication of publish-subscribe is that the framework must store the subscriber information, whereas it must be possible to handle multiple subscribers to any give event type. The event delivery mechanisms are described in Chapters 6 and 7 of Practical UML Statecharts in C/C++, Second Edition.

  • (9) The "Fly 'n' Shoot" application uses the publish-subscribe event delivery mechanism supported by QF, so it needs to provide the storage for the subscriber lists. The subscriber lists remembers which active objects have subscribed to which events. The size of the subscriber database depends on both the number of published events, which is specified in the MAX_PUB_SIG constant found in the game.h header file, and the maximum number of active objects allowed in the system, which is determined by the QF configuration parameter QF_MAX_ACTIVE.
  • (10) The function BSP_init() initializes the board and is defined in the bsp.cpp file.
  • (11) The function QF::init() initializes the QF component and the underlying RTOS/kernel, if such software is used. You need to call QF::init() before you invoke any of QF services.
  • (12-13) The function QF::poolInit() initializes the event pools. The parameters of this function are the pointer to the event pool storage, the size of this storage, and the block-size of this pool. You can call this function up to three times to initialize up to three event pools. The subsequent calls to QF::poolInit() must be made in the increasing order of block sizes. For instance, the small block-size pool must be initialized before the medium block-size pool.
  • (14) The function QF::poolInit() initializes the publish-subscribe event delivery mechanism of QF. The parameters of this function are the pointer to the subscriber-list array and the dimension of this array.

The utility macro Q_DIM(a) provides the dimension of a one-dimensional array a[] computed as sizeof(a)/sizeof(a[0]), which is a compile-time constant. The use of this macro simplifies the code because it allows me to eliminate many #define constants that otherwise I would need to provide for the dimensions of various arrays. I can simply hard-code the dimension right in the definition of an array, which is the only place that I specify it. I then use the macro Q_DIM() whenever I need this dimension in the code.

  • (15-17) The function QActive::start() tells the QF framework to start managing an active object as part of the application. The function takes the following parameters: the pointer to the active object structure, the priority of the active object, the pointer to its event queue, the dimension (length) of that queue, and three other parameters that I explain in Chapter 7 of Practical UML Statecharts in C/C++, Second Edition, since they are not relevant at this point. The active object priorities in QF are numbered from 1 to QF_MAX_ACTIVE, inclusive, where a higher priority number denotes higher urgency of the active object. The constant QF_MAX_ACTIVE is defined in the QF port header file qf_port.h and currently cannot exceed 63.

I like to keep the code and data of every active object strictly encapsulated within its own C-file. For example, all code and data for the active object Ship are encapsulated in the file ship.cpp, with the external interface consisting of the pointer AO_Ship.

  • (18) At this point, you have provided to the framework all the storage and information it needs to manage your application. The last thing you must do is to call the function QF::run() to pass the control to the framework.

After the call to QF::run() the framework is in full control. The framework executes the application by calling your code, not the other way around. The function QF::run() never returns the control back to main(). In the DOS version of the "Fly 'n' Shoot" game, you can terminate the application by pressing the ESC key, in which case QF::run() exits to DOS, but not to main(). In an embedded system, such as the ARM-Cortex board, QF::run() runs forever or till the power is removed, whichever comes first.

Note:
For best cross-platform portability, the source code uses consistently the UNIX end-of-line convention (lines are terminated with LF only, 0xA character). This convention seems to be working for all C/C++ compilers and cross-compilers, including legacy DOS-era tools. In contrast, the DOS/Windows end-of-line convention (lines terminated with the CR,LF, or 0xD,0xA pair of characters), is known to cause problems on UNIX-like platforms, especially in the multi-line preprocessor macros.

Prev: 2. Let's Play
Next: 4. Designing an Event-Driven Application

Copyright © 2002-2011 Quantum Leaps, LLC. All Rights Reserved.
http://www.state-machine.com

Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: 4. Designing an Event-Driven Application

  • QP/C++ Reference Manual
  • QP/C++ Tutorial

4. Designing an Event-Driven Application

This QP/C++ 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: 3. The main() Function
Next: 5. Elaborating State Machines of Active Objects

To proceed further with the explanation of the "Fly 'n' Shoot" application, I need to step up to the design level. At this point I need to explain how the application has been decomposed into the active objects, and how these objects exchange events to collectively deliver the functionality of the "Fly 'n' Shoot" game.

In general, the decomposition of a problem into active objects is not trivial. As usual in any decomposition, your goal is to achieve possibly loose coupling among the active object components (ideally no sharing of any resources), and you also strive for minimizing the communication in terms of the frequency and size of exchanged events.

In the case of the "Fly 'n' Shoot" game, I need first to identify all objects with reactive behavior (i.e. with a state machine). I applied the simplest object-oriented technique of identifying objects, which is to pick the frequently used nouns in the problem specification. From Section 2. Let's Play, I identified Ship, Missile, Mines, and Tunnel. However, not every state machine in the system needs to be an active object (with a separate task context, an event queue, and a unique priority level), and merging them is a valid option when performance or space is needed. As an example of this idea, I ended up merging the Mines into the Tunnel active object, whereas I preserved the Mines as independent state machine components of the Tunnel active object. By doing so I applied the "Orthogonal Component" design pattern described in Chapter 5 of Practical UML Statecharts in C/C++, Second Edition.

The next step in the event-driven application design is assigning responsibilities and resources to the identified active objects. The general design strategy for avoiding sharing of resources is to encapsulate each resource inside a dedicated active object and to let that object manage the resource for the rest of the application. That way, instead of sharing the resource directly, the rest of the application shares the dedicated active object via events.

So, for example, I decided to put the Tunnel active object in charge of the display. Other active objects and state machine components, such as Ship, Missile and Mines, don't draw on the display directly, but rather send events to the Tunnel object with the request to render the Ship, Missile, or Mine bitmaps at the provided (x, y) coordinates of the display.

With some understanding of the responsibilities and resource allocations to active object I can move on to devising the various scenarios of event exchanges among the objects. Perhaps the best instrument to aid the thinking process at this stage is the UML sequence diagram, such as the diagram depicted in Figure 4-1. This particular sequence diagram shows the most common event exchange scenarios in the "Fly 'n' Shoot" game (the primary use cases, if you will). The explanation section immediately following the diagram illuminates the interesting points.

Note:
A UML sequence diagram like Figure 4-1 has two dimensions. Horizontally arranged boxes represent the various objects participating in the scenario whereas heavy boarders indicate active objects. As usual in the UML, the object name in underlined. Time flows down the page along the vertical dashed lines descending from the objects. Events are represented as horizontal arrows originating from the sending object and terminating at the receiving object. Optionally, thin rectangles around instance lines indicate focus of control.

Figure 4-1 The sequence diagram of the Fly 'n' Shoot game.

  • (1) The TIME_TICK is the most important event in the game. This event is generated by the QF framework from the system time tick interrupt at a rate of 30 times per second, which is needed to drive a smooth animation of the display. Because the TIME_TICK event is of interest to virtually all objects in the application, it is published by the framework to all active objects. (The publish-subscribe event delivery in QF is described in Chapter 6 of Practical UML Statecharts in C/C++, Second Edition.)
  • (2) Upon reception of the TIME_TICK event, the Ship object advances its position by one step and posts the event SHIP_IMG(x, y, bmp) to the Tunnel object. The SHIP_IMG event has parameters x and y, which are the coordinates of the Ship on the display, as well as the bitmap number bmp to draw at these coordinates.
  • (3) The Missile object is not in flight yet, so it simply ignores the TIME_TICK event this time.
  • (4) The Tunnel object performs the heaviest lifting for the TIME_TICK event. First, Tunnel redraws the entire display from the current frame buffer. This action performed 30 times per second provides the illusion of animation of the display. Next, the Tunnel clears the frame buffer and starts filling it up again for the next time frame. The Tunnel advances the tunnel walls by one step and copies the walls to the frame buffer. The Tunnel also dispatches the TIME_TICK event to all its Mine state machine components.
  • (5) Each Mine advances its position by one step and posts the MINE_IMG(x, y, bmp) event to the Tunnel to render the appropriate Mine bitmap at the position (x, y) in the current frame buffer. Mines of type 1 send the bitmap number MINE1_BMP, while mines of type 2 send MINE2_BMP.
  • (6) Upon reception of the SHIP_IMG(x, y, bmp) event from the Ship, the Tunnel object renders the specified bitmap in the frame buffer and checks for any collision between the ship bitmap and the tunnel walls. Tunnel also dispatches the original SHIP_IMG(x, y, bmp) event to all active Mines.
  • (7) Each Mine determines if the Ship is in collision with that Mine.
  • (8) The PLAYER_TRIGGER event is generated when the Player reliably presses the button (button press is debounced). This event is published by the QF framework and is delivered to the Ship and Tunnel objects, which both subscribe to the PLAYER_TRIGGER event.
  • (9) Ship generates the MISSILE_FIRE(x, y) event to the Missile object. The parameters of this event are the current (x, y) coordinates of the Ship, which are the starting point for the Missile.
  • (10) Tunnel receives the published PLAYER_TRIGGER event as well because Tunnel occasionally needs to start the game or terminate the screen saver mode based upon this stimulus.
  • (11) Missile reacts to the MISSILE_FIRE(x, y) event by starting to fly, whereas it sets its initial position from the (x, y) event parameters delivered from the Ship.
  • (12) This time around, the TIME_TICK event arrives while Missile is in flight. Missile posts the MISSILE_IMG(x, y, bmp) event to the Table.
  • (13) Table renders the Missile bitmap in the current frame buffer and dispatches the MISSILE_IMG(x, y, bmp) event to all the Mines to let the Mines test for the collision with the Missile. This determination depends on the type of the Mine. In this scenario a particular Mine[n] object detects a hit and posts the HIT_MINE(score) event to the Missile. The Mine provides the score earned for destroying this particular mine as the parameter of this event.
  • (14) Missile handles the HIT_MINE(score) event by becoming immediately ready to launch again and lets the Mine do the exploding. As I decided to make the Ship responsible for the scorekeeping, the Missile also generates the DESTROYED_MINE(score) event to the Ship, to report the score for destroying the Mine.
  • (15) Upon reception of the DESTROYED_MINE(score) event, the Ship updates the score reported by the Missile.
  • (16) The Ship object handles the PLAYER_SHIP_MOVE(x, y) event by updating its position from the event parameters.
  • (17) When the Tunnel object handles the SHIP_IMG(x, y, bmp_id) event next time around, it detects a collision between the Ship and the tunnel wall. In that case it posts the event HIT_WALL to the Ship.
  • (18) The Ship responds to the HIT_WALL event by transitioning to the "exploding" state.

Even though the sequence diagram in Figure 4-1 shows merely some selected scenarios of the "Fly 'n' Shoot" game, I hope that the explanations give you a big picture of how the application works. More importantly, you should start getting the general idea about the thinking process that goes into designing an event-driven system with active objects and events.

Prev: 3. The main() Function
Next: 5. Elaborating State Machines of Active Objects

Copyright © 2002-2011 Quantum Leaps, LLC. All Rights Reserved.
http://www.state-machine.com

Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: 5. Elaborating State Machines of Active Objects

  • QP/C++ Reference Manual
  • QP/C++ Tutorial

5. Elaborating State Machines of Active Objects

This QP/C++ 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: 4. Designing an Event-Driven Application
Next: 6. Defining Event Signals and Event Parameters

I hope that the analysis of the sequence diagram in Figure 4-1 makes it clear that actions performed by an active object depend as much on the events it receives, as on the internal mode of the object. For example, the Missile active object handles the TIME_TICK event very differently when the Missile is in flight (Figure 4-1(12)) compared to the time when it is not (Figure 4-1(3)). The best known mechanism of handling such modal behavior is through state machines because a state machine makes the behavior explicitly dependent on both the event and the state of an object. In Chapter 2 of Practical UML Statecharts in C/C++, Second Edition I introduce UML state machine concepts more thoroughly. In this section, I give a cursory explanation of the state machines associated with each object in the "Fly 'n' Shoot" game.

5.1 The Missile Active Object

I start with the Missile state machine shown in Figure 5-1, because it turns out to be the simplest one. The explanation section immediately following the diagram illuminates the interesting points.

Note:
A UML state diagram like Figure 5-1 preserves the general form of the traditional state transition diagrams, where states are represented as nodes and transitions as arcs connecting the nodes. In the UML notation the state nodes are represented as rectangles with rounded corners. The name of the state appears in bold type in the name compartment at the top of the state. Optionally, right below the name, a state can have an internal transition compartment separated from the name by a horizontal line. The internal transition compartment can contain entry actions (actions following the reserved symbol "entry"), exit actions (actions following the reserved symbol "exit"), and other internal transitions (e.g., those triggered by TIME_TICK in Figure 5-1(3)). State transitions are represented as arrows originating at the boundary of the source state and pointing to the boundary of the target state. At a minimum, a transition must be labeled with the triggering event. Optionally, the trigger can be followed by event parameters, a guard, and a list of actions.

Figure 5-1 Missile state machine diagram.

  • (1) The state transition originating at the black ball is called the initial transition. Such transition designates the first active state after the state machine object is created. An initial transition can have associated actions, which in the UML notation are enlisted after the forward slash "/". In this particular case, the Missile state machine starts in the "armed" state and the actions executed upon the initialization consist of subscribing to the event TIME_TICK. Subscribing to an event means that the framework will deliver the specified event to the Missile active object every time the event is published to the framework. Chapter 7 of Practical UML Statecharts in C/C++, Second Edition describes the implementation of the publish-subscribe event delivery in QF.
  • (2) The arrow labeled with the MISSILE_FIRE(x, y) event denotes a state transition, that is, change of state from "armed" to "flying". The MISSILE_FIRE(x, y) event is generated by the Ship object when the Player triggers the Missile (see the sequence diagram in Figure 4-1). In the MISSILE_FIRE event, Ship provides Missile with the initial coordinates in the event parameters (x, y).
Note:
The UML intentionally does not specify the notation for actions. In practice, the actions are often written in the programming language used for coding the particular state machine. In all state diagrams in this book, I assume the C programming language. Furthermore, in the C expressions I refer to the data members associated with the state machine object through the me-> prefix and to the event parameters through the e-> prefix. For example, the action me->x = e->x; means that the internal data member x of the Missile active object is assigned the value of the event parameter x.
  • (3) The event name TIME_TICK enlisted in the compartment below the state name denotes an internal transition. Internal transitions are simple reactions to events performed without a change of state. An internal transition, as well as a regular transition, can have a guard condition, enclosed in square brackets. Guard condition is a Boolean expression evaluated at runtime. If the guard evaluates to TRUE, the transition is taken. Otherwise, the transition is not taken and no actions enlisted after the forward slash "/" are executed. In this particular case, the guard condition checks whether the x-coordinate propagated by the Missile speed is still visible on the screen. If so, the actions are executed. These actions include propagation of the Missile position by one step and posting the MISSILE_IMG event with the current Missile position and the MISSILE_BMP bitmap number to the Tunnel active object. Direct event posting to an active object is accomplished by the QF function QActive::postFIFO(), which I discuss in Chapter 7 of Practical UML Statecharts in C/C++, Second Edition.
  • (4) The same event TIME_TICK with the [else] guard denotes a regular state transition with the guard condition complementary to the other occurrence of the TIME_TICK event in the same state. In this case, the TIME_TICK transition to "armed" is taken if the Missile object flies out of the screen.
  • (5) The event HIT_MINE(score) triggers another transition to the "armed" state. The action associated with this transition posts the DESTROYED_MINE event with the parameter e->score to the Ship object, to report destroying the mine.
  • (6) The event HIT_WALL triggers a transition to the "exploding" state, with the purpose of animating the explosion bitmaps on the display.
  • (7) The label "entry" denotes the entry action to be executed unconditionally upon the entry to the "exploding" state. This action consists of clearing explosion counter (me->exp_ctr) member of the Missile object.
  • (8) The TIME_TICK internal transition is guarded by the condition that the explosion does not scroll off the screen, and that the explosion counter is lower than 16. The actions executed include propagation of the explosion position and posting the EXPLOSION_IMG event to the Tunnel active object. Please note that the bitmap of the explosion changes as the explosion counter gets bigger.
  • (9) The TIME_TICK regular transition with the complementary guard changes the state back to the "armed" state. This transition is taken after the animation of the explosion completes.

5.2 The Ship Active Object

The state machine of the Ship active object is shown in Figure 5-2. This state machine introduces the profound concept of hierarchical state nesting. The power of state nesting derives from the fact that it is designed to eliminate repetitions that otherwise would have to occur.

One of the main responsibilities of the Ship active object is to maintain the current position of the Ship. On the original LM3S811 board, this position is determined by the potentiometer wheel (see Figure 2-2). The PLAYER_SHIP_MOVE(x, y) event is generated whenever the wheel position changes, as shown in the sequence diagram (Figure 4-1). The Ship object must always keep track of the wheel position, which means that all states of the Ship state machine must handle the PLAYER_SHIP_MOVE(x, y) event.

In the traditional finite state machine (FSM) formalism, you would need to repeat the Ship position update from the PLAYER_SHIP_MOVE(x, y) event in every state. But such repetitions would bloat the state machine and, more importantly, would represent multiple points of maintenance both in the diagram and the code. Such repetitions go against the DRY principle (Don't Repeat Yourself), which is vital for flexible and maintainable code.

Hierarchical state nesting remedies the problem. Consider the state "active" that surrounds all other states in Figure 5-2. The high-level "active" state is called the superstate and is abstract in that the state machine cannot be in this state directly, but only in one of the states nested within, which are called the substates of "active". The UML semantics associated with state nesting prescribes that any event is first handled in the context of the currently active substate. If the substate cannot handle the event, the state machine attempts to handle the event in the context of the next-level superstate. Of course, state nesting in UML is not limited to just one level and the simple rule of processing events applies recursively to any level of nesting.

Specifically to the Ship state machine diagram shown in Figure 5-2, suppose that the event PLAYER_SHIP_MOVE(x, y) arrives when the state machine is in the "parked" state. The "parked" state does not handle the PLAYER_SHIP_MOVE(x, y) event. In the traditional finite state machine this would be the end of story—the PLAYER_SHIP_MOVE(x, y) event would be silently discarded. However, the state machine in Figure 5-2 has another layer of the "active" superstate. Per the semantics of state nesting, this higher-level superstate handles the PLAYER_SHIP_MOVE(x, y) event, which is exactly what's needed. The same exact argumentation applies for any other substate of the "active" superstate, such as "flying" or "exploding", because none of these substates handle the PLAYER_SHIP_MOVE(x, y) event. Instead, the "active" superstate handles the event in one single place, without repetitions.

Figure 5-2 Ship state machine diagram.

  • (1) Upon the initial transition, the Ship state machine enters the "active" superstate and subscribes to events TIME_TICK and PLAYER_TRIGGER.
  • (2) At each level of nesting a superstate can have a private initial transition that designates the active substate after the superstate is entered directly. Here the initial transition of state "active" designates the substate "parked" as the initial active substate.
  • (3) The "active" superstate handles the PLAYER_SHIP_MOVE(x, y) event as an internal transition in which it updates the internal data members me->x and me->y from the event parameters e->x and e->y, respectively.
  • (4) The TAKE_OFF event triggers transition to "flying". This event is generated by the Tunnel object when the Player starts the game (see the description of the game in Section 2. Let's Play).
  • (5) The entry actions to "flying" include clearing the me->score data member and posting the event SCORE with the event parameter me->score to the Tunnel active object.
  • (6) The TIME_TICK internal transition causes posting the event SHIP_IMG with current Ship position and the SHIP_BMP bitmap number to the Tunnel active object. Additionally, the score is incremented for surviving another time tick. Finally, when the score is "round" (divisible by 10) it is also posted to the Tunnel active object. This decimation of the SCORE event is performed just to reduce the bandwidth of the communication, because the Tunnel active object only needs to give an approximation of the running score tally to the user.
  • (7) The PLAYER_TRIIGGER internal transition causes posting the event MISSILE_FIRE with current Ship position to the Missile active object. The parameters (me->x, me->y) provide the Missile with the initial position from the Ship.
  • (8) The DESTROYED_MINE(score) internal transition causes update of the score kept by the Ship. The score is not posted to the Table at this point, because the next TIME_TICK will send the "rounded" score, which is good enough for giving the Player the score approximation.
  • (9) The HIT_WALL event triggers transition to "exploding"
  • (10) The HIT_MINE(type) event also triggers transition to "exploding"
  • (11) The "exploding" state of the Ship state machine is very similar to the "exploding" state of Missile (see Figure 5-1(7-9)).

(12) The TIME_TICK[else] transition is taken when the Ship finishes exploding. Upon this transition, the Ship object posts the event GAME_OVER(me->score) to the Tunnel active object to terminate the game and display the final score to the Player.

5.3 The Tunnel Active Object

The Tunnel active object has the most complex state machine, which is shown in Figure 5-3. Unlike the previous state diagrams, the diagram in Figure 5-3 shows only the high-level of abstraction and omits a lot of details such as most entry/exit actions, internal transitions, guard conditions, or actions on transitions. Such a "zoomed out" view is always legal in the UML, because UML allows you to choose the level of detail that you want to include in your diagram.

The Tunnel state machine uses state hierarchy more extensively than the Ship state machine in Figure 5-2. The explanation section immediately following Figure 5-3 illuminates the new uses of state nesting as well as the new elements not explained yet in the other state diagrams.

Figure 5-3 Tunnel state machine diagram.

  • (1) An initial transition can target a substate at any level of state hierarchy, not necessarily just the next-lower level. Here the top-most initial transition goes down two levels to the substate "demo".
  • (2) The superstate "active" handles the PLAYER_QUIT event as a transition to the final state (see explanation of element (3)). Please note that the PLAYER_QUIT transition applies to all substates directly or transitively nested in the "active" superstate. Because a state transition always involves execution of all exit actions from the states, the high-level PLAYER_QUIT transition guarantees the proper cleanup that is specific to the current state context, whichever substate happens to be active at the time when the PLAYER_QUIT event arrives.
  • (3) The final state is indicated in the UML notation as the bull's-eye symbol and typically indicates destruction of the state machine object. In this case, the PLAYER_QUIT event indicates termination of the game.
  • (4) The MINE_DISABLED(mine_id) event is handled at the high level of the "active" state, which means that this internal transition applies to the whole sub-machine nested inside the "active" superstate. (See also the discussion of Mine object in the next section.)
  • (5) The entry action to the "demo" state starts the screen time event (timer) me->screenTimeEvt to expire in 20 seconds. Time events are allocated by the application, but they are managed by the QF framework. QF provides functions to arm a time event, such as QTimeEvt_postIn() for one-shot timeout, and QTimeEvt_postEvery() for periodic time events. Arming a time event is in effect telling the QF framework, for instance, "Give me a nudge in 20 seconds". QF then posts the time event (the event me->screenTimeEvt in this case) to the active object after the requested number of clock ticks. Chapters 6 and 7 of Practical UML Statecharts in C/C++, Second Edition talk about time events in detail.
  • (6) The exit action from the "demo" state disarms the me->screenTimeEvt time event. This cleanup is necessary when the state can be exited by a different event than the time event, such as the PLAYER_TRIGGER transition.
  • (7) The SCREEN_TIMEOUT transition to "screen_saver" is triggered by the expiration of the me->screenTimeEvt time event. The signal SCREEN_TIMEOUT is assigned to this time event upon initialization and cannot be changed later.
  • (8) The transition triggered by PLAYER_TRIGGER applies equally to the two substates of the "screen_saver" superstate.

5.4 The Mine Components

Mines are also modeled as hierarchical state machines, but are not active objects. Instead, Mines are components of the Tunnel active object and share its event queue and priority level. The Tunnel active object communicates with the Mine components synchronously by directly dispatching events to them via the function QHsm_dispatch(). Mines communicate with Tunnel and all other active objects asynchronously by posting events to their event queues via the function QActive::postFIFO().

Note:
Active objects exchange events asynchronously, meaning that the sender of the event merely posts the event to the event queue of the recipient active object without waiting for the completion of the event processing. In contrast, synchronous event processing corresponds to a function call (e.g., QHsm_dispatch()), which processes the event in the caller's thread of execution.

Figure 5-4 The Table active object manages two types of Mines.

As shown in Figure 5-4, Tunnel maintains the data member mines[], which is an array of pointers to hierarchical state machines (QHsm *). Each of these pointers can point either to a Mine1 object, a Mine2 object, or NULL, if the entry is unused. Please note that Tunnel "knows" the Mines only as generic state machines (pointers to the QHsm structure defined in QP). Tunnel dispatches events to Mines uniformly, without differentiating between different types of Mines. Still, each Mine state machine handles the events it its specific way. For example, Mine type 2 checks for collision with the Missile differently than with the Ship while Mine type 1 handles both identically.

Note:
The last point is actually very interesting. Dispatching the same event to different Mine objects results in different behavior, specific to the type of the Mine, which in OOP is known as polymorphism. I'll have more to say about this in Chapter 3 of Practical UML Statecharts in C/C++, Second Edition.

Each Mine object is fairly autonomous. The Mine maintains its own position and is responsible for informing the Tunnel object whenever the Mine gets destroyed or scrolls out of the display. This information is vital for the Tunnel object so that it can keep track of the unused Mines.

Figure 5-5 shows a hierarchical state machine of Mine2 state machine. Mine1 is very similar, except that it uses the same bitmap for testing collisions with the Missile and the Ship.

Figure 5-5 Mine2 state machine diagram.

  • (1) The Mine starts in the "unused" state.
  • (2) The Tunnel object plants a Mine by dispatching the MINE_PLANT(x, y) event to the Mine. The Tunnel provides the (x, y) coordinates as the original position of the Mine.
  • (3) When the Mine scrolls off the display the state machine transitions to "unused".
  • (4) When the Mine hits the Ship the state machine transitions to "unused".
  • (5) When the Mine scrolls finishes exploding the state machine transitions to "unused".
  • (6) When the Mine is recycled by the Tunnel object the state machine transitions to "unused".
  • (7) The exit action in the "unused" state posts the MINE_DISABLDED(mine_id) event to the Tunnel active object. Through this event, the Mine informs the Tunnel that it's becoming disabled, so that Tunnel can update its mines[] array (see also Figure 5-4(4)). The mine_id parameter of the event becomes the index into the mines[] array. Please note that generating the MINE_DISABLDED(mine_id) event in the exit action from "used" is much safer and more maintainable than repeating this action in each individual transition (3), (4), (5), and (6).

Prev: 4. Designing an Event-Driven Application
Next: 6. Defining Event Signals and Event Parameters

Copyright © 2002-2011 Quantum Leaps, LLC. All Rights Reserved.
http://www.state-machine.com

Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: 6. Defining Event Signals and Event Parameters

  • QP/C++ Reference Manual
  • QP/C++ Tutorial

6. Defining Event Signals and Event Parameters

This QP/C++ 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: 5. Elaborating State Machines of Active Objects
Next: 7. Coding Hierarchical State Machines

The key events in the "Fly 'n' Shoot" game have been identified in the sequence diagram in Figure 4-1. Other events have been invented during the state machine design stage. In any case, you must have noticed that events consist really of two parts. The part of the event called the signal conveys the type of the occurrence (what happened). For example, the TIME_TICK signal conveys the arrival of a time tick, while PLAYER_SHIP_MOVE signal conveys that the player wants to move the Ship. An event can also contain additional quantitative information about the occurrence in form of event parameters. For example, the PLAYER_SHIP_MOVE signal is accompanied by the parameters (x, y) that contain the quantitative information as to where exactly to move the Ship. In QP, events are represented as instances of the QEvent structure provided by the framework. Specifically, the QEvent structure contains the member sig, to represent the signal of that event. Event parameters are added in the process of inheritance, as described in the sidebar Encapsulation and Single Inheritance in C.

6.1 Enumerating Event Signals and Defining Event Parameters

Because events are explicitly shared among most of the application components, it is convenient to declare them in the separate header file game.h shown Listing 6-1. The explanation section immediately following the listing illuminates the interesting points.

Listing 6-1 Signals, event structures, and active object interfaces defined in file game.h.

 (1) enum GameSignals {                                 // signals used in the game
 (2)     TIME_TICK_SIG = Q_USER_SIG,                     // published from tick ISR
         PLAYER_TRIGGER_SIG,    // published by Player (ISR) to trigger the Missile
         PLAYER_QUIT_SIG,             // published by Player (ISR) to quit the game
         GAME_OVER_SIG,             // published by Ship when it finishes exploding

         // insert other published signals here ...
 (3)     MAX_PUB_SIG,                                  // the last published signal

         PLAYER_SHIP_MOVE_SIG,     // posted by Player (ISR) to the Ship to move it

         BLINK_TIMEOUT_SIG,              // signal for Tunnel's blink timeout event
         SCREEN_TIMEOUT_SIG,            // signal for Tunnel's screen timeout event

         TAKE_OFF_SIG,       // from Tunnel to Ship to grant permission to take off
         HIT_WALL_SIG,               // from Tunnel to Ship when Ship hits the wall
         HIT_MINE_SIG,        // from Mine to Ship or Missile when it hits the mine
         SHIP_IMG_SIG,        // from Ship to the Tunnel to draw and check for hits
         MISSILE_IMG_SIG,     // from Missile the Tunnel to draw and check for hits
         MINE_IMG_SIG,               // sent by Mine to the Tunnel to draw the mine
         MISSILE_FIRE_SIG,                   // sent by Ship to the Missile to fire
         DESTROYED_MINE_SIG,    // from Missile to Ship when Missile destroyed Mine
         EXPLOSION_SIG,        // from any exploding object to render the explosion
         MINE_PLANT_SIG,                     // from Tunnel to the Mine to plant it
         MINE_DISABLED_SIG,         // from Mine to Tunnel when it becomes disabled
         MINE_RECYCLE_SIG,            // sent by Tunnel to Mine to recycle the mine
         SCORE_SIG,      // from Ship to Tunnel to adjust game level based on score

 (4)     MAX_SIG                              // the last signal (keep always last)
     };

 (5) struct ObjectPosEvt
 (6)     : public QEvent                            // derive from the QEvent class
     {
 (7)     uint8_t x;                                 // the x-position of the object
 (8)     uint8_t y;                                 // new y-position of the object
     };

     struct ObjectImageEvt : public QEvent {        // derive from the QEvent class
         uint8_t x;                                 // the x-position of the object
         int8_t  y;                                 // the y-position of the object
         uint8_t bmp;                      // the bitmap ID representing the object
     };

     struct MineEvt : public QEvent {               // derive from the QEvent class
         uint8_t id;                                          // the ID of the Mine
         MineEvt(QSignal sig, uint8_t id) {
             this->sig      = sig;
             this->dynamic_ = 0;
             this->id       = id;
         }
     };

     struct ScoreEvt : public QEvent {              // derive from the QEvent class
         uint16_t score;                                       // the current score
         ScoreEvt(QSignal sig, uint16_t score) {
             this->sig      = sig;
             this->dynamic_ = 0;
             this->score    = score;
         }
     };

     // opaque pointers to active objects in the application
 (9) extern QActive * const AO_Tunnel;
(10) extern QActive * const AO_Ship;
(11) extern QActive * const AO_Missile;
  • (1) In QP, signals of events are simply enumerated constants. Placing all signals in a single enumeration is particularly convenient to avoid inadvertent overlap in the numerical values of different signals.
  • (2) The application-level signals do not start from zero but rather are offset by the constant Q_USER_SIG. This is because QP reserves the lowest few signals for the internal use and provides the constant Q_USER_SIG as an offset from which user-level signals can start. Please also note that by convention, I attach the suffix _SIG to all signals so that I can easily distinguish signals from other constants. I drop the suffix _SIG in the state diagrams to reduce the clutter.
  • (3) The constant MAX_PUB_SIG delimits the published signals from the rest. The publish-subscribe event delivery mechanism consumes some RAM, which is proportional to the number of published signals. I save some RAM by providing the lower limit of published signals to QP (MAX_PUB_SIG) rather than maximum of all signals used in the application. (See also Listing 3-1(9)).
  • (4) The last enumeration MAX_SIG indicates the maximum of all signals used in the application.
  • (5) The event structure ObjectPosEvt defines a "class" of events that convey the object's position on the display in the event parameters.
  • (6) The structure ObjectPosEvt derives from the base structure QEvent, as explained in the sidebar Encapsulation and Single Inheritance in C.
  • (7-8) The structure ObjectPosEvt adds parameters x and y, which are coordinates of the object on the display.
  • (9-11) These global pointers represent active objects in the application and are used for posting events directly to active objects. Because the pointers can be initialized at compile time, I like to declare them const, sot that they can be placed in ROM. The active object pointers are "opaque", because they cannot access the whole active object, but only the part inherited from the QActive structure. I'll have more to say about this in the next section.

6.2 Generating, Posting, and Publishing Events

The QF framework supports two types of asynchronous event exchange:

  1. The simple mechanism of direct event posting supported through the functions QActive::postFIFO() and QActive::postLIFO(), where the producer of an event directly posts the event to the event queue of the consumer active object.
  2. A more sophisticated publish-subscribe event delivery mechanism supported through the functions QF::publish() and QActive::subscribe(), where the producers of the events "publish" them to the framework, and the framework then delivers the events to all active objects that had "subscribed" to these events.

In QF, any part of the system can produce events, not necessarily only the active objects. For example, interrupt service routines (ISRs) or device drivers can also produce events. On the other hand, only active objects can consume events, because only active objects have event queues.

Note:
QF also provides "raw" thread-safe event queues (struct QEQueue), which can consume events as well. These "raw" thread-safe queues cannot block and are intended to deliver events to ISRs or device drivers. Please refer to Chapter 7 of Practical UML Statecharts in C/C++, Second Edition for more details.

The most important characteristic of event management in QF is that the framework passes around only pointers to events, not the events themselves. QF never copies the events by value ("zero-copy" policy); even in case of publishing events that often involves multicasting the same event to multiple subscribers. The actual event instances are either constant events statically allocated at compile time, or dynamic events allocated at runtime from one of the event pools that the framework manages. Listing 6-2 provides examples of publishing static events and posting dynamic events from the interrupt service routines (ISRs) of the "Fly 'n' Shoot" version for the ARM-Cortex board (file <qpcpp>\examples\arm-cortex\vanilla\iar\game-ev-lm3s811\bsp.cpp). In the upcoming Section 7. Coding Hierarchical State Machines you will see other examples of event posting from active objects in the state machine code.

Listing 6-2 Generating, posting , and publishing events from the ISRs in bsp.cpp for the ARM-Cortex board.

 (1) extern "C" void ISR_SysTick(void) {
 (2)     static QEvent const tickEvt = { TIME_TICK_SIG, 0 };
 (3)     QF::publish(&tickEvt);        // publish the tick event to all subscribers
 (4)     QF::tick();                               // process all armed time events
     }
     //............................................................................
 (5) extern "C" void ISR_ADC(void) {
         static uint32_t adcLPS = 0;               // Low-Pass-Filtered ADC reading
         static uint32_t wheel = 0;                      // the last wheel position

         static uint32_t btn_debounced  = 0;
         static uint8_t  debounce_state = 0;

         unsigned long tmp;

         ADCIntClear(ADC_BASE, 3);                       // clear the ADC interrupt
 (6)     ADCSequenceDataGet(ADC_BASE, 3, &tmp);       // read the data from the ADC

          // 1st order low-pass filter: time constant ~= 2^n samples
          // TF = (1/2^n)/(z-((2^n - 1)/2^n)),
          // eg, n=3, y(k+1) = y(k) - y(k)/8 + x(k)/8 => y += (x - y)/8
 (7)     adcLPS += (((int)tmp - (int)adcLPS + 4) >> 3);          // Low-Pass-Filter

            // compute the next position of the wheel
 (8)     tmp = (((1 << 10) - adcLPS)*(BSP_SCREEN_HEIGHT - 2)) >> 10;

         if (tmp != wheel) {                      // did the wheel position change?
 (9)         ObjectPosEvt *ope = Q_NEW(ObjectPosEvt, PLAYER_SHIP_MOVE_SIG);
(10)         ope->x = (uint8_t)GAME_SHIP_X;                  // x-position is fixed
(11)         ope->y = (uint8_t)tmp;
(12)         AO_Ship->postFIFO(ope);                            // post to the Ship
             wheel = tmp;                    // save the last position of the wheel
         }
         . . .
     }
  • (1) In the case of the ARM-Cortex board, the function ISR_SysTick() services the system clock tick ISR generated by the ARM-Cortex system tick timer.
  • (2) The TIME_TICK event never changes, so it can be statically allocated just once. This event is declared as const, which means that it can be placed in ROM. The initializer list for this event consists of the signal TIME_TICK_SIG followed by zero. This zero informs the QF framework that this event is static and should never be recycled to an event pool.
  • (3) The ISR calls the framework function QF::publish(), which takes the pointer to the tickEvt event to deliver to all subscribers.
  • (4) The ISR calls the function QF::tick(), in which it the framework manages the armed time events.
  • (5) The function ISR_ADC() services the ADC conversions, which ultimately deliver the position of the Ship.
  • (6) The ISR reads the data from the ADC.
  • (7-8) A low-pass filter is applied to the raw ADC reading and the potentiometer wheel position is computed.
  • (9) The QF macro Q_NEW(ObjectPosEvt, PLAYER_SHIP_MOVE_SIG) dynamically allocates an instance of the ObjectPosEvt event from an event pool managed by QF. The macro also performs the association between the signal PLAYER_SHIP_MOVE_SIG and the allocated event. The Q_NEW() macro returns the pointer to the allocated event.
Note:
The PLAYER_SHIP_MOVE(x, y) event is an example of an event with changing parameters. In general, such an event cannot be allocated statically (like the TIME_TICK event at label (2)) because it can change asynchronously next time the ISR executes. Some active objects in the system might still be referring to the event via a pointer, so the event should not be changing. Dynamic event allocation of QF solves all such concurrency issues, because every time a new event is allocated. QF then recycles the dynamic events, after it determines that all active objects are done with accessing the events.
  • (10-11) The x and y parameters of the event are assigned.
  • (12) The dynamic event is posted directly to the Ship active object.

Prev: 5. Elaborating State Machines of Active Objects
Next: 7. Coding Hierarchical State Machines

Copyright © 2002-2011 Quantum Leaps, LLC. All Rights Reserved.
http://www.state-machine.com

Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: 7. Coding Hierarchical State Machines

  • QP/C++ Reference Manual
  • QP/C++ Tutorial

7. Coding Hierarchical State Machines

This QP/C++ 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: 6. Defining Event Signals and Event Parameters
Next: 8. Using the Built-in Real-Time Kernels and Third-Party RTOSes

Contrary to widespread misconceptions, you don't need big design automation tools to translate hierarchical state machines (UML statecharts) into efficient and highly maintainable C or C++. This section explains how to hand-code the Ship state machine from Figure 5-2 with the help of the QF real-time framework and the QEP hierarchical processor, which is also part of the QP event-driven platform. Once you know how to code this state machine, you know how to code them all.

The source code for the Ship state machine is found in the file ship.cpp located either in the DOS version or the ARM-Cortex version of the "Fly 'n' Shoot" game. I break the explanation of this file into three steps.

7.1 Step 1: Defining the Ship Structure

In the first step you define the Ship data structure. Just like in case of events, you use inheritance to derive the Ship structure from the framework structure QActive (see the sidebar Encapsulation and Single Inheritance in C). Creating this inheritance relationship ties the Ship structure to the QF framework. The main responsibility of the QActive base structure is to store the information about the current active state of the state machine, as well as the event queue and priority level of the Ship active object. In fact, QActive itself derives from a simpler QEP structure QHsm that represents just the current active state of a hierarchical state machine. On top of that information, almost every state machine must also store other "extended-state" information. For example, the Ship object is responsible for maintaining the Ship position as well as the score accumulated in the game. You supply this additional information by means of data members enlisted after the base structure member super, as shown in Listing 7-1.

Listing 7-1 Deriving the Ship structure in file ship.cpp.

 (1) #include "qp_port.h"
 (2) #include "bsp.h"
 (3) #include "game.h"

 (4) class Ship
 (5)     : public QActive                               // extend the QActive class
     {
 (6)     uint8_t m_x;
 (7)     uint8_t m_y;
 (8)     uint8_t m_exp_ctr;
 (9)     uint16_t m_score;

     public:
(10)     Ship(void) : QActive((QState)&Ship::initial),
                      m_x(GAME_SHIP_X), m_y(GAME_SHIP_Y) {}
     private:
(11)     static QState active   (Ship *me, QEvent const *e);
(12)     static QState parked   (Ship *me, QEvent const *e);
(13)     static QState flying   (Ship *me, QEvent const *e);
(14)     static QState exploding(Ship *me, QEvent const *e);

(15)     static QState initial  (Ship *me, QEvent const *e);
     };

(16) static Ship l_ship;             // the sole instance of the Ship active object

     // global objects ------------------------------------------------------------
(17) QActive * const AO_Ship = &l_ship;                // opaque pointer to Ship AO
  • (1) Every application-level C-file that uses the QP platform must include the qp_port.h header file.
  • (2) The bsp.h header file contains the interface to the Board Support Package.
  • (3) The game.h header file contains the declarations of events and other facilities shared among the components of the application (see Listing 6-1).
  • (4) This class defines the Ship active object.
Note:
I like to keep active objects, and indeed all state machine objects (such as Mines), strictly encapsulated. Therefore, I don't put the state machine class definitions in header files but rather define them right in the implementation file, such as ship.cpp. That way, I can be sure that the internal data members of the Ship structure are not known to any other parts of the application.
  • (5) The Ship active object class derives from the framework base class QActive.
  • (6-7) The m_x and m_y data members represent the position of the Ship on the display.
  • (8) The m_exp_ctr member is used for pacing the explosion animation (see also the "exploding" state in the Ship state diagram in Figure 5-2).
  • (9) The m_score member stores the accumulated score in the game.
  • (10) Every derived active object class is responsible for initializing the part inherited from the base class. The constructor QActive::QActive() puts the state machine in the initial pseudostate &Ship::initial.
  • (11-14) These four functions are called state-handler functions because they correspond one-to-one to the states of the Ship state machine shown in Figure 5-2. For example, the active() function represents the "active" state. The QEP event processor calls the state handler functions to realize the UML semantics of state machine execution. A state handler function takes the state machine pointer and the event pointer as arguments, and returns the status of the operation back to the QEP event processor, for example whether the event was handled or not. The return type QState is typedef-ed to uint8_t in the header file <qpcpp>\include\qep.h.
Note:
The state-handler functions are necessarily static members of the class, so that they don't use the "this-calling convention". Please see the Sidebar: Pointers to Member Functions in C++.
  • (15) In addition to state handler functions, every state machine must declare the initial pseudostate, which QEP invokes to execute the top-most initial transition (see Figure 5-2(1)). The initial pseudostate handler has signature almost identical to the regular state handler function, except it returns void.
  • (16) In this line I statically allocate the storage for the Ship active object. Please note that the object l_ship is defined static, so that it is accessible only locally at the file scope of the ship.cpp file.
  • (17) In this line I define and initialize the global pointer AO_Ship to the Ship active object (see also Listing 6-1(10)). This pointer is "opaque", because it treats the Ship object as the generic QActive base structure, rather than the specific Ship structure. The power of an "opaque" pointer is that it allows me to completely hide the definition of the Ship structure and make it inaccessible to the rest of the application. Still, the other application components can access the Ship object to post events directly to it via the AO_Ship->postFIFO(evt) member function call.

Sidebar: Pointers to Member Functions in C++

The C++ state handler function takes the "me" pointer of its own class type, through which it accesses the state machine data members and member functions (e.g., me->operand1 = ...). This is because the state-handler functions are static members of the QHsm subclass, such as the Ship state machine class Calc (see Listing 7-1).

An obvious and more elegant alternative would be to make the state-handler functions regular, non-static class members, which would allow them to access the class members much more naturally through the implicit "this" pointer.

Indeed this much more elegant alternative has been used in the earlier QEP/C++ version published in the first edition of the "Practical Statecharts in C/C++" book. However, this alternative requires using pointers-to-member-functions instead of simple pointers-to-functions, which turned out to be a problem in practice.

Even though the earlier C++ version of QEP used pointers-to-member-functions in a rather standard way, the embedded developers have filed a number of alarming reports from the trenches where the elegant approach either had very lousy performance, or did not work at all. For example, some embedded C++ compilers used over 30 machine instructions to de-reference a pointer-to-member-function and only 3 to de-reference a regular pointer-to-function. Needless to say, 3 machine instructions should do the job.

As it turns out, too many C++ compilers simply don't support pointers-to-member-functions well due to interference of other language features such as multiple inheritance and virtual base classes. As eloquently explained in the online article "Member Function Pointers and the Fastest Possible C++ Delegates" (see "Member Function Pointers and the Fastest Possible C++ Delegates" at http://www.codeproject.com/cpp/FastDelegate.asp), even such widespread and important frameworks as the MFC actually use pointers-to-member-functions in a non-standard way by subverting the normal C++ type checking.

To avoid inefficiencies and portability issues, the current C++ version of QEP does not to use pointers-to-member-functions, but simply plain pointers-to-functions to static member functions that don't have the "this" pointer and therefore are not affected by polymorphism or multiple inheritance. Please note that the explicit "me" pointer required by static class members plays the same role as the "context" pointer required by the object-oriented State design pattern (see Chapter 3 in Practical UML Statecharts in C/C++, Second Edition).

7.2 Step 2: Initializing the State Machine

The state machine initialization is divided into the following two steps for increased flexibility and better control of the initialization timeline:

  1. The state machine constructor; and
  2. The top-most initial transition.

The state machine constructor, such as Ship::Ship() (see Listing 7-1(10)), intentionally does not execute the top-most initial transition defined in the initial pseudostate because at that time some vital objects can be missing and critical hardware might not be properly initialized yet. Instead, the state machine constructor merely puts the state machine in the initial pseudostate. Later, the user code must trigger the top-most initial transition explicitly, which happens actually inside the function QActive::start() (see Listing 3-11(15-17)). Listing 7-2 shows the initialization (the initial pseudostate) of the Ship active object.

Listing 7-2 Instantiation and Initialization of the Ship active object in ship.cpp.

 (1) QState Ship::initial(Ship *me, QEvent const *) {
 (2)     me->subscribe(TIME_TICK_SIG);
 (3)     me->subscribe(PLAYER_TRIGGER_SIG);
 (4)     return Q_TRAN(&Ship::active);               // top-most initial transition
     }
  • (1) The Ship::initial() function defines the top-most initial transition in the Ship state machine (see Figure 5-2(1)).
  • (2-3) The Ship active object subscribes to signals TIME_TICK_SIG and PLAYER_TRIGGER_SIG, as specified in the state diagram in Figure 5-2(1).
  • (4) The initial state "active" is specified by invoking the QP macro Q_TRAN().
Note:
The macro Q_TRAN() must always follow the return statement.

7.3 Step 3: Defining State Handler Functions

In the last step, you actually code the Ship state machine by implementing one state at a time as a state handler function. To determine what elements belong the any given state handler function, you follow around the state's boundary in the diagram (Figure 5-2). You need to implement all transitions originating at the boundary, any entry and exit actions defined in the state, as well as all internal transitions enlisted directly in the state. Additionally, if there is an initial transition embedded directly in the state, you need to implement it as well.

Take for example the state "flying" shown in Figure 5-2. This state has an entry action and two transitions originating at its boundary: HIT_WALL and HIT_MINE(type), as well as three internal transitions TIME_TICK, PLAYER_TRIGGER, and DESTROYED_MINE(score). The "flying" state nests inside the "active" superstate. Listing 7-3 shows two state handler functions of the Ship state machine from Figure 5-2. The state handler functions correspond to the states "active" and "flying", respectively. The explanation section immediately following the listing highlights the important implementation techniques.

Listing 7-3 State handler functions for states "active" and "flying" in ship.cpp.

 (1) QState Ship::active(Ship *me, QEvent const *e) {
 (2)     switch (e->sig) {
 (3)         case Q_INIT_SIG: {                        // nested initial transition
 (4)             // any actions associated with the initial transition
 (5)             return Q_TRAN(&Ship::parked);
             }
 (6)         case PLAYER_SHIP_MOVE_SIG: {
 (7)             me->m_x = ((ObjectPosEvt const *)e)->x;
 (8)             me->m_y = ((ObjectPosEvt const *)e)->y;
 (9)             return Q_HANDLED();
             }
         }
(10)     return Q_SUPER(&QHsm::top);
     }
     //............................................................................
     QState Ship::flying(Ship *me, QEvent const *e) {
         switch (e->sig) {
(11)         case Q_ENTRY_SIG: {
(12)             ScoreEvt *sev;

                 me->m_score = 0;                                // reset the score
(13)             sev = Q_NEW(ScoreEvt, SCORE_SIG);
(14)             sev->score = me->m_score;
(15)             AO_Tunnel->postFIFO(sev);
(16)             return Q_HANDLED();
             }
             case TIME_TICK_SIG: {
                 // tell the Tunnel to draw the Ship and test for hits
                 ObjectImageEvt *oie = Q_NEW(ObjectImageEvt, SHIP_IMG_SIG);
                 oie->x   = me->m_x;
                 oie->y   = me->m_y;
                 oie->bmp = SHIP_BMP;
                 AO_Tunnel->postFIFO(oie);

                 ++me->m_score;   // increment the score for surviving another tick

                 if ((me->m_score % 10) == 0) {            // is the score "round"?
                     ScoreEvt *sev = Q_NEW(ScoreEvt, SCORE_SIG);
                     sev->score = me->m_score;
                     AO_Tunnel->postFIFO(sev);
                 }

                 return Q_HANDLED();
             }
             case PLAYER_TRIGGER_SIG: {                      // trigger the Missile
                 ObjectPosEvt *ope = Q_NEW(ObjectPosEvt, MISSILE_FIRE_SIG);
                 ope->x = me->m_x;
                 ope->y = me->m_y + SHIP_HEIGHT - 1;
                 AO_Missile->postFIFO(ope);
                 return Q_HANDLED();
             }
             case DESTROYED_MINE_SIG: {
                 me->m_score += ((ScoreEvt const *)e)->score;
                 // the score will be sent to the Tunnel by the next TIME_TICK
                 return Q_HANDLED();
             }
(17)         case HIT_WALL_SIG:
(18)         case HIT_MINE_SIG: {
(19)             // any actions associated with the transition
(20)             return Q_TRAN(&Ship::exploding);
             }
         }
(21)     return Q_SUPER(&Ship::active);
     }
  • (1) Each state handler must have the same signature, that is, it must take two parameters: the state machine pointer "me" and the pointer to QEvent. The keyword const before the '*' in the event pointer declaration means that the event pointed to by that pointer cannot be changed inside the state handler function (i.e., the event is read-only). A state handler function must return QState, which conveys the status of the event handling to the QEP event processor.
  • (2) Typically, every state handler is structured as a switch statement that discriminates based on the signal of the event signal e->sig.
  • (3) This line of code pertains to the nested initial transition Figure 5-2(2). QEP provides a reserved signal Q_INIT_SIG that the framework passes to the state handler function when it wants to execute the initial transition.
  • (4) You can enlist any actions associated with this initial transition (none in this particular case).
  • (5) You designate the target substate with the Q_TRAN() macro. This macro must always follow the return statement, through which the state handler function informs the QEP event processor that the transition has been taken.
Note:
The initial transition must necessarily target a direct or transitive substate of a given state. An initial transition cannot target a peer state or go up in state hierarchy to higher-level states, which in the UML would represent a "malformed" state machine.
  • (6) This line of code pertains to the internal transition PLAYER_SHIP_MOVE_SIG(x, y) in Figure 5-2(3).
  • (7-8) You access the data members of the Ship state machine via the "me" argument of the state handler function. You access the event parameters via the "e" argument. You need to cast the event pointer from the generic QEvent base class to the specific event structure expected for the PLAYER_SHIP_MOVE_SIG, which is ObjectPosEvt in this case.
Note:
The association between the event signal and event structure (event parameters) is established at the time the event is generated. All recipients of that event must know about this association to perform the cast to the correct event structure.
  • (9) You terminate the case statement with return Q_HANDLED(), which informs QP that the initial transition has been handled.
  • (10) The final return from a state handler function designates the superstate of that state by means of the QEP macro Q_SUPER(). The final return statement from a state handler function represents the single point of maintenance for changing the nesting level of a given state. The state "active" in Figure 5-2 has no explicit superstate, which means that it is implicitly nested in the "top" state. The "top" state is a UML concept that denotes the ultimate root of the state hierarchy in a hierarchical state machine. QEP provides the "top" state as a state handler function QHsm::top(), and therefore the Ship::active() state handler returns the pointer &QHsm::top.
Note:
In C++, a pointer-to-function QHsm::top() can be written either as QHsm::top, or &QHsm::top. Even though the notation QHsm::top is more succinct, I prefer adding the ampersand explicitly, to leave absolutely no doubt that I mean a pointer-to-function &QHsm::top.
  • (11) This line of code pertains to the entry action into state "flying" (Figure 5-2(5)). QEP provides a reserved signal Q_ENTRY_SIG that the framework passes to the state handler function when it wants to execute the entry actions.
  • (12) The entry action to "flying" posts the SCORE event to the Tunnel active object (Figure 5-2(5)). This line defines a temporary pointer to the event structure ScoreEvt.
  • (13) The QF macro Q_NEW(ScoreEvt, SCORE_SIG) dynamically allocates an instance of the ScoreEvt from an event pool managed by QF. The macro also performs the association between the signal SCORE_SIG and the allocated event. The Q_NEW() macro returns the pointer to the allocated event.
  • (14) The score parameter of the ScoreEvt is set from the state machine member me->score.
  • (15) The SCORE(me->score) event is posted directly to the Tunnel active object by means of the QP function QActive::postFIFO(). The arguments of this function are the recipient active object (AO_Tunnel in this case) and the pointer to the event (the temporary pointer sev in this case).
  • (16) You terminate the case statement with return Q_HANDLED(), which informs QEP that the entry actions have been handled.
  • (17-18) These two lines of code pertain to the state transitions from "flying" to "exploding" (Figure 5-2(9, 10)).
  • (19) You can enlist any actions associated with the transition (none in this particular case).
  • (20) You designate the target of the transition with the Q_TRAN() macro.
  • (21) The final return from a state handler function designates the superstate of that state. The state "flying" in Figure 5-2 nests in the state "active", so the state handler Ship::flying() returns the pointer &Ship::active wrapped with the macro Q_SUPER().

When implementing state handler functions you need to keep in mind that the QEP event processor is in charge here rather than your code. QEP will invoke a state handler function for various reasons: for hierarchical event processing, for execution of entry and exit actions, for triggering initial transitions, or even just to elicit the superstate of a given state handler. Therefore, you should not assume that a state handler would be invoked only for processing signals enlisted in the case statements. You should avoid any code outside the switch statement, especially code that would have side effects.

Prev: 6. Defining Event Signals and Event Parameters
Next: 8. Using the Built-in Real-Time Kernels and Third-Party RTOSes

Copyright © 2002-2011 Quantum Leaps, LLC. All Rights Reserved.
http://www.state-machine.com

Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: 8. Using the Built-in Real-Time Kernels and Third-Party RTOSes

  • QP/C++ Reference Manual
  • QP/C++ Tutorial

8. Using the Built-in Real-Time Kernels and Third-Party RTOSes

This QP/C++ 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: 7. Coding Hierarchical State Machines
Next: 9. Using Software Tracing for Testing and Debugging

As you saw in Listing 3-1(18), the main() function eventually gives control to the event-driven framework by calling QF::run() to execute the application. In this section, I briefly explain how QF allocates the CPU cycles to various tasks within the system and what options you have in choosing the execution model.

8.1 Simple Non-Preemptive "Vanilla" Kernel

In the simplest configuration, the "Fly 'n' Shoot" game executes under the simple cooperative "vanilla" kernel, which is provided in the QP. The "vanilla" kernel operates by constantly polling all event queues of active objects in an endless loop. The kernel always selects the highest-priority active object ready to run, which is the highest-priority active object with a non-empty event queue.

Note:
The "vanilla" kernel is so simple that many commercial real-time frameworks don't even call it a kernel . Instead, this configuration is simply referred to as "without an RTOS". However, if you want to understand what it means to execute active objects "without an RTOS" and what execution profile you can expect in this case, you need to realize that a simple cooperative vanilla kernel is indeed involved.

The interrupt service routines (ISRs) can preempt the execution of active objects at any time, but due to the simplistic nature of the "vanilla" kernel, every ISR returns to exactly the preemption point. If the ISR posts or publishes an event to any active object, the processing of this event won't start until the current RTC step completes. The maximum time an event for the highest-priority active object can be delayed this way is called the task-level response. With the non-preemptive "vanilla" kernel, the task-level response is equal to the longest RTC step of all active objects in the system. Please note that the task-level response of the "vanilla" kernel is still a lot better than the traditional "superloop" (a.k.a., main+ISRs) architecture. I'll have more to say about this in the upcoming Section 10. Comparison to the Traditional Approach, where I compare the event-driven "Fly 'n' Shoot" example to the traditionally structured "Quickstart" application.

The task-level response of the simple "vanilla" kernel turns out to be adequate for surprisingly many applications, because state machines by nature handle events quickly without a need to busy-wait for events. (A state machine simply runs-to-completion and becomes dormant until another event arrives). Please also note that often you can make the task-level response as fast as you need by breaking up longer RTC steps into shorter ones (e.g., by using the "Reminder" state pattern described in Chapter 5 of Practical UML Statecharts in C/C++, Second Edition.

8.2 The QK Preemptive Kernel

In some cases, breaking up long RTC steps into short enough pieces might be very difficult, and consequently the task-level response of the non-preemptive "vanilla" kernel might be too long. An example system could be a GPS receiver. Such a receiver performs a lot of floating point number crunching on a fixed-point CPU to calculate the GPS position. At the same time, the GPS receiver must track the GPS satellite signals, which involves closing control loops in sub-millisecond intervals. It turns out that it's not easy to break up the position-fix computation into short enough RTC steps to allow reliable signal tracking. But the RTC semantics of state machine execution does not mean that a state machine has to monopolize the CPU for the duration of the RTC step. A preemptive kernel can perform a context switch in the middle of the long RTC step to allow a higher-priority active object to run. As long as the active objects don't share resources they can run concurrently and complete their RTC steps independently.

The QP event-driven platform includes a tiny, fully preemptive, priority-based real-time kernel component called QK, which is specifically designed for processing events in the RTC fashion. Configuring QP to use the preemptive QK kernel is very easy, but as with any fully preemptive kernel you must be very careful with any resources shared among active objects5. The "Fly 'n' Shoot" example has been purposely designed to avoid any resource sharing among active objects, so the application code does not need to change at all to run on top of the QK preemptive kerel, or any other preemptive kernel or RTOS for that matter. The accompanying code contains the "Fly 'n' Shoot" example with QK in the following directory: <qpcpp>\examples\80x86\qk\watcom\l\game\. You can execute this example in a DOS-console on any standard Windows-based PC.

Prev: 7. Coding Hierarchical State Machines
Next: 9. Using Software Tracing for Testing and Debugging

Copyright © 2002-2011 Quantum Leaps, LLC. All Rights Reserved.
http://www.state-machine.com

Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: 9. Using Software Tracing for Testing and Debugging

  • QP/C++ Reference Manual
  • QP/C++ Tutorial

9. Using Software Tracing for Testing and Debugging

This QP/C++ 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: 8. Using the Built-in Real-Time Kernels and Third-Party RTOSes
Next: 10. Comparison to the Traditional Approach

A running application built of active objects is a highly structured affair where all important system interactions funnel through the real-time framework (QF) and the state-machine engine (QEP). This offers a unique opportunity to use software tracing techniques to gain unprecedented insight into the entire system.

Software tracing is a method for obtaining diagnostic information in a live environment without the need to stop the application to get the system feedback. In a nutshell, software tracing is similar to peppering the code with printf() statements for logging and debugging, except that mature software tracing techniques are much less intrusive and more selective than the primitive
printf().

Due to the inversion of a control, software tracing is particularly effective and powerful in combination with the event-driven frameworks. The QP event-driven platorm contains the sophisticated software tracing system called Quantum Spy (QS). The QS trace data can be thorough enough to produce complete sequence diagrams and detailed state machine activity for all state machines in the system. You can selectively monitor all event exchanges, event queues, event pools, and time events because all these elements are controlled by the framework. Additionally, if you use one of the kernels built into QP (the vanilla kernel or the preemptive QK kernel), you can obtain all the data available to a traditional RTOS as well, such as context switches and mutex activity

To show you how software tracing works in practice I present an example of a software tracing session. I use the application. All versions of the "Fly 'n' Shoot" game contain the QS instrumentation. The tracing instrumentation becomes active when you build the "Spy" configuration.

Note:
To build the "Spy" configuration in DOS version, please execute the make.bat script with the spy argument (make spy). To buld the "Spy" configuration in the ARM-Cortex version, please select the "Spy" configuration in the IAR EWARM IDE (see Figure 2-3).

Figure 9-1 shows how to collect the software trace data from the DOS version of the "Fly 'n' Shoot" application, which is located in the directory <qpcpp>\examples\80x86\dos\watcom\l\dpp\spy\dpp.exe. You can re-build the "Spy" configuration by executing make spy from the command line. You need to run the GAME.EXE executable on a target PC with a serial port. You connect the serial port of the target machine to the serial port of a Windows or a Linux host workstation via a NULL-modem cable.

Figure 9-1 Collecting software trace data from a 80x86 target.

Actually, all versions of "Fly 'n' Shoot" applications included in the standard QP distribution are instrumented for software tracing and I encourage you to try them all. For example, you can collect trace data from the LM3S811 board (see Figure 9-2). The LM3S811 board sends the QS trace data through the UART0 connected to the Virtual COM Port (VCP) provided by the USB debugger, so the QSPY host application can conveniently receive the trace data on the host PC. No additional serial cable is needed.

Figure 9-2 Collecting software trace data from the LM3S811 board.

On the host workstation, you need to start the QSPY host application that decompresses and visualizes the QS trace data. The Windows executable of the QSPY host application is located in the directory <qpcpp>\tools\qspy\win32\vc2005\Release\qspy.exe. Assuming that this directory is your current directory, or is in your path, you invoke this console application by typing the following command at the command prompt:

qspy -c COM1 -b 115200

The first command-line parameter -c COM1 tells the QSPY host application to receive the trace data from COM1. If your target is connected to a different COM port, you need to adjust the COM number. The second parameter configures the baud rate of the serial port to 115200. Section QSPY Command-Line Parameters explains the comman-line paratmeters of the QSPY host application.

Note:
In the particular case of a Windows PC, you can use the same machine as the target and the host at the same time. You need to use a machine with two serial ports, which you connect with a NULL modem cable. You can use one serial port for the DPP target application running in a DOS-window and the other for the QSPY host application.

You might also use a Linux host machine. In case of Linux, you must first build the executable by running the Makefile located in the directory <qpcpp>/tools/qspy/linux/gnu/. You invoke the Linux executable by typing the following command at the command prompt:

qspy -c /dev/ttyS0 -b 115200

The first parameter -c /dev/ttyS0 tells the QSPY application to receive the trace data from the ttyS0 serial device. If you connected a different serial port to the target, you need to adjust the ttyS number.

If everything is connected correctly, the QSPY host application should produce the human-readable output of the trace data to the screen. Please refer to QSPY Host Application Reference Manual explains the human-readable format as well as importing the trace data to MATLAB®.

Prev: 8. Using the Built-in Real-Time Kernels and Third-Party RTOSes
Next: 10. Comparison to the Traditional Approach

Copyright © 2002-2011 Quantum Leaps, LLC. All

Rights Reserved.
http://www.state-machine.com

Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: 10. Comparison to the Traditional Approach

  • QP/C++ Reference Manual
  • QP/C++ Tutorial

10. Comparison to the Traditional Approach

This QP/C++ 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: 9. Using Software Tracing for Testing and Debugging
Next: 11. Summary

The "Fly 'n' Shoot" game behaves intentionally almost identically to the "Quickstart" application provided in source code with the Luminary Micro ARM Cortex-M3 LM3S811 evaluation kit (http://www.luminarymicro.com). In this section I'd like to compare the traditional approach represented by the "Quickstart" application with the state machine-based solution exemplified in the "Fly 'n' Shoot" game.

Figure 10-1(a) shows schematically the flowchart of the "Quickstart" application, while Figure 10-1(b) shows the flowchart of the "Fly 'n' Shoot" game running on top of the cooperative "vanilla" kernel. At the highest level, the flowcharts are similar in that they both consist of an endless loop surrounding the entire processing. But the internal structure of the main loop is very different in the two cases. As indicated by the heavy lines in the flowcharts, the "Quickstart" application spends most of its time in the tight "event loops" designed to busy-wait for certain events, such as the screen update event. In contrast, the "Fly 'n' Shoot" application spends most of its time right in the main loop. The QP framework dispatches any available event to the appropriate state machine that handles the event and returns quickly to the main loop without ever waiting for events internally.

Figure 10-1 The control flow in the

Quickstart" application (a), and the Fly 'n' Shoot example (b). The heavy lines represent the most frequently exercised paths through the code."

The "Quickstart" application has much more convoluted flow of control than the "Fly 'n' Shoot" example, because the traditional solution is very specific to the problem at hand while the state-machine approach is generic. The "Quickstart" application is structured very much like a traditional sequential program that tries to stay in control from the beginning to the end. From time to time, the application pauses to busy-wait for a certain event, whereas the code is generally not ready to handle any other events than the one it chooses to wait for. All this contributes to the inflexibility of the design. Adding new events is hard because the whole structure of the intervening code is designed to accept only very specific events and would need to change dramatically to accommodate new events. Also, while busy-waiting for the screen update event (equivalent to the TIME_TICK event in "Fly 'n' Shoot" example) the application is really not responsive to any other events. The task-level response is hard to characterize and generally depends on the event type. The timing established by the hard-coded waiting for the existing events might not work well for new events.

In contrast, the "Fly 'n' Shoot" application has a much simpler control flow that is purely event-driven and completely generic (see Figure 10-1(b)). The context of each active object component is represented as the current state of a state machine, rather than as a certain place in the code. That way, hanging in tight "event loops" around certain locations in the code corresponding to the current context is unnecessary. Instead, a state machine remembers the context very efficiently as a small data item (the state-variable, see Chapter 3 of Practical UML Statecharts in C/C++, Second Edition). After processing of each event the state machine can return to the common event loop that is designed generically to handle all kinds of events. For every event, the state machine naturally picks up where it left off and moves on to the next state, if necessary. Adding new events is easy in this design, because a state machine is responsive to any event at any time. An event-driven, state-machine-based application is incomparably more flexible and resilient to change than the traditional one.

Note:
The generic event loop can also very easily detect the situation when no events are available, in which case the QP framework calls the QF::onIdle() function (see Figure 10-1(b)). This callback function is designed to be customized by the application and is the ideal place to put the CPU in a low-power sleep mode to conserve the power. In contrast, the traditional approach does not offer any single place to transition to the low-power sleep mode, and consequently is much less friendly for implementing truly low-power designs.

Prev: 9. Using Software Tracing for Testing and Debugging
Next: 11. Summary

Copyright © 2002-2011 Quantum Leaps, LLC. All Rights Reserved.
http://www.state-machine.com

Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: 11. Summary

  • QP/C++ Reference Manual
  • QP/C++ Tutorial

11. Summary

This QP/C++ 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: 10. Comparison to the Traditional Approach

If you've never done event-driven programming before, the internal structure of the "Fly 'n' Shoot" game must certainly represent a big paradigm shift for you. In fact, I hope that it actually blows your mind, because otherwise I'm not sure that you really appreciate the complete reversal of control of an event-driven program compared to the traditional sequential code. This reversal of control, known as the "Hollywood Principle" (don't call us, we'll call you), baffles many newcomers, who often find it "mind-boggling", "backwards", or "weird".

My main goal in this Tutorial was just to introduce you to the event-driven paradigm and the modern state machines to convince you that these powerful concepts aren't particularly hard to implement directly in C or C++. Indeed, I hope you noticed that the actual coding of the nontrivial "Fly 'n' Shoot" game wasn't a big deal at all. All you needed to know was just a few cookie-cutter rules for coding state machines and familiarity with a few framework services for implementing the actions.

Wile the coding turned out to be essentially a non-issue; the bulk of the programming effort was spent on the design of the application. At this point, I hope that the "Fly 'n' Shoot" example helps you to get the big picture of how the method works. Under the event driven model, the program structure is divided into two rough groups: events and state machine components (active objects). An event represents the occurrence of something interesting. A state machine codifies the reactions to the events, which generally depend both on the nature of the event and on the state of the component. While events often originate from the outside of your program, such as time ticks or button presses in the "Fly 'n' Shoot" game, events can also be generated internally by the program itself. For example the Mine components generate notification events when they detect a collision with the Missile or the Ship.

An event-driven program executes by constantly checking for possible events and, when an event is detected, dispatching the event to the appropriate state machine component (see Figure 10-1(b)). In order for this approach to work, the events must be checked continuously and frequently. This implies that the state machines must execute quickly, so that the program can get back to checking for events. In order to meet this requirement, a state machine cannot go into a condition where it is busy-waiting for some long or indeterminate time. The most common example of this would be a while loop inside a state-handler function, where the condition for termination was not under program control, for instance the button press. This kind of program structure, an indefinite loop, is referred to as "blocking" code6, and you saw examples of it in the "Quickstart" application (see Figure 10-1(a)). In order for the event driven programming model to work, you must only write "non-blocking" code.

Finally, the "Fly 'n' Shoot" example demonstrates the use of the event-driven platform called QP, which is a collection of components for building event-driven application. The QF real-time framework component framework embodies the "Hollywood principle", by calling the application code, not the other way around. Such arrangement is very typical for event-driven systems and application frameworks similar to QF are at the heart of virtually every design automation tool on the market today.

The QF framework operates in the "Fly 'n' Shoot" game in its simplest configuration, in which QF runs on a bare-metal target processor without any operating system. QF can also be configured to work with the build-in preemptive real-time kernel called QK (see Chapter 10 of Practical UML Statecharts in C/C++, Second Edition), or can be easily ported to almost any traditional OS or RTOS (see Chapter 8 of Practical UML Statecharts in C/C++, Second Edition). In fact, you can view the QF framework itself as a high-level, event-driven, real-time operating system.

Prev: 10. Comparison to the Traditional Approach

Copyright © 2002-2011 Quantum Leaps, LLC. All Rights Reserved.
http://www.state-machine.com

Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: Related Pages

Related Pages

Here is a list of all related documentation pages:
  • QP/C++ Revision History
  • Directories and Files in the QP/C++ Distribution
  • Encapsulation and Single Inheritance in C
  • GNU GENERAL PUBLIC LICENSE Version 2
Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: QP/C++ Revision History

QP/C++ Revision History

Version 4.1.06 (Product) Release date: Jan 07, 2011

1. Fixed a bug in the software tracing instrumentation in the function QF::remove_(), file qf_act.cpp.

2. Made cosmetic improvements to the example QM models of the "Fly 'n' Shoot" game.

3. Made improvements in make.bat files for building the examples for DOS/Open Watcom to run better in DosBox on Linux.

4. Upgraded the examples for ARM Cortex with IAR to the latest IAR EWARM version 6.10.

5. Upgraded the examples for ARM Cortex with CodeSourcery to the latest Sourcery G++ 2010.09-66.

Version 4.1.05 (Product) Release date: Nov 01, 2010

This release is adds examples for the QM (QP Modeler) graphical modeling and code generation tool. The examples are based on the "Fly 'n' Shoot" game described in the QP/C++ Tutorial and in Chapter 1 of the PSiCC2 book.

Specifically, the directory <qpcpp>\80x86-qm\ contains the "Fly 'n' Shoot" game model file "game.qm". This model, when opened in the QM tool contains all state machine diagrams and generates code into the subdirectory qm_code\. This code can then be built and executed on any 80x86 machine (newer versions of Windows or Linux require the DOSbox application, see http://www.dosbox.com).

The directory <qpcpp>-cortex-ev-lm3s811-qm\ contains the version of the game for the EV-LM3S811 ARM Cortex-M3 board. This directory contains the model file "game.qm", which is actually identical as the model in the DOS version. The LM3S811 version needs to be compiled with the IAR compiler and executed on the EV-LM3S811 board.

Additionally, the QP/C++ baseline code has been slighlty modified for better conformance to the MISRA C++ 2008 rules and the latest PC-Lint 9.x.

Version 4.1.04 (Product) Release date: Mar 16, 2010

This release is adds compatibility of all examples for DOS with the DOSBox emulator (http://www.dosbox.com/) that recreates a MS-DOS compatible environment on all versions of Windows, including 64-bit Windows that don't run 16-bit DOS applications anymore.

Also, this release includes QP ports and examples for EV-LM3S811 board with the GNU-based Code Sourcery G++ toolset. Support for Sourcery G++ provides a very cost-effective option for developing QP applications for ARM Cortex MCUs.

Finally, this release improves the Cortex Microcontroller Software Interface Standard (CMSIS) for the whole family of the Stellaris LM3Sxxx MCUs. The improvement extends the CMSIS from Sandstorm to Fury, DustDevil, and Tempest Stellaris families.

Version 4.1.03 (Product) Release date: Jan 21, 2010

This release is concerned with the ARM Cortex ports and examples. Specifically, this release contains the following improvements:

1. Unified source code for ARM Cortex-M3 and the new ARM Cortex-M0 cores, including the code for the preemptive QK kernel.

2. Compliance with the Cortex Microcontroller Software Interface Standard (CMSIS) in all ARM Cortex examples.

3. Backward-compatible support for the new LM3S811 EVAL Rev C board with different OLED display than previous revisions. (NOTE: The OSRAM 96x16x1 OLED used in REV A-B boards has been replaced RITEK 96x16x1 OLED used in Rev C.)

In the process of making the examples CMSIS-compliant, the dependency on the Luminary Micro driver library (driverlib.a) has been completely removed.

Additionally, the screen saver of the "Fly 'n' Shoot" game has been improved to periodically switch off the power of the OLED display, which better protects the display from burn-in. The affected file is tunnel.cpp.

Finally, this release introduces the QP_VERSION macro, which identifies the QP version. Otherwise, this maintenance release does not change the QP/C API in any way, so the release has NO IMPACT on the QP/C applications except for the ARM Cortex ports and applications.

Version 4.1.02 (Product) Release date: Jan 14, 2010

The purpose of this minor maintenance release is the change in the directory structure for the ARM Cortex ports and examples. As new ARM Cortex cores are becoming available, the old port name "cortex-m3" could be misleading, because it actually applies to wider range of ARM Cortex cores. Consequently, all ARM Cortex ports and examples are hosted in the directory tree called "arm-cortex".

This maintenance release does not change the QP/C++ API in any way, so the release has NO IMPACT on the QP/C++ applications except for the ARM Cortex ports.

Version 4.1.01 (Product) Release date: Nov 05, 2009

The main purpose of this release is to replace the Turbo C++ 1.01 toolset with the Open Watcom C/C++ toolset, because Turbo C++ 1.01 is no longer available for a free download. In contrast, Open Watcom is distributed under an OSI-certified open source license, which permits free commercial and non-commercial use. Open Watcom can be downloaded from www.openwatcom.org.

All 80x86/DOS and 80x86/qk ports and examples for Turbo C++ 1.01 have been replaced with ports and examples for Open Watcom. The make.bat scripts are provided to build the QP/C++ libraries and examples.

In the process of converting the examples to Open Watcom two new examples have been added to the standard QP/C++ distribution. The Calc2 example located in <qpcpp>\80x86 shows how to derive state machine classes with QP 4.x. The SLS example located in <qpcpp>\80x86 shows the implemenation of the new State-Local Storage state design pattern.

Version 4.1.00 (Product) Release date: Oct 09, 2009

The release provides brings a number of improvements to QP/C++ and updates the QP/C++ ARM Cortex-M3 examples for the EK-LM3S811 board to the latest IAR EWARM 5.40. Due to the acquisition of Liminary Micro by Texas Instruments the directory IAR structure for the examples and drivers has changed and the QP examples had to be changed accordingly.

This maintenance release does not change the QP/C++ API in any way, so the release has NO IMPACT on the QP/C++ applications.

The main changes in QP v4.1.00 with respect to earlier versions are as follows:

  • in qs.h added a new trace record QS_QEP_DISPATCH logged when an event is dispatched to a state machine. This timestamped trace record marks the beginning of an RTC step. The end of the RTC step is marked by the existing timestamped trace records QS_QEP_INTERN_TRAN, QS_QEP_INIT_TRAN, and QS_QEP_IGNORED, depending on how the event is handled. The new QS_QEP_DISPATCH record facilitates measurement of the RTC step lengths.
  • in qhsm_dis.cpp added generation of the QS_QEP_DISPATCH trace record.
  • in the tools\ sub-directory added output of the new trace record to the Q-SPY host application.
  • in the tools\ sub-directory added processing of the new trace record to the qspy.m script.
  • in qpset.h changed the implementation of the Priority Set. In particular, the QPSet64 now derives from QPSet8, which enables a common way of testing for non-empty set (e.g., useful in assembly). Also, the findMax() functions in QPSet8 and QPSet64 now can work with an empty set, in which case they return 0.
  • in qk_sched.cpp simplified the QK_schedule_() function to skip the testing of the ready-set for non-empty condition. Such test is no longer necessary. The test can still be performed outside the QK_schedule_() function (e.g., in assembly) to avoid calling the scheduler if the ready set is empty.
  • in qk_ext.cpp simplified the QK_scheduleExt_() function in the same way as QK_schedule_().
  • modified make.bat files for building QP libraries in the ports\ directory to use the externally defined environment variables for the location of the toolchains. The defaults are applied only when the environment variable is not defined. This enables greater flexibility in installing the development tools in different directories than those chosen by Quantum Leaps.
  • modified the ARM Cortex-M3 examples for the new IAR EWARM 5.40.
  • modified slighlty the Calculator example to allow extensibility.
  • in the ARM Cortex-M3 port file qk_port.s added explicit testing of the QK_readySet_ set for empty condition. This test allows avoiding calling the QK scheduler and two contex-switches if the ready-set is empty.
  • in the game example moved setting up the QS filters from main.cpp to bsp.cpp.

Version 4.0.04 (Product) Release date: Apr 09, 2009

The maintenance release introduces the virtual destructor in the QHsm and QFsm base classes. This is done to allow proper handling of virtual functions in the subclasses of QHsm or QFsm. Please note, however, that the change increases the size of every state machine object by the additional (hidden) virtual pointer (vptr).

Also, this release provides a fix for the compile-time assertions, which did not work correctly for the GNU compiler family.

Finally, the ARM Cortex-M3 examples have been recompiled with the newer IAR EWARM v5.30.

This maintenance release does not change the QP/C++ API in any way, so the release has NO IMPACT on the QP/C++ applications.

The main changes in QP v4.0.04 with respect to earlier version are as follows:

  • in qep.h file, virtual destructors have been added to QFsm and QHsm.
  • in qassert.h file the Q_ASSERT_COMPILE macro has been modified to render a negative array dimension when the asserted condition is not TRUE.

Version 4.0.03 (Product) Release date: Dec 27, 2008

The main purpose of this release is to fix a bug in the QK preemptive kernel, which occurs only when the advanced QK features are used. Specifically, the QK priority-ceiling mutex could interfere with QK thread-local storage (TLS) or QK extended context switch. When the QK mutex is in use, the TLS or the extended context for this task could get saved to an incorrect priority level.

The release 4.0.03 fixes the bug by strictly preserving the semantics of QK_currPrio_ variable. The mutex locking now uses a different variable QK_ceilingPrio_, which represents the ceiling-priority locked by the mutex. The QK scheduler and extended scheduler now perform an additional check to make sure that only tasks with priorities above the ceiling can run. To avoid that additional overhead, the user can define the macro QK_NO_MUTEX, which eliminates the QK mutex API and eliminates the additional tests in the QK schedulers.

This maintenance release does not change the QP/C++ API in any way, so the release has NO IMPACT on the QP/C++ applications.

The main changes in QP v4.0.03 with respect to earlier version are as follows:

  • in qk.h file, made the QK mutex API only visible when the macro QK_NO_MUTEX is *not* defined.
  • in qk_pkg.h file, added the QK_ceilingPrio_ external declaration when the macro QK_NO_MUTEX is not defined.
  • in qk_mutex.cpp file, changed priority-ceiling mutex implementation to use the QK_ceilingPrio_ instead of QK_currPrio_. Also, added compiler error when the macro QK_NO_MUTEX is definedthis and this file is included in the build.
  • in qk_sched.cpp file added testing priority against the QK_ceilingPrio_, when the macro QK_NO_MUTEX is not defined.
  • in qk_ext.cpp file added testing priority against the QK_ceilingPrio_, when the macro QK_NO_MUTEX is not defined.

Version 4.0.02 (Product) Release date: Nov 15, 2008

This maintenance release does not change the QP/C API in any way, so the release has NO IMPACT on the QP/C++ applications.

The main changes in QP v4.0.02 with respect to earlier version are as follows:

  • in qep.h file, added comments to macros Q_TRAN() and Q_SUPER() to suppress the PC-lint warining about using the comma-operator (MISRA rule 42).
  • in qhsm_in.cpp file, fixed a bug in the QHsm::isIn() function. - fixed a bug in tunnel.cpp file ("Fly 'n' Shoot" game). The constant event HIT_WALL was not declared static.

Version 4.0.01 (Product) Release date: June 09, 2008

This maintenace release is made to allow using QS software tracing with the GNU compiler for AVR (WinAVR). Specifically, the output of the strings residing in ROM has been fixed.

This maintenance release does not change the QP/C++ API in any way, so the release has NO IMPACT on the QP/C++ applications.

The main changes in QP v4.0.01 with respect to earlier version are as follows:

  • in qs_.cpp file, updated the function QS::str_ROM_().
  • in qs_str.cpp file, updated the function QS::str_ROM().
  • in qvanilla.cpp file, funciton QF::run(), declared the temporary variables as static to save stack space, because QF::run() never returns and is not reentrant.

Version 4.0.00 (Product) Release date: Apr 07, 2008

This milestone release is made for the book Practical UML Statecharts in C/C++, Second Edition. The book describes in great detail this new release. The older "QP Programmer's Manual" is now phased out and is replaced with this hyper-linked QP/C++ Reference Manual, which provides very detailed, easily searchable reference to the software. The book Practical UML Statecharts in C/C++, Second Edition provies in-depth discussion of the relevant concepts as well as the design study of QP v4.0.

The main changes in QP v4.0 with respect to earlier versions are as follows:

  • the coding techniques for hierarchical state machines (HSMs) and the simpler finite state machines (FSMs) have changed. While the changes are quite simple, the backward compatibility with QEP 3.x has been broken, meaning that some manual changes to the state machines implemented with earlier versions are necessary. Please refer to the "QP/C++ Tutorial" Section 7. Coding Hierarchical State Machines for more information about coding state machines with QEP 4.x.
    • The main change is the signature of a state-handler function, which now returns simply a byte. This return type (typedef'ed as QState) is the status of the event-handling that the state handler conveys to the QEP event processor.
    • The macro Q_TRAN() must now always follow the return statement.
    • The new macro Q_SUPER() designates the superstate of the given state. Again, this macro must follow the return statement.
    • Then two new macros Q_HANDLED() and Q_IGNORED() have been added to return the status of event handled and event ignored, respectively.
  • all callback functions are now consistently called XXX_onYYY() or XXX::onYYY():
    • Q_assert_handler() is now Q_onAssert()
    • QF::start() is now QF::onStartup()
    • QF::cleanup() is now QF::onCleanup()
  • the new header file qevent.h has been broken off the qep.h header file. qevent.h contains the QEvent class and other basic facilities used in the whole QP. This new file allows easier replacement of the entire QEP event processor with custom event processors, if you wish do so.
  • the macro QEP_SIGNAL_SIZE is renamed to Q_SIGNAL_SIZE.
  • the data type QSTATE is now deprecated. Please use QState.
  • the #QF_FSM_ACTIVE macro is now deprecated. Instead, please define QF_ACTIVE_SUPER_ to the base class of QActive and QF_ACTIVE_STATE_ to the data type represented state. By default, these macros are defined to use the QHsm base class from the QEP hierarchical event processor, but you can replace the event processor, if you wish.
  • the internal macro QACTIVE_OSOBJECT_WAIT_() is now QACTIVE_EQUEUE_WAIT_().
  • the internal macro QACTIVE_OSOBJECT_SIGNAL_() is now QACTIVE_EQUEUE_SIGNAL_().
  • the internal macro QACTIVE_OSOBJECT_ONIDLE_() is now QACTIVE_EQUEUE_ONEMPTY_().
  • the data mebers QActive::m_osObject and QActive::m_thread are now present only if the macros #QF_OS_OBJECT_TYPE and #QF_THREAD_TYPE are defined.
  • the ::QPSet class has been renamed to QPSet64.
  • the QPSet::hasElements() has been renamed QPSet64::notEmpty()
  • the QS software tracing is now better integrated with all QP components. You no longer need to explicitly include qs_port.h, because it is automatically included when you define the macro #Q_SPY. Also the file qs_dummy.h is included automatically when the macro #Q_SPY is not defined.
  • the new header file qvanilla.h now replaces the file qsched.h.
  • the macros QF_SCHED_LOCK() and QF_SCHED_UNLOCK() are now obsolete.
  • the native QF event queues (both the active object event queues and the "raw" thread-safe queues) are slightly more efficient by counting down the head and tail pointers rather than up. This leads to wrap-around at zero, which is easier (faster) to test than any other wrap-around point. Also the native QF event queues maintain the minimum of the free events in the queue rather the maximum of used events.
  • the data member of QEQueue::nTot class is removed.
  • the QF::publish() function has been re-written so that QF no does not need to lock the scheduler. The QF::publish() function posts events to active objects with scheduler unlocked starting from the highest-priority active objects. However, the event is protected from inadvertent recycling by incrementing its reference counter before the publish operation. After the event is posted to all subscribers, the garbage collector QF::gc() is called to decrement the reference counter and recycle the event, if necessary.
  • the qf_run.cpp file is obsolete. The QF::run() function for the cooperative "vanilla" kernel is now implemented in the file qvanilla.cpp.
  • the QF::tick() function has been rewritten to allow calling QF::tick() from the task context as well as from the interrupt context. The nested critical section around QF::tick() is no longer needed when it is called from the task level. Among others, this re-design eliminates the need for the recursive mutex in the POSIX QF port.
  • the QMPool::init() function has been re-designed to optimally align the memory buffer in a portable and platform-independent way. This should bring some performance improvements on some CPUs (e.g., 80x86).
  • the extended QK scheduler has been re-designed to save stack space. The extended context (e.g., coprocessor registers) are no longer saved on the precious stack, but rather in the active object.
  • a bug has been fixed in handling of Thread-Local Storage (TLS) in the QK scheduler and extended scheduler.
  • the -q (quiet) flag has been added to the QSPY host application.
  • the support for two new compilers for Windows has been added for the QSPY host application. The application can now be build with the MinGW GNU compiler for Windows as well as the Microsoft Visual C++ 2005.
  • the QP port to Linux has been improved by eliminating the need for recursive P-Thread mutex.
  • the QP port to MicroC/OS-II has been upgraded to the latest version 2.86.
  • all examples in the standard QP distribution have been cleaned up and updated to the latest QP API changes.
  • all examples that use QF now contain the QS software tracing support.

Version 3.4.01 (Product)

Release date: Sep 25, 2007

This product release adds the backward-compatibility layer so that previous QP/C++ ports continue to work with the new version.

This product release also comes with the updated "QP Programmer's Manual", which now includes the QS target component and the QSpy host application.

Version 3.4.00 (Beta)

Release date: Sep 03, 2007

This release brings several changes with the overall goal of simplifying and improving consistency across the whole QP family of frameworks (QP/C, QP/C++, and QP-nano).

The main changes are made to the QEP component. The "static transition optimization" has been removed altogether. This simplifies significantly the state machine structure (which now contains just the currently active state). Also, the efficiency is improved for processing the dynamic transitions and the stack usage is lower. This change brings the QEP/C++ implementation much closer to QEP-nano.

The other big change in this release is including the Quantum Spy (QS) component in the distribution. Previously, the QS component was available only under the commercial licensing. It is now open source, just as the rest of QP.

In, the QF/C++ component, the QTimerEvt::publishIn() and QTimeEvt::publishEvery() have been removed, because they introduced a coupling between time events and publish-subscribe. This is undesirable for projects that do not want to include the publish-subscribe facilty.

Finally, the revision history for individual QP/C++ components has been moved from the header files and is now consolidated in the header file doxygen/qpcpp_rev.h.

The updated "QP Programmer's Manual" is in the works...

Version 3.3.00 (Product)

Release date: Jan 23, 2007

The main change in this release is removing #include <stdint.h> from the qep.h header file. This has been done becasue vast majority of embedded compilers for small MCUs actually do not provide the C-99 Standard header file <stdint.h>. Worse, compilers such as Freescale HC(S)08 C/C++ compiler will not include <stdint.h> unless it's in the compilers's include directory, even though the "stdint.h" file might be in the compiler include path.

Removing the "#include <stdint.h>" from qep.h header file allows more flexibility in the way the standard exact-width integer types are defined. For compilers that do not provide the <stdint.h> file, you provide the typedef's in the qep_port.h file before including qep.h. For compilers that do provide the <stdint.h> header file, you simply include this file in the qep_port.h header file before including qep.h.

The changes in release 3.3.00 have impact on all QP ports, because you need to modify the qep_port.h file in all these ports.

The other significant change in this release is adding the macro Q_ROM_VAR for all constant objects allocated in ROM. The Q_ROM_VAR macro has been added for the compilers like Freescale HC(S)08, which require far pointers to access the objects in ROM. Please note that specifying the pointer size for accessing a ROM objects is syntactically different than specifying that the object is allocated in ROM (see macro Q_ROM).

QS is now better integrated with the rest of QP. This is achieved by using the QP macros Q_ROM, Q_ROM_VAR, QF_INT_KEY_TYPE, QF_INT_LOCK, and QF_INT_UNLOCK. By simply including the header file "qf_port.h" before "qs.h" in the "qs_port.h" include, you no longer need to manually ensure that QS implements the same policies as the rest of QP. This change still allows using QS standalone (without any other QP components), but then the QP macros must be explicitly defined in the qs_port.h header file. Also the macro #QS_ROM_VAR has been added for all constant objects allocated in ROM (see also macro Q_ROM_VAR added to QEP). The #QS_ROM_VAR macro has been added for the compilers like Freescale HC(S)08, which require far pointers to access the objects in ROM. Please note that specifying the pointer size for accessing a ROM objects is syntactically different than specifying that the object is allocated in ROM (see macro Q_ROM).

Finally, in release 3.3.00 the build strategy for QP ports has been simplified as well. Instead of separate Makefile for every QP component, such as QEP, QF, QK, and QS, not the "ports" directory contains a batch file "make.bat" that builds all the libraries at once.

  1. in file qep.h removed "#include <stdint.h>".
  2. in file qassert.h added macro Q_ROM_VAR for objects allocated in ROM and to signatures of functions accessing these objects.
  3. in file qep.h added macro Q_ROM_VAR for objects allocated in ROM and to signatures of functions accessing these objects.
  4. in file qep.h added default empty definitions and Doxygen comments for macros Q_ROM and Q_ROM_VAR.
  5. in file qep.cpp added macro Q_ROM_VAR for objects allocated in ROM and to signatures of functions accessing these objects.
  6. in file qf.cpp added macro Q_ROM_VAR for objects allocated in ROM and to signatures of functions accessing these objects.
  7. in file qk.cpp added macro Q_ROM_VAR for objects allocated in ROM and to signatures of functions accessing these objects.
  8. in file qep.cpp added Q_ROM_VAR to the signature of QEP::getVersion().
  9. in file qep.cpp changed the version number to "3.3.00".
  10. in file qf.h added macro Q_ROM_VAR for objects allocated in ROM and to signatures of functions accessing these objects.
  11. in file qf.h removed method QF::getTime() and deleted external variable QF::tickCtr.
  12. deleted obsolete file qa_fifo_.cpp
  13. deleted obsolete file qa_lifo_.cpp
  14. deleted obsolete file qf_time.cpp
  15. in file qf_act.cpp added Q_ROM_VAR to the signature of QF::getVersion()
  16. in file qf_log2.cpp added Q_ROM_VAR to the definition of the lookup.
  17. in file qf_pwr2.cpp added Q_ROM_VAR to the definition of the lookups.
  18. in file qf_tick.cpp removed incrementing QF::tickCtr.
  19. In file qf_act.cpp updated version number to 3.3.00
  20. Updated the "QP Programmer's Manaul" to Revision E
  21. in file qk.h added macro Q_ROM_VAR for objects allocated in ROM and to signatures of functions accessing these objects.
  22. In file qk.cpp added Q_ROM_VAR to the signature of QK::getVersion().
  23. In file qk.cpp updated version number to 3.3.00
  24. in file qs.h added macro #QS_ROM_VAR for objects allocated in ROM and to signatures of functions accessing these objects.
  25. In file qs.h added default definitions of the QS macros Q_ROM, Q_ROM_VAR, and Q_ROM_BYTE.
  26. In file qs.h added declaration of QS_tickCtr_.
  27. In file qs.cpp added Q_ROM_VAR to the signature of QS::getVersion().
  28. In file qs_.cpp added Q_ROM_VAR to the signature of QS::str_ROM_().
  29. In file qs_.cpp added definition of QS_tickCtr_.
  30. In file qs_str.cpp added Q_ROM_VAR to the signature of QS::str_ROM().
  31. In file qs.cpp updated version number to 3.3.00
  32. Updated the "QP Programmer's Manaul" to Revision E

Version 3.2.05

Release date: Dec 08, 2006

This QF release rolls back the changes made to the reference-counting policy. The reference count of a dynamic event is incremented when the event is posted, but is NOT decremented when the event is retreived from the queue. The reference count is decremented only later, in the garbage collector (QF::gc()).

This release adds direct support for event deferral (the "Deferred Event" state pattern) through methods QActive::defer() and QActive::recall().

  1. In file qf.h added methods QActive::defer() and QActive::recall().
  2. In file qa_get_.cpp removed decrementing the reference count of a dynamic event.
  3. In file qeq_get.cpp removed decrementing the reference count of a dynamic event.
  4. In file qf_gc.cpp restored decrementing of the reference count of a dynamic event.
  5. Added new file qa_defer.cpp that implements QActive::defer() and QActive::recall().
  6. In file qf_act.cpp updated version number to 3.2.05
  7. Updated the "QP Programmer's Manaul" to Revision D

Version 3.2.04 (Beta)

Release date: Dec 01, 2006

This QF release changes the internal policy of reference-counting for dynamic events. The reference count of a dynamic event is now incremented when the event is posted to a queue and decremented when the event is later retreived from the queue. This policy pertains to both active object queues and native QF thread-safe queues (QEQueue).

Previously, the reference count of a dynamic event was not decremented upon retreival of the event from the event queue, but rather in the garbage collector (QF::gc()).

This QK release adds two new features in QK. The first feature added is the extended context switch for CPUs with co-processors, such as the x87 FPU accompanying the x86 CPU. As a fully- preemptive kernel, QK needs to save and restore the context of the co- processor accrosss the asynchronous preemption. This QK release adds a generic mechanism for saving and restoring extened context in the extended scheduler (QK_scheduleExt_()), which is used only at the exit from the interrupts (asynchronous preemptions).

The second feature added is the Thread-Local Storage (TLS) for reentrant libraries, such as the NewLib. This feature allows assigning per-thread memory and providing a hook (callback) activated at every context switch.

  1. In file qf.h eliminated methods QActive::postFIFO_() and QActive::postLIFO_().
  2. In file qf.h promoted method QActive::get_() to the public scope to make it available to various thread-run routines.
  3. In file qf.h promoted method QActive::unsubscribeAll() to the public scope to make it available to various thread-run routines.
  4. In file qf.h promoted method QF::remove_() to the public scope to make it available to various thread-run routines.
  5. In file qf.h added friendship between class QActive and QK_scheduleExt_() and QK_isrExit_().
  6. In file qa_fifo.cpp changed the implementation of QActive::postFIFO() to represent the native QF event queue of an active object.
  7. In file qa_fifo_.cpp removed the implementation of QActive::postFIFO_() and declared the file obsolete (will be removed in future releases).
  8. In file qa_lifo.cpp changed the implementation of QActive::postLIFO() to represent the native QF event queue of an active object.
  9. In file qa_lifo_.cpp removed the implementation of QActive::postLIFO_() and declared the file obsolete (will be removed in future releases).
  10. In file qa_get_.cpp added decrementing the reference count of a dynamic event.
  11. In file qf_gc.cpp removed decrementing of the reference count of a dynamic event. Also changed the test for recycling an event (reference count of zero).
  12. In file qf_pspub.cpp removed incrementing the reference count of a dynamic event.
  13. Removed all uses of the macros #QACTIVE_POST_FIFO_, #QACTIVE_POST_LIFO_ and QACTIVE_GET_. These macros are made now obsolete.
  14. In file qsched.h removed definitions of the obsolete macros #QACTIVE_POST_FIFO_, #QACTIVE_POST_LIFO_, and QACTIVE_GET_.
  15. In file qf_pspub.cpp replaced the macro QACTIVE_POST_FIFO_() with the direct method invocation active_[p]->postFIFO(e).
  16. In file qf_tick.cpp replaced the macro QACTIVE_POST_FIFO_() with the direct method invocation active_[p]->postFIFO(e).
  17. In file qa_run.cpp replaced the macro QACTIVE_POST_GET_() with the direct method invocation get_().
  18. Changed the uC/OS-II port to reflect new policy of handling reference counters inside the dynamic events. Also removed files qa_fifo.cpp and qa_lifo.cpp from the uC/OS-II build.
  19. In file qf_act.cpp updated version number to 3.2.04
  20. In file qk.h updated revision history and added the prototype for the extended scheduler QK_scheduleExt_(). This scheduler implements the generic extended context via macros #QK_EXT_TYPE, QK_EXT_SAVE, and QK_EXT_RESTORE.
  21. In file qk.h removed definitions of the obsolete macros #QACTIVE_POST_FIFO_, #QACTIVE_POST_LIFO_, and QACTIVE_GET_.
  22. In file qk_sched.cpp added logic for handling the TLS via the macro QK_TLS.
  23. Added new file qk_ext.cpp with the definition of the extended scheduler QK_scheduleExt_().
  24. Added the file qk_ext.cpp to the Makefile for QK port to 80x86 with Turbo C++ 1.01.
  25. Extended the QK port to 80x86 with Turbo C++ 1.01 to handle the x87 FPU context.
  26. Extended the QDPP example for QK with Turbo C++ 1.01 to demonstrate threads that use the FPU and require the extended context switch.
  27. In file qk.cpp updated version number to 3.2.04
  28. Updated the "QP Programmer's Manaul" to Revision C

Version 3.2.03 (Product)

Release date: Nov 15, 2006

The main purpose of this release is to adapt the code to the shortcomings of the gcc compiler for handling data in program ROM for Harvard architecture CPUs, such as the Atmel's AVR or the 8051. In such machines, the data space (RAM) and program space (ROM) are accessed with different instructions. The gcc compiler does not automatically synthesize the correct code for accessing data placed in the program ROM, even though __attribute__((__progmem__)) is used. The workaround for the gcc is to add special assembly instructions to transfer the data from the program space to the data space. This version of QP-nano adds macros for each data element allocated to the program space (delcared with the Q_ROM attribute) Please note that commercial compilers, such as IAR, handle data allocated in the program space (ROM) correctly and do not need any workarounds.

This release also fixes a few minor inconsistencies in the code (see the list below):

  1. In file qf.h added default definition of macro Q_ROM_BYTE
  2. In file qf_set.h added macro Q_ROM_BYTE to access the lookup tables allocated in ROM (several places).
  3. In file qf_sched.h changed types QF_OS_OBJECT_TYPE and QF_THREAD_TYPE to uint8_t from int8_t
  4. In file qs_dummy.h added dummy definitions of some missing QS macros
  5. In file qa_sub.cpp added macro Q_ROM_BYTE to access the lookup tables allocated in ROM (several places).
  6. In file qa_usub.cpp added macro Q_ROM_BYTE to access the lookup tables allocated in ROM (several places).
  7. In file qf_usuba.cpp added macro Q_ROM_BYTE to access the lookup tables allocated in ROM (several places).
  8. In file qf_pspub.cpp added macro Q_ROM_BYTE to access the lookup tables allocated in ROM (several places).
  9. In file qf_tick.cpp replaced QF_tickCtr_ with QS::tickCtr_. allocated in ROM (several places).
  10. In file qf_act.cpp updated version number to 3.2.03

Version 3.2.02 (Product)

Release date: Oct 30, 2006

  1. In file qs.h replaced macro Q_ROM with QS_ROM
  2. In file qs.h added methods QS::str_ROM_() and QS::str_ROM()
  3. In file qs.h added macros QS_STR_ROM_() and QS_STR_ROM()
  4. In file qs.h modified macros QS_???_DICTIONARY() to use ROM strings
  5. In file qs.h included qs_dummy.h instead of the dummy definitions of the QS macros
  6. In file qs_pkg.h added #ifndef Q_SPY before definition of macro Q_SPY
  7. In file qs_.cpp added definition of the function QS::str_ROM_()
  8. In file qs_str.cpp added definition of the function QS::str_ROM()
  9. In file qs.cpp updated version number to 3.2.02

Version 3.2.01 (Product)

Release date: Sep 01, 2006

  1. In file qep.cpp updated version number to 3.2.01
  2. Added makefiles for building ports of all QP/C++ libraries at once.
  3. In file qf_act.cpp updated version number to 3.2.01
  4. Added makefiles for building ports of all QP/C++ libraries at once.
  5. Created the consolidated manual "QP/C++ Programmer's Manual".
  6. In file qk.cpp updated version number to 3.2.01
  7. Added makefiles for building ports of all QP/C++ libraries at once.
  8. Created the consolidated manual "QP/C++ Programmer's Manual".
  9. In file qs.cpp updated version number to 3.2.01
  10. In file qs.cpp removed superfluous semicolons after QS_INSERT...()
  11. In file qs_.cpp removed superfluous semicolons after QS_INSERT...()
  12. In file qs_str.cpp removed superfluous semicolons after QS_INSERT...()
  13. In file qs_mem.cpp removed superfluous semicolons after QS_INSERT...()
  14. In file qs_f32.cpp removed superfluous semicolons after QS_INSERT...()
  15. In file qs_f64.cpp removed superfluous semicolons after QS_INSERT...()
  16. Added makefiles for building ports of all QP/C++ libraries at once.
  17. Created the consolidated manual "QP/C++ Programmer's Manual".

Version 3.2.00 (Product)

Release date: Aug 07, 2006

  1. In file qep.h added the default definition of Q_ROM in case it's not defined by the user.
  2. In file qassert.h added the macro Q_ROM to allocate constant strings to ROM.
  3. In file qep.cpp updated version number to 3.2.00 # Updated the "QEP/C++ Programmer's Manual".
  4. In file qf.h added function QF_stop() to be called from the application code to stop the framework.
  5. In file qf.h added callback function QF_cleanup() to be called from the QF port to cleanup before exiting to the OS.
  6. In file qf.h deprecated the function QF_exit().
  7. In file qf.h changed the semantics of the QF::onIdle() callback. This callback is now invoked with interrupts LOCKED from the non-preemptive scheduler used in the "vanilla" QF ports to "bare metal" target boards.

    The modification changes the responsibilities of QF::onIdle(), which now MUST at least unlock interrupts. A failure to unlock interrupts in QF::onIdle() will leave the interrupts locked all the time and would prevent the application from running.

    Also, the signature of QF::onIdle() now depends on the interrupt locking policy. In case of the "save and restore interrupt status" policy, the QF::onIdle() callback takes the interrupt lock key as parameter (to be able to unlock the interrups correctly).
  8. In file qf.h used the macro Q_ROM to allocate constant objects to ROM (
    See also:
    qep.h). Objects allocated to ROM are: the version strings, and the lookup tables (QF::log2Lkup[], QF::pwr2Lkup[], QF::invPwr2Lkup[], and QF::div8Lkup[].
  9. Added new platform-independent header file qsched.h to provide the interface to the simple non-preemptive scheduler used in the "vanilla" ports of QF to "bare metal" targets. This header file is only applicable to the "vanilla" ports.
  10. Added new platform-independent implementation file qf_run.cpp to implement the simple non-preemptive scheduler used in the "vanilla" ports of QF to "bare metal" targets. This implementation file eliminates the need for qf_port.cpp file in the "vanilla" ports of QF. Also, the qf_run.cpp module should only be placed in the QF library in the vanilla QF ports.
  11. Simplified all "vanilla" ports of QF to use the common platform- independent implementation provided in qf_run.cpp.
  12. Updated QF::onIdle() callback in all examples of "vanilla" ports of QF to unlock interrupts.
  13. Updated the "QF/C++ Programmer's Manual".
  14. in file qk.h added new idle callback QK::onIdle(), which in contrast to QF::onIdle() is invoked with interrupts unlocked.
  15. in file qk.h removed QK_schedLock()/QK_schedUnlock() and replaced them with QK_mutexLock()/QK_mutexUnlock(), with the semantics of returning the mutex.
  16. in file qk.h changed the definitions of macros #QF_SCHED_LOCK/ #QF_SCHED_UNLOCK to use the new QK mutex API.
  17. In file qk.h used the macro Q_ROM to allocate constant objects to ROM (
    See also:
    qep.h).
  18. in file qk.h added the typedef for QMutex.
  19. in file qk.cpp replaced the callback QF::onIdle() with the new one QK::onIdle().
  20. removed source file qk_lock.cpp
  21. added source file qk_mutex.cpp
  22. in file qk.cpp changed the version number to 3.2.00
  23. in all QK/C++ examples replaced callback QF::onIdle() with QK::onIdle()
  24. Updated "QK/C++ Programmer's Manual"
  25. In file qs.h replaced QS_QK_SCHED_LOCK/UNLOCK with QS_QK_MUTEX_LOCK/ QS_QK_MUTEX_UNLOCK. Also, changed data accompanying the trace records QS_QK_MUTEX_LOCK/UNLOCK.
  26. In file qs.h used the macro Q_ROM to allocate constant objects to ROM (
    See also:
    qep.h).
  27. in file qs.cpp changed the version number to 3.2.00
  28. Updated "QS Programmer's Manual" in PDF.

Version 3.1.06 (Product)

Release date: May 11, 2006

  1. In file qk_sched.cpp removed unlocking of interrupts upon exit from QK::schedule_(). Now QK_schedule_() enters and exits with interrupts LOCKED.
  2. In file qk.h modified macro QACTIVE_OSOBJECT_SIGNAL_() to always unlock the interrupts, regardless if QK_schedule_() has been called or not.
  3. In file qk.cpp added unlocking interrupts after the call to QK_SCHEDULE_() in the function QF::run().
  4. In file qk_lock.cpp modified the function QK::schedUnlock() to always unlock the interrupts upon exit.
  5. Updated licensing information.
  6. Updated "QS/C++ Programmer's Manual" in PDF.

Version 3.1.03 (Product)

Release date: Feb 10, 2006

  1. In file qep.cpp added the Revision History Doxygen comment, which was previously in doxygen/qp.h
  2. In file qf_act.cpp added the Revision History Doxygen comment, which was previously in doxygen/qp.h
  3. In file qf.h augmented comment for QF_run() to cover the case when QF is used with QK.
  4. In file qf.h added the extern declarations of ::QF_tickCtr_, ::QF_intLockNest, and ::QF_isrNest_, which were previously declared in qf_pkg.h.
  5. In file qf.h added macros QF_QS_INT_LOCK, QF_QS_INT_UNLOCK(), QF_QS_ISR_ENTRY, and QF_QS_ISR_EXIT, which were previously declared in qs_port.h.
  6. In file ports/linux/gcc/qf_port.h added extern uint8_t QF_running_.
  7. In file qf/80x86/dos/tcpp101/l/qf_port.cpp replaced deprecated QPSet::hasElements() to QPSet::isEmpty().
  8. In file qf/80x86/linux/gcc/qf_port.cpp added QF::run()
  9. In file qeq_init.cpp changed QS_OBJ(this) to QS_OBJ(qSto) to consistently refer to a queue by the ring buffer object
  10. In file qf_pkg.h removed extern ::QF_tickCtr_.
  11. In file qk.h removed extern QK_intLockNest_ and QK_isrNest_. These counters have been moved to QF and renamed in the process to QF_intLockNest_ and QF_isrNest_, respectively.
  12. In file qk.h added QS instrumentatin to QF_INT_LOCK and QF_INT_UNLOCK macros for tracing interrupt locking/unlocking. The QS interrupt locking/ unlocking instrumentation has been previously added at the QK port level.
  13. In file qk.h removed macros QK_QS_INT_LOCK()/ QK_QS_INT_UNLOCK(), QK_QS_ISR_ENTRY()/ QK_QS_ISR_EXIT(). These macros have been moved to QF and renamed in the process to QF_QS_INT_LOCK()/ QF_QS_INT_UNLOCK(), QF_QS_ISR_ENTRY()/ QF_QS_ISR_EXIT(), respectively.
  14. In file ports/80x86/qk/tcpp101/l/qk_port.h simplified the definition of the macros #QK_INT_LOCK/ #QK_INT_UNLOCK to NOT contain the QS instrumenation.
  15. In file ports/80x86/qk/tcpp101/l/qk_port.h changed the definitions of QK_ISR_ENTRY and QK_ISR_EXIT to use QF_QS_ISR_ENTRY/ QF_QS_ISR_EXIT.
  16. In file qk.cpp added the Revision History Doxygen comment
  17. In file qk_pkg.h changed the definition of internal QK macros #QK_INT_LOCK_/ #QK_INT_UNLOCK_ to use the QS-instrumented QF_INT_LOCK/ QF_INT_UNLOCK.
  18. In file qk_lock.cpp corrected a comment
  19. In file qk_sched.cpp corrected a comment
  20. Provided "QS/C++ Programmer's Manual" in PDF.
  21. In file qs.h changed around the pre-defined records. Added records: QS_QF_INT_LOCK, QS_QF_INT_UNLOCK, QS_QF_ISR_ENTRY, QS_QF_ISR_EXIT. Removed records QS_QK_INT_LOCK, QS_QK_INT_UNLOCK, QS_QK_ISR_ENTRY, QS_QK_ISR_EXIT.
  22. In file qs.h renamed functions QS::filterIn()/ QS::filerOut() to QS::filterOn()/ QS::filerOff(). Correspondingly, changed macros QS_FILTER_IN(), QS_FILTER_OUT(), to QS_FILTER_ON(), QS_FILTER_OFF().
  23. In file qs.h changed the signature and semantics of QS::getByte() to return QS_EOD (End-Of-Data).
  24. In file qs.h changed the signature of QS::getBlock() to take a pointer to uint16_t rather than uint32_t.
  25. In file qs.h eliminated the callback QS::newRecord()
  26. In file qs.h added new callback QS::flush()
  27. In file qs.h added application-level local filter object QS::apObj_. Consistently, added macro QS_FILTER_AP_OBJ() to set the new local filter. Consistently, added object argument to macros QS_BEGIN() and QS_BEGIN_NOLOCK().
  28. In files qs.cpp, qs_.cpp, qs_blk.cpp, qs_byte.cpp, qs_pkg.h renamed some variables and adjusted comments.
  29. Ported the QSpy host applicatoin to Linux. Added TCP/IP input to QSpy. Added new options.
  30. Added redesigned QS port to Linux with TCP/IP data link.

Version 3.1.02 (Product)

Release date: Jan 29, 2006

  1. Removed Quantum Spy (QS) dependency from the QCalc and QHsmTst examples
  2. In file qk.h removed callbacks QK::init(), QK::start(), QK::idle(), and QK::exit(), because they duplicate the QF callbacks.
  3. Modified qk.cpp to define the following QF "callbacks": QF::getPortVersion(), QF::run(), QActive::start(), and QActive::stop_().
  4. Added an argument to the signature of QK::schedLock() to allow selective QK scheduler locking up to the specified priority level.
  5. Changed the implementation of QK::schedLock() in file qk_lock.cpp.
  6. Eliminated the need for qf_port.cpp in the QF/C++ ports for QK.
  7. Simplified elements that go into qk_port.cpp in the QK/C++ ports.
  8. Added the ARM-Simulator port to the standard QK/C++ distribution.
  9. Cleaned-up the 80x86 QK port.
  10. Provided "QK/C++ Programmer's Manual" in PDF.

Version 3.1.01 (Snapshot)

Release date: Oct 18, 2005

  1. Removed Quantum Spy (QS) dependency from the examples
  2. Added Doxygen documentation to the source code
  3. Added running__ member to the QActive structure
  4. Added QF_EVENT_SIZ_SIZE configuration macro and related data type QEventSize. Made the following changes to the signatures: void QF::poolInit(void *poolSto, uint32_t poolSize, QEventSize evtSize); QEvent *QF::new_(QEventSize evtSize, QSignal sig);
  5. In file qmpool.h changed the definition of the QF_MPOOL_SIZ_SIZE macro to remove the dependency on the QF_EVENT_SIZ_SIZE. Macro QF_EVENT_SIZ_SIZE might not be defined by the time qmpool.h is included.
  6. Added explicit definition of the configuration macro QF_EVENT_SIZ_SIZE to all qf_port.h files.
  7. Fixed a bug in function QMPool::init() (file qmp_init.cpp) by changing the type of variable n from uint8_t to QMPoolCtr. The uint8_t data type was failing for bigger block sizes.
  8. Added the QF::onIdle() callback to qf.h
  9. Improved comments in qpset.h
  10. Corrected dependencies in the Makefile for QDPP example (directory 80x86 and 80x86)
  11. Added Linux QF port to the standard QF/C++ distribution.
  12. Released the "QF/C++ Programmer's Manual"

Version 3.1.00 (Beta)

Release date: Oct 03, 2005

  1. Applied new directory structure desribed in Application Note: QP Directory Structure
  2. Added Quantum Spy instrumentation.
  3. Removed file qfsm_tra.cpp.
  4. Introduced file qfsm_dis.cpp.
  5. Applied new directory structure desribed in Application Note: QP Directory Structure
  6. Added Quantum Spy instrumentation.

Version 3.0.11 (Beta)

Release date: Aug 14, 2005

  1. Fixed potential race condition for static transitions
  2. Added assertion in QHsm::execTran() to catch potential path[] array overrun that previously could go undetected.

Version 3.0.10 (Beta)

Release date: Aug 06, 2005

This release contains completely redesigned Quantum Event Processor (QEP). The main focus is on compliance with standards (MISRA, Lint, Coding Standard), better portability, stack-use efficiency.

  1. This release includes a comprehensive "QEP/C++ v3.0 Programmer's Manual" in PDF.
  2. This release contains in-source comments for automatic generation of this Reference Manual with doxygen.
  3. This release includes re-packaging the code into much larger numberof modules (.cpp files) with typically one function per module. This fine-granularity packaging allows for better automatic elimination of unused code at link time and fine-tuning by applying different compiler options to different files.
  4. Although this is a C++ version, it has been still thoroughly checked against the Motor Industry Software Reliability Association (MISRA) "Guidelines for the Use of the C Language in Vehicle Based Software", April 1998, ISBN 0-9524156-9-0 (see also http://www.misra.org.uk). A separate Application Note "QEP/C++ MISRA Compliance Matrix" contains detailed account how QEP/C++ compiles with the 127 MISRA rules (See http://www.state-machine.com/doc/AN_QP_Cpp_MISRA.pdf).
  5. This release is now "lint-free". The source code has been thoroughly checked with the latest version of PC-lint(TM) (version 8.00q) from Gimpel Software (www.gimpel.com). The PC-lint configuration files and output files are included in the distribution. A separate Application Note "QEP/C++ PC-Lint Compliance" contains detailed account how QEP/C++ compiles with PC-Lint. (See http://www.state-machine.com/doc/AN_QP_Cpp_PC-Lint.pdf).
  6. This release is compliant with the "Quantum Leaps Coding Standard" (http://www.state-machine.com/resources/QL_coding_standard.pdf). Among others, all public names are prefixed by "Q_", or "QEP_" to minimize compile-time and link-time name conflicts. In addition, QEP/C++ uses the C99 standard include file <stdint.h> (C99 Standard, Section 7.18). Pre-standard compilers are still supported by placing <stdint.h> in the compiler's header file directory.
  7. The QEvent class has been redesigned to use memory more efficiently. QEvent takes up only 2 bytes now.
  8. The QHsm class now derives from the QFsm class, which promotes better code re-use. In particular, macros Q_INIT() and Q_TRAN() are now common for both traditional non-hierarchical FSMs and for HSMs.
  9. The QFsm class has been redesigned to allow using entry and exit actions. Now the QFsm class strictly avoids recursion, just as QHsm does (MISRA rule 70).
  10. The QPseudoState type has been eliminated and replaced by QState.
  11. The central QHsm class in QEP has been completely redesigned. The basic transition algorithm is essentially the same as described in "PSiCC", however the implementation is very different. The redesign was necessary to comply with the MISRA rules and to eliminate Lint warnings.
  12. The event processor is now strictly non-recursive (MISRA rule 70), that is, event handlers never call themselves, even indirectly. (Previous algorithm required one-level of indirect recursion.)
  13. Dynamic state transition is now default. Static transition optimization is still supported, but considered optional for performance tuning.
  14. The artificial limitation of initial transitions targeting only immediate substate of a composite state has been removed (see "PSiCC" Figure 5.4[a]). Initial transitions can now target any substate, arbitrarily nested within the composite state.
  15. This distribution uses the legacy Borland Turbo C++ 1.01 as the default compiler. Port to DOS with Turbo C++ 1.01 is provided along with GNU-compatible makefiles for the QEP library and sample applications. This compiler is not C99-compliant and does not provide the <stdint.h> header file. However, the port of QEP includes a minimal <stdint.h>, which should be placed into the INCLUDE directory of the Borland Turbo C++ 1.01 installation.
  16. This distribution contains three sample applications: A simple time bomb (QBomb) to demonstrate use of QFsm, a calculator (QCalc), and an exhaustive test of the QHsm class (QHsmTst). All examples are implemented as text-only application compiled with Turbo C++ 1.01. The QHsmTst sample application supports interactive and batch mode for exhaustive testing of the event processor. The source code for QHsmTst demonstrates also how QEP/C++ application code can be MISRA-compliant.
  17. This distribution contains make files for the Turbo C++ 1.01 make utility, as well as GNU-compatible Makefiles.
Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: Directories and Files in the QP/C++ Distribution

Directories and Files in the QP/C++ Distribution

The following annotated directory tree lists the most important directories and files provided in the standard QP distribution. The explanation section immediately following the directory tree explains the structure in more detail.

 (1)  qpcpp\               - QP/C++ root directory
       |
 (2)   +-qpcpp.chm        - "QP/C++ Reference Manual" in CHM Help format
       |
 (3)   +-doxygen\         - QP documentation generated with Doxygen
       | +-html\          - "QP/C++ Reference Manual" in HTML format
 (4)   | | +-index.html   - The HTML index page for the "QP/C++ Reference Manual"
       | | +- . . .
       | +-Doxyfile       - Doxygen configuration file to generate the Manual
       | +- . . .
       |
 (5)   +-examples\        - QP examples
 (6)   | +-80x86\         - Examples for the 80x86 processor
 (7)   | | +-dos\         - Examples for DOS with the "vanilla" cooperative kernel
 (8)   | | | +-watcom\    - Examples with the Open Watcom compiler
 (9)   | | | | +-l\       - Examples using the Large memory model
(10)   | | | | | +-dpp\   - Dining Philosopher Problem (DPP) example for DOS
       | | | | | | +-dbg\ - Debug build
       | | | | | | | +-dpp.exe - Debug executable
(11)   | | | | | | +-rel\      - Release build
       | | | | | | | +-dpp.exe - Release executable
(12)   | | | | | | +-spy\      - Spy build (with QS tracing instrumentation)
       | | | | | | | +-dpp.exe - Spy executable
(13)   | | | | | | +-make.bat  - Batch file to build QP libraries
       | | | | | |
       | | | | | +-game\       - "Fly 'n' Shoot" game example
       | | | | | | +-dbg\      - Debug build
       | | | | | | | +-GAME.EXE - Debug executable
       | | | | | | +-make.bat  - Batch file to build the application
       | | | | | | +-game.h    - The application header file
       | | | | | | +-bsp.cpp   - BSP for the application
       | | | | | | +-main.cpp  - main() function
       | | | | | |
       | | | | | +-calc\    - Calculator example
       | | | | | +-qhsmtst\ - QHsmTst example (PSiCC2  in Chapter 2)
       | | | | | |
(14)   | | | | | +-comp\    - "Orthogonal Component" pattern (PSiCC2 Chapter 5)
       | | | | | +-defer\   - "Deferred Event" pattern (PSiCC2 Chapter 5)
       | | | | | +-history\ - "Transition to History" pattern (PSiCC2 Chapter 5)
       | | | | | +-hook\    - "Ultimate Hook" pattern (Chapter 5)
       | | | | | +-reminder\ - "Reminder" pattern (PSiCC2 Chapter 5)
       | | |
(15)   | | +-qk\          - Examples for the QK preemptive kernel
(16)   | | +-ucos2\       - Examples for the µC/OS-II RTOS
       | | |
(17)   | | +-linux\       - Examples for Linux (POSIX)
       | | | +-gnu\       - Examples with the GNU compiler
       | | | | +-dpp\     - Dining Philosopher Problem (DPP) example for Linux
       | | | | | +-dbg\   - Debug build
       | | | | | +-rel\      - Release build
       | | | | | +-spy\      - Spy build (with software instrumentation)
(18)   | | | | | +-Makefile  - GNU Makefile to build the application
       | | | | | +-. . .
       | |
(19)   | +-arm-cortex\    - Examples for ARM Cortex
       | | +-vanilla\     - Examples for the cooperative "vanilla" kernel
       | | | +-iar\       - Examples with the IAR compiler
       | | | | +-dpp-ev-lm3s811\  - DPP example for for EV-LM3S811 board
       | | | | +-game-ev-lm3s811\ - "Fly 'n' Shoot" example for EV-LM3S811 board
       | | | | +-. . .    - Other examples for ARM Cortex
       | | | +-gnu\       - Examples with the GNU compiler
       | | | | +-dpp-ev-lm3s811\  - DPP example for for EV-LM3S811 board
       | | | | +-game-ev-lm3s811\ - "Fly 'n' Shoot" example for EV-LM3S811 board
       | | | | +-. . .    - Other examples for ARM Cortex
       | |
       | | +-qk\          - Examples for the preemptive QK kernel
       | | | +-iar\       - Examples with the IAR compiler
       | | | | +-dpp-qk-ev-lm3s811\  - DPP example for for EV-LM3S811 board
       | | | | +-game-qk-ev-lm3s811\ - "Fly 'n' Shoot" example for EV-LM3S811 board
       | | | | +-. . .    - Other examples for ARM Cortex
       | | | +-gnu\       - Examples with the GNU compiler
       | | | | +-dpp-qk-ev-lm3s811\  - DPP example for for EV-LM3S811 board
       | | | | +-game-qk-ev-lm3s811\ - "Fly 'n' Shoot" example for EV-LM3S811 board
       | | | | +-. . .    - Other examples for ARM Cortex
       | |
       | +-. . .          - Examples for other CPUs and compiler
       |
(20)   +-include\         - QP platform-independent header files
       | +-qassert.h      - QP assertions
       | +-qep.h          - QEP platform-independent interface
       | +-qf.h           - QF platform-independent interface
       | +-qk.h           - QK platform-independent interface
       | +-qs.h           - QS platform-independent active interface
       | +-qs_dummy.h     - QS platform-independent inactive interface
       | +-qequeue.h      - QF native event queue facility
       | +-qmpool.h       - QF native memory pool facility
       | +-qpset.h        - QF native priority set facility
       | +-qvanilla.h     - QF native "vanilla" cooperative kernel interface
       |
(21)   +-qep\             - QEP hierarchical event processor
       | +-source\        - QEP platform-independent source code (*.c files)
       | | +- . . .
       |
(22)   +-qf\              - QF real-time framework
       | +-source\        - QF platform-independent source code (*.c files)
       | | +- . . .
       |
(23)   +-qk\              - QK preemptive kernel
       | +-source\        - QK platform-independent source code (*.c files)
       | | +- . . .
       |
(24)   +-qs\              - QS software tracing (target component)
       | +-source\        - QS platform-independent source code (*.c files)
       | | +- . . .
       |
(25)   +-ports\           - Platform-specific QP ports
(26)   | +-80x86\         - Ports to the 80x86 processor
(27)   | | +-dos\         - Ports to DOS with the "vanilla" cooperative kernel
(28)   | | | +-watcom\    - Ports with the Open Watcom compiler
(29)   | | | | +-l\       - Ports using the Large memory model
(30)   | | | | | +-dbg\   - Debug build
(31)   | | | | | | +-qf.lib   - QF  library
(32)   | | | | | | +-qep.lib  - QEP library
       | | | | | +-rel\   - Release build
       | | | | | +-spy\   - Spy build (with software instrumentation)
       | | | | | | +-qep.lib  - QEP library
       | | | | | | +-qf.lib   - QF  library
       | | | | | | +-qs.lib   - QS  library
       | | | | | |
(33)   | | | | | +-make.bat   - batch script for building the QP libraries
(34)   | | | | | +-qep_port.h - QEP platform-dependent include file
(35)   | | | | | +-qf_port.h  - QF  platform-dependent include file
(36)   | | | | | +-qs_port.h  - QS  platform-dependent include file
(37)   | | | | | +-qp_port.h  - QP  platform-dependent include file
       | | |
       | | +-qk\          - Ports to the QK preemptive kernel
       | | | +-. . .
       | | |
       | | +-ucos2\       - Ports to the MicroC/OS-II RTOS
       | | | +-watcom\    - Ports with the Open Watcom compiler
       | | | | +-l\       - Ports using the Large memory model
(38)   | | | | | +-ucos2.86\  - MicroC/OS-II v2.86 object code and header files
(39)   | | | | | +-src\       - Port-specific source files
(40)   | | | | | | +-qf_port.cpp - QF port to µC/OS-II source file
       | | | | | +-. . .
       | | |
       | | +-linux\       - Ports to the Linux operating system (POSIX)
       | | | +-gnu\       - Ports with the GNU compiler
       | | | | +-src\         - Port-specific source files
       | | | | | +- qf_port.cpp - QF port to Linux source file
       | | | | +-. . .
       | |
       | +-arm-cortex\    - Ports to the ARM Cortex processor
       | | +-vanilla\     - Ports to the "vanilla" cooperative kernel
       | | | +-iar\       - Ports with the IAR compiler
       | | | | | +-dbg\   - Debug build
       | | | | | +-rel\   - Release build
       | | | | | +-spy\   - Spy build (with software instrumentation)
       | | | | | +-make_cortex-m3.bat - batch script for building QP libraries
       | | | | | +-qep_port.h - QEP platform-dependent include file
       | | | | | +-qf_port.h  - QF  platform-dependent include file
       | | | | | +-qs_port.h  - QS  platform-dependent include file
       | | | | | +-qp_port.h  - QP  platform-dependent include file
       | | | . . .
       | | | +-gnu\       - Ports with the GNU compiler (Code Sourcery G++)
       | | | | | +-dbg\   - Debug build
       | | | | | +-rel\   - Release build
       | | | | | +-spy\   - Spy build (with software instrumentation)
       | | | | | +-make_cortex-m3_cs.bat - batch script for building QP libraries
       | | | | | +-qep_port.h - QEP platform-dependent include file
       | | | | | +-qf_port.h  - QF  platform-dependent include file
       | | | | | +-qs_port.h  - QS  platform-dependent include file
       | | | | | +-qp_port.h  - QP  platform-dependent include file
       | | | . . .
       | | +-qk\          - Ports to the QK preemptive kernel
       | |   +-iar\       - Ports with the IAR compiler
       | |   +-gnu\       - Ports with the GNU compiler (Code Sourcery G++)
       | +-. . .          - Ports to other CPUs
       |
(41)   +-tools\           - QP-related tools for the host machine
(42)   | +-qspy\          - QSPY host application
       | | +-include\     - QSPY header files
       | | +-source\      - QSPY platform-independent source files
(43)   | | +-linux\       - QSPY port to Linux
       | | | +-gnu\       - QSPY port with the GNU compiler
       | | | | +-rel\     - Release build
       | | | | | +-qspy       - Linux executable (not provided -- must be built)
(44)   | | | | +-Makefile     - GNU Makefile to bulid QSPY for Linux
(45)   | | +-win32\       - QSPY ports to Win32
(46)   | | | +-mingw\     - QSPY port with the open source MinGW GNU compiler
       | | | | +-rel\     - Release build
       | | | | | +-qspy.exe   - Windows executable (console app)
       | | | | +-Makefile     - GNU Makefile to bulid QSPY for Win32 under MinGW
       | | | +-vc2008\    - QSPY port with Visual C++ 2008
(47)   | | | | +-Release\ - Release build
       | | | | | +-qspy.exe   - Windows executable (console app)
       | | | | +-qspy.sln     - Visual C++ solution to build QSPY
(48)   | | | +-vc6\       - QSPY port with Visual C++ 6.0
       | | | | +-Release\ - Release build
       | | | | | +-qspy.exe   - Windows executable (console app)
       | | | | +-qspy.dsw     - Visual C++ 6.0 workspace to build QSPY
(49)   | | +-matlab\      - MATLAB scripts to import QSPY data to MATLAB
  • (1) Every QP version, such as QP/C, QP/C++, or QP-nano resides in the separate directory branch, called henceforth QP Root Directory. The essential element of the design is that the QP Root Directory can be "plugged into" any branch of a hierarchical file system and you can move the QP Root Directory around, or even have multiple versions of the QP Root Directories. You can also freely choose the name of the QP Root Directory, although I recommend the directory names qpc\ for QP/C and qpcpp\ for QP/C++. The ability to relocate the QP Root Directory means that only relative paths should be used in the Makefiles, build scripts, workspaces, or project files.
  • (2) The file qpcpp.chm contains the "QP/C++ Reference Manual" in CHM format.
  • (3) The doxygen\ directory contains this "QP/C++ Reference Manual" generated with the Doxygen utility.
  • (4) The html\ subdirectory contains this HTML verions of the "QP/C++ Reference Manual". In particular, the file index.html is the index page of the Manual.
  • (5) The examples\ directory contains the application examples that are included in the standard QP/C++ distribution. The structure of the examples\ (and also ports\ directory) is the most complicated because of the large number of choices available, such as CPU architectures, compilers, operating systems, and compiler options. Each of those choices is represented as a separate level of nesting in a hierarchical directory tree, so that each dimension in the multi-dimensional space of options can be extended independently from the others. Also, the directory branch for each QP port is individually customizable, so each branch can represent only choices relevant for a given CPU, operating system, compiler, etc.
  • (6) The CPU architecture is placed as the first level of nesting within the examples\ directory. Examples of CPU architectures are: 80x86, ARM, ARM Cortex, AVR, MSP430, M16C, etc. Please note that a separate directory is needed whenever the CPU architecture is significantly different. For example, even though the traditional ARM and the new ARM Cortex are related, the differences are significant enough to require a separate directory branch for ARM and Cortex.
  • (7) The second level of nesting, under the CPU architecture, is the operating system used. For example, in the 80x86 architecture, QP can operate under DOS (with the "vanilla" cooperative kernel), under the QK preemptive kernel, under the MicroC/OS-II RTOS, or under Linux (and perhaps other OSs, such as Win32).
Note:
The ordering of directory levels reflects the embedded focus in the QP design. In most standalone QF applications the CPU architecture is typically more important than the RTOS/OS. For general-purpose operating systems, such as Linux, the reversed order (operating system at a higher level than the CPU architecture) would perhaps feel more natural.
  • (8) The next level of nesting, under each operating system directory, is the directory for the compiler used. For example, the DOS port can be compiled with the Open Watcom or perhaps with Borland C++. Similarly, the port to ARM Cortex with QK kernel can be compiled with the IAR, RealView, or GNU compilers.
  • (9) In some ports, the compiler can emit code for various modes of the CPU. For example, a compiler for 80x86 under DOS can produce small, compact, large, or huge memory models. These different modes result in incompatible object code, and therefore each of them requires a separate branch. Please note that the compiler options level is optional. For example, the ARM Cortex CPU branch does not need the compiler options level.
  • (10) Finally, the example application is located in its own directory. For example, the dpp\ directory contains the "Dining Philosopher Problem" application example for this particular CPU/Kernel/Compiler/Options combinations.
  • (11) The dpp\dbg\ subdirectory contains the object files and the executable for the Debug configuration.
  • (12) The dpp\rel\ subdirectory contains the object files and the executable for the Release configuration.
  • (13) The dpp\spy\ subdirectory contains the object files and the executable for the Spy configuration (with the QS Software Tracing Instrumentation (Target Component)).
  • (14) All five state designed patterns described in Chapter 5 of Practical UML Statecharts in C/C++, Second Edition (PSiCC2) are provided.
  • (15) The directory qk\ contains examples for the QK preemptive kernel.
  • (16) The directory ucos2\ contains examples for the MicroC/OS-II RTOS.
  • (17) The directory linux\ contains examples for the Linux operating system.
Note:
The port to Linux also runs on many POSIX-compliant OSes/RTOSes, such as BSD, Solaris, MacOS X, and QNX.
  • (18) The Makefile for building POSIX port is provided.
  • (19) The directory arm-cortex\ contains QP examples for ARM Cortex.
  • (20) The directory include\ contains platform-independent header files for QP all components. You need to point your C/C++ compiler to include files from this directory.
  • (21-24) The platform-independent source code of each QP component is located in the separate directory. The sources files are only needed to re-build QP libraries, but you don't need to include these directories in the compiler's search path to build applications.
  • (25) The directory ports\ contains platform-dependent header files and libraries to be used by QP applications. This directory structure is the most complicated because of the large number of choices available, such as CPU architectures, compilers, operating systems, and compiler options. Each of those choices is represented as a separate level of nesting in a hierarchical directory tree, so that each dimension in the multi-dimensional space of options can be extended independently from the others. Also, the directory branch for each port is individually customizable, so each branch can represent only choices relevant for a given CPU, operating system, compiler, etc.
  • (26) The CPU architecture is placed as the first level of nesting within the ports\ directory. Examples of CPU architectures are: 80x86, ARM, ARM Cortex, AVR, MSP430, M16C, etc. Please note that a separate directory is needed whenever the CPU architecture is significantly different. For example, even though the traditional ARM and the new ARM Cortex are related, the differences are significant enough to require a separate directory branch for ARM and ARM Cortex.
  • (27) The second level of nesting, under the CPU architecture, is the operating system used. For example, in the 80x86 architecture, QP can operate under DOS (with the "vanilla" cooperative kernel), under the QK preemptive kernel, under the MicroC/OS-II RTOS, or under Linux (and perhaps other OSs, such as Win32).
Note:
The ordering of directory levels reflects the embedded focus in the QP design. In most standalone QF applications the CPU architecture is typically more important than the RTOS/OS. For general-purpose operating systems, such as Linux, the reversed order (operating system at a higher level than the CPU architecture) would perhaps feel more natural.
  • (28) The next level of nesting, under each operating system directory, is the directory for the compiler used. For example, the DOS port can be compiled with the Open Watcom or perhaps with Borland C++. Similarly, the port to ARM Cortex with QK kernel can be compiled with the IAR, RealView, or GNU compilers.
  • (29) In some ports, the compiler can emit code for various modes of the CPU. For example, a compiler for 80x86 under DOS can produce small, compact, large, or huge memory models. These different modes result in incompatible object code, and therefore each of them requires a separate branch. Please note that the compiler options level is optional. For example, the ARM Cortex CPU branch does not need the compiler options level.
  • (30) Finally, the QP libraries can be compiled with different compile-time switches and optimization options. For example, the dbg\ directory holds the Debug configuration, which contains the symbolic debug information.
  • (31) Each specific build directory contains the QP library files. The actual library names should comply with the conventions used on a particular platform. For example, on Linux the libraries are typically named libXXX.a (e.g., libqep.a, libqf.a, etc.).
  • (32) The rel\ directory holds the Release configuration, which typically does not contain debug information but might use aggressive optimizations for best performance.
  • (33) The standard QP ports often contain a simple make.bat script or a Makefile for building all the QP libraries for the port. You typically can choose the build configuration by providing a target to the make.bat script or to the Makefile. The default target is "dbg". Other possible targets are "rel", and "spy". The following table summarizes the targets accepted by the make.bat scripts or the Makefiles.
Build Configuration | Build Command
Debug | make
Release | make rel
Spy | make spy
  • (34) The qep_port.h header file contains platform-specific definitions of macros and typedef's for the QEP component.
  • (35) The qf_port.h header file contains platform-specific definitions of macros and typedef's for the QF component.
  • (36) The qk_port.h header file contains platform-specific definitions of macros and typedef's for the QK component.
  • (37) The qs_port.h header file contains platform-specific definitions of macros and typedef's for the QS component.
  • (38) The subdirectory ucos2.86\ contains the headers and object files of MicroC/OS-II v2.86, compiled for 80x86 with the Open Watcom compiler. This directory is provided only to allow you re-building the example applications based on the QF port to MicroC/OS-II. Typically, however, you will need to obtain the MicroC/OS-II source code to re-build it for the actual processor you're using.
  • (39-40) QP ports to an external RTOS or OS, such as MicroC/OS-II or Linux require some "glue-code" to bolt the QF framework to the external RTOS/OS. This source code is placed in the file qf_port.c in the subdirectory src\.
  • (41) The directory tools\ contains host-resident tools used for QP (see QSPY Host Application Reference Manual).
  • (42) The directory qspy\ contains the portable QSPY host utility.
  • (43) The subdirectory linux\ contains QSPY port to Linux.
  • (44) The Makefile for building Linux QSPY executable is provided.
  • (45) The subdirectory win32\ contains QSPY port to Win32.
  • (46-48) The Windows version of QSPY can be build with three different compilers.
  • (49) The subdirectory matlab\ contains scripts to import QSPY data to MATLAB. You need to place this directory on the MATLAB path to convenietly access the scripts.

Copyright © 2002-2011 Quantum Leaps, LLC. All Rights Reserved.

Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: Encapsulation and Single Inheritance in C

Encapsulation and Single Inheritance in C

Inheritance is the ability to derive new structures based on existing structures in order to reuse and organize code. You can implement single inheritance in C very simply by literally embedding the base structure as the first member of the derived structure. For example, Figure 1(a) shows the structure ScoreEvt derived from the base structure QEvent by embedding the QEvent instance as the first member of ScoreEvt. To make this idiom better stand out, I always name the base structure member super.

Figure 1 (a) Derivation of structures in C, (b) memory alignment, and (c) the UML class diagram.

As shown in Figure 1(b), such nesting of structures always aligns the data member super at the beginning of every instance of the derived structure. In particular, this alignment lets you treat a pointer to the derived ScoreEvt structure as a pointer to the QEvent base structure. Consequently, you can always safely pass a pointer to ScoreEvt to any C function that expects a pointer to QEvent. (To be strictly correct in C, you should explicitly cast this pointer. In OOP such casting is called upcasting and is always safe.) Therefore, all functions designed for the QEvent structure are automatically available to the ScoreEvt structure as well as other structures derived from QEvent. Figure 1(c) shows the UML class diagram depicting the inheritance relationship between ScoreEvt and QEvent structures.

QP uses single inheritance quite extensively not just for derivation of events with parameters, but also for derivation of state machines and active objects. Of course, the C++ version of QP uses the native C++ support for class inheritance rather than "derivation of structures".

Copyright © 2002-2011 Quantum Leaps, LLC. All Rights Reserved.
http://www.state-machine.com

Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: GNU GENERAL PUBLIC LICENSE Version 2

GNU GENERAL PUBLIC LICENSE Version 2

June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.

Preamble

The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too.

When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.

To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.

For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.

We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.

Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.

Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.

The precise terms and conditions for copying, distribution and modification follow.

TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.

1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.

You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.

2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:

a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.
c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.

In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.

3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:

a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.

If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.

4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.

5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.

6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.

7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.

It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.

This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.

8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.

9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.

Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.

10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.

NO WARRANTY

11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

END OF TERMS AND CONDITIONS

How to Apply These Terms to Your New Programs

If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.

To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.

one line to give the program's name and an idea of what it does.
Copyright (C) yyyy  name of author
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this when it starts in an interactive mode:

Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
type `show w'.  This is free software, and you are welcome
to redistribute it under certain conditions; type `show c'
for details.

The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names:

Yoyodyne, Inc., hereby disclaims all copyright
interest in the program `Gnomovision'
(which makes passes at compilers) written
by James Hacker.
signature of Ty Coon, 1 April 1989
Ty Coon, President of Vice

This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License.

Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: Class List

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members

Class List

Here are the classes, structs, unions and interfaces with brief descriptions:
QActive | Base class for derivation of application-level active object classes
QEP | Provides miscellaneous QEP services
QEQueue | Native QF Event Queue class
QEvent | QEvent base class
QF | QF services
QFreeBlock | Structure representing a free block in the Native QF Memory Pool
QFsm | Finite State Machine base class
QHsm | Hierarchical State Machine base class
QK | QK services
QMPool | Native QF memory pool class
QPSet64 | Priority Set of up to 64 elements for building various schedulers, but also useful as a general set of up to 64 elements of any kind
QPSet8 | Priority Set of up to 8 elements for building various schedulers, but also useful as a general set of up to 8 elements of any kind
QS | Quantum Spy logging facilities
QSubscrList | Subscriber List class
QTimeEvt | Time Event class
Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: QActive Class Reference

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members
Public Member Functions | Public Attributes | Protected Member Functions | Friends

QActive Class Reference

Base class for derivation of application-level active object classes. More...

#include <qf.h>

List of all members.

Public Member Functions

void | start (uint8_t prio, QEvent const *qSto[], uint32_t qLen, void *stkSto, uint32_t stkSize, QEvent const *ie=(QEvent *) 0)
Starts execution of an active object and registers the object with the framework.
void | postFIFO (QEvent const *e)
Posts an event e directly to the event queue of the acitve object me using the First-In-First-Out (FIFO) policy.
void | postLIFO (QEvent const *e)
Posts an event directly to the event queue of the active object me using the Last-In-First-Out (LIFO) policy.
void | run (void)
Traditional loop-structured thread routine for an active object.
QEvent const * | get_ (void)
Get an event from the event queue of an active object.
void | unsubscribeAll (void) const
Un-subscribes from the delivery of all signals to the active object.

Public Attributes

uint8_t m_prio
QF priority associated with the active object.
uint8_t m_running
The Boolean loop variable determining if the thread routine of the active object is running.

Protected Member Functions

QActive (QF_ACTIVE_STATE_ initial)
protected constructor
void | stop (void)
Stops execution of an active object and removes it from the framework's supervision.
void | subscribe (QSignal sig) const
Subscribes for delivery of signal sig to the active object.
void | unsubscribe (QSignal sig) const
Un-subscribes from the delivery of signal sig to the active object.
void | defer (QEQueue *eq, QEvent const *e)
Defer an event to a given separate event queue.
QEvent const * | recall (QEQueue *eq)
Recall a deferred event from a given event queue.

Friends

class | QF
class | QTimeEvt

Detailed Description

Base class for derivation of application-level active object classes.

QActive is the base class for derivation of active objects. Active objects in QF are encapsulated tasks (each embedding a state machine and an event queue) that communicate with one another asynchronously by sending and receiving events. Within an active object, events are processed sequentially in a run-to-completion (RTC) fashion, while QF encapsulates all the details of thread-safe event exchange and queuing.

Note:
QActive is not intended to be instantiated directly, but rather serves as the base class for derivation of active objects in the application code.

The following example illustrates how to derive an active object from QActive.

class Philosopher : public QActive {
private:
    uint8_t  m_num;                             // number of this philosopher
    QTimeEvt m_timeEvt;                       // to timeout thining or eating

public:
    Philosopher::Philosopher()
    : QActive((QStateHandler)&Philosopher::initial),
      m_timeEvt(TIMEOUT_SIG)
    {}

protected:
    static QState initial (Philosopher *me, QEvent const *e);
    static QState thinking(Philosopher *me, QEvent const *e);
    static QState hungry  (Philosopher *me, QEvent const *e);
    static QState eating  (Philosopher *me, QEvent const *e);
};
See also:
QF_ACTIVE_SUPER_ defines the base class for QActive

Definition at line 113 of file qf.h.

Constructor & Destructor Documentation

QActive::QActive ( QF_ACTIVE_STATE_ initial ) [inline, protected]

protected constructor

Performs the first step of active object initialization by assigning the initial pseudostate to the currently active state of the state machine.

Note:
The constructor is protected to prevent direct instantiation of QActive objects. This class is intended only for derivation (abstract class).

Definition at line 261 of file qf.h.

Member Function Documentation

void QActive::defer | ( | QEQueue * | eq,
 |  | QEvent const * | e
 | ) |  | [protected]

Defer an event to a given separate event queue.

This function is part of the event deferral support. An active object uses this function to defer an event e to the QF-supported native event queue eq. QF correctly accounts for another outstanding reference to the event and will not recycle the event at the end of the RTC step. Later, the active object might recall one event at a time from the event queue.

An active object can use multiple event queues to defer events of different kinds.

See also:
QActive::recall(), QEQueue

Definition at line 9 of file lint_qf.txt.

QEvent const * QActive::get_ ( void )

Get an event from the event queue of an active object.

This function is used internally by a QF port to extract events from the event queue of an active object. This function depends on the event queue implementation and is sometimes implemented in the QF port (qf_port.cpp file). Depending on the underlying OS or kernel, the function might block the calling thread when no events are available.

Note:
QActive::get_() is public because it often needs to be called from thread-run routines with difficult to foresee signature (so declaring friendship with such function(s) is not possible.)
See also:
QActive::postFIFO(), QActive::postLIFO()

Definition at line 41 of file qa_get_.cpp.

References QS::aoObj_, QEvent::dynamic_, QACTIVE_EQUEUE_ONEMPTY_, QACTIVE_EQUEUE_WAIT_, QF_INT_LOCK_, QF_INT_LOCK_KEY_, QF_INT_UNLOCK_, QS_BEGIN_NOLOCK_, QS_END_NOLOCK_, QS_OBJ_, QS_QF_ACTIVE_GET, QS_QF_ACTIVE_GET_LAST, QS_SIG_, QS_U8_, and QEvent::sig.

Referenced by QF::run(), and run().

void QActive::postFIFO ( QEvent const * e )

Posts an event e directly to the event queue of the acitve object me using the First-In-First-Out (FIFO) policy.

Direct event posting is the simplest asynchronous communication method available in QF. The following example illustrates how the Philosopher active obejct posts directly the HUNGRY event to the Table active object.

extern QActive *AO_Table;

QState Philosopher::hungry(Philosopher *me, QEvent const *e) {
    TableEvt *pe;
    switch (e->sig) {
        case Q_ENTRY_SIG: {
            pe = Q_NEW(TableEvt, HUNGRY_SIG);    // dynamically allocate event
            pe->philNum = me->num_;
            AO_Table->postFIFO(pe);               // post the event directly
            return Q_HANDLED();
        }
        . . .
    }
    return Q_SUPER(&QHsm::top);
}
Note:
The producer of the event (Philosopher in this case) must only "know" the recipient (Table) by a generic (QActive *QDPP_table) pointer, but the specific definition of the Table class is not required.
Direct event posting should not be confused with direct event dispatching. In contrast to asynchronous event posting through event queues, direct event dispatching is synchronous. Direct event dispatching occurs when you call QHsm::dispatch(), or QFsm::dispatch() function.

Definition at line 41 of file qa_fifo.cpp.

References QS::aoObj_, Q_ASSERT, QACTIVE_EQUEUE_SIGNAL_, QF_INT_LOCK_, QF_INT_LOCK_KEY_, QF_INT_UNLOCK_, QS_BEGIN_NOLOCK_, QS_END_NOLOCK_, QS_OBJ_, QS_QF_ACTIVE_POST_FIFO, QS_SIG_, and QS_U8_.

Referenced by QF::tick().

void QActive::postLIFO ( QEvent const * e )

Posts an event directly to the event queue of the active object me using the Last-In-First-Out (LIFO) policy.

Note:
The LIFO policy should be used only with great caution because it alters order of events in the queue.
See also:
QActive::postFIFO()

Definition at line 41 of file qa_lifo.cpp.

References QS::aoObj_, Q_ASSERT, QACTIVE_EQUEUE_SIGNAL_, QF_INT_LOCK_, QF_INT_LOCK_KEY_, QF_INT_UNLOCK_, QS_BEGIN_NOLOCK_, QS_END_NOLOCK_, QS_OBJ_, QS_QF_ACTIVE_POST_LIFO, QS_SIG_, and QS_U8_.

Referenced by recall().

QEvent const * QActive::recall ( QEQueue * eq ) [protected]

Recall a deferred event from a given event queue.

This function is part of the event deferral support. An active object uses this function to recall a deferred event from a given QF event queue. Recalling an event means that it is removed from the deferred event queue eq and posted (LIFO) to the event queue of the active object.

QActive::recall() returns the pointer to the recalled event to the caller. The function returns NULL if no event has been recalled.

An active object can use multiple event queues to defer events of different kinds.

See also:
QActive::defer(), QEQueue, QActive::postLIFO()

Definition at line 43 of file qa_defer.cpp.

References QEvent::dynamic_, QEQueue::get(), postLIFO(), Q_ASSERT, QF_INT_LOCK_, QF_INT_LOCK_KEY_, and QF_INT_UNLOCK_.

void QActive::run ( void )

Traditional loop-structured thread routine for an active object.

This function is only used when QF is ported to a traditional RTOS/Kernel. QActive::run() is structured as a typical endless loop, which blocks on the event queue get() operation of an active object. When an event becomes available, it's dispatched to the active object's state machine and after this recycled with QF::gc(). The loop might optionally use the QActive::m_running flag to terminate and cause QActive::run() to return which is often the cleanest way to terminate the thread.

Definition at line 35 of file qa_run.cpp.

References QF::gc(), get_(), and m_running.

void QActive::start | ( | uint8_t | prio,
 |  | QEvent const * | qSto[],
 |  | uint32_t | qLen,
 |  | void * | stkSto,
 |  | uint32_t | stkSize,
 |  | QEvent const * | ie = (QEvent *)0
 | ) |  |

Starts execution of an active object and registers the object with the framework.

The function takes six arguments. prio is the priority of the active object. QF allows you to start up to 63 active objects, each one having a unique priority number between 1 and 63 inclusive, where higher numerical values correspond to higher priority (urgency) of the active object relative to the others. qSto[] and qLen arguments are the storage and size of the event queue used by this active object. stkSto and stkSize are the stack storage and size in bytes. Please note that a per-active object stack is used only when the underlying OS requies it. If the stack is not required, or the underlying OS allocates the stack internally, the stkSto should be NULL and/or stkSize should be 0. ie is an optional initialization event that can be used to pass additional startup data to the active object. (Pass NULL if your active object does not expect the initialization event).

Note:
This function is strongly OS-dependent and must be defined in the QF port to a particular platform.

The following example shows starting of the Philosopher object when a per-task stack is required:

static Philosopher   l_philo[N];               // N Philosopher active objects
static QEvent const *l_philQueueSto[N][N];   // storage for Philo event queues
static int l_philoStk[N][256];    // stacks for the Philosopher active objects

main() {
    . . .
    for (n = 0; n < N; ++n) {
        TableEvt ie;           // initialization event for the Philosopher HSM
        ie.philNum = n;
        l_philo[n].start((uint8_t)(n*10 + 1),                      // priority
                      l_philoQueueSto[n], Q_DIM(l_philoQueueSto[n]),  // queue
                      l_philoStk[n], sizeof(l_philoStk[n]),  // uC/OS-II stack
                      &ie);                            // initialization event
    }
    . . .
}

Definition at line 85 of file qvanilla.cpp.

References m_prio, Q_REQUIRE, QF_MAX_ACTIVE, and QS_FLUSH.

void QActive::stop ( void ) [protected]

Stops execution of an active object and removes it from the framework's supervision.

The preferred way of calling this function is from within the active object that needs to stop (that's why this function is protected). In other words, an active object should stop itself rather than being stopped by some other entity. This policy works best, because only the active object itself "knows" when it has reached the appropriate state for the shutdown.

Note:
This function is strongly OS-dependent and should be defined in the QF port to a particular platform. This function is optional in embedded systems where active objects never need to be stopped.

Definition at line 101 of file qvanilla.cpp.

References QF::remove_().

void QActive::subscribe ( QSignal sig ) const [protected]

Subscribes for delivery of signal sig to the active object.

This function is part of the Publish-Subscribe event delivery mechanism available in QF. Subscribing to an event means that the framework will start posting all published events with a given signal sig to the event queue of the active object.

The following example shows how the Table active object subscribes to three signals in the initial transition:

QState Table::initial(Table *me, QEvent const *) {
    uint8_t n;
    me->subscribe(HUNGRY_SIG);                          // subscribe to HUNGRY
    me->subscribe(DONE_SIG);                              // subscribe to DONE
    me->subscribe(TERMINATE_SIG);                    // subscribe to TERMINATE
    for (n = 0; n < N; ++n) {
        me->fork_[n] = FREE;
        me->isHungry_[n] = 0;
    }
    return Q_TRAN(&Table::serving);
}
See also:
QF::publish(), QActive::unsubscribe(), and QActive::unsubscribeAll()

Definition at line 38 of file qa_sub.cpp.

References QF::active_, QS::aoObj_, Q_REQUIRE, Q_ROM_BYTE, Q_USER_SIG, QF_div8Lkup, QF_INT_LOCK_, QF_INT_LOCK_KEY_, QF_INT_UNLOCK_, QF_MAX_ACTIVE, QF_maxSignal_, QF_pwr2Lkup, QF_subscrList_, QS_BEGIN_NOLOCK_, QS_END_NOLOCK_, QS_OBJ_, QS_QF_ACTIVE_SUBSCRIBE, and QS_SIG_.

void QActive::unsubscribe ( QSignal sig ) const [protected]

Un-subscribes from the delivery of signal sig to the active object.

This function is part of the Publish-Subscribe event delivery mechanism available in QF. Un-subscribing from an event means that the framework will stop posting published events with a given signal sig to the event queue of the active object.

Note:
Due to the latency of event queues, an active object should NOT assume that a given signal sig will never be dispatched to the state machine of the active object after un-subscribing from that signal. The event might be already in the queue, or just about to be posted and the un-subscribe operation will not flush such events.
Un-subscribing from a signal that has never been subscribed in the first place is considered an error and QF will rise an assertion.
See also:
QF::publish(), QActive::subscribe(), and QActive::unsubscribeAll()

Definition at line 38 of file qa_usub.cpp.

References QF::active_, QS::aoObj_, Q_REQUIRE, Q_ROM_BYTE, Q_USER_SIG, QF_div8Lkup, QF_INT_LOCK_, QF_INT_LOCK_KEY_, QF_INT_UNLOCK_, QF_invPwr2Lkup, QF_MAX_ACTIVE, QF_maxSignal_, QF_subscrList_, QS_BEGIN_NOLOCK_, QS_END_NOLOCK_, QS_OBJ_, QS_QF_ACTIVE_UNSUBSCRIBE, and QS_SIG_.

void QActive::unsubscribeAll ( void ) const

Un-subscribes from the delivery of all signals to the active object.

This function is part of the Publish-Subscribe event delivery mechanism available in QF. Un-subscribing from all events means that the framework will stop posting any published events to the event queue of the active object.

Note:
Due to the latency of event queues, an active object should NOT assume that no events will ever be dispatched to the state machine of the active object after un-subscribing from all events. The events might be already in the queue, or just about to be posted and the un-subscribe operation will not flush such events. Also, the alternative event-delivery mechanisms, such as direct event posting or time events, can be still delivered to the event queue of the active object.
See also:
QF::publish(), QActive::subscribe(), and QActive::unsubscribe()

Definition at line 38 of file qa_usuba.cpp.

References QF::active_, QS::aoObj_, Q_REQUIRE, Q_ROM_BYTE, Q_USER_SIG, QF_div8Lkup, QF_INT_LOCK_, QF_INT_LOCK_KEY_, QF_INT_UNLOCK_, QF_invPwr2Lkup, QF_MAX_ACTIVE, QF_maxSignal_, QF_pwr2Lkup, QF_subscrList_, QS_BEGIN_NOLOCK_, QS_END_NOLOCK_, QS_OBJ_, QS_QF_ACTIVE_UNSUBSCRIBE, and QS_SIG_.

Member Data Documentation

uint8_t QActive::m_prio

QF priority associated with the active object.

See also:
QActive::start()

Definition at line 150 of file qf.h.

Referenced by QF::getVersion(), QF::remove_(), and start().

uint8_t QActive::m_running

The Boolean loop variable determining if the thread routine of the active object is running.

This flag is only used with the traditional loop-structured thread routines. Clearing this flag breaks out of the thread loop, which is often the cleanest way to terminate the thread. The following example illustrates the thread routine for Win32:

void QActive::run(void) {
    do {
        QEvent const *e;
        QACTIVE_GET_(this, e);                               // wait for event
        dispatch(e);    // dispatch event to the active object's state machine
        QF::gc(e);      // check if the event is garbage, and collect it if so
    } while (m_running);

    unsubscribeAll();                          // unsubscribe from all signals
    QF::remove_(this);            // remove this object from any subscriptions
}

Definition at line 160 of file qf.h.

Referenced by run().

The documentation for this class was generated from the following files:
  • qf.h
  • lint_qf.txt
  • qa_defer.cpp
  • qa_fifo.cpp
  • qa_get_.cpp
  • qa_lifo.cpp
  • qa_run.cpp
  • qa_sub.cpp
  • qa_usub.cpp
  • qa_usuba.cpp
  • qvanilla.cpp
  • qk.cpp
Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: QEP Class Reference

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members
Static Public Member Functions

QEP Class Reference

Provides miscellaneous QEP services. More...

#include <qep.h>

List of all members.

Static Public Member Functions

static char const Q_ROM *Q_ROM_VAR getVersion (void)
get the current QEP version number string

Detailed Description

Provides miscellaneous QEP services.

Definition at line 42 of file qep.h.

Member Function Documentation

char const Q_ROM *Q_ROM_VAR QEP::getVersion ( void ) [static]

get the current QEP version number string

Returns:
version of the QEP as a constant 6-character string of the form x.y.zz, where x is a 1-digit major version number, y is a 1-digit minor version number, and zz is a 2-digit release number.

Definition at line 20 of file lint_qep.txt.

References QHsm::dispatch(), QFsm::dispatch(), QHsm::init(), QFsm::init(), QHsm::isIn(), Q_ALLEGE, Q_ASSERT, Q_DEFINE_THIS_MODULE, Q_ENTRY_SIG, Q_EXIT_SIG, Q_RET_TRAN, QEP_EMPTY_SIG_, QEP_ENTER_, QEP_EXIT_, QEP_MAX_NEST_DEPTH_, QEP_TRIG_, QP_VERSION, QS_BEGIN_, QS_FUN_, QS_OBJ_, QS_QEP_DISPATCH, QS_QEP_INIT_TRAN, QS_QEP_STATE_INIT, QS_QEP_TRAN, QS_SIG_, QEvent::sig, QS::smObj_, QHsm::top(), QFsm::~QFsm(), and QHsm::~QHsm().

The documentation for this class was generated from the following files:
  • qep.h
  • lint_qep.txt
  • qep.cpp
Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: QEQueue Class Reference

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members
Public Member Functions | Friends

QEQueue Class Reference

Native QF Event Queue class. More...

#include <qequeue.h>

List of all members.

Public Member Functions

void | init (QEvent const *qSto[], QEQueueCtr qLen)
Initializes the native QF event queue.
void | postFIFO (QEvent const *e)
"raw" thread-safe QF event queue implementation for the First-In-First-Out (FIFO) event posting. You can call this function from any task context or ISR context. Please note that this function uses internally a critical section.
void | postLIFO (QEvent const *e)
"raw" thread-safe QF event queue implementation for the First-In-First-Out (FIFO) event posting. You can call this function from any task context or ISR context. Please note that this function uses internally a critical section.
QEvent const * | get (void)
"raw" thread-safe QF event queue implementation for the Last-In-First-Out (LIFO) event posting.
QEQueueCtr | getNFree (void) const
"raw" thread-safe QF event queue operation for obtaining the number of free entries still available in the queue.

Friends

class | QF
class | QActive

Detailed Description

Native QF Event Queue class.

This structure describes the native QF event queue, which can be used as the event queue for active objects, or as a simple "raw" event queue for thread-safe event passing among non-framework entities, such as ISRs, device drivers, or other third-party components.

The native QF event queue is configured by defining the macro QF_EQUEUE_TYPE as QEQueue in the specific QF port header file.

The QEQueue structure contains only data members for managing an event queue, but does not contain the storage for the queue buffer, which must be provided externally during the queue initialization.

The event queue can store only event pointers, not the whole events. The internal implementation uses the standard ring-buffer plus one external location that optimizes the queue operation for the most frequent case of empty queue.

The QEQueue structure is used with two sets of functions. One set is for the active object event queue, which needs to block the active object task when the event queue is empty and unblock it when events are posted to the queue. The interface for the native active object event queue consists of the following functions: QActive::postFIFO_(), QActive::postLIFO_(), and QActive::get_(). Additionally the function QEQueue_init() is used to initialize the queue.

The other set of functions, uses this structure as a simple "raw" event queue to pass events between entities other than active objects, such as ISRs. The "raw" event queue is not capable of blocking on the get() operation, but is still thread-safe because it uses QF critical section to protect its integrity. The interface for the "raw" thread-safe queue consists of the following functions: QEQueue::postFIFO(), QEQueue::postLIFO(), and QEQueue::get(). Additionally the function QEQueue::init() is used to initialize the queue.

Note:
Most event queue operations (both the active object queues and the "raw" queues) internally use the QF critical section. You should be careful not to invoke those operations from other critical sections when nesting of critical sections is not supported.

Definition at line 110 of file qequeue.h.

Member Function Documentation

QEvent const * QEQueue::get ( void )

"raw" thread-safe QF event queue implementation for the Last-In-First-Out (LIFO) event posting.

Note:
The LIFO policy should be used only with great caution because it alters order of events in the queue.
The function raises an assertion if the native QF queue becomes full and cannot accept the event. You can call this function from any task context or ISR context. Please note that this function uses internally a critical section.
See also:
QEQueue::postFIFO(), QEQueue::get()

Definition at line 38 of file qeq_get.cpp.

References QEvent::dynamic_, QS::eqObj_, QF_INT_LOCK_, QF_INT_LOCK_KEY_, QF_INT_UNLOCK_, QS_BEGIN_NOLOCK_, QS_END_NOLOCK_, QS_OBJ_, QS_QF_EQUEUE_GET, QS_QF_EQUEUE_GET_LAST, QS_SIG_, QS_U8_, and QEvent::sig.

Referenced by QActive::recall().

QEQueueCtr QEQueue::getNFree ( void ) const [inline]

"raw" thread-safe QF event queue operation for obtaining the number of free entries still available in the queue.

Note:
This operation needs to be used with caution because the number of free entries can change unexpectedly. The main intent for using this operation is in conjunction with event deferral. In this case the queue is accessed only from a single thread (by a single AO), so the number of free entries cannot change unexpectedly.
See also:
QActive::defer(), QActive::recall()

Definition at line 205 of file qequeue.h.

void QEQueue::init | ( | QEvent const * | qSto[],
 |  | QEQueueCtr | qLen
 | ) |  |

Initializes the native QF event queue.

The parameters are as follows: qSto[] is the ring buffer storage, qLen is the length of the ring buffer in the units of event- pointers.

Note:
The actual capacity of the queue is qLen + 1, because of the extra location fornEvt_.

Definition at line 35 of file qeq_init.cpp.

References QS::eqObj_, QS_BEGIN_, QS_END_, QS_INT_LOCK_KEY_, QS_OBJ_, and QS_QF_EQUEUE_INIT.

void QEQueue::postFIFO ( QEvent const * e )

"raw" thread-safe QF event queue implementation for the First-In-First-Out (FIFO) event posting. You can call this function from any task context or ISR context. Please note that this function uses internally a critical section.

Note:
The function raises an assertion if the native QF queue becomes full and cannot accept the event.
See also:
QEQueue::postLIFO(), QEQueue::get()

Definition at line 38 of file qeq_fifo.cpp.

References QS::eqObj_, Q_ASSERT, QF_INT_LOCK_, QF_INT_LOCK_KEY_, QF_INT_UNLOCK_, QS_BEGIN_NOLOCK_, QS_END_NOLOCK_, QS_OBJ_, QS_QF_EQUEUE_POST_FIFO, QS_SIG_, and QS_U8_.

void QEQueue::postLIFO ( QEvent const * e )

"raw" thread-safe QF event queue implementation for the First-In-First-Out (FIFO) event posting. You can call this function from any task context or ISR context. Please note that this function uses internally a critical section.

Note:
The function raises an assertion if the native QF queue becomes full and cannot accept the event.
See also:
QEQueue::postLIFO(), QEQueue::get()

Definition at line 38 of file qeq_lifo.cpp.

References QS::eqObj_, Q_ASSERT, QF_INT_LOCK_, QF_INT_LOCK_KEY_, QF_INT_UNLOCK_, QS_BEGIN_NOLOCK_, QS_END_NOLOCK_, QS_OBJ_, QS_QF_EQUEUE_POST_LIFO, QS_SIG_, and QS_U8_.

The documentation for this class was generated from the following files:
  • qequeue.h
  • qeq_fifo.cpp
  • qeq_get.cpp
  • qeq_init.cpp
  • qeq_lifo.cpp
Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: QEvent Struct Reference

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members
Public Attributes

QEvent Struct Reference

QEvent base class. More...

#include <qevent.h>

Inheritance diagram for QEvent:
QTimeEvt

List of all members.

Public Attributes

QSignal sig
signal of the event instance
uint8_t dynamic_
attributes of a dynamic event (0 for static event)

Detailed Description

QEvent base class.

QEvent represents events without parameters and serves as the base class for derivation of events with parameters.

Note:
All data members of the QEvent class must remain public to keep it an AGGREGATE. Therefore, the attribute QEvent::dynamic_ cannot be declared private.

The following example illustrates how to add an event parameter by inheriting from the QEvent class.

struct QCalcEvt : public QEvent {
    uint8_t keyId;                                  // ID of the key depressed
};

Definition at line 139 of file qevent.h.

The documentation for this struct was generated from the following file:
  • qevent.h
Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: QF Class Reference

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members
Static Public Member Functions | Static Public Attributes | Friends

QF Class Reference

QF services. More...

#include <qf.h>

List of all members.

Static Public Member Functions

static void | init (void)
QF initialization.
static void | psInit (QSubscrList *subscrSto, QSignal maxSignal)
Publish-subscribe initialization.
static void | poolInit (void *poolSto, uint32_t poolSize, QEventSize evtSize)
Event pool initialization for dynamic allocation of events.
static void | run (void)
Transfers control to QF to run the application.
static void | onStartup (void)
Startup QF callback.
static void | onCleanup (void)
Cleanup QF callback.
static void | stop (void)
Function invoked by the application layer to stop the QF application and return control to the OS/Kernel.
static void | publish (QEvent const *e)
Publish event to the framework.
static void | tick (void)
Processes all armed time events at every clock tick.
static char const Q_ROM *Q_ROM_VAR | getVersion (void)
Returns the QF version.
static char const Q_ROM *Q_ROM_VAR | getPortVersion (void)
Returns the QF-port version.
static uint32_t | getPoolMargin (uint8_t poolId)
This function returns the margin of the given event pool.
static uint32_t | getQueueMargin (uint8_t prio)
This function returns the margin of the given event queue.
static QEvent * | new_ (uint16_t evtSize, QSignal sig)
Internal QF implementation of the dynamic event allocator.
static void | gc (QEvent const *e)
Recycle a dynamic event.
static void | remove_ (QActive const *a)
Remove the active object from the framework.

Static Public Attributes

static QActive * | active_ []
array of registered active objects

Friends

class | QActive

Detailed Description

QF services.

This class groups together QF services. It has only static members and should not be instantiated.

Definition at line 614 of file qf.h.

Member Function Documentation

void QF::gc ( QEvent const * e ) [static]

Recycle a dynamic event.

This function implements a simple garbage collector for the dynamic events. Only dynamic events are candidates for recycling. (A dynamic event is one that is allocated from an event pool, which is determined as non-zero e->attrQF__ attribute.) Next, the function decrements the reference counter of the event, and recycles the event only if the counter drops to zero (meaning that no more references are outstanding for this event). The dynamic event is recycled by returning it to the pool from which it was originally allocated. The pool-of-origin information is stored in the upper 2-MSBs of the e->attrQF__ attribute.)

Note:
QF invokes the garbage collector at all appropriate contexts, when an event can become garbage (automatic garbage collection), so the application code should have NO need to call QF::gc() directly. The QF::gc() function is exposed only for special cases when your application sends dynamic events to the "raw" thread-safe queues (see QEQueue). Such queues are processed outside of QF and the automatic garbage collection CANNOT be performed for these events. In this case you need to call QF::gc() explicitly.

Definition at line 38 of file qf_gc.cpp.

References Q_ASSERT, QF_EPOOL_PUT_, QF_INT_LOCK_, QF_INT_LOCK_KEY_, QF_INT_UNLOCK_, QF_maxPool_, QF_pool_, QS_BEGIN_NOLOCK_, QS_END_NOLOCK_, QS_QF_GC, QS_QF_GC_ATTEMPT, QS_SIG_, and QS_U8_.

Referenced by run(), and QActive::run().

uint32_t QF::getPoolMargin ( uint8_t poolId ) [static]

This function returns the margin of the given event pool.

This function returns the margin of the given event pool poolId, where poolId is the ID of the pool initialized by the call to QF::poolInit(). The poolId of the first initialized pool is 1, the second 2, and so on.

The returned pool margin is the minimal number of free blocks encountered in the given pool since system startup.

Note:
Requesting the margin of an un-initialized pool raises an assertion in the QF.

Definition at line 62 of file qmp_get.cpp.

References Q_REQUIRE, QF_INT_LOCK_, QF_INT_LOCK_KEY_, QF_INT_UNLOCK_, QF_maxPool_, and QF_pool_.

char const Q_ROM *Q_ROM_VAR QF::getPortVersion ( void ) [static]

Returns the QF-port version.

This function returns constant version string in the format x.y.zz, where x (one digit) is the major version, y (one digit) is the minor version, and zz (two digits) is the maintenance release version. An example of the QF-port version string is "1.1.03".

See also:
QF::getVersion()

Definition at line 46 of file qvanilla.cpp.

References Q_ROM.

uint32_t QF::getQueueMargin ( uint8_t prio ) [static]

This function returns the margin of the given event queue.

This function returns the margin of the given event queue of an active object with priority prio. (QF priorities start with 1 and go up to QF_MAX_ACTIVE.) The margin is the minimal number of free events encountered in the given queue since system startup.

Note:
QF::getQueueMargin() is available only when the native QF event queue implementation is used. Requesting the queue margin of an unused priority level raises an assertion in the QF. (A priority level becomes used in QF after the call to the QF::add_() function.)

Definition at line 82 of file qa_get_.cpp.

References active_, Q_REQUIRE, QF_INT_LOCK_, QF_INT_LOCK_KEY_, QF_INT_UNLOCK_, and QF_MAX_ACTIVE.

const char Q_ROM *Q_ROM_VAR QF::getVersion ( void ) [static]

Returns the QF version.

This function returns constant version string in the format x.y.zz, where x (one digit) is the major version, y (one digit) is the minor version, and zz (two digits) is the maintenance release version. An example of the version string is "3.1.03".

The following example illustrates the usage of this function:

printf("Quantum DPP\nQEP %s\nQF  %s, QF port %s\n"
       "Press ESC to quit...\n",
       QEP::getVersion(),                                       // QEP version
       QF::getVersion(),                                         // QF version
       QF::getPortVersion());                               // QF-port version

Definition at line 44 of file qf_act.cpp.

References active_, QS::aoObj_, QActive::m_prio, Q_REQUIRE, Q_ROM, Q_ROM_VAR, QF_INT_LOCK_, QF_INT_LOCK_KEY_, QF_INT_UNLOCK_, QP_VERSION, QS_BEGIN_NOLOCK_, QS_END_NOLOCK_, QS_OBJ_, QS_QF_ACTIVE_ADD, and QS_U8_.

void QF::init ( void ) [static]

QF initialization.

This function initializes QF and must be called exactly once before any other QF function.

Definition at line 51 of file qvanilla.cpp.

Referenced by QK::getVersion().

QEvent * QF::new_ | ( | uint16_t | evtSize,
 |  | QSignal | sig
 | ) |  | [static]

Internal QF implementation of the dynamic event allocator.

Note:
The application code should not call this function directly. Please use the macro Q_NEW.

Definition at line 38 of file qf_new.cpp.

References QEvent::dynamic_, Q_ASSERT, QF_EPOOL_EVENT_SIZE_, QF_EPOOL_GET_, QF_maxPool_, QF_pool_, QS_BEGIN_, QS_END_, QS_INT_LOCK_KEY_, QS_QF_NEW, QS_SIG_, and QEvent::sig.

static void QF::onCleanup ( void ) [static]

Cleanup QF callback.

QF::onCleanup() is called in some QF ports before QF returns to the underlying operating system or RTOS.

This function is strongly platform-specific and is not implemented in the QF but either in the QF port or in the Board Support Package (BSP) for the given application. Some QF ports might not require implementing QF::onCleanup() at all, because many embedded applications don't have anything to exit to.

See also:
QF::init() and QF::stop()

Referenced by stop().

static void QF::onStartup ( void ) [static]

Startup QF callback.

The timeline for calling QF::onStartup() depends on the particular QF port. In most cases, QF::onStartup() is called from QF::run(), right before starting any multitasking kernel or the background loop.

Referenced by run().

void QF::poolInit | ( | void * | poolSto,
 |  | uint32_t | poolSize,
 |  | QEventSize | evtSize
 | ) |  | [static]

Event pool initialization for dynamic allocation of events.

This function initializes one event pool at a time and must be called exactly once for each event pool before the pool can be used. The arguments are as follows: poolSto is a pointer to the memory block for the events. poolSize is the size of the memory block in bytes. evtSize is the block-size of the pool in bytes, which determines the maximum size of events that can be allocated from the pool.

You might initialize one, two, and up to three event pools by making one, two, or three calls to the QF_poolInit() function. However, for the simplicity of the internal implementation, you must initialize event pools in the ascending order of the event size.

Many RTOSes provide fixed block-size heaps, a.k.a. memory pools that can be used for QF event pools. In case such support is missing, QF provides a native QF event pool implementation. The macro QF_EPOOL_TYPE_ determines the type of event pool used by a particular QF port. See class QMPool for more information.

Note:
The actual number of events available in the pool might be actually less than (poolSize / evtSize) due to the internal alignment of the blocks that the pool might perform. You can always check the capacity of the pool by calling QF::getPoolMargin().
The dynamic allocation of events is optional, meaning that you might choose not to use dynamic events. In that case calling QF::poolInit() and using up memory for the memory blocks is unnecessary.
See also:
QF initialization example for QF::init()

Definition at line 43 of file qf_pool.cpp.

References Q_DIM, Q_REQUIRE, QF_EPOOL_EVENT_SIZE_, QF_EPOOL_INIT_, and QF_maxPool_.

void QF::psInit | ( | QSubscrList * | subscrSto,
 |  | QSignal | maxSignal
 | ) |  | [static]

Publish-subscribe initialization.

This function initializes the publish-subscribe facilities of QF and must be called exactly once before any subscriptions/publications occur in the application. The arguments are as follows: subscrSto is a pointer to the array of subscriber-lists. maxSignal is the dimension of this array and at the same time the maximum signal that can be published or subscribed.

The array of subscriber-lists is indexed by signals and provides mapping between the signals and subscirber-lists. The subscriber- lists are bitmasks of type QSubscrList, each bit in the bitmask corresponding to the unique priority of an active object. The size of the QSubscrList bitmask depends on the value of the QF_MAX_ACTIVE macro.

Note:
The publish-subscribe facilities are optional, meaning that you might choose not to use publish-subscribe. In that case calling QF::psInit() and using up memory for the subscriber-lists is unnecessary.
See also:
QSubscrList

The following example shows the typical initialization sequence of QF:

// allocate storage for active objects, event queues, event pools,
// subscriber lists, and stacks.
static QEvent const *l_tableQueueSto[N_PHILO];
static QEvent const *l_philoQueueSto[N_PHILO][N_PHILO];
static QSubscrList   l_subscrSto[MAX_PUB_SIG];

static union SmallEvents {
    void *min_size;
    TableEvt te;
    // other event types to go into this pool
} l_smlPoolSto[2*N_PHILO];                 // storage for the small event pool

//............................................................................
int main(int argc, char *argv[]) {

    BSP_init(argc, argv);                               // initialize the BSP

    QF::init();       // initialize the framework and the underlying RT kernel

    QF::psInit(l_subscrSto, Q_DIM(l_subscrSto));     // init publish-subscribe

                                                  // initialize event pools...
    QF::poolInit(l_smlPoolSto, sizeof(l_smlPoolSto), sizeof(l_smlPoolSto[0]));

                                                // start the active objects...
    uint8_t n;
    for (n = 0; n < N_PHILO; ++n) {
        AO_Philo[n]->start((uint8_t)(n + 1),
                           l_philoQueueSto[n], Q_DIM(l_philoQueueSto[n]),
                           (void *)0, 0, (QEvent *)0);
    }
    AO_Table->start((uint8_t)(N_PHILO + 1),
                    l_tableQueueSto, Q_DIM(l_tableQueueSto),
                    (void *)0, 0, (QEvent *)0);

    QF::run();                                       // run the QF application

    return 0;
}

Definition at line 40 of file qf_psini.cpp.

References QF_maxSignal_.

void QF::publish ( QEvent const * e ) [static]

Publish event to the framework.

This function posts (using the FIFO policy) the event e it to ALL active object that have subscribed to the signal e->sig. This function is designed to be callable from any part of the system, including ISRs, device drivers, and active objects.

In the general case, event publishing requires multi-casting the event to multiple subscribers. This happens in the caller's thread with the scheduler locked to prevent preemptions during the multi- casting process. (Please note that the interrupts are not locked.)

Definition at line 38 of file qf_pspub.cpp.

References Q_ASSERT, Q_DIM, Q_REQUIRE, Q_ROM_BYTE, QF_INT_LOCK_, QF_INT_LOCK_KEY_, QF_INT_UNLOCK_, QF_invPwr2Lkup, QF_log2Lkup, QF_maxSignal_, QF_subscrList_, QS_BEGIN_NOLOCK_, QS_END_NOLOCK_, QS_QF_PUBLISH, QS_SIG_, and QS_U8_.

void QF::remove_ ( QActive const * a ) [static]

Remove the active object from the framework.

This function should not be called by the application directly, only inside the QF port. The priority level occupied by the active object is freed-up and can be reused for another active object.

The active object that is removed from the framework can no longer participate in the publish-subscribe event exchange.

Note:
This function raises an assertion if the priority of the active object exceeds the maximum value QF_MAX_ACTIVE or is not used.

Definition at line 77 of file qf_act.cpp.

References active_, QS::aoObj_, QActive::m_prio, Q_REQUIRE, QF_INT_LOCK_, QF_INT_LOCK_KEY_, QF_INT_UNLOCK_, QS_BEGIN_NOLOCK_, QS_END_NOLOCK_, QS_OBJ_, QS_QF_ACTIVE_REMOVE, and QS_U8_.

Referenced by QActive::stop().

void QF::run ( void ) [static]

Transfers control to QF to run the application.

QF::run() is typically called from your startup code after you initialize the QF and start at least one active object with QActive::start(). Also, QF::start() call must precede the transfer of control to QF::run(), but some QF ports might call QF::start() from QF::run(). QF::run() typically never returns to the caller.

Note:
This function is strongly platform-dependent and is not implemented in the QF, but either in the QF port or in the Board Support Package (BSP) for the given application. All QF ports must implement QF::run().
When the Quantum Kernel (QK) is used as the underlying real-time kernel for the QF, all platfrom dependencies are handled in the QK, so no porting of QF is necessary. In other words, you only need to recompile the QF platform-independent code with the compiler for your platform, but you don't need to provide any platform-specific implementation (so, no qf_port.cpp file is necessary). Moreover, QK implements the function QF::run() in a platform-independent way, in the modile qk.cpp.

Definition at line 60 of file qvanilla.cpp.

References active_, QPSet64::findMax(), gc(), QActive::get_(), QPSet8::notEmpty(), onStartup(), QF_INT_LOCK_, QF_INT_LOCK_KEY_, and QF_INT_UNLOCK_.

Referenced by QK::getVersion().

void QF::stop ( void ) [static]

Function invoked by the application layer to stop the QF application and return control to the OS/Kernel.

This function stops the QF application. After calling this function, QF attempts to gracefully stop the application. This graceful shutdown might take some time to complete. The typical use of this funcition is for terminating the QF application to return back to the operating system or for handling fatal errors that require shutting down (and possibly re-setting) the system.

This function is strongly platform-specific and is not implemented in the QF but either in the QF port or in the Board Support Package (BSP) for the given application. Some QF ports might not require implementing QF::stop() at all, because many embedded application don't have anything to exit to.

See also:
QF::stop() and QF::onCleanup()

Definition at line 55 of file qvanilla.cpp.

References onCleanup().

Referenced by QK::getVersion().

void QF::tick ( void ) [static]

Processes all armed time events at every clock tick.

This function must be called periodically from a time-tick ISR or from the highest-priority task so that QF can manage the timeout events.

Note:
The QF::tick() function is not reentrant meaning that it must run to completion before it is called again. Also, QF::tick() assumes that it never will get preempted by a task, which is always the case when it is called from an ISR or the highest-priority task.
See also:
QTimeEvt.

The following example illustrates the call to QF::tick():

// case 1: Interrupt Controller available,
// "unconditional interrupt unlocking" critical section policy
// (nesting of critical sections _not_ allowed)
//
interrupt void ISR_timer() {     // entered with interrupts locked in hardware
    QF_INT_UNLOCK(dummy);                                 // unlock interrupts

    QF::tick();                              //<-- call the QF tick processing

    QF_INT_LOCK(dummy);                               // lock interrupts again
    // send the EOI instruction to the Interrupt Controller
}

// case 2: Interrupt Controller not used,
// "saving and restoring interrupt status" critical section policy
// (nesting of critical sections allowed)
//
interrupt void ISR_timer() {
    QF::tick();                              //<-- call the QF tick processing
}

Definition at line 38 of file qf_tick.cpp.

References QActive::postFIFO(), QF_INT_LOCK_, QF_INT_LOCK_KEY_, QF_INT_UNLOCK_, QF_timeEvtListHead_, QS_BEGIN_NOLOCK_, QS_END_NOLOCK_, QS_OBJ_, QS_QF_TICK, QS_QF_TIMEEVT_AUTO_DISARM, QS_QF_TIMEEVT_POST, QS_SIG_, QEvent::sig, QS::teObj_, and QS::tickCtr_.

Member Data Documentation

QActive * QF::active_ [static]

array of registered active objects

Note:
Not to be used by Clients directly, only in ports of QF

Definition at line 904 of file qf.h.

Referenced by getQueueMargin(), getVersion(), remove_(), run(), QActive::subscribe(), QActive::unsubscribe(), and QActive::unsubscribeAll().

The documentation for this class was generated from the following files:
  • qf.h
  • qa_get_.cpp
  • qf_act.cpp
  • qf_gc.cpp
  • qf_new.cpp
  • qf_pool.cpp
  • qf_psini.cpp
  • qf_pspub.cpp
  • qf_tick.cpp
  • qmp_get.cpp
  • qvanilla.cpp
  • qk.cpp
Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: QFreeBlock Struct Reference

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members

QFreeBlock Struct Reference

Structure representing a free block in the Native QF Memory Pool. More...

#include <qf_pkg.h>

List of all members.

Detailed Description

Structure representing a free block in the Native QF Memory Pool.

See also:
QMPool

Definition at line 84 of file qf_pkg.h.

The documentation for this struct was generated from the following file:
  • qf_pkg.h
Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: QFsm Class Reference

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members
Public Member Functions | Protected Member Functions | Protected Attributes

QFsm Class Reference

Finite State Machine base class. More...

#include <qep.h>

List of all members.

Public Member Functions

virtual | ~QFsm ()
virtual destructor
void | init (QEvent const *e=(QEvent *) 0)
Performs the second step of FSM initialization by triggering the top-most initial transition.
void | dispatch (QEvent const *e)
Dispatches an event to a FSM.

Protected Member Functions

QFsm (QStateHandler initial)
Protected constructor of a FSM.

Protected Attributes

QStateHandler m_state
current active state (state-variable)

Detailed Description

Finite State Machine base class.

QFsm represents a traditional non-hierarchical Finite State Machine (FSM) without state hierarchy, but with entry/exit actions.

QFsm is also a base structure for the QHsm class.

Note:
QFsm is not intended to be instantiated directly, but rather serves as the base class for derivation of state machines in the application code.

The following example illustrates how to derive a state machine class from QFsm.

class QBomb : public QFsm {
    uint8_t m_timeout;                     // number of seconds till explosion
    uint8_t m_defuse;                                // the secret defuse code
    uint8_t m_code;                           // the current defuse code entry

public:
    QBomb() : QFsm((QStateHandler)&QBomb::initial) {
    }

protected:
    static QState initial(QBomb *me, QEvent const *e);
    static QState setting(QBomb *me, QEvent const *e);
    static QState timing(QBomb *me, QEvent const *e);
    static QState blast(QBomb *me, QEvent const *e);
};

Definition at line 76 of file qep.h.

Constructor & Destructor Documentation

QFsm::QFsm ( QStateHandler initial ) [inline, protected]

Protected constructor of a FSM.

Performs the first step of FSM initialization by assigning the initial pseudostate to the currently active state of the state machine.

Note:
The constructor is protected to prevent direct instantiating of QFsm objects. This class is intended for subclassing only.
See also:
The QFsm example illustrates how to use the QHsm constructor in the constructor initializer list of the derived state machines.

Definition at line 121 of file qep.h.

Member Function Documentation

void QFsm::dispatch ( QEvent const * e )

Dispatches an event to a FSM.

Processes one event at a time in Run-to-Completion (RTC) fashion. The argument e is a constant pointer the QEvent or a class derived from QEvent.

Note:
Must be called after QFsm::init().
See also:
example for QFsm::init()

Definition at line 35 of file qfsm_dis.cpp.

References m_state, Q_ENTRY_SIG, Q_EXIT_SIG, Q_RET_HANDLED, Q_RET_TRAN, QEP_TRIG_, QS_BEGIN_, QS_END_, QS_FUN_, QS_INT_LOCK_KEY_, QS_OBJ_, QS_QEP_IGNORED, QS_QEP_INTERN_TRAN, QS_QEP_TRAN, QS_SIG_, QEvent::sig, and QS::smObj_.

Referenced by QEP::getVersion().

void QFsm::init ( QEvent const * e = (QEvent *)0 )

Performs the second step of FSM initialization by triggering the top-most initial transition.

The argument e is constant pointer to QEvent or a class derived from QEvent.

Note:
Must be called only ONCE before QFsm::dispatch()

The following example illustrates how to initialize a FSM, and dispatch events to it:

#include "qep.h"                                     // QEP/C public interface
#include "qbomb.h"                              // QBomb FSM derived from QFsm

static QBomb l_qbomb;                              // an instance of QBomb FSM

int main() {
    QBombInitEvt ie;
    ie.defuse = 0x0D;                                           // 1101 binary
    l_qbomb.init(&ie);                           // trigger initial transition

    for (;;) {                                                   // event loop
        QEvent e;
        . . .
        // wait for the next event and assign it to the event object e
        . . .
        l_qbomb.dispatch(&e);                            // dispatch the event
    }
    return 0;
}

Definition at line 41 of file qfsm_ini.cpp.

References m_state, Q_ALLEGE, Q_ENTRY_SIG, Q_RET_TRAN, QEP_TRIG_, QS_BEGIN_, QS_END_, QS_FUN_, QS_INT_LOCK_KEY_, QS_OBJ_, QS_QEP_INIT_TRAN, QS_QEP_STATE_INIT, and QS::smObj_.

Referenced by QEP::getVersion().

The documentation for this class was generated from the following files:
  • qep.h
  • qfsm_dis.cpp
  • qfsm_ini.cpp
Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: QHsm Class Reference

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members
Public Member Functions | Protected Member Functions | Static Protected Member Functions | Protected Attributes

QHsm Class Reference

Hierarchical State Machine base class. More...

#include <qep.h>

List of all members.

Public Member Functions

virtual | ~QHsm ()
virtual destructor
void | init (QEvent const *e=(QEvent *) 0)
Performs the second step of HSM initialization by triggering the top-most initial transition.
void | dispatch (QEvent const *e)
Dispatches an event to a HSM.
uint8_t | isIn (QStateHandler state)
Tests if a given state is part of the current active state configuratioin.

Protected Member Functions

QHsm (QStateHandler initial)
Protected constructor of a HSM.

Static Protected Member Functions

static QState | top (QHsm *me, QEvent const *e)
the top-state.

Protected Attributes

QStateHandler m_state
current active state (state-variable)

Detailed Description

Hierarchical State Machine base class.

QHsm represents a Hierarchical Finite State Machine (HSM). QHsm derives from the QFsm class and extends the capabilities of a basic FSM with state hierarchy.

Note:
QHsm is not intended to be instantiated directly, but rather serves as the base structure for derivation of state machines in the application code.

The following example illustrates how to derive a state machine class from QHsm.

class QCalc : public QHsm {                // Quantum Calculator state machine
private:
    double  m_operand1;
    double  m_operand2;
    char    m_display[DISP_WIDTH + 1];
    uint8_t m_len;
    uint8_t m_opKey;

public:
    QCalc() : QHsm((QStateHandler)&QCalc::initial) {                   // ctor
    }

protected:
    static QState initial  (QCalc *me, QEvent const *e);
    static QState on       (QCalc *me, QEvent const *e);
    static QState error    (QCalc *me, QEvent const *e);
    static QState ready    (QCalc *me, QEvent const *e);
    static QState result   (QCalc *me, QEvent const *e);
    static QState begin    (QCalc *me, QEvent const *e);
    static QState negated1 (QCalc *me, QEvent const *e);
    static QState operand1 (QCalc *me, QEvent const *e);
    static QState zero1    (QCalc *me, QEvent const *e);
    static QState int1     (QCalc *me, QEvent const *e);
    static QState frac1    (QCalc *me, QEvent const *e);
    static QState opEntered(QCalc *me, QEvent const *e);
    static QState negated2 (QCalc *me, QEvent const *e);
    static QState operand2 (QCalc *me, QEvent const *e);
    static QState zero2    (QCalc *me, QEvent const *e);
    static QState int2     (QCalc *me, QEvent const *e);
    static QState frac2    (QCalc *me, QEvent const *e);
};

Definition at line 138 of file qep.h.

Constructor & Destructor Documentation

QHsm::QHsm ( QStateHandler initial ) [inline, protected]

Protected constructor of a HSM.

Performs the first step of HSM initialization by assigning the initial pseudostate to the currently active state of the state machine.

Note:
The constructor is protected to prevent direct instantiating of QHsm objects. This class is intended for subclassing only.
See also:
The QHsm example illustrates how to use the QHsm constructor in the constructor initializer list of the derived state machines.
QFsm::QFsm()

Definition at line 189 of file qep.h.

Member Function Documentation

void QHsm::dispatch ( QEvent const * e )

Dispatches an event to a HSM.

Processes one event at a time in Run-to-Completion (RTC) fashion. The argument e is a constant pointer the QEvent or a class derived from QEvent.

Note:
Must be called after QHsm::init().
See also:
example for QHsm::init()

Definition at line 38 of file qhsm_dis.cpp.

References Q_ASSERT, Q_EXIT_SIG, Q_INIT_SIG, Q_RET_HANDLED, Q_RET_IGNORED, Q_RET_SUPER, Q_RET_TRAN, QEP_EMPTY_SIG_, QEP_ENTER_, QEP_EXIT_, QEP_MAX_NEST_DEPTH_, QEP_TRIG_, QS_BEGIN_, QS_END_, QS_FUN_, QS_INT_LOCK_KEY_, QS_OBJ_, QS_QEP_DISPATCH, QS_QEP_IGNORED, QS_QEP_INTERN_TRAN, QS_QEP_STATE_EXIT, QS_QEP_STATE_INIT, QS_QEP_TRAN, QS_SIG_, and QS::smObj_.

Referenced by QEP::getVersion().

void QHsm::init ( QEvent const * e = (QEvent *)0 )

Performs the second step of HSM initialization by triggering the top-most initial transition.

Parameters:
e constant pointer QEvent or a class derived from QEvent
Note:
Must be called only ONCE before QHsm::dispatch()

The following example illustrates how to initialize a HSM, and dispatch events to it:

#include "qep.h"                                     // QEP/C public interface
#include "qcalc.h"                              // QCalc HSM derived from QHsm

static QCalc l_qcalc;                              // an instance of QCalc HSM

int main() {

    l_qcalc.init();                              // trigger initial transition

    for (;;) {                                                   // event loop
        QEvent e;
        . . .
        // wait for the next event and assign it to the event object e
        . . .
        l_qcalc.dispatch(&e);                            // dispatch the event
    }
    return 0;
}

Definition at line 41 of file qhsm_ini.cpp.

References m_state, Q_ALLEGE, Q_ASSERT, Q_INIT_SIG, Q_RET_TRAN, QEP_EMPTY_SIG_, QEP_ENTER_, QEP_MAX_NEST_DEPTH_, QEP_TRIG_, QS_BEGIN_, QS_END_, QS_FUN_, QS_INT_LOCK_KEY_, QS_OBJ_, QS_QEP_INIT_TRAN, QS_QEP_STATE_INIT, QS::smObj_, and top().

Referenced by QEP::getVersion().

uint8_t QHsm::isIn ( QStateHandler state )

Tests if a given state is part of the current active state configuratioin.

Parameters:
state is a pointer to the state handler function, e.g., &QCalc::on.

Definition at line 35 of file qhsm_in.cpp.

References m_state, Q_RET_IGNORED, QEP_EMPTY_SIG_, and QEP_TRIG_.

Referenced by QEP::getVersion().

QState QHsm::top | ( | QHsm * | me,
 |  | QEvent const * | e
 | ) |  | [static, protected]

the top-state.

QHsm::top() is the ultimate root of state hierarchy in all HSMs derived from QHsm. This state handler always returns (QSTATE)0, which means that it "handles" all events.

See also:
Example of the QCalc::on() state handler.

Definition at line 35 of file qhsm_top.cpp.

References Q_IGNORED.

Referenced by QEP::getVersion(), and init().

The documentation for this class was generated from the following files:
  • qep.h
  • qhsm_dis.cpp
  • qhsm_in.cpp
  • qhsm_ini.cpp
  • qhsm_top.cpp
Generated on Fri Jan 7 2011 21:37:32 for QP/C++ by doxygen 1.7.3


QP/C++: QK Class Reference

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members
Static Public Member Functions

QK Class Reference

QK services. More...

#include <qk.h>

List of all members.

Static Public Member Functions

static char const Q_ROM *Q_ROM_VAR | getVersion (void)
get the current QK version number string
static char const Q_ROM *Q_ROM_VAR | getPortVersion (void)
Returns the QK-port version.
static void | onIdle (void)
QK idle callback (customized in BSPs for QK)
static QMutex | mutexLock (uint8_t prioCeiling)
QK priority-ceiling mutex lock.
static void | mutexUnlock (QMutex mutex)
QK priority-ceiling mutex unlock.

Detailed Description

QK services.

This class groups together QK services. It has only static members and should not be instantiated. to the QK class (as static class members). However, to avoid C++ potential name-mangling problems in assembly language, these elements are defined outside of the QK class and use the extern "C" linkage specification.

Definition at line 195 of file qk.h.

Member Function Documentation

static char const Q_ROM* Q_ROM_VAR QK::getPortVersion ( void ) [static]

Returns the QK-port version.

This function returns constant version string in the format x.y.zz, where x (one digit) is the major version, y (one digit) is the minor version, and zz (two digits) is the maintenance release version. An example of the QK-port version string is "1.1.03".

See also:
QK::getVersion()
char const Q_ROM *Q_ROM_VAR QK::getVersion ( void ) [static]

get the current QK version number string

Returns:
version of the QK as a constant 6-character string of the form x.y.zz, where x is a 1-digit major version number, y is a 1-digit minor version number, and zz is a 2-digit release number.
See also:
QK::getPortVersion()

Definition at line 21 of file lint_qk.txt.

References QS::aoObj_, QF::init(), QPSet8::insert(), QPSet64::insert(), mutexLock(), Q_DEFINE_THIS_MODULE, Q_REQUIRE, QF_INT_KEY_TYPE, QF_MAX_ACTIVE, QK_ceilingPrio_, QK_TLS, QP_VERSION, QS_BEGIN_NOLOCK_, QS_QK_MUTEX_LOCK, QS_QK_MUTEX_UNLOCK, QS_QK_SCHEDULE, QPSet8::remove(), QPSet64::remove(), QF::run(), and QF::stop().

QMutex QK::mutexLock ( uint8_t prioCeiling ) [static]

QK priority-ceiling mutex lock.

Lock the QK scheduler up to the priority level prioCeiling. The code between QK::mutexLock() and QK::mutexUnlock() should be kept to the minimum.

    QMutex mux;
    . . .
    mux = QK::mutexLock(PRIO_CEILING);

    // access the shared resource

    QK::mutexUnlock(mux);

    . . .

Definition at line 44 of file qk_mutex.cpp.

References QK_ceilingPrio_, QS_BEGIN_NOLOCK_, QS_END_NOLOCK_, QS_QK_MUTEX_LOCK, and QS_U8_.

Referenced by getVersion().

void QK::mutexUnlock ( QMutex mutex ) [static]

QK priority-ceiling mutex unlock.

Note:
This function should be always paired with QK::mutexLock(). The code between QK::mutexLock() and QK::mutexUnlock() should be kept to the minimum.
    QMutex mux;
    . . .
    mux = QK::mutexLock(PRIO_CEILING);

    // access the shared resource

    QK::mutexUnlock(mux);

    . . .

Definition at line 62 of file qk_mutex.cpp.

References QK_ceilingPrio_, QS_BEGIN_NOLOCK_, QS_END_NOLOCK_, QS_QK_MUTEX_UNLOCK, and QS_U8_.

static void QK::onIdle ( void ) [static]

QK idle callback (customized in BSPs for QK)

QK::onIdle() is called continously by the QK idle loop. This callback gives the application an opportunity to enter a power-saving CPU mode, or perform some other idle processing.

Note:
QK::onIdle() is invoked with interrupts unlocked and must also return with interrupts unlocked.
See also:
QF::onIdle()
The documentation for this class was generated from the following files:
  • qk.h
  • lint_qk.txt
  • qk.cpp
  • qk_mutex.cpp
Generated on Fri Jan 7 2011 21:37:32 for QP/C++ by doxygen 1.7.3


QP/C++: QMPool Class Reference

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members
Public Member Functions | Friends

QMPool Class Reference

Native QF memory pool class. More...

#include <qmpool.h>

List of all members.

Public Member Functions

void | init (void *poolSto, uint32_t poolSize, QMPoolSize blockSize)
Initializes the native QF event pool.
void * | get (void)
Obtains a memory block from a memory pool.
void | put (void *b)
Returns a memory block back to a memory pool.
QMPoolSize | getBlockSize (void) const
return the fixed block-size of the blocks managed by this pool

Friends

class | QF

Detailed Description

Native QF memory pool class.

This class describes the native QF memory pool, which can be used as the event pool for dynamic event allocation, or as a fast, deterministic fixed block-size heap for any other objects in your application.

The QMPool structure contains only data members for managing a memory pool, but does not contain the pool storage, which must be provided externally during the pool initialization.

The native QF event pool is configured by defining the macro QF_EPOOL_TYPE_ as QEQueue in the specific QF port header file.

Definition at line 98 of file qmpool.h.

Member Function Documentation

void * QMPool::get ( void )

Obtains a memory block from a memory pool.

The only parameter me is a pointer to the QMPool from which the block is requested. The function returns a pointer to the allocated memory block or NULL if no free blocks are available.

A allocated block must be returned to the same pool from which it has been allocated.

This function can be called from any task level or ISR level.

Note:
The memory pool me must be initialized before any events can be requested from it. Also, the QMPool::get() function uses internally a QF critical section, so you should be careful not to call it from within a critical section when nesting of critical section is not supported.
See also:
QMPool::put()

Definition at line 38 of file qmp_get.cpp.

References QS::mpObj_, QF_INT_LOCK_, QF_INT_LOCK_KEY_, QF_INT_UNLOCK_, QS_BEGIN_NOLOCK_, QS_END_NOLOCK_, QS_OBJ_, and QS_QF_MPOOL_GET.

void QMPool::init | ( | void * | poolSto,
 |  | uint32_t | poolSize,
 |  | QMPoolSize | blockSize
 | ) |  |

Initializes the native QF event pool.

The parameters are as follows: poolSto is the pool storage, poolSize is the size of the pool storage in bytes, and blockSize is the block size of this pool.

The caller of this method must make sure that the poolSto pointer is properly aligned. In particular, it must be possible to efficiently store a pointer at the location pointed to by poolSto. Internally, the QMPool::init() function rounds up the block size blockSize so that it can fit an integer number of pointers. This is done to achieve proper alignment of the blocks within the pool.

Note:
Due to the rounding of block size the actual capacity of the pool might be less than (poolSize / blockSize). You can check the capacity of the pool by calling the QF::getPoolMargin() function.

Definition at line 38 of file qmp_init.cpp.

References QS::mpObj_, Q_ASSERT, Q_REQUIRE, QS_BEGIN_, QS_END_, QS_INT_LOCK_KEY_, QS_OBJ_, and QS_QF_MPOOL_INIT.

void QMPool::put ( void * b )

Returns a memory block back to a memory pool.

This function can be called from any task level or ISR level.

Note:
The block must be allocated from the same memory pool to which it is returned. The QMPool::put() function raises an assertion if the returned pointer to the block points outside of the original memory buffer managed by the memory pool. Also, the QMPool::put() function uses internally a QF critical section, so you should be careful not to call it from within a critical section when nesting of critical section is not supported.
See also:
QMPool::get()

Definition at line 38 of file qmp_put.cpp.

References QS::mpObj_, Q_REQUIRE, QF_INT_LOCK_, QF_INT_LOCK_KEY_, QF_INT_UNLOCK_, QS_BEGIN_NOLOCK_, QS_END_NOLOCK_, QS_OBJ_, and QS_QF_MPOOL_PUT.

The documentation for this class was generated from the following files:
  • qmpool.h
  • qmp_get.cpp
  • qmp_init.cpp
  • qmp_put.cpp
Generated on Fri Jan 7 2011 21:37:32 for QP/C++ by doxygen 1.7.3


QP/C++: QPSet64 Class Reference

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members
Public Member Functions

QPSet64 Class Reference

Priority Set of up to 64 elements for building various schedulers, but also useful as a general set of up to 64 elements of any kind. More...

#include <qpset.h>

Inheritance diagram for QPSet64:
QPSet8

List of all members.

Public Member Functions

uint8_t | hasElement (uint8_t n) volatile
the function evaluates to TRUE if the priority set has the element n.
void | insert (uint8_t n) volatile
insert element n into the set, n = 1..64
void | remove (uint8_t n) volatile
remove element n from the set, n = 1..64
uint8_t | findMax (void) volatile
find the maximum element in the set,

Detailed Description

Priority Set of up to 64 elements for building various schedulers, but also useful as a general set of up to 64 elements of any kind.

The priority set represents the set of active objects that are ready to run and need to be considered by scheduling processing. The set is capable of storing up to 64 priority levels.

The priority set allows to build cooperative multitasking schedulers to manage up to 64 tasks. It is also used in the Quantum Kernel (QK) preemptive scheduler.

The inherited 8-bit set is used as the 8-elemtn set of of 8-bit subsets Each bit in the super.bits set represents a subset (8-elements) as follows:
bit 0 in this->m_bits is 1 when subset[0] is not empty
bit 1 in this->m_bits is 1 when subset[1] is not empty
bit 2 in this->m_bits is 1 when subset[2] is not empty
bit 3 in this->m_bits is 1 when subset[3] is not empty
bit 4 in this->m_bits is 1 when subset[4] is not empty
bit 5 in this->m_bits is 1 when subset[5] is not empty
bit 6 in this->m_bits is 1 when subset[6] is not empty
bit 7 in this->m_bits is 1 when subset[7] is not empty

Definition at line 119 of file qpset.h.

Member Function Documentation

uint8_t QPSet64::findMax ( void ) volatile [inline]

find the maximum element in the set,

Note:
returns zero if the set is empty

Reimplemented from QPSet8.

Definition at line 157 of file qpset.h.

References QPSet8::m_bits, Q_ROM_BYTE, and QF_log2Lkup.

Referenced by QF::run().

The documentation for this class was generated from the following file:
  • qpset.h
Generated on Fri Jan 7 2011 21:37:32 for QP/C++ by doxygen 1.7.3


QP/C++: QPSet8 Class Reference

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members
Public Member Functions | Protected Attributes | Friends

QPSet8 Class Reference

Priority Set of up to 8 elements for building various schedulers, but also useful as a general set of up to 8 elements of any kind. More...

#include <qpset.h>

Inheritance diagram for QPSet8:
QPSet64

List of all members.

Public Member Functions

uint8_t | isEmpty (void) volatile
the function evaluates to TRUE if the priority set is empty, which means that no active objects are ready to run.
uint8_t | notEmpty (void) volatile
the function evaluates to TRUE if the priority set has elements, which means that some active objects are ready to run.
uint8_t | hasElement (uint8_t n) volatile
the function evaluates to TRUE if the priority set has the element n.
void | insert (uint8_t n) volatile
insert element n into the set, n = 1..8
void | remove (uint8_t n) volatile
remove element n from the set, n = 1..8
uint8_t | findMax (void) volatile
find the maximum element in the set,

Protected Attributes

uint8_t m_bits
bimask representing elements of the set

Friends

class | QPSet64

Detailed Description

Priority Set of up to 8 elements for building various schedulers, but also useful as a general set of up to 8 elements of any kind.

The priority set represents the set of active objects that are ready to run and need to be considered by scheduling processing. The set is capable of storing up to 8 priority levels.

Definition at line 51 of file qpset.h.

Member Function Documentation

uint8_t QPSet8::findMax ( void ) volatile [inline]

find the maximum element in the set,

Note:
returns zero if the set is empty

Reimplemented in QPSet64.

Definition at line 89 of file qpset.h.

References m_bits, Q_ROM_BYTE, and QF_log2Lkup.

The documentation for this class was generated from the following file:
  • qpset.h
Generated on Fri Jan 7 2011 21:37:32 for QP/C++ by doxygen 1.7.3


QP/C++: QS Class Reference

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members
Static Public Member Functions | Static Public Attributes

QS Class Reference

Quantum Spy logging facilities. More...

#include <qs.h>

List of all members.

Static Public Member Functions

static char const Q_ROM *Q_ROM_VAR | getVersion (void)
Get the current version of QS.
static void | initBuf (uint8_t sto[], uint32_t stoSize)
Initialize the QS data buffer.
static void | filterOn (uint8_t rec)
Turn the global Filter on for a given record type rec.
static void | filterOff (uint8_t rec)
Turn the global Filter off for a given record type rec.
static void | begin (uint8_t rec)
Mark the begin of a QS record rec.
static void | end (void)
Mark the end of a QS record rec.
static void | u8_ (uint8_t d)
output uint8_t data element without format information
static void | u16_ (uint16_t d)
Output uint16_t data element without format information.
static void | u32_ (uint32_t d)
Output uint32_t data element without format information.
static void | str_ (char const *s)
Output zero-terminated ASCII string element without format information.
static void | str_ROM_ (char const Q_ROM *Q_ROM_VAR s)
Output zero-terminated ASCII string element allocated in ROM without format information.
static void | u8 (uint8_t format, uint8_t d)
Output uint8_t data element with format information.
static void | u16 (uint8_t format, uint16_t d)
output uint16_t data element with format information
static void | u32 (uint8_t format, uint32_t d)
Output uint32_t data element with format information.
static void | f32 (uint8_t format, float d)
Output 32-bit floating point data element with format information.
static void | f64 (uint8_t format, double d)
Output 64-bit floating point data element with format information.
static void | str (char const *s)
Output zero-terminated ASCII string element with format information.
static void | str_ROM (char const Q_ROM *Q_ROM_VAR s)
Output zero-terminated ASCII string element allocated in ROM with format information.
static void | mem (uint8_t const *blk, uint8_t size)
Output memory block of up to 255-bytes with format information.
static uint16_t | getByte (void)
Byte-oriented interface to the QS data buffer.
static uint8_t const * | getBlock (uint16_t *pNbytes)
Block-oriented interface to the QS data buffer.
static uint8_t | onStartup (void const *arg)
Callback to startup the QS facility.
static void | onCleanup (void)
Callback to cleanup the QS facility.
static void | onFlush (void)
Callback to flush the QS trace data to the host.
static QSTimeCtr | onGetTime (void)
Callback to obtain a timestamp for a QS record.

Static Public Attributes

static uint8_t | glbFilter_ [32]
global on/off QS filter
static void const * | smObj_
state machine for QEP local filter
static void const * | aoObj_
active object for QF/QK local filter
static void const * | mpObj_
event pool for QF local filter
static void const * | eqObj_
raw queue for QF local filter
static void const * | teObj_
time event for QF local filter
static void const * | apObj_
generic object Application QF local filter
static QSTimeCtr volatile | tickCtr_
tick counter for the QS_QF_TICK record

Detailed Description

Quantum Spy logging facilities.

This class groups together QS services. It has only static members and should not be instantiated.

Definition at line 185 of file qs.h.

Member Function Documentation

void QS::begin ( uint8_t rec ) [static]

Mark the begin of a QS record rec.

This function must be called at the beginning of each QS record. This function should be called indirectly through the macro QS_BEGIN, or QS_BEGIN_NOLOCK, depending if it's called in a normal code or from a critical section.

Definition at line 92 of file qs.cpp.

References QS_chksum_, QS_INSERT_ESC_BYTE, and QS_seq_.

Referenced by getVersion().

void QS::end ( void ) [static]

Mark the end of a QS record rec.

This function must be called at the end of each QS record. This function should be called indirectly through the macro QS_END, or QS_END_NOLOCK, depending if it's called in a normal code or from a critical section.

Definition at line 99 of file qs.cpp.

References QS_end_, QS_FRAME, QS_head_, QS_INSERT_BYTE, QS_INSERT_CHKSUM_BYTE, QS_tail_, and QS_used_.

Referenced by getVersion().

void QS::f32 | ( | uint8_t | format,
 |  | float | d
 | ) |  | [static]

Output 32-bit floating point data element with format information.

Note:
This function is only to be used through macros, never in the client code directly.

Definition at line 35 of file qs_f32.cpp.

References QS_INSERT_ESC_BYTE.

Referenced by getVersion().

void QS::f64 | ( | uint8_t | format,
 |  | double | d
 | ) |  | [static]

Output 64-bit floating point data element with format information.

Note:
This function is only to be used through macros, never in the client code directly.

Definition at line 35 of file qs_f64.cpp.

References QS_INSERT_ESC_BYTE.

Referenced by getVersion().

void QS::filterOff ( uint8_t rec ) [static]

Turn the global Filter off for a given record type rec.

This function sets up the QS filter to disable the record type rec. The argument QS_ALL_RECORDS specifies to suppress all records. This function should be called indirectly through the macro QS_FILTER_OFF.

Note:
Filtering records based on the record-type is only the first layer of filtering. The second layer is based on the object-type. Both filter layers must be enabled for the QS record to be inserted into the QS buffer.
See also:

Definition at line 80 of file qs.cpp.

References glbFilter_, and QS_ALL_RECORDS.

Referenced by getVersion().

void QS::filterOn ( uint8_t rec ) [static]

Turn the global Filter on for a given record type rec.

This function sets up the QS filter to enable the record type rec. The argument QS_ALL_RECORDS specifies to filter-on all records. This function should be called indirectly through the macro QS_FILTER_ON.

Note:
Filtering based on the record-type is only the first layer of filtering. The second layer is based on the object-type. Both filter layers must be enabled for the QS record to be inserted into the QS buffer.
See also:
QS_filterOff(), QS_FILTER_SM_OBJ, QS_FILTER_AO_OBJ, QS_FILTER_MP_OBJ, QS_FILTER_EQ_OBJ, and QS_FILTER_TE_OBJ.

Definition at line 68 of file qs.cpp.

References glbFilter_, and QS_ALL_RECORDS.

Referenced by getVersion().

uint8_t const * QS::getBlock ( uint16_t * pNbytes ) [static]

Block-oriented interface to the QS data buffer.

This function delivers a contiguous block of data from the QS data buffer. The function returns the pointer to the beginning of the block, and writes the number of bytes in the block to the location pointed to by pNbytes. The argument pNbytes is also used as input to provide the maximum size of the data block that the caller can accept.

If no bytes are available in the QS buffer when the function is called, the function returns a NULL pointer and sets the value pointed to by pNbytes to zero.

Note:
Only the NULL return from QS::getBlock() indicates that the QS buffer is empty at the time of the call. The non-NULL return often means that the block is at the end of the buffer and you need to call QS::getBlock() again to obtain the rest of the data that "wrapped around" to the beginning of the QS data buffer.
QS::getBlock() is NOT protected with a critical section.

Definition at line 36 of file qs_blk.cpp.

References QS_end_, QS_ring_, QS_tail_, and QS_used_.

Referenced by getVersion().

uint16_t QS::getByte ( void ) [static]

Byte-oriented interface to the QS data buffer.

This function delivers one byte at a time from the QS data buffer. The function returns the byte in the least-significant 8-bits of the 16-bit return value if the byte is available. If no more data is available at the time, the function returns QS_EOD (End-Of-Data).

Note:
QS::getByte() is NOT protected with a critical section.

Definition at line 35 of file qs_byte.cpp.

References QS_end_, QS_EOD, QS_ring_, QS_tail_, and QS_used_.

Referenced by getVersion().

char const Q_ROM *Q_ROM_VAR QS::getVersion ( void ) [static]

Get the current version of QS.

Returns:
version of the QS as a constant 6-character string of the form x.y.zz, where x is a 1-digit major version number, y is a 1-digit minor version number, and zz is a 2-digit release number.

Definition at line 40 of file lint_qs.txt.

References aoObj_, apObj_, begin(), end(), eqObj_, f32(), f64(), filterOff(), filterOn(), getBlock(), getByte(), glbFilter_, initBuf(), QPSet8::insert(), QPSet64::insert(), mem(), mpObj_, Q_ROM, Q_ROM_VAR, QP_VERSION, QS_INSERT_BYTE, QS_INSERT_CHKSUM_BYTE, QS_INSERT_ESC_BYTE, QS_MEM_T, QS_STR_T, QPSet8::remove(), QPSet64::remove(), smObj_, str(), str_(), str_ROM(), str_ROM_(), teObj_, tickCtr_, u16(), u16_(), u32(), u32_(), u8(), and u8_().

void QS::initBuf | ( | uint8_t | sto[],
 |  | uint32_t | stoSize
 | ) |  | [static]

Initialize the QS data buffer.

This function should be called from QS_init() to provide QS with the data buffer. The first argument sto[] is the address of the memory block, and the second argument stoSize is the size of this block in bytes. Currently the size of the QS buffer cannot exceed 64KB.

QS can work with quite small data buffers, but you will start losing data if the buffer is too small for the bursts of logging activity. The right size of the buffer depends on the data production rate and the data output rate. QS offers flexible filtering to reduce the data production rate.

Note:
If the data output rate cannot keep up with the production rate, QS will start overwriting the older data with newer data. This is consistent with the "last-is-best" QS policy. The record sequence counters and checksums on each record allow to easily detect data loss.

Definition at line 63 of file qs.cpp.

References QS_end_, and QS_ring_.

Referenced by getVersion().

void QS::mem | ( | uint8_t const * | blk,
 |  | uint8_t | size
 | ) |  | [static]

Output memory block of up to 255-bytes with format information.

Note:
This function is only to be used through macros, never in the client code directly.

Definition at line 35 of file qs_mem.cpp.

References QS_chksum_, QS_INSERT_BYTE, QS_INSERT_ESC_BYTE, and QS_MEM_T.

Referenced by getVersion().

static void QS::onCleanup ( void ) [static]

Callback to cleanup the QS facility.

This is a platform-dependent "callback" function invoked through the macro QS_EXIT. You need to implement this function in your application. The main purpose of this function is to close the QS output channel, if necessary.

static void QS::onFlush ( void ) [static]

Callback to flush the QS trace data to the host.

This is a platform-dependent "callback" function to flush the QS trace buffer to the host. The function typically busy-waits until all the data in the buffer is sent to the host. This is acceptable only in the initial transient.

static QSTimeCtr QS::onGetTime ( void ) [static]

Callback to obtain a timestamp for a QS record.

This is a platform-dependent "callback" function invoked from the macro #QS_TIME_ to add the time stamp to the QS record.

Note:
Some of the pre-defined QS records from QP do not output the time stamp. However, ALL user records do output the time stamp.
QS::onGetTime() is called in a critical section and should not unlock interrupts.

The following example shows using a system call to implement QS time stamping:

#ifdef Q_SPY

QSTimeCtr QS::onGetTime(void) {
    return (QSTimeCtr)clock();
}

. . .

#endif // Q_SPY
static uint8_t QS::onStartup ( void const * arg ) [static]

Callback to startup the QS facility.

This is a platform-dependent "callback" function invoked through the macro QS_INIT. You need to implement this function in your application. At a minimum, the function must configure the QS buffer by calling QS::initBuf(). Typically, you will also want to open/ configure the QS output channel, such as a serial port, or a file. The void* argument arg can be used to pass parameter(s) needed to configure the output channel.

The function returns TRUE (1) if the QS initialization was successful, or FALSE (0) if it failed.

The following example illustrates an implementation of QS_onStartup():

#ifdef Q_SPY

uint8_t QS::onStartup(void const *arg) {
    static uint8_t qsBuf[4*1024];                    // buffer for Quantum Spy

    initBuf(qsBuf, sizeof(qsBuf));               // configure the Q-Spy buffer

    // configure UART 0/1 for QSPY output ...
    if (*(char const *)arg == '0') {                             // use UART 0
           // configure UART 0 for QSPY output ...
        . . .
        return (uint8_t)1;                       // UART 0 successfully opened
    }
    else {                                                       // use UART 1
           // configure UART 1 for QSPY output ...
        . . .
        return (uint8_t)1;                       // UART 1 successfully opened
    }
}

. . .

#endif // Q_SPY
void QS::str ( char const * s ) [static]

Output zero-terminated ASCII string element with format information.

Note:
This function is only to be used through macros, never in the client code directly.

Definition at line 36 of file qs_str.cpp.

References QS_chksum_, QS_INSERT_BYTE, and QS_STR_T.

Referenced by getVersion().

void QS::str_ ( char const * s ) [static]

Output zero-terminated ASCII string element without format information.

Note:
This function is only to be used through macros, never in the client code directly.

Definition at line 66 of file qs_.cpp.

References QS_chksum_, and QS_INSERT_BYTE.

Referenced by getVersion().

void QS::str_ROM ( char const Q_ROM *Q_ROM_VAR s ) [static]

Output zero-terminated ASCII string element allocated in ROM with format information.

Note:
This function is only to be used through macros, never in the client code directly.

Definition at line 49 of file qs_str.cpp.

References Q_ROM_BYTE, QS_chksum_, QS_INSERT_BYTE, and QS_STR_T.

Referenced by getVersion().

void QS::str_ROM_ ( char const Q_ROM *Q_ROM_VAR s ) [static]

Output zero-terminated ASCII string element allocated in ROM without format information.

Note:
This function is only to be used through macros, never in the client code directly.

Definition at line 77 of file qs_.cpp.

References Q_ROM_BYTE, QS_chksum_, and QS_INSERT_BYTE.

Referenced by getVersion().

void QS::u16 | ( | uint8_t | format,
 |  | uint16_t | d
 | ) |  | [static]

output uint16_t data element with format information

Note:
This function is only to be used through macros, never in the client code directly.

Definition at line 113 of file qs.cpp.

References QS_INSERT_ESC_BYTE.

Referenced by getVersion().

void QS::u16_ ( uint16_t d ) [static]

Output uint16_t data element without format information.

Note:
This function is only to be used through macros, never in the client code directly.

Definition at line 49 of file qs_.cpp.

References QS_INSERT_ESC_BYTE.

Referenced by getVersion().

void QS::u32 | ( | uint8_t | format,
 |  | uint32_t | d
 | ) |  | [static]

Output uint32_t data element with format information.

Note:
This function is only to be used through macros, never in the client code directly.

Definition at line 120 of file qs.cpp.

References QS_INSERT_ESC_BYTE.

Referenced by getVersion().

void QS::u32_ ( uint32_t d ) [static]

Output uint32_t data element without format information.

Note:
This function is only to be used through macros, never in the client code directly.

Definition at line 55 of file qs_.cpp.

References QS_INSERT_ESC_BYTE.

Referenced by getVersion().

void QS::u8 | ( | uint8_t | format,
 |  | uint8_t | d
 | ) |  | [static]

Output uint8_t data element with format information.

Note:
This function is only to be used through macros, never in the client code directly.

Definition at line 108 of file qs.cpp.

References QS_INSERT_ESC_BYTE.

Referenced by getVersion().

void QS::u8_ ( uint8_t d ) [static]

output uint8_t data element without format information

Note:
This function is only to be used through macros, never in the client code directly.

Definition at line 45 of file qs_.cpp.

References QS_INSERT_ESC_BYTE.

Referenced by getVersion().

The documentation for this class was generated from the following files:
  • qs.h
  • lint_qs.txt
  • qs.cpp
  • qs_.cpp
  • qs_blk.cpp
  • qs_byte.cpp
  • qs_f32.cpp
  • qs_f64.cpp
  • qs_mem.cpp
  • qs_str.cpp
Generated on Fri Jan 7 2011 21:37:32 for QP/C++ by doxygen 1.7.3


QP/C++: QSubscrList Class Reference

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members
Friends

QSubscrList Class Reference

Subscriber List class. More...

#include <qf.h>

List of all members.

Friends

class | QF
class | QActive

Detailed Description

Subscriber List class.

This data type represents a set of active objects that subscribe to a given signal. The set is represented as an array of bits, where each bit corresponds to the unique priority of an active object.

Definition at line 592 of file qf.h.

The documentation for this class was generated from the following file:
  • qf.h
Generated on Fri Jan 7 2011 21:37:32 for QP/C++ by doxygen 1.7.3


QP/C++: QTimeEvt Class Reference

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members
Public Member Functions | Friends

QTimeEvt Class Reference

Time Event class. More...

#include <qf.h>

Inheritance diagram for QTimeEvt:
QEvent

List of all members.

Public Member Functions

QTimeEvt (QSignal s)
The Time Event constructor.
void | postIn (QActive *act, QTimeEvtCtr nTicks)
Arm a one-shot time event for direct event posting.
void | postEvery (QActive *act, QTimeEvtCtr nTicks)
Arm a periodic time event for direct event posting.
uint8_t | disarm (void)
Disarm a time event.
uint8_t | rearm (QTimeEvtCtr nTicks)
Rearm a time event.
void | fireIn (QActive *act, QTimeEvtCtr nTicks)
Arm a one-shot time event for direct event posting (obsolete).
void | fireEvery (QActive *act, QTimeEvtCtr nTicks)
Arm a periodic time event for direct event posting (obsolete).

Friends

class | QF

Detailed Description

Time Event class.

Time events are special QF events equipped with the notion of time passage. The basic usage model of the time events is as follows. An active object allocates one or more QTimeEvt objects (provides the storage for them). When the active object needs to arrange for a timeout, it arms one of its time events to fire either just once (one-shot) or periodically. Each time event times out independently from the others, so a QF application can make multiple parallel timeout requests (from the same or different active objects). When QF detects that the appropriate moment has arrived, it inserts the time event directly into the recipient's event queue. The recipient then processes the time event just like any other event.

Time events, as any other QF events derive from the QEvent base class. Typically, you will use a time event as-is, but you can also further derive more specialized time events from it by adding some more data members and/or specialized functions that operate on the specialized time events.

Internally, the armed time events are organized into a bi-directional linked list. This linked list is scanned in every invocation of the QF::tick() function. Only armed (timing out) time events are in the list, so only armed time events consume CPU cycles.

Note:
QF manages the time events in the function QF::tick(), which must be called periodically, preferably from the clock tick ISR.
In this version of QF QTimeEvt objects should be allocated statically rather than dynamically from event pools. Currently, QF will not correctly recycle the dynamically allocated Time Events.

Definition at line 437 of file qf.h.

Constructor & Destructor Documentation

QTimeEvt::QTimeEvt ( QSignal s )

The Time Event constructor.

The most important initialization performed in the constructor is assigning a signal to the Time Event. You can reuse the Time Event any number of times, but you cannot change the signal. This is because pointers to Time Events might still be held in event queues and changing signal could to hard-to-detect errors.

The following example shows the use of QTimeEvt::QTimeEvt() constructor in the constructor initializer list of the Philosopher active object constructor that owns the time event

class Philosopher : public QActive {
    . . .
public:
    Philosopher::Philosopher()                   // public default constructor
    : QActive((QStateHandler)&Philosopher::initial),
      m_timeEvt(TIMEOUT_SIG)
    {}
    . . .
};

Definition at line 38 of file qte_ctor.cpp.

References Q_REQUIRE, and Q_USER_SIG.

Member Function Documentation

uint8_t QTimeEvt::disarm ( void )

Disarm a time event.

The time event gets disarmed and can be reused. The function returns 1 (TRUE) if the time event was truly disarmed, that is, it was running. The return of 0 (FALSE) means that the time event was not truly disarmed because it was not running. The FALSE return is only possible for one-shot time events that have been automatically disarmed upon expiration. In this case the FALSE return means that the time event has already been posted or published and should be expected in the active object's state machine.

Definition at line 36 of file qte_darm.cpp.

References QF_INT_LOCK_, QF_INT_LOCK_KEY_, QF_INT_UNLOCK_, QF_timeEvtListHead_, QS_BEGIN_NOLOCK_, QS_END_NOLOCK_, QS_OBJ_, QS_QF_TIMEEVT_DISARM, QS_QF_TIMEEVT_DISARM_ATTEMPT, and QS::teObj_.

void QTimeEvt::fireEvery | ( | QActive * | act,
 |  | QTimeEvtCtr | nTicks
 | ) |  | [inline]

Arm a periodic time event for direct event posting (obsolete).

This facility is now obsolete, please use

See also:
QTimeEvt::postEvery().

Definition at line 565 of file qf.h.

References postEvery().

void QTimeEvt::fireIn | ( | QActive * | act,
 |  | QTimeEvtCtr | nTicks
 | ) |  | [inline]

Arm a one-shot time event for direct event posting (obsolete).

This facility is now obsolete, please use

See also:
QTimeEvt::postIn().

Definition at line 558 of file qf.h.

References postIn().

void QTimeEvt::postEvery | ( | QActive * | act,
 |  | QTimeEvtCtr | nTicks
 | ) |  | [inline]

Arm a periodic time event for direct event posting.

Arms a time event to fire every nTicks clock ticks (periodic time event). The time event gets directly posted (using the FIFO policy) into the event queue of the active object act.

After posting, the time event gets automatically re-armed to fire again in the specified nTicks clock ticks.

A periodic time event can be disarmed only by calling the QTimeEvt::disarm() function. After disarming, the time event can be reused for a one-shot or periodic timeout requests.

Note:
An attempt to reuse (arm again) a running periodic time event raises an assertion.

Also, a periodic time event can be re-armed to shorten or extend the current period by calling the QTimeEvt_rearm() function. After adjusting the current period, the periodic time event goes back timing out at the original rate.

Definition at line 518 of file qf.h.

Referenced by fireEvery().

void QTimeEvt::postIn | ( | QActive * | act,
 |  | QTimeEvtCtr | nTicks
 | ) |  | [inline]

Arm a one-shot time event for direct event posting.

Arms a time event to fire in nTicks clock ticks (one-shot time event). The time event gets directly posted (using the FIFO policy) into the event queue of the active object act.

After posting, the time event gets automatically disarmed and can be reused for a one-shot or periodic timeout requests.

A one-shot time event can be disarmed at any time by calling the QTimeEvt::disarm() function. Also, a one-shot time event can be re-armed to fire in a different number of clock ticks by calling the QTimeEvt::rearm() function.

The following example shows how to arm a one-shot time event from a state machine of an active object:

QState Philosopher::eating(Philosopher *me, QEvent const *e) {
    TableEvt *pe;
    switch (e->sig) {
        case Q_ENTRY_SIG: {
            me->timeEvt_.postIn(me, EAT_TIME);      // arm one-shot time event
            return Q_HANDLED();
        }
        case TIMEOUT_SIG: {
            return Q_TRAN(&Philosopher::thinking);
        }
        case Q_EXIT_SIG: {
            busyDelay();
            pe = Q_NEW(TableEvt, DONE_SIG);
            pe->philNum = me->m_num;
            QF::publish(pe);
            return Q_HANDLED();
        }
    }
    return Q_SUPER(&QHsm::top);
}

Definition at line 493 of file qf.h.

Referenced by fireIn().

uint8_t QTimeEvt::rearm ( QTimeEvtCtr nTicks )

Rearm a time event.

The time event gets rearmed with a new number of clock ticks nTicks. This facility can be used to prevent a one-shot time event from expiring (e.g., a watchdog time event), or to adjusts the current period of a periodic time event. Rearming a periodic timer leaves the interval unchanged and is a convenient method to adjust the phasing of the periodic time event.

The function returns 1 (TRUE) if the time event was running as it was re-armed. The return of 0 (FALSE) means that the time event was not truly rearmed because it was not running. The FALSE return is only possible for one-shot time events that have been automatically disarmed upon expiration. In this case the FALSE return means that the time event has already been posted or published and should be expected in the active object's state machine.

Definition at line 38 of file qte_rarm.cpp.

References Q_REQUIRE, Q_USER_SIG, QF_INT_LOCK_, QF_INT_LOCK_KEY_, QF_INT_UNLOCK_, QF_timeEvtListHead_, QS_BEGIN_NOLOCK_, QS_END_NOLOCK_, QS_OBJ_, QS_QF_TIMEEVT_REARM, QS_U8_, and QS::teObj_.

The documentation for this class was generated from the following files:
  • qf.h
  • qte_arm.cpp
  • qte_ctor.cpp
  • qte_darm.cpp
  • qte_rarm.cpp
Generated on Fri Jan 7 2011 21:37:32 for QP/C++ by doxygen 1.7.3


QP/C++: Class Index

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members

Class Index

Q
Q
QEvent QFsm QMPool QS
QActive QF QHsm QPSet64 QSubscrList
QEP QFreeBlock QK QPSet8 QTimeEvt
QEQueue
Q
Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: Class Hierarchy

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members

Class Hierarchy

This inheritance list is sorted roughly, but not completely, alphabetically:
  • QActive
  • QEP
  • QEQueue
  • QEvent
    • QTimeEvt
  • QF
  • QFreeBlock
  • QFsm
  • QHsm
  • QK
  • QMPool
  • QPSet8
    • QPSet64
  • QS
  • QSubscrList
Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: Class Members

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members
  • All
  • Functions
  • Variables
  • a
  • b
  • d
  • e
  • f
  • g
  • h
  • i
  • m
  • n
  • o
  • p
  • q
  • r
  • s
  • t
  • u
  • ~
Here is a list of all documented class members with links to the class documentation for each member:

- a -

  • active_ : QF
  • aoObj_ : QS
  • apObj_ : QS

- b -

  • begin() : QS

- d -

  • defer() : QActive
  • disarm() : QTimeEvt
  • dispatch() : QHsm , QFsm
  • dynamic_ : QEvent

- e -

  • end() : QS
  • eqObj_ : QS

- f -

  • f32() : QS
  • f64() : QS
  • filterOff() : QS
  • filterOn() : QS
  • findMax() : QPSet8 , QPSet64
  • fireEvery() : QTimeEvt
  • fireIn() : QTimeEvt

- g -

  • gc() : QF
  • get() : QEQueue , QMPool
  • get_() : QActive
  • getBlock() : QS
  • getBlockSize() : QMPool
  • getByte() : QS
  • getNFree() : QEQueue
  • getPoolMargin() : QF
  • getPortVersion() : QK , QF
  • getQueueMargin() : QF
  • getVersion() : QS , QF , QK , QEP
  • glbFilter_ : QS

- h -

  • hasElement() : QPSet8 , QPSet64

- i -

  • init() : QFsm , QHsm , QF , QMPool , QEQueue
  • initBuf() : QS
  • insert() : QPSet64 , QPSet8
  • isEmpty() : QPSet8
  • isIn() : QHsm

- m -

  • m_bits : QPSet8
  • m_prio : QActive
  • m_running : QActive
  • m_state : QFsm , QHsm
  • mem() : QS
  • mpObj_ : QS
  • mutexLock() : QK
  • mutexUnlock() : QK

- n -

  • new_() : QF
  • notEmpty() : QPSet8

- o -

  • onCleanup() : QF , QS
  • onFlush() : QS
  • onGetTime() : QS
  • onIdle() : QK
  • onStartup() : QF , QS

- p -

  • poolInit() : QF
  • postEvery() : QTimeEvt
  • postFIFO() : QActive , QEQueue
  • postIn() : QTimeEvt
  • postLIFO() : QActive , QEQueue
  • psInit() : QF
  • publish() : QF
  • put() : QMPool

- q -

  • QActive() : QActive
  • QFsm() : QFsm
  • QHsm() : QHsm
  • QTimeEvt() : QTimeEvt

- r -

  • rearm() : QTimeEvt
  • recall() : QActive
  • remove() : QPSet64 , QPSet8
  • remove_() : QF
  • run() : QActive , QF

- s -

  • sig : QEvent
  • smObj_ : QS
  • start() : QActive
  • stop() : QActive , QF
  • str() : QS
  • str_() : QS
  • str_ROM() : QS
  • str_ROM_() : QS
  • subscribe() : QActive

- t -

  • teObj_ : QS
  • tick() : QF
  • tickCtr_ : QS
  • top() : QHsm

- u -

  • u16() : QS
  • u16_() : QS
  • u32() : QS
  • u32_() : QS
  • u8() : QS
  • u8_() : QS
  • unsubscribe() : QActive
  • unsubscribeAll() : QActive

- ~ -

  • ~QFsm() : QFsm
  • ~QHsm() : QHsm
Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: File List

  • File List
  • File Members

File List

Here is a list of all documented files with brief descriptions:
qa_defer.cpp [code] | QActive::defer() and QActive::recall() implementation
qa_fifo.cpp [code] | QActive::postFIFO() implementation
qa_get_.cpp [code] | QActive::get_() and QF::getQueueMargin() definitions
qa_lifo.cpp [code] | QActive::postLIFO() implementation
qa_run.cpp [code] | QActive::run() implementation
qa_sub.cpp [code] | QActive::subscribe() implementation
qa_usub.cpp [code] | QActive::unsubscribe() implementation
qa_usuba.cpp [code] | QActive::unsubscribeAll() implementation
qassert.h [code] | Customizable QP assertions
qep.cpp [code] | QEP_reservedEvt_ definition and QEP::getVersion() implementation
qep.h [code] | QEP/C++ platform-independent public interface
qep_pkg.h [code] | Internal (package scope) QEP/C++ interface
qep_port.h [code] | QEP/C port to QK for a "generic" C compiler
qeq_fifo.cpp [code] | QEQueue::postFIFO() implementation
qeq_get.cpp [code] | QEQueue::get() implementation
qeq_init.cpp [code] | QEQueue::init() implementation
qeq_lifo.cpp [code] | QEQueue::postLIFO() implementation
qequeue.h [code] | Platform-independent event queue interface
qevent.h [code] | QEvent class and basic macros used by all QP components
qf.h [code] | QF/C++ platform-independent public interface
qf_act.cpp [code] | QF::active_[], QF::getVersion(), and QF::add_()/QF::remove_() implementation
qf_gc.cpp [code] | QF::gc() implementation
qf_log2.cpp [code] | QF_log2Lkup[] implementation
qf_new.cpp [code] | QF::new_() implementation
qf_pkg.h [code] | Internal (package scope) QF/C++ interface
qf_pool.cpp [code] | QF_pool_[] and QF_maxPool_ definition, QF::poolInit() implementation
qf_port.h [code] | QF port to QK for a "generic" C++ compiler
qf_psini.cpp [code] | QF_subscrList_ and QF_maxSignal_ definition, QF::psInit() implementation
qf_pspub.cpp [code] | QF::publish() implementation
qf_pwr2.cpp [code] | QF_pwr2Lkup[], QF_invPwr2Lkup[], and QF_div8Lkup[] definitions
qf_tick.cpp [code] | QF::tick() implementation
qfsm_dis.cpp [code] | QFsm::dispatch() implementation
qfsm_ini.cpp [code] | QFsm::init() implementation
qhsm_dis.cpp [code] | QHsm::dispatch() implementation
qhsm_in.cpp [code] | QHsm::isIn() implementation
qhsm_ini.cpp [code] | QHsm::init() implementation
qhsm_top.cpp [code] | QHsm::top() implementation
qk.cpp [code] | QK_readySet_, QK_currPrio_, and QK_intNest_ definitions and QK::getVersion(), QF::init(), QF::run(), QF::stop(), QActive::start(), QActive::stop() implementations
qk.h [code] | QK/C++ platform-independent public interface
qk_ext.cpp [code] | QK_scheduleExt_() implementation
qk_mutex.cpp [code] | QK::mutexLock()/QK::mutexUnlock() implementation
qk_pkg.h [code] | Internal (package scope) QK/C interface
qk_port.h [code] | QK/C++ port to QK for a "generic" C++ compiler
qk_sched.cpp [code] | QK_schedule_() implementation
qmp_get.cpp [code] | QMPool::get() and QF::getPoolMargin() implementation
qmp_init.cpp [code] | QMPool::init() implementation
qmp_put.cpp [code] | QMPool::put() implementation
qmpool.h [code] | Platform-independent memory pool interface
qp_port.h [code] |
qpset.h [code] | Platform-independent priority sets of 8 or 64 elements
qs.cpp [code] | QS internal variables definitions and core QS functions implementations
qs.h [code] | QS/C++ platform-independent public interface. This header file must be included directly or indirectly in all modules (*.cpp files) that use QS/C++
qs_.cpp [code] | QS functions for internal use inside QP components
qs_blk.cpp [code] | QS::getBlock() implementation
qs_byte.cpp [code] | QS::getByte() implementation
qs_dummy.h [code] | Dummy definitions of the QS macros that avoid code generation from the QS instrumentation
qs_f32.cpp [code] | QS::f32() implementation
qs_f64.cpp [code] | QS::f64() implementation
qs_mem.cpp [code] | QS::mem() implementation
qs_pkg.h [code] | Internal (package scope) QS/C++ interface
qs_port.h [code] | QS/C++ port for a "generic" C++ compiler
qs_str.cpp [code] | QS::str() and QS::str_ROM() implementation
qte_arm.cpp [code] | QF_timeEvtListHead_ definition and QTimeEvt::arm_() implementation
qte_ctor.cpp [code] | QTimeEvt::QTimeEvt() implementation
qte_darm.cpp [code] | QTimeEvt::disarm() implementation
qte_rarm.cpp [code] | QTimeEvt::rearm() implementation
qvanilla.cpp [code] | "vanilla" cooperative kernel, QActive::start(), QActive::stop(), and QF::run() implementation
qvanilla.h [code] | Platform-independent interface to the cooperative "vanilla" kernel
Generated on Fri Jan 7 2011 21:37:32 for QP/C++ by doxygen 1.7.3


QP/C++: qa_defer.cpp File Reference

  • File Members

qa_defer.cpp File Reference

QActive::defer() and QActive::recall() implementation. More...

#include "qf_pkg.h"
#include "qassert.h"

Go to the source code of this file.

Detailed Description

QActive::defer() and QActive::recall() implementation.

Definition in file qa_defer.cpp.


QP/C++: qa_fifo.cpp File Reference

qa_fifo.cpp File Reference

QActive::postFIFO() implementation. More...

#include "qf_pkg.h"
#include "qassert.h"

Go to the source code of this file.

Detailed Description

QActive::postFIFO() implementation.

Note:
this source file is only included in the QF library when the native QF active object queue is used (instead of a message queue of an RTOS).

Definition in file qa_fifo.cpp.


QP/C++: qa_get_.cpp File Reference

qa_get_.cpp File Reference

QActive::get_() and QF::getQueueMargin() definitions. More...

#include "qf_pkg.h"
#include "qassert.h"

Go to the source code of this file.

Detailed Description

QActive::get_() and QF::getQueueMargin() definitions.

Note:
this source file is only included in the QF library when the native QF active object queue is used (instead of a message queue of an RTOS).

Definition in file qa_get_.cpp.


QP/C++: qa_lifo.cpp File Reference

qa_lifo.cpp File Reference

QActive::postLIFO() implementation. More...

#include "qf_pkg.h"
#include "qassert.h"

Go to the source code of this file.

Detailed Description

QActive::postLIFO() implementation.

Note:
this source file is only included in the QF library when the native QF active object queue is used (instead of a message queue of an RTOS).

Definition in file qa_lifo.cpp.


QP/C++: qa_run.cpp File Reference

qa_run.cpp File Reference

QActive::run() implementation. More...

#include "qf_pkg.h"

Go to the source code of this file.

Detailed Description

QActive::run() implementation.

Definition in file qa_run.cpp.


QP/C++: qa_sub.cpp File Reference

qa_sub.cpp File Reference

QActive::subscribe() implementation. More...

#include "qf_pkg.h"
#include "qassert.h"

Go to the source code of this file.

Detailed Description

QActive::subscribe() implementation.

Definition in file qa_sub.cpp.


QP/C++: qa_usub.cpp File Reference

qa_usub.cpp File Reference

QActive::unsubscribe() implementation. More...

#include "qf_pkg.h"
#include "qassert.h"

Go to the source code of this file.

Detailed Description

QActive::unsubscribe() implementation.

Definition in file qa_usub.cpp.


QP/C++: qa_usuba.cpp File Reference

qa_usuba.cpp File Reference

QActive::unsubscribeAll() implementation. More...

#include "qf_pkg.h"
#include "qassert.h"

Go to the source code of this file.

Detailed Description

QActive::unsubscribeAll() implementation.

Definition in file qa_usuba.cpp.


QP/C++: qassert.h File Reference

Defines | Functions

qassert.h File Reference

Customizable QP assertions. More...

Go to the source code of this file.

Defines

#define | Q_DEFINE_THIS_FILE static char const Q_ROM Q_ROM_VAR l_this_file[] = __FILE__;
#define | Q_DEFINE_THIS_MODULE(name_) static char const Q_ROM Q_ROM_VAR l_this_file[] = #name_;
#define | Q_ASSERT(test_)
#define | Q_ALLEGE(test_) Q_ASSERT(test_)
#define | Q_ERROR() (Q_onAssert(l_this_file, __LINE__))
#define | Q_REQUIRE(test_) Q_ASSERT(test_)
#define | Q_ENSURE(test_) Q_ASSERT(test_)
#define | Q_INVARIANT(test_) Q_ASSERT(test_)
#define | Q_ASSERT_COMPILE(test_) extern char Q_assert_compile[(test_) ? 1 : -1]

Functions

void | Q_onAssert (char const Q_ROM *const Q_ROM_VAR file, int line)

Detailed Description

Customizable QP assertions.

Defines customizable and memory-efficient assertions applicable to embedded systems. This header file can be used in C, C++, and mixed C/C++ programs.

Note:
The preprocessor switch Q_NASSERT disables checking assertions. In particular macros Q_ASSERT, Q_REQUIRE, Q_ENSURE, Q_INVARIANT, and Q_ERROR do NOT evaluate the test condition passed as the argument to these macros. One notable exception is the macro Q_ALLEGE, that still evaluates the test condition, but does not report assertion failures when the switch Q_NASSERT is defined.

Definition in file qassert.h.

Define Documentation

#define Q_ALLEGE ( test_ ) Q_ASSERT(test_)

General purpose assertion that ALWAYS evaluates the test_ argument and calls the Q_onAssert() callback if the test_ evaluates to FALSE.

Note:
the test_ argument IS always evaluated even when assertions are disabled with the Q_NASSERT macro. When the Q_NASSERT macro is defined, the Q_onAssert() callback is NOT called, even if the test_ evaluates to FALSE.

Definition at line 108 of file qassert.h.

Referenced by QEP::getVersion(), QHsm::init(), and QFsm::init().

#define Q_ASSERT ( test_ )
Value:
if (test_) { \
        } \
        else (Q_onAssert(l_this_file, __LINE__))

General purpose assertion that makes sure the test_ argument is TRUE. Calls the Q_onAssert() callback if the test_ evaluates to FALSE.

Note:
the test_ is NOT evaluated if assertions are disabled with the Q_NASSERT switch.

Definition at line 95 of file qassert.h.

Referenced by QHsm::dispatch(), QF::gc(), QEP::getVersion(), QMPool::init(), QHsm::init(), QF::new_(), QEQueue::postFIFO(), QActive::postFIFO(), QEQueue::postLIFO(), QActive::postLIFO(), QF::publish(), and QActive::recall().

#define Q_ASSERT_COMPILE ( test_ ) extern char Q_assert_compile[(test_) ? 1 : -1]

Compile-time assertion exploits the fact that in C/C++ a dimension of an array cannot be negative. The following declaration causes a compilation error if the compile-time expression (test_) is not TRUE. The assertion has no runtime side effects.

Definition at line 142 of file qassert.h.

#define Q_DEFINE_THIS_FILE static char const Q_ROM Q_ROM_VAR l_this_file[] = __FILE__;

Place this macro at the top of each C/C++ module to define the file name string using __FILE__ (NOTE: __FILE__ might contain lengthy path name). This file name will be used in reporting assertions in this file.

Definition at line 79 of file qassert.h.

#define Q_DEFINE_THIS_MODULE ( name_ ) static char const Q_ROM Q_ROM_VAR l_this_file[] = #name_;

Place this macro at the top of each C/C++ module to define the module name as the argument name_. This file name will be used in reporting assertions in this file.

Definition at line 86 of file qassert.h.

Referenced by QK::getVersion(), and QEP::getVersion().

#define Q_ENSURE ( test_ ) Q_ASSERT(test_)

Assertion that checks for a postcondition. This macro is equivalent to Q_ASSERT, except the name provides a better documentation of the intention of this assertion.

Definition at line 129 of file qassert.h.

#define Q_ERROR ( ) (Q_onAssert(l_this_file, __LINE__))

Assertion that always calls the Q_onAssert() callback if ever executed.

Note:
can be disabled with the Q_NASSERT switch.

Definition at line 114 of file qassert.h.

#define Q_INVARIANT ( test_ ) Q_ASSERT(test_)

Assertion that checks for an invariant. This macro is equivalent to Q_ASSERT, except the name provides a better documentation of the intention of this assertion.

Definition at line 135 of file qassert.h.

#define Q_REQUIRE ( test_ ) Q_ASSERT(test_)

Assertion that checks for a precondition. This macro is equivalent to Q_ASSERT, except the name provides a better documentation of the intention of this assertion.

Definition at line 123 of file qassert.h.

Referenced by QF::getPoolMargin(), QF::getQueueMargin(), QF::getVersion(), QK::getVersion(), QMPool::init(), QF::poolInit(), QF::publish(), QMPool::put(), QTimeEvt::QTimeEvt(), QTimeEvt::rearm(), QF::remove_(), QActive::start(), QActive::subscribe(), QActive::unsubscribe(), and QActive::unsubscribeAll().

Function Documentation

void Q_onAssert | ( | char const Q_ROM *const Q_ROM_VAR | file,
 |  | int | line
 | ) |  |

callback invoked in case the condition passed to Q_ASSERT, Q_REQUIRE, Q_ENSURE, Q_ERROR, or Q_ALLEGE evaluates to FALSE.

Parameters:
file | file name where the assertion failed
line | line number at which the assertion failed


QP/C++: qep.cpp File Reference

Variables

qep.cpp File Reference

QEP_reservedEvt_ definition and QEP::getVersion() implementation. More...

#include "qep_pkg.h"

Go to the source code of this file.

Variables

QEvent const QEP_reservedEvt_ []
preallocated reserved events

Detailed Description

QEP_reservedEvt_ definition and QEP::getVersion() implementation.

Definition in file qep.cpp.


QP/C++: qep.h File Reference

Classes | Defines | Typedefs | Enumerations

qep.h File Reference

QEP/C++ platform-independent public interface. More...

#include "qevent.h"
#include "qs_port.h"
#include "qs_port.h"

Go to the source code of this file.

Classes

class | QEP
Provides miscellaneous QEP services. More...
class | QFsm
Finite State Machine base class. More...
class | QHsm
Hierarchical State Machine base class. More...

Defines

#define | Q_RET_IGNORED ((QState)1)
Value returned by a non-hierarchical state-handler function when it ignores (does not handle) the event.
#define | Q_IGNORED() (Q_RET_IGNORED)
The macro returned from a non-hierarchical state-handler function when it ignores (does not handle) the event.
#define | Q_RET_HANDLED ((QState)0)
Value returned by a state-handler function when it handles the event.
#define | Q_HANDLED() (Q_RET_HANDLED)
Value returned by a state-handler function when it handles the event.
#define | Q_RET_TRAN ((QState)2)
Value returned by a state-handler function when it takes a regular state transition.
#define | Q_TRAN(target_) (me->m_state = (QStateHandler)(target_), Q_RET_TRAN)
Designates a target for an initial or regular transition. Q_TRAN() can be used both in the FSMs and HSMs.
#define | Q_RET_SUPER ((QState)3)
Value returned by a state-handler function when it cannot handle the event.
#define | Q_SUPER(super_) (me->m_state = (QStateHandler)(super_), Q_RET_SUPER)
Designates the superstate of a given state in an HSM.
#define | QS_SIG_(sig_) QS::u8_(sig_)
Internal QS macro to output an unformatted event signal data element.

Typedefs

typedef uint8_t | QState
Type returned from a state-handler function.
typedef QState(* | QStateHandler )(void *me, QEvent const *e)
pointer to state-handler function

Enumerations

enum | QReservedSignals { Q_ENTRY_SIG = 1, Q_EXIT_SIG, Q_INIT_SIG, Q_USER_SIG }

QEP reserved signals.

More...

Detailed Description

QEP/C++ platform-independent public interface.

This header file must be included directly or indirectly in all modules (*.cpp files) that use QEP/C++.

Definition in file qep.h.

Define Documentation

#define Q_HANDLED ( ) (Q_RET_HANDLED)

Value returned by a state-handler function when it handles the event.

You call that macro after the return statement (return Q_HANDLED();) Q_HANDLED() can be used both in the FSMs and HSMs.

Definition at line 224 of file qep.h.

          #define Q_IGNORED
          (
           )
             (Q_RET_IGNORED)

The macro returned from a non-hierarchical state-handler function when it ignores (does not handle) the event.

You call that macro after the return statement (return Q_IGNORED();)

Definition at line 211 of file qep.h.

Referenced by QHsm::top().

          #define Q_SUPER
          (

          super_ )
             (me->m_state = (QStateHandler)(super_),  Q_RET_SUPER)

Designates the superstate of a given state in an HSM.

Definition at line 246 of file qep.h.

          #define Q_TRAN
          (

          target_ )
             (me->m_state = (QStateHandler)(target_), Q_RET_TRAN)

Designates a target for an initial or regular transition. Q_TRAN() can be used both in the FSMs and HSMs.

Definition at line 235 of file qep.h.

          #define QS_SIG_
          (

          sig_ )
             QS::u8_(sig_)

Internal QS macro to output an unformatted event signal data element.

Note:
the size of the pointer depends on the macro Q_SIGNAL_SIZE.

Definition at line 271 of file qep.h.

Referenced by QHsm::dispatch(), QFsm::dispatch(), QF::gc(), QEQueue::get(), QActive::get_(), QEP::getVersion(), QF::new_(), QEQueue::postFIFO(), QActive::postFIFO(), QEQueue::postLIFO(), QActive::postLIFO(), QF::publish(), QActive::subscribe(), QF::tick(), QActive::unsubscribe(), and QActive::unsubscribeAll().

Enumeration Type Documentation

          enum QReservedSignals

QEP reserved signals.

Enumerator:

Q_ENTRY_SIG

signal for entry actions

Q_EXIT_SIG

signal for exit actions

Q_INIT_SIG

signal for nested initial transitions

Q_USER_SIG

signal to offset user signals

Definition at line 252 of file qep.h.

Generated on Fri Jan 7 2011 21:37:30 for QP/C++ by

  doxygen  1.7.3


QP/C++: qep_pkg.h File Reference

Defines | Enumerations | Variables

qep_pkg.h File Reference

Internal (package scope) QEP/C++ interface. More...

#include "qep_port.h"

Go to the source code of this file.

Defines

#define | QEP_TRIG_(state_, sig_) ((*(state_))(this, &QEP_reservedEvt_[sig_]))
helper macro to trigger internal event in an HSM
#define | QEP_EXIT_(state_)
helper macro to trigger entry action in an HSM
#define | QEP_ENTER_(state_)
helper macro to trigger exit action in an HSM

Enumerations

enum | QEPConst { QEP_EMPTY_SIG_ = 0, QEP_MAX_NEST_DEPTH_ = 6 }

internal QEP constants

More...

Variables

QEvent const | QEP_reservedEvt_ []
preallocated reserved events

Detailed Description

Internal (package scope) QEP/C++ interface.

Definition in file qep_pkg.h.

Enumeration Type Documentation

enum QEPConst

internal QEP constants

Enumerator:
QEP_EMPTY_SIG_

empty signal for internal use only

QEP_MAX_NEST_DEPTH_

maximum depth of state nesting (including the top level), must be >= 3

Definition at line 40 of file qep_pkg.h.


QP/C++: qep_port.h File Reference

Defines | Typedefs

qep_port.h File Reference

QEP/C port to QK for a "generic" C compiler. More...

#include "qep.h"

Go to the source code of this file.

Defines

#define | QEP_SIGNAL_SIZE 1
The size (in bytes) of the signal of an event. Valid values: 1, 2, or 4; default 1.

Typedefs

typedef signed char | int8_t
C99 exact-width 8-bit signed int.
typedef signed short | int16_t
C99 exact-width 16-bit signed int.
typedef signed long | int32_t
C99 exact-width 32-bit signed int.
typedef unsigned char | uint8_t
C99 exact-width 8-bit unsigned int.
typedef unsigned short | uint16_t
C99 exact-width 16-bit unsigned int.
typedef unsigned long | uint32_t
C99 exact-width 32-bit unsigned int.

Detailed Description

QEP/C port to QK for a "generic" C compiler.

Note:
This is just an example of a QEP port used for "linting" the QEP. Ports of QEP are located in the directory <qpc_3>/ports.

Definition in file qep_port.h.

Define Documentation

#define QEP_SIGNAL_SIZE 1

The size (in bytes) of the signal of an event. Valid values: 1, 2, or 4; default 1.

This macro can be defined in the QEP ports to configure the QSignal type. If the macro is not defined, the default of 1 byte will be chosen in qep.h. The valid QEP_SIGNAL_SIZE values of 1, 2, or 4, correspond to QSignal of uint8_t, uint16_t, and uint32_t, respectively. The ::QSingal data type determines the dynamic range of numberical values of signals you your application.

See also:
QEvent
Note:
Once you choose a certain value of QEP_SIGNAL_SIZE, you must consistently use the same value in building all the QP component libraries and your own application code. The consistency is guaranteed if you define this macro only once in the qep_port.h header file and henceforth include this header file in all builds.

Definition at line 54 of file qep_port.h.


QP/C++: qeq_fifo.cpp File Reference

qeq_fifo.cpp File Reference

QEQueue::postFIFO() implementation. More...

#include "qf_pkg.h"
#include "qassert.h"

Go to the source code of this file.

Detailed Description

QEQueue::postFIFO() implementation.

Definition in file qeq_fifo.cpp.


QP/C++: qeq_get.cpp File Reference

qeq_get.cpp File Reference

QEQueue::get() implementation. More...

#include "qf_pkg.h"

Go to the source code of this file.

Detailed Description

QEQueue::get() implementation.

Definition in file qeq_get.cpp.


QP/C++: qeq_init.cpp File Reference

qeq_init.cpp File Reference

QEQueue::init() implementation. More...

#include "qf_pkg.h"

Go to the source code of this file.

Detailed Description

QEQueue::init() implementation.

Definition in file qeq_init.cpp.


QP/C++: qeq_lifo.cpp File Reference

qeq_lifo.cpp File Reference

QEQueue::postLIFO() implementation. More...

#include "qf_pkg.h"
#include "qassert.h"

Go to the source code of this file.

Detailed Description

QEQueue::postLIFO() implementation.

Definition in file qeq_lifo.cpp.


QP/C++: qequeue.h File Reference

Classes | Defines

qequeue.h File Reference

platform-independent event queue interface. More...

Go to the source code of this file.

Classes

class | QEQueue
Native QF Event Queue class. More...

Defines

#define | QF_EQUEUE_CTR_SIZE 1
The size (in bytes) of the ring-buffer counters used in the native QF event queue implementation. Valid values: 1, 2, or 4; default 1.

Detailed Description

platform-independent event queue interface.

This header file must be included in all QF ports that use native QF event queue implementation. Also, this file is needed when the "raw" thread-safe queues are used for communication between active objects and non-framework entities, such as ISRs, device drivers, or legacy code.

Definition in file qequeue.h.

Define Documentation

#define QF_EQUEUE_CTR_SIZE 1

The size (in bytes) of the ring-buffer counters used in the native QF event queue implementation. Valid values: 1, 2, or 4; default 1.

This macro can be defined in the QF port file (qf_port.h) to configure the ::QEQueueCtr type. Here the macro is not defined so the default of 1 byte is chosen.

Definition at line 50 of file qequeue.h.


QP/C++: qevent.h File Reference

Classes | Defines | Typedefs

qevent.h File Reference

QEvent class and basic macros used by all QP components. More...

Go to the source code of this file.

Classes

struct | QEvent
QEvent base class. More...

Defines

#define | QP_VERSION 0x4106
The current QP version number.
#define | Q_ROM
Macro to specify compiler-specific directive for placing a constant object in ROM.
#define | Q_ROM_VAR
Macro to specify compiler-specific directive for accessing a constant object in ROM.
#define | Q_ROM_BYTE(rom_var_) (rom_var_)
Macro to access a byte allocated in ROM.
#define | Q_SIGNAL_SIZE 1
The size (in bytes) of the signal of an event. Valid values: 1, 2, or 4; default 1.
#define | Q_DIM(array_) (sizeof(array_) / sizeof(array_[0]))

Typedefs

typedef uint8_t | QSignal
QSignal represents the signal of an event.

Detailed Description

QEvent class and basic macros used by all QP components.

This header file must be included, perhaps indirectly, in all modules (*.cpp files) that use any component of QP/C++ (such as QEP, QF, or QK).

Definition in file qevent.h.

Define Documentation

#define Q_DIM ( array_ ) (sizeof(array_) / sizeof(array_[0]))

helper macro to calculate static dimension of a 1-dim array array_

Definition at line 146 of file qevent.h.

Referenced by QF::poolInit(), and QF::publish().

#define Q_ROM

Macro to specify compiler-specific directive for placing a constant object in ROM.

Many compilers for Harvard-architecture MCUs provide non-stanard extensions to support placement of objects in different memories. In order to conserve the precious RAM, QP uses the Q_ROM macro for all constant objects that can be allocated in ROM.

To override the following empty definition, you need to define the Q_ROM macro in the qep_port.h header file. Some examples of valid Q_ROM macro definitions are: __code (IAR 8051 compiler), code (Keil Cx51 compiler), PROGMEM (gcc for AVR), __flash (IAR for AVR).

Definition at line 59 of file qevent.h.

Referenced by QF::getPortVersion(), QF::getVersion(), and QS::getVersion().

#define Q_ROM_BYTE ( rom_var_ ) (rom_var_)

Macro to access a byte allocated in ROM.

Some compilers for Harvard-architecture MCUs, such as gcc for AVR, do not generate correct code for accessing data allocated in the program space (ROM). The workaround for such compilers is to explictly add assembly code to access each data element allocated in the program space. The macro Q_ROM_BYTE() retrieves a byte from the given ROM address.

The Q_ROM_BYTE() macro should be defined for the compilers that cannot handle correctly data allocated in ROM (such as the gcc). If the macro is left undefined, the default definition simply returns the argument and lets the compiler generate the correct code.

Definition at line 91 of file qevent.h.

Referenced by QPSet64::findMax(), QPSet8::findMax(), QPSet64::hasElement(), QPSet8::hasElement(), QPSet64::insert(), QPSet8::insert(), QF::publish(), QPSet64::remove(), QPSet8::remove(), QS::str_ROM(), QS::str_ROM_(), QActive::subscribe(), QActive::unsubscribe(), and QActive::unsubscribeAll().

#define Q_ROM_VAR

Macro to specify compiler-specific directive for accessing a constant object in ROM.

Many compilers for MCUs provide different size pointers for accessing objects in various memories. Constant objects allocated in ROM (see Q_ROM macro) 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.

To override the following empty definition, you need to define the Q_ROM_VAR macro in the qep_port.h header file. An example of valid Q_ROM_VAR macro definition is: __far (Freescale HC(S)08 compiler).

Definition at line 75 of file qevent.h.

Referenced by QF::getVersion(), and QS::getVersion().

#define Q_SIGNAL_SIZE 1

The size (in bytes) of the signal of an event. Valid values: 1, 2, or 4; default 1.

This macro can be defined in the QEP port file (qep_port.h) to configure the QSignal type. When the macro is not defined, the default of 1 byte is chosen.

Definition at line 101 of file qevent.h.

#define QP_VERSION 0x4106

The current QP version number.

Returns:
version of the QP as a hex constant constant 0xXYZZ, where X is a 1-digit major version number, Y is a 1-digit minor version number, and ZZ is a 2-digit release number.

Definition at line 44 of file qevent.h.

Referenced by QF::getVersion(), QS::getVersion(), QK::getVersion(), and QEP::getVersion().

Typedef Documentation

typedef uint8_t QSignal

QSignal represents the signal of an event.

The relationship between an event and a signal is as follows. A signal in UML is the specification of an asynchronous stimulus that triggers reactions [UML document ptc/03-08-02], and as such is an essential part of an event. (The signal conveys the type of the occurrence-what happened?) However, an event can also contain additional quantitative information about the occurrence in form of event parameters. Please refer to the document Brief Introduction to UML State Machines) for more information about state machine concepts.

Definition at line 117 of file qevent.h.


QP/C++: qf.h File Reference

Classes | Defines | Variables

qf.h File Reference

QF/C++ platform-independent public interface. More...

#include "qs_port.h"

Go to the source code of this file.

Classes

class | QActive
Base class for derivation of application-level active object classes. More...
class | QTimeEvt
Time Event class. More...
class | QSubscrList
Subscriber List class. More...
class | QF
QF services. More...

Defines

#define | QF_EVENT_SIZ_SIZE 2
Default value of the macro configurable value in qf_port.h.
#define | QF_ACTIVE_SUPER_ QHsm
The macro defining the base class for QActive.
#define | QF_ACTIVE_STATE_ QStateHandler
The argument of the base class' constructor.
#define | QF_TIMEEVT_CTR_SIZE 2
macro to override the default QTimeEvtCtr size. Valid values 1, 2, or 4; default 2
#define | Q_NEW(evtT_, sig_) ((evtT_ *)QF::new_(sizeof(evtT_), (sig_)))
Allocate a dynamic event.

Variables

uint8_t const Q_ROM Q_ROM_VAR | QF_log2Lkup [256]
Lookup table for (log2(n) + 1), where n is the index into the table.
uint8_t const Q_ROM Q_ROM_VAR | QF_pwr2Lkup [65]
Lookup table for (1 << ((n-1) % 8)), where n is the index into the table.
uint8_t const Q_ROM Q_ROM_VAR | QF_invPwr2Lkup [65]
Lookup table for ~(1 << ((n-1) % 8)), where n is the index into the table.
uint8_t const Q_ROM Q_ROM_VAR | QF_div8Lkup [65]
Lookup table for (n-1)/8.

Detailed Description

QF/C++ platform-independent public interface.

This header file must be included directly or indirectly in all modules (*.cpp files) that use QF/C++.

Definition in file qf.h.

Define Documentation

#define Q_NEW | ( | evtT_,
 |  | sig_
 | ) | ((evtT_ *)QF::new_(sizeof(evtT_), (sig_)))

Allocate a dynamic event.

This macro returns an event pointer cast to the type evtT_. The event is initialized with the signal sig. Internally, the macro calls the internal QF function QF::new_(), which always returns a valid event pointer.

Note:
The internal QF function QF::new_() raises an assertion when the allocation of the event turns out to be impossible due to event pool depletion, or incorrect (too big) size of the requested event.

The following example illustrates dynamic allocation of an event:

extern QActive *AO_Table;

QState Philosopher::hungry(Philosopher *me, QEvent const *e) {
    TableEvt *pe;
    switch (e->sig) {
        case Q_ENTRY_SIG: {
            pe = Q_NEW(TableEvt, HUNGRY_SIG);    // dynamically allocate event
            pe->philNum = me->num_;
            AO_Table->postFIFO(pe);               // post the event directly
            return Q_HANDLED();
        }
        . . .
    }
    return Q_SUPER(&QHsm::top);
}

Definition at line 876 of file qf.h.

#define QF_ACTIVE_SUPER_ QHsm

The macro defining the base class for QActive.

By default, the QActive class is derived from QHsm. However, if the macro QF_ACTIVE_SUPER_ is defined, QActive is derived from QF_ACTIVE_SUPER_.

Clients might choose, for example, to define QF_ACTIVE_SUPER_ as QFsm to avoid the 1-2KB overhead of the hierarchical event processor.

Clients might also choose to define QF_ACTIVE_SUPER_ as their own completely customized class that has nothing to do with QHsm or QFsm. The QF_ACTIVE_SUPER_ class must provide member functions init() and dispatch(), consistent with the signatures of QHsm and QFsm. But the implementatin of these functions is completely open.

Definition at line 84 of file qf.h.

Variable Documentation

uint8_t const Q_ROM Q_ROM_VAR QF_div8Lkup[65]

Lookup table for (n-1)/8.

Note:
Index range n = 0..64. The first index (n == 0) should never be used.

Definition at line 59 of file qf_pwr2.cpp.

Referenced by QPSet64::hasElement(), QPSet64::insert(), QPSet64::remove(), QActive::subscribe(), QActive::unsubscribe(), and QActive::unsubscribeAll().

uint8_t const Q_ROM Q_ROM_VAR QF_invPwr2Lkup[65]

Lookup table for ~(1 << ((n-1) % 8)), where n is the index into the table.

Note:
Index range n = 0..64. The first index (n == 0) should never be used.

Definition at line 47 of file qf_pwr2.cpp.

Referenced by QF::publish(), QPSet64::remove(), QPSet8::remove(), QActive::unsubscribe(), and QActive::unsubscribeAll().

uint8_t const Q_ROM Q_ROM_VAR QF_log2Lkup[256]

Lookup table for (log2(n) + 1), where n is the index into the table.

This lookup delivers the 1-based number of the most significant 1-bit of a byte.

Note:
Index range n = 0..255. The first index (n == 0) should never be used.

Definition at line 35 of file qf_log2.cpp.

Referenced by QPSet64::findMax(), QPSet8::findMax(), and QF::publish().

uint8_t const Q_ROM Q_ROM_VAR QF_pwr2Lkup[65]

Lookup table for (1 << ((n-1) % 8)), where n is the index into the table.

Note:
Index range n = 0..64. The first index (n == 0) should never be used.

Definition at line 35 of file qf_pwr2.cpp.

Referenced by QPSet8::hasElement(), QPSet8::insert(), QActive::subscribe(), and QActive::unsubscribeAll().


QP/C++: qf_act.cpp File Reference

Variables

qf_act.cpp File Reference

QF::active_[], QF::getVersion(), and QF::add_()/QF::remove_() implementation. More...

#include "qf_pkg.h"
#include "qassert.h"

Go to the source code of this file.

Variables

uint8_t QF_intLockNest_
interrupt-lock nesting level

Detailed Description

QF::active_[], QF::getVersion(), and QF::add_()/QF::remove_() implementation.

Definition in file qf_act.cpp.

Variable Documentation

uint8_t QF_intLockNest_

interrupt-lock nesting level

Note:
Not to be used by Clients directly, only in ports of QF

Definition at line 40 of file qf_act.cpp.


QP/C++: qf_gc.cpp File Reference

qf_gc.cpp File Reference

QF::gc() implementation. More...

#include "qf_pkg.h"
#include "qassert.h"

Go to the source code of this file.

Detailed Description

QF::gc() implementation.

Definition in file qf_gc.cpp.


QP/C++: qf_log2.cpp File Reference

Variables

qf_log2.cpp File Reference

QF_log2Lkup[] implementation. More...

#include "qf_pkg.h"

Go to the source code of this file.

Variables

uint8_t const Q_ROM Q_ROM_VAR QF_log2Lkup [256]
Lookup table for (log2(n) + 1), where n is the index into the table.

Detailed Description

QF_log2Lkup[] implementation.

Definition in file qf_log2.cpp.

Variable Documentation

uint8_t const Q_ROM Q_ROM_VAR QF_log2Lkup[256]
Initial value:
 {
    0U, 1U, 2U, 2U, 3U, 3U, 3U, 3U, 4U, 4U, 4U, 4U, 4U, 4U, 4U, 4U,
    5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U,
    6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U,
    6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U,
    7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U,
    7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U,
    7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U,
    7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U,
    8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U,
    8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U,
    8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U,
    8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U,
    8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U,
    8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U,
    8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U,
    8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U
}

Lookup table for (log2(n) + 1), where n is the index into the table.

This lookup delivers the 1-based number of the most significant 1-bit of a byte.

Note:
Index range n = 0..255. The first index (n == 0) should never be used.

Definition at line 35 of file qf_log2.cpp.

Referenced by QPSet64::findMax(), QPSet8::findMax(), and QF::publish().


QP/C++: qf_new.cpp File Reference

qf_new.cpp File Reference

QF::new_() implementation. More...

#include "qf_pkg.h"
#include "qassert.h"

Go to the source code of this file.

Detailed Description

QF::new_() implementation.

Definition in file qf_new.cpp.


QP/C++: qf_pkg.h File Reference

Classes | Defines | Variables

qf_pkg.h File Reference

Internal (package scope) QF/C++ interface. More...

#include "qf_port.h"

Go to the source code of this file.

Classes

struct | QFreeBlock
Structure representing a free block in the Native QF Memory Pool. More...

Defines

#define | QF_INT_LOCK_KEY_
This is an internal macro for defining the interrupt lock key.
#define | QF_INT_LOCK_() QF_INT_LOCK(dummy)
This is an internal macro for locking interrupts.
#define | QF_INT_UNLOCK_() QF_INT_UNLOCK(dummy)
This is an internal macro for unlocking interrupts.

Variables

QTimeEvt * QF_timeEvtListHead_
head of linked list of time events
QF_EPOOL_TYPE_ | QF_pool_ [3]
allocate 3 event pools
uint8_t QF_maxPool_
# of initialized event pools
QSubscrList * QF_subscrList_
the subscriber list array
QSignal QF_maxSignal_
the maximum published signal

Detailed Description

Internal (package scope) QF/C++ interface.

Definition in file qf_pkg.h.

Define Documentation

#define QF_INT_LOCK_ ( ) QF_INT_LOCK(dummy)

This is an internal macro for locking interrupts.

The purpose of this macro is to enable writing the same code for the case when interrupt key is defined and when it is not. If the macro QF_INT_KEY_TYPE is defined, this internal macro invokes QF_INT_LOCK passing the key variable as the parameter. Otherwise QF_INT_LOCK is invoked with a dummy parameter.

See also:
QF_INT_LOCK, #QK_INT_LOCK

Definition at line 57 of file qf_pkg.h.

Referenced by QTimeEvt::disarm(), QF::gc(), QMPool::get(), QEQueue::get(), QActive::get_(), QF::getPoolMargin(), QF::getQueueMargin(), QF::getVersion(), QEQueue::postFIFO(), QActive::postFIFO(), QEQueue::postLIFO(), QActive::postLIFO(), QF::publish(), QMPool::put(), QTimeEvt::rearm(), QActive::recall(), QF::remove_(), QF::run(), QActive::subscribe(), QF::tick(), QActive::unsubscribe(), and QActive::unsubscribeAll().

#define QF_INT_LOCK_KEY_

This is an internal macro for defining the interrupt lock key.

The purpose of this macro is to enable writing the same code for the case when interrupt key is defined and when it is not. If the macro QF_INT_KEY_TYPE is defined, this internal macro provides the definition of the lock key variable. Otherwise this macro is empty.

See also:
QF_INT_KEY_TYPE

Definition at line 47 of file qf_pkg.h.

Referenced by QTimeEvt::disarm(), QF::gc(), QMPool::get(), QEQueue::get(), QActive::get_(), QF::getPoolMargin(), QF::getQueueMargin(), QF::getVersion(), QEQueue::postFIFO(), QActive::postFIFO(), QEQueue::postLIFO(), QActive::postLIFO(), QF::publish(), QMPool::put(), QTimeEvt::rearm(), QActive::recall(), QF::remove_(), QF::run(), QActive::subscribe(), QF::tick(), QActive::unsubscribe(), and QActive::unsubscribeAll().

#define QF_INT_UNLOCK_ ( ) QF_INT_UNLOCK(dummy)

This is an internal macro for unlocking interrupts.

The purpose of this macro is to enable writing the same code for the case when interrupt key is defined and when it is not. If the macro QF_INT_KEY_TYPE is defined, this internal macro invokes QF_INT_UNLOCK passing the key variable as the parameter. Otherwise QF_INT_UNLOCK is invoked with a dummy parameter.

See also:
QF_INT_UNLOCK, #QK_INT_UNLOCK

Definition at line 67 of file qf_pkg.h.

Referenced by QTimeEvt::disarm(), QF::gc(), QMPool::get(), QEQueue::get(), QActive::get_(), QF::getPoolMargin(), QF::getQueueMargin(), QF::getVersion(), QEQueue::postFIFO(), QActive::postFIFO(), QEQueue::postLIFO(), QActive::postLIFO(), QF::publish(), QMPool::put(), QTimeEvt::rearm(), QActive::recall(), QF::remove_(), QF::run(), QActive::subscribe(), QF::tick(), QActive::unsubscribe(), and QActive::unsubscribeAll().


QP/C++: qf_pool.cpp File Reference

Variables

qf_pool.cpp File Reference

QF_pool_[] and QF_maxPool_ definition, QF::poolInit() implementation. More...

#include "qf_pkg.h"
#include "qassert.h"

Go to the source code of this file.

Variables

QF_EPOOL_TYPE_ QF_pool_ [3]
allocate 3 event pools
uint8_t QF_maxPool_
# of initialized event pools

Detailed Description

QF_pool_[] and QF_maxPool_ definition, QF::poolInit() implementation.

Definition in file qf_pool.cpp.


QP/C++: qf_port.h File Reference

Defines

qf_port.h File Reference

QF port to QK for a "generic" C++ compiler. More...

#include "qep_port.h"
#include "qk_port.h"
#include "qf.h"
#include "qf.h"

Go to the source code of this file.

Defines

#define | QF_MAX_ACTIVE 63
The maximum number of active objects in the application.
#define | QF_EVENT_SIZ_SIZE 2
The size (in bytes) of the event-size representation in the QF. Valid values: 1, 2, or 4; default 2.
#define | QF_EQUEUE_CTR_SIZE 1
The size (in bytes) of the ring-buffer counters used in the native QF event queue implementation. Valid values: 1, 2, or 4; default 1.
#define | QF_MPOOL_SIZ_SIZE 2
The size (in bytes) of the block-size representation in the native QF event pool. Valid values: 1, 2, or 4; default QF_EVENT_SIZ_SIZE.
#define | QF_MPOOL_CTR_SIZE 2
The size (in bytes) of the block-counter representation in the native QF event pool. Valid values: 1, 2, or 4; default 2.
#define | QF_TIMEEVT_CTR_SIZE 4
The size (in bytes) of the time event -counter representation in the QTimeEvt class. Valid values: 1, 2, or 4; default 2.
#define | QF_ACTIVE_BASE QHsm
The macro defining the base class for QActive.
#define | QF_INT_KEY_TYPE int
Define the type of the interrupt lock key.
#define | QF_INT_LOCK(key_) ((key_) = intLock())
Define the interrupt locking policy.
#define | QF_INT_UNLOCK(key_) intUnlock(key_)
Define the interrupt unlocking policy.

Detailed Description

QF port to QK for a "generic" C++ compiler.

Note:
This is just an example of a QF port used for "linting" the QF. Ports of QF are located in the directory <qpcpp_3>/ports.

Definition in file qf_port.h.

Define Documentation

#define QF_ACTIVE_BASE QHsm

The macro defining the base class for QActive.

By default, the QActive class is derived from QHsm. However, if the macro QF_ACTIVE_BASE is defined, QActive is derived from QF_ACTIVE_BASE.

Clients might choose, for example, to define QF_ACTIVE_BASE as QFsm to avoide the 1-2KB overhead of the hierarchical event processor.

Clients might also choose to define QF_ACTIVE_BASE as their own completely customized class that has nothing to do with QHsm or QFsm. The QF_ACTIVE_BASE class must provide member functions init() and dispatch(), consistent with the signatures of QHsm and QFsm. But the implementatin of these functions is completely open.

Note:
Once you define QF_ACTIVE_BASE, you must consistently it in building all the QP component libraries and your own application code. The consistency is guaranteed if you define this macro only once in the qf_port.h header file and henceforth include this header file in all builds.

Definition at line 175 of file qf_port.h.

#define QF_EQUEUE_CTR_SIZE 1

The size (in bytes) of the ring-buffer counters used in the native QF event queue implementation. Valid values: 1, 2, or 4; default 1.

This macro can be defined in the QF ports to configure the ::QEQueueCtr type. If the macro is not defined, the default of 1 byte will be chosen in qequeue.h. The valid QF_EQUEUE_CTR_SIZE values of 1, 2, or 4, correspond to ::QEQueueCtr of uint8_t, uint16_t, and uint32_t, respectively. The ::QEQueueCtr data type determines the dynamic range of numerical values of ring-buffer counters inside event queues, or, in other words, the maximum number of events that the native QF event queue can manage.

See also:
QEQueue
Note:
Once you choose a certain value of QF_EQUEUE_CTR_SIZE, you must consistently use the same value in building all the QP component libraries and your own application code. The consistency is guaranteed if you define this macro only once in the qf_port.h header file and henceforth include this header file in all builds.

Definition at line 93 of file qf_port.h.

#define QF_EVENT_SIZ_SIZE 2

The size (in bytes) of the event-size representation in the QF. Valid values: 1, 2, or 4; default 2.

This macro can be defined in the QF ports to configure the ::QEventSize type. If the macro is not defined, the default of 2 byte will be chosen in qf.h. The valid QF_EVENT_SIZ_SIZE values of 1, 2, or 4, correspond to ::QEventSize of uint8_t, uint16_t, and uint32_t, respectively. The ::QEventSize data type determines the dynamic range of event-sizes in your application.

See also:
QF::poolInit(), QF::new_()
Note:
Once you choose a certain value of QF_EVENT_SIZ_SIZE, you must consistently use the same value in building all the QP component libraries and your own application code. The consistency is guaranteed if you define this macro only once in the qf_port.h header file and henceforth include this header file in all builds.

Definition at line 74 of file qf_port.h.

#define QF_INT_KEY_TYPE int

Define the type of the interrupt lock key.

Defining this macro configures the "saving and restoring interrupt status" policy of locking and unlocking interrupts. Coversely, if this macro is not defined, the simple "unconditional interrupt locking and unlocking" is used.

Definition at line 183 of file qf_port.h.

Referenced by QK::getVersion().

#define QF_INT_LOCK ( key_ ) ((key_) = intLock())

Define the interrupt locking policy.

This macro establishes a critical section (typically by locking interrupts). When the "saving and restoring interrupt status" policy is used, the macro sets the "interrupt key" to the interrupt status just before locking interrupts. When the policy of "unconditional interrupt unlocking" is used, the macro does not use the "interrupt key" parameter.

Note:
the QF_INT_LOCK macro should always be used in pair with the macro QF_INT_UNLOCK.

Definition at line 195 of file qf_port.h.

#define QF_INT_UNLOCK ( key_ ) intUnlock(key_)

Define the interrupt unlocking policy.

This macro leaves a critical section (typically by unlocking interrupts). When the "saving and restoring interrupt status" policy is used, the macro restores the interrupt status from the "interrupt key" parameter. When the policy of "unconditional interrupt unlocking" is used, the macro unconditionally unlocks interrupts ignoring the "interrupt key" parameter.

Note:
the QF_INT_LOCK macro should always be used in pair with the macro QF_INT_UNLOCK.

Definition at line 207 of file qf_port.h.

#define QF_MAX_ACTIVE 63

The maximum number of active objects in the application.

This macro should be defined in the QF ports and should be in range of 1..63, inclusive. The value of this macro determines the maximum priority level of an active object in the system. Not all priority levels must be used, but the maximum priority cannot exceed QF_MAX_ACTIVE.

If the macro is not defined, the default value is 63, which is the maximum. Defining the value below the maximum saves some memory, mostly for the subscriber-lists.

See also:
QSubscrList.
Note:
Once you choose a certain value of QF_MAX_ACTIVE, you must consistently use the same value in building all the QP component libraries and your own application code. The consistency is guaranteed if you define this macro only once in the qf_port.h header file and henceforth include this header file in all builds.

Definition at line 56 of file qf_port.h.

Referenced by QF::getQueueMargin(), QK::getVersion(), QActive::start(), QActive::subscribe(), QActive::unsubscribe(), and QActive::unsubscribeAll().

#define QF_MPOOL_CTR_SIZE 2

The size (in bytes) of the block-counter representation in the native QF event pool. Valid values: 1, 2, or 4; default 2.

This macro can be defined in the QF ports to configure the ::QMPoolCtr type. If the macro is not defined, the default of 2 bytes will be chosen in qmpool.h. The valid QF_MPOOL_CTR_SIZE values of 1, 2, or 4, correspond to ::QMPoolSize of uint8_t, uint16_t, and uint32_t, respectively. The ::QMPoolCtr data type determines the dynamic range of block-counters that the native QMPool can handle, or, in other words, the maximum number of blocks that the native QF event pool can manage.

See also:
QMPool
Note:
Once you choose a certain value of QF_MPOOL_CTR_SIZE, you must consistently use the same value in building all the QP component libraries and your own application code. The consistency is guaranteed if you define this macro only once in the qf_port.h header file and henceforth include this header file in all builds.

Definition at line 134 of file qf_port.h.

#define QF_MPOOL_SIZ_SIZE 2

The size (in bytes) of the block-size representation in the native QF event pool. Valid values: 1, 2, or 4; default QF_EVENT_SIZ_SIZE.

This macro can be defined in the QF ports to configure the ::QMPoolSize type. If the macro is not defined, the default of QF_EVENT_SIZ_SIZE will be chosen in qmpool.h, because the memory pool is primarily used for implementing event pools.

The valid QF_MPOOL_SIZ_SIZE values of 1, 2, or 4, correspond to ::QMPoolSize of uint8_t, uint16_t, and uint32_t, respectively. The ::QMPoolSize data type determines the dynamic range of block-sizes that the native QMPool can hanle.

See also:
QF_EVENT_SIZ_SIZE, QMPool
Note:
Once you choose a certain value of QF_MPOOL_SIZ_SIZE, you must consistently use the same value in building all the QP component libraries and your own application code. The consistency is guaranteed if you define this macro only once in the qf_port.h header file and henceforth include this header file in all builds.

Definition at line 115 of file qf_port.h.

#define QF_TIMEEVT_CTR_SIZE 4

The size (in bytes) of the time event -counter representation in the QTimeEvt class. Valid values: 1, 2, or 4; default 2.

This macro can be defined in the QF ports to configure the internal tick counters of Time Events. If the macro is not defined, the default of 2 bytes will be chosen in qf.h. The valid QF_TIMEEVT_CTR_SIZE values of 1, 2, or 4, correspond to tick counters of uint8_t, uint16_t, and uint32_t, respectively. The tick counter representation determines the dynamic range of time delays that a Time Event can handle.

See also:
QTimeEvt
Note:
Once you choose a certain value of QF_TIMEEVT_CTR_SIZE, you must consistently use the same value in building all the QP component libraries and your own application code. The consistency is guaranteed if you define this macro only once in the qf_port.h header file and henceforth include this header file in all builds.

Definition at line 152 of file qf_port.h.


QP/C++: qf_psini.cpp File Reference

Variables

qf_psini.cpp File Reference

QF_subscrList_ and QF_maxSignal_ definition, QF::psInit() implementation. More...

#include "qf_pkg.h"

Go to the source code of this file.

Variables

QSubscrList * QF_subscrList_
the subscriber list array
QSignal QF_maxSignal_
the maximum published signal

Detailed Description

QF_subscrList_ and QF_maxSignal_ definition, QF::psInit() implementation.

Definition in file qf_psini.cpp.


QP/C++: qf_pspub.cpp File Reference

qf_pspub.cpp File Reference

QF::publish() implementation. More...

#include "qf_pkg.h"
#include "qassert.h"

Go to the source code of this file.

Detailed Description

QF::publish() implementation.

Definition in file qf_pspub.cpp.


QP/C++: qf_pwr2.cpp File Reference

Variables

qf_pwr2.cpp File Reference

QF_pwr2Lkup[], QF_invPwr2Lkup[], and QF_div8Lkup[] definitions. More...

#include "qf_pkg.h"

Go to the source code of this file.

Variables

uint8_t const Q_ROM Q_ROM_VAR | QF_pwr2Lkup [65]
Lookup table for (1 << ((n-1) % 8)), where n is the index into the table.
uint8_t const Q_ROM Q_ROM_VAR | QF_invPwr2Lkup [65]
Lookup table for ~(1 << ((n-1) % 8)), where n is the index into the table.
uint8_t const Q_ROM Q_ROM_VAR | QF_div8Lkup [65]
Lookup table for (n-1)/8.

Detailed Description

QF_pwr2Lkup[], QF_invPwr2Lkup[], and QF_div8Lkup[] definitions.

Definition in file qf_pwr2.cpp.

Variable Documentation

uint8_t const Q_ROM Q_ROM_VAR QF_div8Lkup[65]
Initial value:
 {
    0U,
    0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
    1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U,
    2U, 2U, 2U, 2U, 2U, 2U, 2U, 2U,
    3U, 3U, 3U, 3U, 3U, 3U, 3U, 3U,
    4U, 4U, 4U, 4U, 4U, 4U, 4U, 4U,
    5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U,
    6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U,
    7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U
}

Lookup table for (n-1)/8.

Note:
Index range n = 0..64. The first index (n == 0) should never be used.

Definition at line 59 of file qf_pwr2.cpp.

Referenced by QPSet64::hasElement(), QPSet64::insert(), QPSet64::remove(), QActive::subscribe(), QActive::unsubscribe(), and QActive::unsubscribeAll().

uint8_t const Q_ROM Q_ROM_VAR QF_invPwr2Lkup[65]
Initial value:
 {
    0xFFU,
    0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU,
    0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU,
    0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU,
    0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU,
    0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU,
    0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU,
    0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU,
    0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU
}

Lookup table for ~(1 << ((n-1) % 8)), where n is the index into the table.

Note:
Index range n = 0..64. The first index (n == 0) should never be used.

Definition at line 47 of file qf_pwr2.cpp.

Referenced by QF::publish(), QPSet64::remove(), QPSet8::remove(), QActive::unsubscribe(), and QActive::unsubscribeAll().

uint8_t const Q_ROM Q_ROM_VAR QF_pwr2Lkup[65]
Initial value:
 {
    0x00U,
    0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U,
    0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U,
    0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U,
    0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U,
    0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U,
    0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U,
    0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U,
    0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U
}

Lookup table for (1 << ((n-1) % 8)), where n is the index into the table.

Note:
Index range n = 0..64. The first index (n == 0) should never be used.

Definition at line 35 of file qf_pwr2.cpp.

Referenced by QPSet8::hasElement(), QPSet8::insert(), QActive::subscribe(), and QActive::unsubscribeAll().


QP/C++: qf_tick.cpp File Reference

qf_tick.cpp File Reference

QF::tick() implementation. More...

#include "qf_pkg.h"

Go to the source code of this file.

Detailed Description

QF::tick() implementation.

Definition in file qf_tick.cpp.


QP/C++: qfsm_dis.cpp File Reference

qfsm_dis.cpp File Reference

QFsm::dispatch() implementation. More...

#include "qep_pkg.h"

Go to the source code of this file.

Detailed Description

QFsm::dispatch() implementation.

Definition in file qfsm_dis.cpp.


QP/C++: qfsm_ini.cpp File Reference

qfsm_ini.cpp File Reference

QFsm::init() implementation. More...

#include "qep_pkg.h"
#include "qassert.h"

Go to the source code of this file.

Detailed Description

QFsm::init() implementation.

Definition in file qfsm_ini.cpp.


QP/C++: qhsm_dis.cpp File Reference

qhsm_dis.cpp File Reference

QHsm::dispatch() implementation. More...

#include "qep_pkg.h"
#include "qassert.h"

Go to the source code of this file.

Detailed Description

QHsm::dispatch() implementation.

Definition in file qhsm_dis.cpp.


QP/C++: qhsm_in.cpp File Reference

qhsm_in.cpp File Reference

QHsm::isIn() implementation. More...

#include "qep_pkg.h"

Go to the source code of this file.

Detailed Description

QHsm::isIn() implementation.

Definition in file qhsm_in.cpp.


QP/C++: qhsm_ini.cpp File Reference

qhsm_ini.cpp File Reference

QHsm::init() implementation. More...

#include "qep_pkg.h"
#include "qassert.h"

Go to the source code of this file.

Detailed Description

QHsm::init() implementation.

Definition in file qhsm_ini.cpp.


QP/C++: qhsm_top.cpp File Reference

qhsm_top.cpp File Reference

QHsm::top() implementation. More...

#include "qep_pkg.h"

Go to the source code of this file.

Detailed Description

QHsm::top() implementation.

Definition in file qhsm_top.cpp.


QP/C++: qk.cpp File Reference

Variables

qk.cpp File Reference

QK_readySet_, QK_currPrio_, and QK_intNest_ definitions and QK::getVersion(), QF::init(), QF::run(), QF::stop(), QActive::start(), QActive::stop() implementations. More...

#include "qk_pkg.h"
#include "qassert.h"

Go to the source code of this file.

Variables

QPSet64 volatile | QK_readySet_
ready set of QK
uint8_t volatile | QK_currPrio_ = (uint8_t)( 63 + 1)
current task/interrupt priority
uint8_t volatile | QK_intNest_
interrupt nesting level

Detailed Description

QK_readySet_, QK_currPrio_, and QK_intNest_ definitions and QK::getVersion(), QF::init(), QF::run(), QF::stop(), QActive::start(), QActive::stop() implementations.

Definition in file qk.cpp.


QP/C++: qk.h File Reference

Classes | Defines | Typedefs | Functions | Variables

qk.h File Reference

QK/C++ platform-independent public interface. More...

#include "qequeue.h"
#include "qmpool.h"
#include "qpset.h"
#include "qs_port.h"

Go to the source code of this file.

Classes

class | QK
QK services. More...

Defines

#define | QF_EQUEUE_TYPE QEQueue
This macro defines the type of the event queue used for the active objects.
#define | QACTIVE_EQUEUE_WAIT_(me_) Q_ASSERT((me_)->m_eQueue.m_frontEvt != (QEvent *)0)
Platform-dependent macro defining how QF should block the calling task when the QF native queue is empty.
#define | QACTIVE_EQUEUE_SIGNAL_(me_)
Platform-dependent macro defining how QF should signal the active object task that an event has just arrived.
#define | QACTIVE_EQUEUE_ONEMPTY_(me_) QK_readySet_.remove((me_)->m_prio)
Platform-dependent macro defining the action QF should take when the native QF event queue becomes empty.
#define | QF_EPOOL_TYPE_ QMPool
This macro defines the type of the event pool used in this QF port.
#define | QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_) (p_).init(poolSto_, poolSize_, evtSize_)
Platform-dependent macro defining the event pool initialization.
#define | QF_EPOOL_EVENT_SIZE_(p_) ((p_).getBlockSize())
Platform-dependent macro defining how QF should obtain the event pool block-size.
#define | QF_EPOOL_GET_(p_, e_) ((e_) = (QEvent *)(p_).get())
Platform-dependent macro defining how QF should obtain an event e_ from the event pool p_.
#define | QF_EPOOL_PUT_(p_, e_) ((p_).put(e_))
Platform-dependent macro defining how QF should return an event e_ to the event pool p_.

Typedefs

typedef uint8_t | QMutex
QK Mutex type.

Functions

void | QK_init (void)
QK initialization.

Variables

QPSet64 volatile | QK_readySet_
ready set of QK
uint8_t volatile | QK_currPrio_
current task/interrupt priority
uint8_t volatile | QK_intNest_
interrupt nesting level

Detailed Description

QK/C++ platform-independent public interface.

This header file must be included directly or indirectly in all modules (*.cpp files) that use QK/C++.

Definition in file qk.h.

Define Documentation

#define QACTIVE_EQUEUE_ONEMPTY_ ( me_ ) QK_readySet_.remove((me_)->m_prio)

Platform-dependent macro defining the action QF should take when the native QF event queue becomes empty.

Note:
QACTIVE_EQUEUE_ONEMPTY_ is called from a critical section. It should not leave the critical section.
This is just an example of QACTIVE_EQUEUE_ONEMPTY_ for the QK-port of QF. In other QF ports you need to define the macro appropriately for the underlying kernel/OS you're using.

Definition at line 129 of file qk.h.

Referenced by QActive::get_().

#define QACTIVE_EQUEUE_SIGNAL_ ( me_ )
Value:
QK_readySet_.insert((me_)->m_prio); \
    if (QK_intNest_ == (uint8_t)0) { \
        QK_SCHEDULE_(); \
    } else ((void)0)

Platform-dependent macro defining how QF should signal the active object task that an event has just arrived.

The macro is necessary only when the native QF event queue is used. The signaling of task involves unblocking the task if it is blocked.

Note:
QACTIVE_EQUEUE_SIGNAL_ is called from a critical section. It might leave the critical section internally, but must restore the critical section before exiting to the caller.
This is just an example of QACTIVE_EQUEUE_SIGNAL_ for the QK-port of QF. In other QF ports you need to define the macro appropriately for the underlying kernel/OS you're using.

Definition at line 114 of file qk.h.

Referenced by QActive::postFIFO(), and QActive::postLIFO().

#define QACTIVE_EQUEUE_WAIT_ ( me_ ) Q_ASSERT((me_)->m_eQueue.m_frontEvt != (QEvent *)0)

Platform-dependent macro defining how QF should block the calling task when the QF native queue is empty.

Note:
This is just an example of QACTIVE_EQUEUE_WAIT_ for the QK-port of QF. QK never activates a task that has no events to process, so in this case the macro asserts that the queue is not empty. In other QF ports you using.

Definition at line 98 of file qk.h.

Referenced by QActive::get_().

#define QF_EPOOL_EVENT_SIZE_ ( p_ ) ((p_).getBlockSize())

Platform-dependent macro defining how QF should obtain the event pool block-size.

Note:
This is just an example of QF_EPOOL_EVENT_SIZE_ for the QK-port of QF. In other QF ports you need to define the macro appropriately for the underlying kernel/OS you're using.

Definition at line 156 of file qk.h.

Referenced by QF::new_(), and QF::poolInit().

#define QF_EPOOL_GET_ | ( | p_,
 |  | e_
 | ) | ((e_) = (QEvent *)(p_).get())

Platform-dependent macro defining how QF should obtain an event e_ from the event pool p_.

Note:
This is just an example of QF_EPOOL_GET_ for the QK-port of QF. In other QF ports you need to define the macro appropriately for the underlying kernel/OS you're using.

Definition at line 164 of file qk.h.

Referenced by QF::new_().

#define QF_EPOOL_INIT_ | ( | p_,
 |  | poolSto_,
 |  | poolSize_,
 |  | evtSize_
 | ) | (p_).init(poolSto_, poolSize_, evtSize_)

Platform-dependent macro defining the event pool initialization.

Note:
This is just an example of QF_EPOOL_INIT_ for the QK-port of QF. In other QF ports you need to define the macro appropriately for the underlying kernel/OS you're using.

Definition at line 147 of file qk.h.

Referenced by QF::poolInit().

#define QF_EPOOL_PUT_ | ( | p_,
 |  | e_
 | ) | ((p_).put(e_))

Platform-dependent macro defining how QF should return an event e_ to the event pool p_.

Note:
This is just an example of QF_EPOOL_PUT_ for the QK-port of QF. In other QF ports you need to define the macro appropriately for the underlying kernel/OS you're using.

Definition at line 172 of file qk.h.

Referenced by QF::gc().

#define QF_EPOOL_TYPE_ QMPool

This macro defines the type of the event pool used in this QF port.

Note:
This is just an example of the macro definition. Typically, you need to define it in the specific QF port file (qf_port.h). In case of QK, which always depends on the native QF memory pool, this macro is defined at the level of the platform-independent interface qk.h.

Definition at line 140 of file qk.h.

#define QF_EQUEUE_TYPE QEQueue

This macro defines the type of the event queue used for the active objects.

Note:
This is just an example of the macro definition. Typically, you need to define it in the specific QF port file (qf_port.h). In case of QK, which always depends on the native QF queue, this macro is defined at the level of the platform-independent interface qk.h.

Definition at line 53 of file qk.h.

Typedef Documentation

typedef uint8_t QMutex

QK Mutex type.

QMutex represents the priority-ceiling mutex available in QK.

See also:
QK::mutexLock()
QK::mutexUnlock()

Definition at line 181 of file qk.h.

Function Documentation

void QK_init ( void )

QK initialization.

QK_init() is called from QF_init() in qk.cpp. This function is defined in the QK ports.


QP/C++: qk_ext.cpp File Reference

qk_ext.cpp File Reference

QK_scheduleExt_() implementation. More...

#include "qk_pkg.h"
#include "qassert.h"

Go to the source code of this file.

Detailed Description

QK_scheduleExt_() implementation.

Definition in file qk_ext.cpp.


QP/C++: qk_mutex.cpp File Reference

Variables

qk_mutex.cpp File Reference

QK::mutexLock()/QK::mutexUnlock() implementation. More...

#include "qk_pkg.h"

Go to the source code of this file.

Variables

uint8_t volatile QK_ceilingPrio_
QK mutex priority ceiling.

Detailed Description

QK::mutexLock()/QK::mutexUnlock() implementation.

Definition in file qk_mutex.cpp.


QP/C++: qk_pkg.h File Reference

Variables

qk_pkg.h File Reference

Internal (package scope) QK/C interface. More...

#include "qf_port.h"

Go to the source code of this file.

Variables

uint8_t volatile QK_ceilingPrio_
QK mutex priority ceiling.

Detailed Description

Internal (package scope) QK/C interface.

Definition in file qk_pkg.h.


QP/C++: qk_port.h File Reference

Defines

qk_port.h File Reference

QK/C++ port to QK for a "generic" C++ compiler. More...

#include "qk.h"
#include "qk.h"

Go to the source code of this file.

Defines

#define | QK_EXT_SAVE(act_) FPU_save((FPU_context *)(act_)->m_thread)
Define the method for saving the extended context (e.g., the context of a floating-point co-processor).
#define | QK_EXT_RESTORE(act_) FPU_restore((FPU_context *)(act_)->m_thread)
Define the method for restoring the extended context (e.g., the context of a floating-point co-processor).
#define | QK_TLS(act_) _impure_ptr = (struct _reent *)(act_)->m_thread
Define the method for switching the Thread-Local-Storage for for a given thread.
#define | QK_ISR_ENTRY()
Define the ISR entry sequence, if the compiler supports writing interrupts in C++.
#define | QK_ISR_EXIT()
Define the ISR exit sequence, if the compiler supports writing interrupts in C++.

Detailed Description

QK/C++ port to QK for a "generic" C++ compiler.

Note:
This is just an EXAMPLE of a QK port used for "linting" the QK. Ports of QK are located in the directory <qpcpp_3>/ports.

Definition in file qk_port.h.

Define Documentation

#define QK_EXT_RESTORE ( act_ ) FPU_restore((FPU_context *)(act_)->m_thread)

Define the method for restoring the extended context (e.g., the context of a floating-point co-processor).

Note:
This is just an example of QK_EXT_RESTORE macro. You need to define the macro appropriately for the co-processor you're using. This macro is only used in the extended QK scheduler QK_scheduleExt_(). If you define QK_EXT_RESTORE, you also need to provide QK_EXT_SAVE and #QK_EXT_TYPE.

Definition at line 57 of file qk_port.h.

#define QK_EXT_SAVE ( act_ ) FPU_save((FPU_context *)(act_)->m_thread)

Define the method for saving the extended context (e.g., the context of a floating-point co-processor).

Note:
This is just an example of QK_EXT_SAVE macro. You need to define the macro appropriately for the co-processor you're using. This macro is only used in the extended QK scheduler QK_scheduleExt_(). If you define QK_EXT_SAVE, you also need to provide QK_EXT_RESTORE and #QK_EXT_TYPE.

Definition at line 48 of file qk_port.h.

#define QK_ISR_ENTRY ( )
Value:
do { \
    ++QK_intNest_; \
    QF_QS_ISR_ENTRY(QK_intNest_, QK_currPrio_); \
} while (0)

Define the ISR entry sequence, if the compiler supports writing interrupts in C++.

Note:
This is just an example of QK_ISR_ENTRY. You need to define the macro appropriately for the CPU/compiler you're using. Also, some QK ports will not define this macro, but instead will provide ISR skeleton code in assembly.

Definition at line 96 of file qk_port.h.

#define QK_ISR_EXIT ( )
Value:
do { \
    send End-Of-Interrupt instruction to the Interrupt Controller; \
    QF_QS_ISR_EXIT(QK_intNest_, QK_currPrio_); \
    --QK_intNest_; \
    if (QK_intNest_ == (uint8_t)0) { \
        QK_scheduleExt_(); \
    } \
} while (0)

Define the ISR exit sequence, if the compiler supports writing interrupts in C++.

Note:
This is just an example of QK_ISR_EXIT. You need to define the macro appropriately for the CPU/compiler you're using. Also, some QK ports will not define this macro, but instead will provide ISR skeleton code in assembly.

Definition at line 109 of file qk_port.h.

#define QK_TLS ( act_ ) _impure_ptr = (struct _reent *)(act_)->m_thread

Define the method for switching the Thread-Local-Storage for for a given thread.

Note:
This is just an example of QK_TLS macro. You need to define the macro appropriately for the runtime library you're using. This macro is optional and you don't need to define it. The macro is used in both the regular QK scheduler QK_schedule_() and the extended QK scheduler QK_scheduleExt_().

Definition at line 77 of file qk_port.h.

Referenced by QK::getVersion().


QP/C++: qk_sched.cpp File Reference

qk_sched.cpp File Reference

QK_schedule_() implementation. More...

#include "qk_pkg.h"
#include "qassert.h"

Go to the source code of this file.

Detailed Description

QK_schedule_() implementation.

Definition in file qk_sched.cpp.


QP/C++: qmp_get.cpp File Reference

qmp_get.cpp File Reference

QMPool::get() and QF::getPoolMargin() implementation. More...

#include "qf_pkg.h"
#include "qassert.h"

Go to the source code of this file.

Detailed Description

QMPool::get() and QF::getPoolMargin() implementation.

Definition in file qmp_get.cpp.


QP/C++: qmp_init.cpp File Reference

qmp_init.cpp File Reference

QMPool::init() implementation. More...

#include "qf_pkg.h"
#include "qassert.h"

Go to the source code of this file.

Detailed Description

QMPool::init() implementation.

Definition in file qmp_init.cpp.


QP/C++: qmp_put.cpp File Reference

qmp_put.cpp File Reference

QMPool::put() implementation. More...

#include "qf_pkg.h"
#include "qassert.h"

Go to the source code of this file.

Detailed Description

QMPool::put() implementation.

Definition in file qmp_put.cpp.


QP/C++: qmpool.h File Reference

Classes | Defines

qmpool.h File Reference

platform-independent memory pool interface. More...

Go to the source code of this file.

Classes

class | QMPool
Native QF memory pool class. More...

Defines

#define | QF_MPOOL_SIZ_SIZE 2
macro to override the default ::QMPoolSize size. Valid values 1, 2, or 4; default 2
#define | QF_MPOOL_CTR_SIZE 2
macro to override the default QMPoolCtr size. Valid values 1, 2, or 4; default 2

Detailed Description

platform-independent memory pool interface.

This header file must be included in all QF ports that use native QF memory pool implementation.

Definition in file qmpool.h.


QP/C++: qpset.h File Reference

Classes | Variables

qpset.h File Reference

platform-independent priority sets of 8 or 64 elements. More...

Go to the source code of this file.

Classes

class | QPSet8
Priority Set of up to 8 elements for building various schedulers, but also useful as a general set of up to 8 elements of any kind. More...
class | QPSet64
Priority Set of up to 64 elements for building various schedulers, but also useful as a general set of up to 64 elements of any kind. More...

Variables

uint8_t const Q_ROM Q_ROM_VAR | QF_log2Lkup [256]
Lookup table for (log2(n) + 1), where n is the index into the table.
uint8_t const Q_ROM Q_ROM_VAR | QF_pwr2Lkup [65]
Lookup table for (1 << ((n-1) % 8)), where n is the index into the table.
uint8_t const Q_ROM Q_ROM_VAR | QF_invPwr2Lkup [65]
Lookup table for ~(1 << ((n-1) % 8)), where n is the index into the table.
uint8_t const Q_ROM Q_ROM_VAR | QF_div8Lkup [65]
Lookup table for (n-1)/8.

Detailed Description

platform-independent priority sets of 8 or 64 elements.

This header file must be included in those QF ports that use the cooperative multitasking QF scheduler or the QK.

Definition in file qpset.h.

Variable Documentation

uint8_t const Q_ROM Q_ROM_VAR QF_div8Lkup[65]

Lookup table for (n-1)/8.

Note:
Index range n = 0..64. The first index (n == 0) should never be used.

Definition at line 59 of file qf_pwr2.cpp.

uint8_t const Q_ROM Q_ROM_VAR QF_invPwr2Lkup[65]

Lookup table for ~(1 << ((n-1) % 8)), where n is the index into the table.

Note:
Index range n = 0..64. The first index (n == 0) should never be used.

Definition at line 47 of file qf_pwr2.cpp.

uint8_t const Q_ROM Q_ROM_VAR QF_log2Lkup[256]

Lookup table for (log2(n) + 1), where n is the index into the table.

This lookup delivers the 1-based number of the most significant 1-bit of a byte.

Note:
Index range n = 0..255. The first index (n == 0) should never be used.

Definition at line 35 of file qf_log2.cpp.

uint8_t const Q_ROM Q_ROM_VAR QF_pwr2Lkup[65]

Lookup table for (1 << ((n-1) % 8)), where n is the index into the table.

Note:
Index range n = 0..64. The first index (n == 0) should never be used.

Definition at line 35 of file qf_pwr2.cpp.


QP/C++: qs.cpp File Reference

Variables

qs.cpp File Reference

QS internal variables definitions and core QS functions implementations. More...

#include "qs_pkg.h"

Go to the source code of this file.

Variables

uint8_t * QS_ring_
pointer to the start of the ring buffer
QSCtr QS_end_
offset of the end of the ring buffer
QSCtr QS_head_
offset to where next byte will be inserted
QSCtr QS_tail_
offset of where next event will be extracted
QSCtr QS_used_
number of bytes currently in the ring buffer
uint8_t QS_seq_
the record sequence number
uint8_t QS_chksum_
the checksum of the current record
uint8_t QS_full_
the ring buffer is temporarily full

Detailed Description

QS internal variables definitions and core QS functions implementations.

Definition in file qs.cpp.


QP/C++: qs.h File Reference

Classes | Defines | Enumerations | Variables

qs.h File Reference

QS/C++ platform-independent public interface. This header file must be included directly or indirectly in all modules (*.cpp files) that use QS/C++. More...

Go to the source code of this file.

Classes

class | QS
Quantum Spy logging facilities. More...

Defines

#define | QS_ALL_RECORDS ((uint8_t)0xFF)
Specification of all QS records for the QS::filterOn() and QS::filterOff()
#define | QS_EOD ((uint16_t)0xFFFF)
Constant representing End-Of-Data condition returned from the QS::getByte() function.
#define | QS_TIME_SIZE 4
The size (in bytes) of the QS time stamp. Valid values: 1, 2, or 4; default 4.
#define | QS_INIT(arg_) QS::onStartup(arg_)
Initialize the QS facility.
#define | QS_EXIT() QS::onCleanup()
Cleanup the QS facility.
#define | QS_FILTER_ON(rec_) QS::filterOn(rec_)
Global Filter ON for a given record type rec.
#define | QS_FILTER_OFF(rec_) QS::filterOff(rec_)
Global filter OFF for a given record type rec.
#define | QS_FILTER_SM_OBJ(obj_) (QS::smObj_ = (obj_))
Local Filter for a given state machine object obj_.
#define | QS_FILTER_AO_OBJ(obj_) (QS::aoObj_ = (obj_))
Local Filter for a given active object obj_.
#define | QS_FILTER_MP_OBJ(obj_) (QS::mpObj_ = (obj_))
Local Filter for a given memory pool object obj_.
#define | QS_FILTER_EQ_OBJ(obj_) (QS::eqObj_ = (obj_))
Filter for a given event queue object obj_.
#define | QS_FILTER_TE_OBJ(obj_) (QS::teObj_ = (obj_))
Local Filter for a given time event object obj_.
#define | QS_FILTER_AP_OBJ(obj_) (QS_apObj_ = (obj_))
Local Filter for a generic application object obj_.
#define | QS_BEGIN_NOLOCK(rec_, obj_)
Begin a QS user record without locking interrupts.
#define | QS_END_NOLOCK() QS_END_NOLOCK_()
End a QS user record without locking interrupts.
#define | QS_INT_LOCK_KEY_
This is an internal macro for defining the interrupt lock key.
#define | QS_INT_LOCK_() QF_INT_LOCK(ignore_)
This is an internal macro for locking interrupts.
#define | QS_INT_UNLOCK_() QF_INT_UNLOCK(ignore_)
This is an internal macro for unlocking interrupts.
#define | QS_BEGIN(rec_, obj_)
Begin a user QS record with locking interrupts.
#define | QS_END() QS_END_()
End a QS record with locking interrupts.
#define | QS_BEGIN_(rec_, objFilter_, obj_)
Internal QS macro to begin a QS record with locking the interrupts.
#define | QS_END_()
Internal QS macro to end a QS record with locking the interrupts.
#define | QS_BEGIN_NOLOCK_(rec_, objFilter_, obj_)
Internal QS macro to begin a QS record without locking the interrupts.
#define | QS_END_NOLOCK_()
Internal QS macro to end a QS record without locking the interrupts.
#define | QS_U8_(data_) QS::u8_(data_)
Internal QS macro to output an unformatted uint8_t data element.
#define | QS_U16_(data_) QS::u16_(data_)
Internal QS macro to output an unformatted uint16_t data element.
#define | QS_U32_(data_) QS::u32_(data_)
Internal QS macro to output an unformatted uint32_t data element.
#define | QS_OBJ_(obj_) QS::u32_((uint32_t)(obj_))
Internal QS macro to output an unformatted object pointer data element.
#define | QS_FUN_(fun_) QS::u32_((uint32_t)(fun_))
Internal QS macro to output an unformatted function pointer data element.
#define | QS_STR_(msg_) QS::str_(msg_)
Internal QS macro to output a zero-terminated ASCII string data element.
#define | QS_STR_ROM_(msg_) QS::str_ROM_(msg_)
Internal QS macro to output a zero-terminated ASCII string allocated in ROM data element.
#define | QS_I8(width_, data_) QS::u8((uint8_t)(((width_) << 4)) | QS_I8_T, (data_))
Output formatted int8_t to the QS record.
#define | QS_U8(width_, data_) QS::u8((uint8_t)(((width_) << 4)) | QS_U8_T, (data_))
Output formatted uint8_t to the QS record.
#define | QS_I16(width_, data_) QS::u16((uint8_t)(((width_) << 4)) | QS_I16_T, (data_))
Output formatted int16_t to the QS record.
#define | QS_U16(width_, data_) QS::u16((uint8_t)(((width_) << 4)) | QS_U16_T, (data_))
Output formatted uint16_t to the QS record.
#define | QS_I32(width_, data_) QS::u32((uint8_t)(((width_) << 4)) | QS_I32_T, (data_))
Output formatted int32_t to the QS record.
#define | QS_U32(width_, data_) QS::u32((uint8_t)(((width_) << 4)) | QS_U32_T, (data_))
Output formatted uint32_t to the QS record.
#define | QS_F32(width_, data_) QS::f32((uint8_t)(((width_) << 4)) | QS_F32_T, (data_))
Output formatted 32-bit floating point number to the QS record.
#define | QS_F64(width_, data_) QS::f64((uint8_t)(((width_) << 4)) | QS_F64_T, (data_))
Output formatted 64-bit floating point number to the QS record.
#define | QS_STR(str_) QS::str(str_)
Output formatted zero-terminated ASCII string to the QS record.
#define | QS_STR_ROM(str_) QS::str_ROM(str_)
Output formatted zero-terminated ASCII string from ROM to the QS record.
#define | QS_MEM(mem_, size_) QS::mem((mem_), (size_))
Output formatted memory block of up to 255 bytes to the QS record.
#define | QS_OBJ(obj_) QS::u32(QS_OBJ_T, (uint32_t)(obj_))
Output formatted object pointer to the QS record.
#define | QS_FUN(fun_) QS::u32(QS_FUN_T, (uint32_t)(fun_))
Output formatted function pointer to the QS record.
#define | QS_SIG_DICTIONARY(sig_, obj_)
Output signal dictionary record.
#define | QS_OBJ_DICTIONARY(obj_)
Output object dictionary record.
#define | QS_FUN_DICTIONARY(fun_)
Output function dictionary record.
#define | QS_FLUSH() QS::onFlush()
Flush the QS trace data to the host.
#define | QF_QS_INT_LOCK()
Output the interrupt lock record.
#define | QF_QS_INT_UNLOCK()
Output the interrupt unlock record.
#define | QF_QS_ISR_ENTRY(isrnest_, prio_)
Output the interrupt entry record.
#define | QF_QS_ISR_EXIT(isrnest_, prio_)
Output the interrupt exit record.
#define | QF_QS_ACTION(act_) (act_)
Execute an action that is only necessary for QS output.

Enumerations

enum QSpyRecords { ,
QS_QEP_STATE_ENTRY, QS_QEP_STATE_EXIT, QS_QEP_STATE_INIT, QS_QEP_INIT_TRAN,
QS_QEP_INTERN_TRAN, QS_QEP_TRAN, QS_QEP_IGNORED, QS_QEP_DISPATCH ,
QS_QF_ACTIVE_ADD, QS_QF_ACTIVE_REMOVE, QS_QF_ACTIVE_SUBSCRIBE, QS_QF_ACTIVE_UNSUBSCRIBE,
QS_QF_ACTIVE_POST_FIFO, QS_QF_ACTIVE_POST_LIFO, QS_QF_ACTIVE_GET, QS_QF_ACTIVE_GET_LAST,
QS_QF_EQUEUE_INIT, QS_QF_EQUEUE_POST_FIFO, QS_QF_EQUEUE_POST_LIFO, QS_QF_EQUEUE_GET,
QS_QF_EQUEUE_GET_LAST, QS_QF_MPOOL_INIT, QS_QF_MPOOL_GET, QS_QF_MPOOL_PUT,
QS_QF_PUBLISH , QS_QF_NEW, QS_QF_GC_ATTEMPT, QS_QF_GC,
QS_QF_TICK, QS_QF_TIMEEVT_ARM, QS_QF_TIMEEVT_AUTO_DISARM, QS_QF_TIMEEVT_DISARM_ATTEMPT,
QS_QF_TIMEEVT_DISARM, QS_QF_TIMEEVT_REARM, QS_QF_TIMEEVT_POST , QS_QF_INT_LOCK,
QS_QF_INT_UNLOCK, QS_QF_ISR_ENTRY, QS_QF_ISR_EXIT , QS_QK_MUTEX_LOCK,
QS_QK_MUTEX_UNLOCK, QS_QK_SCHEDULE , QS_SIG_DICTIONARY, QS_OBJ_DICTIONARY,
QS_FUN_DICTIONARY, QS_ASSERT , QS_USER
}

Quantum Spy record types.

More...
enum QSType {
QS_I8_T, QS_U8_T, QS_I16_T, QS_U16_T,
QS_I32_T, QS_U32_T, QS_F32_T, QS_F64_T,
QS_STR_T, QS_MEM_T, QS_SIG_T, QS_OBJ_T,
QS_FUN_T
}

Enumerates data formats recognized by QS.

More...

Variables

uint8_t QF_intLockNest_
interrupt-lock nesting level

Detailed Description

QS/C++ platform-independent public interface. This header file must be included directly or indirectly in all modules (*.cpp files) that use QS/C++.

Definition in file qs.h.

Define Documentation

#define QS_BEGIN | ( | rec_,
 |  | obj_
 | ) |
Value:
if (((QS::glbFilter_[(uint8_t)(rec_) >> 3U] \
          & (1U << ((uint8_t)(rec_) & 7U))) != 0U) \
        && ((QS::apObj_ == (void *)0) || (QS::apObj_ == (obj_)))) \
    { \
        QS_INT_LOCK_KEY_ \
        QS_INT_LOCK_(); \
        QS::begin((uint8_t)(rec_)); \
        QS_TIME_();

Begin a user QS record with locking interrupts.

The following example shows how to build a user QS record using the macros QS_BEGIN, QS_END, and the formatted output macros: QS_U8 and QS_STR.

enum UserSpyRecords {
    QS_QDPP_DISPLAY = QS_USER                      // define user record types
    . . .
};

void displyPhilStat(uint8_t n, char const *stat) {
    . . .

    QS_BEGIN(QS_QDPP_DISPLAY);                      // output a user QS record
        QS_U8(1, n);
        QS_STR(stat);
    QS_END();
}
Note:
Must always be used in pair with QS_END

Definition at line 646 of file qs.h.

#define QS_BEGIN_ | ( | rec_,
 |  | objFilter_,
 |  | obj_
 | ) |
Value:
if (((QS::glbFilter_[(uint8_t)(rec_) >> 3U] \
          & (1U << ((uint8_t)(rec_) & 7U))) != 0U) \
        && (((objFilter_) == (void *)0) || ((objFilter_) == (obj_)))) \
    { \
        QS_INT_LOCK_(); \
        QS::begin((uint8_t)(rec_));

Internal QS macro to begin a QS record with locking the interrupts.

Note:
This macro is intended to use only inside QP components and NOT at the application level.
See also:
QS_BEGIN

Definition at line 669 of file qs.h.

Referenced by QHsm::dispatch(), QFsm::dispatch(), QEP::getVersion(), QMPool::init(), QHsm::init(), QFsm::init(), QEQueue::init(), and QF::new_().

#define QS_BEGIN_NOLOCK_ | ( | rec_,
 |  | objFilter_,
 |  | obj_
 | ) |
Value:
if (((QS::glbFilter_[(uint8_t)(rec_) >> 3U] \
          & (1U << ((uint8_t)(rec_) & 7U))) != 0U) \
        && (((objFilter_) == (void *)0) || ((objFilter_) == (obj_)))) \
    { \
        QS::begin((uint8_t)(rec_));

Internal QS macro to begin a QS record without locking the interrupts.

Note:
This macro is intended to use only inside QP components and NOT at the application level.
See also:
QS_BEGIN_NOLOCK

Definition at line 689 of file qs.h.

Referenced by QTimeEvt::disarm(), QF::gc(), QMPool::get(), QEQueue::get(), QActive::get_(), QF::getVersion(), QK::getVersion(), QK::mutexLock(), QK::mutexUnlock(), QEQueue::postFIFO(), QActive::postFIFO(), QEQueue::postLIFO(), QActive::postLIFO(), QF::publish(), QMPool::put(), QTimeEvt::rearm(), QF::remove_(), QActive::subscribe(), QF::tick(), QActive::unsubscribe(), and QActive::unsubscribeAll().

#define QS_END ( ) QS_END_()

End a QS record with locking interrupts.

See also:
example for QS_BEGIN
Note:
Must always be used in pair with QS_BEGIN

Definition at line 659 of file qs.h.

#define QS_END_ ( )
Value:
QS::end(); \
        QS_INT_UNLOCK_(); \
    }

Internal QS macro to end a QS record with locking the interrupts.

Note:
This macro is intended to use only inside QP components and NOT at the application level.
See also:
QS_END

Definition at line 680 of file qs.h.

Referenced by QHsm::dispatch(), QFsm::dispatch(), QMPool::init(), QHsm::init(), QFsm::init(), QEQueue::init(), and QF::new_().

#define QS_END_NOLOCK_ ( )
Value:
QS::end(); \
    }

Internal QS macro to end a QS record without locking the interrupts.

Note:
This macro is intended to use only inside QP components and NOT at the application level.
See also:
QS_END_NOLOCK

Definition at line 700 of file qs.h.

Referenced by QTimeEvt::disarm(), QF::gc(), QMPool::get(), QEQueue::get(), QActive::get_(), QF::getVersion(), QK::mutexLock(), QK::mutexUnlock(), QEQueue::postFIFO(), QActive::postFIFO(), QEQueue::postLIFO(), QActive::postLIFO(), QF::publish(), QMPool::put(), QTimeEvt::rearm(), QF::remove_(), QActive::subscribe(), QF::tick(), QActive::unsubscribe(), and QActive::unsubscribeAll().

#define QS_EXIT ( ) QS::onCleanup()

Cleanup the QS facility.

This macro provides an indirection layer to invoke the QS cleanup routine if #Q_SPY is defined, or do nothing if #Q_SPY is not defined.

See also:
QS::onCleanup()

Definition at line 453 of file qs.h.

#define QS_FILTER_AO_OBJ ( obj_ ) (QS::aoObj_ = (obj_))

Local Filter for a given active object obj_.

This macro sets up the active object local filter if #Q_SPY is defined, or does nothing if #Q_SPY is not defined. The argument obj_ is the pointer to the active object that you want to monitor.

The active object filter allows you to filter QS records pertaining only to a given active object. With this filter disabled, QS will output records from all active objects in your application. The object filter is disabled by setting the active object pointer obj_ to NULL.

The active object filter affects the following QS records: QS_QF_ACTIVE_ADD, QS_QF_ACTIVE_REMOVE, QS_QF_ACTIVE_SUBSCRIBE, QS_QF_ACTIVE_UNSUBSCRIBE, QS_QF_ACTIVE_POST_FIFO, QS_QF_ACTIVE_POST_LIFO, QS_QF_ACTIVE_GET, and QS_QF_ACTIVE_GET_LAST.

See also:
Example of using QS filters in QS_FILTER_ON documentation

Definition at line 514 of file qs.h.

#define QS_FILTER_AP_OBJ ( obj_ ) (QS_apObj_ = (obj_))

Local Filter for a generic application object obj_.

This macro sets up the local application object filter if #Q_SPY is defined, or does nothing if #Q_SPY is not defined. The argument obj_ is the pointer to the application object you want to monitor.

The application object filter allows you to filter QS records pertaining only to a given application object. With this filter disabled, QS will output records from all application-records enabled by the global filter. The local filter is disabled by setting the time event pointer obj_ to NULL.

See also:
Example of using QS filters in QS_FILTER_ON documentation

Definition at line 584 of file qs.h.

#define QS_FILTER_EQ_OBJ ( obj_ ) (QS::eqObj_ = (obj_))

Filter for a given event queue object obj_.

This macro sets up the event queue object filter if #Q_SPY is defined, or does nothing if #Q_SPY is not defined. The argument obj_ is the pointer to the "raw" thread-safe queue object you want to monitor.

The event queue filter allows you to filter QS records pertaining only to a given event queue. With this filter disabled, QS will output records from all event queues in your application. The object filter is disabled by setting the event queue pointer obj_ to NULL.

The event queue filter affects the following QS records: QS_QF_EQUEUE_INIT, QS_QF_EQUEUE_POST_FIFO, QS_QF_EQUEUE_POST_LIFO, QS_QF_EQUEUE_GET, and QS_QF_EQUEUE_GET_LAST.

See also:
Example of using QS filters in #QS_FILTER_IN documentation

Definition at line 550 of file qs.h.

#define QS_FILTER_MP_OBJ ( obj_ ) (QS::mpObj_ = (obj_))

Local Filter for a given memory pool object obj_.

This macro sets up the memory pool object local filter if #Q_SPY is defined, or does nothing if #Q_SPY is not defined. The argument obj_ is the pointer to the memory buffer used during the initialization of the event pool with QF::poolInit().

The memory pool filter allows you to filter QS records pertaining only to a given memory pool. With this filter disabled, QS will output records from all memory pools in your application. The object filter is disabled by setting the memory pool pointer obj_ to NULL.

The memory pool filter affects the following QS records: QS_QF_MPOOL_INIT, QS_QF_MPOOL_GET, and QS_QF_MPOOL_PUT.

See also:
Example of using QS filters in QS_FILTER_ON documentation

Definition at line 532 of file qs.h.

#define QS_FILTER_OFF ( rec_ ) QS::filterOff(rec_)

Global filter OFF for a given record type rec.

This macro provides an indirection layer to call QS::filterOff() if #Q_SPY is defined, or do nothing if #Q_SPY is not defined.

See also:
Example of using QS filters in QS_FILTER_ON documentation

Definition at line 470 of file qs.h.

#define QS_FILTER_ON ( rec_ ) QS::filterOn(rec_)

Global Filter ON for a given record type rec.

This macro provides an indirection layer to call QS::filterOn() if #Q_SPY is defined, or do nothing if #Q_SPY is not defined.

The following example shows how to use QS filters:

main () {
    . . .

    if (!QS_INIT("1")) {                      // Initialize QSpy to use UART 1
        return -1;                                // Unable to initialize QSpy
    }
    QS_FILTER_IN(QS_ALL_RECORDS);        // start with enabling all QS records

    QS_FILTER_OUT(QS_QK_INT_LOCK);         // disable QS output of this record
    QS_FILTER_OUT(QS_QK_INT_UNLOCK);       // disable QS output of this record
    QS_FILTER_OUT(QS_QK_ISR_ENTRY);        // disable QS output of this record
    QS_FILTER_OUT(QS_QK_ISR_EXIT);         // disable QS output of this record

    QS_FILTER_SM_OBJ(&philo[3]);       // trace only this state machine object

    QS_FILTER_AO_OBJ(&philo[3]);              // trace only this active object

    QS_FILTER_MP_OBJ(regSizePoolSto);            // trace only this event pool

    QS_FILTER_EQ_OBJ(&rawQueue);                // trace only this event queue

    QS_FILTER_TE_OBJ(&philo[3].timeEvt__);       // trace only this time event

    . . .
}

Definition at line 462 of file qs.h.

#define QS_FILTER_SM_OBJ ( obj_ ) (QS::smObj_ = (obj_))

Local Filter for a given state machine object obj_.

This macro sets up the state machine object local filter if #Q_SPY is defined, or does nothing if #Q_SPY is not defined. The argument obj_ is the pointer to the state machine object that you want to monitor.

The state machine object filter allows you to filter QS records pertaining only to a given state machine object. With this filter disabled, QS will output records from all state machines in your application. The object filter is disabled by setting the state machine pointer to NULL.

The state machine filter affects the following QS records: QS_QEP_STATE_ENTRY, QS_QEP_STATE_EXIT, QS_QEP_STATE_INIT, QS_QEP_INIT_TRAN, QS_QEP_INTERN_TRAN, QS_QEP_TRAN, and QS_QEP_IGNORED.

Note:
Because active objects are state machines at the same time, the state machine filter (QS_FILTER_SM_OBJ) pertains to active objects as well. However, the state machine filter is more general, because it can be used only for state machines that are not active objects, such as "Orthogonal Components".
See also:
Example of using QS filters in QS_FILTER_ON documentation

Definition at line 495 of file qs.h.

#define QS_FILTER_TE_OBJ ( obj_ ) (QS::teObj_ = (obj_))

Local Filter for a given time event object obj_.

This macro sets up the time event object local filter if #Q_SPY is defined, or does nothing if #Q_SPY is not defined. The argument obj_ is the pointer to the time event object you want to monitor.

The time event filter allows you to filter QS records pertaining only to a given time event. With this filter disabled, QS will output records from all time events in your application. The object filter is disabled by setting the time event pointer obj_ to NULL.

The time event filter affects the following QS records: QS_QF_TIMEEVT_ARM, QS_QF_TIMEEVT_AUTO_DISARM, QS_QF_TIMEEVT_DISARM_ATTEMPT, QS_QF_TIMEEVT_DISARM, QS_QF_TIMEEVT_REARM, QS_QF_TIMEEVT_POST, and ::QS_QF_TIMEEVT_PUBLISH.

See also:
Example of using QS filters in QS_FILTER_ON documentation

Definition at line 569 of file qs.h.

#define QS_FLUSH ( ) QS::onFlush()

Flush the QS trace data to the host.

This macro invokes the QS::flush() platform-dependent callback function to flush the QS trace buffer to the host. The function typically busy-waits until all the data in the buffer is sent to the host. This is acceptable only in the initial transient.

Definition at line 958 of file qs.h.

Referenced by QActive::start().

#define QS_FUN_ ( fun_ ) QS::u32_((uint32_t)(fun_))

Internal QS macro to output an unformatted function pointer data element.

Note:
the size of the pointer depends on the macro #QS_FUN_PTR_SIZE. If the size is not defined the size of pointer is assumed 4-bytes.

Definition at line 742 of file qs.h.

Referenced by QHsm::dispatch(), QFsm::dispatch(), QEP::getVersion(), QHsm::init(), and QFsm::init().

#define QS_FUN_DICTIONARY ( fun_ )
Value:
if (((QS::glbFilter_[(uint8_t)QS_FUN_DICTIONARY >> 3U] \
          & (1U << ((uint8_t)QS_FUN_DICTIONARY & 7U))) != 0U)) \
    { \
        static char const Q_ROM Q_ROM_VAR fun_name__[] = #fun_; \
        QS_INT_LOCK_KEY_ \
        QS_INT_LOCK_(); \
        QS::begin((uint8_t)QS_FUN_DICTIONARY); \
        QS_FUN_(fun_); \
        QS_STR_ROM_(fun_name__); \
        QS::end(); \
        QS_INT_UNLOCK_(); \
        QS::onFlush(); \
    } else ((void)0)

Output function dictionary record.

A function dictionary record associates the binary address of a function in the target's memory with the human-readable name of the function.

Providing a function dictionary QS record can vastly improve readability of the QS log, because instead of dealing with cryptic machine addresses the QSpy host utility can display human-readable function names.

The example from QS_SIG_DICTIONARY shows the definition of a function dictionary.

Definition at line 937 of file qs.h.

#define QS_INIT ( arg_ ) QS::onStartup(arg_)

Initialize the QS facility.

This macro provides an indirection layer to invoke the QS initialization routine if #Q_SPY is defined, or do nothing if #Q_SPY is not defined.

See also:
QS::onStartup(), example of setting up a QS filter in #QS_FILTER_IN

Definition at line 446 of file qs.h.

#define QS_INT_LOCK_ ( ) QF_INT_LOCK(ignore_)

This is an internal macro for locking interrupts.

The purpose of this macro is to enable writing the same code for the case when interrupt key is defined and when it is not. If the macro #QS_INT_KEY_TYPE is defined, this internal macro invokes #QS_INT_LOCK passing the key variable as the parameter. Otherwise #QS_INT_LOCK is invoked with a dummy parameter.

See also:
#QS_INT_LOCK, QF_INT_LOCK, #QK_INT_LOCK

Definition at line 622 of file qs.h.

#define QS_INT_LOCK_KEY_

This is an internal macro for defining the interrupt lock key.

The purpose of this macro is to enable writing the same code for the case when interrupt key is defined and when it is not. If the macro #QS_INT_KEY_TYPE is defined, this internal macro provides the definition of the lock key variable. Otherwise this macro is empty.

See also:
#QS_INT_KEY_TYPE, QF_INT_KEY_TYPE

Definition at line 612 of file qs.h.

Referenced by QHsm::dispatch(), QFsm::dispatch(), QMPool::init(), QHsm::init(), QFsm::init(), QEQueue::init(), and QF::new_().

#define QS_INT_UNLOCK_ ( ) QF_INT_UNLOCK(ignore_)

This is an internal macro for unlocking interrupts.

The purpose of this macro is to enable writing the same code for the case when interrupt key is defined and when it is not. If the macro #QS_INT_KEY_TYPE is defined, this internal macro invokes #QS_INT_UNLOCK passing the key variable as the parameter. Otherwise #QS_INT_UNLOCK is invoked with a dummy parameter.

See also:
#QS_INT_UNLOCK, QF_INT_UNLOCK, #QK_INT_UNLOCK

Definition at line 632 of file qs.h.

#define QS_OBJ_ ( obj_ ) QS::u32_((uint32_t)(obj_))

Internal QS macro to output an unformatted object pointer data element.

Note:
the size of the pointer depends on the macro #QS_OBJ_PTR_SIZE. If the size is not defined the size of pointer is assumed 4-bytes.

Definition at line 726 of file qs.h.

Referenced by QTimeEvt::disarm(), QHsm::dispatch(), QFsm::dispatch(), QMPool::get(), QEQueue::get(), QActive::get_(), QF::getVersion(), QEP::getVersion(), QMPool::init(), QHsm::init(), QFsm::init(), QEQueue::init(), QEQueue::postFIFO(), QActive::postFIFO(), QEQueue::postLIFO(), QActive::postLIFO(), QMPool::put(), QTimeEvt::rearm(), QF::remove_(), QActive::subscribe(), QF::tick(), QActive::unsubscribe(), and QActive::unsubscribeAll().

#define QS_OBJ_DICTIONARY ( obj_ )
Value:
if (((QS::glbFilter_[(uint8_t)QS_OBJ_DICTIONARY >> 3U] \
          & (1U << ((uint8_t)QS_OBJ_DICTIONARY & 7U))) != 0U)) \
    { \
        static char const Q_ROM Q_ROM_VAR obj_name__[] = #obj_; \
        QS_INT_LOCK_KEY_ \
        QS_INT_LOCK_(); \
        QS::begin((uint8_t)QS_OBJ_DICTIONARY); \
        QS_OBJ_(obj_); \
        QS_STR_ROM_(obj_name__); \
        QS::end(); \
        QS_INT_UNLOCK_(); \
        QS::onFlush(); \
    } else ((void)0)

Output object dictionary record.

An object dictionary record associates the binary address of an object in the target's memory with the human-readable name of the object.

Providing an object dictionary QS record can vastly improve readability of the QS log, because instead of dealing with cryptic machine addresses the QSpy host utility can display human-readable object names.

The following example shows the definition of object dictionary entry for the Table active object:

void tableStart(uint8_t prio,
                QEvent const *qSto[], uint32_t qLen,
                void *stkSto, uint32_t stkSize)
{
    static Table table;

    QS_OBJ_DICTIONARY(table);           // provide object dictionary for table

    table.start(prio,
                qSto, qLen, stkSto, stkSize,
                (QEvent *)0);
}

Definition at line 911 of file qs.h.

#define QS_SIG_DICTIONARY | ( | sig_,
 |  | obj_
 | ) |
Value:
if (((QS::glbFilter_[(uint8_t)QS_SIG_DICTIONARY >> 3U] \
          & (1U << ((uint8_t)QS_SIG_DICTIONARY & 7U))) != 0U)) \
    { \
        static char const Q_ROM Q_ROM_VAR sig_name__[] = #sig_; \
        QS_INT_LOCK_KEY_ \
        QS_INT_LOCK_(); \
        QS::begin((uint8_t)QS_SIG_DICTIONARY); \
        QS_SIG_(sig_); \
        QS_OBJ_(obj_); \
        QS_STR_ROM_(sig_name__); \
        QS::end(); \
        QS_INT_UNLOCK_(); \
        QS::onFlush(); \
    } else ((void)0)

Output signal dictionary record.

A signal dictionary record associates the numerical value of the signal and the binary address of the state machine that consumes that signal with the human-readable name of the signal.

Providing a signal dictionary QS record can vastly improve readability of the QS log, because instead of dealing with cryptic machine addresses the QSpy host utility can display human-readable names.

A signal dictionary entry is associated with both the signal value sig_ and the state machine obj_, because signals are required to be unique only within a given state machine and therefore the same numerical values can represent different signals in different state machines.

For the "global" signals that have the same meaning in all state machines (such as globally published signals), you can specify a signal dictionary entry with the obj_ parameter set to NULL.

The following example shows the definition of signal dictionary entries in the initial transition of the Table active object. Please note that signals HUNGRY_SIG and DONE_SIG are associated with the Table state machine only ("me" obj_ pointer). The EAT_SIG signal, on the other hand, is global (0 obj_ pointer):

QState Table::initial(Table *me, QEvent const *) {
    uint8_t n;

    QS_SIG_DICTIONARY(HUNGRY_SIG, me);   // output signal dictionary QS record
    QS_SIG_DICTIONARY(DONE_SIG, me);     // output signal dictionary QS record
    QS_SIG_DICTIONARY(EAT_SIG, 0);       // output signal dictionary QS record

    QS_FUN_DICTIONARY(Table::serving);

    subscribe(HUNGRY_SIG);
    subscribe(DONE_SIG);
    subscribe(TERMINATE_SIG);

    for (n = 0; n < N; ++n) {
        me->fork__[n] = FREE;
        me->isHungry__[n] = 0;
    }
    return Q_TRAN(&Table::serving);
}
Note:
The QSpy log utility must capture the signal dictionary record in order to use the human-readable information. You need to connect to the target before the dictionary entries have been transmitted.

The following QSpy log example shows the signal dictionary records generated from the Table initial transition and subsequent records that show human-readable names of the signals:

qspy -fqs.bin -S2 -Q2 -P4 -p4 -T4
QSpy 4.0.00
Thu Apr 06 09:56:10 2005
-f qs.bin
-S 2
-Q 2
-P 4
-p 4
-T 4
. . .      . . .
           Obj Dic: 00419048->table
           EQ.INIT: Obj=00419050 Len= 5
0000000000 AO.ADD : Active=table Prio=51
           Fun Dic: 00401CEE->Table_serving
           Sig Dic: 00000004,Obj=00419048 ->HUNGRY_SIG
           Sig Dic: 00000005,Obj=00419048 ->DONE_SIG
           Sig Dic: 00000006,Obj=00000000 ->EAT_SIG
0000000000 AO.SUB : Active=table Sig=HUNGRY_SIG
0000000000 AO.SUB : Active=table Sig=DONE_SIG
0000000000 AO.SUB : Active=table Sig=00000007,Obj=00419048
           Q_INIT : Obj=table Source=00403CE0 Target=Table_serving
0000000000 ==>Init: Obj=table New=Table_serving
. . .      . . .

// the Philosophers become hungry...

0000000007 AO.FIFO: Obj=table Evt(Sig=HUNGRY_SIG, Pool=1, Ref= 1)
           Queue(nUsed=  0, nMax=  0)
0000000007 AO.FIFO: Obj=table Evt(Sig=HUNGRY_SIG, Pool=1, Ref= 1)
           Queue(nUsed=  0, nMax=  0)
0000000007 AO.FIFO: Obj=table Evt(Sig=HUNGRY_SIG, Pool=1, Ref= 1)
           Queue(nUsed=  1, nMax=  1)
0000000007 AO.FIFO: Obj=table Evt(Sig=HUNGRY_SIG, Pool=1, Ref= 1)
           Queue(nUsed=  2, nMax=  2)
           Q_ENTRY: Obj=philo[2] State=Philosopher_hungry
0000000007 AO.GET : Active= table Evt(Sig=HUNGRY_SIG, Pool=1, Ref= 1)
           Queue(nUsed=  2)
0000000007 AO.FIFO: Obj=table Evt(Sig=HUNGRY_SIG, Pool=1, Ref= 1)
           Queue(nUsed=  2, nMax=  3)
           Q_ENTRY: Obj=philo[4] State=Philosopher_hungry
           Q_ENTRY: Obj=philo[1] State=Philosopher_hungry
           Q_ENTRY: Obj=philo[3] State=Philosopher_hungry
0000000007 ==>Tran: Obj=philo[2] Sig=TIMEOUT_SIG Source=Philosopher_thinking
           New=Philosopher_hungry
0000000007 ==>Tran: Obj=philo[4] Sig=TIMEOUT_SIG Source=Philosopher_thinking
           New=Philosopher_hungry
0000000007 ==>Tran: Obj=philo[3] Sig=TIMEOUT_SIG Source=Philosopher_thinking
           New=Philosopher_hungry
0000000007 ==>Tran: Obj=philo[1] Sig=TIMEOUT_SIG Source=Philosopher_thinking
           New=Philosopher_hungry
           Q_ENTRY: Obj=philo[0] State=Philosopher_hungry
0000000007 ==>Tran: Obj=philo[0] Sig=TIMEOUT_SIG Source=Philosopher_thinking
           New=Philosopher_hungry

// user record output
0000000007 User070: 2 hungry

// Table grants permissions to eat
0000000007 NEW    : Evt(Sig=EAT_SIG, size=    6)
0000000007 MP.GET : Obj=00418E18 nFree=   5 nMin=   5
0000000007 AO.FIFO: Obj=philo[4] Evt(Sig=EAT_SIG, Pool=1, Ref= 0)
           Queue(nUsed=  0, nMax=  0)
0000000007 AO.FIFO: Obj=philo[3] Evt(Sig=EAT_SIG, Pool=1, Ref= 0)
           Queue(nUsed=  0, nMax=  0)
0000000007 AO.FIFO: Obj=philo[2] Evt(Sig=EAT_SIG, Pool=1, Ref= 0)
           Queue(nUsed=  0, nMax=  0)
0000000007 AO.FIFO: Obj=philo[1] Evt(Sig=EAT_SIG, Pool=1, Ref= 0)
           Queue(nUsed=  0, nMax=  0)
0000000007 AO.FIFO: Obj=philo[0] Evt(Sig=EAT_SIG, Pool=1, Ref= 0)
           Queue(nUsed=  0, nMax=  0)
0000000007 PUBLISH: Evt(Sig=EAT_SIG, Pool=1, Ref= 5) nSubsr=  5
0000000007 AO.GETL: Active= philo[4] Evt(Sig=EAT_SIG, Pool=1, Ref= 5)
0000000007 AO.GETL: Active= philo[2] Evt(Sig=EAT_SIG, Pool=1, Ref= 5)
0000000007 AO.GETL: Active= philo[3] Evt(Sig=EAT_SIG, Pool=1, Ref= 5)
0000000007 AO.GETL: Active= philo[1] Evt(Sig=EAT_SIG, Pool=1, Ref= 5)
0000000007 AO.GETL: Active= philo[0] Evt(Sig=EAT_SIG, Pool=1, Ref= 5)
. . .      . . .

The following QSpy log example shows the same sequence of records, but with dictionary records removed. The human-readable signal names are not available.

qspy -fqs0.bin -S2 -Q2 -P4 -p4 -T4
QSpy 4.0.00
Thu Apr 06 10:10:22 2005
-f qs0.bin
-S 2
-Q 2
-P 4
-p 4
-T 4
. . .      . . .
           Obj Dic: 00419048->table
           EQ.INIT: Obj=00419050 Len= 5
0000000000 AO.ADD : Active=table Prio=51

// the signal dictionary entries removed from the binary QS log
*** Dropped   4 records

0000000000 AO.SUB : Active=table Sig=00000004,Obj=00419048
0000000000 AO.SUB : Active=table Sig=00000005,Obj=00419048
0000000000 AO.SUB : Active=table Sig=00000007,Obj=00419048
           Q_INIT : Obj=table Source=00403CE0 Target=00403CE0
0000000000 ==>Init: Obj=table New=00401CEE
. . .      . . .

// the Philosophers become hungry...

0000000007 AO.FIFO: Obj=table Evt(Sig=00000004,Obj=00419048, Pool=1, Ref= 1)
           Queue(nUsed=  0, nMax=  0)
0000000007 AO.FIFO: Obj=table Evt(Sig=00000004,Obj=00419048, Pool=1, Ref= 1)
           Queue(nUsed=  0, nMax=  0)
0000000007 AO.FIFO: Obj=table Evt(Sig=00000004,Obj=00419048, Pool=1, Ref= 1)
           Queue(nUsed=  1, nMax=  1)
0000000007 AO.FIFO: Obj=table Evt(Sig=00000004,Obj=00419048, Pool=1, Ref= 1)
           Queue(nUsed=  2, nMax=  2)
           Q_ENTRY: Obj=philo[2] State=Philosopher_hungry
0000000007 AO.GET : Active= table Evt(Sig=00000004,Obj=00419048, Pool=1, Ref= 1)
           Queue(nUsed=  2)
0000000007 AO.FIFO: Obj=table Evt(Sig=00000004,Obj=00419048, Pool=1, Ref= 1)
           Queue(nUsed=  2, nMax=  3)
           Q_ENTRY: Obj=philo[4] State=Philosopher_hungry
           Q_ENTRY: Obj=philo[1] State=Philosopher_hungry
           Q_ENTRY: Obj=philo[3] State=Philosopher_hungry
0000000007 ==>Tran: Obj=philo[2] Sig=TIMEOUT_SIG Source=Philosopher_thinking
           New=Philosopher_hungry
0000000007 ==>Tran: Obj=philo[4] Sig=TIMEOUT_SIG Source=Philosopher_thinking
           New=Philosopher_hungry
0000000007 ==>Tran: Obj=philo[3] Sig=TIMEOUT_SIG Source=Philosopher_thinking
           New=Philosopher_hungry
0000000007 ==>Tran: Obj=philo[1] Sig=TIMEOUT_SIG Source=Philosopher_thinking
           New=Philosopher_hungry
           Q_ENTRY: Obj=philo[0] State=Philosopher_hungry
0000000007 ==>Tran: Obj=philo[0] Sig=TIMEOUT_SIG Source=Philosopher_thinking
           New=Philosopher_hungry

// user record output
0000000007 User070: 2 hungry

// Table grants permissions to eat
0000000007 NEW    : Evt(Sig=00000006,Obj=00000000, size=    6)
0000000007 MP.GET : Obj=00418E18 nFree=   5 nMin=   5
0000000007 AO.FIFO: Obj=philo[4] Evt(Sig=00000006,Obj=00419000, Pool=1, Ref= 0)
           Queue(nUsed=  0, nMax=  0)
0000000007 AO.FIFO: Obj=philo[3] Evt(Sig=00000006,Obj=00418FBC, Pool=1, Ref= 0)
           Queue(nUsed=  0, nMax=  0)
0000000007 AO.FIFO: Obj=philo[2] Evt(Sig=00000006,Obj=00418F78, Pool=1, Ref= 0)
           Queue(nUsed=  0, nMax=  0)
0000000007 AO.FIFO: Obj=philo[1] Evt(Sig=00000006,Obj=00418F34, Pool=1, Ref= 0)
           Queue(nUsed=  0, nMax=  0)
0000000007 AO.FIFO: Obj=philo[0] Evt(Sig=00000006,Obj=00418EF0, Pool=1, Ref= 0)
           Queue(nUsed=  0, nMax=  0)
0000000007 PUBLISH: Evt(Sig=00000006,Obj=00000000, Pool=1, Ref= 5) nSubsr=  5
0000000007 AO.GETL: Active= philo[4] Evt(Sig=00000006,Obj=00419000, Pool=1, Ref= 5)
0000000007 AO.GETL: Active= philo[2] Evt(Sig=00000006,Obj=00418F78, Pool=1, Ref= 5)
0000000007 AO.GETL: Active= philo[3] Evt(Sig=00000006,Obj=00418FBC, Pool=1, Ref= 5)
0000000007 AO.GETL: Active= philo[1] Evt(Sig=00000006,Obj=00418F34, Pool=1, Ref= 5)
0000000007 AO.GETL: Active= philo[0] Evt(Sig=00000006,Obj=00418EF0, Pool=1, Ref= 5)
. . .      . . .

Definition at line 883 of file qs.h.

#define QS_TIME_SIZE 4

The size (in bytes) of the QS time stamp. Valid values: 1, 2, or 4; default 4.

This macro can be defined in the QS port file (qs_port.h) to configure the ::QSTimeCtr type. Here the macro is not defined so the default of 4 byte is chosen.

Definition at line 149 of file qs.h.

Enumeration Type Documentation

enum QSpyRecords

Quantum Spy record types.

This enumeration specifies the record types used in the QP components. You can specify your own record types starting from QS_USER offset. Currently, the maximum of all records cannot exceed 256.

See also:
QS::filterOn()/QS_FILTER_ON and QS::filterOff()/QS_FILTER_OFF
Enumerator:
QS_QEP_STATE_ENTRY

a state was entered

QS_QEP_STATE_EXIT

a state was exited

QS_QEP_STATE_INIT

an intial transition was taken in a state

QS_QEP_INIT_TRAN

the top-most initial transition was taken

QS_QEP_INTERN_TRAN

an internal transition was taken

QS_QEP_TRAN

a regular transition was taken

QS_QEP_IGNORED

an event was ignored (silently discarded)

QS_QEP_DISPATCH

an event was dispatched (begin of RTC step)

QS_QF_ACTIVE_ADD

an AO has been added to QF (started)

QS_QF_ACTIVE_REMOVE

an AO has been removed from QF (stopped)

QS_QF_ACTIVE_SUBSCRIBE

an AO subscribed to an event

QS_QF_ACTIVE_UNSUBSCRIBE

an AO unsubscribed to an event

QS_QF_ACTIVE_POST_FIFO

an event was posted (FIFO) directly to an AO

QS_QF_ACTIVE_POST_LIFO

an event was posted (LIFO) directly to an AO

QS_QF_ACTIVE_GET

an AO got an event and its queue is still not empty

QS_QF_ACTIVE_GET_LAST

an AO got an event and its queue is empty

QS_QF_EQUEUE_INIT

an event queue was initialized

QS_QF_EQUEUE_POST_FIFO

an event was posted (FIFO) to a raw queue

QS_QF_EQUEUE_POST_LIFO

an event was posted (LIFO) to a raw queue

QS_QF_EQUEUE_GET

get an event and queue still not empty

QS_QF_EQUEUE_GET_LAST

get the last event from the queue

QS_QF_MPOOL_INIT

a memory pool was initialized

QS_QF_MPOOL_GET

a memory block was removed from a memory pool

QS_QF_MPOOL_PUT

a memory block was returned to a memory pool

QS_QF_PUBLISH

an event was truly published to some subscribers

QS_QF_NEW

new event creation

QS_QF_GC_ATTEMPT

garbage collection attempt

QS_QF_GC

garbage collection

QS_QF_TICK

QF::tick() was called.

QS_QF_TIMEEVT_ARM

a time event was armed

QS_QF_TIMEEVT_AUTO_DISARM

a time event expired and was disarmed

QS_QF_TIMEEVT_DISARM_ATTEMPT

an attempt to disarmed a disarmed tevent

QS_QF_TIMEEVT_DISARM

true disarming of an armed time event

QS_QF_TIMEEVT_REARM

rearming of a time event

QS_QF_TIMEEVT_POST

a time event posted itself directly to an AO

QS_QF_INT_LOCK

interrupts were locked

QS_QF_INT_UNLOCK

interrupts were unlocked

QS_QF_ISR_ENTRY

an ISR was entered

QS_QF_ISR_EXIT

an ISR was exited

QS_QK_MUTEX_LOCK

the QK mutex was locked

QS_QK_MUTEX_UNLOCK

the QK mutex was unlocked

QS_QK_SCHEDULE

the QK scheduler scheduled a new task to execute

QS_SIG_DICTIONARY

signal dictionary entry

QS_OBJ_DICTIONARY

object dictionary entry

QS_FUN_DICTIONARY

function dictionary entry

QS_ASSERT

assertion fired in the code

QS_USER

the first record available for user QS records

Definition at line 49 of file qs.h.

enum QSType

Enumerates data formats recognized by QS.

QS uses this enumeration is used only internally for the formatted user data elements.

Enumerator:
QS_I8_T

signed 8-bit integer format

QS_U8_T

unsigned 8-bit integer format

QS_I16_T

signed 16-bit integer format

QS_U16_T

unsigned 16-bit integer format

QS_I32_T

signed 32-bit integer format

QS_U32_T

unsigned 32-bit integer format

QS_F32_T

32-bit floating point format

QS_F64_T

64-bit floating point format

QS_STR_T

zero-terminated ASCII string format

QS_MEM_T

up to 255-bytes memory block format

QS_SIG_T

event signal format

QS_OBJ_T

object pointer format

QS_FUN_T

function pointer format

Definition at line 760 of file qs.h.

Variable Documentation

uint8_t QF_intLockNest_

interrupt-lock nesting level

Note:
Not to be used by Clients directly, only in ports of QF

Definition at line 40 of file qf_act.cpp.


QP/C++: qs_.cpp File Reference

qs_.cpp File Reference

QS functions for internal use inside QP components. More...

#include "qs_pkg.h"

Go to the source code of this file.

Detailed Description

QS functions for internal use inside QP components.

Definition in file qs_.cpp.


QP/C++: qs_blk.cpp File Reference

qs_blk.cpp File Reference

QS::getBlock() implementation. More...

#include "qs_pkg.h"

Go to the source code of this file.

Detailed Description

QS::getBlock() implementation.

Definition in file qs_blk.cpp.


QP/C++: qs_byte.cpp File Reference

qs_byte.cpp File Reference

QS::getByte() implementation. More...

#include "qs_pkg.h"

Go to the source code of this file.

Detailed Description

QS::getByte() implementation.

Definition in file qs_byte.cpp.


QP/C++: qs_dummy.h File Reference

qs_dummy.h File Reference

Dummy definitions of the QS macros that avoid code generation from the QS instrumentation. More...

Go to the source code of this file.

Detailed Description

Dummy definitions of the QS macros that avoid code generation from the QS instrumentation.

Definition in file qs_dummy.h.


QP/C++: qs_f32.cpp File Reference

qs_f32.cpp File Reference

QS::f32() implementation. More...

#include "qs_pkg.h"

Go to the source code of this file.

Detailed Description

QS::f32() implementation.

Definition in file qs_f32.cpp.


QP/C++: qs_f64.cpp File Reference

qs_f64.cpp File Reference

QS::f64() implementation. More...

#include "qs_pkg.h"

Go to the source code of this file.

Detailed Description

QS::f64() implementation.

Definition in file qs_f64.cpp.


QP/C++: qs_mem.cpp File Reference

qs_mem.cpp File Reference

QS::mem() implementation. More...

#include "qs_pkg.h"

Go to the source code of this file.

Detailed Description

QS::mem() implementation.

Definition in file qs_mem.cpp.


QP/C++: qs_pkg.h File Reference

Defines | Typedefs | Variables

qs_pkg.h File Reference

Internal (package scope) QS/C++ interface. More...

#include "qs_port.h"

Go to the source code of this file.

Defines

#define | QS_INSERT_BYTE(b_)
Internal QS macro to insert an un-escaped byte into the QS buffer.
#define | QS_INSERT_ESC_BYTE(b_)
Internal QS macro to insert an escaped byte into the QS buffer.
#define | QS_INSERT_CHKSUM_BYTE()
Internal QS macro to insert a escaped checksum byte into the QS buffer.
#define | QS_FRAME ((uint8_t)0x7E)
Frame character of the QS output protocol.
#define | QS_ESC ((uint8_t)0x7D)
Escape character of the QS output protocol.
#define | QS_ESC_XOR 0x20
Escape modifier of the QS output protocol.
#define | Q_ROM_BYTE(rom_var_) (rom_var_)
Macro to access a byte allocated in ROM.

Typedefs

typedef uint16_t | QSCtr
QS ring buffer counter and offset type.

Variables

uint8_t * QS_ring_
pointer to the start of the ring buffer
QSCtr QS_end_
offset of the end of the ring buffer
QSCtr QS_head_
offset to where next byte will be inserted
QSCtr QS_tail_
offset of where next event will be extracted
QSCtr QS_used_
number of bytes currently in the ring buffer
uint8_t QS_seq_
the record sequence number
uint8_t QS_chksum_
the checksum of the current record
uint8_t QS_full_
the ring buffer is temporarily full

Detailed Description

Internal (package scope) QS/C++ interface.

Definition in file qs_pkg.h.

Define Documentation

#define Q_ROM_BYTE ( rom_var_ ) (rom_var_)

Macro to access a byte allocated in ROM.

Some compilers for Harvard-architecture MCUs, such as gcc for AVR, do not generate correct code for accessing data allocated in the program space (ROM). The workaround for such compilers is to explictly add assembly code to access each data element allocated in the program space. The macro Q_ROM_BYTE() retrieves a byte from the given ROM address.

The Q_ROM_BYTE() macro should be defined for the compilers that cannot handle correctly data allocated in ROM (such as the gcc). If the macro is left undefined, the default definition simply returns the argument and lets the compiler generate the correct code.

Definition at line 101 of file qs_pkg.h.

#define QS_ESC_XOR 0x20

Escape modifier of the QS output protocol.

The escaped byte is XOR-ed with the escape modifier before it is inserted into the QS buffer.

Definition at line 85 of file qs_pkg.h.


QP/C++: qs_port.h File Reference

qs_port.h File Reference

QS/C++ port for a "generic" C++ compiler. More...

#include "qf_port.h"
#include "qs.h"
#include "qs.h"

Go to the source code of this file.

Detailed Description

QS/C++ port for a "generic" C++ compiler.

Note:
This is just an EXAMPLE of a QS port used for "linting" the QS. Ports of QS are located in the directory <qpcpp_3>/ports.

Definition in file qs_port.h.


QP/C++: qs_str.cpp File Reference

qs_str.cpp File Reference

QS::str() and QS::str_ROM() implementation. More...

#include "qs_pkg.h"

Go to the source code of this file.

Detailed Description

QS::str() and QS::str_ROM() implementation.

Definition in file qs_str.cpp.


QP/C++: qte_arm.cpp File Reference

Variables

qte_arm.cpp File Reference

QF_timeEvtListHead_ definition and QTimeEvt::arm_() implementation. More...

#include "qf_pkg.h"
#include "qassert.h"

Go to the source code of this file.

Variables

QTimeEvt * QF_timeEvtListHead_
head of linked list of time events

Detailed Description

QF_timeEvtListHead_ definition and QTimeEvt::arm_() implementation.

Definition in file qte_arm.cpp.


QP/C++: qte_ctor.cpp File Reference

qte_ctor.cpp File Reference

QTimeEvt::QTimeEvt() implementation. More...

#include "qf_pkg.h"
#include "qassert.h"

Go to the source code of this file.

Detailed Description

QTimeEvt::QTimeEvt() implementation.

Definition in file qte_ctor.cpp.


QP/C++: qte_darm.cpp File Reference

qte_darm.cpp File Reference

QTimeEvt::disarm() implementation. More...

#include "qf_pkg.h"

Go to the source code of this file.

Detailed Description

QTimeEvt::disarm() implementation.

Definition in file qte_darm.cpp.


QP/C++: qte_rarm.cpp File Reference

qte_rarm.cpp File Reference

QTimeEvt::rearm() implementation. More...

#include "qf_pkg.h"
#include "qassert.h"

Go to the source code of this file.

Detailed Description

QTimeEvt::rearm() implementation.

Definition in file qte_rarm.cpp.


QP/C++: qvanilla.cpp File Reference

Variables

qvanilla.cpp File Reference

"vanilla" cooperative kernel, QActive::start(), QActive::stop(), and QF::run() implementation. More...

#include "qf_pkg.h"
#include "qassert.h"

Go to the source code of this file.

Variables

QPSet64 volatile QF_readySet_
QF-ready set of active objects.

Detailed Description

"vanilla" cooperative kernel, QActive::start(), QActive::stop(), and QF::run() implementation.

Definition in file qvanilla.cpp.


QP/C++: qvanilla.h File Reference

Variables

qvanilla.h File Reference

platform-independent interface to the cooperative "vanilla" kernel. More...

#include "qequeue.h"
#include "qmpool.h"
#include "qpset.h"

Go to the source code of this file.

Variables

QPSet64 volatile QF_readySet_
QF-ready set of active objects.

Detailed Description

platform-independent interface to the cooperative "vanilla" kernel.

Definition in file qvanilla.h.


QP/C++: File Members

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • i
  • q
  • u
Here is a list of all documented file members with links to the documentation:

- i -

  • int16_t : qep_port.h
  • int32_t : qep_port.h
  • int8_t : qep_port.h
Generated on Fri Jan 7 2011 21:37:32 for QP/C++ by doxygen 1.7.3


QP/C++: Member List

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members

QActive Member List

This is the complete list of members for QActive, including all inherited members.
defer(QEQueue *eq, QEvent const *e) | QActive | [protected]
get_(void) | QActive |
m_prio | QActive |
m_running | QActive |
postFIFO(QEvent const *e) | QActive |
postLIFO(QEvent const *e) | QActive |
QActive(QF_ACTIVE_STATE_ initial) | QActive | [inline, protected]
recall(QEQueue *eq) | QActive | [protected]
run(void) | QActive |
start(uint8_t prio, QEvent const *qSto[], uint32_t qLen, void *stkSto, uint32_t stkSize, QEvent const *ie=(QEvent *) 0) | QActive |
stop(void) | QActive | [protected]
subscribe(QSignal sig) const | QActive | [protected]
unsubscribe(QSignal sig) const | QActive | [protected]
unsubscribeAll(void) const | QActive |
Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: Member List

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members

QEP Member List

This is the complete list of members for QEP, including all inherited members.
getVersion(void) QEP [static]
Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: Member List

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members

QEQueue Member List

This is the complete list of members for QEQueue, including all inherited members.
get(void) | QEQueue |
getNFree(void) const | QEQueue | [inline]
init(QEvent const *qSto[], QEQueueCtr qLen) | QEQueue |
postFIFO(QEvent const *e) | QEQueue |
postLIFO(QEvent const *e) | QEQueue |
Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: Member List

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members

QF Member List

This is the complete list of members for QF, including all inherited members.
active_ | QF | [static]
gc(QEvent const *e) | QF | [static]
getPoolMargin(uint8_t poolId) | QF | [static]
getPortVersion(void) | QF | [static]
getQueueMargin(uint8_t prio) | QF | [static]
getVersion(void) | QF | [static]
init(void) | QF | [static]
new_(uint16_t evtSize, QSignal sig) | QF | [static]
onCleanup(void) | QF | [static]
onStartup(void) | QF | [static]
poolInit(void *poolSto, uint32_t poolSize, QEventSize evtSize) | QF | [static]
psInit(QSubscrList *subscrSto, QSignal maxSignal) | QF | [static]
publish(QEvent const *e) | QF | [static]
remove_(QActive const *a) | QF | [static]
run(void) | QF | [static]
stop(void) | QF | [static]
tick(void) | QF | [static]
Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: Member List

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members

QFsm Member List

This is the complete list of members for QFsm, including all inherited members.
dispatch(QEvent const *e) | QFsm |
init(QEvent const *e=(QEvent *) 0) | QFsm |
m_state | QFsm | [protected]
QFsm(QStateHandler initial) | QFsm | [inline, protected]
~QFsm() | QFsm | [virtual]
Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: Member List

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members

QHsm Member List

This is the complete list of members for QHsm, including all inherited members.
dispatch(QEvent const *e) | QHsm |
init(QEvent const *e=(QEvent *) 0) | QHsm |
isIn(QStateHandler state) | QHsm |
m_state | QHsm | [protected]
QHsm(QStateHandler initial) | QHsm | [inline, protected]
top(QHsm *me, QEvent const *e) | QHsm | [protected, static]
~QHsm() | QHsm | [virtual]
Generated on Fri Jan 7 2011 21:37:32 for QP/C++ by doxygen 1.7.3


QP/C++: Member List

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members

QK Member List

This is the complete list of members for QK, including all inherited members.
getPortVersion(void) | QK | [static]
getVersion(void) | QK | [static]
mutexLock(uint8_t prioCeiling) | QK | [static]
mutexUnlock(QMutex mutex) | QK | [static]
onIdle(void) | QK | [static]
Generated on Fri Jan 7 2011 21:37:32 for QP/C++ by doxygen 1.7.3


QP/C++: Member List

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members

QMPool Member List

This is the complete list of members for QMPool, including all inherited members.
get(void) | QMPool |
getBlockSize(void) const | QMPool | [inline]
init(void *poolSto, uint32_t poolSize, QMPoolSize blockSize) | QMPool |
put(void *b) | QMPool |
Generated on Fri Jan 7 2011 21:37:32 for QP/C++ by doxygen 1.7.3


QP/C++: Member List

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members

QPSet8 Member List

This is the complete list of members for QPSet8, including all inherited members.
findMax(void) volatile | QPSet8 | [inline]
hasElement(uint8_t n) volatile | QPSet8 | [inline]
insert(uint8_t n) volatile | QPSet8 | [inline]
isEmpty(void) volatile | QPSet8 | [inline]
m_bits | QPSet8 | [protected]
notEmpty(void) volatile | QPSet8 | [inline]
remove(uint8_t n) volatile | QPSet8 | [inline]
Generated on Fri Jan 7 2011 21:37:32 for QP/C++ by doxygen 1.7.3


QP/C++: Member List

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members

QPSet64 Member List

This is the complete list of members for QPSet64, including all inherited members.
findMax(void) volatile | QPSet64 | [inline]
hasElement(uint8_t n) volatile | QPSet64 | [inline]
insert(uint8_t n) volatile | QPSet64 | [inline]
isEmpty(void) volatile | QPSet8 | [inline]
m_bits | QPSet8 | [protected]
notEmpty(void) volatile | QPSet8 | [inline]
remove(uint8_t n) volatile | QPSet64 | [inline]
Generated on Fri Jan 7 2011 21:37:32 for QP/C++ by doxygen 1.7.3


QP/C++: Member List

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members

QS Member List

This is the complete list of members for QS, including all inherited members.
aoObj_ | QS | [static]
apObj_ | QS | [static]
begin(uint8_t rec) | QS | [static]
end(void) | QS | [static]
eqObj_ | QS | [static]
f32(uint8_t format, float d) | QS | [static]
f64(uint8_t format, double d) | QS | [static]
filterOff(uint8_t rec) | QS | [static]
filterOn(uint8_t rec) | QS | [static]
getBlock(uint16_t *pNbytes) | QS | [static]
getByte(void) | QS | [static]
getVersion(void) | QS | [static]
glbFilter_ | QS | [static]
initBuf(uint8_t sto[], uint32_t stoSize) | QS | [static]
mem(uint8_t const *blk, uint8_t size) | QS | [static]
mpObj_ | QS | [static]
onCleanup(void) | QS | [static]
onFlush(void) | QS | [static]
onGetTime(void) | QS | [static]
onStartup(void const *arg) | QS | [static]
smObj_ | QS | [static]
str(char const *s) | QS | [static]
str_(char const *s) | QS | [static]
str_ROM(char const Q_ROM *Q_ROM_VAR s) | QS | [static]
str_ROM_(char const Q_ROM *Q_ROM_VAR s) | QS | [static]
teObj_ | QS | [static]
tickCtr_ | QS | [static]
u16(uint8_t format, uint16_t d) | QS | [static]
u16_(uint16_t d) | QS | [static]
u32(uint8_t format, uint32_t d) | QS | [static]
u32_(uint32_t d) | QS | [static]
u8(uint8_t format, uint8_t d) | QS | [static]
u8_(uint8_t d) | QS | [static]
Generated on Fri Jan 7 2011 21:37:32 for QP/C++ by doxygen 1.7.3


QP/C++: Member List

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members

QSubscrList Member List

This is the complete list of members for QSubscrList, including all inherited members.
Generated on Fri Jan 7 2011 21:37:32 for QP/C++ by doxygen 1.7.3


QP/C++: Member List

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members

QTimeEvt Member List

This is the complete list of members for QTimeEvt, including all inherited members.
disarm(void) | QTimeEvt |
dynamic_ | QEvent |
fireEvery(QActive *act, QTimeEvtCtr nTicks) | QTimeEvt | [inline]
fireIn(QActive *act, QTimeEvtCtr nTicks) | QTimeEvt | [inline]
postEvery(QActive *act, QTimeEvtCtr nTicks) | QTimeEvt | [inline]
postIn(QActive *act, QTimeEvtCtr nTicks) | QTimeEvt | [inline]
QTimeEvt(QSignal s) | QTimeEvt |
rearm(QTimeEvtCtr nTicks) | QTimeEvt |
sig | QEvent |
Generated on Fri Jan 7 2011 21:37:32 for QP/C++ by doxygen 1.7.3


QP/C++: Class Members - Functions

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members
  • All
  • Functions
  • Variables
  • b
  • d
  • e
  • f
  • g
  • h
  • i
  • m
  • n
  • o
  • p
  • q
  • r
  • s
  • t
  • u
  • ~

- b -

  • begin() : QS

- d -

  • defer() : QActive
  • disarm() : QTimeEvt
  • dispatch() : QFsm , QHsm

- e -

  • end() : QS

- f -

  • f32() : QS
  • f64() : QS
  • filterOff() : QS
  • filterOn() : QS
  • findMax() : QPSet8 , QPSet64
  • fireEvery() : QTimeEvt
  • fireIn() : QTimeEvt

- g -

  • gc() : QF
  • get() : QEQueue , QMPool
  • get_() : QActive
  • getBlock() : QS
  • getBlockSize() : QMPool
  • getByte() : QS
  • getNFree() : QEQueue
  • getPoolMargin() : QF
  • getPortVersion() : QF , QK
  • getQueueMargin() : QF
  • getVersion() : QEP , QF , QK , QS

- h -

  • hasElement() : QPSet8 , QPSet64

- i -

  • init() : QFsm , QHsm , QF , QMPool , QEQueue
  • initBuf() : QS
  • insert() : QPSet64 , QPSet8
  • isEmpty() : QPSet8
  • isIn() : QHsm

- m -

  • mem() : QS
  • mutexLock() : QK
  • mutexUnlock() : QK

- n -

  • new_() : QF
  • notEmpty() : QPSet8

- o -

  • onCleanup() : QF , QS
  • onFlush() : QS
  • onGetTime() : QS
  • onIdle() : QK
  • onStartup() : QF , QS

- p -

  • poolInit() : QF
  • postEvery() : QTimeEvt
  • postFIFO() : QActive , QEQueue
  • postIn() : QTimeEvt
  • postLIFO() : QActive , QEQueue
  • psInit() : QF
  • publish() : QF
  • put() : QMPool

- q -

  • QActive() : QActive
  • QFsm() : QFsm
  • QHsm() : QHsm
  • QTimeEvt() : QTimeEvt

- r -

  • rearm() : QTimeEvt
  • recall() : QActive
  • remove() : QPSet64 , QPSet8
  • remove_() : QF
  • run() : QActive , QF

- s -

  • start() : QActive
  • stop() : QActive , QF
  • str() : QS
  • str_() : QS
  • str_ROM() : QS
  • str_ROM_() : QS
  • subscribe() : QActive

- t -

  • tick() : QF
  • top() : QHsm

- u -

  • u16() : QS
  • u16_() : QS
  • u32() : QS
  • u32_() : QS
  • u8() : QS
  • u8_() : QS
  • unsubscribe() : QActive
  • unsubscribeAll() : QActive

- ~ -

  • ~QFsm() : QFsm
  • ~QHsm() : QHsm
Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: Class Members - Variables

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members
  • All
  • Functions
  • Variables
  • active_ : QF
  • aoObj_ : QS
  • apObj_ : QS
  • dynamic_ : QEvent
  • eqObj_ : QS
  • glbFilter_ : QS
  • m_bits : QPSet8
  • m_prio : QActive
  • m_running : QActive
  • m_state : QFsm , QHsm
  • mpObj_ : QS
  • sig : QEvent
  • smObj_ : QS
  • teObj_ : QS
  • tickCtr_ : QS
Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: File Members

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • i
  • q
  • u
Here is a list of all documented file members with links to the documentation:

- q -

  • Q_ALLEGE : qassert.h
  • Q_ASSERT : qassert.h
  • Q_ASSERT_COMPILE : qassert.h
  • Q_DEFINE_THIS_FILE : qassert.h
  • Q_DEFINE_THIS_MODULE : qassert.h
  • Q_DIM : qevent.h
  • Q_ENSURE : qassert.h
  • Q_ENTRY_SIG : qep.h
  • Q_ERROR : qassert.h
  • Q_EXIT_SIG : qep.h
  • Q_HANDLED : qep.h
  • Q_IGNORED : qep.h
  • Q_INIT_SIG : qep.h
  • Q_INVARIANT : qassert.h
  • Q_NEW : qf.h
  • Q_onAssert() : qassert.h
  • Q_REQUIRE : qassert.h
  • Q_RET_HANDLED : qep.h
  • Q_RET_IGNORED : qep.h
  • Q_RET_SUPER : qep.h
  • Q_RET_TRAN : qep.h
  • Q_ROM : qevent.h
  • Q_ROM_BYTE : qevent.h , qs_pkg.h
  • Q_ROM_VAR : qevent.h
  • Q_SIGNAL_SIZE : qevent.h
  • Q_SUPER : qep.h
  • Q_TRAN : qep.h
  • Q_USER_SIG : qep.h
  • QACTIVE_EQUEUE_ONEMPTY_ : qk.h
  • QACTIVE_EQUEUE_SIGNAL_ : qk.h
  • QACTIVE_EQUEUE_WAIT_ : qk.h
  • QEP_EMPTY_SIG_ : qep_pkg.h
  • QEP_ENTER_ : qep_pkg.h
  • QEP_EXIT_ : qep_pkg.h
  • QEP_MAX_NEST_DEPTH_ : qep_pkg.h
  • QEP_reservedEvt_ : qep.cpp , qep_pkg.h
  • QEP_SIGNAL_SIZE : qep_port.h
  • QEP_TRIG_ : qep_pkg.h
  • QEPConst : qep_pkg.h
  • QF_ACTIVE_BASE : qf_port.h
  • QF_ACTIVE_STATE_ : qf.h
  • QF_ACTIVE_SUPER_ : qf.h
  • QF_div8Lkup : qf.h , qpset.h , qf_pwr2.cpp
  • QF_EPOOL_EVENT_SIZE_ : qk.h
  • QF_EPOOL_GET_ : qk.h
  • QF_EPOOL_INIT_ : qk.h
  • QF_EPOOL_PUT_ : qk.h
  • QF_EPOOL_TYPE_ : qk.h
  • QF_EQUEUE_CTR_SIZE : qf_port.h , qequeue.h
  • QF_EQUEUE_TYPE : qk.h
  • QF_EVENT_SIZ_SIZE : qf_port.h , qf.h
  • QF_INT_KEY_TYPE : qf_port.h
  • QF_INT_LOCK : qf_port.h
  • QF_INT_LOCK_ : qf_pkg.h
  • QF_INT_LOCK_KEY_ : qf_pkg.h
  • QF_INT_UNLOCK : qf_port.h
  • QF_INT_UNLOCK_ : qf_pkg.h
  • QF_intLockNest_ : qs.h , qf_act.cpp
  • QF_invPwr2Lkup : qf.h , qpset.h , qf_pwr2.cpp
  • QF_log2Lkup : qf.h , qpset.h , qf_log2.cpp
  • QF_MAX_ACTIVE : qf_port.h
  • QF_maxPool_ : qf_pkg.h , qf_pool.cpp
  • QF_maxSignal_ : qf_pkg.h , qf_psini.cpp
  • QF_MPOOL_CTR_SIZE : qf_port.h , qmpool.h
  • QF_MPOOL_SIZ_SIZE : qf_port.h , qmpool.h
  • QF_pool_ : qf_pkg.h , qf_pool.cpp
  • QF_pwr2Lkup : qf.h , qpset.h , qf_pwr2.cpp
  • QF_QS_ACTION : qs.h
  • QF_QS_INT_LOCK : qs.h
  • QF_QS_INT_UNLOCK : qs.h
  • QF_QS_ISR_ENTRY : qs.h
  • QF_QS_ISR_EXIT : qs.h
  • QF_readySet_ : qvanilla.h , qvanilla.cpp
  • QF_subscrList_ : qf_pkg.h , qf_psini.cpp
  • QF_TIMEEVT_CTR_SIZE : qf_port.h , qf.h
  • QF_timeEvtListHead_ : qf_pkg.h , qte_arm.cpp
  • QK_ceilingPrio_ : qk_mutex.cpp , qk_pkg.h
  • QK_currPrio_ : qk.h , qk.cpp
  • QK_EXT_RESTORE : qk_port.h
  • QK_EXT_SAVE : qk_port.h
  • QK_init() : qk.h
  • QK_intNest_ : qk.h , qk.cpp
  • QK_ISR_ENTRY : qk_port.h
  • QK_ISR_EXIT : qk_port.h
  • QK_readySet_ : qk.h , qk.cpp
  • QK_TLS : qk_port.h
  • QMutex : qk.h
  • QP_VERSION : qevent.h
  • QReservedSignals : qep.h
  • QS_ALL_RECORDS : qs.h
  • QS_ASSERT : qs.h
  • QS_BEGIN : qs.h
  • QS_BEGIN_ : qs.h
  • QS_BEGIN_NOLOCK : qs.h
  • QS_BEGIN_NOLOCK_ : qs.h
  • QS_chksum_ : qs.cpp , qs_pkg.h
  • QS_END : qs.h
  • QS_END_ : qs.h
  • QS_end_ : qs.cpp , qs_pkg.h
  • QS_END_NOLOCK : qs.h
  • QS_END_NOLOCK_ : qs.h
  • QS_EOD : qs.h
  • QS_ESC : qs_pkg.h
  • QS_ESC_XOR : qs_pkg.h
  • QS_EXIT : qs.h
  • QS_F32 : qs.h
  • QS_F32_T : qs.h
  • QS_F64 : qs.h
  • QS_F64_T : qs.h
  • QS_FILTER_AO_OBJ : qs.h
  • QS_FILTER_AP_OBJ : qs.h
  • QS_FILTER_EQ_OBJ : qs.h
  • QS_FILTER_MP_OBJ : qs.h
  • QS_FILTER_OFF : qs.h
  • QS_FILTER_ON : qs.h
  • QS_FILTER_SM_OBJ : qs.h
  • QS_FILTER_TE_OBJ : qs.h
  • QS_FLUSH : qs.h
  • QS_FRAME : qs_pkg.h
  • QS_full_ : qs.cpp , qs_pkg.h
  • QS_FUN : qs.h
  • QS_FUN_ : qs.h
  • QS_FUN_DICTIONARY : qs.h
  • QS_FUN_T : qs.h
  • QS_head_ : qs_pkg.h , qs.cpp
  • QS_I16 : qs.h
  • QS_I16_T : qs.h
  • QS_I32 : qs.h
  • QS_I32_T : qs.h
  • QS_I8 : qs.h
  • QS_I8_T : qs.h
  • QS_INIT : qs.h
  • QS_INSERT_BYTE : qs_pkg.h
  • QS_INSERT_CHKSUM_BYTE : qs_pkg.h
  • QS_INSERT_ESC_BYTE : qs_pkg.h
  • QS_INT_LOCK_ : qs.h
  • QS_INT_LOCK_KEY_ : qs.h
  • QS_INT_UNLOCK_ : qs.h
  • QS_MEM : qs.h
  • QS_MEM_T : qs.h
  • QS_OBJ : qs.h
  • QS_OBJ_ : qs.h
  • QS_OBJ_DICTIONARY : qs.h
  • QS_OBJ_T : qs.h
  • QS_QEP_DISPATCH : qs.h
  • QS_QEP_IGNORED : qs.h
  • QS_QEP_INIT_TRAN : qs.h
  • QS_QEP_INTERN_TRAN : qs.h
  • QS_QEP_STATE_ENTRY : qs.h
  • QS_QEP_STATE_EXIT : qs.h
  • QS_QEP_STATE_INIT : qs.h
  • QS_QEP_TRAN : qs.h
  • QS_QF_ACTIVE_ADD : qs.h
  • QS_QF_ACTIVE_GET : qs.h
  • QS_QF_ACTIVE_GET_LAST : qs.h
  • QS_QF_ACTIVE_POST_FIFO : qs.h
  • QS_QF_ACTIVE_POST_LIFO : qs.h
  • QS_QF_ACTIVE_REMOVE : qs.h
  • QS_QF_ACTIVE_SUBSCRIBE : qs.h
  • QS_QF_ACTIVE_UNSUBSCRIBE : qs.h
  • QS_QF_EQUEUE_GET : qs.h
  • QS_QF_EQUEUE_GET_LAST : qs.h
  • QS_QF_EQUEUE_INIT : qs.h
  • QS_QF_EQUEUE_POST_FIFO : qs.h
  • QS_QF_EQUEUE_POST_LIFO : qs.h
  • QS_QF_GC : qs.h
  • QS_QF_GC_ATTEMPT : qs.h
  • QS_QF_INT_LOCK : qs.h
  • QS_QF_INT_UNLOCK : qs.h
  • QS_QF_ISR_ENTRY : qs.h
  • QS_QF_ISR_EXIT : qs.h
  • QS_QF_MPOOL_GET : qs.h
  • QS_QF_MPOOL_INIT : qs.h
  • QS_QF_MPOOL_PUT : qs.h
  • QS_QF_NEW : qs.h
  • QS_QF_PUBLISH : qs.h
  • QS_QF_TICK : qs.h
  • QS_QF_TIMEEVT_ARM : qs.h
  • QS_QF_TIMEEVT_AUTO_DISARM : qs.h
  • QS_QF_TIMEEVT_DISARM : qs.h
  • QS_QF_TIMEEVT_DISARM_ATTEMPT : qs.h
  • QS_QF_TIMEEVT_POST : qs.h
  • QS_QF_TIMEEVT_REARM : qs.h
  • QS_QK_MUTEX_LOCK : qs.h
  • QS_QK_MUTEX_UNLOCK : qs.h
  • QS_QK_SCHEDULE : qs.h
  • QS_ring_ : qs.cpp , qs_pkg.h
  • QS_seq_ : qs_pkg.h , qs.cpp
  • QS_SIG_ : qep.h
  • QS_SIG_DICTIONARY : qs.h
  • QS_SIG_T : qs.h
  • QS_STR : qs.h
  • QS_STR_ : qs.h
  • QS_STR_ROM : qs.h
  • QS_STR_ROM_ : qs.h
  • QS_STR_T : qs.h
  • QS_tail_ : qs.cpp , qs_pkg.h
  • QS_TIME_SIZE : qs.h
  • QS_U16 : qs.h
  • QS_U16_ : qs.h
  • QS_U16_T : qs.h
  • QS_U32 : qs.h
  • QS_U32_ : qs.h
  • QS_U32_T : qs.h
  • QS_U8 : qs.h
  • QS_U8_ : qs.h
  • QS_U8_T : qs.h
  • QS_used_ : qs_pkg.h , qs.cpp
  • QS_USER : qs.h
  • QSCtr : qs_pkg.h
  • QSignal : qevent.h
  • QSpyRecords : qs.h
  • QState : qep.h
  • QStateHandler : qep.h
  • QSType : qs.h
Generated on Fri Jan 7 2011 21:37:32 for QP/C++ by doxygen 1.7.3


QP/C++: File Members

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • i
  • q
  • u
Here is a list of all documented file members with links to the documentation:

- u -

  • uint16_t : qep_port.h
  • uint32_t : qep_port.h
  • uint8_t : qep_port.h
Generated on Fri Jan 7 2011 21:37:32 for QP/C++ by doxygen 1.7.3


QP/C++: File Members

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • q

- q -

  • Q_ALLEGE : qassert.h
  • Q_ASSERT : qassert.h
  • Q_ASSERT_COMPILE : qassert.h
  • Q_DEFINE_THIS_FILE : qassert.h
  • Q_DEFINE_THIS_MODULE : qassert.h
  • Q_DIM : qevent.h
  • Q_ENSURE : qassert.h
  • Q_ERROR : qassert.h
  • Q_HANDLED : qep.h
  • Q_IGNORED : qep.h
  • Q_INVARIANT : qassert.h
  • Q_NEW : qf.h
  • Q_REQUIRE : qassert.h
  • Q_RET_HANDLED : qep.h
  • Q_RET_IGNORED : qep.h
  • Q_RET_SUPER : qep.h
  • Q_RET_TRAN : qep.h
  • Q_ROM : qevent.h
  • Q_ROM_BYTE : qevent.h , qs_pkg.h
  • Q_ROM_VAR : qevent.h
  • Q_SIGNAL_SIZE : qevent.h
  • Q_SUPER : qep.h
  • Q_TRAN : qep.h
  • QACTIVE_EQUEUE_ONEMPTY_ : qk.h
  • QACTIVE_EQUEUE_SIGNAL_ : qk.h
  • QACTIVE_EQUEUE_WAIT_ : qk.h
  • QEP_ENTER_ : qep_pkg.h
  • QEP_EXIT_ : qep_pkg.h
  • QEP_SIGNAL_SIZE : qep_port.h
  • QEP_TRIG_ : qep_pkg.h
  • QF_ACTIVE_BASE : qf_port.h
  • QF_ACTIVE_STATE_ : qf.h
  • QF_ACTIVE_SUPER_ : qf.h
  • QF_EPOOL_EVENT_SIZE_ : qk.h
  • QF_EPOOL_GET_ : qk.h
  • QF_EPOOL_INIT_ : qk.h
  • QF_EPOOL_PUT_ : qk.h
  • QF_EPOOL_TYPE_ : qk.h
  • QF_EQUEUE_CTR_SIZE : qf_port.h , qequeue.h
  • QF_EQUEUE_TYPE : qk.h
  • QF_EVENT_SIZ_SIZE : qf_port.h , qf.h
  • QF_INT_KEY_TYPE : qf_port.h
  • QF_INT_LOCK : qf_port.h
  • QF_INT_LOCK_ : qf_pkg.h
  • QF_INT_LOCK_KEY_ : qf_pkg.h
  • QF_INT_UNLOCK : qf_port.h
  • QF_INT_UNLOCK_ : qf_pkg.h
  • QF_MAX_ACTIVE : qf_port.h
  • QF_MPOOL_CTR_SIZE : qf_port.h , qmpool.h
  • QF_MPOOL_SIZ_SIZE : qf_port.h , qmpool.h
  • QF_QS_ACTION : qs.h
  • QF_QS_INT_LOCK : qs.h
  • QF_QS_INT_UNLOCK : qs.h
  • QF_QS_ISR_ENTRY : qs.h
  • QF_QS_ISR_EXIT : qs.h
  • QF_TIMEEVT_CTR_SIZE : qf_port.h , qf.h
  • QK_EXT_RESTORE : qk_port.h
  • QK_EXT_SAVE : qk_port.h
  • QK_ISR_ENTRY : qk_port.h
  • QK_ISR_EXIT : qk_port.h
  • QK_TLS : qk_port.h
  • QP_VERSION : qevent.h
  • QS_ALL_RECORDS : qs.h
  • QS_BEGIN : qs.h
  • QS_BEGIN_ : qs.h
  • QS_BEGIN_NOLOCK : qs.h
  • QS_BEGIN_NOLOCK_ : qs.h
  • QS_END : qs.h
  • QS_END_ : qs.h
  • QS_END_NOLOCK : qs.h
  • QS_END_NOLOCK_ : qs.h
  • QS_EOD : qs.h
  • QS_ESC : qs_pkg.h
  • QS_ESC_XOR : qs_pkg.h
  • QS_EXIT : qs.h
  • QS_F32 : qs.h
  • QS_F64 : qs.h
  • QS_FILTER_AO_OBJ : qs.h
  • QS_FILTER_AP_OBJ : qs.h
  • QS_FILTER_EQ_OBJ : qs.h
  • QS_FILTER_MP_OBJ : qs.h
  • QS_FILTER_OFF : qs.h
  • QS_FILTER_ON : qs.h
  • QS_FILTER_SM_OBJ : qs.h
  • QS_FILTER_TE_OBJ : qs.h
  • QS_FLUSH : qs.h
  • QS_FRAME : qs_pkg.h
  • QS_FUN : qs.h
  • QS_FUN_ : qs.h
  • QS_FUN_DICTIONARY : qs.h
  • QS_I16 : qs.h
  • QS_I32 : qs.h
  • QS_I8 : qs.h
  • QS_INIT : qs.h
  • QS_INSERT_BYTE : qs_pkg.h
  • QS_INSERT_CHKSUM_BYTE : qs_pkg.h
  • QS_INSERT_ESC_BYTE : qs_pkg.h
  • QS_INT_LOCK_ : qs.h
  • QS_INT_LOCK_KEY_ : qs.h
  • QS_INT_UNLOCK_ : qs.h
  • QS_MEM : qs.h
  • QS_OBJ : qs.h
  • QS_OBJ_ : qs.h
  • QS_OBJ_DICTIONARY : qs.h
  • QS_SIG_ : qep.h
  • QS_SIG_DICTIONARY : qs.h
  • QS_STR : qs.h
  • QS_STR_ : qs.h
  • QS_STR_ROM : qs.h
  • QS_STR_ROM_ : qs.h
  • QS_TIME_SIZE : qs.h
  • QS_U16 : qs.h
  • QS_U16_ : qs.h
  • QS_U32 : qs.h
  • QS_U32_ : qs.h
  • QS_U8 : qs.h
  • QS_U8_ : qs.h
Generated on Fri Jan 7 2011 21:37:32 for QP/C++ by doxygen 1.7.3


QP/C++: File Members

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • QEPConst : qep_pkg.h
  • QReservedSignals : qep.h
  • QSpyRecords : qs.h
  • QSType : qs.h
Generated on Fri Jan 7 2011 21:37:32 for QP/C++ by doxygen 1.7.3


QP/C++: File Members

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • q

- q -

  • Q_ENTRY_SIG : qep.h
  • Q_EXIT_SIG : qep.h
  • Q_INIT_SIG : qep.h
  • Q_USER_SIG : qep.h
  • QEP_EMPTY_SIG_ : qep_pkg.h
  • QEP_MAX_NEST_DEPTH_ : qep_pkg.h
  • QS_ASSERT : qs.h
  • QS_F32_T : qs.h
  • QS_F64_T : qs.h
  • QS_FUN_DICTIONARY : qs.h
  • QS_FUN_T : qs.h
  • QS_I16_T : qs.h
  • QS_I32_T : qs.h
  • QS_I8_T : qs.h
  • QS_MEM_T : qs.h
  • QS_OBJ_DICTIONARY : qs.h
  • QS_OBJ_T : qs.h
  • QS_QEP_DISPATCH : qs.h
  • QS_QEP_IGNORED : qs.h
  • QS_QEP_INIT_TRAN : qs.h
  • QS_QEP_INTERN_TRAN : qs.h
  • QS_QEP_STATE_ENTRY : qs.h
  • QS_QEP_STATE_EXIT : qs.h
  • QS_QEP_STATE_INIT : qs.h
  • QS_QEP_TRAN : qs.h
  • QS_QF_ACTIVE_ADD : qs.h
  • QS_QF_ACTIVE_GET : qs.h
  • QS_QF_ACTIVE_GET_LAST : qs.h
  • QS_QF_ACTIVE_POST_FIFO : qs.h
  • QS_QF_ACTIVE_POST_LIFO : qs.h
  • QS_QF_ACTIVE_REMOVE : qs.h
  • QS_QF_ACTIVE_SUBSCRIBE : qs.h
  • QS_QF_ACTIVE_UNSUBSCRIBE : qs.h
  • QS_QF_EQUEUE_GET : qs.h
  • QS_QF_EQUEUE_GET_LAST : qs.h
  • QS_QF_EQUEUE_INIT : qs.h
  • QS_QF_EQUEUE_POST_FIFO : qs.h
  • QS_QF_EQUEUE_POST_LIFO : qs.h
  • QS_QF_GC : qs.h
  • QS_QF_GC_ATTEMPT : qs.h
  • QS_QF_INT_LOCK : qs.h
  • QS_QF_INT_UNLOCK : qs.h
  • QS_QF_ISR_ENTRY : qs.h
  • QS_QF_ISR_EXIT : qs.h
  • QS_QF_MPOOL_GET : qs.h
  • QS_QF_MPOOL_INIT : qs.h
  • QS_QF_MPOOL_PUT : qs.h
  • QS_QF_NEW : qs.h
  • QS_QF_PUBLISH : qs.h
  • QS_QF_TICK : qs.h
  • QS_QF_TIMEEVT_ARM : qs.h
  • QS_QF_TIMEEVT_AUTO_DISARM : qs.h
  • QS_QF_TIMEEVT_DISARM : qs.h
  • QS_QF_TIMEEVT_DISARM_ATTEMPT : qs.h
  • QS_QF_TIMEEVT_POST : qs.h
  • QS_QF_TIMEEVT_REARM : qs.h
  • QS_QK_MUTEX_LOCK : qs.h
  • QS_QK_MUTEX_UNLOCK : qs.h
  • QS_QK_SCHEDULE : qs.h
  • QS_SIG_DICTIONARY : qs.h
  • QS_SIG_T : qs.h
  • QS_STR_T : qs.h
  • QS_U16_T : qs.h
  • QS_U32_T : qs.h
  • QS_U8_T : qs.h
  • QS_USER : qs.h
Generated on Fri Jan 7 2011 21:37:32 for QP/C++ by doxygen 1.7.3


QP/C++: File Members

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • Q_onAssert() : qassert.h
  • QK_init() : qk.h
Generated on Fri Jan 7 2011 21:37:32 for QP/C++ by doxygen 1.7.3


QP/C++: File Members

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • int16_t : qep_port.h
  • int32_t : qep_port.h
  • int8_t : qep_port.h
  • QMutex : qk.h
  • QSCtr : qs_pkg.h
  • QSignal : qevent.h
  • QState : qep.h
  • QStateHandler : qep.h
  • uint16_t : qep_port.h
  • uint32_t : qep_port.h
  • uint8_t : qep_port.h
Generated on Fri Jan 7 2011 21:37:32 for QP/C++ by doxygen 1.7.3


QP/C++: File Members

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • q

- q -

  • QEP_reservedEvt_ : qep.cpp , qep_pkg.h
  • QF_div8Lkup : qpset.h , qf_pwr2.cpp , qf.h
  • QF_intLockNest_ : qs.h , qf_act.cpp
  • QF_invPwr2Lkup : qf.h , qpset.h , qf_pwr2.cpp
  • QF_log2Lkup : qf.h , qpset.h , qf_log2.cpp
  • QF_maxPool_ : qf_pkg.h , qf_pool.cpp
  • QF_maxSignal_ : qf_pkg.h , qf_psini.cpp
  • QF_pool_ : qf_pkg.h , qf_pool.cpp
  • QF_pwr2Lkup : qf.h , qpset.h , qf_pwr2.cpp
  • QF_readySet_ : qvanilla.h , qvanilla.cpp
  • QF_subscrList_ : qf_pkg.h , qf_psini.cpp
  • QF_timeEvtListHead_ : qf_pkg.h , qte_arm.cpp
  • QK_ceilingPrio_ : qk_mutex.cpp , qk_pkg.h
  • QK_currPrio_ : qk.h , qk.cpp
  • QK_intNest_ : qk.h , qk.cpp
  • QK_readySet_ : qk.cpp , qk.h
  • QS_chksum_ : qs.cpp , qs_pkg.h
  • QS_end_ : qs_pkg.h , qs.cpp
  • QS_full_ : qs_pkg.h , qs.cpp
  • QS_head_ : qs.cpp , qs_pkg.h
  • QS_ring_ : qs_pkg.h , qs.cpp
  • QS_seq_ : qs_pkg.h , qs.cpp
  • QS_tail_ : qs_pkg.h , qs.cpp
  • QS_used_ : qs.cpp , qs_pkg.h
Generated on Fri Jan 7 2011 21:37:32 for QP/C++ by doxygen 1.7.3


QP/C++: qa_defer.cpp Source File

qa_defer.cpp

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029 #include "qassert.h"
00030
00031 Q_DEFINE_THIS_MODULE(qa_defer)
00032
00033
00034
00035
00036
00037
00038 //............................................................................
00039 void QActive::defer(QEQueue *eq, QEvent const *e) {
00040     eq->postFIFO(e);
00041 }
00042 //............................................................................
00043 QEvent const *QActive::recall(QEQueue *eq) {
00044     QEvent const *e = eq->get();    // try to get an event from deferred queue
00045     if (e != (QEvent *)0) {                                // event available?
00046
00047         postLIFO(e);      // post it to the front of the Active Object's queue
00048
00049         QF_INT_LOCK_KEY_
00050         QF_INT_LOCK_();
00051
00052         if (e->dynamic_ != (uint8_t)0) {             // is it a dynamic event?
00053
00054             // after posting to the AO's queue the event must be referenced
00055             // at least twice: once in the deferred event queue (eq->get()
00056             // did NOT decrement the reference counter) and once in the
00057             // AO's event queue.
00058             Q_ASSERT((e->dynamic_ & 0x3F) > 1);
00059
00060             // we need to decrement the reference counter once, to account
00061             // for removing the event from the deferred event queue.
00062             //
00063             //lint -e1773                           Attempt to cast away const
00064             --((QEvent *)e)->dynamic_;      // decrement the reference counter
00065                    // NOTE: cast the 'const' away, which is legitimate because
00066                    // it's a dynamic event
00067         }
00068
00069         QF_INT_UNLOCK_();
00070
00071     }
00072     return e;  // pass the recalled event to the caller (NULL if not recalled)
00073 }
Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: qa_fifo.cpp Source File

qa_fifo.cpp

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029 #include "qassert.h"
00030
00031 Q_DEFINE_THIS_MODULE(qa_fifo)
00032
00033
00034
00035
00036
00037
00038
00039
00040 //............................................................................
00041 void QActive::postFIFO(QEvent const *e) {
00042     QF_INT_LOCK_KEY_
00043     QF_INT_LOCK_();
00044
00045     QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_POST_FIFO, QS::aoObj_, this)
00046         QS_TIME_();                                               // timestamp
00047         QS_SIG_(e->sig);                            // the signal of the event
00048         QS_OBJ_(this);                                   // this active object
00049         QS_U8_(e->dynamic_);                  // the QF attribute of the event
00050         QS_EQC_(m_eQueue.m_nFree);                   // number of free entries
00051         QS_EQC_(m_eQueue.m_nMin);                // min number of free entries
00052     QS_END_NOLOCK_()
00053
00054     if (e->dynamic_ != (uint8_t)0) {                 // is it a dynamic event?
00055         //lint -e1773                               Attempt to cast away const
00056         ++((QEvent *)e)->dynamic_;          // increment the reference counter
00057                    // NOTE: cast the 'const' away, which is legitimate because
00058                    // it's a dynamic event
00059     }
00060
00061     if (m_eQueue.m_frontEvt == (QEvent *)0) {           // is the queue empty?
00062         m_eQueue.m_frontEvt = e;                     // deliver event directly
00063         QACTIVE_EQUEUE_SIGNAL_(this);                // signal the event queue
00064     }
00065     else {               // queue is not empty, leave event in the ring-buffer
00066                                         // queue must accept all posted events
00067         Q_ASSERT(m_eQueue.m_nFree != (QEQueueCtr)0);
00068         m_eQueue.m_ring[m_eQueue.m_head] = e;//insert e into the buffer (FIFO)
00069         if (m_eQueue.m_head == (QEQueueCtr)0) {      // need to wrap the head?
00070             m_eQueue.m_head = m_eQueue.m_end;                   // wrap around
00071         }
00072         --m_eQueue.m_head;
00073
00074         --m_eQueue.m_nFree;                    // update number of free events
00075         if (m_eQueue.m_nMin > m_eQueue.m_nFree) {
00076             m_eQueue.m_nMin = m_eQueue.m_nFree;       // update minimum so far
00077         }
00078     }
00079     QF_INT_UNLOCK_();
00080 }
Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: qa_get_.cpp Source File

qa_get_.cpp

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029 #include "qassert.h"
00030
00031 Q_DEFINE_THIS_MODULE(qa_get_)
00032
00033
00034
00035
00036
00037
00038
00039
00040 //............................................................................
00041 QEvent const *QActive::get_(void) {
00042     QF_INT_LOCK_KEY_
00043     QF_INT_LOCK_();
00044
00045     QACTIVE_EQUEUE_WAIT_(this);           // wait for event to arrive directly
00046
00047     QEvent const *e = m_eQueue.m_frontEvt;
00048
00049     if (m_eQueue.m_nFree != m_eQueue.m_end) { //any events in the ring buffer?
00050                                                  // remove event from the tail
00051         m_eQueue.m_frontEvt = m_eQueue.m_ring[m_eQueue.m_tail];
00052         if (m_eQueue.m_tail == (QEQueueCtr)0) {      // need to wrap the tail?
00053             m_eQueue.m_tail = m_eQueue.m_end;                   // wrap around
00054         }
00055         --m_eQueue.m_tail;
00056
00057         ++m_eQueue.m_nFree;          // one more free event in the ring buffer
00058
00059         QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_GET, QS::aoObj_, this)
00060             QS_TIME_();                                           // timestamp
00061             QS_SIG_(e->sig);                       // the signal of this event
00062             QS_OBJ_(this);                               // this active object
00063             QS_U8_(e->dynamic_);        // the dynamic attributes of the event
00064             QS_EQC_(m_eQueue.m_nFree);               // number of free entries
00065         QS_END_NOLOCK_()
00066     }
00067     else {
00068         m_eQueue.m_frontEvt = (QEvent *)0;          // the queue becomes empty
00069         QACTIVE_EQUEUE_ONEMPTY_(this);
00070
00071         QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_GET_LAST, QS::aoObj_, this)
00072             QS_TIME_();                                           // timestamp
00073             QS_SIG_(e->sig);                       // the signal of this event
00074             QS_OBJ_(this);                               // this active object
00075             QS_U8_(e->dynamic_);        // the dynamic attributes of the event
00076         QS_END_NOLOCK_()
00077     }
00078     QF_INT_UNLOCK_();
00079     return e;
00080 }
00081 //............................................................................
00082 uint32_t QF::getQueueMargin(uint8_t prio) {
00083     Q_REQUIRE((prio <= (uint8_t)QF_MAX_ACTIVE)
00084               && (active_[prio] != (QActive *)0));
00085
00086     QF_INT_LOCK_KEY_
00087     QF_INT_LOCK_();
00088     uint32_t margin = (uint32_t)(active_[prio]->m_eQueue.m_nMin);
00089     QF_INT_UNLOCK_();
00090
00091     return margin;
00092 }
Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: qa_lifo.cpp Source File

qa_lifo.cpp

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029 #include "qassert.h"
00030
00031 Q_DEFINE_THIS_MODULE(qa_lifo)
00032
00033
00034
00035
00036
00037
00038
00039
00040 //............................................................................
00041 void QActive::postLIFO(QEvent const *e) {
00042     QF_INT_LOCK_KEY_
00043     QF_INT_LOCK_();
00044
00045     QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_POST_LIFO, QS::aoObj_, this)
00046         QS_TIME_();                                               // timestamp
00047         QS_SIG_(e->sig);                           // the signal of this event
00048         QS_OBJ_(this);                                   // this active object
00049         QS_U8_(e->dynamic_);            // the dynamic attributes of the event
00050         QS_EQC_(m_eQueue.m_nFree);                   // number of free entries
00051         QS_EQC_(m_eQueue.m_nMin);                // min number of free entries
00052     QS_END_NOLOCK_()
00053
00054     if (e->dynamic_ != (uint8_t)0) {                    // is it a pool event?
00055         //lint -e1773                               Attempt to cast away const
00056         ++((QEvent *)e)->dynamic_;          // increment the reference counter
00057                    // NOTE: cast the 'const' away, which is legitimate because
00058                    // it's a dynamic event
00059     }
00060
00061     if (m_eQueue.m_frontEvt == (QEvent *)0) {           // is the queue empty?
00062         m_eQueue.m_frontEvt = e;                     // deliver event directly
00063         QACTIVE_EQUEUE_SIGNAL_(this);                // signal the event queue
00064     }
00065     else {               // queue is not empty, leave event in the ring-buffer
00066                                         // queue must accept all posted events
00067         Q_ASSERT(m_eQueue.m_nFree != (QEQueueCtr)0);
00068
00069         ++m_eQueue.m_tail;
00070         if (m_eQueue.m_tail == m_eQueue.m_end) {     // need to wrap the tail?
00071             m_eQueue.m_tail = (QEQueueCtr)0;                    // wrap around
00072         }
00073
00074         m_eQueue.m_ring[m_eQueue.m_tail] = m_eQueue.m_frontEvt;
00075         m_eQueue.m_frontEvt = e;                         // put event to front
00076
00077         --m_eQueue.m_nFree;                    // update number of free events
00078         if (m_eQueue.m_nMin > m_eQueue.m_nFree) {
00079             m_eQueue.m_nMin = m_eQueue.m_nFree;       // update minimum so far
00080         }
00081     }
00082     QF_INT_UNLOCK_();
00083 }
Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: qa_run.cpp Source File

qa_run.cpp

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029
00033
00034 //............................................................................
00035 void QActive::run(void) {
00036     m_running = (uint8_t)1;                    // allow the thread-loop to run
00037     do {
00038         QEvent const *e = get_();                            // wait for event
00039         dispatch(e);          // dispatch to the active object's state machine
00040         QF::gc(e);      // check if the event is garbage, and collect it if so
00041
00042     } while (m_running); // loop until m_running is cleared in QActive::stop()
00043 }
Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: qa_sub.cpp Source File

qa_sub.cpp

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029 #include "qassert.h"
00030
00031 Q_DEFINE_THIS_MODULE(qa_sub)
00032
00033
00034
00035
00036
00037 //............................................................................
00038 void QActive::subscribe(QSignal sig) const {
00039     uint8_t p = m_prio;
00040     Q_REQUIRE(((QSignal)Q_USER_SIG <= sig)
00041               && (sig < QF_maxSignal_)
00042               && ((uint8_t)0 < p) && (p <= (uint8_t)QF_MAX_ACTIVE)
00043               && (QF::active_[p] == this));
00044
00045     uint8_t i = Q_ROM_BYTE(QF_div8Lkup[p]);
00046
00047     QF_INT_LOCK_KEY_
00048     QF_INT_LOCK_();
00049
00050     QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_SUBSCRIBE, QS::aoObj_, this)
00051         QS_TIME_();                                               // timestamp
00052         QS_SIG_(sig);                              // the signal of this event
00053         QS_OBJ_(this);                                   // this active object
00054     QS_END_NOLOCK_()
00055                                                        // set the priority bit
00056     QF_subscrList_[sig].m_bits[i] |= Q_ROM_BYTE(QF_pwr2Lkup[p]);
00057     QF_INT_UNLOCK_();
00058 }
Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: qa_usub.cpp Source File

qa_usub.cpp

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029 #include "qassert.h"
00030
00031 Q_DEFINE_THIS_MODULE(qa_usub)
00032
00033
00034
00035
00036
00037 //............................................................................
00038 void QActive::unsubscribe(QSignal sig) const {
00039     uint8_t p = m_prio;
00040     Q_REQUIRE(((QSignal)Q_USER_SIG <= sig)
00041               && (sig < QF_maxSignal_)
00042               && ((uint8_t)0 < p) && (p <= (uint8_t)QF_MAX_ACTIVE)
00043               && (QF::active_[p] == this));
00044
00045     uint8_t i = Q_ROM_BYTE(QF_div8Lkup[p]);
00046
00047     QF_INT_LOCK_KEY_
00048     QF_INT_LOCK_();
00049
00050     QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_UNSUBSCRIBE, QS::aoObj_, this)
00051         QS_TIME_();                                               // timestamp
00052         QS_SIG_(sig);                              // the signal of this event
00053         QS_OBJ_(this);                                   // this active object
00054     QS_END_NOLOCK_()
00055                                                      // clear the priority bit
00056     QF_subscrList_[sig].m_bits[i] &= Q_ROM_BYTE(QF_invPwr2Lkup[p]);
00057     QF_INT_UNLOCK_();
00058 }
Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: qa_usuba.cpp Source File

qa_usuba.cpp

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029 #include "qassert.h"
00030
00031 Q_DEFINE_THIS_MODULE(qa_usuba)
00032
00033
00034
00035
00036
00037 //............................................................................
00038 void QActive::unsubscribeAll(void) const {
00039     uint8_t p = m_prio;
00040     Q_REQUIRE(((uint8_t)0 < p) && (p <= (uint8_t)QF_MAX_ACTIVE)
00041               && (QF::active_[p] == this));
00042
00043     uint8_t i = Q_ROM_BYTE(QF_div8Lkup[p]);
00044
00045     QSignal sig;
00046     for (sig = (QSignal)Q_USER_SIG; sig < QF_maxSignal_; ++sig) {
00047         QF_INT_LOCK_KEY_
00048         QF_INT_LOCK_();
00049         if ((QF_subscrList_[sig].m_bits[i] & Q_ROM_BYTE(QF_pwr2Lkup[p]))
00050              != 0)
00051         {
00052
00053             QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_UNSUBSCRIBE, QS::aoObj_, this)
00054                 QS_TIME_();                                       // timestamp
00055                 QS_SIG_(sig);                      // the signal of this event
00056                 QS_OBJ_(this);                           // this active object
00057             QS_END_NOLOCK_()
00058                                                      // clear the priority bit
00059             QF_subscrList_[sig].m_bits[i] &= Q_ROM_BYTE(QF_invPwr2Lkup[p]);
00060         }
00061         QF_INT_UNLOCK_();
00062     }
00063 }
Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: qassert.h Source File

qassert.h

Go to the documentation of this file.
00001 /*****************************************************************************
00002 * Product:  QP/C/C++
00003 * Last Updated for Version: 4.0.04
00004 * Date of the Last Update:  Apr 09, 2009
00005 *
00006 *                    Q u a n t u m     L e a P s
00007 *                    ---------------------------
00008 *                    innovating embedded systems
00009 *
00010 * Copyright (C) 2002-2009 Quantum Leaps, LLC. All rights reserved.
00011 *
00012 * This software may be distributed and modified under the terms of the GNU
00013 * General Public License version 2 (GPL) as published by the Free Software
00014 * Foundation and appearing in the file GPL.TXT included in the packaging of
00015 * this file. Please note that GPL Section 2[b] requires that all works based
00016 * on this software must also be made publicly available under the terms of
00017 * the GPL ("Copyleft").
00018 *
00019 * Alternatively, this software may be distributed and modified under the
00020 * terms of Quantum Leaps commercial licenses, which expressly supersede
00021 * the GPL and are specifically designed for licensees interested in
00022 * retaining the proprietary status of their code.
00023 *
00024 * Contact information:
00025 * Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 * e-mail:                  info@quantum-leaps.com
00027 *****************************************************************************/
00028 #ifndef qassert_h
00029 #define qassert_h
00030
00047 #ifdef Q_NASSERT          /* Q_NASSERT defined--assertion checking disabled */
00048
00049     #define Q_DEFINE_THIS_FILE
00050     #define Q_DEFINE_THIS_MODULE(name_)
00051     #define Q_ASSERT(test_)    ((void)0)
00052     #define Q_ALLEGE(test_)    ((void)(test_))
00053     #define Q_ERROR()          ((void)0)
00054
00055 #else                  /* Q_NASSERT not defined--assertion checking enabled */
00056
00057     #ifdef __cplusplus
00058         extern "C" {
00059     #endif
00060
00068     /*lint -sem(Q_onAssert, r_no)                Q_onAssert() never returns */
00069     void Q_onAssert(char const Q_ROM * const Q_ROM_VAR file, int line);
00070
00071     #ifdef __cplusplus
00072         }
00073     #endif
00074
00079     #define Q_DEFINE_THIS_FILE \
00080         static char const Q_ROM Q_ROM_VAR l_this_file[] = __FILE__;
00081
00086     #define Q_DEFINE_THIS_MODULE(name_) \
00087         static char const Q_ROM Q_ROM_VAR l_this_file[] = #name_;
00088
00095     #define Q_ASSERT(test_) \
00096         if (test_) { \
00097         } \
00098         else (Q_onAssert(l_this_file, __LINE__))
00099
00108     #define Q_ALLEGE(test_)    Q_ASSERT(test_)
00109
00114     #define Q_ERROR() \
00115         (Q_onAssert(l_this_file, __LINE__))
00116
00117 #endif                                                         /* Q_NASSERT */
00118
00123 #define Q_REQUIRE(test_)   Q_ASSERT(test_)
00124
00129 #define Q_ENSURE(test_)    Q_ASSERT(test_)
00130
00135 #define Q_INVARIANT(test_) Q_ASSERT(test_)
00136
00142 #define Q_ASSERT_COMPILE(test_) \
00143     extern char Q_assert_compile[(test_) ? 1 : -1]
00144
00145 #endif                                                         /* qassert_h */
Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: qep.cpp Source File

qep.cpp

Go to the documentation of this file.
00001
00002 // Product: QEP/C++
00003 // Last Updated for Version: 4.1.03
00004 // Date of the Last Update:  Feb 15, 2010
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2010 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qep_pkg.h"
00029
00033
00034 // Package-scope objects -----------------------------------------------------
00035 QEvent const QEP_reservedEvt_[] = {
00036     { (QSignal)QEP_EMPTY_SIG_, (uint8_t)0 },
00037     { (QSignal)Q_ENTRY_SIG,    (uint8_t)0 },
00038     { (QSignal)Q_EXIT_SIG,     (uint8_t)0 },
00039     { (QSignal)Q_INIT_SIG,     (uint8_t)0 }
00040 };
00041 //............................................................................
00042 //lint -e970 -e971               ignore MISRA rules 13 and 14 in this function
00043 char const Q_ROM * Q_ROM_VAR QEP::getVersion(void) {
00044     static char const Q_ROM Q_ROM_VAR version[] = {
00045         ((QP_VERSION >> 12) & 0xF) + '0',
00046         '.',
00047         ((QP_VERSION >>  8) & 0xF) + '0',
00048         '.',
00049         ((QP_VERSION >>  4) & 0xF) + '0',
00050         (QP_VERSION         & 0xF) + '0',
00051         '\0'
00052     };
00053     return version;
00054 }
Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: qep.h Source File

qep.h

Go to the documentation of this file.
00001
00002 // Product: QEP/C++ platform-independent public interface
00003 // Last Updated for Version: 4.0.04
00004 // Date of the Last Update:  Apr 08, 2009
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2009 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #ifndef qep_h
00029 #define qep_h
00030
00037
00038 #include "qevent.h"           // QEP event processor needs the QEvent facility
00039
00042 class QEP {
00043 public:
00049     static char const Q_ROM * Q_ROM_VAR getVersion(void);
00050 };
00051
00053
00055 typedef uint8_t QState;
00056
00058 typedef QState (*QStateHandler)(void *me, QEvent const *e);
00059
00060
00076 class QFsm {
00077 protected:
00078     QStateHandler m_state;
00079
00080 public:
00082     virtual ~QFsm();
00083
00095     void init(QEvent const *e = (QEvent *)0);
00096
00106     void dispatch(QEvent const *e);
00107
00108 protected:
00109
00121     QFsm(QStateHandler initial) : m_state(initial) {}
00122 };
00123
00138 class QHsm {
00139 protected:
00140     QStateHandler m_state;
00141
00142 public:
00144     virtual ~QHsm();
00145
00155     void init(QEvent const *e = (QEvent *)0);
00156
00166     void dispatch(QEvent const *e);
00167
00173     uint8_t isIn(QStateHandler state);
00174
00175 protected:
00176
00189     QHsm(QStateHandler initial) : m_state(initial) {}
00190
00198     static QState top(QHsm *me, QEvent const *e);
00199 };
00200
00203 #define Q_RET_IGNORED       ((QState)1)
00204
00211 #define Q_IGNORED()         (Q_RET_IGNORED)
00212
00215 #define Q_RET_HANDLED       ((QState)0)
00216
00224 #define Q_HANDLED()         (Q_RET_HANDLED)
00225
00228 #define Q_RET_TRAN          ((QState)2)
00229
00234 //lint -e960 -e1924 ignore MISRA Rule 42 (comma operator) and C-style cast
00235 #define Q_TRAN(target_)  \
00236     (me->m_state = (QStateHandler)(target_), Q_RET_TRAN)
00237
00240 #define Q_RET_SUPER         ((QState)3)
00241
00245 //lint -e960 -e1924 ignore MISRA Rule 42 (comma operator) and C-style cast
00246 #define Q_SUPER(super_)  \
00247     (me->m_state = (QStateHandler)(super_),  Q_RET_SUPER)
00248
00249
00252 enum QReservedSignals {
00253     Q_ENTRY_SIG = 1,
00254     Q_EXIT_SIG,
00255     Q_INIT_SIG,
00256     Q_USER_SIG
00257 };
00258
00260 // QS software tracing integration, only if enabled
00261 #ifdef Q_SPY                                   // QS software tracing enabled?
00262     #ifndef qs_h
00263     #include "qs_port.h"                                    // include QS port
00264     #endif                                                             // qs_h
00265
00266     #if (Q_SIGNAL_SIZE == 1)
00267
00271         #define QS_SIG_(sig_)       QS::u8_(sig_)
00272     #elif (Q_SIGNAL_SIZE == 2)
00273         #define QS_SIG_(sig_)       QS::u16_(sig_)
00274     #elif (Q_SIGNAL_SIZE == 4)
00275         #define QS_SIG_(sig_)       QS::u32_(sig_)
00276     #endif
00277
00278 #else
00279     #ifndef qs_dummy_h
00280     #include "qs_dummy.h"                   // disable the QS software tracing
00281     #endif
00282 #endif                                                                // Q_SPY
00283
00284 #endif                                                                // qep_h
Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: qep_pkg.h Source File

qep_pkg.h

Go to the documentation of this file.
00001
00002 // Product: QEP/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 06, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #ifndef qep_pkg_h
00029 #define qep_pkg_h
00030
00034
00035 #include "qep_port.h"                                              // QEP port
00036
00037 extern QEvent const QEP_reservedEvt_[];
00038
00040 enum QEPConst {
00041     QEP_EMPTY_SIG_ = 0,
00042
00044     QEP_MAX_NEST_DEPTH_ = 6
00045 };
00046
00048 #define QEP_TRIG_(state_, sig_) \
00049     ((*(state_))(this, &QEP_reservedEvt_[sig_]))
00050
00052 #define QEP_EXIT_(state_) \
00053     if (QEP_TRIG_(state_, Q_EXIT_SIG) == Q_RET_HANDLED) { \
00054         QS_BEGIN_(QS_QEP_STATE_EXIT, QS::smObj_, this) \
00055             QS_OBJ_(this); \
00056             QS_FUN_(state_); \
00057         QS_END_() \
00058     }
00059
00061 #define QEP_ENTER_(state_) \
00062     if (QEP_TRIG_(state_, Q_ENTRY_SIG) == Q_RET_HANDLED) { \
00063         QS_BEGIN_(QS_QEP_STATE_ENTRY, QS::smObj_, this) \
00064             QS_OBJ_(this); \
00065             QS_FUN_(state_); \
00066         QS_END_() \
00067     }
00068
00069 #endif                                                            // qep_pkg_h
Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: qep_port.h Source File

qep_port.h

Go to the documentation of this file.
00001
00002 // Product: QEP/C++  port to lint, generic C++ compiler
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #ifndef qep_port_h
00029 #define qep_port_h
00030
00037
00054 #define QEP_SIGNAL_SIZE 1
00055
00056 // Exact-width types. WG14/N843 C99 Standard, Section 7.18.1.1
00057 typedef signed   char  int8_t;
00058 typedef signed   short int16_t;
00059 typedef signed   long  int32_t;
00060 typedef unsigned char  uint8_t;
00061 typedef unsigned short uint16_t;
00062 typedef unsigned long  uint32_t;
00063
00064 #include "qep.h"                  // QEP platform-independent public interface
00065
00066 #endif                                                           // qep_port_h
Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: qeq_fifo.cpp Source File

qeq_fifo.cpp

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029 #include "qassert.h"
00030
00031 Q_DEFINE_THIS_MODULE(qeq_fifo)
00032
00033
00034
00035
00036
00037 //............................................................................
00038 void QEQueue::postFIFO(QEvent const *e) {
00039     QF_INT_LOCK_KEY_
00040     QF_INT_LOCK_();
00041
00042     QS_BEGIN_NOLOCK_(QS_QF_EQUEUE_POST_FIFO, QS::eqObj_, this)
00043         QS_TIME_();                                               // timestamp
00044         QS_SIG_(e->sig);                           // the signal of this event
00045         QS_OBJ_(this);                                    // this queue object
00046         QS_U8_(e->dynamic_);            // the dynamic attributes of the event
00047         QS_EQC_(m_nFree);                            // number of free entries
00048         QS_EQC_(m_nMin);                         // min number of free entries
00049     QS_END_NOLOCK_()
00050
00051     if (e->dynamic_ != (uint8_t)0) {                    // is it a pool event?
00052         //lint -e1773                               Attempt to cast away const
00053         ++((QEvent *)e)->dynamic_;          // increment the reference counter
00054                    // NOTE: cast the 'const' away, which is legitimate because
00055                    // it's a dynamic event
00056     }
00057
00058     if (m_frontEvt == (QEvent *)0) {                    // is the queue empty?
00059         m_frontEvt = e;                              // deliver event directly
00060     }
00061     else {               // queue is not empty, leave event in the ring-buffer
00062                // the queue must be able to accept the event (cannot overflow)
00063         Q_ASSERT(m_nFree != (QEQueueCtr)0);
00064
00065         m_ring[m_head] = e;             // insert event into the buffer (FIFO)
00066         if (m_head == (QEQueueCtr)0) {               // need to wrap the head?
00067             m_head = m_end;                                     // wrap around
00068         }
00069         --m_head;
00070
00071         --m_nFree;                             // update number of free events
00072         if (m_nMin > m_nFree) {
00073             m_nMin = m_nFree;                         // update minimum so far
00074         }
00075     }
00076     QF_INT_UNLOCK_();
00077 }
Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: qeq_get.cpp Source File

qeq_get.cpp

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029
00030 // #include "qassert.h"
00031 // Q_DEFINE_THIS_MODULE(qeq_get)
00032
00036
00037 //............................................................................
00038 QEvent const *QEQueue::get(void) {
00039     QEvent const *e;
00040     QF_INT_LOCK_KEY_
00041
00042     QF_INT_LOCK_();
00043     if (m_frontEvt == (QEvent *)0) {                    // is the queue empty?
00044         e = (QEvent *)0;                    // no event available at this time
00045     }
00046     else {
00047         e = m_frontEvt;
00048
00049         if (m_nFree != m_end) {          // any events in the the ring buffer?
00050             m_frontEvt = m_ring[m_tail];         // remove event from the tail
00051             if (m_tail == (QEQueueCtr)0) {           // need to wrap the tail?
00052                 m_tail = m_end;                                 // wrap around
00053             }
00054             --m_tail;
00055
00056             ++m_nFree;               // one more free event in the ring buffer
00057
00058             QS_BEGIN_NOLOCK_(QS_QF_EQUEUE_GET, QS::eqObj_, this)
00059                 QS_TIME_();                                       // timestamp
00060                 QS_SIG_(e->sig);                   // the signal of this event
00061                 QS_OBJ_(this);                            // this queue object
00062                 QS_U8_(e->dynamic_);    // the dynamic attributes of the event
00063                 QS_EQC_(m_nFree);                    // number of free entries
00064             QS_END_NOLOCK_()
00065         }
00066         else {
00067             m_frontEvt = (QEvent *)0;               // the queue becomes empty
00068
00069             QS_BEGIN_NOLOCK_(QS_QF_EQUEUE_GET_LAST, QS::eqObj_, this)
00070                 QS_TIME_();                                       // timestamp
00071                 QS_SIG_(e->sig);                   // the signal of this event
00072                 QS_OBJ_(this);                            // this queue object
00073                 QS_U8_(e->dynamic_);     // the dynamic attribute of the event
00074             QS_END_NOLOCK_()
00075         }
00076     }
00077     QF_INT_UNLOCK_();
00078     return e;
00079 }
Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: qeq_init.cpp Source File

qeq_init.cpp

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029
00033
00034 //............................................................................
00035 void QEQueue::init(QEvent const *qSto[], QEQueueCtr qLen) {
00036     m_frontEvt = (QEvent *)0;                        // no events in the queue
00037     m_ring     = &qSto[0];
00038     m_end      = qLen;
00039     m_head     = (QEQueueCtr)0;
00040     m_tail     = (QEQueueCtr)0;
00041     m_nFree    = qLen;
00042     m_nMin     = qLen;
00043
00044     QS_INT_LOCK_KEY_
00045     QS_BEGIN_(QS_QF_EQUEUE_INIT, QS::eqObj_, this)
00046         QS_OBJ_(qSto);                                  // this QEQueue object
00047         QS_EQC_(qLen);                              // the length of the queue
00048     QS_END_()
00049 }
Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: qeq_lifo.cpp Source File

qeq_lifo.cpp

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029 #include "qassert.h"
00030
00031 Q_DEFINE_THIS_MODULE(qeq_lifo)
00032
00033
00034
00035
00036
00037 //............................................................................
00038 void QEQueue::postLIFO(QEvent const *e) {
00039     QF_INT_LOCK_KEY_
00040     QF_INT_LOCK_();
00041
00042     QS_BEGIN_NOLOCK_(QS_QF_EQUEUE_POST_LIFO, QS::eqObj_, this)
00043         QS_TIME_();                                               // timestamp
00044         QS_SIG_(e->sig);                           // the signal of this event
00045         QS_OBJ_(this);                                    // this queue object
00046         QS_U8_(e->dynamic_);             // the dynamic attribute of the event
00047         QS_EQC_(m_nFree);                            // number of free entries
00048         QS_EQC_(m_nMin);                         // min number of free entries
00049     QS_END_NOLOCK_()
00050
00051     if (e->dynamic_ != (uint8_t)0) {                 // is it a dynamic event?
00052         //lint -e1773                               Attempt to cast away const
00053         ++((QEvent *)e)->dynamic_;          // increment the reference counter
00054                    // NOTE: cast the 'const' away, which is legitimate because
00055                    // it's a dynamic event
00056     }
00057
00058     if (m_frontEvt != (QEvent *)0) {                // is the queue not empty?
00059                // the queue must be able to accept the event (cannot overflow)
00060         Q_ASSERT(m_nFree != (QEQueueCtr)0);
00061
00062         ++m_tail;
00063         if (m_tail == m_end) {                       // need to wrap the tail?
00064             m_tail = (QEQueueCtr)0;                             // wrap around
00065         }
00066
00067         m_ring[m_tail] = m_frontEvt;               // buffer the old front evt
00068
00069         --m_nFree;                             // update number of free events
00070         if (m_nMin > m_nFree) {
00071             m_nMin = m_nFree;                         // update minimum so far
00072         }
00073     }
00074
00075     m_frontEvt = e;                        // stick the new event to the front
00076
00077     QF_INT_UNLOCK_();
00078 }
Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: qequeue.h Source File

qequeue.h

Go to the documentation of this file.
00001
00002 // Product: QF/C++, platform-independent event queue interface.
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 06, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #ifndef qequeue_h
00029 #define qequeue_h
00030
00040
00041 #ifndef QF_EQUEUE_CTR_SIZE
00042
00050     #define QF_EQUEUE_CTR_SIZE 1
00051 #endif
00052 #if (QF_EQUEUE_CTR_SIZE == 1)
00053
00059     typedef uint8_t QEQueueCtr;
00060 #elif (QF_EQUEUE_CTR_SIZE == 2)
00061     typedef uint16_t QEQueueCtr;
00062 #elif (QF_EQUEUE_CTR_SIZE == 4)
00063     typedef uint32_t QEQueueCtr;
00064 #else
00065     #error "QF_EQUEUE_CTR_SIZE defined incorrectly, expected 1, 2, or 4"
00066 #endif
00067
00068
00110 class QEQueue {
00111 private:
00112
00123     QEvent const *m_frontEvt;
00124
00126     QEvent const **m_ring;
00127
00130     QEQueueCtr m_end;
00131
00133     QEQueueCtr m_head;
00134
00136     QEQueueCtr m_tail;
00137
00139     QEQueueCtr m_nFree;
00140
00146     QEQueueCtr m_nMin;
00147
00148 public:
00149
00158     void init(QEvent const *qSto[], QEQueueCtr qLen);
00159
00169     void postFIFO(QEvent const *e);
00170
00180     void postLIFO(QEvent const *e);
00181
00193     QEvent const *get(void);
00194
00205     QEQueueCtr getNFree(void) const {
00206         return m_nFree;
00207     }
00208
00209 private:
00210     friend class QF;
00211     friend class QActive;
00212 };
00213
00214 #endif                                                            // qequeue_h
00215
Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: qevent.h Source File

qevent.h

Go to the documentation of this file.
00001
00002 // Product: QEP/C++ platform-independent public interface
00003 // Last Updated for Version: 4.1.06
00004 // Date of the Last Update:  Jan 06, 2011
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2011 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #ifndef qevent_h
00029 #define qevent_h
00030
00037
00044 #define QP_VERSION      0x4106
00045
00046 #ifndef Q_ROM
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059     #define Q_ROM
00060 #endif
00061 #ifndef Q_ROM_VAR            // if NOT defined, provide the default definition
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075     #define Q_ROM_VAR
00076 #endif
00077 #ifndef Q_ROM_BYTE
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091     #define Q_ROM_BYTE(rom_var_)   (rom_var_)
00092 #endif
00093
00094 #ifndef Q_SIGNAL_SIZE
00095
00096
00097
00098
00099
00100
00101     #define Q_SIGNAL_SIZE 1
00102 #endif
00103 #if (Q_SIGNAL_SIZE == 1)
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117     typedef uint8_t QSignal;
00118 #elif (Q_SIGNAL_SIZE == 2)
00119     typedef uint16_t QSignal;
00120 #elif (Q_SIGNAL_SIZE == 4)
00121     typedef uint32_t QSignal;
00122 #else
00123     #error "Q_SIGNAL_SIZE defined incorrectly, expected 1, 2, or 4"
00124 #endif
00125
00139 struct QEvent {
00140     QSignal sig;
00141     uint8_t dynamic_;
00142 };
00143
00146 #define Q_DIM(array_) (sizeof(array_) / sizeof(array_[0]))
00147
00148 #endif                                                             // qevent_h
Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: qf.h Source File

qf.h

Go to the documentation of this file.
00001
00002 // Product: QF/C++ platform-independent public interface
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 06, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #ifndef qf_h
00029 #define qf_h
00030
00037
00039 #if (QF_MAX_ACTIVE < 1) || (63 < QF_MAX_ACTIVE)
00040     #error "QF_MAX_ACTIVE not defined or out of range. Valid range is 1..63"
00041 #endif
00042
00044 #ifndef QF_EVENT_SIZ_SIZE
00045
00047     #define QF_EVENT_SIZ_SIZE 2
00048 #endif
00049 #if (QF_EVENT_SIZ_SIZE == 1)
00050
00056     typedef uint8_t QEventSize;
00057 #elif (QF_EVENT_SIZ_SIZE == 2)
00058     typedef uint16_t QEventSize;
00059 #elif (QF_EVENT_SIZ_SIZE == 4)
00060     typedef uint32_t QEventSize;
00061 #else
00062     #error "QF_EVENT_SIZ_SIZE defined incorrectly, expected 1, 2, or 4"
00063 #endif
00064
00065
00067 #ifndef QF_ACTIVE_SUPER_
00068
00084     #define QF_ACTIVE_SUPER_  QHsm
00085
00087     #define QF_ACTIVE_STATE_  QStateHandler
00088
00089 #endif
00090
00091 class QEQueue;                                          // forward declaration
00092
00093
00113 class QActive : public QF_ACTIVE_SUPER_ {
00114 private:
00115
00125     QF_EQUEUE_TYPE m_eQueue;
00126
00127 public:
00128 #ifdef QF_OS_OBJECT_TYPE
00129
00130
00131
00132
00133
00134
00135     QF_OS_OBJECT_TYPE m_osObject;
00136 #endif
00137
00138 #ifdef QF_THREAD_TYPE
00139
00140
00141
00142
00143
00144
00145     QF_THREAD_TYPE m_thread;
00146 #endif
00147
00150     uint8_t m_prio;
00151
00160     uint8_t m_running;
00161
00162 public:
00163
00190     void start(uint8_t prio,
00191                QEvent const *qSto[], uint32_t qLen,
00192                void *stkSto, uint32_t stkSize,
00193                QEvent const *ie = (QEvent *)0);
00194
00213     void postFIFO(QEvent const *e);
00214
00221     void postLIFO(QEvent const *e);
00222
00233     void run(void);
00234
00248     QEvent const *get_(void);
00249
00250 protected:
00251
00261     QActive(QF_ACTIVE_STATE_ initial) : QF_ACTIVE_SUPER_(initial) {
00262     }
00263
00277     void stop(void);
00278
00292     void subscribe(QSignal sig) const;
00293
00312     void unsubscribe(QSignal sig) const;
00313
00327     void defer(QEQueue *eq, QEvent const *e);
00328
00344     QEvent const *recall(QEQueue *eq);
00345
00346 public:
00365     void unsubscribeAll(void) const;
00366
00367 private:
00368
00369     friend class QF;
00370     friend class QTimeEvt;
00371     #ifndef QF_INT_KEY_TYPE
00372         friend void QK_schedule_(void);
00373         friend void QK_scheduleExt_(void);
00374     #else
00375         friend void QK_schedule_(QF_INT_KEY_TYPE intLockKey);
00376         friend void QK_scheduleExt_(QF_INT_KEY_TYPE intLockKey);
00377     #endif
00378 };
00379
00380
00382 #ifndef QF_TIMEEVT_CTR_SIZE
00383
00384
00385     #define QF_TIMEEVT_CTR_SIZE 2
00386 #endif
00387 #if (QF_TIMEEVT_CTR_SIZE == 1)
00388
00397     typedef uint8_t QTimeEvtCtr;
00398 #elif (QF_TIMEEVT_CTR_SIZE == 2)
00399     typedef uint16_t QTimeEvtCtr;
00400 #elif (QF_TIMEEVT_CTR_SIZE == 4)
00401     typedef uint32_t QTimeEvtCtr;
00402 #else
00403     #error "QF_TIMEEVT_CTR_SIZE defined incorrectly, expected 1, 2, or 4"
00404 #endif
00405
00437 class QTimeEvt : public QEvent {
00438 private:
00439
00441     QTimeEvt *m_prev;
00442
00444     QTimeEvt *m_next;
00445
00447     QActive *m_act;
00448
00452     QTimeEvtCtr m_ctr;
00453
00458     QTimeEvtCtr m_interval;
00459
00460 public:
00461
00474     QTimeEvt(QSignal s);
00475
00493     void postIn(QActive *act, QTimeEvtCtr nTicks) {
00494         m_interval = (uint16_t)0;
00495         arm_(act, nTicks);
00496     }
00497
00518     void postEvery(QActive *act, QTimeEvtCtr nTicks) {
00519         m_interval = nTicks;
00520         arm_(act, nTicks);
00521     }
00522
00533     uint8_t disarm(void);
00534
00551     uint8_t rearm(QTimeEvtCtr nTicks);
00552
00553     // for backwards compatibility
00554
00558     void fireIn(QActive *act, QTimeEvtCtr nTicks) {
00559         postIn(act, nTicks);
00560     }
00561
00565     void fireEvery(QActive *act, QTimeEvtCtr nTicks) {
00566         postEvery(act, nTicks);
00567     }
00568
00569 private:
00570
00576     void arm_(QActive *act, QTimeEvtCtr nTicks);
00577
00578     friend class QF;
00579 };
00580
00581
00582 #if (QF_MAX_ACTIVE > 63)
00583     #error "QF_MAX_ACTIVE exceeds 63"
00584 #endif
00585
00592 class QSubscrList {
00593 private:
00594
00603     uint8_t m_bits[((QF_MAX_ACTIVE - 1) / 8) + 1];
00604
00605     friend class QF;
00606     friend class QActive;
00607 };
00608
00614 class QF {
00615 public:
00616
00621     static void init(void);
00622
00648     static void psInit(QSubscrList *subscrSto, QSignal maxSignal);
00649
00682     static void poolInit(void *poolSto, uint32_t poolSize,
00683                          QEventSize evtSize);
00684
00706     static void run(void);
00707
00713     static void onStartup(void);
00714
00727     static void onCleanup(void);
00728
00729 #ifndef QF_INT_KEY_TYPE
00730     static void onIdle(void);                // interrupt lock key NOT defined
00731
00732 #else
00733
00757     static void onIdle(QF_INT_KEY_TYPE intLockKey);   // int. lock key defined
00758
00759 #endif                                                      // QF_INT_KEY_TYPE
00760
00778     static void stop(void);
00779
00791     static void publish(QEvent const *e);
00792
00807     static void tick(void);
00808
00818     static char const Q_ROM * Q_ROM_VAR getVersion(void);
00819
00828     static char const Q_ROM * Q_ROM_VAR getPortVersion(void);
00829
00842     static uint32_t getPoolMargin(uint8_t poolId);
00843
00855     static uint32_t getQueueMargin(uint8_t prio);
00856
00861     static QEvent *new_(uint16_t evtSize, QSignal sig);
00862
00876     #define Q_NEW(evtT_, sig_) ((evtT_ *)QF::new_(sizeof(evtT_), (sig_)))
00877
00899     static void gc(QEvent const *e);
00900
00904     static QActive *active_[];
00905
00906 private:                              // functions to be used in QF ports only
00907
00918     static void add_(QActive *a);
00919
00920 public:
00932     static void remove_(QActive const *a);
00933
00934     friend class QActive;
00935 };
00936
00938 // useful lookup tables
00939
00949 extern uint8_t const Q_ROM Q_ROM_VAR QF_log2Lkup[256];
00950
00956 extern uint8_t const Q_ROM Q_ROM_VAR QF_pwr2Lkup[65];
00957
00963 extern uint8_t const Q_ROM Q_ROM_VAR QF_invPwr2Lkup[65];
00964
00969 extern uint8_t const Q_ROM Q_ROM_VAR QF_div8Lkup[65];
00970
00971
00973 // QS software tracing integration, only if enabled
00974 #ifdef Q_SPY                                   // QS software tracing enabled?
00975     #ifndef qs_h
00976     #include "qs_port.h"                                    // include QS port
00977     #endif                                                             // qs_h
00978
00979     #if (QF_EQUEUE_CTR_SIZE == 1)
00980
00984         #define QS_EQC_(ctr_)       QS::u8_(ctr_)
00985     #elif (QF_EQUEUE_CTR_SIZE == 2)
00986         #define QS_EQC_(ctr_)       QS::u16_(ctr_)
00987     #elif (QF_EQUEUE_CTR_SIZE == 4)
00988         #define QS_EQC_(ctr_)       QS::u32_(ctr_)
00989     #else
00990         #error "QF_EQUEUE_CTR_SIZE not defined"
00991     #endif
00992
00993
00994     #if (QF_EVENT_SIZ_SIZE == 1)
00995
00999         #define QS_EVS_(size_)      QS::u8_(size_)
01000     #elif (QF_EVENT_SIZ_SIZE == 2)
01001         #define QS_EVS_(size_)      QS::u16_(size_)
01002     #elif (QF_EVENT_SIZ_SIZE == 4)
01003         #define QS_EVS_(size_)      QS::u32_(size_)
01004     #endif
01005
01006
01007     #if (QF_MPOOL_SIZ_SIZE == 1)
01008
01012         #define QS_MPS_(size_)      QS::u8_(size_)
01013     #elif (QF_MPOOL_SIZ_SIZE == 2)
01014         #define QS_MPS_(size_)      QS::u16_(size_)
01015     #elif (QF_MPOOL_SIZ_SIZE == 4)
01016         #define QS_MPS_(size_)      QS::u32_(size_)
01017     #endif
01018
01019     #if (QF_MPOOL_CTR_SIZE == 1)
01020
01024         #define QS_MPC_(ctr_)       QS::u8_(ctr_)
01025     #elif (QF_MPOOL_CTR_SIZE == 2)
01026         #define QS_MPC_(ctr_)       QS::u16_(ctr_)
01027     #elif (QF_MPOOL_CTR_SIZE == 4)
01028         #define QS_MPC_(ctr_)       QS::u32_(ctr_)
01029     #endif
01030
01031
01032     #if (QF_TIMEEVT_CTR_SIZE == 1)
01033
01037         #define QS_TEC_(ctr_)       QS::u8_(ctr_)
01038     #elif (QF_TIMEEVT_CTR_SIZE == 2)
01039         #define QS_TEC_(ctr_)       QS::u16_(ctr_)
01040     #elif (QF_TIMEEVT_CTR_SIZE == 4)
01041         #define QS_TEC_(ctr_)       QS::u32_(ctr_)
01042     #endif
01043
01044 #else
01045     #ifndef qs_dummy_h
01046     #include "qs_dummy.h"                   // disable the QS software tracing
01047     #endif
01048 #endif                                                                // Q_SPY
01049
01050 #endif                                                                 // qf_h
Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: qf_act.cpp Source File

qf_act.cpp

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.1.06
00004 // Date of the Last Update:  Dec 01, 2010
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2010 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029 #include "qassert.h"
00030
00031 Q_DEFINE_THIS_MODULE(qf_act)
00032
00033
00034
00035
00036
00037
00038 // public objects ------------------------------------------------------------
00039 QActive *QF::active_[QF_MAX_ACTIVE + 1];        // to be used by QF ports only
00040 uint8_t QF_intLockNest_;                       // interrupt-lock nesting level
00041
00042 //............................................................................
00043 //lint -e970 -e971               ignore MISRA rules 13 and 14 in this function
00044 const char Q_ROM * Q_ROM_VAR QF::getVersion(void) {
00045     static char const Q_ROM Q_ROM_VAR version[] = {
00046         ((QP_VERSION >> 12) & 0xF) + '0',
00047         '.',
00048         ((QP_VERSION >>  8) & 0xF) + '0',
00049         '.',
00050         ((QP_VERSION >>  4) & 0xF) + '0',
00051         (QP_VERSION         & 0xF) + '0',
00052         '\0'
00053     };
00054     return version;
00055 }
00056 //............................................................................
00057 void QF::add_(QActive *a) {
00058     uint8_t p = a->m_prio;
00059
00060     Q_REQUIRE(((uint8_t)0 < p) && (p <= (uint8_t)QF_MAX_ACTIVE)
00061               && (active_[p] == (QActive *)0));
00062
00063     QF_INT_LOCK_KEY_
00064     QF_INT_LOCK_();
00065
00066     active_[p] = a;            // registger the active object at this priority
00067
00068     QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_ADD, QS::aoObj_, a)
00069         QS_TIME_();                                               // timestamp
00070         QS_OBJ_(a);                                       // the active object
00071         QS_U8_(p);                        // the priority of the active object
00072     QS_END_NOLOCK_()
00073
00074     QF_INT_UNLOCK_();
00075 }
00076 //............................................................................
00077 void QF::remove_(QActive const *a) {
00078     uint8_t p = a->m_prio;
00079
00080     Q_REQUIRE(((uint8_t)0 < p) && (p <= (uint8_t)QF_MAX_ACTIVE)
00081               && (active_[p] == a));
00082
00083     QF_INT_LOCK_KEY_
00084     QF_INT_LOCK_();
00085
00086     active_[p] = (QActive *)0;                   // free-up the priority level
00087
00088     QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_REMOVE, QS::aoObj_, a)
00089         QS_TIME_();                                               // timestamp
00090         QS_OBJ_(a);                                       // the active object
00091         QS_U8_(p);                        // the priority of the active object
00092     QS_END_NOLOCK_()
00093
00094     QF_INT_UNLOCK_();
00095 }
Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: qf_gc.cpp Source File

qf_gc.cpp

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029 #include "qassert.h"
00030
00031 Q_DEFINE_THIS_MODULE(qf_gc)
00032
00033
00034
00035
00036
00037 //............................................................................
00038 void QF::gc(QEvent const *e) {
00039     if (e->dynamic_ != (uint8_t)0) {                 // is it a dynamic event?
00040         QF_INT_LOCK_KEY_
00041         QF_INT_LOCK_();
00042
00043         if ((e->dynamic_ & 0x3F) > 1) {      // isn't this the last reference?
00044
00045             //lint -e1773                           Attempt to cast away const
00046             --((QEvent *)e)->dynamic_;      // decrement the reference counter
00047                    // NOTE: cast the 'const' away, which is legitimate because
00048                    // it's a dynamic event
00049
00050             QS_BEGIN_NOLOCK_(QS_QF_GC_ATTEMPT, (void *)0, (void *)0)
00051                 QS_TIME_();                                       // timestamp
00052                 QS_SIG_(e->sig);                    // the signal of the event
00053                 QS_U8_(e->dynamic_);    // the dynamic attributes of the event
00054             QS_END_NOLOCK_()
00055
00056             QF_INT_UNLOCK_();
00057         }
00058         else {         // this is the last reference to this event, recycle it
00059             uint8_t idx = (uint8_t)((e->dynamic_ >> 6) - 1);
00060
00061             QS_BEGIN_NOLOCK_(QS_QF_GC, (void *)0, (void *)0)
00062                 QS_TIME_();                                       // timestamp
00063                 QS_SIG_(e->sig);                    // the signal of the event
00064                 QS_U8_(e->dynamic_);    // the dynamic attributes of the event
00065             QS_END_NOLOCK_()
00066
00067             QF_INT_UNLOCK_();
00068
00069             Q_ASSERT(idx < QF_maxPool_);
00070
00071             //lint -e1773                           Attempt to cast away const
00072             QF_EPOOL_PUT_(QF_pool_[idx], (QEvent *)e);   // cast 'const' away,
00073                              // which is legitimate, because it's a pool event
00074         }
00075     }
00076 }
Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: qf_log2.cpp Source File

qf_log2.cpp

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.1.05
00004 // Date of the Last Update:  oCT 26, 2010
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2010 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029
00033
00034 // Global objects ------------------------------------------------------------
00035 uint8_t const Q_ROM Q_ROM_VAR QF_log2Lkup[256] = {
00036     0U, 1U, 2U, 2U, 3U, 3U, 3U, 3U, 4U, 4U, 4U, 4U, 4U, 4U, 4U, 4U,
00037     5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U,
00038     6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U,
00039     6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U,
00040     7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U,
00041     7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U,
00042     7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U,
00043     7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U,
00044     8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U,
00045     8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U,
00046     8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U,
00047     8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U,
00048     8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U,
00049     8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U,
00050     8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U,
00051     8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U
00052 };
Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: qf_new.cpp Source File

qf_new.cpp

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029 #include "qassert.h"
00030
00031 Q_DEFINE_THIS_MODULE(qf_new)
00032
00033
00034
00035
00036
00037 //............................................................................
00038 QEvent *QF::new_(uint16_t evtSize, QSignal sig) {
00039                     // find the pool id that fits the requested event size ...
00040     uint8_t id = (uint8_t)0;
00041     while (evtSize > QF_EPOOL_EVENT_SIZE_(QF_pool_[id])) {
00042         ++id;
00043         Q_ASSERT(id < QF_maxPool_);      // cannot run out of registered pools
00044     }
00045
00046     QS_INT_LOCK_KEY_
00047     QS_BEGIN_(QS_QF_NEW, (void *)0, (void *)0)
00048         QS_TIME_();                                               // timestamp
00049         QS_EVS_(evtSize);                             // the size of the event
00050         QS_SIG_(sig);                               // the signal of the event
00051     QS_END_()
00052
00053     QEvent *e;
00054     QF_EPOOL_GET_(QF_pool_[id], e);
00055     Q_ASSERT(e != (QEvent *)0);             // pool must not run out of events
00056
00057     e->sig = sig;                                 // set signal for this event
00058
00059                                  // store the dynamic attributes of the event:
00060                                  // the pool ID and the reference counter == 0
00061     e->dynamic_ = (uint8_t)((id + 1) << 6);
00062     return e;
00063 }
Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: qf_pkg.h Source File

qf_pkg.h

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.0.01
00004 // Date of the Last Update:  Jun 09, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #ifndef qf_pkg_h
00029 #define qf_pkg_h
00030
00034
00035 #include "qf_port.h"                                                // QF port
00036
00037                                     // QF-specific interrupt locking/unlocking
00038 #ifndef QF_INT_KEY_TYPE
00039
00047     #define QF_INT_LOCK_KEY_
00048
00057     #define QF_INT_LOCK_()      QF_INT_LOCK(dummy)
00058
00067     #define QF_INT_UNLOCK_()    QF_INT_UNLOCK(dummy)
00068 #else
00069     #define QF_INT_LOCK_KEY_    QF_INT_KEY_TYPE intLockKey_;
00070     #define QF_INT_LOCK_()      QF_INT_LOCK(intLockKey_)
00071     #define QF_INT_UNLOCK_()    QF_INT_UNLOCK(intLockKey_)
00072 #endif
00073
00074 // package-scope objects -----------------------------------------------------
00075 extern QTimeEvt *QF_timeEvtListHead_;
00076 extern QF_EPOOL_TYPE_ QF_pool_[3];
00077 extern uint8_t QF_maxPool_;
00078 extern QSubscrList *QF_subscrList_;
00079 extern QSignal QF_maxSignal_;
00080
00081 //............................................................................
00084 struct QFreeBlock {
00085     QFreeBlock *m_next;
00086 };
00087
00088 #endif                                                             // qf_pkg_h
00089
Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: qf_pool.cpp Source File

qf_pool.cpp

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029 #include "qassert.h"
00030
00031 Q_DEFINE_THIS_MODULE(qf_pool)
00032
00033
00034
00035
00036
00037
00038 // Package-scope objects -----------------------------------------------------
00039 QF_EPOOL_TYPE_ QF_pool_[3];                          // allocate 3 event pools
00040 uint8_t QF_maxPool_;                      // number of initialized event pools
00041
00042 //............................................................................
00043 void QF::poolInit(void *poolSto, uint32_t poolSize, QEventSize evtSize) {
00044                          // cannot exceed the number of available memory pools
00045     Q_REQUIRE(QF_maxPool_ < (uint8_t)Q_DIM(QF_pool_));
00046                // please initialize event pools in ascending order of evtSize:
00047     Q_REQUIRE((QF_maxPool_ == (uint8_t)0)
00048               || (QF_EPOOL_EVENT_SIZE_(QF_pool_[QF_maxPool_ - 1]) < evtSize));
00049     QF_EPOOL_INIT_(QF_pool_[QF_maxPool_], poolSto, poolSize, evtSize);
00050     ++QF_maxPool_;                                            // one more pool
00051 }
Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: qf_port.h Source File

qf_port.h

Go to the documentation of this file.
00001
00002 // Product: QF/C++ port to Lint, Generic C++ compiler
00003 // Last Updated for Version: 4.0.03
00004 // Date of the Last Update:  Dec 27, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #ifndef qf_port_h
00029 #define qf_port_h
00030
00037
00056 #define QF_MAX_ACTIVE               63
00057
00074 #define QF_EVENT_SIZ_SIZE           2
00075
00093 #define QF_EQUEUE_CTR_SIZE          1
00094
00115 #define QF_MPOOL_SIZ_SIZE           2
00116
00134 #define QF_MPOOL_CTR_SIZE           2
00135
00152 #define QF_TIMEEVT_CTR_SIZE         4
00153
00175 #define QF_ACTIVE_BASE              QHsm
00176
00182 /*lint -e970 */
00183 #define QF_INT_KEY_TYPE             int
00184
00195 #define QF_INT_LOCK(key_)           ((key_) = intLock())
00196
00207 #define QF_INT_UNLOCK(key_) intUnlock(key_)
00208
00209 QF_INT_KEY_TYPE intLock(void);
00210 void intUnlock(QF_INT_KEY_TYPE intLockKey);
00211
00212
00213 #include "qep_port.h"                                              // QEP port
00214 #include "qk_port.h"                                                // QK port
00215 #include "qf.h"                    // QF platform-independent public interface
00216
00217 #endif                                                            // qf_port_h
Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: qf_psini.cpp Source File

qf_psini.cpp

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029
00034
00035 // Package-scope objects -----------------------------------------------------
00036 QSubscrList *QF_subscrList_;
00037 QSignal QF_maxSignal_;
00038
00039 //............................................................................
00040 void QF::psInit(QSubscrList *subscrSto, QSignal maxSignal) {
00041     QF_subscrList_ = subscrSto;
00042     QF_maxSignal_ = maxSignal;
00043 }
Generated on Fri Jan 7 2011 21:37:29 for QP/C++ by doxygen 1.7.3


QP/C++: qf_pspub.cpp Source File

qf_pspub.cpp

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029 #include "qassert.h"
00030
00031 Q_DEFINE_THIS_MODULE(qf_pspub)
00032
00033
00034
00035
00036
00037 //............................................................................
00038 void QF::publish(QEvent const *e) {
00039          // make sure that the published signal is within the configured range
00040     Q_REQUIRE(e->sig < QF_maxSignal_);
00041
00042     QF_INT_LOCK_KEY_
00043     QF_INT_LOCK_();
00044
00045     QS_BEGIN_NOLOCK_(QS_QF_PUBLISH, (void *)0, (void *)0)
00046         QS_TIME_();                                           // the timestamp
00047         QS_SIG_(e->sig);                            // the signal of the event
00048         QS_U8_(e->dynamic_);            // the dynamic attributes of the event
00049     QS_END_NOLOCK_()
00050
00051     if (e->dynamic_ != (uint8_t)0) {                 // is it a dynamic event?
00052         //lint -e1773                               Attempt to cast away const
00053         ++((QEvent *)e)->dynamic_;      // increment reference counter, NOTE01
00054                    // NOTE: cast the 'const' away, which is legitimate because
00055                    // it's a dynamic event */
00056     }
00057     QF_INT_UNLOCK_();
00058
00059 #if (QF_MAX_ACTIVE <= 8)
00060     uint8_t tmp = QF_subscrList_[e->sig].m_bits[0];
00061     while (tmp != (uint8_t)0) {
00062         uint8_t p = Q_ROM_BYTE(QF_log2Lkup[tmp]);
00063         tmp &= Q_ROM_BYTE(QF_invPwr2Lkup[p]);      // clear the subscriber bit
00064         Q_ASSERT(active_[p] != (QActive *)0);            // must be registered
00065
00066         active_[p]->postFIFO(e);  // internally asserts if the queue overflows
00067     }
00068 #else
00069     uint8_t i = Q_DIM(QF_subscrList_[0].m_bits);// number of bytes in the list
00070     do {                       // go through all bytes in the subsciption list
00071         --i;
00072         uint8_t tmp = QF_subscrList_[e->sig].m_bits[i];
00073         while (tmp != (uint8_t)0) {
00074             uint8_t p = Q_ROM_BYTE(QF_log2Lkup[tmp]);
00075             tmp &= Q_ROM_BYTE(QF_invPwr2Lkup[p]);  // clear the subscriber bit
00076             p = (uint8_t)(p + (i << 3));                // adjust the priority
00077             Q_ASSERT(active_[p] != (QActive *)0);        // must be registered
00078
00079                        // postFIFO() internally asserts if the queue overflows
00080             active_[p]->postFIFO(e);
00081         }
00082     } while (i != (uint8_t)0);
00083 #endif
00084
00085     gc(e);                            // run the garbage collector, see NOTE01
00086 }
00087
00089 // NOTE01:
00090 // QF::publish() increments the reference counter to prevent premature
00091 // recycling of the event while the multicasting is still in progress.
00092 // At the end of the function, the garbage collector step decrements the
00093 // reference counter and recycles the event if the counter drops to zero.
00094 // This covers the case when the event was published without any subscribers.
00095 //


QP/C++: qf_pwr2.cpp Source File

qf_pwr2.cpp

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.1.05
00004 // Date of the Last Update:  oCT 26, 2010
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2010 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029
00033
00034 // Global objects ------------------------------------------------------------
00035 uint8_t const Q_ROM Q_ROM_VAR QF_pwr2Lkup[65] = {
00036     0x00U,                                                  // unused location
00037     0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U,
00038     0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U,
00039     0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U,
00040     0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U,
00041     0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U,
00042     0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U,
00043     0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U,
00044     0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U
00045 };
00046
00047 uint8_t const Q_ROM Q_ROM_VAR QF_invPwr2Lkup[65] = {
00048     0xFFU,                                                  // unused location
00049     0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU,
00050     0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU,
00051     0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU,
00052     0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU,
00053     0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU,
00054     0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU,
00055     0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU,
00056     0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU
00057 };
00058
00059 uint8_t const Q_ROM Q_ROM_VAR QF_div8Lkup[65] = {
00060     0U,                                                     // unused location
00061     0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
00062     1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U,
00063     2U, 2U, 2U, 2U, 2U, 2U, 2U, 2U,
00064     3U, 3U, 3U, 3U, 3U, 3U, 3U, 3U,
00065     4U, 4U, 4U, 4U, 4U, 4U, 4U, 4U,
00066     5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U,
00067     6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U,
00068     7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U
00069 };


QP/C++: qf_tick.cpp Source File

qf_tick.cpp

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.1.05
00004 // Date of the Last Update:  Oct 27, 2010
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2010 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029
00030 // #include "qassert.h"
00031 // Q_DEFINE_THIS_MODULE(qf_tick)
00032
00036
00037 //............................................................................
00038 void QF::tick(void) {                                            // see NOTE01
00039     QF_INT_LOCK_KEY_
00040     QF_INT_LOCK_();
00041
00042     QS_BEGIN_NOLOCK_(QS_QF_TICK, (void *)0, (void *)0)
00043         QS_TEC_(++QS::tickCtr_);                           // the tick counter
00044     QS_END_NOLOCK_()
00045
00046     QTimeEvt *t = QF_timeEvtListHead_;
00047     while (t != (QTimeEvt *)0) {
00048         --t->m_ctr;
00049         if (t->m_ctr == (QTimeEvtCtr)0) {  // is the time evt about to expire?
00050             if (t->m_interval != (QTimeEvtCtr)0) {//is it a periodic time evt?
00051                 t->m_ctr = t->m_interval;                // rearm the time evt
00052             }
00053             else {   // one-shot time evt, disarm by removing it from the list
00054                 if (t == QF_timeEvtListHead_) {
00055                     QF_timeEvtListHead_ = t->m_next;
00056                 }
00057                 else {
00058                     if (t->m_next != (QTimeEvt *)0) {// not the last time evt?
00059                         t->m_next->m_prev = t->m_prev;
00060                     }
00061                     t->m_prev->m_next = t->m_next;
00062                 }
00063                 t->m_prev = (QTimeEvt *)0;     // mark the time event disarmed
00064
00065                 QS_BEGIN_NOLOCK_(QS_QF_TIMEEVT_AUTO_DISARM, QS::teObj_, t)
00066                     QS_OBJ_(t);                      // this time event object
00067                     QS_OBJ_(t->m_act);                     // the active object
00068                 QS_END_NOLOCK_()
00069             }
00070
00071             QS_BEGIN_NOLOCK_(QS_QF_TIMEEVT_POST, QS::teObj_, t)
00072                 QS_TIME_();                                       // timestamp
00073                 QS_OBJ_(t);                           // the time event object
00074                 QS_SIG_(t->sig);              // the signal of this time event
00075                 QS_OBJ_(t->m_act);                        // the active object
00076             QS_END_NOLOCK_()
00077
00078             QF_INT_UNLOCK_();   // unlock interrupts before calling QF service
00079
00080                   // postFIFO() asserts internally that the event was accepted
00081             t->m_act->postFIFO(t);
00082         }
00083         else {
00084             QF_INT_UNLOCK_();
00085             static uint8_t volatile dummy;
00086             dummy = (uint8_t)0;      // execute a few instructions, see NOTE02
00087         }
00088
00089         QF_INT_LOCK_();           // lock interrupts again to advance the link
00090         t = t->m_next;
00091     }
00092     QF_INT_UNLOCK_();
00093 }
00094
00096 // NOTE01:
00097 // QF::tick() must always run to completion and never preempt itself.
00098 // In particular, if QF::tick() runs in an ISR, the ISR is not allowed to
00099 // preempt itself. Also, QF::tick() should not be called from two different
00100 // ISRs, which potentially could preempt each other.
00101 //
00102 // NOTE02:
00103 // On many CPUs, the interrupt unlocking takes only effect on the next
00104 // machine instruction, which happens to be here another interrupt lock.
00105 // The assignment of a volatile variable requires a few instructions, which
00106 // the compiler cannot optimize away. This ensures that the interrupts get
00107 // actually unlocked, so that the interrupt latency stays low.
00108 //


QP/C++: qfsm_dis.cpp Source File

qfsm_dis.cpp

Go to the documentation of this file.
00001
00002 // Product: QEP/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 06, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qep_pkg.h"
00029
00033
00034 //............................................................................
00035 void QFsm::dispatch(QEvent const *e) {
00036     QStateHandler s = m_state;
00037     QS_INT_LOCK_KEY_
00038     QState r = (*s)(this, e);                        // call the event handler
00039
00040     if (r == Q_RET_TRAN) {                                // transition taken?
00041
00042         QS_BEGIN_(QS_QEP_TRAN, QS::smObj_, this)
00043             QS_TIME_();                                          // time stamp
00044             QS_SIG_(e->sig);                        // the signal of the event
00045             QS_OBJ_(this);                        // this state machine object
00046             QS_FUN_(s);                        // the source of the transition
00047             QS_FUN_(m_state);                          // the new active state
00048         QS_END_()
00049
00050         (void)QEP_TRIG_(s, Q_EXIT_SIG);                     // exit the source
00051         (void)QEP_TRIG_(m_state, Q_ENTRY_SIG);             // enter the target
00052     }
00053     else {
00054 #ifdef Q_SPY
00055         if (r == Q_RET_HANDLED) {
00056
00057             QS_BEGIN_(QS_QEP_INTERN_TRAN, QS::smObj_, this)
00058                 QS_TIME_();                                      // time stamp
00059                 QS_SIG_(e->sig);                    // the signal of the event
00060                 QS_OBJ_(this);                    // this state machine object
00061                 QS_FUN_(s);                // the state that handled the event
00062             QS_END_()
00063
00064         }
00065         else {
00066
00067             QS_BEGIN_(QS_QEP_IGNORED, QS::smObj_, this)
00068                 QS_TIME_();                                      // time stamp
00069                 QS_SIG_(e->sig);                    // the signal of the event
00070                 QS_OBJ_(this);                    // this state machine object
00071                 QS_FUN_(m_state);                         // the current state
00072             QS_END_()
00073
00074         }
00075 #endif
00076     }
00077 }


QP/C++: qfsm_ini.cpp Source File

qfsm_ini.cpp

Go to the documentation of this file.
00001
00002 // Product: QEP/C++
00003 // Last Updated for Version: 4.0.04
00004 // Date of the Last Update:  Apr 08, 2009
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2009 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qep_pkg.h"
00029 #include "qassert.h"
00030
00031 Q_DEFINE_THIS_MODULE(qfsm_ini)
00032
00033
00034
00035
00036
00037 //............................................................................
00038 QFsm::~QFsm() {
00039 }
00040 //............................................................................
00041 void QFsm::init(QEvent const *e) {
00042     QS_INT_LOCK_KEY_
00043
00044     QS_BEGIN_(QS_QEP_STATE_INIT, QS::smObj_, this)
00045         QS_OBJ_(this);                            // this state machine object
00046         QS_FUN_((QStateHandler)0);       // the source (not defined for a FSM)
00047         QS_FUN_(m_state);                      // the target of the transition
00048     QS_END_()
00049
00050                                     // execute the top-most initial transition
00051     Q_ALLEGE((*m_state)(this, e) == Q_RET_TRAN);   // transition must be taken
00052
00053     (void)QEP_TRIG_(m_state, Q_ENTRY_SIG);                 // enter the target
00054
00055     QS_BEGIN_(QS_QEP_INIT_TRAN, QS::smObj_, this)
00056         QS_TIME_();                                              // time stamp
00057         QS_OBJ_(this);                            // this state machine object
00058         QS_FUN_(m_state);                              // the new active state
00059     QS_END_()
00060 }


QP/C++: qhsm_dis.cpp Source File

qhsm_dis.cpp

Go to the documentation of this file.
00001
00002 // Product: QEP/C++
00003 // Last Updated for Version: 4.1.05
00004 // Date of the Last Update:  Oct 27, 2010
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2010 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qep_pkg.h"
00029 #include "qassert.h"
00030
00031 Q_DEFINE_THIS_MODULE(qhsm_dis)
00032
00033
00034
00035
00036
00037 //............................................................................
00038 void QHsm::dispatch(QEvent const *e) {
00039     QStateHandler path[QEP_MAX_NEST_DEPTH_];
00040     QStateHandler s;
00041     QStateHandler t;
00042     QState r;
00043     QS_INT_LOCK_KEY_
00044
00045     t = m_state;                                     // save the current state
00046
00047     QS_BEGIN_(QS_QEP_DISPATCH, QS::smObj_, this)
00048         QS_TIME_();                                              // time stamp
00049         QS_SIG_(e->sig);                            // the signal of the event
00050         QS_OBJ_(this);                            // this state machine object
00051         QS_FUN_(t);                                       // the current state
00052     QS_END_()
00053
00054     do {                                // process the event hierarchically...
00055         s = m_state;
00056         r = (*s)(this, e);                           // invoke state handler s
00057     } while (r == Q_RET_SUPER);
00058
00059     if (r == Q_RET_TRAN) {                                // transition taken?
00060 #ifdef Q_SPY
00061         QStateHandler src = s;       // save the transition source for tracing
00062 #endif
00063         int8_t ip = (int8_t)(-1);               // transition entry path index
00064         int8_t iq;                       // helper transition entry path index
00065
00066         path[0] = m_state;                // save the target of the transition
00067         path[1] = t;
00068
00069         while (t != s) {       // exit current state to transition source s...
00070             if (QEP_TRIG_(t, Q_EXIT_SIG) == Q_RET_HANDLED) {   //exit handled?
00071                 QS_BEGIN_(QS_QEP_STATE_EXIT, QS::smObj_, this)
00072                     QS_OBJ_(this);                // this state machine object
00073                     QS_FUN_(t);                            // the exited state
00074                 QS_END_()
00075
00076                 (void)QEP_TRIG_(t, QEP_EMPTY_SIG_);    // find superstate of t
00077             }
00078             t = m_state;                       // m_state holds the superstate
00079         }
00080
00081         t = path[0];                               // target of the transition
00082
00083         if (s == t) {         // (a) check source==target (transition to self)
00084             QEP_EXIT_(s)                                    // exit the source
00085             ip = (int8_t)0;                                // enter the target
00086         }
00087         else {
00088             (void)QEP_TRIG_(t, QEP_EMPTY_SIG_);        // superstate of target
00089             t = m_state;
00090             if (s == t) {                   // (b) check source==target->super
00091                 ip = (int8_t)0;                            // enter the target
00092             }
00093             else {
00094                 (void)QEP_TRIG_(s, QEP_EMPTY_SIG_);       // superstate of src
00095                                      // (c) check source->super==target->super
00096                 if (m_state == t) {
00097                     QEP_EXIT_(s)                            // exit the source
00098                     ip = (int8_t)0;                        // enter the target
00099                 }
00100                 else {
00101                                             // (d) check source->super==target
00102                     if (m_state == path[0]) {
00103                         QEP_EXIT_(s)                        // exit the source
00104                     }
00105                     else { // (e) check rest of source==target->super->super..
00106                            // and store the entry path along the way
00107                            //
00108                         iq = (int8_t)0;         // indicate that LCA not found
00109                         ip = (int8_t)1;     // enter target and its superstate
00110                         path[1] = t;          // save the superstate of target
00111                         t = m_state;                     // save source->super
00112                                                   // find target->super->super
00113                         r = QEP_TRIG_(path[1], QEP_EMPTY_SIG_);
00114                         while (r == Q_RET_SUPER) {
00115                             ++ip;
00116                             path[ip] = m_state;        // store the entry path
00117                             if (m_state == s) {           // is it the source?
00118                                 iq = (int8_t)1;     // indicate that LCA found
00119                                                // entry path must not overflow
00120                                 Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_);
00121                                 --ip;               // do not enter the source
00122                                 r = Q_RET_HANDLED;       // terminate the loop
00123                             }
00124                             else {      // it is not the source, keep going up
00125                                 r = QEP_TRIG_(m_state, QEP_EMPTY_SIG_);
00126                             }
00127                         }
00128                         if (iq == (int8_t)0) {       // the LCA not found yet?
00129
00130                                                // entry path must not overflow
00131                             Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_);
00132
00133                             QEP_EXIT_(s)                   // exit the source
00134
00135                             // (f) check the rest of source->super
00136                             //                  == target->super->super...
00137                             //
00138                             iq = ip;
00139                             r = Q_RET_IGNORED;       // indicate LCA NOT found
00140                             do {
00141                                 if (t == path[iq]) {       // is this the LCA?
00142                                     r = Q_RET_HANDLED;   // indicate LCA found
00143                                     ip = (int8_t)(iq - 1); // do not enter LCA
00144                                     iq = (int8_t)(-1);   // terminate the loop
00145                                 }
00146                                 else {
00147                                     --iq;    // try lower superstate of target
00148                                 }
00149                             } while (iq >= (int8_t)0);
00150
00151                             if (r != Q_RET_HANDLED) {    // LCA not found yet?
00152                                 // (g) check each source->super->...
00153                                 // for each target->super...
00154                                 //
00155                                 r = Q_RET_IGNORED;             // keep looping
00156                                 do {
00157                                                           // exit t unhandled?
00158                                     if (QEP_TRIG_(t, Q_EXIT_SIG)
00159                                         == Q_RET_HANDLED)
00160                                     {
00161                                         QS_BEGIN_(QS_QEP_STATE_EXIT,
00162                                                   QS::smObj_, this)
00163                                             QS_OBJ_(this);
00164                                             QS_FUN_(t);
00165                                         QS_END_()
00166
00167                                         (void)QEP_TRIG_(t, QEP_EMPTY_SIG_);
00168                                     }
00169                                     t = m_state;         //  set to super of t
00170                                     iq = ip;
00171                                     do {
00172                                         if (t == path[iq]) {   // is this LCA?
00173                                                            // do not enter LCA
00174                                             ip = (int8_t)(iq - 1);
00175                                             iq = (int8_t)(-1);   //break inner
00176                                             r = Q_RET_HANDLED;   //break outer
00177                                         }
00178                                         else {
00179                                             --iq;
00180                                         }
00181                                     } while (iq >= (int8_t)0);
00182                                 } while (r != Q_RET_HANDLED);
00183                             }
00184                         }
00185                     }
00186                 }
00187             }
00188         }
00189                        // retrace the entry path in reverse (desired) order...
00190         for (; ip >= (int8_t)0; --ip) {
00191             QEP_ENTER_(path[ip])                             // enter path[ip]
00192         }
00193         t = path[0];                         // stick the target into register
00194         m_state = t;                               // update the current state
00195
00196                                          // drill into the target hierarchy...
00197         while (QEP_TRIG_(t, Q_INIT_SIG) == Q_RET_TRAN) {
00198
00199             QS_BEGIN_(QS_QEP_STATE_INIT, QS::smObj_, this)
00200                 QS_OBJ_(this);                    // this state machine object
00201                 QS_FUN_(t);                        // the source (pseudo)state
00202                 QS_FUN_(m_state);              // the target of the transition
00203             QS_END_()
00204
00205             ip = (int8_t)0;
00206             path[0] = m_state;
00207             (void)QEP_TRIG_(m_state, QEP_EMPTY_SIG_);       // find superstate
00208             while (m_state != t) {
00209                 ++ip;
00210                 path[ip] = m_state;
00211                 (void)QEP_TRIG_(m_state, QEP_EMPTY_SIG_);   // find superstate
00212             }
00213             m_state = path[0];
00214                                                // entry path must not overflow
00215             Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_);
00216
00217             do {       // retrace the entry path in reverse (correct) order...
00218                 QEP_ENTER_(path[ip])                         // enter path[ip]
00219                 --ip;
00220             } while (ip >= (int8_t)0);
00221
00222             t = path[0];
00223         }
00224
00225         QS_BEGIN_(QS_QEP_TRAN, QS::smObj_, this)
00226             QS_TIME_();                                          // time stamp
00227             QS_SIG_(e->sig);                        // the signal of the event
00228             QS_OBJ_(this);                        // this state machine object
00229             QS_FUN_(src);                      // the source of the transition
00230             QS_FUN_(t);                                // the new active state
00231         QS_END_()
00232
00233     }
00234     else {                                             // transition not taken
00235 #ifdef Q_SPY
00236         if (r == Q_RET_IGNORED) {                            // event ignored?
00237
00238             QS_BEGIN_(QS_QEP_IGNORED, QS::smObj_, this)
00239                 QS_TIME_();                                      // time stamp
00240                 QS_SIG_(e->sig);                    // the signal of the event
00241                 QS_OBJ_(this);                    // this state machine object
00242                 QS_FUN_(t);                               // the current state
00243             QS_END_()
00244
00245         }
00246         else {                                                // event handled
00247
00248             QS_BEGIN_(QS_QEP_INTERN_TRAN, QS::smObj_, this)
00249                 QS_TIME_();                                      // time stamp
00250                 QS_SIG_(e->sig);                    // the signal of the event
00251                 QS_OBJ_(this);                    // this state machine object
00252                 QS_FUN_(s);                // the state that handled the event
00253             QS_END_()
00254
00255         }
00256 #endif
00257     }
00258     m_state = t;                 // set new state or restore the current state
00259 }


QP/C++: qhsm_in.cpp Source File

qhsm_in.cpp

Go to the documentation of this file.
00001
00002 // Product: QEP/C++
00003 // Last Updated for Version: 4.0.02
00004 // Date of the Last Update:  Oct 27, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qep_pkg.h"
00029
00033
00034 //............................................................................
00035 uint8_t QHsm::isIn(QStateHandler state) {
00036     QStateHandler s = m_state;
00037     QState r;
00038     uint8_t inState = (uint8_t)0;    // assume that this HSM is not in 'state'
00039     do {
00040         if (m_state == state) {                        // do the states match?
00041             inState = (uint8_t)1;                  // match found, return TRUE
00042             r = Q_RET_IGNORED;                        // break out of the loop
00043         }
00044         else {
00045             r = QEP_TRIG_(m_state, QEP_EMPTY_SIG_);
00046         }
00047     } while (r != Q_RET_IGNORED);                // QHsm_top state not reached
00048     m_state = s;                                 // restore the original state
00049     return inState;                                       // return the status
00050 }


QP/C++: qhsm_ini.cpp Source File

qhsm_ini.cpp

Go to the documentation of this file.
00001
00002 // Product: QEP/C++
00003 // Last Updated for Version: 4.1.05
00004 // Date of the Last Update:  Oct 27, 2010
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2010 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qep_pkg.h"
00029 #include "qassert.h"
00030
00031 Q_DEFINE_THIS_MODULE(qhsm_ini)
00032
00033
00034
00035
00036
00037 //............................................................................
00038 QHsm::~QHsm() {
00039 }
00040 //............................................................................
00041 void QHsm::init(QEvent const *e) {
00042     QStateHandler t;
00043     QS_INT_LOCK_KEY_
00044
00045                               // the top-most initial transition must be taken
00046     Q_ALLEGE((*m_state)(this, e) == Q_RET_TRAN);
00047
00048     t = (QStateHandler)&QHsm::top;              // HSM starts in the top state
00049     do {                                           // drill into the target...
00050         QStateHandler path[QEP_MAX_NEST_DEPTH_];
00051         int8_t ip = (int8_t)0;                  // transition entry path index
00052
00053
00054         QS_BEGIN_(QS_QEP_STATE_INIT, QS::smObj_, this)
00055             QS_OBJ_(this);                        // this state machine object
00056             QS_FUN_(t);                                    // the source state
00057             QS_FUN_(m_state);          // the target of the initial transition
00058         QS_END_()
00059
00060         path[0] = m_state;
00061         (void)QEP_TRIG_(m_state, QEP_EMPTY_SIG_);
00062         while (m_state != t) {
00063             ++ip;
00064             path[ip] = m_state;
00065             (void)QEP_TRIG_(m_state, QEP_EMPTY_SIG_);
00066         }
00067         m_state = path[0];
00068                                                // entry path must not overflow
00069         Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_);
00070
00071         do {           // retrace the entry path in reverse (desired) order...
00072             QEP_ENTER_(path[ip]);                            // enter path[ip]
00073             --ip;
00074         } while (ip >= (int8_t)0);
00075
00076         t = path[0];                   // current state becomes the new source
00077     } while (QEP_TRIG_(t, Q_INIT_SIG) == Q_RET_TRAN);
00078     m_state = t;
00079
00080     QS_BEGIN_(QS_QEP_INIT_TRAN, QS::smObj_, this)
00081         QS_TIME_();                                              // time stamp
00082         QS_OBJ_(this);                            // this state machine object
00083         QS_FUN_(m_state);                              // the new active state
00084     QS_END_()
00085 }


QP/C++: qhsm_top.cpp Source File

qhsm_top.cpp

Go to the documentation of this file.
00001
00002 // Product: QEP/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 06, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qep_pkg.h"
00029
00033
00034 //............................................................................
00035 QState QHsm::top(QHsm *, QEvent const *) {
00036     return Q_IGNORED();                    // the top state ignores all events
00037 }


QP/C++: qk.cpp Source File

qk.cpp

Go to the documentation of this file.
00001
00002 // Product: QK/C++
00003 // Last Updated for Version: 4.1.03
00004 // Date of the Last Update:  Feb 15, 2010
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2010 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qk_pkg.h"
00029 #include "qassert.h"
00030
00031 Q_DEFINE_THIS_MODULE(qk)
00032
00033
00034
00035
00036
00037
00038
00039 // Public-scope objects ------------------------------------------------------
00040 #if (QF_MAX_ACTIVE <= 8)
00041     QPSet8  volatile QK_readySet_;                          // ready set of QK
00042 #else
00043     QPSet64 volatile QK_readySet_;                          // ready set of QK
00044 #endif
00045                                          // start with the QK scheduler locked
00046 uint8_t volatile QK_currPrio_ = (uint8_t)(QF_MAX_ACTIVE + 1);
00047 uint8_t volatile QK_intNest_;                 // start with nesting level of 0
00048
00049
00050 //............................................................................
00051 //lint -e970 -e971               ignore MISRA rules 13 and 14 in this function
00052 char const Q_ROM * Q_ROM_VAR QK::getVersion(void) {
00053     static char const Q_ROM Q_ROM_VAR version[] = {
00054         ((QP_VERSION >> 12) & 0xF) + '0',
00055         '.',
00056         ((QP_VERSION >>  8) & 0xF) + '0',
00057         '.',
00058         ((QP_VERSION >>  4) & 0xF) + '0',
00059         (QP_VERSION         & 0xF) + '0',
00060         '\0'
00061     };
00062     return version;
00063 }
00064 //............................................................................
00065 void QF::init(void) {
00066     QK_init();           // QK initialization ("C" linkage, might be assembly)
00067 }
00068 //............................................................................
00069 void QF::stop(void) {
00070     QF::onCleanup();                                       // cleanup callback
00071     // nothing else to do for the QK preemptive kernel
00072 }
00073 //............................................................................
00074 void QF::run(void) {
00075     QK_INT_LOCK_KEY_
00076
00077     QK_INT_LOCK_();
00078     QK_currPrio_ = (uint8_t)0;        // set the priority for the QK idle loop
00079     QK_SCHEDULE_();                      // process all events produced so far
00080     QK_INT_UNLOCK_();
00081
00082     QF::onStartup();                                       // startup callback
00083
00084     for (;;) {                                             // the QK idle loop
00085         QK::onIdle();                        // invoke the QK on-idle callback
00086     }
00087 }
00088 //............................................................................
00089 void QActive::start(uint8_t prio,
00090                     QEvent const *qSto[], uint32_t qLen,
00091                     void *tls, uint32_t flags,
00092                     QEvent const *ie)
00093 {
00094     Q_REQUIRE(((uint8_t)0 < prio) && (prio <= (uint8_t)QF_MAX_ACTIVE));
00095
00096     m_eQueue.init(qSto, (QEQueueCtr)qLen);       // initialize the event queue
00097     m_prio = prio;
00098     QF::add_(this);                     // make QF aware of this active object
00099
00100 #if defined(QK_TLS) || defined(QK_EXT_SAVE)
00101     m_osObject = (uint8_t)flags;       // m_osObject contains the thread flags
00102     m_thread   = tls;      // contains the pointer to the thread-local-storage
00103 #else
00104     Q_ASSERT((tls == (void *)0) && (flags == (uint32_t)0));
00105 #endif
00106
00107     init(ie);                                    // execute initial transition
00108
00109     QS_FLUSH();                          // flush the trace buffer to the host
00110 }
00111 //............................................................................
00112 void QActive::stop(void) {
00113     QF::remove_(this);                // remove this active object from the QF
00114 }


QP/C++: qk.h Source File

qk.h

Go to the documentation of this file.
00001
00002 // Product: QK/C++ platform-independent public interface
00003 // Last Updated for Version: 4.0.03
00004 // Date of the Last Update:  Dec 26, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #ifndef qk_h
00029 #define qk_h
00030
00037
00038 #include "qequeue.h"          // The QK kernel uses the native QF event queue
00039 #include "qmpool.h"           // The QK kernel uses the native QF memory pool
00040 #include "qpset.h"            // The QK kernel uses the native QF priority set
00041
00042
00044 // QF configuration for QK
00045
00053 #define QF_EQUEUE_TYPE             QEQueue
00054
00055 #if defined(QK_TLS) || defined(QK_EXT_SAVE)
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067     #define QF_OS_OBJECT_TYPE      uint8_t
00068
00076     #define QF_THREAD_TYPE         void *
00077 #endif                                             /* QK_TLS || QK_EXT_SAVE */
00078
00079 #if (QF_MAX_ACTIVE <= 8)
00080     extern QPSet8  volatile QK_readySet_;
00081 #else
00082     extern QPSet64 volatile QK_readySet_;
00083 #endif
00084
00085 extern uint8_t volatile QK_currPrio_;
00086 extern uint8_t volatile QK_intNest_;
00087
00088 // QK active object queue implementation .....................................
00089
00096 // need to define the macro appropriately for the underlying kernel/OS you're
00098 #define QACTIVE_EQUEUE_WAIT_(me_) \
00099     Q_ASSERT((me_)->m_eQueue.m_frontEvt != (QEvent *)0)
00100
00114 #define QACTIVE_EQUEUE_SIGNAL_(me_) \
00115     QK_readySet_.insert((me_)->m_prio); \
00116     if (QK_intNest_ == (uint8_t)0) { \
00117         QK_SCHEDULE_(); \
00118     } else ((void)0)
00119
00129 #define QACTIVE_EQUEUE_ONEMPTY_(me_) \
00130     QK_readySet_.remove((me_)->m_prio)
00131
00132 // QK event pool operations ..................................................
00133
00140 #define QF_EPOOL_TYPE_              QMPool
00141
00147 #define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_) \
00148     (p_).init(poolSto_, poolSize_, evtSize_)
00149
00156 #define QF_EPOOL_EVENT_SIZE_(p_)    ((p_).getBlockSize())
00157
00164 #define QF_EPOOL_GET_(p_, e_)       ((e_) = (QEvent *)(p_).get())
00165
00172 #define QF_EPOOL_PUT_(p_, e_)       ((p_).put(e_))
00173
00174 #ifndef QK_NO_MUTEX
00175
00176
00177
00178
00179
00180
00181     typedef uint8_t QMutex;
00182 #endif                                                          // QK_NO_MUTEX
00183
00190 // \note The QK scheduler, QK priority, QK ready set, etc. belong conceptually
00195 class QK {
00196 public:
00197
00205     static char const Q_ROM * Q_ROM_VAR getVersion(void);
00206
00215     static char const Q_ROM * Q_ROM_VAR getPortVersion(void);
00216
00227     static void onIdle(void);
00228
00229 #ifndef QK_NO_MUTEX
00230
00235     // \note This function should be always paired with QK::mutexUnlock().
00240     static QMutex mutexLock(uint8_t prioCeiling);
00241
00249     static void mutexUnlock(QMutex mutex);
00250
00251 #endif                                                          // QK_NO_MUTEX
00252
00253 };
00254
00255 extern "C" {
00256
00261 void QK_init(void);
00262
00263 // QK scheduler and extended scheduler
00264 #ifndef QF_INT_KEY_TYPE
00265     void QK_schedule_(void);                                   // QK scheduler
00266     void QK_scheduleExt_(void);                       // QK extended scheduler
00267
00268     #define QK_SCHEDULE_()    QK_schedule_()
00269 #else
00270
00287     void QK_schedule_(QF_INT_KEY_TYPE intLockKey);
00288
00302     void QK_scheduleExt_(QF_INT_KEY_TYPE intLockKey); // QK extended scheduler
00303
00308     #define QK_SCHEDULE_()    QK_schedule_(intLockKey_)
00309
00310 #endif
00311 }                                                                // extern "C"
00312
00314 // QS software tracing integration, only if enabled
00315 #ifdef Q_SPY                                   // QS software tracing enabled?
00316     #ifndef qs_h
00317     #include "qs_port.h"                                    // include QS port
00318     #endif
00319 #else
00320     #ifndef qs_dummy_h
00321     #include "qs_dummy.h"                   // disable the QS software tracing
00322     #endif
00323 #endif                                                                // Q_SPY
00324
00325 #endif                                                                 // qk_h


QP/C++: qk_ext.cpp Source File

qk_ext.cpp

Go to the documentation of this file.
00001
00002 // Product: QK/C++
00003 // Last Updated for Version: 4.1.00
00004 // Date of the Last Update:  Oct 09, 2009
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2009 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qk_pkg.h"
00029 #include "qassert.h"
00030
00031 Q_DEFINE_THIS_MODULE(qk_ext)
00032
00033
00034
00035
00036
00037 //............................................................................
00038 // NOTE: the QK scheduler is entered and exited with interrupts LOCKED
00039 #ifndef QF_INT_KEY_TYPE
00040 void QK_scheduleExt_(void) {
00041 #else
00042 void QK_scheduleExt_(QF_INT_KEY_TYPE intLockKey_) {
00043 #endif
00044                          // the QK scheduler must be called at task level only
00045     Q_REQUIRE(QK_intNest_ == (uint8_t)0);
00046
00047            // determine the priority of the highest-priority task ready to run
00048     uint8_t p = QK_readySet_.findMax();
00049
00050 #ifdef QK_NO_MUTEX
00051     if (p > QK_currPrio_) {                        // do we have a preemption?
00052 #else                                   // QK priority-ceiling mutexes allowed
00053     if ((p > QK_currPrio_) && (p > QK_ceilingPrio_)) {
00054 #endif
00055         uint8_t pin = QK_currPrio_;               // save the initial priority
00056         QActive *a;
00057 #ifdef QK_TLS                                    // thread-local storage used?
00058         uint8_t pprev = pin;
00059 #endif
00060 #ifdef QK_EXT_SAVE                            // extended context-switch used?
00061         if (pin != (uint8_t)0) {      // no extended context for the idle loop
00062             a = QF::active_[pin];           // the pointer to the preempted AO
00063             QK_EXT_SAVE(a);                       // save the extended context
00064         }
00065 #endif
00066         do {
00067             QEvent const *e;
00068             a = QF::active_[p];                // obtain the pointer to the AO
00069             QK_currPrio_ = p;        // this becomes the current task priority
00070
00071 #ifdef QK_TLS                                    // thread-local storage used?
00072             if (p != pprev) {                      // are we changing threads?
00073                 QK_TLS(a);                  // switch new thread-local storage
00074                 pprev = p;
00075             }
00076 #endif
00077             QS_BEGIN_NOLOCK_(QS_QK_SCHEDULE, QS::aoObj_, a)
00078                 QS_TIME_();                                       // timestamp
00079                 QS_U8_(p);                // the priority of the active object
00080                 QS_U8_(pin);                         // the preempted priority
00081             QS_END_NOLOCK_()
00082
00083             QK_INT_UNLOCK_();                         // unlock the interrupts
00084
00085             e = a->get_();        // get the next event for this active object
00086             a->dispatch(e);                 // dispatch e to the active object
00087             QF::gc(e);              // garbage collect the event, if necessary
00088
00089             QK_INT_LOCK_();
00090                              // determine the highest-priority AO ready to run
00091             p = QK_readySet_.findMax();
00092
00093 #ifdef QK_NO_MUTEX
00094         } while (p > pin);         // is the new priority higher than initial?
00095 #else                                   // QK priority-ceiling mutexes allowed
00096         } while ((p > pin) && (p > QK_ceilingPrio_));
00097 #endif
00098         QK_currPrio_ = pin;                    // restore the initial priority
00099
00100 #if defined(QK_TLS) || defined(QK_EXT_RESTORE)
00101         if (pin != (uint8_t)0) {      // no extended context for the idle loop
00102             a = QF::active_[pin];           // the pointer to the preempted AO
00103     #ifdef QK_TLS                                // thread-local storage used?
00104             QK_TLS(a);                             // restore the original TLS
00105     #endif
00106     #ifdef QK_EXT_RESTORE                     // extended context-switch used?
00107             QK_EXT_RESTORE(a);                 // restore the extended context
00108     #endif
00109         }
00110 #endif
00111     }
00112 }


QP/C++: qk_mutex.cpp Source File

qk_mutex.cpp

Go to the documentation of this file.
00001
00002 // Product: QK/C++
00003 // Last Updated for Version: 4.0.03
00004 // Date of the Last Update:  Dec 26, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qk_pkg.h"
00029
00030 //Q_DEFINE_THIS_MODULE(qk_mutex)
00031
00035
00036 #ifdef QK_NO_MUTEX
00037     #error "qk_mutex.cpp included in the build when QK_NO_MUTEX defined"
00038 #endif
00039
00040 // package-scope objects -----------------------------------------------------
00041 uint8_t volatile QK_ceilingPrio_;               // ceiling priority of a mutex
00042
00043 //............................................................................
00044 QMutex QK::mutexLock(uint8_t prioCeiling) {
00045     QK_INT_LOCK_KEY_
00046     QK_INT_LOCK_();
00047     uint8_t mutex = QK_ceilingPrio_; // original QK priority ceiling to return
00048     if (QK_ceilingPrio_ < prioCeiling) {
00049         QK_ceilingPrio_ = prioCeiling;        // raise the QK priority ceiling
00050     }
00051
00052     QS_BEGIN_NOLOCK_(QS_QK_MUTEX_LOCK, (void *)0, (void *)0)
00053         QS_TIME_();                                               // timestamp
00054         QS_U8_(mutex);                                // the original priority
00055         QS_U8_(QK_ceilingPrio_);               // the current priority ceiling
00056     QS_END_NOLOCK_()
00057
00058     QK_INT_UNLOCK_();
00059     return mutex;
00060 }
00061 //............................................................................
00062 void QK::mutexUnlock(QMutex mutex) {
00063     QK_INT_LOCK_KEY_
00064     QK_INT_LOCK_();
00065
00066     QS_BEGIN_NOLOCK_(QS_QK_MUTEX_UNLOCK, (void *)0, (void *)0)
00067         QS_TIME_();                                               // timestamp
00068         QS_U8_(mutex);                                // the original priority
00069         QS_U8_(QK_ceilingPrio_);               // the current priority ceiling
00070     QS_END_NOLOCK_()
00071
00072     if (QK_ceilingPrio_ > mutex) {
00073         QK_ceilingPrio_ = mutex;         // restore the saved priority ceiling
00074         QK_SCHEDULE_();
00075     }
00076     QK_INT_UNLOCK_();
00077 }


QP/C++: qk_pkg.h Source File

qk_pkg.h

Go to the documentation of this file.
00001
00002 // Product: QK/C++
00003 // Last Updated for Version: 4.0.03
00004 // Date of the Last Update:  Dec 26, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #ifndef qk_pkg_h
00029 #define qk_pkg_h
00030
00034
00035 #include "qf_port.h"                    // QF port include; includes qk_port.h
00036
00037                                     // QK internal interrupt locking/unlocking
00038 #ifndef QF_INT_KEY_TYPE
00039     #define QK_INT_LOCK_KEY_
00040     #define QK_INT_LOCK_()      QF_INT_LOCK(dummy)
00041     #define QK_INT_UNLOCK_()    QF_INT_UNLOCK(dummy)
00042 #else
00043
00051     #define QK_INT_LOCK_KEY_    QF_INT_KEY_TYPE intLockKey_;
00052
00061     #define QK_INT_LOCK_()      QF_INT_LOCK(intLockKey_)
00062
00071     #define QK_INT_UNLOCK_()    QF_INT_UNLOCK(intLockKey_)
00072 #endif
00073
00074                                                    // package-scope objects...
00075 #ifndef QK_NO_MUTEX
00076     extern uint8_t volatile QK_ceilingPrio_;
00077 #endif
00078
00079 #endif                                                             // qk_pkg_h
00080


QP/C++: qk_port.h Source File

qk_port.h

Go to the documentation of this file.
00001
00002 // Product: QK/C++ port to Lint, Generic C++ compiler
00003 // Last Updated for Version: 4.0.03
00004 // Date of the Last Update:  Dec 27, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #ifndef qk_port_h
00029 #define qk_port_h
00030
00037
00039 // QK extended context (FPU) save/restore
00040
00048 #define QK_EXT_SAVE(act_)      FPU_save((FPU_context *)(act_)->m_thread)
00049
00057 #define QK_EXT_RESTORE(act_)   FPU_restore((FPU_context *)(act_)->m_thread)
00058
00059 struct FPU_context {
00060     uint32_t align;
00061     uint8_t  fpu[108];                  // the x87 FPU context takes 108-bytes
00062 };
00063 extern "C" void FPU_save(FPU_context *ctx);             // defined in assembly
00064 extern "C" void FPU_restore(FPU_context *ctx);          // defined in assembly
00065
00067 // Thread-Local-Storage switching
00068
00077 #define QK_TLS(act_)        \
00078     _impure_ptr = (struct _reent *)(act_)->m_thread
00079
00080 // fake struct _reent and _impure_ptr elements of Newlib...
00081 struct _reent {
00082     int foo[32];
00083 };
00084 extern struct _reent *_impure_ptr;
00085
00087 // QK interrupt entry and exit
00088
00096 #define QK_ISR_ENTRY() do { \
00097     ++QK_intNest_; \
00098     QF_QS_ISR_ENTRY(QK_intNest_, QK_currPrio_); \
00099 } while (0)
00100
00101
00109 #define QK_ISR_EXIT() do { \
00110     send End-Of-Interrupt instruction to the Interrupt Controller; \
00111     QF_QS_ISR_EXIT(QK_intNest_, QK_currPrio_); \
00112     --QK_intNest_; \
00113     if (QK_intNest_ == (uint8_t)0) { \
00114         QK_scheduleExt_(); \
00115     } \
00116 } while (0)
00117
00118
00119 #include "qk.h"                    // QK platform-independent public interface
00120
00121 #endif                                                            // qk_port_h


QP/C++: qk_sched.cpp Source File

qk_sched.cpp

Go to the documentation of this file.
00001
00002 // Product: QK/C++
00003 // Last Updated for Version: 4.1.00
00004 // Date of the Last Update:  Oct 09, 2009
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2009 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qk_pkg.h"
00029 #include "qassert.h"
00030
00031 Q_DEFINE_THIS_MODULE(qk_sched)
00032
00033
00034
00035
00036
00037 //............................................................................
00038 // NOTE: the QK scheduler is entered and exited with interrupts LOCKED
00039 #ifndef QF_INT_KEY_TYPE
00040 void QK_schedule_(void) {
00041 #else
00042 void QK_schedule_(QF_INT_KEY_TYPE intLockKey_) {
00043 #endif
00044                          // the QK scheduler must be called at task level only
00045     Q_REQUIRE(QK_intNest_ == (uint8_t)0);
00046
00047            // determine the priority of the highest-priority task ready to run
00048     uint8_t p = QK_readySet_.findMax();
00049
00050 #ifdef QK_NO_MUTEX
00051     if (p > QK_currPrio_) {                        // do we have a preemption?
00052 #else                                   // QK priority-ceiling mutexes allowed
00053     if ((p > QK_currPrio_) && (p > QK_ceilingPrio_)) {
00054 #endif
00055         uint8_t pin = QK_currPrio_;               // save the initial priority
00056         QActive *a;
00057 #ifdef QK_TLS                                    // thread-local storage used?
00058         uint8_t pprev = pin;
00059 #endif
00060         do {
00061             QEvent const *e;
00062             a = QF::active_[p];                // obtain the pointer to the AO
00063             QK_currPrio_ = p;        // this becomes the current task priority
00064
00065 #ifdef QK_TLS                                    // thread-local storage used?
00066             if (p != pprev) {                      // are we changing threads?
00067                 QK_TLS(a);                  // switch new thread-local storage
00068                 pprev = p;
00069             }
00070 #endif
00071             QS_BEGIN_NOLOCK_(QS_QK_SCHEDULE, QS::aoObj_, a)
00072                 QS_TIME_();                                       // timestamp
00073                 QS_U8_(p);                // the priority of the active object
00074                 QS_U8_(pin);                         // the preempted priority
00075             QS_END_NOLOCK_()
00076
00077             QK_INT_UNLOCK_();                         // unlock the interrupts
00078
00079             e = a->get_();        // get the next event for this active object
00080             a->dispatch(e);                 // dispatch e to the active object
00081             QF::gc(e);              // garbage collect the event, if necessary
00082
00083             QK_INT_LOCK_();
00084                              // determine the highest-priority AO ready to run
00085             if (QK_readySet_.notEmpty()) {
00086                 p = QK_readySet_.findMax();
00087             }
00088             else {
00089                 p = (uint8_t)0;
00090             }
00091 #ifdef QK_NO_MUTEX
00092         } while (p > pin);         // is the new priority higher than initial?
00093 #else                                   // QK priority-ceiling mutexes allowed
00094         } while ((p > pin) && (p > QK_ceilingPrio_));
00095 #endif
00096         QK_currPrio_ = pin;                    // restore the initial priority
00097
00098 #ifdef QK_TLS                                    // thread-local storage used?
00099         if (pin != (uint8_t)0) {      // no extended context for the idle loop
00100             a = QF::active_[pin];           // the pointer to the preempted AO
00101             QK_TLS(a);                             // restore the original TLS
00102         }
00103 #endif
00104     }
00105 }


QP/C++: qmp_get.cpp Source File

qmp_get.cpp

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029 #include "qassert.h"
00030
00031 Q_DEFINE_THIS_MODULE(qmp_get)
00032
00033
00034
00035
00036
00037 //............................................................................
00038 void *QMPool::get(void) {
00039     QF_INT_LOCK_KEY_
00040     QF_INT_LOCK_();
00041
00042     QFreeBlock *fb = (QFreeBlock *)m_free;         // get a free block or NULL
00043     if (fb != (QFreeBlock *)0) {                      // free block available?
00044         m_free = fb->m_next;          // adjust list head to the next free block
00045         --m_nFree;                                      // one free block less
00046         if (m_nMin > m_nFree) {
00047             m_nMin = m_nFree;                   // remember the minimum so far
00048         }
00049     }
00050
00051     QS_BEGIN_NOLOCK_(QS_QF_MPOOL_GET, QS::mpObj_, m_start)
00052         QS_TIME_();                                               // timestamp
00053         QS_OBJ_(m_start);                   // the memory managed by this pool
00054         QS_MPC_(m_nFree);             // the number of free blocks in the pool
00055         QS_MPC_(m_nMin);     // the mninimum number of free blocks in the pool
00056     QS_END_NOLOCK_()
00057
00058     QF_INT_UNLOCK_();
00059     return fb;               // return the block or NULL pointer to the caller
00060 }
00061 //............................................................................
00062 uint32_t QF::getPoolMargin(uint8_t poolId) {
00063     Q_REQUIRE(((uint8_t)1 <= poolId) && (poolId <= QF_maxPool_));
00064
00065     QF_INT_LOCK_KEY_
00066     QF_INT_LOCK_();
00067     uint32_t margin = (uint32_t)QF_pool_[poolId - (uint8_t)1].m_nMin;
00068     QF_INT_UNLOCK_();
00069
00070     return margin;
00071 }


QP/C++: qmp_init.cpp Source File

qmp_init.cpp

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029 #include "qassert.h"
00030
00031 Q_DEFINE_THIS_MODULE(qmp_init)
00032
00033
00034
00035
00036
00037 //............................................................................
00038 void QMPool::init(void *poolSto, uint32_t poolSize, QMPoolSize blockSize) {
00039     // The memory block must be valid
00040     // and the poolSize must fit at least one free block
00041     // and the blockSize must not be too close to the top of the dynamic range
00042     Q_REQUIRE((poolSto != (void *)0)
00043               && (poolSize >= (uint32_t)sizeof(QFreeBlock))
00044               && ((QMPoolSize)(blockSize + (QMPoolSize)sizeof(QFreeBlock))
00045                     > blockSize));
00046
00047     //lint -e923                       ignore MISRA Rule 45 in this expression
00048     uint32_t corr = ((uint32_t)poolSto
00049                       & ((uint32_t)sizeof(QFreeBlock) - (uint32_t)1));
00050     if (corr != (uint32_t)0) {                            // alignment needed?
00051         corr = (uint32_t)sizeof(QFreeBlock) - corr; // amount to align poolSto
00052         poolSize -= corr;                    // reduce the available pool size
00053     }
00054     //lint -e826   align the head of free list at the free block-size boundary
00055     m_free = (void *)((uint8_t *)poolSto + corr);
00056
00057                 // round up the blockSize to fit an integer number of pointers
00058     m_blockSize = (QMPoolSize)sizeof(QFreeBlock);       // start with just one
00059     uint32_t nblocks = (uint32_t)1;// # free blocks that fit in a memory block
00060     while (m_blockSize < blockSize) {
00061         m_blockSize += (QMPoolSize)sizeof(QFreeBlock);
00062         ++nblocks;
00063     }
00064     blockSize = m_blockSize;          // use the rounded-up value from here on
00065
00066                // the whole pool buffer must fit at least one rounded-up block
00067     Q_ASSERT(poolSize >= (uint32_t)blockSize);
00068
00069                                 // chain all blocks together in a free-list...
00070     poolSize -= (uint32_t)blockSize;             // don't chain the last block
00071     m_nTot     = (QMPoolCtr)1;             // one (the last) block in the pool
00072     QFreeBlock *fb = (QFreeBlock *)m_free;//start at the head of the free list
00073     while (poolSize >= (uint32_t)blockSize) {
00074         fb->m_next = &fb[nblocks];                      // setup the next link
00075         fb = fb->m_next;                              // advance to next block
00076         poolSize -= (uint32_t)blockSize;     // reduce the available pool size
00077         ++m_nTot;                     // increment the number of blocks so far
00078     }
00079
00080     fb->m_next = (QFreeBlock *)0;              // the last link points to NULL
00081     m_nFree    = m_nTot;                                // all blocks are free
00082     m_nMin     = m_nTot;                  // the minimum number of free blocks
00083     m_start    = poolSto;               // the original start this pool buffer
00084     m_end      = fb;                            // the last block in this pool
00085
00086     QS_INT_LOCK_KEY_
00087     QS_BEGIN_(QS_QF_MPOOL_INIT, QS::mpObj_, m_start)
00088         QS_OBJ_(m_start);                   // the memory managed by this pool
00089         QS_MPC_(m_nTot);                         // the total number of blocks
00090     QS_END_()
00091 }


QP/C++: qmp_put.cpp Source File

qmp_put.cpp

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029 #include "qassert.h"
00030
00031 Q_DEFINE_THIS_MODULE(qmp_put)
00032
00033
00034
00035
00036
00037 //............................................................................
00038 void QMPool::put(void *b) {
00039     //lint -e946 -e1904             ignore MISRA Rule 103 in this precondition
00040     Q_REQUIRE((m_start <= b) && (b <= m_end)           /*  must be in range */
00041               && (m_nFree <= m_nTot));        // # free blocks must be < total
00042
00043     QF_INT_LOCK_KEY_
00044     QF_INT_LOCK_();
00045
00046     ((QFreeBlock *)b)->m_next = (QFreeBlock *)m_free;//link into the free list
00047     m_free = b;                            // set as new head of the free list
00048     ++m_nFree;                             // one more free block in this pool
00049
00050     QS_BEGIN_NOLOCK_(QS_QF_MPOOL_PUT, QS::mpObj_, m_start)
00051         QS_TIME_();                                               // timestamp
00052         QS_OBJ_(m_start);                   // the memory managed by this pool
00053         QS_MPC_(m_nFree);             // the number of free blocks in the pool
00054     QS_END_NOLOCK_()
00055
00056     QF_INT_UNLOCK_();
00057 }
00058     //lint -e946 -e1904             ignore MISRA Rule 103 in this precondition


QP/C++: qmpool.h Source File

qmpool.h

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 06, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #ifndef qmpool_h
00029 #define qmpool_h
00030
00037
00038
00040 #ifndef QF_MPOOL_SIZ_SIZE
00041
00042
00043     #define QF_MPOOL_SIZ_SIZE 2
00044 #endif
00045 #if (QF_MPOOL_SIZ_SIZE == 1)
00046
00052     typedef uint8_t QMPoolSize;
00053 #elif (QF_MPOOL_SIZ_SIZE == 2)
00054
00055     typedef uint16_t QMPoolSize;
00056 #elif (QF_MPOOL_SIZ_SIZE == 4)
00057     typedef uint32_t QMPoolSize;
00058 #else
00059     #error "QF_MPOOL_SIZ_SIZE defined incorrectly, expected 1, 2, or 4"
00060 #endif
00061
00063 #ifndef QF_MPOOL_CTR_SIZE
00064
00067     #define QF_MPOOL_CTR_SIZE 2
00068 #endif
00069 #if (QF_MPOOL_CTR_SIZE == 1)
00070
00076     typedef uint8_t QMPoolCtr;
00077 #elif (QF_MPOOL_CTR_SIZE == 2)
00078     typedef uint16_t QMPoolCtr;
00079 #elif (QF_MPOOL_CTR_SIZE == 4)
00080     typedef uint32_t QMPoolCtr;
00081 #else
00082     #error "QF_MPOOL_CTR_SIZE defined incorrectly, expected 1, 2, or 4"
00083 #endif
00084
00098 class QMPool {
00099 private:
00100
00102     void *m_start;
00103
00105     void *m_end;
00106
00108     void *m_free;
00109
00111     QMPoolSize m_blockSize;
00112
00114     QMPoolCtr m_nTot;
00115
00117     QMPoolCtr m_nFree;
00118
00124     QMPoolCtr m_nMin;
00125
00126 public:
00127
00145     void init(void *poolSto, uint32_t poolSize, QMPoolSize blockSize);
00146
00165     void *get(void);
00166
00181     void put(void *b);
00182
00184     QMPoolSize getBlockSize(void) const {
00185         return m_blockSize;
00186     }
00187
00188 private:
00189     friend class QF;
00190 };
00191
00192 #endif                                                             // qmpool_h


QP/C++: qp_port.h Source File

qp_port.h

00001
00002 // Product: QP/C++ port
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #ifndef qp_port_h
00029 #define qp_port_h
00030
00031 #include "qf_port.h"             // includes qep_port.h and qk_port.h, if used
00032 #include "qassert.h"                                // customizable assertions
00033
00034 #endif                                                            // qp_port_h


QP/C++: qpset.h Source File

qpset.h

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.1.00
00004 // Date of the Last Update:  Oct 09, 2009
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2009 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #ifndef qpset_h
00029 #define qpset_h
00030
00037
00038                       // external declarations of QF lookup tables used inline
00039 extern uint8_t const Q_ROM Q_ROM_VAR QF_log2Lkup[256];
00040 extern uint8_t const Q_ROM Q_ROM_VAR QF_pwr2Lkup[65];
00041 extern uint8_t const Q_ROM Q_ROM_VAR QF_invPwr2Lkup[65];
00042 extern uint8_t const Q_ROM Q_ROM_VAR QF_div8Lkup[65];
00043
00051 class QPSet8 {
00052 protected:
00055     uint8_t m_bits;
00056
00057 public:
00058
00061     uint8_t isEmpty(void) volatile {
00062         return (uint8_t)(m_bits == (uint8_t)0);
00063     }
00064
00067     uint8_t notEmpty(void) volatile {
00068         return (uint8_t)(m_bits != (uint8_t)0);
00069     }
00070
00073     uint8_t hasElement(uint8_t n) volatile {
00074         return (uint8_t)((m_bits & Q_ROM_BYTE(QF_pwr2Lkup[n])) != 0);
00075     }
00076
00078     void insert(uint8_t n) volatile {
00079         m_bits |= Q_ROM_BYTE(QF_pwr2Lkup[n]);
00080     }
00081
00083     void remove(uint8_t n) volatile {
00084         m_bits &= Q_ROM_BYTE(QF_invPwr2Lkup[n]);
00085     }
00086
00089     uint8_t findMax(void) volatile {
00090         return Q_ROM_BYTE(QF_log2Lkup[m_bits]);
00091     }
00092
00093     friend class QPSet64;
00094 };
00095
00119 class QPSet64 : public QPSet8 {
00120
00130     QPSet8 m_subset[8];
00131
00132 public:
00133
00136     uint8_t hasElement(uint8_t n) volatile {
00137          return m_subset[Q_ROM_BYTE(QF_div8Lkup[n])].QPSet8::hasElement(n);
00138     }
00139
00141     void insert(uint8_t n) volatile {
00142         QPSet8::insert(Q_ROM_BYTE(QF_div8Lkup[n]) + 1);
00143         m_subset[Q_ROM_BYTE(QF_div8Lkup[n])].QPSet8::insert(n);
00144     }
00145
00147     void remove(uint8_t n) volatile {
00148         if ((m_subset[Q_ROM_BYTE(QF_div8Lkup[n])].m_bits
00149                  &= Q_ROM_BYTE(QF_invPwr2Lkup[n])) == (uint8_t)0)
00150         {
00151             QPSet8::remove(Q_ROM_BYTE(QF_div8Lkup[n]) + 1);
00152         }
00153     }
00154
00157     uint8_t findMax(void) volatile {
00158         if (m_bits != (uint8_t)0) {
00159             uint8_t n = (uint8_t)(Q_ROM_BYTE(QF_log2Lkup[m_bits]) - 1);
00160             return (uint8_t)(Q_ROM_BYTE(QF_log2Lkup[m_subset[n].m_bits])
00161                              + (n << 3));
00162         }
00163         else {
00164             return (uint8_t)0;
00165         }
00166     }
00167 };
00168
00169 #endif                                                              // qpset_h
00170


QP/C++: qs.cpp Source File

qs.cpp

Go to the documentation of this file.
00001
00002 // Product: QS/C++
00003 // Last Updated for Version: 4.1.03
00004 // Date of the Last Update:  Feb 15, 2010
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2010 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qs_pkg.h"
00029
00034
00035 //............................................................................
00036 uint8_t QS::glbFilter_[32];                                // global QS filter
00037
00038 //............................................................................
00039 uint8_t *QS_ring_;                  // pointer to the start of the ring buffer
00040 QSCtr QS_end_;                         // offset of the end of the ring buffer
00041 QSCtr QS_head_;                  // offset to where next byte will be inserted
00042 QSCtr QS_tail_;                 // offset of where next byte will be extracted
00043 QSCtr QS_used_;                // number of bytes currently in the ring buffer
00044 uint8_t QS_seq_;                                 // the record sequence number
00045 uint8_t QS_chksum_;                      // the checksum of the current record
00046 uint8_t QS_full_;                       // the ring buffer is temporarily full
00047
00048 //............................................................................
00049 //lint -e970 -e971               ignore MISRA rules 13 and 14 in this function
00050 char const Q_ROM * Q_ROM_VAR QS::getVersion(void) {
00051     static char const Q_ROM Q_ROM_VAR version[] = {
00052         ((QP_VERSION >> 12) & 0xF) + '0',
00053         '.',
00054         ((QP_VERSION >>  8) & 0xF) + '0',
00055         '.',
00056         ((QP_VERSION >>  4) & 0xF) + '0',
00057         (QP_VERSION         & 0xF) + '0',
00058         '\0'
00059     };
00060     return version;
00061 }
00062 //............................................................................
00063 void QS::initBuf(uint8_t sto[], uint32_t stoSize) {
00064     QS_ring_ = &sto[0];
00065     QS_end_  = (QSCtr)stoSize;
00066 }
00067 //............................................................................
00068 void QS::filterOn(uint8_t rec) {
00069     if (rec == QS_ALL_RECORDS) {
00070         uint8_t i;
00071         for (i = (uint8_t)0; i < (uint8_t)sizeof(glbFilter_); ++i) {
00072             glbFilter_[i] = (uint8_t)0xFF;
00073         }
00074     }
00075     else {
00076         glbFilter_[rec >> 3] |= (uint8_t)(1U << (rec & 0x07));
00077     }
00078 }
00079 //............................................................................
00080 void QS::filterOff(uint8_t rec) {
00081     if (rec == QS_ALL_RECORDS) {
00082         uint8_t i;
00083         for (i = (uint8_t)0; i < (uint8_t)sizeof(glbFilter_); ++i) {
00084             glbFilter_[i] = (uint8_t)0;
00085         }
00086     }
00087     else {
00088         glbFilter_[rec >> 3] &= (uint8_t)(~(1U << (rec & 0x07)));
00089     }
00090 }
00091 //............................................................................
00092 void QS::begin(uint8_t rec) {
00093     QS_chksum_ = (uint8_t)0;                             // clear the checksum
00094     ++QS_seq_;                         // always increment the sequence number
00095     QS_INSERT_ESC_BYTE(QS_seq_)                   // store the sequence number
00096     QS_INSERT_ESC_BYTE(rec)                             // store the record ID
00097 }
00098 //............................................................................
00099 void QS::end(void) {
00100     QS_INSERT_CHKSUM_BYTE()
00101     QS_INSERT_BYTE(QS_FRAME)
00102     if (QS_used_ > QS_end_) {                    // overrun over the old data?
00103         QS_tail_ = QS_head_;                 // shift the tail to the old data
00104         QS_used_ = QS_end_;                        // the whole buffer is used
00105     }
00106 }
00107 //............................................................................
00108 void QS::u8(uint8_t format, uint8_t d) {
00109     QS_INSERT_ESC_BYTE(format)
00110     QS_INSERT_ESC_BYTE(d)
00111 }
00112 //............................................................................
00113 void QS::u16(uint8_t format, uint16_t d) {
00114     QS_INSERT_ESC_BYTE(format)
00115     QS_INSERT_ESC_BYTE((uint8_t)d)
00116     d >>= 8;
00117     QS_INSERT_ESC_BYTE((uint8_t)d)
00118 }
00119 //............................................................................
00120 void QS::u32(uint8_t format, uint32_t d) {
00121     QS_INSERT_ESC_BYTE(format)
00122     QS_INSERT_ESC_BYTE((uint8_t)d)
00123     d >>= 8;
00124     QS_INSERT_ESC_BYTE((uint8_t)d)
00125     d >>= 8;
00126     QS_INSERT_ESC_BYTE((uint8_t)d)
00127     d >>= 8;
00128     QS_INSERT_ESC_BYTE((uint8_t)d)
00129 }


QP/C++: qs.h Source File

qs.h

Go to the documentation of this file.
00001
00002 // Product: QS/C++ platform-independent public interface.
00003 // Last Updated for Version: 4.1.05
00004 // Date of the Last Update:  Oct 27, 2010
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2010 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #ifndef qs_h
00029 #define qs_h
00030
00036
00037 #ifndef Q_SPY
00038     #error "Q_SPY must be defined to include qs.h"
00039 #endif
00040
00042
00049 enum QSpyRecords {
00050     // QEP records
00051     QS_QEP_STATE_EMPTY,
00052     QS_QEP_STATE_ENTRY,
00053     QS_QEP_STATE_EXIT,
00054     QS_QEP_STATE_INIT,
00055     QS_QEP_INIT_TRAN,
00056     QS_QEP_INTERN_TRAN,
00057     QS_QEP_TRAN,
00058     QS_QEP_IGNORED,
00059     QS_QEP_DISPATCH,
00060     QS_QEP_RESERVED0,
00061
00062     // QF records
00063     QS_QF_ACTIVE_ADD,
00064     QS_QF_ACTIVE_REMOVE,
00065     QS_QF_ACTIVE_SUBSCRIBE,
00066     QS_QF_ACTIVE_UNSUBSCRIBE,
00067     QS_QF_ACTIVE_POST_FIFO,
00068     QS_QF_ACTIVE_POST_LIFO,
00069     QS_QF_ACTIVE_GET,
00070     QS_QF_ACTIVE_GET_LAST,
00071     QS_QF_EQUEUE_INIT,
00072     QS_QF_EQUEUE_POST_FIFO,
00073     QS_QF_EQUEUE_POST_LIFO,
00074     QS_QF_EQUEUE_GET,
00075     QS_QF_EQUEUE_GET_LAST,
00076     QS_QF_MPOOL_INIT,
00077     QS_QF_MPOOL_GET,
00078     QS_QF_MPOOL_PUT,
00079     QS_QF_PUBLISH,
00080     QS_QF_RESERVED8,
00081     QS_QF_NEW,
00082     QS_QF_GC_ATTEMPT,
00083     QS_QF_GC,
00084     QS_QF_TICK,
00085     QS_QF_TIMEEVT_ARM,
00086     QS_QF_TIMEEVT_AUTO_DISARM,
00087     QS_QF_TIMEEVT_DISARM_ATTEMPT,
00088     QS_QF_TIMEEVT_DISARM,
00089     QS_QF_TIMEEVT_REARM,
00090     QS_QF_TIMEEVT_POST,
00091     QS_QF_RESERVED7,
00092     QS_QF_INT_LOCK,
00093     QS_QF_INT_UNLOCK,
00094     QS_QF_ISR_ENTRY,
00095     QS_QF_ISR_EXIT,
00096     QS_QF_RESERVED6,
00097     QS_QF_RESERVED5,
00098     QS_QF_RESERVED4,
00099     QS_QF_RESERVED3,
00100     QS_QF_RESERVED2,
00101     QS_QF_RESERVED1,
00102     QS_QF_RESERVED0,
00103
00104     // QK records
00105     QS_QK_MUTEX_LOCK,
00106     QS_QK_MUTEX_UNLOCK,
00107     QS_QK_SCHEDULE,
00108     QS_QK_RESERVED6,
00109     QS_QK_RESERVED5,
00110     QS_QK_RESERVED4,
00111     QS_QK_RESERVED3,
00112     QS_QK_RESERVED2,
00113     QS_QK_RESERVED1,
00114     QS_QK_RESERVED0,
00115
00116     // Miscellaneous QS records
00117     QS_SIG_DICTIONARY,
00118     QS_OBJ_DICTIONARY,
00119     QS_FUN_DICTIONARY,
00120     QS_ASSERT,
00121     QS_RESERVED5,
00122     QS_RESERVED4,
00123     QS_RESERVED3,
00124     QS_RESERVED2,
00125     QS_RESERVED1,
00126     QS_RESERVED0,
00127
00128     // User records
00129     QS_USER
00130 };
00131
00134 #define QS_ALL_RECORDS          ((uint8_t)0xFF)
00135
00138 #define QS_EOD                  ((uint16_t)0xFFFF)
00139
00140
00141 #ifndef QS_TIME_SIZE
00142
00149     #define QS_TIME_SIZE 4
00150 #endif
00151 #if (QS_TIME_SIZE == 1)
00152     typedef uint8_t QSTimeCtr;
00153     #define QS_TIME_()   QS::u8_(QS::onGetTime())
00154 #elif (QS_TIME_SIZE == 2)
00155     typedef uint16_t QSTimeCtr;
00156     #define QS_TIME_()   QS::u16_(QS::onGetTime())
00157 #elif (QS_TIME_SIZE == 4)
00158
00162     typedef uint32_t QSTimeCtr;
00163
00165     #define QS_TIME_()   QS::u32_(QS::onGetTime())
00166 #else
00167     #error "QS_TIME_SIZE defined incorrectly, expected 1, 2, or 4"
00168 #endif
00169
00170 #ifndef Q_ROM                      // provide the default if Q_ROM NOT defined
00171     #define Q_ROM
00172 #endif
00173 #ifndef Q_ROM_VAR              // provide the default if Q_ROM_VAR NOT defined
00174     #define Q_ROM_VAR
00175 #endif
00176 #ifndef Q_ROM_BYTE            // provide the default if Q_ROM_BYTE NOT defined
00177     #define Q_ROM_BYTE(rom_var_)   (rom_var_)
00178 #endif
00179
00180
00185 class QS {
00186 public:
00187
00193     static char const Q_ROM * Q_ROM_VAR getVersion(void);
00194
00213     static void initBuf(uint8_t sto[], uint32_t stoSize);
00214
00228     static void filterOn(uint8_t rec);
00229
00242     static void filterOff(uint8_t rec);
00243
00250     static void begin(uint8_t rec);
00251
00258     static void end(void);
00259
00260     // unformatted data elements output ......................................
00261
00265     static void u8_(uint8_t d);
00266
00270     static void u16_(uint16_t d);
00271
00275     static void u32_(uint32_t d);
00276
00281     static void str_(char const *s);
00282
00287     static void str_ROM_(char const Q_ROM * Q_ROM_VAR s);
00288
00289     // formatted data elements output ........................................
00290
00294     static void u8(uint8_t format, uint8_t d);
00295
00299     static void u16(uint8_t format, uint16_t d);
00300
00304     static void u32(uint8_t format, uint32_t d);
00305
00310     static void f32(uint8_t format, float d);
00311
00316     static void f64(uint8_t format, double d);
00317
00322     static void str(char const *s);
00323
00328     static void str_ROM(char const Q_ROM * Q_ROM_VAR s);
00329
00333     static void mem(uint8_t const *blk, uint8_t size);
00334
00335     // QS buffer access ......................................................
00336
00345     static uint16_t getByte(void);
00346
00367     static uint8_t const *getBlock(uint16_t *pNbytes);
00368
00369 // platform-dependent callback functions, need to be implemented by clients
00370 public:
00371
00372     // platform-specific callback functions, need to be implemented by clients
00388     static uint8_t onStartup(void const *arg);
00389
00396     static void onCleanup(void);
00397
00404     static void onFlush(void);
00405
00419     static QSTimeCtr onGetTime(void);
00420
00421 // Global and Local QS filters ...............................................
00422 public:
00423     static uint8_t glbFilter_[32];
00424     static void const *smObj_;
00425     static void const *aoObj_;
00426     static void const *mpObj_;
00427     static void const *eqObj_;
00428     static void const *teObj_;
00429     static void const *apObj_;
00430
00431 // Miscallaneous .............................................................
00432 public:
00434     static QSTimeCtr volatile tickCtr_;
00435 };
00436
00437
00439 // Macros for adding QS instrumentation to the client code
00440
00446 #define QS_INIT(arg_)           QS::onStartup(arg_)
00447
00453 #define QS_EXIT()               QS::onCleanup()
00454
00462 #define QS_FILTER_ON(rec_)      QS::filterOn(rec_)
00463
00470 #define QS_FILTER_OFF(rec_)     QS::filterOff(rec_)
00471
00495 #define QS_FILTER_SM_OBJ(obj_)  (QS::smObj_ = (obj_))
00496
00514 #define QS_FILTER_AO_OBJ(obj_)  (QS::aoObj_ = (obj_))
00515
00532 #define QS_FILTER_MP_OBJ(obj_)  (QS::mpObj_ = (obj_))
00533
00550 #define QS_FILTER_EQ_OBJ(obj_)  (QS::eqObj_ = (obj_))
00551
00569 #define QS_FILTER_TE_OBJ(obj_)  (QS::teObj_ = (obj_))
00570
00584 #define QS_FILTER_AP_OBJ(obj_)  (QS_apObj_ = (obj_))
00585
00586
00588 // Macros to generate user QS records
00589
00591 #define QS_BEGIN_NOLOCK(rec_, obj_) \
00592     if (((QS::glbFilter_[(uint8_t)(rec_) >> 3U] \
00593           & (1U << ((uint8_t)(rec_) & 7U))) != 0) \
00594         && ((QS::apObj_ == (void *)0) || (QS::apObj_ == (obj_)))) \
00595     { \
00596         QS::begin((uint8_t)(rec_)); \
00597         QS_TIME_();
00598
00600 #define QS_END_NOLOCK() \
00601     QS_END_NOLOCK_()
00602
00603                                     // QS-specific interrupt locking/unlocking
00604 #ifndef QF_INT_KEY_TYPE
00605
00606
00607
00608
00609
00610
00611
00612     #define QS_INT_LOCK_KEY_
00613
00622     #define QS_INT_LOCK_()      QF_INT_LOCK(ignore_)
00623
00632     #define QS_INT_UNLOCK_()    QF_INT_UNLOCK(ignore_)
00633 #else
00634     #define QS_INT_LOCK_KEY_    QF_INT_KEY_TYPE intLockKey_;
00635     #define QS_INT_LOCK_()      QF_INT_LOCK(intLockKey_)
00636     #define QS_INT_UNLOCK_()    QF_INT_UNLOCK(intLockKey_)
00637 #endif
00638
00646 #define QS_BEGIN(rec_, obj_) \
00647     if (((QS::glbFilter_[(uint8_t)(rec_) >> 3U] \
00648           & (1U << ((uint8_t)(rec_) & 7U))) != 0U) \
00649         && ((QS::apObj_ == (void *)0) || (QS::apObj_ == (obj_)))) \
00650     { \
00651         QS_INT_LOCK_KEY_ \
00652         QS_INT_LOCK_(); \
00653         QS::begin((uint8_t)(rec_)); \
00654         QS_TIME_();
00655
00659 #define QS_END() \
00660     QS_END_()
00661
00662
00664 // Macros for use inside other macros or internally in the QP code
00665
00669 #define QS_BEGIN_(rec_, objFilter_, obj_) \
00670     if (((QS::glbFilter_[(uint8_t)(rec_) >> 3U] \
00671           & (1U << ((uint8_t)(rec_) & 7U))) != 0U) \
00672         && (((objFilter_) == (void *)0) || ((objFilter_) == (obj_)))) \
00673     { \
00674         QS_INT_LOCK_(); \
00675         QS::begin((uint8_t)(rec_));
00676
00680 #define QS_END_() \
00681         QS::end(); \
00682         QS_INT_UNLOCK_(); \
00683     }
00684
00689 #define QS_BEGIN_NOLOCK_(rec_, objFilter_, obj_) \
00690     if (((QS::glbFilter_[(uint8_t)(rec_) >> 3U] \
00691           & (1U << ((uint8_t)(rec_) & 7U))) != 0U) \
00692         && (((objFilter_) == (void *)0) || ((objFilter_) == (obj_)))) \
00693     { \
00694         QS::begin((uint8_t)(rec_));
00695
00700 #define QS_END_NOLOCK_() \
00701         QS::end(); \
00702     }
00703
00705 #define QS_U8_(data_)           QS::u8_(data_)
00706
00708 #define QS_U16_(data_)          QS::u16_(data_)
00709
00711 #define QS_U32_(data_)          QS::u32_(data_)
00712
00713
00714 #if (QS_OBJ_PTR_SIZE == 1)
00715     #define QS_OBJ_(obj_)       QS::u8_((uint8_t)(obj_))
00716 #elif (QS_OBJ_PTR_SIZE == 2)
00717     #define QS_OBJ_(obj_)       QS::u16_((uint16_t)(obj_))
00718 #elif (QS_OBJ_PTR_SIZE == 4)
00719     #define QS_OBJ_(obj_)       QS::u32_((uint32_t)(obj_))
00720 #else
00721
00726     #define QS_OBJ_(obj_)       QS::u32_((uint32_t)(obj_))
00727 #endif
00728
00729
00730 #if (QS_FUN_PTR_SIZE == 1)
00731     #define QS_FUN_(fun_)       QS::u8_((uint8_t)(fun_))
00732 #elif (QS_FUN_PTR_SIZE == 2)
00733     #define QS_FUN_(fun_)       QS::u16_((uint16_t)(fun_))
00734 #elif (QS_FUN_PTR_SIZE == 4)
00735     #define QS_FUN_(fun_)       QS::u32_((uint32_t)(fun_))
00736 #else
00737
00742     #define QS_FUN_(fun_)       QS::u32_((uint32_t)(fun_))
00743 #endif
00744
00747 #define QS_STR_(msg_)           QS::str_(msg_)
00748
00751 #define QS_STR_ROM_(msg_)       QS::str_ROM_(msg_)
00752
00754 // Macros for use in the client code
00755
00760 enum QSType {
00761     QS_I8_T,
00762     QS_U8_T,
00763     QS_I16_T,
00764     QS_U16_T,
00765     QS_I32_T,
00766     QS_U32_T,
00767     QS_F32_T,
00768     QS_F64_T,
00769     QS_STR_T,
00770     QS_MEM_T,
00771     QS_SIG_T,
00772     QS_OBJ_T,
00773     QS_FUN_T
00774 };
00775
00777 #define QS_I8(width_, data_) \
00778     QS::u8((uint8_t)(((width_) << 4)) | QS_I8_T, (data_))
00779
00781 #define QS_U8(width_, data_) \
00782     QS::u8((uint8_t)(((width_) << 4)) | QS_U8_T, (data_))
00783
00785 #define QS_I16(width_, data_) \
00786     QS::u16((uint8_t)(((width_) << 4)) | QS_I16_T, (data_))
00787
00789 #define QS_U16(width_, data_) \
00790     QS::u16((uint8_t)(((width_) << 4)) | QS_U16_T, (data_))
00791
00793 #define QS_I32(width_, data_) \
00794     QS::u32((uint8_t)(((width_) << 4)) | QS_I32_T, (data_))
00795
00797 #define QS_U32(width_, data_) \
00798     QS::u32((uint8_t)(((width_) << 4)) | QS_U32_T, (data_))
00799
00801 #define QS_F32(width_, data_) \
00802     QS::f32((uint8_t)(((width_) << 4)) | QS_F32_T, (data_))
00803
00805 #define QS_F64(width_, data_) \
00806     QS::f64((uint8_t)(((width_) << 4)) | QS_F64_T, (data_))
00807
00809 #define QS_STR(str_)            QS::str(str_)
00810
00813 #define QS_STR_ROM(str_)        QS::str_ROM(str_)
00814
00817 #define QS_MEM(mem_, size_)     QS::mem((mem_), (size_))
00818
00819
00820 #if (QS_OBJ_PTR_SIZE == 1)
00821     #define QS_OBJ(obj_)        QS::u8(QS_OBJ_T, (uint8_t)(obj_))
00822 #elif (QS_OBJ_PTR_SIZE == 2)
00823     #define QS_OBJ(obj_)        QS::u16(QS_OBJ_T, (uint16_t)(obj_))
00824 #elif (QS_OBJ_PTR_SIZE == 4)
00825     #define QS_OBJ(obj_)        QS::u32(QS_OBJ_T, (uint32_t)(obj_))
00826 #else
00827
00828     #define QS_OBJ(obj_)        QS::u32(QS_OBJ_T, (uint32_t)(obj_))
00829 #endif
00830
00831
00832 #if (QS_FUN_PTR_SIZE == 1)
00833     #define QS_FUN(fun_)        QS::u8(QS_FUN_T, (uint8_t)(fun_))
00834 #elif (QS_FUN_PTR_SIZE == 2)
00835     #define QS_FUN(fun_)        QS::u16(QS_FUN_T, (uint16_t)(fun_))
00836 #elif (QS_FUN_PTR_SIZE == 4)
00837     #define QS_FUN(fun_)        QS::u32(QS_FUN_T, (uint32_t)(fun_))
00838 #else
00839
00840     #define QS_FUN(fun_)        QS::u32(QS_FUN_T, (uint32_t)(fun_))
00841 #endif
00842
00843
00883 #define QS_SIG_DICTIONARY(sig_, obj_) \
00884     if (((QS::glbFilter_[(uint8_t)QS_SIG_DICTIONARY >> 3U] \
00885           & (1U << ((uint8_t)QS_SIG_DICTIONARY & 7U))) != 0U)) \
00886     { \
00887         static char const Q_ROM Q_ROM_VAR sig_name__[] = #sig_; \
00888         QS_INT_LOCK_KEY_ \
00889         QS_INT_LOCK_(); \
00890         QS::begin((uint8_t)QS_SIG_DICTIONARY); \
00891         QS_SIG_(sig_); \
00892         QS_OBJ_(obj_); \
00893         QS_STR_ROM_(sig_name__); \
00894         QS::end(); \
00895         QS_INT_UNLOCK_(); \
00896         QS::onFlush(); \
00897     } else ((void)0)
00898
00911 #define QS_OBJ_DICTIONARY(obj_) \
00912     if (((QS::glbFilter_[(uint8_t)QS_OBJ_DICTIONARY >> 3U] \
00913           & (1U << ((uint8_t)QS_OBJ_DICTIONARY & 7U))) != 0U)) \
00914     { \
00915         static char const Q_ROM Q_ROM_VAR obj_name__[] = #obj_; \
00916         QS_INT_LOCK_KEY_ \
00917         QS_INT_LOCK_(); \
00918         QS::begin((uint8_t)QS_OBJ_DICTIONARY); \
00919         QS_OBJ_(obj_); \
00920         QS_STR_ROM_(obj_name__); \
00921         QS::end(); \
00922         QS_INT_UNLOCK_(); \
00923         QS::onFlush(); \
00924     } else ((void)0)
00925
00937 #define QS_FUN_DICTIONARY(fun_) \
00938     if (((QS::glbFilter_[(uint8_t)QS_FUN_DICTIONARY >> 3U] \
00939           & (1U << ((uint8_t)QS_FUN_DICTIONARY & 7U))) != 0U)) \
00940     { \
00941         static char const Q_ROM Q_ROM_VAR fun_name__[] = #fun_; \
00942         QS_INT_LOCK_KEY_ \
00943         QS_INT_LOCK_(); \
00944         QS::begin((uint8_t)QS_FUN_DICTIONARY); \
00945         QS_FUN_(fun_); \
00946         QS_STR_ROM_(fun_name__); \
00947         QS::end(); \
00948         QS_INT_UNLOCK_(); \
00949         QS::onFlush(); \
00950     } else ((void)0)
00951
00958 #define QS_FLUSH()   QS::onFlush()
00959
00960
00962 #define QF_QS_INT_LOCK() \
00963     QS_BEGIN_NOLOCK_(QS_QF_INT_LOCK, (void *)0, (void *)0); \
00964         QS_TIME_(); \
00965         QS_U8_((uint8_t)(++QF_intLockNest_)); \
00966     QS_END_NOLOCK_()
00967
00969 #define QF_QS_INT_UNLOCK() \
00970     QS_BEGIN_NOLOCK_(QS_QF_INT_UNLOCK, (void *)0, (void *)0); \
00971         QS_TIME_(); \
00972         QS_U8_((uint8_t)(QF_intLockNest_--)); \
00973     QS_END_NOLOCK_()
00974
00976 #define QF_QS_ISR_ENTRY(isrnest_, prio_) \
00977     QS_BEGIN_NOLOCK_(QS_QF_ISR_ENTRY, (void *)0, (void *)0); \
00978         QS_TIME_(); \
00979         QS_U8_(isrnest_); \
00980         QS_U8_(prio_); \
00981     QS_END_NOLOCK_()
00982
00984 #define QF_QS_ISR_EXIT(isrnest_, prio_) \
00985     QS_BEGIN_NOLOCK_(QS_QF_ISR_EXIT, (void *)0, (void *)0); \
00986         QS_TIME_(); \
00987         QS_U8_(isrnest_); \
00988         QS_U8_(prio_); \
00989     QS_END_NOLOCK_()
00990
00992 #define QF_QS_ACTION(act_)      (act_)
00993
00997 extern uint8_t QF_intLockNest_;
00998
00999 #endif                                                                 // qs_h


QP/C++: qs_.cpp Source File

qs_.cpp

Go to the documentation of this file.
00001
00002 // Product: QS/C++
00003 // Last Updated for Version: 4.0.01
00004 // Date of the Last Update:  Jun 09, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qs_pkg.h"
00029
00033
00034 //............................................................................
00035 void const *QS::smObj_;                  // local state machine for QEP filter
00036 void const *QS::aoObj_;                   // local active object for QF filter
00037 void const *QS::mpObj_;                     //  local event pool for QF filter
00038 void const *QS::eqObj_;                      //  local raw queue for QF filter
00039 void const *QS::teObj_;                     //  local time event for QF filter
00040 void const *QS::apObj_;                    //  local object Application filter
00041
00042 QSTimeCtr volatile QS::tickCtr_;     // tick counter for the QS_QF_TICK record
00043
00044 //............................................................................
00045 void QS::u8_(uint8_t d) {
00046     QS_INSERT_ESC_BYTE(d)
00047 }
00048 //............................................................................
00049 void QS::u16_(uint16_t d) {
00050     QS_INSERT_ESC_BYTE((uint8_t)d)
00051     d >>= 8;
00052     QS_INSERT_ESC_BYTE((uint8_t)d)
00053 }
00054 //............................................................................
00055 void QS::u32_(uint32_t d) {
00056     QS_INSERT_ESC_BYTE((uint8_t)d)
00057     d >>= 8;
00058     QS_INSERT_ESC_BYTE((uint8_t)d)
00059     d >>= 8;
00060     QS_INSERT_ESC_BYTE((uint8_t)d)
00061     d >>= 8;
00062     QS_INSERT_ESC_BYTE((uint8_t)d)
00063 }
00064 //............................................................................
00065 //lint -e970 -e971               ignore MISRA rules 13 and 14 in this function
00066 void QS::str_(char const *s) {
00067     while (*s != '\0') {
00068                                        // ASCII characters don't need escaping
00069         QS_chksum_ = (uint8_t)(QS_chksum_ + (uint8_t)(*s));
00070         QS_INSERT_BYTE((uint8_t)(*s))
00071         ++s;
00072     }
00073     QS_INSERT_BYTE((uint8_t)0)
00074 }
00075 //............................................................................
00076 //lint -e970 -e971               ignore MISRA rules 13 and 14 in this function
00077 void QS::str_ROM_(char const Q_ROM * Q_ROM_VAR s) {
00078     uint8_t b;
00079     while ((b = (uint8_t)Q_ROM_BYTE(*s)) != (uint8_t)0) {
00080                                        // ASCII characters don't need escaping
00081         QS_chksum_ = (uint8_t)(QS_chksum_ + b);
00082         QS_INSERT_BYTE(b)
00083         ++s;
00084     }
00085     QS_INSERT_BYTE((uint8_t)0)
00086 }


QP/C++: qs_blk.cpp Source File

qs_blk.cpp

Go to the documentation of this file.
00001
00002 // Product: QS/C++
00003 // Last Updated for Version: 4.1.05
00004 // Date of the Last Update:  Oct 27, 2010
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2010 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qs_pkg.h"
00029
00033
00034 //............................................................................
00035 // get up to *pn bytes of contiguous memory
00036 uint8_t const *QS::getBlock(uint16_t *pNbytes) {
00037     uint8_t *block;
00038     if (QS_used_ == (QSCtr)0) {
00039         *pNbytes = (uint16_t)0;
00040         block = (uint8_t *)0;                  // no bytes to return right now
00041     }
00042     else {
00043         QSCtr n = (QSCtr)(QS_end_ - QS_tail_);
00044         if (n > QS_used_) {
00045             n = QS_used_;
00046         }
00047         if (n > (QSCtr)(*pNbytes)) {
00048             n = (QSCtr)(*pNbytes);
00049         }
00050         *pNbytes = (uint16_t)n;
00051         QS_used_ = (QSCtr)(QS_used_ - n);
00052         QSCtr t  = QS_tail_;
00053         QS_tail_ = (QSCtr)(QS_tail_ + n);
00054         if (QS_tail_ == QS_end_) {
00055             QS_tail_ = (QSCtr)0;
00056         }
00057         block = &QS_ring_[t];
00058     }
00059     return block;
00060 }


QP/C++: qs_byte.cpp Source File

qs_byte.cpp

Go to the documentation of this file.
00001
00002 // Product: QS/C++
00003 // Last Updated for Version: 4.1.05
00004 // Date of the Last Update:  Oct 27, 2010
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2010 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qs_pkg.h"
00029
00033
00034 //............................................................................
00035 uint16_t QS::getByte(void) {
00036     uint16_t ret;
00037     if (QS_used_ == (QSCtr)0) {
00038         ret = QS_EOD;                                       // set End-Of-Data
00039     }
00040     else {
00041         ret = QS_ring_[QS_tail_];                    // set the byte to return
00042         ++QS_tail_;                                        // advance the tail
00043         if (QS_tail_ == QS_end_) {                        // tail wrap around?
00044             QS_tail_ = (QSCtr)0;
00045         }
00046         --QS_used_;                                      // one less byte used
00047     }
00048     return ret;                                      // return the byte or EOD
00049 }


QP/C++: qs_dummy.h Source File

qs_dummy.h

Go to the documentation of this file.
00001
00002 // Product: QP/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 06, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #ifndef qs_dummy_h
00029 #define qs_dummy_h
00030
00035
00036 #ifdef Q_SPY
00037     #error "Q_SPY must NOT be defined to include qs_dummy.h"
00038 #endif
00039
00040 #define QS_INIT(arg_)                   ((uint8_t)1)
00041 #define QS_EXIT()                       ((void)0)
00042 #define QS_DUMP()                       ((void)0)
00043 #define QS_FILTER_ON(rec_)              ((void)0)
00044 #define QS_FILTER_OFF(rec_)             ((void)0)
00045 #define QS_FILTER_SM_OBJ(obj_)          ((void)0)
00046 #define QS_FILTER_AO_OBJ(obj_)          ((void)0)
00047 #define QS_FILTER_MP_OBJ(obj_)          ((void)0)
00048 #define QS_FILTER_EQ_OBJ(obj_)          ((void)0)
00049 #define QS_FILTER_TE_OBJ(obj_)          ((void)0)
00050 #define QS_FILTER_AP_OBJ(obj_)          ((void)0)
00051
00052 #define QS_GET_BYTE(pByte_)             ((uint16_t)0xFFFF)
00053 #define QS_GET_BLOCK(pSize_)            ((uint8_t *)0)
00054
00055 #define QS_BEGIN(rec_, obj_)            if (0) {
00056 #define QS_END()                        }
00057 #define QS_BEGIN_NOLOCK(rec_, obj_)     if (0) {
00058 #define QS_END_NOLOCK()                 }
00059
00060 #define QS_I8(width_, data_)            ((void)0)
00061 #define QS_U8(width_, data_)            ((void)0)
00062 #define QS_I16(width_, data_)           ((void)0)
00063 #define QS_U16(width_, data_)           ((void)0)
00064 #define QS_I32(width_, data_)           ((void)0)
00065 #define QS_U32(width_, data_)           ((void)0)
00066 #define QS_F32(width_, data_)           ((void)0)
00067 #define QS_F64(width_, data_)           ((void)0)
00068 #define QS_STR(str_)                    ((void)0)
00069 #define QS_STR_ROM(str_)                ((void)0)
00070 #define QS_MEM(mem_, size_)             ((void)0)
00071 #define QS_SIG(sig_, obj_)              ((void)0)
00072 #define QS_OBJ(obj_)                    ((void)0)
00073 #define QS_FUN(fun_)                    ((void)0)
00074
00075 #define QS_SIG_DICTIONARY(sig_, obj_)   ((void)0)
00076 #define QS_OBJ_DICTIONARY(obj_)         ((void)0)
00077 #define QS_FUN_DICTIONARY(fun_)         ((void)0)
00078 #define QS_FLUSH()                      ((void)0)
00079
00080 // internal QS macros used only in the QP components .........................
00081 #define QS_INT_LOCK_KEY_
00082 #define QS_BEGIN_(rec_, refObj_, obj_)  if (0) {
00083 #define QS_END_()                       }
00084 #define QS_BEGIN_NOLOCK_(rec_, refObj_, obj_) if (0) {
00085 #define QS_END_NOLOCK_()                }
00086 #define QS_U8_(data_)                   ((void)0)
00087 #define QS_U16_(data_)                  ((void)0)
00088 #define QS_U32_(data_)                  ((void)0)
00089 #define QS_TIME_()                      ((void)0)
00090 #define QS_SIG_(sig_)                   ((void)0)
00091 #define QS_EVS_(size_)                  ((void)0)
00092 #define QS_OBJ_(obj_)                   ((void)0)
00093 #define QS_FUN_(fun_)                   ((void)0)
00094 #define QS_EQC_(ctr_)                   ((void)0)
00095 #define QS_MPC_(ctr_)                   ((void)0)
00096 #define QS_MPS_(size_)                  ((void)0)
00097 #define QS_TEC_(ctr_)                   ((void)0)
00098
00099 #define QF_QS_INT_LOCK()                ((void)0)
00100 #define QF_QS_INT_UNLOCK()              ((void)0)
00101 #define QF_QS_ISR_ENTRY(isrnest_, prio_) ((void)0)
00102 #define QF_QS_ISR_EXIT(isrnest_, prio_) ((void)0)
00103 #define QF_QS_ACTION(act_)              ((void)0)
00104
00105 #endif                                                           // qs_dummy_h


QP/C++: qs_f32.cpp Source File

qs_f32.cpp

Go to the documentation of this file.
00001
00002 // Product: QS/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qs_pkg.h"
00029
00033
00034 //............................................................................
00035 void QS::f32(uint8_t format, float f) {
00036     union F32Rep {
00037         float f;
00038         uint32_t u;
00039     } fu32;
00040     fu32.f = f;
00041
00042     QS_INSERT_ESC_BYTE(format)
00043     QS_INSERT_ESC_BYTE((uint8_t)fu32.u)
00044     fu32.u >>= 8;
00045     QS_INSERT_ESC_BYTE((uint8_t)fu32.u)
00046     fu32.u >>= 8;
00047     QS_INSERT_ESC_BYTE((uint8_t)fu32.u)
00048     fu32.u >>= 8;
00049     QS_INSERT_ESC_BYTE((uint8_t)fu32.u)
00050 }


QP/C++: qs_f64.cpp Source File

qs_f64.cpp

Go to the documentation of this file.
00001
00002 // Product: QS/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qs_pkg.h"
00029
00033
00034 //............................................................................
00035 void QS::f64(uint8_t format, double d) {
00036     union F64Rep {
00037         double d;
00038         struct UInt2 {
00039             uint32_t u1, u2;
00040         } i;
00041     } fu64;
00042     fu64.d = d;
00043
00044     QS_INSERT_ESC_BYTE(format)
00045
00046     QS_INSERT_ESC_BYTE((uint8_t)fu64.i.u1)
00047     fu64.i.u1 >>= 8;
00048     QS_INSERT_ESC_BYTE((uint8_t)fu64.i.u1)
00049     fu64.i.u1 >>= 8;
00050     QS_INSERT_ESC_BYTE((uint8_t)fu64.i.u1)
00051     fu64.i.u1 >>= 8;
00052     QS_INSERT_ESC_BYTE((uint8_t)fu64.i.u1)
00053
00054     QS_INSERT_ESC_BYTE((uint8_t)fu64.i.u2)
00055     fu64.i.u2 >>= 8;
00056     QS_INSERT_ESC_BYTE((uint8_t)fu64.i.u2)
00057     fu64.i.u2 >>= 8;
00058     QS_INSERT_ESC_BYTE((uint8_t)fu64.i.u2)
00059     fu64.i.u2 >>= 8;
00060     QS_INSERT_ESC_BYTE((uint8_t)fu64.i.u2)
00061 }


QP/C++: qs_mem.cpp Source File

qs_mem.cpp

Go to the documentation of this file.
00001
00002 // Product: QS/C++
00003 // Last Updated for Version: 4.1.05
00004 // Date of the Last Update:  Oct 27, 2010
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2010 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qs_pkg.h"
00029
00033
00034 //............................................................................
00035 void QS::mem(uint8_t const *blk, uint8_t size) {
00036     QS_INSERT_BYTE((uint8_t)QS_MEM_T)
00037     QS_chksum_ = (uint8_t)(QS_chksum_ + (uint8_t)QS_MEM_T);
00038     QS_INSERT_ESC_BYTE(size)
00039     while (size != (uint8_t)0) {
00040         QS_INSERT_ESC_BYTE(*blk)
00041         ++blk;
00042         --size;
00043     }
00044 }


QP/C++: qs_pkg.h Source File

qs_pkg.h

Go to the documentation of this file.
00001
00002 // Product: QS/C++
00003 // Last Updated for Version: 4.1.05
00004 // Date of the Last Update:  Oct 27, 2010
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2010 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #ifndef qs_pkg_h
00029 #define qs_pkg_h
00030
00034
00035 #include "qs_port.h"                                                // QS port
00036
00038 typedef uint16_t QSCtr;
00039
00043 #define QS_INSERT_BYTE(b_) \
00044     QS_ring_[QS_head_] = (b_); \
00045     ++QS_head_; \
00046     if (QS_head_ == QS_end_) { \
00047         QS_head_ = (QSCtr)0; \
00048     } \
00049     ++QS_used_;
00050
00052 #define QS_INSERT_ESC_BYTE(b_) \
00053     QS_chksum_ = (uint8_t)(QS_chksum_ + (b_)); \
00054     if (((b_) == QS_FRAME) || ((b_) == QS_ESC)) { \
00055         QS_INSERT_BYTE(QS_ESC) \
00056         QS_INSERT_BYTE((uint8_t)((b_) ^ QS_ESC_XOR)) \
00057     } \
00058     else { \
00059         QS_INSERT_BYTE(b_) \
00060     }
00061
00064 #define QS_INSERT_CHKSUM_BYTE() \
00065     QS_chksum_ = (uint8_t)~QS_chksum_; \
00066     if ((QS_chksum_ == QS_FRAME) || (QS_chksum_ == QS_ESC)) { \
00067         QS_INSERT_BYTE(QS_ESC) \
00068         QS_INSERT_BYTE((uint8_t)(QS_chksum_ ^ QS_ESC_XOR)) \
00069     } \
00070     else { \
00071         QS_INSERT_BYTE(QS_chksum_) \
00072     }
00073
00074
00076 #define QS_FRAME    ((uint8_t)0x7E)
00077
00079 #define QS_ESC      ((uint8_t)0x7D)
00080
00085 #define QS_ESC_XOR  0x20
00086
00087 #ifndef Q_ROM_BYTE
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101     #define Q_ROM_BYTE(rom_var_)   (rom_var_)
00102 #endif
00103
00104 //............................................................................
00105 extern uint8_t *QS_ring_;
00106 extern QSCtr QS_end_;
00107 extern QSCtr QS_head_;
00108 extern QSCtr QS_tail_;
00109 extern QSCtr QS_used_;
00110 extern uint8_t QS_seq_;
00111 extern uint8_t QS_chksum_;
00112 extern uint8_t QS_full_;
00113
00114 #endif                                                             // qs_pkg_h


QP/C++: qs_port.h Source File

qs_port.h

Go to the documentation of this file.
00001
00002 // Product: QS/C++ port
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #ifndef qs_port_h
00029 #define qs_port_h
00030
00037
00038 #define QS_TIME_SIZE            4
00039 #define QS_OBJ_PTR_SIZE         4
00040 #define QS_FUN_PTR_SIZE         4
00041
00043 // NOTE:
00044 // QS might be used with or without other QP components, in which case
00045 // the separate definitions of the macros Q_ROM, Q_ROM_VAR, Q_ROM_BYTE,
00046 // QF_INT_KEY_TYPE, QF_INT_LOCK, and QF_INT_UNLOCK are needed. In this
00047 // port QS is configured to be used with the other QP component, by
00048 // simply including "qf_port.h" *before* "qs.h".
00049 //
00050 #include "qf_port.h"
00051
00052 #include "qs.h"                // QS platform-independent public interface
00053
00054 #endif                                                            // qs_port_h


QP/C++: qs_str.cpp Source File

qs_str.cpp

Go to the documentation of this file.
00001
00002 // Product: QS/C++
00003 // Last Updated for Version: 4.0.01
00004 // Date of the Last Update:  Jun 09, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qs_pkg.h"
00029
00033
00034 //............................................................................
00035 //lint -e970 -e971               ignore MISRA rules 13 and 14 in this function
00036 void QS::str(char const *s) {
00037     QS_INSERT_BYTE((uint8_t)QS_STR_T)
00038     QS_chksum_ = (uint8_t)(QS_chksum_ + (uint8_t)QS_STR_T);
00039     while ((*s) != '\0') {
00040                                        // ASCII characters don't need escaping
00041         QS_INSERT_BYTE((uint8_t)(*s))
00042         QS_chksum_ = (uint8_t)(QS_chksum_ + (uint8_t)(*s));
00043         ++s;
00044     }
00045     QS_INSERT_BYTE((uint8_t)0)
00046 }
00047 //............................................................................
00048 //lint -e970 -e971               ignore MISRA rules 13 and 14 in this function
00049 void QS::str_ROM(char const Q_ROM * Q_ROM_VAR s) {
00050     QS_INSERT_BYTE((uint8_t)QS_STR_T)
00051     QS_chksum_ = (uint8_t)(QS_chksum_ + (uint8_t)QS_STR_T);
00052     uint8_t b;
00053     while ((b = (uint8_t)Q_ROM_BYTE(*s)) != (uint8_t)0) {
00054                                        // ASCII characters don't need escaping
00055         QS_INSERT_BYTE(b)
00056         QS_chksum_ = (uint8_t)(QS_chksum_ + b);
00057         ++s;
00058     }
00059     QS_INSERT_BYTE((uint8_t)0)
00060 }


QP/C++: qte_arm.cpp Source File

qte_arm.cpp

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029 #include "qassert.h"
00030
00031 Q_DEFINE_THIS_MODULE(qte_arm)
00032
00033
00034
00035
00036
00037 // Package-scope objects -----------------------------------------------------
00038 QTimeEvt *QF_timeEvtListHead_;           // head of linked list of time events
00039
00040 //............................................................................
00041 void QTimeEvt::arm_(QActive *act, QTimeEvtCtr nTicks) {
00042     Q_REQUIRE((nTicks > (QTimeEvtCtr)0)          /* cannot arm with 0 ticks */
00043               && (sig >= (QSignal)Q_USER_SIG)               /* valid signal */
00044               && (m_prev == (QTimeEvt *)0)   /* time event must NOT be used */
00045               && (act != (QActive *)0));  /* active object must be provided */
00046     m_ctr = nTicks;
00047     m_prev = this;                                    // mark the timer in use
00048     m_act = act;
00049     QF_INT_LOCK_KEY_
00050     QF_INT_LOCK_();
00051
00052     QS_BEGIN_NOLOCK_(QS_QF_TIMEEVT_ARM, QS::teObj_, this)
00053         QS_TIME_();                                               // timestamp
00054         QS_OBJ_(this);                               // this time event object
00055         QS_OBJ_(act);                                     // the active object
00056         QS_TEC_(nTicks);                                // the number of ticks
00057         QS_TEC_(m_interval);                                   // the interval
00058     QS_END_NOLOCK_()
00059
00060     m_next = QF_timeEvtListHead_;
00061     if (QF_timeEvtListHead_ != (QTimeEvt *)0) {
00062         QF_timeEvtListHead_->m_prev = this;
00063     }
00064     QF_timeEvtListHead_ = this;
00065     QF_INT_UNLOCK_();
00066 }


QP/C++: qte_ctor.cpp Source File

qte_ctor.cpp

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029 #include "qassert.h"
00030
00031 Q_DEFINE_THIS_MODULE(qte_ctor)
00032
00033
00034
00035
00036
00037 //............................................................................
00038 QTimeEvt::QTimeEvt(QSignal s)
00039     : m_prev((QTimeEvt *)0),
00040       m_next((QTimeEvt *)0),
00041       m_act((QActive *)0),
00042       m_ctr((QTimeEvtCtr)0),
00043       m_interval((QTimeEvtCtr)0)
00044 {
00045     Q_REQUIRE(s >= (QSignal)Q_USER_SIG);                       // valid signal
00046     sig = s;
00047     dynamic_ = (uint8_t)0;            // time event must be static, see NOTE01
00048 }
00049
00051 // NOTE01:
00052 // Setting the dynamic_ attribute to zero is correct only for events not
00053 // allocated from event pools. In the future releases of QF, time events
00054 // actually could be allocated dynamically. However, for simplicity in this
00055 // release of QF, time events are limited to be statically allocated.
00056 //


QP/C++: qte_darm.cpp Source File

qte_darm.cpp

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029
00033
00034 //............................................................................
00035 // NOTE: disarm a time evt (no harm in disarming an already disarmed time evt)
00036 uint8_t QTimeEvt::disarm(void) {
00037     uint8_t wasArmed;
00038     QF_INT_LOCK_KEY_
00039     QF_INT_LOCK_();
00040     if (m_prev != (QTimeEvt *)0) {        // is the time event actually armed?
00041         wasArmed = (uint8_t)1;
00042         if (this == QF_timeEvtListHead_) {
00043             QF_timeEvtListHead_ = m_next;
00044         }
00045         else {
00046             if (m_next != (QTimeEvt *)0) {        // not the last in the list?
00047                 m_next->m_prev = m_prev;
00048             }
00049             m_prev->m_next = m_next;
00050         }
00051         m_prev = (QTimeEvt *)0;             // mark the time event as disarmed
00052
00053         QS_BEGIN_NOLOCK_(QS_QF_TIMEEVT_DISARM, QS::teObj_, this)
00054             QS_TIME_();                                           // timestamp
00055             QS_OBJ_(this);                           // this time event object
00056             QS_OBJ_(m_act);                               // the active object
00057             QS_TEC_(m_ctr);                             // the number of ticks
00058             QS_TEC_(m_interval);                               // the interval
00059         QS_END_NOLOCK_()
00060     }
00061     else {                                     // the time event was not armed
00062         wasArmed = (uint8_t)0;
00063
00064         QS_BEGIN_NOLOCK_(QS_QF_TIMEEVT_DISARM_ATTEMPT, QS::teObj_, this)
00065             QS_TIME_();                                           // timestamp
00066             QS_OBJ_(this);                           // this time event object
00067             QS_OBJ_(m_act);                               // the active object
00068         QS_END_NOLOCK_()
00069     }
00070     QF_INT_UNLOCK_();
00071     return wasArmed;
00072 }


QP/C++: qte_rarm.cpp Source File

qte_rarm.cpp

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029 #include "qassert.h"
00030
00031 Q_DEFINE_THIS_MODULE(qte_rarm)
00032
00033
00034
00035
00036
00037 //............................................................................
00038 uint8_t QTimeEvt::rearm(QTimeEvtCtr nTicks) {
00039     Q_REQUIRE((nTicks > (QTimeEvtCtr)0)        /* cannot rearm with 0 ticks */
00040               && (sig >= (QSignal)Q_USER_SIG)               /* valid signal */
00041               && (m_act != (QActive *)0));              // valid active object
00042     uint8_t isArmed;
00043     QF_INT_LOCK_KEY_
00044     QF_INT_LOCK_();
00045     m_ctr = nTicks;
00046     if (m_prev == (QTimeEvt *)0) {             // is this time event disarmed?
00047         isArmed = (uint8_t)0;
00048         m_next = QF_timeEvtListHead_;
00049         if (QF_timeEvtListHead_ != (QTimeEvt *)0) {
00050             QF_timeEvtListHead_->m_prev = this;
00051         }
00052         QF_timeEvtListHead_ = this;
00053         m_prev = this;                             // mark the time evt in use
00054     }
00055     else {                                          // the time event is armed
00056         isArmed = (uint8_t)1;
00057     }
00058
00059     QS_BEGIN_NOLOCK_(QS_QF_TIMEEVT_REARM, QS::teObj_, this)
00060         QS_TIME_();                                               // timestamp
00061         QS_OBJ_(this);                               // this time event object
00062         QS_OBJ_(m_act);                                   // the active object
00063         QS_TEC_(m_ctr);                                 // the number of ticks
00064         QS_TEC_(m_interval);                                   // the interval
00065         QS_U8_(isArmed);                               // was the timer armed?
00066     QS_END_NOLOCK_()
00067
00068     QF_INT_UNLOCK_();
00069     return isArmed;
00070 }


QP/C++: qvanilla.cpp Source File

qvanilla.cpp

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029 #include "qassert.h"
00030
00031 Q_DEFINE_THIS_MODULE(qvanilla)
00032
00033
00034
00035
00036
00037
00038 // Package-scope objects -----------------------------------------------------
00039 #if (QF_MAX_ACTIVE <= 8)
00040     QPSet8  volatile QF_readySet_;           // QF-ready set of active objects
00041 #else
00042     QPSet64 volatile QF_readySet_;           // QF-ready set of active objects
00043 #endif
00044
00045 //............................................................................
00046 char const Q_ROM * Q_ROM_VAR QF::getPortVersion(void) {
00047     static const char Q_ROM version[] = "4.0.00";
00048     return version;
00049 }
00050 //............................................................................
00051 void QF::init(void) {
00052     // nothing to do for the "vanilla" kernel
00053 }
00054 //............................................................................
00055 void QF::stop(void) {
00056     QF::onCleanup();                                       // cleanup callback
00057     // nothing else to do for the "vanilla" kernel
00058 }
00059 //............................................................................
00060 void QF::run(void) {
00061     QF::onStartup();                                       // startup callback
00062
00063     for (;;) {                                           // the bacground loop
00064         QF_INT_LOCK_KEY_
00065         QF_INT_LOCK_();
00066         if (QF_readySet_.notEmpty()) {
00067             uint8_t p = QF_readySet_.findMax();
00068             QActive *a = active_[p];
00069             QF_INT_UNLOCK_();
00070
00071             QEvent const *e = a->get_();     // get the next event for this AO
00072             a->dispatch(e);                         // dispatch evt to the HSM
00073             gc(e);       // determine if event is garbage and collect it if so
00074         }
00075         else {
00076 #ifndef QF_INT_KEY_TYPE
00077             QF::onIdle();                                        // see NOTE01
00078 #else
00079             QF::onIdle(intLockKey_);                             // see NOTE01
00080 #endif                                                      // QF_INT_KEY_TYPE
00081         }
00082     }
00083 }
00084 //............................................................................
00085 void QActive::start(uint8_t prio,
00086                     QEvent const *qSto[], uint32_t qLen,
00087                     void *stkSto, uint32_t /*lint -e1904 stkSize */,
00088                     QEvent const *ie)
00089 {
00090     Q_REQUIRE(((uint8_t)0 < prio) && (prio <= (uint8_t)QF_MAX_ACTIVE)
00091               && (stkSto == (void *)0));      // does not need per-actor stack
00092
00093     m_eQueue.init(qSto, (QEQueueCtr)qLen);               // initialize QEQueue
00094     m_prio = prio;                // set the QF priority of this active object
00095     QF::add_(this);                     // make QF aware of this active object
00096     init(ie);                                    // execute initial transition
00097
00098     QS_FLUSH();                          // flush the trace buffer to the host
00099 }
00100 //............................................................................
00101 void QActive::stop(void) {
00102     QF::remove_(this);
00103 }
00104
00106 // NOTE01:
00107 // QF::onIdle() must be called with interrupts LOCKED because the
00108 // determination of the idle condition (no events in the queues) can change
00109 // at any time by an interrupt posting events to a queue. The QF::onIdle()
00110 // MUST enable interrups internally, perhaps at the same time as putting the
00111 // CPU into a power-saving mode.
00112 //
00113


QP/C++: qvanilla.h Source File

qvanilla.h

Go to the documentation of this file.
00001
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 06, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #ifndef qvanilla_h
00029 #define qvanilla_h
00030
00034
00035 #include "qequeue.h"       // "Vanilla" kernel uses the native QF event queue
00036 #include "qmpool.h"        // "Vanilla" kernel uses the native QF memory pool
00037 #include "qpset.h"         // "Vanilla" kernel uses the native QF priority set
00038
00039                               // the event queue type for the "Vanilla" kernel
00040 #define QF_EQUEUE_TYPE              QEQueue
00041                                               // native event queue operations
00042 #define QACTIVE_EQUEUE_WAIT_(me_) \
00043     Q_ASSERT((me_)->m_eQueue.m_frontEvt != (QEvent *)0)
00044
00045 #define QACTIVE_EQUEUE_SIGNAL_(me_) \
00046     QF_readySet_.insert((me_)->m_prio)
00047
00048 #define QACTIVE_EQUEUE_ONEMPTY_(me_) \
00049     QF_readySet_.remove((me_)->m_prio)
00050
00051                                             // native QF event pool operations
00052 #define QF_EPOOL_TYPE_              QMPool
00053 #define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_) \
00054     (p_).init(poolSto_, poolSize_, evtSize_)
00055 #define QF_EPOOL_EVENT_SIZE_(p_)    ((p_).getBlockSize())
00056 #define QF_EPOOL_GET_(p_, e_)       ((e_) = (QEvent *)(p_).get())
00057 #define QF_EPOOL_PUT_(p_, e_)       ((p_).put(e_))
00058
00059 #if (QF_MAX_ACTIVE <= 8)
00060     extern QPSet8  volatile QF_readySet_;
00061 #else
00062     extern QPSet64 volatile QF_readySet_;
00063 #endif
00064
00065 #endif                                                           // qvanilla_h


QP/C++: Member List

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members

QEvent Member List

This is the complete list of members for QEvent, including all inherited members.
dynamic_ | QEvent
sig | QEvent
Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3


QP/C++: Member List

  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members

QFreeBlock Member List

This is the complete list of members for QFreeBlock, including all inherited members.
Generated on Fri Jan 7 2011 21:37:31 for QP/C++ by doxygen 1.7.3