QP/C++  7.3.4
Real-Time Embedded Framework
Loading...
Searching...
No Matches
Examples

General Comments

The QP/C++ distribution contains many example projects with the following main goals:

  • to help you learn how to use the QP framework — the examples show the intended way of using QP/C++ features and structuring your QP/C++ applications.
  • to provide unit testing support — the QUTest examples illustrate unit testing techniques both for the development host computers and for embedded targets.
  • to provide a starting point for your own projects — the examples are complete working projects, with correctly pre-configured tools, such as compiler options, linker script, debugger setup, etc.
Note
It is highly recommended that you create your own projects by copying and modifying existing example projects rather than starting your QP/C++ projects from scratch.

Example Applications

To demonstrate QP/C++ features on an embedded board, you need to create an application that does "something interesting". Instead of inventing this "something interesting" for each and every example, the example projects implement one of the three "example applications", which are described on the QP™/C Tutorial:

With the exception of the game application, all other example applications can be implemented on a board with just a couple of LEDs. The "Fly 'n' Shoot" Game application is a bit more involved and requires a small graphic display on the board.

The QP/C++ examples/posix-win32 directory contains all examples described in the book Practical UML Statecharts in C/C++, 2nd Edition. These examples work on the host computer (e.g., Windows, Linux, macOS), so you don't need any special embedded hardware to build and run these examples.

Development Boards

The embedded example projects require special hardware in form of various evaluation boards, which you need to acquire to be able to run the examples. The boards chosen for the examples are generally inexpensive and self-contained with no need for external hardware (such as external JTAG debuggers or power supplies).

Development Tools

Most provided examples require special embedded cross-development tools, such as embedded compilers, linkers, debuggers and IDEs, which you need to acquire independently from the QP/C++ distribution. Generally, the examples work with the free evaluation versions of the commercial tools.

Build Configurations

The QP/C++ examples are typically provided in the following three build configurations:

  • Debug — this configuration is built with full debugging information and minimal optimization. The QS trace instrumentation is disabled.
  • Release — this configuration is built with high optimization. Debugging at the source-code level is severely impaired due to the highly optimized code, but the debugger can be used to download and start the executable. The QS trace instrumentation is disabled.
  • Spy — like the debug variant, this variant is built with full debugging information and minimal optimization. Additionally, it is build with the QS trace instrumentation enabled. The on-board serial port and the Q-Spy host application are used for sending and viewing trace data.
Remarks
Why do you need multiple build configurations?
The different phases of embedded software life cycle pose different challenges. During the development and maintenance phase, for example, the emphasis is on the ease of debugging and verifying the correctness of the code, which require lower levels of optimization and special instrumentation code. In contrast, for releasing the code in the final product, the emphasis is on small memory footprint, CPU efficiency, and low power consumption, which require high-level of optimization and removal of any code instrumentation. To address these conflicting objectives, the same source code is compiled into multiple build configurations that differ in the use of compiler options and activation of the code instrumentation.

QM Models

Many example projects contain code auto-generated by the QM modeling tool. Such projects always contain the corresponding QM model file (extension .qm), which you can open in QM, modify, and re-generate the code.

Remarks
The auto-generated files are saved as read-only. This protects them from inadvertent modifications, which will get lost when the files are re-generated by QM (or QMC). All modifications to the auto-generated code should be done in the QM model, not in the code.
Note
If you don't like automatic code generation, you can create all your QP/C++ application code manually. In that case, the generated files can serve as starting points for your implementation. To edit the files manually, you need to change the file attributes to remove the read-only protection.

Third-Party Code

The QP/C++ example projects often need to use various additional code, such as MCU register definition files, startup code, device drivers, etc., which are provided by Third-Party vendors. All such code is located in the 3rd_party top-level folder.

Note
As far as possible, the code in the 3rd_party folder has been left unchanged from the original source. (Any modified code is clearly identified by top-level comments that detail the applied changes.) For that reason, the Third-Party code might produce compilation warnings in your builds.

