Building Applications with QP (qp_dpp Example)

Description

The qp_dpp example program demonstrates the use of the QP active object framework. The example is based on the classic Dining Philosophers Problem (DPP), which was originally posed and solved by Edsger Dijkstra back in 1971. The qp_dpp example program for mbed is relatively simple and can be tested only with a couple of LEDs on the mbed board. Still, DPP contains six concurrent active objects (encapsulated, concurrent state machines) that exchange events via publish-subscribe and direct event posting mechanisms. The application uses five time events (timers), as well as dynamic and static events. Additionally, the qp_dpp example shows how to use the professional QP-Spy software tracing system available in the QP framework with the mbed virtual COM port.

Information

Application Note: Dining Philosophers Problem

The Application Note: Dining Philosophers Problem describes the design and implementation of the qp_dpp example.

Running the qp_dpp Example

You compile and download the qp_dpp program to the mbed board in the usual way. When qp_dpp starts executing, you should see the LED1, LED2, and LED3 blink (the LEDs are counted from the left, see picture below). These three LEDs indicate the "eating" status of the Dining Philosophers 0, 1, and 2, respectively (the remaining Philosophers 3 and 4 are not shown).

mbed-1768 LEDs

The right-most LED4 is used to visualize the status of the idle processing. This LED4 is turned rapidly on and off in the idle loop, which human eye perceives as a continuous glow. The intensity of this glow represents the wasted CPU cycles (see also the section "Power Saving Demonstration" below).

Code Generation Demonstration

QM

Free, graphical QM modeling tool

All state machine code in the qp_dpp program has been generated automatically by the free QM modeling tool. Unfortunately, the QM model of the DPP application could not be included in the qp_dpp example program, where it belongs, because the mbed archive accepts only .h and .cpp source files. Therefore, you need to download the DPP model file separately, as described in the box below.

Downloading the QM model

Please right-click on the link below and and select "Save link as..." option to save the dpp.qm model file to your computer.

/media/uploads/QL/dpp.qm

Please refer to the Graphical Modeling and Code Generation notebook page for more information.

Software Tracing Demonstration

The qp_dpp program also produces output to the serial port connected to the mbed USB interface. This output is then available through the virtual COM port on the host workstation.

The data produced by the qp_dpp program contains very detailed, timestamped information about the program execution. The data is produced by specially designed instrumenation of the QP framework code and available to the application code as well, which is conceptually like peppering the code with the printf() statements, but with much less overhead imposed on the target system. This way of obtaining information about a live system without the need to stopping the software execution is called software tracing. This technique is particularly important for the mbed platform, because the online development system offers no traditional single-step debugger.

Software tracing

The minimal overhead of the software tracing instrumentation comes from several factors, but most importantly from avoiding formatting the data to ASCII in the time-critical code on the target, and instead sending raw binary data. This implies that the software tracing instrumentation requires a special application on the host to receive, decompress and format the data in human-readable ASCII form. In case of the QP framework, the host application is called QSPY.

Downloading the QSPY application

The QSPY host application is available for download from SourceForge at:

sourceforge.net/projects/qpc/files/QSPY/

The ZIP file you download contains pre-compiled QSPY for Windows and Linux hosts. Please read the provided README file to find the executable for your platform.

QSPY is a console application that you invoke from a command line (please make sure that the directory with the QSPY executable is on the PATH). QSPY outputs human-readable tracing data to the console and also to a file, if you choose so. The reference manual of QSPY is available online at state-machine.com/doxygen/qspy.

The command line to invoke QSPY for receiving data from the qp_dpp program on Windows looks as follows:

qspy -b115200 -cCOM7

Most likely you need to adjust the -c parameter to the virtual COM port number of the mbed board. On Windows, you can discover this by running Device Manager.

The following screen shot shows the QSPY output from the qp_dpp example:

QSPY output

You can greatly improve the output by starting QSPY before resetting the mbed board. In that case, you get a much more readable output, like the following screen shot:

QSPY output

The reason is that the qp_dpp program outputs special symbolic information during the initialization. This symbolic information allows the QSPY host application to map binary addresses of various objects to their names, just like a source-level debugger uses information stored in the ELF file to show names of functions and variables. Of course, when you start QSPY after the initialization of the board, the symbolic information is not available and QSPY can only show cryptic hexadecimal addresses.

Application-Specific Software Trace

The last screen of the QSPY output contains special trace records highlighted with red boarders. These are trace records showing the status of the Dining Philosophers and are generated from the qp_dpp application, as opposed to be generated by the QP framework. This demonstrates how you can use the QP software tracing instead of the expensive printf() in your own code. The following code snippet shows how the qp_dpp program generates the output (file bsp.cpp):

