The ultra-simple Blinky example is the embedded systems' equivalent of the venerable "Hello World!" program, that is, the simplest possible working application that does "something". In the case of Blinky, this "something" is blinking an LED at the rate of 1Hz, where an LED turns on and remains on for 0.5 seconds, then turns off and remains off for 0.5 seconds.
The Blinky example demonstrates the following QP/C features:
The Blinky example is provided in many versions for various execution targets, including host computers and embedded boards. All of these Blinky versions contain essentially the same state machine code and differ only in the Board Support Package (BSP).
<qp> // QP/C or QP/C++ installation directory | +---examples // QP examples | | | +---posix-win32 // examples for the host (POSIX, Windows) | | +---blinky // Blinky for Windows, Linux, macOS <== TRY FIRST | | | +---arm-cm // examples for ARM Cortex-M embedded boards | | +---blinky_ek-tm4c123gxl // Blinky for EK-TM4C123GXL (Cortex-M4) | | +---blinky_nucleo-c031c6 // Blinky for STM32 NUCLEO-C031C6 (Cortex-M0+) | | +---blinky_nucleo-u545re // Blinky for STM32 NUCLEO-U545RE (Cortex-M33) | | | +---stm32cube // examples for STM32Cube IDE | | +---blinky_nucleo-u545re // Blinky for STM32 NUCLEO-U545RE (Cortex-M33) | | | +---arm-cr // examples for ARM Cortex-R embedded boards | | +---blinky_launchxl2-tms57012 // Blinky for LAUNCHXL2-TMS57012 (Cortex-R4) | | | +---msp430 // examples for MSP430 embedded boards | | +---blinky_msp-exp430g2 // Blinky for MSP-EXP430G2 (MSP430 classic) | | +---blinky_msp-exp430f5529lp // Blinky for MSP-EXP430f5529LP (MSP430 extended) | | | +---zephyr // examples for Zephyr RTOS | | +---blinky // Blinky for all Zephyr-supported boards
The Blinky example demonstrate multiple build configurations:
The Blinky example demonstrates the general structure of QP/C applications. Most of the code is identical for any deployment target. The only target-dependent part is the Board Support Package (BSP) implementation (the file bsp.c ). Here are the annotated files comprising the Blinky example:
blinky // Blinky example | blinky.qm // QM model file for the Blinky application | app.h // Application interface | bsp.h // Board Support Package interface | blinky.c // active object implementation | bsp.c // Board Support Package implementatin | main.c // main function | qp_config.h // QP/C configuration
The file main.c shows the steps to initialize and run the QP/C application. This main() function applies generally to all QP applications and is used in all examples.
The Blinky Active Object has a simple state machine depicted in the state diagram below. On the right, you can see the generated code for the state machine, with a very clear mapping of state machine elements to code. The mapping between the state machine elements and code is specified in the State Dynamics Viewpoint of the Software Design Specification.
Unlike the main() function and the state machine code, which are generic and can be written in a hardware-independent way, the BSP (Board Support Package) is hardware-specific. A minimal BSP for running Blinky in a console is presented below. For other targets, including embedded boards, the BSP needs to be implemented differently.
The Blinky example for the host computers (Windows, Linux, macOS) is located in the directory qpc/examples/posix-win32/blinky (see also Blinky Versions). To build the Blinky example on the host, you need the make utility and the GNU C/C++ compiler. (On Windows, these tools are provided in the QP-bundle, which you should install beforehand).
Deafault Debug build configuration:
cd \qp\qpc\examples\posix-win32\blinky make
This assumes that the qpc framework exists in the directory \qp\qpc. Please check your installation and adjust the location as necessary.
Release build configuration:
cd \qp\qpc\examples\posix-win32\blinky make CONF=rel
Spy build configuration (with QP/Spy software tracing enabled):
cd \qp\qpc\examples\posix-win32\blinky make CONF=spy
Deafault Debug build configuration:
cd ~/qp/qpc/examples/posix-win32/blinky make
This assumes that the qpc framework exists in the directory ~/qp/qpc. Please check your installation and adjust the location as necessary.
Release build configuration:
cd ~/qp/qpc/examples/posix-win32/blinky make CONF=rel
Spy build configuration (with QP/Spy software tracing enabled):
cd ~/qp/qpc/examples/posix-win32/blinky make CONF=spy
The previous build step should produce the executable in the build subdirectory inside the blinky project. Assuming that your current directory is the blinky project, you run the executable as follows:
On Windows:
build\blinky
On Linux or macOS:
build/blinky
And here is a typical output:
Simple Blinky example QP/C version: 8.1.2 Press Ctrl-C to quit... LED OFF LED ON LED OFF LED ON LED OFF ^C
The BSP (Board Support Package) implements the hardware-specific functions (e.g., turning the LED on and off in case of Blinky) as well as the QP customization callbacks. A minimal BSP for Blinky running in a console is shown below.
The Blinky examples for various embedded boards are located in the qpc/examples (see Blinky Versions). For embedded targets, you have many more choices than on the host. The choices include:
This section shows the Blinky version for one embedded board (NUCLEO-C031C6). Versions for other boards and kernels (including 3rd-party RTOSes) are organized similarly.
The following annotated directory structure explains the Blinky code for ARM Cortex-M, NUCLEO-C031C6 board (Blinky example for other boards have very similar structure):
qpc/examples/arm-cm/blinky_nucleo-c031c6 // Blinky for ARM Cortex-M, NUCLEO-C031C6
| app.h // Application interface
| bsp.h // BSP interface
| blinky.c // Blinky state machine
| main.c // main() function
| qp_config.h // QP/C configuration
|
+---qk // Preemptive, non-blocking QK kernel
| | bsp.c // BSP implementation for the QK kernel
| |
| +---armclang // ARM-CLANG toolchain (KEIL compiler 6)
| | blinky-qk.sct // linker script for KEIL linker
| | blinky-qk.uvoptx // KEIL uVision project
| | blinky-qk.uvprojx // KEIL uVision project
| |
| +---gnu // GNU-ARM toolchain
| | blinky-qk.ld // linker script for GNU-ARM
| | Makefile // Makefile to build from command-line
| |
| \---iar // IAR toolchain
| blinky-qk.ewd // IAR debugger configuration
| blinky-qk.ewp // IAR project
| blinky-qk.eww // IAR workspace
| blinky-qk.icf // linker script for IAR
|
+---qv // Non-prreemptive QV kernel
| | bsp.c // BSP implementation for the QV kernel
| |
| +---armclang // ARM-CLANG toolchain (KEIL compiler 6)
| | blinky-qk.sct // linker script for KEIL linker
| | blinky-qk.uvoptx // KEIL uVision project
| | blinky-qk.uvprojx // KEIL uVision project
| |
| +---gnu // GNU-ARM toolchain
| | blinky-qv.ld // linker script for GNU-ARM
| | Makefile // Makefile to build from command-line
| |
| \---iar // IAR toolchain
| blinky-qv.ewd // IAR debugger configuration
| blinky-qv.ewp // IAR project
| blinky-qv.eww // IAR workspace
| blinky-qv.icf // linker script for IAR
|
\---qxk // Preemptive, preemptive dual-mode QXK kernel
| bsp.c // BSP implementation for the QXK kernel
| xthr.c // extended-threads for QXK
|
+---armclang // ARM-CLANG toolchain (KEIL compiler 6)
| blinky-qxk.sct // linker script for KEIL linker
| blinky-qxk.uvoptx // KEIL uVision project
| blinky-qxk.uvprojx // KEIL uVision project
|
+---gnu // GNU-ARM toolchain
| blinky-qxk.ld // linker script for GNU-ARM
| Makefile // Makefile to build from command-line
|
\---iar // IAR toolchain
blinky-qxk.ewd // IAR debugger configuration
blinky-qxk.ewp // IAR project
blinky-qxk.eww // IAR workspace
blinky-qxk.icf // linker script for IAR
To build Blinky for the QK kernel and GNU-ARM, open a terminal and type:
cd qpc\examples\arm-cm\blinky_nucleo-c031c6\qk\gnu make C:\qp\qpc\examples\arm-cm\blinky_nucleo-c031c6\qk\gnu>make C:\qp\qtools/gnu_arm-none-eabi/bin/arm-none-eabi-gcc -c -g -mcpu=cortex-m0plus -mthumb -Wall -ffunction-sections -fdata-sections -O -I../.. -I../../../../../include -I../../../../../ports/arm-cm/qk/gnu -I../../../../../3rd_party/CMSIS/Include -I../../../../../3rd_party/nucleo-c031c6 -DSTM32C031xx ../bsp.c -o dbg/bsp.o . . . C:\qp\qtools/gnu_arm-none-eabi/bin/arm-none-eabi-gcc -Tblinky-qk.ld -mcpu=cortex-m0plus -mthumb -specs=nosys.specs -specs=nano.specs -Wl,-Map,dbg/blinky-qk.map,--cref,--gc-sections -o dbg/blinky-qk.elf dbg/bsp.o dbg/main.o dbg/blinky.o dbg/system_stm32c0xx.o dbg/startup_stm32c031xx.o dbg/qep_hsm.o dbg/qep_msm.o dbg/qf_act.o dbg/qf_actq.o dbg/qf_defer.o dbg/qf_dyn.o dbg/qf_mem.o dbg/qf_ps.o dbg/qf_qact.o dbg/qf_qeq.o dbg/qf_qmact.o dbg/qf_time.o dbg/qk.o dbg/qk_port.o dbg/syscalls.o dbg/qstamp.o C:\qp\qtools/gnu_arm-none-eabi/bin/arm-none-eabi-objcopy -O binary dbg/blinky-qk.elf dbg/blinky-qk.bin
To build Blinky for the QK kernel and ARM-CLANG (KEIL compiler 6), launch the KEIL uVision and load the project: qpc/examples/arm-cm/blinky_nucleo-c031c6/qk/armclang/blink-qk.uvprojx
To build Blinky for the QK kernel and IAR, launch the IAR IDE and load the project: qpc/examples/arm-cm/blinky_nucleo-c031c6/qk/iar/blinky-qk.eww