The code in the 3rd_party folder comes from various sources, and Quantum Leaps, LLC expressly makes no claims of ownership to any of this code, even though some of the code might be customized or modified by Quantum Leaps.

Attention
The Third-Party software components included in the 3rd_party folder are licensed under a variety of different licensing terms that are defined by the respective owners of this software and are spelled out in the README.txt or LICENSE.txt files included in the respective sub-folders.

Creating your Own QP/C++ Projects

Perhaps the most important fact of life to remember is that in embedded systems nothing works until everything works. This means that you should always start with a working system and gradually evolve it, changing one thing at a time and making sure that it keeps working every step of the way.

Keeping this in mind, the provided QP/C++ application examples, such as the super-simple Blinky, or a bit more advanced Dining Philosophers Problem (DPP) or "Fly 'n' Shoot" Game, allow you to get started with a working project rather than starting from scratch. You should also always try one of the provided example projects on the same evaluation board that it was designed for, before making any changes.

Note
The evaluation boards used in the examples are all very inexpensive and available from major electronic distributors (e.g., Arrow, DigiKey, Mouser, Avnet), as well as directly from the silicon vendors (e.g., a TI board is also available from TI.com).
Remarks
Even before you acquire a specific evaluation board, you can always at least build a project that interests you on your host computer.

Only after convincing yourself that the example project works "as is", you can think about creating your own projects. At this point, the easiest and recommended way is to copy the existing working example project folder (such as the Blinky example) and rename it.

After copying the project folder, you still need to change the name of the project/workspace. The easiest and safest way to do this is to open the project/workspace in the corresponding IDE and use the Save As~~~ option to save the project under a different name. You can do this also with the QM model file, which you can open in QM and "Save As" a different model.

Note
By copying and re-naming an existing, working project, as opposed to creating a new one from scratch, you inherit the correct compiler and linker options an other project settings, which will help you get started much faster.

Next Steps and Further Reading About QP and QM

