diff --git a/.gitignore b/.gitignore index 259148f..7603663 100644 --- a/.gitignore +++ b/.gitignore @@ -1,32 +1,55 @@ +# QM sessions +*.qms + # Prerequisites *.d -# Compiled Object files -*.slo -*.lo +# Object files *.o +*.ko *.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp # Precompiled Headers *.gch *.pch -# Compiled Dynamic libraries +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll *.so +*.so.* *.dylib -*.dll - -# Fortran module files -*.mod -*.smod - -# Compiled Static libraries -*.lai -*.la -*.a -*.lib # Executables *.exe *.out *.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf diff --git a/README.md b/README.md index cd52c79..5b49ce0 100644 --- a/README.md +++ b/README.md @@ -2,17 +2,17 @@ [![Quantum Leaps](https://www.state-machine.com/attachments/logo_ql_400.png)](https://www.state-machine.com)
-# About qpcpp-examples -This repository contains the application examples for the QP/C++ -Real-Time Embedded Framework (see https://github.com/QuantumLeaps/qpcpp ). +# About qpc-examples +This repository contains the application examples for the QP/C +Real-Time Embedded Framework (see https://github.com/QuantumLeaps/qpc ). This repository can be used in several ways: - [Standalone examples](#standalone-examples-in-the-cmsis-packs-folder) - that don't require the [qpcpp framework repo](https://github.com/QuantumLeaps/qpcpp). - (These examples rely on the qpcpp framework included from the + that don't require the [qpc framework repo](https://github.com/QuantumLeaps/qpc). + (These examples rely on the qpc framework included from the [CMIS-packs](https://github.com/QuantumLeaps/cmsis-packs)) -- [As a sub-module to the qpcpp repo](#as-a-sub-module-to-the-qpcpp-repository) +- [As a sub-module to the qpc repo](#as-a-sub-module-to-the-qpc-repository) - [Examples for the QView monitoring system](#examples-for-qview-monitoring-system) @@ -29,7 +29,7 @@ This repository can be used in several ways: | ``` -## As a sub-module to the qpcpp repository +## As a sub-module to the qpc repository ``` +---arm-cm | +---blinky_ek-tm4c123gxl @@ -106,6 +106,17 @@ This repository can be used in several ways: | +---reminder | \---reminder2 | ++---threadx +| \---arm-cm +| +---dpp_ek-tm4c123gxl +| \---dpp_stm32f429-discovery ++---uc-os2 +| \---arm-cm +| \---dpp_ek-tm4c123gxl ++---zephyr +| +---blinky +| \---dpp +| +---qutest <== examples for QUTest testing harness | +---blinky | +---dpp @@ -124,20 +135,12 @@ This repository can be used in several ways: | +---src | \---test | -+---threadx -| \---arm-cm -| +---dpp_ek-tm4c123gxl -| \---dpp_stm32f429-discovery -+---uc-os2 -| \---arm-cm -| \---dpp_ek-tm4c123gxl -+---zephyr -| +---blinky -| \---dpp -| -+---qview-dpp <== examples for the QView monitoring system ++---qview-dpp <== examples for QView monitoring (DPP example) | +---img | dpp.py +| dpp1.py +| qview-dpp.lnk +| qview-dpp.lnk | +---qwin-gui <== examples for the QWin GUI | +---dpp-gui @@ -145,6 +148,22 @@ This repository can be used in several ways: | ``` +## Examples for QTest Testing System +The "qutest" Python package (included in the +[QTools collection](https://github.com/QuantumLeaps/qtools)) +is a powerful [testing system](https://www.state-machine.com/qtools/qutest.html). +It has been specifically designed for deeply embedded systems, but also supports +unit and integration testing of embedded code on host computers ("dual targeting"). +QUTest is the fundamental tooling for Test-Driven Development (TDD) and Behavior- +Driven Development (BDD) of QP/C/C++ applications , which is a highly recommended +best-practice. + +The following screen shot show a typical QUTest run with the QSPY ouptut +in the background. + +![](qutest/img/qutest-dpp.webp) + + ## Examples for QView Monitoring System The "qview" Python package (included in the [QTools collection](https://github.com/QuantumLeaps/qtools)) @@ -174,18 +193,3 @@ application with the QSPY ouptut in the background. ![](qview-dpp/img/qview-dpp.webp) - -## Examples for QTest Testing System -The "qutest" Python package (included in the -[QTools collection](https://github.com/QuantumLeaps/qtools)) -is a powerful [testing system](https://www.state-machine.com/qtools/qutest.html). -It has been specifically designed for deeply embedded systems, but also supports -unit and integration testing of embedded code on host computers ("dual targeting"). -QUTest is the fundamental tooling for Test-Driven Development (TDD) and Behavior- -Driven Development (BDD) of QP/C/C++ applications , which is a highly recommended -best-practice. - -The following screen shot show a typical QUTest run with the QSPY ouptut -in the background. - -![](qutest/img/qutest-dpp.webp) diff --git a/arm-cm/blinky_ek-tm4c123gxl/README.md b/arm-cm/blinky_ek-tm4c123gxl/README.md index b8dd279..9f4b2a2 100644 --- a/arm-cm/blinky_ek-tm4c123gxl/README.md +++ b/arm-cm/blinky_ek-tm4c123gxl/README.md @@ -2,11 +2,11 @@ This file is best viewed in a **markdown viewer**, such as the one built into GitHub. Markdown viewers are also available as plug-ins to popular Internet browsers. # Blinky on EK-TM4C123GXL -This example implements the simple [Blinky application](https://www.state-machine.com/qpcpp/tut_blinky.html) on the EK-TM4C123GLX board (ARM Cortex-M4F). The example blinks the LED +This example implements the simple [Blinky application](https://www.state-machine.com/qpc/tut_blinky.html) on the EK-TM4C123GLX board (ARM Cortex-M4F). The example blinks the LED on the EK-TM4C123GXL board at 1Hz (0.5 seconds on, 0.5 seconds off).

-
+
EK-TM4C123GXL (TivaC LaunchPad)

diff --git a/arm-cm/blinky_ek-tm4c123gxl/ek-tm4c123gxl.jpg b/arm-cm/blinky_ek-tm4c123gxl/ek-tm4c123gxl.jpg deleted file mode 100644 index 5ed6188..0000000 Binary files a/arm-cm/blinky_ek-tm4c123gxl/ek-tm4c123gxl.jpg and /dev/null differ diff --git a/arm-cm/blinky_ek-tm4c123gxl/ek-tm4c123gxl.webp b/arm-cm/blinky_ek-tm4c123gxl/ek-tm4c123gxl.webp new file mode 100644 index 0000000..320870b Binary files /dev/null and b/arm-cm/blinky_ek-tm4c123gxl/ek-tm4c123gxl.webp differ diff --git a/arm-cm/blinky_nucleo-c031c6/README.md b/arm-cm/blinky_nucleo-c031c6/README.md index ba38367..72a3c0f 100644 --- a/arm-cm/blinky_nucleo-c031c6/README.md +++ b/arm-cm/blinky_nucleo-c031c6/README.md @@ -2,10 +2,10 @@ This file is best viewed in a **markdown viewer**, such as the one built into GitHub. Markdown viewers are also available as plug-ins to popular Internet browsers. # Blinky on NUCLEO-C031C6 -This example demonstrates the [Blinky application](https://www.state-machine.com/qpcpp/tut_blinky.html) on the STM32 NUCLEO-C031C6 board (ARM Cortex-M0+). +This example demonstrates the [Blinky application](https://www.state-machine.com/qpc/tut_blinky.html) on the STM32 NUCLEO-C031C6 board (ARM Cortex-M0+).

-
+
STM32 NUCLEO-C031C6

diff --git a/arm-cm/blinky_nucleo-c031c6/stm32-nucleo-c031c6.jpg b/arm-cm/blinky_nucleo-c031c6/stm32-nucleo-c031c6.jpg deleted file mode 100644 index 6647e2d..0000000 Binary files a/arm-cm/blinky_nucleo-c031c6/stm32-nucleo-c031c6.jpg and /dev/null differ diff --git a/arm-cm/blinky_nucleo-c031c6/stm32-nucleo-c031c6.webp b/arm-cm/blinky_nucleo-c031c6/stm32-nucleo-c031c6.webp new file mode 100644 index 0000000..7671b37 Binary files /dev/null and b/arm-cm/blinky_nucleo-c031c6/stm32-nucleo-c031c6.webp differ diff --git a/arm-cm/dpp_efm32-slstk3401a/README.md b/arm-cm/dpp_efm32-slstk3401a/README.md index 2810293..bc708dc 100644 --- a/arm-cm/dpp_efm32-slstk3401a/README.md +++ b/arm-cm/dpp_efm32-slstk3401a/README.md @@ -1,5 +1,131 @@ -![STM32 EFM32-SLSTK3401A](../../../doxygen/images/bd_EFM32-SLSTK3401A.jpg) +> **NOTE** +This file is best viewed in a **markdown viewer**, such as the one built into GitHub. Markdown viewers are also available as plug-ins to popular Internet browsers. -Documentation for this example is available in the QP/C Manual at: +# DPP on EFM32-SLSTK3401A +This example demonstrates the [Dining Philosophers Problem (DPP) application](https://www.state-machine.com/qpc/tut_dpp.html) on the EFM32-SLSTK3401A board (ARM Cortex-M4F). + +

+
+EFM32-SLSTK3401A (Pearl Gecko) +

+ +## Features Demonstrated +- multiple cooperating active objects +- immutable (const) events +- mutable (dynamic) events +- time events +- direct event posting +- publish-subscribe event delivery +- cooperative QV kernel + + with ARM-KEIL toolchain + + with GNU-ARM toolchain + + with IAR-ARM toolchain +- preemptive run-to-completion QK kernel + + with ARM-KEIL toolchain + + with GNU-ARM toolchain + + with IAR-ARM toolchain +- preemptive dual-mode QXK kernel + + with ARM-KEIL toolchain + + with GNU-ARM toolchain + + with IAR-ARM toolchain + +## Build Configurations +- Debug +- Release +- Spy - software tracing with the built-in virtual COM port + +# Code Organization +``` +examples\arm-cm\dpp_efm32-slstk3401a +| ++---qk // preemptive QK kernel +| +---gnu // GNU-ARM toolchain +| | \---targetConfigs +| | Makefile // Makefile for GNU-ARM +| +---armclang // ARM/KEIL toolchain with Compiler 6 (ARM/CLANG) +| | dpp-qk.uvprojx // uVision project +| \---iar // IAR EWARM +| dpp-qk.eww // IAR EW-ARM workspace +| +\---qv // cooperative QK kernel +| +---gnu // GNU-ARM toolchain +| | \---targetConfigs +| | Makefile // Makefile for GNU-ARM +| +---armclang // ARM/KEIL toolchain with Compiler 6 (ARM/CLANG) +| | dpp-qv.uvprojx // uVision project +| \---iar // IAR EWARM +| dpp-qv.eww // IAR EW-ARM workspace +| ++---qxk // preemptive, dual-mode QXK kernel +| +---gnu // GNU-ARM toolchain +| | \---targetConfigs +| | Makefile // Makefile for GNU-ARM +| +---armclang // ARM/KEIL toolchain with Compiler 6 (ARM/CLANG) +| | dpp-qk.uvprojx // uVision project +| \---iar // IAR EWARM +| dpp-qk.eww // IAR EW-ARM workspace +| +``` + +# Building the example + +### GNU/ARM +- open terminal window +- change to the desired directory (either `examples\arm-cm\dpp_efm32-slstk3401a\qk\gnu`, `examples\arm-cm\dpp_efm32-slstk3401a\qv\gnu`, or `examples\arm-cm\dpp_efm32-slstk3401a\qxk\gnu`) +- to build the default Debug configuration, type: + +``` +make +``` + +> **NOTE** +The `make` utility for Windows is provided in the QTools collection for Windows. + +- to build the Release configuration, type: + +``` +make CONF=rel +``` + +- to build the Spy configuration, type: + +``` +make CONF=spy +``` + + +### ARM/KEIL MDK +- Open the provided KEIL uVision project (either `dpp-qk.uvprojx`, `dpp-qv.uvprojx`, or `dpp-qxk.uvprojx`) +in Keil uVision IDE. Build/Debug/Download to the board from the IDE. +- Change the build configuration in the "Project Target" drop-down menu. + + +### IAR EWARM +- Open the provided IAR EWARM workspace (either `dpp-qk.eww`, `dpp-qv.eww`, or `dpp-qxk.eww`) +in IAR EWARM IDE. Build/Debug/Download to the board from the IDE. +- Change the build configuration in the "Project Configuration" drop-down menu. + + +# Tracing with QP/Spy +When the board is flashed with the Spy build configuration, it produces the QP/Spy software tracing output to the built-in virtual COM port of the TivaC LauchPad board. The trace is binary rather than ASCII, and therefore requires a special host-based application called QSPY. + +> **NOTE** QSPY host application is available in the QTools collection. + +To launch the QSPY host application: +- open terminal window +- type: + +``` +qspy -c COM5 +``` + +where "COM5" is an example virtual COM port enumerated by the board. You need to check the specific COM port number on your host computer using the Device Manager application, Ports (COM and LPT) section. + + +The following screen shot shows a typical output from QSPY: + +

+
+Typical QSPY output produced by the Spy build configuration +

-- https://www.state-machine.com/qpcpp/arm-cm_dpp_efm32-slstk3401a.html diff --git a/arm-cm/dpp_efm32-slstk3401a/efm32-slstk3401a.webp b/arm-cm/dpp_efm32-slstk3401a/efm32-slstk3401a.webp new file mode 100644 index 0000000..0292490 Binary files /dev/null and b/arm-cm/dpp_efm32-slstk3401a/efm32-slstk3401a.webp differ diff --git a/arm-cm/dpp_efm32-slstk3401a/qspy-output.png b/arm-cm/dpp_efm32-slstk3401a/qspy-output.png new file mode 100644 index 0000000..ee76445 Binary files /dev/null and b/arm-cm/dpp_efm32-slstk3401a/qspy-output.png differ diff --git a/arm-cm/dpp_ek-tm4c123gxl/README.md b/arm-cm/dpp_ek-tm4c123gxl/README.md index 30842ba..663bcd4 100644 --- a/arm-cm/dpp_ek-tm4c123gxl/README.md +++ b/arm-cm/dpp_ek-tm4c123gxl/README.md @@ -1,5 +1,131 @@ -![STM32 EFM32-SLSTK3401A](../../../doxygen/images/bd_EK-TM4C123GXL.jpg) +> **NOTE** +This file is best viewed in a **markdown viewer**, such as the one built into GitHub. Markdown viewers are also available as plug-ins to popular Internet browsers. -Documentation for this example is available in the QP/C Manual at: +# DPP on EK-TM4C123GXL +This example demonstrates the [Dining Philosophers Problem (DPP) application](https://www.state-machine.com/qpc/tut_dpp.html) on the EK-TM4C123GLX board (ARM Cortex-M4F). + +

+
+EK-TM4C123GXL (TivaC LaunchPad) +

+ +## Features Demonstrated +- multiple cooperating active objects +- immutable (const) events +- mutable (dynamic) events +- time events +- direct event posting +- publish-subscribe event delivery +- cooperative QV kernel + + with ARM-KEIL toolchain + + with GNU-ARM toolchain + + with IAR-ARM toolchain +- preemptive run-to-completion QK kernel + + with ARM-KEIL toolchain + + with GNU-ARM toolchain + + with IAR-ARM toolchain +- preemptive dual-mode QXK kernel + + with ARM-KEIL toolchain + + with GNU-ARM toolchain + + with IAR-ARM toolchain + +## Build Configurations +- Debug +- Release +- Spy - software tracing with the built-in virtual COM port + +# Code Organization +``` +examples\arm-cm\dpp_ek-tm4c123gxl +| ++---qk // preemptive QK kernel +| +---gnu // GNU-ARM toolchain +| | \---targetConfigs +| | Makefile // Makefile for GNU-ARM +| +---armclang // ARM/KEIL toolchain with Compiler 6 (ARM/CLANG) +| | dpp-qk.uvprojx // uVision project +| \---iar // IAR EWARM +| dpp-qk.eww // IAR EW-ARM workspace +| +\---qv // cooperative QK kernel +| +---gnu // GNU-ARM toolchain +| | \---targetConfigs +| | Makefile // Makefile for GNU-ARM +| +---armclang // ARM/KEIL toolchain with Compiler 6 (ARM/CLANG) +| | dpp-qv.uvprojx // uVision project +| \---iar // IAR EWARM +| dpp-qv.eww // IAR EW-ARM workspace +| ++---qxk // preemptive, dual-mode QXK kernel +| +---gnu // GNU-ARM toolchain +| | \---targetConfigs +| | Makefile // Makefile for GNU-ARM +| +---armclang // ARM/KEIL toolchain with Compiler 6 (ARM/CLANG) +| | dpp-qk.uvprojx // uVision project +| \---iar // IAR EWARM +| dpp-qk.eww // IAR EW-ARM workspace +| +``` + +# Building the example + +### GNU/ARM +- open terminal window +- change to the desired directory (either `examples\arm-cm\dpp_ek-tm4c123gxl\qk\gnu`, `examples\arm-cm\dpp_ek-tm4c123gxl\qv\gnu`, or `examples\arm-cm\dpp_ek-tm4c123gxl\qxk\gnu`) +- to build the default Debug configuration, type: + +``` +make +``` + +> **NOTE** +The `make` utility for Windows is provided in the QTools collection for Windows. + +- to build the Release configuration, type: + +``` +make CONF=rel +``` + +- to build the Spy configuration, type: + +``` +make CONF=spy +``` + + +### ARM/KEIL MDK +- Open the provided KEIL uVision project (either `dpp-qk.uvprojx`, `dpp-qv.uvprojx`, or `dpp-qxk.uvprojx`) +in Keil uVision IDE. Build/Debug/Download to the board from the IDE. +- Change the build configuration in the "Project Target" drop-down menu. + + +### IAR EWARM +- Open the provided IAR EWARM workspace (either `dpp-qk.eww`, `dpp-qv.eww`, or `dpp-qxk.eww`) +in IAR EWARM IDE. Build/Debug/Download to the board from the IDE. +- Change the build configuration in the "Project Configuration" drop-down menu. + + +# Tracing with QP/Spy +When the board is flashed with the Spy build configuration, it produces the QP/Spy software tracing output to the built-in virtual COM port of the TivaC LauchPad board. The trace is binary rather than ASCII, and therefore requires a special host-based application called QSPY. + +> **NOTE** QSPY host application is available in the QTools collection. + +To launch the QSPY host application: +- open terminal window +- type: + +``` +qspy -c COM5 +``` + +where "COM5" is an example virtual COM port enumerated by the board. You need to check the specific COM port number on your host computer using the Device Manager application, Ports (COM and LPT) section. + + +The following screen shot shows a typical output from QSPY: + +

+
+Typical QSPY output produced by the Spy build configuration +

-- https://www.state-machine.com/qpcpp/arm-cm_dpp_ek-tm4c123gxl.html diff --git a/arm-cm/dpp_ek-tm4c123gxl/ek-tm4c123gxl.webp b/arm-cm/dpp_ek-tm4c123gxl/ek-tm4c123gxl.webp new file mode 100644 index 0000000..320870b Binary files /dev/null and b/arm-cm/dpp_ek-tm4c123gxl/ek-tm4c123gxl.webp differ diff --git a/arm-cm/dpp_ek-tm4c123gxl/qspy-output.png b/arm-cm/dpp_ek-tm4c123gxl/qspy-output.png new file mode 100644 index 0000000..ee76445 Binary files /dev/null and b/arm-cm/dpp_ek-tm4c123gxl/qspy-output.png differ diff --git a/arm-cm/dpp_nucleo-c031c6/README.md b/arm-cm/dpp_nucleo-c031c6/README.md index 9f5e47a..b090412 100644 --- a/arm-cm/dpp_nucleo-c031c6/README.md +++ b/arm-cm/dpp_nucleo-c031c6/README.md @@ -5,7 +5,7 @@ This file is best viewed in a **markdown viewer**, such as the one built into Gi This example demonstrates the [Dining Philosophers Problem (DPP) application](https://www.state-machine.com/qpc/tut_dpp.html) on the STM32 NUCLEO-C031C6 board (ARM Cortex-M0+).

-
+
STM32 NUCLEO-C031C6

diff --git a/arm-cm/dpp_nucleo-c031c6/stm32-nucleo-c031c6.jpg b/arm-cm/dpp_nucleo-c031c6/stm32-nucleo-c031c6.jpg deleted file mode 100644 index 6647e2d..0000000 Binary files a/arm-cm/dpp_nucleo-c031c6/stm32-nucleo-c031c6.jpg and /dev/null differ diff --git a/arm-cm/dpp_nucleo-c031c6/stm32-nucleo-c031c6.webp b/arm-cm/dpp_nucleo-c031c6/stm32-nucleo-c031c6.webp new file mode 100644 index 0000000..7671b37 Binary files /dev/null and b/arm-cm/dpp_nucleo-c031c6/stm32-nucleo-c031c6.webp differ diff --git a/arm-cm/dpp_nucleo-h743zi/README.md b/arm-cm/dpp_nucleo-h743zi/README.md index d710070..a15adac 100644 --- a/arm-cm/dpp_nucleo-h743zi/README.md +++ b/arm-cm/dpp_nucleo-h743zi/README.md @@ -1,5 +1,149 @@ -![STM32 NUCLEO-H743ZI Q](../../../doxygen/images/bd_NUCLEO-H743ZI.jpg) +> **NOTE** +This file is best viewed in a **markdown viewer**, such as the one built into GitHub. Markdown viewers are also available as plug-ins to popular Internet browsers. -Documentation for this example is available in the QP/C Manual at: +# DPP on NUCLEO-H743ZI +This example demonstrates the [Dining Philosophers Problem (DPP) application](https://www.state-machine.com/qpc/tut_dpp.html) on the STM32 NUCLEO-H743ZI board (ARM Cortex-M7 with double-precision FPU). + +

+
+STM32 NUCLEO-H743ZI +

+ +> **NOTE** +This example can be used as a starting point for any other ARM Cortex-M MCU, including those based on different Cortex-M cores (M0/M0+/M3/M4/M7/M23/M33/M55/M85...) The most simplifying factor is that the QP-ports to Cortex-M don't need to change at all (the correct port is selected automatically based on the standard preprocessor macros provided by the compiler). + +

+ +

+ +## Features Demonstrated +- multiple cooperating active objects +- immutable (const) events +- mutable (dynamic) events +- time events +- direct event posting +- publish-subscribe event delivery +- cooperative QV kernel + + with ARM-KEIL toolchain + + with GNU-ARM toolchain + + with IAR-ARM toolchain +- preemptive run-to-completion QK kernel + + with ARM-KEIL toolchain + + with GNU-ARM toolchain + + with IAR-ARM toolchain +- preemptive dual-mode QXK kernel + + with ARM-KEIL toolchain + + with GNU-ARM toolchain + + with IAR-ARM toolchain + +## Build Configurations +- Debug +- Release +- Spy - software tracing with the built-in virtual COM port + +# Code Organization +``` +examples\arm-cm\dpp_nucleo-h743zi +| ++---qk // preemptive QK kernel +| +---gnu // GNU-ARM toolchain +| | \---targetConfigs +| | Makefile // Makefile for GNU-ARM +| +---armclang // ARM/KEIL toolchain with Compiler 6 (ARM/CLANG) +| | dpp-qk.uvprojx // uVision project +| \---iar // IAR EWARM +| dpp-qk.eww // IAR EW-ARM workspace +| +\---qv // cooperative QK kernel +| +---gnu // GNU-ARM toolchain +| | \---targetConfigs +| | Makefile // Makefile for GNU-ARM +| +---armclang // ARM/KEIL toolchain with Compiler 6 (ARM/CLANG) +| | dpp-qv.uvprojx // uVision project +| \---iar // IAR EWARM +| dpp-qv.eww // IAR EW-ARM workspace +| ++---qxk // preemptive, dual-mode QXK kernel +| +---gnu // GNU-ARM toolchain +| | \---targetConfigs +| | Makefile // Makefile for GNU-ARM +| +---armclang // ARM/KEIL toolchain with Compiler 6 (ARM/CLANG) +| | dpp-qxk.uvprojx // uVision project +| \---iar // IAR EWARM +| dpp-qxk.eww // IAR EW-ARM workspace +| +``` + +# Building the example + +### GNU/ARM +- open terminal window +- change to the desired directory (either `examples\arm-cm\dpp_nucleo-h743zi\qk\gnu`, `examples\arm-cm\dpp_nucleo-h743zi\qv\gnu`, or `examples\arm-cm\dpp_nucleo-h743zi\qxk\gnu`) +- to build the default Debug configuration, type: + +``` +make +``` + +> **NOTE** +The `make` utility for Windows is provided in the QTools collection for Windows. + +- to build the Release configuration, type: + +``` +make CONF=rel +``` + +- to build the Spy configuration, type: + +``` +make CONF=spy +``` + + +### ARM/KEIL MDK +- Open the provided KEIL uVision project (either `dpp-qk.uvprojx`, `dpp-qv.uvprojx`, or `dpp-qxk.uvprojx`) +in Keil uVision IDE. Build/Debug/Download to the board from the IDE. +- Change the build configuration in the "Project Target" drop-down menu. + + +### IAR EWARM +- Open the provided IAR EWARM workspace (either `dpp-qk.eww`, `dpp-qv.eww`, or `dpp-qxk.eww`) +in IAR EWARM IDE. Build/Debug/Download to the board from the IDE. +- Change the build configuration in the "Project Configuration" drop-down menu. + + +# Uploading the Binary to the Board +The STM32 NUCLEO boards enumerate as a USB drive when connected to the host computer. The boards then can be programmed by **copying** the binary to that USB drive. This can be useful for the command-line GNU/ARM build. For example, to program the binary produced for the Debug configuration, you can type: + +``` +copy dbg\dpp-qk.bin E: +``` +NOTE: The above command assumes that the NUCLEO board enumerated as drive E:. Of course you need to adjust the command for your specific drive letter. + +Alternatively, if you use IDEs, such as KEIL-MDK or IAR EWARM, you can program the board from the IDE (e.g., by starting a debug session). + + +# Tracing with QP/Spy +When the board is flashed with the Spy build configuration, it produces the QP/Spy software tracing output to the built-in virtual COM port of the TivaC LauchPad board. The trace is binary rather than ASCII, and therefore requires a special host-based application called QSPY. + +> **NOTE** QSPY host application is available in the QTools collection. + +To launch the QSPY host application: +- open terminal window +- type: + +``` +qspy -c COM5 +``` + +where "COM5" is an example virtual COM port enumerated by the board. You need to check the specific COM port number on your host computer using the Device Manager application, Ports (COM and LPT) section. + + +The following screen shot shows a typical output from QSPY: + +

+
+Typical QSPY output produced by the Spy build configuration +

-- https://www.state-machine.com/qpcpp/arm-cm_dpp_nucleo-h743zi.html diff --git a/arm-cm/dpp_nucleo-h743zi/qk/gnu/Makefile b/arm-cm/dpp_nucleo-h743zi/qk/gnu/Makefile index 7512310..ffb441b 100644 --- a/arm-cm/dpp_nucleo-h743zi/qk/gnu/Makefile +++ b/arm-cm/dpp_nucleo-h743zi/qk/gnu/Makefile @@ -73,7 +73,7 @@ VPATH = \ $(QPCPP)/src/qs \ $(QP_PORT_DIR) \ $(QPCPP)/3rd_party/STM32CubeH7/nucleo-h743zi/gnu \ - $(QPCPP)/3rd_party/STM32CubeH7/Drivers/BSP\STM32H7xx_Nucleo_144 \ + $(QPCPP)/3rd_party/STM32CubeH7/Drivers/BSP/STM32H7xx_Nucleo_144 \ $(QPCPP)/3rd_party/STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src \ $(QPCPP)/3rd_party/STM32CubeH7/Drivers/CMSIS/Device/ST/STM32H7xx/Source/Templates diff --git a/arm-cm/dpp_nucleo-h743zi/qspy-output.png b/arm-cm/dpp_nucleo-h743zi/qspy-output.png new file mode 100644 index 0000000..ee76445 Binary files /dev/null and b/arm-cm/dpp_nucleo-h743zi/qspy-output.png differ diff --git a/arm-cm/dpp_nucleo-h743zi/qv/gnu/Makefile b/arm-cm/dpp_nucleo-h743zi/qv/gnu/Makefile index db8f982..5fbdf72 100644 --- a/arm-cm/dpp_nucleo-h743zi/qv/gnu/Makefile +++ b/arm-cm/dpp_nucleo-h743zi/qv/gnu/Makefile @@ -74,7 +74,7 @@ VPATH = \ $(QPCPP)/src/qs \ $(QP_PORT_DIR) \ $(QPCPP)/3rd_party/STM32CubeH7/nucleo-h743zi/gnu \ - $(QPCPP)/3rd_party/STM32CubeH7/Drivers/BSP\STM32H7xx_Nucleo_144 \ + $(QPCPP)/3rd_party/STM32CubeH7/Drivers/BSP/STM32H7xx_Nucleo_144 \ $(QPCPP)/3rd_party/STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src \ $(QPCPP)/3rd_party/STM32CubeH7/Drivers/CMSIS/Device/ST/STM32H7xx/Source/Templates diff --git a/arm-cm/dpp_nucleo-h743zi/qxk/gnu/Makefile b/arm-cm/dpp_nucleo-h743zi/qxk/gnu/Makefile index 81ae52c..7013053 100644 --- a/arm-cm/dpp_nucleo-h743zi/qxk/gnu/Makefile +++ b/arm-cm/dpp_nucleo-h743zi/qxk/gnu/Makefile @@ -73,7 +73,7 @@ VPATH = \ $(QPCPP)/src/qs \ $(QP_PORT_DIR) \ $(QPCPP)/3rd_party/STM32CubeH7/nucleo-h743zi/gnu \ - $(QPCPP)/3rd_party/STM32CubeH7/Drivers/BSP\STM32H7xx_Nucleo_144 \ + $(QPCPP)/3rd_party/STM32CubeH7/Drivers/BSP/STM32H7xx_Nucleo_144 \ $(QPCPP)/3rd_party/STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src \ $(QPCPP)/3rd_party/STM32CubeH7/Drivers/CMSIS/Device/ST/STM32H7xx/Source/Templates diff --git a/arm-cm/dpp_nucleo-h743zi/stm32-nucleo-h743zi.webp b/arm-cm/dpp_nucleo-h743zi/stm32-nucleo-h743zi.webp new file mode 100644 index 0000000..594e7f7 Binary files /dev/null and b/arm-cm/dpp_nucleo-h743zi/stm32-nucleo-h743zi.webp differ diff --git a/arm-cm/dpp_nucleo-l053r8/README.md b/arm-cm/dpp_nucleo-l053r8/README.md index 538e556..bf96c14 100644 --- a/arm-cm/dpp_nucleo-l053r8/README.md +++ b/arm-cm/dpp_nucleo-l053r8/README.md @@ -1,5 +1,149 @@ -![STM32 EFM32-SLSTK3401A](../../../doxygen/images/bd_NUCLEO-L053R8.jpg) +> **NOTE** +This file is best viewed in a **markdown viewer**, such as the one built into GitHub. Markdown viewers are also available as plug-ins to popular Internet browsers. -Documentation for this example is available in the QP/C Manual at: +# DPP on NUCLEO-L053R8 +This example demonstrates the [Dining Philosophers Problem (DPP) application](https://www.state-machine.com/qpc/tut_dpp.html) on the STM32 NUCLEO-L053R8 board (ARM Cortex-M0+). + +

+
+STM32 NUCLEO-L053R8 +

+ +> **NOTE** +This example can be used as a starting point for any other ARM Cortex-M MCU, including those based on different Cortex-M cores (M0/M0+/M3/M4/M7/M23/M33/M55/M85...) The most simplifying factor is that the QP-ports to Cortex-M don't need to change at all (the correct port is selected automatically based on the standard preprocessor macros provided by the compiler). + +

+ +

+ +## Features Demonstrated +- multiple cooperating active objects +- immutable (const) events +- mutable (dynamic) events +- time events +- direct event posting +- publish-subscribe event delivery +- cooperative QV kernel + + with ARM-KEIL toolchain + + with GNU-ARM toolchain + + with IAR-ARM toolchain +- preemptive run-to-completion QK kernel + + with ARM-KEIL toolchain + + with GNU-ARM toolchain + + with IAR-ARM toolchain +- preemptive dual-mode QXK kernel + + with ARM-KEIL toolchain + + with GNU-ARM toolchain + + with IAR-ARM toolchain + +## Build Configurations +- Debug +- Release +- Spy - software tracing with the built-in virtual COM port + +# Code Organization +``` +examples\arm-cm\dpp_nucleo-l053r8 +| ++---qk // preemptive QK kernel +| +---gnu // GNU-ARM toolchain +| | \---targetConfigs +| | Makefile // Makefile for GNU-ARM +| +---armclang // ARM/KEIL toolchain with Compiler 6 (ARM/CLANG) +| | dpp-qk.uvprojx // uVision project +| \---iar // IAR EWARM +| dpp-qk.eww // IAR EW-ARM workspace +| +\---qv // cooperative QK kernel +| +---gnu // GNU-ARM toolchain +| | \---targetConfigs +| | Makefile // Makefile for GNU-ARM +| +---armclang // ARM/KEIL toolchain with Compiler 6 (ARM/CLANG) +| | dpp-qv.uvprojx // uVision project +| \---iar // IAR EWARM +| dpp-qv.eww // IAR EW-ARM workspace +| ++---qxk // preemptive, dual-mode QXK kernel +| +---gnu // GNU-ARM toolchain +| | \---targetConfigs +| | Makefile // Makefile for GNU-ARM +| +---armclang // ARM/KEIL toolchain with Compiler 6 (ARM/CLANG) +| | dpp-qxk.uvprojx // uVision project +| \---iar // IAR EWARM +| dpp-qxk.eww // IAR EW-ARM workspace +| +``` + +# Building the example + +### GNU/ARM +- open terminal window +- change to the desired directory (either `examples\arm-cm\dpp_nucleo-l053r8\qk\gnu`, `examples\arm-cm\dpp_nucleo-l053r8\qv\gnu`, or `examples\arm-cm\dpp_nucleo-l053r8\qxk\gnu`) +- to build the default Debug configuration, type: + +``` +make +``` + +> **NOTE** +The `make` utility for Windows is provided in the QTools collection for Windows. + +- to build the Release configuration, type: + +``` +make CONF=rel +``` + +- to build the Spy configuration, type: + +``` +make CONF=spy +``` + + +### ARM/KEIL MDK +- Open the provided KEIL uVision project (either `dpp-qk.uvprojx`, `dpp-qv.uvprojx`, or `dpp-qxk.uvprojx`) +in Keil uVision IDE. Build/Debug/Download to the board from the IDE. +- Change the build configuration in the "Project Target" drop-down menu. + + +### IAR EWARM +- Open the provided IAR EWARM workspace (either `dpp-qk.eww`, `dpp-qv.eww`, or `dpp-qxk.eww`) +in IAR EWARM IDE. Build/Debug/Download to the board from the IDE. +- Change the build configuration in the "Project Configuration" drop-down menu. + + +# Uploading the Binary to the Board +The STM32 NUCLEO boards enumerate as a USB drive when connected to the host computer. The boards then can be programmed by **copying** the binary to that USB drive. This can be useful for the command-line GNU/ARM build. For example, to program the binary produced for the Debug configuration, you can type: + +``` +copy dbg\dpp-qk.bin E: +``` +NOTE: The above command assumes that the NUCLEO board enumerated as drive E:. Of course you need to adjust the command for your specific drive letter. + +Alternatively, if you use IDEs, such as KEIL-MDK or IAR EWARM, you can program the board from the IDE (e.g., by starting a debug session). + + +# Tracing with QP/Spy +When the board is flashed with the Spy build configuration, it produces the QP/Spy software tracing output to the built-in virtual COM port of the TivaC LauchPad board. The trace is binary rather than ASCII, and therefore requires a special host-based application called QSPY. + +> **NOTE** QSPY host application is available in the QTools collection. + +To launch the QSPY host application: +- open terminal window +- type: + +``` +qspy -c COM5 +``` + +where "COM5" is an example virtual COM port enumerated by the board. You need to check the specific COM port number on your host computer using the Device Manager application, Ports (COM and LPT) section. + + +The following screen shot shows a typical output from QSPY: + +

+
+Typical QSPY output produced by the Spy build configuration +

-- https://www.state-machine.com/qpcpp/arm-cm_dpp_nucleo-l053r8.html diff --git a/arm-cm/dpp_nucleo-l053r8/qspy-output.png b/arm-cm/dpp_nucleo-l053r8/qspy-output.png new file mode 100644 index 0000000..ee76445 Binary files /dev/null and b/arm-cm/dpp_nucleo-l053r8/qspy-output.png differ diff --git a/arm-cm/dpp_nucleo-l053r8/stm32-nucleo-l053r8.webp b/arm-cm/dpp_nucleo-l053r8/stm32-nucleo-l053r8.webp new file mode 100644 index 0000000..8ec1391 Binary files /dev/null and b/arm-cm/dpp_nucleo-l053r8/stm32-nucleo-l053r8.webp differ diff --git a/arm-cm/dpp_nucleo-l552ze/README.md b/arm-cm/dpp_nucleo-l552ze/README.md index b1b9c9f..30500b9 100644 --- a/arm-cm/dpp_nucleo-l552ze/README.md +++ b/arm-cm/dpp_nucleo-l552ze/README.md @@ -1,5 +1,149 @@ -![STM32 NUCLEO-L552ZE Q](../../../doxygen/images/bd_NUCLEO-L552ZE.jpg) +> **NOTE** +This file is best viewed in a **markdown viewer**, such as the one built into GitHub. Markdown viewers are also available as plug-ins to popular Internet browsers. -Documentation for this example is available in the QP/C Manual at: +# DPP on NUCLEO-L552ZE +This example demonstrates the [Dining Philosophers Problem (DPP) application](https://www.state-machine.com/qpc/tut_dpp.html) on the STM32 NUCLEO-L552ZE board (ARM Cortex-M33). + +

+
+STM32 NUCLEO-L552ZE +

+ +> **NOTE** +This example can be used as a starting point for any other ARM Cortex-M MCU, including those based on different Cortex-M cores (M0/M0+/M3/M4/M7/M23/M33/M55/M85...) The most simplifying factor is that the QP-ports to Cortex-M don't need to change at all (the correct port is selected automatically based on the standard preprocessor macros provided by the compiler). + +

+ +

+ +## Features Demonstrated +- multiple cooperating active objects +- immutable (const) events +- mutable (dynamic) events +- time events +- direct event posting +- publish-subscribe event delivery +- cooperative QV kernel + + with ARM-KEIL toolchain + + with GNU-ARM toolchain + + with IAR-ARM toolchain +- preemptive run-to-completion QK kernel + + with ARM-KEIL toolchain + + with GNU-ARM toolchain + + with IAR-ARM toolchain +- preemptive dual-mode QXK kernel + + with ARM-KEIL toolchain + + with GNU-ARM toolchain + + with IAR-ARM toolchain + +## Build Configurations +- Debug +- Release +- Spy - software tracing with the built-in virtual COM port + +# Code Organization +``` +examples\arm-cm\dpp_nucleo-l552ze +| ++---qk // preemptive QK kernel +| +---gnu // GNU-ARM toolchain +| | \---targetConfigs +| | Makefile // Makefile for GNU-ARM +| +---armclang // ARM/KEIL toolchain with Compiler 6 (ARM/CLANG) +| | dpp-qk.uvprojx // uVision project +| \---iar // IAR EWARM +| dpp-qk.eww // IAR EW-ARM workspace +| +\---qv // cooperative QK kernel +| +---gnu // GNU-ARM toolchain +| | \---targetConfigs +| | Makefile // Makefile for GNU-ARM +| +---armclang // ARM/KEIL toolchain with Compiler 6 (ARM/CLANG) +| | dpp-qv.uvprojx // uVision project +| \---iar // IAR EWARM +| dpp-qv.eww // IAR EW-ARM workspace +| ++---qxk // preemptive, dual-mode QXK kernel +| +---gnu // GNU-ARM toolchain +| | \---targetConfigs +| | Makefile // Makefile for GNU-ARM +| +---armclang // ARM/KEIL toolchain with Compiler 6 (ARM/CLANG) +| | dpp-qxk.uvprojx // uVision project +| \---iar // IAR EWARM +| dpp-qxk.eww // IAR EW-ARM workspace +| +``` + +# Building the example + +### GNU/ARM +- open terminal window +- change to the desired directory (either `examples\arm-cm\dpp_nucleo-l552ze\qk\gnu`, `examples\arm-cm\dpp_nucleo-l552ze\qv\gnu`, or `examples\arm-cm\dpp_nucleo-l552ze\qxk\gnu`) +- to build the default Debug configuration, type: + +``` +make +``` + +> **NOTE** +The `make` utility for Windows is provided in the QTools collection for Windows. + +- to build the Release configuration, type: + +``` +make CONF=rel +``` + +- to build the Spy configuration, type: + +``` +make CONF=spy +``` + + +### ARM/KEIL MDK +- Open the provided KEIL uVision project (either `dpp-qk.uvprojx`, `dpp-qv.uvprojx`, or `dpp-qxk.uvprojx`) +in Keil uVision IDE. Build/Debug/Download to the board from the IDE. +- Change the build configuration in the "Project Target" drop-down menu. + + +### IAR EWARM +- Open the provided IAR EWARM workspace (either `dpp-qk.eww`, `dpp-qv.eww`, or `dpp-qxk.eww`) +in IAR EWARM IDE. Build/Debug/Download to the board from the IDE. +- Change the build configuration in the "Project Configuration" drop-down menu. + + +# Uploading the Binary to the Board +The STM32 NUCLEO boards enumerate as a USB drive when connected to the host computer. The boards then can be programmed by **copying** the binary to that USB drive. This can be useful for the command-line GNU/ARM build. For example, to program the binary produced for the Debug configuration, you can type: + +``` +copy dbg\dpp-qk.bin E: +``` +NOTE: The above command assumes that the NUCLEO board enumerated as drive E:. Of course you need to adjust the command for your specific drive letter. + +Alternatively, if you use IDEs, such as KEIL-MDK or IAR EWARM, you can program the board from the IDE (e.g., by starting a debug session). + + +# Tracing with QP/Spy +When the board is flashed with the Spy build configuration, it produces the QP/Spy software tracing output to the built-in virtual COM port of the TivaC LauchPad board. The trace is binary rather than ASCII, and therefore requires a special host-based application called QSPY. + +> **NOTE** QSPY host application is available in the QTools collection. + +To launch the QSPY host application: +- open terminal window +- type: + +``` +qspy -c COM5 +``` + +where "COM5" is an example virtual COM port enumerated by the board. You need to check the specific COM port number on your host computer using the Device Manager application, Ports (COM and LPT) section. + + +The following screen shot shows a typical output from QSPY: + +

+
+Typical QSPY output produced by the Spy build configuration +

-- https://www.state-machine.com/qpcpp/arm-cm_dpp_nucleo-l552ze.html diff --git a/arm-cm/dpp_nucleo-l552ze/qspy-output.png b/arm-cm/dpp_nucleo-l552ze/qspy-output.png new file mode 100644 index 0000000..ee76445 Binary files /dev/null and b/arm-cm/dpp_nucleo-l552ze/qspy-output.png differ diff --git a/arm-cm/dpp_nucleo-l552ze/stm32-nucleo-l552ze.jpg b/arm-cm/dpp_nucleo-l552ze/stm32-nucleo-l552ze.jpg deleted file mode 100644 index 9c7f096..0000000 Binary files a/arm-cm/dpp_nucleo-l552ze/stm32-nucleo-l552ze.jpg and /dev/null differ diff --git a/arm-cm/dpp_nucleo-l552ze/stm32-nucleo-l552ze.webp b/arm-cm/dpp_nucleo-l552ze/stm32-nucleo-l552ze.webp new file mode 100644 index 0000000..7290782 Binary files /dev/null and b/arm-cm/dpp_nucleo-l552ze/stm32-nucleo-l552ze.webp differ diff --git a/arm-cm/dpp_nucleo-u545re/README.md b/arm-cm/dpp_nucleo-u545re/README.md index 6297f38..027500c 100644 --- a/arm-cm/dpp_nucleo-u545re/README.md +++ b/arm-cm/dpp_nucleo-u545re/README.md @@ -5,7 +5,7 @@ This file is best viewed in a **markdown viewer**, such as the one built into Gi This example demonstrates the [Dining Philosophers Problem (DPP) application](https://www.state-machine.com/qpc/tut_dpp.html) on the STM32 NUCLEO-U545RE board (ARM Cortex-__M33__).

-
+
STM32 NUCLEO-U545RE

diff --git a/arm-cm/dpp_nucleo-u545re/stm32-nucleo-u545re.jpg b/arm-cm/dpp_nucleo-u545re/stm32-nucleo-u545re.jpg deleted file mode 100644 index d980914..0000000 Binary files a/arm-cm/dpp_nucleo-u545re/stm32-nucleo-u545re.jpg and /dev/null differ diff --git a/arm-cm/dpp_nucleo-u545re/stm32-nucleo-u545re.webp b/arm-cm/dpp_nucleo-u545re/stm32-nucleo-u545re.webp new file mode 100644 index 0000000..2c422f5 Binary files /dev/null and b/arm-cm/dpp_nucleo-u545re/stm32-nucleo-u545re.webp differ diff --git a/arm-cm/dpp_stm32f4-discovery/README.md b/arm-cm/dpp_stm32f4-discovery/README.md deleted file mode 100644 index 2e5b7ff..0000000 --- a/arm-cm/dpp_stm32f4-discovery/README.md +++ /dev/null @@ -1,5 +0,0 @@ -![STM32F4-Discovery](../../../doxygen/images/bd_STM32F4-Disco.jpg) - -Documentation for this example is available in the QP/C Manual at: - -- https://www.state-machine.com/qpcpp/arm-cm_dpp_stm32f4-discovery.html diff --git a/arm-cm/game_efm32-slstk3401a/README.md b/arm-cm/game_efm32-slstk3401a/README.md index bc96459..5dc0d3e 100644 --- a/arm-cm/game_efm32-slstk3401a/README.md +++ b/arm-cm/game_efm32-slstk3401a/README.md @@ -1,21 +1,24 @@ -![STM32 EFM32-SLSTK3401A](../../../doxygen/images/bd_EFM32-SLSTK3401A.jpg) - -Documentation for this example is available in the QP/C Manual at: - -- https://www.state-machine.com/qpcpp/arm-cm_game_efm32-slstk3401a - # About this Example This directory contains the "Fly 'n' Shoot" game example application for the EFM32-SLSTK3401A board (Pearl Gecko evaluation kit) board. This directory contains portable code that should compile with any C compiler for ARM Cortex-M. +

+
+EFM32-SLSTK3401A (Pearl Gecko) +

+ The sub-directories contain code and project files, which are specific to the particular ARM toolchains, such as ARM (MDK-ARM), GCC, and IAR. Please refer to the README files in the sub-directories for specific instructions how to use and customize the example to your needs. +Documentation for this example is available in the QP/C Manual at: + +- https://www.state-machine.com/qpc/tut_game.html + # Support Code for EFM32-SLSTK3401A Board The directory qpc\3rd_party\efm32pg1b\ contains the CMSIS-compliant @@ -44,10 +47,10 @@ Please check the Device Manager to find the COM port number. # Win32-GUI Emulation -The sub-directory "win32-gui" provides the emulation of the example -on Windows GUI, either single-threaded (win32-qv) or multithreaded (win32). -This sub-directory contains the Makefile for the GNU-GCC toolset (MinGW) -and Visual Studio solution file (game-gui.sln) for Visual C++. +The directory `qpc\examples\workstation\game-gui` contains the emulation +of the "Fly 'n' Shoot" game on Windows GUI, either single-threaded (win32-qv) +or multithreaded (win32). This sub-directory contains the Visual Studio +solution file (game-gui.sln) for Visual C++. The Win32-GUI emulation is based on the QWin™ GUI Prototyping Toolkit, see: diff --git a/arm-cm/game_efm32-slstk3401a/efm32-slstk3401a.webp b/arm-cm/game_efm32-slstk3401a/efm32-slstk3401a.webp new file mode 100644 index 0000000..0292490 Binary files /dev/null and b/arm-cm/game_efm32-slstk3401a/efm32-slstk3401a.webp differ diff --git a/arm-cm/low-power_ek-tm4c123gxl/README.md b/arm-cm/low-power_ek-tm4c123gxl/README.md index d98ec7e..9029628 100644 --- a/arm-cm/low-power_ek-tm4c123gxl/README.md +++ b/arm-cm/low-power_ek-tm4c123gxl/README.md @@ -1,5 +1,95 @@ -![EK-TM4C123GXL](../../../doxygen/images/bd_EK-TM4C123GXL.jpg) +> **NOTE** +This file is best viewed in a **markdown viewer**, such as the one built into GitHub. Markdown viewers are also available as plug-ins to popular Internet browsers. -Documentation for this example is available in the QP/C Manual at: +# Low-Power Example on EK-TM4C123GXL +This example demonstrates the [low-power application](https://www.state-machine.com/qpc/tut_low.html) on the EK-TM4C123GLX board (ARM Cortex-M4F). + +

+
+EK-TM4C123GXL (TivaC LaunchPad) +

+ +## Example Behavior +The the low-power example illustrates the use of **two** clock tick rates to toggle the LEDs available on the EK-TM4C123GXL board. After the application code is loaded to the board, the Green-LED starts blinking once per two seconds (a second on and a second off), while the Red-LED lights up and stays on. If no buttons on the board are pressed, the Green-LED stops blinking after 4 times. The Red-LED shows the idle condition, where the system is in a sleep mode. + +When your press the SW1-Button, the Green-LED starts blinking as before, but additionally, the Blue-LED starts blinking rapidly for 13 times (1/10 of a second on and 1/10 off). + +So, depending when the SW1 switch is pressed, you can have only Green-LED blinking, or both green and blue blinking at different rates. The Red-LED appears to be on all the time. + +> **Note**
+Actually, the Red-LED is also turned off for very brief moments, but this is imperceptible to the human eye. Instead, the Red-LED appears to be on all the time, which corresponds to the application being mostly idle. + +The behavior just described is designed for the slow human interaction with the application. However, for more precise measurements with a __logic analyzer__, it is more convenient to speed up the application by factor of 100. This speed up can be achieved by editing the bsp.h header file: + + +# Code Organization +``` +qpc|qpcpp/ // QP/C/C++ installation directory + +-examples/ // QP/C/C++ examples directory (application) + | +-arm-cm/ // QP/C/C++ examples for ARM Cortex-M + | | +-low-power_ek-tm4c123gxl/ // Low-Power example on the EK-TM4C123GLX board + | | | +-qk/ //----------- Projects for the preemptive QK kernel + | | | | +-arm/ // ARM-KEIL toolchain + | | | | | low-power-qk.uvprojx // uVision project + | | | | +-gnu/ // GNU-ARM toolchain + | | | | | Makefile // Makefile for building the project + | | | | +-iar/ // IAR-ARM toolchain + | | | | low-power-qk.eww // IAR EW-ARM workspace + | | | | bsp.c // BSP for the QK kernel + | | | +-qv/ //----------- Projects for the non-preemptive QV kernel + | | | | +-arm/ // ARM-KEIL toolchain + | | | | | low-power-qv.uvprojx // uVision project + | | | | +-gnu/ // GNU-ARM toolchain + | | | | | Makefile // Makefile for building the project with GNU-ARM + | | | | +-iar/ // IAR-ARM toolchain + | | | | low-power-qk.eww // IAR EW-ARM workspace + | | | | bsp.c|.cpp // BSP for the QV kernel + | | | +-qxk/ //----------- Projects for the dual-mode QXK kernel + | | | | +-arm/ // ARM-KEIL toolchain + | | | | | low-power-qxk.uvprojx // uVision project + | | | | +-gnu/ // GNU-ARM toolchain + | | | | | Makefile // Makefile for building the project + | | | | +-iar/ // IAR-ARM toolchain + | | | | low-power-qxk.eww // IAR EW-ARM workspace + | | | | bsp.c|.cpp // BSP for the QxK kernel + | | | | xblinky1.c|.cpp // eXtended thread for the QXK kernel``` +``` + +# Building the example + +## GNU/ARM +- open terminal window +- change to the desired directory (either `examples\arm-cm\dpp_ek-tm4c123gxl\qk\gnu`, `examples\arm-cm\dpp_ek-tm4c123gxl\qv\gnu`, or `examples\arm-cm\dpp_ek-tm4c123gxl\qxk\gnu`) +- to build the default Debug configuration, type: + +``` +make +``` + +> **NOTE** +The `make` utility for Windows is provided in the QTools collection for Windows. + +- to build the Release configuration, type: + +``` +make CONF=rel +``` + +- to build the Spy configuration, type: + +``` +make CONF=spy +``` + + +### ARM/KEIL MDK +- Open the provided KEIL uVision project (either `dpp-qk.uvprojx`, `dpp-qv.uvprojx`, or `dpp-qxk.uvprojx`) +in Keil uVision IDE. Build/Debug/Download to the board from the IDE. +- Change the build configuration in the "Project Target" drop-down menu. + + +### IAR EWARM +- Open the provided IAR EWARM workspace (either `dpp-qk.eww`, `dpp-qv.eww`, or `dpp-qxk.eww`) +in IAR EWARM IDE. Build/Debug/Download to the board from the IDE. +- Change the build configuration in the "Project Configuration" drop-down menu. -- https://www.state-machine.com/qpcpp/arm-cm_low-power.html diff --git a/arm-cm/low-power_ek-tm4c123gxl/ek-tm4c123gxl.webp b/arm-cm/low-power_ek-tm4c123gxl/ek-tm4c123gxl.webp new file mode 100644 index 0000000..320870b Binary files /dev/null and b/arm-cm/low-power_ek-tm4c123gxl/ek-tm4c123gxl.webp differ diff --git a/arm-cm/real-time_nucleo-l053r8/README.md b/arm-cm/real-time_nucleo-l053r8/README.md index 1467248..b1fa611 100644 --- a/arm-cm/real-time_nucleo-l053r8/README.md +++ b/arm-cm/real-time_nucleo-l053r8/README.md @@ -5,7 +5,7 @@ This file is best viewed in a **markdown viewer**, such as the one built into Gi This example implements the "Periodic-Sporadic" application on the STM32 NUCLEO-L053R8 board (ARM Cortex-M0+). The example demonstrates various real-time preemption scenarios among active objects in the **QK** and **QV** kernels. The example requires a **logic analyzer**.

-
+
STM32 NUCLEO-L053R8

diff --git a/arm-cm/real-time_nucleo-l053r8/stm32-nucleo-l053r8.jpg b/arm-cm/real-time_nucleo-l053r8/stm32-nucleo-l053r8.jpg deleted file mode 100644 index 1c7c415..0000000 Binary files a/arm-cm/real-time_nucleo-l053r8/stm32-nucleo-l053r8.jpg and /dev/null differ diff --git a/arm-cm/real-time_nucleo-l053r8/stm32-nucleo-l053r8.webp b/arm-cm/real-time_nucleo-l053r8/stm32-nucleo-l053r8.webp new file mode 100644 index 0000000..8ec1391 Binary files /dev/null and b/arm-cm/real-time_nucleo-l053r8/stm32-nucleo-l053r8.webp differ diff --git a/arm-cr/blinky_launchxl2-tms57012/README.md b/arm-cr/blinky_launchxl2-tms57012/README.md index 7f84df1..b6bef22 100644 --- a/arm-cr/blinky_launchxl2-tms57012/README.md +++ b/arm-cr/blinky_launchxl2-tms57012/README.md @@ -6,7 +6,7 @@ This example implements the simple [Blinky application](https://www.state-machin on the LAUNCHXL2-TMS57012 board at 1Hz (0.5 seconds on, 0.5 seconds off).

-
+
LAUNCHXL2-TMS57012 board

diff --git a/arm-cr/blinky_launchxl2-tms57012/launchxl2-tms57012.png b/arm-cr/blinky_launchxl2-tms57012/launchxl2-tms57012.png deleted file mode 100644 index 04766ae..0000000 Binary files a/arm-cr/blinky_launchxl2-tms57012/launchxl2-tms57012.png and /dev/null differ diff --git a/arm-cr/blinky_launchxl2-tms57012/launchxl2-tms57012.webp b/arm-cr/blinky_launchxl2-tms57012/launchxl2-tms57012.webp new file mode 100644 index 0000000..72df6cd Binary files /dev/null and b/arm-cr/blinky_launchxl2-tms57012/launchxl2-tms57012.webp differ diff --git a/arm-cr/dpp_launchxl2-tms57012/README.md b/arm-cr/dpp_launchxl2-tms57012/README.md index 757e8aa..a755329 100644 --- a/arm-cr/dpp_launchxl2-tms57012/README.md +++ b/arm-cr/dpp_launchxl2-tms57012/README.md @@ -5,7 +5,7 @@ This file is best viewed in a **markdown viewer**, such as the one built into Gi This example implements the [Dining Philosophers Problem (DPP) application](https://www.state-machine.com/qpc/tut_dpp.html) on the LAUNCHXL2-TMS57012 board (ARM Cortex-R4F). The example blinks the LED on the LAUNCHXL2-TMS57012 board at 1Hz (0.5 seconds on, 0.5 seconds off).

-
+
LAUNCHXL2-TMS57012 board

diff --git a/arm-cr/dpp_launchxl2-tms57012/launchxl2-tms57012.png b/arm-cr/dpp_launchxl2-tms57012/launchxl2-tms57012.png deleted file mode 100644 index 04766ae..0000000 Binary files a/arm-cr/dpp_launchxl2-tms57012/launchxl2-tms57012.png and /dev/null differ diff --git a/arm-cr/dpp_launchxl2-tms57012/launchxl2-tms57012.webp b/arm-cr/dpp_launchxl2-tms57012/launchxl2-tms57012.webp new file mode 100644 index 0000000..72df6cd Binary files /dev/null and b/arm-cr/dpp_launchxl2-tms57012/launchxl2-tms57012.webp differ diff --git a/embos/arm-cm/dpp_nucleo-h743zi/README.md b/embos/arm-cm/dpp_nucleo-h743zi/README.md new file mode 100644 index 0000000..272e95e --- /dev/null +++ b/embos/arm-cm/dpp_nucleo-h743zi/README.md @@ -0,0 +1,112 @@ +> **NOTE** +This file is best viewed in a **markdown viewer**, such as the one built into GitHub. Markdown viewers are also available as plug-ins to popular Internet browsers. + +# DPP on NUCLEO-H743ZI +This example demonstrates QP port to the SEGGER embOS RTOS on the STM32 NUCLEO-H743ZI board (ARM Cortex-M7). + +

+ +

+ +The example uses the [Dining Philosophers Problem (DPP) application](https://www.state-machine.com/qpc/tut_dpp.html) + +

+
+STM32 NUCLEO-H743ZI +

+ +## Features Demonstrated +- QP port to SEGGER embOS RTOS + + with GNU-ARM toolchain + + with IAR-ARM toolchain +- multiple cooperating active objects +- immutable (const) events +- mutable (dynamic) events +- time events +- direct event posting +- publish-subscribe event delivery + + +## Build Configurations +- Debug +- Release +- Spy - software tracing with the built-in virtual COM port + +# Code Organization +``` +examples\embos\dpp_nucleo-h743zi +| +| +---gnu // GNU-ARM toolchain +| | \---targetConfigs +| | Makefile // Makefile for GNU-ARM +| \---iar // IAR EWARM +| dpp-qk.eww // IAR EW-ARM workspace +``` + +# Building the example + +### GNU/ARM +- open terminal window +- change to the desired directory (either `examples\embos\dpp_nucleo-h743zi\qk\gnu`, `examples\embos\dpp_nucleo-h743zi\qv\gnu`, or `examples\embos\dpp_nucleo-h743zi\qxk\gnu`) +- to build the default Debug configuration, type: + +``` +make +``` + +> **NOTE** +The `make` utility for Windows is provided in the QTools collection for Windows. + +- to build the Release configuration, type: + +``` +make CONF=rel +``` + +- to build the Spy configuration, type: + +``` +make CONF=spy +``` + + +### IAR EWARM +- Open the provided IAR EWARM workspace (either `dpp-qk.eww`, `dpp-qv.eww`, or `dpp-qxk.eww`) +in IAR EWARM IDE. Build/Debug/Download to the board from the IDE. +- Change the build configuration in the "Project Configuration" drop-down menu. + + +# Uploading the Binary to the Board +The STM32 NUCLEO boards enumerate as a USB drive when connected to the host computer. The boards then can be programmed by **copying** the binary to that USB drive. This can be useful for the command-line GNU/ARM build. For example, to program the binary produced for the Debug configuration, you can type: + +``` +copy dbg\dpp-qk.bin E: +``` +NOTE: The above command assumes that the NUCLEO board enumerated as drive E:. Of course you need to adjust the command for your specific drive letter. + +Alternatively, if you use IDEs, such as KEIL-MDK or IAR EWARM, you can program the board from the IDE (e.g., by starting a debug session). + + +# Tracing with QP/Spy +When the board is flashed with the Spy build configuration, it produces the QP/Spy software tracing output to the built-in virtual COM port of the TivaC LauchPad board. The trace is binary rather than ASCII, and therefore requires a special host-based application called QSPY. + +> **NOTE** QSPY host application is available in the QTools collection. + +To launch the QSPY host application: +- open terminal window +- type: + +``` +qspy -c COM5 +``` + +where "COM5" is an example virtual COM port enumerated by the board. You need to check the specific COM port number on your host computer using the Device Manager application, Ports (COM and LPT) section. + + +The following screen shot shows a typical output from QSPY: + +

+
+Typical QSPY output produced by the Spy build configuration +

+ diff --git a/embos/arm-cm/dpp_nucleo-h743zi/gnu/Makefile b/embos/arm-cm/dpp_nucleo-h743zi/gnu/Makefile index 142ff1e..8d75a81 100644 --- a/embos/arm-cm/dpp_nucleo-h743zi/gnu/Makefile +++ b/embos/arm-cm/dpp_nucleo-h743zi/gnu/Makefile @@ -75,7 +75,7 @@ VPATH = \ $(QPCPP)/src/qs \ $(QP_PORT_DIR) \ $(QPCPP)/3rd_party/STM32CubeH7/nucleo-h743zi/gnu \ - $(QPCPP)/3rd_party/STM32CubeH7/Drivers/BSP\STM32H7xx_Nucleo_144 \ + $(QPCPP)/3rd_party/STM32CubeH7/Drivers/BSP/STM32H7xx_Nucleo_144 \ $(QPCPP)/3rd_party/STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src \ $(QPCPP)/3rd_party/STM32CubeH7/Drivers/CMSIS/Device/ST/STM32H7xx/Source/Templates diff --git a/embos/arm-cm/dpp_nucleo-h743zi/logo_embos.webp b/embos/arm-cm/dpp_nucleo-h743zi/logo_embos.webp new file mode 100644 index 0000000..45fc72c Binary files /dev/null and b/embos/arm-cm/dpp_nucleo-h743zi/logo_embos.webp differ diff --git a/embos/arm-cm/dpp_nucleo-h743zi/qspy-output.png b/embos/arm-cm/dpp_nucleo-h743zi/qspy-output.png new file mode 100644 index 0000000..ee76445 Binary files /dev/null and b/embos/arm-cm/dpp_nucleo-h743zi/qspy-output.png differ diff --git a/embos/arm-cm/dpp_nucleo-h743zi/stm32-nucleo-h743zi.webp b/embos/arm-cm/dpp_nucleo-h743zi/stm32-nucleo-h743zi.webp new file mode 100644 index 0000000..594e7f7 Binary files /dev/null and b/embos/arm-cm/dpp_nucleo-h743zi/stm32-nucleo-h743zi.webp differ diff --git a/freertos/arm-cm/dpp_ek-tm4c123gxl/README.md b/freertos/arm-cm/dpp_ek-tm4c123gxl/README.md deleted file mode 100644 index 7346acd..0000000 --- a/freertos/arm-cm/dpp_ek-tm4c123gxl/README.md +++ /dev/null @@ -1,5 +0,0 @@ -![EK-TM4C123GXL](../../../../doxygen/images/bd_EK-TM4C123GXL.jpg) - -Documentation for this example is available in the QP/C Manual at: - -- https://www.state-machine.com/qpcpp/freertos_dpp_ek-tm4c123gxl.html diff --git a/freertos/arm-cm/dpp_nucleo-h743zi/README.md b/freertos/arm-cm/dpp_nucleo-h743zi/README.md new file mode 100644 index 0000000..9a9fdd3 --- /dev/null +++ b/freertos/arm-cm/dpp_nucleo-h743zi/README.md @@ -0,0 +1,121 @@ +> **NOTE** +This file is best viewed in a **markdown viewer**, such as the one built into GitHub. Markdown viewers are also available as plug-ins to popular Internet browsers. + +# DPP on NUCLEO-H743ZI +This example demonstrates QP port to the FreeRTOS on the STM32 NUCLEO-H743ZI board (ARM Cortex-M7). + +

+ +

+ +The example uses the [Dining Philosophers Problem (DPP) application](https://www.state-machine.com/qpc/tut_dpp.html) + +

+
+STM32 NUCLEO-H743ZI +

+ +## Features Demonstrated +- QP port to FreeRTOS + + with GNU-ARM toolchain + + with Keil-MDK toolchain + + with IAR-ARM toolchain +- multiple cooperating active objects +- immutable (const) events +- mutable (dynamic) events +- time events +- direct event posting +- publish-subscribe event delivery + + +## Build Configurations +- Debug +- Release +- Spy - software tracing with the built-in virtual COM port + +# Code Organization +``` +examples\freertos\dpp_nucleo-h743zi +| +| +---armcland // Keil-MDK toolchain +| | \---targetConfigs +| | dpp.uvprojx // Keil uVision project +| +---gnu // GNU-ARM toolchain +| | \---targetConfigs +| | Makefile // Makefile for GNU-ARM +| \---iar // IAR EWARM +| dpp-qk.eww // IAR EW-ARM workspace +``` + +# Building the example + +### GNU/ARM +- open terminal window +- change to the desired directory (either `examples\freertos\dpp_nucleo-h743zi\qk\gnu`, `examples\freertos\dpp_nucleo-h743zi\qv\gnu`, or `examples\freertos\dpp_nucleo-h743zi\qxk\gnu`) +- to build the default Debug configuration, type: + +``` +make +``` + +> **NOTE** +The `make` utility for Windows is provided in the QTools collection for Windows. + +- to build the Release configuration, type: + +``` +make CONF=rel +``` + +- to build the Spy configuration, type: + +``` +make CONF=spy +``` + +### ARM/KEIL MDK +- Open the provided KEIL uVision project (either `dpp-qk.uvprojx`, `dpp-qv.uvprojx`, or `dpp-qxk.uvprojx`) +in Keil uVision IDE. Build/Debug/Download to the board from the IDE. +- Change the build configuration in the "Project Target" drop-down menu. + + +### IAR EWARM +- Open the provided IAR EWARM workspace (either `dpp-qk.eww`, `dpp-qv.eww`, or `dpp-qxk.eww`) +in IAR EWARM IDE. Build/Debug/Download to the board from the IDE. +- Change the build configuration in the "Project Configuration" drop-down menu. + + +# Uploading the Binary to the Board +The STM32 NUCLEO boards enumerate as a USB drive when connected to the host computer. The boards then can be programmed by **copying** the binary to that USB drive. This can be useful for the command-line GNU/ARM build. For example, to program the binary produced for the Debug configuration, you can type: + +``` +copy dbg\dpp-qk.bin E: +``` +NOTE: The above command assumes that the NUCLEO board enumerated as drive E:. Of course you need to adjust the command for your specific drive letter. + +Alternatively, if you use IDEs, such as KEIL-MDK or IAR EWARM, you can program the board from the IDE (e.g., by starting a debug session). + + +# Tracing with QP/Spy +When the board is flashed with the Spy build configuration, it produces the QP/Spy software tracing output to the built-in virtual COM port of the TivaC LauchPad board. The trace is binary rather than ASCII, and therefore requires a special host-based application called QSPY. + +> **NOTE** QSPY host application is available in the QTools collection. + +To launch the QSPY host application: +- open terminal window +- type: + +``` +qspy -c COM5 +``` + +where "COM5" is an example virtual COM port enumerated by the board. You need to check the specific COM port number on your host computer using the Device Manager application, Ports (COM and LPT) section. + + +The following screen shot shows a typical output from QSPY: + +

+
+Typical QSPY output produced by the Spy build configuration +

+ diff --git a/freertos/arm-cm/dpp_nucleo-h743zi/gnu/Makefile b/freertos/arm-cm/dpp_nucleo-h743zi/gnu/Makefile index 05e8358..8481ce4 100644 --- a/freertos/arm-cm/dpp_nucleo-h743zi/gnu/Makefile +++ b/freertos/arm-cm/dpp_nucleo-h743zi/gnu/Makefile @@ -79,7 +79,7 @@ VPATH = \ $(FREERTOS) \ $(FREERTOS)/portable/GCC/ARM_CM7/r0p1 \ $(QPCPP)/3rd_party/STM32CubeH7/nucleo-h743zi/gnu \ - $(QPCPP)/3rd_party/STM32CubeH7/Drivers/BSP\STM32H7xx_Nucleo_144 \ + $(QPCPP)/3rd_party/STM32CubeH7/Drivers/BSP/STM32H7xx_Nucleo_144 \ $(QPCPP)/3rd_party/STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src \ $(QPCPP)/3rd_party/STM32CubeH7/Drivers/CMSIS/Device/ST/STM32H7xx/Source/Templates diff --git a/freertos/arm-cm/dpp_nucleo-h743zi/logo_freertos.webp b/freertos/arm-cm/dpp_nucleo-h743zi/logo_freertos.webp new file mode 100644 index 0000000..4652862 Binary files /dev/null and b/freertos/arm-cm/dpp_nucleo-h743zi/logo_freertos.webp differ diff --git a/freertos/arm-cm/dpp_nucleo-h743zi/stm32-nucleo-h743zi.webp b/freertos/arm-cm/dpp_nucleo-h743zi/stm32-nucleo-h743zi.webp new file mode 100644 index 0000000..594e7f7 Binary files /dev/null and b/freertos/arm-cm/dpp_nucleo-h743zi/stm32-nucleo-h743zi.webp differ diff --git a/lwip/arm-cm/lwip_ek-lm3s6965/README.txt b/lwip/arm-cm/lwip_ek-lm3s6965/README.md similarity index 84% rename from lwip/arm-cm/lwip_ek-lm3s6965/README.txt rename to lwip/arm-cm/lwip_ek-lm3s6965/README.md index 10b4728..3fdcc22 100644 --- a/lwip/arm-cm/lwip_ek-lm3s6965/README.txt +++ b/lwip/arm-cm/lwip_ek-lm3s6965/README.md @@ -4,6 +4,11 @@ This example application demonstrates the lightweight TCP/IP stack called lwIP (version 1.4.1) running on top of the QP state machine framework, which are both briefly described below. +

+
+EK-LM3S6965 board +

+ The example provides an HTTP server with simple Server Side Include (SSI) and Common Gateway Interface (CGI) facility capability, so that dynamic web pages can be served and the pages can send data or commands to the target. Internal @@ -14,40 +19,32 @@ The example also demonstrates UDP. A UDP test application for a Windows or Linux hosts is provided (qudp). -Building the QP-lwIP Example ----------------------------- +# Building the QP-lwIP Example The sub-directories "arm", "gnu", and "iar" contain ready-to-use projects Makefile for the GNU-ARM, and the IAR EWARM workspace, respectively. Please run the make utility on the Makefile, or open the IAR workspace in IAR EWARM IDE. -*** -NOTE: The build process supports three build configurations: Debug, Release, +> NOTE: The build process supports three build configurations: Debug, Release, and Spy. Please refer to the Makefile or the IAR project to select the desired build configuration. -*** -*** -NOTE: This example pushes the limits of the free evaluation versions of the + +> NOTE: This example pushes the limits of the free evaluation versions of the development tools. The example will barely fit in the 64KB codesize limit of the IAR EWARM KickStart (with the highest levels of optimization for size), but unfortunately the Spy configuration will no longer link due to exceeding the code size limit. Unfortunately also, the example won't compile with the free evaluation MDK-ARM uVision, because it exceeds the 32KB limit of this toolset. -*** -*** -NOTE: -The QP-lwIP example code assume that you are using the EK-LM3S6965 board +> NOTE: The QP-lwIP example code assume that you are using the EK-LM3S6965 board Revision C or higher (please check the back of your board). At board Revision C Luminary Micro changed the graphical OLED display from OSRAM to RITEK. The provided RITEK driver won't work for the boards with the OSRAM display. -*** -Downloading the Code to the EK-LM3S6965 Board ---------------------------------------------- +# Downloading the Code to the EK-LM3S6965 Board The "gnu" sub-folder contains the flash.bat file to download the binary image to the board. This batch file requires installation of the free LMFlash utility from Texas Instruments. @@ -56,8 +53,7 @@ The IAR project in the "iar" sub-folder allows you to download and debug the code on the board from the EWARM IDE. -Running the QP-lwIP Example ---------------------------- +# Running the QP-lwIP Example Connect the EK-LM3S6965 board to the wired Ethernet and power it up by plugging in the USB cable. Immediately after the power-up, you should see the startup screen on the OLED-display. The status of the Dining Philosophers @@ -68,19 +64,20 @@ so it assumes the presence of a DHCP server, such as a typical Ethernet router. The IP address acquired from the DHCP will be displayed at the top of the screen. You should type this IP address at your browser, for example: +``` http://192.168.1.77 +``` This should open an example website served by the EK-LM3S6965 board. This website contains a few menu item for testing SSI, CGI, and UDP. Please refer to the instructions on the website to test these features. -NOTE: By modifying the lwipopts.h header file, the application can also be +NOTE: By modifying the `lwipopts.h` header file, the application can also be configured to obtain the IP address via AUTOIP (as described in RFC 3927), or to use a static IP address. -QS Software Tracing Instrumentation ------------------------------------ +# QS Software Tracing Instrumentation This example provides the "Spy" build configuration, which outputs the QS (Quantum Spy) software tracing data through UART0 of the EK-LM3S6965 board, which is connected to the virtual COM port of the mbed USB connection. @@ -96,8 +93,7 @@ The actual COM port number might be different on your Windows machine. Please check the Device Manager to find the COM port number. -About QP-lwIP Integration -========================= +# About QP-lwIP Integration The QP-lwIP integration has been carefully designed for hard real-time control-type applications, in which the TCP/IP stack is used to monitor and configure the device as well as to provide remote user interface (e.g., by @@ -118,60 +114,55 @@ for more information. The Application Note in PDF is provided in the QP-lwIP example code. -Customizing the Website ------------------------ +# Customizing the Website The sub-directory "website" contains the website that you want to embed in your microcontroller to be served by your lwIP Web-Server. You need to put the files and directories of your website in there. To be useful in the microcontroller, the content of the "webstie" directory -needs to be converted to the "fsdata.h" header file. The provided batch +needs to be converted to the `fsdata.h` header file. The provided batch file "website.bat" re-generates the website after you change any file in it. The batch file calls internally the qfsgen.exe utility, which is described below. -qfsgen Utility to Generate Websites ------------------------------------ +## qfsgen Utility to Generate Websites Quantum Leaps provides a cross-platform, command-line utility, called "qfsgen", which converts all the files in a given folder (your website) into a C header file that contains a bunch of constant byte arrays representing -your files and directories. This generated file (fsdata.h) is subsequently +your files and directories. This generated file (`fsdata.h`) is subsequently included in the fs.c ROM-Based File System implementation. The "qfsgen" utility (both compiled executable and source code) is -provided in the Qtools collection, available for download from: +provided in the QTools collection, available for download from: -https://sourceforge.net/projects/qpc/files/Qtools +https://github.com/QuantumLeaps/qtools -*** -NOTE: The qfsgen utility is a simple executable (versions are available +> NOTE: The qfsgen utility is a simple executable (versions are available for Windows and Linux), which does not require any interpreters to run (such as Python, etc.) -*** You use the qfsgen utility from command-prompt. First, change current directory to examples\lwip\arm-cm\lwip_ek-lm3s6965 and from there execute: +``` qfsgen website -h +``` This will recursively generate the file-system corresponding to the directory website with HTTP headers (-h option). -Utilities to Test UDP ---------------------- +## Utilities to Test UDP Quantum Leaps provides a utility "qudp" to send and receive UDP packets for testing. The "qudp" utility (both compiled executable and source code) -is provided in the Qtools collection, available for download from: - -https://sourceforge.net/projects/qpc/files/Qtools +is provided in the QTools collection, available for download from: +https://github.com/QuantumLeaps/qtools -About QP Active Object Frameworks -================================= +# About QP Active Object Frameworks QP is a family of very lightweight, open source, active-object (actor) frameworks for embedded microcontrollers. QP enables developing well- structured embedded applications as a set of concurrently executing @@ -201,11 +192,10 @@ national defense, and many more. QP is licensed under the GPL version 3 open source license as well as under commercial closed-source licenses, which are expressly designed for users, who wish to retain the proprietary character of their code. More information about -QP can be found at the QP homepage at http://www.state-machine.com. +QP can be found at the QP homepage at https://www.state-machine.com. -About lwIP TCP/IP Stack -======================= +# About lwIP TCP/IP Stack lwIP is an open source implementation of the TCP/IP protocol suite that was originally written by Adam Dunkels of the Swedish Institute of Computer Science (SICS) but now is being actively developed by a team of developers @@ -226,7 +216,6 @@ qpc\3rd_party\lwip directory. Please refer to this directory for more information about licensing lwIP and the source. -Contact information -=================== -Web: www.state-machine.com -Email: info@state-machine.com +# Contact information +- Web: www.state-machine.com +- Email: info@state-machine.com diff --git a/lwip/arm-cm/lwip_ek-lm3s6965/ek-lm3s6965.webp b/lwip/arm-cm/lwip_ek-lm3s6965/ek-lm3s6965.webp new file mode 100644 index 0000000..ff9c35e Binary files /dev/null and b/lwip/arm-cm/lwip_ek-lm3s6965/ek-lm3s6965.webp differ diff --git a/qutest/qhsmtst/src/qhsmtst.cpp b/qutest/qhsm/src/cut_qhsm.cpp similarity index 57% rename from qutest/qhsmtst/src/qhsmtst.cpp rename to qutest/qhsm/src/cut_qhsm.cpp index 7c6d532..bcdfc83 100644 --- a/qutest/qhsmtst/src/qhsmtst.cpp +++ b/qutest/qhsm/src/cut_qhsm.cpp @@ -1,11 +1,15 @@ -//$file${.::qhsmtst.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +//$file${.::cut_qhsm.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv // -// Model: qhsmtst.qm -// File: ${.::qhsmtst.cpp} +// Model: qhsm.qm +// File: ${.::cut_qhsm.cpp} // -// This code has been generated by QM 5.3.0 . +// This code has been generated by QM 6.2.2 . // DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. // +// Q u a n t u m L e a P s +// ------------------------ +// Modern Embedded Software +// // SPDX-License-Identifier: GPL-3.0-or-later // // This generated code is open source software: you can redistribute it under @@ -18,18 +22,18 @@ // more details. // // NOTE: -// Alternatively, this generated code may be distributed under the terms -// of Quantum Leaps commercial licenses, which expressly supersede the GNU -// General Public License and are specifically designed for licensees -// interested in retaining the proprietary status of their code. +// Please contact Quantum Leaps for commercial licensing options, which +// expressly supersede the GNU General Public License and are specifically +// designed for licensees interested in retaining the proprietary status +// of the generated code. // // Contact information: // // // -//$endhead${.::qhsmtst.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -#include "qpcpp.hpp" -#include "qhsmtst.hpp" +//$endhead${.::cut_qhsm.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#include "qpcpp.hpp" // QP/C++ framework +#include "cut_qhsm.hpp" // Code Under Test (CUT) namespace { Q_DEFINE_THIS_FILE @@ -57,9 +61,20 @@ class QHsmTst : public QP::QHsm { Q_STATE_DECL(s); Q_STATE_DECL(s1); Q_STATE_DECL(s11); + Q_STATE_DECL(s111); + Q_STATE_DECL(s112); + Q_STATE_DECL(s12); Q_STATE_DECL(s2); Q_STATE_DECL(s21); Q_STATE_DECL(s211); + Q_STATE_DECL(s212); + Q_STATE_DECL(s22); + Q_STATE_DECL(t); + +protected: + QP::QStateHandler hist_s; + QP::QStateHandler hist_s1; + QP::QStateHandler hist_s2; }; // class QHsmTst //$enddecl${SMs::QHsmTst} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -70,11 +85,10 @@ QP::QAsm * const the_sm = &l_hsmtst; // the opaque pointer //$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv // Check for the minimum required QP version -#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U)) +#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U)) #error qpcpp version 7.3.0 or higher required #endif //$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - //$define${SMs::QHsmTst} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv //${SMs::QHsmTst} ............................................................ @@ -82,7 +96,6 @@ QP::QAsm * const the_sm = &l_hsmtst; // the opaque pointer //${SMs::QHsmTst::SM} ........................................................ Q_STATE_DEF(QHsmTst, initial) { //${SMs::QHsmTst::SM::initial} - Q_UNUSED_PAR(e); m_foo = 0U; BSP_display("top-INIT;"); @@ -95,15 +108,23 @@ Q_STATE_DEF(QHsmTst, initial) { QS_SIG_DICTIONARY(G_SIG, nullptr); QS_SIG_DICTIONARY(H_SIG, nullptr); QS_SIG_DICTIONARY(I_SIG, nullptr); - QS_SIG_DICTIONARY(TERMINATE_SIG, nullptr); - QS_SIG_DICTIONARY(IGNORE_SIG, nullptr); + // state history attributes + hist_s = &s1; + hist_s1 = &s111; + hist_s2 = &s211; QS_FUN_DICTIONARY(&QHsmTst::s); QS_FUN_DICTIONARY(&QHsmTst::s1); QS_FUN_DICTIONARY(&QHsmTst::s11); + QS_FUN_DICTIONARY(&QHsmTst::s111); + QS_FUN_DICTIONARY(&QHsmTst::s112); + QS_FUN_DICTIONARY(&QHsmTst::s12); QS_FUN_DICTIONARY(&QHsmTst::s2); QS_FUN_DICTIONARY(&QHsmTst::s21); QS_FUN_DICTIONARY(&QHsmTst::s211); + QS_FUN_DICTIONARY(&QHsmTst::s212); + QS_FUN_DICTIONARY(&QHsmTst::s22); + QS_FUN_DICTIONARY(&QHsmTst::t); return tran(&s2); } @@ -121,26 +142,15 @@ Q_STATE_DEF(QHsmTst, s) { //${SMs::QHsmTst::SM::s} case Q_EXIT_SIG: { BSP_display("s-EXIT;"); + // save shallow history + hist_s = childState(&s); status_ = Q_RET_HANDLED; break; } //${SMs::QHsmTst::SM::s::initial} case Q_INIT_SIG: { BSP_display("s-INIT;"); - status_ = tran(&s11); - break; - } - //${SMs::QHsmTst::SM::s::I} - case I_SIG: { - //${SMs::QHsmTst::SM::s::I::[m_foo]} - if (m_foo) { - m_foo = 0U; - BSP_display("s-I;"); - status_ = Q_RET_HANDLED; - } - else { - status_ = Q_RET_UNHANDLED; - } + status_ = tran(&s1); break; } //${SMs::QHsmTst::SM::s::E} @@ -149,12 +159,18 @@ Q_STATE_DEF(QHsmTst, s) { status_ = tran(&s11); break; } - //${SMs::QHsmTst::SM::s::TERMINATE} - case TERMINATE_SIG: { - BSP_terminate(0); + //${SMs::QHsmTst::SM::s::I} + case I_SIG: { + BSP_display("s-I;"); status_ = Q_RET_HANDLED; break; } + //${SMs::QHsmTst::SM::s::C} + case C_SIG: { + BSP_display("s-C;"); + status_ = tran(&t); + break; + } default: { status_ = super(&top); break; @@ -176,56 +192,40 @@ Q_STATE_DEF(QHsmTst, s1) { //${SMs::QHsmTst::SM::s::s1} case Q_EXIT_SIG: { BSP_display("s1-EXIT;"); + // save deep history + hist_s1 = state(); status_ = Q_RET_HANDLED; break; } //${SMs::QHsmTst::SM::s::s1::initial} case Q_INIT_SIG: { BSP_display("s1-INIT;"); - status_ = tran(&s11); + status_ = tran(&s111); break; } - //${SMs::QHsmTst::SM::s::s1::I} - case I_SIG: { - BSP_display("s1-I;"); - status_ = Q_RET_HANDLED; - break; - } - //${SMs::QHsmTst::SM::s::s1::D} - case D_SIG: { - //${SMs::QHsmTst::SM::s::s1::D::[!m_foo]} - if (!m_foo) { - m_foo = true; - BSP_display("s1-D;"); - status_ = tran(&s); - } - else { - status_ = Q_RET_UNHANDLED; - } - break; - } - //${SMs::QHsmTst::SM::s::s1::A} - case A_SIG: { - BSP_display("s1-A;"); - status_ = tran(&s1); - break; - } - //${SMs::QHsmTst::SM::s::s1::B} - case B_SIG: { - BSP_display("s1-B;"); - status_ = tran(&s11); + //${SMs::QHsmTst::SM::s::s1::E} + case E_SIG: { + BSP_display("s1-E;"); + status_ = tran(&s12); break; } //${SMs::QHsmTst::SM::s::s1::F} case F_SIG: { BSP_display("s1-F;"); - status_ = tran(&s211); + status_ = tran(&s21); break; } - //${SMs::QHsmTst::SM::s::s1::C} - case C_SIG: { - BSP_display("s1-C;"); - status_ = tran(&s2); + //${SMs::QHsmTst::SM::s::s1::I} + case I_SIG: { + //${SMs::QHsmTst::SM::s::s1::I::[m_foo]} + if (m_foo) { + m_foo = 0U; + BSP_display("s1-I;"); + status_ = Q_RET_HANDLED; + } + else { + status_ = Q_RET_UNHANDLED; + } break; } default: { @@ -252,17 +252,29 @@ Q_STATE_DEF(QHsmTst, s11) { status_ = Q_RET_HANDLED; break; } - //${SMs::QHsmTst::SM::s::s1::s11::H} - case H_SIG: { - BSP_display("s11-H;"); - status_ = tran(&s); + //${SMs::QHsmTst::SM::s::s1::s11::initial} + case Q_INIT_SIG: { + BSP_display("s11-INIT;"); + status_ = tran(&s111); + break; + } + //${SMs::QHsmTst::SM::s::s1::s11::A} + case A_SIG: { + BSP_display("s11-A;"); + status_ = tran(&s11); + break; + } + //${SMs::QHsmTst::SM::s::s1::s11::B} + case B_SIG: { + BSP_display("s11-B;"); + status_ = tran(&s111); break; } //${SMs::QHsmTst::SM::s::s1::s11::D} case D_SIG: { - //${SMs::QHsmTst::SM::s::s1::s11::D::[m_foo]} - if (m_foo) { - m_foo = false; + //${SMs::QHsmTst::SM::s::s1::s11::D::[!m_foo]} + if (!m_foo) { + m_foo = 1U; BSP_display("s11-D;"); status_ = tran(&s1); } @@ -273,8 +285,92 @@ Q_STATE_DEF(QHsmTst, s11) { } //${SMs::QHsmTst::SM::s::s1::s11::G} case G_SIG: { - BSP_display("s11-G;"); - status_ = tran(&s211); + BSP_display("s11-G->H*-s2;"); + status_ = tran_hist(hist_s2); + break; + } + default: { + status_ = super(&s1); + break; + } + } + return status_; +} + +//${SMs::QHsmTst::SM::s::s1::s11::s111} ...................................... +Q_STATE_DEF(QHsmTst, s111) { + QP::QState status_; + switch (e->sig) { + //${SMs::QHsmTst::SM::s::s1::s11::s111} + case Q_ENTRY_SIG: { + BSP_display("s111-ENTRY;"); + status_ = Q_RET_HANDLED; + break; + } + //${SMs::QHsmTst::SM::s::s1::s11::s111} + case Q_EXIT_SIG: { + BSP_display("s111-EXIT;"); + status_ = Q_RET_HANDLED; + break; + } + //${SMs::QHsmTst::SM::s::s1::s11::s111::C} + case C_SIG: { + BSP_display("s111-C;"); + status_ = tran(&s112); + break; + } + default: { + status_ = super(&s11); + break; + } + } + return status_; +} + +//${SMs::QHsmTst::SM::s::s1::s11::s112} ...................................... +Q_STATE_DEF(QHsmTst, s112) { + QP::QState status_; + switch (e->sig) { + //${SMs::QHsmTst::SM::s::s1::s11::s112} + case Q_ENTRY_SIG: { + BSP_display("s112-ENTRY;"); + status_ = Q_RET_HANDLED; + break; + } + //${SMs::QHsmTst::SM::s::s1::s11::s112} + case Q_EXIT_SIG: { + BSP_display("s112-EXIT;"); + status_ = Q_RET_HANDLED; + break; + } + //${SMs::QHsmTst::SM::s::s1::s11::s112::H} + case H_SIG: { + BSP_display("s112-H;"); + status_ = tran(&s); + break; + } + default: { + status_ = super(&s11); + break; + } + } + return status_; +} + +//${SMs::QHsmTst::SM::s::s1::s12} ............................................ +Q_STATE_DEF(QHsmTst, s12) { + QP::QState status_; + switch (e->sig) { + //${SMs::QHsmTst::SM::s::s1::s12} + case Q_ENTRY_SIG: { + BSP_display("s12-ENTRY;"); + status_ = Q_RET_HANDLED; + break; + } + //${SMs::QHsmTst::SM::s::s1::s12} + case Q_EXIT_SIG: { + BSP_display("s12-EXIT;"); + status_ = Q_RET_HANDLED; break; } default: { @@ -298,6 +394,8 @@ Q_STATE_DEF(QHsmTst, s2) { //${SMs::QHsmTst::SM::s::s2} case Q_EXIT_SIG: { BSP_display("s2-EXIT;"); + // save deep history + hist_s2 = state(); status_ = Q_RET_HANDLED; break; } @@ -307,17 +405,10 @@ Q_STATE_DEF(QHsmTst, s2) { status_ = tran(&s211); break; } - //${SMs::QHsmTst::SM::s::s2::I} - case I_SIG: { - //${SMs::QHsmTst::SM::s::s2::I::[!m_foo]} - if (!m_foo) { - m_foo = true; - BSP_display("s2-I;"); - status_ = Q_RET_HANDLED; - } - else { - status_ = Q_RET_UNHANDLED; - } + //${SMs::QHsmTst::SM::s::s2::E} + case E_SIG: { + BSP_display("s2-E;"); + status_ = tran(&s22); break; } //${SMs::QHsmTst::SM::s::s2::F} @@ -326,10 +417,17 @@ Q_STATE_DEF(QHsmTst, s2) { status_ = tran(&s11); break; } - //${SMs::QHsmTst::SM::s::s2::C} - case C_SIG: { - BSP_display("s2-C;"); - status_ = tran(&s1); + //${SMs::QHsmTst::SM::s::s2::I} + case I_SIG: { + //${SMs::QHsmTst::SM::s::s2::I::[m_foo]} + if (m_foo) { + m_foo = 0U; + BSP_display("s2-I;"); + status_ = Q_RET_HANDLED; + } + else { + status_ = Q_RET_UNHANDLED; + } break; } default: { @@ -362,12 +460,6 @@ Q_STATE_DEF(QHsmTst, s21) { status_ = tran(&s211); break; } - //${SMs::QHsmTst::SM::s::s2::s21::G} - case G_SIG: { - BSP_display("s21-G;"); - status_ = tran(&s1); - break; - } //${SMs::QHsmTst::SM::s::s2::s21::A} case A_SIG: { BSP_display("s21-A;"); @@ -380,6 +472,25 @@ Q_STATE_DEF(QHsmTst, s21) { status_ = tran(&s211); break; } + //${SMs::QHsmTst::SM::s::s2::s21::D} + case D_SIG: { + //${SMs::QHsmTst::SM::s::s2::s21::D::[!m_foo]} + if (!m_foo) { + m_foo = 1U; + BSP_display("s21-D;"); + status_ = tran(&s2); + } + else { + status_ = Q_RET_UNHANDLED; + } + break; + } + //${SMs::QHsmTst::SM::s::s2::s21::G} + case G_SIG: { + BSP_display("s21-G->H*-s1;"); + status_ = tran_hist(hist_s1); + break; + } default: { status_ = super(&s2); break; @@ -404,20 +515,98 @@ Q_STATE_DEF(QHsmTst, s211) { status_ = Q_RET_HANDLED; break; } - //${SMs::QHsmTst::SM::s::s2::s21::s211::H} + //${SMs::QHsmTst::SM::s::s2::s21::s211::C} + case C_SIG: { + BSP_display("s211-C;"); + status_ = tran(&s212); + break; + } + default: { + status_ = super(&s21); + break; + } + } + return status_; +} + +//${SMs::QHsmTst::SM::s::s2::s21::s212} ...................................... +Q_STATE_DEF(QHsmTst, s212) { + QP::QState status_; + switch (e->sig) { + //${SMs::QHsmTst::SM::s::s2::s21::s212} + case Q_ENTRY_SIG: { + BSP_display("s212-ENTRY;"); + status_ = Q_RET_HANDLED; + break; + } + //${SMs::QHsmTst::SM::s::s2::s21::s212} + case Q_EXIT_SIG: { + BSP_display("s212-EXIT;"); + status_ = Q_RET_HANDLED; + break; + } + //${SMs::QHsmTst::SM::s::s2::s21::s212::H} case H_SIG: { - BSP_display("s211-H;"); + BSP_display("s212-H;"); status_ = tran(&s); break; } - //${SMs::QHsmTst::SM::s::s2::s21::s211::D} - case D_SIG: { - BSP_display("s211-D;"); - status_ = tran(&s21); + default: { + status_ = super(&s21); + break; + } + } + return status_; +} + +//${SMs::QHsmTst::SM::s::s2::s22} ............................................ +Q_STATE_DEF(QHsmTst, s22) { + QP::QState status_; + switch (e->sig) { + //${SMs::QHsmTst::SM::s::s2::s22} + case Q_ENTRY_SIG: { + BSP_display("s22-ENTRY;"); + status_ = Q_RET_HANDLED; + break; + } + //${SMs::QHsmTst::SM::s::s2::s22} + case Q_EXIT_SIG: { + BSP_display("s22-EXIT;"); + status_ = Q_RET_HANDLED; break; } default: { - status_ = super(&s21); + status_ = super(&s2); + break; + } + } + return status_; +} + +//${SMs::QHsmTst::SM::t} ..................................................... +Q_STATE_DEF(QHsmTst, t) { + QP::QState status_; + switch (e->sig) { + //${SMs::QHsmTst::SM::t} + case Q_ENTRY_SIG: { + BSP_display("t-ENTRY;"); + status_ = Q_RET_HANDLED; + break; + } + //${SMs::QHsmTst::SM::t} + case Q_EXIT_SIG: { + BSP_display("t-EXIT;"); + status_ = Q_RET_HANDLED; + break; + } + //${SMs::QHsmTst::SM::t::C} + case C_SIG: { + BSP_display("t-C->H-s;"); + status_ = tran_hist(hist_s); + break; + } + default: { + status_ = super(&top); break; } } @@ -438,6 +627,15 @@ bool QHsmTst_isIn(std::uint32_t const state_num) { case 11: stat = me->isIn(Q_STATE_CAST(&QHsmTst::s11)); break; + case 111: + stat = me->isIn(Q_STATE_CAST(&QHsmTst::s111)); + break; + case 112: + stat = me->isIn(Q_STATE_CAST(&QHsmTst::s112)); + break; + case 12: + stat = me->isIn(Q_STATE_CAST(&QHsmTst::s12)); + break; case 2: stat = me->isIn(Q_STATE_CAST(&QHsmTst::s2)); break; @@ -447,6 +645,12 @@ bool QHsmTst_isIn(std::uint32_t const state_num) { case 211: stat = me->isIn(Q_STATE_CAST(&QHsmTst::s211)); break; + case 212: + stat = me->isIn(Q_STATE_CAST(&QHsmTst::s212)); + break; + case 22: + stat = me->isIn(Q_STATE_CAST(&QHsmTst::s22)); + break; default: Q_ERROR(); } diff --git a/qutest/qhsmtst/src/qhsmtst.hpp b/qutest/qhsm/src/cut_qhsm.hpp similarity index 61% rename from qutest/qhsmtst/src/qhsmtst.hpp rename to qutest/qhsm/src/cut_qhsm.hpp index 4413d40..c137a69 100644 --- a/qutest/qhsmtst/src/qhsmtst.hpp +++ b/qutest/qhsm/src/cut_qhsm.hpp @@ -1,11 +1,15 @@ -//$file${.::qhsmtst.hpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +//$file${.::cut_qhsm.hpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv // -// Model: qhsmtst.qm -// File: ${.::qhsmtst.hpp} +// Model: qhsm.qm +// File: ${.::cut_qhsm.hpp} // -// This code has been generated by QM 5.3.0 . +// This code has been generated by QM 6.2.2 . // DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. // +// Q u a n t u m L e a P s +// ------------------------ +// Modern Embedded Software +// // SPDX-License-Identifier: GPL-3.0-or-later // // This generated code is open source software: you can redistribute it under @@ -18,18 +22,18 @@ // more details. // // NOTE: -// Alternatively, this generated code may be distributed under the terms -// of Quantum Leaps commercial licenses, which expressly supersede the GNU -// General Public License and are specifically designed for licensees -// interested in retaining the proprietary status of their code. +// Please contact Quantum Leaps for commercial licensing options, which +// expressly supersede the GNU General Public License and are specifically +// designed for licensees interested in retaining the proprietary status +// of the generated code. // // Contact information: // // // -//$endhead${.::qhsmtst.hpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -#ifndef QHSMTST_HPP_ -#define QHSMTST_HPP_ +//$endhead${.::cut_qhsm.hpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#ifndef CUT_QHSM_HPP_ +#define CUT_QHSM_HPP_ namespace APP { @@ -43,8 +47,6 @@ enum QHsmTstSignals { G_SIG, H_SIG, I_SIG, - TERMINATE_SIG, - IGNORE_SIG, MAX_SIG }; @@ -58,4 +60,4 @@ void BSP_terminate(int16_t const result); } // namespace APP -#endif // QHSMTST_HPP_ +#endif // CUT_QHSM_HPP_ diff --git a/qutest/qhsm/src/qhsm.qm b/qutest/qhsm/src/qhsm.qm new file mode 100644 index 0000000..da5da6f --- /dev/null +++ b/qutest/qhsm/src/qhsm.qm @@ -0,0 +1,484 @@ + + + QHsmTst is a contrived state machine from Chapter 2 of the PSiCC2 book for testing all possible transition topologies with up to 4-levels of state nesting. + + + + + + + Test active object + + + + + + + : QHsm(&initial) + + + + + + m_foo = 0U; +BSP_display("top-INIT;"); + +QS_SIG_DICTIONARY(A_SIG, nullptr); +QS_SIG_DICTIONARY(B_SIG, nullptr); +QS_SIG_DICTIONARY(C_SIG, nullptr); +QS_SIG_DICTIONARY(D_SIG, nullptr); +QS_SIG_DICTIONARY(E_SIG, nullptr); +QS_SIG_DICTIONARY(F_SIG, nullptr); +QS_SIG_DICTIONARY(G_SIG, nullptr); +QS_SIG_DICTIONARY(H_SIG, nullptr); +QS_SIG_DICTIONARY(I_SIG, nullptr); + + + + + + + BSP_display("s-ENTRY;"); + BSP_display("s-EXIT;"); + + + BSP_display("s-INIT;"); + + + + + + + + + + + BSP_display("s-E;"); + + + + + + + BSP_display("s-I;"); + + + + + + + BSP_display("s-C;"); + + + + + + + BSP_display("s1-ENTRY;"); + BSP_display("s1-EXIT;"); + + + BSP_display("s1-INIT;"); + + + + + + + + + + + BSP_display("s1-E;"); + + + + + + + BSP_display("s1-F;"); + + + + + + + + + m_foo + m_foo = 0U; +BSP_display("s1-I;"); + + + + + + + + + + + BSP_display("s11-ENTRY;"); + BSP_display("s11-EXIT;"); + + + BSP_display("s11-INIT;"); + + + + + + + BSP_display("s11-A;"); + + + + + + + BSP_display("s11-B;"); + + + + + + + + + !m_foo + m_foo = 1U; +BSP_display("s11-D;"); + + + + + + + + + + + BSP_display("s11-G->H*-s2;"); + + + + + + + BSP_display("s111-ENTRY;"); + BSP_display("s111-EXIT;"); + + + BSP_display("s111-C;"); + + + + + + + + + + + + BSP_display("s112-ENTRY;"); + BSP_display("s112-EXIT;"); + + + BSP_display("s112-H;"); + + + + + + + + + + + + + + + + + BSP_display("s12-ENTRY;"); + BSP_display("s12-EXIT;"); + + + + + + + + + + + + + BSP_display("s2-ENTRY;"); + BSP_display("s2-EXIT;"); + + + BSP_display("s2-INIT;"); + + + + + + + + + + + BSP_display("s2-E;"); + + + + + + + BSP_display("s2-F;"); + + + + + + + + + m_foo + m_foo = 0U; +BSP_display("s2-I;"); + + + + + + + + + + + BSP_display("s21-ENTRY;"); + BSP_display("s21-EXIT;"); + + + BSP_display("s21-INIT;"); + + + + + + + BSP_display("s21-A;"); + + + + + + + BSP_display("s21-B;"); + + + + + + + + + !m_foo + m_foo = 1U; +BSP_display("s21-D;"); + + + + + + + + + + + BSP_display("s21-G->H*-s1;"); + + + + + + + BSP_display("s211-ENTRY;"); + BSP_display("s211-EXIT;"); + + + BSP_display("s211-C;"); + + + + + + + + + + + + BSP_display("s212-ENTRY;"); + BSP_display("s212-EXIT;"); + + + BSP_display("s212-H;"); + + + + + + + + + + + + + + + + + BSP_display("s22-ENTRY;"); + BSP_display("s22-EXIT;"); + + + + + + + + + + + + + + + + + + BSP_display("t-ENTRY;"); + BSP_display("t-EXIT;"); + + + BSP_display("t-C->H-s;"); + + + + + + + + + + + + + + + + + + #ifndef CUT_QHSM_HPP_ +#define CUT_QHSM_HPP_ + +namespace APP { + +enum QHsmTstSignals { + A_SIG = QP::Q_USER_SIG, + B_SIG, + C_SIG, + D_SIG, + E_SIG, + F_SIG, + G_SIG, + H_SIG, + I_SIG, + MAX_SIG +}; + +extern QP::QAsm * const the_sm; // opaque pointer to the test SM + +bool QHsmTst_isIn(std::uint32_t const state_num); + +// BSP functions to display a message and exit +void BSP_display(char const *msg); +void BSP_terminate(int16_t const result); + +} // namespace APP + +#endif // CUT_QHSM_HPP_ + + + + #include "qpcpp.hpp" // QP/C++ framework +#include "cut_qhsm.hpp" // Code Under Test (CUT) + +namespace { +Q_DEFINE_THIS_FILE +} + +namespace APP { + +$declare ${SMs::QHsmTst} + +static QHsmTst l_hsmtst; // the only instance of the QHsmTst class + +// global-scope definitions ----------------------------------------- +QP::QAsm * const the_sm = &l_hsmtst; // the opaque pointer + +$define ${SMs::QHsmTst} + +bool QHsmTst_isIn(std::uint32_t const state_num) { + QP::QHsm * const me = &l_hsmtst; + bool stat = false; + switch (state_num) { + case 0: + stat = me->isIn(Q_STATE_CAST(&QHsmTst::s)); + break; + case 1: + stat = me->isIn(Q_STATE_CAST(&QHsmTst::s1)); + break; + case 11: + stat = me->isIn(Q_STATE_CAST(&QHsmTst::s11)); + break; + case 111: + stat = me->isIn(Q_STATE_CAST(&QHsmTst::s111)); + break; + case 112: + stat = me->isIn(Q_STATE_CAST(&QHsmTst::s112)); + break; + case 12: + stat = me->isIn(Q_STATE_CAST(&QHsmTst::s12)); + break; + case 2: + stat = me->isIn(Q_STATE_CAST(&QHsmTst::s2)); + break; + case 21: + stat = me->isIn(Q_STATE_CAST(&QHsmTst::s21)); + break; + case 211: + stat = me->isIn(Q_STATE_CAST(&QHsmTst::s211)); + break; + case 212: + stat = me->isIn(Q_STATE_CAST(&QHsmTst::s212)); + break; + case 22: + stat = me->isIn(Q_STATE_CAST(&QHsmTst::s22)); + break; + default: + Q_ERROR(); + } + return stat; +} + +} // namespace APP + + + diff --git a/qutest/qhsmtst/test/Makefile b/qutest/qhsm/test/Makefile similarity index 96% rename from qutest/qhsmtst/test/Makefile rename to qutest/qhsm/test/Makefile index 8232004..bb51143 100644 --- a/qutest/qhsmtst/test/Makefile +++ b/qutest/qhsm/test/Makefile @@ -1,7 +1,7 @@ ############################################################################## # Product: Makefile for QUTEST-QP/C++ for Windows and POSIX *HOSTS* -# Last Updated for Version: 7.2.0 -# Date of the Last Update: 2022-12-21 +# Last Updated for Version: 7.4.0 +# Date of the Last Update: 2024-09-02 # # Q u a n t u m L e a P s # ------------------------ @@ -82,7 +82,7 @@ C_SRCS := # C++ source files... CPP_SRCS := \ - qhsmtst.cpp \ + cut_qhsm.cpp \ test_qhsm.cpp LIB_DIRS := @@ -122,6 +122,7 @@ LIBS += -lws2_32 else QP_PORT_DIR := $(QPCPP)/ports/posix-qutest +#QP_PORT_DIR := $(QPCPP)/ports/posix LIBS += -lpthread endif @@ -218,8 +219,14 @@ $(TARGET_EXE) : $(C_OBJS_EXT) $(CPP_OBJS_EXT) $(CPP) $(CPPFLAGS) $(QPCPP)/src/qs/qstamp.cpp -o $(BIN_DIR)/qstamp.o $(LINK) $(LINKFLAGS) $(LIB_DIRS) -o $@ $^ $(BIN_DIR)/qstamp.o $(LIBS) +ifdef GCOV run : $(TARGET_EXE) + -$(RM) $(BIN_DIR)/*.gcda $(QUTEST) -e$(TARGET_EXE) -q$(QSPY) -l$(LOG) -o$(OPT) -- $(TESTS) +else +run : $(TARGET_EXE) + $(QUTEST) -e$(TARGET_EXE) -q$(QSPY) -l$(LOG) -o$(OPT) -- $(TESTS) +endif $(BIN_DIR)/%.d : %.cpp $(CPP) -MM -MT $(@:.d=.o) $(CPPFLAGS) $< > $@ diff --git a/qutest/qhsm/test/gcov_qhsm.bat b/qutest/qhsm/test/gcov_qhsm.bat new file mode 100644 index 0000000..b08704e --- /dev/null +++ b/qutest/qhsm/test/gcov_qhsm.bat @@ -0,0 +1 @@ +gcov -f -o build qep_hsm.o diff --git a/qutest/qhsmtst/test/make_nucleo-l053r8 b/qutest/qhsm/test/make_nucleo-l053r8 similarity index 99% rename from qutest/qhsmtst/test/make_nucleo-l053r8 rename to qutest/qhsm/test/make_nucleo-l053r8 index b7765fb..6eb5e6d 100644 --- a/qutest/qhsmtst/test/make_nucleo-l053r8 +++ b/qutest/qhsm/test/make_nucleo-l053r8 @@ -1,7 +1,7 @@ ############################################################################## # Product: Makefile for QP/C on NUCLEO-L053R8 board, QUTEST, GNU-ARM -# Last Updated for Version: 7.3.1 -# Date of the Last Update: 2023-11-13 +# Last Updated for Version: 7.4.0 +# Date of the Last Update: 2024-09-04 # # Q u a n t u m L e a P s # ------------------------ @@ -103,7 +103,7 @@ C_SRCS := \ # C++ source files CPP_SRCS := \ - qhsmtst.cpp \ + cut_qhsm.cpp \ test_qhsm.cpp OUTPUT := $(PROJECT) diff --git a/qutest/qhsmtst/test/make_tm4c123 b/qutest/qhsm/test/make_tm4c123 similarity index 99% rename from qutest/qhsmtst/test/make_tm4c123 rename to qutest/qhsm/test/make_tm4c123 index 1b63189..aa940a6 100644 --- a/qutest/qhsmtst/test/make_tm4c123 +++ b/qutest/qhsm/test/make_tm4c123 @@ -1,7 +1,7 @@ ############################################################################## # Product: Makefile for QP/C++ on TM4C123, QUTEST, GNU-ARM -# Last Updated for Version: 7.2.0 -# Date of the Last Update: 2022-12-21 +# Last Updated for Version: 7.4.0 +# Date of the Last Update: 2024-09-04 # # Q u a n t u m L e a P s # ------------------------ @@ -103,7 +103,7 @@ C_SRCS := \ # C++ source files CPP_SRCS := \ - qhsmtst.cpp \ + cut_qhsm.cpp \ test_qhsm.cpp OUTPUT := $(PROJECT) diff --git a/qutest/qhsm/test/qep_hsm.cpp.gcov b/qutest/qhsm/test/qep_hsm.cpp.gcov new file mode 100644 index 0000000..77c00a6 --- /dev/null +++ b/qutest/qhsm/test/qep_hsm.cpp.gcov @@ -0,0 +1,677 @@ + -: 0:Source:../../../../src/qf/qep_hsm.cpp + -: 0:Graph:build/qep_hsm.gcno + -: 0:Data:build/qep_hsm.gcda + -: 0:Runs:3 + -: 1://$file${src::qf::qep_hsm.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 2:// + -: 3:// Model: qpcpp.qm + -: 4:// File: ${src::qf::qep_hsm.cpp} + -: 5:// + -: 6:// This code has been generated by QM 6.1.1 . + -: 7:// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. + -: 8:// + -: 9:// This code is covered by the following QP license: + -: 10:// License # : LicenseRef-QL-dual + -: 11:// Issued to : Any user of the QP/C++ real-time embedded framework + -: 12:// Framework(s) : qpcpp + -: 13:// Support ends : 2024-12-31 + -: 14:// License scope: + -: 15:// + -: 16:// Copyright (C) 2005 Quantum Leaps, LLC . + -: 17:// + -: 18:// Q u a n t u m L e a P s + -: 19:// ------------------------ + -: 20:// Modern Embedded Software + -: 21:// + -: 22:// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial + -: 23:// + -: 24:// This software is dual-licensed under the terms of the open source GNU + -: 25:// General Public License version 3 (or any later version), or alternatively, + -: 26:// under the terms of one of the closed source Quantum Leaps commercial + -: 27:// licenses. + -: 28:// + -: 29:// The terms of the open source GNU General Public License version 3 + -: 30:// can be found at: + -: 31:// + -: 32:// The terms of the closed source Quantum Leaps commercial licenses + -: 33:// can be found at: + -: 34:// + -: 35:// Redistributions in source code must retain this top-level comment block. + -: 36:// Plagiarizing this software to sidestep the license obligations is illegal. + -: 37:// + -: 38:// Contact information: + -: 39:// + -: 40:// + -: 41:// + -: 42://$endhead${src::qf::qep_hsm.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 43:#define QP_IMPL // this is QP implementation + -: 44:#include "qp_port.hpp" // QP port + -: 45:#include "qp_pkg.hpp" // QP package-scope interface + -: 46:#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem + -: 47:#ifdef Q_SPY // QS software tracing enabled? + -: 48: #include "qs_port.hpp" // QS port + -: 49: #include "qs_pkg.hpp" // QS facilities for pre-defined trace records + -: 50:#else + -: 51: #include "qs_dummy.hpp" // disable the QS software tracing + -: 52:#endif // Q_SPY + -: 53: + -: 54://============================================================================ + -: 55://! @cond INTERNAL + -: 56: + -: 57:// unnamed namespace for local definitions with internal linkage + -: 58:namespace { + -: 59:Q_DEFINE_THIS_MODULE("qep_hsm") + -: 60: + -: 61:// immutable events corresponding to the reserved signals. + -: 62:static QP::QEvt const l_reservedEvt_[4] { + -: 63: QP::QEvt(static_cast(QP::QHsm::Q_EMPTY_SIG)), + -: 64: QP::QEvt(static_cast(QP::QHsm::Q_ENTRY_SIG)), + -: 65: QP::QEvt(static_cast(QP::QHsm::Q_EXIT_SIG)), + -: 66: QP::QEvt(static_cast(QP::QHsm::Q_INIT_SIG)) + -: 67:}; + -: 68: + -: 69:} // unnamed namespace + -: 70: + -: 71:// helper macro to handle reserved event in an QHsm + -: 72:#define QHSM_RESERVED_EVT_(state_, sig_) \ + -: 73: ((*(state_))(this, &l_reservedEvt_[(sig_)])) + -: 74: + -: 75:// helper macro to trace state entry + -: 76:#define QS_STATE_ENTRY_(state_, qsId_) \ + -: 77: QS_CRIT_ENTRY(); \ + -: 78: QS_MEM_SYS(); \ + -: 79: QS_BEGIN_PRE_(QS_QEP_STATE_ENTRY, (qsId_)) \ + -: 80: QS_OBJ_PRE_(this); \ + -: 81: QS_FUN_PRE_(state_); \ + -: 82: QS_END_PRE_() \ + -: 83: QS_MEM_APP(); \ + -: 84: QS_CRIT_EXIT() + -: 85: + -: 86:// helper macro to trace state exit + -: 87:#define QS_STATE_EXIT_(state_, qsId_) \ + -: 88: QS_CRIT_ENTRY(); \ + -: 89: QS_MEM_SYS(); \ + -: 90: QS_BEGIN_PRE_(QS_QEP_STATE_EXIT, (qsId_)) \ + -: 91: QS_OBJ_PRE_(this); \ + -: 92: QS_FUN_PRE_(state_); \ + -: 93: QS_END_PRE_() \ + -: 94: QS_MEM_APP(); \ + -: 95: QS_CRIT_EXIT() + -: 96: + -: 97://! @endcond + -: 98://============================================================================ + -: 99: + -: 100://$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 101:// Check for the minimum required QP version + -: 102:#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U)) + -: 103:#error qpcpp version 7.3.0 or higher required + -: 104:#endif + -: 105://$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 106: + -: 107://$define${QEP::versionStr[]} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 108:namespace QP { + -: 109: + -: 110:} // namespace QP + -: 111://$enddef${QEP::versionStr[]} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 112: + -: 113://$define${QEP::QHsm} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 114:namespace QP { + -: 115: + -: 116://${QEP::QHsm} ............................................................... + -: 117: + -: 118://${QEP::QHsm::QHsm} ......................................................... + 3: 119:QHsm::QHsm(QStateHandler const initial) noexcept + 3: 120:: QAsm() + -: 121:{ + 3: 122: m_state.fun = Q_STATE_CAST(&top); + 3: 123: m_temp.fun = initial; + 3: 124:} + -: 125: + -: 126://${QEP::QHsm::init} ......................................................... + 3: 127:void QHsm::init( + -: 128: void const * const e, + -: 129: std::uint_fast8_t const qsId) + -: 130:{ + -: 131: QF_CRIT_STAT + -: 132: + -: 133: #ifdef Q_SPY + 3: 134: QS_CRIT_ENTRY(); + 3: 135: QS_MEM_SYS(); + 3: 136: if ((QS::priv_.flags & 0x01U) == 0U) { + 3: 137: QS::priv_.flags |= 0x01U; + 3: 138: QS_MEM_APP(); + 3: 139: QS_CRIT_EXIT(); + 3: 140: QS_FUN_DICTIONARY(&QP::QHsm::top); + -: 141: } + -: 142: else { + #####: 143: QS_MEM_APP(); + #####: 144: QS_CRIT_EXIT(); + -: 145: } + -: 146: #else + -: 147: Q_UNUSED_PAR(qsId); + -: 148: #endif + -: 149: + 3: 150: QStateHandler t = m_state.fun; + -: 151: + 3: 152: QF_CRIT_ENTRY(); + 3*: 153: Q_REQUIRE_INCRIT(200, (m_temp.fun != nullptr) + -: 154: && (t == Q_STATE_CAST(&top))); + 3: 155: QF_CRIT_EXIT(); + -: 156: + -: 157: // execute the top-most initial tran. + 3: 158: QState r = (*m_temp.fun)(this, Q_EVT_CAST(QEvt)); + -: 159: + 3: 160: QF_CRIT_ENTRY(); + -: 161: // the top-most initial tran. must be taken + 3*: 162: Q_ASSERT_INCRIT(210, r == Q_RET_TRAN); + -: 163: + 3: 164: QS_MEM_SYS(); + 3: 165: QS_BEGIN_PRE_(QS_QEP_STATE_INIT, qsId) + 3: 166: QS_OBJ_PRE_(this); // this state machine object + 3: 167: QS_FUN_PRE_(t); // the source state + 3: 168: QS_FUN_PRE_(m_temp.fun); // the target of the initial tran. + 3: 169: QS_END_PRE_() + 3: 170: QS_MEM_APP(); + -: 171: + 3: 172: QF_CRIT_EXIT(); + -: 173: + -: 174: // drill down into the state hierarchy with initial transitions... + 3: 175: std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit + 6: 176: do { + 6: 177: QStateHandler path[MAX_NEST_DEPTH_]; // tran entry path array + 6: 178: std::int_fast8_t ip = 0; // tran entry path index + -: 179: + 6: 180: path[0] = m_temp.fun; + 6: 181: static_cast(QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG)); + 12: 182: while (m_temp.fun != t) { + 6: 183: ++ip; + 6: 184: path[ip] = m_temp.fun; + 6: 185: static_cast(QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG)); + -: 186: } + 6: 187: QF_CRIT_ENTRY(); + -: 188: // The initial transition source state must be reached + -: 189: // Too many state nesting levels or "malformed" HSM. + 6*: 190: Q_ASSERT_INCRIT(220, m_temp.fun == t); + 6: 191: QF_CRIT_EXIT(); + -: 192: + 6: 193: m_temp.fun = path[0]; + -: 194: + -: 195: // retrace the entry path in reverse (desired) order... + 12: 196: do { + -: 197: // enter path[ip] + 12: 198: if (QHSM_RESERVED_EVT_(path[ip], Q_ENTRY_SIG) + -: 199: == Q_RET_HANDLED) + -: 200: { + 12: 201: QS_STATE_ENTRY_(path[ip], qsId); + -: 202: } + 12: 203: --ip; + 12: 204: } while (ip >= 0); + -: 205: + 6: 206: t = path[0]; // current state becomes the new source + -: 207: + 6: 208: r = QHSM_RESERVED_EVT_(t, Q_INIT_SIG); // execute initial tran. + -: 209: + -: 210: #ifdef Q_SPY + 6: 211: if (r == Q_RET_TRAN) { + 3: 212: QS_CRIT_ENTRY(); + 3: 213: QS_MEM_SYS(); + 3: 214: QS_BEGIN_PRE_(QS_QEP_STATE_INIT, qsId) + 3: 215: QS_OBJ_PRE_(this); // this state machine object + 3: 216: QS_FUN_PRE_(t); // the source state + 3: 217: QS_FUN_PRE_(m_temp.fun); // the target of the initial tran. + 3: 218: QS_END_PRE_() + 3: 219: QS_MEM_APP(); + 3: 220: QS_CRIT_EXIT(); + -: 221: } + -: 222: #endif // Q_SPY + -: 223: + 6: 224: --limit; + 6: 225: } while ((r == Q_RET_TRAN) && (limit > 0)); + -: 226: + 3: 227: QF_CRIT_ENTRY(); + -: 228: // Loop limit must not be reached. + -: 229: // Too many state nesting levels or likely "malformed" HSM + 3*: 230: Q_ENSURE_INCRIT(290, limit > 0); + -: 231: + 3: 232: QS_MEM_SYS(); + 3: 233: QS_BEGIN_PRE_(QS_QEP_INIT_TRAN, qsId) + 3: 234: QS_TIME_PRE_(); // time stamp + 3: 235: QS_OBJ_PRE_(this); // this state machine object + 3: 236: QS_FUN_PRE_(t); // the new active state + 3: 237: QS_END_PRE_() + 3: 238: QS_MEM_APP(); + -: 239: + 3: 240: QF_CRIT_EXIT(); + -: 241: + 3: 242: m_state.fun = t; // change the current active state + -: 243: #ifndef Q_UNSAFE + 3: 244: m_temp.uint = ~m_state.uint; + -: 245: #endif + 3: 246:} + -: 247: + -: 248://${QEP::QHsm::dispatch} ..................................................... + 18: 249:void QHsm::dispatch( + -: 250: QEvt const * const e, + -: 251: std::uint_fast8_t const qsId) + -: 252:{ + -: 253: #ifndef Q_SPY + -: 254: Q_UNUSED_PAR(qsId); + -: 255: #endif + -: 256: + 18: 257: QStateHandler s = m_state.fun; + 18: 258: QStateHandler t = s; + -: 259: QF_CRIT_STAT + -: 260: + 18: 261: QF_CRIT_ENTRY(); + 18*: 262: Q_REQUIRE_INCRIT(300, (s != Q_STATE_CAST(0)) + -: 263: && (m_state.uint == static_cast(~m_temp.uint))); + 18*: 264: Q_REQUIRE_INCRIT(302, QEvt::verify_(e)); + -: 265: + 18: 266: QS_MEM_SYS(); + 18: 267: QS_BEGIN_PRE_(QS_QEP_DISPATCH, qsId) + 18: 268: QS_TIME_PRE_(); // time stamp + 18: 269: QS_SIG_PRE_(e->sig); // the signal of the event + 18: 270: QS_OBJ_PRE_(this); // this state machine object + 18: 271: QS_FUN_PRE_(s); // the current state + 18: 272: QS_END_PRE_() + 18: 273: QS_MEM_APP(); + -: 274: + 18: 275: QF_CRIT_EXIT(); + -: 276: + -: 277: // process the event hierarchically... + 18: 278: QState r; + 18: 279: m_temp.fun = s; + 18: 280: std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit + 43: 281: do { + 43: 282: s = m_temp.fun; + 43: 283: r = (*s)(this, e); // invoke state handler s + -: 284: + 43: 285: if (r == Q_RET_UNHANDLED) { // unhandled due to a guard? + -: 286: + 2: 287: QS_CRIT_ENTRY(); + 2: 288: QS_MEM_SYS(); + 2: 289: QS_BEGIN_PRE_(QS_QEP_UNHANDLED, qsId) + 2: 290: QS_SIG_PRE_(e->sig); // the signal of the event + 2: 291: QS_OBJ_PRE_(this); // this state machine object + 2: 292: QS_FUN_PRE_(s); // the current state + 2: 293: QS_END_PRE_() + 2: 294: QS_MEM_APP(); + 2: 295: QS_CRIT_EXIT(); + -: 296: + 2: 297: r = QHSM_RESERVED_EVT_(s, Q_EMPTY_SIG); // superstate of s + -: 298: } + -: 299: + 43: 300: --limit; + 43: 301: } while ((r == Q_RET_SUPER) && (limit > 0)); + -: 302: + 18: 303: QF_CRIT_ENTRY(); + 18*: 304: Q_ASSERT_INCRIT(310, limit > 0); + 18: 305: QF_CRIT_EXIT(); + -: 306: + 18: 307: if (r >= Q_RET_TRAN) { // regular tran. taken? + 14: 308: QStateHandler path[MAX_NEST_DEPTH_]; + -: 309: + 14: 310: path[0] = m_temp.fun; // tran. target + 14: 311: path[1] = t; // current state + 14: 312: path[2] = s; // tran. source + -: 313: + -: 314: // exit current state to tran. source s... + 14: 315: limit = MAX_NEST_DEPTH_; // loop hard limit + 26: 316: for (; (t != s) && (limit > 0); t = m_temp.fun) { + -: 317: // exit from t + 12: 318: if (QHSM_RESERVED_EVT_(t, Q_EXIT_SIG) == Q_RET_HANDLED) { + 12: 319: QS_STATE_EXIT_(t, qsId); + -: 320: // find superstate of t + 12: 321: static_cast(QHSM_RESERVED_EVT_(t, Q_EMPTY_SIG)); + -: 322: } + 12: 323: --limit; + -: 324: } + 14: 325: QF_CRIT_ENTRY(); + 14*: 326: Q_ASSERT_INCRIT(320, limit > 0); + 14: 327: QF_CRIT_EXIT(); + -: 328: + 14: 329: std::int_fast8_t ip = hsm_tran(path, qsId); // take the tran. + -: 330: + -: 331: #ifdef Q_SPY + 14: 332: if (r == Q_RET_TRAN_HIST) { + 3: 333: QS_CRIT_ENTRY(); + 3: 334: QS_MEM_SYS(); + 3: 335: QS_BEGIN_PRE_(QS_QEP_TRAN_HIST, qsId) + 3: 336: QS_OBJ_PRE_(this); // this state machine object + 3: 337: QS_FUN_PRE_(t); // the source of the transition + 3: 338: QS_FUN_PRE_(path[0]); // the target of the tran. to history + 3: 339: QS_END_PRE_() + 3: 340: QS_MEM_APP(); + 3: 341: QS_CRIT_EXIT(); + -: 342: } + -: 343: #endif // Q_SPY + -: 344: + -: 345: // execute state entry actions in the desired order... + 31: 346: for (; ip >= 0; --ip) { + -: 347: // enter path[ip] + 17: 348: if (QHSM_RESERVED_EVT_(path[ip], Q_ENTRY_SIG) + -: 349: == Q_RET_HANDLED) + -: 350: { + 17: 351: QS_STATE_ENTRY_(path[ip], qsId); + -: 352: } + -: 353: } + 14: 354: t = path[0]; // stick the target into register + 14: 355: m_temp.fun = t; // update the next state + -: 356: + -: 357: // drill into the target hierarchy... + 21: 358: while (QHSM_RESERVED_EVT_(t, Q_INIT_SIG) == Q_RET_TRAN) { + -: 359: + 7: 360: QS_CRIT_ENTRY(); + 7: 361: QS_MEM_SYS(); + 7: 362: QS_BEGIN_PRE_(QS_QEP_STATE_INIT, qsId) + 7: 363: QS_OBJ_PRE_(this); // this state machine object + 7: 364: QS_FUN_PRE_(t); // the source (pseudo)state + 7: 365: QS_FUN_PRE_(m_temp.fun); // the target of the tran. + 7: 366: QS_END_PRE_() + 7: 367: QS_MEM_APP(); + 7: 368: QS_CRIT_EXIT(); + -: 369: + 7: 370: ip = 0; + 7: 371: path[0] = m_temp.fun; + -: 372: + -: 373: // find superstate + 7: 374: static_cast(QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG)); + -: 375: + 11: 376: while ((m_temp.fun != t) && (ip < (MAX_NEST_DEPTH_ - 1))) { + 4: 377: ++ip; + 4: 378: path[ip] = m_temp.fun; + -: 379: // find superstate + 4: 380: static_cast( + 4: 381: QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG)); + -: 382: } + 7: 383: QF_CRIT_ENTRY(); + -: 384: // The initial transition source state must be reached. + -: 385: // Too many state nesting levels or "malformed" HSM. + 7*: 386: Q_ASSERT_INCRIT(330, m_temp.fun == t); + 7: 387: QF_CRIT_EXIT(); + -: 388: + 7: 389: m_temp.fun = path[0]; + -: 390: + -: 391: // retrace the entry path in reverse (correct) order... + 11: 392: do { + -: 393: // enter path[ip] + 11: 394: if (QHSM_RESERVED_EVT_(path[ip], Q_ENTRY_SIG) + -: 395: == Q_RET_HANDLED) + -: 396: { + 11: 397: QS_STATE_ENTRY_(path[ip], qsId); + -: 398: } + 11: 399: --ip; + 11: 400: } while (ip >= 0); + -: 401: + 7: 402: t = path[0]; // current state becomes the new source + -: 403: } + -: 404: + 14: 405: QS_CRIT_ENTRY(); + 14: 406: QS_MEM_SYS(); + 14: 407: QS_BEGIN_PRE_(QS_QEP_TRAN, qsId) + 14: 408: QS_TIME_PRE_(); // time stamp + 14: 409: QS_SIG_PRE_(e->sig); // the signal of the event + 14: 410: QS_OBJ_PRE_(this); // this state machine object + 14: 411: QS_FUN_PRE_(s); // the source of the tran. + 14: 412: QS_FUN_PRE_(t); // the new active state + 14: 413: QS_END_PRE_() + 14: 414: QS_MEM_APP(); + 14: 415: QS_CRIT_EXIT(); + -: 416: } + -: 417: + -: 418: #ifdef Q_SPY + 4: 419: else if (r == Q_RET_HANDLED) { + 2: 420: QS_CRIT_ENTRY(); + 2: 421: QS_MEM_SYS(); + 2: 422: QS_BEGIN_PRE_(QS_QEP_INTERN_TRAN, qsId) + 2: 423: QS_TIME_PRE_(); // time stamp + 2: 424: QS_SIG_PRE_(e->sig); // the signal of the event + 2: 425: QS_OBJ_PRE_(this); // this state machine object + 2: 426: QS_FUN_PRE_(s); // the source state + 2: 427: QS_END_PRE_() + 2: 428: QS_MEM_APP(); + 2: 429: QS_CRIT_EXIT(); + -: 430: } + -: 431: else { + 2: 432: QS_CRIT_ENTRY(); + 2: 433: QS_MEM_SYS(); + 2: 434: QS_BEGIN_PRE_(QS_QEP_IGNORED, qsId) + 2: 435: QS_TIME_PRE_(); // time stamp + 2: 436: QS_SIG_PRE_(e->sig); // the signal of the event + 2: 437: QS_OBJ_PRE_(this); // this state machine object + 2: 438: QS_FUN_PRE_(m_state.fun); // the current state + 2: 439: QS_END_PRE_() + 2: 440: QS_MEM_APP(); + 2: 441: QS_CRIT_EXIT(); + -: 442: } + -: 443: #endif // Q_SPY + -: 444: + 18: 445: m_state.fun = t; // change the current active state + -: 446: #ifndef Q_UNSAFE + 18: 447: m_temp.uint = ~m_state.uint; + -: 448: #endif + 18: 449:} + -: 450: + -: 451://${QEP::QHsm::isIn} ......................................................... + 5: 452:bool QHsm::isIn(QStateHandler const state) noexcept { + -: 453: QF_CRIT_STAT + 5: 454: QF_CRIT_ENTRY(); + 5*: 455: Q_REQUIRE_INCRIT(602, m_state.uint + -: 456: == static_cast(~m_temp.uint)); + 5: 457: QF_CRIT_EXIT(); + -: 458: + 5: 459: bool inState = false; // assume that this HSM is not in 'state' + -: 460: + -: 461: // scan the state hierarchy bottom-up + 5: 462: QStateHandler s = m_state.fun; + 5: 463: std::int_fast8_t limit = MAX_NEST_DEPTH_ + 1; // loop hard limit + 5: 464: QState r = Q_RET_SUPER; + 13: 465: for (; (r != Q_RET_IGNORED) && (limit > 0); --limit) { + 12: 466: if (s == state) { // do the states match? + -: 467: inState = true; // 'true' means that match found + -: 468: break; // break out of the for-loop + -: 469: } + -: 470: else { + 8: 471: r = QHSM_RESERVED_EVT_(s, Q_EMPTY_SIG); + 8: 472: s = m_temp.fun; + -: 473: } + -: 474: } + -: 475: + 5: 476: QF_CRIT_ENTRY(); + 5*: 477: Q_ENSURE_INCRIT(690, limit > 0); + 5: 478: QF_CRIT_EXIT(); + -: 479: + -: 480: #ifndef Q_UNSAFE + 5: 481: m_temp.uint = ~m_state.uint; + -: 482: #endif + -: 483: + 5: 484: return inState; // return the status + -: 485:} + -: 486: + -: 487://${QEP::QHsm::childState} ................................................... + 1: 488:QStateHandler QHsm::childState(QStateHandler const parent) noexcept { + 1: 489: QStateHandler child = m_state.fun; // start with the current state + 1: 490: bool isFound = false; // start with the child not found + -: 491: + -: 492: // establish stable state configuration + 1: 493: m_temp.fun = child; + 4: 494: QState r; + 4: 495: do { + -: 496: // is this the parent of the current child? + 4: 497: if (m_temp.fun == parent) { + -: 498: isFound = true; // child is found + -: 499: r = Q_RET_IGNORED; // break out of the loop + -: 500: } + -: 501: else { + 3: 502: child = m_temp.fun; + 3: 503: r = QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG); + -: 504: } + 4: 505: } while (r != Q_RET_IGNORED); // QHsm::top() state not reached + -: 506: + -: 507: #ifndef Q_UNSAFE + 1: 508: m_temp.uint = ~m_state.uint; + -: 509: #endif + -: 510: + -: 511: QF_CRIT_STAT + 1: 512: QF_CRIT_ENTRY(); + 1*: 513: Q_ASSERT_INCRIT(890, isFound); + 1: 514: QF_CRIT_EXIT(); + -: 515: + 1: 516: return child; // return the child + -: 517:} + -: 518: + -: 519://${QEP::QHsm::hsm_tran} ..................................................... + 14: 520:std::int_fast8_t QHsm::hsm_tran( + -: 521: QStateHandler (&path)[MAX_NEST_DEPTH_], + -: 522: std::uint_fast8_t const qsId) + -: 523:{ + -: 524: #ifndef Q_SPY + -: 525: Q_UNUSED_PAR(qsId); + -: 526: #endif + -: 527: + 14: 528: std::int_fast8_t ip = -1; // tran. entry path index + 14: 529: QStateHandler t = path[0]; + 14: 530: QStateHandler const s = path[2]; + -: 531: QF_CRIT_STAT + -: 532: + -: 533: // (a) check source==target (tran. to self)... + 14: 534: if (s == t) { + -: 535: // exit source s + 1: 536: if (QHSM_RESERVED_EVT_(s, Q_EXIT_SIG) == Q_RET_HANDLED) { + 1: 537: QS_STATE_EXIT_(s, qsId); + -: 538: } + -: 539: ip = 0; // enter the target + -: 540: } + -: 541: else { + -: 542: // find superstate of target + 13: 543: static_cast(QHSM_RESERVED_EVT_(t, Q_EMPTY_SIG)); + -: 544: + 13: 545: t = m_temp.fun; + -: 546: + -: 547: // (b) check source==target->super... + 13: 548: if (s == t) { + -: 549: ip = 0; // enter the target + -: 550: } + -: 551: else { + -: 552: // find superstate of src + 11: 553: static_cast(QHSM_RESERVED_EVT_(s, Q_EMPTY_SIG)); + -: 554: + -: 555: // (c) check source->super==target->super... + 11: 556: if (m_temp.fun == t) { + -: 557: // exit source s + 4: 558: if (QHSM_RESERVED_EVT_(s, Q_EXIT_SIG) == Q_RET_HANDLED) { + 4: 559: QS_STATE_EXIT_(s, qsId); + -: 560: } + -: 561: ip = 0; // enter the target + -: 562: } + -: 563: else { + -: 564: // (d) check source->super==target... + 7: 565: if (m_temp.fun == path[0]) { + -: 566: // exit source s + 2: 567: if (QHSM_RESERVED_EVT_(s, Q_EXIT_SIG) == Q_RET_HANDLED) { + 2: 568: QS_STATE_EXIT_(s, qsId); + -: 569: } + -: 570: } + -: 571: else { + -: 572: // (e) check rest of source==target->super->super.. + -: 573: // and store the entry path along the way + 5: 574: std::int_fast8_t iq = 0; // indicate that LCA was found + 5: 575: ip = 1; // enter target and its superstate + 5: 576: path[1] = t; // save the superstate of target + 5: 577: t = m_temp.fun; // save source->super + -: 578: + -: 579: // find target->super->super... + 5: 580: QState r = QHSM_RESERVED_EVT_(path[1], Q_EMPTY_SIG); + 14: 581: while ((r == Q_RET_SUPER) + 14: 582: && (ip < (MAX_NEST_DEPTH_ - 1))) + -: 583: { + 9: 584: ++ip; + 9: 585: path[ip] = m_temp.fun; // store the entry path + 9: 586: if (m_temp.fun == s) { // is it the source? + -: 587: iq = 1; // indicate that the LCA found + -: 588: --ip; // do not enter the source + -: 589: r = Q_RET_HANDLED; // terminate the loop + -: 590: } + -: 591: else { // it is not the source, keep going up + 9: 592: r = QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG); + -: 593: } + -: 594: } + 5: 595: QF_CRIT_ENTRY(); + -: 596: // Tran. source must be found within the nesting depth + -: 597: // Too many state nesting levels or "malformed" HSM. + 5*: 598: Q_ASSERT_INCRIT(510, r != Q_RET_SUPER); + 5: 599: QF_CRIT_EXIT(); + -: 600: + -: 601: // the LCA not found yet? + 5: 602: if (iq == 0) { + -: 603: // exit source s + 5: 604: if (QHSM_RESERVED_EVT_(s, Q_EXIT_SIG) + -: 605: == Q_RET_HANDLED) + -: 606: { + 5: 607: QS_STATE_EXIT_(s, qsId); + -: 608: } + -: 609: + -: 610: // (f) check the rest of source->super + -: 611: // == target->super->super... + 5: 612: iq = ip; + 5: 613: r = Q_RET_IGNORED; // indicate that the LCA NOT found + 15: 614: do { + 15: 615: if (t == path[iq]) { // is this the LCA? + 2: 616: r = Q_RET_HANDLED; // indicate the LCA found + 2: 617: ip = iq - 1; // do not enter the LCA + 2: 618: iq = -1; // cause termination of the loop + -: 619: } + -: 620: else { + 13: 621: --iq; // try lower superstate of target + -: 622: } + 15: 623: } while (iq >= 0); + -: 624: + -: 625: // the LCA not found yet? + 5: 626: if (r != Q_RET_HANDLED) { + -: 627: // (g) check each source->super->... + -: 628: // for each target->super... + -: 629: r = Q_RET_IGNORED; // keep looping + -: 630: std::int_fast8_t limit = MAX_NEST_DEPTH_; + 4: 631: do { + -: 632: // exit from t + 4: 633: if (QHSM_RESERVED_EVT_(t, Q_EXIT_SIG) + -: 634: == Q_RET_HANDLED) + -: 635: { + 4: 636: QS_STATE_EXIT_(t, qsId); + -: 637: // find superstate of t + 4: 638: static_cast( + 4: 639: QHSM_RESERVED_EVT_(t, Q_EMPTY_SIG)); + -: 640: } + 4: 641: t = m_temp.fun; // set to super of t + 4: 642: iq = ip; + 8: 643: do { + -: 644: // is this the LCA? + 8: 645: if (t == path[iq]) { + 3: 646: ip = iq - 1; // do not enter the LCA + 3: 647: iq = -1; // break out of inner loop + 3: 648: r = Q_RET_HANDLED; // break outer loop + -: 649: } + -: 650: else { + 5: 651: --iq; + -: 652: } + 8: 653: } while (iq >= 0); + -: 654: + 4: 655: --limit; + 4: 656: } while ((r != Q_RET_HANDLED) && (limit > 0)); + 3: 657: QF_CRIT_ENTRY(); + 3*: 658: Q_ASSERT_INCRIT(530, limit > 0); + 3: 659: QF_CRIT_EXIT(); + -: 660: } + -: 661: } + -: 662: } + -: 663: } + -: 664: } + -: 665: } + 14: 666: QF_CRIT_ENTRY(); + 14*: 667: Q_ENSURE_INCRIT(590, ip < MAX_NEST_DEPTH_); + 14: 668: QF_CRIT_EXIT(); + 14: 669: return ip; + -: 670:} + -: 671: + -: 672:} // namespace QP + -: 673://$enddef${QEP::QHsm} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/qutest/qhsm/test/qp.hpp.gcov b/qutest/qhsm/test/qp.hpp.gcov new file mode 100644 index 0000000..3a9266c --- /dev/null +++ b/qutest/qhsm/test/qp.hpp.gcov @@ -0,0 +1,1284 @@ + -: 0:Source:../../../../include/qp.hpp + -: 0:Graph:build/qep_hsm.gcno + -: 0:Data:build/qep_hsm.gcda + -: 0:Runs:3 + -: 1://$file${include::qp.hpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 2:// + -: 3:// Model: qpcpp.qm + -: 4:// File: ${include::qp.hpp} + -: 5:// + -: 6:// This code has been generated by QM 6.1.1 . + -: 7:// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. + -: 8:// + -: 9:// This code is covered by the following QP license: + -: 10:// License # : LicenseRef-QL-dual + -: 11:// Issued to : Any user of the QP/C++ real-time embedded framework + -: 12:// Framework(s) : qpcpp + -: 13:// Support ends : 2024-12-31 + -: 14:// License scope: + -: 15:// + -: 16:// Copyright (C) 2005 Quantum Leaps, LLC . + -: 17:// + -: 18:// Q u a n t u m L e a P s + -: 19:// ------------------------ + -: 20:// Modern Embedded Software + -: 21:// + -: 22:// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial + -: 23:// + -: 24:// This software is dual-licensed under the terms of the open source GNU + -: 25:// General Public License version 3 (or any later version), or alternatively, + -: 26:// under the terms of one of the closed source Quantum Leaps commercial + -: 27:// licenses. + -: 28:// + -: 29:// The terms of the open source GNU General Public License version 3 + -: 30:// can be found at: + -: 31:// + -: 32:// The terms of the closed source Quantum Leaps commercial licenses + -: 33:// can be found at: + -: 34:// + -: 35:// Redistributions in source code must retain this top-level comment block. + -: 36:// Plagiarizing this software to sidestep the license obligations is illegal. + -: 37:// + -: 38:// Contact information: + -: 39:// + -: 40:// + -: 41:// + -: 42://$endhead${include::qp.hpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 43:#ifndef QP_HPP_ + -: 44:#define QP_HPP_ + -: 45: + -: 46://============================================================================ + -: 47:#define QP_VERSION 734U + -: 48:#define QP_VERSION_STR "7.3.4" + -: 49: + -: 50://! Encrypted current QP release (7.3.4) and date (2024-03-21) + -: 51:#define QP_RELEASE 0x70C1EA11U + -: 52: + -: 53://============================================================================ + -: 54://! @cond INTERNAL + -: 55: + -: 56:#ifndef Q_SIGNAL_SIZE + -: 57:#define Q_SIGNAL_SIZE 2U + -: 58:#endif // ndef Q_SIGNAL_SIZE + -: 59: + -: 60:#ifndef QF_MAX_ACTIVE + -: 61:#define QF_MAX_ACTIVE 32U + -: 62:#endif + -: 63: + -: 64:#if (QF_MAX_ACTIVE > 64U) + -: 65:#error QF_MAX_ACTIVE exceeds the maximum of 64U; + -: 66:#endif + -: 67: + -: 68:#ifndef QF_MAX_TICK_RATE + -: 69:#define QF_MAX_TICK_RATE 1U + -: 70:#endif + -: 71: + -: 72:#if (QF_MAX_TICK_RATE > 15U) + -: 73:#error QF_MAX_TICK_RATE exceeds the maximum of 15U; + -: 74:#endif + -: 75: + -: 76:#ifndef QF_MAX_EPOOL + -: 77:#define QF_MAX_EPOOL 3U + -: 78:#endif + -: 79: + -: 80:#if (QF_MAX_EPOOL > 15U) + -: 81:#error QF_MAX_EPOOL exceeds the maximum of 15U; + -: 82:#endif + -: 83: + -: 84:#ifndef QF_TIMEEVT_CTR_SIZE + -: 85:#define QF_TIMEEVT_CTR_SIZE 4U + -: 86:#endif + -: 87: + -: 88:#if (QF_TIMEEVT_CTR_SIZE > 4U) + -: 89:#error QF_TIMEEVT_CTR_SIZE defined incorrectly, expected 1U, 2U, or 4U; + -: 90:#endif + -: 91: + -: 92:#ifndef QF_EVENT_SIZ_SIZE + -: 93:#define QF_EVENT_SIZ_SIZE 2U + -: 94:#endif + -: 95: + -: 96:#if (QF_EVENT_SIZ_SIZE > 4U) + -: 97:#error QF_EVENT_SIZ_SIZE defined incorrectly, expected 1U, 2U, or 4U; + -: 98:#endif + -: 99: + -: 100://! @endcond + -: 101://============================================================================ + -: 102://$declare${glob-types} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 103: + -: 104://${glob-types::int_t} ....................................................... + -: 105:using int_t = int; + -: 106: + -: 107://${glob-types::enum_t} ...................................................... + -: 108:using enum_t = int; + -: 109: + -: 110://${glob-types::float32_t} ................................................... + -: 111:using float32_t = float; + -: 112: + -: 113://${glob-types::float64_t} ................................................... + -: 114:using float64_t = double; + -: 115://$enddecl${glob-types} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 116: + -: 117://$declare${QEP} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 118:namespace QP { + -: 119: + -: 120://${QEP::versionStr[]} ....................................................... + -: 121:constexpr char const versionStr[] {QP_VERSION_STR}; + -: 122: + -: 123://${QEP::QSignal} ............................................................ + -: 124:#if (Q_SIGNAL_SIZE == 1U) + -: 125:using QSignal = std::uint8_t; + -: 126:#endif // (Q_SIGNAL_SIZE == 1U) + -: 127: + -: 128://${QEP::QSignal} ............................................................ + -: 129:#if (Q_SIGNAL_SIZE == 2U) + -: 130:using QSignal = std::uint16_t; + -: 131:#endif // (Q_SIGNAL_SIZE == 2U) + -: 132: + -: 133://${QEP::QSignal} ............................................................ + -: 134:#if (Q_SIGNAL_SIZE == 4U) + -: 135:using QSignal = std::uint32_t; + -: 136:#endif // (Q_SIGNAL_SIZE == 4U) + -: 137: + -: 138://${QEP::QEvt} ............................................................... + -: 139:class QEvt { + -: 140:public: + -: 141: QSignal sig; + -: 142: std::uint8_t volatile refCtr_; + -: 143: std::uint8_t evtTag_; + -: 144: + -: 145:public: + -: 146: static constexpr std::uint8_t MARKER {0xE0U}; + -: 147: + -: 148:#ifdef QEVT_DYN_CTOR + -: 149: enum DynEvt: std::uint8_t { DYNAMIC }; + -: 150:#endif // def QEVT_DYN_CTOR + -: 151: + -: 152:public: + -: 153: + -: 154:#ifdef QEVT_DYN_CTOR + -: 155: QEvt * ctor(DynEvt const dummy) noexcept; + -: 156:#endif // def QEVT_DYN_CTOR + -: 157: explicit constexpr QEvt(QSignal const s) noexcept + -: 158: : sig(s), + -: 159: refCtr_(0U), + -: 160: evtTag_(MARKER) + -: 161: {} + -: 162: QEvt() = delete; + 18: 163: static bool verify_(QEvt const * const e) noexcept { + 18: 164: return (e != nullptr) + 18: 165: && ((e->evtTag_ & 0xF0U) == MARKER); + -: 166: } + -: 167: std::uint_fast8_t getPoolNum_() const noexcept { + -: 168: return static_cast(evtTag_) & 0x0FU; + -: 169: } + -: 170:}; // class QEvt + -: 171: + -: 172://${QEP::QState} ............................................................. + -: 173:using QState = std::uint_fast8_t; + -: 174: + -: 175://${QEP::QStateHandler} ...................................................... + -: 176:using QStateHandler = QState (*)(void * const me, QEvt const * const e); + -: 177: + -: 178://${QEP::QActionHandler} ..................................................... + -: 179:using QActionHandler = QState (*)(void * const me); + -: 180: + -: 181://${QEP::QXThread} ........................................................... + -: 182:// forward declaration + -: 183:class QXThread; + -: 184: + -: 185://${QEP::QXThreadHandler} .................................................... + -: 186:using QXThreadHandler = void (*)(QXThread * const me); + -: 187: + -: 188://${QEP::QMState} ............................................................ + -: 189:struct QMState { + -: 190: QMState const * superstate; + -: 191: QStateHandler const stateHandler; + -: 192: QActionHandler const entryAction; + -: 193: QActionHandler const exitAction; + -: 194: QActionHandler const initAction; + -: 195:}; + -: 196: + -: 197://${QEP::QMTranActTable} ..................................................... + -: 198:struct QMTranActTable { + -: 199: QMState const * target; + -: 200: QActionHandler const act[1]; + -: 201:}; + -: 202: + -: 203://${QEP::QAsmAttr} ........................................................... + -: 204:union QAsmAttr { + -: 205: QStateHandler fun; + -: 206: QActionHandler act; + -: 207: QXThreadHandler thr; + -: 208: QMState const *obj; + -: 209: QMTranActTable const *tatbl; + -: 210:#ifndef Q_UNSAFE + -: 211: std::uintptr_t uint; + -: 212:#endif + 3: 213: constexpr QAsmAttr() : fun(nullptr) {} + -: 214:}; + -: 215: + -: 216://${QEP::Q_USER_SIG} ......................................................... + -: 217:constexpr enum_t Q_USER_SIG {4}; + -: 218: + -: 219://${QEP::QAsm} ............................................................... + -: 220:class QAsm { + -: 221:protected: + -: 222: QAsmAttr m_state; + -: 223: QAsmAttr m_temp; + -: 224: + -: 225:public: + -: 226: + -: 227: //! All possible return values from state-handlers + -: 228: //! @note + -: 229: //! The order is important for algorithmic correctness. + -: 230: enum QStateRet : QState { + -: 231: // unhandled and need to "bubble up" + -: 232: Q_RET_SUPER, //!< event passed to superstate to handle + -: 233: Q_RET_SUPER_SUB, //!< event passed to submachine superstate + -: 234: Q_RET_UNHANDLED, //!< event unhandled due to a guard + -: 235: + -: 236: // handled and do not need to "bubble up" + -: 237: Q_RET_HANDLED, //!< event handled (internal transition) + -: 238: Q_RET_IGNORED, //!< event silently ignored (bubbled up to top) + -: 239: + -: 240: // entry/exit + -: 241: Q_RET_ENTRY, //!< state entry action executed + -: 242: Q_RET_EXIT, //!< state exit action executed + -: 243: + -: 244: // no side effects + -: 245: Q_RET_NULL, //!< return value without any effect + -: 246: + -: 247: // transitions need to execute transition-action table in QP::QMsm + -: 248: Q_RET_TRAN, //!< regular transition + -: 249: Q_RET_TRAN_INIT, //!< initial transition in a state or submachine + -: 250: Q_RET_TRAN_EP, //!< entry-point transition into a submachine + -: 251: + -: 252: // transitions that additionally clobber QHsm.m_state + -: 253: Q_RET_TRAN_HIST, //!< transition to history of a given state + -: 254: Q_RET_TRAN_XP //!< exit-point transition out of a submachine + -: 255: }; + -: 256: + -: 257: //! Reserved signals by the QP-framework. + -: 258: enum ReservedSig : QSignal { + -: 259: Q_EMPTY_SIG, //!< signal to execute the default case + -: 260: Q_ENTRY_SIG, //!< signal for entry actions + -: 261: Q_EXIT_SIG, //!< signal for exit actions + -: 262: Q_INIT_SIG //!< signal for nested initial transitions + -: 263: }; + -: 264: + -: 265:protected: + 3: 266: explicit QAsm() noexcept + 3: 267: : m_state(), + 3: 268: m_temp () + -: 269: {} + -: 270: + -: 271:public: + -: 272: + -: 273:#ifdef Q_XTOR + -: 274: virtual ~QAsm() noexcept { + -: 275: // empty + -: 276: } + -: 277:#endif // def Q_XTOR + -: 278: virtual void init( + -: 279: void const * const e, + -: 280: std::uint_fast8_t const qsId) = 0; + -: 281: virtual void init(std::uint_fast8_t const qsId) { + -: 282: this->init(nullptr, qsId); + -: 283: } + -: 284: virtual void dispatch( + -: 285: QEvt const * const e, + -: 286: std::uint_fast8_t const qsId) = 0; + -: 287: virtual bool isIn(QStateHandler const state) noexcept { + -: 288: static_cast(state); + -: 289: return false; + -: 290: } + -: 291: QStateHandler state() const noexcept { + -: 292: return m_state.fun; + -: 293: } + -: 294: QMState const * stateObj() const noexcept { + -: 295: return m_state.obj; + -: 296: } + -: 297: + -: 298:#ifdef Q_SPY + -: 299: virtual QStateHandler getStateHandler() noexcept { + -: 300: return m_state.fun; + -: 301: } + -: 302:#endif // def Q_SPY + #####: 303: static QState top( + -: 304: void * const me, + -: 305: QEvt const * const e) noexcept + -: 306: { + #####: 307: static_cast(me); + #####: 308: static_cast(e); + #####: 309: return Q_RET_IGNORED; // the top state ignores all events + -: 310: } + -: 311: + -: 312:protected: + -: 313: QState tran(QStateHandler const target) noexcept { + -: 314: m_temp.fun = target; + -: 315: return Q_RET_TRAN; + -: 316: } + -: 317: QState tran_hist(QStateHandler const hist) noexcept { + -: 318: m_temp.fun = hist; + -: 319: return Q_RET_TRAN_HIST; + -: 320: } + -: 321: QState super(QStateHandler const superstate) noexcept { + -: 322: m_temp.fun = superstate; + -: 323: return Q_RET_SUPER; + -: 324: } + -: 325: QState qm_tran(void const * const tatbl) noexcept { + -: 326: m_temp.tatbl = static_cast(tatbl); + -: 327: return Q_RET_TRAN; + -: 328: } + -: 329: QState qm_tran_init(void const * const tatbl) noexcept { + -: 330: m_temp.tatbl = static_cast(tatbl); + -: 331: return Q_RET_TRAN_INIT; + -: 332: } + -: 333: QState qm_tran_hist( + -: 334: QMState const * const hist, + -: 335: void const * const tatbl) noexcept + -: 336: { + -: 337: m_state.obj = hist; + -: 338: m_temp.tatbl = static_cast(tatbl); + -: 339: return Q_RET_TRAN_HIST; + -: 340: } + -: 341: QState qm_tran_ep(void const * const tatbl) noexcept { + -: 342: m_temp.tatbl = static_cast(tatbl); + -: 343: return Q_RET_TRAN_EP; + -: 344: } + -: 345: QState qm_tran_xp( + -: 346: QActionHandler const xp, + -: 347: void const * const tatbl) noexcept + -: 348: { + -: 349: m_state.act = xp; + -: 350: m_temp.tatbl = static_cast(tatbl); + -: 351: return Q_RET_TRAN_XP; + -: 352: } + -: 353: + -: 354:#ifdef Q_SPY + -: 355: QState qm_entry(QMState const * const s) noexcept { + -: 356: m_temp.obj = s; + -: 357: return Q_RET_ENTRY; + -: 358: } + -: 359:#endif // def Q_SPY + -: 360: + -: 361:#ifndef Q_SPY + -: 362: QState qm_entry(QMState const * const s) noexcept { + -: 363: static_cast(s); // unused parameter + -: 364: return Q_RET_ENTRY; + -: 365: } + -: 366:#endif // ndef Q_SPY + -: 367: + -: 368:#ifdef Q_SPY + -: 369: QState qm_exit(QMState const * const s) noexcept { + -: 370: m_temp.obj = s; + -: 371: return Q_RET_EXIT; + -: 372: } + -: 373:#endif // def Q_SPY + -: 374: + -: 375:#ifndef Q_SPY + -: 376: QState qm_exit(QMState const * const s) noexcept { + -: 377: static_cast(s); // unused parameter + -: 378: return Q_RET_EXIT; + -: 379: } + -: 380:#endif // ndef Q_SPY + -: 381: QState qm_sm_exit(QMState const * const s) noexcept { + -: 382: m_temp.obj = s; + -: 383: return Q_RET_EXIT; + -: 384: } + -: 385: QState qm_super_sub(QMState const * const s) noexcept { + -: 386: m_temp.obj = s; + -: 387: return Q_RET_SUPER_SUB; + -: 388: } + -: 389:}; // class QAsm + -: 390: + -: 391://${QEP::QHsm} ............................................................... + -: 392:class QHsm : public QP::QAsm { + -: 393:public: + -: 394: static constexpr std::int_fast8_t MAX_NEST_DEPTH_{6}; + -: 395: + -: 396:protected: + -: 397: explicit QHsm(QStateHandler const initial) noexcept; + -: 398: + -: 399:public: + -: 400: void init( + -: 401: void const * const e, + -: 402: std::uint_fast8_t const qsId) override; + #####: 403: void init(std::uint_fast8_t const qsId) override { + #####: 404: this->init(nullptr, qsId); + #####: 405: } + -: 406: void dispatch( + -: 407: QEvt const * const e, + -: 408: std::uint_fast8_t const qsId) override; + -: 409: bool isIn(QStateHandler const state) noexcept override; + -: 410: QStateHandler childState(QStateHandler const parent) noexcept; + -: 411: + -: 412:#ifdef Q_SPY + #####: 413: QStateHandler getStateHandler() noexcept override { + #####: 414: return m_state.fun; + -: 415: } + -: 416:#endif // def Q_SPY + -: 417: + -: 418:private: + -: 419: std::int_fast8_t hsm_tran( + -: 420: QStateHandler (&path)[MAX_NEST_DEPTH_], + -: 421: std::uint_fast8_t const qsId); + -: 422:}; // class QHsm + -: 423: + -: 424://${QEP::QMsm} ............................................................... + -: 425:class QMsm : public QP::QAsm { + -: 426:protected: + -: 427: explicit QMsm(QStateHandler const initial) noexcept; + -: 428: + -: 429:public: + -: 430: void init( + -: 431: void const * const e, + -: 432: std::uint_fast8_t const qsId) override; + -: 433: void init(std::uint_fast8_t const qsId) override { + -: 434: this->init(nullptr, qsId); + -: 435: } + -: 436: void dispatch( + -: 437: QEvt const * const e, + -: 438: std::uint_fast8_t const qsId) override; + -: 439: + -: 440:#ifdef Q_SPY + -: 441: QStateHandler getStateHandler() noexcept override { + -: 442: return m_state.obj->stateHandler; + -: 443: } + -: 444:#endif // def Q_SPY + -: 445: bool isIn(QStateHandler const state) noexcept override; + -: 446: + -: 447: //! @deprecated instead use: QMsm::isIn() + -: 448: bool isInState(QMState const * const stateObj) const noexcept; + -: 449: QMState const * childStateObj(QMState const * const parent) const noexcept; + -: 450: + -: 451:private: + -: 452: QState execTatbl_( + -: 453: QMTranActTable const * const tatbl, + -: 454: std::uint_fast8_t const qsId); + -: 455: void exitToTranSource_( + -: 456: QMState const * const cs, + -: 457: QMState const * const ts, + -: 458: std::uint_fast8_t const qsId); + -: 459: QState enterHistory_( + -: 460: QMState const * const hist, + -: 461: std::uint_fast8_t const qsId); + -: 462: + -: 463:public: + -: 464: QMState const * topQMState() const noexcept; + -: 465:}; // class QMsm + -: 466: + -: 467:} // namespace QP + -: 468://$enddecl${QEP} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 469: + -: 470://$declare${QEP-macros} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 471: + -: 472://${QEP-macros::Q_STATE_DECL} ................................................ + -: 473:#define Q_STATE_DECL(state_) \ + -: 474: QP::QState state_ ## _h(QP::QEvt const * const e); \ + -: 475: static QP::QState state_(void * const me, QP::QEvt const * const e) + -: 476: + -: 477://${QEP-macros::Q_STATE_DEF} ................................................. + -: 478:#define Q_STATE_DEF(subclass_, state_) \ + -: 479: QP::QState subclass_::state_(void * const me, QP::QEvt const * const e) { \ + -: 480: return static_cast(me)->state_ ## _h(e); } \ + -: 481: QP::QState subclass_::state_ ## _h(QP::QEvt const * const e) + -: 482: + -: 483://${QEP-macros::Q_HANDLED} ................................................... + -: 484:#define Q_HANDLED() (Q_RET_HANDLED) + -: 485: + -: 486://${QEP-macros::Q_UNHANDLED} ................................................. + -: 487:#define Q_UNHANDLED() (Q_RET_UNHANDLED) + -: 488: + -: 489://${QEP-macros::Q_EVT_CAST} .................................................. + -: 490:#define Q_EVT_CAST(subclass_) (static_cast(e)) + -: 491: + -: 492://${QEP-macros::Q_STATE_CAST} ................................................ + -: 493:#define Q_STATE_CAST(handler_) \ + -: 494: (reinterpret_cast(handler_)) + -: 495: + -: 496://${QEP-macros::QM_STATE_DECL} ............................................... + -: 497:#define QM_STATE_DECL(state_) \ + -: 498: QP::QState state_ ## _h(QP::QEvt const * const e); \ + -: 499: static QP::QState state_(void * const me, QP::QEvt const * const e); \ + -: 500: static QP::QMState const state_ ## _s + -: 501: + -: 502://${QEP-macros::QM_SM_STATE_DECL} ............................................ + -: 503:#define QM_SM_STATE_DECL(subm_, state_) \ + -: 504: QP::QState state_ ## _h(QP::QEvt const * const e);\ + -: 505: static QP::QState state_(void * const me, QP::QEvt const * const e); \ + -: 506: static SM_ ## subm_ const state_ ## _s + -: 507: + -: 508://${QEP-macros::QM_ACTION_DECL} .............................................. + -: 509:#define QM_ACTION_DECL(action_) \ + -: 510: QP::QState action_ ## _h(); \ + -: 511: static QP::QState action_(void * const me) + -: 512: + -: 513://${QEP-macros::QM_STATE_DEF} ................................................ + -: 514:#define QM_STATE_DEF(subclass_, state_) \ + -: 515: QP::QState subclass_::state_(void * const me, QP::QEvt const * const e) {\ + -: 516: return static_cast(me)->state_ ## _h(e); } \ + -: 517: QP::QState subclass_::state_ ## _h(QP::QEvt const * const e) + -: 518: + -: 519://${QEP-macros::QM_ACTION_DEF} ............................................... + -: 520:#define QM_ACTION_DEF(subclass_, action_) \ + -: 521: QP::QState subclass_::action_(void * const me) { \ + -: 522: return static_cast(me)->action_ ## _h(); } \ + -: 523: QP::QState subclass_::action_ ## _h() + -: 524: + -: 525://${QEP-macros::QM_HANDLED} .................................................. + -: 526:#define QM_HANDLED() (Q_RET_HANDLED) + -: 527: + -: 528://${QEP-macros::QM_UNHANDLED} ................................................ + -: 529:#define QM_UNHANDLED() (Q_RET_HANDLED) + -: 530: + -: 531://${QEP-macros::QM_SUPER} .................................................... + -: 532:#define QM_SUPER() (Q_RET_SUPER) + -: 533: + -: 534://${QEP-macros::QM_STATE_NULL} ............................................... + -: 535:#define QM_STATE_NULL (nullptr) + -: 536: + -: 537://${QEP-macros::Q_ACTION_NULL} ............................................... + -: 538:#define Q_ACTION_NULL (nullptr) + -: 539: + -: 540://${QEP-macros::Q_UNUSED_PAR} ................................................ + -: 541:#define Q_UNUSED_PAR(par_) (static_cast(par_)) + -: 542: + -: 543://${QEP-macros::Q_DIM} ....................................................... + -: 544:#define Q_DIM(array_) (sizeof(array_) / sizeof((array_)[0U])) + -: 545: + -: 546://${QEP-macros::Q_UINT2PTR_CAST} ............................................. + -: 547:#define Q_UINT2PTR_CAST(type_, uint_) (reinterpret_cast(uint_)) + -: 548: + -: 549://${QEP-macros::INIT} ........................................................ + -: 550:#ifdef Q_SPY + -: 551:#define INIT(qsId_) init((qsId_)) + -: 552:#endif // def Q_SPY + -: 553: + -: 554://${QEP-macros::INIT} ........................................................ + -: 555:#ifndef Q_SPY + -: 556:#define INIT(dummy) init(0U) + -: 557:#endif // ndef Q_SPY + -: 558: + -: 559://${QEP-macros::DISPATCH} .................................................... + -: 560:#ifdef Q_SPY + -: 561:#define DISPATCH(e_, qsId_) dispatch((e_), (qsId_)) + -: 562:#endif // def Q_SPY + -: 563: + -: 564://${QEP-macros::DISPATCH} .................................................... + -: 565:#ifndef Q_SPY + -: 566:#define DISPATCH(e_, dummy) dispatch((e_), 0U) + -: 567:#endif // ndef Q_SPY + -: 568://$enddecl${QEP-macros} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 569: + -: 570://$declare${QF::types} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 571:namespace QP { + -: 572: + -: 573://${QF::types::QPrioSpec} .................................................... + -: 574:using QPrioSpec = std::uint16_t; + -: 575: + -: 576://${QF::types::QTimeEvtCtr} .................................................. + -: 577:#if (QF_TIMEEVT_CTR_SIZE == 1U) + -: 578:using QTimeEvtCtr = std::uint8_t; + -: 579:#endif // (QF_TIMEEVT_CTR_SIZE == 1U) + -: 580: + -: 581://${QF::types::QTimeEvtCtr} .................................................. + -: 582:#if (QF_TIMEEVT_CTR_SIZE == 2U) + -: 583:using QTimeEvtCtr = std::uint16_t; + -: 584:#endif // (QF_TIMEEVT_CTR_SIZE == 2U) + -: 585: + -: 586://${QF::types::QTimeEvtCtr} .................................................. + -: 587:#if (QF_TIMEEVT_CTR_SIZE == 4U) + -: 588:using QTimeEvtCtr = std::uint32_t; + -: 589:#endif // (QF_TIMEEVT_CTR_SIZE == 4U) + -: 590: + -: 591://${QF::types::QPSetBits} .................................................... + -: 592:#if (QF_MAX_ACTIVE <= 8U) + -: 593:using QPSetBits = std::uint8_t; + -: 594:#endif // (QF_MAX_ACTIVE <= 8U) + -: 595: + -: 596://${QF::types::QPSetBits} .................................................... + -: 597:#if (8U < QF_MAX_ACTIVE) && (QF_MAX_ACTIVE <= 16U) + -: 598:using QPSetBits = std::uint16_t; + -: 599:#endif // (8U < QF_MAX_ACTIVE) && (QF_MAX_ACTIVE <= 16U) + -: 600: + -: 601://${QF::types::QPSetBits} .................................................... + -: 602:#if (16 < QF_MAX_ACTIVE) + -: 603:using QPSetBits = std::uint32_t; + -: 604:#endif // (16 < QF_MAX_ACTIVE) + -: 605: + -: 606://${QF::types::QF_LOG2} ...................................................... + -: 607:#ifndef QF_LOG2 + -: 608:std::uint_fast8_t QF_LOG2(QP::QPSetBits x) noexcept; + -: 609:#endif // ndef QF_LOG2 + -: 610: + -: 611://${QF::types::QPSet} ........................................................ + -: 612:class QPSet { + -: 613:private: + -: 614: QPSetBits m_bits[((QF_MAX_ACTIVE + (8U*sizeof(QPSetBits))) - 1U)/(8U*sizeof(QPSetBits))]; + -: 615: + -: 616:public: + -: 617: void setEmpty() noexcept { + -: 618: m_bits[0] = 0U; + -: 619: #if (QF_MAX_ACTIVE > 32) + -: 620: m_bits[1] = 0U; + -: 621: #endif + -: 622: } + -: 623: bool isEmpty() const noexcept { + -: 624: #if (QF_MAX_ACTIVE <= 32U) + -: 625: return (m_bits[0] == 0U); + -: 626: #else + -: 627: return (m_bits[0] == 0U) ? (m_bits[1] == 0U) : false; + -: 628: #endif + -: 629: } + -: 630: bool notEmpty() const noexcept { + -: 631: #if (QF_MAX_ACTIVE <= 32U) + -: 632: return (m_bits[0] != 0U); + -: 633: #else + -: 634: return (m_bits[0] != 0U) ? true : (m_bits[1] != 0U); + -: 635: #endif + -: 636: } + -: 637: bool hasElement(std::uint_fast8_t const n) const noexcept { + -: 638: #if (QF_MAX_ACTIVE <= 32U) + -: 639: return (m_bits[0] & (static_cast(1U) << (n - 1U))) != 0U; + -: 640: #else + -: 641: return (n <= 32U) + -: 642: ? ((m_bits[0] & (static_cast(1U) << (n - 1U))) != 0U) + -: 643: : ((m_bits[1] & (static_cast(1U) << (n - 33U))) != 0U); + -: 644: #endif + -: 645: } + -: 646: void insert(std::uint_fast8_t const n) noexcept { + -: 647: #if (QF_MAX_ACTIVE <= 32U) + -: 648: m_bits[0] = (m_bits[0] | (static_cast(1U) << (n - 1U))); + -: 649: #else + -: 650: if (n <= 32U) { + -: 651: m_bits[0] = (m_bits[0] | (static_cast(1U) << (n - 1U))); + -: 652: } + -: 653: else { + -: 654: m_bits[1] = (m_bits[1] | (static_cast(1U) << (n - 33U))); + -: 655: } + -: 656: #endif + -: 657: } + -: 658: void remove(std::uint_fast8_t const n) noexcept { + -: 659: #if (QF_MAX_ACTIVE <= 32U) + -: 660: m_bits[0] = (m_bits[0] & static_cast(~(1U << (n - 1U)))); + -: 661: #else + -: 662: if (n <= 32U) { + -: 663: (m_bits[0] = (m_bits[0] & ~(static_cast(1U) << (n - 1U)))); + -: 664: } + -: 665: else { + -: 666: (m_bits[1] = (m_bits[1] & ~(static_cast(1U) << (n - 33U)))); + -: 667: } + -: 668: #endif + -: 669: } + -: 670: std::uint_fast8_t findMax() const noexcept { + -: 671: #if (QF_MAX_ACTIVE <= 32U) + -: 672: return QF_LOG2(m_bits[0]); + -: 673: #else + -: 674: return (m_bits[1] != 0U) + -: 675: ? (QF_LOG2(m_bits[1]) + 32U) + -: 676: : (QF_LOG2(m_bits[0])); + -: 677: #endif + -: 678: } + -: 679: + -: 680:#ifndef Q_UNSAFE + -: 681: void update_(QPSet * const dis) const noexcept { + -: 682: dis->m_bits[0] = ~m_bits[0]; + -: 683: #if (QF_MAX_ACTIVE > 32U) + -: 684: dis->m_bits[1] = ~m_bits[1]; + -: 685: #endif + -: 686: } + -: 687:#endif // ndef Q_UNSAFE + -: 688: + -: 689:#ifndef Q_UNSAFE + -: 690: bool verify_(QPSet const * const dis) const noexcept { + -: 691: #if (QF_MAX_ACTIVE <= 32U) + -: 692: return m_bits[0] == static_cast(~dis->m_bits[0]); + -: 693: #else + -: 694: return (m_bits[0] == static_cast(~dis->m_bits[0])) + -: 695: && (m_bits[1] == static_cast(~dis->m_bits[1])); + -: 696: #endif + -: 697: } + -: 698:#endif // ndef Q_UNSAFE + -: 699:}; // class QPSet + -: 700: + -: 701://${QF::types::QSubscrList} .................................................. + -: 702:class QSubscrList { + -: 703:private: + -: 704: QPSet m_set; + -: 705: + -: 706:#ifndef Q_UNSAFE + -: 707: QPSet m_set_dis; + -: 708:#endif // ndef Q_UNSAFE + -: 709: + -: 710: // friends... + -: 711: friend class QActive; + -: 712:}; // class QSubscrList + -: 713: + -: 714://${QF::types::QEQueue} ...................................................... + -: 715:class QEQueue; + -: 716: + -: 717:} // namespace QP + -: 718://$enddecl${QF::types} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 719: + -: 720://$declare${QF::QActive} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 721:namespace QP { + -: 722: + -: 723://${QF::QActive} ............................................................. + -: 724:class QActive : public QP::QAsm { + -: 725:protected: + -: 726: std::uint8_t m_prio; + -: 727: std::uint8_t m_pthre; + -: 728: + -: 729:#ifdef QACTIVE_THREAD_TYPE + -: 730: QACTIVE_THREAD_TYPE m_thread; + -: 731:#endif // def QACTIVE_THREAD_TYPE + -: 732: + -: 733:#ifdef QACTIVE_OS_OBJ_TYPE + -: 734: QACTIVE_OS_OBJ_TYPE m_osObject; + -: 735:#endif // def QACTIVE_OS_OBJ_TYPE + -: 736: + -: 737:#ifdef QACTIVE_EQUEUE_TYPE + -: 738: QACTIVE_EQUEUE_TYPE m_eQueue; + -: 739:#endif // def QACTIVE_EQUEUE_TYPE + -: 740: + -: 741:public: + -: 742: + -: 743:#ifndef Q_UNSAFE + -: 744: std::uint8_t m_prio_dis; + -: 745:#endif // ndef Q_UNSAFE + -: 746: + -: 747:#ifndef Q_UNSAFE + -: 748: std::uint8_t m_pthre_dis; + -: 749:#endif // ndef Q_UNSAFE + -: 750: static QActive * registry_[QF_MAX_ACTIVE + 1U]; + -: 751: static QSubscrList * subscrList_; + -: 752: static enum_t maxPubSignal_; + -: 753: + -: 754: // friends... + -: 755: friend class QTimeEvt; + -: 756: friend class QTicker; + -: 757: friend class QXThread; + -: 758: friend class QXMutex; + -: 759: friend class QXSemaphore; + -: 760: friend class QActiveDummy; + -: 761: friend class GuiQActive; + -: 762: friend class GuiQMActive; + -: 763: friend void schedLock(); + -: 764: + -: 765:protected: + -: 766: explicit QActive(QStateHandler const initial) noexcept + -: 767: : QAsm(), + -: 768: m_prio(0U), + -: 769: m_pthre(0U) + -: 770: { + -: 771: m_state.fun = Q_STATE_CAST(&top); + -: 772: m_temp.fun = initial; + -: 773: + -: 774: #ifndef Q_UNSAFE + -: 775: m_prio_dis = static_cast(~m_prio); + -: 776: m_pthre_dis = static_cast(~m_pthre); + -: 777: #endif + -: 778: } + -: 779: + -: 780:public: + -: 781: void init( + -: 782: void const * const e, + -: 783: std::uint_fast8_t const qsId) override + -: 784: { + -: 785: reinterpret_cast(this)->QHsm::init(e, qsId); + -: 786: } + -: 787: void init(std::uint_fast8_t const qsId) override { + -: 788: this->init(nullptr, qsId); + -: 789: } + -: 790: void dispatch( + -: 791: QEvt const * const e, + -: 792: std::uint_fast8_t const qsId) override + -: 793: { + -: 794: reinterpret_cast(this)->QHsm::dispatch(e, qsId); + -: 795: } + -: 796: bool isIn(QStateHandler const state) noexcept override { + -: 797: return reinterpret_cast(this)->QHsm::isIn(state); + -: 798: } + -: 799: QStateHandler childState(QStateHandler const parent) noexcept { + -: 800: return reinterpret_cast(this)->QHsm::childState(parent); + -: 801: } + -: 802: void setAttr( + -: 803: std::uint32_t attr1, + -: 804: void const * attr2 = nullptr); + -: 805: void start( + -: 806: QPrioSpec const prioSpec, + -: 807: QEvt const * * const qSto, + -: 808: std::uint_fast16_t const qLen, + -: 809: void * const stkSto, + -: 810: std::uint_fast16_t const stkSize, + -: 811: void const * const par); + -: 812: void start( + -: 813: QPrioSpec const prioSpec, + -: 814: QEvt const * * const qSto, + -: 815: std::uint_fast16_t const qLen, + -: 816: void * const stkSto, + -: 817: std::uint_fast16_t const stkSize) + -: 818: { + -: 819: this->start(prioSpec, qSto, qLen, stkSto, stkSize, nullptr); + -: 820: } + -: 821: + -: 822:#ifdef QACTIVE_CAN_STOP + -: 823: void stop(); + -: 824:#endif // def QACTIVE_CAN_STOP + -: 825: void register_() noexcept; + -: 826: void unregister_() noexcept; + -: 827: bool post_( + -: 828: QEvt const * const e, + -: 829: std::uint_fast16_t const margin, + -: 830: void const * const sender) noexcept; + -: 831: void postLIFO(QEvt const * const e) noexcept; + -: 832: QEvt const * get_() noexcept; + -: 833: static std::uint_fast16_t getQueueMin(std::uint_fast8_t const prio) noexcept; + -: 834: static void psInit( + -: 835: QSubscrList * const subscrSto, + -: 836: enum_t const maxSignal) noexcept; + -: 837: static void publish_( + -: 838: QEvt const * const e, + -: 839: void const * const sender, + -: 840: std::uint_fast8_t const qsId) noexcept; + -: 841: void subscribe(enum_t const sig) const noexcept; + -: 842: void unsubscribe(enum_t const sig) const noexcept; + -: 843: void unsubscribeAll() const noexcept; + -: 844: bool defer( + -: 845: QEQueue * const eq, + -: 846: QEvt const * const e) const noexcept; + -: 847: bool recall(QEQueue * const eq) noexcept; + -: 848: std::uint_fast16_t flushDeferred( + -: 849: QEQueue * const eq, + -: 850: std::uint_fast16_t const num = 0xFFFFU) const noexcept; + -: 851: std::uint_fast8_t getPrio() const noexcept { + -: 852: return static_cast(m_prio); + -: 853: } + -: 854: void setPrio(QPrioSpec const prio) noexcept { + -: 855: m_prio = static_cast(prio & 0xFFU); + -: 856: m_pthre = static_cast(prio >> 8U); + -: 857: } + -: 858: std::uint_fast8_t getPThre() const noexcept { + -: 859: return static_cast(m_pthre); + -: 860: } + -: 861: + -: 862:#ifdef QACTIVE_EQUEUE_TYPE + -: 863: QACTIVE_EQUEUE_TYPE const & getEQueue() const noexcept { + -: 864: return m_eQueue; + -: 865: } + -: 866:#endif // def QACTIVE_EQUEUE_TYPE + -: 867: + -: 868:#ifdef QACTIVE_OS_OBJ_TYPE + -: 869: QACTIVE_OS_OBJ_TYPE const & getOsObject() const noexcept { + -: 870: return m_osObject; + -: 871: } + -: 872:#endif // def QACTIVE_OS_OBJ_TYPE + -: 873: + -: 874:#ifdef QACTIVE_THREAD_TYPE + -: 875: QACTIVE_THREAD_TYPE const & getThread() const noexcept { + -: 876: return m_thread; + -: 877: } + -: 878:#endif // def QACTIVE_THREAD_TYPE + -: 879: + -: 880:#ifdef QACTIVE_THREAD_TYPE + -: 881: void setThread(QACTIVE_THREAD_TYPE const & thr) { + -: 882: m_thread = thr; + -: 883: } + -: 884:#endif // def QACTIVE_THREAD_TYPE + -: 885: static void evtLoop_(QActive * act); + -: 886: + -: 887:#ifdef QF_ISR_API + -: 888: virtual bool postFromISR( + -: 889: QEvt const * const e, + -: 890: std::uint_fast16_t const margin, + -: 891: void * par, + -: 892: void const * const sender) noexcept; + -: 893:#endif // def QF_ISR_API + -: 894: + -: 895:#ifdef QF_ISR_API + -: 896: static void publishFromISR( + -: 897: QEvt const * e, + -: 898: void * par, + -: 899: void const * sender) noexcept; + -: 900:#endif // def QF_ISR_API + -: 901:}; // class QActive + -: 902: + -: 903:} // namespace QP + -: 904://$enddecl${QF::QActive} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 905: + -: 906://$declare${QF::QMActive} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 907:namespace QP { + -: 908: + -: 909://${QF::QMActive} ............................................................ + -: 910:class QMActive : public QP::QActive { + -: 911:protected: + -: 912: QMActive(QStateHandler const initial) noexcept; + -: 913: + -: 914:public: + -: 915: void init( + -: 916: void const * const e, + -: 917: std::uint_fast8_t const qsId) override + -: 918: { + -: 919: reinterpret_cast(this)->QMsm::init(e, qsId); + -: 920: } + -: 921: void init(std::uint_fast8_t const qsId) override { + -: 922: this->init(nullptr, qsId); + -: 923: } + -: 924: void dispatch( + -: 925: QEvt const * const e, + -: 926: std::uint_fast8_t const qsId) override + -: 927: { + -: 928: reinterpret_cast(this)->QMsm::dispatch(e, qsId); + -: 929: } + -: 930: bool isIn(QStateHandler const state) noexcept override { + -: 931: return reinterpret_cast(this)->QMsm::isIn(state); + -: 932: } + -: 933: + -: 934:#ifdef Q_SPY + -: 935: QStateHandler getStateHandler() noexcept override { + -: 936: return reinterpret_cast(this)->QMsm::getStateHandler(); + -: 937: } + -: 938:#endif // def Q_SPY + -: 939: bool isInState(QMState const * const st) const noexcept { + -: 940: return reinterpret_cast(this)->QMsm::isInState(st); + -: 941: } + -: 942: QMState const * childStateObj(QMState const * const parent) const noexcept { + -: 943: return reinterpret_cast(this) + -: 944: ->QMsm::childStateObj(parent); + -: 945: } + -: 946:}; // class QMActive + -: 947: + -: 948:} // namespace QP + -: 949://$enddecl${QF::QMActive} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 950: + -: 951://$declare${QF::QTimeEvt} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 952:namespace QP { + -: 953: + -: 954://${QF::QTimeEvt} ............................................................ + -: 955:class QTimeEvt : public QP::QEvt { + -: 956:private: + -: 957: QTimeEvt * volatile m_next; + -: 958: void * m_act; + -: 959: QTimeEvtCtr volatile m_ctr; + -: 960: QTimeEvtCtr m_interval; + -: 961: + -: 962:public: + -: 963: static QTimeEvt timeEvtHead_[QF_MAX_TICK_RATE]; + -: 964: + -: 965:private: + -: 966: friend class QXThread; + -: 967: + -: 968:public: + -: 969: QTimeEvt( + -: 970: QActive * const act, + -: 971: QSignal const sig, + -: 972: std::uint_fast8_t const tickRate = 0U) noexcept; + -: 973: + -: 974:#ifdef Q_XTOR + -: 975: ~QTimeEvt(); + -: 976:#endif // def Q_XTOR + -: 977: void armX( + -: 978: QTimeEvtCtr const nTicks, + -: 979: QTimeEvtCtr const interval = 0U) noexcept; + -: 980: bool disarm() noexcept; + -: 981: bool rearm(QTimeEvtCtr const nTicks) noexcept; + -: 982: bool wasDisarmed() noexcept; + -: 983: void const * getAct() const noexcept { + -: 984: return m_act; + -: 985: } + -: 986: QTimeEvtCtr getCtr() const noexcept { + -: 987: return m_ctr; + -: 988: } + -: 989: QTimeEvtCtr getInterval() const noexcept { + -: 990: return m_interval; + -: 991: } + -: 992: static void tick( + -: 993: std::uint_fast8_t const tickRate, + -: 994: void const * const sender) noexcept; + -: 995: + -: 996:#ifdef Q_UTEST + -: 997: static void tick1_( + -: 998: std::uint_fast8_t const tickRate, + -: 999: void const * const sender); + -: 1000:#endif // def Q_UTEST + -: 1001: + -: 1002:#ifdef QF_ISR_API + -: 1003: static void tickFromISR( + -: 1004: std::uint_fast8_t const tickRate, + -: 1005: void * par, + -: 1006: void const * sender) noexcept; + -: 1007:#endif // def QF_ISR_API + -: 1008: static bool noActive(std::uint_fast8_t const tickRate) noexcept; + -: 1009: QActive * toActive() noexcept { + -: 1010: return static_cast(m_act); + -: 1011: } + -: 1012: QTimeEvt * toTimeEvt() noexcept { + -: 1013: return static_cast(m_act); + -: 1014: } + -: 1015: + -: 1016:private: + -: 1017: QTimeEvt() noexcept; + -: 1018: QTimeEvt(QTimeEvt const & other) = delete; + -: 1019: QTimeEvt & operator=(QTimeEvt const & other) = delete; + -: 1020:}; // class QTimeEvt + -: 1021: + -: 1022:} // namespace QP + -: 1023://$enddecl${QF::QTimeEvt} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 1024: + -: 1025://$declare${QF::QTicker} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 1026:namespace QP { + -: 1027: + -: 1028://${QF::QTicker} ............................................................. + -: 1029:class QTicker : public QP::QActive { + -: 1030:public: + -: 1031: explicit QTicker(std::uint_fast8_t const tickRate) noexcept; + -: 1032: void init( + -: 1033: void const * const e, + -: 1034: std::uint_fast8_t const qsId) override; + -: 1035: void init(std::uint_fast8_t const qsId) override { + -: 1036: this->init(nullptr, qsId); + -: 1037: } + -: 1038: void dispatch( + -: 1039: QEvt const * const e, + -: 1040: std::uint_fast8_t const qsId) override; + -: 1041: void trig_(void const * const sender) noexcept; + -: 1042:}; // class QTicker + -: 1043: + -: 1044:} // namespace QP + -: 1045://$enddecl${QF::QTicker} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 1046: + -: 1047://$declare${QF::QF-base} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 1048:namespace QP { + -: 1049:namespace QF { + -: 1050: + -: 1051://${QF::QF-base::init} ....................................................... + -: 1052:void init(); + -: 1053: + -: 1054://${QF::QF-base::stop} ....................................................... + -: 1055:void stop(); + -: 1056: + -: 1057://${QF::QF-base::run} ........................................................ + -: 1058:int_t run(); + -: 1059: + -: 1060://${QF::QF-base::onStartup} .................................................. + -: 1061:void onStartup(); + -: 1062: + -: 1063://${QF::QF-base::onCleanup} .................................................. + -: 1064:void onCleanup(); + -: 1065: + -: 1066://${QF::QF-base::psInit} ..................................................... + -: 1067://! @deprecated + -: 1068:inline void psInit( + -: 1069: QSubscrList * const subscrSto, + -: 1070: enum_t const maxSignal) noexcept + -: 1071:{ + -: 1072: QActive::psInit(subscrSto, maxSignal); + -: 1073:} + -: 1074: + -: 1075://${QF::QF-base::publish_} ................................................... + -: 1076://! @deprecated + -: 1077:inline void publish_( + -: 1078: QEvt const * const e, + -: 1079: void const * const sender, + -: 1080: std::uint_fast8_t const qsId) noexcept + -: 1081:{ + -: 1082: QActive::publish_(e, sender, qsId); + -: 1083:} + -: 1084: + -: 1085://${QF::QF-base::tick} ....................................................... + -: 1086://! @deprecated + -: 1087:inline void tick( + -: 1088: std::uint_fast8_t const tickRate, + -: 1089: void const * const sender) noexcept + -: 1090:{ + -: 1091: QTimeEvt::tick(tickRate, sender); + -: 1092:} + -: 1093: + -: 1094://${QF::QF-base::getQueueMin} ................................................ + -: 1095://! @deprecated + -: 1096:inline std::uint_fast16_t getQueueMin(std::uint_fast8_t const prio) noexcept { + -: 1097: return QActive::getQueueMin(prio); + -: 1098:} + -: 1099: + -: 1100://${QF::QF-base::NO_MARGIN} .................................................. + -: 1101:constexpr std::uint_fast16_t NO_MARGIN {0xFFFFU}; + -: 1102: + -: 1103:} // namespace QF + -: 1104:} // namespace QP + -: 1105://$enddecl${QF::QF-base} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 1106: + -: 1107://$declare${QF::QF-dyn} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 1108:namespace QP { + -: 1109:namespace QF { + -: 1110: + -: 1111://${QF::QF-dyn::poolInit} .................................................... + -: 1112:void poolInit( + -: 1113: void * const poolSto, + -: 1114: std::uint_fast32_t const poolSize, + -: 1115: std::uint_fast16_t const evtSize) noexcept; + -: 1116: + -: 1117://${QF::QF-dyn::poolGetMaxBlockSize} ......................................... + -: 1118:std::uint_fast16_t poolGetMaxBlockSize() noexcept; + -: 1119: + -: 1120://${QF::QF-dyn::getPoolMin} .................................................. + -: 1121:std::uint_fast16_t getPoolMin(std::uint_fast8_t const poolNum) noexcept; + -: 1122: + -: 1123://${QF::QF-dyn::newX_} ....................................................... + -: 1124:QEvt * newX_( + -: 1125: std::uint_fast16_t const evtSize, + -: 1126: std::uint_fast16_t const margin, + -: 1127: enum_t const sig) noexcept; + -: 1128: + -: 1129://${QF::QF-dyn::gc} .......................................................... + -: 1130:void gc(QEvt const * const e) noexcept; + -: 1131: + -: 1132://${QF::QF-dyn::newRef_} ..................................................... + -: 1133:QEvt const * newRef_( + -: 1134: QEvt const * const e, + -: 1135: QEvt const * const evtRef) noexcept; + -: 1136: + -: 1137://${QF::QF-dyn::deleteRef_} .................................................. + -: 1138:void deleteRef_(QEvt const * const evtRef) noexcept; + -: 1139: + -: 1140://${QF::QF-dyn::newXfromISR_} ................................................ + -: 1141:#ifdef QF_ISR_API + -: 1142:QEvt * newXfromISR_( + -: 1143: std::uint_fast16_t const evtSize, + -: 1144: std::uint_fast16_t const margin, + -: 1145: enum_t const sig) noexcept; + -: 1146:#endif // def QF_ISR_API + -: 1147: + -: 1148://${QF::QF-dyn::gcFromISR} ................................................... + -: 1149:#ifdef QF_ISR_API + -: 1150:void gcFromISR(QEvt const * e) noexcept; + -: 1151:#endif // def QF_ISR_API + -: 1152: + -: 1153:} // namespace QF + -: 1154:} // namespace QP + -: 1155://$enddecl${QF::QF-dyn} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 1156: + -: 1157:extern "C" { + -: 1158://$declare${QF-extern-C} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 1159: + -: 1160://${QF-extern-C::QF_onContextSw} ............................................. + -: 1161:#ifdef QF_ON_CONTEXT_SW + -: 1162:void QF_onContextSw( + -: 1163: QP::QActive * prev, + -: 1164: QP::QActive * next); + -: 1165:#endif // def QF_ON_CONTEXT_SW + -: 1166://$enddecl${QF-extern-C} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 1167:} // extern "C" + -: 1168: + -: 1169://$declare${QF-macros} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 1170: + -: 1171://${QF-macros::Q_PRIO} ....................................................... + -: 1172:#define Q_PRIO(prio_, pthre_) \ + -: 1173: (static_cast((prio_) | (pthre_) << 8U)) + -: 1174: + -: 1175://${QF-macros::Q_NEW} ........................................................ + -: 1176:#ifndef QEVT_DYN_CTOR + -: 1177:#define Q_NEW(evtT_, sig_) (static_cast( \ + -: 1178: QP::QF::newX_(sizeof(evtT_), QP::QF::NO_MARGIN, (sig_)))) + -: 1179:#endif // ndef QEVT_DYN_CTOR + -: 1180: + -: 1181://${QF-macros::Q_NEW} ........................................................ + -: 1182:#ifdef QEVT_DYN_CTOR + -: 1183:#define Q_NEW(evtT_, sig_, ...) ( static_cast( \ + -: 1184: QP::QF::newX_(sizeof(evtT_), QP::QF::NO_MARGIN, (sig_)))->ctor(__VA_ARGS__)) + -: 1185:#endif // def QEVT_DYN_CTOR + -: 1186: + -: 1187://${QF-macros::Q_NEW_X} ...................................................... + -: 1188:#ifndef QEVT_DYN_CTOR + -: 1189:#define Q_NEW_X(evtT_, margin_, sig_) (static_cast( \ + -: 1190: QP::QF::newX_(sizeof(evtT_), (margin_), (sig_)))) + -: 1191:#endif // ndef QEVT_DYN_CTOR + -: 1192: + -: 1193://${QF-macros::Q_NEW_X} ...................................................... + -: 1194:#ifdef QEVT_DYN_CTOR + -: 1195:#define Q_NEW_X(evtT_, margin_, sig_, ...) ( static_cast( \ + -: 1196: QP::QF::newX_(sizeof(evtT_), (margin_), (sig_)))->ctor(__VA_ARGS__)) + -: 1197:#endif // def QEVT_DYN_CTOR + -: 1198: + -: 1199://${QF-macros::Q_NEW_REF} .................................................... + -: 1200:#define Q_NEW_REF(evtRef_, evtT_) \ + -: 1201: ((evtRef_) = static_cast(QP::QF::newRef_(e, (evtRef_)))) + -: 1202: + -: 1203://${QF-macros::Q_DELETE_REF} ................................................. + -: 1204:#define Q_DELETE_REF(evtRef_) do { \ + -: 1205: QP::QF::deleteRef_((evtRef_)); \ + -: 1206: (evtRef_) = 0U; \ + -: 1207:} while (false) + -: 1208: + -: 1209://${QF-macros::PUBLISH} ...................................................... + -: 1210:#ifdef Q_SPY + -: 1211:#define PUBLISH(e_, sender_) \ + -: 1212: publish_((e_), (sender_), (sender_)->getPrio()) + -: 1213:#endif // def Q_SPY + -: 1214: + -: 1215://${QF-macros::PUBLISH} ...................................................... + -: 1216:#ifndef Q_SPY + -: 1217:#define PUBLISH(e_, dummy) publish_((e_), nullptr, 0U) + -: 1218:#endif // ndef Q_SPY + -: 1219: + -: 1220://${QF-macros::POST} ......................................................... + -: 1221:#ifdef Q_SPY + -: 1222:#define POST(e_, sender_) post_((e_), QP::QF::NO_MARGIN, (sender_)) + -: 1223:#endif // def Q_SPY + -: 1224: + -: 1225://${QF-macros::POST} ......................................................... + -: 1226:#ifndef Q_SPY + -: 1227:#define POST(e_, dummy) post_((e_), QP::QF::NO_MARGIN, nullptr) + -: 1228:#endif // ndef Q_SPY + -: 1229: + -: 1230://${QF-macros::POST_X} ....................................................... + -: 1231:#ifdef Q_SPY + -: 1232:#define POST_X(e_, margin_, sender_) \ + -: 1233: post_((e_), (margin_), (sender_)) + -: 1234:#endif // def Q_SPY + -: 1235: + -: 1236://${QF-macros::POST_X} ....................................................... + -: 1237:#ifndef Q_SPY + -: 1238:#define POST_X(e_, margin_, dummy) post_((e_), (margin_), nullptr) + -: 1239:#endif // ndef Q_SPY + -: 1240: + -: 1241://${QF-macros::TICK_X} ....................................................... + -: 1242:#ifdef Q_SPY + -: 1243:#define TICK_X(tickRate_, sender_) tick((tickRate_), (sender_)) + -: 1244:#endif // def Q_SPY + -: 1245: + -: 1246://${QF-macros::TICK_X} ....................................................... + -: 1247:#ifndef Q_SPY + -: 1248:#define TICK_X(tickRate_, dummy) tick((tickRate_), nullptr) + -: 1249:#endif // ndef Q_SPY + -: 1250: + -: 1251://${QF-macros::TICK} ......................................................... + -: 1252:#define TICK(sender_) TICK_X(0U, (sender_)) + -: 1253: + -: 1254://${QF-macros::TRIG} ......................................................... + -: 1255:#ifdef Q_SPY + -: 1256:#define TRIG(sender_) trig_((sender_)) + -: 1257:#endif // def Q_SPY + -: 1258: + -: 1259://${QF-macros::TRIG} ......................................................... + -: 1260:#ifndef Q_SPY + -: 1261:#define TRIG(sender_) trig_(nullptr) + -: 1262:#endif // ndef Q_SPY + -: 1263: + -: 1264://${QF-macros::QF_CRIT_EXIT_NOP} ............................................. + -: 1265:#ifndef QF_CRIT_EXIT_NOP + -: 1266:#define QF_CRIT_EXIT_NOP() (static_cast(0)) + -: 1267:#endif // ndef QF_CRIT_EXIT_NOP + -: 1268: + -: 1269://${QF-macros::QF_MEM_SYS} ................................................... + -: 1270:#ifndef QF_MEM_SYS + -: 1271:#define QF_MEM_SYS() (static_cast(0)) + -: 1272:#endif // ndef QF_MEM_SYS + -: 1273: + -: 1274://${QF-macros::QF_MEM_APP} ................................................... + -: 1275:#ifndef QF_MEM_APP + -: 1276:#define QF_MEM_APP() (static_cast(0)) + -: 1277:#endif // ndef QF_MEM_APP + -: 1278://$enddecl${QF-macros} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 1279: + -: 1280:#endif // QP_HPP_ diff --git a/qutest/qhsmtst/test/test_qhsm-funct.py b/qutest/qhsm/test/test_qhsm-funct.py similarity index 61% rename from qutest/qhsmtst/test/test_qhsm-funct.py rename to qutest/qhsm/test/test_qhsm-funct.py index 263fd41..74b04e6 100644 --- a/qutest/qhsmtst/test/test_qhsm-funct.py +++ b/qutest/qhsm/test/test_qhsm-funct.py @@ -8,7 +8,8 @@ def on_reset(): current_obj(OBJ_SM, "the_sm") # tests... -test("QHsmTst_init") +#========================================================== +test("QHsmTst::init") init() expect("@timestamp BSP_DISPLAY top-INIT;") expect("@timestamp BSP_DISPLAY s-ENTRY;") @@ -18,17 +19,29 @@ def on_reset(): expect("@timestamp BSP_DISPLAY s211-ENTRY;") expect("@timestamp Trg-Done QS_RX_EVENT") +#---------------------------------------------------------- test("QHsmTst isIn", NORESET) +command(0) # get state handler +expect("@timestamp CMD QHsmTst::s211") +expect("@timestamp Trg-Done QS_RX_COMMAND") + command(1, 1) # is in state s1 -expect("@timestamp CMD 0 1"); # NOT in s1 +expect("@timestamp CMD 0 1") # NO +expect("@timestamp Trg-Done QS_RX_COMMAND") + +command(1, 2) # is in state s2 +expect("@timestamp CMD 1 2") # YES expect("@timestamp Trg-Done QS_RX_COMMAND") + command(1, 21) # is in state s21 -expect("@timestamp CMD 1 21"); # YES, in s21 +expect("@timestamp CMD 1 21") # YES expect("@timestamp Trg-Done QS_RX_COMMAND") + command(1, 211) # is in state s211 -expect("@timestamp CMD 1 211"); # YES, in s211 +expect("@timestamp CMD 1 211") # YES expect("@timestamp Trg-Done QS_RX_COMMAND") +#---------------------------------------------------------- test("QHsmTst dispatch", NORESET) dispatch("A_SIG") expect("@timestamp BSP_DISPLAY s21-A;") @@ -45,156 +58,146 @@ def on_reset(): expect("@timestamp BSP_DISPLAY s211-ENTRY;") expect("@timestamp Trg-Done QS_RX_EVENT") -dispatch("D_SIG") -expect("@timestamp BSP_DISPLAY s211-D;") +dispatch("C_SIG") +expect("@timestamp BSP_DISPLAY s211-C;") expect("@timestamp BSP_DISPLAY s211-EXIT;") -expect("@timestamp BSP_DISPLAY s21-INIT;") -expect("@timestamp BSP_DISPLAY s211-ENTRY;") +expect("@timestamp BSP_DISPLAY s212-ENTRY;") expect("@timestamp Trg-Done QS_RX_EVENT") -dispatch("E_SIG") -expect("@timestamp BSP_DISPLAY s-E;") -expect("@timestamp BSP_DISPLAY s211-EXIT;") +dispatch("D_SIG") +expect("@timestamp BSP_DISPLAY s21-D;") +expect("@timestamp BSP_DISPLAY s212-EXIT;") expect("@timestamp BSP_DISPLAY s21-EXIT;") -expect("@timestamp BSP_DISPLAY s2-EXIT;") -expect("@timestamp BSP_DISPLAY s1-ENTRY;") -expect("@timestamp BSP_DISPLAY s11-ENTRY;") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("I_SIG") -expect("@timestamp BSP_DISPLAY s1-I;") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("F_SIG") -expect("@timestamp BSP_DISPLAY s1-F;") -expect("@timestamp BSP_DISPLAY s11-EXIT;") -expect("@timestamp BSP_DISPLAY s1-EXIT;") -expect("@timestamp BSP_DISPLAY s2-ENTRY;") +expect("@timestamp BSP_DISPLAY s2-INIT;") expect("@timestamp BSP_DISPLAY s21-ENTRY;") expect("@timestamp BSP_DISPLAY s211-ENTRY;") expect("@timestamp Trg-Done QS_RX_EVENT") -dispatch("I_SIG") -expect("@timestamp BSP_DISPLAY s2-I;") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("I_SIG") -expect("@timestamp BSP_DISPLAY s-I;") +dispatch("E_SIG") +expect("@timestamp BSP_DISPLAY s2-E;") +expect("@timestamp BSP_DISPLAY s211-EXIT;") +expect("@timestamp BSP_DISPLAY s21-EXIT;") +expect("@timestamp BSP_DISPLAY s22-ENTRY;") expect("@timestamp Trg-Done QS_RX_EVENT") dispatch("F_SIG") expect("@timestamp BSP_DISPLAY s2-F;") -expect("@timestamp BSP_DISPLAY s211-EXIT;") -expect("@timestamp BSP_DISPLAY s21-EXIT;") +expect("@timestamp BSP_DISPLAY s22-EXIT;") expect("@timestamp BSP_DISPLAY s2-EXIT;") expect("@timestamp BSP_DISPLAY s1-ENTRY;") expect("@timestamp BSP_DISPLAY s11-ENTRY;") +expect("@timestamp BSP_DISPLAY s11-INIT;") +expect("@timestamp BSP_DISPLAY s111-ENTRY;") expect("@timestamp Trg-Done QS_RX_EVENT") -dispatch("A_SIG") -expect("@timestamp BSP_DISPLAY s1-A;") +dispatch("C_SIG") +expect("@timestamp BSP_DISPLAY s111-C;") +expect("@timestamp BSP_DISPLAY s111-EXIT;") +expect("@timestamp BSP_DISPLAY s112-ENTRY;") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("H_SIG") +expect("@timestamp BSP_DISPLAY s112-H;") +expect("@timestamp BSP_DISPLAY s112-EXIT;") expect("@timestamp BSP_DISPLAY s11-EXIT;") expect("@timestamp BSP_DISPLAY s1-EXIT;") +expect("@timestamp BSP_DISPLAY s-INIT;") expect("@timestamp BSP_DISPLAY s1-ENTRY;") expect("@timestamp BSP_DISPLAY s1-INIT;") expect("@timestamp BSP_DISPLAY s11-ENTRY;") +expect("@timestamp BSP_DISPLAY s111-ENTRY;") expect("@timestamp Trg-Done QS_RX_EVENT") -dispatch("B_SIG") -expect("@timestamp BSP_DISPLAY s1-B;") -expect("@timestamp BSP_DISPLAY s11-EXIT;") -expect("@timestamp BSP_DISPLAY s11-ENTRY;") +#========================================================== +test("QHsmTst guards") +init() +expect("@timestamp BSP_DISPLAY top-INIT;") +expect("@timestamp BSP_DISPLAY s-ENTRY;") +expect("@timestamp BSP_DISPLAY s2-ENTRY;") +expect("@timestamp BSP_DISPLAY s2-INIT;") +expect("@timestamp BSP_DISPLAY s21-ENTRY;") +expect("@timestamp BSP_DISPLAY s211-ENTRY;") expect("@timestamp Trg-Done QS_RX_EVENT") dispatch("D_SIG") -expect("@timestamp BSP_DISPLAY s1-D;") -expect("@timestamp BSP_DISPLAY s11-EXIT;") -expect("@timestamp BSP_DISPLAY s1-EXIT;") -expect("@timestamp BSP_DISPLAY s-INIT;") -expect("@timestamp BSP_DISPLAY s1-ENTRY;") -expect("@timestamp BSP_DISPLAY s11-ENTRY;") +expect("@timestamp BSP_DISPLAY s21-D;") +expect("@timestamp BSP_DISPLAY s211-EXIT;") +expect("@timestamp BSP_DISPLAY s21-EXIT;") +expect("@timestamp BSP_DISPLAY s2-INIT;") +expect("@timestamp BSP_DISPLAY s21-ENTRY;") +expect("@timestamp BSP_DISPLAY s211-ENTRY;") expect("@timestamp Trg-Done QS_RX_EVENT") dispatch("D_SIG") -expect("@timestamp BSP_DISPLAY s11-D;") -expect("@timestamp BSP_DISPLAY s11-EXIT;") -expect("@timestamp BSP_DISPLAY s1-INIT;") -expect("@timestamp BSP_DISPLAY s11-ENTRY;") expect("@timestamp Trg-Done QS_RX_EVENT") -dispatch("E_SIG") -expect("@timestamp BSP_DISPLAY s-E;") -expect("@timestamp BSP_DISPLAY s11-EXIT;") -expect("@timestamp BSP_DISPLAY s1-EXIT;") -expect("@timestamp BSP_DISPLAY s1-ENTRY;") -expect("@timestamp BSP_DISPLAY s11-ENTRY;") +dispatch("I_SIG") +expect("@timestamp BSP_DISPLAY s2-I;") expect("@timestamp Trg-Done QS_RX_EVENT") -dispatch("G_SIG") -expect("@timestamp BSP_DISPLAY s11-G;") -expect("@timestamp BSP_DISPLAY s11-EXIT;") -expect("@timestamp BSP_DISPLAY s1-EXIT;") +dispatch("I_SIG") +expect("@timestamp BSP_DISPLAY s-I;") +expect("@timestamp Trg-Done QS_RX_EVENT") + +#========================================================== +test("QHsmTst history") +init() +expect("@timestamp BSP_DISPLAY top-INIT;") +expect("@timestamp BSP_DISPLAY s-ENTRY;") expect("@timestamp BSP_DISPLAY s2-ENTRY;") +expect("@timestamp BSP_DISPLAY s2-INIT;") expect("@timestamp BSP_DISPLAY s21-ENTRY;") expect("@timestamp BSP_DISPLAY s211-ENTRY;") expect("@timestamp Trg-Done QS_RX_EVENT") -dispatch("H_SIG") -expect("@timestamp BSP_DISPLAY s211-H;") +dispatch("G_SIG") +expect("@timestamp BSP_DISPLAY s21-G->H*-s1;") expect("@timestamp BSP_DISPLAY s211-EXIT;") expect("@timestamp BSP_DISPLAY s21-EXIT;") expect("@timestamp BSP_DISPLAY s2-EXIT;") -expect("@timestamp BSP_DISPLAY s-INIT;") expect("@timestamp BSP_DISPLAY s1-ENTRY;") expect("@timestamp BSP_DISPLAY s11-ENTRY;") +expect("@timestamp BSP_DISPLAY s111-ENTRY;") expect("@timestamp Trg-Done QS_RX_EVENT") +command(1, 111) # is in state s111 +expect("@timestamp CMD 1 111") +expect("@timestamp Trg-Done QS_RX_COMMAND") -dispatch("H_SIG") -expect("@timestamp BSP_DISPLAY s11-H;") -expect("@timestamp BSP_DISPLAY s11-EXIT;") -expect("@timestamp BSP_DISPLAY s1-EXIT;") -expect("@timestamp BSP_DISPLAY s-INIT;") -expect("@timestamp BSP_DISPLAY s1-ENTRY;") -expect("@timestamp BSP_DISPLAY s11-ENTRY;") +dispatch("C_SIG") +expect("@timestamp BSP_DISPLAY s111-C;") +expect("@timestamp BSP_DISPLAY s111-EXIT;") +expect("@timestamp BSP_DISPLAY s112-ENTRY;") expect("@timestamp Trg-Done QS_RX_EVENT") dispatch("C_SIG") -expect("@timestamp BSP_DISPLAY s1-C;") +expect("@timestamp BSP_DISPLAY s-C;") +expect("@timestamp BSP_DISPLAY s112-EXIT;") expect("@timestamp BSP_DISPLAY s11-EXIT;") expect("@timestamp BSP_DISPLAY s1-EXIT;") -expect("@timestamp BSP_DISPLAY s2-ENTRY;") -expect("@timestamp BSP_DISPLAY s2-INIT;") -expect("@timestamp BSP_DISPLAY s21-ENTRY;") -expect("@timestamp BSP_DISPLAY s211-ENTRY;") +expect("@timestamp BSP_DISPLAY s-EXIT;") +expect("@timestamp BSP_DISPLAY t-ENTRY;") expect("@timestamp Trg-Done QS_RX_EVENT") +command(1, 0) # is in state s +expect("@timestamp CMD 0 0") # NO +expect("@timestamp Trg-Done QS_RX_COMMAND") -dispatch("G_SIG") -expect("@timestamp BSP_DISPLAY s21-G;") -expect("@timestamp BSP_DISPLAY s211-EXIT;") -expect("@timestamp BSP_DISPLAY s21-EXIT;") -expect("@timestamp BSP_DISPLAY s2-EXIT;") +dispatch("C_SIG") +expect("@timestamp BSP_DISPLAY t-C->H-s;") +expect("@timestamp BSP_DISPLAY t-EXIT;") +expect("@timestamp BSP_DISPLAY s-ENTRY;") expect("@timestamp BSP_DISPLAY s1-ENTRY;") expect("@timestamp BSP_DISPLAY s1-INIT;") expect("@timestamp BSP_DISPLAY s11-ENTRY;") +expect("@timestamp BSP_DISPLAY s111-ENTRY;") expect("@timestamp Trg-Done QS_RX_EVENT") -dispatch("C_SIG") -expect("@timestamp BSP_DISPLAY s1-C;") +dispatch("G_SIG") +expect("@timestamp BSP_DISPLAY s11-G->H*-s2;") +expect("@timestamp BSP_DISPLAY s111-EXIT;") expect("@timestamp BSP_DISPLAY s11-EXIT;") expect("@timestamp BSP_DISPLAY s1-EXIT;") expect("@timestamp BSP_DISPLAY s2-ENTRY;") -expect("@timestamp BSP_DISPLAY s2-INIT;") expect("@timestamp BSP_DISPLAY s21-ENTRY;") expect("@timestamp BSP_DISPLAY s211-ENTRY;") expect("@timestamp Trg-Done QS_RX_EVENT") -dispatch("C_SIG") -expect("@timestamp BSP_DISPLAY s2-C;") -expect("@timestamp BSP_DISPLAY s211-EXIT;") -expect("@timestamp BSP_DISPLAY s21-EXIT;") -expect("@timestamp BSP_DISPLAY s2-EXIT;") -expect("@timestamp BSP_DISPLAY s1-ENTRY;") -expect("@timestamp BSP_DISPLAY s1-INIT;") -expect("@timestamp BSP_DISPLAY s11-ENTRY;") -expect("@timestamp Trg-Done QS_RX_EVENT") - diff --git a/qutest/qhsmtst/test/test_qhsm-struct.py b/qutest/qhsm/test/test_qhsm-struct.py similarity index 64% rename from qutest/qhsmtst/test/test_qhsm-struct.py rename to qutest/qhsm/test/test_qhsm-struct.py index 0d1aad9..e6e02f0 100644 --- a/qutest/qhsmtst/test/test_qhsm-struct.py +++ b/qutest/qhsm/test/test_qhsm-struct.py @@ -4,10 +4,11 @@ # preamble... def on_reset(): expect_run() - glb_filter(GRP_SM) + glb_filter(GRP_SM, GRP_U1) current_obj(OBJ_SM, "the_sm") # tests... +#========================================================== test("QHsmTst init") init() expect("===RTC===> St-Init Obj=the_sm,State=QP::QHsm::top->QHsmTst::s2") @@ -19,6 +20,29 @@ def on_reset(): expect("@timestamp Init===> Obj=the_sm,State=QHsmTst::s211") expect("@timestamp Trg-Done QS_RX_EVENT") +#---------------------------------------------------------- +test("QHsmTst isIn", NORESET) +command(0) # get state handler +expect("@timestamp CMD QHsmTst::s211") +expect("@timestamp Trg-Done QS_RX_COMMAND") + +command(1, 1) # is in state s1 +expect("@timestamp CMD 0 1") # NO +expect("@timestamp Trg-Done QS_RX_COMMAND") + +command(1, 2) # is in state s2 +expect("@timestamp CMD 1 2") # YES +expect("@timestamp Trg-Done QS_RX_COMMAND") + +command(1, 21) # is in state s21 +expect("@timestamp CMD 1 21") # YES +expect("@timestamp Trg-Done QS_RX_COMMAND") + +command(1, 211) # is in state s211 +expect("@timestamp CMD 1 211") # YES +expect("@timestamp Trg-Done QS_RX_COMMAND") + +#---------------------------------------------------------- test("QHsmTst dispatch", NORESET) dispatch("A_SIG") expect("@timestamp Disp===> Obj=the_sm,Sig=A_SIG,State=QHsmTst::s211") @@ -37,145 +61,116 @@ def on_reset(): expect("@timestamp ===>Tran Obj=the_sm,Sig=B_SIG,State=QHsmTst::s21->QHsmTst::s211") expect("@timestamp Trg-Done QS_RX_EVENT") -dispatch("D_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=D_SIG,State=QHsmTst::s211") +dispatch("C_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=C_SIG,State=QHsmTst::s211") expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s211") -expect("===RTC===> St-Init Obj=the_sm,State=QHsmTst::s21->QHsmTst::s211") -expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s211") -expect("@timestamp ===>Tran Obj=the_sm,Sig=D_SIG,State=QHsmTst::s211->QHsmTst::s211") +expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s212") +expect("@timestamp ===>Tran Obj=the_sm,Sig=C_SIG,State=QHsmTst::s211->QHsmTst::s212") expect("@timestamp Trg-Done QS_RX_EVENT") -dispatch("E_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=E_SIG,State=QHsmTst::s211") -expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s211") +dispatch("D_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=D_SIG,State=QHsmTst::s212") +expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s212") expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s21") -expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s2") -expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s1") -expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s11") -expect("@timestamp ===>Tran Obj=the_sm,Sig=E_SIG,State=QHsmTst::s->QHsmTst::s11") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("I_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=I_SIG,State=QHsmTst::s11") -expect("@timestamp =>Intern Obj=the_sm,Sig=I_SIG,State=QHsmTst::s1") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("F_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=F_SIG,State=QHsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s1") -expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s2") +expect("===RTC===> St-Init Obj=the_sm,State=QHsmTst::s2->QHsmTst::s211") expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s21") expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s211") -expect("@timestamp ===>Tran Obj=the_sm,Sig=F_SIG,State=QHsmTst::s1->QHsmTst::s211") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("I_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=I_SIG,State=QHsmTst::s211") -expect("@timestamp =>Intern Obj=the_sm,Sig=I_SIG,State=QHsmTst::s2") +expect("@timestamp ===>Tran Obj=the_sm,Sig=D_SIG,State=QHsmTst::s21->QHsmTst::s211") expect("@timestamp Trg-Done QS_RX_EVENT") -dispatch("I_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=I_SIG,State=QHsmTst::s211") -expect("===RTC===> St-Unhnd Obj=the_sm,Sig=I_SIG,State=QHsmTst::s2") -expect("@timestamp =>Intern Obj=the_sm,Sig=I_SIG,State=QHsmTst::s") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("F_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=F_SIG,State=QHsmTst::s211") +dispatch("E_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=E_SIG,State=QHsmTst::s211") expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s211") expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s21") -expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s2") -expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s1") -expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s11") -expect("@timestamp ===>Tran Obj=the_sm,Sig=F_SIG,State=QHsmTst::s2->QHsmTst::s11") +expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s22") +expect("@timestamp ===>Tran Obj=the_sm,Sig=E_SIG,State=QHsmTst::s2->QHsmTst::s22") expect("@timestamp Trg-Done QS_RX_EVENT") -dispatch("A_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=A_SIG,State=QHsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s1") +dispatch("F_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=F_SIG,State=QHsmTst::s22") +expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s22") +expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s2") expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s1") -expect("===RTC===> St-Init Obj=the_sm,State=QHsmTst::s1->QHsmTst::s11") -expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s11") -expect("@timestamp ===>Tran Obj=the_sm,Sig=A_SIG,State=QHsmTst::s1->QHsmTst::s11") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("B_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=B_SIG,State=QHsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s11") expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s11") -expect("@timestamp ===>Tran Obj=the_sm,Sig=B_SIG,State=QHsmTst::s1->QHsmTst::s11") +expect("===RTC===> St-Init Obj=the_sm,State=QHsmTst::s11->QHsmTst::s111") +expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s111") +expect("@timestamp ===>Tran Obj=the_sm,Sig=F_SIG,State=QHsmTst::s2->QHsmTst::s111") expect("@timestamp Trg-Done QS_RX_EVENT") -dispatch("D_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=D_SIG,State=QHsmTst::s11") -expect("===RTC===> St-Unhnd Obj=the_sm,Sig=D_SIG,State=QHsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s1") -expect("===RTC===> St-Init Obj=the_sm,State=QHsmTst::s->QHsmTst::s11") -expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s1") -expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s11") -expect("@timestamp ===>Tran Obj=the_sm,Sig=D_SIG,State=QHsmTst::s1->QHsmTst::s11") +dispatch("H_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=H_SIG,State=QHsmTst::s111") +expect("@timestamp =>Ignore Obj=the_sm,Sig=H_SIG,State=QHsmTst::s111") expect("@timestamp Trg-Done QS_RX_EVENT") -dispatch("D_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=D_SIG,State=QHsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s11") -expect("===RTC===> St-Init Obj=the_sm,State=QHsmTst::s1->QHsmTst::s11") -expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s11") -expect("@timestamp ===>Tran Obj=the_sm,Sig=D_SIG,State=QHsmTst::s11->QHsmTst::s11") +dispatch("C_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=C_SIG,State=QHsmTst::s111") +expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s111") +expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s112") +expect("@timestamp ===>Tran Obj=the_sm,Sig=C_SIG,State=QHsmTst::s111->QHsmTst::s112") expect("@timestamp Trg-Done QS_RX_EVENT") -dispatch("E_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=E_SIG,State=QHsmTst::s11") +dispatch("H_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=H_SIG,State=QHsmTst::s112") +expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s112") expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s11") expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s1") +expect("===RTC===> St-Init Obj=the_sm,State=QHsmTst::s->QHsmTst::s1") expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s1") +expect("===RTC===> St-Init Obj=the_sm,State=QHsmTst::s1->QHsmTst::s111") expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s11") -expect("@timestamp ===>Tran Obj=the_sm,Sig=E_SIG,State=QHsmTst::s->QHsmTst::s11") +expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s111") +expect("@timestamp ===>Tran Obj=the_sm,Sig=H_SIG,State=QHsmTst::s112->QHsmTst::s111") expect("@timestamp Trg-Done QS_RX_EVENT") -dispatch("G_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=G_SIG,State=QHsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s1") +#========================================================== +test("QHsmTst guards") +init() +expect("===RTC===> St-Init Obj=the_sm,State=QP::QHsm::top->QHsmTst::s2") +expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s") expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s2") +expect("===RTC===> St-Init Obj=the_sm,State=QHsmTst::s2->QHsmTst::s211") expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s21") expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s211") -expect("@timestamp ===>Tran Obj=the_sm,Sig=G_SIG,State=QHsmTst::s11->QHsmTst::s211") +expect("@timestamp Init===> Obj=the_sm,State=QHsmTst::s211") expect("@timestamp Trg-Done QS_RX_EVENT") -dispatch("H_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=H_SIG,State=QHsmTst::s211") +dispatch("D_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=D_SIG,State=QHsmTst::s211") expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s211") expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s21") -expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s2") -expect("===RTC===> St-Init Obj=the_sm,State=QHsmTst::s->QHsmTst::s11") -expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s1") -expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s11") -expect("@timestamp ===>Tran Obj=the_sm,Sig=H_SIG,State=QHsmTst::s211->QHsmTst::s11") +expect("===RTC===> St-Init Obj=the_sm,State=QHsmTst::s2->QHsmTst::s211") +expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s21") +expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s211") +expect("@timestamp ===>Tran Obj=the_sm,Sig=D_SIG,State=QHsmTst::s21->QHsmTst::s211") expect("@timestamp Trg-Done QS_RX_EVENT") -dispatch("H_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=H_SIG,State=QHsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s1") -expect("===RTC===> St-Init Obj=the_sm,State=QHsmTst::s->QHsmTst::s11") -expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s1") -expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s11") -expect("@timestamp ===>Tran Obj=the_sm,Sig=H_SIG,State=QHsmTst::s11->QHsmTst::s11") +dispatch("D_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=D_SIG,State=QHsmTst::s211") +expect("===RTC===> St-Unhnd Obj=the_sm,Sig=D_SIG,State=QHsmTst::s21") +expect("@timestamp =>Ignore Obj=the_sm,Sig=D_SIG,State=QHsmTst::s211") expect("@timestamp Trg-Done QS_RX_EVENT") -dispatch("C_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=C_SIG,State=QHsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s1") +dispatch("I_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=I_SIG,State=QHsmTst::s211") +expect("@timestamp =>Intern Obj=the_sm,Sig=I_SIG,State=QHsmTst::s2") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("I_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=I_SIG,State=QHsmTst::s211") +expect("===RTC===> St-Unhnd Obj=the_sm,Sig=I_SIG,State=QHsmTst::s2") +expect("@timestamp =>Intern Obj=the_sm,Sig=I_SIG,State=QHsmTst::s") +expect("@timestamp Trg-Done QS_RX_EVENT") + +#========================================================== +test("QHsmTst history") +init() +expect("===RTC===> St-Init Obj=the_sm,State=QP::QHsm::top->QHsmTst::s2") +expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s") expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s2") expect("===RTC===> St-Init Obj=the_sm,State=QHsmTst::s2->QHsmTst::s211") expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s21") expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s211") -expect("@timestamp ===>Tran Obj=the_sm,Sig=C_SIG,State=QHsmTst::s1->QHsmTst::s211") +expect("@timestamp Init===> Obj=the_sm,State=QHsmTst::s211") expect("@timestamp Trg-Done QS_RX_EVENT") dispatch("G_SIG") @@ -183,31 +178,53 @@ def on_reset(): expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s211") expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s21") expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s2") +expect("===RTC===> St-Hist Obj=the_sm,State=QHsmTst::s21->QHsmTst::s111") expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s1") -expect("===RTC===> St-Init Obj=the_sm,State=QHsmTst::s1->QHsmTst::s11") expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s11") -expect("@timestamp ===>Tran Obj=the_sm,Sig=G_SIG,State=QHsmTst::s21->QHsmTst::s11") +expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s111") +expect("@timestamp ===>Tran Obj=the_sm,Sig=G_SIG,State=QHsmTst::s21->QHsmTst::s111") expect("@timestamp Trg-Done QS_RX_EVENT") +command(1, 111) # is in state s111 +expect("@timestamp CMD 1 111") +expect("@timestamp Trg-Done QS_RX_COMMAND") dispatch("C_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=C_SIG,State=QHsmTst::s11") +expect("@timestamp Disp===> Obj=the_sm,Sig=C_SIG,State=QHsmTst::s111") +expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s111") +expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s112") +expect("@timestamp ===>Tran Obj=the_sm,Sig=C_SIG,State=QHsmTst::s111->QHsmTst::s112") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("C_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=C_SIG,State=QHsmTst::s112") +expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s112") expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s11") expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s1") -expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s2") -expect("===RTC===> St-Init Obj=the_sm,State=QHsmTst::s2->QHsmTst::s211") -expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s21") -expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s211") -expect("@timestamp ===>Tran Obj=the_sm,Sig=C_SIG,State=QHsmTst::s1->QHsmTst::s211") +expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s") +expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::t") +expect("@timestamp ===>Tran Obj=the_sm,Sig=C_SIG,State=QHsmTst::s->QHsmTst::t") expect("@timestamp Trg-Done QS_RX_EVENT") dispatch("C_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=C_SIG,State=QHsmTst::s211") -expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s211") -expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s21") -expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s2") +expect("@timestamp Disp===> Obj=the_sm,Sig=C_SIG,State=QHsmTst::t") +expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::t") +expect("===RTC===> St-Hist Obj=the_sm,State=QHsmTst::t->QHsmTst::s1") +expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s") expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s1") -expect("===RTC===> St-Init Obj=the_sm,State=QHsmTst::s1->QHsmTst::s11") +expect("===RTC===> St-Init Obj=the_sm,State=QHsmTst::s1->QHsmTst::s111") expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s11") -expect("@timestamp ===>Tran Obj=the_sm,Sig=C_SIG,State=QHsmTst::s2->QHsmTst::s11") +expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s111") +expect("@timestamp ===>Tran Obj=the_sm,Sig=C_SIG,State=QHsmTst::t->QHsmTst::s111") expect("@timestamp Trg-Done QS_RX_EVENT") +dispatch("G_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=G_SIG,State=QHsmTst::s111") +expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s111") +expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s11") +expect("===RTC===> St-Exit Obj=the_sm,State=QHsmTst::s1") +expect("===RTC===> St-Hist Obj=the_sm,State=QHsmTst::s11->QHsmTst::s211") +expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s2") +expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s21") +expect("===RTC===> St-Entry Obj=the_sm,State=QHsmTst::s211") +expect("@timestamp ===>Tran Obj=the_sm,Sig=G_SIG,State=QHsmTst::s11->QHsmTst::s211") +expect("@timestamp Trg-Done QS_RX_EVENT") diff --git a/qutest/qhsmtst/test/test_qhsm.cpp b/qutest/qhsm/test/test_qhsm.cpp similarity index 94% rename from qutest/qhsmtst/test/test_qhsm.cpp rename to qutest/qhsm/test/test_qhsm.cpp index fb54431..854285d 100644 --- a/qutest/qhsmtst/test/test_qhsm.cpp +++ b/qutest/qhsm/test/test_qhsm.cpp @@ -1,7 +1,7 @@ //============================================================================ // Purpose: Fixture for QUTEST -// Last Updated for Version: 7.3.1 -// Date of the Last Update: 2023-12-11 +// Last Updated for Version: 7.4.0 +// Date of the Last Update: 2024-09-04 // // Q u a n t u m L e a P s // ------------------------ @@ -32,7 +32,7 @@ // //============================================================================ #include "qpcpp.hpp" -#include "qhsmtst.hpp" +#include "cut_qhsm.hpp" Q_DEFINE_THIS_FILE @@ -40,8 +40,10 @@ Q_DEFINE_THIS_FILE namespace APP { enum { - BSP_DISPLAY = QP::QS_USER, - CMD, + BSP_DISPLAY = QP::QS_USER0, +}; +enum { + CMD = QP::QS_USER1, }; void BSP_display(char const *msg) { @@ -76,7 +78,9 @@ void QS::onCommand(std::uint8_t cmdId, std::uint32_t param1, //PRINTF_S(" Command id=%d param=%d\n", (int)cmdId, (int)param); switch (cmdId) { case 0U: { + QP::QStateHandler state = APP::the_sm->getStateHandler(); QS_BEGIN_ID(APP::CMD, 0U) // app-specific record + QS_FUN(state); QS_END() break; } diff --git a/qutest/qhsmtst/src/qhsmtst.qm b/qutest/qhsmtst/src/qhsmtst.qm deleted file mode 100644 index a7e89dc..0000000 --- a/qutest/qhsmtst/src/qhsmtst.qm +++ /dev/null @@ -1,387 +0,0 @@ - - - QHsmTst is a contrived state machine from Chapter 2 of the PSiCC2 book for testing all possible transition topologies with up to 4-levels of state nesting. - - - - - - - Test active object - - - - - - - : QHsm(&initial) - - - - - - Q_UNUSED_PAR(e); -m_foo = 0U; -BSP_display("top-INIT;"); - -QS_SIG_DICTIONARY(A_SIG, nullptr); -QS_SIG_DICTIONARY(B_SIG, nullptr); -QS_SIG_DICTIONARY(C_SIG, nullptr); -QS_SIG_DICTIONARY(D_SIG, nullptr); -QS_SIG_DICTIONARY(E_SIG, nullptr); -QS_SIG_DICTIONARY(F_SIG, nullptr); -QS_SIG_DICTIONARY(G_SIG, nullptr); -QS_SIG_DICTIONARY(H_SIG, nullptr); -QS_SIG_DICTIONARY(I_SIG, nullptr); -QS_SIG_DICTIONARY(TERMINATE_SIG, nullptr); -QS_SIG_DICTIONARY(IGNORE_SIG, nullptr); - - - - - - - BSP_display("s-ENTRY;"); - BSP_display("s-EXIT;"); - - - BSP_display("s-INIT;"); - - - - - - - - - m_foo - m_foo = 0U; -BSP_display("s-I;"); - - - - - - - - - - - BSP_display("s-E;"); - - - - - - - BSP_terminate(0); - - - - - - - BSP_display("s1-ENTRY;"); - BSP_display("s1-EXIT;"); - - - BSP_display("s1-INIT;"); - - - - - - - BSP_display("s1-I;"); - - - - - - - - - !m_foo - m_foo = true; -BSP_display("s1-D;"); - - - - - - - - - - - BSP_display("s1-A;"); - - - - - - - BSP_display("s1-B;"); - - - - - - - BSP_display("s1-F;"); - - - - - - - BSP_display("s1-C;"); - - - - - - - BSP_display("s11-ENTRY;"); - BSP_display("s11-EXIT;"); - - - BSP_display("s11-H;"); - - - - - - - - - m_foo - m_foo = false; -BSP_display("s11-D;"); - - - - - - - - - - - BSP_display("s11-G;"); - - - - - - - - - - - - - - - - - BSP_display("s2-ENTRY;"); - BSP_display("s2-EXIT;"); - - - BSP_display("s2-INIT;"); - - - - - - - - - !m_foo - m_foo = true; -BSP_display("s2-I;"); - - - - - - - - - - - BSP_display("s2-F;"); - - - - - - - BSP_display("s2-C;"); - - - - - - - BSP_display("s21-ENTRY;"); - BSP_display("s21-EXIT;"); - - - BSP_display("s21-INIT;"); - - - - - - - BSP_display("s21-G;"); - - - - - - - BSP_display("s21-A;"); - - - - - - - BSP_display("s21-B;"); - - - - - - - BSP_display("s211-ENTRY;"); - BSP_display("s211-EXIT;"); - - - BSP_display("s211-H;"); - - - - - - - BSP_display("s211-D;"); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #ifndef QHSMTST_HPP_ -#define QHSMTST_HPP_ - -namespace APP { - -enum QHsmTstSignals { - A_SIG = QP::Q_USER_SIG, - B_SIG, - C_SIG, - D_SIG, - E_SIG, - F_SIG, - G_SIG, - H_SIG, - I_SIG, - TERMINATE_SIG, - IGNORE_SIG, - MAX_SIG -}; - -extern QP::QAsm * const the_sm; // opaque pointer to the test SM - -bool QHsmTst_isIn(std::uint32_t const state_num); - -// BSP functions to display a message and exit -void BSP_display(char const *msg); -void BSP_terminate(int16_t const result); - -} // namespace APP - -#endif // QHSMTST_HPP_ - - - - #include "qpcpp.hpp" -#include "qhsmtst.hpp" - -namespace { -Q_DEFINE_THIS_FILE -} - -namespace APP { - -$declare ${SMs::QHsmTst} - -static QHsmTst l_hsmtst; // the only instance of the QHsmTst class - -// global-scope definitions ----------------------------------------- -QP::QAsm * const the_sm = &l_hsmtst; // the opaque pointer - -$define ${SMs::QHsmTst} - -bool QHsmTst_isIn(std::uint32_t const state_num) { - QP::QHsm * const me = &l_hsmtst; - bool stat = false; - switch (state_num) { - case 0: - stat = me->isIn(Q_STATE_CAST(&QHsmTst::s)); - break; - case 1: - stat = me->isIn(Q_STATE_CAST(&QHsmTst::s1)); - break; - case 11: - stat = me->isIn(Q_STATE_CAST(&QHsmTst::s11)); - break; - case 2: - stat = me->isIn(Q_STATE_CAST(&QHsmTst::s2)); - break; - case 21: - stat = me->isIn(Q_STATE_CAST(&QHsmTst::s21)); - break; - case 211: - stat = me->isIn(Q_STATE_CAST(&QHsmTst::s211)); - break; - default: - Q_ERROR(); - } - return stat; -} - -} // namespace APP - - - diff --git a/qutest/qmsm/src/cut_qmsm.cpp b/qutest/qmsm/src/cut_qmsm.cpp new file mode 100644 index 0000000..63986ba --- /dev/null +++ b/qutest/qmsm/src/cut_qmsm.cpp @@ -0,0 +1,849 @@ +//$file${.::cut_qmsm.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +// +// Model: qmsm.qm +// File: ${.::cut_qmsm.cpp} +// +// This code has been generated by QM 6.2.2 . +// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. +// +// Q u a n t u m L e a P s +// ------------------------ +// Modern Embedded Software +// +// SPDX-License-Identifier: GPL-3.0-or-later +// +// This generated code is open source software: you can redistribute it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation. +// +// This code 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. +// +// NOTE: +// Please contact Quantum Leaps for commercial licensing options, which +// expressly supersede the GNU General Public License and are specifically +// designed for licensees interested in retaining the proprietary status +// of the generated code. +// +// Contact information: +// +// +// +//$endhead${.::cut_qmsm.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#include "qpcpp.hpp" +#include "cut_qmsm.hpp" + +namespace { +Q_DEFINE_THIS_FILE +} + +namespace APP { + +//$declare${SMs::QMsmTst} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + +//${SMs::QMsmTst} ............................................................ +class QMsmTst : public QP::QMsm { +private: + bool m_foo; + +public: + friend bool QMsmTst_isIn(std::uint32_t const state_num); + +public: + QMsmTst() + : QMsm(&initial) + {} + +protected: + // exit points for submachine ${SMs::QMsmTst::SM::sub} + struct SM_sub { + QP::QMState super; + QP::QActionHandler const xpH; // exit-point segment + QP::QActionHandler const xpG; // exit-point segment + } const *sub_sub; + + QM_STATE_DECL( initial); + QM_STATE_DECL( s); + QM_ACTION_DECL(s_e); + QM_ACTION_DECL(s_x); + QM_ACTION_DECL(s_i); + QM_SM_STATE_DECL(sub, s1); + QM_ACTION_DECL(s1_e); + QM_ACTION_DECL(s1_xpH); + QM_ACTION_DECL(s1_xpG); + QM_SM_STATE_DECL(sub, s2); + QM_ACTION_DECL(s2_e); + QM_ACTION_DECL(s2_xpH); + QM_ACTION_DECL(s2_xpG); + QM_STATE_DECL( t); + QM_ACTION_DECL(t_e); + QM_ACTION_DECL(t_x); + + // submachine ${SMs::QMsmTst::SM::sub} + QM_STATE_DECL( sub); + QM_ACTION_DECL(sub_e); + QM_ACTION_DECL(sub_x); + QM_ACTION_DECL(sub_i); + QM_ACTION_DECL(sub_ep1_ep); + QM_STATE_DECL( sub_sub1); + QM_ACTION_DECL(sub_sub1_e); + QM_ACTION_DECL(sub_sub1_x); + QM_ACTION_DECL(sub_sub1_i); + QM_STATE_DECL( sub_sub11); + QM_ACTION_DECL(sub_sub11_e); + QM_ACTION_DECL(sub_sub11_x); + QM_STATE_DECL( sub_sub12); + QM_ACTION_DECL(sub_sub12_e); + QM_ACTION_DECL(sub_sub12_x); + QM_STATE_DECL( sub_sub2); + QM_ACTION_DECL(sub_sub2_e); + QM_ACTION_DECL(sub_sub2_x); + +protected: + QP::QMState const *hist_s; + QP::QMState const *hist_s1; + QP::QMState const *hist_s2; +}; // class QMsmTst +//$enddecl${SMs::QMsmTst} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +static QMsmTst l_msmtst; // the only instance of the QMsmTst class + +// global-scope definitions ----------------------------------------- +QP::QAsm * const the_sm = &l_msmtst; // the opaque pointer + +//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +// Check for the minimum required QP version +#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U)) +#error qpcpp version 7.3.0 or higher required +#endif +//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//$define${SMs::QMsmTst} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + +//${SMs::QMsmTst} ............................................................ + +//${SMs::QMsmTst::SM} ........................................................ +QM_STATE_DEF(QMsmTst, initial) { + //${SMs::QMsmTst::SM::initial} + Q_UNUSED_PAR(e); + m_foo = 0U; + BSP_display("top-INIT;"); + + QS_SIG_DICTIONARY(A_SIG, nullptr); + QS_SIG_DICTIONARY(B_SIG, nullptr); + QS_SIG_DICTIONARY(C_SIG, nullptr); + QS_SIG_DICTIONARY(D_SIG, nullptr); + QS_SIG_DICTIONARY(E_SIG, nullptr); + QS_SIG_DICTIONARY(F_SIG, nullptr); + QS_SIG_DICTIONARY(G_SIG, nullptr); + QS_SIG_DICTIONARY(H_SIG, nullptr); + QS_SIG_DICTIONARY(I_SIG, nullptr); + // state history attributes + hist_s = &s1_s.super; + hist_s1 = &sub_sub11_s; + hist_s2 = &sub_sub11_s; + + QS_FUN_DICTIONARY(&QMsmTst::s); + QS_FUN_DICTIONARY(&QMsmTst::s1); + QS_FUN_DICTIONARY(&QMsmTst::s2); + QS_FUN_DICTIONARY(&QMsmTst::t); + QS_FUN_DICTIONARY(&QMsmTst::sub_sub1); + QS_FUN_DICTIONARY(&QMsmTst::sub_sub11); + QS_FUN_DICTIONARY(&QMsmTst::sub_sub12); + QS_FUN_DICTIONARY(&QMsmTst::sub_sub2); + QS_FUN_DICTIONARY(&QMsmTst::sub); + + static struct { + QP::QMState const *target; + QP::QActionHandler act[4]; + } const tatbl_ = { // tran-action table + &sub_s, // target submachine + { + &s_e, // entry + &s2_e, // entry + &sub_i, // initial tran. + Q_ACTION_NULL // zero terminator + } + }; + return qm_tran_init(&tatbl_); +} + +//${SMs::QMsmTst::SM::s} ..................................................... +QP::QMState const QMsmTst::s_s = { + QM_STATE_NULL, // superstate (top) + &QMsmTst::s, + &QMsmTst::s_e, + &QMsmTst::s_x, + &QMsmTst::s_i +}; +//${SMs::QMsmTst::SM::s} +QM_ACTION_DEF(QMsmTst, s_e) { + BSP_display("s-ENTRY;"); + return qm_entry(&s_s); +} +//${SMs::QMsmTst::SM::s} +QM_ACTION_DEF(QMsmTst, s_x) { + BSP_display("s-EXIT;"); + // save shallow history + hist_s = childStateObj(&s_s); + return qm_exit(&s_s); +} +//${SMs::QMsmTst::SM::s::initial} +QM_ACTION_DEF(QMsmTst, s_i) { + //${SMs::QMsmTst::SM::s::initial} + BSP_display("s-INIT;"); + + static struct { + QP::QMState const *target; + QP::QActionHandler act[3]; + } const tatbl_ = { // tran-action table + &sub_s, // target submachine + { + &s1_e, // entry + &sub_i, // initial tran. + Q_ACTION_NULL // zero terminator + } + }; + return qm_tran_init(&tatbl_); +} +//${SMs::QMsmTst::SM::s} +QM_STATE_DEF(QMsmTst, s) { + QP::QState status_; + switch (e->sig) { + //${SMs::QMsmTst::SM::s::E} + case E_SIG: { + BSP_display("s-E;"); + + static struct { + QP::QMState const *target; + QP::QActionHandler act[3]; + } const tatbl_ = { // tran-action table + &sub_s, // target submachine + { + &s1_e, // entry + &sub_ep1_ep, // EP + Q_ACTION_NULL // zero terminator + } + }; + status_ = qm_tran_ep(&tatbl_); + break; + } + //${SMs::QMsmTst::SM::s::I} + case I_SIG: { + BSP_display("s-I;"); + status_ = Q_RET_HANDLED; + break; + } + //${SMs::QMsmTst::SM::s::C} + case C_SIG: { + BSP_display("s-C;"); + + static struct { + QP::QMState const *target; + QP::QActionHandler act[3]; + } const tatbl_ = { // tran-action table + &t_s, // target state + { + &s_x, // exit + &t_e, // entry + Q_ACTION_NULL // zero terminator + } + }; + status_ = qm_tran(&tatbl_); + break; + } + default: { + status_ = Q_RET_SUPER; + break; + } + } + return status_; +} + +//${SMs::QMsmTst::SM::s::s1} ................................................. +QMsmTst::SM_sub const QMsmTst::s1_s = { + { + &QMsmTst::s_s, // superstate + &QMsmTst::s1, + &QMsmTst::s1_e, + Q_ACTION_NULL, // no exit action + &QMsmTst::sub_i // reuse from submachine + }, + &QMsmTst::s1_xpH, + &QMsmTst::s1_xpG +}; +//${SMs::QMsmTst::SM::s::s1} +QM_ACTION_DEF(QMsmTst, s1_e) { + sub_sub = &QMsmTst::s1_s; // attach submachine + return sub_e(this); // enter submachine +} +//${SMs::QMsmTst::SM::s::s1} +QM_ACTION_DEF(QMsmTst, s1_xpG) { + + static struct { + QP::QMState const *target; + QP::QActionHandler act[3]; + } const tatbl_ = { // tran-action table + &sub_s, // target submachine + { + &sub_x, // submachine exit + &s2_e, // entry + Q_ACTION_NULL // zero terminator + } + }; + return qm_tran_hist(hist_s2, &tatbl_); +} +//${SMs::QMsmTst::SM::s::s1} +QM_ACTION_DEF(QMsmTst, s1_xpH) { + + static struct { + QP::QMState const *target; + QP::QActionHandler act[3]; + } const tatbl_ = { // tran-action table + &s_s, // target state + { + &sub_x, // submachine exit + &s_i, // initial tran. + Q_ACTION_NULL // zero terminator + } + }; + return qm_tran(&tatbl_); +} +//${SMs::QMsmTst::SM::s::s1} +QM_STATE_DEF(QMsmTst, s1) { + QP::QState status_; + switch (e->sig) { + //${SMs::QMsmTst::SM::s::s1::F} + case F_SIG: { + BSP_display("s1-F;"); + + static struct { + QP::QMState const *target; + QP::QActionHandler act[3]; + } const tatbl_ = { // tran-action table + &sub_s, // target submachine + { + &s2_e, // entry + &sub_ep1_ep, // EP + Q_ACTION_NULL // zero terminator + } + }; + status_ = qm_tran_ep(&tatbl_); + break; + } + default: { + status_ = Q_RET_SUPER; + break; + } + } + return status_; +} + +//${SMs::QMsmTst::SM::s::s2} ................................................. +QMsmTst::SM_sub const QMsmTst::s2_s = { + { + &QMsmTst::s_s, // superstate + &QMsmTst::s2, + &QMsmTst::s2_e, + Q_ACTION_NULL, // no exit action + &QMsmTst::sub_i // reuse from submachine + }, + &QMsmTst::s2_xpH, + &QMsmTst::s2_xpG +}; +//${SMs::QMsmTst::SM::s::s2} +QM_ACTION_DEF(QMsmTst, s2_e) { + sub_sub = &QMsmTst::s2_s; // attach submachine + return sub_e(this); // enter submachine +} +//${SMs::QMsmTst::SM::s::s2} +QM_ACTION_DEF(QMsmTst, s2_xpH) { + + static struct { + QP::QMState const *target; + QP::QActionHandler act[3]; + } const tatbl_ = { // tran-action table + &s_s, // target state + { + &sub_x, // submachine exit + &s_i, // initial tran. + Q_ACTION_NULL // zero terminator + } + }; + return qm_tran(&tatbl_); +} +//${SMs::QMsmTst::SM::s::s2} +QM_ACTION_DEF(QMsmTst, s2_xpG) { + + static struct { + QP::QMState const *target; + QP::QActionHandler act[3]; + } const tatbl_ = { // tran-action table + &sub_s, // target submachine + { + &sub_x, // submachine exit + &s1_e, // entry + Q_ACTION_NULL // zero terminator + } + }; + return qm_tran_hist(hist_s1, &tatbl_); +} +//${SMs::QMsmTst::SM::s::s2} +QM_STATE_DEF(QMsmTst, s2) { + QP::QState status_; + switch (e->sig) { + //${SMs::QMsmTst::SM::s::s2::F} + case F_SIG: { + BSP_display("s2-F;"); + + static struct { + QP::QMState const *target; + QP::QActionHandler act[3]; + } const tatbl_ = { // tran-action table + &sub_s, // target submachine + { + &s1_e, // entry + &sub_ep1_ep, // EP + Q_ACTION_NULL // zero terminator + } + }; + status_ = qm_tran_ep(&tatbl_); + break; + } + default: { + status_ = Q_RET_SUPER; + break; + } + } + return status_; +} + +//${SMs::QMsmTst::SM::t} ..................................................... +QP::QMState const QMsmTst::t_s = { + QM_STATE_NULL, // superstate (top) + &QMsmTst::t, + &QMsmTst::t_e, + &QMsmTst::t_x, + Q_ACTION_NULL // no initial tran. +}; +//${SMs::QMsmTst::SM::t} +QM_ACTION_DEF(QMsmTst, t_e) { + BSP_display("t-ENTRY;"); + return qm_entry(&t_s); +} +//${SMs::QMsmTst::SM::t} +QM_ACTION_DEF(QMsmTst, t_x) { + BSP_display("t-EXIT;"); + return qm_exit(&t_s); +} +//${SMs::QMsmTst::SM::t} +QM_STATE_DEF(QMsmTst, t) { + QP::QState status_; + switch (e->sig) { + //${SMs::QMsmTst::SM::t::C} + case C_SIG: { + BSP_display("t-C->H-s;"); + + static struct { + QP::QMState const *target; + QP::QActionHandler act[3]; + } const tatbl_ = { // tran-action table + &s_s, // target state + { + &t_x, // exit + &s_e, // entry + Q_ACTION_NULL // zero terminator + } + }; + status_ = qm_tran_hist(hist_s, &tatbl_); + break; + } + default: { + status_ = Q_RET_SUPER; + break; + } + } + return status_; +} + +//${SMs::QMsmTst::SM::sub} ................................................... +//${SMs::QMsmTst::SM::sub} +QP::QMState const QMsmTst::sub_s = { + QM_STATE_NULL, // superstate unused + &QMsmTst::sub, + &QMsmTst::sub_e, + &QMsmTst::sub_x, + &QMsmTst::sub_i +}; +//${SMs::QMsmTst::SM::sub} +QM_ACTION_DEF(QMsmTst, sub_e) { + BSP_display("sub-ENTRY;"); + return qm_entry(&sub_s); +} +//${SMs::QMsmTst::SM::sub} +QM_ACTION_DEF(QMsmTst, sub_x) { + BSP_display("sub-EXIT;"); + return qm_sm_exit(&sub_sub->super); +} +//${SMs::QMsmTst::SM::sub::initial} +QM_ACTION_DEF(QMsmTst, sub_i) { + //${SMs::QMsmTst::SM::sub::initial} + BSP_display("sub-INIT;"); + + static struct { + QP::QMState const *target; + QP::QActionHandler act[3]; + } const tatbl_ = { // tran-action table + &sub_sub11_s, // target state + { + &sub_sub1_e, // entry + &sub_sub11_e, // entry + Q_ACTION_NULL // zero terminator + } + }; + return qm_tran_init(&tatbl_); +} +//${SMs::QMsmTst::SM::sub} +QM_STATE_DEF(QMsmTst, sub) { + QP::QState status_; + switch (e->sig) { + //${SMs::QMsmTst::SM::sub::E} + case E_SIG: { + BSP_display("sub-E;"); + + static struct { + QP::QMState const *target; + QP::QActionHandler act[2]; + } const tatbl_ = { // tran-action table + &sub_sub2_s, // target state + { + &sub_sub2_e, // entry + Q_ACTION_NULL // zero terminator + } + }; + status_ = qm_tran(&tatbl_); + break; + } + //${SMs::QMsmTst::SM::sub::I} + case I_SIG: { + //${SMs::QMsmTst::SM::sub::I::[m_foo]} + if (m_foo) { + m_foo = 0U; + BSP_display("sub-I;"); + status_ = Q_RET_HANDLED; + } + else { + status_ = qm_super_sub(&sub_sub->super); + } + break; + } + default: { + status_ = qm_super_sub(&sub_sub->super); + break; + } + } + return status_; +} +//${SMs::QMsmTst::SM::sub::EP-ep1} +QM_ACTION_DEF(QMsmTst, sub_ep1_ep) { + BSP_display("sub-ep1;"); + + static struct { + QP::QMState const *target; + QP::QActionHandler act[3]; + } const tatbl_ = { // tran-action table + &sub_sub1_s, // target state + { + &sub_sub1_e, // entry + &sub_sub1_i, // initial tran. + Q_ACTION_NULL // zero terminator + } + }; + return qm_tran_ep(&tatbl_); +} + +//${SMs::QMsmTst::SM::sub::sub1} ............................................. +QP::QMState const QMsmTst::sub_sub1_s = { + &QMsmTst::sub_s, // superstate + &QMsmTst::sub_sub1, + &QMsmTst::sub_sub1_e, + &QMsmTst::sub_sub1_x, + &QMsmTst::sub_sub1_i +}; +//${SMs::QMsmTst::SM::sub::sub1} +QM_ACTION_DEF(QMsmTst, sub_sub1_e) { + BSP_display("sub1-ENTRY;"); + return qm_entry(&sub_sub1_s); +} +//${SMs::QMsmTst::SM::sub::sub1} +QM_ACTION_DEF(QMsmTst, sub_sub1_x) { + BSP_display("sub1-EXIT;"); + return qm_exit(&sub_sub1_s); +} +//${SMs::QMsmTst::SM::sub::sub1::initial} +QM_ACTION_DEF(QMsmTst, sub_sub1_i) { + //${SMs::QMsmTst::SM::sub::sub1::initial} + BSP_display("sub1-INIT;"); + + static struct { + QP::QMState const *target; + QP::QActionHandler act[2]; + } const tatbl_ = { // tran-action table + &sub_sub11_s, // target state + { + &sub_sub11_e, // entry + Q_ACTION_NULL // zero terminator + } + }; + return qm_tran_init(&tatbl_); +} +//${SMs::QMsmTst::SM::sub::sub1} +QM_STATE_DEF(QMsmTst, sub_sub1) { + QP::QState status_; + switch (e->sig) { + //${SMs::QMsmTst::SM::sub::sub1::A} + case A_SIG: { + BSP_display("sub1-A;"); + + static struct { + QP::QMState const *target; + QP::QActionHandler act[4]; + } const tatbl_ = { // tran-action table + &sub_sub1_s, // target state + { + &sub_sub1_x, // exit + &sub_sub1_e, // entry + &sub_sub1_i, // initial tran. + Q_ACTION_NULL // zero terminator + } + }; + status_ = qm_tran(&tatbl_); + break; + } + //${SMs::QMsmTst::SM::sub::sub1::B} + case B_SIG: { + BSP_display("sub1-B;"); + + static struct { + QP::QMState const *target; + QP::QActionHandler act[2]; + } const tatbl_ = { // tran-action table + &sub_sub11_s, // target state + { + &sub_sub11_e, // entry + Q_ACTION_NULL // zero terminator + } + }; + status_ = qm_tran(&tatbl_); + break; + } + //${SMs::QMsmTst::SM::sub::sub1::D} + case D_SIG: { + //${SMs::QMsmTst::SM::sub::sub1::D::[!m_foo]} + if (!m_foo) { + m_foo = 1U; + BSP_display("sub1-D;"); + + static struct { + QP::QMState const *target; + QP::QActionHandler act[3]; + } const tatbl_ = { // tran-action table + &sub_s, // target submachine + { + &sub_sub1_x, // exit + &sub_i, // initial tran. + Q_ACTION_NULL // zero terminator + } + }; + status_ = qm_tran(&tatbl_); + } + else { + status_ = Q_RET_UNHANDLED; + } + break; + } + //${SMs::QMsmTst::SM::sub::sub1::G} + case G_SIG: { + BSP_display("sub1-G->xpG;"); + + static struct { + QP::QMState const *target; + QP::QActionHandler act[2]; + } const tatbl_ = { // tran-action table + &sub_s, // target submachine + { + &sub_sub1_x, // exit + Q_ACTION_NULL // zero terminator + } + }; + status_ = qm_tran_xp(sub_sub->xpG, &tatbl_); + break; + } + default: { + status_ = Q_RET_SUPER; + break; + } + } + return status_; +} + +//${SMs::QMsmTst::SM::sub::sub1::sub11} ...................................... +QP::QMState const QMsmTst::sub_sub11_s = { + &QMsmTst::sub_sub1_s, // superstate + &QMsmTst::sub_sub11, + &QMsmTst::sub_sub11_e, + &QMsmTst::sub_sub11_x, + Q_ACTION_NULL // no initial tran. +}; +//${SMs::QMsmTst::SM::sub::sub1::sub11} +QM_ACTION_DEF(QMsmTst, sub_sub11_e) { + BSP_display("sub11-ENTRY;"); + return qm_entry(&sub_sub11_s); +} +//${SMs::QMsmTst::SM::sub::sub1::sub11} +QM_ACTION_DEF(QMsmTst, sub_sub11_x) { + BSP_display("sub11-EXIT;"); + return qm_exit(&sub_sub11_s); +} +//${SMs::QMsmTst::SM::sub::sub1::sub11} +QM_STATE_DEF(QMsmTst, sub_sub11) { + QP::QState status_; + switch (e->sig) { + //${SMs::QMsmTst::SM::sub::sub1::sub11::C} + case C_SIG: { + BSP_display("sub11-C;"); + + static struct { + QP::QMState const *target; + QP::QActionHandler act[3]; + } const tatbl_ = { // tran-action table + &sub_sub12_s, // target state + { + &sub_sub11_x, // exit + &sub_sub12_e, // entry + Q_ACTION_NULL // zero terminator + } + }; + status_ = qm_tran(&tatbl_); + break; + } + default: { + status_ = Q_RET_SUPER; + break; + } + } + return status_; +} + +//${SMs::QMsmTst::SM::sub::sub1::sub12} ...................................... +QP::QMState const QMsmTst::sub_sub12_s = { + &QMsmTst::sub_sub1_s, // superstate + &QMsmTst::sub_sub12, + &QMsmTst::sub_sub12_e, + &QMsmTst::sub_sub12_x, + Q_ACTION_NULL // no initial tran. +}; +//${SMs::QMsmTst::SM::sub::sub1::sub12} +QM_ACTION_DEF(QMsmTst, sub_sub12_e) { + BSP_display("sub12-ENTRY;"); + return qm_entry(&sub_sub12_s); +} +//${SMs::QMsmTst::SM::sub::sub1::sub12} +QM_ACTION_DEF(QMsmTst, sub_sub12_x) { + BSP_display("sub12-EXIT;"); + return qm_exit(&sub_sub12_s); +} +//${SMs::QMsmTst::SM::sub::sub1::sub12} +QM_STATE_DEF(QMsmTst, sub_sub12) { + QP::QState status_; + switch (e->sig) { + //${SMs::QMsmTst::SM::sub::sub1::sub12::H} + case H_SIG: { + BSP_display("sub12-H->xpH;"); + + static struct { + QP::QMState const *target; + QP::QActionHandler act[3]; + } const tatbl_ = { // tran-action table + &sub_s, // target submachine + { + &sub_sub12_x, // exit + &sub_sub1_x, // exit + Q_ACTION_NULL // zero terminator + } + }; + status_ = qm_tran_xp(sub_sub->xpH, &tatbl_); + break; + } + default: { + status_ = Q_RET_SUPER; + break; + } + } + return status_; +} + +//${SMs::QMsmTst::SM::sub::sub2} ............................................. +QP::QMState const QMsmTst::sub_sub2_s = { + &QMsmTst::sub_s, // superstate + &QMsmTst::sub_sub2, + &QMsmTst::sub_sub2_e, + &QMsmTst::sub_sub2_x, + Q_ACTION_NULL // no initial tran. +}; +//${SMs::QMsmTst::SM::sub::sub2} +QM_ACTION_DEF(QMsmTst, sub_sub2_e) { + BSP_display("sub2-ENTRY;"); + return qm_entry(&sub_sub2_s); +} +//${SMs::QMsmTst::SM::sub::sub2} +QM_ACTION_DEF(QMsmTst, sub_sub2_x) { + BSP_display("sub2-EXIT;"); + return qm_exit(&sub_sub2_s); +} +//${SMs::QMsmTst::SM::sub::sub2} +QM_STATE_DEF(QMsmTst, sub_sub2) { + QP::QState status_; + switch (e->sig) { + default: { + status_ = Q_RET_SUPER; + break; + } + } + return status_; +} +//$enddef${SMs::QMsmTst} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +bool QMsmTst_isIn(std::uint32_t const state_num) { + QP::QMsm * const me = &l_msmtst; + bool stat = false; + switch (state_num) { + case 0: + stat = me->isIn(Q_STATE_CAST(&QMsmTst::s)); + break; + case 1: + stat = me->isIn(Q_STATE_CAST(&QMsmTst::s1)); + break; + case 2: + stat = me->isIn(Q_STATE_CAST(&QMsmTst::s2)); + break; + case 11: + stat = me->isIn(Q_STATE_CAST(&QMsmTst::sub_sub1)); + break; + case 111: + stat = me->isIn(Q_STATE_CAST(&QMsmTst::sub_sub11)); + break; + case 112: + stat = me->isIn(Q_STATE_CAST(&QMsmTst::sub_sub12)); + break; + case 12: + stat = me->isIn(Q_STATE_CAST(&QMsmTst::sub_sub2)); + break; + default: + Q_ERROR(); + } + return stat; +} + +} // namespace APP diff --git a/qutest/qmsmtst/src/qmsmtst.hpp b/qutest/qmsm/src/cut_qmsm.hpp similarity index 61% rename from qutest/qmsmtst/src/qmsmtst.hpp rename to qutest/qmsm/src/cut_qmsm.hpp index 2dccc60..6d21940 100644 --- a/qutest/qmsmtst/src/qmsmtst.hpp +++ b/qutest/qmsm/src/cut_qmsm.hpp @@ -1,11 +1,15 @@ -//$file${.::qmsmtst.hpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +//$file${.::cut_qmsm.hpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv // -// Model: qmsmtst.qm -// File: ${.::qmsmtst.hpp} +// Model: qmsm.qm +// File: ${.::cut_qmsm.hpp} // -// This code has been generated by QM 5.3.0 . +// This code has been generated by QM 6.2.2 . // DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. // +// Q u a n t u m L e a P s +// ------------------------ +// Modern Embedded Software +// // SPDX-License-Identifier: GPL-3.0-or-later // // This generated code is open source software: you can redistribute it under @@ -18,18 +22,18 @@ // more details. // // NOTE: -// Alternatively, this generated code may be distributed under the terms -// of Quantum Leaps commercial licenses, which expressly supersede the GNU -// General Public License and are specifically designed for licensees -// interested in retaining the proprietary status of their code. +// Please contact Quantum Leaps for commercial licensing options, which +// expressly supersede the GNU General Public License and are specifically +// designed for licensees interested in retaining the proprietary status +// of the generated code. // // Contact information: // // // -//$endhead${.::qmsmtst.hpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -#ifndef QMSMTST_HPP_ -#define QMSMTST_HPP_ +//$endhead${.::cut_qmsm.hpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#ifndef CUT_QMSM_HPP_ +#define CUT_QMSM_HPP_ namespace APP { @@ -43,8 +47,6 @@ enum QMsmTstSignals { G_SIG, H_SIG, I_SIG, - TERMINATE_SIG, - IGNORE_SIG, MAX_SIG }; @@ -58,4 +60,4 @@ void BSP_terminate(int16_t const result); } // namespace APP -#endif // QMSMTST_HPP_ +#endif // CUT_QMSM_HPP_ diff --git a/qutest/qmsm/src/qmsm.qm b/qutest/qmsm/src/qmsm.qm new file mode 100644 index 0000000..9c90e24 --- /dev/null +++ b/qutest/qmsm/src/qmsm.qm @@ -0,0 +1,390 @@ + + + QMsmTst is a contrived state machine from Chapter 2 of the PSiCC2 book for testing all possible transition topologies with up to 4-levels of state nesting. + + + + + + + Test State Machine + + + + + + + : QMsm(&initial) + + + + + + Q_UNUSED_PAR(e); +m_foo = 0U; +BSP_display("top-INIT;"); + +QS_SIG_DICTIONARY(A_SIG, nullptr); +QS_SIG_DICTIONARY(B_SIG, nullptr); +QS_SIG_DICTIONARY(C_SIG, nullptr); +QS_SIG_DICTIONARY(D_SIG, nullptr); +QS_SIG_DICTIONARY(E_SIG, nullptr); +QS_SIG_DICTIONARY(F_SIG, nullptr); +QS_SIG_DICTIONARY(G_SIG, nullptr); +QS_SIG_DICTIONARY(H_SIG, nullptr); +QS_SIG_DICTIONARY(I_SIG, nullptr); + + + + + + + BSP_display("s-ENTRY;"); + BSP_display("s-EXIT;"); + + + BSP_display("s-INIT;"); + + + + + + + + + + + BSP_display("s-E;"); + + + + + + + BSP_display("s-I;"); + + + + + + + BSP_display("s-C;"); + + + + + + + + + + + + + + + + + + + + + BSP_display("s1-F;"); + + + + + + + + + + + + + + + + + + + + + + + BSP_display("s2-F;"); + + + + + + + + + + + + + + BSP_display("t-ENTRY;"); + BSP_display("t-EXIT;"); + + + BSP_display("t-C->H-s;"); + + + + + + + + + + + + BSP_display("sub-ENTRY;"); + BSP_display("sub-EXIT;"); + + + BSP_display("sub-ep1;"); + + + + + + + + + + + + + + + + + + + + BSP_display("sub-INIT;"); + + + + + + + + + + + BSP_display("sub-E;"); + + + + + + + + + m_foo + m_foo = 0U; +BSP_display("sub-I;"); + + + + + + + + + + + BSP_display("sub1-ENTRY;"); + BSP_display("sub1-EXIT;"); + + + BSP_display("sub1-INIT;"); + + + + + + + BSP_display("sub1-A;"); + + + + + + + BSP_display("sub1-B;"); + + + + + + + + + !m_foo + m_foo = 1U; +BSP_display("sub1-D;"); + + + + + + + + + + + BSP_display("sub1-G->xpG;"); + + + + + + + BSP_display("sub11-ENTRY;"); + BSP_display("sub11-EXIT;"); + + + BSP_display("sub11-C;"); + + + + + + + + + + + + BSP_display("sub12-ENTRY;"); + BSP_display("sub12-EXIT;"); + + + BSP_display("sub12-H->xpH;"); + + + + + + + + + + + + + + + + + BSP_display("sub2-ENTRY;"); + BSP_display("sub2-EXIT;"); + + + + + + + + + + + + + + + + + + + #ifndef CUT_QMSM_HPP_ +#define CUT_QMSM_HPP_ + +namespace APP { + +enum QMsmTstSignals { + A_SIG = QP::Q_USER_SIG, + B_SIG, + C_SIG, + D_SIG, + E_SIG, + F_SIG, + G_SIG, + H_SIG, + I_SIG, + MAX_SIG +}; + +extern QP::QAsm * const the_sm; // opaque pointer to the test SM + +bool QMsmTst_isIn(std::uint32_t const state_num); + +// BSP functions to display a message and exit +void BSP_display(char const *msg); +void BSP_terminate(int16_t const result); + +} // namespace APP + +#endif // CUT_QMSM_HPP_ + + + + #include "qpcpp.hpp" +#include "cut_qmsm.hpp" + +namespace { +Q_DEFINE_THIS_FILE +} + +namespace APP { + +$declare ${SMs::QMsmTst} + +static QMsmTst l_msmtst; // the only instance of the QMsmTst class + +// global-scope definitions ----------------------------------------- +QP::QAsm * const the_sm = &l_msmtst; // the opaque pointer + +$define ${SMs::QMsmTst} + +bool QMsmTst_isIn(std::uint32_t const state_num) { + QP::QMsm * const me = &l_msmtst; + bool stat = false; + switch (state_num) { + case 0: + stat = me->isIn(Q_STATE_CAST(&QMsmTst::s)); + break; + case 1: + stat = me->isIn(Q_STATE_CAST(&QMsmTst::s1)); + break; + case 2: + stat = me->isIn(Q_STATE_CAST(&QMsmTst::s2)); + break; + case 11: + stat = me->isIn(Q_STATE_CAST(&QMsmTst::sub_sub1)); + break; + case 111: + stat = me->isIn(Q_STATE_CAST(&QMsmTst::sub_sub11)); + break; + case 112: + stat = me->isIn(Q_STATE_CAST(&QMsmTst::sub_sub12)); + break; + case 12: + stat = me->isIn(Q_STATE_CAST(&QMsmTst::sub_sub2)); + break; + default: + Q_ERROR(); + } + return stat; +} + +} // namespace APP + + + diff --git a/qutest/qmsmtst/test/Makefile b/qutest/qmsm/test/Makefile similarity index 96% rename from qutest/qmsmtst/test/Makefile rename to qutest/qmsm/test/Makefile index 303bbd5..6d6b7fe 100644 --- a/qutest/qmsmtst/test/Makefile +++ b/qutest/qmsm/test/Makefile @@ -1,7 +1,7 @@ ############################################################################## # Product: Makefile for QUTEST-QP/C++ for Windows and POSIX *HOSTS* -# Last Updated for Version: 7.2.0 -# Date of the Last Update: 2022-12-21 +# Last Updated for Version: 7.4.0 +# Date of the Last Update: 2024-09-02 # # Q u a n t u m L e a P s # ------------------------ @@ -82,7 +82,7 @@ C_SRCS := # C++ source files... CPP_SRCS := \ - qmsmtst.cpp \ + cut_qmsm.cpp \ test_qmsm.cpp LIB_DIRS := @@ -122,6 +122,7 @@ LIBS += -lws2_32 else QP_PORT_DIR := $(QPCPP)/ports/posix-qutest +#QP_PORT_DIR := $(QPCPP)/ports/posix LIBS += -lpthread endif @@ -218,8 +219,14 @@ $(TARGET_EXE) : $(C_OBJS_EXT) $(CPP_OBJS_EXT) $(CPP) $(CPPFLAGS) $(QPCPP)/src/qs/qstamp.cpp -o $(BIN_DIR)/qstamp.o $(LINK) $(LINKFLAGS) $(LIB_DIRS) -o $@ $^ $(BIN_DIR)/qstamp.o $(LIBS) +ifdef GCOV run : $(TARGET_EXE) + -$(RM) $(BIN_DIR)/*.gcda $(QUTEST) -e$(TARGET_EXE) -q$(QSPY) -l$(LOG) -o$(OPT) -- $(TESTS) +else +run : $(TARGET_EXE) + $(QUTEST) -e$(TARGET_EXE) -q$(QSPY) -l$(LOG) -o$(OPT) -- $(TESTS) +endif $(BIN_DIR)/%.d : %.cpp $(CPP) -MM -MT $(@:.d=.o) $(CPPFLAGS) $< > $@ diff --git a/qutest/qmsm/test/gcov_qmsm.bat b/qutest/qmsm/test/gcov_qmsm.bat new file mode 100644 index 0000000..3c2ff74 --- /dev/null +++ b/qutest/qmsm/test/gcov_qmsm.bat @@ -0,0 +1 @@ +gcov -f -o build qep_msm.o diff --git a/qutest/qmsmtst/test/make_nucleo-l053r8 b/qutest/qmsm/test/make_nucleo-l053r8 similarity index 99% rename from qutest/qmsmtst/test/make_nucleo-l053r8 rename to qutest/qmsm/test/make_nucleo-l053r8 index 707acd7..d4740e7 100644 --- a/qutest/qmsmtst/test/make_nucleo-l053r8 +++ b/qutest/qmsm/test/make_nucleo-l053r8 @@ -1,7 +1,7 @@ ############################################################################## # Product: Makefile for QP/C on NUCLEO-L053R8 board, QUTEST, GNU-ARM -# Last Updated for Version: 7.3.1 -# Date of the Last Update: 2023-11-13 +# Last Updated for Version: 7.4.0 +# Date of the Last Update: 2024-09-04 # # Q u a n t u m L e a P s # ------------------------ @@ -103,7 +103,7 @@ C_SRCS := \ # C++ source files CPP_SRCS := \ - qmsmtst.cpp \ + cut_qmsm.cpp \ test_qmsm.cpp OUTPUT := $(PROJECT) diff --git a/qutest/qmsmtst/test/make_tm4c123 b/qutest/qmsm/test/make_tm4c123 similarity index 99% rename from qutest/qmsmtst/test/make_tm4c123 rename to qutest/qmsm/test/make_tm4c123 index 86f9793..c9d808d 100644 --- a/qutest/qmsmtst/test/make_tm4c123 +++ b/qutest/qmsm/test/make_tm4c123 @@ -1,7 +1,7 @@ ############################################################################## # Product: Makefile for QP/C++ on TM4C123, QUTEST, GNU-ARM -# Last Updated for Version: 7.2.0 -# Date of the Last Update: 2022-12-21 +# Last Updated for Version: 7.4.0 +# Date of the Last Update: 2024-09-04 # # Q u a n t u m L e a P s # ------------------------ @@ -103,7 +103,7 @@ C_SRCS := \ # C++ source files CPP_SRCS := \ - qmsmtst.cpp \ + cut_qmsm.cpp \ test_qmsm.cpp OUTPUT := $(PROJECT) diff --git a/qutest/qmsm/test/qep_msm.cpp.gcov b/qutest/qmsm/test/qep_msm.cpp.gcov new file mode 100644 index 0000000..a650cf7 --- /dev/null +++ b/qutest/qmsm/test/qep_msm.cpp.gcov @@ -0,0 +1,669 @@ + -: 0:Source:../../../../src/qf/qep_msm.cpp + -: 0:Graph:build/qep_msm.gcno + -: 0:Data:build/qep_msm.gcda + -: 0:Runs:6 + -: 1://$file${src::qf::qep_msm.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 2:// + -: 3:// Model: qpcpp.qm + -: 4:// File: ${src::qf::qep_msm.cpp} + -: 5:// + -: 6:// This code has been generated by QM 6.1.1 . + -: 7:// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. + -: 8:// + -: 9:// This code is covered by the following QP license: + -: 10:// License # : LicenseRef-QL-dual + -: 11:// Issued to : Any user of the QP/C++ real-time embedded framework + -: 12:// Framework(s) : qpcpp + -: 13:// Support ends : 2024-12-31 + -: 14:// License scope: + -: 15:// + -: 16:// Copyright (C) 2005 Quantum Leaps, LLC . + -: 17:// + -: 18:// Q u a n t u m L e a P s + -: 19:// ------------------------ + -: 20:// Modern Embedded Software + -: 21:// + -: 22:// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial + -: 23:// + -: 24:// This software is dual-licensed under the terms of the open source GNU + -: 25:// General Public License version 3 (or any later version), or alternatively, + -: 26:// under the terms of one of the closed source Quantum Leaps commercial + -: 27:// licenses. + -: 28:// + -: 29:// The terms of the open source GNU General Public License version 3 + -: 30:// can be found at: + -: 31:// + -: 32:// The terms of the closed source Quantum Leaps commercial licenses + -: 33:// can be found at: + -: 34:// + -: 35:// Redistributions in source code must retain this top-level comment block. + -: 36:// Plagiarizing this software to sidestep the license obligations is illegal. + -: 37:// + -: 38:// Contact information: + -: 39:// + -: 40:// + -: 41:// + -: 42://$endhead${src::qf::qep_msm.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 43:#define QP_IMPL // this is QP implementation + -: 44:#include "qp_port.hpp" // QP port + -: 45:#include "qp_pkg.hpp" // QP package-scope interface + -: 46:#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem + -: 47:#ifdef Q_SPY // QS software tracing enabled? + -: 48: #include "qs_port.hpp" // QS port + -: 49: #include "qs_pkg.hpp" // QS facilities for pre-defined trace records + -: 50:#else + -: 51: #include "qs_dummy.hpp" // disable the QS software tracing + -: 52:#endif // Q_SPY + -: 53: + -: 54://============================================================================ + -: 55://! @cond INTERNAL + -: 56: + -: 57:// unnamed namespace for local definitions with internal linkage + -: 58:namespace { + -: 59: + -: 60:Q_DEFINE_THIS_MODULE("qep_msm") + -: 61: + -: 62:// maximum depth of state nesting in a QMsm (including the top level) + -: 63:static constexpr std::int_fast8_t MAX_NEST_DEPTH_ {6}; + -: 64: + -: 65:// maximum length of transition-action array + -: 66:static constexpr std::int_fast8_t MAX_TRAN_LENGTH_ {3*MAX_NEST_DEPTH_}; + -: 67: + -: 68:// maximum depth of entry levels in a MSM for tran. to history. + -: 69:static constexpr std::int_fast8_t MAX_ENTRY_DEPTH_ {4}; + -: 70: + -: 71:// top-state object for QMsm-style state machines + -: 72:QP::QMState const l_msm_top_s = { + -: 73: nullptr, + -: 74: nullptr, + -: 75: nullptr, + -: 76: nullptr, + -: 77: nullptr + -: 78:}; + -: 79: + -: 80:} // unnamed namespace + -: 81: + -: 82://! @endcond + -: 83://============================================================================ + -: 84: + -: 85://$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 86:// Check for the minimum required QP version + -: 87:#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U)) + -: 88:#error qpcpp version 7.3.0 or higher required + -: 89:#endif + -: 90://$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 91: + -: 92://$define${QEP::QMsm} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 93:namespace QP { + -: 94: + -: 95://${QEP::QMsm} ............................................................... + -: 96: + -: 97://${QEP::QMsm::QMsm} ......................................................... + 6: 98:QMsm::QMsm(QStateHandler const initial) noexcept + 6: 99: : QAsm() + -: 100:{ + 6: 101: m_state.obj = &l_msm_top_s; // the current state (top) + 6: 102: m_temp.fun = initial; // the initial tran. handler + 6: 103:} + -: 104: + -: 105://${QEP::QMsm::init} ......................................................... + 6: 106:void QMsm::init( + -: 107: void const * const e, + -: 108: std::uint_fast8_t const qsId) + -: 109:{ + -: 110: #ifndef Q_SPY + -: 111: Q_UNUSED_PAR(qsId); + -: 112: #endif + -: 113: + -: 114: QF_CRIT_STAT + 6: 115: QF_CRIT_ENTRY(); + 6*: 116: Q_REQUIRE_INCRIT(200, (m_temp.fun != nullptr) + -: 117: && (m_state.obj == &l_msm_top_s)); + 6: 118: QF_CRIT_EXIT(); + -: 119: + -: 120: // execute the top-most initial tran. + 6: 121: QState r = (*m_temp.fun)(this, Q_EVT_CAST(QEvt)); + -: 122: + 6: 123: QF_CRIT_ENTRY(); + -: 124: // the top-most initial tran. must be taken + 6*: 125: Q_ASSERT_INCRIT(210, r == Q_RET_TRAN_INIT); + -: 126: + 6: 127: QS_MEM_SYS(); + 6: 128: QS_BEGIN_PRE_(QS_QEP_STATE_INIT, qsId) + 3: 129: QS_OBJ_PRE_(this); // this state machine object + 3: 130: QS_FUN_PRE_(m_state.obj->stateHandler); // source state + 3: 131: QS_FUN_PRE_(m_temp.tatbl->target->stateHandler); // target state + 3: 132: QS_END_PRE_() + 6: 133: QS_MEM_APP(); + -: 134: + 6: 135: QF_CRIT_EXIT(); + -: 136: + -: 137: // set state to the last tran. target + 6: 138: m_state.obj = m_temp.tatbl->target; + -: 139: + -: 140: // drill down into the state hierarchy with initial transitions... + 6: 141: std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit + 12: 142: do { + -: 143: // execute the tran. table + 12: 144: r = execTatbl_(m_temp.tatbl, qsId); + 12: 145: --limit; + 12: 146: } while ((r >= Q_RET_TRAN_INIT) && (limit > 0)); + -: 147: + 6: 148: QF_CRIT_ENTRY(); + 6*: 149: Q_ENSURE_INCRIT(290, limit > 0); + -: 150: + 6: 151: QS_MEM_SYS(); + 6: 152: QS_BEGIN_PRE_(QS_QEP_INIT_TRAN, qsId) + 3: 153: QS_TIME_PRE_(); // time stamp + 3: 154: QS_OBJ_PRE_(this); // this state machine object + 3: 155: QS_FUN_PRE_(m_state.obj->stateHandler); // the new current state + 3: 156: QS_END_PRE_() + 6: 157: QS_MEM_APP(); + -: 158: + 6: 159: QF_CRIT_EXIT(); + -: 160: + -: 161: #ifndef Q_UNSAFE + 6: 162: m_temp.uint = ~m_state.uint; + -: 163: #endif + 6: 164:} + -: 165: + -: 166://${QEP::QMsm::dispatch} ..................................................... + 35: 167:void QMsm::dispatch( + -: 168: QEvt const * const e, + -: 169: std::uint_fast8_t const qsId) + -: 170:{ + -: 171: #ifndef Q_SPY + -: 172: Q_UNUSED_PAR(qsId); + -: 173: #endif + -: 174: + 35: 175: QMState const *s = m_state.obj; // store the current state + 35: 176: QMState const *t = s; + -: 177: + -: 178: QF_CRIT_STAT + 35: 179: QF_CRIT_ENTRY(); + 35*: 180: Q_REQUIRE_INCRIT(300, (s != nullptr) + -: 181: && (m_state.uint == static_cast(~m_temp.uint))); + 35*: 182: Q_REQUIRE_INCRIT(302, QEvt::verify_(e)); + -: 183: + 35: 184: QS_MEM_SYS(); + 35: 185: QS_BEGIN_PRE_(QS_QEP_DISPATCH, qsId) + 18: 186: QS_TIME_PRE_(); // time stamp + 18: 187: QS_SIG_PRE_(e->sig); // the signal of the event + 18: 188: QS_OBJ_PRE_(this); // this state machine object + 18: 189: QS_FUN_PRE_(s->stateHandler); // the current state handler + 18: 190: QS_END_PRE_() + 35: 191: QS_MEM_APP(); + -: 192: + 35: 193: QF_CRIT_EXIT(); + -: 194: + -: 195: // scan the state hierarchy up to the top state... + 35: 196: QState r; + 35: 197: std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit + 87: 198: do { + 87: 199: r = (*t->stateHandler)(this, e); // call state handler function + -: 200: + -: 201: // event handled? (the most frequent case) + 87: 202: if (r >= Q_RET_HANDLED) { + -: 203: break; // done scanning the state hierarchy + -: 204: } + -: 205: // event unhandled and passed to the superstate? + 55: 206: else if (r == Q_RET_SUPER) { + 44: 207: t = t->superstate; // advance to the superstate + -: 208: } + -: 209: // event unhandled and passed to a submachine superstate? + 11: 210: else if (r == Q_RET_SUPER_SUB) { + 9: 211: t = m_temp.obj; // current host state of the submachie + -: 212: } + -: 213: else { // event unhandled due to a guard? + 2: 214: QF_CRIT_ENTRY(); + -: 215: // event must be unhandled due to a guard evaluating to 'false' + 2*: 216: Q_ASSERT_INCRIT(310, r == Q_RET_UNHANDLED); + -: 217: + 2: 218: QS_MEM_SYS(); + 2: 219: QS_BEGIN_PRE_(QS_QEP_UNHANDLED, qsId) + 1: 220: QS_SIG_PRE_(e->sig); // the signal of the event + 1: 221: QS_OBJ_PRE_(this); // this state machine object + 1: 222: QS_FUN_PRE_(t->stateHandler); // the current state + 1: 223: QS_END_PRE_() + 2: 224: QS_MEM_APP(); + -: 225: + 2: 226: QF_CRIT_EXIT(); + -: 227: + 2: 228: t = t->superstate; // advance to the superstate + -: 229: } + 55: 230: --limit; + 55: 231: } while ((t != nullptr) && (limit > 0)); + 35: 232: QF_CRIT_ENTRY(); + 35*: 233: Q_ASSERT_INCRIT(310, limit > 0); + 35: 234: QF_CRIT_EXIT(); + -: 235: + 35: 236: if (r >= Q_RET_TRAN) { // any kind of tran. taken? + -: 237: #ifdef Q_SPY + 28: 238: QMState const * const ts = t; // tran. source for QS tracing + -: 239: + 28: 240: QF_CRIT_ENTRY(); + -: 241: // the tran. source state must not be nullptr + 28*: 242: Q_ASSERT_INCRIT(320, ts != nullptr); + 28: 243: QF_CRIT_EXIT(); + -: 244: #endif // Q_SPY + -: 245: + 28: 246: limit = MAX_NEST_DEPTH_; // loop hard limit + 50: 247: do { + -: 248: // save the tran-action table before it gets clobbered + 50: 249: QMTranActTable const * const tatbl = m_temp.tatbl; + 50: 250: QAsmAttr tmp; // temporary to save intermediate values + -: 251: + -: 252: // was TRAN, TRAN_INIT, or TRAN_EP taken? + 50: 253: if (r <= Q_RET_TRAN_EP) { + 38: 254: m_temp.obj = nullptr; // clear + 38: 255: exitToTranSource_(s, t, qsId); + 38: 256: r = execTatbl_(tatbl, qsId); + 38: 257: s = m_state.obj; + -: 258: } + -: 259: // was a tran. segment to history taken? + 12: 260: else if (r == Q_RET_TRAN_HIST) { + 6: 261: tmp.obj = m_state.obj; // save history + 6: 262: m_state.obj = s; // restore the original state + 6: 263: exitToTranSource_(s, t, qsId); + 6: 264: static_cast(execTatbl_(tatbl, qsId)); + 6: 265: r = enterHistory_(tmp.obj, qsId); + 6: 266: s = m_state.obj; + -: 267: } + -: 268: else { + 6: 269: QF_CRIT_ENTRY(); + -: 270: // must be tran. to exit point + 6*: 271: Q_ASSERT_INCRIT(340, r == Q_RET_TRAN_XP); + 6: 272: QF_CRIT_EXIT(); + -: 273: + 6: 274: tmp.act = m_state.act; // save XP action + 6: 275: m_state.obj = s; // restore the original state + 6: 276: r = (*tmp.act)(this); // execute the XP action + 6: 277: if (r == Q_RET_TRAN) { // XP -> TRAN ? + -: 278: #ifdef Q_SPY + 2: 279: tmp.tatbl = m_temp.tatbl; // save m_temp + -: 280: #endif // Q_SPY + 2: 281: exitToTranSource_(s, t, qsId); + -: 282: // take the tran-to-XP segment inside submachine + 2: 283: static_cast(execTatbl_(tatbl, qsId)); + 2: 284: s = m_state.obj; + -: 285: #ifdef Q_SPY + 2: 286: m_temp.tatbl = tmp.tatbl; // restore m_temp + -: 287: #endif // Q_SPY + -: 288: } + 4: 289: else if (r == Q_RET_TRAN_HIST) { // XP -> HIST ? + 4: 290: tmp.obj = m_state.obj; // save the history + 4: 291: m_state.obj = s; // restore the original state + -: 292: #ifdef Q_SPY + 4: 293: s = m_temp.obj; // save m_temp + -: 294: #endif // Q_SPY + 4: 295: exitToTranSource_(m_state.obj, t, qsId); + -: 296: // take the tran-to-XP segment inside submachine + 4: 297: static_cast(execTatbl_(tatbl, qsId)); + -: 298: #ifdef Q_SPY + 4: 299: m_temp.obj = s; // restore m_temp + -: 300: #endif // Q_SPY + 4: 301: s = m_state.obj; + 4: 302: m_state.obj = tmp.obj; // restore the history + -: 303: } + -: 304: else { + #####: 305: QF_CRIT_ENTRY(); + -: 306: // TRAN_XP must NOT be followed by any other tran type + #####: 307: Q_ASSERT_INCRIT(330, r < Q_RET_TRAN); + #####: 308: QF_CRIT_EXIT(); + -: 309: } + -: 310: } + -: 311: + 50: 312: t = s; // set target to the current state + 50: 313: --limit; + 50: 314: } while ((r >= Q_RET_TRAN) && (limit > 0)); + -: 315: + 28: 316: QF_CRIT_ENTRY(); + 28*: 317: Q_ASSERT_INCRIT(320, limit > 0); + -: 318: + 28: 319: QS_MEM_SYS(); + 28: 320: QS_BEGIN_PRE_(QS_QEP_TRAN, qsId) + 14: 321: QS_TIME_PRE_(); // time stamp + 14: 322: QS_SIG_PRE_(e->sig); // the signal of the event + 14: 323: QS_OBJ_PRE_(this); // this state machine object + 14: 324: QS_FUN_PRE_(ts->stateHandler); // the tran. source + 14: 325: QS_FUN_PRE_(s->stateHandler); // the new active state + 14: 326: QS_END_PRE_() + 28: 327: QS_MEM_APP(); + -: 328: + 28: 329: QF_CRIT_EXIT(); + -: 330: } + -: 331: + -: 332: #ifdef Q_SPY + -: 333: // was the event handled? + 7: 334: else if (r == Q_RET_HANDLED) { + 4: 335: QF_CRIT_ENTRY(); + -: 336: // internal tran. source can't be nullptr + 4*: 337: Q_ASSERT_INCRIT(340, t != nullptr); + -: 338: + 4: 339: QS_MEM_SYS(); + 4: 340: QS_BEGIN_PRE_(QS_QEP_INTERN_TRAN, qsId) + 2: 341: QS_TIME_PRE_(); // time stamp + 2: 342: QS_SIG_PRE_(e->sig); // the signal of the event + 2: 343: QS_OBJ_PRE_(this); // this state machine object + 2: 344: QS_FUN_PRE_(t->stateHandler); // the source state + 2: 345: QS_END_PRE_() + 4: 346: QS_MEM_APP(); + -: 347: + 4: 348: QF_CRIT_EXIT(); + -: 349: } + -: 350: // event bubbled to the 'top' state? + 3: 351: else if (t == nullptr) { + 3: 352: QS_CRIT_ENTRY(); + 3: 353: QS_MEM_SYS(); + 3: 354: QS_BEGIN_PRE_(QS_QEP_IGNORED, qsId) + 2: 355: QS_TIME_PRE_(); // time stamp + 2: 356: QS_SIG_PRE_(e->sig); // the signal of the event + 2: 357: QS_OBJ_PRE_(this); // this state machine object + 2: 358: QS_FUN_PRE_(s->stateHandler); // the current state + 2: 359: QS_END_PRE_() + 3: 360: QS_MEM_APP(); + 3: 361: QS_CRIT_EXIT(); + -: 362: } + -: 363: #endif // Q_SPY + -: 364: else { + -: 365: // empty + -: 366: } + -: 367: + -: 368: #ifndef Q_UNSAFE + 35: 369: m_temp.uint = ~m_state.uint; + -: 370: #endif + 35: 371:} + -: 372: + -: 373://${QEP::QMsm::isIn} ......................................................... + 8: 374:bool QMsm::isIn(QStateHandler const state) noexcept { + 8: 375: bool inState = false; // assume that this SM is not in 'state' + -: 376: + 8: 377: QMState const *s = m_state.obj; + 8: 378: std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit + 17: 379: for (; (s != nullptr) && (limit > 0); --limit) { + 14: 380: if (s->stateHandler == state) { // match found? + -: 381: inState = true; + -: 382: break; + -: 383: } + -: 384: else { + 9: 385: s = s->superstate; // advance to the superstate + -: 386: } + -: 387: } + -: 388: + -: 389: QF_CRIT_STAT + 8: 390: QF_CRIT_ENTRY(); + 8*: 391: Q_ENSURE_INCRIT(490, limit > 0); + 8: 392: QF_CRIT_EXIT(); + -: 393: + 8: 394: return inState; + -: 395:} + -: 396: + -: 397://${QEP::QMsm::isInState} .................................................... + #####: 398:bool QMsm::isInState(QMState const * const stateObj) const noexcept { + #####: 399: bool inState = false; // assume that this SM is not in 'state' + -: 400: + #####: 401: QMState const *s = m_state.obj; + #####: 402: std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit + #####: 403: for (; (s != nullptr) && (limit > 0); --limit) { + #####: 404: if (s == stateObj) { // match found? + -: 405: inState = true; + -: 406: break; + -: 407: } + -: 408: else { + #####: 409: s = s->superstate; // advance to the superstate + -: 410: } + -: 411: } + -: 412: + -: 413: QF_CRIT_STAT + #####: 414: QF_CRIT_ENTRY(); + #####: 415: Q_ENSURE_INCRIT(590, limit > 0); + #####: 416: QF_CRIT_EXIT(); + -: 417: + #####: 418: return inState; + -: 419:} + -: 420: + -: 421://${QEP::QMsm::childStateObj} ................................................ + 2: 422:QMState const * QMsm::childStateObj(QMState const * const parent) const noexcept { + 2: 423: QMState const *child = m_state.obj; + 2: 424: bool isFound = false; // start with the child not found + 2: 425: QMState const *s; + -: 426: + 2: 427: std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit + 2: 428: for (s = m_state.obj; + 8: 429: (s != nullptr) && (limit > 0); + 6: 430: s = s->superstate) + -: 431: { + 6: 432: if (s == parent) { + -: 433: isFound = true; // child is found + -: 434: break; + -: 435: } + -: 436: else { + 6: 437: child = s; + -: 438: } + 6: 439: --limit; + -: 440: } + -: 441: QF_CRIT_STAT + 2: 442: QF_CRIT_ENTRY(); + 2*: 443: Q_ASSERT_INCRIT(610, limit > 0); + 2: 444: QF_CRIT_EXIT(); + -: 445: + 2: 446: if (!isFound) { // still not found? + 2: 447: limit = MAX_NEST_DEPTH_; // loop hard limit + 2: 448: for (s = m_temp.obj; + 4: 449: (s != nullptr) && (limit > 0); + 2: 450: s = s->superstate) + -: 451: { + 4: 452: if (s == parent) { + -: 453: isFound = true; // child is found + -: 454: break; + -: 455: } + -: 456: else { + 2: 457: child = s; + -: 458: } + 2: 459: --limit; + -: 460: } + -: 461: } + -: 462: + 2: 463: QF_CRIT_ENTRY(); + 2*: 464: Q_ENSURE_INCRIT(690, isFound && (limit > 0)); + 2: 465: QF_CRIT_EXIT(); + -: 466: + 2: 467: return child; // return the child + -: 468:} + -: 469: + -: 470://${QEP::QMsm::execTatbl_} ................................................... + 62: 471:QState QMsm::execTatbl_( + -: 472: QMTranActTable const * const tatbl, + -: 473: std::uint_fast8_t const qsId) + -: 474:{ + -: 475: #ifndef Q_SPY + -: 476: Q_UNUSED_PAR(qsId); + -: 477: #endif + -: 478: + -: 479: QF_CRIT_STAT + 62: 480: QF_CRIT_ENTRY(); + -: 481: // precondition: + -: 482: // - the tran-action table pointer must not be NULL + 62*: 483: Q_REQUIRE_INCRIT(700, tatbl != nullptr); + 62: 484: QF_CRIT_EXIT(); + -: 485: + 62: 486: QState r = Q_RET_NULL; + 62: 487: std::int_fast8_t limit = MAX_TRAN_LENGTH_; // loop hard limit + 62: 488: QActionHandler const *a = &tatbl->act[0]; + 182: 489: for (; (*a != nullptr) && (limit > 0); ++a) { + 120: 490: r = (*(*a))(this); // call the action through the 'a' pointer + -: 491: #ifdef Q_SPY + 120: 492: QS_CRIT_ENTRY(); + 120: 493: QS_MEM_SYS(); + 120: 494: if (r == Q_RET_ENTRY) { + 70: 495: QS_BEGIN_PRE_(QS_QEP_STATE_ENTRY, qsId) + 35: 496: QS_OBJ_PRE_(this); // this state machine object + 35: 497: QS_FUN_PRE_(m_temp.obj->stateHandler); // entered state + 35: 498: QS_END_PRE_() + -: 499: } + 50: 500: else if (r == Q_RET_EXIT) { + 30: 501: QS_BEGIN_PRE_(QS_QEP_STATE_EXIT, qsId) + 15: 502: QS_OBJ_PRE_(this); // this state machine object + 15: 503: QS_FUN_PRE_(m_temp.obj->stateHandler); // exited state + 15: 504: QS_END_PRE_() + -: 505: } + 20: 506: else if (r == Q_RET_TRAN_INIT) { + 18: 507: QS_BEGIN_PRE_(QS_QEP_STATE_INIT, qsId) + 9: 508: QS_OBJ_PRE_(this); // this state machine object + 9: 509: QS_FUN_PRE_(tatbl->target->stateHandler); // source + 9: 510: QS_FUN_PRE_(m_temp.tatbl->target->stateHandler); // target + 9: 511: QS_END_PRE_() + -: 512: } + 2: 513: else if (r == Q_RET_TRAN_EP) { + 2: 514: QS_BEGIN_PRE_(QS_QEP_TRAN_EP, qsId) + 1: 515: QS_OBJ_PRE_(this); // this state machine object + 1: 516: QS_FUN_PRE_(tatbl->target->stateHandler); // source + 1: 517: QS_FUN_PRE_(m_temp.tatbl->target->stateHandler); // target + 1: 518: QS_END_PRE_() + -: 519: } + #####: 520: else if (r == Q_RET_TRAN_XP) { + #####: 521: QS_BEGIN_PRE_(QS_QEP_TRAN_XP, qsId) + #####: 522: QS_OBJ_PRE_(this); // this state machine object + #####: 523: QS_FUN_PRE_(tatbl->target->stateHandler); // source + #####: 524: QS_FUN_PRE_(m_temp.tatbl->target->stateHandler); // target + #####: 525: QS_END_PRE_() + -: 526: } + -: 527: else { + -: 528: // empty + -: 529: } + 120: 530: QS_MEM_APP(); + 120: 531: QS_CRIT_EXIT(); + -: 532: #endif // Q_SPY + 120: 533: --limit; + -: 534: } + 62: 535: QF_CRIT_ENTRY(); + 62*: 536: Q_ENSURE_INCRIT(790, *a == nullptr); + 62: 537: QF_CRIT_EXIT(); + -: 538: + 62: 539: m_state.obj = (r >= Q_RET_TRAN) + 20: 540: ? m_temp.tatbl->target + -: 541: : tatbl->target; + 62: 542: return r; + -: 543:} + -: 544: + -: 545://${QEP::QMsm::exitToTranSource_} ............................................ + 50: 546:void QMsm::exitToTranSource_( + -: 547: QMState const * const cs, + -: 548: QMState const * const ts, + -: 549: std::uint_fast8_t const qsId) + -: 550:{ + -: 551: #ifndef Q_SPY + -: 552: Q_UNUSED_PAR(qsId); + -: 553: #endif + -: 554: + -: 555: QF_CRIT_STAT + -: 556: + -: 557: // exit states from the current state to the tran. source state + 50: 558: QMState const *s = cs; + 50: 559: std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit + 78: 560: for (; (s != ts) && (limit > 0); --limit) { + -: 561: // exit action provided in state 's'? + 28: 562: if (s->exitAction != nullptr) { + -: 563: // execute the exit action + 26: 564: static_cast((*s->exitAction)(this)); + -: 565: + 26: 566: QS_CRIT_ENTRY(); + 26: 567: QS_MEM_SYS(); + 26: 568: QS_BEGIN_PRE_(QS_QEP_STATE_EXIT, qsId) + 13: 569: QS_OBJ_PRE_(this); // this state machine object + 13: 570: QS_FUN_PRE_(s->stateHandler); // the exited state handler + 13: 571: QS_END_PRE_() + 26: 572: QS_MEM_APP(); + 26: 573: QS_CRIT_EXIT(); + -: 574: } + -: 575: + 28: 576: s = s->superstate; // advance to the superstate + -: 577: + 28: 578: if (s == nullptr) { // reached the top of a submachine? + 4: 579: s = m_temp.obj; // the superstate from QM_SM_EXIT() + 4: 580: QF_CRIT_ENTRY(); + 4*: 581: Q_ASSERT_INCRIT(810, s != nullptr); // must be valid + 4: 582: QF_CRIT_EXIT(); + -: 583: } + -: 584: } + 50: 585: QF_CRIT_ENTRY(); + 50*: 586: Q_ENSURE_INCRIT(890, limit > 0); + 50: 587: QF_CRIT_EXIT(); + 50: 588:} + -: 589: + -: 590://${QEP::QMsm::enterHistory_} ................................................ + 6: 591:QState QMsm::enterHistory_( + -: 592: QMState const * const hist, + -: 593: std::uint_fast8_t const qsId) + -: 594:{ + -: 595: #ifndef Q_SPY + -: 596: Q_UNUSED_PAR(qsId); + -: 597: #endif + -: 598: + 6: 599: QMState const *s = hist; + 6: 600: QMState const *ts = m_state.obj; // tran. source + 6: 601: QMState const *epath[MAX_ENTRY_DEPTH_]; + -: 602: + -: 603: QF_CRIT_STAT + -: 604: + 6: 605: QS_CRIT_ENTRY(); + 6: 606: QS_MEM_SYS(); + 6: 607: QS_BEGIN_PRE_(QS_QEP_TRAN_HIST, qsId) + 3: 608: QS_OBJ_PRE_(this); // this state machine object + 3: 609: QS_FUN_PRE_(ts->stateHandler); // source state handler + 3: 610: QS_FUN_PRE_(hist->stateHandler); // target state handler + 3: 611: QS_END_PRE_() + 6: 612: QS_MEM_APP(); + 6: 613: QS_CRIT_EXIT(); + -: 614: + 6: 615: std::int_fast8_t i = 0; // tran. entry path index + 16: 616: while ((s != ts) && (i < MAX_ENTRY_DEPTH_)) { + 10: 617: if (s->entryAction != nullptr) { + 10: 618: epath[i] = s; + 10: 619: ++i; + -: 620: } + 10: 621: s = s->superstate; + 10: 622: if (s == nullptr) { + #####: 623: ts = s; // force exit from the for-loop + -: 624: } + -: 625: } + 6: 626: QF_CRIT_ENTRY(); + 6*: 627: Q_ASSERT_INCRIT(910, s == ts); + 6: 628: QF_CRIT_EXIT(); + -: 629: + -: 630: // retrace the entry path in reverse (desired) order... + 16: 631: while (i > 0) { + 10: 632: --i; + 10: 633: (*epath[i]->entryAction)(this); // run entry action in epath[i] + -: 634: + 10: 635: QS_CRIT_ENTRY(); + 10: 636: QS_MEM_SYS(); + 10: 637: QS_BEGIN_PRE_(QS_QEP_STATE_ENTRY, qsId) + 5: 638: QS_OBJ_PRE_(this); + 5: 639: QS_FUN_PRE_(epath[i]->stateHandler); // entered state handler + 5: 640: QS_END_PRE_() + 10: 641: QS_MEM_APP(); + 10: 642: QS_CRIT_EXIT(); + -: 643: } + -: 644: + 6: 645: m_state.obj = hist; // set current state to the tran. target + -: 646: + -: 647: // initial tran. present? + 6: 648: QState r; + 6: 649: if (hist->initAction != nullptr) { + 2: 650: r = (*hist->initAction)(this); // execute the tran. action + -: 651: } + -: 652: else { + -: 653: r = Q_RET_NULL; + -: 654: } + -: 655: + 6: 656: return r; + -: 657:} + -: 658: + -: 659://${QEP::QMsm::topQMState} ................................................... + #####: 660:QMState const * QMsm::topQMState() const noexcept { + #####: 661: return &l_msm_top_s; + -: 662:} + -: 663: + -: 664:} // namespace QP + -: 665://$enddef${QEP::QMsm} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/qutest/qmsm/test/qp.hpp.gcov b/qutest/qmsm/test/qp.hpp.gcov new file mode 100644 index 0000000..8924ce2 --- /dev/null +++ b/qutest/qmsm/test/qp.hpp.gcov @@ -0,0 +1,1284 @@ + -: 0:Source:../../../../include/qp.hpp + -: 0:Graph:build/qep_msm.gcno + -: 0:Data:build/qep_msm.gcda + -: 0:Runs:6 + -: 1://$file${include::qp.hpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 2:// + -: 3:// Model: qpcpp.qm + -: 4:// File: ${include::qp.hpp} + -: 5:// + -: 6:// This code has been generated by QM 6.1.1 . + -: 7:// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. + -: 8:// + -: 9:// This code is covered by the following QP license: + -: 10:// License # : LicenseRef-QL-dual + -: 11:// Issued to : Any user of the QP/C++ real-time embedded framework + -: 12:// Framework(s) : qpcpp + -: 13:// Support ends : 2024-12-31 + -: 14:// License scope: + -: 15:// + -: 16:// Copyright (C) 2005 Quantum Leaps, LLC . + -: 17:// + -: 18:// Q u a n t u m L e a P s + -: 19:// ------------------------ + -: 20:// Modern Embedded Software + -: 21:// + -: 22:// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial + -: 23:// + -: 24:// This software is dual-licensed under the terms of the open source GNU + -: 25:// General Public License version 3 (or any later version), or alternatively, + -: 26:// under the terms of one of the closed source Quantum Leaps commercial + -: 27:// licenses. + -: 28:// + -: 29:// The terms of the open source GNU General Public License version 3 + -: 30:// can be found at: + -: 31:// + -: 32:// The terms of the closed source Quantum Leaps commercial licenses + -: 33:// can be found at: + -: 34:// + -: 35:// Redistributions in source code must retain this top-level comment block. + -: 36:// Plagiarizing this software to sidestep the license obligations is illegal. + -: 37:// + -: 38:// Contact information: + -: 39:// + -: 40:// + -: 41:// + -: 42://$endhead${include::qp.hpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 43:#ifndef QP_HPP_ + -: 44:#define QP_HPP_ + -: 45: + -: 46://============================================================================ + -: 47:#define QP_VERSION 734U + -: 48:#define QP_VERSION_STR "7.3.4" + -: 49: + -: 50://! Encrypted current QP release (7.3.4) and date (2024-03-21) + -: 51:#define QP_RELEASE 0x70C1EA11U + -: 52: + -: 53://============================================================================ + -: 54://! @cond INTERNAL + -: 55: + -: 56:#ifndef Q_SIGNAL_SIZE + -: 57:#define Q_SIGNAL_SIZE 2U + -: 58:#endif // ndef Q_SIGNAL_SIZE + -: 59: + -: 60:#ifndef QF_MAX_ACTIVE + -: 61:#define QF_MAX_ACTIVE 32U + -: 62:#endif + -: 63: + -: 64:#if (QF_MAX_ACTIVE > 64U) + -: 65:#error QF_MAX_ACTIVE exceeds the maximum of 64U; + -: 66:#endif + -: 67: + -: 68:#ifndef QF_MAX_TICK_RATE + -: 69:#define QF_MAX_TICK_RATE 1U + -: 70:#endif + -: 71: + -: 72:#if (QF_MAX_TICK_RATE > 15U) + -: 73:#error QF_MAX_TICK_RATE exceeds the maximum of 15U; + -: 74:#endif + -: 75: + -: 76:#ifndef QF_MAX_EPOOL + -: 77:#define QF_MAX_EPOOL 3U + -: 78:#endif + -: 79: + -: 80:#if (QF_MAX_EPOOL > 15U) + -: 81:#error QF_MAX_EPOOL exceeds the maximum of 15U; + -: 82:#endif + -: 83: + -: 84:#ifndef QF_TIMEEVT_CTR_SIZE + -: 85:#define QF_TIMEEVT_CTR_SIZE 4U + -: 86:#endif + -: 87: + -: 88:#if (QF_TIMEEVT_CTR_SIZE > 4U) + -: 89:#error QF_TIMEEVT_CTR_SIZE defined incorrectly, expected 1U, 2U, or 4U; + -: 90:#endif + -: 91: + -: 92:#ifndef QF_EVENT_SIZ_SIZE + -: 93:#define QF_EVENT_SIZ_SIZE 2U + -: 94:#endif + -: 95: + -: 96:#if (QF_EVENT_SIZ_SIZE > 4U) + -: 97:#error QF_EVENT_SIZ_SIZE defined incorrectly, expected 1U, 2U, or 4U; + -: 98:#endif + -: 99: + -: 100://! @endcond + -: 101://============================================================================ + -: 102://$declare${glob-types} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 103: + -: 104://${glob-types::int_t} ....................................................... + -: 105:using int_t = int; + -: 106: + -: 107://${glob-types::enum_t} ...................................................... + -: 108:using enum_t = int; + -: 109: + -: 110://${glob-types::float32_t} ................................................... + -: 111:using float32_t = float; + -: 112: + -: 113://${glob-types::float64_t} ................................................... + -: 114:using float64_t = double; + -: 115://$enddecl${glob-types} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 116: + -: 117://$declare${QEP} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 118:namespace QP { + -: 119: + -: 120://${QEP::versionStr[]} ....................................................... + -: 121:constexpr char const versionStr[] {QP_VERSION_STR}; + -: 122: + -: 123://${QEP::QSignal} ............................................................ + -: 124:#if (Q_SIGNAL_SIZE == 1U) + -: 125:using QSignal = std::uint8_t; + -: 126:#endif // (Q_SIGNAL_SIZE == 1U) + -: 127: + -: 128://${QEP::QSignal} ............................................................ + -: 129:#if (Q_SIGNAL_SIZE == 2U) + -: 130:using QSignal = std::uint16_t; + -: 131:#endif // (Q_SIGNAL_SIZE == 2U) + -: 132: + -: 133://${QEP::QSignal} ............................................................ + -: 134:#if (Q_SIGNAL_SIZE == 4U) + -: 135:using QSignal = std::uint32_t; + -: 136:#endif // (Q_SIGNAL_SIZE == 4U) + -: 137: + -: 138://${QEP::QEvt} ............................................................... + -: 139:class QEvt { + -: 140:public: + -: 141: QSignal sig; + -: 142: std::uint8_t volatile refCtr_; + -: 143: std::uint8_t evtTag_; + -: 144: + -: 145:public: + -: 146: static constexpr std::uint8_t MARKER {0xE0U}; + -: 147: + -: 148:#ifdef QEVT_DYN_CTOR + -: 149: enum DynEvt: std::uint8_t { DYNAMIC }; + -: 150:#endif // def QEVT_DYN_CTOR + -: 151: + -: 152:public: + -: 153: + -: 154:#ifdef QEVT_DYN_CTOR + -: 155: QEvt * ctor(DynEvt const dummy) noexcept; + -: 156:#endif // def QEVT_DYN_CTOR + -: 157: explicit constexpr QEvt(QSignal const s) noexcept + -: 158: : sig(s), + -: 159: refCtr_(0U), + -: 160: evtTag_(MARKER) + -: 161: {} + -: 162: QEvt() = delete; + 35: 163: static bool verify_(QEvt const * const e) noexcept { + 35: 164: return (e != nullptr) + 35: 165: && ((e->evtTag_ & 0xF0U) == MARKER); + -: 166: } + -: 167: std::uint_fast8_t getPoolNum_() const noexcept { + -: 168: return static_cast(evtTag_) & 0x0FU; + -: 169: } + -: 170:}; // class QEvt + -: 171: + -: 172://${QEP::QState} ............................................................. + -: 173:using QState = std::uint_fast8_t; + -: 174: + -: 175://${QEP::QStateHandler} ...................................................... + -: 176:using QStateHandler = QState (*)(void * const me, QEvt const * const e); + -: 177: + -: 178://${QEP::QActionHandler} ..................................................... + -: 179:using QActionHandler = QState (*)(void * const me); + -: 180: + -: 181://${QEP::QXThread} ........................................................... + -: 182:// forward declaration + -: 183:class QXThread; + -: 184: + -: 185://${QEP::QXThreadHandler} .................................................... + -: 186:using QXThreadHandler = void (*)(QXThread * const me); + -: 187: + -: 188://${QEP::QMState} ............................................................ + -: 189:struct QMState { + -: 190: QMState const * superstate; + -: 191: QStateHandler const stateHandler; + -: 192: QActionHandler const entryAction; + -: 193: QActionHandler const exitAction; + -: 194: QActionHandler const initAction; + -: 195:}; + -: 196: + -: 197://${QEP::QMTranActTable} ..................................................... + -: 198:struct QMTranActTable { + -: 199: QMState const * target; + -: 200: QActionHandler const act[1]; + -: 201:}; + -: 202: + -: 203://${QEP::QAsmAttr} ........................................................... + -: 204:union QAsmAttr { + -: 205: QStateHandler fun; + -: 206: QActionHandler act; + -: 207: QXThreadHandler thr; + -: 208: QMState const *obj; + -: 209: QMTranActTable const *tatbl; + -: 210:#ifndef Q_UNSAFE + -: 211: std::uintptr_t uint; + -: 212:#endif + 6: 213: constexpr QAsmAttr() : fun(nullptr) {} + -: 214:}; + -: 215: + -: 216://${QEP::Q_USER_SIG} ......................................................... + -: 217:constexpr enum_t Q_USER_SIG {4}; + -: 218: + -: 219://${QEP::QAsm} ............................................................... + -: 220:class QAsm { + -: 221:protected: + -: 222: QAsmAttr m_state; + -: 223: QAsmAttr m_temp; + -: 224: + -: 225:public: + -: 226: + -: 227: //! All possible return values from state-handlers + -: 228: //! @note + -: 229: //! The order is important for algorithmic correctness. + -: 230: enum QStateRet : QState { + -: 231: // unhandled and need to "bubble up" + -: 232: Q_RET_SUPER, //!< event passed to superstate to handle + -: 233: Q_RET_SUPER_SUB, //!< event passed to submachine superstate + -: 234: Q_RET_UNHANDLED, //!< event unhandled due to a guard + -: 235: + -: 236: // handled and do not need to "bubble up" + -: 237: Q_RET_HANDLED, //!< event handled (internal transition) + -: 238: Q_RET_IGNORED, //!< event silently ignored (bubbled up to top) + -: 239: + -: 240: // entry/exit + -: 241: Q_RET_ENTRY, //!< state entry action executed + -: 242: Q_RET_EXIT, //!< state exit action executed + -: 243: + -: 244: // no side effects + -: 245: Q_RET_NULL, //!< return value without any effect + -: 246: + -: 247: // transitions need to execute transition-action table in QP::QMsm + -: 248: Q_RET_TRAN, //!< regular transition + -: 249: Q_RET_TRAN_INIT, //!< initial transition in a state or submachine + -: 250: Q_RET_TRAN_EP, //!< entry-point transition into a submachine + -: 251: + -: 252: // transitions that additionally clobber QHsm.m_state + -: 253: Q_RET_TRAN_HIST, //!< transition to history of a given state + -: 254: Q_RET_TRAN_XP //!< exit-point transition out of a submachine + -: 255: }; + -: 256: + -: 257: //! Reserved signals by the QP-framework. + -: 258: enum ReservedSig : QSignal { + -: 259: Q_EMPTY_SIG, //!< signal to execute the default case + -: 260: Q_ENTRY_SIG, //!< signal for entry actions + -: 261: Q_EXIT_SIG, //!< signal for exit actions + -: 262: Q_INIT_SIG //!< signal for nested initial transitions + -: 263: }; + -: 264: + -: 265:protected: + 6: 266: explicit QAsm() noexcept + 6: 267: : m_state(), + 6: 268: m_temp () + -: 269: {} + -: 270: + -: 271:public: + -: 272: + -: 273:#ifdef Q_XTOR + -: 274: virtual ~QAsm() noexcept { + -: 275: // empty + -: 276: } + -: 277:#endif // def Q_XTOR + -: 278: virtual void init( + -: 279: void const * const e, + -: 280: std::uint_fast8_t const qsId) = 0; + -: 281: virtual void init(std::uint_fast8_t const qsId) { + -: 282: this->init(nullptr, qsId); + -: 283: } + -: 284: virtual void dispatch( + -: 285: QEvt const * const e, + -: 286: std::uint_fast8_t const qsId) = 0; + -: 287: virtual bool isIn(QStateHandler const state) noexcept { + -: 288: static_cast(state); + -: 289: return false; + -: 290: } + -: 291: QStateHandler state() const noexcept { + -: 292: return m_state.fun; + -: 293: } + -: 294: QMState const * stateObj() const noexcept { + -: 295: return m_state.obj; + -: 296: } + -: 297: + -: 298:#ifdef Q_SPY + -: 299: virtual QStateHandler getStateHandler() noexcept { + -: 300: return m_state.fun; + -: 301: } + -: 302:#endif // def Q_SPY + -: 303: static QState top( + -: 304: void * const me, + -: 305: QEvt const * const e) noexcept + -: 306: { + -: 307: static_cast(me); + -: 308: static_cast(e); + -: 309: return Q_RET_IGNORED; // the top state ignores all events + -: 310: } + -: 311: + -: 312:protected: + -: 313: QState tran(QStateHandler const target) noexcept { + -: 314: m_temp.fun = target; + -: 315: return Q_RET_TRAN; + -: 316: } + -: 317: QState tran_hist(QStateHandler const hist) noexcept { + -: 318: m_temp.fun = hist; + -: 319: return Q_RET_TRAN_HIST; + -: 320: } + -: 321: QState super(QStateHandler const superstate) noexcept { + -: 322: m_temp.fun = superstate; + -: 323: return Q_RET_SUPER; + -: 324: } + -: 325: QState qm_tran(void const * const tatbl) noexcept { + -: 326: m_temp.tatbl = static_cast(tatbl); + -: 327: return Q_RET_TRAN; + -: 328: } + -: 329: QState qm_tran_init(void const * const tatbl) noexcept { + -: 330: m_temp.tatbl = static_cast(tatbl); + -: 331: return Q_RET_TRAN_INIT; + -: 332: } + -: 333: QState qm_tran_hist( + -: 334: QMState const * const hist, + -: 335: void const * const tatbl) noexcept + -: 336: { + -: 337: m_state.obj = hist; + -: 338: m_temp.tatbl = static_cast(tatbl); + -: 339: return Q_RET_TRAN_HIST; + -: 340: } + -: 341: QState qm_tran_ep(void const * const tatbl) noexcept { + -: 342: m_temp.tatbl = static_cast(tatbl); + -: 343: return Q_RET_TRAN_EP; + -: 344: } + -: 345: QState qm_tran_xp( + -: 346: QActionHandler const xp, + -: 347: void const * const tatbl) noexcept + -: 348: { + -: 349: m_state.act = xp; + -: 350: m_temp.tatbl = static_cast(tatbl); + -: 351: return Q_RET_TRAN_XP; + -: 352: } + -: 353: + -: 354:#ifdef Q_SPY + -: 355: QState qm_entry(QMState const * const s) noexcept { + -: 356: m_temp.obj = s; + -: 357: return Q_RET_ENTRY; + -: 358: } + -: 359:#endif // def Q_SPY + -: 360: + -: 361:#ifndef Q_SPY + -: 362: QState qm_entry(QMState const * const s) noexcept { + -: 363: static_cast(s); // unused parameter + -: 364: return Q_RET_ENTRY; + -: 365: } + -: 366:#endif // ndef Q_SPY + -: 367: + -: 368:#ifdef Q_SPY + -: 369: QState qm_exit(QMState const * const s) noexcept { + -: 370: m_temp.obj = s; + -: 371: return Q_RET_EXIT; + -: 372: } + -: 373:#endif // def Q_SPY + -: 374: + -: 375:#ifndef Q_SPY + -: 376: QState qm_exit(QMState const * const s) noexcept { + -: 377: static_cast(s); // unused parameter + -: 378: return Q_RET_EXIT; + -: 379: } + -: 380:#endif // ndef Q_SPY + -: 381: QState qm_sm_exit(QMState const * const s) noexcept { + -: 382: m_temp.obj = s; + -: 383: return Q_RET_EXIT; + -: 384: } + -: 385: QState qm_super_sub(QMState const * const s) noexcept { + -: 386: m_temp.obj = s; + -: 387: return Q_RET_SUPER_SUB; + -: 388: } + -: 389:}; // class QAsm + -: 390: + -: 391://${QEP::QHsm} ............................................................... + -: 392:class QHsm : public QP::QAsm { + -: 393:public: + -: 394: static constexpr std::int_fast8_t MAX_NEST_DEPTH_{6}; + -: 395: + -: 396:protected: + -: 397: explicit QHsm(QStateHandler const initial) noexcept; + -: 398: + -: 399:public: + -: 400: void init( + -: 401: void const * const e, + -: 402: std::uint_fast8_t const qsId) override; + -: 403: void init(std::uint_fast8_t const qsId) override { + -: 404: this->init(nullptr, qsId); + -: 405: } + -: 406: void dispatch( + -: 407: QEvt const * const e, + -: 408: std::uint_fast8_t const qsId) override; + -: 409: bool isIn(QStateHandler const state) noexcept override; + -: 410: QStateHandler childState(QStateHandler const parent) noexcept; + -: 411: + -: 412:#ifdef Q_SPY + -: 413: QStateHandler getStateHandler() noexcept override { + -: 414: return m_state.fun; + -: 415: } + -: 416:#endif // def Q_SPY + -: 417: + -: 418:private: + -: 419: std::int_fast8_t hsm_tran( + -: 420: QStateHandler (&path)[MAX_NEST_DEPTH_], + -: 421: std::uint_fast8_t const qsId); + -: 422:}; // class QHsm + -: 423: + -: 424://${QEP::QMsm} ............................................................... + -: 425:class QMsm : public QP::QAsm { + -: 426:protected: + -: 427: explicit QMsm(QStateHandler const initial) noexcept; + -: 428: + -: 429:public: + -: 430: void init( + -: 431: void const * const e, + -: 432: std::uint_fast8_t const qsId) override; + #####: 433: void init(std::uint_fast8_t const qsId) override { + #####: 434: this->init(nullptr, qsId); + #####: 435: } + -: 436: void dispatch( + -: 437: QEvt const * const e, + -: 438: std::uint_fast8_t const qsId) override; + -: 439: + -: 440:#ifdef Q_SPY + #####: 441: QStateHandler getStateHandler() noexcept override { + #####: 442: return m_state.obj->stateHandler; + -: 443: } + -: 444:#endif // def Q_SPY + -: 445: bool isIn(QStateHandler const state) noexcept override; + -: 446: + -: 447: //! @deprecated instead use: QMsm::isIn() + -: 448: bool isInState(QMState const * const stateObj) const noexcept; + -: 449: QMState const * childStateObj(QMState const * const parent) const noexcept; + -: 450: + -: 451:private: + -: 452: QState execTatbl_( + -: 453: QMTranActTable const * const tatbl, + -: 454: std::uint_fast8_t const qsId); + -: 455: void exitToTranSource_( + -: 456: QMState const * const cs, + -: 457: QMState const * const ts, + -: 458: std::uint_fast8_t const qsId); + -: 459: QState enterHistory_( + -: 460: QMState const * const hist, + -: 461: std::uint_fast8_t const qsId); + -: 462: + -: 463:public: + -: 464: QMState const * topQMState() const noexcept; + -: 465:}; // class QMsm + -: 466: + -: 467:} // namespace QP + -: 468://$enddecl${QEP} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 469: + -: 470://$declare${QEP-macros} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 471: + -: 472://${QEP-macros::Q_STATE_DECL} ................................................ + -: 473:#define Q_STATE_DECL(state_) \ + -: 474: QP::QState state_ ## _h(QP::QEvt const * const e); \ + -: 475: static QP::QState state_(void * const me, QP::QEvt const * const e) + -: 476: + -: 477://${QEP-macros::Q_STATE_DEF} ................................................. + -: 478:#define Q_STATE_DEF(subclass_, state_) \ + -: 479: QP::QState subclass_::state_(void * const me, QP::QEvt const * const e) { \ + -: 480: return static_cast(me)->state_ ## _h(e); } \ + -: 481: QP::QState subclass_::state_ ## _h(QP::QEvt const * const e) + -: 482: + -: 483://${QEP-macros::Q_HANDLED} ................................................... + -: 484:#define Q_HANDLED() (Q_RET_HANDLED) + -: 485: + -: 486://${QEP-macros::Q_UNHANDLED} ................................................. + -: 487:#define Q_UNHANDLED() (Q_RET_UNHANDLED) + -: 488: + -: 489://${QEP-macros::Q_EVT_CAST} .................................................. + -: 490:#define Q_EVT_CAST(subclass_) (static_cast(e)) + -: 491: + -: 492://${QEP-macros::Q_STATE_CAST} ................................................ + -: 493:#define Q_STATE_CAST(handler_) \ + -: 494: (reinterpret_cast(handler_)) + -: 495: + -: 496://${QEP-macros::QM_STATE_DECL} ............................................... + -: 497:#define QM_STATE_DECL(state_) \ + -: 498: QP::QState state_ ## _h(QP::QEvt const * const e); \ + -: 499: static QP::QState state_(void * const me, QP::QEvt const * const e); \ + -: 500: static QP::QMState const state_ ## _s + -: 501: + -: 502://${QEP-macros::QM_SM_STATE_DECL} ............................................ + -: 503:#define QM_SM_STATE_DECL(subm_, state_) \ + -: 504: QP::QState state_ ## _h(QP::QEvt const * const e);\ + -: 505: static QP::QState state_(void * const me, QP::QEvt const * const e); \ + -: 506: static SM_ ## subm_ const state_ ## _s + -: 507: + -: 508://${QEP-macros::QM_ACTION_DECL} .............................................. + -: 509:#define QM_ACTION_DECL(action_) \ + -: 510: QP::QState action_ ## _h(); \ + -: 511: static QP::QState action_(void * const me) + -: 512: + -: 513://${QEP-macros::QM_STATE_DEF} ................................................ + -: 514:#define QM_STATE_DEF(subclass_, state_) \ + -: 515: QP::QState subclass_::state_(void * const me, QP::QEvt const * const e) {\ + -: 516: return static_cast(me)->state_ ## _h(e); } \ + -: 517: QP::QState subclass_::state_ ## _h(QP::QEvt const * const e) + -: 518: + -: 519://${QEP-macros::QM_ACTION_DEF} ............................................... + -: 520:#define QM_ACTION_DEF(subclass_, action_) \ + -: 521: QP::QState subclass_::action_(void * const me) { \ + -: 522: return static_cast(me)->action_ ## _h(); } \ + -: 523: QP::QState subclass_::action_ ## _h() + -: 524: + -: 525://${QEP-macros::QM_HANDLED} .................................................. + -: 526:#define QM_HANDLED() (Q_RET_HANDLED) + -: 527: + -: 528://${QEP-macros::QM_UNHANDLED} ................................................ + -: 529:#define QM_UNHANDLED() (Q_RET_HANDLED) + -: 530: + -: 531://${QEP-macros::QM_SUPER} .................................................... + -: 532:#define QM_SUPER() (Q_RET_SUPER) + -: 533: + -: 534://${QEP-macros::QM_STATE_NULL} ............................................... + -: 535:#define QM_STATE_NULL (nullptr) + -: 536: + -: 537://${QEP-macros::Q_ACTION_NULL} ............................................... + -: 538:#define Q_ACTION_NULL (nullptr) + -: 539: + -: 540://${QEP-macros::Q_UNUSED_PAR} ................................................ + -: 541:#define Q_UNUSED_PAR(par_) (static_cast(par_)) + -: 542: + -: 543://${QEP-macros::Q_DIM} ....................................................... + -: 544:#define Q_DIM(array_) (sizeof(array_) / sizeof((array_)[0U])) + -: 545: + -: 546://${QEP-macros::Q_UINT2PTR_CAST} ............................................. + -: 547:#define Q_UINT2PTR_CAST(type_, uint_) (reinterpret_cast(uint_)) + -: 548: + -: 549://${QEP-macros::INIT} ........................................................ + -: 550:#ifdef Q_SPY + -: 551:#define INIT(qsId_) init((qsId_)) + -: 552:#endif // def Q_SPY + -: 553: + -: 554://${QEP-macros::INIT} ........................................................ + -: 555:#ifndef Q_SPY + -: 556:#define INIT(dummy) init(0U) + -: 557:#endif // ndef Q_SPY + -: 558: + -: 559://${QEP-macros::DISPATCH} .................................................... + -: 560:#ifdef Q_SPY + -: 561:#define DISPATCH(e_, qsId_) dispatch((e_), (qsId_)) + -: 562:#endif // def Q_SPY + -: 563: + -: 564://${QEP-macros::DISPATCH} .................................................... + -: 565:#ifndef Q_SPY + -: 566:#define DISPATCH(e_, dummy) dispatch((e_), 0U) + -: 567:#endif // ndef Q_SPY + -: 568://$enddecl${QEP-macros} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 569: + -: 570://$declare${QF::types} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 571:namespace QP { + -: 572: + -: 573://${QF::types::QPrioSpec} .................................................... + -: 574:using QPrioSpec = std::uint16_t; + -: 575: + -: 576://${QF::types::QTimeEvtCtr} .................................................. + -: 577:#if (QF_TIMEEVT_CTR_SIZE == 1U) + -: 578:using QTimeEvtCtr = std::uint8_t; + -: 579:#endif // (QF_TIMEEVT_CTR_SIZE == 1U) + -: 580: + -: 581://${QF::types::QTimeEvtCtr} .................................................. + -: 582:#if (QF_TIMEEVT_CTR_SIZE == 2U) + -: 583:using QTimeEvtCtr = std::uint16_t; + -: 584:#endif // (QF_TIMEEVT_CTR_SIZE == 2U) + -: 585: + -: 586://${QF::types::QTimeEvtCtr} .................................................. + -: 587:#if (QF_TIMEEVT_CTR_SIZE == 4U) + -: 588:using QTimeEvtCtr = std::uint32_t; + -: 589:#endif // (QF_TIMEEVT_CTR_SIZE == 4U) + -: 590: + -: 591://${QF::types::QPSetBits} .................................................... + -: 592:#if (QF_MAX_ACTIVE <= 8U) + -: 593:using QPSetBits = std::uint8_t; + -: 594:#endif // (QF_MAX_ACTIVE <= 8U) + -: 595: + -: 596://${QF::types::QPSetBits} .................................................... + -: 597:#if (8U < QF_MAX_ACTIVE) && (QF_MAX_ACTIVE <= 16U) + -: 598:using QPSetBits = std::uint16_t; + -: 599:#endif // (8U < QF_MAX_ACTIVE) && (QF_MAX_ACTIVE <= 16U) + -: 600: + -: 601://${QF::types::QPSetBits} .................................................... + -: 602:#if (16 < QF_MAX_ACTIVE) + -: 603:using QPSetBits = std::uint32_t; + -: 604:#endif // (16 < QF_MAX_ACTIVE) + -: 605: + -: 606://${QF::types::QF_LOG2} ...................................................... + -: 607:#ifndef QF_LOG2 + -: 608:std::uint_fast8_t QF_LOG2(QP::QPSetBits x) noexcept; + -: 609:#endif // ndef QF_LOG2 + -: 610: + -: 611://${QF::types::QPSet} ........................................................ + -: 612:class QPSet { + -: 613:private: + -: 614: QPSetBits m_bits[((QF_MAX_ACTIVE + (8U*sizeof(QPSetBits))) - 1U)/(8U*sizeof(QPSetBits))]; + -: 615: + -: 616:public: + -: 617: void setEmpty() noexcept { + -: 618: m_bits[0] = 0U; + -: 619: #if (QF_MAX_ACTIVE > 32) + -: 620: m_bits[1] = 0U; + -: 621: #endif + -: 622: } + -: 623: bool isEmpty() const noexcept { + -: 624: #if (QF_MAX_ACTIVE <= 32U) + -: 625: return (m_bits[0] == 0U); + -: 626: #else + -: 627: return (m_bits[0] == 0U) ? (m_bits[1] == 0U) : false; + -: 628: #endif + -: 629: } + -: 630: bool notEmpty() const noexcept { + -: 631: #if (QF_MAX_ACTIVE <= 32U) + -: 632: return (m_bits[0] != 0U); + -: 633: #else + -: 634: return (m_bits[0] != 0U) ? true : (m_bits[1] != 0U); + -: 635: #endif + -: 636: } + -: 637: bool hasElement(std::uint_fast8_t const n) const noexcept { + -: 638: #if (QF_MAX_ACTIVE <= 32U) + -: 639: return (m_bits[0] & (static_cast(1U) << (n - 1U))) != 0U; + -: 640: #else + -: 641: return (n <= 32U) + -: 642: ? ((m_bits[0] & (static_cast(1U) << (n - 1U))) != 0U) + -: 643: : ((m_bits[1] & (static_cast(1U) << (n - 33U))) != 0U); + -: 644: #endif + -: 645: } + -: 646: void insert(std::uint_fast8_t const n) noexcept { + -: 647: #if (QF_MAX_ACTIVE <= 32U) + -: 648: m_bits[0] = (m_bits[0] | (static_cast(1U) << (n - 1U))); + -: 649: #else + -: 650: if (n <= 32U) { + -: 651: m_bits[0] = (m_bits[0] | (static_cast(1U) << (n - 1U))); + -: 652: } + -: 653: else { + -: 654: m_bits[1] = (m_bits[1] | (static_cast(1U) << (n - 33U))); + -: 655: } + -: 656: #endif + -: 657: } + -: 658: void remove(std::uint_fast8_t const n) noexcept { + -: 659: #if (QF_MAX_ACTIVE <= 32U) + -: 660: m_bits[0] = (m_bits[0] & static_cast(~(1U << (n - 1U)))); + -: 661: #else + -: 662: if (n <= 32U) { + -: 663: (m_bits[0] = (m_bits[0] & ~(static_cast(1U) << (n - 1U)))); + -: 664: } + -: 665: else { + -: 666: (m_bits[1] = (m_bits[1] & ~(static_cast(1U) << (n - 33U)))); + -: 667: } + -: 668: #endif + -: 669: } + -: 670: std::uint_fast8_t findMax() const noexcept { + -: 671: #if (QF_MAX_ACTIVE <= 32U) + -: 672: return QF_LOG2(m_bits[0]); + -: 673: #else + -: 674: return (m_bits[1] != 0U) + -: 675: ? (QF_LOG2(m_bits[1]) + 32U) + -: 676: : (QF_LOG2(m_bits[0])); + -: 677: #endif + -: 678: } + -: 679: + -: 680:#ifndef Q_UNSAFE + -: 681: void update_(QPSet * const dis) const noexcept { + -: 682: dis->m_bits[0] = ~m_bits[0]; + -: 683: #if (QF_MAX_ACTIVE > 32U) + -: 684: dis->m_bits[1] = ~m_bits[1]; + -: 685: #endif + -: 686: } + -: 687:#endif // ndef Q_UNSAFE + -: 688: + -: 689:#ifndef Q_UNSAFE + -: 690: bool verify_(QPSet const * const dis) const noexcept { + -: 691: #if (QF_MAX_ACTIVE <= 32U) + -: 692: return m_bits[0] == static_cast(~dis->m_bits[0]); + -: 693: #else + -: 694: return (m_bits[0] == static_cast(~dis->m_bits[0])) + -: 695: && (m_bits[1] == static_cast(~dis->m_bits[1])); + -: 696: #endif + -: 697: } + -: 698:#endif // ndef Q_UNSAFE + -: 699:}; // class QPSet + -: 700: + -: 701://${QF::types::QSubscrList} .................................................. + -: 702:class QSubscrList { + -: 703:private: + -: 704: QPSet m_set; + -: 705: + -: 706:#ifndef Q_UNSAFE + -: 707: QPSet m_set_dis; + -: 708:#endif // ndef Q_UNSAFE + -: 709: + -: 710: // friends... + -: 711: friend class QActive; + -: 712:}; // class QSubscrList + -: 713: + -: 714://${QF::types::QEQueue} ...................................................... + -: 715:class QEQueue; + -: 716: + -: 717:} // namespace QP + -: 718://$enddecl${QF::types} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 719: + -: 720://$declare${QF::QActive} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 721:namespace QP { + -: 722: + -: 723://${QF::QActive} ............................................................. + -: 724:class QActive : public QP::QAsm { + -: 725:protected: + -: 726: std::uint8_t m_prio; + -: 727: std::uint8_t m_pthre; + -: 728: + -: 729:#ifdef QACTIVE_THREAD_TYPE + -: 730: QACTIVE_THREAD_TYPE m_thread; + -: 731:#endif // def QACTIVE_THREAD_TYPE + -: 732: + -: 733:#ifdef QACTIVE_OS_OBJ_TYPE + -: 734: QACTIVE_OS_OBJ_TYPE m_osObject; + -: 735:#endif // def QACTIVE_OS_OBJ_TYPE + -: 736: + -: 737:#ifdef QACTIVE_EQUEUE_TYPE + -: 738: QACTIVE_EQUEUE_TYPE m_eQueue; + -: 739:#endif // def QACTIVE_EQUEUE_TYPE + -: 740: + -: 741:public: + -: 742: + -: 743:#ifndef Q_UNSAFE + -: 744: std::uint8_t m_prio_dis; + -: 745:#endif // ndef Q_UNSAFE + -: 746: + -: 747:#ifndef Q_UNSAFE + -: 748: std::uint8_t m_pthre_dis; + -: 749:#endif // ndef Q_UNSAFE + -: 750: static QActive * registry_[QF_MAX_ACTIVE + 1U]; + -: 751: static QSubscrList * subscrList_; + -: 752: static enum_t maxPubSignal_; + -: 753: + -: 754: // friends... + -: 755: friend class QTimeEvt; + -: 756: friend class QTicker; + -: 757: friend class QXThread; + -: 758: friend class QXMutex; + -: 759: friend class QXSemaphore; + -: 760: friend class QActiveDummy; + -: 761: friend class GuiQActive; + -: 762: friend class GuiQMActive; + -: 763: friend void schedLock(); + -: 764: + -: 765:protected: + -: 766: explicit QActive(QStateHandler const initial) noexcept + -: 767: : QAsm(), + -: 768: m_prio(0U), + -: 769: m_pthre(0U) + -: 770: { + -: 771: m_state.fun = Q_STATE_CAST(&top); + -: 772: m_temp.fun = initial; + -: 773: + -: 774: #ifndef Q_UNSAFE + -: 775: m_prio_dis = static_cast(~m_prio); + -: 776: m_pthre_dis = static_cast(~m_pthre); + -: 777: #endif + -: 778: } + -: 779: + -: 780:public: + -: 781: void init( + -: 782: void const * const e, + -: 783: std::uint_fast8_t const qsId) override + -: 784: { + -: 785: reinterpret_cast(this)->QHsm::init(e, qsId); + -: 786: } + -: 787: void init(std::uint_fast8_t const qsId) override { + -: 788: this->init(nullptr, qsId); + -: 789: } + -: 790: void dispatch( + -: 791: QEvt const * const e, + -: 792: std::uint_fast8_t const qsId) override + -: 793: { + -: 794: reinterpret_cast(this)->QHsm::dispatch(e, qsId); + -: 795: } + -: 796: bool isIn(QStateHandler const state) noexcept override { + -: 797: return reinterpret_cast(this)->QHsm::isIn(state); + -: 798: } + -: 799: QStateHandler childState(QStateHandler const parent) noexcept { + -: 800: return reinterpret_cast(this)->QHsm::childState(parent); + -: 801: } + -: 802: void setAttr( + -: 803: std::uint32_t attr1, + -: 804: void const * attr2 = nullptr); + -: 805: void start( + -: 806: QPrioSpec const prioSpec, + -: 807: QEvt const * * const qSto, + -: 808: std::uint_fast16_t const qLen, + -: 809: void * const stkSto, + -: 810: std::uint_fast16_t const stkSize, + -: 811: void const * const par); + -: 812: void start( + -: 813: QPrioSpec const prioSpec, + -: 814: QEvt const * * const qSto, + -: 815: std::uint_fast16_t const qLen, + -: 816: void * const stkSto, + -: 817: std::uint_fast16_t const stkSize) + -: 818: { + -: 819: this->start(prioSpec, qSto, qLen, stkSto, stkSize, nullptr); + -: 820: } + -: 821: + -: 822:#ifdef QACTIVE_CAN_STOP + -: 823: void stop(); + -: 824:#endif // def QACTIVE_CAN_STOP + -: 825: void register_() noexcept; + -: 826: void unregister_() noexcept; + -: 827: bool post_( + -: 828: QEvt const * const e, + -: 829: std::uint_fast16_t const margin, + -: 830: void const * const sender) noexcept; + -: 831: void postLIFO(QEvt const * const e) noexcept; + -: 832: QEvt const * get_() noexcept; + -: 833: static std::uint_fast16_t getQueueMin(std::uint_fast8_t const prio) noexcept; + -: 834: static void psInit( + -: 835: QSubscrList * const subscrSto, + -: 836: enum_t const maxSignal) noexcept; + -: 837: static void publish_( + -: 838: QEvt const * const e, + -: 839: void const * const sender, + -: 840: std::uint_fast8_t const qsId) noexcept; + -: 841: void subscribe(enum_t const sig) const noexcept; + -: 842: void unsubscribe(enum_t const sig) const noexcept; + -: 843: void unsubscribeAll() const noexcept; + -: 844: bool defer( + -: 845: QEQueue * const eq, + -: 846: QEvt const * const e) const noexcept; + -: 847: bool recall(QEQueue * const eq) noexcept; + -: 848: std::uint_fast16_t flushDeferred( + -: 849: QEQueue * const eq, + -: 850: std::uint_fast16_t const num = 0xFFFFU) const noexcept; + -: 851: std::uint_fast8_t getPrio() const noexcept { + -: 852: return static_cast(m_prio); + -: 853: } + -: 854: void setPrio(QPrioSpec const prio) noexcept { + -: 855: m_prio = static_cast(prio & 0xFFU); + -: 856: m_pthre = static_cast(prio >> 8U); + -: 857: } + -: 858: std::uint_fast8_t getPThre() const noexcept { + -: 859: return static_cast(m_pthre); + -: 860: } + -: 861: + -: 862:#ifdef QACTIVE_EQUEUE_TYPE + -: 863: QACTIVE_EQUEUE_TYPE const & getEQueue() const noexcept { + -: 864: return m_eQueue; + -: 865: } + -: 866:#endif // def QACTIVE_EQUEUE_TYPE + -: 867: + -: 868:#ifdef QACTIVE_OS_OBJ_TYPE + -: 869: QACTIVE_OS_OBJ_TYPE const & getOsObject() const noexcept { + -: 870: return m_osObject; + -: 871: } + -: 872:#endif // def QACTIVE_OS_OBJ_TYPE + -: 873: + -: 874:#ifdef QACTIVE_THREAD_TYPE + -: 875: QACTIVE_THREAD_TYPE const & getThread() const noexcept { + -: 876: return m_thread; + -: 877: } + -: 878:#endif // def QACTIVE_THREAD_TYPE + -: 879: + -: 880:#ifdef QACTIVE_THREAD_TYPE + -: 881: void setThread(QACTIVE_THREAD_TYPE const & thr) { + -: 882: m_thread = thr; + -: 883: } + -: 884:#endif // def QACTIVE_THREAD_TYPE + -: 885: static void evtLoop_(QActive * act); + -: 886: + -: 887:#ifdef QF_ISR_API + -: 888: virtual bool postFromISR( + -: 889: QEvt const * const e, + -: 890: std::uint_fast16_t const margin, + -: 891: void * par, + -: 892: void const * const sender) noexcept; + -: 893:#endif // def QF_ISR_API + -: 894: + -: 895:#ifdef QF_ISR_API + -: 896: static void publishFromISR( + -: 897: QEvt const * e, + -: 898: void * par, + -: 899: void const * sender) noexcept; + -: 900:#endif // def QF_ISR_API + -: 901:}; // class QActive + -: 902: + -: 903:} // namespace QP + -: 904://$enddecl${QF::QActive} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 905: + -: 906://$declare${QF::QMActive} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 907:namespace QP { + -: 908: + -: 909://${QF::QMActive} ............................................................ + -: 910:class QMActive : public QP::QActive { + -: 911:protected: + -: 912: QMActive(QStateHandler const initial) noexcept; + -: 913: + -: 914:public: + -: 915: void init( + -: 916: void const * const e, + -: 917: std::uint_fast8_t const qsId) override + -: 918: { + -: 919: reinterpret_cast(this)->QMsm::init(e, qsId); + -: 920: } + -: 921: void init(std::uint_fast8_t const qsId) override { + -: 922: this->init(nullptr, qsId); + -: 923: } + -: 924: void dispatch( + -: 925: QEvt const * const e, + -: 926: std::uint_fast8_t const qsId) override + -: 927: { + -: 928: reinterpret_cast(this)->QMsm::dispatch(e, qsId); + -: 929: } + -: 930: bool isIn(QStateHandler const state) noexcept override { + -: 931: return reinterpret_cast(this)->QMsm::isIn(state); + -: 932: } + -: 933: + -: 934:#ifdef Q_SPY + -: 935: QStateHandler getStateHandler() noexcept override { + -: 936: return reinterpret_cast(this)->QMsm::getStateHandler(); + -: 937: } + -: 938:#endif // def Q_SPY + -: 939: bool isInState(QMState const * const st) const noexcept { + -: 940: return reinterpret_cast(this)->QMsm::isInState(st); + -: 941: } + -: 942: QMState const * childStateObj(QMState const * const parent) const noexcept { + -: 943: return reinterpret_cast(this) + -: 944: ->QMsm::childStateObj(parent); + -: 945: } + -: 946:}; // class QMActive + -: 947: + -: 948:} // namespace QP + -: 949://$enddecl${QF::QMActive} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 950: + -: 951://$declare${QF::QTimeEvt} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 952:namespace QP { + -: 953: + -: 954://${QF::QTimeEvt} ............................................................ + -: 955:class QTimeEvt : public QP::QEvt { + -: 956:private: + -: 957: QTimeEvt * volatile m_next; + -: 958: void * m_act; + -: 959: QTimeEvtCtr volatile m_ctr; + -: 960: QTimeEvtCtr m_interval; + -: 961: + -: 962:public: + -: 963: static QTimeEvt timeEvtHead_[QF_MAX_TICK_RATE]; + -: 964: + -: 965:private: + -: 966: friend class QXThread; + -: 967: + -: 968:public: + -: 969: QTimeEvt( + -: 970: QActive * const act, + -: 971: QSignal const sig, + -: 972: std::uint_fast8_t const tickRate = 0U) noexcept; + -: 973: + -: 974:#ifdef Q_XTOR + -: 975: ~QTimeEvt(); + -: 976:#endif // def Q_XTOR + -: 977: void armX( + -: 978: QTimeEvtCtr const nTicks, + -: 979: QTimeEvtCtr const interval = 0U) noexcept; + -: 980: bool disarm() noexcept; + -: 981: bool rearm(QTimeEvtCtr const nTicks) noexcept; + -: 982: bool wasDisarmed() noexcept; + -: 983: void const * getAct() const noexcept { + -: 984: return m_act; + -: 985: } + -: 986: QTimeEvtCtr getCtr() const noexcept { + -: 987: return m_ctr; + -: 988: } + -: 989: QTimeEvtCtr getInterval() const noexcept { + -: 990: return m_interval; + -: 991: } + -: 992: static void tick( + -: 993: std::uint_fast8_t const tickRate, + -: 994: void const * const sender) noexcept; + -: 995: + -: 996:#ifdef Q_UTEST + -: 997: static void tick1_( + -: 998: std::uint_fast8_t const tickRate, + -: 999: void const * const sender); + -: 1000:#endif // def Q_UTEST + -: 1001: + -: 1002:#ifdef QF_ISR_API + -: 1003: static void tickFromISR( + -: 1004: std::uint_fast8_t const tickRate, + -: 1005: void * par, + -: 1006: void const * sender) noexcept; + -: 1007:#endif // def QF_ISR_API + -: 1008: static bool noActive(std::uint_fast8_t const tickRate) noexcept; + -: 1009: QActive * toActive() noexcept { + -: 1010: return static_cast(m_act); + -: 1011: } + -: 1012: QTimeEvt * toTimeEvt() noexcept { + -: 1013: return static_cast(m_act); + -: 1014: } + -: 1015: + -: 1016:private: + -: 1017: QTimeEvt() noexcept; + -: 1018: QTimeEvt(QTimeEvt const & other) = delete; + -: 1019: QTimeEvt & operator=(QTimeEvt const & other) = delete; + -: 1020:}; // class QTimeEvt + -: 1021: + -: 1022:} // namespace QP + -: 1023://$enddecl${QF::QTimeEvt} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 1024: + -: 1025://$declare${QF::QTicker} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 1026:namespace QP { + -: 1027: + -: 1028://${QF::QTicker} ............................................................. + -: 1029:class QTicker : public QP::QActive { + -: 1030:public: + -: 1031: explicit QTicker(std::uint_fast8_t const tickRate) noexcept; + -: 1032: void init( + -: 1033: void const * const e, + -: 1034: std::uint_fast8_t const qsId) override; + -: 1035: void init(std::uint_fast8_t const qsId) override { + -: 1036: this->init(nullptr, qsId); + -: 1037: } + -: 1038: void dispatch( + -: 1039: QEvt const * const e, + -: 1040: std::uint_fast8_t const qsId) override; + -: 1041: void trig_(void const * const sender) noexcept; + -: 1042:}; // class QTicker + -: 1043: + -: 1044:} // namespace QP + -: 1045://$enddecl${QF::QTicker} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 1046: + -: 1047://$declare${QF::QF-base} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 1048:namespace QP { + -: 1049:namespace QF { + -: 1050: + -: 1051://${QF::QF-base::init} ....................................................... + -: 1052:void init(); + -: 1053: + -: 1054://${QF::QF-base::stop} ....................................................... + -: 1055:void stop(); + -: 1056: + -: 1057://${QF::QF-base::run} ........................................................ + -: 1058:int_t run(); + -: 1059: + -: 1060://${QF::QF-base::onStartup} .................................................. + -: 1061:void onStartup(); + -: 1062: + -: 1063://${QF::QF-base::onCleanup} .................................................. + -: 1064:void onCleanup(); + -: 1065: + -: 1066://${QF::QF-base::psInit} ..................................................... + -: 1067://! @deprecated + -: 1068:inline void psInit( + -: 1069: QSubscrList * const subscrSto, + -: 1070: enum_t const maxSignal) noexcept + -: 1071:{ + -: 1072: QActive::psInit(subscrSto, maxSignal); + -: 1073:} + -: 1074: + -: 1075://${QF::QF-base::publish_} ................................................... + -: 1076://! @deprecated + -: 1077:inline void publish_( + -: 1078: QEvt const * const e, + -: 1079: void const * const sender, + -: 1080: std::uint_fast8_t const qsId) noexcept + -: 1081:{ + -: 1082: QActive::publish_(e, sender, qsId); + -: 1083:} + -: 1084: + -: 1085://${QF::QF-base::tick} ....................................................... + -: 1086://! @deprecated + -: 1087:inline void tick( + -: 1088: std::uint_fast8_t const tickRate, + -: 1089: void const * const sender) noexcept + -: 1090:{ + -: 1091: QTimeEvt::tick(tickRate, sender); + -: 1092:} + -: 1093: + -: 1094://${QF::QF-base::getQueueMin} ................................................ + -: 1095://! @deprecated + -: 1096:inline std::uint_fast16_t getQueueMin(std::uint_fast8_t const prio) noexcept { + -: 1097: return QActive::getQueueMin(prio); + -: 1098:} + -: 1099: + -: 1100://${QF::QF-base::NO_MARGIN} .................................................. + -: 1101:constexpr std::uint_fast16_t NO_MARGIN {0xFFFFU}; + -: 1102: + -: 1103:} // namespace QF + -: 1104:} // namespace QP + -: 1105://$enddecl${QF::QF-base} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 1106: + -: 1107://$declare${QF::QF-dyn} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 1108:namespace QP { + -: 1109:namespace QF { + -: 1110: + -: 1111://${QF::QF-dyn::poolInit} .................................................... + -: 1112:void poolInit( + -: 1113: void * const poolSto, + -: 1114: std::uint_fast32_t const poolSize, + -: 1115: std::uint_fast16_t const evtSize) noexcept; + -: 1116: + -: 1117://${QF::QF-dyn::poolGetMaxBlockSize} ......................................... + -: 1118:std::uint_fast16_t poolGetMaxBlockSize() noexcept; + -: 1119: + -: 1120://${QF::QF-dyn::getPoolMin} .................................................. + -: 1121:std::uint_fast16_t getPoolMin(std::uint_fast8_t const poolNum) noexcept; + -: 1122: + -: 1123://${QF::QF-dyn::newX_} ....................................................... + -: 1124:QEvt * newX_( + -: 1125: std::uint_fast16_t const evtSize, + -: 1126: std::uint_fast16_t const margin, + -: 1127: enum_t const sig) noexcept; + -: 1128: + -: 1129://${QF::QF-dyn::gc} .......................................................... + -: 1130:void gc(QEvt const * const e) noexcept; + -: 1131: + -: 1132://${QF::QF-dyn::newRef_} ..................................................... + -: 1133:QEvt const * newRef_( + -: 1134: QEvt const * const e, + -: 1135: QEvt const * const evtRef) noexcept; + -: 1136: + -: 1137://${QF::QF-dyn::deleteRef_} .................................................. + -: 1138:void deleteRef_(QEvt const * const evtRef) noexcept; + -: 1139: + -: 1140://${QF::QF-dyn::newXfromISR_} ................................................ + -: 1141:#ifdef QF_ISR_API + -: 1142:QEvt * newXfromISR_( + -: 1143: std::uint_fast16_t const evtSize, + -: 1144: std::uint_fast16_t const margin, + -: 1145: enum_t const sig) noexcept; + -: 1146:#endif // def QF_ISR_API + -: 1147: + -: 1148://${QF::QF-dyn::gcFromISR} ................................................... + -: 1149:#ifdef QF_ISR_API + -: 1150:void gcFromISR(QEvt const * e) noexcept; + -: 1151:#endif // def QF_ISR_API + -: 1152: + -: 1153:} // namespace QF + -: 1154:} // namespace QP + -: 1155://$enddecl${QF::QF-dyn} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 1156: + -: 1157:extern "C" { + -: 1158://$declare${QF-extern-C} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 1159: + -: 1160://${QF-extern-C::QF_onContextSw} ............................................. + -: 1161:#ifdef QF_ON_CONTEXT_SW + -: 1162:void QF_onContextSw( + -: 1163: QP::QActive * prev, + -: 1164: QP::QActive * next); + -: 1165:#endif // def QF_ON_CONTEXT_SW + -: 1166://$enddecl${QF-extern-C} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 1167:} // extern "C" + -: 1168: + -: 1169://$declare${QF-macros} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + -: 1170: + -: 1171://${QF-macros::Q_PRIO} ....................................................... + -: 1172:#define Q_PRIO(prio_, pthre_) \ + -: 1173: (static_cast((prio_) | (pthre_) << 8U)) + -: 1174: + -: 1175://${QF-macros::Q_NEW} ........................................................ + -: 1176:#ifndef QEVT_DYN_CTOR + -: 1177:#define Q_NEW(evtT_, sig_) (static_cast( \ + -: 1178: QP::QF::newX_(sizeof(evtT_), QP::QF::NO_MARGIN, (sig_)))) + -: 1179:#endif // ndef QEVT_DYN_CTOR + -: 1180: + -: 1181://${QF-macros::Q_NEW} ........................................................ + -: 1182:#ifdef QEVT_DYN_CTOR + -: 1183:#define Q_NEW(evtT_, sig_, ...) ( static_cast( \ + -: 1184: QP::QF::newX_(sizeof(evtT_), QP::QF::NO_MARGIN, (sig_)))->ctor(__VA_ARGS__)) + -: 1185:#endif // def QEVT_DYN_CTOR + -: 1186: + -: 1187://${QF-macros::Q_NEW_X} ...................................................... + -: 1188:#ifndef QEVT_DYN_CTOR + -: 1189:#define Q_NEW_X(evtT_, margin_, sig_) (static_cast( \ + -: 1190: QP::QF::newX_(sizeof(evtT_), (margin_), (sig_)))) + -: 1191:#endif // ndef QEVT_DYN_CTOR + -: 1192: + -: 1193://${QF-macros::Q_NEW_X} ...................................................... + -: 1194:#ifdef QEVT_DYN_CTOR + -: 1195:#define Q_NEW_X(evtT_, margin_, sig_, ...) ( static_cast( \ + -: 1196: QP::QF::newX_(sizeof(evtT_), (margin_), (sig_)))->ctor(__VA_ARGS__)) + -: 1197:#endif // def QEVT_DYN_CTOR + -: 1198: + -: 1199://${QF-macros::Q_NEW_REF} .................................................... + -: 1200:#define Q_NEW_REF(evtRef_, evtT_) \ + -: 1201: ((evtRef_) = static_cast(QP::QF::newRef_(e, (evtRef_)))) + -: 1202: + -: 1203://${QF-macros::Q_DELETE_REF} ................................................. + -: 1204:#define Q_DELETE_REF(evtRef_) do { \ + -: 1205: QP::QF::deleteRef_((evtRef_)); \ + -: 1206: (evtRef_) = 0U; \ + -: 1207:} while (false) + -: 1208: + -: 1209://${QF-macros::PUBLISH} ...................................................... + -: 1210:#ifdef Q_SPY + -: 1211:#define PUBLISH(e_, sender_) \ + -: 1212: publish_((e_), (sender_), (sender_)->getPrio()) + -: 1213:#endif // def Q_SPY + -: 1214: + -: 1215://${QF-macros::PUBLISH} ...................................................... + -: 1216:#ifndef Q_SPY + -: 1217:#define PUBLISH(e_, dummy) publish_((e_), nullptr, 0U) + -: 1218:#endif // ndef Q_SPY + -: 1219: + -: 1220://${QF-macros::POST} ......................................................... + -: 1221:#ifdef Q_SPY + -: 1222:#define POST(e_, sender_) post_((e_), QP::QF::NO_MARGIN, (sender_)) + -: 1223:#endif // def Q_SPY + -: 1224: + -: 1225://${QF-macros::POST} ......................................................... + -: 1226:#ifndef Q_SPY + -: 1227:#define POST(e_, dummy) post_((e_), QP::QF::NO_MARGIN, nullptr) + -: 1228:#endif // ndef Q_SPY + -: 1229: + -: 1230://${QF-macros::POST_X} ....................................................... + -: 1231:#ifdef Q_SPY + -: 1232:#define POST_X(e_, margin_, sender_) \ + -: 1233: post_((e_), (margin_), (sender_)) + -: 1234:#endif // def Q_SPY + -: 1235: + -: 1236://${QF-macros::POST_X} ....................................................... + -: 1237:#ifndef Q_SPY + -: 1238:#define POST_X(e_, margin_, dummy) post_((e_), (margin_), nullptr) + -: 1239:#endif // ndef Q_SPY + -: 1240: + -: 1241://${QF-macros::TICK_X} ....................................................... + -: 1242:#ifdef Q_SPY + -: 1243:#define TICK_X(tickRate_, sender_) tick((tickRate_), (sender_)) + -: 1244:#endif // def Q_SPY + -: 1245: + -: 1246://${QF-macros::TICK_X} ....................................................... + -: 1247:#ifndef Q_SPY + -: 1248:#define TICK_X(tickRate_, dummy) tick((tickRate_), nullptr) + -: 1249:#endif // ndef Q_SPY + -: 1250: + -: 1251://${QF-macros::TICK} ......................................................... + -: 1252:#define TICK(sender_) TICK_X(0U, (sender_)) + -: 1253: + -: 1254://${QF-macros::TRIG} ......................................................... + -: 1255:#ifdef Q_SPY + -: 1256:#define TRIG(sender_) trig_((sender_)) + -: 1257:#endif // def Q_SPY + -: 1258: + -: 1259://${QF-macros::TRIG} ......................................................... + -: 1260:#ifndef Q_SPY + -: 1261:#define TRIG(sender_) trig_(nullptr) + -: 1262:#endif // ndef Q_SPY + -: 1263: + -: 1264://${QF-macros::QF_CRIT_EXIT_NOP} ............................................. + -: 1265:#ifndef QF_CRIT_EXIT_NOP + -: 1266:#define QF_CRIT_EXIT_NOP() (static_cast(0)) + -: 1267:#endif // ndef QF_CRIT_EXIT_NOP + -: 1268: + -: 1269://${QF-macros::QF_MEM_SYS} ................................................... + -: 1270:#ifndef QF_MEM_SYS + -: 1271:#define QF_MEM_SYS() (static_cast(0)) + -: 1272:#endif // ndef QF_MEM_SYS + -: 1273: + -: 1274://${QF-macros::QF_MEM_APP} ................................................... + -: 1275:#ifndef QF_MEM_APP + -: 1276:#define QF_MEM_APP() (static_cast(0)) + -: 1277:#endif // ndef QF_MEM_APP + -: 1278://$enddecl${QF-macros} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -: 1279: + -: 1280:#endif // QP_HPP_ diff --git a/qutest/qmsm/test/test_qmsm-funct.py b/qutest/qmsm/test/test_qmsm-funct.py new file mode 100644 index 0000000..c22417d --- /dev/null +++ b/qutest/qmsm/test/test_qmsm-funct.py @@ -0,0 +1,204 @@ +# test-script for QUTest unit testing harness +# see https://www.state-machine.com/qtools/qutest.html + +# preamble... +def on_reset(): + expect_run() + glb_filter(GRP_UA) + current_obj(OBJ_SM, "the_sm") + +# tests... +#========================================================== +test("QMsmTst::init") +init() +expect("@timestamp BSP_DISPLAY top-INIT;") +expect("@timestamp BSP_DISPLAY s-ENTRY;") +expect("@timestamp BSP_DISPLAY sub-ENTRY;") +expect("@timestamp BSP_DISPLAY sub-INIT;") +expect("@timestamp BSP_DISPLAY sub1-ENTRY;") +expect("@timestamp BSP_DISPLAY sub11-ENTRY;") +expect("@timestamp Trg-Done QS_RX_EVENT") + +#---------------------------------------------------------- +test("QMsmTst isIn", NORESET) +command(0) # get state handler +expect("@timestamp CMD QMsmTst::sub_sub11") +expect("@timestamp Trg-Done QS_RX_COMMAND") + +command(1, 1) # is in state s1 +expect("@timestamp CMD 0 1") # NO +expect("@timestamp Trg-Done QS_RX_COMMAND") + +#command(1, 2) # is in state sub +#expect("@timestamp CMD 1 2") # YES +#expect("@timestamp Trg-Done QS_RX_COMMAND") + +command(1, 11) # is in state sub1 +expect("@timestamp CMD 1 11") # YES +expect("@timestamp Trg-Done QS_RX_COMMAND") + +command(1, 111) # is in state sub11 +expect("@timestamp CMD 1 111") # YES +expect("@timestamp Trg-Done QS_RX_COMMAND") + +#---------------------------------------------------------- +test("QMsmTst dispatch", NORESET) +dispatch("A_SIG") +expect("@timestamp BSP_DISPLAY sub1-A;") +expect("@timestamp BSP_DISPLAY sub11-EXIT;") +expect("@timestamp BSP_DISPLAY sub1-EXIT;") +expect("@timestamp BSP_DISPLAY sub1-ENTRY;") +expect("@timestamp BSP_DISPLAY sub1-INIT;") +expect("@timestamp BSP_DISPLAY sub11-ENTRY;") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("B_SIG") +expect("@timestamp BSP_DISPLAY sub1-B;") +expect("@timestamp BSP_DISPLAY sub11-EXIT;") +expect("@timestamp BSP_DISPLAY sub11-ENTRY;") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("C_SIG") +expect("@timestamp BSP_DISPLAY sub11-C;") +expect("@timestamp BSP_DISPLAY sub11-EXIT;") +expect("@timestamp BSP_DISPLAY sub12-ENTRY;") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("D_SIG") +expect("@timestamp BSP_DISPLAY sub1-D;") +expect("@timestamp BSP_DISPLAY sub12-EXIT;") +expect("@timestamp BSP_DISPLAY sub1-EXIT;") +expect("@timestamp BSP_DISPLAY sub-INIT;") +expect("@timestamp BSP_DISPLAY sub1-ENTRY;") +expect("@timestamp BSP_DISPLAY sub11-ENTRY;") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("E_SIG") +expect("@timestamp BSP_DISPLAY sub-E;") +expect("@timestamp BSP_DISPLAY sub11-EXIT;") +expect("@timestamp BSP_DISPLAY sub1-EXIT;") +expect("@timestamp BSP_DISPLAY sub2-ENTRY;") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("F_SIG") +expect("@timestamp BSP_DISPLAY s2-F;") +expect("@timestamp BSP_DISPLAY sub2-EXIT;") +expect("@timestamp BSP_DISPLAY sub-EXIT;") +expect("@timestamp BSP_DISPLAY sub-ENTRY;") +expect("@timestamp BSP_DISPLAY sub-ep1;") +expect("@timestamp BSP_DISPLAY sub1-ENTRY;") +expect("@timestamp BSP_DISPLAY sub1-INIT;") +expect("@timestamp BSP_DISPLAY sub11-ENTRY;") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("C_SIG") +expect("@timestamp BSP_DISPLAY sub11-C;") +expect("@timestamp BSP_DISPLAY sub11-EXIT;") +expect("@timestamp BSP_DISPLAY sub12-ENTRY;") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("H_SIG") +expect("@timestamp BSP_DISPLAY sub12-H->xpH;") +expect("@timestamp BSP_DISPLAY sub12-EXIT;") +expect("@timestamp BSP_DISPLAY sub1-EXIT;") +expect("@timestamp BSP_DISPLAY sub-EXIT;") +expect("@timestamp BSP_DISPLAY s-INIT;") +expect("@timestamp BSP_DISPLAY sub-ENTRY;") +expect("@timestamp BSP_DISPLAY sub-INIT;") +expect("@timestamp BSP_DISPLAY sub1-ENTRY;") +expect("@timestamp BSP_DISPLAY sub11-ENTRY;") +expect("@timestamp Trg-Done QS_RX_EVENT") + +#========================================================== +test("QMsmTst guards") +init() +expect("@timestamp BSP_DISPLAY top-INIT;") +expect("@timestamp BSP_DISPLAY s-ENTRY;") +expect("@timestamp BSP_DISPLAY sub-ENTRY;") +expect("@timestamp BSP_DISPLAY sub-INIT;") +expect("@timestamp BSP_DISPLAY sub1-ENTRY;") +expect("@timestamp BSP_DISPLAY sub11-ENTRY;") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("D_SIG") +expect("@timestamp BSP_DISPLAY sub1-D;") +expect("@timestamp BSP_DISPLAY sub11-EXIT;") +expect("@timestamp BSP_DISPLAY sub1-EXIT;") +expect("@timestamp BSP_DISPLAY sub-INIT;") +expect("@timestamp BSP_DISPLAY sub1-ENTRY;") +expect("@timestamp BSP_DISPLAY sub11-ENTRY;") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("D_SIG") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("I_SIG") +expect("@timestamp BSP_DISPLAY sub-I;") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("I_SIG") +expect("@timestamp BSP_DISPLAY s-I;") +expect("@timestamp Trg-Done QS_RX_EVENT") + +#========================================================== +test("QMsmTst history") +init() +expect("@timestamp BSP_DISPLAY top-INIT;") +expect("@timestamp BSP_DISPLAY s-ENTRY;") +expect("@timestamp BSP_DISPLAY sub-ENTRY;") +expect("@timestamp BSP_DISPLAY sub-INIT;") +expect("@timestamp BSP_DISPLAY sub1-ENTRY;") +expect("@timestamp BSP_DISPLAY sub11-ENTRY;") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("G_SIG") +expect("@timestamp BSP_DISPLAY sub1-G->xpG;") +expect("@timestamp BSP_DISPLAY sub11-EXIT;") +expect("@timestamp BSP_DISPLAY sub1-EXIT;") +expect("@timestamp BSP_DISPLAY sub-EXIT;") +expect("@timestamp BSP_DISPLAY sub-ENTRY;") +expect("@timestamp BSP_DISPLAY sub1-ENTRY;") +expect("@timestamp BSP_DISPLAY sub11-ENTRY;") +expect("@timestamp Trg-Done QS_RX_EVENT") +command(1, 111) # is in state s111 +expect("@timestamp CMD 1 111") +expect("@timestamp Trg-Done QS_RX_COMMAND") + +dispatch("C_SIG") +expect("@timestamp BSP_DISPLAY sub11-C;") +expect("@timestamp BSP_DISPLAY sub11-EXIT;") +expect("@timestamp BSP_DISPLAY sub12-ENTRY;") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("C_SIG") +expect("@timestamp BSP_DISPLAY s-C;") +expect("@timestamp BSP_DISPLAY sub12-EXIT;") +expect("@timestamp BSP_DISPLAY sub1-EXIT;") +expect("@timestamp BSP_DISPLAY sub-EXIT;") +expect("@timestamp BSP_DISPLAY s-EXIT;") +expect("@timestamp BSP_DISPLAY t-ENTRY;") +expect("@timestamp Trg-Done QS_RX_EVENT") +command(1, 0) # is in state s +expect("@timestamp CMD 0 0") # NO +expect("@timestamp Trg-Done QS_RX_COMMAND") + +dispatch("C_SIG") +expect("@timestamp BSP_DISPLAY t-C->H-s;") +expect("@timestamp BSP_DISPLAY t-EXIT;") +expect("@timestamp BSP_DISPLAY s-ENTRY;") +expect("@timestamp BSP_DISPLAY sub-ENTRY;") +expect("@timestamp BSP_DISPLAY sub-INIT;") +expect("@timestamp BSP_DISPLAY sub1-ENTRY;") +expect("@timestamp BSP_DISPLAY sub11-ENTRY;") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("G_SIG") +expect("@timestamp BSP_DISPLAY sub1-G->xpG;") +expect("@timestamp BSP_DISPLAY sub11-EXIT;") +expect("@timestamp BSP_DISPLAY sub1-EXIT;") +expect("@timestamp BSP_DISPLAY sub-EXIT;") +expect("@timestamp BSP_DISPLAY sub-ENTRY;") +expect("@timestamp BSP_DISPLAY sub1-ENTRY;") +expect("@timestamp BSP_DISPLAY sub11-ENTRY;") +expect("@timestamp Trg-Done QS_RX_EVENT") + diff --git a/qutest/qmsm/test/test_qmsm-struct.py b/qutest/qmsm/test/test_qmsm-struct.py new file mode 100644 index 0000000..e8e08d1 --- /dev/null +++ b/qutest/qmsm/test/test_qmsm-struct.py @@ -0,0 +1,227 @@ +# test-script for QUTest unit testing harness +# see https://www.state-machine.com/qtools/qutest.html + +# preamble... +def on_reset(): + expect_run() + glb_filter(GRP_SM, GRP_U1) + current_obj(OBJ_SM, "the_sm") + +# tests... +#========================================================== +test("QMsmTst init") +init() +expect("===RTC===> St-Init Obj=the_sm,State=NULL->QMsmTst::sub") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub") +expect("===RTC===> St-Init Obj=the_sm,State=QMsmTst::sub->QMsmTst::sub_sub11") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub_sub1") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub_sub11") +expect("@timestamp Init===> Obj=the_sm,State=QMsmTst::sub_sub11") +expect("@timestamp Trg-Done QS_RX_EVENT") + +#---------------------------------------------------------- +test("QMsmTst isIn", NORESET) +command(0) # get state handler +expect("@timestamp CMD QMsmTst::sub_sub11") +expect("@timestamp Trg-Done QS_RX_COMMAND") + +command(1, 1) # is in state s1 +expect("@timestamp CMD 0 1") # NO +expect("@timestamp Trg-Done QS_RX_COMMAND") + +#command(1, 2) # is in state sub +#expect("@timestamp CMD 1 2") # YES +#expect("@timestamp Trg-Done QS_RX_COMMAND") + +command(1, 11) # is in state sub1 +expect("@timestamp CMD 1 11") # YES +expect("@timestamp Trg-Done QS_RX_COMMAND") + +command(1, 111) # is in state sub11 +expect("@timestamp CMD 1 111") # YES +expect("@timestamp Trg-Done QS_RX_COMMAND") + +#---------------------------------------------------------- +test("QMsmTst dispatch", NORESET) +dispatch("A_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=A_SIG,State=QMsmTst::sub_sub11") +expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::sub_sub11") +expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::sub_sub1") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub_sub1") +expect("===RTC===> St-Init Obj=the_sm,State=QMsmTst::sub_sub1->QMsmTst::sub_sub11") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub_sub11") +expect("@timestamp ===>Tran Obj=the_sm,Sig=A_SIG,State=QMsmTst::sub_sub1->QMsmTst::sub_sub11") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("B_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=B_SIG,State=QMsmTst::sub_sub11") +expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::sub_sub11") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub_sub11") +expect("@timestamp ===>Tran Obj=the_sm,Sig=B_SIG,State=QMsmTst::sub_sub1->QMsmTst::sub_sub11") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("C_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=C_SIG,State=QMsmTst::sub_sub11") +expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::sub_sub11") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub_sub12") +expect("@timestamp ===>Tran Obj=the_sm,Sig=C_SIG,State=QMsmTst::sub_sub11->QMsmTst::sub_sub12") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("D_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=D_SIG,State=QMsmTst::sub_sub12") +expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::sub_sub12") +expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::sub_sub1") +expect("===RTC===> St-Init Obj=the_sm,State=QMsmTst::sub->QMsmTst::sub_sub11") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub_sub1") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub_sub11") +expect("@timestamp ===>Tran Obj=the_sm,Sig=D_SIG,State=QMsmTst::sub_sub1->QMsmTst::sub_sub11") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("E_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=E_SIG,State=QMsmTst::sub_sub11") +expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::sub_sub11") +expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::sub_sub1") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub_sub2") +expect("@timestamp ===>Tran Obj=the_sm,Sig=E_SIG,State=QMsmTst::sub->QMsmTst::sub_sub2") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("F_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=F_SIG,State=QMsmTst::sub_sub2") +expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::sub_sub2") +expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::sub") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub") +expect("===RTC===> St-EP Obj=the_sm,State=QMsmTst::sub->QMsmTst::sub_sub1") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub_sub1") +expect("===RTC===> St-Init Obj=the_sm,State=QMsmTst::sub_sub1->QMsmTst::sub_sub11") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub_sub11") +expect("@timestamp ===>Tran Obj=the_sm,Sig=F_SIG,State=QMsmTst::s2->QMsmTst::sub_sub11") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("H_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=H_SIG,State=QMsmTst::sub_sub11") +expect("@timestamp =>Ignore Obj=the_sm,Sig=H_SIG,State=QMsmTst::sub_sub11") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("C_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=C_SIG,State=QMsmTst::sub_sub11") +expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::sub_sub11") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub_sub12") +expect("@timestamp ===>Tran Obj=the_sm,Sig=C_SIG,State=QMsmTst::sub_sub11->QMsmTst::sub_sub12") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("H_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=H_SIG,State=QMsmTst::sub_sub12") +expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::sub_sub12") +expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::sub_sub1") +expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s1") +expect("===RTC===> St-Init Obj=the_sm,State=QMsmTst::s->QMsmTst::sub") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub") +expect("===RTC===> St-Init Obj=the_sm,State=QMsmTst::sub->QMsmTst::sub_sub11") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub_sub1") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub_sub11") +expect("@timestamp ===>Tran Obj=the_sm,Sig=H_SIG,State=QMsmTst::sub_sub12->QMsmTst::sub_sub11") +expect("@timestamp Trg-Done QS_RX_EVENT") + +#========================================================== +test("QMsmTst guards") +init() +expect("===RTC===> St-Init Obj=the_sm,State=NULL->QMsmTst::sub") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub") +expect("===RTC===> St-Init Obj=the_sm,State=QMsmTst::sub->QMsmTst::sub_sub11") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub_sub1") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub_sub11") +expect("@timestamp Init===> Obj=the_sm,State=QMsmTst::sub_sub11") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("D_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=D_SIG,State=QMsmTst::sub_sub11") +expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::sub_sub11") +expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::sub_sub1") +expect("===RTC===> St-Init Obj=the_sm,State=QMsmTst::sub->QMsmTst::sub_sub11") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub_sub1") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub_sub11") +expect("@timestamp ===>Tran Obj=the_sm,Sig=D_SIG,State=QMsmTst::sub_sub1->QMsmTst::sub_sub11") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("D_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=D_SIG,State=QMsmTst::sub_sub11") +expect("===RTC===> St-Unhnd Obj=the_sm,Sig=D_SIG,State=QMsmTst::sub_sub1") +expect("@timestamp =>Ignore Obj=the_sm,Sig=D_SIG,State=QMsmTst::sub_sub11") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("I_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=I_SIG,State=QMsmTst::sub_sub11") +expect("@timestamp =>Intern Obj=the_sm,Sig=I_SIG,State=QMsmTst::sub") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("I_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=I_SIG,State=QMsmTst::sub_sub11") +#expect("===RTC===> St-Unhnd Obj=the_sm,Sig=I_SIG,State=QMsmTst::sub") +expect("@timestamp =>Intern Obj=the_sm,Sig=I_SIG,State=QMsmTst::s") +expect("@timestamp Trg-Done QS_RX_EVENT") + +#========================================================== +test("QMsmTst history") +init() +expect("===RTC===> St-Init Obj=the_sm,State=NULL->QMsmTst::sub") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub") +expect("===RTC===> St-Init Obj=the_sm,State=QMsmTst::sub->QMsmTst::sub_sub11") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub_sub1") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub_sub11") +expect("@timestamp Init===> Obj=the_sm,State=QMsmTst::sub_sub11") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("G_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=G_SIG,State=QMsmTst::sub_sub11") +expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::sub_sub11") +expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::sub_sub1") +expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s2") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub") +expect("===RTC===> St-Hist Obj=the_sm,State=QMsmTst::sub->QMsmTst::sub_sub11") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub_sub1") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub_sub11") +expect("@timestamp ===>Tran Obj=the_sm,Sig=G_SIG,State=QMsmTst::sub_sub1->QMsmTst::sub_sub11") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("C_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=C_SIG,State=QMsmTst::sub_sub11") +expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::sub_sub11") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub_sub12") +expect("@timestamp ===>Tran Obj=the_sm,Sig=C_SIG,State=QMsmTst::sub_sub11->QMsmTst::sub_sub12") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("C_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=C_SIG,State=QMsmTst::sub_sub12") +expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::sub_sub12") +expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::sub_sub1") +expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::sub") +expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::t") +expect("@timestamp ===>Tran Obj=the_sm,Sig=C_SIG,State=QMsmTst::s->QMsmTst::t") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("C_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=C_SIG,State=QMsmTst::t") +expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::t") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s") +expect("===RTC===> St-Hist Obj=the_sm,State=QMsmTst::s->QMsmTst::s1") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s1") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub_sub1") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub_sub11") +expect("@timestamp ===>Tran Obj=the_sm,Sig=C_SIG,State=QMsmTst::t->QMsmTst::sub_sub11") +expect("@timestamp Trg-Done QS_RX_EVENT") + +dispatch("G_SIG") +expect("@timestamp Disp===> Obj=the_sm,Sig=G_SIG,State=QMsmTst::sub_sub11") +expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::sub_sub11") +expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::sub_sub1") +expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s1") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub") +expect("===RTC===> St-Hist Obj=the_sm,State=QMsmTst::sub->QMsmTst::sub_sub11") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub_sub1") +expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::sub_sub11") +expect("@timestamp ===>Tran Obj=the_sm,Sig=G_SIG,State=QMsmTst::sub_sub1->QMsmTst::sub_sub11") +expect("@timestamp Trg-Done QS_RX_EVENT") diff --git a/qutest/qmsmtst/test/test_qmsm.cpp b/qutest/qmsm/test/test_qmsm.cpp similarity index 94% rename from qutest/qmsmtst/test/test_qmsm.cpp rename to qutest/qmsm/test/test_qmsm.cpp index ac34e69..3aaec16 100644 --- a/qutest/qmsmtst/test/test_qmsm.cpp +++ b/qutest/qmsm/test/test_qmsm.cpp @@ -1,7 +1,7 @@ //============================================================================ // Purpose: Fixture for QUTEST -// Last Updated for Version: 7.3.1 -// Date of the Last Update: 2023-12-11 +// Last Updated for Version: 7.4.0 +// Date of the Last Update: 2024-09-04 // // Q u a n t u m L e a P s // ------------------------ @@ -32,7 +32,7 @@ // //============================================================================ #include "qpcpp.hpp" -#include "qmsmtst.hpp" +#include "cut_qmsm.hpp" Q_DEFINE_THIS_FILE @@ -40,8 +40,10 @@ Q_DEFINE_THIS_FILE namespace APP { enum { - BSP_DISPLAY = QP::QS_USER, - CMD, + BSP_DISPLAY = QP::QS_USER0, +}; +enum { + CMD = QP::QS_USER1, }; void BSP_display(char const *msg) { @@ -76,7 +78,9 @@ void QS::onCommand(std::uint8_t cmdId, std::uint32_t param1, //PRINTF_S(" Command id=%d param=%d\n", (int)cmdId, (int)param); switch (cmdId) { case 0U: { + QP::QStateHandler state = APP::the_sm->getStateHandler(); QS_BEGIN_ID(APP::CMD, 0U) // app-specific record + QS_FUN(state); QS_END() break; } diff --git a/qutest/qmsmtst/src/qmsmtst.cpp b/qutest/qmsmtst/src/qmsmtst.cpp deleted file mode 100644 index 6af3edc..0000000 --- a/qutest/qmsmtst/src/qmsmtst.cpp +++ /dev/null @@ -1,772 +0,0 @@ -//$file${.::qmsmtst.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qmsmtst.qm -// File: ${.::qmsmtst.cpp} -// -// This code has been generated by QM 5.3.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. -// -// SPDX-License-Identifier: GPL-3.0-or-later -// -// This generated code is open source software: you can redistribute it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation. -// -// This code 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. -// -// NOTE: -// Alternatively, this generated code may be distributed under the terms -// of Quantum Leaps commercial licenses, which expressly supersede the GNU -// General Public License and are specifically designed for licensees -// interested in retaining the proprietary status of their code. -// -// Contact information: -// -// -// -//$endhead${.::qmsmtst.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -#include "qpcpp.hpp" -#include "qmsmtst.hpp" - -namespace { -Q_DEFINE_THIS_FILE -} - -namespace APP { - -//$declare${SMs::QMsmTst} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv - -//${SMs::QMsmTst} ............................................................ -class QMsmTst : public QP::QMsm { -private: - bool m_foo; - -public: - friend bool QMsmTst_isIn(std::uint32_t const state_num); - -public: - QMsmTst() - : QMsm(&initial) - {} - -protected: - QM_STATE_DECL( initial); - QM_STATE_DECL( s); - QM_ACTION_DECL(s_e); - QM_ACTION_DECL(s_x); - QM_ACTION_DECL(s_i); - QM_STATE_DECL( s1); - QM_ACTION_DECL(s1_e); - QM_ACTION_DECL(s1_x); - QM_ACTION_DECL(s1_i); - QM_STATE_DECL( s11); - QM_ACTION_DECL(s11_e); - QM_ACTION_DECL(s11_x); - QM_STATE_DECL( s2); - QM_ACTION_DECL(s2_e); - QM_ACTION_DECL(s2_x); - QM_ACTION_DECL(s2_i); - QM_STATE_DECL( s21); - QM_ACTION_DECL(s21_e); - QM_ACTION_DECL(s21_x); - QM_ACTION_DECL(s21_i); - QM_STATE_DECL( s211); - QM_ACTION_DECL(s211_e); - QM_ACTION_DECL(s211_x); -}; // class QMsmTst -//$enddecl${SMs::QMsmTst} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -static QMsmTst l_msmtst; // the only instance of the QMsmTst class - -// global-scope definitions ----------------------------------------- -QP::QAsm * const the_sm = &l_msmtst; // the opaque pointer - -//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// Check for the minimum required QP version -#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U)) -#error qpcpp version 7.3.0 or higher required -#endif -//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$define${SMs::QMsmTst} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv - -//${SMs::QMsmTst} ............................................................ - -//${SMs::QMsmTst::SM} ........................................................ -QM_STATE_DEF(QMsmTst, initial) { - //${SMs::QMsmTst::SM::initial} - Q_UNUSED_PAR(e); - - m_foo = 0U; - BSP_display("top-INIT;"); - - QS_SIG_DICTIONARY(A_SIG, nullptr); - QS_SIG_DICTIONARY(B_SIG, nullptr); - QS_SIG_DICTIONARY(C_SIG, nullptr); - QS_SIG_DICTIONARY(D_SIG, nullptr); - QS_SIG_DICTIONARY(E_SIG, nullptr); - QS_SIG_DICTIONARY(F_SIG, nullptr); - QS_SIG_DICTIONARY(G_SIG, nullptr); - QS_SIG_DICTIONARY(H_SIG, nullptr); - QS_SIG_DICTIONARY(I_SIG, nullptr); - QS_SIG_DICTIONARY(TERMINATE_SIG, nullptr); - QS_SIG_DICTIONARY(IGNORE_SIG, nullptr); - - QS_FUN_DICTIONARY(&QMsmTst::s); - QS_FUN_DICTIONARY(&QMsmTst::s1); - QS_FUN_DICTIONARY(&QMsmTst::s11); - QS_FUN_DICTIONARY(&QMsmTst::s2); - QS_FUN_DICTIONARY(&QMsmTst::s21); - QS_FUN_DICTIONARY(&QMsmTst::s211); - - static struct { - QP::QMState const *target; - QP::QActionHandler act[4]; - } const tatbl_ = { // tran-action table - &s2_s, // target state - { - &s_e, // entry - &s2_e, // entry - &s2_i, // initial tran. - Q_ACTION_NULL // zero terminator - } - }; - return qm_tran_init(&tatbl_); -} - -//${SMs::QMsmTst::SM::s} ..................................................... -QP::QMState const QMsmTst::s_s = { - QM_STATE_NULL, // superstate (top) - &QMsmTst::s, - &QMsmTst::s_e, - &QMsmTst::s_x, - &QMsmTst::s_i -}; -//${SMs::QMsmTst::SM::s} -QM_ACTION_DEF(QMsmTst, s_e) { - BSP_display("s-ENTRY;"); - return qm_entry(&s_s); -} -//${SMs::QMsmTst::SM::s} -QM_ACTION_DEF(QMsmTst, s_x) { - BSP_display("s-EXIT;"); - return qm_exit(&s_s); -} -//${SMs::QMsmTst::SM::s::initial} -QM_ACTION_DEF(QMsmTst, s_i) { - //${SMs::QMsmTst::SM::s::initial} - BSP_display("s-INIT;"); - - static struct { - QP::QMState const *target; - QP::QActionHandler act[3]; - } const tatbl_ = { // tran-action table - &s11_s, // target state - { - &s1_e, // entry - &s11_e, // entry - Q_ACTION_NULL // zero terminator - } - }; - return qm_tran_init(&tatbl_); -} -//${SMs::QMsmTst::SM::s} -QM_STATE_DEF(QMsmTst, s) { - QP::QState status_; - switch (e->sig) { - //${SMs::QMsmTst::SM::s::I} - case I_SIG: { - //${SMs::QMsmTst::SM::s::I::[m_foo]} - if (m_foo) { - m_foo = 0U; - BSP_display("s-I;"); - status_ = Q_RET_HANDLED; - } - else { - status_ = Q_RET_UNHANDLED; - } - break; - } - //${SMs::QMsmTst::SM::s::E} - case E_SIG: { - BSP_display("s-E;"); - - static struct { - QP::QMState const *target; - QP::QActionHandler act[3]; - } const tatbl_ = { // tran-action table - &s11_s, // target state - { - &s1_e, // entry - &s11_e, // entry - Q_ACTION_NULL // zero terminator - } - }; - status_ = qm_tran(&tatbl_); - break; - } - //${SMs::QMsmTst::SM::s::TERMINATE} - case TERMINATE_SIG: { - BSP_terminate(0); - status_ = Q_RET_HANDLED; - break; - } - default: { - status_ = Q_RET_SUPER; - break; - } - } - return status_; -} - -//${SMs::QMsmTst::SM::s::s1} ................................................. -QP::QMState const QMsmTst::s1_s = { - &QMsmTst::s_s, // superstate - &QMsmTst::s1, - &QMsmTst::s1_e, - &QMsmTst::s1_x, - &QMsmTst::s1_i -}; -//${SMs::QMsmTst::SM::s::s1} -QM_ACTION_DEF(QMsmTst, s1_e) { - BSP_display("s1-ENTRY;"); - return qm_entry(&s1_s); -} -//${SMs::QMsmTst::SM::s::s1} -QM_ACTION_DEF(QMsmTst, s1_x) { - BSP_display("s1-EXIT;"); - return qm_exit(&s1_s); -} -//${SMs::QMsmTst::SM::s::s1::initial} -QM_ACTION_DEF(QMsmTst, s1_i) { - //${SMs::QMsmTst::SM::s::s1::initial} - BSP_display("s1-INIT;"); - - static struct { - QP::QMState const *target; - QP::QActionHandler act[2]; - } const tatbl_ = { // tran-action table - &s11_s, // target state - { - &s11_e, // entry - Q_ACTION_NULL // zero terminator - } - }; - return qm_tran_init(&tatbl_); -} -//${SMs::QMsmTst::SM::s::s1} -QM_STATE_DEF(QMsmTst, s1) { - QP::QState status_; - switch (e->sig) { - //${SMs::QMsmTst::SM::s::s1::I} - case I_SIG: { - BSP_display("s1-I;"); - status_ = Q_RET_HANDLED; - break; - } - //${SMs::QMsmTst::SM::s::s1::D} - case D_SIG: { - //${SMs::QMsmTst::SM::s::s1::D::[!m_foo]} - if (!m_foo) { - m_foo = true; - BSP_display("s1-D;"); - - static struct { - QP::QMState const *target; - QP::QActionHandler act[3]; - } const tatbl_ = { // tran-action table - &s_s, // target state - { - &s1_x, // exit - &s_i, // initial tran. - Q_ACTION_NULL // zero terminator - } - }; - status_ = qm_tran(&tatbl_); - } - else { - status_ = Q_RET_UNHANDLED; - } - break; - } - //${SMs::QMsmTst::SM::s::s1::A} - case A_SIG: { - BSP_display("s1-A;"); - - static struct { - QP::QMState const *target; - QP::QActionHandler act[4]; - } const tatbl_ = { // tran-action table - &s1_s, // target state - { - &s1_x, // exit - &s1_e, // entry - &s1_i, // initial tran. - Q_ACTION_NULL // zero terminator - } - }; - status_ = qm_tran(&tatbl_); - break; - } - //${SMs::QMsmTst::SM::s::s1::B} - case B_SIG: { - BSP_display("s1-B;"); - - static struct { - QP::QMState const *target; - QP::QActionHandler act[2]; - } const tatbl_ = { // tran-action table - &s11_s, // target state - { - &s11_e, // entry - Q_ACTION_NULL // zero terminator - } - }; - status_ = qm_tran(&tatbl_); - break; - } - //${SMs::QMsmTst::SM::s::s1::F} - case F_SIG: { - BSP_display("s1-F;"); - - static struct { - QP::QMState const *target; - QP::QActionHandler act[5]; - } const tatbl_ = { // tran-action table - &s211_s, // target state - { - &s1_x, // exit - &s2_e, // entry - &s21_e, // entry - &s211_e, // entry - Q_ACTION_NULL // zero terminator - } - }; - status_ = qm_tran(&tatbl_); - break; - } - //${SMs::QMsmTst::SM::s::s1::C} - case C_SIG: { - BSP_display("s1-C;"); - - static struct { - QP::QMState const *target; - QP::QActionHandler act[4]; - } const tatbl_ = { // tran-action table - &s2_s, // target state - { - &s1_x, // exit - &s2_e, // entry - &s2_i, // initial tran. - Q_ACTION_NULL // zero terminator - } - }; - status_ = qm_tran(&tatbl_); - break; - } - default: { - status_ = Q_RET_SUPER; - break; - } - } - return status_; -} - -//${SMs::QMsmTst::SM::s::s1::s11} ............................................ -QP::QMState const QMsmTst::s11_s = { - &QMsmTst::s1_s, // superstate - &QMsmTst::s11, - &QMsmTst::s11_e, - &QMsmTst::s11_x, - Q_ACTION_NULL // no initial tran. -}; -//${SMs::QMsmTst::SM::s::s1::s11} -QM_ACTION_DEF(QMsmTst, s11_e) { - BSP_display("s11-ENTRY;"); - return qm_entry(&s11_s); -} -//${SMs::QMsmTst::SM::s::s1::s11} -QM_ACTION_DEF(QMsmTst, s11_x) { - BSP_display("s11-EXIT;"); - return qm_exit(&s11_s); -} -//${SMs::QMsmTst::SM::s::s1::s11} -QM_STATE_DEF(QMsmTst, s11) { - QP::QState status_; - switch (e->sig) { - //${SMs::QMsmTst::SM::s::s1::s11::H} - case H_SIG: { - BSP_display("s11-H;"); - - static struct { - QP::QMState const *target; - QP::QActionHandler act[4]; - } const tatbl_ = { // tran-action table - &s_s, // target state - { - &s11_x, // exit - &s1_x, // exit - &s_i, // initial tran. - Q_ACTION_NULL // zero terminator - } - }; - status_ = qm_tran(&tatbl_); - break; - } - //${SMs::QMsmTst::SM::s::s1::s11::D} - case D_SIG: { - //${SMs::QMsmTst::SM::s::s1::s11::D::[m_foo]} - if (m_foo) { - m_foo = false; - BSP_display("s11-D;"); - - static struct { - QP::QMState const *target; - QP::QActionHandler act[3]; - } const tatbl_ = { // tran-action table - &s1_s, // target state - { - &s11_x, // exit - &s1_i, // initial tran. - Q_ACTION_NULL // zero terminator - } - }; - status_ = qm_tran(&tatbl_); - } - else { - status_ = Q_RET_UNHANDLED; - } - break; - } - //${SMs::QMsmTst::SM::s::s1::s11::G} - case G_SIG: { - BSP_display("s11-G;"); - - static struct { - QP::QMState const *target; - QP::QActionHandler act[6]; - } const tatbl_ = { // tran-action table - &s211_s, // target state - { - &s11_x, // exit - &s1_x, // exit - &s2_e, // entry - &s21_e, // entry - &s211_e, // entry - Q_ACTION_NULL // zero terminator - } - }; - status_ = qm_tran(&tatbl_); - break; - } - default: { - status_ = Q_RET_SUPER; - break; - } - } - return status_; -} - -//${SMs::QMsmTst::SM::s::s2} ................................................. -QP::QMState const QMsmTst::s2_s = { - &QMsmTst::s_s, // superstate - &QMsmTst::s2, - &QMsmTst::s2_e, - &QMsmTst::s2_x, - &QMsmTst::s2_i -}; -//${SMs::QMsmTst::SM::s::s2} -QM_ACTION_DEF(QMsmTst, s2_e) { - BSP_display("s2-ENTRY;"); - return qm_entry(&s2_s); -} -//${SMs::QMsmTst::SM::s::s2} -QM_ACTION_DEF(QMsmTst, s2_x) { - BSP_display("s2-EXIT;"); - return qm_exit(&s2_s); -} -//${SMs::QMsmTst::SM::s::s2::initial} -QM_ACTION_DEF(QMsmTst, s2_i) { - //${SMs::QMsmTst::SM::s::s2::initial} - BSP_display("s2-INIT;"); - - static struct { - QP::QMState const *target; - QP::QActionHandler act[3]; - } const tatbl_ = { // tran-action table - &s211_s, // target state - { - &s21_e, // entry - &s211_e, // entry - Q_ACTION_NULL // zero terminator - } - }; - return qm_tran_init(&tatbl_); -} -//${SMs::QMsmTst::SM::s::s2} -QM_STATE_DEF(QMsmTst, s2) { - QP::QState status_; - switch (e->sig) { - //${SMs::QMsmTst::SM::s::s2::I} - case I_SIG: { - //${SMs::QMsmTst::SM::s::s2::I::[!m_foo]} - if (!m_foo) { - m_foo = true; - BSP_display("s2-I;"); - status_ = Q_RET_HANDLED; - } - else { - status_ = Q_RET_UNHANDLED; - } - break; - } - //${SMs::QMsmTst::SM::s::s2::F} - case F_SIG: { - BSP_display("s2-F;"); - - static struct { - QP::QMState const *target; - QP::QActionHandler act[4]; - } const tatbl_ = { // tran-action table - &s11_s, // target state - { - &s2_x, // exit - &s1_e, // entry - &s11_e, // entry - Q_ACTION_NULL // zero terminator - } - }; - status_ = qm_tran(&tatbl_); - break; - } - //${SMs::QMsmTst::SM::s::s2::C} - case C_SIG: { - BSP_display("s2-C;"); - - static struct { - QP::QMState const *target; - QP::QActionHandler act[4]; - } const tatbl_ = { // tran-action table - &s1_s, // target state - { - &s2_x, // exit - &s1_e, // entry - &s1_i, // initial tran. - Q_ACTION_NULL // zero terminator - } - }; - status_ = qm_tran(&tatbl_); - break; - } - default: { - status_ = Q_RET_SUPER; - break; - } - } - return status_; -} - -//${SMs::QMsmTst::SM::s::s2::s21} ............................................ -QP::QMState const QMsmTst::s21_s = { - &QMsmTst::s2_s, // superstate - &QMsmTst::s21, - &QMsmTst::s21_e, - &QMsmTst::s21_x, - &QMsmTst::s21_i -}; -//${SMs::QMsmTst::SM::s::s2::s21} -QM_ACTION_DEF(QMsmTst, s21_e) { - BSP_display("s21-ENTRY;"); - return qm_entry(&s21_s); -} -//${SMs::QMsmTst::SM::s::s2::s21} -QM_ACTION_DEF(QMsmTst, s21_x) { - BSP_display("s21-EXIT;"); - return qm_exit(&s21_s); -} -//${SMs::QMsmTst::SM::s::s2::s21::initial} -QM_ACTION_DEF(QMsmTst, s21_i) { - //${SMs::QMsmTst::SM::s::s2::s21::initial} - BSP_display("s21-INIT;"); - - static struct { - QP::QMState const *target; - QP::QActionHandler act[2]; - } const tatbl_ = { // tran-action table - &s211_s, // target state - { - &s211_e, // entry - Q_ACTION_NULL // zero terminator - } - }; - return qm_tran_init(&tatbl_); -} -//${SMs::QMsmTst::SM::s::s2::s21} -QM_STATE_DEF(QMsmTst, s21) { - QP::QState status_; - switch (e->sig) { - //${SMs::QMsmTst::SM::s::s2::s21::G} - case G_SIG: { - BSP_display("s21-G;"); - - static struct { - QP::QMState const *target; - QP::QActionHandler act[5]; - } const tatbl_ = { // tran-action table - &s1_s, // target state - { - &s21_x, // exit - &s2_x, // exit - &s1_e, // entry - &s1_i, // initial tran. - Q_ACTION_NULL // zero terminator - } - }; - status_ = qm_tran(&tatbl_); - break; - } - //${SMs::QMsmTst::SM::s::s2::s21::A} - case A_SIG: { - BSP_display("s21-A;"); - - static struct { - QP::QMState const *target; - QP::QActionHandler act[4]; - } const tatbl_ = { // tran-action table - &s21_s, // target state - { - &s21_x, // exit - &s21_e, // entry - &s21_i, // initial tran. - Q_ACTION_NULL // zero terminator - } - }; - status_ = qm_tran(&tatbl_); - break; - } - //${SMs::QMsmTst::SM::s::s2::s21::B} - case B_SIG: { - BSP_display("s21-B;"); - - static struct { - QP::QMState const *target; - QP::QActionHandler act[2]; - } const tatbl_ = { // tran-action table - &s211_s, // target state - { - &s211_e, // entry - Q_ACTION_NULL // zero terminator - } - }; - status_ = qm_tran(&tatbl_); - break; - } - default: { - status_ = Q_RET_SUPER; - break; - } - } - return status_; -} - -//${SMs::QMsmTst::SM::s::s2::s21::s211} ...................................... -QP::QMState const QMsmTst::s211_s = { - &QMsmTst::s21_s, // superstate - &QMsmTst::s211, - &QMsmTst::s211_e, - &QMsmTst::s211_x, - Q_ACTION_NULL // no initial tran. -}; -//${SMs::QMsmTst::SM::s::s2::s21::s211} -QM_ACTION_DEF(QMsmTst, s211_e) { - BSP_display("s211-ENTRY;"); - return qm_entry(&s211_s); -} -//${SMs::QMsmTst::SM::s::s2::s21::s211} -QM_ACTION_DEF(QMsmTst, s211_x) { - BSP_display("s211-EXIT;"); - return qm_exit(&s211_s); -} -//${SMs::QMsmTst::SM::s::s2::s21::s211} -QM_STATE_DEF(QMsmTst, s211) { - QP::QState status_; - switch (e->sig) { - //${SMs::QMsmTst::SM::s::s2::s21::s211::H} - case H_SIG: { - BSP_display("s211-H;"); - - static struct { - QP::QMState const *target; - QP::QActionHandler act[5]; - } const tatbl_ = { // tran-action table - &s_s, // target state - { - &s211_x, // exit - &s21_x, // exit - &s2_x, // exit - &s_i, // initial tran. - Q_ACTION_NULL // zero terminator - } - }; - status_ = qm_tran(&tatbl_); - break; - } - //${SMs::QMsmTst::SM::s::s2::s21::s211::D} - case D_SIG: { - BSP_display("s211-D;"); - - static struct { - QP::QMState const *target; - QP::QActionHandler act[3]; - } const tatbl_ = { // tran-action table - &s21_s, // target state - { - &s211_x, // exit - &s21_i, // initial tran. - Q_ACTION_NULL // zero terminator - } - }; - status_ = qm_tran(&tatbl_); - break; - } - default: { - status_ = Q_RET_SUPER; - break; - } - } - return status_; -} -//$enddef${SMs::QMsmTst} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -bool QMsmTst_isIn(std::uint32_t const state_num) { - QP::QMsm * const me = &l_msmtst; - bool stat = false; - switch (state_num) { - case 0: - stat = me->isIn(Q_STATE_CAST(&QMsmTst::s)); - break; - case 1: - stat = me->isIn(Q_STATE_CAST(&QMsmTst::s1)); - break; - case 11: - stat = me->isIn(Q_STATE_CAST(&QMsmTst::s11)); - break; - case 2: - stat = me->isIn(Q_STATE_CAST(&QMsmTst::s2)); - break; - case 21: - stat = me->isIn(Q_STATE_CAST(&QMsmTst::s21)); - break; - case 211: - stat = me->isIn(Q_STATE_CAST(&QMsmTst::s211)); - break; - default: - Q_ERROR(); - } - return stat; -} - -} // namespace APP diff --git a/qutest/qmsmtst/src/qmsmtst.qm b/qutest/qmsmtst/src/qmsmtst.qm deleted file mode 100644 index 33bcebe..0000000 --- a/qutest/qmsmtst/src/qmsmtst.qm +++ /dev/null @@ -1,388 +0,0 @@ - - - QMsmTst is a contrived state machine from Chapter 2 of the PSiCC2 book for testing all possible transition topologies with up to 4-levels of state nesting. - - - - - - - Test State Machine - - - - - - - : QMsm(&initial) - - - - - - Q_UNUSED_PAR(e); - -m_foo = 0U; -BSP_display("top-INIT;"); - -QS_SIG_DICTIONARY(A_SIG, nullptr); -QS_SIG_DICTIONARY(B_SIG, nullptr); -QS_SIG_DICTIONARY(C_SIG, nullptr); -QS_SIG_DICTIONARY(D_SIG, nullptr); -QS_SIG_DICTIONARY(E_SIG, nullptr); -QS_SIG_DICTIONARY(F_SIG, nullptr); -QS_SIG_DICTIONARY(G_SIG, nullptr); -QS_SIG_DICTIONARY(H_SIG, nullptr); -QS_SIG_DICTIONARY(I_SIG, nullptr); -QS_SIG_DICTIONARY(TERMINATE_SIG, nullptr); -QS_SIG_DICTIONARY(IGNORE_SIG, nullptr); - - - - - - - BSP_display("s-ENTRY;"); - BSP_display("s-EXIT;"); - - - BSP_display("s-INIT;"); - - - - - - - - - m_foo - m_foo = 0U; -BSP_display("s-I;"); - - - - - - - - - - - BSP_display("s-E;"); - - - - - - - BSP_terminate(0); - - - - - - - BSP_display("s1-ENTRY;"); - BSP_display("s1-EXIT;"); - - - BSP_display("s1-INIT;"); - - - - - - - BSP_display("s1-I;"); - - - - - - - - - !m_foo - m_foo = true; -BSP_display("s1-D;"); - - - - - - - - - - - BSP_display("s1-A;"); - - - - - - - BSP_display("s1-B;"); - - - - - - - BSP_display("s1-F;"); - - - - - - - BSP_display("s1-C;"); - - - - - - - BSP_display("s11-ENTRY;"); - BSP_display("s11-EXIT;"); - - - BSP_display("s11-H;"); - - - - - - - - - m_foo - m_foo = false; -BSP_display("s11-D;"); - - - - - - - - - - - BSP_display("s11-G;"); - - - - - - - - - - - - - - - - - BSP_display("s2-ENTRY;"); - BSP_display("s2-EXIT;"); - - - BSP_display("s2-INIT;"); - - - - - - - - - !m_foo - m_foo = true; -BSP_display("s2-I;"); - - - - - - - - - - - BSP_display("s2-F;"); - - - - - - - BSP_display("s2-C;"); - - - - - - - BSP_display("s21-ENTRY;"); - BSP_display("s21-EXIT;"); - - - BSP_display("s21-INIT;"); - - - - - - - BSP_display("s21-G;"); - - - - - - - BSP_display("s21-A;"); - - - - - - - BSP_display("s21-B;"); - - - - - - - BSP_display("s211-ENTRY;"); - BSP_display("s211-EXIT;"); - - - BSP_display("s211-H;"); - - - - - - - BSP_display("s211-D;"); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #ifndef QMSMTST_HPP_ -#define QMSMTST_HPP_ - -namespace APP { - -enum QMsmTstSignals { - A_SIG = QP::Q_USER_SIG, - B_SIG, - C_SIG, - D_SIG, - E_SIG, - F_SIG, - G_SIG, - H_SIG, - I_SIG, - TERMINATE_SIG, - IGNORE_SIG, - MAX_SIG -}; - -extern QP::QAsm * const the_sm; // opaque pointer to the test SM - -bool QMsmTst_isIn(std::uint32_t const state_num); - -// BSP functions to display a message and exit -void BSP_display(char const *msg); -void BSP_terminate(int16_t const result); - -} // namespace APP - -#endif // QMSMTST_HPP_ - - - - #include "qpcpp.hpp" -#include "qmsmtst.hpp" - -namespace { -Q_DEFINE_THIS_FILE -} - -namespace APP { - -$declare ${SMs::QMsmTst} - -static QMsmTst l_msmtst; // the only instance of the QMsmTst class - -// global-scope definitions ----------------------------------------- -QP::QAsm * const the_sm = &l_msmtst; // the opaque pointer - -$define ${SMs::QMsmTst} - -bool QMsmTst_isIn(std::uint32_t const state_num) { - QP::QMsm * const me = &l_msmtst; - bool stat = false; - switch (state_num) { - case 0: - stat = me->isIn(Q_STATE_CAST(&QMsmTst::s)); - break; - case 1: - stat = me->isIn(Q_STATE_CAST(&QMsmTst::s1)); - break; - case 11: - stat = me->isIn(Q_STATE_CAST(&QMsmTst::s11)); - break; - case 2: - stat = me->isIn(Q_STATE_CAST(&QMsmTst::s2)); - break; - case 21: - stat = me->isIn(Q_STATE_CAST(&QMsmTst::s21)); - break; - case 211: - stat = me->isIn(Q_STATE_CAST(&QMsmTst::s211)); - break; - default: - Q_ERROR(); - } - return stat; -} - -} // namespace APP - - - diff --git a/qutest/qmsmtst/test/test_qmsm-funct.py b/qutest/qmsmtst/test/test_qmsm-funct.py deleted file mode 100644 index f755c02..0000000 --- a/qutest/qmsmtst/test/test_qmsm-funct.py +++ /dev/null @@ -1,200 +0,0 @@ -# test-script for QUTest unit testing harness -# see https://www.state-machine.com/qtools/qutest.html - -# preamble... -def on_reset(): - expect_run() - glb_filter(GRP_UA) - current_obj(OBJ_SM, "the_sm") - -# tests... -test("QMsmTst_init") -init() -expect("@timestamp BSP_DISPLAY top-INIT;") -expect("@timestamp BSP_DISPLAY s-ENTRY;") -expect("@timestamp BSP_DISPLAY s2-ENTRY;") -expect("@timestamp BSP_DISPLAY s2-INIT;") -expect("@timestamp BSP_DISPLAY s21-ENTRY;") -expect("@timestamp BSP_DISPLAY s211-ENTRY;") -expect("@timestamp Trg-Done QS_RX_EVENT") - -test("QMsmTst isIn", NORESET) -command(1, 1) # is in state s1 -expect("@timestamp CMD 0 1"); # NOT in s1 -expect("@timestamp Trg-Done QS_RX_COMMAND") -command(1, 21) # is in state s21 -expect("@timestamp CMD 1 21"); # YES, in s21 -expect("@timestamp Trg-Done QS_RX_COMMAND") -command(1, 211) # is in state s211 -expect("@timestamp CMD 1 211"); # YES, in s211 -expect("@timestamp Trg-Done QS_RX_COMMAND") - -test("QMsmTst dispatch", NORESET) -dispatch("A_SIG") -expect("@timestamp BSP_DISPLAY s21-A;") -expect("@timestamp BSP_DISPLAY s211-EXIT;") -expect("@timestamp BSP_DISPLAY s21-EXIT;") -expect("@timestamp BSP_DISPLAY s21-ENTRY;") -expect("@timestamp BSP_DISPLAY s21-INIT;") -expect("@timestamp BSP_DISPLAY s211-ENTRY;") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("B_SIG") -expect("@timestamp BSP_DISPLAY s21-B;") -expect("@timestamp BSP_DISPLAY s211-EXIT;") -expect("@timestamp BSP_DISPLAY s211-ENTRY;") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("D_SIG") -expect("@timestamp BSP_DISPLAY s211-D;") -expect("@timestamp BSP_DISPLAY s211-EXIT;") -expect("@timestamp BSP_DISPLAY s21-INIT;") -expect("@timestamp BSP_DISPLAY s211-ENTRY;") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("E_SIG") -expect("@timestamp BSP_DISPLAY s-E;") -expect("@timestamp BSP_DISPLAY s211-EXIT;") -expect("@timestamp BSP_DISPLAY s21-EXIT;") -expect("@timestamp BSP_DISPLAY s2-EXIT;") -expect("@timestamp BSP_DISPLAY s1-ENTRY;") -expect("@timestamp BSP_DISPLAY s11-ENTRY;") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("I_SIG") -expect("@timestamp BSP_DISPLAY s1-I;") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("F_SIG") -expect("@timestamp BSP_DISPLAY s1-F;") -expect("@timestamp BSP_DISPLAY s11-EXIT;") -expect("@timestamp BSP_DISPLAY s1-EXIT;") -expect("@timestamp BSP_DISPLAY s2-ENTRY;") -expect("@timestamp BSP_DISPLAY s21-ENTRY;") -expect("@timestamp BSP_DISPLAY s211-ENTRY;") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("I_SIG") -expect("@timestamp BSP_DISPLAY s2-I;") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("I_SIG") -expect("@timestamp BSP_DISPLAY s-I;") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("F_SIG") -expect("@timestamp BSP_DISPLAY s2-F;") -expect("@timestamp BSP_DISPLAY s211-EXIT;") -expect("@timestamp BSP_DISPLAY s21-EXIT;") -expect("@timestamp BSP_DISPLAY s2-EXIT;") -expect("@timestamp BSP_DISPLAY s1-ENTRY;") -expect("@timestamp BSP_DISPLAY s11-ENTRY;") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("A_SIG") -expect("@timestamp BSP_DISPLAY s1-A;") -expect("@timestamp BSP_DISPLAY s11-EXIT;") -expect("@timestamp BSP_DISPLAY s1-EXIT;") -expect("@timestamp BSP_DISPLAY s1-ENTRY;") -expect("@timestamp BSP_DISPLAY s1-INIT;") -expect("@timestamp BSP_DISPLAY s11-ENTRY;") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("B_SIG") -expect("@timestamp BSP_DISPLAY s1-B;") -expect("@timestamp BSP_DISPLAY s11-EXIT;") -expect("@timestamp BSP_DISPLAY s11-ENTRY;") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("D_SIG") -expect("@timestamp BSP_DISPLAY s1-D;") -expect("@timestamp BSP_DISPLAY s11-EXIT;") -expect("@timestamp BSP_DISPLAY s1-EXIT;") -expect("@timestamp BSP_DISPLAY s-INIT;") -expect("@timestamp BSP_DISPLAY s1-ENTRY;") -expect("@timestamp BSP_DISPLAY s11-ENTRY;") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("D_SIG") -expect("@timestamp BSP_DISPLAY s11-D;") -expect("@timestamp BSP_DISPLAY s11-EXIT;") -expect("@timestamp BSP_DISPLAY s1-INIT;") -expect("@timestamp BSP_DISPLAY s11-ENTRY;") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("E_SIG") -expect("@timestamp BSP_DISPLAY s-E;") -expect("@timestamp BSP_DISPLAY s11-EXIT;") -expect("@timestamp BSP_DISPLAY s1-EXIT;") -expect("@timestamp BSP_DISPLAY s1-ENTRY;") -expect("@timestamp BSP_DISPLAY s11-ENTRY;") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("G_SIG") -expect("@timestamp BSP_DISPLAY s11-G;") -expect("@timestamp BSP_DISPLAY s11-EXIT;") -expect("@timestamp BSP_DISPLAY s1-EXIT;") -expect("@timestamp BSP_DISPLAY s2-ENTRY;") -expect("@timestamp BSP_DISPLAY s21-ENTRY;") -expect("@timestamp BSP_DISPLAY s211-ENTRY;") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("H_SIG") -expect("@timestamp BSP_DISPLAY s211-H;") -expect("@timestamp BSP_DISPLAY s211-EXIT;") -expect("@timestamp BSP_DISPLAY s21-EXIT;") -expect("@timestamp BSP_DISPLAY s2-EXIT;") -expect("@timestamp BSP_DISPLAY s-INIT;") -expect("@timestamp BSP_DISPLAY s1-ENTRY;") -expect("@timestamp BSP_DISPLAY s11-ENTRY;") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("H_SIG") -expect("@timestamp BSP_DISPLAY s11-H;") -expect("@timestamp BSP_DISPLAY s11-EXIT;") -expect("@timestamp BSP_DISPLAY s1-EXIT;") -expect("@timestamp BSP_DISPLAY s-INIT;") -expect("@timestamp BSP_DISPLAY s1-ENTRY;") -expect("@timestamp BSP_DISPLAY s11-ENTRY;") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("C_SIG") -expect("@timestamp BSP_DISPLAY s1-C;") -expect("@timestamp BSP_DISPLAY s11-EXIT;") -expect("@timestamp BSP_DISPLAY s1-EXIT;") -expect("@timestamp BSP_DISPLAY s2-ENTRY;") -expect("@timestamp BSP_DISPLAY s2-INIT;") -expect("@timestamp BSP_DISPLAY s21-ENTRY;") -expect("@timestamp BSP_DISPLAY s211-ENTRY;") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("G_SIG") -expect("@timestamp BSP_DISPLAY s21-G;") -expect("@timestamp BSP_DISPLAY s211-EXIT;") -expect("@timestamp BSP_DISPLAY s21-EXIT;") -expect("@timestamp BSP_DISPLAY s2-EXIT;") -expect("@timestamp BSP_DISPLAY s1-ENTRY;") -expect("@timestamp BSP_DISPLAY s1-INIT;") -expect("@timestamp BSP_DISPLAY s11-ENTRY;") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("C_SIG") -expect("@timestamp BSP_DISPLAY s1-C;") -expect("@timestamp BSP_DISPLAY s11-EXIT;") -expect("@timestamp BSP_DISPLAY s1-EXIT;") -expect("@timestamp BSP_DISPLAY s2-ENTRY;") -expect("@timestamp BSP_DISPLAY s2-INIT;") -expect("@timestamp BSP_DISPLAY s21-ENTRY;") -expect("@timestamp BSP_DISPLAY s211-ENTRY;") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("C_SIG") -expect("@timestamp BSP_DISPLAY s2-C;") -expect("@timestamp BSP_DISPLAY s211-EXIT;") -expect("@timestamp BSP_DISPLAY s21-EXIT;") -expect("@timestamp BSP_DISPLAY s2-EXIT;") -expect("@timestamp BSP_DISPLAY s1-ENTRY;") -expect("@timestamp BSP_DISPLAY s1-INIT;") -expect("@timestamp BSP_DISPLAY s11-ENTRY;") -expect("@timestamp Trg-Done QS_RX_EVENT") - diff --git a/qutest/qmsmtst/test/test_qmsm-struct.py b/qutest/qmsmtst/test/test_qmsm-struct.py deleted file mode 100644 index fc89a31..0000000 --- a/qutest/qmsmtst/test/test_qmsm-struct.py +++ /dev/null @@ -1,213 +0,0 @@ -# test-script for QUTest unit testing harness -# see https://www.state-machine.com/qtools/qutest.html - -# preamble... -def on_reset(): - expect_run() - glb_filter(GRP_SM) - current_obj(OBJ_SM, "the_sm") - -# tests... -test("QMsmTst init") -init() -expect("===RTC===> St-Init Obj=the_sm,State=NULL->QMsmTst::s2") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s2") -expect("===RTC===> St-Init Obj=the_sm,State=QMsmTst::s2->QMsmTst::s211") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s21") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s211") -expect("@timestamp Init===> Obj=the_sm,State=QMsmTst::s211") -expect("@timestamp Trg-Done QS_RX_EVENT") - -test("QMsmTst dispatch", NORESET) -dispatch("A_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=A_SIG,State=QMsmTst::s211") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s211") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s21") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s21") -expect("===RTC===> St-Init Obj=the_sm,State=QMsmTst::s21->QMsmTst::s211") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s211") -expect("@timestamp ===>Tran Obj=the_sm,Sig=A_SIG,State=QMsmTst::s21->QMsmTst::s211") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("B_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=B_SIG,State=QMsmTst::s211") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s211") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s211") -expect("@timestamp ===>Tran Obj=the_sm,Sig=B_SIG,State=QMsmTst::s21->QMsmTst::s211") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("D_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=D_SIG,State=QMsmTst::s211") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s211") -expect("===RTC===> St-Init Obj=the_sm,State=QMsmTst::s21->QMsmTst::s211") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s211") -expect("@timestamp ===>Tran Obj=the_sm,Sig=D_SIG,State=QMsmTst::s211->QMsmTst::s211") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("E_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=E_SIG,State=QMsmTst::s211") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s211") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s21") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s2") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s1") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s11") -expect("@timestamp ===>Tran Obj=the_sm,Sig=E_SIG,State=QMsmTst::s->QMsmTst::s11") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("I_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=I_SIG,State=QMsmTst::s11") -expect("@timestamp =>Intern Obj=the_sm,Sig=I_SIG,State=QMsmTst::s1") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("F_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=F_SIG,State=QMsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s1") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s2") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s21") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s211") -expect("@timestamp ===>Tran Obj=the_sm,Sig=F_SIG,State=QMsmTst::s1->QMsmTst::s211") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("I_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=I_SIG,State=QMsmTst::s211") -expect("@timestamp =>Intern Obj=the_sm,Sig=I_SIG,State=QMsmTst::s2") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("I_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=I_SIG,State=QMsmTst::s211") -expect("===RTC===> St-Unhnd Obj=the_sm,Sig=I_SIG,State=QMsmTst::s2") -expect("@timestamp =>Intern Obj=the_sm,Sig=I_SIG,State=QMsmTst::s") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("F_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=F_SIG,State=QMsmTst::s211") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s211") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s21") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s2") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s1") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s11") -expect("@timestamp ===>Tran Obj=the_sm,Sig=F_SIG,State=QMsmTst::s2->QMsmTst::s11") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("A_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=A_SIG,State=QMsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s1") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s1") -expect("===RTC===> St-Init Obj=the_sm,State=QMsmTst::s1->QMsmTst::s11") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s11") -expect("@timestamp ===>Tran Obj=the_sm,Sig=A_SIG,State=QMsmTst::s1->QMsmTst::s11") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("B_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=B_SIG,State=QMsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s11") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s11") -expect("@timestamp ===>Tran Obj=the_sm,Sig=B_SIG,State=QMsmTst::s1->QMsmTst::s11") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("D_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=D_SIG,State=QMsmTst::s11") -expect("===RTC===> St-Unhnd Obj=the_sm,Sig=D_SIG,State=QMsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s1") -expect("===RTC===> St-Init Obj=the_sm,State=QMsmTst::s->QMsmTst::s11") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s1") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s11") -expect("@timestamp ===>Tran Obj=the_sm,Sig=D_SIG,State=QMsmTst::s1->QMsmTst::s11") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("D_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=D_SIG,State=QMsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s11") -expect("===RTC===> St-Init Obj=the_sm,State=QMsmTst::s1->QMsmTst::s11") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s11") -expect("@timestamp ===>Tran Obj=the_sm,Sig=D_SIG,State=QMsmTst::s11->QMsmTst::s11") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("E_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=E_SIG,State=QMsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s1") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s1") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s11") -expect("@timestamp ===>Tran Obj=the_sm,Sig=E_SIG,State=QMsmTst::s->QMsmTst::s11") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("G_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=G_SIG,State=QMsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s1") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s2") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s21") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s211") -expect("@timestamp ===>Tran Obj=the_sm,Sig=G_SIG,State=QMsmTst::s11->QMsmTst::s211") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("H_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=H_SIG,State=QMsmTst::s211") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s211") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s21") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s2") -expect("===RTC===> St-Init Obj=the_sm,State=QMsmTst::s->QMsmTst::s11") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s1") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s11") -expect("@timestamp ===>Tran Obj=the_sm,Sig=H_SIG,State=QMsmTst::s211->QMsmTst::s11") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("H_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=H_SIG,State=QMsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s1") -expect("===RTC===> St-Init Obj=the_sm,State=QMsmTst::s->QMsmTst::s11") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s1") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s11") -expect("@timestamp ===>Tran Obj=the_sm,Sig=H_SIG,State=QMsmTst::s11->QMsmTst::s11") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("C_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=C_SIG,State=QMsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s1") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s2") -expect("===RTC===> St-Init Obj=the_sm,State=QMsmTst::s2->QMsmTst::s211") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s21") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s211") -expect("@timestamp ===>Tran Obj=the_sm,Sig=C_SIG,State=QMsmTst::s1->QMsmTst::s211") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("G_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=G_SIG,State=QMsmTst::s211") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s211") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s21") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s2") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s1") -expect("===RTC===> St-Init Obj=the_sm,State=QMsmTst::s1->QMsmTst::s11") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s11") -expect("@timestamp ===>Tran Obj=the_sm,Sig=G_SIG,State=QMsmTst::s21->QMsmTst::s11") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("C_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=C_SIG,State=QMsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s11") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s1") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s2") -expect("===RTC===> St-Init Obj=the_sm,State=QMsmTst::s2->QMsmTst::s211") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s21") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s211") -expect("@timestamp ===>Tran Obj=the_sm,Sig=C_SIG,State=QMsmTst::s1->QMsmTst::s211") -expect("@timestamp Trg-Done QS_RX_EVENT") - -dispatch("C_SIG") -expect("@timestamp Disp===> Obj=the_sm,Sig=C_SIG,State=QMsmTst::s211") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s211") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s21") -expect("===RTC===> St-Exit Obj=the_sm,State=QMsmTst::s2") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s1") -expect("===RTC===> St-Init Obj=the_sm,State=QMsmTst::s1->QMsmTst::s11") -expect("===RTC===> St-Entry Obj=the_sm,State=QMsmTst::s11") -expect("@timestamp ===>Tran Obj=the_sm,Sig=C_SIG,State=QMsmTst::s2->QMsmTst::s11") -expect("@timestamp Trg-Done QS_RX_EVENT") - diff --git a/uc-os2/arm-cm/dpp_ek-tm4c123gxl/README.txt b/uc-os2/arm-cm/dpp_ek-tm4c123gxl/README.md similarity index 82% rename from uc-os2/arm-cm/dpp_ek-tm4c123gxl/README.txt rename to uc-os2/arm-cm/dpp_ek-tm4c123gxl/README.md index 732c961..a704e25 100644 --- a/uc-os2/arm-cm/dpp_ek-tm4c123gxl/README.txt +++ b/uc-os2/arm-cm/dpp_ek-tm4c123gxl/README.md @@ -1,10 +1,18 @@ -About this Example -================== +# About this Example This directory contains the "Dining Philosophers Problem" (DPP) example for uC/OS-II application running on the EK-TM4C123GXL board, a.k.a. TivaC LauchPad (ARM Cortex-M4F). This directory contains portable code that should compile with any C compiler for ARM Cortex-M. +

+ +

+ +

+
+EK-TM4C123GXL (TivaC LaunchPad) +

+ The sub-directories contain code and project files, which are specific to the particular ARM toolchains, such as ARM (MDK-ARM) and IAR. @@ -12,15 +20,13 @@ Please refer to the README files in the sub-directories for specific instructions how to use and customize the example to your needs. -Support Code for EK-TM4C123GXL Board -==================================== +# Support Code for EK-TM4C123GXL Board The directory qpc\3rd_party\ek-tm4c123gxl contains the CMSIS-compliant device code for the TM4C123GH6PM MCU (ARM Cortex-M4F). Please see the README.txt file in this folder for more details. -QS Software Tracing Instrumentation -=================================== +# QS Software Tracing Instrumentation This example provides the "Spy" build configuration, which outputs the QS (Quantum Spy) software tracing data through UART0, which is connected to the virtual COM port of the TI Stellaris debugger. @@ -30,7 +36,9 @@ The output is generated at 115200 baud rate. Here is an example invocation of the QSPY host application to receive the QS data from EK-TM4C123GXL: +``` qspy -cCOM1 +``` The actual COM port number might be different on your Windows machine. Please check the Device Manager to find the COM port number. diff --git a/uc-os2/arm-cm/dpp_ek-tm4c123gxl/ek-tm4c123gxl.webp b/uc-os2/arm-cm/dpp_ek-tm4c123gxl/ek-tm4c123gxl.webp new file mode 100644 index 0000000..320870b Binary files /dev/null and b/uc-os2/arm-cm/dpp_ek-tm4c123gxl/ek-tm4c123gxl.webp differ diff --git a/uc-os2/arm-cm/dpp_ek-tm4c123gxl/logo_ucos2.webp b/uc-os2/arm-cm/dpp_ek-tm4c123gxl/logo_ucos2.webp new file mode 100644 index 0000000..9470fdc Binary files /dev/null and b/uc-os2/arm-cm/dpp_ek-tm4c123gxl/logo_ucos2.webp differ diff --git a/zephyr/blinky/README.md b/zephyr/blinky/README.md index 2554d7d..ff4e318 100644 --- a/zephyr/blinky/README.md +++ b/zephyr/blinky/README.md @@ -1,14 +1,17 @@ -# Blinky example +# Blinky example for Zephyr -# Overview +

+ +

+# Overview Blinks an on-board LED once per second. The blinking is performed by an Active Object (Blinky) with a state machine. # Building and Running (Linux) -Open a terminal in the directory of this example (`qpcpp/examples/zephry/blinky`). +Open a terminal in the directory of this example (`qpc/examples/zephry/blinky`). Depending on your Zephyr installation, you might need to shell the script to configure Zephyr environment: @@ -37,7 +40,7 @@ west flash # Sample Output The application also produces ASCII output to the serial terminal -(if supported by the board): +(if suppoted by the board): ``` *** Booting Zephyr OS build v2.6.0-rc2-88-g3d39f72a88b3 *** diff --git a/zephyr/blinky/qp-zephyr.webp b/zephyr/blinky/qp-zephyr.webp new file mode 100644 index 0000000..a6d63f2 Binary files /dev/null and b/zephyr/blinky/qp-zephyr.webp differ diff --git a/zephyr/dpp/README.md b/zephyr/dpp/README.md index 4ba621c..2ad72e6 100644 --- a/zephyr/dpp/README.md +++ b/zephyr/dpp/README.md @@ -1,12 +1,16 @@ # DPP example +

+ +

+ + # Overview Dining Philosophers Problem (DPP) example with multiple active objects. - # Building and Running (Linux) -Open a terminal in the directory of this example (`qpcpp/examples/zephry/dpp`). +Open a terminal in the directory of this example (`qpc/examples/zephry/dpp`). Depending on your Zephyr installation, you might need to shell the script to configure Zephyr environment: diff --git a/zephyr/dpp/qp-zephyr.webp b/zephyr/dpp/qp-zephyr.webp new file mode 100644 index 0000000..a6d63f2 Binary files /dev/null and b/zephyr/dpp/qp-zephyr.webp differ