diff --git a/README.md b/README.md index 3083a0c7d..164e4f2e2 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,9 @@ obtaining QP/C++ bundled together like that is that you get all components, tools and examples ready to go. ### Getting Started Resources +- ["QP/C++ Tutorial"][Tutorial] +describes a series of progressively advanced QP/C++ example applications. + - [Video: "Getting Started with QP Real-Time Embedded Frameworks"][Video] provides instructions on how to download, install, and get started with QP. @@ -26,15 +29,6 @@ provides instructions on how to download, install, and get started with QP. contains also a tutorial, in which you build a simple "Blinky" application. -# Documentation -The online HTML documention for the **latest** version of QP/C++ is located -at: https://www.state-machine.com/qpcpp - -The offline HTML documentation for **this** particular version of QP/C++ -is located in the sub-folder [html](html). To view the offline documentation, -open the file [html/index.html](html/index.html) in your web browser. - - # About QP/C++ QP/C++ (Quantum Platform in C++) is a lightweight, open source [Real-Time Embedded Framework (RTEF)][RTEF] for building modern embedded @@ -104,7 +98,12 @@ you don't use any open source license and you do not violate your policy. # QP/C++ Documentation -The **QP/C++ Manual** is located online at: https://www.state-machine.com/qpcpp +The online HTML documention for the **latest** version of QP/C++ is located +at: https://www.state-machine.com/qpcpp + +The offline HTML documentation for **this** particular version of QP/C++ +is located in the sub-folder [html](html). To view the offline documentation, +open the file [html/index.html](html/index.html) in your web browser. # How to Get Help? @@ -125,4 +124,5 @@ The **QP/C++ Manual** is located online at: https://www.state-machine.com/qpcpp [Lic]: [Cust]: [AN]: + [Tutorial]: [Video]: diff --git a/doxygen/Doxyfile b/doxygen/Doxyfile index 55dd33c5e..53e32453d 100644 --- a/doxygen/Doxyfile +++ b/doxygen/Doxyfile @@ -120,14 +120,8 @@ WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- -INPUT = modules.dox \ - main.dox \ +INPUT = main.dox \ gs.dox \ - ../../cert-pack/srs.dox \ - ../../cert-pack/sas.dox \ - ../../cert-pack/sds.dox \ - ../../cert-pack/autosar.dox \ - api.dox \ exa.dox \ exa_native.dox \ exa_rtos.dox \ @@ -139,9 +133,15 @@ INPUT = modules.dox \ ports_arm-cm.dox \ ports_rtos.dox \ ports_os.dox \ - metrics.dox \ + api.dox \ history.dox \ - modules.dox \ + ../../ql-doxygen/help.dox \ + ../../cert-pack/srs.dox \ + ../../cert-pack/sas.dox \ + ../../cert-pack/sds.dox \ + ../../cert-pack/autosar.dox \ + ../../cert-pack/tr.dox \ + metrics.dox \ dir.dox \ macros.h \ ../include/qpc.hpp \ @@ -157,7 +157,9 @@ INPUT = modules.dox \ ../include/qs.hpp \ ../include \ ../src \ - ../../ql-doxygen/help.dox + ../ports/arm-cm/qv/gnu \ + ../ports/arm-cm/qk/gnu \ + ../ports/arm-cm/qxk/gnu INPUT_ENCODING = UTF-8 FILE_PATTERNS = *.dox \ @@ -170,7 +172,8 @@ FILE_PATTERNS = *.dox \ *.lnt RECURSIVE = YES -EXCLUDE = ../include/qs_dummy.h +EXCLUDE = ../include/qs_dummy.hpp \ + ../include/quit.hpp EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = diff --git a/doxygen/DoxygenLayout.xml b/doxygen/DoxygenLayout.xml new file mode 100644 index 000000000..2a44f75af --- /dev/null +++ b/doxygen/DoxygenLayout.xml @@ -0,0 +1,240 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doxygen/api.dox b/doxygen/api.dox index 8181ea458..46f4366f8 100644 --- a/doxygen/api.dox +++ b/doxygen/api.dox @@ -1,8 +1,8 @@ @namespace QP { /*! @page api API Reference - @tableofcontents +@nav_next{deprecated} @section api_qep QEP (Hierarchical State Machines) QEP is a universal, UML-compliant event processor that enables developers to code UML state machines in highly readable ANSI-C, in which every state machine element is mapped to code precisely, unambiguously, and exactly once (traceability). QEP fully supports hierarchical state nesting, which is the fundamental mechanism for reusing behavior across many states instead of repeating the same actions and transitions over and over again. @@ -21,7 +21,6 @@ QEP is a universal, UML-compliant event processor that enables developers to cod - QMsm::isInState() - QMsm::stateObj() - Q_STATE_CAST() -- Q_EVT_CAST() @section api_qf QF (Active Object Framework) @@ -52,13 +51,14 @@ QF is a portable, event-driven, real-time framework for execution of active obje - QActive::unsubscribeAll() -@subsection api_qf_evt Dynamic Events +@subsection api_qf_evt Event Management - QEvt class - Q_NEW() - Q_NEW_X() - Q_NEW_REF() - Q_DELETE_REF() - QF::gc() +- Q_EVT_CAST() @subsection api_qf_time Time Events @@ -92,7 +92,6 @@ QF is a portable, event-driven, real-time framework for execution of active obje - QMPool::put() - @section api_qs QS ("Quantum Spy" Software Tracing) QS is a software tracing system that enables developers to monitor live event-driven QP applications with minimal target system resources and without stopping or significantly slowing down the code. QS is an ideal tool for testing, troubleshooting, and optimizing QP applications. QS can even be used to support acceptance testing in product manufacturing. @@ -116,26 +115,22 @@ QS is a software tracing system that enables developers to monitor live event-dr @subsection api_qs_filter QS Filters -- QS_FILTER_ON() -- QS_FILTER_OFF() -- QS_FILTER_SM_OBJ() -- QS_FILTER_AO_OBJ() -- QS_FILTER_MP_OBJ() -- QS_FILTER_EQ_OBJ() -- QS_FILTER_TE_OBJ() +- QS_GLB_FILTER() +- QS_LOC_FILTER() - QS_FILTER_AP_OBJ() @subsection api_qs_dict QS Dictionaries - QS_SIG_DICTIONARY() - QS_OBJ_DICTIONARY() +- QS_OBJ_ARR_DICTIONARY() - QS_FUN_DICTIONARY() - QS_USR_DICTIONARY() @subsection api_qs_user QS Application-Specific Records - ::QS_USER enumeration -- QS_BEGIN() +- QS_BEGIN_ID() - QS_END() - QS_U8() / QS_I8() - QS_U16() / QS_I16() @@ -145,7 +140,6 @@ QS is a software tracing system that enables developers to monitor live event-dr - QS_MEM() - @section api_qv QV (Cooperative Kernel) QV is a simple **cooperative** kernel (previously called "Vanilla" kernel). This kernel executes active objects one at a time, with priority-based scheduling performed before processing of each event. Due to naturally short duration of event processing in state machines, the simple QV kernel is often adequate for many real-time systems. @@ -163,23 +157,18 @@ Given the simplicity, portability, and low-resource consumption, the QV schedule - QF_run() - QV::onIdle() - QV_CPU_SLEEP() -- QV::getVersion() - @section api_qk QK (Preemptive Run-to-Completion Kernel) QK is a tiny **preemptive**, priority-based, non-blocking kernel designed specifically for executing active objects. QK runs active objects in the same way as prioritized interrupt controller (such as NVIC in ARM Cortex-M) runs interrupts using the single stack. Active objects process their events in run-to-completion (RTC) fashion and remove themselves from the call stack, the same way as nested interrupts remove themselves from the stack upon completion. At the same time high-priority active objects can preempt lower-priority active objects, just like interrupts can preempt each other under a prioritized interrupt controller. QK meets all the requirement of the Rate Monotonic Scheduling (a.k.a. Rate Monotonic Analysis RMA) and can be used in hard real-time systems. - @subsection api_qk_ctrl Kernel Initialization and Control - QK_INIT() - QF_run() - QK::onIdle() - QK::schedLock() - QK::schedUnlock() -- QK::getVersion() - @subsection api_qk_isr Interrupt Management @@ -187,20 +176,16 @@ QK is a tiny **preemptive**, priority-based, non-blocking kernel designed specif - QK_ISR_EXIT() - @section api_qxk QXK (Preemptive Dual-Mode Run-to-Completion/Blocking RTOS Kernel) QXK is a small, preemptive, priority-based, dual-mode **blocking** kernel that executes active objects like the @ref qk "QK kernel", but can also execute traditional __blocking__ threads (extended threads). In this respect, QXK behaves exactly as a conventional __RTOS__ (Real-Time Operating System). QXK has been designed specifically for mixing event-driven active objects with traditional blocking code, such as commercial middleware (TCP/IP stacks, UDP stacks, embedded file systems, etc.) or legacy software. - @subsection api_qxk_ctrl Kernel Initialization and Control - QXK_INIT() - QF_run() - QXK::onIdle() - QXK::schedLock() - QXK::schedUnlock() -- QXK::getVersion() - @subsection api_qxk_isr Interrupt Management @@ -208,7 +193,6 @@ QXK is a small, preemptive, priority-based, dual-mode **blocking** kernel that e - QXK_ISR_EXIT() - @subsection api_qxk_xthr Extended Thread Management - QXThread class - QXThread::QXThread() @@ -217,7 +201,8 @@ QXK is a small, preemptive, priority-based, dual-mode **blocking** kernel that e - QXThread::delayCancel() - QXThread::queueGet() - Q_XTHREAD_CAST() - +- QXK_current() +- QXK_TLS() @subsection api_qxk_sema Semaphores @@ -228,7 +213,6 @@ QXK is a small, preemptive, priority-based, dual-mode **blocking** kernel that e - QXSemaphore::signal() - @subsection api_qxk_mutex Mutexes - QXMutex class (Mutex Control Block) - QXMutex::init() @@ -237,33 +221,20 @@ QXK is a small, preemptive, priority-based, dual-mode **blocking** kernel that e - QXMutex::unlock() - @subsection api_qxk_queue Message Queues - %QXThread:: POST() - %QXThread:: POST_X() - QXThread::queueGet() - waiting (blocking) on message queue - @subsection api_qxk_mem Memory Pools - QMPool class - QMPool::init() - QMPool::get() - QMPool::put() - - -@subsection api_qxk_tls Thread-Local Storage -- QXK_current() -- QXK_TLS() - - -@section api_dep Deprecated APIs - -See also the list of @subpage deprecated "deprecated QP/C++ APIs". - - -@next{deprecated} +
+@nav_next{deprecated} */ /*##########################################################################*/ /*! @page deprecated Deprecated APIs diff --git a/doxygen/exa.dox b/doxygen/exa.dox index f7b2692ff..b6904557e 100644 --- a/doxygen/exa.dox +++ b/doxygen/exa.dox @@ -1,5 +1,4 @@ /*! @page exa Examples - @tableofcontents @section exa_gen General Comments @@ -26,6 +25,8 @@ QP/C++ examples are located in sub-directories of the e
  • arm-cm/ — Native examples for ARM-Cortex-M (bare-metal)       A
    • +
    • blinky_ek-tm4c123gxl/ — Blinky example for EK-TM4C123GXL board +
    • dpp_ek-tm4c123gxl/ — DPP example for EK-TM4C123GXL board
    • qk/ — Version for the @ref comp_qk "preemptive QK kernel" @@ -191,7 +192,7 @@ QP/C++ examples are located in sub-directories of the e
    • A @subpage exa_native "Native examples" are located in sub-directories named after the CPU architecture, such as arm-cm for ARM Cortex-M. Under that directory, the sub-directories blinky_ek-tm4c123gxl contain the specific example on the specified board, such as "Blinky" on the EK-TM4C123GXL board here. In the specific example folder, you find sub-folders for the @ref comp_qv "QV", @ref comp_qk "QK" and @ref comp_qxk "QXK" kernels, respectively.
    • -
    • B @subpage exa_rtos "Examples for 3rd-party RTOS"/@ref exa_os "OS" are located in sub-directories named after the RTOS/OS, such as ucos-ii for uCOS-II RTOS. Under that directory, the sub-directories, such as arm-cm, contain examples for the specified CPU architecture, such as ARM Cortex-M here. +
    • B @subpage exa_rtos "Examples for 3rd-party RTOS"/@ref exa_os "OS" are located in sub-directories named after the RTOS/OS, such as uc-os2 for uc-os2 RTOS. Under that directory, the sub-directories, such as arm-cm, contain examples for the specified CPU architecture, such as ARM Cortex-M here.
    • C @subpage exa_mware "Examples for 3rd-party Middleware" are located in sub-directories named after the middleware, such as lwIP for the lwIP TCP/IP stack. Under that directory, the sub-directories, such as arm-cm, contain examples for the specified CPU architecture, such as ARM Cortex-M here. @@ -208,13 +209,12 @@ QP/C++ examples are located in sub-directories of the e Because the QP distribution contains *all* examples, the number of sub-directories and files in the examples folder may seem daunting. However, knowing the structure of the examples folder, you can simply ignore or even delete the sub-directories that are not interesting to you. - @subsection exa_sec_apps Example Applications To demonstrate QP/C++ features on an embedded board, you need to create an application that does "something interesting". Instead of inventing this "something interesting" for each and every example, the example projects implement one of the three @subpage exa_apps "example applications", which are described on the separate pages: -- @ref blinky -- @ref dpp -- @ref game +- @ref tut_blinky +- @ref tut_dpp +- @ref tut_game With the exception of the game application, all other example applications can be implemented on a board with just a couple of LEDs. The @ref game application is a bit more involved and requires a small graphic display on the board. @@ -222,17 +222,14 @@ Beyond these basic applications for demonstrating and testing the various @ref p @sa @ref exa_os - @subsection exa_sec_boards Development Boards While some provided examples can run on your @ref exa_os "desktop computer", most embedded example projects require special hardware in form of @ref exa_sec_boards, which you need to acquire to be able to run the examples. The boards chosen for the examples are generally inexpensive and self-contained with no need for external hardware (such as external JTAG debuggers or power supplies). - @subsection exa_sec_tools Development Tools Most provided examples require special embedded cross-development tools, such as embedded compilers, linkers, debuggers and IDEs, which you need to acquire independently from the QP/C++ distribution. Generally, the examples work with the free (size limited) evaluation versions of the commercial tools. The examples list the versions of tools they were developed and tested with. Please refer to the @ref exa_ref "cross-reference section" @ref exa_sec_tools to see which embedded toolchains are used. - @subsection exa_sec_conf Build Configurations QP examples @ref ports "QP ports" are provided in the following three **build configurations**: @@ -248,7 +245,6 @@ QP examples @ref ports "QP ports" are provided in the following three **build co The different phases of embedded software life cycle pose different challenges. During the development and maintenance phase, for example, the emphasis is on the ease of debugging and verifying the correctness of the code, which require lower levels of optimization and special scaffolding code. In contrast, for releasing the code in the final product, the emphasis is on small memory footprint and CPU time efficiency, which require high-level of optimization and removal of any scaffolding code. To address these conflicting needs, the same source code is compiled into multiple **build configurations** that differ in the use of compiler options and activation of the scaffolding code. - @subsection exa_sec_qm QM Models Many example projects contain code auto-generated by the QM modeling tool. Such projects always contain the corresponding **QM model** file, which you can open in QM, modify, and re-generate the code. @@ -256,7 +252,6 @@ Many example projects contain code auto-generated by the 3rd_party top-level folder. @@ -271,9 +266,7 @@ The Third-Party software components included in the 3rd sub-folders. - @subsection exa_own Creating your Own QP/C++ Projects - Perhaps the most important fact of life to remember is that in embedded systems nothing works until everything works. This means that you should always start with a working system and gradually evolve it, changing one thing at a time and making sure that it keeps working every step of the way. Keeping this in mind, the provided QP/C++ application examples, such as the super-simple Blinky, or a bit more advanced @ref dpp or @ref game, allow you to get started with a working project rather than starting from scratch. You should also always try one of the provided example projects on the same evaluation board that it was designed for, before making any changes. @@ -293,7 +286,6 @@ After copying the project folder, you still need to change the name of the proje By copying and re-naming an existing, working project, as opposed to creating a new one from scratch, you inherit the correct compiler and linker options an other project settings, which will help you get started much faster. - @subsection exa_doc Next Steps and Further Reading About QP and QM To work with QP/C++ effectively, you need to learn a bit more about active objects and state machines. Below is a list of links to enable you to further your knowledge: @@ -301,8 +293,8 @@ To work with QP/C++ effectively, you need to learn a bit more about active objec 1. The book “Practical UML Statecharts in C/C++, 2nd Edition” [PSiCC2] and the companion web-page to the book (https://www.state-machine.com/psicc2/ 2. Free Support Forum for QP/QM (https://sourceforge.net/p/qpc/discussion/668726 ) 3. QP Code Downloads summary (https://www.state-machine.com/#Downloads ) -4. QP Application Notes (https://www.state-machine.com/doc/an ) -5. "State Space" Blog (https://embeddedgurus.com/state-space/ ) +4. QP Application Notes (https://www.state-machine.com/an/ ) +5. "State Space" Blog (https://www.state-machine.com/category/blog/ ) @next{exa_ref} */ @@ -313,39 +305,30 @@ To work with QP/C++ effectively, you need to learn a bit more about active objec @tableofcontents - @section exa_ref_kernel Native Examples (by Built-in Kernel) - @ref exa_qv - @ref exa_qk - @ref exa_qxk - @section exa_ref_tool Native Examples (by Development Toolchain) @n -@subsection exa_ref_arm-keil ARM-Keil Toolchain (ARM Compiler 5) -- @ref arm-cm_blinky_ek-tm4c123gxl   (Cortex-M4) +@subsection exa_ref_arm-clang ARM-Clang Toolchain (ARM Compiler 6) - @ref arm-cm_blinky_efm32-slstk3401a   (Cortex-M4) - @ref arm-cm_dpp_ek-tm4c123gxl   (Cortex-M4) - @ref arm-cm_dpp_efm32-slstk3401a   (Cortex-M4) - @ref arm-cm_dpp_mbed-lpc1768   (Cortex-M4) -- @ref arm-cm_dpp_nucleo-l053r8   (Cortex-M0+) -- @ref arm-cm_dpp_nucleo-l152re   (Cortex-M3) +- @ref arm-cm_dpp_nucleo-l053r8   (Cortex-M0+) +- @ref arm-cm_dpp_nucleo-l152re   (Cortex-M3) - @ref arm-cm_game_efm32-slstk3401a   (Cortex-M4) - @ref arm-cm_dpp_stm32f4-discovery -- @ref arm-cm_dpp_stm32f746g-disco   (Cortex-M7) - - -@subsection exa_ref_arm-clang ARM-Clang Toolchain (ARM Compiler 6) -- @ref arm-cm_dpp_nucleo-l053r8   (Cortex-M0+) +- @ref arm-cm_dpp_nucleo-l053r8   (Cortex-M0+) - @ref arm-cm_dpp_efm32-slstk3401a   (Cortex-M4) -- @ref arm-cm_dpp_stm32f746g-disco   (Cortex-M7) - @ref arm-cm_dpp_nucleo-h743zi   (Cortex-M7) - @subsection exa_ref_gnu-arm GNU-ARM (command-line with Makefile, importable to Eclipse) - @ref arm-cm_blinky_ek-tm4c123gxl   (Cortex-M4) - @ref arm-cm_blinky_efm32-slstk3401a   (Cortex-M4) @@ -356,17 +339,14 @@ To work with QP/C++ effectively, you need to learn a bit more about active objec - @ref arm-cm_dpp_nucleo-l152re   (Cortex-M3) - @ref arm-cm_game_efm32-slstk3401a   (Cortex-M4) - @ref arm-cm_dpp_stm32f4-discovery -- @ref arm-cm_dpp_stm32f746g-disco   (Cortex-M7) - @ref lwip_ek-lm3s6965   (Cortex-M3) - @ref arm7-9_dpp_at91sam7s-ek   (ARM7TDMI) - @subsection exa_ref_gnu-ccs GNU-ARM with TI CCS IDE - @ref arm-cm_dpp_ek-tm4c123gxl   (Cortex-M4) - @subsection exa_ref_iar-arm IAR EWARM - @ref arm-cm_blinky_ek-tm4c123gxl   (Cortex-M4) - @ref arm-cm_blinky_efm32-slstk3401a   (Cortex-M4) @@ -376,26 +356,22 @@ To work with QP/C++ effectively, you need to learn a bit more about active objec - @ref arm-cm_dpp_nucleo-l053r8   (Cortex-M0+) - @ref arm-cm_dpp_nucleo-l152re   (Cortex-M3) - @ref arm-cm_game_efm32-slstk3401a   (Cortex-M4) -- @ref arm-cm_dpp_stm32f746g-disco   (Cortex-M7) - @ref arm-cr_blinky_launchxl2-tms57012   (Cortex-R4) - @ref arm-cr_dpp_launchxl2-tms57012   (Cortex-R4) - @ref lwip_ek-lm3s6965   (Cortex-M3) - @ref arm7-9_dpp_at91sam7s-ek   (ARM7TDMI) - @subsection exa_ref_ccs-430 CCS for MSP430 - @ref msp430_blinky_msp-exp430f5529lp - @ref msp430_dpp_msp-exp430f5529lp - @subsection exa_ref_iar-430 IAR EW430 - @ref msp430_blinky_msp-exp430f5529lp - @ref msp430_dpp_msp-exp430f5529lp - @section exa_ref_native Native Examples (by Processor) - @ref exa_arm-cm - @ref exa_arm-cr @@ -403,13 +379,11 @@ To work with QP/C++ effectively, you need to learn a bit more about active objec - @ref exa_msp430 ("classic" MSP430 and "extended" MSP430x) - @section exa_ref_rtos Examples for Third-Party RTOS - @ref exa_embos (SEGGER) - @ref exa_freertos (Amazon Web Services) - @ref exa_threadx (Express Logic) -- @ref exa_ucos-ii (Micrium/SiLabs) - +- @ref exa_uc-os2 (Micrium/SiLabs) @section exa_ref_os Examples for Workstations (Windows, Linux, MacOS) @@ -427,7 +401,6 @@ The examples in the "workstation" directory are designed for workstations (runni - @ref exa_emwin (SEGGER, a.k.a. uC/GUI by Micrium) - @section exa_ref_boards Examples by Development Board The boards chosen for the examples are generally inexpensive and self-contained with minimal need for external hardware (such as external JTAG debuggers or power supplies). Also, all the selected boards provide a virtual COM port (ideally) or can be easily connected to a TTL-to-USB serial converter cable for @ref comp_qs "QS software tracing" output. @@ -435,7 +408,6 @@ The boards chosen for the examples are generally inexpensive and self-contained You can hover the mouse cursor over the    icon in the list below to see the picture of the board. - @subsection exa_ref_arm-cm ARM Cortex-M Boards @anchor EK-TM4C123GXL @@ -446,8 +418,7 @@ You can hover the mouse cursor over the    - @ref freertos_dpp_ek-tm4c123gxl (FreeRTOS kernel; ARM-KEIL, GNU-ARM, IAR-EWARM toolchains) - @ref freertos_dpp_nucleo-h743zi (FreeRTOS kernel; ARM-KEIL, GNU-ARM, IAR-EWARM toolchains) - @ref threadx_dpp_ek-tm4c123gxl (ThreadX kernel; IAR-EWARM toolchain) -- @ref ucos-ii_dpp_ek-tm4c123gxl (uC/OS-II kernel; ARM-KEIL, GNU-ARM, IAR-EWARM toolchains) - +- @ref uc-os2_dpp_ek-tm4c123gxl (uC/OS-II kernel; ARM-KEIL, GNU-ARM, IAR-EWARM toolchains) @anchor EFM32-SLSTK3401A @@ -457,24 +428,20 @@ You can hover the mouse cursor over the    - @ref arm-cm_game_efm32-slstk3401a (QV, QK kernels; ARM-KEIL, GNU-ARM, IAR-EWARM toolchains; QWin-GUI emulation) - @anchor mbed-LPC1768 ![mbed-LPC1768](bd_mbed-LPC1768.jpg) - @ref arm-cm_dpp_mbed-lpc1768 (QV, QK kernels; ARM-KEIL, GNU-ARM, IAR-EWARM toolchains) - @anchor NUCLEO-L053R8 ![NUCLEO-L053R8](bd_NUCLEO-L053R8.jpg) - @ref arm-cm_dpp_nucleo-l053r8 (QV, QK, QXK kernels; ARM-KEIL, GNU-ARM, IAR-EWARM toolchains) - @anchor NUCLEO-L152RE ![NUCLEO-L152RE](bd_NUCLEO-L152RE.jpg) - @ref arm-cm_dpp_nucleo-l152re (QV, QK kernels; ARM-KEIL, GNU-ARM, IAR-EWARM toolchains) -- @ref ucos-ii_dpp_nucleo-l053r8 (uC/OS-II kernel; ARM-KEIL, IAR-EWARM toolchains) - +- @ref uc-os2_dpp_nucleo-l053r8 (uC/OS-II kernel; ARM-KEIL, IAR-EWARM toolchains) @anchor exa_EK-LM3S6965 @@ -482,14 +449,12 @@ You can hover the mouse cursor over the    - @ref lwip_ek-lm3s6965 (**LwIP TCP/IP**; QV, QK kernels; ARM-KEIL, GNU-ARM, IAR-EWARM toolchains) - @anchor NUCLEO-H743ZI ![NUCLEO-H743ZI](bd_NUCLEO-H743ZI.jpg) - @ref arm-cm_dpp_nucleo-h743zi (QV, QK, QXK kernels; ARM-KEIL, GNU-ARM, IAR-EWARM toolchains) - @ref freertos_dpp_nucleo-h743zi (FreeRTOS kernel; ARM-KEIL, GNU-ARM, IAR-EWARM toolchains) - @anchor STM32F4-Discovery ![STM32F4-Discovery](bd_STM32F4-Discovery.jpg) - @ref arm-cm_dpp_stm32f4-discovery (QV, QK, QXK kernels; ARM-KEIL, GNU-ARM, IAR-EWARM toolchains) @@ -497,14 +462,12 @@ You can hover the mouse cursor over the    - @ref threadx_dpp_stm32f429-discovery (ThreadX kernel; IAR-EWARM toolchain) - @anchor STM32F746G-Discovery ![STM32F746G-Discovery](bd_STM32F746G-Disco.jpg) - @ref arm-cm_dpp_stm32f746g-disco (QV, QK, QXK kernels; ARM-KEIL, GNU-ARM, IAR-EWARM toolchains) - @ref freertos_dpp_stm32f746g-disco (FreeRTOS kernel; ARM-KEIL, GNU-ARM, IAR-EWARM toolchains) - @subsection exa_ref_arm-cr ARM Cortex-R Boards: @anchor LAUNCHXL2-TMS57012 ![LAUNCHXL2-TMS57012](bd_LAUNCHXL2-TMS57012.jpg) @@ -512,14 +475,12 @@ You can hover the mouse cursor over the    - @ref arm-cr_dpp_launchxl2-tms57012 (QV, QK kernels; CCS-TI-ARM, IAR-EWARM toolchains) - @subsection exa_ref_arm7-9 ARM7 Boards: @anchor AT91SAM7S-EK ![AT91SAM7S-EK](bd_AT91SAM7S-EK.jpg) - @ref arm7-9_dpp_at91sam7s-ek (QV, QK kernels; IAR-EWARM toolchains) - @subsection exa_ref_msp430 MSP430 Boards: @anchor MSP-EXP430F5529LP ![MSP-EXP430F5529LP](bd_MSP-EXP430F5529LP.jpg) @@ -527,8 +488,6 @@ You can hover the mouse cursor over the    - @ref msp430_dpp_msp-exp430f5529lp (QV, QK kernels; CCS=430, IAR-EW430 toolchains) - - @section exa_ref_mcu Examples by MCU Architecture - ARM Cortex-M0/M0+ - @ref arm-cm_dpp_nucleo-l053r8 @@ -557,8 +516,6 @@ You can hover the mouse cursor over the    - @ref msp430_blinky_msp-exp430f5529lp - @ref msp430_dpp_msp-exp430f5529lp - - @section exa_ref_vendor Examples by MCU Vendor - Atmel - @ref arm7-9_dpp_at91sam7s-ek diff --git a/doxygen/exa_rtos.dox b/doxygen/exa_rtos.dox index 8b3ab2a58..c0af7d778 100644 --- a/doxygen/exa_rtos.dox +++ b/doxygen/exa_rtos.dox @@ -8,7 +8,7 @@ The main purpose of integrating QP/C++ with conventional RTOSes is to enable you - @subpage exa_embos (directory examples/embos/) - @subpage exa_freertos (directory examples/freertos/) - @subpage exa_threadx (directory examples/threadx/) -- @subpage exa_ucos-ii (directory examples/ucos-ii/) +- @subpage exa_uc-os2 (directory examples/uc-os2/) @note You do **not** need to use a third-party RTOS just to achieve preemptive multitasking with QP/C++. The framework contains a selection of built-in real-time kernels, such as the cooperative @ref qv "QV kernel", the preemptive non-blocking @ref qk "QK kernel", and the preemptive, dual-mode, blocking @ref qxk "QXK kernel". Specifically, the QXK kernel has been designed specifically for mixing event-driven active objects with traditional **blocking code**, such as commercial middleware (TCP/IP stacks, UDP stacks, embedded file systems, etc.) or legacy software. @@ -234,7 +234,7 @@ The QP/C++ examples for ThreadX (Express Logic) are as follows: @note You can hover the mouse cursor over the    icon in the list below to see the picture of the board. -@next{exa_ucos-ii examples} +@next{exa_uc-os2 examples} */ /*##########################################################################*/ /*! @page threadx_dpp_ek-tm4c123gxl DPP on EK-TM4C123GXL @@ -290,17 +290,17 @@ 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. -@next{exa_ucos-ii examples} +@next{exa_uc-os2 examples} */ /*##########################################################################*/ -/*! @page exa_ucos-ii uC/OS-II +/*! @page exa_uc-os2 uC/OS-II The QP/C++ examples for uC/OS-II are as follows: - ARM Cortex-M - - @subpage ucos-ii_dpp_ek-tm4c123gxl (Cortex-M4F)
      (ARM-CLANG, GNU-ARM and IAR EWARM toolsets) - - @subpage ucos-ii_dpp_nucleo-l053r8 (Cortex-M0+)
      (ARM-CLANG, GNU-ARM, and IAR EWARM toolsets) + - @subpage uc-os2_dpp_ek-tm4c123gxl (Cortex-M4F)
      (ARM-CLANG, GNU-ARM and IAR EWARM toolsets) + - @subpage uc-os2_dpp_nucleo-l053r8 (Cortex-M0+)
      (ARM-CLANG, GNU-ARM, and IAR EWARM toolsets) @note You can hover the mouse cursor over the    icon in the list below to see the picture of the board. @@ -308,7 +308,7 @@ You can hover the mouse cursor over the    @next{exa_os examples} */ /*##########################################################################*/ -/*! @page ucos-ii_dpp_ek-tm4c123gxl DPP on EK-TM4C123GXL +/*! @page uc-os2_dpp_ek-tm4c123gxl DPP on EK-TM4C123GXL @image html bd_EK-TM4C123GXL.jpg "EK-TM4C123GXL board" @@ -316,10 +316,10 @@ DPP example for Texas Instruments TivaC123GXL MCU (Cortex-M4F) and ARM-CLANG, GN @image html under_construction.jpg -@next{ucos-ii_dpp_nucleo-l053r8 examples} +@next{uc-os2_dpp_nucleo-l053r8 examples} */ /*##########################################################################*/ -/*! @page ucos-ii_dpp_nucleo-l053r8 DPP on STM32-NUCLEO-L053R8 +/*! @page uc-os2_dpp_nucleo-l053r8 DPP on STM32-NUCLEO-L053R8 @image html bd_NUCLEO-L053R8.jpg "STM32-NUCLEO-L053R8 board" diff --git a/doxygen/gs.dox b/doxygen/gs.dox index 9d5a11712..42c00b004 100644 --- a/doxygen/gs.dox +++ b/doxygen/gs.dox @@ -1,28 +1,502 @@ /*! @page gs Getting Started +@nav{index,gs_get} + +The following sections describe how to get started with QP™/C++ quickly: +- @subpage gs_get +- @subpage gs_over +- @subpage gs_tut + +The YouTube Video Getting Started with QP™ Frameworks provides instructions on how to download, install and get started with QP quickly. + +[![Video: Getting Started with QP™ Real-Time Embedded Framework](gs-video.jpg)](https://youtu.be/O7ER6_VqIH0) + +@nav{index,gs_get} +*/ +/*##########################################################################*/ +/*! @page gs_get Downloading & Installing QP™/C++ @tableofcontents -@nav{index,struct} +@nav{gs,gs_tut} -@section gs_obtain Downloading & Installing QP™/C++ -The most recommended way of obtaining QP/C++™ is by downloading the @webref{#Downloads, QP-bundle™}, which includes QP™/C++ as well as other QP™ frameworks and also the @webref{products/qm, QM™ modeling tool} and the @webref{products/qtools, QTools™ collection}. The main advantage of obtaining QP™/C++ bundled together like that is that you get all components, tools and examples ready to go. +@section gs_bundle Downloading QP™/C++ in QP™-Bundle +The most recommended way of obtaining QP™/C++ is by downloading the @webref{#Downloads, QP-bundle™}, which includes QP™/C++ as well as other QP™ frameworks and also the @webref{products/qm, QM™ modeling tool} and the @webref{products/qtools, QTools™ collection}. The main advantage of obtaining QP™/C++ bundled together like that is that you get all components, tools and examples ready to go. [![QP-bundle Downloads](qp-bundle.png)](https://www.state-machine.com/#Downloads) @note - -GitHub QP™/C++ repository -If you are allergic to installers and GUIs or don't have administrator privileges you can also **download and install QP™/C++ separately** from the QP™/C++ GitHub repository. + +If you are allergic to installers and GUIs or don't have administrator privileges you can also **download and install QP™/C++ separately** from the QP™/C++ GitHub repository, as described in the next section. -@section gs_video Getting Started with QP™ Video -The YouTube Video Getting Started with QP™ Frameworks provides instructions on how to download, install and get started with QP quickly. +@section gs_gh Downloading QP™/C++ from GitHub +Go to the QP™/C++ release page on GitHub, and choose the QP™/C++ version number you wish to download. You should select the latest QP™/C++ version, unless you have a very specific reason to go with an older release. + +![QP™/C++ downloads from GitHub](qpcpp_gh.jpg) + + +@section gs_dir QP™/C++ Installation Folder +The following annotated directory tree lists the top-level directories provided in the standard QP™/C++ distribution. + +
        +
      • qpcpp/ +
      • +
          +
        • 3rd_party/ — 3rd-Party code used in the @ref exa "QP™/C++ Examples" +
        • +
        • examples/ — @ref exa "QP™/C++ Examples" +
        • +
        • ports/ — @ref ports "QP™/C++ Ports" +
        • +
        • @ref /qp-dev/qpcpp/include "include/" — Platform-independent QP™/C++ API, see also @ref api +
        • +
        • @ref /qp-dev/qpcpp/src "src/" — Platform-independent QP™/C++ source code +
        • +
        +
      + +@attention +The QP/C++ GitHub repository does not contain the `3rd_party` folder, which is needed to build the @ref exa "QP™/C++ Examples". Therefore, it is highly **recommended** to download the latest [QP/C++ Release](https://github.com/QuantumLeaps/qpcpp/releases) as opposed to cloning the repo directly. + +@remark +The standard QP™/C++ distribution contains the `examples` folder with many @ref exa "Example Projects", which are specifically designed to help you learn to use QP™/C++ and to serve you as starting points for your own projects. + +
      +@nav{gs,gs_tut} +*/ +/*##########################################################################*/ +/*! @page gs_tut QP™/C++ Tutorial +@tableofcontents +@nav{gs_over,tut_blinky} + +This Tutorial describes how to use the QP/C++™ real-time embedded framework in a series of progressively advancing examples. The first example ("Blinky") uses only one Active Object with a simple non-hierarchical state machine. The following example ("DPP") demonstrates multiple, communicating Active Objects. Finally, the last example ("Fly'n'Shoot" game) demonstrates all features the QP™ framework. It is highly recommended to study the simpler examples before the more advanced ones, as the basic information won't be repeated in the later examples. + +This Tutorial consists of the following lessons: +- @subpage tut_blinky +- @subpage tut_dpp +- @subpage tut_game +- @subpage tut_low + +@remark +Perhaps the most important fact of life to remember is that in embedded systems nothing works until everything works. This means that you should always start with a *working* system and *gradually* evolve it, changing one thing at a time and making sure that it keeps *working* every step of the way.
      +
      +Keeping this in mind, the provided @ref exa "QP™/C++ application examples", such as the super-simple Blinky, or a bit more advanced DPP or “Fly 'n' Shoot” game, allow you to get started with a working project rather than starting from scratch. You should also always try one of the provided example projects on the same evaluation board that it was designed for, before making any changes. + + +Only after convincing yourself that the example project works "as is", you can think about creating your own projects. At this point, the easiest and recommended way is to copy the existing working example project folder (such as the Blinky example) and rename it. + +After copying the project folder, you still need to change the name of the project/workspace. The easiest and safest way to do this is to open the project/workspace in the corresponding IDE and use the Save As... option to save the project under a different name. (You can do this also with the @webref{products/qm, QM model file}, which you can open in QM and "Save As" a different model.) + +@note +By copying and re-naming an existing, working project, as opposed to creating a new one from scratch, you inherit the correct compiler and linker options an other project settings, which will help you get started much faster. + +
      +@nav{gs_over,tut_blinky} +*/ +/*##########################################################################*/ +/*! @page tut_blinky Simple Blinky Application +@tableofcontents +@nav{gs_tut,tut_dpp} + +The ultra-simple Blinky example is the embedded systems' equivalent of the venerable "Hello World!" program, that is, the simplest possible working QP™ application that does "something". In the case of Blinky, this "something" is blinking an LED at the rate of 1Hz, where an LED turns on and remains on for 0.5 seconds on then turns off and remains off for 0.5 seconds. + +![Blinky on EK-TM4C123GLX (TivaC LaunchPad)](blinky_ek-tm4c123gxl.gif) + +@note +The Blinky example is provided for other supported boards as well, not just TivaC LaunchPad. Please look for examples named dpp_ in the @ref exa "qpcpp/examples/examples" directory (e.g., `qpcpp/examples/arm-cm/blinky_ek-tm4c123gxl` for the EK-TM4C123GXL board (TivaC LaunchPad)). + + +The ultra-simple Blinky application, which consists of just one active object named `Blinky`, is intentionally kept small and illustrates only the most basic QP features, such as: + +- a simple Blinky active object (AO) @ref oop "class"; +- hand-coding the simple state machine of the Blinky AO; +- using a periodic time event; +- initializing the QP™ framework; +- starting an active object; and +- transferring control to QP™ to run the application. + +The details of the Blinky application are describe in the Quantum Leaps Application Note @webref{doc/AN_Getting_Started_with_QP.pdf, Getting Started with QP™ Real-Time Embedded Frameworks}. + +[![Application Note: Getting Started with QP™](AN-getting_started.jpg)](https://www.state-machine.com/doc/AN_Getting_Started_with_QP.pdf) + +
      +@nav{gs_tut,tut_dpp} +*/ +/*##########################################################################*/ +/*! @page tut_dpp Dining Philosophers Problem (DPP) +@tableofcontents +@nav{tut_blinky,tut_game} + +The Dining Philosophers Problem (DPP) example is an intermediate-level application with *multiple* active objects. It illustrates the following QP™ features, such as: + +- multiple active objects, including an array of active objects; +- designing the simple state machines in the QM tool and generating the code automatically (can be also done manually); +- using multiple periodic time events; +- using mutable events with parameters; +- direct event posting to active objects; +- publish-subscribe event delivery; +- initializing the QP™ framework; +- starting multiple active objects; and +- transferring control to QP™ to run the application. + +@note +The DPP example is provided for most supported boards as well as in the command-line version (on the host). Please look for examples named dpp_ in the @ref exa "qpcpp/examples/examples" directory (e.g., `qpcpp/examples/arm-cm/dpp_ek-tm4c123gxl` for the EK-TM4C123GXL board (TivaC LaunchPad)). + +The Dining Philosophers Problem (DPP) example is described in the @webref{doc/AN_DPP.pdf, Application Note: Dining Philosophers Problem (DPP) Example}. + +[![Application Note: Dining Philosophers Problem (DPP) Example](AN_DPP.jpg)](https://www.state-machine.com/doc/AN_Fly-n-Shoot.pdf) + + +@note +There is also a DPP variant that implements the "Philosophers" as passive "Orthogonal Components" of the "Table" active object. That DPP version is located in qpcpp/examples/examples/workstation/dpp-comp/ + +
      +@nav{tut_blinky,tut_game} +*/ +/*##########################################################################*/ +/*! @page tut_game "Fly 'n' Shoot" Game +@nav{tut_dpp,tut_low} + +The "Fly 'n' shoot" game example is a moderately advanced application of a vintage computer game. It requires a LCD screen and push-buttons on the board. + +![EFM32 Pearl-Gecko board](bd_EFM32-SLSTK3401A.jpg) + +"Fly 'n' shoot" game and illustrates the following QP™ features, such as: + +- multiple active objects; +- multiple passive state machines ("Orthogonal Components"); +- multiple periodic time events; +- mutable events with parameters; +- direct event posting to active objects; +- publish-subscribe event delivery; +- developing of embedded software on Windows (see also @webref{qtools/qwin.html,QWin™ GUI Prototyping Toolkit}) + +!["Fly 'n' Shoot" game running on Windows](qwin_ani.gif) + +The "Fly 'n' Shoot" game example is described in the @webref{doc/AN_Fly-n-Shoot.pdf, Application Note: Fly 'n' Shoot Game Example}. + + +[![Application Note: Fly 'n' Shoot Game Example](AN-game.jpg)](https://www.state-machine.com/doc/AN_Fly-n-Shoot.pdf) + + +[!["Fly'n'Shoot" game tutorial video](game-video.jpg)](https://youtu.be/h_u92uLssDo) + +
      +@nav{tut_dpp,tut_low} +*/ +/*##########################################################################*/ +/*! @page tut_low Low-Power Example +@tableofcontents +@nav{tut_game,exa} + +The main principle of low-power design for software is to keep the hardware in the most appropriate low-power sleep mode for as long as possible. Most commonly, the software enters a low-power sleep mode from the **idle callback** (a.k.a. "idle hook"), which is called when the software has nothing left to do and is waiting for an interrupt to deliver more work. The QP/C++ and QP/C++ Real-Time Embedded Frameworks (RTEFs) support the *idle callback* in all of the built-in real-time kernels, such as the cooperative @ref srs_qv "QV kernel", the preemptive non-blocking @ref srs_qk "QK kernel" and the preemptive blocking @ref srs_qxk "QXK kernel". Also, such an *idle callback* is provided in all 3rd-party traditional RTOS kernels that QP/C/C++ have been @ref ports_rtos "ported to". + +@remark +Design for low-power is a broad subject that requires a holistic system approach to achieve a really long battery-powered operation. This example covers only certain *software-related* aspects of the problem. + + +@section arm-cm_low_power_tick The System Clock Tick +Most real-time systems, including traditional RTOSes and RTEFs, require a periodic time +source called the **system clock tick** to keep track of time delays, timeouts, and QP::QTimeEvt "time events" in case of the event-driven QP frameworks. The system clock tick is typically a periodic +interrupt that occurs at a predetermined rate, typically between 10Hz and 1000Hz. + +While the system clock tick is very useful, it also has the unfortunate side effect of taking the processor out of a low power state as many as 1000 times per second regardless if real work needs to be done or not. This effect can have a significant negative impact on the power efficiency of the system. + +![Additional power dissipation caused by the system clock tick](exa_low-power_tick.gif) + + +@subsection arm-cm_low_power_tickless The "Tickless Mode" +Some real-time kernels use the low-power optimization called the "tickless mode" (a.k.a. "tick supression" or "dynamic tick"). In this mode, instead of indiscriminately making the clock tick fire with a fixed period, the kernel adjusts the clock ticks *dynamically*, as needed. Specifically, after each clock tick the kernel re-calculates the time for the next clock tick and then sets the clock tick interrupt for the earliest timeout it has to wait for. So for example, if the shortest wait the kernel has to attend to is 300 milliseconds into the future, then the clock interrupt will be set for 300 milliseconds. + +This approach maximizes the amount of time the processor can remain asleep, but requires the kernel to perform the additional work to calculate the dynamic tick intervals and to program them into the hardware. This additional bookkeeping adds complexity to the kernel, is often non-deterministic and, most importantly, extends the time CPU spends in the high-power active mode and thus eliminates some of the power gains the "tickless mode" was supposed to bring. + +Also, the "tickless mode" requires a more capable hardware timer that must be able of being reprogrammed for every interrupt in a wide dynamic range and also must accurately keep track of the elapsed time to correct for the irregular (dynamic) tick intervals. Still, "tickless mode" often causes a drift in the timing of the clock tick. + + +@subsection arm-cm_low_power_multiple Multiple Tick Rates +For the reasons just mentioned, the QP™ Real-Time Embedded Frameworks don't provide the "tickless mode". Instead, the QP™ frameworks support **multiple clock tick rates**, which can be turned on and off, as needed. The QP™ frameworks also provide methods for finding out *when* a given clock tick rate is not used, which allows the idle callback inside the application to shut down the given clock tick rate and also to decide which sleep mode to use for the CPU and the peripherals. + +The support for multiple static clock tick rates is much *simpler* than the "dynamic tick", and essentially does not increase the complexity of the kernel (because the same code for the single tick rate can handle other tick rates the same way). Also, multiple static tick rates require much simpler hardware timers, which can be clocked specifically to the desired frequency and don't need particularly wide dynamic range. For example, 16-bit timers or even 8-bit timers are completely adequate. + +Yet the *multiple clock rates* can deliver similar low-power operation for the system, while keeping the QP framework much simpler and easier to certify than "tickless" kernels. The rest of this example explains how to use the multiple static clock rates in QP/C/C++ and shows how to leverage this feature to achieve low-power software design. + + +@section arm-cm_low_power_app The Low-Power Example Application +The low-power example is located in QP/C and QP/C++ distributions, in the directory with the following structure: + +@code{.c} + 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 cooperative 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 +@endcode + + +@note +To focus the discussion, this example uses the **EK-TM4C123GXL** evaluation board (a.k.a. TivaC LaunchPad) with Cortex-M4 MCU. However, the general demonstrated principles apply to most modern microcontrollers. + +
      +![EK-TM4C123GXL evaluation board](bd_EK-TM4C123GXL_pins.jpg) + +@subsection arm-cm_low_power_behave 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{.c} +/* The following ticks-per-second constants determine the speed of the app. +* The default (#if 1) is the SLOW speed for humans to see the blinking. +* Change the #if 1 into #if 0 for FAST speed appropriate for logic analyzers. +*/ +#if 0 + #define BSP_TICKS0_PER_SEC 2U + #define BSP_TICKS1_PER_SEC 20U +#else + #define BSP_TICKS0_PER_SEC 200U + #define BSP_TICKS1_PER_SEC 2000U +#endif + +. . . +@endcode + +The following logic analyzer trace shows the behavior of the low-power application at the faster time scale. The explanation section immediately following the tarce explains the most interesting points: + +![low-power application after pressing the SW1 button](exa_low-power_sig.png) + +
      +
      0
      +The plot shows the logic-analyzer traces of the following signals (from the top): **SW1** button (active low), **Blinky1** (Blue-LED), **Blinky0** (Green-LED) and **Idle** (Red-LED). The Idle callback turns the **Red-LED** on when the system enters the low-power sleep mode and it turns the **Red-LED** off when the system is active. +
      +
      1
      +At this time the **SW1** button is depressed, which triggers an interrupt that activates both the slow and the fast clock tick rates. The clock tick interrupts trigger toggling of the **Blinky0** (Green-LED) at the slower tick rate-0 and **Blinky1** (Blue-LED) at the faster tick rate-1. +
      +
      2
      +The **Blinky1** (Blue-LED) stops toggling after 13 cycles. At this point also the **Idle** callback turns the **fast tick rate-1** off. +
      +
      3
      +The **Blinky0** (Green-LED) stops toggling after 4 cycles. +
      +
      4
      +The **Idle** callback turns the **slow tick rate-0** off. The system enters the low-power sleep mode without any clock ticks running and remains in this state until the **SW1** button is pressed again. +
      +
      +
      + +@note +The **Idle** line (Red-LED) goes down twice as fast as the changes in the state of the **Green-LED** or the **Blue-LED**. This is because the application uses timeouts of **2 clock ticks** for toggling these lines instead of just one clock tick, which then could be slower. This is not quite optimal for the energy dissipation (as the CPU is woken up twice as often as it needs to be), but it illustrates more accurately how the fixed clock rates work as well as the one-tick delay to enter the low-power sleep mode from the idle callback. + + +@subsection arm-cm_low_power_sm State Machines +The versions of this low-power example for the **QK** and **QV** kernels use two active objects **Blinky0** and **Blinky1**, which toggle the **Green-LED** at the slow tick rate 0, and the **Blue-LED** at the fast tick rate 1, respectively. The state machines of the Blinky0 and Blinky1 active objects are shown below: + +![state machines Blinky0 and Blinky1 active objects](exa_low-power_sm.png) + +
      +
      0
      +The **Blinky0** state machine, in the entry action to the "active" state, calls `BSP_tickRate0_on()` to turn the tick rate-0 on. This is done *before* arming the time event `me->timeEvt0` that uses the clock rate-0. +
      +
      1
      +Similarly, the **Blinky1** state machine, in the entry action to the "active" state, calls `BSP_tickRate1_on()` to turn the tick rate-1 on. This is done *before* arming the time event `me->timeEvt1` that uses the clock rate-1. +
      +
      +
      + + +@subsection arm-cm_low_power_xt Extended Thread (QXK) +The version of this low-power example for the **QXK** kernel uses one active object **Blinky0** (with the state machine shown above), but instead of the Blinky1 active object, the QXK version uses an eXtended thread (::QXThread) called **XBlinky1**, with the code shown below: + +@code{.cpp} + #include "qpcpp.hpp" + #include "low_power.hpp" + #include "bsp.hpp" + + /* local objects -----------------------------------------------------------*/ + static void XBlinky1_run(QXThread * const me); + + /* global objects ----------------------------------------------------------*/ + QXThread XT_Blinky1; + QXSemaphore XSEM_sw1; + + /*..........................................................................*/ + void XBlinky1_ctor(void) { + QXThread_ctor(&XT_Blinky1, + &XBlinky1_run, /* thread routine */ + 1U); /* associate the thread with tick rate-1 */ + } + + /*..........................................................................*/ + static void XBlinky1_run(QXThread * const me) { + bool isActive = false; + + (void)me; /* unused parameter */ + for (;;) { + if (!isActive) { +[0] QXSemaphore_wait(&XSEM_sw1, QXTHREAD_NO_TIMEOUT); + isActive = true; + } + else { + uint8_t count; +[1] BSP_tickRate1_on(); + for (count = 13U; count > 0U; --count) { + BSP_led1_on(); + QXThread_delay(1U); + BSP_led1_off(); + QXThread_delay(1U); + } + isActive = false; + } + } + } +@endcode + +
      +
      0
      The **XBlinky1** extended thread emulates the states with the `isActive` flag. When the flag is not set (meaning that the system is not active), the thread waits (and blocks) on the global semaphore `XSEM_sw1`. +
      +
      1
      After the semaphore is signalled (from the GPIO interrupt in the BSP), the **XBlinky1** extened thread calls `BSP_tickRate1_on()` to turn the tick rate-1 on. This is done *before* later calling QXThread_delay() function, which in case uses the clock rate-1. +
      +
      +
      + + +@subsection arm-cm_low_power_idle The Idle Callback (QK/QXK) +The most important functionality in this low-power example is implemented in the **idle callback** located in the BSP (Board Support Package). The idle callback QK_onIdle() for the preemptive QK kernel and the idle callback QXK_onIdle() for the QXK kernel are almost identical and are explained in this section. + +@code{.cpp} +[0] void QXK::onIdle(void) { + +[1] QF_INT_DISABLE(); +[2] if (((l_activeSet & (1U << SYSTICK_ACTIVE)) != 0U) /* rate-0 enabled? */ +[3] && QF_noTimeEvtsActiveX(0U)) /* no time events at rate-0? */ + { + /* safe to disable SysTick and interrupt */ +[4] SysTick->CTRL &= ~(SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk); +[5] l_activeSet &= ~(1U << SYSTICK_ACTIVE); /* mark rate-0 as disabled */ + } +[6] if (((l_activeSet & (1U << TIMER0_ACTIVE)) != 0U) /* rate-1 enabled? */ +[7] && QF_noTimeEvtsActiveX(1U)) /* no time events at rate-1? */ + { + /* safe to disable Timer0 and interrupt */ +[8] TIMER0->CTL &= ~(1U << 0); /* disable Timer0 */ +[9] TIMER0->IMR &= ~(1U << 0); /* disable timer interrupt */ +[10] l_activeSet &= ~(1U << TIMER0_ACTIVE); /* mark rate-1 as disabled */ + } +[11] QF_INT_ENABLE(); + +[12] GPIOF->DATA_Bits[LED_RED] = 0xFFU; /* turn LED on, see NOTE2 */ +[13] __WFI(); // wait for interrupt */ +[14] GPIOF->DATA_Bits[LED_RED] = 0x00U; /* turn LED off, see NOTE2 */ + } +@endcode + +
      +
      0
      The idle callback for QK and QXK are called from the idle loop with interrupts enabled. +
      +
      1
      Interrupts are disabled to access the shared bitmask `l_activeSet`, which stores the information about active clock rates and peripherals. This bitmask is shared between the idle callback and the application-level threads. +
      +
      2
      If the SYSTICK timer is active (source of the tick-0 rate)... +
      +
      3
      The `QF_noTimeEvtsActiveX(0)` function is called to check whether no time events are active at the clock rate-0. + +> NOTE: The QF_noTimeEvtsActiveX() function is designed to be called from a critical section, which is the case here. + +
      +
      4
      If both of these conditions hold, it is safe to turn the clock rate-0 off, which is done here. +
      +
      5
      The bit indicating that SYSTICK timer is active is cleared in the `l_activeSet` bitmask. +
      +
      6
      Simliarly, the bit corresponding to TIMER0 is checked in the `l_activeSet` bitmask. +
      +
      7
      The `QF_noTimeEvtsActiveX(1)` function is called to check whether no time events are active at the clock rate-1. +
      +
      8-9
      If both of these conditions hold, it is safe to turn the clock rate-1 off, which is done here. +
      +
      10
      The bit indicating that TIMER0 timer is active is cleared in the `l_activeSet` bitmask. +
      +
      11
      Interrupts are enabled, so the following code is no logner inside critical section +
      +
      12
      The **Red-LED** is turned ON right before entering the low-power sleep mode +
      +
      13
      The `__WFI()` instruction stops the CPU and enters the **low-power sleep mode** +
      +
      14
      The **Red-LED** is turned off after waking up from the sleep mode +
      +
      +
      + + +@subsection arm-cm_low_power_idle-qv The Idle Callback (QV) +The idle callback QV_onIdle() for the cooperative QV kernel is slightly different, because it is called with interrupts **disabled**. The following listing shows the complete QV_onIdle() callback, with the most important points explained in the section below: + +@code{.cpp} +[0] void QV::onIdle(void) { /* NOTE: called with interrupts DISABLED */ + +[1] if (((l_activeSet & (1U << SYSTICK_ACTIVE)) != 0U) /* rate-0 enabled? */ +[2] && QF_noTimeEvtsActiveX(0U)) /* no time events at rate-0? */ + { + /* safe to disable SysTick and interrupt */ + SysTick->CTRL &= ~(SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk); + l_activeSet &= ~(1U << SYSTICK_ACTIVE); /* mark rate-0 as disabled */ + } + if (((l_activeSet & (1U << TIMER0_ACTIVE)) != 0U) /* rate-1 enabled? */ + && QF_noTimeEvtsActiveX(1U)) /* no time events at rate-1? */ + { + /* safe to disable Timer0 and interrupt */ + TIMER0->CTL &= ~(1U << 0); /* disable Timer0 */ + TIMER0->IMR &= ~(1U << 0); /* disable timer interrupt */ + l_activeSet &= ~(1U << TIMER0_ACTIVE); /* mark rate-1 as disabled */ + } -[![Video: Getting Started with QP™ Real-Time Embedded Framework](getting-started-with-qp.jpg)](https://youtu.be/O7ER6_VqIH0) + GPIOF->DATA_Bits[LED_RED] = 0xFFU; /* turn LED on, see NOTE2 */ +[3] QV_CPU_SLEEP(); /* atomically go to sleep and enable interrupts */ + GPIOF->DATA_Bits[LED_RED] = 0x00U; /* turn LED off, see NOTE2 */ + } +@endcode +
      +
      0
      The idle callback for QV is called from the QV event-loop with interrupts **disabled**. +
      +
      1
      The `l_activeSet` bitmask is tested right away, because interrupts are already disabled +
      +
      2
      The `QF_noTimeEvtsActiveX(0)` function is called to check whether no time events are active at the clock rate-0. -@section gs_an Getting Started with QP™ AppNote -The Quantum Leaps Application Note @webref{doc/AN_Getting_Started_with_QP.pdf, Getting Started with QP™/C++} provides instructions on how to download, install and get started with QP™/C++ quickly. The application note also contains a **QP™/C++ Tutorial**, in which you build a simple "Blinky" application. +> NOTE: The QF_noTimeEvtsActiveX() function is designed to be called from a critical section, which is the case here. -[![Application Note: Getting Started with QP™ Real-Time Embedded Framework](AN_Getting-Started.png)](https://www.state-machine.com/doc/AN_Getting_Started_with_QP.pdf) +
      +
      3
      The QV_CPU_SLEEP() macro enters **low-power sleep mode** with interrupts still disabled. This port-specific macro is designed to re-anable interrupts **atomically** with entering the sleep mode. +
      +
      -@nav{index,struct} +
      +@nav{tut_game,exa} */ diff --git a/doxygen/history.dox b/doxygen/history.dox index 7e3006cb5..91550fe31 100644 --- a/doxygen/history.dox +++ b/doxygen/history.dox @@ -3,14 +3,39 @@ namespace QP { /** @page history Revision History @section qpcpp_7_0_0 Version 7.0.0, 2022-04-30 +This major focus of this release is the adaptation of the code and documentation to better support safety certification (see [QP Certification Pack](https://www.state-machine.com/products/qp#CERT)) +__Modified QP/C++ source code:__ +- updated QP/C++ source code for AUTOSAR:C++14 +- made the compliant with the updated [Quantum Leaps Embedded C/C++ Coding Style (QL-C/C++:2022)](https://github.com/QuantumLeaps/embedded-coding-style) +- added traceability links between QP/C++ source code and requirements, architecture, design, and MISRA deviation permits. +- modified the top-level file comments now have standard-compliant license specification (SPDX-License-Identifiers). This allows QP/C++ to be included in automatic generation of Software Bill Of Materials (SBOM). + +__Modified QP/C++ ports:__ +- modified the QK and QXK ports to ARM Cortex-M to allow compile-time selection between using either NMI or an unused IRQ (via macro QK_USE_IRQ_HANDLER) as a mechanism to return to the thread mode - removed unused `ARM_ARCH` symbol from Makefiles for GNU-ARM -- restructured the Doxygen documentation - + introudced new styling for the HTML documentation - + updated links in the documentation +- fixed the following bugs in QXK port to ARM Cortex-M + + [bug#305 Floating-point context corruption in QXK](https://sourceforge.net/p/qpc/bugs/305) + + [bug#306 QXK_ON_CONTEXT_SW option is not compatible with soft-float](https://sourceforge.net/p/qpc/bugs/306) -@section qpcpp_6_9_3 Version 6.9.3, 2021-04-12 +__Modified GitHub repository:__ +- removed the `3rd_party` directory from the [qpcpp GitHub repository](https://github.com/QuantumLeaps/qpcpp) to avoid tracking changes caused by updates to the 3rd-party components. (The QP/C++ releases still have the `3rd_party` directory, because it is needed for building the examples). + +__Added/Modified examples:__ +- modified examples for ARM Cortex-M7 (to integrate better with STM32CubeH7) +- added examples for ARM Cortex-M33 (for STM32 NUCLEO-L552ZE and STM32CubeL5) +- added `qutest` examples for Unity (comparison between Unity and QUTest) + +__Modified QP/C++ documentation:__ +- restructured the Doxygen documentation for traceability +- added the @ref gs_tut "QP/C++ Tutorial" +- added the @ref srs "QP Certification Pack" +@remark +The [QP Certification Pack](https://www.state-machine.com/products/qp#CERT) is still work in progress in this release, but the remaining work is limited to documentation only and no code restructuring is anticipated for that. + + +@section qpcpp_6_9_3 Version 6.9.3, 2021-04-12 __Feature Requests:__ - [feature#191 "Add QS local filtering to QF_PUBLISH()"](https://sourceforge.net/p/qpc/feature-requests/191/) @@ -91,7 +116,7 @@ __Modified QP/C++ ports:__ - `qpcpp/ports/embos/` - added missing `noexcept` specifiers - `qpcpp/ports/freertos/` - added missing `noexcept` specifiers - `qpcpp/ports/threadx/` - added missing `noexcept` specifiers -- `qpcpp/ports/ucos-ii/` - added missing `noexcept` specifiers +- `qpcpp/ports/uc-os2/` - added missing `noexcept` specifiers - `qpcpp/ports/qt/` - added missing `noexcept` specifiers @@ -259,14 +284,14 @@ __Source code changes:__ __Updated Ports:__ + enabled #QF_ACTIVE_STOP in the ports: Win32, Win32-QV, Win32-QUTEST, POSIX, POSIX-QV, and POSIX-QUTEST. - + @ref ucos-ii "port to uC/OS-II" has been adapted to the new uC/OS-II v2.93.00 (recently released by Silicon Labs under the open source Apache 2.0 license). + + @ref uc-os2 "port to uC/OS-II" has been adapted to the new uC/OS-II v2.93.00 (recently released by Silicon Labs under the open source Apache 2.0 license). __Updated Examples:__ + Modidfied `Makefile`s for the workstation examples to add the `-no-pie` linker option only when `GCC_OLD` environment variable is NOT defined. This is to accommodates older POSIX platforms with older GCC distribution. + Modified all ARM-KEIL uVision projects for ARM-CLANG to use the startup code in the ARM-ASM syntax. - + New uC/OS-II example @ref ucos-ii_dpp_nucleo-l053r8 (Cortex-M0+) + + New uC/OS-II example @ref uc-os2_dpp_nucleo-l053r8 (Cortex-M0+) + Removed uC/OS-II example for the STM32-NUCLEO-L152RE (Cortex-M3) + Added QM model files: `workstation/defer/defer.qm` and `workstation/reminder2/reminder2.qm` @@ -639,7 +664,7 @@ Additionally, this release modifies all IAR-ARM example projects by adding compi Additionally, this release fixes some problems with the native examples for STM32F4 and STM32F7 boards. -Additionally, this release adds a generic function QP::QActive::setAttr() to set thread attributes in various QP ports to 3rd-party RTOSes. This function is then used in the @ref embos "embOS port" and the @ref ucos-ii "uC/OS-II port". +Additionally, this release adds a generic function QP::QActive::setAttr() to set thread attributes in various QP ports to 3rd-party RTOSes. This function is then used in the @ref embos "embOS port" and the @ref uc-os2 "uC/OS-II port". Finally, this release fixes the following bug in the @ref threadx "ThreadX port": @@ -1439,7 +1464,7 @@ Changes in detail: 11. Added @ref threadx "port to Thread-X". Example is available for the Thread-X demo with Visual Studio on Windows. -12. Updated port to @ref ucos-ii "uC/OS-II" for the latest version v2.92. Examples are available for TI EK-TM4C123GLX and STM32 NUCLEO-L152RE boards with ARM-KEIL and IAR-ARM toolsets. +12. Updated port to @ref uc-os2 "uC/OS-II" for the latest version v2.92. Examples are available for TI EK-TM4C123GLX and STM32 NUCLEO-L152RE boards with ARM-KEIL and IAR-ARM toolsets. 13. Updated @ref win32 "port to Win32" (Windows). Modified the port to apply a generous "fudge factor" in over-sizing QP event queues and event pools, to minimize the risk of overflowing queues/pools due to non-deterministic Windows behavior. diff --git a/doxygen/images/AN-game.jpg b/doxygen/images/AN-game.jpg new file mode 100644 index 000000000..6ed6df01c Binary files /dev/null and b/doxygen/images/AN-game.jpg differ diff --git a/doxygen/images/AN-getting_started.jpg b/doxygen/images/AN-getting_started.jpg new file mode 100644 index 000000000..3f5b7b5bd Binary files /dev/null and b/doxygen/images/AN-getting_started.jpg differ diff --git a/doxygen/images/AN_DPP.jpg b/doxygen/images/AN_DPP.jpg new file mode 100644 index 000000000..4176fea7e Binary files /dev/null and b/doxygen/images/AN_DPP.jpg differ diff --git a/doxygen/images/AN_Getting-Started.png b/doxygen/images/AN_Getting-Started.png deleted file mode 100644 index 301ade982..000000000 Binary files a/doxygen/images/AN_Getting-Started.png and /dev/null differ diff --git a/doxygen/images/an-qp_performance.png b/doxygen/images/an-qp_performance.png new file mode 100644 index 000000000..de6add8ba Binary files /dev/null and b/doxygen/images/an-qp_performance.png differ diff --git a/doxygen/images/bd_mbed-LPC1768.jpg b/doxygen/images/bd_mbed-LPC1768.jpg index 6552e4690..e39cb0541 100644 Binary files a/doxygen/images/bd_mbed-LPC1768.jpg and b/doxygen/images/bd_mbed-LPC1768.jpg differ diff --git a/doxygen/images/game-video.jpg b/doxygen/images/game-video.jpg new file mode 100644 index 000000000..e88cae43a Binary files /dev/null and b/doxygen/images/game-video.jpg differ diff --git a/doxygen/images/gs-video.jpg b/doxygen/images/gs-video.jpg new file mode 100644 index 000000000..373c721c7 Binary files /dev/null and b/doxygen/images/gs-video.jpg differ diff --git a/doxygen/images/logo_embos.png b/doxygen/images/logo_embos.png new file mode 100644 index 000000000..e90f5dd05 Binary files /dev/null and b/doxygen/images/logo_embos.png differ diff --git a/doxygen/images/logo_freertos.png b/doxygen/images/logo_freertos.png new file mode 100644 index 000000000..cfab10ea5 Binary files /dev/null and b/doxygen/images/logo_freertos.png differ diff --git a/doxygen/images/logo_pclintplus.jpg b/doxygen/images/logo_pclintplus.jpg new file mode 100644 index 000000000..9abfd51b4 Binary files /dev/null and b/doxygen/images/logo_pclintplus.jpg differ diff --git a/doxygen/images/logo_threadx.jpg b/doxygen/images/logo_threadx.jpg new file mode 100644 index 000000000..1fd0ff90d Binary files /dev/null and b/doxygen/images/logo_threadx.jpg differ diff --git a/doxygen/images/logo_uc-os2.jpg b/doxygen/images/logo_uc-os2.jpg new file mode 100644 index 000000000..c9ef02746 Binary files /dev/null and b/doxygen/images/logo_uc-os2.jpg differ diff --git a/doxygen/images/qpcpp_gh.jpg b/doxygen/images/qpcpp_gh.jpg new file mode 100644 index 000000000..ea3ebd7d1 Binary files /dev/null and b/doxygen/images/qpcpp_gh.jpg differ diff --git a/doxygen/images/qwin_ani.gif b/doxygen/images/qwin_ani.gif new file mode 100644 index 000000000..68d726547 Binary files /dev/null and b/doxygen/images/qwin_ani.gif differ diff --git a/doxygen/img/cert-pack.png b/doxygen/img/cert-pack.png new file mode 100644 index 000000000..39e2ad841 Binary files /dev/null and b/doxygen/img/cert-pack.png differ diff --git a/doxygen/img/img.htm b/doxygen/img/img.htm index 898ec8559..cd73b9e43 100644 --- a/doxygen/img/img.htm +++ b/doxygen/img/img.htm @@ -6,14 +6,17 @@ QP built-in images + + - + + diff --git a/doxygen/img/logo_github.png b/doxygen/img/logo_github.png index 99b383929..ba26711bf 100644 Binary files a/doxygen/img/logo_github.png and b/doxygen/img/logo_github.png differ diff --git a/doxygen/main.dox b/doxygen/main.dox index 54d82ab34..ac306985b 100644 --- a/doxygen/main.dox +++ b/doxygen/main.dox @@ -1,69 +1,77 @@ -/*! @mainpage About QP™/C++ +/*! @mainpage Overview @image html qp_banner.jpg - -@section ab_new What's new? -To check what's new in QP™/C++, please see @ref history "QP/C++ Revision History". You can also get the latest **QP™/C code**, with the recent enhancements and bug fixes, from the GitHub QP/C++ repository. +@remark + +To check what's new in QP™/C++, please see @ref history "QP/C++ Revision History". You can also get the latest **QP™/C++ code**, with the recent enhancements and bug fixes, from the GitHub QP™/C++ repository.
      -@section ab_about What is it? -@webref{products/qp, QP™/C++ (Quantum Platform in C)} is a lightweight @webref{rtef, Real-Time Embedded Framework (RTEF)} for building modern, responsive and modular real-time embedded applications as systems of asynchronous event-driven @webref{active-object, active objects} (actors). The QP™/C++ RTEF is a member of a @webref{products/qp, larger family of real-time embedded frameworks (RTEFs)} consisting of QP™/C and QP™/C++ frameworks, which are strictly quality controlled, thoroughly documented, and available under @ref licensing "dual licensing model". +@section over_about What is it? +QP™/C++ Real-Time Embedded Framework (RTEF) is a lightweight implementation of the @webref{active-object, Active Object model of computation} specifically tailored for real-time embedded (RTE) systems. QP is both a software infrastructure for building applications consisting of Active Objects (actors) and a runtime environment for executing the Active Objects in a deterministic fashion. Additionally, QP Framework supports @webref{fsm#HSM, Hierarchical State Machines} with which to specify the behavior of Active Objects @ref srs_ref "[ROOM:94], [UML 2.5],[Sutter:10]". -The behavior of active objects is specified in QP™/C++ by means of @webref{fsm/#HSM, hierarchical state machines} (UML statecharts). The framework supports @ref sm "manual coding of UML state machines in C" as well as automatic code generation by means of the free @webref{products/qm, QM™ model-based design tool}. +@note + +The @webref{products/qp#CERT,QP Certification Pack} provides: +- @ref srs_over "Software Requirements Specification" with a good overview of the QP/C++ Framework +- @ref sas_core "Software Architecture Specification" with concise description of QP/C++ architecture +- @ref sds "Software Design Specification" with detailed description of the QP/C++ design. + + +@section over_goals What does it do? +The main objectives of the QP/C++ RTEF are: + +- to provide a modern, event-driven model of concurrency based on the best practices of concurrent programming @ref srs_ref "[ROOM:94], [Cummings:10], [Sutter:10]", collectively known as the @webref{active-object, Active Object (Actor) model of computation}, which is inherently *safer* than the traditional "shared-state concurrency, mutual-exclusion, and blocking" approach based on a conventional Real-Time Operating System (RTOS); -@attention -To use QP™/C++ effectively, you need to understand the @webref{category/concepts, key concepts} that underline the architecture of the framework and your applications based on the framework. +- to provide a *higher-level of abstraction* closer to the problem domain than the "naked" RTOS threads; +- to provide the *right* abstractions for applying modern techniques like visual modeling, hierarchical state machines, and automatic code generation; -@section ab_goals What does it do? -The main goals of the QP™/C++ framework are: -- to provide a reusable event-driven **architecture** based on @webref{active-object, active objects (actors)}, which is inherently **safer**, more extensible, and easier to understand than the usual *shared-state concurrency* based on a traditional Real-Time Operating System (RTOS). -- to provide a simple-to-use coding techniques for @webref{fsm/#HSM, hierarchical state machines}, with which to implement the behavior of active objects. -- to provide efficient and thread-safe asynchronous mechanisms for active objects to communicate, such as direct event passing and publish-subscribe. -- to provide event-driven timing services (time events). -- to provide a selection of built-in real-time kernels to run the QP applications, such as the cooperative @ref qv "QV kernel", the preemptive non-blocking @ref qk "QK kernel", and the preemptive blocking @ref qxk "QXK kernel". -- to provide testing support for applications based on software tracing (@ref qs "Q-Spy"). -- to provide **unit testing** support for applications based on software tracing (@webref{qtools/qutest.html, QUTest™}). -- to provide portability layer and ready-to-use ports to @ref ports_rtos "3rd-party RTOSes" and general purpose operating systems such as @ref posix "Linux" and @ref win32 "Windows". -- to provide a target for modeling and automatic code generation from the @webref{products/qm, QM™ modeling tool}. +- to bridge the semantic gap between the higher level modeling concepts (such as UML) and the traditional programming languages like C or C++. -@section ab_special What's special about it? +@section over_special What's special about it? The QP™/C++ Real-Time Embedded Framework (RTEF) is a unique offering on the embedded software market. It provides a modern, reusable **architecture** of embedded applications, which combines object-orientation with the particular model of concurrency, known as @webref{active-object, active objects} (actors). This architecture is generally **safer**, more responsive and easier to understand than "free threading" with a traditional Real-Time Operating System (RTOS). It also provides sufficiently high level of abstraction and the right abstractions to effectively apply modeling and code generation to deeply embedded systems. -@subsection oop Object Orientation -QP™/C++ is fundamentally an **object-oriented** framework, which means that the framework itself and your applications derived from the framework are fundamentally composed of classes and only classes can have @ref sm "state machines" associated with them. +@subsection over_oop Object Orientation +QP™/C++ is fundamentally an **object-oriented** framework, which means that the framework itself and your applications derived from the framework are fundamentally composed of classes and only classes can have @ref srs_sm "state machines" associated with them. +@subsection over_hsms Hierarchical State Machines +The behavior of active objects is specified in QP™/C++ by means of @webref{fsm/#HSM, hierarchical state machines (UML statecharts)}. The framework supports @ref sds_sm "manual coding of UML state machines in C++" as well as fully **automatic code generation** by means of the free graphical @webref{products/qm, QM™ model-based design (MBD) tool}. -@subsection lightweight Lightweight -The most unique characteristic of the QP™/C++ framework is its very small footprint, especially in RAM. In this respect, QP™/C++ requires less resources than even the smallest conventional Real-Time Operating System (RTOS) kernel. At the same time, QP gives you a much higher level of abstraction than a conventional RTOS. With QP, you work at the level of active objects, state machines and events, as opposed to "naked" threads of an RTOS. +@subsection over_kernels Built-in Kernels +The QP™/C++ framework can run on @ref exa_native "bare-metal single-chip microcontrollers", completely replacing a traditional RTOS. The framework contains a selection of built-in real-time kernels, such as the cooperative @ref srs_qv "QV kernel", the preemptive non-blocking @ref srs_qk "QK kernel", and the preemptive, dual-mode, blocking @ref srs_qxk "QXK kernel". The QXK kernel provides all the features you might expect from a traditional RTOS kernel and has been specifically designed for mixing event-driven active objects with traditional blocking code, such as commercial middleware (TCP/IP stacks, UDP stacks, embedded file systems, etc.) or legacy software. @ref ports_native "Native QP ports" and ready-to-use @ref exa_native "examples" are provided for major @ref exa_ref_mcu "CPU families". -@subsection hsms Hierarchical State Machines -The behavior of active objects is specified in QP™/C++ by means of @webref{fsm/#HSM, hierarchical state machines (UML statecharts)}. The framework supports @ref sm "manual coding of UML state machines in C+++" (or C++ in case of QP™/C++) as well as fully **automatic code generation** by means of the free graphical @webref{products/qm, QM™ model-based design (MBD) tool}. -@remarks -State machines can be an incredibly powerful technique, but they require an event-driven **infrastructure** (framework) that provides, at a minimum: a run-to-completion (RTC) execution context for each state machine, queuing of events, and event-based timing services. This is really the pivotal point. Without an event-driven framework (like QP™/C++), state machines are like @webref{rtef, cars without an infrastructure of roads}. +@subsection over_eff Efficiency +Even though QP™/C++ offers much higher level of abstraction than a traditional RTOS, it typically outperforms equivalent traditional RTOS offerings both in RAM/ROM footprint and in CPU efficiency. The specific measurements and results are reported in the following @webref{doc/AN_QP_Performance.pdf, Application Note: "QP Performance Tests and Results"}: +[![Application Note: "QP Performance Tests and Results"](an-qp_performance.png)](https://www.state-machine.com/doc/AN_QP_Performance.pdf) -@subsection kernels Built-in Kernels -The QP™/C++ framework can run on @ref exa_native "bare-metal single-chip microcontrollers", completely replacing a traditional RTOS. The framework contains a selection of built-in real-time kernels, such as the cooperative @ref qv "QV kernel", the preemptive non-blocking @ref qk "QK kernel", and the preemptive, dual-mode, blocking @ref qxk "QXK kernel". The QXK kernel provides all the features you might expect from a traditional RTOS kernel and has been specifically designed for mixing event-driven active objects with traditional blocking code, such as commercial middleware (TCP/IP stacks, UDP stacks, embedded file systems, etc.) or legacy software. @ref ports_native "Native QP ports" and ready-to-use @ref exa_native "examples" are provided for major @ref exa_ref_mcu "CPU families". +@subsection over_simple Simplicity +The QP Framework is simple to get started, simple to use and simple to build. The numerous provided @ref exa "examples" come with projects for typical embedded toolchains (e.g., GNU, ARM, IAR, etc.). The framework does not impose any proprietary build or configuring procedures or tooling, just simple makefiles and native projects for the demonstrated toolchains. While these are possibly inadequate for really complex projects, experience shows that bigger teams have their own DevOps (e.g., CI/CD) and imposing a particular process is typically counterproductive. -@subsection inter Interoperability + +@subsection over_inter Interoperability QP™/C++ can also work with many traditional @ref exa_rtos "RTOSes" and @ref exa_os "general-purpose OSes" (such as Linux and Windows). -@subsection popular Popularity & Maturity +@subsection over_trace Traceability +QP™/C++ offers unprecedented, bidirectional @ref trace "traceability" among all work artifacts, which gives teams full visibility from requirements through architecture, design, source code, tests, and back again. + + +@subsection over_popular Popularity & Maturity With 20 years of continuous development, over @webref{customers#Customers, 350 commercial licensees}, and many times more open source users worldwide, the QP™ frameworks are the most popular such offering on the market. They power countless electronic products ranging from implantable medical devices to complex weapon systems. -@subsection use Widespread Use + +@subsection over_use Widespread Use The QP™ real-time embedded frameworks address high-reliability applications across a @webref{customers#Markets, wide variety of markets}, such as medical, consumer, IoT, defense, robotics, industrial, communication, transportation, semiconductor IP, and many others. In each of these application areas, the elegant software architecture and modern design philosophy of QP™ have distinct advantages. -@subsection psicc2 Books +@subsection over_psicc2 Books The two editions of the book, @webref{psicc2, Practical Statecharts in C/C++} provide a detailed design study of the QP™ frameworks and explain the related concepts. [![Practical UML Statecharts in C/C++, 2nd Edition](psicc2.jpg)](https://www.state-machine.com/psicc2) @@ -72,38 +80,38 @@ The two editions of the book, @webref{psicc2, Practical Statecharts in C [![Practical Statecharts in C/C++, 1nd Edition](psicc1.jpg)](https://www.state-machine.com/psicc) -@section licensing How is it licensed? +@section over_licensing How is it licensed? QP™/C++ is licensed under the sustainable @webref{licensing, dual licensing model}, in which both the open source software distribution mechanism and traditional closed source software distribution models are combined. @note If your company has a policy forbidding open source in your product, all QP frameworks can be @webref{licensing#Commercial, licensed commercially}, in which case you don't use any open source license and you do not violate your policy. -@subsection open-source Open Source Projects +@subsection over_open-source Open Source Projects If you are developing and distributing **open source** applications under the GNU General Public License (GPL), as published by the Free Software Foundation, then you are free to use the Quantum Leaps software under the GPL version 3 of the License, or (at your option) any later version. Please note that GPL requires that all modifications to the original code as well as your application code (Derivative Works as defined in the Copyright Law) must also be released under the terms of the GPL open source license. -@subsection closed-source Closed Source Projects +@subsection over_closed-source Closed Source Projects If you are developing and distributing traditional **closed source** applications, you can purchase one of @webref{licensing/#Commercial, Quantum Leaps commercial licenses}, which are specifically designed for users interested in retaining the proprietary status of their code. All Quantum Leaps commercial licenses expressly supersede the GPL open source license. This means that when you license Quantum Leaps software under a commercial license, you specifically do not use the software under the open source license and therefore you are not subject to any of its terms. -@section support How to get help? +@section over_support How to get help? Please post any **technical questions** to the Free Support Forum hosted on SourceForge.net. Posts to this forum benefit the whole community and are typically answered the same day. Direct **Commercial Support** is available to the commercial licensees. Every commercial license includes one year of Technical Support for the licensed software. The support term can be extended annually. Training and consulting services are also available from Quantum Leaps. Please refer to the @webref{contact, Contact web-page} for more information. +@note +The features of this online help and tips for using it are described in Section @ref help. -@section contact Contact Information +@section over_contact Contact Information - Quantum Leaps Web site: @webref{,state-machine.com} - - Quantum Leaps licensing: @webref{licensing, state-machine.com/licensing} - -- QP/QM on GitHub: github.com/QuantumLeaps - +- Quantum Leaps on GitHub: github.com/QuantumLeaps - e-mail: info@state-machine.com +
      @next{gs} */ diff --git a/doxygen/make.bat b/doxygen/make.bat index 77ed03ee2..fbc4ef0e6 100644 --- a/doxygen/make.bat +++ b/doxygen/make.bat @@ -49,14 +49,14 @@ @set METRICS_INP=%QPCPP%\include %QPCPP%\src -x %QPCPP%\src\qs\* @set METRICS_OUT=metrics.dox -@echo /** @page metrics Code Metrics > %METRICS_OUT% +@echo /** @defgroup metrics Code Metrics> %METRICS_OUT% @echo.>> %METRICS_OUT% -@echo @code{cpp} >> %METRICS_OUT% -@echo Code Metrics >> %METRICS_OUT% +@echo @code{.cpp}>> %METRICS_OUT% +@echo QP/C++ Code Metrics >> %METRICS_OUT% %LIZARD% -m -L500 -a10 -C20 -V %METRICS_INP% >> %METRICS_OUT% -@echo @endcode >> %METRICS_OUT% +@echo @endcode>> %METRICS_OUT% @echo */ >> %METRICS_OUT% :: Generate Doxygen Documentation... diff --git a/doxygen/metrics.dox b/doxygen/metrics.dox index b21a1b8bd..ee37e5367 100644 --- a/doxygen/metrics.dox +++ b/doxygen/metrics.dox @@ -1,101 +1,103 @@ -/** @page metrics Code Metrics +/** @defgroup metrics Code Metrics -@code{cpp} - Code Metrics +@code{.cpp} + QP/C++ Code Metrics ================================================ NLOC CCN token PARAM length location ------------------------------------------------ - 3 1 14 1 4 QP::QEvt::QEvt@148-151@..\include\qep.hpp - 5 1 26 2 5 QP::QEvt::QEvt@155-159@..\include\qep.hpp - 1 1 6 0 1 QP::QEvt::~QEvt@163-163@..\include\qep.hpp - 3 1 17 1 3 QP::QHsm::init@269-271@..\include\qep.hpp - 3 1 13 1 3 QP::QHsm::state@283-285@..\include\qep.hpp - 4 1 18 1 4 QP::QHsm::tran@341-344@..\include\qep.hpp - 4 1 18 1 4 QP::QHsm::tran_hist@347-350@..\include\qep.hpp - 4 1 18 1 4 QP::QHsm::super@353-356@..\include\qep.hpp - 4 1 30 1 4 QP::QHsm::qm_tran@367-370@..\include\qep.hpp - 7 1 42 2 7 QP::QHsm::qm_tran_hist@374-380@..\include\qep.hpp - 4 1 30 1 4 QP::QHsm::qm_tran_init@384-387@..\include\qep.hpp - 4 1 30 1 4 QP::QHsm::qm_tran_ep@391-394@..\include\qep.hpp - 7 1 40 2 7 QP::QHsm::qm_tran_xp@398-404@..\include\qep.hpp - 4 1 20 1 4 QP::QHsm::qm_entry@408-411@..\include\qep.hpp - 4 1 20 1 4 QP::QHsm::qm_exit@414-417@..\include\qep.hpp - 4 1 19 1 4 QP::QHsm::qm_entry@423-426@..\include\qep.hpp - 4 1 19 1 4 QP::QHsm::qm_exit@429-432@..\include\qep.hpp - 4 1 20 1 4 QP::QHsm::qm_sm_exit@436-439@..\include\qep.hpp - 4 1 20 1 4 QP::QHsm::qm_super_sub@443-446@..\include\qep.hpp - 3 1 13 1 3 QP::QMsm::stateObj@504-506@..\include\qep.hpp - 3 1 10 1 3 QP::QEP::getVersion@588-590@..\include\qep.hpp - 3 1 11 1 3 QP::QEQueue::getNFree@216-218@..\include\qequeue.hpp - 3 1 11 1 3 QP::QEQueue::getNMin@231-233@..\include\qequeue.hpp - 3 1 13 1 3 QP::QEQueue::isEmpty@245-247@..\include\qequeue.hpp - 6 1 51 5 6 QP::QActive::start@193-198@..\include\qf.hpp - 3 1 19 1 3 QP::QActive::getPrio@244-246@..\include\qf.hpp - 3 1 22 1 3 QP::QActive::setPrio@249-251@..\include\qf.hpp - 1 1 10 1 1 QP::QActive::getOsObject@259-259@..\include\qf.hpp - 1 1 10 1 1 QP::QActive::getThread@265-265@..\include\qf.hpp + 3 1 14 1 4 QP::QEvt::QEvt@141-144@..\include\qep.hpp + 5 1 26 2 5 QP::QEvt::QEvt@148-152@..\include\qep.hpp + 1 1 6 0 1 QP::QEvt::~QEvt@156-156@..\include\qep.hpp + 3 1 17 1 3 QP::QHsm::init@262-264@..\include\qep.hpp + 3 1 13 1 3 QP::QHsm::state@276-278@..\include\qep.hpp + 4 1 18 1 4 QP::QHsm::tran@334-337@..\include\qep.hpp + 4 1 18 1 4 QP::QHsm::tran_hist@340-343@..\include\qep.hpp + 4 1 18 1 4 QP::QHsm::super@346-349@..\include\qep.hpp + 4 1 30 1 4 QP::QHsm::qm_tran@360-363@..\include\qep.hpp + 7 1 42 2 7 QP::QHsm::qm_tran_hist@367-373@..\include\qep.hpp + 4 1 30 1 4 QP::QHsm::qm_tran_init@377-380@..\include\qep.hpp + 4 1 30 1 4 QP::QHsm::qm_tran_ep@384-387@..\include\qep.hpp + 7 1 40 2 7 QP::QHsm::qm_tran_xp@391-397@..\include\qep.hpp + 4 1 20 1 4 QP::QHsm::qm_entry@401-404@..\include\qep.hpp + 4 1 20 1 4 QP::QHsm::qm_exit@407-410@..\include\qep.hpp + 4 1 19 1 4 QP::QHsm::qm_entry@416-419@..\include\qep.hpp + 4 1 19 1 4 QP::QHsm::qm_exit@422-425@..\include\qep.hpp + 4 1 20 1 4 QP::QHsm::qm_sm_exit@429-432@..\include\qep.hpp + 4 1 20 1 4 QP::QHsm::qm_super_sub@436-439@..\include\qep.hpp + 3 1 13 1 3 QP::QMsm::stateObj@500-502@..\include\qep.hpp + 3 1 10 1 3 QP::QEP::getVersion@584-586@..\include\qep.hpp + 3 1 11 1 3 QP::QEQueue::getNFree@215-217@..\include\qequeue.hpp + 3 1 11 1 3 QP::QEQueue::getNMin@230-232@..\include\qequeue.hpp + 3 1 13 1 3 QP::QEQueue::isEmpty@244-246@..\include\qequeue.hpp + 6 1 51 5 6 QP::QActive::start@192-197@..\include\qf.hpp + 3 1 19 1 3 QP::QActive::getPrio@243-245@..\include\qf.hpp + 3 1 22 1 3 QP::QActive::setPrio@248-250@..\include\qf.hpp + 1 1 10 1 1 QP::QActive::getOsObject@258-258@..\include\qf.hpp + 1 1 10 1 1 QP::QActive::getThread@264-264@..\include\qf.hpp 3 1 13 1 3 QP::QMActive::stateObj@340-342@..\include\qf.hpp 3 1 17 1 3 QP::QTimeEvt::toActive@455-457@..\include\qf.hpp 3 1 17 1 3 QP::QTimeEvt::toTimeEvt@460-462@..\include\qf.hpp 3 1 10 1 3 QP::QF::getVersion@491-493@..\include\qf.hpp - 3 1 10 1 3 QP::QK::getVersion@147-149@..\include\qk.hpp - 3 1 11 1 3 QP::QMPool::getBlockSize@143-145@..\include\qmpool.hpp - 3 1 11 1 3 QP::QPSet::setEmpty@74-76@..\include\qpset.hpp - 3 1 15 1 3 QP::QPSet::isEmpty@79-81@..\include\qpset.hpp - 3 1 15 1 3 QP::QPSet::notEmpty@84-86@..\include\qpset.hpp - 3 1 30 1 3 QP::QPSet::hasElement@89-91@..\include\qpset.hpp - 3 1 24 1 3 QP::QPSet::insert@94-96@..\include\qpset.hpp - 4 1 36 1 4 QP::QPSet::rmove@102-105@..\include\qpset.hpp - 3 1 14 1 3 QP::QPSet::findMax@107-109@..\include\qpset.hpp - 4 1 21 1 4 QP::QPSet::setEmpty@128-131@..\include\qpset.hpp - 3 2 29 1 3 QP::QPSet::isEmpty@135-137@..\include\qpset.hpp - 3 2 29 1 3 QP::QPSet::notEmpty@141-143@..\include\qpset.hpp - 7 2 79 1 7 QP::QPSet::hasElement@146-152@..\include\qpset.hpp - 8 2 70 1 8 QP::QPSet::insert@155-162@..\include\qpset.hpp - 8 2 74 1 8 QP::QPSet::rmove@168-175@..\include\qpset.hpp - 5 2 40 1 5 QP::QPSet::findMax@178-182@..\include\qpset.hpp - 3 1 19 1 3 QP::QSpyId::getPrio@206-208@..\include\qs.hpp - 7 1 28 1 7 QP::QS::force_cast@498-504@..\include\qs.hpp - 14 3 72 1 14 QP::QS::rxPut@539-552@..\include\qs.hpp + 3 1 10 1 3 QP::QK::getVersion@146-148@..\include\qk.hpp + 3 1 11 1 3 QP::QMPool::getBlockSize@142-144@..\include\qmpool.hpp + 3 1 11 1 3 QP::QPSet::setEmpty@73-75@..\include\qpset.hpp + 3 1 15 1 3 QP::QPSet::isEmpty@78-80@..\include\qpset.hpp + 3 1 15 1 3 QP::QPSet::notEmpty@83-85@..\include\qpset.hpp + 3 1 30 1 3 QP::QPSet::hasElement@88-90@..\include\qpset.hpp + 3 1 24 1 3 QP::QPSet::insert@93-95@..\include\qpset.hpp + 4 1 36 1 4 QP::QPSet::rmove@101-104@..\include\qpset.hpp + 3 1 14 1 3 QP::QPSet::findMax@106-108@..\include\qpset.hpp + 4 1 21 1 4 QP::QPSet::setEmpty@127-130@..\include\qpset.hpp + 3 2 29 1 3 QP::QPSet::isEmpty@134-136@..\include\qpset.hpp + 3 2 29 1 3 QP::QPSet::notEmpty@140-142@..\include\qpset.hpp + 7 2 79 1 7 QP::QPSet::hasElement@145-151@..\include\qpset.hpp + 8 2 70 1 8 QP::QPSet::insert@154-161@..\include\qpset.hpp + 8 2 74 1 8 QP::QPSet::rmove@167-174@..\include\qpset.hpp + 5 2 40 1 5 QP::QPSet::findMax@177-181@..\include\qpset.hpp + 3 1 19 1 3 QP::QSpyId::getPrio@205-207@..\include\qs.hpp + 7 1 28 1 7 QP::QS::force_cast@497-503@..\include\qs.hpp + 14 3 72 1 14 QP::QS::rxPut@538-551@..\include\qs.hpp 6 1 49 5 6 QP::QActiveDummy::start@587-592@..\include\qs.hpp - 3 1 19 1 3 QP::QSpyId::getPrio@107-109@..\include\qs_dummy.hpp - 3 1 20 1 3 QP::QXThread::init@80-82@..\include\qxthread.hpp - 6 1 51 5 6 QP::QXThread::start@96-101@..\include\qxthread.hpp - 2 1 19 2 3 QP::QEvt@93-95@..\src\qf\qep_hsm.cpp + 3 1 19 1 3 QP::QSpyId::getPrio@106-108@..\include\qs_dummy.hpp + 3 1 20 1 3 QP::QXThread::init@79-81@..\include\qxthread.hpp + 6 1 51 5 6 QP::QXThread::start@95-100@..\include\qxthread.hpp + 2 1 19 2 3 QP::QEvt@92-94@..\src\qf\qep_hsm.cpp 4 1 27 1 4 QP::QHsm::QHsm@117-120@..\src\qf\qep_hsm.cpp 2 1 7 0 2 QP::QHsm::~QHsm@126-127@..\src\qf\qep_hsm.cpp - 47 7 318 2 68 QP::QHsm::init@139-206@..\src\qf\qep_hsm.cpp - 5 1 37 2 5 QP::QHsm::top@224-228@..\src\qf\qep_hsm.cpp - 102 15 608 2 152 QP::QHsm::dispatch@242-393@..\src\qf\qep_hsm.cpp - 95 15 460 2 129 QP::QHsm::hsm_tran@407-535@..\src\qf\qep_hsm.cpp - 3 1 13 0 3 QP::QHsm::getStateHandler@539-541@..\src\qf\qep_hsm.cpp - 16 3 85 1 23 QP::QHsm::isIn@557-579@..\src\qf\qep_hsm.cpp - 20 4 108 1 29 QP::QHsm::childState@602-630@..\src\qf\qep_hsm.cpp - 6 1 29 1 6 QP::QMsm::QMsm@75-80@..\src\qf\qep_msm.cpp - 22 3 168 2 36 QP::QMsm::init@93-128@..\src\qf\qep_msm.cpp - 113 21 661 2 166 QP::QMsm::dispatch@141-306@..\src\qf\qep_msm.cpp - 3 1 15 0 3 QP::QMsm::getStateHandler@313-315@..\src\qf\qep_msm.cpp - 51 9 298 2 64 QP::QMsm::execTatbl_@332-395@..\src\qf\qep_msm.cpp - 21 4 116 3 28 QP::QMsm::exitToTranSource_@407-434@..\src\qf\qep_msm.cpp - 43 6 236 2 54 QP::QMsm::enterHistory_@448-501@..\src\qf\qep_msm.cpp - 13 3 59 1 14 QP::QMsm::isInState@516-529@..\src\qf\qep_msm.cpp - 21 4 90 1 28 QP::QMsm::childStateObj@546-573@..\src\qf\qep_msm.cpp - 9 3 72 1 10 QP::QF::add_@69-78@..\src\qf\qf_act.cpp - 10 3 80 1 11 QP::QF::remove_@93-103@..\src\qf\qf_act.cpp - 7 2 61 2 7 QP::QF::bzero@118-124@..\src\qf\qf_act.cpp - 24 6 155 1 29 QF_LOG2@140-168@..\src\qf\qf_act.cpp - 79 13 387 2 114 QP::QActive::post_@92-205@..\src\qf\qf_actq.cpp - 42 7 230 1 63 QP::QActive::postLIFO@221-283@..\src\qf\qf_actq.cpp - 34 3 199 1 46 QP::QActive::get_@304-349@..\src\qf\qf_actq.cpp - 10 2 68 1 13 QP::QF::getQueueMin@369-381@..\src\qf\qf_actq.cpp - 5 1 30 1 6 QP::QTicker::QTicker@384-389@..\src\qf\qf_actq.cpp - 7 1 41 2 7 QP::QTicker::init@391-397@..\src\qf\qf_actq.cpp - 14 2 88 2 16 QP::QTicker::dispatch@399-414@..\src\qf\qf_actq.cpp - 27 3 146 2 39 QP::QTicker::post_@424-462@..\src\qf\qf_actq.cpp - 4 1 26 1 4 QP::QTicker::postLIFO@465-468@..\src\qf\qf_actq.cpp - 12 1 79 2 14 QP::QActive::defer@75-88@..\src\qf\qf_defer.cpp - 32 3 157 1 49 QP::QActive::recall@111-159@..\src\qf\qf_defer.cpp - 11 2 62 1 11 QP::QActive::flushDeferred@176-186@..\src\qf\qf_defer.cpp + 47 7 318 2 68 QP::QHsm::init@141-208@..\src\qf\qep_hsm.cpp + 5 1 37 2 5 QP::QHsm::top@229-233@..\src\qf\qep_hsm.cpp + 102 15 608 2 154 QP::QHsm::dispatch@250-403@..\src\qf\qep_hsm.cpp + 95 15 460 2 129 QP::QHsm::hsm_tran@420-548@..\src\qf\qep_hsm.cpp + 3 1 13 0 3 QP::QHsm::getStateHandler@552-554@..\src\qf\qep_hsm.cpp + 16 3 85 1 23 QP::QHsm::isIn@573-595@..\src\qf\qep_hsm.cpp + 20 4 108 1 29 QP::QHsm::childState@619-647@..\src\qf\qep_hsm.cpp + 6 1 29 1 6 QP::QMsm::QMsm@74-79@..\src\qf\qep_msm.cpp + 22 3 168 2 36 QP::QMsm::init@92-127@..\src\qf\qep_msm.cpp + 3 1 21 1 3 QP::QMsm::init@139-141@..\src\qf\qep_msm.cpp + 113 21 661 2 166 QP::QMsm::dispatch@154-319@..\src\qf\qep_msm.cpp + 3 1 15 0 3 QP::QMsm::getStateHandler@326-328@..\src\qf\qep_msm.cpp + 51 9 298 2 64 QP::QMsm::execTatbl_@345-408@..\src\qf\qep_msm.cpp + 21 4 116 3 28 QP::QMsm::exitToTranSource_@420-447@..\src\qf\qep_msm.cpp + 43 6 236 2 54 QP::QMsm::enterHistory_@461-514@..\src\qf\qep_msm.cpp + 13 3 59 1 14 QP::QMsm::isInState@529-542@..\src\qf\qep_msm.cpp + 21 4 90 1 28 QP::QMsm::childStateObj@559-586@..\src\qf\qep_msm.cpp + 9 3 72 1 10 QP::QF::add_@68-77@..\src\qf\qf_act.cpp + 10 3 80 1 11 QP::QF::remove_@92-102@..\src\qf\qf_act.cpp + 7 2 61 2 7 QP::QF::bzero@117-123@..\src\qf\qf_act.cpp + 24 6 155 1 29 QF_LOG2@139-167@..\src\qf\qf_act.cpp + 79 13 387 2 114 QP::QActive::post_@91-204@..\src\qf\qf_actq.cpp + 42 7 230 1 63 QP::QActive::postLIFO@220-282@..\src\qf\qf_actq.cpp + 34 3 199 1 46 QP::QActive::get_@303-348@..\src\qf\qf_actq.cpp + 10 2 68 1 13 QP::QF::getQueueMin@368-380@..\src\qf\qf_actq.cpp + 5 1 30 1 6 QP::QTicker::QTicker@383-388@..\src\qf\qf_actq.cpp + 7 1 41 2 7 QP::QTicker::init@390-396@..\src\qf\qf_actq.cpp + 14 2 88 2 16 QP::QTicker::dispatch@398-413@..\src\qf\qf_actq.cpp + 3 1 22 1 3 QP::QTicker::init@415-417@..\src\qf\qf_actq.cpp + 27 3 146 2 39 QP::QTicker::post_@427-465@..\src\qf\qf_actq.cpp + 4 1 26 1 4 QP::QTicker::postLIFO@468-471@..\src\qf\qf_actq.cpp + 12 1 79 2 14 QP::QActive::defer@74-87@..\src\qf\qf_defer.cpp + 32 3 157 1 49 QP::QActive::recall@110-158@..\src\qf\qf_defer.cpp + 11 2 62 1 11 QP::QActive::flushDeferred@175-185@..\src\qf\qf_defer.cpp 16 3 133 3 24 QP::QF::poolInit@82-105@..\src\qf\qf_dyn.cpp 39 7 268 3 55 QP::QF::newX_@133-187@..\src\qf\qf_dyn.cpp 35 5 244 1 57 QP::QF::gc@212-268@..\src\qf\qf_dyn.cpp @@ -107,8 +109,8 @@ 17 2 105 2 23 QP::QMPool::put@171-193@..\src\qf\qf_mem.cpp 42 4 206 2 65 QP::QMPool::get@224-288@..\src\qf\qf_mem.cpp 10 3 71 1 13 QP::QF::getPoolMin@303-315@..\src\qf\qf_mem.cpp - 7 1 42 2 11 QP::QF::psInit@86-96@..\src\qf\qf_ps.cpp - 90 17 587 1 202 QP::QF::publish_@116-317@..\src\qf\qf_ps.cpp + 7 1 42 2 11 QP::QF::psInit@85-95@..\src\qf\qf_ps.cpp + 90 17 587 1 202 QP::QF::publish_@115-316@..\src\qf\qf_ps.cpp 7 3 47 1 12 QP::QActive::QActive@37-48@..\src\qf\qf_qact.cpp 9 1 44 1 9 QP::QEQueue::QEQueue@55-63@..\src\qf\qf_qeq.cpp 13 2 74 2 13 QP::QEQueue::init@81-93@..\src\qf\qf_qeq.cpp @@ -117,82 +119,83 @@ 36 4 188 1 46 QP::QEQueue::get@281-326@..\src\qf\qf_qeq.cpp 5 1 22 1 5 QP::QMActive::QMActive@59-63@..\src\qf\qf_qmact.cpp 4 1 41 2 4 QP::QMActive::init@66-69@..\src\qf\qf_qmact.cpp - 5 1 32 2 5 QP::QMActive::dispatch@71-75@..\src\qf\qf_qmact.cpp - 3 1 27 1 3 QP::QMActive::isInState@78-80@..\src\qf\qf_qmact.cpp - 6 1 27 1 6 QP::QMActive::childStateObj@82-87@..\src\qf\qf_qmact.cpp - 3 1 20 0 3 QP::QMActive::getStateHandler@92-94@..\src\qf\qf_qmact.cpp - 67 7 352 1 99 QP::QF::tickX_@79-177@..\src\qf\qf_time.cpp - 14 3 70 1 17 QP::QF::noTimeEvtsActiveX@192-208@..\src\qf\qf_time.cpp - 16 2 104 3 32 QP::QTimeEvt::QTimeEvt@221-252@..\src\qf\qf_time.cpp - 13 1 53 0 29 QP::QTimeEvt::QTimeEvt@258-286@..\src\qf\qf_time.cpp - 33 8 211 2 59 QP::QTimeEvt::armX@315-373@..\src\qf\qf_time.cpp - 31 3 150 1 40 QP::QTimeEvt::disarm@391-430@..\src\qf\qf_time.cpp - 33 8 205 1 61 QP::QTimeEvt::rearm@452-512@..\src\qf\qf_time.cpp - 5 1 28 1 5 QP::QTimeEvt::wasDisarmed@534-538@..\src\qf\qf_time.cpp - 7 1 28 1 8 QP::QTimeEvt::currCtr@553-560@..\src\qf\qf_time.cpp - 11 2 79 1 16 QP::QF::init@71-86@..\src\qk\qk.cpp - 3 1 14 1 4 QP::QF::stop@104-107@..\src\qk\qk.cpp - 6 2 26 1 8 QP::initial_events@112-119@..\src\qk\qk.cpp - 12 3 49 1 19 QP::QF::run@130-148@..\src\qk\qk.cpp - 21 5 144 6 30 QP::QActive::start@166-195@..\src\qk\qk.cpp - 21 2 136 1 32 QP::QK::schedLock@220-251@..\src\qk\qk.cpp - 22 4 147 1 33 QP::QK::schedUnlock@270-302@..\src\qk\qk.cpp - 14 3 94 1 17 QK_sched_@322-338@..\src\qk\qk.cpp - 59 15 397 1 103 QK_activate_@349-451@..\src\qk\qk.cpp - 9 2 67 1 13 QP::QF::init@77-89@..\src\qv\qv.cpp - 3 1 12 1 4 QP::QF::stop@107-110@..\src\qv\qv.cpp - 38 9 200 1 75 QP::QF::run@128-202@..\src\qv\qv.cpp - 15 3 114 6 22 QP::QActive::start@220-241@..\src\qv\qv.cpp - 2 1 10 0 2 QP::QXKIdleThread::QXKIdleThread@64-65@..\src\qxk\qxk.cpp - 14 2 105 1 22 QP::QF::init@80-101@..\src\qxk\qxk.cpp - 3 1 12 1 4 QP::QF::stop@119-122@..\src\qxk\qxk.cpp - 6 2 26 1 8 QP::initial_events@127-134@..\src\qxk\qxk.cpp - 12 3 49 1 20 QP::QF::run@143-162@..\src\qxk\qxk.cpp - 23 6 158 6 32 QP::QActive::start@179-210@..\src\qxk\qxk.cpp - 23 3 148 1 33 QP::QXK::schedLock@233-265@..\src\qxk\qxk.cpp - 22 4 147 1 34 QP::QXK::schedUnlock@288-321@..\src\qxk\qxk.cpp - 48 7 279 1 67 QXK_sched_@341-407@..\src\qxk\qxk.cpp - 74 16 510 1 130 QXK_activate_@418-547@..\src\qxk\qxk.cpp - 12 2 70 1 18 QXK_current@550-567@..\src\qxk\qxk.cpp - 16 4 108 1 24 QP::QXMutex::init@83-106@..\src\qxk\qxk_mutex.cpp - 66 12 472 1 108 QP::QXMutex::lock@128-235@..\src\qxk\qxk_mutex.cpp - 45 10 283 1 69 QP::QXMutex::tryLock@255-323@..\src\qxk\qxk_mutex.cpp - 65 16 457 1 112 QP::QXMutex::unlock@342-453@..\src\qxk\qxk_mutex.cpp - 8 1 58 2 10 QP::QXSemaphore::init@76-85@..\src\qxk\qxk_sema.cpp - 43 7 277 1 69 QP::QXSemaphore::wait@108-176@..\src\qxk\qxk_sema.cpp - 15 2 55 1 20 QP::QXSemaphore::tryWait@191-210@..\src\qxk\qxk_sema.cpp - 27 6 175 1 46 QP::QXSemaphore::signal@230-275@..\src\qxk\qxk_sema.cpp - 8 1 54 2 8 QP::QXThread::QXThread@84-91@..\src\qxk\qxk_xthr.cpp - 7 1 40 2 7 QP::QXThread::init@95-101@..\src\qxk\qxk_xthr.cpp - 7 1 40 2 7 QP::QXThread::dispatch@104-110@..\src\qxk\qxk_xthr.cpp - 25 6 191 6 44 QP::QXThread::start@133-176@..\src\qxk\qxk_xthr.cpp - 94 13 462 2 127 QP::QXThread::post_@215-341@..\src\qxk\qxk_xthr.cpp - 4 1 26 1 4 QP::QXThread::postLIFO@352-355@..\src\qxk\qxk_xthr.cpp - 58 7 418 1 84 QP::QXThread::queueGet@377-460@..\src\qxk\qxk_xthr.cpp - 5 1 50 1 6 QP::QXThread::block_@469-474@..\src\qxk\qxk_xthr.cpp - 8 3 59 1 9 QP::QXThread::unblock_@483-491@..\src\qxk\qxk_xthr.cpp - 18 3 135 2 33 QP::QXThread::teArm_@501-533@..\src\qxk\qxk_xthr.cpp - 11 2 42 1 14 QP::QXThread::teDisarm_@542-555@..\src\qxk\qxk_xthr.cpp - 21 4 175 1 36 QP::QXThread::delay@571-606@..\src\qxk\qxk_xthr.cpp - 14 2 58 1 16 QP::QXThread::delayCancel@618-633@..\src\qxk\qxk_xthr.cpp - 14 2 110 1 23 QXK_threadRet_@650-672@..\src\qxk\qxk_xthr.cpp - 3 1 16 1 3 QP::QF_EVT_POOL_ID_@140-142@..\src\qf_pkg.hpp - 3 1 16 1 3 QP::QF_EVT_REF_CTR_@145-147@..\src\qf_pkg.hpp - 3 1 21 1 3 QP::QF_EVT_REF_CTR_INC_@150-152@..\src\qf_pkg.hpp - 3 1 21 1 3 QP::QF_EVT_REF_CTR_DEC_@155-157@..\src\qf_pkg.hpp + 4 1 33 1 4 QP::QMActive::init@71-74@..\src\qf\qf_qmact.cpp + 5 1 32 2 5 QP::QMActive::dispatch@76-80@..\src\qf\qf_qmact.cpp + 3 1 27 1 3 QP::QMActive::isInState@83-85@..\src\qf\qf_qmact.cpp + 6 1 27 1 6 QP::QMActive::childStateObj@87-92@..\src\qf\qf_qmact.cpp + 3 1 20 0 3 QP::QMActive::getStateHandler@97-99@..\src\qf\qf_qmact.cpp + 67 7 352 1 99 QP::QF::tickX_@78-176@..\src\qf\qf_time.cpp + 14 3 70 1 17 QP::QF::noTimeEvtsActiveX@191-207@..\src\qf\qf_time.cpp + 16 2 104 3 32 QP::QTimeEvt::QTimeEvt@220-251@..\src\qf\qf_time.cpp + 13 1 53 0 29 QP::QTimeEvt::QTimeEvt@257-285@..\src\qf\qf_time.cpp + 33 8 211 2 59 QP::QTimeEvt::armX@314-372@..\src\qf\qf_time.cpp + 31 3 150 1 40 QP::QTimeEvt::disarm@390-429@..\src\qf\qf_time.cpp + 33 8 205 1 61 QP::QTimeEvt::rearm@451-511@..\src\qf\qf_time.cpp + 5 1 28 1 5 QP::QTimeEvt::wasDisarmed@533-537@..\src\qf\qf_time.cpp + 7 1 28 1 8 QP::QTimeEvt::currCtr@552-559@..\src\qf\qf_time.cpp + 11 2 79 1 16 QP::QF::init@70-85@..\src\qk\qk.cpp + 3 1 14 1 4 QP::QF::stop@103-106@..\src\qk\qk.cpp + 6 2 26 1 8 QP::initial_events@111-118@..\src\qk\qk.cpp + 12 3 49 1 19 QP::QF::run@129-147@..\src\qk\qk.cpp + 21 5 144 6 30 QP::QActive::start@165-194@..\src\qk\qk.cpp + 21 2 136 1 32 QP::QK::schedLock@219-250@..\src\qk\qk.cpp + 22 4 147 1 33 QP::QK::schedUnlock@269-301@..\src\qk\qk.cpp + 14 3 94 1 17 QK_sched_@321-337@..\src\qk\qk.cpp + 59 15 397 1 103 QK_activate_@348-450@..\src\qk\qk.cpp + 9 2 67 1 13 QP::QF::init@76-88@..\src\qv\qv.cpp + 3 1 12 1 4 QP::QF::stop@106-109@..\src\qv\qv.cpp + 38 9 200 1 75 QP::QF::run@127-201@..\src\qv\qv.cpp + 15 3 114 6 22 QP::QActive::start@219-240@..\src\qv\qv.cpp + 2 1 10 0 2 QP::QXKIdleThread::QXKIdleThread@63-64@..\src\qxk\qxk.cpp + 14 2 105 1 22 QP::QF::init@79-100@..\src\qxk\qxk.cpp + 3 1 12 1 4 QP::QF::stop@118-121@..\src\qxk\qxk.cpp + 6 2 26 1 8 QP::initial_events@126-133@..\src\qxk\qxk.cpp + 12 3 49 1 20 QP::QF::run@142-161@..\src\qxk\qxk.cpp + 23 6 158 6 32 QP::QActive::start@178-209@..\src\qxk\qxk.cpp + 23 3 148 1 33 QP::QXK::schedLock@232-264@..\src\qxk\qxk.cpp + 22 4 147 1 34 QP::QXK::schedUnlock@287-320@..\src\qxk\qxk.cpp + 48 7 279 1 67 QXK_sched_@340-406@..\src\qxk\qxk.cpp + 74 16 510 1 130 QXK_activate_@417-546@..\src\qxk\qxk.cpp + 12 2 70 1 18 QXK_current@549-566@..\src\qxk\qxk.cpp + 16 4 108 1 24 QP::QXMutex::init@82-105@..\src\qxk\qxk_mutex.cpp + 66 12 472 1 108 QP::QXMutex::lock@127-234@..\src\qxk\qxk_mutex.cpp + 45 10 283 1 69 QP::QXMutex::tryLock@254-322@..\src\qxk\qxk_mutex.cpp + 65 16 457 1 112 QP::QXMutex::unlock@341-452@..\src\qxk\qxk_mutex.cpp + 8 1 58 2 10 QP::QXSemaphore::init@75-84@..\src\qxk\qxk_sema.cpp + 43 7 277 1 69 QP::QXSemaphore::wait@107-175@..\src\qxk\qxk_sema.cpp + 15 2 55 1 20 QP::QXSemaphore::tryWait@190-209@..\src\qxk\qxk_sema.cpp + 27 6 175 1 46 QP::QXSemaphore::signal@229-274@..\src\qxk\qxk_sema.cpp + 8 1 54 2 8 QP::QXThread::QXThread@83-90@..\src\qxk\qxk_xthr.cpp + 7 1 40 2 7 QP::QXThread::init@94-100@..\src\qxk\qxk_xthr.cpp + 7 1 40 2 7 QP::QXThread::dispatch@103-109@..\src\qxk\qxk_xthr.cpp + 25 6 191 6 44 QP::QXThread::start@132-175@..\src\qxk\qxk_xthr.cpp + 94 13 462 2 127 QP::QXThread::post_@214-340@..\src\qxk\qxk_xthr.cpp + 4 1 26 1 4 QP::QXThread::postLIFO@351-354@..\src\qxk\qxk_xthr.cpp + 58 7 418 1 84 QP::QXThread::queueGet@376-459@..\src\qxk\qxk_xthr.cpp + 5 1 50 1 6 QP::QXThread::block_@468-473@..\src\qxk\qxk_xthr.cpp + 8 3 59 1 9 QP::QXThread::unblock_@482-490@..\src\qxk\qxk_xthr.cpp + 18 3 135 2 33 QP::QXThread::teArm_@500-532@..\src\qxk\qxk_xthr.cpp + 11 2 42 1 14 QP::QXThread::teDisarm_@541-554@..\src\qxk\qxk_xthr.cpp + 21 4 175 1 36 QP::QXThread::delay@570-605@..\src\qxk\qxk_xthr.cpp + 14 2 58 1 16 QP::QXThread::delayCancel@617-632@..\src\qxk\qxk_xthr.cpp + 14 2 110 1 23 QXK_threadRet_@649-671@..\src\qxk\qxk_xthr.cpp + 3 1 16 1 3 QP::QF_EVT_POOL_ID_@139-141@..\src\qf_pkg.hpp + 3 1 16 1 3 QP::QF_EVT_REF_CTR_@144-146@..\src\qf_pkg.hpp + 3 1 21 1 3 QP::QF_EVT_REF_CTR_INC_@149-151@..\src\qf_pkg.hpp + 3 1 21 1 3 QP::QF_EVT_REF_CTR_DEC_@154-156@..\src\qf_pkg.hpp 37 file analyzed. ============================================================== NLOC Avg.NLOC AvgCCN Avg.token function_cnt file -------------------------------------------------------------- 4 0.0 0.0 0.0 0 ..\include\qassert.h - 226 4.0 1.0 21.1 21 ..\include\qep.hpp + 227 4.0 1.0 21.1 21 ..\include\qep.hpp 40 3.0 1.0 11.7 3 ..\include\qequeue.hpp - 192 2.9 1.0 18.8 9 ..\include\qf.hpp + 194 2.9 1.0 18.8 9 ..\include\qf.hpp 32 3.0 1.0 10.0 1 ..\include\qk.hpp 37 3.0 1.0 11.0 1 ..\include\qmpool.hpp 5 0.0 0.0 0.0 0 ..\include\qpcpp.hpp 72 4.3 1.4 34.8 14 ..\include\qpset.hpp - 306 7.5 1.5 42.0 4 ..\include\qs.hpp + 308 7.5 1.5 42.0 4 ..\include\qs.hpp 5 0.0 0.0 0.0 0 ..\include\qstamp.cpp 4 0.0 0.0 0.0 0 ..\include\qstamp.hpp 21 3.0 1.0 19.0 1 ..\include\qs_dummy.hpp @@ -201,16 +204,16 @@ NLOC Avg.NLOC AvgCCN Avg.token function_cnt file 32 0.0 0.0 0.0 0 ..\include\qxk.hpp 66 4.5 1.0 35.5 2 ..\include\qxthread.hpp 317 29.6 4.9 168.2 10 ..\src\qf\qep_hsm.cpp - 310 32.6 5.8 185.8 9 ..\src\qf\qep_msm.cpp + 313 29.6 5.3 169.3 10 ..\src\qf\qep_msm.cpp 64 12.5 3.5 92.0 4 ..\src\qf\qf_act.cpp - 238 24.7 3.7 135.0 9 ..\src\qf\qf_actq.cpp + 241 22.5 3.4 123.7 10 ..\src\qf\qf_actq.cpp 66 18.3 2.0 99.3 3 ..\src\qf\qf_defer.cpp 135 20.3 3.2 140.2 6 ..\src\qf\qf_dyn.cpp 120 21.8 3.0 131.8 5 ..\src\qf\qf_mem.cpp 109 48.5 9.0 314.5 2 ..\src\qf\qf_ps.cpp 10 7.0 3.0 47.0 1 ..\src\qf\qf_qact.cpp 160 29.8 4.0 150.6 5 ..\src\qf\qf_qeq.cpp - 32 4.3 1.0 28.2 6 ..\src\qf\qf_qmact.cpp + 36 4.3 1.0 28.9 7 ..\src\qf\qf_qmact.cpp 233 24.3 3.8 133.4 9 ..\src\qf\qf_time.cpp 184 18.8 4.1 120.7 9 ..\src\qk\qk.cpp 79 16.2 3.8 98.2 4 ..\src\qv\qv.cpp @@ -227,10 +230,10 @@ NLOC Avg.NLOC AvgCCN Avg.token function_cnt file ================================================ NLOC CCN token PARAM length location ------------------------------------------------ - 113 21 661 2 166 QP::QMsm::dispatch@141-306@..\src\qf\qep_msm.cpp + 113 21 661 2 166 QP::QMsm::dispatch@154-319@..\src\qf\qep_msm.cpp ========================================================================================== Total nloc Avg.NLOC AvgCCN Avg.token Fun Cnt Warning cnt Fun Rt nloc Rt ------------------------------------------------------------------------------------------ - 4058 16.8 3.1 101.5 175 1 0.01 0.04 + 4073 16.5 3.1 100.2 178 1 0.01 0.04 @endcode */ diff --git a/doxygen/ports.dox b/doxygen/ports.dox index ae21b8f51..122f7928b 100644 --- a/doxygen/ports.dox +++ b/doxygen/ports.dox @@ -1,10 +1,13 @@ /*! @page ports Ports +@tableofcontents @section ports_gen General Comments The QP/C++ framework can be easily adapted to various operating systems, processor architectures, and compilers. Adapting the QP/C++ software is called porting and the QP/C++ framework has been designed from the ground up to make porting easy. The QP/C++ distribution contains many QP/C++ ports, which are organized into the three categories: +- @subpage ports_lint (generic C compiler) QP/C++ "port" to the PC-Lint Plus static analysis tool (a "compiler") + - @subpage ports_native "Native Ports" adapt QP/C++ to run on bare-metal processors "natively", using one of the built-in kernels (@ref qv "QV", @ref qk "QK", or @ref qxk "QXK") - @subpage ports_rtos "3rd-Party RTOS Ports" adapt QP/C++ to run on top of a 3rd-Party Real-Time Operating System (RTOS) @@ -12,7 +15,6 @@ The QP/C++ distribution contains many QP/C++ ports, which are organized into the - @subpage ports_os "3rd-Party OS Ports" adapt QP/C++ to run on top of a 3rd-Party Operating System (OS), such as @ref win32 "Windows" or @ref posix "Linux". - @section ports_code Port Code Structure Starting with QP/C++ release 5.4.0, **all** available ports are bundled into the QP/C++ download, as opposed to being distributed as separate QP Development Kits (QDKs). The main benefit is of this approach is that it greatly reduces chances of mistakes in combining the mainline QP/C++ code with various QDKs. The downside is that the QP/C++ distribution becomes quite large and that ports cannot be added or updated independently from the QP/C++ baseline code. @@ -61,7 +63,7 @@ All ports are located in sub-directories of the ports
    -
  • ucos-ii/ — Port to uCOS-II (3rd-party RTOS)       B +
  • uc-os2/ — Port to uc-os2 (3rd-party RTOS)       B
    • arm-cm — Port to ARM-Cortex-M @@ -108,7 +110,7 @@ All ports are located in sub-directories of the portsA **Native Ports** are located in sub-directories named after the CPU architecture, such as arm-cm for ARM Cortex-M. Under that directory, the sub-directories qk and qv contain ports for the @ref comp_qk "QK" and @ref comp_qv "QV" kernels, respectively.
    • -
    • B **Ports for 3rd-party RTOS** are located in sub-directories named after the RTOS, such as ucos-ii for uCOS-II RTOS. Under that directory, the sub-directories, such as arm-cm, contain examples for the specified CPU architecture, such as ARM Cortex-M here. +
    • B **Ports for 3rd-party RTOS** are located in sub-directories named after the RTOS, such as uc-os2 for uc-os2 RTOS. Under that directory, the sub-directories, such as arm-cm, contain examples for the specified CPU architecture, such as ARM Cortex-M here.
    • C **Ports for 3rd-party OS** are located in sub-directories named after the OS, such as win32 for the Win32 API (Windows OS). (NOTE: The builds for desktop operating systems, such as Windows or Linux contain the pre-build QP libraries for the Debug, Release, and Spy build configurations). @@ -118,6 +120,108 @@ All ports are located in sub-directories of the portsports folder may seem daunting. However, knowing the structure of the ports folder, you can simply **delete** the sub-directories that are not interesting to you. +@nav_next{ports_lint} +*/ +/*##########################################################################*/ +/*! @page ports_lint PC-Lint-Plus +@tableofcontents + +![PC-Lint Plus](logo_pclintplus.jpg) + +The QP/C++ distribution contains a "port" to PC-Lint-Plus static analysis tool from Gimpel Software, which is a static analysis tool for C and C++ with one of the longest track records and best value of the money in the industry. The "PC-Lint-Plus port" allows you to statically analyze the QP/C++ source code and facilitates static analysis of your **application code** based on QP/C++. + +The QP/C++ "port" to PC-Lint-Plus is located in the directory qpcpp/ports/lint-plus and includes also lint configuration files, as well as an example of "linting" application code in the directory qpcpp/examples/arm-cm/dpp_ek-tm4c123gxl/lint-plus. The following listing describes the most important files in these three directories. + +@code{.x} + qpcpp\ - QP/C++ installation directory + | + | +-ports/ - QP/C++ ports directory + | | +-lint-plus/ - QP/C++ "port" to PC-Lint-Plus + | | | +-16bit/ - QP/C++ "port" to 16-bit CPUs + | | | | +-cpu.lnt - Lint options for a 16-bit CPU + | | | | +-cstdint - Standard exact-width integers for a 16-bit CPU + | | | +-32bit/ - QP/C++ "port" to 32-bit CPUs + | | | | +-cpu.lnt - Lint options for a 32-bit CPU + | | | | +-cstdint - Standard exact-width integers for a 32-bit CPU + | | | +-qk/ - QP/C++ port with the QK kernel + | | | +-qv/ - QP/C++ port with the QV kernel + | | | +-qxk/ - QP/C++ port with the QXK kernel + | | | +-au-ds.lnt - Dan Saks recommendations + | | | +-au-misra-cpp.lnt - MISRA-C++:2008 compliance checks + | | | +-qpc.lnt - PC-Lint-Plus options for QP/C++ applications + | | | +-std.lnt - Standard PC-Lint-Plus settings recommended by Quantum Leaps + | | | +-lin.bat - Batch file to invoke PC-Lint-Plus to run analysis of QP/C++ code + | | | +-options.lnt - PC/Lint-Plus options for "linting" QP/C++ source code + | | | +-lint_qf.log - PC/Lint-Plus output for the QEP/QF components of QP/C++ + | | | +-lint_qs.log - PC/Lint-Plus output for the QS component of QP/C++ + | | | +-lint_qv.log - PC/Lint-Plus output for the QV component of QP/C++ + | | | +-lint_qk.log - PC/Lint-Plus output for the QK component of QP/C++ + | | | +-lint_qxk.log - PC/Lint-Plus output for the QXK component of QP/C++ + | | | +-qep_port.hpp - QEP component "port" to a "generic C++ compiler" + | | + | +-examples\ - QP/C++ examples directory (application) + | | +-arm-cm\ - QP/C++ examples for ARM Cortex-M + | | | +-dpp_ek-tm4c123gxl\ - DPP example on the EK-TM4C123GLX board + | | | | +-lint-plus\ - directory for linting the application + | | | | | +-lin.bat - Batch to run PC-Lint-Plus analysis of application code + | | | | | +-options.lnt - PC-Lint-Plus options for "linting" of application code +@endcode + + +@section lint_qpcpp Linting the QP/C++ Source Code +The directory qpcpp/ports/lint-plus (see listing above) contains also the **lin.bat** batch file for "linting" the QP/C++ source code. The `lin.bat` batch file invokes PC-Lint-Plus and generates the lint output files. As shown in the listing above, the lint output is collected into four text files `lint_qf.log`, `lint_qs.log`, `lint_qk.log`, `lint_qv.log`, and `lint_qs.log`, for QEP/QF, QK, QV, QXK and QS components of the QP/C++ framework, respectively. + +@note +In order to execute the `lin.bat` file on your system, you might need to adjust the symbol `PCLP_DIR` at the top of the batch file, to the PC-Lint-Plus installation directory on your computer. + +@remarks +The `lin.bat` batch file invoked without any command-line options checks the QP/C++ code in the ::Q_SPY build configuration with software tracing enabled. However, by the nature of software tracing, the ::Q_SPY configuration transgresses many more MISRA-C++ rules than the standard configuration. However, the ::Q_SPY configuration is never used for production code, so the MISRA-C++ compliance of the QP/C++ framework should not be judged by the deviations that happen only in the ::Q_SPY configuration. + + +According to the PC-Lint-Plus guidelines, the `lin.bat` uses two option files: the `qpcpp.lnt` configuration file discussed before and the `options.lnt` configuration file that covers all deviations from the AUTOSAR-C++ rules **within the QP/C++ source code**. These deviations are intentionally localized to QP/C++ code and are independent from your **application-level** code. In other words, a MISRA-C deviation present in the QP/C++ code does **not** mean that such deviation is somehow allowed or its detection is somehow suppressed in the **application-level** code. This is because the the `options.lnt` configuration file for internals of QP/C is **not** used to "lint" the application-level code. + + +@section lint_app Linting QP/C++ Application Code +The QP/C++ baseline code contains an example of MISRA-C++ compliance checking with PC-Lint-Plus: the DPP example for the EK-TM4C123GLX Cortex-M4F board, located in the directory qpcpp/examples/arm-cm/dpp_ek-tm4c123gxl/lint-plus. The PC-Lint-Plus analysis is very simple and requires invoking the **lin.bat** file. + +@note +In order to execute the **lin.bat** file on your system, you might need to adjust the symbol `PCLP_DIR` at the top of the batch file, to the PC-Lint-Plus installation directory on your computer. You + + +The `lint-plus` subdirectory contains also the local version of the `options.lnt` configuration file with the PC-Lint-Plus options specific to linting the application. Here, you might include linting options for your specific compiler, as described in the "PC-Lint-Plus Manual", Chapter 2 "Installation and Configuration". + + +@section lint_options Structure of PC-Lint-Plus Options for QP/C++ +PC-Lint-Plus has several places where it reads its currently valid options: +- From special PC-Lint-Plus option files (usually called `*.lnt`) +- From the command line +- From within the special lint-comments in the source code modules (not recommended) + +The QP/C++ source code and example application code has been "linted" only by means of the first alternative (option files) with possibility of adding options via command line. The third alternative--lint comments--is not used and Quantum Leaps does not recommend this alternative. + +@note +The QP/C++ source code is completely free of lint comments, which are viewed as a contamination of the source code. + +The structure of the PC-Lint-Plus option files used for "linting" QP/C++ follows exactly the Gimpel Software guidelines for configuring PC-Lint-Plus (See Section 2 "Configuration" in the *PC-Lint-Plus Manual*). The design and grouping of the lint options also reflects the fact that static code analysis of a software framework, such as QP/C++, has really two major aspects. First, the source code of the framework itself has to be analyzed. But even more important and helpful to the users of the framework is providing the infrastructure to effectively analyze the application-level code based on the framework. With this in mind, the PC-Lint-Plus options for static analysis of QP/C++ are divided into two groups, located in directories qpcpp/include and qpcpp/ports/lint. These two groups are for analyzing QP/C++ **applications** and QP/C++ **source code**, respectively. + +As shown in the PC-Lint-Plus "port" files description, the directory qpcpp/include, contains the PC-Lint-Plus options for "linting" the application code along with all platform-independent QP/C++ header files required by the applications. This collocation of lint options with header files simplifies "linting", because specifying just `-iqpcpp/include` include directory to PC-Lint-Plus accomplishes both inclusion of QP/C++ header files and PC-Lint-Plus options. +Note that the `qpc/include` directory contains all PC-Lint-Plus option files used in "linting" the code, including the standard MISRA-C++:2008 `au-misra-cpp.lnt` option file as well as Dan Saks' recommendations `au-ds.lnt`, which are copied from the PC-Lint-Plus distribution. This design freezes the lint options for which the compliance has been checked. + + +@subsection lint_std_lnt The std.lnt option file +According to the Gimpel Software *PC-Lint-Plus Configuration Guidelines*, the file `qpcpp/include/std.lnt` file, contains the top-level options, which Quantum Leaps recommends for all projects. These options include the formatting of the PC-Lint-Plus messages and making two passes to perform better cross-module analysis. However, the most important option is `-restore_at_end`, which has the effect of surrounding each source file with options `-save` and `-restore`. This precaution prevents options from "bleeding" from one file to another. + +Top-level option file std.lnt +@include std.lnt + + +@subsection lint_qpcpp_lnt The qpcpp.lnt option file +The most important file for "linting" QP/C++ applications is the **qpcpp.lnt** option file. This file handles all deviations from the MISRA-C++:2008 rules, which might arise at the application-level code from the use of the QP/C++ framework. In other words, the **qpcpp.lnt** option file allows completely clean "linting" of the application-level code, as long as the application code does not violate any of the MISRA-C++:2008 rules. + +At the same time, the **qpcpp.lnt** option file has been very carefully designed not to suppress any MISRA-C++:2008 rule checking outside the very specific context of the QP/C++ API. In other words, the qpcpp.lnt option file still supports 100% of the MISRA-C++:2008 rule checks that PC-Lint-Plus is capable of performing. + +@remarks +For example, for reasons explained in Section 5.10 of the "QP/C++ MISRA Compliance Matrix", QP/C++ extensively uses function-like macros, which deviates from the MISRA-C++:2008 Rule 16-0-4 and which PC-Lint-Plus checks with the warning 9026. However, instead of suppressing this warning globally (with the -e9096 directive), the qpcpp.lnt option file suppresses warning 9096 only for the specific QP function-like macros that are visible to the application level. So specifically, the `qpcpp.lnt` file contains directives `-esym(9026, Q_TRAN, Q_SUPER, ...)`, which suppresses the warning only for the specified macros, but does not disable checking of any other macros in the application-level code. -@next{ports_native} +@nav_next{ports_native} */ diff --git a/doxygen/ports_arm-cm.dox b/doxygen/ports_arm-cm.dox index a7c91478e..c8a4b3c5f 100644 --- a/doxygen/ports_arm-cm.dox +++ b/doxygen/ports_arm-cm.dox @@ -1,14 +1,8 @@ /*##########################################################################*/ /*! @page arm-cm ARM Cortex-M - -@htmlonly - -@endhtmlonly - @tableofcontents -

      This section describes the QP™ ports to the ARM Cortex-M processor family (Cortex M0/M0+/M3/M4/M7/M33). Three main implementation options are covered: the @subpage arm-cm_qv "cooperative, priority-based QV kernel", the @subpage arm-cm_qk "preemptive, run-to-completion QK kernel", and the @subpage arm-cm_qxk "preemptive, dual-mode blocking QXK kernel". Additionally, the use of the VFP (floating point coprocessor) in the M4F/M7 CPUs is explained as well. This document assumes QP version 7.x or higher. -

      +This section describes the QP™ ports to the ARM Cortex-M processor family (Cortex M0/M0+/M3/M4/M7/M33). Three main implementation options are covered: the @subpage arm-cm_qv "cooperative, priority-based QV kernel", the @subpage arm-cm_qk "preemptive, run-to-completion QK kernel", and the @subpage arm-cm_qxk "preemptive, dual-mode blocking QXK kernel". Additionally, the use of the VFP (floating point coprocessor) in the M4F/M7/M33 CPUs is explained as well. This document assumes QP version 7.x or higher. @note To focus the discussion, this section references the **GNU-ARM toolchain**, the EK-TM4C123GXL (ARM Cortex-M4F) and the Eclipse-based IDE (CCS from Texas Instruments). However, the general implementation strategy applies equally to all toolchains for ARM Cortex-M, such as **ARM-KEIL**, **IAR EWARM**, **GNU-ARM** and **TI-ARM**, which are all supported as well. The QP code downloads contain also examples for other boards, such as STM32 Nucleo, NXP mbed-1768, SilLabs Gecko and others. @@ -18,69 +12,48 @@ To focus the discussion, this section references the **GNU-ARM toolchain**, the @section arm-cm_files Directories and Files The QP ports to ARM Cortex-M are available in the standard QP distribution. Specifically, the ARM Cortex-M ports are placed in the following directories: -
        -
      • /pors/arm-cm/ -
      • -
          -
        • qv/ — QV ports -
        • -
            -
          • arm/ — ARM-KEIL toolchain -
          • -
          • armclang/ — ARM-KEIL toolchain CLANG/LLVM compiler -
          • -
          • gnu/ — GNU-ARM toolchain -
              -
            • qep_port.h — QEP port header -
            • -
            • qf_port.h — QF port header -
            • -
            • qv_port.h — QV port header -
            • -
            • qv_port.c/.cpp — QV port implementation -
            • -
            -
          • -
          • iar/ — IAR-EWARM toolchain -
          • -
          -
        • qk/ — QK ports -
        • -
            -
          • arm/ — ARM-KEIL toolchain -
          • -
          • armclang/ — ARM-KEIL toolchain CLANG/LLVM compiler -
          • -
          • gnu/ — GNU-ARM toolchain -
          • -
          • iar/ — IAR-EWARM toolchain -
          • -
          -
        • qxk/ — QXK ports" -
        • -
            -
          • arm/ — ARM-KEIL toolchain -
          • -
          • armclang/ — ARM-KEIL toolchain CLANG/LLVM compiler -
          • -
          • gnu/ — GNU-ARM toolchain -
          • -
          • iar/ — IAR-EWARM toolchain -
          • -
          -
        • qutest/QUTest Unit Testing port to Cortex-M" -
        • -
        -
      +@verbatim +qpc/ports/arm-cm - QP/C ports to ARM Cortex-M +├───qk - QP/C ports to QK preemptive kernel +│ ├───armclang - ports for ARM-CLANG (LLVM) +│ │ ├───qep_port.h - QEP port +│ │ ├───qf_port.h - QF ports +│ │ ├───qk_port.h - QK ports +│ │ └───qk_port.c - QK port implementation +│ ├───gnu - ports for GNU-ARM +│ │ └───... +│ └───iar - ports for IAR EWARM +│ │ └───... +├───qutest - QP/C ports to QUTest testing harness +├───qv - QP/C ports to QV cooperative kernel +│ ├───armclang - ports for ARM-CLANG (LLVM) +│ │ ├───qep_port.h - QEP port +│ │ ├───qf_port.h - QF ports +│ │ ├───qk_port.h - QK ports +│ │ └───qk_port.c - QK port implementation +│ ├───gnu - ports for GNU-ARM +│ │ └───... +│ └───iar - ports for IAR EWARM +│ │ └───... +└───qxk +│ ├───armclang - ports for ARM-CLANG (LLVM) +│ │ ├───qep_port.h - QEP port +│ │ ├───qf_port.h - QF ports +│ │ ├───qk_port.h - QK ports +│ │ └───qk_port.c - QK port implementation +│ ├───gnu - ports for GNU-ARM +│ │ └───... +│ └───iar - ports for IAR EWARM +│ │ └───... +@endverbatim @section arm-cm_int Interrupts in the QP Ports to ARM Cortex-M The QP real-time framework, like any real-time kernel, needs to disable interrupts in order to access critical sections of code and re-enable interrupts when done. This section describes the general policy used in the ARM Cortex-M ports of all built-in real time kernels in QP, such as QV, QK, and QXK. -
      @subsection arm-cm_kernel-aware "Kernel-Aware" and "Kernel-Unaware" Interrupts -The QP ports to ARM Cortex-M3/M4/M7 **never completely disables interrupts**, even inside the critical sections. On Cortex-M3/M4/M7 (ARMv7-M architecture), the QP port disables interrupts **selectively** using the BASEPRI register. This policy divides interrupts into "kernel-unaware" interrupts, which are never disabled, and "kernel-aware" interrupts, which are disabled in the QP critical sections. +The QP ports to ARMv7M or higher architectures **never completely disables interrupts**, even inside the critical sections. On ARMv7M or higher architectures, the QP port disables interrupts **selectively** using the BASEPRI register. This policy divides interrupts into "kernel-unaware" interrupts, which are never disabled, and "kernel-aware" interrupts, which are disabled in the QP critical sections. @note The BASEPRI register is not implemented in the ARMv6-M architecture (Cortex-M0/M0+), so Cortex-M0/M0+ CPUs need to use the PRIMASK register to disable interrupts globally. In other words, in the QP ports to Cortex-M0/M0+, all interrupts are "kernel-aware". @@ -92,11 +65,12 @@ Only "kernel-aware" interrupts are allowed to call QP services. "Kernel-unaware" As illustrated in the figures below, the number of interrupt priority bits actually available is implementation dependent, meaning that the various ARM Cortex-M silicon vendors can provide different number of priority bits, varying from just 3 bits (which is the minimum for ARMv7-M architecture) up to 8 bits. For example, the TI Tiva-C microcontrollers implement only 3 priority bits (see figure below). -@image html arm-cm_int3bit.png "Kernel-aware and Kernel-unaware interrupts with 3 priority bits +![Kernel-aware and Kernel-unaware interrupts with 3 priority bits](arm-cm_int3bit.png) + -On the other hand, the STM32 MCUs implement 4 priority bits (see figure below). The CMSIS standard provides the macro __NVIC_PRIO_BITS, which specifies the number of NVIC priority bits defined in a given ARM Cortex-M implementation. +On the other hand, the STM32 MCUs implement 4 priority bits (see figure below). The CMSIS standard provides the macro **NVIC_PRIO_BITS**, which specifies the number of NVIC priority bits defined in a given ARM Cortex-M implementation. -@image html arm-cm_int4bit.png "Kernel-aware and Kernel-unaware interrupts with 4 priority bits +![Kernel-aware and Kernel-unaware interrupts with 4 priority bits](arm-cm_int4bit.png) Another important fact to note is that the ARM Cortex-M core stores the interrupt priority values in the *most significant bits* of its eight bit interrupt priority registers inside the NVIC (Nested Vectored Interrupt Controller). For example, if an implementation of a ARM Cortex-M microcontroller only implements three priority bits, then these three bits are shifted to occupy bits five, six and seven respectively. The unimplemented bits can be written as zero or one and always read as zero. @@ -105,24 +79,21 @@ And finally, the NVIC uses an inverted priority numbering scheme for interrupts, @note Starting with QP 5.9.x, the QF_init() call sets interrupt priority of all IRQs to the "kernel aware" value QF_BASEPRI. Still, it is highly recommended to set the priority of all interrupts used by an application **explicitly**, preferably in the `QF_onStartup()`. - @attention Some 3rd-party libraries (e.g., STM32Cube) change the interrupt priorities and sometimes priority grouping internally and unexpectedly, so care must be taken to change the priorities back to the appropriate values right before running the application. - -The CMSIS provides the function @c NVIC_SetPriority() which you should use to set priority of every interrupt. +The CMSIS provides the function `NVIC_SetPriority()` which you should use to set priority of every interrupt. @note The priority scheme passed to `NVIC_SetPriority()` is different again than the values stored in the NVIC registers, as shown in the figures above as "CMSIS priorities" -
      @subsection arm-cm_int-assign Assigning Interrupt Priorities -The @ref exa_arm-cm "example projects" included in the QP distribution the recommended way of assigning interrupt priorities in your applications. The initialization consist of two steps: (1) you enumerate the "kernel-unaware" and "kernel-aware" interrupt priorities, and (2) you assign the priorities by calling the @c NVIC_SetPriority() CMSIS function. The following snippet of code illustrates these steps with the explanation section following immediately after the code. +The @ref exa_arm-cm "example projects" included in the QP distribution the recommended way of assigning interrupt priorities in your applications. The initialization consist of two steps: (1) you enumerate the "kernel-unaware" and "kernel-aware" interrupt priorities, and (2) you assign the priorities by calling the `NVIC_SetPriority()` CMSIS function. The following snippet of code illustrates these steps with the explanation section following immediately after the code. @anchor arm-cm_int-assign-code Listing: Assigning the interrupt priorities (see file bsp.c in the example projects) -@code{c} +@code{.c} /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CAUTION !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! * Assign a priority to EVERY ISR explicitly by calling NVIC_SetPriority(). * DO NOT LEAVE THE ISR PRIORITIES AT THE DEFAULT VALUE! @@ -166,48 +137,48 @@ The @ref exa_arm-cm "example projects" included in the QP distribution the recom } @endcode -
        -
      • 1 +
        +
        1
        The enumeration @c KernelUnawareISRs lists the priority numbers for the "kernel-unaware" interrupts. These priorities start with zero (highest possible). The priorities are suitable as the argument for the @c NVC_SetPriority() CMSIS function. +
        +> NOTE: The NVIC allows you to assign the same priority level to multiple interrupts, so you can have more ISRs than priority levels running as "kernel-unaware" or "kernel-aware" interrupts. -> NOTE: The NVIC allows you to assign the same priority level to multiple interrupts, so you can have more ISRs than priority levels running as "kernel-unaware" or "kernel-aware" interrupts. - -
      • -
      • 2 + +
        2
        The last value in the enumeration MAX_KERNEL_UNAWARE_CMSIS_PRI keeps track of the maximum priority used for a "kernel-unaware" interrupt. -
      • -
      • 3 + +
        3
        The compile-time assertion ensures that the "kernel-unaware" interrupt priorities do not overlap the "kernel-aware" interrupts, which start at QF_AWARE_ISR_CMSIS_PRI. -
      • -
      • 4 + +
        4
        The enumeration KernelAwareISRs lists the priority numbers for the "kernel-aware" interrupts. -
      • -
      • 5 + +
        5
        The "kernel-aware" interrupt priorities start with the QF_AWARE_ISR_CMSIS_PRI offset, which is provided in the qf_port.h header file. -
      • -
      • 6 + +
        6
        The last value in the enumeration MAX_KERNEL_AWARE_CMSIS_PRI keeps track of the maximum priority used for a "kernel-aware" interrupt. -
      • -
      • 7 + +
        7
        The compile-time assertion ensures that the "kernel-aware" interrupt priorities do not overlap the lowest priority level reserved for the PendSV exception. -
      • -
      • 8 + +
        8
        The QF_onStartup() callback function is where you set up the interrupts. -
      • -
      • 9 -This call to the CMIS function @c NVIC_SetPriorityGrouping() assigns all the priority bits to be preempt priority bits, leaving no priority bits as subpriority bits to preserve the direct relationship between the interrupt priorities and the ISR preemption rules. This is the default configuration out of reset for the ARM Cortex-M3/M4 cores, but it can be changed by some vendor-supplied startup code. To avoid any surprises, the call to NVIC_SetPriorityGrouping(0U) is recommended. -
      • -
      • 10-11 -The interrupt priories fall all interrupts ("kernel-unaware" and "kernel-aware" alike) are set explicitly by calls to the CMSIS function @c NVIC_SetPriority(). -
      • -
      • 12 + +
        9
        +This call to the CMIS function `NVIC_SetPriorityGrouping()` assigns all the priority bits to be preempt priority bits, leaving no priority bits as subpriority bits to preserve the direct relationship between the interrupt priorities and the ISR preemption rules. This is the default configuration out of reset for the ARM Cortex-M3/M4 cores, but it can be changed by some vendor-supplied startup code. To avoid any surprises, the call to `NVIC_SetPriorityGrouping(0U)` is recommended. +
        +
        10-11
        +The interrupt priories fall all interrupts ("kernel-unaware" and "kernel-aware" alike) are set explicitly by calls to the CMSIS function `NVIC_SetPriority()`. +
        +
        12
        All used IRQ interrupts need to be explicitly enabled by calling the CMSIS function. -
      • -
      + + + -
      -@subsection arm-cm_int-fpu Interrupts and the FPU (Cortex-M4F/M7) -The QP ports described in this section support also the ARM Cortex-M4F/M7. Compared to all other members of the Cortex-M family, these cores includes the single precision variant of the ARMv7-M Floating-Point Unit (Fpv4-SP). The hardware FPU implementation adds an extra floating-point register bank consisting of S0-S31 and some other FPU registers. This FPU register set represents additional context that need to be preserved across interrupts and thread switching (e.g., in the preemptive QK kernel). +@subsection arm-cm_int-fpu Interrupts and the FPU (ARMv7M or higher architectures) +The QP ports described in this section support also the ARMv7M or higher architectures. Compared to all other members of the Cortex-M family, these cores includes the single precision variant of the ARMv7-M Floating-Point Unit (Fpv4-SP). The hardware FPU implementation adds an extra floating-point register bank consisting of S0-S31 and some other FPU registers. This FPU register set represents additional context that need to be preserved across interrupts and thread switching (e.g., in the preemptive QK kernel). The ARM VFP has a very interesting feature called **lazy stacking** [@ref ARM-AN298]. This feature avoids an increase of interrupt latency by skipping the stacking of floating-point registers, if not required, that is: @@ -221,7 +192,6 @@ All built-in kernels in QP are designed to take advantage of the lazy stacking f @section arm-cm_ref References - @anchor ARM-AN298 - **[ARM AN298]** ARM Application Note 298 "Cortex-M4(F) Lazy Stacking and Context Switching", ARM 2012 @@ -235,11 +205,10 @@ All built-in kernels in QP are designed to take advantage of the lazy stacking f */ /*##########################################################################*/ /*! @page arm-cm_qv Cooperative QV Kernel - @tableofcontents -

      The non-preemptive, cooperative QV kernel executes active objects one at a time, with priority-based scheduling performed after run-to-completion (RTC) processing of each event. Due to naturally short duration of event processing in state machines, the simple QV kernel is often adequate for many real-time systems. (NOTE: Long RTC steps can be often broken into shorter pieces by means of the "Reminder" state pattern [@ref Reminder]) -

      +The non-preemptive, cooperative QV kernel executes active objects one at a time, with priority-based scheduling performed after run-to-completion (RTC) processing of each event. Due to naturally short duration of event processing in state machines, the simple QV kernel is often adequate for many real-time systems. (NOTE: Long RTC steps can be often broken into shorter pieces by means of the "Reminder" state pattern [@ref Reminder]) + @remarks In the QV port, the only components requiring platform-specific porting are QF and QV itself. The other two components: QEP and QS require merely recompilation and will not be discussed here. With the QV port you're not using the QK or QXK kernels. The QV port to ARM Cortex-M is located in the folder /ports/arm-cm/qv/. @@ -255,7 +224,7 @@ The cooperative QV kernel works essentially as the traditional foreground-backgr 3. QV uses only the Main Stack Pointer. The Process Stack Pointer is not used and is not initialized. 4. ARM Cortex-M enters interrupt context without disabling interrupts (without setting the PRIMASK bit or the BASEPRI register). Generally, you should not disable interrupts inside your ISRs. In particular, the QP services QF_PUBLISH(), QF_TICK_X(), and QACTIVE_POST() should be called with **interrupts enabled**, to avoid nesting of critical sections. - +
      > NOTE: If you don't wish an interrupt to be preempted by another interrupt, you can always prioritize that interrupt in the NVIC to a higher level (use a lower numerical value of priority). 5. The `QF_init()` function calls the function `QV_init()` to set the interrupt priority of all IRQs available in the MCU to the safe value of @ref QF_BASEPRI "QF_BASEPRI" (for ARM-v7 architecture). @@ -276,19 +245,17 @@ The QEP header file for the ARM Cortex-M port is located in `/ports/arm-cm/qv/gnu/qf_port.h`. This file specifies the interrupt disabling policy (QF critical section) as well as the configuration constants for QF (see Chapter 8 in [PSiCC2]). @note The ARM Cortex-M allows you to use the simplest "unconditional interrupt disabling"� policy (see Section 7.3.2 in [PSiCC2]), because ARM Cortex-M is equipped with the standard nested vectored interrupt controller (NVIC) and generally runs ISRs with interrupts enabled (so the body of an ISR is not a critical section). - The following listing shows the `qf_port.h` header file for ARM Cortex-M with the GNU-ARM toolchain. Other toolchains use slightly different conditional compilation macros to select the Cortex-M variants, but implement the same policies. @anchor arm-cm_qf_port_h-code Listing: The qf_port.h header file for ARM Cortex-M -@code{c} +@code{.c} /* The maximum number of active objects in the application, see NOTE1 */ [1] #define QF_MAX_ACTIVE 32 @@ -354,92 +321,99 @@ The following listing shows the `qf_port.h` header file for ARM Cortex-M with th #include "qf.h" /* QF platform-independent public interface */ @endcode -
        -
      • 1 +
        +
        1
        The #QF_MAX_ACTIVE specifies the maximum number of active object priorities in the application. You always need to provide this constant. Here, #QF_MAX_ACTIVE is set to 32, but it can be increased up to the maximum limit of 63 active object priorities in the system. - +
        > NOTE: The `qf_port.h` header file does not change the default settings for all the rest of various object sizes inside QF. Please refer to Chapter 8 of [PSiCC2] for discussion of all configurable QF parameters. -
      • -
      • 2 -The #QF_MAX_TICK_RATE specifies the maximum number of clock tick rates for QP time events. If you don't need to specify this limit, in which case the default of a single clock rate will be chosen. -
      • -
      • 3 -As described in the previous @ref arm-cm_int "Section", the interrupt disabling policy for the ARMv6-M architecture (Cortex-M0/M0+) is different than the policy for the ARMv7-M. In GNU-ARM, the macro `__ARM_ARCH` is defined as 6 for the ARMv6-M architecture (Cortex-M0/M0+), and 7 for ARMv7-M (Cortex-M3/M4/M4F). + +
        2
        +The macro `QF_MAX_TICK_RATE` specifies the maximum number of clock tick rates for QP time events. If you do not need to specify this limit, in which case the default of a single clock rate will be chosen. +
        +
        3
        +As described in the previous @ref arm-cm_int "Section", the interrupt disabling policy for the ARMv6-M architecture (Cortex-M0/M0+) is different than the policy for the ARMv7-M. In GNU-ARM, the macro `__ARM_ARCH` is defined as 6 for the ARMv6-M architecture (Cortex-M0/M0+), and 7 for ARMv7-M (Cortex-M3/M4/M4F). +
        > NOTE: The `__ARM_ARCH` macro is specific to the GNU-ARM compiler. Other compilers for ARM Cortex-M provide different macros to detect the CPU type. -
      • -
      • 4-5 + + +
        4-5
        For the ARMv6-M architecture, the interrupt disabling policy uses the PRIMASK register to disable interrupts globally. The @c QF_INT_DISABLE() macro resolves in this case to the inline assembly instruction "CPSD i", which sets the PRIMASK. The @c QF_INT_ENABLE() macro resolves to the inline assembly instruction "CPSE i", which clears the PRIMASK. -
      • -
      • 6 + +
        6
        The #QF_CRIT_STAT_TYPE is NOT defined, meaning that the critical section uses the simple policy of "unconditional interrupt disablin". - +
        > NOTE: The "unconditional interrupt disabling" policy precludes nesting of critical sections, but this is not needed for ARM Cortex-M, because this CPU never disables interrupts, even when handling exceptions/interrupts. -
      • -
      • 7 + + +
        7
        The QF_CRIT_ENTRY() enters a critical section. Interrupts are disabled by setting the PRIMASK register. -
      • -
      • 8 + +
        8
        The QF_CRIT_EXIT() macro leaves the critical section. Interrupts are unconditionally re-enabled by clearing the PRIMASK register. -
      • -
      • 9 + +
        9
        For the ARMv6-M architecture, the `QF_AWARE_ISR_CMSIS_PRI` priority level is defined as zero, meaning that all interrupts are "kernel-aware", because all interrupt priorities are disabled by the kernel. -
      • -
      • 10 + +
        10
        The `QF_LOG2()` macro is defined as a call to the function `QF_qlog2()` ("quick log-base-2 logarithm"). This function is coded in hand-optimized assembly, which always takes only 14 CPU cycles to execute (see also label [23]). - +
        > NOTE: ARM Cortex-M0/M0+ does NOT implement the `CLZ` instruction. Therefore the log-base-2 calculation cannot be accelerated in hardware, as it is for ARM Cortex-M3 and higher. -
      • -
      • 11 + + +
        11
        For the ARMv7-M (Cortex-M3/M4/M4F) architecture... -
      • -
      • 12 + +
        12
        The `QF_PRIMASK_DISABLE()` macro resolves to the inline assembly instruction `CPSD i`, which sets the PRIMASK. -
      • -
      • 13 + +
        13
        The `QF_PRIMASK_ENABLE()` macro resolves to the inline assembly instruction `CPSE i`, which clears the PRIMASK. -
      • -
      • 14 -Interrupts are disabled by setting the BASEPRI register to the value defined in the `QF_BASEPRI` macro (see label [19]). This setting of the BASEPRI instruction `msr BASEPRI,...` is surrounded by setting and clearing the PRIMASK register, as a workaround a hardware problem in ARM Cortex-M7 core r0p1: - -> NOTE: The selective disabling of "QF-aware" interrupts with the BASEPRI register has a problem on ARM Cortex-M7 core r0p1 (see [@ref ARM-EPM-064408], Erratum 837070). The workaround recommended by ARM is to surround `MSR BASEPRI,...` with the `CPSID i`/`CPSIE i` pair, which is implemented in the QF_INT_DISABLE() macro. This workaround works also for Cortex-M3/M4 cores. -
      • -
      • 15 + +
        14
        +Interrupts are disabled by setting the BASEPRI register to the value defined in the `QF_BASEPRI` macro (see label [19]). This setting of the BASEPRI instruction `msr BASEPRI,...` is surrounded by setting and clearing the PRIMASK register, as a workaround a hardware problem in ARMv7M or higher architectures core r0p1: +
        +> NOTE: The selective disabling of "QF-aware" interrupts with the BASEPRI register has a problem on ARMv7M or higher architectures core r0p1 (see [@ref ARM-EPM-064408], Erratum 837070). The workaround recommended by ARM is to surround `MSR BASEPRI,...` with the `CPSID i`/`CPSIE i` pair, which is implemented in the QF_INT_DISABLE() macro. This workaround works also for Cortex-M3/M4 cores. + +
        +
        15
        The `QF_INT_ENABLE()` macro sets the BASEPRI register to zero, which disables BASEPRI interrupt masking. - +
        > NOTE: this method can never disable interrupt of priority 0 (highest). -
      • -
      • 16 -The #QF_CRIT_STAT_TYPE is NOT defined, meaning that the critical section uses the simple policy of "unconditional interrupt disabling". + +
        16
        +The #QF_CRIT_STAT_TYPE is NOT defined, meaning that the critical section uses the simple policy of "unconditional interrupt disabling". +
        > NOTE: The "unconditional interrupt disabling" policy precludes nesting of critical sections, but this is not needed for ARM Cortex-M, because this CPU never disables interrupts, even when handling exceptions/interrupts. -
      • -
      • 17 + + +
        17
        The QF_CRIT_ENTRY() enters a critical section. Interrupts are disabled with the macro `QF_INT_DISABLE()` defined at label [12]. -
      • -
      • 18 + +
        18
        The QF_CRIT_EXIT() macro leaves the critical section. Interrupts are unconditionally re-enabled with the macro `QF_INT_ENABLE()` defined at label [13]. -
      • -
      • 19 + +
        19
        @anchor QF_BASEPRI -The `QF_BASEPRI` value is defined such that it is the lowest priority for the minimum number of 3 priority-bits that the ARM7-M architecture must provide. This partitions the interrupts as "kernel-unaware" and "kernel-aware" interrupts, as shown in section @ref arm-cm_int-assign. -
      • -
      • 20 +The `QF_BASEPRI` value is defined such that it is the lowest priority for the minimum number of 3 priority-bits that the ARMv7M or higher architectures architecture must provide. This partitions the interrupts as "kernel-unaware" and "kernel-aware" interrupts, as shown in section @ref arm-cm_int-assign. + +
        20
        For the ARMv7-M architecture, the `QF_AWARE_ISR_CMSIS_PRI` priority level suitable for the CMSIS function `NVIC_SetPriority()` is determined by the `QF_BASEPRI` value. -
      • -
      • 21 + +
        21
        The macro `QF_LOG2()` is defined to take advantage of the CLZ instruction (Count Leading Zeroes), which is available in the ARMv7-M architecture. - +
        > NOTE: The `__builtin_cls()` intrinsic function is specific to the GNU-ARM compiler. Other compilers for ARM Cortex-M use different function names for this intrinsic function. -
      • -
      • 22 + + +
        22
        The macro @c QF_CRIT_EXIT_NOP() provides the protection against merging two critical sections occurring back-to-back in the QP code. -
      • -
      • 23 + +
        23
        For ARMv6 architecture, the prototype of the quick, hand-optimized log-base-2 function is provided (see also label [10]). -
      • -
      - + + @section arm-cm_qv_port_h The qv_port.h Header File @@ -451,7 +425,7 @@ To avoid race conditions between interrupts waking up active objects and going t @anchor arm-cm_qv_port_h-code Listing: The qv_port.h header file for ARM Cortex-M -@code{c} +@code{.c} #ifdef ARM_ARCH_V6M /* Cortex-M0/M0+/M1 ? */ [1] #define QV_CPU_SLEEP() do { \ @@ -474,21 +448,19 @@ To avoid race conditions between interrupts waking up active objects and going t void QV_init(); #include "qv.h" /* QV platform-independent public interface */ - @endcode -
        -
      • 1 +
        +
        1
        For the ARMv6-M architecture, the macro `QV_CPU_SLEEP()` stops the CPU with the WFI instruction (Wait For Interrupt). After the CPU is woken up by an interrupt, interrupts are re-enabled with the PRIMASK. -
      • -
      • 2 -For the ARMv7-M architecture, the macro `QV_CPU_SLEEP()` first disables interrupts by setting the PRIMASK, then clears the BASEPRI to enable all "kernel-aware" interrupts and only then stops the CPU with the WFI instruction (Wait For Interrupt). After the CPU is woken up by an interrupt, interrupts are re-enabled with the PRIMASK. This sequence is necessary, because the ARM Cortex-M3/M4/M7 cores cannot be woken up by any interrupt blocked by the BASEPRI register. -
      • -
      • 2 + +
        2
        +For the ARMv7-M architecture, the macro `QV_CPU_SLEEP()` first disables interrupts by setting the PRIMASK, then clears the BASEPRI to enable all "kernel-aware" interrupts and only then stops the CPU with the WFI instruction (Wait For Interrupt). After the CPU is woken up by an interrupt, interrupts are re-enabled with the PRIMASK. This sequence is necessary, because the ARMv7M or higher architectures cannot be woken up by any interrupt blocked by the BASEPRI register. +
        +
        2
        The macro `QV_INIT()` is defined as a call to the `QV_init()` function, which means that this function will be called from `QF_init()`. The `QV_init()` function initializes all available IRQ priorities in the MCU to the safe value of @ref QF_BASEPRI "QF_BASEPRI". -
      • -
      - + + @section arm-cm_qv_port_c The qv_port.c Implementation File @@ -531,27 +503,26 @@ The QV implementation file for the ARM Cortex-M port is located in -
    • 1 +
      +
      1
      For the ARMv7-M architecture (Cortex-M3/M4/M7)... -
    • -
    • 2 + +
      2
      The exception priorities for User-Fault, Bus-Fault, and Mem-Fault are set to the value @ref QF_BASEPRI "QF_BASEPRI". -
    • -
    • 3 + +
      3
      The exception priority for SVCCall is set to the value @ref QF_BASEPRI "QF_BASEPRI". -
    • -
    • 4 + +
      4
      The exception priority for SysTick, PendSV, and Debug is set to the value @ref QF_BASEPRI "QF_BASEPRI". -
    • -
    • 5 + +
      5
      The number of implemented IRQs is read from the @c SCnSCB_ICTR register -
    • -
    • 6 + +
      6
      The interrupt priority of all implemented IRQs is set to the safe value @ref QF_BASEPRI "QF_BASEPRI" in a loop. -
    • -
    - + + @section arm-cm_qv-isr Writing ISRs for QV @@ -579,9 +550,9 @@ The following listing shows an example of the SysTick_Handler() ISR (from the DP The QP port to ARM Cortex-M complies with the CMSIS standard, which dictates the names of all exception handlers and IRQ handlers. +@section arm-cm_qv-fpu Using the FPU in the QV Port -@section arm-cm_qv-fpu Using the FPU in the QV Port (Cortex-M4F/M7) -If you have the Cortex-M4/M7 CPU and your application uses the hardware FPU, it should be enabled because it is turned off out of reset. The CMSIS-compliant way of turning the FPU on looks as follows: +If you use ARMv7M or higher CPU and your application uses the hardware FPU, it should be enabled because it is turned off out of reset. The CMSIS-compliant way of turning the FPU on looks as follows: @verbatim SCB->CPACR |= (0xFU << 20); @@ -594,7 +565,6 @@ The FPU must be enabled before executing any floating point instruction. An atte Depending on whether or not you use the FPU in your ISRs, the QV port allows you to configure the FPU in various ways, as described in the following sub-sections. -
    @subsection arm-cm_qv-fpu_noisr FPU NOT used in the ISRs If you use the FPU only at the thread-level (inside active objects) and none of your ISRs use the FPU, you can setup the FPU not to use the automatic state preservation and not to use the lazy stacking feature as follows: @@ -608,7 +578,6 @@ With this setting, the Cortex-M4F processor handles the ISRs in the exact-same w This FPU setting will lead to FPU errors, if any of the ISRs indeed starts to use the FPU -
    @subsection arm-cm_qv-fpu_isr FPU used in the ISRs If you use the FPU both at the thread-level (inside active objects) and in any of your ISRs as well, you should setup the FPU to use the automatic state preservation and the lazy stacking feature as follows: @@ -622,7 +591,6 @@ This will enable the lazy stacking feature of the Cortex-M4F/M7 processor [@ref As described in the ARM Application Note "Cortex-M4(F) Lazy Stacking and Context Switching" [@ref ARM-AN298], the FPU automatic state saving requires more stack plus additional CPU time to save the FPU registers, but only when the FPU is actually used. - @section arm-cm_qv-idle QV Idle Processing Customization in QV_onIdle() When no events are available, the non-preemptive QV kernel invokes the platform-specific callback function QV_onIdle(), which you can use to save CPU power, or perform any other "idle" processing (such as Quantum Spy software trace output). @@ -648,20 +616,20 @@ Because QV_onIdle() must enable interrupts internally, the signature of the func @endcode -
      -
    • 1 +
      +
      1
      The cooperative QV kernel calls the QV_onIdle() callback with interrupts disabled, to avoid race condition with interrupts that can post events to active objects and thus invalidate the idle condition.
    • -
    • 2 +
      2
      The sleep mode is used only in the non-debug configuration, because sleep mode stops CPU clock, which can interfere with debugging.
    • -
    • 3 +
      3
      The macro QV_CPU_SLEEP() is used to put the CPU to the low-power sleep mode safely. The macro QV_CPU_SLEEP() is defined in the qv_port.h header file for the QV kernel and depends on the interrupt disabling policy used.
    • -
    • 4 +
      4
      When a sleep mode is not used, the QV_onIdle() callback simply re-enables interrupts. -
    • -
    + + @next{arm-cm_qk} */ @@ -677,7 +645,6 @@ When a sleep mode is not used, the QV_onIdle() callback simply re-enables interr In a QK port, the only components requiring platform-specific porting are QF and QV itself. The other two components: QEP and QS require merely recompilation and will not be discussed here. With the QV port you're not using the QV or QXK kernels. The QK port to ARM Cortex-M is located in the folder /ports/arm-cm/qk/. - @section arm-cm_qk-synopsis Synopsis of the QK Port on ARM Cortex-M The ARM Cortex-M architecture is designed primarily for the traditional real-time kernels that use multiple per-thread stacks. Therefore, implementation of the non-blocking, single-stack kernel like QK is a bit more involved on Cortex-M than other CPUs and works as follows: @@ -687,76 +654,76 @@ The ARM Cortex-M architecture is designed primarily for the traditional real-tim 3. ARM Cortex-M enters interrupt context without disabling interrupts (without setting the PRIMASK bit or the BASEPRI register). Generally, you should not disable interrupts inside your ISRs. In particular, the QP services QF_PUBLISH(), QF_TICK_X(), and QACTIVE_POST() should be called with interrupts enabled, to avoid nesting of critical sections. (NOTE: If you don’t wish an interrupt to be preempted by another interrupt, you can always prioritize that interrupt in the NVIC to a higher level -- use a lower numerical value of priority). +4. The QK port uses the PendSV exception (number 14) to perform asynchronous preemption (see Chapter 10 in @webref{psicc2, PSiCC2}). The startup code must initialize the Interrupt Vector Table with the addresses of @c PendSV_Handler() exception handler. +
    +> NOTE: QK uses only the CMSIS-compliant exception and interrupt names, such as `PendSV_Handler` -4. The QK port uses the PendSV exception (number 14) and the NMI exception (number 2) to perform asynchronous preemption and return to the preempted thread, respectively (see Chapter 10 in [PSiCC2]). The startup code must initialize the Interrupt Vector Table with the addresses of @c PendSV_Handler() and @c NMI_Handler() exception handlers. -@n -> NOTE: QK uses only the CMSIS-compliant exception and interrupt names, such as @c PendSV_Handler, @c NMI_Handler, etc.@n -> NOTE: The QK port specifically does **not** use the SVC exception (Supervisor Call). This makes the QK ports compatible with various "hypervisors" (such as mbed uVisor or Nordic SoftDevice), which use the SVC exception. - +5. The QK port uses the NMI exception (number 2) or any unused IRQ interrupt to *return* to the preempted thread (see Chapter 10 in @webref{psicc2, PSiCC2}). The startup code must initialize the Interrupt Vector Table with the addresses of `NMI_Handler()` and `__IRQHandler()` exception handlers. +
    +> NOTE: In case the NMI exception is needed for something else, the QK allows the developers to configure any otherwise unused IRQ to be used instead. This is accomplished by the pair of macros: `QK_USE_IRQ_NUM` and `QK_USE_IRQ_HANDLER`. +
    +> NOTE: The QK port specifically does **not** use the SVC exception (Supervisor Call). This makes the QK ports compatible with various "hypervisors" (such as mbed uVisor or Nordic SoftDevice), which use the SVC exception. -5. The QF_init() function calls the function QK_init() to set the priority of the PendSV exception to the lowest level in the whole system (0xFF). The function QK_init() additionally sets the interrupt priority of all IRQs available in the MCU to the safe value of @ref QF_BASEPRI "QF_BASEPRI" (for ARM-v7 architecture). +6. The QF_init() function calls the function QK_init() to set the priority of the PendSV exception to the lowest level in the whole system (0xFF). The function QK_init() additionally sets the interrupt priority of all IRQs available in the MCU to the safe value of @ref QF_BASEPRI "QF_BASEPRI" (for ARM-v7 architecture). -6. It is strongly recommended that you do not assign the lowest priority (0xFF) to any interrupt in your application. With 3 MSB-bits of priority, this leaves the following 7 priority levels for you (listed from the lowest to the highest urgency): 0xC0, 0xA0, 0x80, 0x60, 0x40, 0x20, and 0x00 (the highest priority). +7. It is strongly recommended that you do not assign the lowest priority (0xFF) to any interrupt in your application. With 3 MSB-bits of priority, this leaves the following 7 priority levels for you (listed from the lowest to the highest urgency): 0xC0, 0xA0, 0x80, 0x60, 0x40, 0x20, and 0x00 (the highest priority). -7. Before returning, every "kernel aware" ISR must check whether an active object has been activated that has a higher priority than the currently running active object. If this is the case, the ISR must set the PensSV pending flag in the NVIC. All this is accomplished in the macro QK_ISR_EXIT(), which must be called just before exiting every ISRs. +8. Before returning, every "kernel aware" ISR must check whether an active object has been activated that has a higher priority than the currently running active object. If this is the case, the ISR must set the PensSV pending flag in the NVIC. All this is accomplished in the macro QK_ISR_EXIT(), which must be called just before exiting every ISRs. -8. In ARM Cortex-M the whole prioritization of interrupts, including the PendSV exception, is performed entirely by the NVIC. Because the PendSV has the lowest priority in the system, the NVIC tail-chains to the PendSV exception only after exiting the last nested interrupt. +9. In ARM Cortex-M the whole prioritization of interrupts, including the PendSV exception, is performed entirely by the NVIC. Because the PendSV has the lowest priority in the system, the NVIC tail-chains to the PendSV exception only after exiting the last nested interrupt. -9. The pushing of the 8 registers comprising the ARM Cortex-M interrupt stack frame upon entry to NMI exception is wasteful in a single-stack kernel, but is necessary to perform full interrupt return to the preempted context through the NMI's return. +10. The pushing of the 8 registers comprising the ARM Cortex-M interrupt stack frame upon entry to the to the preempted thread (NMI or IRQ) is wasteful in a single-stack kernel, but is necessary to perform full interrupt return to the preempted context through the exception return. -
    @subsection arm-cm_qk-preempt Preemption Scenarios in QK on ARM Cortex-M - @anchor arm-cm_qk-arm-cm-fig -@image html qk_arm-cm.gif "Several preemption scenarios in QK" +![Several preemption scenarios in QK](qk_arm-cm.gif) -
      -
    • 0 +
      +
      0
      The timeline begins with the QK executing the idle loop. -
    • -
    • 1 + +
      1
      At some point an interrupt occurs and the CPU immediately suspends the idle loop, pushes the interrupt stack frame to the Main Stack and starts executing the ISR. -
    • -
    • 2 + +
      2
      The ISR performs its work, and in QK always must call the QK_ISR_EXIT() macro, which calls the QK scheduler (QK_sched()) to determine if there is a higher-priority AO to run. If so, the macro sets the pending flag for the PendSV exception in the NVIC. The priority of the PendSV exception is configured to be the lowest of all exceptions (0xFF), so the ISR continues executing and PendSV exception remains pending. At the ISR return, the ARM Cortex-M CPU performs tail-chaining to the pending PendSV exception. -
    • -
    • 3 + +
      3
      The PendSV exception synthesize an exception stack frame to return to the QK "activator" (QK_activate_()) to run this new thread. -> NOTE: The QK activator must run in the thread context, while PendSV executes in the exception context. The change of the context is accomplished by returning from the PendSV exception directly to the QK "activator". +> NOTE: The QK activator must run in the thread context, while PendSV executes in the exception context. The change of the context is accomplished by returning from the PendSV exception directly to the QK "activator". To return directly to the QK activator, PendSV synthesizes an exception stack frame, which contains the exception return address set to QK_activate_(). The QK activator activates the Low-priority thread (discovered by the QK scheduler QK_sched()). The QK activator enables interrupts and launches the Low-priority thread, which is simply a C-function call in QK. The Low-priority thread (active object) starts running. -
    • -
    • 4 + +
      4
      Some time later a low-priority interrupt occurs. The Low-priority thread is suspended and the CPU pushes the interrupt stack frame to the Main Stack and starts executing the ISR. -
    • -
    • 5 + +
      5
      Before the Low-priority ISR completes, it too gets preempted by a High-priority ISR. The CPU pushes another interrupt stack frame and starts executing the High-priority ISR. -
    • -
    • 6 + +
      6
      The High-priority ISR sets the pending flag for the PendSV exception by means of the QK_ISR_EXIT() macro. When the High-priority ISR returns, the NVIC does not tail-chain to the PendSV exception, because a higher-priority ISR than PendSV is still active. The NVIC performs an exception return to the preempted Low-priority interrupt, which finally completes. -
    • -
    • 7 + +
      7
      Upon the exit from the Low-priority ISR, it too sets the pending flag for the PendSV exception by means of the QK_ISR_EXIT() macro. The PendSV is already pended from the High-priority interrupt, so pending is again is redundant, but it is not an error. At the ISR return, the ARM Cortex-M CPU performs tail-chaining to the pending PendSV exception. -
    • -
    • 8 + +
      8
      The PendSV exception synthesizes an interrupt stack frame to return to the QK activator. The QK activator detects that the High-priority thread is ready to run and launches the High-priority thread (normal C-function call). The High-priority thread runs to completion and returns to the activator. -
    • -
    • 9 -The QK activator does not find any more higher-priority threads to execute and needs to return to the preempted thread. The only way to restore the interrupted context in ARM Cortex-M is through the interrupt return, but the thread is executing outside of the interrupt context (in fact, threads are executing in the Privileged Thread mode). The thread enters the Handler mode by pending the NMI exception. -> NOTE: The NMI exception is pended while interrupts are still disabled. This is not a problem, because NMI cannot be masked by disabling interrupts, so runs without any problems. -
    • -
    • 10 -The only job of the NMI exception is to discard its own interrupt stack frame, re-enable interrupts, and return using the interrupt stack frame that has been on the stack from the moment of thread preemption. -
    • -
    • 11 -The Low-priority thread, which has been preempted all that time, resumes and finally runs to completion and returns to the QK activator. The QK activaotr does not find any more threads to launch and causes the NMI exception to return to the preempted thread. -
    • -
    • 12 -The NMI exception discards its own interrupt stack frame and returns using the interrupt stack frame from the preempted thread context -
    • -
    - + +
    9
    +The QK activator does not find any more higher-priority threads to execute and needs to return to the preempted thread. The only way to restore the interrupted context in ARM Cortex-M is through the interrupt return, but the thread is executing outside of the interrupt context (in fact, threads are executing in the Privileged Thread mode). The thread enters the Handler mode by pending the NMI or IRQ exception. +
    +
    10
    +The only job of the NMI or IRQ exception is to discard its own interrupt stack frame, re-enable interrupts, and return using the interrupt stack frame that has been on the stack from the moment of thread preemption. +
    +
    11
    +The Low-priority thread, which has been preempted all that time, resumes and finally runs to completion and returns to the QK activator. The QK activaotr does not find any more threads to launch and causes the NMI or IRQ exception to return to the preempted thread. +
    +
    12
    +The NMI or IRQ exception discards its own interrupt stack frame and returns using the interrupt stack frame from the preempted thread context +
    + +
    @section arm-cm_qk-qf_port The qf_port.h Header File @@ -797,55 +764,50 @@ As any preemptive kernel, QK needs to be notified about entering the interrupt c #include "qk.h" /* QK platform-independent public interface */ @endcode -
      -
    • 1 +
      +
      1
      The macro @c QK_ISR_CONTEXT() returns true when the code executes in the ISR context and false otherwise. The macro takes advantage of the ARM Cortex-M register IPSR, which is non-zero when the CPU executes an exception (or interrupt) and is zero when the CPU is executing thread code. -> NOTE: QK needs to distinguish between ISR and thread contexts, because threads need to perform synchronous context switch (when a higher-priority thread becomes ready to run), while ISRs should not do that. -
    • -
    • 2 +> NOTE: QK needs to distinguish between ISR and thread contexts, because threads need to perform synchronous context switch (when a higher-priority thread becomes ready to run), while ISRs should not do that. + + +
      2
      The inline function @c QK_get_IPSR() obtains the IPSR register and returns it to the caller. This function is defined explicitly for the GNU-ARM toolchain, but many other toolchains provide this function as an intrinsic, built-in facility. -
    • -
    • 3 + +
      3
      The @c QK_ISR_ENTRY() macro notifies QK about entering an ISR. The macro is empty, because the determination of the ISR vs thread context is performed independently in the @c QK_ISR_CONTEXT() macro (see above). -
    • -
    • 4 + +
      4
      The @c QK_ISR_EXIT() macro notifies QK about exiting an ISR. -
    • -
    • 5 + +
      5
      Interrupts are disabled before calling QK scheduler. -
    • -
    • 6 + +
      6
      The QK scheduler is called to find out whether an active object of a higher priority than the current one needs activation. The @c QK_sched_() function returns non zero value if this is the case. -
    • -
    • 7 + +
      7
      If asynchronous preemption becomes necessary, the code sets the PENDSV Pend bit(28) in the ICSR register (Interrupt Control and State Register). The register is mapped at address 0xE000ED04 in all ARM Cortex-M cores. -
    • -
    • 8 + +
      8
      The interrupts are re-enabled after they have been disabled in step [5]. -> NOTE: Because the priority of the PendSV exception is the lowest of all interrupts, it is actually triggered only after all nested interrupts exit. The PendSV exception is then entered through the efficient **tail-chaining** process, which eliminates the restoring and re-entering the interrupt context. -
    • -
    +> NOTE: Because the priority of the PendSV exception is the lowest of all interrupts, it is actually triggered only after all nested interrupts exit. The PendSV exception is then entered through the efficient **tail-chaining** process, which eliminates the restoring and re-entering the interrupt context. + + @section arm-cm_qk-qk_impl QK Port Implementation for ARM Cortex-M -The QK port to ARM Cortex-M requires coding the PendSV and NMI exceptions in assembly. This ARM Cortex-M-specific code, as well as QK initialization (@c QK_init()) is located in the file ­ports/arm-cm/­qk/­gnu/qk_port.c +The QK port to ARM Cortex-M requires coding the PendSV and NMI or IRQ exceptions in assembly. This ARM Cortex-M-specific code, as well as QK initialization (@c QK_init()) is located in the file ­ports/arm-cm/­qk/­gnu/qk_port.c @note The single assembly module `qk_port.s` contains common code for all Cortex-M variants (Architecture v6M and v7M) as well as options with and without the VFP. The CPU variants are distinguished by conditional compilation, when necessary. -
    @subsection arm-cm_qk_port-asm_init QK_init() Implementation - Listing: QK_init() function in qk_port.c file -@code{c} +@code{.c} [1] void QK_init(void) { - [2] #if (__ARM_ARCH != 6) /* NOT Cortex-M0/M0+/M1 (v6-M, v6S-M)? */ - - uint32_t n; - /* set exception priorities to QF_BASEPRI... * SCB_SYSPRI1: Usage-fault, Bus-fault, Memory-fault */ @@ -858,55 +820,66 @@ The single assembly module `qk_port.s` contains common code for all Cortex-M var [5] SCB_SYSPRI[3] |= (QF_BASEPRI << 24) | (QF_BASEPRI << 16) | QF_BASEPRI; /* set all implemented IRQ priories to QF_BASEPRI... */ - [6] n = 8U + ((*SCnSCB_ICTR & 0x7U) << 3); /* (# NVIC_PRIO registers)/4 */ - do { - --n; - [7] NVIC_IP[n] = (QF_BASEPRI << 24) | (QF_BASEPRI << 16) - | (QF_BASEPRI << 8) | QF_BASEPRI; - } while (n != 0); + [6] uint8_t nprio = (8U + ((*SCnSCB_ICTR & 0x7U) << 3U))*4; + for (uint8_t n = 0U; n < nprio; ++n) { + [7] NVIC_IP[n] = QF_BASEPRI; + } #endif /* NOT Cortex-M0/M0+/M1(v6-M, v6S-M) */ /* SCB_SYSPRI3: PendSV set to the lowest priority 0xFF */ [8] SCB_SYSPRI[3] |= (0xFFU << 16); + + #ifdef QK_USE_IRQ_NUM + /* The QK port is configured to use a given ARM Cortex-M IRQ # + * to return to thread mode (default is to use the NMI exception) + */ + [9] NVIC_IP[QK_USE_IRQ_NUM] = 0U; /* priority 0 (highest) */ +[10] NVIC_EN[QK_USE_IRQ_NUM / 32U] = (1U << (QK_USE_IRQ_NUM % 32U)); + #endif } @endcode -
      -
    • 1 +
      +
      1
      The QK_init() function is called from QF_init() to perform initialization specific to the QK kernel. -
    • -
    • 2 -If the ARM Architecture is NOT v6 (Cortex-M0/M0+), that is for Cortex-M3/M4/M7, the function initializes the exception priorities of PendSV and NMI as well as interrupt priorities of all IRQs available in a given MCU. (NOTE: for Cortex-M0/M0+, this initialization is not needed, as the CPU does not support the BASEPRI register and the only way to disable interrupts is via the PRIMASK register. In this case, all interrupts are "kernel-aware" and there is no need to initialize interrupt priorities to a safe value. -
    • -
    • 3 + +
      2
      +If the ARM Architecture is NOT v6 (Cortex-M0/M0+), that is for ARMv7M or higher architectures, the function initializes the exception priorities of PendSV and NMI as well as interrupt priorities of all IRQs available in a given MCU. (NOTE: for Cortex-M0/M0+, this initialization is not needed, as the CPU does not support the BASEPRI register and the only way to disable interrupts is via the PRIMASK register. In this case, all interrupts are "kernel-aware" and there is no need to initialize interrupt priorities to a safe value. +
      +
      3
      Exception priorities of Usage-fault, Bus-fault, and Memory-fault are set to @ref QF_BASEPRI "QF_BASEPRI". -
    • -
    • 4 + +
      4
      Exception priorities of SVCall is set to @ref QF_BASEPRI "QF_BASEPRI". -
    • -
    • 5 + +
      5
      Exception priorities of SysTick, PendSV and Debug are set to @ref QF_BASEPRI "QF_BASEPRI". - +
      > NOTE: the exception priority of PedSV is later changed to 0xFF in step [8] -
    • -
    • 6 + + +
      6
      The number of implemented interrupts is extraced fom SCnSCB_ICTR register. -
    • -
    • 7 + +
      7
      Exception priorities of all implemented interrupts are set to @ref QF_BASEPRI "QF_BASEPRI". -
    • -
    • 8 + +
      8
      Exception priority of PendSV is set to 0xFF, which is the lowest interrupt priority in the system. -
    • -
    + +
    9
    +In case a regular IRQ is configured for returning to the thread mode, the priority of the IRQ is set to zero (highest). +
    +
    10
    +In case a regular IRQ is configured for returning to the thread mode, the IRQ is enabled in the NVIC. +
    + -
    @subsection arm-cm_qk_port-asm_pendsv PendSV_Handler() Implementation - Listing: PendSV_Handler() and Thread_ret() functions in qk_port.c file -@code{c} +@code{.c} [1] __attribute__ ((naked)) [2] void PendSV_Handler(void) { [3] __asm volatile ( @@ -942,7 +915,7 @@ Exception priority of PendSV is set to 0xFF, which is the lowest interrupt prior * QK_activate_(). * * returns with interrupts DISABLED. - * NOTE: the QK activator is called with interrupts DISABLED and also + * NOTE: the QK activator is called with interrupts DISABLED and also */ [14] " LSR r3,r1,#3 \n" /* r3 := (r1 >> 3), set the T bit (new xpsr) */ [15] " LDR r2,=QK_activate_ \n" /* address of QK_activate_ */ @@ -968,7 +941,7 @@ Exception priority of PendSV is set to 0xFF, which is the lowest interrupt prior * thread. However, this must be accomplished by a return-from-exception, * while we are still in the thread context. The switch to the exception * context is accomplished by triggering the NMI exception. - * NOTE: The NMI exception is triggered with nterrupts DISABLED, + * NOTE: The NMI exception is triggered with nterrupts DISABLED, * because QK activator disables interrutps before return. */ @@ -983,7 +956,7 @@ Exception priority of PendSV is set to 0xFF, which is the lowest interrupt prior #endif /* VFP available */ /* trigger NMI to return to preempted task... - * NOTE: The NMI exception is triggered with nterrupts DISABLED + * NOTE: The NMI exception is triggered with nterrupts DISABLED */ [29] " LDR r0,=0xE000ED04 \n" /* Interrupt Control and State Register */ [30] " MOV r1,#1 \n" @@ -994,72 +967,78 @@ Exception priority of PendSV is set to 0xFF, which is the lowest interrupt prior } @endcode -
      -
    • 1 +
      +
      1
      Attribute `naked` means that the GNU-ARM compiler won't generate any entry/exit code for this function. -
    • -
    • 2 + +
      2
      `PendSV_Handler` is a CMSIS-complinat name of the PendSV exception handler. The `PendSV_Handler` exception is always entered via tail-chaining from the last nested interrupt. -
    • -
    • 3 + +
      3
      Entire body of this function will be defined in this one inline-assembly instruction. -
    • -
    • 4,5,6 + +
      4,5,6
      Before interrupts are disabled, the following constants are loaded into registers: address of ICSR into r3 and (1<<27) into r1. -
    • +
    • For the ARMv6-M architecture (Cortex-M0/M0+)... -
    • -
    • 7 + +
      7
      Interrupts are globally disabled by setting PRIMASK (see Section 3) -
    • +
    • Otherwise, for the ARMv7-M architecture (Cortex-M3/4/7) and when the `__ARM_FP` macro is defined... -> NOTE: The symbol `__ARM_FP` is defined by the GNU-ARM compiler when the compile options indicate that the ARM FPU is used. -
    • -
    • 8 +> NOTE: The symbol `__ARM_FP` is defined by the GNU-ARM compiler when the compile options indicate that the ARM FPU is used. + + +
      8
      The lr register (EXC_RETURN) is pushed to the stack along with r0, to keep the stack aligned at 8-byte boundary. -> NOTE: In the presence of the FPU (Cortex-M4F/M7), the EXC_RETURN[4] bit carries the information about the stack frame format used, whereas EXC_RETURN[4] ==0 means that the stack contains room for the S0-S15 and FPSCR registers in addition to the usual R0-R3,R12,LR,PC,xPSR registers. This information must be preserved, in order to properly return from the exception at the end. -
    • -
    • 9 +> NOTE: In the presence of the FPU (ARMv7M or higher architectures), the EXC_RETURN[4] bit carries the information about the stack frame format used, whereas EXC_RETURN[4] ==0 means that the stack contains room for the S0-S15 and FPSCR registers in addition to the usual R0-R3,R12,LR,PC,xPSR registers. This information must be preserved, in order to properly return from the exception at the end. + + +
      9
      For the ARMv7-M architecture (Cortex-M3/M4), interrupts are selectively disabled by setting the BASEPRI register. -> NOTE: The value moved to BASEPRI must be identical to the @ref QF_BASEPRI "QF_BASEPRI" macro defined in `qf_port.h`. -
    • -
    • 10 +> NOTE: The value moved to BASEPRI must be identical to the @ref QF_BASEPRI "QF_BASEPRI" macro defined in `qf_port.h`. + + +
      10
      Before setting the BASEPRI register, interrupts are disabled with the PRIMASK register, which is the recommended workaround for the Cortex-M7 r0p1 hardware bug, as described in the ARM Ltd. [@ref ARM-EPM-064408], Erratum 837070. -
    • -
    • 11 + +
      11
      The BASEPRI register is set to the @ref QF_BASEPRI "QF_BASEPRI" value. -
    • -
    • 12 + +
      12
      After setting the BASEPRI register, interrupts are re-anabed with the PRIMASK register, which is the recommended workaround for the Cortex-M7 r0p1 hardware bug, as described in the ARM Ltd. [@ref ARM-EPM-064408], Erratum 837070. -
    • -
    • 13 + +
      13
      The PendSV exception is **explicitly** un-pended. -> NOTE: The PendSV exception handler can be preempted by an interrupt, which might pend PendSV exception again. This would trigger PendSV incorrectly again immediately after calling QK activator. -
    • +> NOTE: The PendSV exception handler can be preempted by an interrupt, which might pend PendSV exception again. This would trigger PendSV incorrectly again immediately after calling QK activator. + + -
    • The following code [14-23] fabricates an exception stack frame, to perform an exception-return to the QK activator without destroying the original exception stack frame of the PendSV exception. This is necessary to preserve the context of the preempted code. -
    • -
    • 14 +
      14-23
      This code fabricates an exception stack frame, to perform an exception-return to the QK activator without destroying the original exception stack frame of the PendSV exception. This is necessary to preserve the context of the preempted code. +
      +
      14
      The value (1 << 24) is synthesized in r3 from the value (1 << 27) already available in r1. This value is going to be stacked and later restored to xPSR register (only the T bit set). -
    • -
    • 15 + +
      15
      The address of the QK activator function `QK_activate_()` is loaded into r2. This will be pushed to the stack as the PC register value. -
    • -
    • 16 + +
      16
      The address of the QK activator function `QK_activate_()` in r2 is adjusted to be half-word aligned instead of being an odd THUMB address. -> NOTE: This is necessary, because the value will be loaded directly to the PC, which cannot accept odd values. -
    • -
    • 17 +> NOTE: This is necessary, because the value will be loaded directly to the PC, which cannot accept odd values. + + +
      17
      The address of the `Thread_ret()` function is loaded into r1. This will be pushed to the stack as the lr register value. -> NOTE: The address of the @c Thread_ret label must be a THUMB address, that is, the least-significant bit of this address must be set (this address must be odd number). This is essential for the correct return of the QK activator with setting the THUMB bit in the PSR. Without the LS-bit set, the ARM Cortex-M CPU will clear the T bit in the PSR and cause the Hard Fault. The GNU-ARM assembler/linker will synthesize the correct THUMB address of the svc_ret label only if this label is declared with the `.type Thread_ret , %function` attribute (see step [23]). -
    • -
    • 18 +> NOTE: The address of the @c Thread_ret label must be a THUMB address, that is, the least-significant bit of this address must be set (this address must be odd number). This is essential for the correct return of the QK activator with setting the THUMB bit in the PSR. Without the LS-bit set, the ARM Cortex-M CPU will clear the T bit in the PSR and cause the Hard Fault. The GNU-ARM assembler/linker will synthesize the correct THUMB address of the svc_ret label only if this label is declared with the `.type Thread_ret , %function` attribute (see step [23]). + + +
      18
      The stack pointer is adjusted to leave room for 8 registers. -
    • -
    • 19 + +
      19
      The top of stack, adjusted by 5 registers, (r0, r1, r2, r3, and r12) is stored to r0. -
    • -
    • 20 + +
      20
      The values of xpsr, pc, and lr prepared in r3, r2, and r1, respectively, are pushed on the top of stack (now in r0). This operation completes the synthesis of the exception stack frame. After this step the stack looks as follows:
       Hi memory
      @@ -1084,40 +1063,40 @@ old SP --> "aligner"  (pushed in step [7] if FPU is present)
           SP --> r0   don't care
       Low memory
       
      -
    • -
    • 21-22 + +
      21-22
      The special exception-return value 0xFFFFFFF9 is synthesized in r0 (two instructions are used to make the code compatible with Cortex-M0, which has no barrel shifter). -> NOTE: the r0 register is used instead of lr because the Cortex-M0 instruction set cannot manipulate the higher-registers (r9-r15). -> NOTE: The exception-return value is consistent with the synthesized stack-frame with the lr[4] bit set to 1, which means that the FPU registers are not included in this stack frame. -
    • +> NOTE: the r0 register is used instead of lr because the Cortex-M0 instruction set cannot manipulate the higher-registers (r9-r15). +> NOTE: The exception-return value is consistent with the synthesized stack-frame with the lr[4] bit set to 1, which means that the FPU registers are not included in this stack frame. -
    • 23 + +
      23
      PendSV exception returns using the special value of the r0 register of 0xFFFFFFF9 (return to Privileged Thread mode using the Main Stack pointer). The synthesized stack frame causes actually a function call to QK_sched_ function in C. -> NOTE: The return from the PendSV exception just executed switches the ARM Cortex-M core to the Privileged Thread mode. The QK_sched_ function internally re-enables interrupts before launching any thread, so the threads always run in the Thread mode with interrupts enabled and can be preempted by interrupts of any priority. -> NOTE: In the presence of the FPU, the exception-return to the QK activator does not change any of the FPU status bit, such as CONTROL.FPCA or LSPACT. -
    • +> NOTE: The return from the PendSV exception just executed switches the ARM Cortex-M core to the Privileged Thread mode. The QK_sched_ function internally re-enables interrupts before launching any thread, so the threads always run in the Thread mode with interrupts enabled and can be preempted by interrupts of any priority. +> NOTE: In the presence of the FPU, the exception-return to the QK activator does not change any of the FPU status bit, such as CONTROL.FPCA or LSPACT. -
    • 24 + +
      24
      The @c Thread_ret function is the place, where the QK activator `QK_activate_()` returns to, because this return address is pushed to the stack in step [16]. Please note that the address of the @c Thread_ret label must be a THUMB address. -
    • -
    • 25-28 + +
      25-28
      If the FPU is present, the read-modify-write code clears the CONTROL[2] bit [2]. This bit, called CONTROL.FPCA (Floating Point Active), would cause generating the FPU-type stack frame, which you want to avoid in this case (because the NMI exception will certainly not use the FPU). -> NOTE: Clearing the CONTROL.FPCA bit occurs with interrupts disabled, so it is protected from a context switch. -
    • -
    • 28-32 +> NOTE: Clearing the CONTROL.FPCA bit occurs with interrupts disabled, so it is protected from a context switch. + + +
      28-32
      The asynchronous NMI exception is triggered by setting ICSR[31]. The job of this exception is to put the CPU into the exception mode and correctly return to the thread level. -
    • -
    • 33 + +
      33
      This endless loop should not be reached, because the NMI exception should preempt the code immediately after step [31] -
    • -
    + + -
    @subsection arm-cm_qk_port-asm_nmi NMI_Handler() Implementation Listing: NMI_Handler() function in qk_port.c file -@code{c} +@code{.c} __attribute__ ((naked)) [1] void NMI_Handler(void) { __asm volatile ( @@ -1140,8 +1119,8 @@ This endless loop should not be reached, because the NMI exception should preemp } @endcode -
      -
    • 1 +
      +
      1
      The @c NMI_Handler is the CMSIS-compliant name of the NMI exception handler. This exception is triggered after returning from the QK activator in step [31] of the previous listing. The job of NMI is to discard its own stack frame and cause the exception-return to the original preempted thread context. The stack contents just after entering NMI is shown below:
       Hi memory
      @@ -1166,31 +1145,29 @@ old SP --> EXC_RETURN (pushed in PendSV [7] if FPU is present)
           SP --> r0   don't care
       Low memory
       
      -
    • -
    • 2 + +
      2
      The stack pointer is adjusted to un-stack the 8 registers of the interrupt stack frame corresponding to the NMI exception itself. This moves the stack pointer from the "old SP" to "SP" in the picture above, which "uncovers" the original exception stack frame left by the PendSV exception. -
    • -
    • 3 + +
      3
      For ARMv6-M, interrupts are enabled by clearing the PRIMASK. -
    • -
    • 4 + +
      4
      For ARMv6-M, The NMI exception returns to the preempted thread using the standard EXC_RETURN, which is in lr. -
    • -
    • 5-6 + +
      5-6
      For the ARMv7-M, interrupts are enabled by writing 0 into the BASEPRI register. -
    • -
    • 7 + +
      7
      If the FPU is used, the EXC_RETURN and the "stack aligner" saved in PendSV step [7] are popped from the stack into r0 and pc, respectively. Updating the pc causes the return from PendSV. -
    • -
    • 8 + +
      8
      Otherwise, NMI returns to the preempted thread using the standard EXC_RETURN, which is in lr. -
    • -
    + + @anchor qk_stack-detail -@image html qk_stack-detail.gif "Detailed stack allocation in QK for ARM Cortex-M" - - +![Detailed stack allocation in QK for ARM Cortex-M](qk_stack-detail.gif) @section arm-cm_qk-isr Writing ISRs for QK @@ -1206,7 +1183,7 @@ The following listing shows an example of the `SysTick_Handler()` ISR (from the @anchor arm-cm_qk-isr-code Listing: An ISR header for QK -@code{c} +@code{.c} void SysTick_Handler(void) __attribute__((__interrupt__)); void SysTick_Handler(void) { ~ ~ ~ @@ -1218,22 +1195,20 @@ The following listing shows an example of the `SysTick_Handler()` ISR (from the } @endcode -
      -
    • 1 +
      +
      1
      Every ISR for QK must call `QK_ISR_ENTRY()` before calling any QP API -
    • -
    • 2 + +
      2
      Every ISR for QK must call `QK_ISR_EXIT()` right before exiting to let the QK kernel schedule an asynchronous preemption, if necessary. -
    • -
    + + @note The QK port to ARM Cortex-M complies with the requirement of the ARM-EABI to preserve stack pointer alignment at **8-byte boundary**. Also, all QP examples for ARM Cortex-M comply with the CMSIS naming convention for all exception handlers and IRQ handlers. - -@section arm-cm_qk-fpu Using the FPU in the QK Port (Cortex-M4F/M7) -If you have the Cortex-M4F CPU and your application uses the hardware FPU, it should be enabled because it is turned off out of reset. The CMSIS-compliant way of turning the FPU on looks as follows: +@section arm-cm_qk-fpu Using the FPU in the QK Port (ARMv7M or higher architectures) If you have the Cortex-M4F CPU and your application uses the hardware FPU, it should be enabled because it is turned off out of reset. The CMSIS-compliant way of turning the FPU on looks as follows: @verbatim SCB->CPACR |= (0xFU << 20); @@ -1245,7 +1220,6 @@ The FPU must be enabled before executing any floating point instruction. An atte Depending on wheter or not you use the FPU in your ISRs, the "Vanilla" QP port allows you to configure the FPU in various ways, as described in the following sub-sections. -
    @subsection arm-cm_qk-fpu_1thread FPU used in ONE thread only and not in any ISR If you use the FPU only at a single thread (active object) and none of your ISRs use the FPU, you can setup the FPU not to use the automatic state preservation and not to use the lazy stacking feature as follows: @@ -1259,7 +1233,6 @@ With this setting, the Cortex-M4F processor handles the ISRs in the exact-same w This FPU setting will lead to FPU errors, if more than one thread or any of the ISRs indeed start to use the FPU -
    @subsection arm-cm_qk-fpu_nthreadd FPU used in more than one thread only or the ISR If you use the FPU in more than one of the threads (active objects) or in any of your ISRs, you should setup the FPU to use the automatic state preservation and the lazy stacking feature as follows: @@ -1271,7 +1244,6 @@ This is actually the default setting of the hardware FPU and is recommended for As described in the ARM Application Note "Cortex-M4(F) Lazy Stacking and Context Switching" [@ref ARM-AN298], the FPU automatic state saving requires more stack plus additional CPU time to save the FPU registers, but only when the FPU is actually used. - @section arm-cm_qk-idle QK Idle Processing Customization in QK_onIdle() QK can very easily detect the situation when no events are available, in which case QK calls the `QK_onIdle()` callback. You can use `QK_onIdle()` to suspended the CPU to save power, if your CPU supports such a power-saving mode. Please note that `QK_onIdle()` is called repetitively from an endless loop, which is the QK idle-thread. The `QK_onIdle()` callback is called with interrupts **enabled** (which is in contrast to the @ref arm-cm_qv-idle "QV_onIdle() callback" used in the non-preemptive configuration). @@ -1293,18 +1265,17 @@ The THUMB-2 instruction set used exclusively in ARM Cortex-M provides a special } @endcode -
      -
    • 1 +
      +
      1
      The preemptive QK kernel calls the `QK_onIdle()` callback with interrupts enabled. -
    • -
    • 2 +
    • +
      2
      The sleep mode is used only in the non-debug configuration, because sleep mode stops CPU clock, which can interfere with debugging. -
    • -
    • 3 +
    • +
      3
      The `WFI` instruction is generated using inline assembly. -
    • -
    - + + @section arm-cm_qk-testing Testing QK Preemption Scenarios @@ -1331,7 +1302,6 @@ The figure below hows how to trigger the GPIOA interrupt from the CCS debugger. The general testing strategy is to break into the application at an interesting place for preemption, set breakpoints to verify which path through the code is taken, and trigger the GPIO interrupt. Next, you need to free-run the code (don’t use single stepping) so that the NVIC can perform prioritization. You observe the order in which the breakpoints are hit. This procedure will become clearer after a few examples. -
    @subsection arm-cm_qk-test-isr Interrupt Nesting Test The first interesting test is verifying the correct tail-chaining to the PendSV exception after the interrupt nesting occurs, as shown in @ref arm-cm_qk-synch-fig "Synchronous Preemption in QK". To test this scenario, you place a breakpoint inside the `GPIOPortA_IRQHandler()` and also inside the `SysTick_Handler()` ISR. When the breakpoint is hit, you remove the original breakpoint and place another breakpoint at the very next machine instruction (use the Disassembly window) and also another breakpoint on the first instruction of the `QK_PendSV` handler. Next you trigger the PIOINT0 interrupt per the instructions given in the previous section. You hit the Run button. @@ -1344,7 +1314,6 @@ The pass criteria of this test are as follows: 3. The last breakpoint hit is the one in `PendSV_Handler()` exception handler, which means that the PendSV exception is tail-chained only after all interrupts are processed. You need to remove all breakpoints before proceeding to the next test. -
    @subsection arm-cm_qk-test-thread Thread Preemption Test The next interesting test is verifying that threads can preempt each other. You set a breakpoint anywhere in the Philosopher state machine code. You run the application until the breakpoint is hit. After this happens, you remove the original breakpoint and place another breakpoint at the very next machine instruction (use the Disassembly window). You also place a breakpoint inside the `GPIOPortA_IRQHandler()` interrupt handler and on the first instruction of the `PendSV_Handler()` handler. Next you trigger the GPIOA interrupt per the instructions given in the previous section. You hit the Run button. @@ -1359,9 +1328,8 @@ The pass criteria of this test are as follows: 4. After this you free-run the application and verify that the next breakpoint hit is the one inside the Philosopher state machine. This validates that the preempted thread continues executing only after the preempting thread (the Table state machine) completes. -
    -@subsection arm-cm_qk-test-fpu Testing the FPU (Cortex-M4F/M7) -In order to test the FPU, the Board Support Package (BSP) for the Cortex-M4F EK-TM4C123GXL board uses the FPU in the following contexts: +@subsection arm-cm_qk-test-fpu Testing the FPU +In order to test the FPU (ARMv7M or higher architectures), the Board Support Package (BSP) for the Cortex-M4F EK-TM4C123GXL board uses the FPU in the following contexts: - In the idle loop via the `QK_onIdle()` callback (QP priority 0) @@ -1376,7 +1344,6 @@ To test the FPU, you could step through the code in the debugger and verify that Next, you can selectively comment out the FPU code at various levels of priority and verify that the QK context switching works as expected with both types of exception stak frames (with and without the FPU). -
    @subsection arm-cm_qk-test-other Other Tests Other interesting tests that you can perform include changing priority of the GPIOA interrupt to be lower than the priority of SysTick to verify that the PendSV is still activated only after all interrupts complete. @@ -1386,23 +1353,18 @@ In yet another test you could post an event to Philosopher active object rather */ /*##########################################################################*/ /*! @page arm-cm_qxk Preemptive "Dual-Mode" QXK Kernel - @tableofcontents -

    This section describes how to use QP on ARM Cortex-M with the @ref qxk "preemptive, dual-mode QXK real-time kernel", which combines the lightweight non-blocking @ref qxk_basic "basic threads" of QK with traditional blocking @ref qxk_extended "extended threads" found in conventional RTOS kernels. QXK provides all typical services of a conventional blocking RTOS, such as blocking time-delays, semaphores, mutextes, and message queues. -

    +This section describes how to use QP on ARM Cortex-M with the @ref qxk "preemptive, dual-mode QXK real-time kernel", which combines the lightweight non-blocking @ref qxk_basic "basic threads" of QK with traditional blocking @ref qxk_extended "extended threads" found in conventional RTOS kernels. QXK provides all typical services of a conventional blocking RTOS, such as blocking time-delays, semaphores, mutextes, and message queues. QXK has been designed specifically for mixing event-driven active objects with traditional blocking code, such as commercial middleware (TCP/IP stacks, UDP stacks, embedded file systems, etc.) or legacy software. @note -If you are currently using QP on top of a conventional 3rd-party RTOS, consider moving your application to the QXK kernel. QXK is not only more efficient than running QP on top of a @ref ports_rtos "traditional 3rd-party RTOS" (because non-blocking @ref qxk_basic "basic threads" take far less stack space and CPU cycles for context switch than the much heavier @ref qxk_extended "extended threads"). But the biggest advantage of QXK is that it __protects__ the application-level code from inadvertent mixing of blocking calls inside the event-driven active objects. Specifically, QXK "knows" the type of the thread context (extended/basic) and asserts internally if a blocking call (e.g., semaphore-wait or a time-delay) is attempted in a basic thread (active object). This is something that a QP port to a @ref ports_rtos "conventional 3rd-party RTOS" cannot do, because such an RTOS runs all code (including active objects) in the context of havyweight extended threads. - +If you are currently using QP on top of a conventional 3rd-party RTOS, consider moving your application to the QXK kernel. QXK is not only more efficient than running QP on top of a @ref ports_rtos "traditional 3rd-party RTOS" (because non-blocking @ref qxk_basic "basic threads" take far less stack space and CPU cycles for context switch than the much heavier @ref qxk_extended "extended threads"). But the biggest advantage of QXK is that it __protects__ the application-level code from inadvertent mixing of blocking calls inside the event-driven active objects. Specifically, QXK "knows" the type of the thread context (extended/basic) and asserts internally if a blocking call (e.g., semaphore-wait or a time-delay) is attempted in a basic thread (active object). This is something that a QP port to a @ref ports_rtos "conventional 3rd-party RTOS" cannot do, because such an RTOS runs all code (including active objects) in the context of heavyweight extended threads. @section arm-cm_qxk-synopsis Synopsis of the QXK Port on ARM Cortex-M - -

    The preemptive, blocking QXK kernel works on ARM Cortex-M as follows: -

    +The preemptive, blocking QXK kernel works on ARM Cortex-M as follows: 1. The ARM Cortex-M processor executes application code in the Privileged Thread mode, which is exactly the mode entered out of reset. The exceptions (including all interrupts) are always processed in the Privileged Handler mode. @@ -1410,31 +1372,30 @@ If you are currently using QP on top of a conventional 3rd-party RTOS, consider 3. QXK uses the Process Stack Pointer (PSP) for handling @ref qxk_extended "extended threads". Each extended thread must provide a private stack space to be associated with the PSP. -4. The QXK port uses the @c PendSV (exception number 14) and the NMI exception (number 2) to perform context switch. The application code (your code) must initialize the Interrupt Vector Table with the addresses of the @c PendSV_Handler and @c NMI_Handler exception handlers. -@n -> NOTE: QXK uses only the CMSIS-compliant exception and interrupt names, such as @c PendSV_Handler, @c NMI_Handler, etc.@n +4. The QXK port uses the @c PendSV (exception number 14) and the NMI or the IRQ exception (number 2) to perform context switch. The application code (your code) must initialize the Interrupt Vector Table with the addresses of the `PendSV_Handler` and `NMI_Handler` exception handlers. +
    +> NOTE: QXK uses only the CMSIS-compliant exception and interrupt names, such as `PendSV_Handler`, `NMI_Handler`, etc.@n > NOTE: The QXK port specifically does **not** use the SVC exception (Supervisor Call). This makes the QXK ports compatible with various "hypervisors" (such as mbed uVisor or Nordic SoftDevice), which use the SVC exception. 5. You need to explicitly **assign priorities of the all interrupts** used in your application, as described in @ref arm-cm_int. -@n -> NOTE: For Cortex-M3/M4/M7 (ARMv7M architecture), the QXK initialization code (executed from the QF initialization) initializes all interrupt priorities to the safe value maskable with the BASEPRI register. However, this is just a safety precaution not to leave the interrupts kernel-unaware, which they are out of reset. It is highly recommended to set the priorities of all interrupts explicitly in the application-level code. +
    +> NOTE: For ARMv7M or higher architectures (M3/M4/M7/M33...), the QXK initialization code (executed from the QF initialization) initializes all interrupt priorities to the safe value maskable with the BASEPRI register. However, this is just a safety precaution not to leave the interrupts kernel-unaware, which they are out of reset. It is highly recommended to set the priorities of all interrupts explicitly in the application-level code. 6. It is strongly recommended that you do not assign the lowest NVIC priority (0xFF) to any interrupt in your application, because it is used by the PendSV handler. For example, with 3 bits of priority implemented in the NVIC, this leaves the following 7 priority levels for you (listed from the lowest to the highest urgency): 0xC0, 0xA0, 0x80, 0x60, 0x40, 0x20, and 0x00 (the highest priority). -@n -> NOTE: The prioritization of interrupts, including the PendSV exception, is performed entirely by the NVIC. Because the PendSV has the lowest priority in the system, the NVIC tail-chains to the PendSV exception only after exiting the last nested interrupt. +
    +> NOTE: The prioritization of interrupts, including the PendSV exception, is performed entirely by the NVIC. Because the PendSV has the lowest priority in the system, the NVIC tail-chains to the PendSV exception only after exiting the last nested interrupt. 7. ISRs are written as regular C functions, but they need to call QXK_ISR_ENTRY() before using any QF services, and they must call QXK_ISR_EXIT() after using any of the QF services. 8. ARM Cortex-M enters interrupt context without disabling interrupts. Generally, you should not disable interrupts inside your ISRs. In particular, the QF services (such as QF_PUBLISH(), QF_TICK_X(), and QACTIVE_POST()) should be called with interrupts enabled, to avoid nesting of critical sections. -@n -> NOTE: If you don't wish an interrupt to be preempted by another interrupt, you can always prioritize that interrupt in the NVIC to a higher or equal level as other interrupts (use a lower numerical value of priority). +
    +> NOTE: If you don't wish an interrupt to be preempted by another interrupt, you can always prioritize that interrupt in the NVIC to a higher or equal level as other interrupts (use a lower numerical value of priority). 9. In compliance with the ARM Application Procedure Call Standard (AAPCS), the QXK kernel always preserves the 8-byte alignment of the stack (both MSP and PSP). -
    @subsection arm-com_qxk_vfp Using the VFP -If you have the Cortex-M4F/M7 CPU and your application is compiled with the VFP present, the QXK kernel will enable the VFP along with the VFP automatic state preservation and lazy stacking features. This will cause the NVIC to automatically use the VFP-exception stack frame (with additional 18 VFP registers S0-S15 plus VFP status and stack "aligner"). The QXK context switch will add to this the rest of the VFP registers (S16-S31) on context switches to and from extended threads. +If you have the ARMv7M or higher architectures (ARMv7M or higher architectures) and your application is compiled with the VFP present, the QXK kernel will enable the VFP along with the VFP automatic state preservation and lazy stacking features. This will cause the NVIC to automatically use the VFP-exception stack frame (with additional 18 VFP registers S0-S15 plus VFP status and stack "aligner"). The QXK context switch will add to this the rest of the VFP registers (S16-S31) on context switches to and from extended threads. @note With VFP enabled, any QXK thread (both a basic and an extended thread) will use 136 more bytes of its stack space, regardless if VFP is actually used by this thread. However, due to the "lazy-stacking" hardware feature, only a thread that actually uses the VFP will save and restore the VFP registers on the stack (which will cost some additional CPU cycles to perform a context switch). diff --git a/doxygen/ports_native.dox b/doxygen/ports_native.dox index 3658c30c9..3c3b04aaf 100644 --- a/doxygen/ports_native.dox +++ b/doxygen/ports_native.dox @@ -1,7 +1,6 @@ /*##########################################################################*/ /*! @page ports_native Native (Bare-Metal) Ports -- @subpage lint (generic C++ compiler) - @subpage arm-cm (Cortex-M0/M0+/M3/M4/M4/M7) - @ref arm-cm_qv (ARM-CLANG, ARM-KEIL, GNU-ARM, IAR-ARM ) - @ref arm-cm_qk (ARM-CLANG, ARM-KEIL, GNU-ARM, IAR-ARM) @@ -16,148 +15,37 @@ - @ref msp430_qv (TI-CCS, IAR toolchains) - @ref msp430_qk (TI-CCS, IAR toolchains) -*/ -/*##########################################################################*/ -/*! @page lint PC-Lint-Plus - -@tableofcontents - -

    The QP/C++ distribution contains a "port" to PC-Lint-Plus static analysis tool from Gimpel Software, which is a static analysis tool for C and C++ with one of the longest track records and best value of the money in the industry. The "PC-Lint-Plus port" allows you to statically analyze the QP/C++ source code and facilitates static analysis of your **application code** based on QP/C++. -

    -The QP/C++ "port" to PC-Lint-Plus is located in the directory qpcpp/ports/lint-plus and includes also lint configuration files, as well as an example of "linting" application code in the directory qpcpp/examples/arm-cm/dpp_ek-tm4c123gxl/lint-plus. The following listing describes the most important files in these three directories. - -@code{.x} - qpcpp\ - QP/C++ installation directory - | - | +-ports/ - QP/C++ ports directory - | | +-lint-plus/ - QP/C++ "port" to PC-Lint-Plus - | | | +-16bit/ - QP/C++ "port" to 16-bit CPUs - | | | | +-cpu.lnt - Lint options for a 16-bit CPU - | | | | +-cstdint - Standard exact-width integers for a 16-bit CPU - | | | +-32bit/ - QP/C++ "port" to 32-bit CPUs - | | | | +-cpu.lnt - Lint options for a 32-bit CPU - | | | | +-cstdint - Standard exact-width integers for a 32-bit CPU - | | | +-qk/ - QP/C++ port with the QK kernel - | | | +-qv/ - QP/C++ port with the QV kernel - | | | +-qxk/ - QP/C++ port with the QXK kernel - | | | +-au-ds.lnt - Dan Saks recommendations - | | | +-au-misra-cpp.lnt - MISRA-C++:2008 compliance checks - | | | +-qpc.lnt - PC-Lint-Plus options for QP/C++ applications - | | | +-std.lnt - Standard PC-Lint-Plus settings recommended by Quantum Leaps - | | | +-lin.bat - Batch file to invoke PC-Lint-Plus to run analysis of QP/C++ code - | | | +-options.lnt - PC/Lint-Plus options for "linting" QP/C++ source code - | | | +-lint_qf.log - PC/Lint-Plus output for the QEP/QF components of QP/C++ - | | | +-lint_qs.log - PC/Lint-Plus output for the QS component of QP/C++ - | | | +-lint_qv.log - PC/Lint-Plus output for the QV component of QP/C++ - | | | +-lint_qk.log - PC/Lint-Plus output for the QK component of QP/C++ - | | | +-lint_qxk.log - PC/Lint-Plus output for the QXK component of QP/C++ - | | | +-qep_port.hpp - QEP component "port" to a "generic C++ compiler" - | | - | +-examples\ - QP/C++ examples directory (application) - | | +-arm-cm\ - QP/C++ examples for ARM Cortex-M - | | | +-dpp_ek-tm4c123gxl\ - DPP example on the EK-TM4C123GLX board - | | | | +-lint-plus\ - directory for linting the application - | | | | | +-lin.bat - Batch to run PC-Lint-Plus analysis of application code - | | | | | +-options.lnt - PC-Lint-Plus options for "linting" of application code -@endcode - - - -@section lint_qpcpp Linting the QP/C++ Source Code -The directory qpcpp/ports/lint-plus (see listing above) contains also the **lin.bat** batch file for "linting" the QP/C++ source code. The `lin.bat` batch file invokes PC-Lint-Plus and generates the lint output files. As shown in the listing above, the lint output is collected into four text files `lint_qf.log`, `lint_qs.log`, `lint_qk.log`, `lint_qv.log`, and `lint_qs.log`, for QEP/QF, QK, QV, QXK and QS components of the QP/C++ framework, respectively. - -@note -In order to execute the `lin.bat` file on your system, you might need to adjust the symbol `PCLP_DIR` at the top of the batch file, to the PC-Lint-Plus installation directory on your computer. - -@remarks -The `lin.bat` batch file invoked without any command-line options checks the QP/C++ code in the ::Q_SPY build configuration with software tracing enabled. However, by the nature of software tracing, the ::Q_SPY configuration transgresses many more MISRA-C++ rules than the standard configuration. However, the ::Q_SPY configuration is never used for production code, so the MISRA-C++ compliance of the QP/C++ framework should not be judged by the deviations that happen only in the ::Q_SPY configuration. - - -According to the PC-Lint-Plus guidelines, the `lin.bat` uses two option files: the `qpcpp.lnt` configuration file discussed before and the `options.lnt` configuration file that covers all deviations from the MISRA-C++ rules **within the QP/C++ source code**. These deviations are intentionally localized to QP/C++ code and are independent from your **application-level** code. In other words, a MISRA-C++ deviation present in the QP/C++ code does **not** mean that such deviation is somehow allowed or its detection is somehow suppressed in the **application-level** code. This is because the the `options.lnt` configuration file for internals of QP/C++ is **not** used to "lint" the application-level code. - - - -@section lint_app Linting QP/C++ Application Code -The QP/C++ baseline code contains an example of MISRA-C++ compliance checking with PC-Lint-Plus: the DPP example for the EK-TM4C123GLX Cortex-M4F board, located in the directory qpcpp/examples/arm-cm/dpp_ek-tm4c123gxl/lint-plus. The PC-Lint-Plus analysis is very simple and requires invoking the **lin.bat** file. - -@note -In order to execute the **lin.bat** file on your system, you might need to adjust the symbol `PCLP_DIR` at the top of the batch file, to the PC-Lint-Plus installation directory on your computer. You - - -The `lint-plus` subdirectory contains also the `options.lnt` with the PC-Lint-Plus options specific to linting the application. Here, you might include linting options for your specific compiler, as described in the "PC-Lint-Plus Manual", Chapter 2 "Installation and Configuration". - - - -@section lint_options Structure of PC-Lint-Plus Options for QP/C++ -PC-Lint-Plus has several places where it reads its currently valid options: -- From special PC-Lint-Plus option files (usually called `*.lnt`) -- From the command line -- From within the special lint-comments in the source code modules (not recommended) - -The QP/C++ source code and example application code has been "linted" only by means of the first alternative (option files) with possibility of adding options via command line. The third alternative--lint comments--is not used and Quantum Leaps does not recommend this alternative. - -@note -The QP/C++ source code is completely free of lint comments, which are viewed as a contamination of the source code. - -The structure of the PC-Lint-Plus option files used for "linting" QP/C++ follows exactly the Gimpel Software guidelines for configuring PC-Lint-Plus (See Section 2 "Configuration" in the *PC-Lint-Plus Manual*). The design and grouping of the lint options also reflects the fact that static code analysis of a software framework, such as QP/C++, has really two major aspects. First, the source code of the framework itself has to be analyzed. But even more important and helpful to the users of the framework is providing the infrastructure to effectively analyze the application-level code based on the framework. With this in mind, the PC-Lint-Plus options for static analysis of QP/C++ are divided into two groups, located in directories qpcpp/include and qpcpp/ports/lint. These two groups are for analyzing QP/C++ **applications** and QP/C++ **source code**, respectively. - -As shown in the PC-Lint-Plus "port" files description, the directory qpcpp/include, contains the PC-Lint-Plus options for "linting" the application code along with all platform-independent QP/C++ header files required by the applications. This collocation of lint options with header files simplifies "linting", because specifying just `-iqpcpp/include` include directory to PC-Lint-Plus accomplishes both inclusion of QP/C++ header files and PC-Lint-Plus options. -Note that the `qpc/include` directory contains all PC-Lint-Plus option files used in "linting" the code, including the standard MISRA-C++:2008 `au-misra-cpp.lnt` option file as well as Dan Saks' recommendations `au-ds.lnt`, which are copied from the PC-Lint-Plus distribution. This design freezes the lint options for which the compliance has been checked. - - - -@subsection lint_std_lnt The std.lnt option file -According to the Gimpel Software *PC-Lint-Plus Configuration Guidelines*, the file `qpcpp/include/std.lnt` file, contains the top-level options, which Quantum Leaps recommends for all projects. These options include the formatting of the PC-Lint-Plus messages and making two passes to perform better cross-module analysis. However, the most important option is `-restore_at_end`, which has the effect of surrounding each source file with options `-save` and `-restore`. This precaution prevents options from "bleeding" from one file to another. - -Top-level option file std.lnt -@include std.lnt - - - -@subsection lint_qpcpp_lnt The qpcpp.lnt option file -The most important file for "linting" QP/C++ applications is the **qpcpp.lnt** option file. This file handles all deviations from the MISRA-C++:2008 rules, which might arise at the application-level code from the use of the QP/C++ framework. In other words, the **qpcpp.lnt** option file allows completely clean "linting" of the application-level code, as long as the application code does not violate any of the MISRA-C++:2008 rules. - -At the same time, the **qpcpp.lnt** option file has been very carefully designed not to suppress any MISRA-C++:2008 rule checking outside the very specific context of the QP/C++ API. In other words, the qpcpp.lnt option file still supports 100% of the MISRA-C++:2008 rule checks that PC-Lint-Plus is capable of performing. - -@remarks -For example, for reasons explained in Section 5.10 of the "QP/C++ MISRA Compliance Matrix", QP/C++ extensively uses function-like macros, which deviates from the MISRA-C++:2008 Rule 16-0-4 and which PC-Lint-Plus checks with the warning 9026. However, instead of suppressing this warning globally (with the -e9096 directive), the qpcpp.lnt option file suppresses warning 9096 only for the specific QP function-like macros that are visible to the application level. So specifically, the `qpcpp.lnt` file contains directives `-esym(9026, Q_TRAN, Q_SUPER, ...)`, which suppresses the warning only for the specified macros, but does not disable checking of any other macros in the application-level code. - - -@next{arm-cm} +@nav_next{arm-cm} */ /*##########################################################################*/ /*! @page arm-cr ARM Cortex-R -@image html under_construction.jpg - -@section arm-cr_qk Preemptive QK Kernel - -@includelineno ports/arm-cr/qk/gnu/qk_port.hpp +The QP/C/C++ ports and examples for ARM Cortex-R are described in the Quantum Leaps Application Note @webref{doc/AN_QP_and_ARM-Cortex-R.pdf, QP and ARM Cortex-R}. -@section arm-cr_qv Cooperative QV Kernel +[![QP and ARM Cortex-R](img/AN.jpg)](https://www.state-machine.com/doc/AN_QP_and_ARM-Cortex-R.pdf) +@caption{[Application Note: "QP and ARM Cortex-R"](https://www.state-machine.com/doc/AN_QP_and_ARM-Cortex-R.pdf)} @next{arm7-9} */ /*##########################################################################*/ /*! @page arm7-9 ARM7/ARM9 -@image html under_construction.jpg - -@section arm7-9_qk Preemptive QK Kernel - -@includelineno ports/arm7-9/qk/gnu/qk_port.s +The QP/C/C++ ports and examples for ARM7/ARM9 are described in the Quantum Leaps Application Note @webref{doc/AN_QP_and_ARM-Cortex-R.pdf, QP and ARM7/ARM9}. -@section arm7-9_qv Cooperative QV Kernel +[![QP and ARM Cortex-R](img/AN.jpg)](https://www.state-machine.com/doc/AN_QP_and_ARM7_ARM9-GNU.pdf) +@caption{[Application Note: "QP and ARM7/ARM9"](https://www.state-machine.com/doc/AN_QP_and_ARM7_ARM9-GNU.pdf)} @next{msp430} */ /*##########################################################################*/ /*! @page msp430 MSP430 -@image html under_construction.jpg +The QP/C/C++ ports and examples for MSP430 are described in the Quantum Leaps Development Kit @webref{doc/QDK_MSP430-CCS.pdf, QP and MSP430 with CCS} and @webref{doc/QDK_MSP430-IAR.pdf, QP and MSP430 with IAR}. -@section msp430_qk Preemptive QK Kernel +[![QP and QP and MSP430 with CCS](img/AN.jpg)](https://www.state-machine.com/doc/QDK_MSP430-CCS.pdf) +@caption{[Application Note: "QP and MSP430-CCS"](https://www.state-machine.com/doc/QDK_MSP430-CCS.pdf)} -@section msp430_qv Cooperative QV Kernel +[![QP and QP and MSP430 with IAR](img/AN.jpg)](https://www.state-machine.com/doc/QDK_MSP430-IAR.pdf) +@caption{[Application Note: "QP and MSP430-IAR"](https://www.state-machine.com/doc/QDK_MSP430-IAR.pdf)} */ diff --git a/doxygen/ports_rtos.dox b/doxygen/ports_rtos.dox index 35c1deb0f..2a54db0b4 100644 --- a/doxygen/ports_rtos.dox +++ b/doxygen/ports_rtos.dox @@ -31,26 +31,22 @@ Combined with a conventional RTOS, QP/C++ takes full advantage of the multitaski /*##########################################################################*/ /*! @page embos embOS -

    The QP/C/C++ ports and examples for embOS are described in the Quantum Leaps Application Note @webref{doc/AN_RTOS-embOS.pdf, QP and embOS}. -

    +![SEGGER embOS](logo_embos.png) + +The QP/C/C++ ports and examples for embOS are described in the Quantum Leaps Application Note @webref{doc/AN_RTOS-embOS.pdf, QP and embOS}. -@htmlonly -
    - -
    -Application Note: QP and embOS -
    -
    -@endhtmlonly +[![Application Note: QP and embOS](img/AN.jpg)](https://www.state-machine.com/doc/AN_RTOS-embOS.pdf) +@caption{[Application Note: "QP and embOS"](https://www.state-machine.com/doc/AN_RTOS-embOS.pdf)} @next{freertos} */ /*##########################################################################*/ /*! @page freertos FreeRTOS - @tableofcontents +![FreeRTOS](logo_freertos.png) + @section freertos_about About the QP Port to FreeRTOS The ports/freertos/ directory contains a generic platform-independent QP/C++ port to FreeRTOS kernel (version 10). The provided QP port to FreeRTOS has been designed *generically* to rely exclusively on the existing FreeRTOS API. This means that the port should run without changes on any CPU/compiler platform supported by FreeRTOS. @@ -79,21 +75,20 @@ The design of FreeRTOS requires the use of special "FromISR" API inside ISRs, wh - The QP port does not mandate any specific method to manage the QP time events, but the provided examples use the FreeRTOS "hook" `vApplicationTickHook()` to periodically invoke the QP clock tick QF_TICK_X_FROM_ISR(). (NOTE: the `vApplicationTickHook()` executes in the ISR context and therefore mandates the use of the "FromISR" APIs). - @section freertos_examples Example Code -The QP port to FreeRTOS comes with examples located in the directory `qpc/examples/freertos/`. Currently, the examples are provided for the following boards and development toolchains: +The QP port to FreeRTOS comes with examples located in the directory `qpcpp/examples/freertos/`. Currently, the examples are provided for the following boards and development toolchains: - EK-TM4C123GXL (ARM Cortex-M4F), ARM-KEIL, GNU-ARM, IAR-ARM - STM32F746G-Discovery (ARM Cortex-M7), ARM-KEIL, GNU-ARM, IAR-ARM - @subsection freertos_isr Writing ISRs for QP/FreeRTOS The provided examples show how to write regular "kernel-aware" ISRs as well as "kernel-unaware" ISRs for QP/FreeRTOS. (See also the FreeRTOS documentation for [configMAX_SYSCALL_INTERRUPT_PRIORITY](https://www.freertos.org/a00110.html#kernel_priority). -Here is an example of a regular "kernel-aware" ISR (note the use of the "FromISR" QP APIs"): +Here is an example of a regular "kernel-aware" ISR (note the use of the `FromISR` suffix in the QP APIs): -@code{cpp} +@code{.cpp} +// NOTE: only the "FromISR" API variants are allowed in the ISRs! void GPIOPortA_IRQHandler(void) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; @@ -108,9 +103,9 @@ void GPIOPortA_IRQHandler(void) { } @endcode -Here is an example of a "kernel-unaware" ISR (See also the FreeRTOS documentation for [configMAX_SYSCALL_INTERRUPT_PRIORITY](https://www.freertos.org/a00110.html#kernel_priority): +Here is an example of a "kernel-unaware" ISR (See also the FreeRTOS documentation for [configMAX_SYSCALL_INTERRUPT_PRIORITY](https://www.freertos.org/a00110.html#kernel_priority): -@code{cpp} +@code{.cpp} // ISR for receiving bytes from the QSPY Back-End // NOTE: This ISR is "kernel-unaware" meaning that it does not interact with // the FreeRTOS or QP and is not disabled. Such ISRs don't need to call @@ -150,7 +145,7 @@ void vApplicationTickHook(void) { @subsection freertos_ao Starting Active Objects in QP/FreeRTOS As mentioned in the @ref freertos_about "FreeRTOS port summary", the QP port to FreeRTOS uses the [static memory allocation of FreeRTOS](https://freertos.org/Static_Vs_Dynamic_Memory_Allocation.html). This means that all memory for an active object, including the private queue buffer and the private **stack** for the the associated FreeRTOS task must be allocated by the user. Here is an example code that starts an active object: -@code{cpp} +@code{.cpp} int main() { . . . static QEvt const *tableQueueSto[N_PHILO]; @@ -162,30 +157,23 @@ int main() { tableQueueSto, // event queue storage Q_DIM(tableQueueSto), // queue length [events] tableStack, // stack storage - sizeof(tableStack), // stack size [bytes] - nullptr); // initialization param (not used) + sizeof(tableStack)); // stack size [bytes] . . . return QP::QF::run(); // run the QF application } @endcode - -@next{embos} +@next{threadx} */ /*##########################################################################*/ /*! @page threadx ThreadX -

    The QP/C/C++ ports and examples for ThreadX are described in the Quantum Leaps Application Note QP and ThreadX. -

    +![ThreadX](logo_threadx.jpg) -@htmlonly -
    - -
    -Application Note: QP and ThreadX -
    -
    -@endhtmlonly +The QP/C/C++ ports and examples for ThreadX (now Azure RTOS) are described in the Quantum Leaps Application Note @webref{doc/AN_RTOS-ThreadX.pdf, QP and ThreadX}. + +[![Application Note: QP and ThreadX](img/AN.jpg)](https://www.state-machine.com/doc/AN_RTOS-ThreadX.pdf) +@caption{[Application Note: "QP and ThreadX"](https://www.state-machine.com/doc/AN_RTOS-ThreadX.pdf)} @next{uc-os2} */ @@ -193,17 +181,16 @@ Application Note: QP and ThreadX /*##########################################################################*/ /*! @page uc-os2 uC-OS2 +![uC-OS2](logo_uc-os2.jpg) + @section uc-os2_about About the QP Port to uC-OS2 -This directory contains a generic platform-independent QP/C++ port to uC-OS2 V2.92. +This directory contains a generic platform-independent QP/C port to uC-OS2 V2.92. Typically, you should not need to change the files in this directory to adapt the QP-uC-OS2 port on any CPU/Compiler to which uC-OS2 has been ported, because all the CPU and compiler specifics are handled by the uC-OS2 RTOS. -@note -Currently, the port has been tested only on ARM Cortex-M3 and M4F. - @section uc-os2_source uC-OS2 Source and ARM Cortex-M3/M4 Ports -The uC-OS2 V2.92 source code and ports are located in 3rd_party/uC-OS2. Please make sure to read about uC-OS2 licensing in the README file found in this directory. +The uC-OS2 V2.92 source code and ports are located in `3rd_party/uc-os2`. Please make sure to read about uC-OS2 licensing in the README file found in this directory. @note The official Micrium ARM-Cortex-M ports have been modified by Quantum Leaps to remove the dependencies on the Micrium's uC-CPU and uC-LIB components, and instead to inter-operate with the Cortex Microcontroller Software Interface Standard (CMSIS). @@ -254,14 +241,8 @@ Specifically, the QP source files qf_actq.cpp and qf_mem.cpp must **NOT** be inc The QP/C/C++ ports and examples for uC-OS2 are described in the Quantum Leaps Application Note @webref{doc/AN_RTOS-uCOS2.pdf, QP and uC-OS2}. -@htmlonly -
    - -
    -Application Note: QP and uC-OS2 -
    -
    -@endhtmlonly +[![QP and uC-OS2](img/AN.jpg)](https://www.state-machine.com/doc/AN_RTOS-uCOS2.pdf) +@caption{[Application Note: QP and uC-OS2](https://www.state-machine.com/doc/AN_RTOS-uCOS2.pdf)} @next{ports_os} */ diff --git a/doxygen/sm.dox b/doxygen/sm.dox deleted file mode 100644 index 74925ec1c..000000000 --- a/doxygen/sm.dox +++ /dev/null @@ -1,307 +0,0 @@ -namespace QP { - -/*! @page sm Coding State Machines in QP/C++ - -@tableofcontents - -

    This section describes how to implement hierarchical state machines with the QP/C++ real-time embedded framework, which is quite a mechanical process consisting of just a few simple rules. (In fact, the process of coding state machines in QP/C++ has been automated by the QM model-based design and code-generating tool.) -

    - -To focus this discussion, this section uses the Calculator example, located in the directory qpcpp/examples/workstation/calc. This example has been used in the PSiCC2 book (Section 4.6 "Summary of Steps for Implementing HSMs with QEP") - -This section explains how to code the following (marked) elements of a hierarchical state machine: - -![Fragment of the Calculator hierarchical state machine](hsm.png) - -
      -
    • 1 The top-most initial pseudo-state -
    • -
    • 2 A state (nested in the implicit `top` state) -
    • -
    • 3 An entry action to a state -
    • -
    • 4 An exit action from a state -
    • -
    • 5 An initial transition nested in a state -
    • -
    • 6 A regular state transition -
    • -
    • 7 A state (substate) nested in another state (superstate) -
    • -
    • 8 Even more deeply nested substate -
    • -
    • 9 A choice point with a guard -
    • -
    - -@attention -This section describes the "no me-> pointer" state machine implementation introduced in QP/C++ 6.5.0, where the state-handlers are regular **member** functions of the state machine class. This means that the state-handlers have direct access to all other members of the state machine class via the implicit `this` pointer, without the need for the `me` pointer. This "no me-> pointer" state machine implementation is supported in the QM modeling tool starting from version 4.5.0. - - -@note -This section describes the @ref sm_qhsm_strategy "QHsm state machine implementation strategy", suitable for **manual coding** of hierarchical state machines in QP/C++. The alternative @ref sm_qmsm_strategy "QMsm state machine implementation strategy", which QP/C++ also supports, is not covered in this section, as the code needs to be generated automatically by the QM modeling tool. - - -@par Historical Notes -The previous implementation (from QP/C++ version 3.x through 6.4.x) used state-handlers that were `static` members of the state machine class, which don't have the `this` pointer and therefore needed to use the specially supplied "me-> pointer" to access the members of the state machine class. That previous "me-> pointer" state machine implementation style is still supported in QP/C++ for backwards compatibility with the existing code, but it is not recommended for new designs.@n -@n -An even earlier QP/C++ state machine implementation strategy, used in QP/C++ version 2.x and published in the first edition of the PSiCC book, also implemented state handlers as regular *members* of the state machine class. However, this earlier implementation relied internally on pointers to *member* functions, which turned out to be a problematic in practice, because some embedded C++ compilers at the time didn't implement pointers to *member* functions efficiently. Therefore, the implementation published in the second edition of the PSiCC2 book, switched to *static* state-handler functions (without the `this` pointer), which allowed it to use internally the simple pointers to functions that are very efficient.@n -@n -This latest "no me-> pointer" state machine implementation style in QP/C++ applies a hybrid approach. Internally, it represents states as simple and efficient pointers to "state-caller" functions. But these "state-caller" functions call "state-handlers" as regular members of the state machine class, which have the `this` pointer and therefore can access all members of the state machine class naturally (without the need for the "me-> pointer"). - - - -@section sm_decl State Machine Declaration -Hierarchical state machines are represented in QP/C++ as subclasses of the @ref classes "QHsm abstract base class", which is defined in the header file qpcpp\include\qep.h. Please note that abstract classes like QP::QMsm, QP::QActive and QP::QMActive are also subclasses of QP::QHsm, so their subclasses also can have state machines. - -@code{cpp} - [1] class Calc : public QP::QHsm { - private: - [2] double m_operand1; - uint8_t m_operator; - - public: - [3] Calc() // constructor - [4] : QHsm(&initial) // superclass' constructor - {} - protected: - [5] Q_STATE_DECL(initial); - [6] Q_STATE_DECL(on); - Q_STATE_DECL(ready); - Q_STATE_DECL(result); - Q_STATE_DECL(begin); - . . . -@endcode - -
      -
    • 1 Class `Calc` (Calculator) derives from QP::QHsm, so it can have a state machine -
    • -
    • 2 The class can have data members (typically private), which will be accessible inside the state machine as the "extended-state variables". -
    • - -@anchor sm_ctor -
    • 3 The class needs to provide a **constructor**, typically without any parameters. -
    • -
    • 4 The constructor must call the appropriate superclass' constructor. The superclass' constructor takes the top-most a pointer to the `initial` pseudo-state (see step [5]), which binds the state-machine to the class. -
    • -
    • 5 Each state machine must have exactly one initial pseudo-state, which by convention should be always called **initial**. The initial pseudo-state is declared with the macro Q_STATE_DECL(initial). -
    • -
    • 6 The same Q_STATE_DECL() macro is also used to declare all other states in the state machine. -
    • -
    - - - -@subsection sm_state_decl The Q_STATE_DECL() Macro -The Q_STATE_DECL() macro declares **two** functions for every state: the "state-handler" **regular member** function and the "state-caller" **static member** function. So, for example, the declaration of the "on" state Q_STATE_DECL(on) expands to the following two declarations within the `Calc` class: - -@code{cpp} -[1] QP::QState on_h(QP::QEvt const * const e); // "state-handler" -[2] static QP::QState on(void * const me, QP::QEvt const * const e); // "state-caller" -@endcode - -The two functions have each a different purpose. - -
      -
    • 1 The "state-handler" `on_h()` is a **regular member** function used to implement the state behavior. As a regular class member, it has convenient, direct access to the state machine class attributes. The "state-handler" is called by the "state-caller". -
    • -
    • 2 The "state-caller" `on()` is a **static member** function that has a simple job to call the state-handler member function on the specified instance of the class. Internally, the QEP event processor uses "state-callers" as unique "handles" for the states. Specifically, the QEP event processor uses the simple **function pointers** to these `state-callers`, which are simple objects (e.g. 32-bit addresses in ARM Cortex-M CPUs), because they don't use the `this` calling convention. These simple function pointers can be stored very efficiently inside the state machine objects and can be compared quickly inside the QEP algorithm that implements the UML semantics of hierarchical state machines. -
    • -
    - -@sa -@ref sm_call - -@remark -Because the state-handler functions are regular members of the state machine class, they can be `virtual`, which allows them to be overridden in the subclasses of a given state machine class. Such **inheritance of entire sate machines** is an advanced concept, which should be used only in very special circumstances and with great caution. To declare a `virtual` state-handler, you simply prepend `virtual` in front of the Q_STATE_DECL() macro, as in the following examples: -@code{cpp} -virtual Q_STATE_DECL(on); -virtual Q_STATE_DECL(ready); -. . . -@endcode - - - -@section sm_def State Machine Definition -The definition of the state machine class is the actual code for your state machine. You need to define (i.e., write the code for) all "state-handler" member functions you declared in the @ref sm_decl "state machine class declaration". You don't need to explicitly define the "state-caller" static functions, because they are synthesized implicitly in the macro Q_STATE_DEF()). - -One important aspect to realize about coding "state-handler" functions is that they are always called from the @ref comp_qep "QEP event processor". The purpose of the "state-handlers" is to perform *your* specific actions and then to *tell* the event processor what needs to be done with the state machine. For example, if your "state-handler" performs a state transition, it executes some actions and then it calls the special @ref QP::QHsm::tran() "tran()" function, where it specifies the `` state of this state transition. The state-handler then **returns** the status from the `tran()` function, and through this return value it informs the @ref comp_qep "QEP event processor" what needs to be done with the state machine. Based on this information, the event-processor might decide to call this or other state-handler functions to process the same current event. The following code examples should make all this clearer. - - - -@subsection sm_state_def The Q_STATE_DEF() Macro -Every state that has been declared with the @ref sm_decl "Q_STATE_DECL()" macro in the state machine class needs to be defined with the Q_STATE_DEF() macro. For example, the state "ready" in the Calculator state machines, the Q_STATE_DEF(Calc, ready) macro expands into the following code: - -@code{cpp} -[1] QP::QState Calc::ready(void * const me, QP::QEvt const * const e) { - return static_cast(me)->ready_h(e); - } -[2] QP::QState Calc::ready_h(QP::QEvt const * const e) -@endcode - -
      -
    • 1 The static `Calc::ready()` state-caller function is fully defined to call the "state-handler" function on the provided `me` pointer, which is explicitly cast to the class instance. -
    • -
    • 2 The signature of the `Calc::ready_h()` "state-handler" member function is provided, which needs to be followed by the body (`{...}`) of the "state-handler" member function. -
    • -
    - - - -@subsection sm_def_init Top-Most Initial Pseudostate -Every state machine must have exactly one top-most initial pseudo-state, which is assumed when the state machine is instantiated in the @ref sm_ctor "constructor" of the state machine class. By convention, the initial pseudo-state should be always called **initial**. - -This top-most initial pseudo-state has one transition, which points to the state that will become active after the state machine is initialized (through the QHsm::init() function). The following code the definition of the `initial` pseudo-state for the `Calc` class: - -@code{cpp} -[1] Q_STATE_DEF(Calc, initial) { -[2] . . . // initialize the members of the state machine class -[3] (void)e; // unused parameter -[4] return tran(&on); - } -@endcode - -
      -
    • 1 The initial pseudo-state is defined by means of the macro Q_STATE_DEF(), which takes two parameters: the class name and the state name (`initial` in this case). -
    • -
    • 2 The function body following the macro Q_STATE_DEF() provides the definition of the "state-handler" member function, so it can access all class members via the implicit `this` pointer. -
    • -
    • 3 The initial pseudo-state receives the "initialization event" `e`, which is often not used. If the event is not used, this line of code avoids the compiler warning about unused parameter. -
    • -
    • 4 The top-most initial transition from the initial pseudo-state is coded with the function @ref QP::QHsm::tran() "tran()". The single parameter to the `tran()` function is the pointer to the target state of the transition. The top-most initial pseudo-state must return the value from the `tran()` function. -
    • -
    - - - -@subsection sm_def_state State-Handler Member Functions -Every regular state (including states nested in other states) is also coded with the Q_STATE_DEF() macro. The function body, following the macro, consists of the `switch` statement that discriminates based on the event signal (`e->sig`). The following code shows the complete definition of the Calculator "on" state. The explanation section below the code clarifies the main points. - -@code{cpp} -[1] Q_STATE_DEF(Calc, ready) { -[2] QP::QState status_; -[3] switch (e->sig) { -[4] case Q_ENTRY_SIG: { -[5] BSP_message("ready-ENTRY;"); -[6] status_ = Q_RET_HANDLED; -[7] break; - } -[8] case Q_EXIT_SIG: { - BSP_message("ready-EXIT;"); -[9] status_ = Q_RET_HANDLED; - break; - } -[10] case Q_INIT_SIG: { - BSP_message("ready-INIT;"); -[11] status_ = tran(&begin); - break; - } - case DIGIT_0_SIG: { - BSP_clear(); - status_ = tran(&zero1); - break; - } -[12] case DIGIT_1_9_SIG: { - BSP_clear(); -[13] BSP_insert(Q_EVT_CAST(CalcEvt)->key_code); -[14] status_ = tran(&int1); - break; - } - case POINT_SIG: { - BSP_clear(); - BSP_insert((int)'0'); - BSP_insert((int)'.'); - status_ = tran(&frac1); - break; - } - case OPER_SIG: { -[15] m_operand1 = BSP_get_value(); -[16] m_operator = Q_EVT_CAST(CalcEvt)->key_code; - status_ = tran(&opEntered); - break; - } - case CE_SIG: { - BSP_clear(); - status_ = tran(&ready); - break; - } -[17] default: { -[18] status_ = super(&on); - break; - } - } -[19] return status_; - } -@endcode - -
      -
    • 1 The state is defined by means of the macro Q_STATE_DEF(), which takes two parameters: the class name and the state name (`on` in this case). -
    • -
    • 2 The automatic variable `status_` will hold the status of what will happen in the state-handler. This status will be eventually returned from the state-handler to the QEP event processor. -
    • -
    • 3 Generally, every state handler is structured as a single switch that discriminates based on the signal of the **current event** `e->sig`, which is passed to the state-handler as parameter. -
    • -
    • 4 The special, reserved event signal @ref QP::QHsm::Q_ENTRY_SIG "Q_ENTRY_SIG" is generated by the QEP event processor to let the state-handler process an **entry action** to the state.@n -NOTE: By convention, all event signals end with the `_SIG` suffix. The `_SIG` suffix is omitted in the QM state machine diagrams. -
    • - -
    • 5 You place your own code, which might contain references to the members of the state machine class (via the implicit `this` pointer) -
    • -
    • 6 After your *entry action* code, you inform the QEP event processor that the state entry has been handled by setting `status_` to @ref QP::QHsm::Q_RET_HANDLED "Q_RET_HANDLED". -
    • -
    • 7 Finally, you close each `case` with the `break` statement. -
    • -
    • 8 The special, reserved event signal @ref QP::QHsm::Q_EXIT_SIG "Q_EXIT_SIG" is generated by the QEP event processor to let the state-handler process an **exit action** from the state. -
    • -
    • 9 Again, after your *exit action* code, you inform the QEP event processor that the state exit has been handled by setting `status_` to @ref QP::QHsm::Q_RET_HANDLED "Q_RET_HANDLED". -
    • -
    • 10 The special, reserved event signal @ref QP::QHsm::Q_INIT_SIG "Q_INIT_SIG" is generated by the QEP event processor to let the state-handler process an **initial transition** nested in the state. -
    • -
    • 11 After your *initial action* code, you inform the QEP event processor to complete the initial transition and to go to the specified target state indicated as the parameter of the @ref QP::QHsm::tran() "tran()" function. You set `status_` to the value returned from `tran()`. -
    • -
    • 12 A user-defined event, like `DIGIT_1_9_SIG` is handled in its own `case` statement. -
    • -
    • 13 The state-handler code has access to the **current event `e`**. The macro Q_EVT_CAST() encapsulates **downcasting** the event pointer `e` to the specific event type (`CalcEvt` in this case). -
    • -
    • 14 The `DIGIT_1_9_SIG` event triggers a state transition to state "int1", which you code with the @ref QP::QHsm::tran() "tran(&int1)" function. -
    • -
    • 15-16 The state-handler function has direct access to the data members of the `Calc` class.@n -NOTE: The previous implementation would require the use of "me->" pointer to access the data members. -
    • - -
    • 17 The `default` case handles the situation when this state does not prescribe how to handle the given event. This is where you define the **superstate** of the given state. -
    • -
    • 18 The **superstate** of the given state is specified by calling the @ref QP::QHsm::super() "super()" function.@n -NOTE: A state that does not explicitly nest in any state, such as the "on" state in the Calculator, calls **super(&top)** -
    • - -
    • 19 The state-handler ends by returning the status to the QEP event processor. -
    • -
    - -@note -The `switch` statement code and the single `return` from the state-handler function is compliant with the MISRA standards. - - - -@section sm_call State-Handler Call Overhead -For embedded system applications, it is always interesting to know the overhead of the implementation used. It turns out that the chosen "state-caller"/"state-handler" implementation is very efficient. The following dis-assembly listing shows the code generated for invocation of a state-handler from the QEP code. The compiler used is IAR C/C++ EWARM 8.32 with Cortex-M target CPU and Medium level of optimization. - -@code{asm} - r = (*s)(this, e); // invoke state handler s -[1] MOV R1, R7 // place `e` pointer in R1 -[2] MOV R0, R6 // place `this` pointer in R0 -[3] BLX R4 // branch to the state-caller - - state-caller: -[4] B.W MyHsm::state_h() ; branch to state-handler member -@endcode - -The machine code instructions [1-3] are the minimum code to call a function with two parameters via a function pointer (in R4). -The single branch instruction [4] represents the only overhead of using the "state-caller" indirection layer. This instruction takes about 4 CPU clock cycles, which is minuscule and typically much better than using a pointer to a C++ *member* function. - -@next{api} -*/ - -} // namespace QP - diff --git a/doxygen/snippets/qs_objArrDic.cpp b/doxygen/snippets/qs_objArrDic.cpp new file mode 100644 index 000000000..97d611dce --- /dev/null +++ b/doxygen/snippets/qs_objArrDic.cpp @@ -0,0 +1,6 @@ +Philo Philo::inst; +. . . +for (std::uint8_t n = 0U; n < N_PHILO; ++n) { + QS_OBJ_ARR_DICTIONARY(&Philo::inst[n], n); + QS_OBJ_ARR_DICTIONARY(&Philo::inst[n].m_timeEvt, n); +} diff --git a/doxygen/struct.dox b/doxygen/struct.dox deleted file mode 100644 index 1260234b5..000000000 --- a/doxygen/struct.dox +++ /dev/null @@ -1,259 +0,0 @@ -namespace QP { - -/*! @page struct Structure and Features - -@tableofcontents - -@section files Directories and Files - -The following annotated directory tree lists the top-level directories provided in the standard QP/C++ distribution: - -
      -
    • qpcpp/ -
    • -
        -
      • 3rd_party/ — Third-Party code used in the QP/C++ @ref ports "ports" and @ref exa "examples" -
      • -
      • examples/ — @ref exa "QP/C++ Examples" -
      • -
      • ports/ — @ref ports "QP/C++ Ports" -
      • -
      • include/ — Platform-independent QP/C++ API -
      • -
      • src/ — Platform-independent QP/C++ source code -
      • -
      -
    - -@note -The standard QP/C++ distribution contains many @ref exa "Example Projects", which are specifically designed to help you learn to use QP/C++ and to serve you as starting points for your own projects. - - - -@section comp Components of QP/C++ -

    As shown in the diagram below, the QP/C++ framework has a layered structure. The Target hardware sits at the bottom. The Board Support Package (BSP) above it provides access to the board-specific features, such as the peripherals. The real-time kernel (@ref comp_qv "QV", @ref comp_qk "QK", @ref comp_qxk "QXK", or a conventional @ref ports_rtos "3rd-party RTOS") provides the foundation for multitasking, such as task scheduling, context-switching, and inter-task communication. Based on these services, the active object framework (@ref comp_qf "QF") supplies the event-driven infrastructure for executing active objects and ensuring thread-safe event-driven exchanges among them. Finally, the event-processor (@ref comp_qep "QEP") implements the [hierarchical state machine](https://www.state-machine.com/fsm/#HSM) semantics (based on UML statecharts). The top layer is the application-level code consisting of loosely-coupled [active objects](https://www.state-machine.com/active-object/). -

    - -@image html qp_components.jpg "Components of the QP Framework" -@n - - -@subsection comp_qep QEP Hierarchical Event Processor -QEP is a universal "event processor" that provides implementation of hierarchical state machines (UML statecharts) in highly readable and portable ISO-C++. The hallmark of the @ref sm "QEP state machine implementation strategy" is **traceability**, which means that every state machine element is mapped to code precisely, unambiguously, and exactly once. QEP fully supports hierarchical state nesting, which is the fundamental mechanism for reusing behavior across many states instead of repeating the same actions and transitions over and over again. (See @ref qep for detailed documentation). - - -@subsection comp_qf QF Active-Object Framework -QF is a lightweight, event-driven, active object framework specifically designed for real-time embedded (RTE) systems. The main job of the framework is to guarantee **thread-safe**, run-to-completion event processing within each active object. This includes direct event posting as well as publish-subscribe event delivery, event queuing, and time events (time-delayed requests for posing events). (See @ref qf for detailed documentation). - - -@subsection comp_qv QV Cooperative Kernel -QV is a simple cooperative kernel (previously called "Vanilla" kernel). This kernel always processes one event at a time to completion, and performs priority-based scheduling of active objects after processing of each event. The QV kernel is "implicitly-cooperative", because the active object do not need to yield the CPU explicitly. Instead, they simply return to the QV scheduler after completion of event processing. Due to naturally short duration of event processing in state machines, the simple QV kernel is often adequate for many real-time systems. (See @ref qv for detailed documentation). This is the fastest, smallest, and easiest to understand way of executing active objects. - - -@subsection comp_qk QK Preemptive Non-Blocking Kernel -QK is an ultra-fast **preemptive**, priority-based, single-stack, real-time kernel designed specifically for executing active objects. The QK kernel always executes the highest-priority active object that has event(s) queued up, but it processes events as one-shot function calls (instead of endless loops, as traditional RTOS kernels). Still, the QK kernel allows these one-shot event-processing functions to preempt each other, if the priority of the new event is higher than the currently-processed event (very much like prioritized interrupt controllers allow interrupts to preempt each other). This means that QK can use _single stack_ for keeping the context all active objects (in the same way as prioritized interrupt controllers use a single stack to nest all interrupts). QK meets all the requirement of the Rate Monotonic Scheduling (a.k.a. Rate Monotonic Analysis — RMA) and can be used in hard real-time systems. (See @ref qk for detailed documentation). - - -@subsection comp_qxk QXK Preemptive Blocking Kernel -QXK is a small, preemptive, priority-based, **dual-mode** blocking kernel that executes active objects like the @ref comp_qk "QK kernel" (@ref qxk "basic threads"), but can also execute traditional blocking threads (@ref qxk "extended threads"). In this respect, QXK behaves exactly as a conventional RTOS (Real-Time Operating System). QXK has been designed specifically for mixing event-driven active objects with traditional blocking code, such as commercial middleware (TCP/IP stacks, UDP stacks, embedded file systems, etc.) or legacy software. QXK meets all the requirement of the Rate Monotonic Scheduling (a.k.a. Rate Monotonic Analysis — RMA) and can be used in hard real-time systems. (See @ref qxk for detailed documentation). - -@note -QXK has most features you might expect of a traditional blocking RTOS kernel and is recommended as the preferred RTOS kernel for QP/C++ applications that need to mix active objects with traditional blocking code. Due to the tight and optimal integration between QXK and the rest of QP/C++, QXK offers better performance and smaller memory footprint than any QP port to a @ref ports_rtos "3rd-party RTOS". - - - -@subsection comp_qs QS Software Tracing System -QS is software tracing system that enables developers to monitor live event-driven QP applications with minimal target system resources and without stopping or significantly slowing down the code. QS is an ideal tool for testing, troubleshooting, and optimizing QP applications. QS can even be used to support acceptance testing in product manufacturing. (See @ref qs for detailed documentation). - - - -@section qpcpp_oo Object-Orientation -As most C++ frameworks, QP/C++ uses classes, inheritance, and polymorphism as the main mechanisms for customizing the framework into applications. The framework is also layered and consists of components with well defined responsibilities. - - - -@section classes Classes in QP/C++ -The figure below shows the main classes comprising the QP/C++ framework and their relation to the application-level code, such as the @ref game example application (shown at the bottom 1/3 of the diagram). - -@image html qp_classes.gif "Main Classes in the QP Framework" - -
    -
    0
    The QP::QEvt class represents events without parameters and serves as the base class for derivation of time events and any events with parameters. For example, application-level events `ObjectPosEvt` and `ObjectImageEvt` inherit QP::QEvt and add to it some parameters (see [8]). -
    - -@anchor sm_qhsm_strategy -
    1
    The abstract QP::QHsm class represents a Hierarchical State Machine (HSM) with full support for hierarchical nesting of states, entry/exit actions, initial transitions, and transitions to history in any composite state. This class is designed for ease of **manual coding** of HSMs in C++, but it is also supported by the QM modeling tool. -QP::QHsm is also the base class for the QP::QMsm state machine, which provides a superior efficiency, but requires the use of the QM modeling tool to generate code.@n -NOTE: Please refer to Section @ref sm for information on how to code hierarchical state machines with QP/C++. -
    - -
    2
    The abstract QP::QActive class represents an active object that uses the QP::QHsm style implementation strategy for state machines. This strategy is tailored to manual coding, but it is also supported by the QM modeling tool. The resulting code is slower than in the QP::QMsm-style implementation strategy. The @ref game application provides an example of application-level classes deriving from QP::QActive and QP::QHsm (see [6] and [7]). -
    - -@anchor sm_qmsm_strategy -
    3
    The abstract QP::QMsm class (QM State Machine) derives from QP::QHsm and implements the fastest and the most efficient strategy for coding hierarchical state machines, but this strategy designed for **automatic code generation** by the QM model-based design tool. The resulting code is still highly human-readable, but is not designed to be maintained by humans. The QP::QMsm class is abstract, meaning that it cannot be instantiated directly, but rather serves only as the base class for inheritance.@n -NOTE: Please refer to Section @ref sm for information on how to code hierarchical state machines with QP/C++. -
    - -
    4
    The abstract QP::QMActive class represents an active object that uses the QP::QMsm state machine implementation strategy. This strategy requires the use of the QM modeling tool to generate state machine code automatically, but the code is faster than in the QP::QHsm style implementation strategy and needs less run-time support (smaller event-processor). -
    - -
    5
    The QP::QTimeEvt class represents time events in QP. **Time events** are special QP events equipped with the notion of time passage. The basic usage model of the time events is as follows. An active object allocates one or more QP::QTimeEvt objects (provides the storage for them). When the active object needs to arrange for a timeout, it arms one of its time events to fire either just once (one-shot) or periodically. Each time event times out independently from the others, so a QP application can make multiple parallel timeout requests (from the same or different active objects). When QP detects that the appropriate moment has arrived, it inserts the time event directly into the recipient's event queue. The recipient then processes the time event just like any other event. -
    - -
    6
    Active Objects in the application derive either from the QP::QActive or QP::QMActive base class. -
    - -
    7
    Applications can also use classes derived directly from the QP::QHsm or QP::QMsm base classes to represent "raw" state machines that are not active objects, because they don't have event queue and execution thread. Such "raw" state machines are typically used as "Orthogonal Components". -
    - -
    8
    Application-level events with parameters derive from the QP::QEvt class. -
    -
    - - - -@section hsm Hierarchical State Machines - -The behavior of each active object in QP/C++ is specified by means of a **hierarchical state machine** (UML statechart), which is the most effective and elegant technique of describing event-driven behavior. The most important innovation of UML state machines over classical finite state machines (FSMs) is the hierarchical state nesting. The value of state nesting lies in avoiding repetitions, which are inevitable in the traditional "flat" FSM formalism and are the main reason for the "state-transition explosion" in FSMs. The semantics of state nesting allow substates to define only the differences of behavior from the superstates, thus promoting sharing and reusing behavior. - -@htmlonly -
    - -
    -Application Note: A Crash Course in UML State Machines -
    -
    -@endhtmlonly - -The Quantum Leaps Application Note A Crash Course in UML State Machines introduces the main state machine concepts backed up by examples. -
    - -@note -The hallmark of the QP/C++ implementation of UML state machines is **traceability**, which is direct, precise, and unambiguous mapping of every state machine element to human readable, portable, MISRA compliant C++ code. Preserving the traceability from requirements through design to code is essential for mission-critical systems, such as medical devices or avionic systems. - - -@section DbC Design by Contract - -Design by Contract (DbC) is a philosophy that views a software system as a set of components whose collaboration is based on precisely defined specifications of mutual obligations — the contracts. The central idea of this method is to inherently embed the contracts in the code and validate them automatically at runtime. -In C and C++, the most important aspects of DbC (the contracts) can be implemented with assertions. Assertions are increasingly popular among the developers of mission-critical software. For example, NASA requires certain density of assertions in such software. - -In the context of the QP/C++ framework, DbC provides an excellent methodology for implementing a very robust error-handling policy. Due to inversion of control so typical in all event-driven systems, the QP/C++ framework controls many more aspects of the application than a traditional RTOS. A framework is in a much better position to make sure that the application is performing correctly, rather than the application to check error codes or catch exceptions originating from the framework. - - - - -@section coding Coding Standard -The QP/C++ framework has been developed in strict adherence to the documented Quantum Leaps Coding Standard. - -@htmlonly -
    - -
    -Application Note: Quantum Leaps C/C++ Coding Standard -
    -
    -@endhtmlonly - - - -@section misra MISRA Compliance - -

    The QP/C++ framework complies with most of the Motor Industry Software Reliability Association (MISRA) MISRA-C++:2008 rules. -

    - -@htmlonly -
    - -
    -Application Note: QP/C++ MISRA-C++:2008 Compliance Matrix -
    -
    -@endhtmlonly - -All deviations are carefully limited into very specific contexts and are documented with the Application Note: QP/C++ MISRA-C++:2008 Compliance Matrix. - -@note -MISRA and MISRA C++ are registered trademarks of MIRA Ltd, held on behalf of the MISRA Consortium. - -The MISRA guidelines place great emphasis on the use of static code analysts tools to check compliance with the MISRA-C++ language subset. To this end, QP/C++ comes with an extensive support for automatic rule checking with @ref lint "PC-Lint". The QP frameworks go even beyond MISRA, by complying with the strict type checking of PC-Lint. - - - -@section pc-lint PC-Lint Support - -The QP/C++ framework comes with extensive support for automatic rule checking by means of PC-Lint, which is designed not just for proving compliance of the QP/C++ framework code, but more importantly, to aid in checking compliance of the application-level code. Any organization engaged in designing safety-related embedded software could benefit from the unprecedented quality infrastructure built around the QP/C++ framework. - -@sa @ref lint "Lint Port" - -@next{sm} -*/ - -/*##########################################################################*/ -/*! @dir ../include - -Platform-independent QP/C++ API - -@note -The QP/C include directory needs to be added to the compiler's include path in the applications using QP/C. -*/ - -/*##########################################################################*/ -/*! @dir ../src - -Platform-independent QP/C++ source code - -Files from this directory need to be added to the project, to build the QP/C++ framework from source code. - -@note -The QP/C src directory needs to be added to the compiler's include path in the applications that build QP/C framework from sources (as opposed to using QP as a pre-built library). - -*/ - -/*##########################################################################*/ -/*! @dir ../src/qf - -Platform-independent implementation of the @ref qep and @ref qf components. - -@note -Typically, files in this directory need to be added to the application build, but some QP ports might not need all the files in this directory. For example, a QP port to a 3rd-party RTOS kernel might be using a message queue of the RTOS instead of the native QP event queue, in which case the file qf_actq.c would not be needed and should be excluded from the build. - -*/ - -/*##########################################################################*/ -/*! @dir ../src/qv - -Platform-independent implementation of the @ref qv built-in kernel. - -@attention -Files in this directory need to be included in the QP application build only if the application uses the @ref qv kernel. -*/ - - -/*##########################################################################*/ -/*! @dir ../src/qk - -Platform-independent implementation of the @ref qk built-in kernel. - -@attention -Files in this directory need to be included in the QP application build only if the application uses the @ref qk kernel. -*/ - - -/*##########################################################################*/ -/*! @dir ../src/qxk - -Platform-independent implementation of the @ref qxk built-in kernel. - -@attention -Files in this directory need to be included in the QP application build only if the application uses the @ref qxk kernel. -*/ - - -/*##########################################################################*/ -/*! @dir ../src/qs - -Platform-independent implementation of the @ref qs component (software tracing). -*/ - -} // namespace QP diff --git a/examples/arm-cm/blinky_efm32-slstk3401a/README.md b/examples/arm-cm/blinky_efm32-slstk3401a/README.md new file mode 100644 index 000000000..fcaa75681 --- /dev/null +++ b/examples/arm-cm/blinky_efm32-slstk3401a/README.md @@ -0,0 +1,5 @@ +![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_blinky_efm32-slstk3401a.html diff --git a/examples/arm-cm/blinky_efm32-slstk3401a/README.txt b/examples/arm-cm/blinky_efm32-slstk3401a/README.txt deleted file mode 100644 index fb8172090..000000000 --- a/examples/arm-cm/blinky_efm32-slstk3401a/README.txt +++ /dev/null @@ -1,36 +0,0 @@ -About this Example -================== -This directory contains the simple "Blinky" QP example application for -the EK-TM4C123GXL board (TivaC LauchPad) with the preemptive QK kernel. -This directory contains portable code that should compile with any C -compiler for ARM Cortex-M. - -The sub-directories contain code and project files, which are specific -to the particular ARM toolchains, such as ARM (MDK-ARM), GNU, 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. - - -Support Code for EK-TM4C123GXL Board -==================================== -The directory qpc\3rd_party\ek-tm4c123gxl contains the CMSIS-compliant -device code for the TM4C123GH6PM MCU. Please see the README.txt file in -this folder for more details. - - -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. - -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/examples/arm-cm/blinky_ek-tm4c123gxl/README.md b/examples/arm-cm/blinky_ek-tm4c123gxl/README.md new file mode 100644 index 000000000..91e8b362b --- /dev/null +++ b/examples/arm-cm/blinky_ek-tm4c123gxl/README.md @@ -0,0 +1,5 @@ +![STM32 EFM32-SLSTK3401A](../../../doxygen/images/bd_EK-TM4C123GXL.jpg) + +Documentation for this example is available in the QP/C Manual at: + +- https://www.state-machine.com/qpcpp/arm-cm_blinky_ek-tm4c123gxl.html diff --git a/examples/arm-cm/blinky_ek-tm4c123gxl/README.txt b/examples/arm-cm/blinky_ek-tm4c123gxl/README.txt deleted file mode 100644 index fb8172090..000000000 --- a/examples/arm-cm/blinky_ek-tm4c123gxl/README.txt +++ /dev/null @@ -1,36 +0,0 @@ -About this Example -================== -This directory contains the simple "Blinky" QP example application for -the EK-TM4C123GXL board (TivaC LauchPad) with the preemptive QK kernel. -This directory contains portable code that should compile with any C -compiler for ARM Cortex-M. - -The sub-directories contain code and project files, which are specific -to the particular ARM toolchains, such as ARM (MDK-ARM), GNU, 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. - - -Support Code for EK-TM4C123GXL Board -==================================== -The directory qpc\3rd_party\ek-tm4c123gxl contains the CMSIS-compliant -device code for the TM4C123GH6PM MCU. Please see the README.txt file in -this folder for more details. - - -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. - -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/examples/arm-cm/dpp_efm32-slstk3401a/README.md b/examples/arm-cm/dpp_efm32-slstk3401a/README.md new file mode 100644 index 000000000..2810293ea --- /dev/null +++ b/examples/arm-cm/dpp_efm32-slstk3401a/README.md @@ -0,0 +1,5 @@ +![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_dpp_efm32-slstk3401a.html diff --git a/examples/arm-cm/dpp_efm32-slstk3401a/README.txt b/examples/arm-cm/dpp_efm32-slstk3401a/README.txt deleted file mode 100644 index 206475edd..000000000 --- a/examples/arm-cm/dpp_efm32-slstk3401a/README.txt +++ /dev/null @@ -1,50 +0,0 @@ -About this Example -================== -This directory contains a QP example application for the -EFM32-SLSTK3401A board (Pearl Gecko Starter Kit). This directory -contains portable code that should compile with any C compiler for -ARM Cortex-M. - -The sub-directories contain code and project files, which are specific -to the particular ARM toolchains, such as ARM (MDK-ARM), GNU, 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. - - -Support Code for EFM32-SLSTK3401A Board -======================================= -The directory 3rd_party\efm32pg1b contains the CMSIS-compliant -device code for the EFM32PG1B200F256GM48 MCU. Please see the README.txt -file in this folder for more details. - - -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. - -The output is generated at 115200 baud rate. - -Here is an example invocation of the QSPY host application to receive -the QS data from EFM32-SLSTK3401A: - -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. - - -Win32 Emulations -================ -The sub-directorie win32 and win32-qv provide the emulations of the example -on Windows GUI (with regular Win32 threads and with cooperative QV scheduler, -respectively. These sub-directories contain the Makefiles for the MinGW -toolset and Visual Studio solution files (game-gui.sln) for Visual C++. - -The Win32 emulations use exactly the same code as the embedded board and -differ only in the Board Support Package (bsp.c). This example demonstrates -the "dual targeting" development approach, where most of the embedded code -is developed on the desktop machine (Windows), but is intended for a deeply -embedded target (EFM32-SLSTK3401A here). diff --git a/examples/arm-cm/dpp_efm32-slstk3401a/qk/armclang/dpp-qk.uvoptx b/examples/arm-cm/dpp_efm32-slstk3401a/qk/armclang/dpp-qk.uvoptx index d8af19498..0b941927f 100644 --- a/examples/arm-cm/dpp_efm32-slstk3401a/qk/armclang/dpp-qk.uvoptx +++ b/examples/arm-cm/dpp_efm32-slstk3401a/qk/armclang/dpp-qk.uvoptx @@ -10,7 +10,7 @@ *.s*; *.src; *.a* *.obj; *.o *.lib - *.txt; *.h; *.inc + *.txt; *.h; *.inc; *.md *.plm *.cpp 0 @@ -103,7 +103,7 @@ 1 0 0 - 3 + 4 diff --git a/examples/arm-cm/dpp_efm32-slstk3401a/qk/armclang/dpp-qk.uvprojx b/examples/arm-cm/dpp_efm32-slstk3401a/qk/armclang/dpp-qk.uvprojx index b0583113c..8068342ec 100644 --- a/examples/arm-cm/dpp_efm32-slstk3401a/qk/armclang/dpp-qk.uvprojx +++ b/examples/arm-cm/dpp_efm32-slstk3401a/qk/armclang/dpp-qk.uvprojx @@ -10,13 +10,13 @@ dpp-dbg 0x4 ARM-ADS - 6130001::V6.13.1::.\ARMCLANG + 6160000::V6.16::ARMCLANG 1 EFM32PG1B200F256GM48 Silicon Labs - SiliconLabs.EFM32PG1B_DFP.5.5.0 + SiliconLabs.GeckoPlatform_EFM32PG1B_DFP.4.0.0 https://www.silabs.com/documents/public/cmsis-packs/ IRAM(0x20000000,0x00008000) IROM(0x00000000,0x00020000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE @@ -185,6 +185,7 @@ 0 2 0 + 0 0 0 8 @@ -351,7 +352,7 @@ 0 1 0 - 0 + 4 Stack_Size=1024 Heap_Size=16 @@ -531,6 +532,57 @@ qk_port.cpp 8 ..\..\..\..\..\ports\arm-cm\qk\armclang\qk_port.cpp + + + 2 + 0 + 0 + 0 + 0 + 2 + 2 + 2 + 2 + 2 + 11 + + + 1 + + + + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 0 + 0 + 2 + 2 + 2 + 2 + 2 + + + QK_USE_IRQ_NUM=25 QK_USE_IRQ_HANDLER=CRYPTO_IRQHandler + + + + + + @@ -595,7 +647,7 @@ 2 2 2 - 2 + 0 @@ -640,7 +692,7 @@ EFM32PG1B200F256GM48 Silicon Labs - SiliconLabs.EFM32PG1B_DFP.5.5.0 + SiliconLabs.GeckoPlatform_EFM32PG1B_DFP.4.0.0 https://www.silabs.com/documents/public/cmsis-packs/ IRAM(0x20000000,0x00008000) IROM(0x00000000,0x00020000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE @@ -809,6 +861,7 @@ 0 2 0 + 0 0 0 8 @@ -975,7 +1028,7 @@ 0 1 0 - 0 + 4 Stack_Size=1024 Heap_Size=16 @@ -1219,7 +1272,7 @@ 2 2 2 - 2 + 0 @@ -1264,7 +1317,7 @@ EFM32PG1B200F256GM48 Silicon Labs - SiliconLabs.EFM32PG1B_DFP.5.5.0 + SiliconLabs.GeckoPlatform_EFM32PG1B_DFP.4.0.0 https://www.silabs.com/documents/public/cmsis-packs/ IRAM(0x20000000,0x00008000) IROM(0x00000000,0x00020000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE @@ -1433,6 +1486,7 @@ 0 2 0 + 0 0 0 8 @@ -1599,7 +1653,7 @@ 0 1 0 - 0 + 4 Stack_Size=1024 Heap_Size=16 diff --git a/examples/arm-cm/dpp_efm32-slstk3401a/qk/gnu/Makefile b/examples/arm-cm/dpp_efm32-slstk3401a/qk/gnu/Makefile index cafa8c7c3..37c089a21 100644 --- a/examples/arm-cm/dpp_efm32-slstk3401a/qk/gnu/Makefile +++ b/examples/arm-cm/dpp_efm32-slstk3401a/qk/gnu/Makefile @@ -138,7 +138,9 @@ LIB_DIRS := LIBS := # defines -DEFINES := -DEFM32PG1B200F256GM48=1 +DEFINES := -DEFM32PG1B200F256GM48=1 \ + -DQK_USE_IRQ_NUM=25 \ + -DQK_USE_IRQ_HANDLER=CRYPTO_IRQHandler # ARM CPU, ARCH, FPU, and Float-ABI types... # ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4] diff --git a/examples/arm-cm/dpp_efm32-slstk3401a/qk/iar/dpp-qk.ewp b/examples/arm-cm/dpp_efm32-slstk3401a/qk/iar/dpp-qk.ewp index 675cc6106..d5dfef4cd 100644 --- a/examples/arm-cm/dpp_efm32-slstk3401a/qk/iar/dpp-qk.ewp +++ b/examples/arm-cm/dpp_efm32-slstk3401a/qk/iar/dpp-qk.ewp @@ -11,9 +11,13 @@ General 3 - 31 + 33 1 1 + - - - - - + + ICCARM 2 - 35 + 37 1 1 - - - + AARM 2 - 10 + 11 1 1 + @@ -674,13 +658,9 @@ 0 + inputOutputBased - - BICOMP - 0 - - BUILDACTION 1 @@ -693,17 +673,13 @@ ILINK 0 - 23 + 25 1 1 - + + + + + @@ -1052,11 +1048,6 @@ - - BILINK - 0 - - Coder 0 @@ -1073,9 +1064,13 @@ General 3 - 31 + 33 1 0 + - - - - - + + ICCARM 2 - 35 + 37 1 0 - - - + AARM 2 - 10 + 11 1 0 + @@ -1737,13 +1712,9 @@ 0 + inputOutputBased - - BICOMP - 0 - - BUILDACTION 1 @@ -1756,17 +1727,13 @@ ILINK 0 - 23 + 25 1 0 - + + + + + @@ -2115,11 +2102,6 @@ - - BILINK - 0 - - Coder 0 @@ -2136,9 +2118,13 @@ General 3 - 31 + 33 1 1 + - - - - - + + ICCARM 2 - 35 + 37 1 1 - - - + AARM 2 - 10 + 11 1 1 + @@ -2800,13 +2766,9 @@ 0 + inputOutputBased - - BICOMP - 0 - - BUILDACTION 1 @@ -2819,17 +2781,13 @@ ILINK 0 - 23 + 25 1 1 - + + + + + @@ -3178,20 +3156,12 @@ - - BILINK - 0 - - Coder 0 - - Debug - Application @@ -3289,6 +3259,256 @@ QP_port $PROJ_DIR$\..\..\..\..\..\ports\arm-cm\qk\iar\qk_port.cpp + + Debug + + ICCARM + + 37 + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/arm-cm/dpp_efm32-slstk3401a/qxk/armclang/dpp-qxk.uvoptx b/examples/arm-cm/dpp_efm32-slstk3401a/qxk/armclang/dpp-qxk.uvoptx index 987cac8a9..f0715f395 100644 --- a/examples/arm-cm/dpp_efm32-slstk3401a/qxk/armclang/dpp-qxk.uvoptx +++ b/examples/arm-cm/dpp_efm32-slstk3401a/qxk/armclang/dpp-qxk.uvoptx @@ -10,7 +10,7 @@ *.s*; *.src; *.a* *.obj; *.o *.lib - *.txt; *.h; *.inc + *.txt; *.h; *.inc; *.md *.plm *.cpp 0 @@ -103,7 +103,7 @@ 1 0 0 - 3 + 4 @@ -892,7 +892,7 @@ QP_port - 0 + 1 0 0 0 diff --git a/examples/arm-cm/dpp_efm32-slstk3401a/qxk/armclang/dpp-qxk.uvprojx b/examples/arm-cm/dpp_efm32-slstk3401a/qxk/armclang/dpp-qxk.uvprojx index 325c68c8d..e1df2ce61 100644 --- a/examples/arm-cm/dpp_efm32-slstk3401a/qxk/armclang/dpp-qxk.uvprojx +++ b/examples/arm-cm/dpp_efm32-slstk3401a/qxk/armclang/dpp-qxk.uvprojx @@ -10,13 +10,13 @@ dpp-dbg 0x4 ARM-ADS - 6130001::V6.13.1::.\ARMCLANG + 6160000::V6.16::ARMCLANG 1 EFM32PG1B200F256GM48 Silicon Labs - SiliconLabs.EFM32PG1B_DFP.5.5.0 + SiliconLabs.GeckoPlatform_EFM32PG1B_DFP.4.0.0 https://www.silabs.com/documents/public/cmsis-packs/ IRAM(0x20000000,0x00008000) IROM(0x00000000,0x00020000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE @@ -185,6 +185,7 @@ 0 2 0 + 0 0 0 8 @@ -351,7 +352,7 @@ 0 1 0 - 0 + 4 Stack_Size=1024 Heap_Size=16 @@ -551,6 +552,57 @@ qxk_port.cpp 8 ..\..\..\..\..\ports\arm-cm\qxk\armclang\qxk_port.cpp + + + 2 + 0 + 0 + 0 + 0 + 2 + 2 + 2 + 2 + 2 + 11 + + + 1 + + + + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 0 + 0 + 2 + 2 + 2 + 2 + 2 + + + QXK_USE_IRQ_NUM=25 QXK_USE_IRQ_HANDLER=CRYPTO_IRQHandler + + + + + + @@ -615,7 +667,7 @@ 2 2 2 - 2 + 0 @@ -660,7 +712,7 @@ EFM32PG1B200F256GM48 Silicon Labs - SiliconLabs.EFM32PG1B_DFP.5.5.0 + SiliconLabs.GeckoPlatform_EFM32PG1B_DFP.4.0.0 https://www.silabs.com/documents/public/cmsis-packs/ IRAM(0x20000000,0x00008000) IROM(0x00000000,0x00020000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE @@ -829,6 +881,7 @@ 0 2 0 + 0 0 0 8 @@ -995,7 +1048,7 @@ 0 1 0 - 0 + 4 Stack_Size=1024 Heap_Size=16 @@ -1259,7 +1312,7 @@ 2 2 2 - 2 + 0 @@ -1304,7 +1357,7 @@ EFM32PG1B200F256GM48 Silicon Labs - SiliconLabs.EFM32PG1B_DFP.5.5.0 + SiliconLabs.GeckoPlatform_EFM32PG1B_DFP.4.0.0 https://www.silabs.com/documents/public/cmsis-packs/ IRAM(0x20000000,0x00008000) IROM(0x00000000,0x00020000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE @@ -1473,6 +1526,7 @@ 0 2 0 + 0 0 0 8 @@ -1639,7 +1693,7 @@ 0 1 0 - 0 + 4 Stack_Size=1024 Heap_Size=16 diff --git a/examples/arm-cm/dpp_efm32-slstk3401a/qxk/gnu/Makefile b/examples/arm-cm/dpp_efm32-slstk3401a/qxk/gnu/Makefile index e30f0a58a..eb9522d6a 100644 --- a/examples/arm-cm/dpp_efm32-slstk3401a/qxk/gnu/Makefile +++ b/examples/arm-cm/dpp_efm32-slstk3401a/qxk/gnu/Makefile @@ -1,13 +1,13 @@ ############################################################################## # Product: Makefile for QP/C++ on EMF32-SLSTK3401A, QXK kernel, GNU-ARM # Last Updated for Version: 7.0.0 -# Date of the Last Update: 2021-07-01 +# Date of the Last Update: 2022-05-02 # # Q u a n t u m L e a P s # ------------------------ # Modern Embedded Software # -# Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. +# Copyright (C) 2005-2022 Quantum Leaps, LLC. All rights reserved. # # This program is open source software: you can redistribute it and/or # modify it under the terms of the GNU General Public License as published @@ -143,7 +143,9 @@ LIB_DIRS := LIBS := # defines -DEFINES := -DEFM32PG1B200F256GM48=1 +DEFINES := -DEFM32PG1B200F256GM48=1 \ + -DQXK_USE_IRQ_NUM=25 \ + -DQXK_USE_IRQ_HANDLER=CRYPTO_IRQHandler # ARM CPU, ARCH, FPU, and Float-ABI types... # ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4] diff --git a/examples/arm-cm/dpp_efm32-slstk3401a/qxk/iar/dpp-qxk.ewp b/examples/arm-cm/dpp_efm32-slstk3401a/qxk/iar/dpp-qxk.ewp index 34f7ab6a4..14a455b0b 100644 --- a/examples/arm-cm/dpp_efm32-slstk3401a/qxk/iar/dpp-qxk.ewp +++ b/examples/arm-cm/dpp_efm32-slstk3401a/qxk/iar/dpp-qxk.ewp @@ -11,9 +11,13 @@ General 3 - 31 + 33 1 1 + - - - - - + + ICCARM 2 - 36 + 37 1 1 - - - @@ -678,13 +658,9 @@ 0 + inputOutputBased - - BICOMP - 0 - - BUILDACTION 1 @@ -697,17 +673,13 @@ ILINK 0 - 23 + 25 1 1 - + + + + + @@ -1056,11 +1048,6 @@ - - BILINK - 0 - - Coder 0 @@ -1077,9 +1064,13 @@ General 3 - 31 + 33 1 0 + - - - - - + + ICCARM 2 - 36 + 37 1 0 - - - @@ -1745,13 +1712,9 @@ 0 + inputOutputBased - - BICOMP - 0 - - BUILDACTION 1 @@ -1764,17 +1727,13 @@ ILINK 0 - 23 + 25 1 0 - + + + + + @@ -2123,11 +2102,6 @@ - - BILINK - 0 - - Coder 0 @@ -2144,9 +2118,13 @@ General 3 - 31 + 33 1 1 + - - - - - + + ICCARM 2 - 36 + 37 1 1 - - - @@ -2812,13 +2766,9 @@ 0 + inputOutputBased - - BICOMP - 0 - - BUILDACTION 1 @@ -2831,17 +2781,13 @@ ILINK 0 - 23 + 25 1 1 - + + + + + @@ -3190,20 +3156,12 @@ - - BILINK - 0 - - Coder 0 - - Debug - Application @@ -3307,6 +3265,256 @@ QP_port $PROJ_DIR$\..\..\..\..\..\ports\arm-cm\qxk\iar\qxk_port.cpp + + Debug + + ICCARM + + 37 + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/arm-cm/dpp_ek-tm4c123gxl/README.md b/examples/arm-cm/dpp_ek-tm4c123gxl/README.md new file mode 100644 index 000000000..30842bae9 --- /dev/null +++ b/examples/arm-cm/dpp_ek-tm4c123gxl/README.md @@ -0,0 +1,5 @@ +![STM32 EFM32-SLSTK3401A](../../../doxygen/images/bd_EK-TM4C123GXL.jpg) + +Documentation for this example is available in the QP/C Manual at: + +- https://www.state-machine.com/qpcpp/arm-cm_dpp_ek-tm4c123gxl.html diff --git a/examples/arm-cm/dpp_ek-tm4c123gxl/README.txt b/examples/arm-cm/dpp_ek-tm4c123gxl/README.txt deleted file mode 100644 index 80fd32267..000000000 --- a/examples/arm-cm/dpp_ek-tm4c123gxl/README.txt +++ /dev/null @@ -1,37 +0,0 @@ -About this Example -================== -This directory contains the "DPP" (Dining Philosopher Problem) QP example -application for the EK-TM4C123GXL board (TivaC LauchPad). This directory -contains portable code that should compile with any C compiler for ARM -Cortex-M. - -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. - - -Support Code for EK-TM4C123GXL Board -==================================== -The directory qpc\3rd_party\ek-tm4c123gxl contains the CMSIS- -compliant device code for the TM4C123GH6PM MCU. Please see the README -file in this folder for more details. - - -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. - -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/examples/arm-cm/dpp_mbed-lpc1768/README.md b/examples/arm-cm/dpp_mbed-lpc1768/README.md new file mode 100644 index 000000000..f2bd185a2 --- /dev/null +++ b/examples/arm-cm/dpp_mbed-lpc1768/README.md @@ -0,0 +1,5 @@ +![STM32 EFM32-SLSTK3401A](../../../doxygen/images/bd_mbed-LPC1768.jpg) + +Documentation for this example is available in the QP/C Manual at: + +- https://www.state-machine.com/qpcpp/arm-cm_dpp_mbed-lpc1768.html diff --git a/examples/arm-cm/dpp_mbed-lpc1768/README.txt b/examples/arm-cm/dpp_mbed-lpc1768/README.txt deleted file mode 100644 index 12c2019b8..000000000 --- a/examples/arm-cm/dpp_mbed-lpc1768/README.txt +++ /dev/null @@ -1,60 +0,0 @@ -About this Example -================== -This directory contains the "Dining Philosophers Problem" (DPP) example -for the preemptive QK kernel running on the NXP mbed-LPC1768 board -(ARM Cortex-M3). This directory contains portable code that should -compile with any C compiler for ARM Cortex-M. - -The sub-directory "gnu" contains the Makefile for a generic GNU-ARM -toolset (e.g., see http://gnutoolchains.com/arm-eabi/). Thus, this -project provides a way of building mbed applications locally with -free and unrestricted tools. - -*** -NOTE: To build the code on Windows, you need to download and install -the GNU make utility. The Qtools collection from Quantum Leaps contains -GNU make and other UNIX-style utilites for Windows (native Windows, -without the need to install CygWin). -*** - -After building the code with the provided Makefile, you can simply -copy the binary image to the mbed folder for execution. - -The whole build process and loading the image to the mbed board can -be executed directly from the QM modeling (by means of external tools). -The provided QM model (dpp.qm) comes pre-configured with tools -setup to build (via make) and copy the code to the mbed board. - - -Support Code for NXP mbed-LPC1768 Board -======================================= -The directory 3rd_party\mbed-lpc1768 contains the CMSIS-compliant -device code for the NXP LPC176xx MCUs (ARM Cortex-M3). Please see the -README.txt file in this folder for more details. - - -Note About the Board Support Package for NXP mbed-LPC1768 -========================================================= -The provided Board Support Package (see bsp.c) is minimal for the -application at hand and is completely **standalone**, meaning that -it does NOT use the extensive mbed driver library. The use of the -mbed-library is possible, but not necessary (but requires C++). - - -QS Software Tracing Instrumentation -=================================== -This example provides the "Spy" build configuration, which outputs the QS -(Quantum Spy) software tracing data through UART0 of the mbed-LPC1768 board, -which is connected to the virtual COM port of the mbed USB connection. - -The output is generated at 115200 baud rate. - -Here is an example invocation of the QSPY host application to receive -the QS data from mbed-LPC1768 : - -qspy -cCOM20 - -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/examples/arm-cm/dpp_nucleo-h743zi/README.md b/examples/arm-cm/dpp_nucleo-h743zi/README.md new file mode 100644 index 000000000..d71007007 --- /dev/null +++ b/examples/arm-cm/dpp_nucleo-h743zi/README.md @@ -0,0 +1,5 @@ +![STM32 NUCLEO-H743ZI Q](../../../doxygen/images/bd_NUCLEO-H743ZI.jpg) + +Documentation for this example is available in the QP/C Manual at: + +- https://www.state-machine.com/qpcpp/arm-cm_dpp_nucleo-h743zi.html diff --git a/examples/arm-cm/dpp_nucleo-l053r8/README.md b/examples/arm-cm/dpp_nucleo-l053r8/README.md new file mode 100644 index 000000000..538e55669 --- /dev/null +++ b/examples/arm-cm/dpp_nucleo-l053r8/README.md @@ -0,0 +1,5 @@ +![STM32 EFM32-SLSTK3401A](../../../doxygen/images/bd_NUCLEO-L053R8.jpg) + +Documentation for this example is available in the QP/C Manual at: + +- https://www.state-machine.com/qpcpp/arm-cm_dpp_nucleo-l053r8.html diff --git a/examples/arm-cm/dpp_nucleo-l053r8/README.txt b/examples/arm-cm/dpp_nucleo-l053r8/README.txt deleted file mode 100644 index 057ce3cda..000000000 --- a/examples/arm-cm/dpp_nucleo-l053r8/README.txt +++ /dev/null @@ -1,74 +0,0 @@ -About this Example -================== -This directory contains the "Dining Philosophers Problem" (DPP) example -running on the STM32 NUCLEO-L053R8 board (ARM Cortex-M0+). The following -versions of the example are provided: - -dpp_nucleo-l053r8/ - | - +-qk/ - preemptive QK kernel - | +-arm/ - ARM-KEIL toolset - | +-gnu/ - GNU-ARM toolset - | +-iar/ - IAR-ARM toolset - | - +-qv/ - cooperative QV kernel - | +-arm/ - ARM-KEIL toolset - | +-gnu/ - GNU-ARM toolset - | +-iar/ - IAR-ARM toolset - -*** -NOTE: The sub-directory "gnu" contains the Makefile for a generic GNU-ARM -toolset (e.g., see http://gnutoolchains.com/arm-eabi/). Thus, this -project provides a way of building mbed applications locally with -free and unrestricted tools. -*** -*** -NOTE: To build the code on Windows, you need to download and install -the GNU make utility. The Qtools collection from Quantum Leaps contains -GNU make and other UNIX-style utilites for Windows (native Windows, -without the need to install CygWin). -*** - -Downloading the Code to STM32 NUCLEO-L053R8 Board -================================================= -After building the code with any of the supported toosets, you have -two options of loading the code to the NUCLEO board. - -First, you can use the on-board ST-Link debugger to download the code -from the toolset IDE (e.g., uVision or IAR EW). - -Alternatively, you can simply copy the binary image to the NUCLEO -folder for execution. - -*** -NOTE: -The whole build process and loading the image to the mbed board can -be executed directly from the QM modeling (by means of external tools). -The provided QM model (dpp.qm) comes pre-configured with tools -setup to build (via make) and copy the code to the mbed board. -*** - - -Support Code for STM32 NUCLEO-L053R8 Board ------------------------------------------- -The directory qpc\3rd_party\nucleo-l053r8 contains the CMSIS- -compliant device code for the STM32L0xx MCUs (ARM Cortex-M0+). Please see -the README file in this folder for more details. - - -QS Software Tracing Instrumentation -=================================== -This example provides the "Spy" build configuration, which outputs the QS -(Quantum Spy) software tracing data through UART2, which is connected to -the virtual COM port of the ST-Link V2 USB debugger. - -The output is generated at 115200 baud rate. - -Here is an example invocation of the QSPY host application to receive -the QS data from NUCLEO board: - -qspy -cCOM20 - -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/examples/arm-cm/dpp_nucleo-l053r8/qk/armclang/dpp-qk.uvoptx b/examples/arm-cm/dpp_nucleo-l053r8/qk/armclang/dpp-qk.uvoptx index cfc853564..e6cad75c7 100644 --- a/examples/arm-cm/dpp_nucleo-l053r8/qk/armclang/dpp-qk.uvoptx +++ b/examples/arm-cm/dpp_nucleo-l053r8/qk/armclang/dpp-qk.uvoptx @@ -10,7 +10,7 @@ *.s*; *.src; *.a* *.obj; *.o *.lib - *.txt; *.h; *.inc + *.txt; *.h; *.inc; *.md *.plm *.cpp 0 @@ -103,7 +103,7 @@ 1 0 0 - 5 + 6 diff --git a/examples/arm-cm/dpp_nucleo-l053r8/qk/armclang/dpp-qk.uvprojx b/examples/arm-cm/dpp_nucleo-l053r8/qk/armclang/dpp-qk.uvprojx index bb869ee43..a14f661b8 100644 --- a/examples/arm-cm/dpp_nucleo-l053r8/qk/armclang/dpp-qk.uvprojx +++ b/examples/arm-cm/dpp_nucleo-l053r8/qk/armclang/dpp-qk.uvprojx @@ -10,13 +10,13 @@ dpp-dbg 0x4 ARM-ADS - 6070000::V6.7::.\ARMCLANG + 6160000::V6.16::ARMCLANG 1 STM32L053R8Tx STMicroelectronics - Keil.STM32L0xx_DFP.2.0.0 + Keil.STM32L0xx_DFP.2.2.0 http://www.keil.com/pack/ IRAM(0x20000000,0x00002000) IROM(0x08000000,0x00010000) CPUTYPE("Cortex-M0+") CLOCK(12000000) ELITTLE @@ -185,6 +185,7 @@ 0 0 0 + 0 0 0 8 @@ -351,7 +352,7 @@ 0 1 0 - 0 + 4 Stack_Size=1024 Heap_Size=16 @@ -521,6 +522,57 @@ qk_port.cpp 8 ..\..\..\..\..\ports\arm-cm\qk\armclang\qk_port.cpp + + + 2 + 0 + 0 + 0 + 0 + 2 + 2 + 2 + 2 + 2 + 11 + + + 1 + + + + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 0 + 0 + 2 + 2 + 2 + 2 + 2 + + + QK_USE_IRQ_NUM=30 QK_USE_IRQ_HANDLER=LCD_IRQHandler + + + + + + @@ -585,7 +637,7 @@ 2 2 2 - 2 + 0 @@ -625,7 +677,7 @@ STM32L053R8Tx STMicroelectronics - Keil.STM32L0xx_DFP.2.0.0 + Keil.STM32L0xx_DFP.2.2.0 http://www.keil.com/pack/ IRAM(0x20000000,0x00002000) IROM(0x08000000,0x00010000) CPUTYPE("Cortex-M0+") CLOCK(12000000) ELITTLE @@ -794,6 +846,7 @@ 0 0 0 + 0 0 0 8 @@ -960,7 +1013,7 @@ 0 1 0 - 0 + 4 Stack_Size=1024 Heap_Size=16 @@ -1194,7 +1247,7 @@ 2 2 2 - 2 + 0 @@ -1234,7 +1287,7 @@ STM32L053R8Tx STMicroelectronics - Keil.STM32L0xx_DFP.2.0.0 + Keil.STM32L0xx_DFP.2.2.0 http://www.keil.com/pack/ IRAM(0x20000000,0x00002000) IROM(0x08000000,0x00010000) CPUTYPE("Cortex-M0+") CLOCK(12000000) ELITTLE @@ -1403,6 +1456,7 @@ 0 0 0 + 0 0 0 8 @@ -1569,7 +1623,7 @@ 0 1 0 - 0 + 4 Stack_Size=1024 Heap_Size=16 diff --git a/examples/arm-cm/dpp_nucleo-l053r8/qk/gnu/Makefile b/examples/arm-cm/dpp_nucleo-l053r8/qk/gnu/Makefile index a5ba5abd5..7f1f44130 100644 --- a/examples/arm-cm/dpp_nucleo-l053r8/qk/gnu/Makefile +++ b/examples/arm-cm/dpp_nucleo-l053r8/qk/gnu/Makefile @@ -1,7 +1,7 @@ ############################################################################## # Product: Makefile for QP/C++ on STM32 NUCLEO-L053R8, QK kernel, GNU-ARM # Last Updated for Version: 7.0.0 -# Date of the Last Update: 2021-07-01 +# Date of the Last Update: 2022-05-02 # # Q u a n t u m L e a P s # ------------------------ @@ -134,7 +134,9 @@ LIB_DIRS := LIBS := # defines -DEFINES := +DEFINES := \ + -DQK_USE_IRQ_NUM=30 \ + -DQK_USE_IRQ_HANDLER=LCD_IRQHandler # ARM CPU, ARCH, FPU, and Float-ABI types... # ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4] diff --git a/examples/arm-cm/dpp_nucleo-l053r8/qk/iar/dpp-qk.ewp b/examples/arm-cm/dpp_nucleo-l053r8/qk/iar/dpp-qk.ewp index 795505ba4..35d13232d 100644 --- a/examples/arm-cm/dpp_nucleo-l053r8/qk/iar/dpp-qk.ewp +++ b/examples/arm-cm/dpp_nucleo-l053r8/qk/iar/dpp-qk.ewp @@ -11,9 +11,13 @@ General 3 - 31 + 33 1 1 + - - - - - + + ICCARM 2 - 35 + 37 1 1 - - - + AARM 2 - 10 + 11 1 1 + @@ -673,13 +657,9 @@ 0 + inputOutputBased - - BICOMP - 0 - - BUILDACTION 1 @@ -692,17 +672,13 @@ ILINK 0 - 23 + 25 1 1 - + + + + + @@ -1051,11 +1047,6 @@ - - BILINK - 0 - - Coder 0 @@ -1072,9 +1063,13 @@ General 3 - 31 + 33 1 0 + - - - - - + + ICCARM 2 - 35 + 37 1 0 - - - + AARM 2 - 10 + 11 1 0 + @@ -1734,13 +1709,9 @@ 0 + inputOutputBased - - BICOMP - 0 - - BUILDACTION 1 @@ -1753,17 +1724,13 @@ ILINK 0 - 23 + 25 1 0 - + + + + + @@ -2112,11 +2099,6 @@ - - BILINK - 0 - - Coder 0 @@ -2133,9 +2115,13 @@ General 3 - 31 + 33 1 1 + - - - - - + + ICCARM 2 - 35 + 37 1 1 - - - + AARM 2 - 10 + 11 1 1 + @@ -2795,13 +2761,9 @@ 0 + inputOutputBased - - BICOMP - 0 - - BUILDACTION 1 @@ -2814,17 +2776,13 @@ ILINK 0 - 23 + 25 1 1 - + + + + + @@ -3173,11 +3151,6 @@ - - BILINK - 0 - - Coder 0 @@ -3284,6 +3257,254 @@ $PROJ_DIR$\..\..\..\..\..\ports\arm-cm\qk\iar\qk_port.cpp + + Debug + + ICCARM + + 37 + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $PROJ_DIR$\..\..\..\..\..\ports\arm-cm\qk\iar\qk_port.h diff --git a/examples/arm-cm/dpp_nucleo-l053r8/qxk/armclang/dpp-qxk.uvoptx b/examples/arm-cm/dpp_nucleo-l053r8/qxk/armclang/dpp-qxk.uvoptx index ed96a07d8..872bf963a 100644 --- a/examples/arm-cm/dpp_nucleo-l053r8/qxk/armclang/dpp-qxk.uvoptx +++ b/examples/arm-cm/dpp_nucleo-l053r8/qxk/armclang/dpp-qxk.uvoptx @@ -10,7 +10,7 @@ *.s*; *.src; *.a* *.obj; *.o *.lib - *.txt; *.h; *.inc + *.txt; *.h; *.inc; *.md *.plm *.cpp 0 @@ -103,7 +103,7 @@ 1 0 0 - 5 + 6 diff --git a/examples/arm-cm/dpp_nucleo-l053r8/qxk/armclang/dpp-qxk.uvprojx b/examples/arm-cm/dpp_nucleo-l053r8/qxk/armclang/dpp-qxk.uvprojx index e4229b71a..a09eac021 100644 --- a/examples/arm-cm/dpp_nucleo-l053r8/qxk/armclang/dpp-qxk.uvprojx +++ b/examples/arm-cm/dpp_nucleo-l053r8/qxk/armclang/dpp-qxk.uvprojx @@ -10,13 +10,13 @@ dpp-dbg 0x4 ARM-ADS - 6100001::V6.10.1::.\ARMCLANG + 6160000::V6.16::ARMCLANG 1 STM32L053R8Tx STMicroelectronics - Keil.STM32L0xx_DFP.2.0.0 + Keil.STM32L0xx_DFP.2.2.0 http://www.keil.com/pack/ IRAM(0x20000000,0x00002000) IROM(0x08000000,0x00010000) CPUTYPE("Cortex-M0+") CLOCK(12000000) ELITTLE @@ -185,6 +185,7 @@ 0 0 0 + 0 0 0 8 @@ -351,7 +352,7 @@ 0 1 0 - 0 + 4 Stack_Size=1024 Heap_Size=16 @@ -541,6 +542,57 @@ qxk_port.cpp 8 ..\..\..\..\..\ports\arm-cm\qxk\armclang\qxk_port.cpp + + + 2 + 0 + 0 + 0 + 0 + 2 + 2 + 2 + 2 + 2 + 11 + + + 1 + + + + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 0 + 0 + 2 + 2 + 2 + 2 + 2 + + + QXK_USE_IRQ_NUM=30 QXK_USE_IRQ_HANDLER=LCD_IRQHandler + + + + + + @@ -605,7 +657,7 @@ 2 2 2 - 2 + 0 @@ -645,7 +697,7 @@ STM32L053R8Tx STMicroelectronics - Keil.STM32L0xx_DFP.2.0.0 + Keil.STM32L0xx_DFP.2.2.0 http://www.keil.com/pack/ IRAM(0x20000000,0x00002000) IROM(0x08000000,0x00010000) CPUTYPE("Cortex-M0+") CLOCK(12000000) ELITTLE @@ -814,6 +866,7 @@ 0 0 0 + 0 0 0 8 @@ -980,7 +1033,7 @@ 0 1 0 - 0 + 4 Stack_Size=1024 Heap_Size=16 @@ -1234,7 +1287,7 @@ 2 2 2 - 2 + 0 @@ -1274,7 +1327,7 @@ STM32L053R8Tx STMicroelectronics - Keil.STM32L0xx_DFP.2.0.0 + Keil.STM32L0xx_DFP.2.2.0 http://www.keil.com/pack/ IRAM(0x20000000,0x00002000) IROM(0x08000000,0x00010000) CPUTYPE("Cortex-M0+") CLOCK(12000000) ELITTLE @@ -1443,6 +1496,7 @@ 0 0 0 + 0 0 0 8 @@ -1609,7 +1663,7 @@ 0 1 0 - 0 + 4 Stack_Size=1024 Heap_Size=16 diff --git a/examples/arm-cm/dpp_nucleo-l053r8/qxk/gnu/Makefile b/examples/arm-cm/dpp_nucleo-l053r8/qxk/gnu/Makefile index bc9973ae2..4e6879209 100644 --- a/examples/arm-cm/dpp_nucleo-l053r8/qxk/gnu/Makefile +++ b/examples/arm-cm/dpp_nucleo-l053r8/qxk/gnu/Makefile @@ -1,13 +1,13 @@ ############################################################################## # Product: Makefile for QP/C++ on NUCLEO-L053R8, QXK kernel, GNU-ARM # Last Updated for Version: 7.0.0 -# Date of the Last Update: 2021-07-01 +# Date of the Last Update: 2022-05-02 # # Q u a n t u m L e a P s # ------------------------ # Modern Embedded Software # -# Copyright (C) 2005-2021 Quantum Leaps, LLC. All rights reserved. +# Copyright (C) 2005-2022 Quantum Leaps, LLC. All rights reserved. # # This program is open source software: you can redistribute it and/or # modify it under the terms of the GNU General Public License as published @@ -138,7 +138,9 @@ LIB_DIRS := LIBS := # defines -DEFINES := -DQXK_ON_CONTEXT_SW +DEFINES := -DQXK_ON_CONTEXT_SW \ + -DQXK_USE_IRQ_NUM=30 \ + -DQXK_USE_IRQ_HANDLER=LCD_IRQHandler # ARM CPU, ARCH, FPU, and Float-ABI types... # ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4] diff --git a/examples/arm-cm/dpp_nucleo-l053r8/qxk/iar/dpp-qxk.ewp b/examples/arm-cm/dpp_nucleo-l053r8/qxk/iar/dpp-qxk.ewp index e9eab8127..30e77fdff 100644 --- a/examples/arm-cm/dpp_nucleo-l053r8/qxk/iar/dpp-qxk.ewp +++ b/examples/arm-cm/dpp_nucleo-l053r8/qxk/iar/dpp-qxk.ewp @@ -11,9 +11,13 @@ General 3 - 31 + 33 1 1 + - - - - - + + ICCARM 2 - 35 + 37 1 1 - - - + AARM 2 - 10 + 11 1 1 + @@ -673,13 +657,9 @@ 0 + inputOutputBased - - BICOMP - 0 - - BUILDACTION 1 @@ -692,17 +672,13 @@ ILINK 0 - 23 + 25 1 1 - + + + + + @@ -1051,11 +1047,6 @@ - - BILINK - 0 - - Coder 0 @@ -1072,9 +1063,13 @@ General 3 - 31 + 33 1 0 + - - - - - + + ICCARM 2 - 35 + 37 1 0 - - - + AARM 2 - 10 + 11 1 0 + @@ -1734,13 +1709,9 @@ 0 + inputOutputBased - - BICOMP - 0 - - BUILDACTION 1 @@ -1753,17 +1724,13 @@ ILINK 0 - 23 + 25 1 0 - + + + + + @@ -2112,11 +2099,6 @@ - - BILINK - 0 - - Coder 0 @@ -2133,9 +2115,13 @@ General 3 - 31 + 33 1 1 + - - - - - + + ICCARM 2 - 35 + 37 1 1 - - - + AARM 2 - 10 + 11 1 1 + @@ -2796,13 +2762,9 @@ 0 + inputOutputBased - - BICOMP - 0 - - BUILDACTION 1 @@ -2815,17 +2777,13 @@ ILINK 0 - 23 + 25 1 1 - + + + + + @@ -3174,11 +3152,6 @@ - - BILINK - 0 - - Coder 0 @@ -3294,6 +3267,255 @@ $PROJ_DIR$\..\..\..\..\..\ports\arm-cm\qxk\iar\qxk_port.cpp + + Debug + + ICCARM + + 37 + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $PROJ_DIR$\..\..\..\..\..\ports\arm-cm\qxk\iar\qxk_port.h diff --git a/examples/arm-cm/dpp_nucleo-l152re/README.md b/examples/arm-cm/dpp_nucleo-l152re/README.md new file mode 100644 index 000000000..aeacdf4eb --- /dev/null +++ b/examples/arm-cm/dpp_nucleo-l152re/README.md @@ -0,0 +1,5 @@ +![STM32 NUCLEO-L552ZE Q](../../../doxygen/images/bd_NUCLEO-L152RE.jpg) + +Documentation for this example is available in the QP/C Manual at: + +- https://www.state-machine.com/qpcpp/arm-cm_dpp_nucleo-l152re.html diff --git a/examples/arm-cm/dpp_nucleo-l152re/README.txt b/examples/arm-cm/dpp_nucleo-l152re/README.txt deleted file mode 100644 index c333bade5..000000000 --- a/examples/arm-cm/dpp_nucleo-l152re/README.txt +++ /dev/null @@ -1,74 +0,0 @@ -About this Example -================== -This directory contains the "Dining Philosophers Problem" (DPP) example -running on the STM32 NUCLEO-L152RE board (ARM Cortex-M3). The following -versions of the example are provided: - -dpp_nucleo-l152re/ - | - +-qk/ - preemptive QK kernel - | +-arm/ - ARM-KEIL toolset - | +-gnu/ - GNU-ARM toolset - | +-iar/ - IAR-ARM toolset - | - +-qv/ - cooperative QV kernel - | +-arm/ - ARM-KEIL toolset - | +-gnu/ - GNU-ARM toolset - | +-iar/ - IAR-ARM toolset - -*** -NOTE: The sub-directory "gnu" contains the Makefile for a generic GNU-ARM -toolset (e.g., see http://gnutoolchains.com/arm-eabi/). Thus, this -project provides a way of building mbed applications locally with -free and unrestricted tools. -*** -*** -NOTE: To build the code on Windows, you need to download and install -the GNU make utility. The Qtools collection from Quantum Leaps contains -GNU make and other UNIX-style utilites for Windows (native Windows, -without the need to install CygWin). -*** - -Downloading the Code to STM32 NUCLEO-L152RE Board -================================================= -After building the code with any of the supported toosets, you have -two options of loading the code to the NUCLEO board. - -First, you can use the on-board ST-Link debugger to download the code -from the toolset IDE (e.g., uVision or IAR EW). - -Alternatively, you can simply copy the binary image to the NUCLEO -folder for execution. - -*** -NOTE: -The whole build process and loading the image to the mbed board can -be executed directly from the QM modeling (by means of external tools). -The provided QM model (dpp.qm) comes pre-configured with tools -setup to build (via make) and copy the code to the mbed board. -*** - - -Support Code for STM32 NUCLEO-L152RE Board ------------------------------------------- -The directory qpc\3rd_party\nucleo-l152re contains the CMSIS- -compliant device code for the STM32L0xx MCUs (ARM Cortex-M3). Please see -the README file in this folder for more details. - - -QS Software Tracing Instrumentation -=================================== -This example provides the "Spy" build configuration, which outputs the QS -(Quantum Spy) software tracing data through UART2, which is connected to -the virtual COM port of the ST-Link V2 USB debugger. - -The output is generated at 115200 baud rate. - -Here is an example invocation of the QSPY host application to receive -the QS data from NUCLEO board: - -qspy -cCOM20 - -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/examples/arm-cm/dpp_nucleo-l552ze/README.md b/examples/arm-cm/dpp_nucleo-l552ze/README.md new file mode 100644 index 000000000..b1b9c9f9f --- /dev/null +++ b/examples/arm-cm/dpp_nucleo-l552ze/README.md @@ -0,0 +1,5 @@ +![STM32 NUCLEO-L552ZE Q](../../../doxygen/images/bd_NUCLEO-L552ZE.jpg) + +Documentation for this example is available in the QP/C Manual at: + +- https://www.state-machine.com/qpcpp/arm-cm_dpp_nucleo-l552ze.html diff --git a/examples/arm-cm/dpp_stm32f4-discovery/README.md b/examples/arm-cm/dpp_stm32f4-discovery/README.md new file mode 100644 index 000000000..2e5b7ffd4 --- /dev/null +++ b/examples/arm-cm/dpp_stm32f4-discovery/README.md @@ -0,0 +1,5 @@ +![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/examples/arm-cm/game_efm32-slstk3401a/README.md b/examples/arm-cm/game_efm32-slstk3401a/README.md new file mode 100644 index 000000000..4f72de3ec --- /dev/null +++ b/examples/arm-cm/game_efm32-slstk3401a/README.md @@ -0,0 +1,72 @@ +![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. + +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. + + +# Support Code for EFM32-SLSTK3401A Board +The directory qpc\3rd_party\efm32pg1b\ contains the CMSIS-compliant +device code for the LM3S811 MCU. Please see the README file in this +folder for more details. + + +# QS Software Tracing Instrumentation +The 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 board. + +The output is generated at 115200 baud rate. + +Here is an example invocation of the QSPY host application to receive +the QS data from EFM32-SLSTK3401A: + +``` +qspy -c COM1 (Windows) + +qspy -c /dev/ttyS1 (POSIX) +``` + +The actual serial-port number might be different on your workstation. +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 multithreded (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 Win32-GUI emulation is based on the QWin™ GUI Prototyping Toolkit, see: + +- https://www.state-machine.com/products/qtools#QWIN + +The emulation uses exactly the same code as the embedded board and differs +only in the Board Support Package (bsp.c). This example demonstrates the +"dual targeting" development approach, where most of the embedded code is +developed on the workstation (Windows), but is intended for a deeply +embedded target (EFM32-SLSTK3401A here). + + +# QS Software Tracing Instrumentation +The "win32-gui" emulation also supports the "Spy" build configuration, +in which case it attempts to connect to the QSPY host application via +a TCP/IP socket (default). Here is how you launch the QSPY host utility: + + +``` +qspy +``` + diff --git a/examples/arm-cm/game_efm32-slstk3401a/README.txt b/examples/arm-cm/game_efm32-slstk3401a/README.txt deleted file mode 100644 index 977c97eb2..000000000 --- a/examples/arm-cm/game_efm32-slstk3401a/README.txt +++ /dev/null @@ -1,36 +0,0 @@ -About this Example -================== -This directory contains the "Fly 'n' Shoot" game example application for -the EK-LM3S811 board. This directory contains portable code that should -compile with any C/C++ compiler for ARM Cortex-M. - -The sub-directories contain code and project files, which are specific to -the particular ARM toolchains, such as ARM (MDK-ARM), GNU, 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. - - -Support Code for EK-LM3S811 Board ----------------------------------- -The directory 3rd_party\ek-lm3s811 contains the CMSIS-compliant -device code for the LM3S811 MCU. Please see the README file in this -folder for more details. - - -QS Software Tracing Instrumentation ------------------------------------ -The Blinky 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. - -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/examples/arm-cm/low-power_ek-tm4c123gxl/README.md b/examples/arm-cm/low-power_ek-tm4c123gxl/README.md new file mode 100644 index 000000000..d98ec7ed9 --- /dev/null +++ b/examples/arm-cm/low-power_ek-tm4c123gxl/README.md @@ -0,0 +1,5 @@ +![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/arm-cm_low-power.html diff --git a/examples/arm-cm/low-power_ek-tm4c123gxl/README.txt b/examples/arm-cm/low-power_ek-tm4c123gxl/README.txt deleted file mode 100644 index 7629701cf..000000000 --- a/examples/arm-cm/low-power_ek-tm4c123gxl/README.txt +++ /dev/null @@ -1,26 +0,0 @@ -About this Example -================== -This directory contains the simple "Low-Power" QP example application for -the EK-TM4C123GXL board (TivaC LauchPad) with the coopertative QV kernel, -the preemptive QK kernel, and the dual-mode QXK kernel. This directory -contains portable code that should compile with any C compiler for -ARM Cortex-M. - -The sub-directories contain code and project files, which are specific -to the particular ARM toolchains, such as ARM (MDK-ARM), GNU-ARM, and -IAR EWARM. - -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 -==================================== -The directory qpc\3rd_party\ek-tm4c123gxl contains the CMSIS-compliant -device code for the TM4C123GH6PM MCU. Please see the README.txt file in -this folder for more details. - - -QS Software Tracing Instrumentation ------------------------------------ -This example does NOT provide the "Spy" build configuration. diff --git a/examples/arm-cr/blinky_launchxl2-tms57012/README.md b/examples/arm-cr/blinky_launchxl2-tms57012/README.md new file mode 100644 index 000000000..ae7ed5c8c --- /dev/null +++ b/examples/arm-cr/blinky_launchxl2-tms57012/README.md @@ -0,0 +1,5 @@ +![LAUNCHXL2-TMS57012](../../../doxygen/images/bd_LAUNCHXL2-TMS57012.jpg) + +Documentation for this example is available in the QP/C Manual at: + +- https://www.state-machine.com/qpcpp/arm-cr_blinky_launchxl2-tms57012.html diff --git a/examples/arm-cr/dpp_launchxl2-tms57012/README.md b/examples/arm-cr/dpp_launchxl2-tms57012/README.md new file mode 100644 index 000000000..4219f7cc9 --- /dev/null +++ b/examples/arm-cr/dpp_launchxl2-tms57012/README.md @@ -0,0 +1,5 @@ +![LAUNCHXL2-TMS57012](../../../doxygen/images/bd_LAUNCHXL2-TMS57012.jpg) + +Documentation for this example is available in the QP/C Manual at: + +- https://www.state-machine.com/qpcpp/arm-cr_dpp_launchxl2-tms57012.html diff --git a/examples/arm7-9/dpp_at91sam7s-ek/README.md b/examples/arm7-9/dpp_at91sam7s-ek/README.md new file mode 100644 index 000000000..9ade9e534 --- /dev/null +++ b/examples/arm7-9/dpp_at91sam7s-ek/README.md @@ -0,0 +1,5 @@ +![STM32 EFM32-SLSTK3401A](../../../doxygen/images/bd_AT91SAM7S-EK.jpg) + +Documentation for this example is available in the QP/C Manual at: + +- https://www.state-machine.com/qpcpp/arm7-9_dpp_at91sam7s-ek.html diff --git a/examples/embos/arm-cm/dpp_nucleo-h743zi/README.md b/examples/embos/arm-cm/dpp_nucleo-h743zi/README.md new file mode 100644 index 000000000..a9ccdbf89 --- /dev/null +++ b/examples/embos/arm-cm/dpp_nucleo-h743zi/README.md @@ -0,0 +1,5 @@ +![STM32 NUCLEO-H743ZI Q](../../../../doxygen/images/bd_NUCLEO-H743ZI.jpg) + +Documentation for this example is available in the QP/C Manual at: + +- https://www.state-machine.com/qpcpp/embos_dpp_nucleo-h743zi.html diff --git a/examples/freertos/arm-cm/dpp_ek-tm4c123gxl/README.md b/examples/freertos/arm-cm/dpp_ek-tm4c123gxl/README.md new file mode 100644 index 000000000..7346acd18 --- /dev/null +++ b/examples/freertos/arm-cm/dpp_ek-tm4c123gxl/README.md @@ -0,0 +1,5 @@ +![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/examples/qutest/self_test/test/test_qutest.cpp b/examples/qutest/self_test/test/test_qutest.cpp index 5b5f071ae..4616775d0 100644 --- a/examples/qutest/self_test/test/test_qutest.cpp +++ b/examples/qutest/self_test/test/test_qutest.cpp @@ -1,6 +1,5 @@ //! @file //! @brief Fixture for QUTEST self-test -//! @ingroup qs //! @cond //============================================================================ //! Last updated for version 6.9.3 diff --git a/examples/qutest/target_efm32/qutest_port.cpp b/examples/qutest/target_efm32/qutest_port.cpp index e95e78610..785797d41 100644 --- a/examples/qutest/target_efm32/qutest_port.cpp +++ b/examples/qutest/target_efm32/qutest_port.cpp @@ -1,6 +1,5 @@ //! @file //! @brief QUTEST port for the EFM32-SLSTK3401A board -//! @ingroup qs //! @cond //============================================================================ //! Last updated for version 6.9.2a diff --git a/examples/qutest/target_exp430f55/qutest_port.cpp b/examples/qutest/target_exp430f55/qutest_port.cpp index 4e198ba8f..de67c281f 100644 --- a/examples/qutest/target_exp430f55/qutest_port.cpp +++ b/examples/qutest/target_exp430f55/qutest_port.cpp @@ -1,6 +1,5 @@ //! @file //! @brief QUTEST port for the MSP-EXP430F5529LP board -//! @ingroup qs //! @cond //============================================================================ //! Last updated for version 6.8.0 diff --git a/examples/qutest/target_nucleo-l053r8/qutest_port.cpp b/examples/qutest/target_nucleo-l053r8/qutest_port.cpp index a3b1ff7f3..983d9ecb5 100644 --- a/examples/qutest/target_nucleo-l053r8/qutest_port.cpp +++ b/examples/qutest/target_nucleo-l053r8/qutest_port.cpp @@ -1,6 +1,5 @@ //! @file //! @brief QUTEST port for NUCLEO-L053R8 board -//! @ingroup qs //! @cond //============================================================================ //! Last updated for: @qpcpp_7_0_0 diff --git a/examples/qutest/target_tm4c123/qutest_port.cpp b/examples/qutest/target_tm4c123/qutest_port.cpp index 22e2a1ce5..6a53a6899 100644 --- a/examples/qutest/target_tm4c123/qutest_port.cpp +++ b/examples/qutest/target_tm4c123/qutest_port.cpp @@ -1,6 +1,5 @@ //! @file //! @brief QUTEST port for the EK-TM4C123GXL board -//! @ingroup qs //! @cond //============================================================================ //! Last updated for version 6.9.2a diff --git a/examples/workstation/blinky/README.md b/examples/workstation/blinky/README.md new file mode 100644 index 000000000..fe4dfad21 --- /dev/null +++ b/examples/workstation/blinky/README.md @@ -0,0 +1,18 @@ +@page exa_workstation_blinky Example: Blinky Console + +![Blinky on Win32](blinky_win.png) + +# Example: Blinky Console + +This example corresponds to the QM Tutorial at: + +https://www.state-machine.com/qm/gs_tut.html + + +Specifically the files are as follows: + +``` +blinky.qm - the QM model for the Blinky active object +blinky.c - the generated code for the Blinky application +Makefile - the makefile to build Blinky on Windows/Linux/macOS +``` diff --git a/examples/workstation/blinky/README.txt b/examples/workstation/blinky/README.txt deleted file mode 100644 index ae7b7f091..000000000 --- a/examples/workstation/blinky/README.txt +++ /dev/null @@ -1,11 +0,0 @@ -This example corresponds to the QM Tutorial at: - -https://www.state-machine.com/qm/gs_tut.html - - -Specifically the files are as follows: - -blinky.qm - the QM model for the Blinky active object -blinky.cpp - the generated code for the Blinky application -make.bat - the batch file for building Blinky on Windows -Makefile - the makefile to build Blinky on Linux diff --git a/examples/workstation/blinky/blinky_win.png b/examples/workstation/blinky/blinky_win.png new file mode 100644 index 000000000..1771e8863 Binary files /dev/null and b/examples/workstation/blinky/blinky_win.png differ diff --git a/include/qassert.h b/include/qassert.h index c211a55ad..5efda1eea 100644 --- a/include/qassert.h +++ b/include/qassert.h @@ -28,7 +28,6 @@ * * @file * @brief Customizable and memory-efficient assertions for embedded systems -* @ingroup qp */ #ifndef QASSERT_H #define QASSERT_H @@ -63,7 +62,7 @@ /* provide typedefs so that qassert.h could be used "standalone"... */ /*! typedef for assertions-ids and line numbers in assertions. - * @description + * @details * This typedef specifies integer type for exclusive use in assertions. * Use of this type, rather than plain 'int', is in compliance * with the MISRA-C 2012 Dir 4.6 (adv). @@ -73,7 +72,7 @@ #endif /*! Define the file name (with `__FILE__`) for assertions in this file - * @description + * @details * Macro to be placed at the top of each C/C++ module to define the * single instance of the file name string to be used in reporting * assertions in this module. @@ -89,7 +88,7 @@ static char const Q_this_module_[] = __FILE__; /*! Define the user-specified module name for assertions in this file. - * @description + * @details * Macro to be placed at the top of each C/C++ module to define the * single instance of the module name string to be used in reporting * assertions in this module. This macro takes the user-supplied parameter @@ -104,7 +103,7 @@ static char const Q_this_module_[] = name_; /*! General purpose assertion. - * @description + * @details * Makes sure the @p test_ parameter is TRUE. Calls the Q_onAssert() * callback if the @p test_ expression evaluates to FALSE. This * macro identifies the assertion location within the file by means @@ -119,7 +118,7 @@ ? (void)0 : Q_onAssert(&Q_this_module_[0], __LINE__)) /*! General purpose assertion with user-specified assertion-id. - * @description + * @details * Makes sure the @p test_ parameter is TRUE. Calls the Q_onAssert() * callback if the @p test_ evaluates to FALSE. This assertion takes the * user-supplied parameter @p id_ to identify the location of this @@ -138,7 +137,7 @@ /*! General purpose assertion that __always__ evaluates the @p test_ * expression. - * @description + * @details * Like the Q_ASSERT() macro, except it __always__ evaluates the @p test_ * expression even when assertions are disabled with the #Q_NASSERT macro. * However, when the #Q_NASSERT macro is defined, the Q_onAssert() @@ -152,7 +151,7 @@ /*! General purpose assertion with user-specified assertion-id that * __always__ evaluates the @p test_ expression. - * @description + * @details * Like the Q_ASSERT_ID() macro, except it __always__ evaluates the * @p test_ expression even when assertions are disabled with the * #Q_NASSERT macro. However, when the #Q_NASSERT macro is defined, the @@ -165,7 +164,7 @@ #define Q_ALLEGE_ID(id_, test_) Q_ASSERT_ID((id_), (test_)) /*! Assertion for a wrong path through the code. - * @description + * @details * Calls the Q_onAssert() callback if ever executed. * * @note Does noting if assertions are disabled with the #Q_NASSERT switch. @@ -174,7 +173,7 @@ Q_onAssert(&Q_this_module_[0], __LINE__) /*! Assertion with user-specified assertion-id for a wrong path - * @description + * @details * Calls the Q_onAssert() callback if ever executed. This assertion * takes the user-supplied parameter @p id_ to identify the location of * this assertion within the file. This avoids the volatility of using @@ -201,7 +200,7 @@ #endif /* Q_NORETURN */ /*! Callback function invoked in case of any assertion failure. -* @description +* @details * This is an application-specific callback function needs to be defined in * the application to perform the clean system shutdown and perhaps a reset. * @@ -234,7 +233,7 @@ Q_NORETURN Q_onAssert(char const * const module, int_t const location); #endif /*! Assertion for checking preconditions. -* @description +* @details * This macro is equivalent to #Q_ASSERT, except the name provides a better * documentation of the intention of this assertion. * @@ -243,7 +242,7 @@ Q_NORETURN Q_onAssert(char const * const module, int_t const location); #define Q_REQUIRE(test_) Q_ASSERT(test_) /*! Assertion for checking preconditions with user-specified assertion-id. -* @description +* @details * Equivalent to #Q_ASSERT_ID, except the macro name provides a better * documentation of the intention of this assertion. * @@ -253,7 +252,7 @@ Q_NORETURN Q_onAssert(char const * const module, int_t const location); #define Q_REQUIRE_ID(id_, test_) Q_ASSERT_ID((id_), (test_)) /*! Assertion for checking postconditions. -* @description +* @details * Equivalent to #Q_ASSERT, except the macro name provides a better * documentation of the intention of this assertion. * @@ -262,7 +261,7 @@ Q_NORETURN Q_onAssert(char const * const module, int_t const location); #define Q_ENSURE(test_) Q_ASSERT(test_) /*! Assertion for checking postconditions with user-specified assertion-id. -* @description +* @details * Equivalent to #Q_ASSERT_ID, except the name provides a better documentation * of the intention of this assertion. * @@ -272,7 +271,7 @@ Q_NORETURN Q_onAssert(char const * const module, int_t const location); #define Q_ENSURE_ID(id_, test_) Q_ASSERT_ID((id_), (test_)) /*! Assertion for checking invariants. -* @description +* @details * Equivalent to #Q_ASSERT, except the macro name provides a better * documentation of the intention of this assertion. * @@ -281,7 +280,7 @@ Q_NORETURN Q_onAssert(char const * const module, int_t const location); #define Q_INVARIANT(test_) Q_ASSERT(test_) /*! Assertion for checking invariants with user-specified assertion-id. -* @description +* @details * Equivalent to #Q_ASSERT_ID, except the macro name provides a better * documentation of the intention of this assertion. * @@ -291,7 +290,7 @@ Q_NORETURN Q_onAssert(char const * const module, int_t const location); #define Q_INVARIANT_ID(id_, test_) Q_ASSERT_ID((id_), (test_)) /*! Static (compile-time) assertion. -* @description +* @details * This type of assertion deliberately causes a compile-time error when * the @p test_ evaluates to FALSE. The macro exploits the fact that in C/C++ * a dimension of an array cannot be negative. The compile-time assertion has diff --git a/include/qep.hpp b/include/qep.hpp index e482333b7..eb80a7980 100644 --- a/include/qep.hpp +++ b/include/qep.hpp @@ -27,15 +27,11 @@ //! //! @file //! @brief QEP/C++ platform-independent public interface. -//! @ingroup qep //! #ifndef QEP_HPP #define QEP_HPP //============================================================================ -//! @addtogroup qp -//! @{ - //! The current QP version as a decimal constant XXYZ, where XX is a 2-digit //! major version number, Y is a 1-digit minor version number, and Z is //! a 1-digit release number. @@ -46,7 +42,7 @@ //! and Z is a 1-digit release number. #define QP_VERSION_STR "7.0.0" -//! Encrypted current QP release (7.0.0) and date (2022-01-31) */ +//! Encrypted current QP release (7.0.0) and date (2022-01-31) #define QP_RELEASE 0x7CCAAA13U //============================================================================ @@ -87,8 +83,6 @@ using float32_t = float; //! using float64_t = double; -//! @} - //============================================================================ //! Perform downcast of an event onto a subclass of QEvt @p class_ //! @description @@ -116,7 +110,6 @@ using float64_t = double; //============================================================================ //! namespace associated with the QP/C++ framework -//! @ingroup qep qf qs qv qk qxk namespace QP { //! the current QP version number string based on QP_VERSION_STR @@ -267,7 +260,7 @@ class QHsm { //! overloaded init(qs_id) virtual void init(std::uint_fast8_t const qs_id) { - init(nullptr, qs_id); // virtual call + init(nullptr, qs_id); } //! Dispatches an event to QHsm @@ -493,6 +486,9 @@ class QMsm : public QHsm { void init(void const * const e, std::uint_fast8_t const qs_id) override; + //! overloaded init(qs_id) + void init(std::uint_fast8_t const qs_id) override; + //! Dispatches an event to a HSM void dispatch(QEvt const * const e, std::uint_fast8_t const qs_id) override; diff --git a/include/qequeue.hpp b/include/qequeue.hpp index 84513b80a..20706b237 100644 --- a/include/qequeue.hpp +++ b/include/qequeue.hpp @@ -27,7 +27,6 @@ //! //! @file //! @brief platform-independent fast "raw" thread-safe event queue interface -//! @ingroup qf #ifndef QEQUEUE_HPP #define QEQUEUE_HPP diff --git a/include/qf.hpp b/include/qf.hpp index e707252ca..102a43d94 100644 --- a/include/qf.hpp +++ b/include/qf.hpp @@ -27,7 +27,6 @@ //! //! @file //! @brief QF/C++ platform-independent public interface. -//! @ingroup qf #ifndef QF_HPP #define QF_HPP @@ -325,6 +324,7 @@ class QMActive : public QActive { // all the following operations delegate to the QHsm class... void init(void const * const e, std::uint_fast8_t const qs_id) override; + void init(std::uint_fast8_t const qs_id) override; void dispatch(QEvt const * const e, std::uint_fast8_t const qs_id) override; @@ -638,6 +638,7 @@ class QTicker : public QActive { void init(void const * const e, std::uint_fast8_t const qs_id) noexcept override; + void init(std::uint_fast8_t const qs_id) noexcept override; void dispatch(QEvt const * const e, std::uint_fast8_t const qs_id) noexcept override; #ifndef Q_SPY diff --git a/include/qk.hpp b/include/qk.hpp index fc263b559..6d5c67e78 100644 --- a/include/qk.hpp +++ b/include/qk.hpp @@ -27,7 +27,6 @@ //! //! @file //! @brief QK/C++ platform-independent public interface. -//! @ingroup qk #ifndef QK_HPP #define QK_HPP diff --git a/include/qmpool.hpp b/include/qmpool.hpp index 18ed08854..a822c65ec 100644 --- a/include/qmpool.hpp +++ b/include/qmpool.hpp @@ -27,7 +27,6 @@ //! //! @file //! @brief platform-independent memory pool QP::QMPool interface. -//! @ingroup qf #ifndef QMPOOL_HPP #define QMPOOL_HPP diff --git a/include/qpcpp.hpp b/include/qpcpp.hpp index bc5cdd1fd..be1d1bc5b 100644 --- a/include/qpcpp.hpp +++ b/include/qpcpp.hpp @@ -30,7 +30,6 @@ //! @description //! This header file must be included directly or indirectly //! in all application modules (*.cpp files) that use QP/C++. -//! @ingroup qp #ifndef qpcpp_h #define qpcpp_h diff --git a/include/qpset.hpp b/include/qpset.hpp index 1acd6e50f..63c57d35b 100644 --- a/include/qpset.hpp +++ b/include/qpset.hpp @@ -27,7 +27,6 @@ //! //! @file //! @brief platform-independent priority sets of 8 or 64 elements. -//! @ingroup qf #ifndef QPSET_HPP #define QPSET_HPP diff --git a/include/qs.hpp b/include/qs.hpp index 764395493..6e554462e 100644 --- a/include/qs.hpp +++ b/include/qs.hpp @@ -27,7 +27,6 @@ //! //! @file //! @brief QS/C++ platform-independent public interface. -//! @ingroup qs #ifndef QS_HPP #define QS_HPP @@ -565,6 +564,7 @@ class QHsmDummy : public QHsm { void init(void const * const e, std::uint_fast8_t const qs_id) noexcept override; + void init(std::uint_fast8_t const qs_id) noexcept override; void dispatch(QEvt const * const e, std::uint_fast8_t const qs_id) noexcept override; }; @@ -593,6 +593,7 @@ class QActiveDummy : public QActive { void init(void const * const e, std::uint_fast8_t const qs_id) noexcept override; + void init(std::uint_fast8_t const qs_id) noexcept override; void dispatch(QEvt const * const e, std::uint_fast8_t const qs_id) noexcept override; bool post_(QEvt const * const e, @@ -959,9 +960,9 @@ extern std::uint8_t volatile QF_intNest; //! the QS log, because instead of dealing with cryptic machine addresses the //! QSpy host utility can display human-readable object names. //! -//! The following example shows the definition of object dictionary entry -//! for the Table active object: -//! @include qs_objDic.cpp +//! The following example shows the definition of object array dictionary +//! for `Philo::inst[n]` and `Philo::inst[n].m_timeEvt`: +//! @include qs_objObjDic.cpp #define QS_OBJ_ARR_DICTIONARY(obj_, idx_) \ (QP::QS::obj_arr_dict_pre_((obj_), (idx_), #obj_)) diff --git a/include/qs_dummy.hpp b/include/qs_dummy.hpp index d51b7939b..51302294f 100644 --- a/include/qs_dummy.hpp +++ b/include/qs_dummy.hpp @@ -28,7 +28,6 @@ //! @file //! @brief Dummy definitions of the QS macros that avoid code generation from //! the QS instrumentation. -//! @ingroup qs qpspy #ifndef QS_DUMMY_HPP #define QS_DUMMY_HPP diff --git a/include/qv.hpp b/include/qv.hpp index f684d3ebe..3179c0d61 100644 --- a/include/qv.hpp +++ b/include/qv.hpp @@ -27,7 +27,6 @@ //! //! @file //! @brief QV/C++ platform-independent public interface. -//! @ingroup qv #ifndef QV_HPP #define QV_HPP diff --git a/include/qxk.hpp b/include/qxk.hpp index 2ba5a9d21..ddc79c6db 100644 --- a/include/qxk.hpp +++ b/include/qxk.hpp @@ -28,7 +28,6 @@ //! @file //! @brief QXK/C++ preemptive extended (blocking) kernel, platform-independent //! public interface. -//! @ingroup qxk #ifndef QXK_HPP #define QXK_HPP diff --git a/include/qxthread.hpp b/include/qxthread.hpp index 274049e0b..3a63b9716 100644 --- a/include/qxthread.hpp +++ b/include/qxthread.hpp @@ -27,7 +27,6 @@ //! //! @file //! @brief QXK/C++ extended (blocking) thread -//! @ingroup qxk #ifndef QXTHREAD_HPP #define QXTHREAD_HPP diff --git a/ports/arm-cm/README.md b/ports/arm-cm/README.md index 0e878aba1..12b8ff5df 100644 --- a/ports/arm-cm/README.md +++ b/ports/arm-cm/README.md @@ -1,4 +1,4 @@ -# Native QP/C++ Ports to ARM Cortex-M +# Native QP/C Ports to ARM Cortex-M ## Supported ARM Cortex-M Architectures: @@ -6,7 +6,7 @@ - ARMv7-M (**ARM Cortex-M3/M4/M7**) - ARMv8-M (**ARM Cortex-M23/M33**) -## Supported QP/C++ Kernels and Toolchains: +## Supported QP/C Kernels and Toolchains: - [Cooperative QV kernel](https://www.state-machine.com/qpcpp/group__qv.html) + ARM/KEIL MDK, ARM Compiler 6 (ARM-CLANG) + IAR-ARM @@ -22,6 +22,6 @@ ## Documentation: -Detailed documentation for these ports is available in the QP/C++ Manual at: +Detailed documentation for these ports is available in the QP/C Manual at: - https://www.state-machine.com/qpcpp/arm-cm.html diff --git a/ports/arm-cm/qk/armclang/qk_port.cpp b/ports/arm-cm/qk/armclang/qk_port.cpp index 46ae6df42..6a544d6ba 100644 --- a/ports/arm-cm/qk/armclang/qk_port.cpp +++ b/ports/arm-cm/qk/armclang/qk_port.cpp @@ -23,8 +23,8 @@ * ============================================================================*/ /*! -* @date Last updated on: 2022-04-09 -* @version Last updated for: @ref qpcpp_7_0_0 +* @date Last updated on: 2022-05-02 +* @version Last updated for: @ref qpc_7_0_0 * * @file * @brief QK/C++ port to ARM Cortex-M, ARM-CLANG toolset @@ -37,15 +37,17 @@ extern "C" { /* prototypes --------------------------------------------------------------*/ void PendSV_Handler(void); -#ifndef QK_ARM_CM_USE_NMI - void SVC_Handler(void); -#else - void NMI_Handler(void); +#ifdef QK_USE_IRQ_HANDLER /* if use IRQ... */ +void QK_USE_IRQ_HANDLER(void); +#else /* use default (NMI) */ +void NMI_Handler(void); #endif #define SCnSCB_ICTR ((uint32_t volatile *)0xE000E004) #define SCB_SYSPRI ((uint32_t volatile *)0xE000ED14) -#define NVIC_IP ((uint32_t volatile *)0xE000E400) +#define NVIC_EN ((uint32_t volatile *)0xE000E100) +#define NVIC_IP ((uint8_t volatile *)0xE000E400) +#define NVIC_PEND 0xE000E200 #define NVIC_ICSR 0xE000ED04 /* helper macros to "stringify" values */ @@ -69,7 +71,6 @@ void PendSV_Handler(void); * changed by the application-level code. */ void QK_init(void) { - #if (__ARM_ARCH != 6) /* if ARMv7-M and higher... */ /* set exception priorities to QF_BASEPRI... @@ -84,21 +85,22 @@ void QK_init(void) { SCB_SYSPRI[3] |= (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U) | QF_BASEPRI; /* set all implemented IRQ priories to QF_BASEPRI... */ - uint32_t n = 8U + ((*SCnSCB_ICTR & 0x7U) << 3U); /*(# NVIC_PRIO regs)/4 */ - do { - --n; - NVIC_IP[n] = (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U) - | (QF_BASEPRI << 8U) | QF_BASEPRI; - } while (n != 0U); + uint8_t nprio = (8U + ((*SCnSCB_ICTR & 0x7U) << 3U))*4; + for (uint8_t n = 0U; n < nprio; ++n) { + NVIC_IP[n] = QF_BASEPRI; + } -#endif /* ARMv7-M and higher */ +#endif /* ARMv7-M or higher */ /* SCB_SYSPRI3: PendSV set to priority 0xFF (lowest) */ SCB_SYSPRI[3] |= (0xFFU << 16U); -#ifndef QK_ARM_CM_USE_NMI - /* SCB_SYSPRI2: SVCall */ - SCB_SYSPRI[2] &= ~(0xFFU << 24U); /* prioiry 0 (highest) */ +#ifdef QK_USE_IRQ_NUM + /* The QK port is configured to use a given ARM Cortex-M IRQ # + * to return to thread mode (default is to use the NMI exception) + */ + NVIC_IP[QK_USE_IRQ_NUM] = 0U; /* priority 0 (highest) */ + NVIC_EN[QK_USE_IRQ_NUM / 32U] = (1U << (QK_USE_IRQ_NUM % 32U)); #endif } @@ -209,9 +211,13 @@ __asm volatile ( #endif /* VFP available */ #endif /* ARMv7-M and higher */ -#ifndef QK_ARM_CM_USE_NMI /* if use SVC... */ - " SVC #0 \n" /* trigger SVC */ -#else /* use NMI */ +#ifdef QK_USE_IRQ_NUM /* if use IRQ... */ + " LDR r0,=" STRINGIFY(NVIC_PEND + (QK_USE_IRQ_NUM / 32)) "\n" + " MOVS r1,#1 \n" + " LSLS r1,r1,#" STRINGIFY(QK_USE_IRQ_NUM % 32) "\n" /* r1 := IRQ bit */ + " STR r1,[r0] \n" /* pend the IRQ */ + " B . \n" /* wait for preemption by the IRQ */ +#else /* use the NMI */ " LDR r0,=" STRINGIFY(NVIC_ICSR) "\n" /* Interrupt Control and State */ " MOVS r1,#1 \n" " LSLS r1,r1,#31 \n" /* r1 := (1 << 31) (NMI bit) */ @@ -228,8 +234,8 @@ __asm volatile ( * stack frame that must be at the top of the stack. */ __attribute__ ((naked)) -#ifndef QK_ARM_CM_USE_NMI /* if use SVC... */ -void SVC_Handler(void) +#ifdef QK_USE_IRQ_HANDLER /* if use IRQ... */ +void QK_USE_IRQ_HANDLER(void) #else /* use NMI */ void NMI_Handler(void) #endif /* use NMI */ @@ -237,12 +243,12 @@ void NMI_Handler(void) __asm volatile ( " ADD sp,sp,#(8*4) \n" /* remove one 8-register exception frame */ -#if (__ARM_ARCH != 6) /* if ARMv7-M and higher... */ +#if (__ARM_ARCH != 6) /* if ARMv7-M or higher... */ #if (__ARM_FP != 0) /* if VFP available... */ " POP {r0,lr} \n" /* pop stack aligner and EXC_RETURN to LR */ " DSB \n" /* ARM Erratum 838869 */ #endif /* VFP available */ -#endif /* ARMv7-M and higher */ +#endif /* ARMv7-M or higher */ " BX lr \n" /* return to the preempted task */ ); } @@ -276,7 +282,7 @@ __asm volatile ( "QF_qlog2_3: \n" " LDR r2,=QF_qlog2_LUT \n" " LDRB r0,[r2,r0] \n" - " ADDS r0,r1, r0 \n" + " ADDS r0,r1,r0 \n" " BX lr \n" " .align \n" "QF_qlog2_LUT: \n" diff --git a/ports/arm-cm/qk/armclang/qk_port.hpp b/ports/arm-cm/qk/armclang/qk_port.hpp index aaa655145..7a0fbbf06 100644 --- a/ports/arm-cm/qk/armclang/qk_port.hpp +++ b/ports/arm-cm/qk/armclang/qk_port.hpp @@ -21,7 +21,7 @@ // // //============================================================================ -//! @date Last updated on: 2022-04-10 +//! @date Last updated on: 2022-05-02 //! @version Last updated for: @ref qpcpp_7_0_0 //! //! @file @@ -63,8 +63,17 @@ static inline uint32_t QK_get_IPSR(void) { __asm volatile ("dsb" ::: "memory") #endif -// Use NMI ARM Cortex-M exception to return to thread mode (default SVC) -//#define QK_ARM_CM_USE_NMI 1 +// Use a given ARM Cortex-M IRQ to return to thread mode (default NMI) +// +// NOTE: +// If you need the NMI for other purposes, you can define the macros +// QK_USE_IRQ_NUM and QK_USE_IRQ_HANDLER to use thus specified IRQ +// instead of the NMI (the IRQ should not be used for anything else). +// These two macros can be defined on the command line to the compiler +// and are actually needed only to compile the qk_port.cpp file. +// +//#define QK_USE_IRQ_NUM 25 +//#define QK_USE_IRQ_HANDLER CRYPTO_IRQHandler // initialization of the QK kernel #define QK_INIT() QK_init() diff --git a/ports/arm-cm/qk/gnu/qk_port.cpp b/ports/arm-cm/qk/gnu/qk_port.cpp index fe0890297..afdd55929 100644 --- a/ports/arm-cm/qk/gnu/qk_port.cpp +++ b/ports/arm-cm/qk/gnu/qk_port.cpp @@ -23,7 +23,7 @@ * ============================================================================*/ /*! -* @date Last updated on: 2022-04-09 +* @date Last updated on: 2022-05-02 * @version Last updated for: @ref qpcpp_7_0_0 * * @file @@ -37,15 +37,17 @@ extern "C" { /* prototypes --------------------------------------------------------------*/ void PendSV_Handler(void); -#ifndef QK_ARM_CM_USE_NMI - void SVC_Handler(void); -#else - void NMI_Handler(void); +#ifdef QK_USE_IRQ_HANDLER /* if use IRQ... */ +void QK_USE_IRQ_HANDLER(void); +#else /* use default (NMI) */ +void NMI_Handler(void); #endif #define SCnSCB_ICTR ((uint32_t volatile *)0xE000E004) #define SCB_SYSPRI ((uint32_t volatile *)0xE000ED14) -#define NVIC_IP ((uint32_t volatile *)0xE000E400) +#define NVIC_EN ((uint32_t volatile *)0xE000E100) +#define NVIC_IP ((uint8_t volatile *)0xE000E400) +#define NVIC_PEND 0xE000E200 #define NVIC_ICSR 0xE000ED04 /* helper macros to "stringify" values */ @@ -69,7 +71,6 @@ void PendSV_Handler(void); * changed by the application-level code. */ void QK_init(void) { - #if (__ARM_ARCH != 6) /* if ARMv7-M and higher... */ /* set exception priorities to QF_BASEPRI... @@ -84,21 +85,22 @@ void QK_init(void) { SCB_SYSPRI[3] |= (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U) | QF_BASEPRI; /* set all implemented IRQ priories to QF_BASEPRI... */ - uint32_t n = 8U + ((*SCnSCB_ICTR & 0x7U) << 3U); /*(# NVIC_PRIO regs)/4 */ - do { - --n; - NVIC_IP[n] = (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U) - | (QF_BASEPRI << 8U) | QF_BASEPRI; - } while (n != 0U); + uint8_t nprio = (8U + ((*SCnSCB_ICTR & 0x7U) << 3U))*4; + for (uint8_t n = 0U; n < nprio; ++n) { + NVIC_IP[n] = QF_BASEPRI; + } #endif /* ARMv7-M and higher */ /* SCB_SYSPRI3: PendSV set to priority 0xFF (lowest) */ SCB_SYSPRI[3] |= (0xFFU << 16U); -#ifndef QK_ARM_CM_USE_NMI - /* SCB_SYSPRI2: SVCall */ - SCB_SYSPRI[2] &= ~(0xFFU << 24U); /* prioiry 0 (highest) */ +#ifdef QK_USE_IRQ_NUM + /* The QK port is configured to use a given ARM Cortex-M IRQ # + * to return to thread mode (default is to use the NMI exception) + */ + NVIC_IP[QK_USE_IRQ_NUM] = 0U; /* priority 0 (highest) */ + NVIC_EN[QK_USE_IRQ_NUM / 32U] = (1U << (QK_USE_IRQ_NUM % 32U)); #endif } @@ -214,9 +216,13 @@ __asm volatile ( #endif /* VFP available */ #endif /* ARMv7-M and higher */ -#ifndef QK_ARM_CM_USE_NMI /* if use SVC... */ - " SVC #0 \n" /* trigger SVC */ -#else /* use NMI */ +#ifdef QK_USE_IRQ_NUM /* if use IRQ... */ + " LDR r0,=" STRINGIFY(NVIC_PEND + (QK_USE_IRQ_NUM / 32)) "\n" + " MOV r1,#1 \n" + " LSL r1,r1,#" STRINGIFY(QK_USE_IRQ_NUM % 32) "\n" /* r1 := IRQ bit */ + " STR r1,[r0] \n" /* pend the IRQ */ + " B . \n" /* wait for preemption by the IRQ */ +#else /* use the NMI */ " LDR r0,=" STRINGIFY(NVIC_ICSR) "\n" /* Interrupt Control and State */ " MOV r1,#1 \n" " LSL r1,r1,#31 \n" /* r1 := (1 << 31) (NMI bit) */ @@ -233,8 +239,8 @@ __asm volatile ( * stack frame that must be at the top of the stack. */ __attribute__ ((naked, optimize("-fno-stack-protector"))) -#ifndef QK_ARM_CM_USE_NMI /* if use SVC... */ -void SVC_Handler(void) +#ifdef QK_USE_IRQ_HANDLER /* if use IRQ... */ +void QK_USE_IRQ_HANDLER(void) #else /* use NMI */ void NMI_Handler(void) #endif /* use NMI */ diff --git a/ports/arm-cm/qk/gnu/qk_port.hpp b/ports/arm-cm/qk/gnu/qk_port.hpp index 04defc229..9c4637947 100644 --- a/ports/arm-cm/qk/gnu/qk_port.hpp +++ b/ports/arm-cm/qk/gnu/qk_port.hpp @@ -21,7 +21,7 @@ // // //============================================================================ -//! @date Last updated on: 2022-04-10 +//! @date Last updated on: 2022-05-02 //! @version Last updated for: @ref qpcpp_7_0_0 //! //! @file @@ -63,8 +63,17 @@ static inline uint32_t QK_get_IPSR(void) { __asm volatile ("dsb" ::: "memory") #endif -// Use NMI ARM Cortex-M exception to return to thread mode (default SVC) -//#define QK_ARM_CM_USE_NMI 1 +// Use a given ARM Cortex-M IRQ to return to thread mode (default NMI) +// +// NOTE: +// If you need the NMI for other purposes, you can define the macros +// QK_USE_IRQ_NUM and QK_USE_IRQ_HANDLER to use thus specified IRQ +// instead of the NMI (the IRQ should not be used for anything else). +// These two macros can be defined on the command line to the compiler +// and are actually needed only to compile the qk_port.cpp file. +// +//#define QK_USE_IRQ_NUM 25 +//#define QK_USE_IRQ_HANDLER CRYPTO_IRQHandler // initialization of the QK kernel #define QK_INIT() QK_init() diff --git a/ports/arm-cm/qk/iar/qk_port.cpp b/ports/arm-cm/qk/iar/qk_port.cpp index 32262095c..840dd7d36 100644 --- a/ports/arm-cm/qk/iar/qk_port.cpp +++ b/ports/arm-cm/qk/iar/qk_port.cpp @@ -23,7 +23,7 @@ * ============================================================================*/ /*! -* @date Last updated on: 2022-04-09 +* @date Last updated on: 2022-05-02 * @version Last updated for: @ref qpcpp_7_0_0 * * @file @@ -37,15 +37,17 @@ extern "C" { /* prototypes --------------------------------------------------------------*/ void PendSV_Handler(void); -#ifndef QK_ARM_CM_USE_NMI - void SVC_Handler(void); -#else - void NMI_Handler(void); +#ifdef QK_USE_IRQ_HANDLER /* if use IRQ... */ +void QK_USE_IRQ_HANDLER(void); +#else /* use default (NMI) */ +void NMI_Handler(void); #endif #define SCnSCB_ICTR ((uint32_t volatile *)0xE000E004) #define SCB_SYSPRI ((uint32_t volatile *)0xE000ED14) -#define NVIC_IP ((uint32_t volatile *)0xE000E400) +#define NVIC_EN ((uint32_t volatile *)0xE000E100) +#define NVIC_IP ((uint8_t volatile *)0xE000E400) +#define NVIC_PEND 0xE000E200 #define NVIC_ICSR 0xE000ED04 /* helper macros to "stringify" values */ @@ -69,7 +71,6 @@ void PendSV_Handler(void); * changed by the application-level code. */ void QK_init(void) { - #if (__ARM_ARCH != 6) /* if ARMv7-M and higher... */ /* set exception priorities to QF_BASEPRI... @@ -84,21 +85,22 @@ void QK_init(void) { SCB_SYSPRI[3] |= (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U) | QF_BASEPRI; /* set all implemented IRQ priories to QF_BASEPRI... */ - uint32_t n = 8U + ((*SCnSCB_ICTR & 0x7U) << 3U); /*(# NVIC_PRIO regs)/4 */ - do { - --n; - NVIC_IP[n] = (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U) - | (QF_BASEPRI << 8U) | QF_BASEPRI; - } while (n != 0U); + uint8_t nprio = (8U + ((*SCnSCB_ICTR & 0x7U) << 3U))*4; + for (uint8_t n = 0U; n < nprio; ++n) { + NVIC_IP[n] = QF_BASEPRI; + } #endif /* ARMv7-M and higher */ /* SCB_SYSPRI3: PendSV set to priority 0xFF (lowest) */ SCB_SYSPRI[3] |= (0xFFU << 16U); -#ifndef QK_ARM_CM_USE_NMI - /* SCB_SYSPRI2: SVCall */ - SCB_SYSPRI[2] &= ~(0xFFU << 24U); /* prioiry 0 (highest) */ +#ifdef QK_USE_IRQ_NUM + /* The QK port is configured to use a given ARM Cortex-M IRQ # + * to return to thread mode (default is to use the NMI exception) + */ + NVIC_IP[QK_USE_IRQ_NUM] = 0U; /* priority 0 (highest) */ + NVIC_EN[QK_USE_IRQ_NUM / 32U] = (1U << (QK_USE_IRQ_NUM % 32U)); #endif } @@ -164,7 +166,7 @@ __asm volatile ( " LSRS r3,r1,#3 \n" /* r3 := (r1 >> 3), set the T bit (new xpsr) */ " LDR r2,=QK_activate_ \n" /* address of QK_activate_ */ " SUBS r2,r2,#1 \n" /* align Thumb-address at halfword (new pc) */ - " LDR r1,=QK_thread_ret\n" /* return address after the call (new lr) */ + " LDR r1,=QK_thread_ret \n" /* return address after the call (new lr) */ " SUB sp,sp,#8*4 \n" /* reserve space for exception stack frame */ " ADD r0,sp,#5*4 \n" /* r0 := 5 registers below the SP */ @@ -185,6 +187,7 @@ __asm volatile ( * NOTE: QK_thread_ret does not execute in the PendSV context! * NOTE: QK_thread_ret is entered with interrupts DISABLED. */ + __stackless void QK_thread_ret(void) { __asm volatile ( @@ -197,7 +200,7 @@ __asm volatile ( #if (__ARM_ARCH == 6) /* if ARMv6-M... */ " CPSIE i \n" /* enable interrupts (clear PRIMASK) */ -#else /* ARMv7-M and higher */ +#else /* ARMv7-M or higher */ " MOVS r0,#0 \n" " MSR BASEPRI,r0 \n" /* enable interrupts (clear BASEPRI) */ #if (__ARM_FP != 0) /* if VFP available... */ @@ -207,11 +210,19 @@ __asm volatile ( " MSR CONTROL,r0 \n" /* CONTROL := r0 (clear CONTROL[2] FPCA bit) */ " ISB \n" /* ISB after MSR CONTROL (ARM AN321,Sect.4.16) */ #endif /* VFP available */ -#endif /* ARMv7-M and higher */ +#endif /* ARMv7-M or higher */ -#ifndef QK_ARM_CM_USE_NMI /* if use SVC... */ - " SVC #0 \n" /* trigger SVC */ -#else /* use NMI */ +#ifdef QK_USE_IRQ_NUM /* if use IRQ... */ + " LDR r0,=" STRINGIFY(NVIC_PEND + (QK_USE_IRQ_NUM / 32)) "\n" + " MOVS r1,#1 \n" + /* NOTE: the following IRQ bit calculation should be done simply as + * (QK_USE_IRQ_NUM % 32), but the IAR assembler does not accept it. + * As a workaround the modulo (%) operation is replaced with the following: + */ + " LSLS r1,r1,#" STRINGIFY(QK_USE_IRQ_NUM - (QK_USE_IRQ_NUM/32)*32) "\n" + " STR r1,[r0] \n" /* pend the IRQ */ + " B . \n" /* wait for preemption by the IRQ */ +#else /* use the NMI */ " LDR r0,=" STRINGIFY(NVIC_ICSR) "\n" /* Interrupt Control and State */ " MOVS r1,#1 \n" " LSLS r1,r1,#31 \n" /* r1 := (1 << 31) (NMI bit) */ @@ -228,8 +239,8 @@ __asm volatile ( * stack frame that must be at the top of the stack. */ __stackless -#ifndef QK_ARM_CM_USE_NMI /* if use SVC... */ -void SVC_Handler(void) +#ifdef QK_USE_IRQ_HANDLER /* if use IRQ... */ +void QK_USE_IRQ_HANDLER(void) #else /* use NMI */ void NMI_Handler(void) #endif /* use NMI */ diff --git a/ports/arm-cm/qk/iar/qk_port.hpp b/ports/arm-cm/qk/iar/qk_port.hpp index 1e6754e8c..c373b6dbe 100644 --- a/ports/arm-cm/qk/iar/qk_port.hpp +++ b/ports/arm-cm/qk/iar/qk_port.hpp @@ -21,7 +21,7 @@ // // //============================================================================ -//! @date Last updated on: 2022-04-10 +//! @date Last updated on: 2022-05-02 //! @version Last updated for: @ref qpcpp_7_0_0 //! //! @file @@ -55,8 +55,17 @@ #define QK_ARM_ERRATUM_838869() __DSB() #endif -// Use NMI ARM Cortex-M exception to return to thread mode (default SVC) -//#define QK_ARM_CM_USE_NMI 1 +// Use a given ARM Cortex-M IRQ to return to thread mode (default NMI) +// +// NOTE: +// If you need the NMI for other purposes, you can define the macros +// QK_USE_IRQ_NUM and QK_USE_IRQ_HANDLER to use thus specified IRQ +// instead of the NMI (the IRQ should not be used for anything else). +// These two macros can be defined on the command line to the compiler +// and are actually needed only to compile the qk_port.cpp file. +// +//#define QK_USE_IRQ_NUM 25 +//#define QK_USE_IRQ_HANDLER CRYPTO_IRQHandler // initialization of the QK kernel #define QK_INIT() QK_init() diff --git a/ports/arm-cm/qutest/qf_port.hpp b/ports/arm-cm/qutest/qf_port.hpp index f1f1ccf4f..ca4b9f97d 100644 --- a/ports/arm-cm/qutest/qf_port.hpp +++ b/ports/arm-cm/qutest/qf_port.hpp @@ -1,6 +1,5 @@ //! @file //! @brief QF/C++ port for QUTEST Unit Test, ARM Cortex-M with GNU or Visual C++ -//! @ingroup qutest //! @cond //============================================================================ //! Last updated for version 6.9.1 diff --git a/ports/arm-cm/qxk/armclang/qxk_port.cpp b/ports/arm-cm/qxk/armclang/qxk_port.cpp index 6c8d8715f..7a18da7fd 100644 --- a/ports/arm-cm/qxk/armclang/qxk_port.cpp +++ b/ports/arm-cm/qxk/armclang/qxk_port.cpp @@ -23,7 +23,7 @@ * ============================================================================*/ /*! -* @date Last updated on: 2022-04-11 +* @date Last updated on: 2022-05-02 * @version Last updated for: @ref qpcpp_7_0_0 * * @file @@ -38,15 +38,17 @@ extern "C" { /* prototypes --------------------------------------------------------------*/ void PendSV_Handler(void); -#ifndef QXK_ARM_CM_USE_NMI - void SVC_Handler(void); -#else - void NMI_Handler(void); +#ifdef QXK_USE_IRQ_HANDLER /* if use IRQ... */ +void QXK_USE_IRQ_HANDLER(void); +#else /* use default (NMI) */ +void NMI_Handler(void); #endif #define SCnSCB_ICTR ((uint32_t volatile *)0xE000E004) #define SCB_SYSPRI ((uint32_t volatile *)0xE000ED14) -#define NVIC_IP ((uint32_t volatile *)0xE000E400) +#define NVIC_EN ((uint32_t volatile *)0xE000E100) +#define NVIC_IP ((uint8_t volatile *)0xE000E400) +#define NVIC_PEND 0xE000E200 #define NVIC_ICSR 0xE000ED04 /* helper macros to "stringify" values */ @@ -85,21 +87,22 @@ void QXK_init(void) { SCB_SYSPRI[3] |= (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U) | QF_BASEPRI; /* set all implemented IRQ priories to QF_BASEPRI... */ - uint32_t n = 8U + ((*SCnSCB_ICTR & 0x7U) << 3U); /*(# NVIC_PRIO regs)/4 */ - do { - --n; - NVIC_IP[n] = (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U) - | (QF_BASEPRI << 8U) | QF_BASEPRI; - } while (n != 0U); + uint8_t nprio = (8U + ((*SCnSCB_ICTR & 0x7U) << 3U))*4; + for (uint8_t n = 0U; n < nprio; ++n) { + NVIC_IP[n] = QF_BASEPRI; + } -#endif /* ARMv7-M and higher */ +#endif /* ARMv7-M or higher */ /* SCB_SYSPRI3: PendSV set to priority 0xFF (lowest) */ SCB_SYSPRI[3] |= (0xFFU << 16U); -#ifndef QXK_ARM_CM_USE_NMI - /* SCB_SYSPRI2: SVCall */ - SCB_SYSPRI[2] &= ~(0xFFU << 24U); /* prioiry 0 (highest) */ +#ifdef QXK_USE_IRQ_NUM + /* The QXK port is configured to use a given ARM Cortex-M IRQ # + * to return to thread mode (default is to use the NMI exception) + */ + NVIC_IP[QXK_USE_IRQ_NUM] = 0U; /* priority 0 (highest) */ + NVIC_EN[QXK_USE_IRQ_NUM / 32U] = (1U << (QXK_USE_IRQ_NUM % 32U)); #endif } @@ -536,9 +539,13 @@ __asm volatile ( #endif /* VFP available */ #endif /* ARMv7-M or higher */ -#ifndef QXK_ARM_CM_USE_NMI /* if use SVC... */ - " SVC #0 \n" /* trigger SVC */ -#else /* use NMI */ +#ifdef QXK_USE_IRQ_NUM /* if use IRQ... */ + " LDR r0,=" STRINGIFY(NVIC_PEND + (QXK_USE_IRQ_NUM / 32)) "\n" + " MOVS r1,#1 \n" + " LSLS r1,r1,#" STRINGIFY(QXK_USE_IRQ_NUM % 32) "\n" /* r1 := IRQ bit */ + " STR r1,[r0] \n" /* pend the IRQ */ + " B . \n" /* wait for preemption by the IRQ */ +#else /* use the NMI */ " LDR r0,=" STRINGIFY(NVIC_ICSR) "\n" /* Interrupt Control and State */ " MOVS r1,#1 \n" " LSLS r1,r1,#31 \n" /* r1 := (1 << 31) (NMI bit) */ @@ -555,8 +562,8 @@ __asm volatile ( * stack frame that must be at the top of the stack. */ __attribute__ ((naked)) -#ifndef QXK_ARM_CM_USE_NMI /* if use SVC... */ -void SVC_Handler(void) +#ifdef QXK_USE_IRQ_HANDLER /* if use IRQ... */ +void QXK_USE_IRQ_HANDLER(void) #else /* use NMI */ void NMI_Handler(void) #endif /* use NMI */ diff --git a/ports/arm-cm/qxk/armclang/qxk_port.hpp b/ports/arm-cm/qxk/armclang/qxk_port.hpp index bce51f6ce..e6fd6e913 100644 --- a/ports/arm-cm/qxk/armclang/qxk_port.hpp +++ b/ports/arm-cm/qxk/armclang/qxk_port.hpp @@ -21,7 +21,7 @@ // // //============================================================================ -//! @date Last updated on: 2022-04-10 +//! @date Last updated on: 2022-05-02 //! @version Last updated for: @ref qpcpp_7_0_0 //! //! @file @@ -56,7 +56,7 @@ static inline uint32_t QXK_get_IPSR(void) { QXK_ARM_ERRATUM_838869(); \ } while (false) -#if (__ARM_ARCH == 6) // Cortex-M0/M0+/M1 (v6-M, v6S-M)? +#if (__ARM_ARCH == 6) // ARMv6-M? #define QXK_ARM_ERRATUM_838869() ((void)0) #else // Cortex-M3/M4/M7 (v7-M) // The following macro implements the recommended workaround for the @@ -65,10 +65,19 @@ static inline uint32_t QXK_get_IPSR(void) { // #define QXK_ARM_ERRATUM_838869() \ __asm volatile ("dsb" ::: "memory") -#endif +#endif // ARMv6-M -// Use NMI ARM Cortex-M exception to return to thread mode (default SVC) -//#define QXK_ARM_CM_USE_NMI 1 +// Use a given ARM Cortex-M IRQ to return to thread mode (default NMI) +// +// NOTE: +// If you need the NMI for other purposes, you can define the macros +// QXK_USE_IRQ_NUM and QXK_USE_IRQ_HANDLER to use thus specified IRQ +// instead of the NMI (the IRQ should not be used for anything else). +// These two macros can be defined on the command line to the compiler +// and are actually needed only to compile the qxk_port.c file. +// +//#define QXK_USE_IRQ_NUM 25 +//#define QXK_USE_IRQ_HANDLER CRYPTO_IRQHandler // initialization of the QXK kernel #define QXK_INIT() QXK_init() diff --git a/ports/arm-cm/qxk/gnu/qxk_port.cpp b/ports/arm-cm/qxk/gnu/qxk_port.cpp index 3be3df62d..57dd97042 100644 --- a/ports/arm-cm/qxk/gnu/qxk_port.cpp +++ b/ports/arm-cm/qxk/gnu/qxk_port.cpp @@ -23,7 +23,7 @@ * ============================================================================*/ /*! -* @date Last updated on: 2022-04-11 +* @date Last updated on: 2022-05-02 * @version Last updated for: @ref qpcpp_7_0_0 * * @file @@ -38,15 +38,17 @@ extern "C" { /* prototypes --------------------------------------------------------------*/ void PendSV_Handler(void); -#ifndef QXK_ARM_CM_USE_NMI - void SVC_Handler(void); -#else - void NMI_Handler(void); +#ifdef QXK_USE_IRQ_HANDLER /* if use IRQ... */ +void QXK_USE_IRQ_HANDLER(void); +#else /* use default (NMI) */ +void NMI_Handler(void); #endif #define SCnSCB_ICTR ((uint32_t volatile *)0xE000E004) #define SCB_SYSPRI ((uint32_t volatile *)0xE000ED14) -#define NVIC_IP ((uint32_t volatile *)0xE000E400) +#define NVIC_EN ((uint32_t volatile *)0xE000E100) +#define NVIC_IP ((uint8_t volatile *)0xE000E400) +#define NVIC_PEND 0xE000E200 #define NVIC_ICSR 0xE000ED04 /* helper macros to "stringify" values */ @@ -85,21 +87,22 @@ void QXK_init(void) { SCB_SYSPRI[3] |= (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U) | QF_BASEPRI; /* set all implemented IRQ priories to QF_BASEPRI... */ - uint32_t n = 8U + ((*SCnSCB_ICTR & 0x7U) << 3U); /*(# NVIC_PRIO regs)/4 */ - do { - --n; - NVIC_IP[n] = (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U) - | (QF_BASEPRI << 8U) | QF_BASEPRI; - } while (n != 0U); + uint8_t nprio = (8U + ((*SCnSCB_ICTR & 0x7U) << 3U))*4; + for (uint8_t n = 0U; n < nprio; ++n) { + NVIC_IP[n] = QF_BASEPRI; + } -#endif /* ARMv7-M and higher */ +#endif /* ARMv7-M or higher */ /* SCB_SYSPRI3: PendSV set to priority 0xFF (lowest) */ SCB_SYSPRI[3] |= (0xFFU << 16U); -#ifndef QXK_ARM_CM_USE_NMI - /* SCB_SYSPRI2: SVCall */ - SCB_SYSPRI[2] &= ~(0xFFU << 24U); /* prioiry 0 (highest) */ +#ifdef QXK_USE_IRQ_NUM + /* The QXK port is configured to use a given ARM Cortex-M IRQ # + * to return to thread mode (default is to use the NMI exception) + */ + NVIC_IP[QXK_USE_IRQ_NUM] = 0U; /* priority 0 (highest) */ + NVIC_EN[QXK_USE_IRQ_NUM / 32U] = (1U << (QXK_USE_IRQ_NUM % 32U)); #endif } @@ -541,9 +544,13 @@ __asm volatile ( #endif /* VFP available */ #endif /* ARMv7-M or higher */ -#ifndef QXK_ARM_CM_USE_NMI /* if use SVC... */ - " SVC #0 \n" /* trigger SVC */ -#else /* use NMI */ +#ifdef QXK_USE_IRQ_NUM /* if use IRQ... */ + " LDR r0,=" STRINGIFY(NVIC_PEND + (QXK_USE_IRQ_NUM / 32)) "\n" + " MOV r1,#1 \n" + " LSL r1,r1,#" STRINGIFY(QXK_USE_IRQ_NUM % 32) "\n" /* r1 := IRQ bit */ + " STR r1,[r0] \n" /* pend the IRQ */ + " B . \n" /* wait for preemption by the IRQ */ +#else /* use the NMI */ " LDR r0,=" STRINGIFY(NVIC_ICSR) "\n" /* Interrupt Control and State */ " MOV r1,#1 \n" " LSL r1,r1,#31 \n" /* r1 := (1 << 31) (NMI bit) */ @@ -560,8 +567,8 @@ __asm volatile ( * stack frame that must be at the top of the stack. */ __attribute__ ((naked, optimize("-fno-stack-protector"))) -#ifndef QXK_ARM_CM_USE_NMI /* if use SVC... */ -void SVC_Handler(void) +#ifdef QXK_USE_IRQ_HANDLER /* if use IRQ... */ +void QXK_USE_IRQ_HANDLER(void) #else /* use NMI */ void NMI_Handler(void) #endif /* use NMI */ diff --git a/ports/arm-cm/qxk/gnu/qxk_port.hpp b/ports/arm-cm/qxk/gnu/qxk_port.hpp index 6ab5e937f..e5c4c24c0 100644 --- a/ports/arm-cm/qxk/gnu/qxk_port.hpp +++ b/ports/arm-cm/qxk/gnu/qxk_port.hpp @@ -21,7 +21,7 @@ // // //============================================================================ -//! @date Last updated on: 2022-04-10 +//! @date Last updated on: 2022-05-02 //! @version Last updated for: @ref qpcpp_7_0_0 //! //! @file @@ -57,7 +57,7 @@ static inline uint32_t QXK_get_IPSR(void) { QXK_ARM_ERRATUM_838869(); \ } while (false) -#if (__ARM_ARCH == 6) // Cortex-M0/M0+/M1 (v6-M, v6S-M)? +#if (__ARM_ARCH == 6) // ARMv6-M? #define QXK_ARM_ERRATUM_838869() ((void)0) #else // Cortex-M3/M4/M7 (v7-M) // The following macro implements the recommended workaround for the @@ -66,10 +66,19 @@ static inline uint32_t QXK_get_IPSR(void) { // #define QXK_ARM_ERRATUM_838869() \ __asm volatile ("dsb" ::: "memory") -#endif +#endif // ARMv6-M -// Use NMI ARM Cortex-M exception to return to thread mode (default SVC) -//#define QXK_ARM_CM_USE_NMI 1 +// Use a given ARM Cortex-M IRQ to return to thread mode (default NMI) +// +// NOTE: +// If you need the NMI for other purposes, you can define the macros +// QXK_USE_IRQ_NUM and QXK_USE_IRQ_HANDLER to use thus specified IRQ +// instead of the NMI (the IRQ should not be used for anything else). +// These two macros can be defined on the command line to the compiler +// and are actually needed only to compile the qxk_port.c file. +// +//#define QXK_USE_IRQ_NUM 25 +//#define QXK_USE_IRQ_HANDLER CRYPTO_IRQHandler // initialization of the QXK kernel #define QXK_INIT() QXK_init() diff --git a/ports/arm-cm/qxk/iar/qxk_port.cpp b/ports/arm-cm/qxk/iar/qxk_port.cpp index f545d1700..b159fd515 100644 --- a/ports/arm-cm/qxk/iar/qxk_port.cpp +++ b/ports/arm-cm/qxk/iar/qxk_port.cpp @@ -23,7 +23,7 @@ * ============================================================================*/ /*! -* @date Last updated on: 2022-04-11 +* @date Last updated on: 2022-05-02 * @version Last updated for: @ref qpcpp_7_0_0 * * @file @@ -38,15 +38,17 @@ extern "C" { /* prototypes --------------------------------------------------------------*/ void PendSV_Handler(void); -#ifndef QXK_ARM_CM_USE_NMI - void SVC_Handler(void); -#else - void NMI_Handler(void); +#ifdef QXK_USE_IRQ_HANDLER /* if use IRQ... */ +void QXK_USE_IRQ_HANDLER(void); +#else /* use default (NMI) */ +void NMI_Handler(void); #endif #define SCnSCB_ICTR ((uint32_t volatile *)0xE000E004) #define SCB_SYSPRI ((uint32_t volatile *)0xE000ED14) -#define NVIC_IP ((uint32_t volatile *)0xE000E400) +#define NVIC_EN ((uint32_t volatile *)0xE000E100) +#define NVIC_IP ((uint8_t volatile *)0xE000E400) +#define NVIC_PEND 0xE000E200 #define NVIC_ICSR 0xE000ED04 /* helper macros to "stringify" values */ @@ -85,21 +87,22 @@ void QXK_init(void) { SCB_SYSPRI[3] |= (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U) | QF_BASEPRI; /* set all implemented IRQ priories to QF_BASEPRI... */ - uint32_t n = 8U + ((*SCnSCB_ICTR & 0x7U) << 3U); /*(# NVIC_PRIO regs)/4 */ - do { - --n; - NVIC_IP[n] = (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U) - | (QF_BASEPRI << 8U) | QF_BASEPRI; - } while (n != 0U); + uint8_t nprio = (8U + ((*SCnSCB_ICTR & 0x7U) << 3U))*4; + for (uint8_t n = 0U; n < nprio; ++n) { + NVIC_IP[n] = QF_BASEPRI; + } -#endif /* ARMv7-M and higher */ +#endif /* ARMv7-M or higher */ /* SCB_SYSPRI3: PendSV set to priority 0xFF (lowest) */ SCB_SYSPRI[3] |= (0xFFU << 16U); -#ifndef QXK_ARM_CM_USE_NMI - /* SCB_SYSPRI2: SVCall */ - SCB_SYSPRI[2] &= ~(0xFFU << 24U); /* prioiry 0 (highest) */ +#ifdef QXK_USE_IRQ_NUM + /* The QXK port is configured to use a given ARM Cortex-M IRQ # + * to return to thread mode (default is to use the NMI exception) + */ + NVIC_IP[QXK_USE_IRQ_NUM] = 0U; /* priority 0 (highest) */ + NVIC_EN[QXK_USE_IRQ_NUM / 32U] = (1U << (QXK_USE_IRQ_NUM % 32U)); #endif } @@ -524,7 +527,7 @@ __asm ( #if (__ARM_ARCH == 6) /* if ARMv6-M... */ " CPSIE i \n" /* enable interrupts (clear PRIMASK) */ -#else /* ARMv7-M and higher */ +#else /* ARMv7-M or higher */ " MOVS r0,#0 \n" " MSR BASEPRI,r0 \n" /* enable interrupts (clear BASEPRI) */ #if (__ARM_FP != 0) /* if VFP available... */ @@ -536,9 +539,17 @@ __asm ( #endif /* VFP available */ #endif /* ARMv7-M or higher */ -#ifndef QXK_ARM_CM_USE_NMI /* if use SVC... */ - " SVC #0 \n" /* trigger SVC */ -#else /* use NMI */ +#ifdef QXK_USE_IRQ_NUM /* if use IRQ... */ + " LDR r0,=" STRINGIFY(NVIC_PEND + (QXK_USE_IRQ_NUM / 32)) "\n" + " MOVS r1,#1 \n" + /* NOTE: the following IRQ bit calculation should be done simply as + * (QK_USE_IRQ_NUM % 32), but the IAR assembler does not accept it. + * As a workaround the modulo (%) operation is replaced with the following: + */ + " LSLS r1,r1,#" STRINGIFY(QXK_USE_IRQ_NUM - (QXK_USE_IRQ_NUM/32)*32) "\n" + " STR r1,[r0] \n" /* pend the IRQ */ + " B . \n" /* wait for preemption by the IRQ */ +#else /* use the NMI */ " LDR r0,=" STRINGIFY(NVIC_ICSR) "\n" /* Interrupt Control and State */ " MOVS r1,#1 \n" " LSLS r1,r1,#31 \n" /* r1 := (1 << 31) (NMI bit) */ @@ -555,8 +566,8 @@ __asm ( * stack frame that must be at the top of the stack. */ __stackless -#ifndef QXK_ARM_CM_USE_NMI /* if use SVC... */ -void SVC_Handler(void) +#ifdef QXK_USE_IRQ_HANDLER /* if use IRQ... */ +void QXK_USE_IRQ_HANDLER(void) #else /* use NMI */ void NMI_Handler(void) #endif /* use NMI */ diff --git a/ports/arm-cm/qxk/iar/qxk_port.hpp b/ports/arm-cm/qxk/iar/qxk_port.hpp index 26cf02a35..fc23c9fa4 100644 --- a/ports/arm-cm/qxk/iar/qxk_port.hpp +++ b/ports/arm-cm/qxk/iar/qxk_port.hpp @@ -21,7 +21,7 @@ // // //============================================================================ -//! @date Last updated on: 2022-04-10 +//! @date Last updated on: 2022-05-02 //! @version Last updated for: @ref qpcpp_7_0_0 //! //! @file @@ -49,7 +49,7 @@ QXK_ARM_ERRATUM_838869(); \ } while (false) -#if (__ARM_ARCH == 6) // Cortex-M0/M0+/M1 (v6-M, v6S-M)? +#if (__ARM_ARCH == 6) // ARMv6-M? #define QXK_ARM_ERRATUM_838869() ((void)0) #else // Cortex-M3/M4/M7 (v7-M) // The following macro implements the recommended workaround for the @@ -57,10 +57,19 @@ // (memory barrier) instruction needs to be added before exiting an ISR. // #define QXK_ARM_ERRATUM_838869() __DSB() -#endif +#endif // ARMv6-M -// Use NMI ARM Cortex-M exception to return to thread mode (default SVC) -//#define QXK_ARM_CM_USE_NMI 1 +// Use a given ARM Cortex-M IRQ to return to thread mode (default NMI) +// +// NOTE: +// If you need the NMI for other purposes, you can define the macros +// QXK_USE_IRQ_NUM and QXK_USE_IRQ_HANDLER to use thus specified IRQ +// instead of the NMI (the IRQ should not be used for anything else). +// These two macros can be defined on the command line to the compiler +// and are actually needed only to compile the qxk_port.c file. +// +//#define QXK_USE_IRQ_NUM 25 +//#define QXK_USE_IRQ_HANDLER CRYPTO_IRQHandler // initialization of the QXK kernel #define QXK_INIT() QXK_init() diff --git a/ports/freertos/qf_port.hpp b/ports/freertos/qf_port.hpp index e371bc26c..2fd1d6b79 100644 --- a/ports/freertos/qf_port.hpp +++ b/ports/freertos/qf_port.hpp @@ -1,6 +1,5 @@ //! @file //! @brief QF/C++ port to FreeRTOS 10.x, ARM Cortex-M, IAR-ARM toolset -//! @ingroup ports //! @cond //============================================================================ //! Last updated for version 6.9.1 diff --git a/ports/lint-plus/qep_port.hpp b/ports/lint-plus/qep_port.hpp index 9df824dff..f0301301f 100644 --- a/ports/lint-plus/qep_port.hpp +++ b/ports/lint-plus/qep_port.hpp @@ -26,7 +26,6 @@ //! @version Last updated for: @ref qpcpp_7_0_0 //! //! @file -//! @ingroup ports //! @brief QEP/C++ port, generic C++11 compiler //! @description //! This is an example QP/C++ port with the documentation for the main diff --git a/ports/lint-plus/qk/qf_port.hpp b/ports/lint-plus/qk/qf_port.hpp index 26aa6f1fd..94ea8dd4f 100644 --- a/ports/lint-plus/qk/qf_port.hpp +++ b/ports/lint-plus/qk/qf_port.hpp @@ -1,6 +1,5 @@ //! @file //! @brief QF/C++ port for QK kernel, Generic C++ compiler -//! @ingroup qk //! @cond //============================================================================ //! Last updated for version 6.8.2 diff --git a/ports/lint-plus/qs_port.hpp b/ports/lint-plus/qs_port.hpp index aab4a241f..6afada963 100644 --- a/ports/lint-plus/qs_port.hpp +++ b/ports/lint-plus/qs_port.hpp @@ -26,7 +26,6 @@ //! @version Last updated for: @ref qpcpp_7_0_0 //! //! @file -//! @ingroup qs //! @brief QS/C++ port to a 32-bit CPU, generic C++ compiler //! @description //! This is an example QP/C++ port with the documentation for the main diff --git a/ports/lint-plus/qv/qf_port.hpp b/ports/lint-plus/qv/qf_port.hpp index d9967b12c..bb868e5bb 100644 --- a/ports/lint-plus/qv/qf_port.hpp +++ b/ports/lint-plus/qv/qf_port.hpp @@ -1,6 +1,5 @@ //! @file //! @brief QF/C++ port for QV kernel, Generic C++ compiler -//! @ingroup qk //! @cond //============================================================================ //! Last updated for version 6.8.2 diff --git a/ports/lint-plus/qxk/qf_port.hpp b/ports/lint-plus/qxk/qf_port.hpp index a535bb653..680006075 100644 --- a/ports/lint-plus/qxk/qf_port.hpp +++ b/ports/lint-plus/qxk/qf_port.hpp @@ -26,7 +26,6 @@ //! @version Last updated for: @ref qpcpp_7_0_0 //! //! @file -//! @ingroup qf //! @brief QF/C++ port example, Generic C++11 compiler //! @description //! This is an example QP/C++ port with the documentation for the main diff --git a/ports/lint-plus/qxk/qxk_port.hpp b/ports/lint-plus/qxk/qxk_port.hpp index 7d3d84ee7..8e4697305 100644 --- a/ports/lint-plus/qxk/qxk_port.hpp +++ b/ports/lint-plus/qxk/qxk_port.hpp @@ -26,7 +26,6 @@ //! @version Last updated for: @ref qpcpp_7_0_0 //! //! @file -//! @ingroup qxk //! @brief QXK/C++ port example, Generic C++ compiler //! @description //! This is an example QP/C++ port with the documentation for the main diff --git a/ports/msp430/README.md b/ports/msp430/README.md new file mode 100644 index 000000000..dabe98156 --- /dev/null +++ b/ports/msp430/README.md @@ -0,0 +1,5 @@ +# MSP430 Port + +Documentation for this port is available in the QP/C Manual at: + +- https://www.state-machine.com/qpcpp/msp430.html diff --git a/ports/msp430/README.txt b/ports/msp430/README.txt deleted file mode 100644 index f7a63f1e0..000000000 --- a/ports/msp430/README.txt +++ /dev/null @@ -1,12 +0,0 @@ -About The QP-MSP430 Port -======================= -This directory contains the QP/C++ ports to the MSP430 processor family, -for both "classic" MSP430 and "extended" MSP430X cores. The following -ports are provided: - -qpcpp/ - +-ports/ - | +-msp430/ - | | +-qk/ - port to the preemptive QK kernel - | | +-qv/ - port to the cooperative QV kernel - | | +-qutest/ - port to QUTest unit testing harness diff --git a/ports/pic32/qk/xc32/qf_port.hpp b/ports/pic32/qk/xc32/qf_port.hpp index 5c2a12942..cbc35c368 100644 --- a/ports/pic32/qk/xc32/qf_port.hpp +++ b/ports/pic32/qk/xc32/qf_port.hpp @@ -1,6 +1,5 @@ //! @file //! @brief QF/C++ port to PIC32, preemptive QK kernel, XC32 toolchain -//! @ingroup qep //! @cond //============================================================================ //! Last updated for version 6.8.0 diff --git a/ports/pic32/qk/xc32/qk_port.cpp b/ports/pic32/qk/xc32/qk_port.cpp index e55363885..1d38468e2 100644 --- a/ports/pic32/qk/xc32/qk_port.cpp +++ b/ports/pic32/qk/xc32/qk_port.cpp @@ -1,6 +1,5 @@ //! @file //! @brief QK/C++ port to PIC32, preemptive QK kernel, XC32 toolchain -//! @ingroup qep //! @cond //============================================================================ //! Last updated for version 6.6.0 diff --git a/ports/pic32/qk/xc32/qk_port.hpp b/ports/pic32/qk/xc32/qk_port.hpp index 85eb67082..bc5b3ca44 100644 --- a/ports/pic32/qk/xc32/qk_port.hpp +++ b/ports/pic32/qk/xc32/qk_port.hpp @@ -1,6 +1,5 @@ //! @file //! @brief QK/C++ port to PIC32, preemptive QK kernel, XC32 toolchain -//! @ingroup qep //! @cond //============================================================================ //! Last updated for version 6.6.0 diff --git a/ports/pic32/qk/xc32/qs_port.hpp b/ports/pic32/qk/xc32/qs_port.hpp index 1368edae0..b67b81462 100644 --- a/ports/pic32/qk/xc32/qs_port.hpp +++ b/ports/pic32/qk/xc32/qs_port.hpp @@ -1,6 +1,5 @@ //! @file //! @brief QS/C++ port to 32-bit CPU, generic C++ compiler -//! @ingroup qep //! @cond //============================================================================ //! Last updated for version 6.6.0 diff --git a/ports/pic32/qutest/xc32/qf_port.hpp b/ports/pic32/qutest/xc32/qf_port.hpp index cce47e2f4..dd7b82c48 100644 --- a/ports/pic32/qutest/xc32/qf_port.hpp +++ b/ports/pic32/qutest/xc32/qf_port.hpp @@ -1,6 +1,5 @@ //! @file //! @brief QF/C++ port for QUTEST Unit Test, PIC32 -//! @ingroup qutest //! @cond //============================================================================ //! Last updated for version 6.9.1 diff --git a/ports/pic32/qv/xc32/qf_port.hpp b/ports/pic32/qv/xc32/qf_port.hpp index 058a35dfa..3114b4126 100644 --- a/ports/pic32/qv/xc32/qf_port.hpp +++ b/ports/pic32/qv/xc32/qf_port.hpp @@ -1,6 +1,5 @@ //! @file //! @brief QF/C++ port to PIC32, cooperative QV kernel, XC32 toolchain -//! @ingroup qep //! @cond //============================================================================ //! Last updated for version 6.6.0 diff --git a/ports/pic32/qv/xc32/qs_port.hpp b/ports/pic32/qv/xc32/qs_port.hpp index 1368edae0..b67b81462 100644 --- a/ports/pic32/qv/xc32/qs_port.hpp +++ b/ports/pic32/qv/xc32/qs_port.hpp @@ -1,6 +1,5 @@ //! @file //! @brief QS/C++ port to 32-bit CPU, generic C++ compiler -//! @ingroup qep //! @cond //============================================================================ //! Last updated for version 6.6.0 diff --git a/ports/pic32/qv/xc32/qv_port.hpp b/ports/pic32/qv/xc32/qv_port.hpp index 42ba1d6dd..22081c9b1 100644 --- a/ports/pic32/qv/xc32/qv_port.hpp +++ b/ports/pic32/qv/xc32/qv_port.hpp @@ -1,6 +1,5 @@ //! @file //! @brief QV/C++ port to PIC32, cooperative QV kernel, XC32 toolchain -//! @ingroup qep //! @cond //============================================================================ //! Last updated for version 6.6.0 diff --git a/ports/posix-qutest/README.md b/ports/posix-qutest/README.md new file mode 100644 index 000000000..6e988cf3f --- /dev/null +++ b/ports/posix-qutest/README.md @@ -0,0 +1,5 @@ +# POSIX port for the QUTest unit testing harness + +Documentation for this port is available in the QP/C Manual at: + +- https://www.state-machine.com/qpcpp/posix-qutest.html diff --git a/ports/posix-qutest/README.txt b/ports/posix-qutest/README.txt deleted file mode 100644 index 947712bdf..000000000 --- a/ports/posix-qutest/README.txt +++ /dev/null @@ -1,16 +0,0 @@ -This QP port is for the QUTest unit testing harness. - -If you are interested in using a POSIX target as embedded platform, -consider the following QP ports: - -- posix for multithreaded (P-threads) QP applications -- posix-qv single-threaded QP port to POSIX - - -NOTE: -Building of the QP libraries on the POSIX targets or hosts -is no longer necessary. The example projects for POSIX are -built directly from QP source files and don't need a library. - -Quantum Leaps -04/05/2018 \ No newline at end of file diff --git a/ports/posix-qutest/qutest_port.cpp b/ports/posix-qutest/qutest_port.cpp index 23142cbb2..2f4c1e3a6 100644 --- a/ports/posix-qutest/qutest_port.cpp +++ b/ports/posix-qutest/qutest_port.cpp @@ -1,6 +1,5 @@ //! @file //! @brief QUTEST port for POSIX -//! @ingroup ports //! @cond //============================================================================ //! Last updated for: @ref qpcpp_7_0_0 diff --git a/ports/posix-qutest/safe_std.h b/ports/posix-qutest/safe_std.h index 2cb539409..989212c12 100644 --- a/ports/posix-qutest/safe_std.h +++ b/ports/posix-qutest/safe_std.h @@ -1,7 +1,6 @@ /** * @file * @brief "safe" and facilities -* @ingroup qpspy * @cond ****************************************************************************** * Last updated for version 6.9.0 diff --git a/ports/posix-qv/README.md b/ports/posix-qv/README.md new file mode 100644 index 000000000..5670bcb9d --- /dev/null +++ b/ports/posix-qv/README.md @@ -0,0 +1,5 @@ +# POSIX (single-threaded) + +Documentation for this port is available in the QP/C Manual at: + +- https://www.state-machine.com/qpcpp/posix-qv.html diff --git a/ports/posix-qv/README.txt b/ports/posix-qv/README.txt deleted file mode 100644 index a12a160b5..000000000 --- a/ports/posix-qv/README.txt +++ /dev/null @@ -1,22 +0,0 @@ -This QP port to POSIX with a single thread executing all active -objects (like the cooperative QV kernel). - -If you are interested in using a POSIX target for deployment, -consider the following QP port: - -- posix multithreaded (P-threads) QP port to POSIX - - -If you are interested in testing your embedded QP applications -on a POSIX host, consider the following QP port: - -- posix-qutest for running QUTest unit testing harness - - -NOTE: -Building of the QP libraries on the POSIX targets or hosts -is no longer necessary. The example projects for POSIX are -built directly from QP source files and don't need a library. - -Quantum Leaps -04/05/2018 \ No newline at end of file diff --git a/ports/posix-qv/safe_std.h b/ports/posix-qv/safe_std.h index 2cb539409..989212c12 100644 --- a/ports/posix-qv/safe_std.h +++ b/ports/posix-qv/safe_std.h @@ -1,7 +1,6 @@ /** * @file * @brief "safe" and facilities -* @ingroup qpspy * @cond ****************************************************************************** * Last updated for version 6.9.0 diff --git a/ports/posix/README.md b/ports/posix/README.md new file mode 100644 index 000000000..f508258a6 --- /dev/null +++ b/ports/posix/README.md @@ -0,0 +1,5 @@ +# POSIX (multi-threaded with p-threads) + +Documentation for this port is available in the QP/C Manual at: + +- https://www.state-machine.com/qpcpp/posix.html diff --git a/ports/posix/README.txt b/ports/posix/README.txt deleted file mode 100644 index 6cb38a3ec..000000000 --- a/ports/posix/README.txt +++ /dev/null @@ -1,17 +0,0 @@ -This QP port to POSIX with P-threads is intended for building -multithreaded QP applications running on embedded POSIX targets. - -If you are interested in using a POSIX host for testing your -embedded QP applications, consider the following QP ports: - -- posix-qutest for running QUTest unit testing harness -- posix-qv single-threaded QP port to POSIX - - -NOTE: -Building of the QP libraries on the POSIX targets or hosts -is no longer necessary. The example projects for POSIX are -built directly from QP source files and don't need a library. - -Quantum Leaps -04/05/2018 \ No newline at end of file diff --git a/ports/posix/safe_std.h b/ports/posix/safe_std.h index 2cb539409..989212c12 100644 --- a/ports/posix/safe_std.h +++ b/ports/posix/safe_std.h @@ -1,7 +1,6 @@ /** * @file * @brief "safe" and facilities -* @ingroup qpspy * @cond ****************************************************************************** * Last updated for version 6.9.0 diff --git a/ports/threadx/README.md b/ports/threadx/README.md new file mode 100644 index 000000000..e02884f46 --- /dev/null +++ b/ports/threadx/README.md @@ -0,0 +1,5 @@ +# ThreadX Port + +Documentation for this port is available in the QP/C Manual at: + +- https://www.state-machine.com/qpcpp/threadx.html diff --git a/ports/threadx/README.txt b/ports/threadx/README.txt deleted file mode 100644 index 0c5bf5dcf..000000000 --- a/ports/threadx/README.txt +++ /dev/null @@ -1,11 +0,0 @@ -This directory contains a generic platform-independent QP/C port -to ThreadX. - -Typically, you don't need to change any of the files in this directory -to run QP-ThreadX port on any CPU/Compiler to which ThreadX has been -ported, because all the CPU and compiler specifics are handled by the -ThreadX RTOS. - -Quantun Leaps -state-machine.com -info@state-machine.com \ No newline at end of file diff --git a/ports/uc-os2/qf_port.cpp b/ports/uc-os2/qf_port.cpp index 2192a9333..8a75b40c7 100644 --- a/ports/uc-os2/qf_port.cpp +++ b/ports/uc-os2/qf_port.cpp @@ -76,7 +76,7 @@ void QActive::start(std::uint_fast8_t const prio, void const * const par) { // task name to be passed to OSTaskCreateExt() - void *task_name = static_cast(m_eQueue); + void * const task_name = static_cast(m_eQueue); // create uC-OS2 queue and make sure it was created correctly m_eQueue = OSQCreate((void **)qSto, qLen); @@ -89,7 +89,7 @@ void QActive::start(std::uint_fast8_t const prio, QS_FLUSH(); // flush the trace buffer to the host // map from QP to uC-OS2 priority - INT8U p_ucos = static_cast(QF_MAX_ACTIVE - m_prio); + INT8U const p_ucos = static_cast(QF_MAX_ACTIVE - m_prio); // create AO's task... // @@ -98,7 +98,7 @@ void QActive::start(std::uint_fast8_t const prio, // stack memory. This is correct only for CPUs with downward-growing // stack, but must be changed for CPUs with upward-growing stack // - INT8U err = OSTaskCreateExt( + INT8U const err = OSTaskCreateExt( &task_function, // the task function this, // the 'pdata' parameter #if OS_STK_GROWTH @@ -165,15 +165,14 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, void const * const sender) noexcept #endif { - bool status; - std::uint_fast16_t nFree; QF_CRIT_STAT_ QF_CRIT_E_(); - nFree = static_cast( + std::uint_fast16_t const nFree = static_cast( reinterpret_cast(m_eQueue)->OSQSize - reinterpret_cast(m_eQueue)->OSNMsgs); + bool status; if (margin == QF_NO_MARGIN) { if (nFree > 0U) { status = true; // can post @@ -258,12 +257,11 @@ void QActive::postLIFO(QEvt const * const e) noexcept { //............................................................................ QEvt const *QActive::get_(void) noexcept { INT8U err; - QS_CRIT_STAT_ - QEvt const *e = static_cast( OSQPend(static_cast(m_eQueue), 0U, &err)); Q_ASSERT_ID(910, err == OS_ERR_NONE); + QS_CRIT_STAT_ QS_BEGIN_PRE_(QS_QF_ACTIVE_GET, m_prio) QS_TIME_PRE_(); // timestamp QS_SIG_PRE_(e->sig); // the signal of this event diff --git a/ports/vxworks/qf_port.cpp b/ports/vxworks/qf_port.cpp index 8d46baa56..86929b384 100644 --- a/ports/vxworks/qf_port.cpp +++ b/ports/vxworks/qf_port.cpp @@ -1,6 +1,5 @@ //! @file //! @brief QF/C++ port to VxWorks API -//! @ingroup ports //! @cond //============================================================================ //! Last updated for version 6.8.0 diff --git a/ports/vxworks/qf_port.hpp b/ports/vxworks/qf_port.hpp index 4876e8083..9412518a6 100644 --- a/ports/vxworks/qf_port.hpp +++ b/ports/vxworks/qf_port.hpp @@ -1,6 +1,5 @@ //! @file //! @brief QF/C++ port to VxWorks API -//! @ingroup ports //! @cond //============================================================================ //! Last updated for version 6.6.0 diff --git a/ports/win32-quit/qf_port.h b/ports/win32-quit/qf_port.h index a2f9b780f..cf852b039 100644 --- a/ports/win32-quit/qf_port.h +++ b/ports/win32-quit/qf_port.h @@ -1,7 +1,6 @@ /** * @file * @brief QF/C "port" for QUIT unit internal test, Win32 with GNU or VisualC++ -* @ingroup ports * @cond ****************************************************************************** * Last updated for version 6.9.2 diff --git a/ports/win32-quit/qf_port.hpp b/ports/win32-quit/qf_port.hpp index 9932cda28..9eeb6cf9f 100644 --- a/ports/win32-quit/qf_port.hpp +++ b/ports/win32-quit/qf_port.hpp @@ -1,6 +1,5 @@ //! @file //! @brief QF/C++ port for QUIT unit internal test, Win32 with GNU/VisualC++ -//! @ingroup ports //! @cond //============================================================================ //! Last updated for version 6.9.2 diff --git a/ports/win32-quit/qs_port.hpp b/ports/win32-quit/qs_port.hpp index 114ae63aa..31828a8e7 100644 --- a/ports/win32-quit/qs_port.hpp +++ b/ports/win32-quit/qs_port.hpp @@ -1,6 +1,5 @@ //! @file //! @brief QS/C++ port to QUTEST, Win32 API -//! @ingroup qf //! @cond //============================================================================ //! Last updated for version 6.6.0 diff --git a/ports/win32-qutest/README.md b/ports/win32-qutest/README.md new file mode 100644 index 000000000..ae207519b --- /dev/null +++ b/ports/win32-qutest/README.md @@ -0,0 +1,5 @@ +# Win32-API (Windows port for QUTest Unit Testing Harness) + +Documentation for this port is available in the QP/C Manual at: + +- https://www.state-machine.com/qpcpp/win32-qutest.html diff --git a/ports/win32-qutest/qf_port.hpp b/ports/win32-qutest/qf_port.hpp index a560d38f3..f7bdb9dda 100644 --- a/ports/win32-qutest/qf_port.hpp +++ b/ports/win32-qutest/qf_port.hpp @@ -1,6 +1,5 @@ //! @file //! @brief QF/C++ port for QUTEST Unit Test, Win32 with GNU or Visual C++ -//! @ingroup qutest //! @cond //============================================================================ //! Last updated for version 6.9.1 diff --git a/ports/win32-qutest/qs_port.hpp b/ports/win32-qutest/qs_port.hpp index 114ae63aa..31828a8e7 100644 --- a/ports/win32-qutest/qs_port.hpp +++ b/ports/win32-qutest/qs_port.hpp @@ -1,6 +1,5 @@ //! @file //! @brief QS/C++ port to QUTEST, Win32 API -//! @ingroup qf //! @cond //============================================================================ //! Last updated for version 6.6.0 diff --git a/ports/win32-qutest/qutest_port.cpp b/ports/win32-qutest/qutest_port.cpp index 0e071ede0..45083ea36 100644 --- a/ports/win32-qutest/qutest_port.cpp +++ b/ports/win32-qutest/qutest_port.cpp @@ -1,6 +1,5 @@ //! @file //! @brief QUTEST port for Win32 -//! @ingroup ports //! @cond //============================================================================ //! Last updated for version 6.9.3 diff --git a/ports/win32-qutest/safe_std.h b/ports/win32-qutest/safe_std.h index 2cb539409..989212c12 100644 --- a/ports/win32-qutest/safe_std.h +++ b/ports/win32-qutest/safe_std.h @@ -1,7 +1,6 @@ /** * @file * @brief "safe" and facilities -* @ingroup qpspy * @cond ****************************************************************************** * Last updated for version 6.9.0 diff --git a/ports/win32-qv/README.md b/ports/win32-qv/README.md new file mode 100644 index 000000000..adc51548a --- /dev/null +++ b/ports/win32-qv/README.md @@ -0,0 +1,5 @@ +# Win32-API (Windows single-threaded) + +Documentation for this port is available in the QP/C Manual at: + +- https://www.state-machine.com/qpcpp/win32-qv.html diff --git a/ports/win32-qv/qf_port.cpp b/ports/win32-qv/qf_port.cpp index a6c1b1f1f..057a3ceb7 100644 --- a/ports/win32-qv/qf_port.cpp +++ b/ports/win32-qv/qf_port.cpp @@ -1,6 +1,5 @@ //! @file //! @brief QF/C++ port to Win32 API (single-threaded, like the QV kernel) -//! @ingroup ports //! @cond //============================================================================ //! Last updated for version 6.9.1 diff --git a/ports/win32-qv/qf_port.hpp b/ports/win32-qv/qf_port.hpp index 80cbea9f9..f3da0827e 100644 --- a/ports/win32-qv/qf_port.hpp +++ b/ports/win32-qv/qf_port.hpp @@ -1,6 +1,5 @@ //! @file //! @brief QF/C++ port to Win32 API (single-threaded, like the QV kernel) -//! @ingroup ports //! @cond //============================================================================ //! Last updated for version 6.9.1 diff --git a/ports/win32-qv/qs_port.cpp b/ports/win32-qv/qs_port.cpp index 42332ac60..b0279c9bb 100644 --- a/ports/win32-qv/qs_port.cpp +++ b/ports/win32-qv/qs_port.cpp @@ -1,6 +1,5 @@ //! @file //! @brief QS/C++ port to Win32 API -//! @ingroup ports //! @cond //============================================================================ //! Last updated for version 6.9.3 diff --git a/ports/win32-qv/qs_port.hpp b/ports/win32-qv/qs_port.hpp index ef3e567b1..2372baee4 100644 --- a/ports/win32-qv/qs_port.hpp +++ b/ports/win32-qv/qs_port.hpp @@ -1,6 +1,5 @@ //! @file //! @brief QS/C++ port to Win32 with GNU or Visual C++ compilers -//! @ingroup qf //! @cond //============================================================================ //! Last updated for version 6.6.0 diff --git a/ports/win32-qv/safe_std.h b/ports/win32-qv/safe_std.h index 2cb539409..989212c12 100644 --- a/ports/win32-qv/safe_std.h +++ b/ports/win32-qv/safe_std.h @@ -1,7 +1,6 @@ /** * @file * @brief "safe" and facilities -* @ingroup qpspy * @cond ****************************************************************************** * Last updated for version 6.9.0 diff --git a/ports/win32/README.md b/ports/win32/README.md new file mode 100644 index 000000000..62fa09c54 --- /dev/null +++ b/ports/win32/README.md @@ -0,0 +1,5 @@ +# Win32-API (Windows multi-threaded with Win32-threads) + +Documentation for this port is available in the QP/C Manual at: + +- https://www.state-machine.com/qpcpp/win32.html diff --git a/ports/win32/qf_port.cpp b/ports/win32/qf_port.cpp index c71b0deb2..ad3e6e2a8 100644 --- a/ports/win32/qf_port.cpp +++ b/ports/win32/qf_port.cpp @@ -1,6 +1,5 @@ //! @file //! @brief QF/C++ port to Win32 API (multi-threaded) -//! @ingroup qf //! @cond //============================================================================ //! Last updated for version 6.9.1 diff --git a/ports/win32/qf_port.hpp b/ports/win32/qf_port.hpp index 2774643e1..c7f6c48b2 100644 --- a/ports/win32/qf_port.hpp +++ b/ports/win32/qf_port.hpp @@ -1,6 +1,5 @@ //! @file //! @brief QF/C++ port to Win32 API (multi-threaded) -//! @ingroup ports //! @cond //============================================================================ //! Last updated for version 6.8.2 diff --git a/ports/win32/qs_port.cpp b/ports/win32/qs_port.cpp index 42332ac60..b0279c9bb 100644 --- a/ports/win32/qs_port.cpp +++ b/ports/win32/qs_port.cpp @@ -1,6 +1,5 @@ //! @file //! @brief QS/C++ port to Win32 API -//! @ingroup ports //! @cond //============================================================================ //! Last updated for version 6.9.3 diff --git a/ports/win32/qs_port.hpp b/ports/win32/qs_port.hpp index ef3e567b1..2372baee4 100644 --- a/ports/win32/qs_port.hpp +++ b/ports/win32/qs_port.hpp @@ -1,6 +1,5 @@ //! @file //! @brief QS/C++ port to Win32 with GNU or Visual C++ compilers -//! @ingroup qf //! @cond //============================================================================ //! Last updated for version 6.6.0 diff --git a/ports/win32/safe_std.h b/ports/win32/safe_std.h index 2cb539409..989212c12 100644 --- a/ports/win32/safe_std.h +++ b/ports/win32/safe_std.h @@ -1,7 +1,6 @@ /** * @file * @brief "safe" and facilities -* @ingroup qpspy * @cond ****************************************************************************** * Last updated for version 6.9.0 diff --git a/src/qf/qep_hsm.cpp b/src/qf/qep_hsm.cpp index aa45e3c31..e6e001256 100644 --- a/src/qf/qep_hsm.cpp +++ b/src/qf/qep_hsm.cpp @@ -27,8 +27,7 @@ //! //! @file //! @brief QP::QHsm implementation -//! @ingroup qep -//! @tr{RQP103} @tr{RQP120} +//! @tr{RQP103} @tr{RQP104} @tr{RQP120} @tr{RQP130} #define QP_IMPL // this is QP implementation #include "qep_port.hpp" // QEP port @@ -113,6 +112,7 @@ namespace QP { //! //! @param[in] initial pointer to the top-most initial state-handler //! function in the derived state machine +//! @tr{RQP103} //! QHsm::QHsm(QStateHandler const initial) noexcept { m_state.fun = Q_STATE_CAST(&top); @@ -136,6 +136,8 @@ QHsm::~QHsm() { //! @note //! Must be called exactly __once__ before the QP::QHsm::dispatch(). //! +//! @tr{RQP103} @tr{RQP120I} @tr{RQP120D} +//! void QHsm::init(void const * const e, std::uint_fast8_t const qs_id) { static_cast(qs_id); // unused parameter (if Q_SPY not defined) @@ -218,9 +220,12 @@ void QHsm::init(void const * const e, std::uint_fast8_t const qs_id) { //! all events. //! //! @note -//! The arguments to this state handler are not used. They are provided for +//! The parameters to this state handler are not used. They are provided for //! conformance with the state-handler function signature QP::QStateHandler. //! +//! +//! @tr{RQP103} @tr{RQP120T} +//! QState QHsm::top(void * const me, QEvt const * const e) noexcept { static_cast(me); // unused parameter static_cast(e); // unused parameter @@ -239,6 +244,9 @@ QState QHsm::top(void * const me, QEvt const * const e) noexcept { //! This state machine must be initialized by calling QP::QHsm::init() exactly //! __once__ before calling QP::QHsm::dispatch(). //! +//! @tr{RQP103} +//! @tr{RQP120A} @tr{RQP120B} @tr{RQP120C} @tr{RQP120D} @tr{RQP120E} +//! void QHsm::dispatch(QEvt const * const e, std::uint_fast8_t const qs_id) { QStateHandler t = m_state.fun; QS_CRIT_STAT_ @@ -313,7 +321,8 @@ void QHsm::dispatch(QEvt const * const e, std::uint_fast8_t const qs_id) { } #endif // Q_SPY - // retrace the entry path in reverse (desired) order... + // execute state entry actions in the desired order... + //! @tr{RQP120B} for (; ip >= 0; --ip) { QEP_ENTER_(path[ip]); // enter path[ip] } @@ -321,6 +330,7 @@ void QHsm::dispatch(QEvt const * const e, std::uint_fast8_t const qs_id) { m_temp.fun = t; // update the next state // drill into the target hierarchy... + //! @tr{RQP120I} while (QEP_TRIG_(t, Q_INIT_SIG) == Q_RET_TRAN) { QS_BEGIN_PRE_(QS_QEP_STATE_INIT, qs_id) @@ -403,7 +413,10 @@ void QHsm::dispatch(QEvt const * const e, std::uint_fast8_t const qs_id) { //! //! @returns //! the depth of the entry path stored in the @p path parameter. -//!/ +//! +//! @tr{RQP103} +//! @tr{RQP120E} @tr{RQP120F} +//! std::int_fast8_t QHsm::hsm_tran(QStateHandler (&path)[MAX_NEST_DEPTH_], std::uint_fast8_t const qs_id) { @@ -554,6 +567,9 @@ std::int_fast8_t QHsm::hsm_tran(QStateHandler (&path)[MAX_NEST_DEPTH_], //! @returns //! 'true' if the HSM is in the @p state and 'false' otherwise //! +//! @tr{RQP103} +//! @tr{RQP120S} +//! bool QHsm::isIn(QStateHandler const s) noexcept { //! @pre state configuration must be stable @@ -597,8 +613,9 @@ bool QHsm::isIn(QStateHandler const s) noexcept { //! does not necessarily start in a stable state configuration. //! However, the function establishes stable state configuration upon exit. //! +//! @tr{RQP103} //! @tr{RQP120H} - +//! QStateHandler QHsm::childState(QStateHandler const parent) noexcept { QStateHandler child = m_state.fun; // start with the current state bool isFound = false; // start with the child not found @@ -630,3 +647,4 @@ QStateHandler QHsm::childState(QStateHandler const parent) noexcept { } } // namespace QP + diff --git a/src/qf/qep_msm.cpp b/src/qf/qep_msm.cpp index 885242e17..9976d7812 100644 --- a/src/qf/qep_msm.cpp +++ b/src/qf/qep_msm.cpp @@ -27,7 +27,6 @@ //! //! @file //! @brief QP::QMsm implementation -//! @ingroup qep #define QP_IMPL // this is QP implementation #include "qep_port.hpp" // QEP port @@ -127,6 +126,20 @@ void QMsm::init(void const * const e, std::uint_fast8_t const qs_id) { static_cast(qs_id); // unused parameter (if Q_SPY not defined) } +//============================================================================ +//! @description +//! Executes the top-most initial transition in a MSM (overloaded). +//! +//! @param[in] qs_id QS-id of this state machine (for QS local filter) +//! +//! @attention +//! QP::QMsm::init() must be called exactly __once__ before +//! QP::QMsm::dispatch() +//! +void QMsm::init(std::uint_fast8_t const qs_id) { + QMsm::init(nullptr, qs_id); +} + //============================================================================ //! @description //! Dispatches an event for processing to a meta state machine (MSM). diff --git a/src/qf/qf_act.cpp b/src/qf/qf_act.cpp index c21e7c7ae..f549b4d14 100644 --- a/src/qf/qf_act.cpp +++ b/src/qf/qf_act.cpp @@ -27,7 +27,6 @@ //! //! @file //! @brief QP::QActive services and QF support code -//! @ingroup qf #define QP_IMPL // this is QP implementation #include "qf_port.hpp" // QF port diff --git a/src/qf/qf_actq.cpp b/src/qf/qf_actq.cpp index 909653b43..8f27a3719 100644 --- a/src/qf/qf_actq.cpp +++ b/src/qf/qf_actq.cpp @@ -32,7 +32,6 @@ //! this source file is only included in the QF library when the native //! QF active object queue is used (instead of a message queue of an RTOS). //! -//! @ingroup qf #define QP_IMPL // this is QP implementation #include "qf_port.hpp" // QF port @@ -413,6 +412,10 @@ void QTicker::dispatch(QEvt const * const e, } } //............................................................................ +void QTicker::init(std::uint_fast8_t const qs_id) noexcept { + QTicker::init(nullptr, qs_id); +} +//............................................................................ #ifdef Q_SPY //============================================================================ //! @sa diff --git a/src/qf/qf_defer.cpp b/src/qf/qf_defer.cpp index 6b65355a2..e1b5c4c43 100644 --- a/src/qf/qf_defer.cpp +++ b/src/qf/qf_defer.cpp @@ -27,7 +27,6 @@ //! //! @file //! @brief QP::QActive::defer() and QP::QActive::recall() definitions. -//! @ingroup qf #define QP_IMPL // this is QP implementation #include "qf_port.hpp" // QF port diff --git a/src/qf/qf_ps.cpp b/src/qf/qf_ps.cpp index e1175a75c..7898c6424 100644 --- a/src/qf/qf_ps.cpp +++ b/src/qf/qf_ps.cpp @@ -28,7 +28,6 @@ //! @file //! @brief QF/C++ Publish-Subscribe services //! definitions. -//! @ingroup qf #define QP_IMPL // this is QP implementation #include "qf_port.hpp" // QF port diff --git a/src/qf/qf_qmact.cpp b/src/qf/qf_qmact.cpp index bb3ae833f..970baee98 100644 --- a/src/qf/qf_qmact.cpp +++ b/src/qf/qf_qmact.cpp @@ -68,6 +68,11 @@ void QMActive::init(void const * const e, std::uint_fast8_t const qs_id) { QF_QMACTIVE_TO_QMSM_CAST_(this)->QMsm::init(e, qs_id); } //............................................................................ +void QMActive::init(std::uint_fast8_t const qs_id) { + m_state.obj = &QMsm::msm_top_s; + QF_QMACTIVE_TO_QMSM_CAST_(this)->QMsm::init(qs_id); +} +//............................................................................ void QMActive::dispatch(QEvt const * const e, std::uint_fast8_t const qs_id) { diff --git a/src/qf/qf_time.cpp b/src/qf/qf_time.cpp index a8a22b341..225425418 100644 --- a/src/qf/qf_time.cpp +++ b/src/qf/qf_time.cpp @@ -27,7 +27,6 @@ //! //! @file //! @brief QF/C++ time events and time management services -//! @ingroup qf #define QP_IMPL // this is QP implementation #include "qf_port.hpp" // QF port diff --git a/src/qf_pkg.hpp b/src/qf_pkg.hpp index 8da923eca..b13130444 100644 --- a/src/qf_pkg.hpp +++ b/src/qf_pkg.hpp @@ -1,5 +1,4 @@ //! @file -//! @ingroup qf //! @brief Internal (package scope) QF/C++ interface. //! @cond //============================================================================ diff --git a/src/qk/qk.cpp b/src/qk/qk.cpp index 4ca7f4573..c6f76ad03 100644 --- a/src/qk/qk.cpp +++ b/src/qk/qk.cpp @@ -27,7 +27,6 @@ //! //! @file //! @brief QK/C++ preemptive kernel core functions -//! @ingroup qk #define QP_IMPL // this is QF/QK implementation #include "qf_port.hpp" // QF port diff --git a/src/qs/qs.cpp b/src/qs/qs.cpp index da9f08393..7eb1ffe15 100644 --- a/src/qs/qs.cpp +++ b/src/qs/qs.cpp @@ -27,7 +27,6 @@ //! //! @file //! @brief QS software tracing services -//! @ingroup qs #define QP_IMPL // this is QP implementation #include "qs_port.hpp" // QS port diff --git a/src/qs/qs_64bit.cpp b/src/qs/qs_64bit.cpp index e01b2f164..86ba86c5c 100644 --- a/src/qs/qs_64bit.cpp +++ b/src/qs/qs_64bit.cpp @@ -27,7 +27,6 @@ //! //! @file //! @brief QS long-long (64-bit) output -//! @ingroup qs #define QP_IMPL // this is QF/QK implementation #include "qs_port.hpp" // QS port diff --git a/src/qs/qs_fp.cpp b/src/qs/qs_fp.cpp index 13265e3ca..a211cf06d 100644 --- a/src/qs/qs_fp.cpp +++ b/src/qs/qs_fp.cpp @@ -27,7 +27,6 @@ //! //! @file //! @brief QS floating point output implementation -//! @ingroup qs #define QP_IMPL // this is QF/QK implementation #include "qs_port.hpp" // QS port diff --git a/src/qs/qs_rx.cpp b/src/qs/qs_rx.cpp index d1a66d6e9..e47f59eb0 100644 --- a/src/qs/qs_rx.cpp +++ b/src/qs/qs_rx.cpp @@ -27,7 +27,6 @@ //! //! @file //! @brief QS receive channel services -//! @ingroup qs #define QP_IMPL // this is QP implementation #include "qs_port.hpp" // QS port diff --git a/src/qs/qutest.cpp b/src/qs/qutest.cpp index df82bf4ec..9faacadeb 100644 --- a/src/qs/qutest.cpp +++ b/src/qs/qutest.cpp @@ -22,12 +22,11 @@ // // //============================================================================ -//! @date Last updated on: 2022-04-29 +//! @date Last updated on: 2022-05-02 //! @version Last updated for: @ref qpcpp_7_0_0 //! //! @file //! @brief QF/C++ stub for QUTEST unit testing -//! @ingroup qs // only build when Q_UTEST is defined #ifdef Q_UTEST @@ -131,6 +130,10 @@ void QHsmDummy::init(void const * const e, QS_END_PRE_() } //............................................................................ +void QHsmDummy::init(std::uint_fast8_t const qs_id) noexcept { + QHsmDummy::init(nullptr, qs_id); +} +//............................................................................ void QHsmDummy::dispatch(QEvt const * const e, std::uint_fast8_t const qs_id) noexcept { @@ -182,6 +185,10 @@ void QActiveDummy::init(void const * const e, QS_END_PRE_() } //............................................................................ +void QActiveDummy::init(std::uint_fast8_t const qs_id) noexcept { + QActiveDummy::init(nullptr, qs_id); +} +//............................................................................ void QActiveDummy::dispatch(QEvt const * const e, std::uint_fast8_t const qs_id) noexcept { diff --git a/src/qs_pkg.hpp b/src/qs_pkg.hpp index a61478bbe..3ea2274a3 100644 --- a/src/qs_pkg.hpp +++ b/src/qs_pkg.hpp @@ -27,7 +27,6 @@ //! //! @file //! @brief Internal (package scope) QS/C++ interface. -//! @ingroup qs #ifndef QS_PKG_HPP #define QS_PKG_HPP diff --git a/src/qv/qv.cpp b/src/qv/qv.cpp index c73505862..214e7a8da 100644 --- a/src/qv/qv.cpp +++ b/src/qv/qv.cpp @@ -28,7 +28,6 @@ //! @file //! @brief Cooperative QV kernel, definition of QP::QV_readySet_ and //! implementation of kernel-specific functions. -//! @ingroup qv #define QP_IMPL // this is QP implementation #include "qf_port.hpp" // QF port diff --git a/src/qxk/qxk.cpp b/src/qxk/qxk.cpp index 4165b438f..6f649f8b0 100644 --- a/src/qxk/qxk.cpp +++ b/src/qxk/qxk.cpp @@ -28,7 +28,6 @@ //! @file //! @brief QXK/C++ preemptive kernel core functions //! public interface. -//! @ingroup qxk #define QP_IMPL // this is QP implementation #include "qf_port.hpp" // QF port diff --git a/src/qxk/qxk_mutex.cpp b/src/qxk/qxk_mutex.cpp index 7891f411d..696aedc52 100644 --- a/src/qxk/qxk_mutex.cpp +++ b/src/qxk/qxk_mutex.cpp @@ -27,7 +27,6 @@ //! //! @file //! @brief Priority-ceiling blocking mutex QP::QXMutex class definition -//! @ingroup qxk #define QP_IMPL // this is QP implementation #include "qf_port.hpp" // QF port diff --git a/src/qxk/qxk_sema.cpp b/src/qxk/qxk_sema.cpp index 3475af27f..35c1d5b07 100644 --- a/src/qxk/qxk_sema.cpp +++ b/src/qxk/qxk_sema.cpp @@ -27,7 +27,6 @@ //! //! @file //! @brief QXK/C++ preemptive kernel counting semaphore implementation -//! @ingroup qxk #define QP_IMPL // this is QP implementation #include "qf_port.hpp" // QF port diff --git a/src/qxk/qxk_xthr.cpp b/src/qxk/qxk_xthr.cpp index 3b7770bf9..1d76d9acc 100644 --- a/src/qxk/qxk_xthr.cpp +++ b/src/qxk/qxk_xthr.cpp @@ -27,7 +27,6 @@ //! //! @file //! @brief QXK/C++ preemptive kernel extended (blocking) thread implementation -//! @ingroup qxk #define QP_IMPL // this is QP implementation #include "qf_port.hpp" // QF port diff --git a/src/qxk_pkg.hpp b/src/qxk_pkg.hpp index 9b870d86c..a5b4d5f89 100644 --- a/src/qxk_pkg.hpp +++ b/src/qxk_pkg.hpp @@ -1,6 +1,5 @@ //! @file //! @brief Internal (package scope) QXK/C++ interface. -//! @ingroup qxk //! @cond //============================================================================ //! Last updated for version 6.8.0