To work with QP/C++ effectively, you need to learn a bit more about active objects and state machines. Below is a list of links to enable you to further your knowledge:

  1. The book "Practical UML Statecharts in C/C++, 2nd Edition" [PSiCC2] and the companion web-page to the book (https://www.state-machine.com/psicc2/
  2. Free Support Forum for QP/QM (https://sourceforge.net/p/qpc/discussion/668726 )
  3. QP Code Downloads summary (https://www.state-machine.com/#Downloads )
  4. QP Application Notes (https://www.state-machine.com/an/ )
  5. "State Space" Blog (https://www.state-machine.com/category/blog/ )

Example Code Organization

QP/C++ examples are located in sub-directories of the examples top-level folder, with the hierarchical organization outlined below:

Note
Each example project is described on its own dedicated README.md file located in the example folder.
qpc/ // QP/C installation directory
+---examples/ // examples directory (applications)
| |
| [1]--arm-cm/ // native examples for ARM Cortex-M
| | +---dpp_ek-tm4c123gxl/ // DPP example on the EK-TM4C123GLX board
| | | +---qk/ // version for preemptive QK kernel
| | | | +---armclang/ // build with ARM-Clang (Compiler Version 6) toolchain
| | | | | +---dbg/ // debug build configuration
| | | | | +---rel/ // release build configuration
| | | | | +---spy/ // spy build configuration (QP/Spy tracing enabled)
| | | | +---gnu/ // build with GNU-ARM toolchain
| | | | +---iar/ // build with IAR toolchain
| | | | ~ ~ ~ // source files independent from the toolchain
| | | |
| | | +---qv/ // version for non-preemptive QV kernel
| | | +---qxk/ // version for dual-mode QXK kernel
| | | |
| | | | ~ ~ ~ // source files independent on the built-in kernel
| | | | README.md // documentation for this example
| |
| [2]--freertos/ // examples for FreeRTOS (3rd-party RTOS)
| | +---arm-cm/ // examples for ARM Cortex-M
| | | +---dpp_ek-tm4c123gxl/ // DPP example on the EK-TM4C123GLX board
| | | | +---gnu/ // build with GNU-ARM toolchain
| | | | ~ ~ ~ // source files independent from the toolchain
| | | | README.md // documentation for this example
| |
| [3]--posix-win32/ // examples for GPOS (Linux, macOS, Windows)
| | +---blinky/ // simple Blinky example
| | +---calc/ // calculator example
| | +---comp/ // "Orthogonal Component" example
| | +--- ~ ~ ~ // other examples from the PSiCC2 book
| |
| [4]--lwip/ // examples for lwIP (3rd-party middleware)
| | +---arm-cm/ // examples for ARM Cortex-M
| | | +---qk/ // version for preemptive QK kernel
| | | +---qv/ // version for non-preemptive QV kernel
| | | \---qxk/ // version for dual-mode QXK kernel
| |
| [5]--qutest/ // examples for QUTest unit testing harness
| | +---blinky/ // simple Blinky example
| | | +---src/ // source code under test
| | | | ~ ~ ~ // CUT (Code Under Test) header file
| | | | ~ ~ ~ // CUT (Code Under Test) source file
| | | +---test/ // code for unit testing
| | | | Makefile // makefile for testing on the host
| | | | make_nucleo-l053r8 // makefile for testing on NUCLEO board
| | | | make_tm4c123 // makefile for testing on NUCLEO board
| | | | test_blinky.c|.cpp // test fixture
| | | | test_blinky.py // test script
| | | | README.md // documentation for this example
| |
| [6]--qwin-gui/ // examples for QWin-GUI prototyping system (dual-targeting)
| | +---dpp-gui/ // DPP GUI prototype
| | | dpp-gui.sln // Visual Studio solution
| | |
| | +---game-gui/ // "Fly 'n' Shoot" game prototype
| | | game-gui.sln // Visual Studio solution

The examples provided in the QP/C++ distribution fall into the following categories:

[1] Native Examples

[2] Examples for 3rd-party RTOS

[3] Examples for GPOS

[4] Examples for 3rd-party Middleware

[5] Examples for QUTest

[6] Examples for QWin-GUI

Remarks
Because the QP distribution contains all examples, the number of sub-directories and files in the examples folder may seem daunting. However, knowing the structure of the examples folder, you can simply ignore or even delete the sub-directories that are not interesting to you.

Native Examples

Native examples are located in sub-directories named after the CPU architecture (see [1] in Example Code Organization), such as arm-cm for ARM Cortex-M. Under that directory, the sub-directories blinky_ek-tm4c123gxl contain the specific example on the specified board, such as "Blinky" on the EK-TM4C123GXL board here. In the specific example folder, you find sub-folders for the QV, QK and QXK kernels, respectively.

Examples for 3rd-party RTOS

Examples for 3rd-party RTOS are located in sub-directories named after the RTOS/OS, such as freertos for FreeRTOS (see [2] in Example Code Organization). Under that directory, the sub-directories, such as arm-cm, contain examples for the specified CPU architecture, such as ARM Cortex-M here.

Examples for GPOS

Examples for GPOS (POSIX/Win32) General-Purpose OS (see [3] in Example Code Organization) run directly on your host computer without any embedded hardware. These examples are simple console applications. This group includes examples described in the PSiCC2 book.

Note
Examples in this directory can also be used on the embedded versions of the desktop operating systems, such as embedded-Linux and Windows-embedded.

Examples for 3rd-party Middleware

Examples for 3rd-party Middleware are located in sub-directories named after the middleware (see [4] in Example Code Organization), such as lwIP for the lwIP TCP/IP stack. Under that directory, the sub-directories, such as arm-cm, contain examples for the specified CPU architecture, such as ARM Cortex-M here.

Examples for QUTest

Examples for QUTest (see [5] in Example Code Organization) illustrate unit testing of embedded event-driven code.

Note
Examples in this directory can run on various General-Purpose OSes (Linux, macOS, Windows) (Windows, Linux, MacOS), as well as embedded targets.

Examples for QWin-GUI

Examples for QUTest (see [6] in Example Code Organization) illustrate prototyping of embedded software on Windows ("dual targeting"). The examples contain are designed for Visual Studio and contain the solution files.

API Reference