void BSP_displyPhilStat(uint8_t n, char const *stat) {
    . . .    
    QS_BEGIN(PHILO_STAT, AO_Philo[n]) // application-specific record
        QS_U8(1, n);   // Philosopher number
        QS_STR(stat);  // Philosopher status
    QS_END()
}

More Information about QP Software Tracing

Of course, this short description can barely scratch the surface of the QP software tracing system. For more information, such as filtering the data, generating accurate time stamps, application-specific tracing, MATLAB interface, and many more, please refer to Chapter 11 of the "Practical UML Statecharts in C/C++" book and the QSPY online manual.

Power Saving Demonstration

Event-driven framework, like QP, can very easily detect a situation when no events are available for processing (called the idle condition). The QP framework provides the idle callback function QK::onIdle(), which allows you to customize the response of the system to the idle condition.

When software tracing is enabled, the idle callback is ideal place to perform the transfer of the tracing data to the host. This minimizes the impact of software tracing on the system, because tracing takes only the CPU cycles that the application does not need anyway.

However, when software tracing is disabled, the idle callback is the ideal place to put the system into a low-power sleep mode. You can actually try it, because the basic code for putting the CPU to sleep is already in place, but is inactive as long as software tracing is used.

You disable software tracing and enable low-power sleep mode by commenting out the define Q_SPY macro in the file qp_config.h:

qp_config.h

#ifndef qp_config_h
#define qp_config_h

// enable the Q-SPY software tracing instrumentation
//#define Q_SPY

// enable preemptive QK kernel
#define QK_PREEMPTIVE

// The maximum number of active objects in the application (could be up to 63)
#define QF_MAX_ACTIVE      16

#endif                                                   // qp_config_h

After you modify qp_config.h, you can recompile the qp_dpp program and load it to your mbed board. This time, when you run the code, you will see no intensity of LED4, which means that far fewer CPU cycles are wasted in the idle loop. (Actually, LED4 still blinks, but only 100 times per second instead of millions times per second, as before).

Information

Power management of the mbed board is also discussed in the following articles:

Preemptive Multitasking Demonstration

Finally, the qp_dpp demonstrates the preemptive QK multitasking kernel on mbed. As any preemptive kernel, QK must be informed about entering and exiting every interrupt service routine (ISR), but QK perfectly accepts ISRs written in C, while most other kernels require writing ISRs (or at least ISR "wrappers") in assembly.

The one thing you should remember when writing ISRs is to call the macro QK_ISR_ENTRY() at the beginning of every ISR, and the macro QK_ISR_EXIT() at the end of every ISR. The following code snipped illustrates the use of these macro in the SysTick_Handler():

extern "C" void SysTick_Handler(void) {
    QK_ISR_ENTRY();                // inform the QK kernel of entering the ISR

#ifdef Q_SPY
    uint32_t volatile dummy = SysTick->CTRL; // clear the COUNTFLAG in SysTick
    l_tickTime += l_tickPeriod;              // account for the clock rollover
#endif

    QF::tick();                               // process all armed time events

    QK_ISR_EXIT();                  // inform the QK kernel of exiting the ISR
}

More Information

Of course, the simple DPP example barely scratches the surface of QP/QM capabilities. The active object model of computation with advanced hierarchical state machines underlying QP is very powerful and uniquely suitable for programming complex behavior, such as in robotics. For an example of an advanced QP application for mbed, please refer to the article "Design and implementation of software architecture behavioral-based robot control system using Active Object Computing Model"

The ultimate resource for QP/QM is the state-machine.com website, which provides the latest updates, resources, and support for QP.


5 comments on Building Applications with QP (qp_dpp Example):

07 Feb 2012

When I comment out the #define Q_SPY line of code I get this error when I try to compile:

  • cannot open source input file "qs_dummy.h": No such file or directory" in file "lib/qp/qp.h", Line: 2272, Col: 78

What does that mean? How can I fix it?

07 Feb 2012

Hi Tyler,

It appears that you are using an older version of the QP library. Please make sure that you update it. For example, if you download the QP library to ZIP file and look in the qp.h header file, you will not find "qs_dummy.h" at line 2272.

I've just verified again, that all example code compiles and runs with the line #define Q_SPY commented out in the file qp_config.h.

Miro

20 Apr 2012

Hi!

The download link to the QSPy does not seem to work. It links to sourceforge which says that "The "/QSPY" file could not be found or is not available. Please select another file."

Is the file available somewhere else?

- Axel

24 Apr 2012

Found it myself. It is available in the qTools package at

http://sourceforge.net/projects/qpc/files/

- Axel

Axel Kohonen wrote:

Hi!

The download link to the QSPy does not seem to work. It links to sourceforge which says that "The "/QSPY" file could not be found or is not available. Please select another file."

Is the file available somewhere else?

- Axel

26 Jan 2021

Hello, does this example works on new M4 boards, like stm32f4-discovery boards?

Please log in to post comments.