diff --git a/doxygen/Doxyfile b/doxygen/Doxyfile deleted file mode 100644 index 3a56eca..0000000 --- a/doxygen/Doxyfile +++ /dev/null @@ -1,279 +0,0 @@ -# Doxyfile 1.9.5 - -@INCLUDE = ../../ql-doxygen/ql-doxyfile - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- -DOXYFILE_ENCODING = UTF-8 -PROJECT_NAME = QTools -PROJECT_NUMBER = 7.2.1 -PROJECT_BRIEF = "Collection of Host-Based Tools" -PROJECT_LOGO = ../../ql-doxygen/images/logo_ql.png -OUTPUT_DIRECTORY = -CREATE_SUBDIRS = NO -CREATE_SUBDIRS_LEVEL = 6 -ALLOW_UNICODE_NAMES = NO -OUTPUT_LANGUAGE = English -BRIEF_MEMBER_DESC = YES -REPEAT_BRIEF = NO -ABBREVIATE_BRIEF = "The $name class" \ - "The $name widget" \ - "The $name file" \ - is \ - provides \ - specifies \ - contains \ - represents \ - a \ - an \ - the -ALWAYS_DETAILED_SEC = NO -INLINE_INHERITED_MEMB = NO -FULL_PATH_NAMES = NO -STRIP_FROM_PATH = -STRIP_FROM_INC_PATH = -SHORT_NAMES = NO -JAVADOC_AUTOBRIEF = YES -JAVADOC_BANNER = NO -QT_AUTOBRIEF = NO -MULTILINE_CPP_IS_BRIEF = NO -PYTHON_DOCSTRING = YES -INHERIT_DOCS = YES -SEPARATE_MEMBER_PAGES = NO -TAB_SIZE = 4 -OPTIMIZE_OUTPUT_FOR_C = NO -OPTIMIZE_OUTPUT_JAVA = NO -OPTIMIZE_FOR_FORTRAN = NO -OPTIMIZE_OUTPUT_VHDL = NO -OPTIMIZE_OUTPUT_SLICE = NO -EXTENSION_MAPPING = lnt=Objective-C -MARKDOWN_SUPPORT = YES -TOC_INCLUDE_HEADINGS = 4 -AUTOLINK_SUPPORT = YES -BUILTIN_STL_SUPPORT = NO -CPP_CLI_SUPPORT = NO -SIP_SUPPORT = NO -IDL_PROPERTY_SUPPORT = YES -DISTRIBUTE_GROUP_DOC = NO -GROUP_NESTED_COMPOUNDS = NO -SUBGROUPING = YES -INLINE_GROUPED_CLASSES = YES -INLINE_SIMPLE_STRUCTS = YES -TYPEDEF_HIDES_STRUCT = YES -LOOKUP_CACHE_SIZE = 0 -NUM_PROC_THREADS = 1 -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- -EXTRACT_ALL = YES -EXTRACT_PRIVATE = YES -EXTRACT_PRIV_VIRTUAL = NO -EXTRACT_PACKAGE = YES -EXTRACT_STATIC = YES -EXTRACT_LOCAL_CLASSES = YES -EXTRACT_LOCAL_METHODS = NO -EXTRACT_ANON_NSPACES = NO -RESOLVE_UNNAMED_PARAMS = YES -HIDE_UNDOC_MEMBERS = NO -HIDE_UNDOC_CLASSES = NO -HIDE_FRIEND_COMPOUNDS = NO -HIDE_IN_BODY_DOCS = NO -INTERNAL_DOCS = NO -CASE_SENSE_NAMES = NO -HIDE_SCOPE_NAMES = YES -HIDE_COMPOUND_REFERENCE= NO -SHOW_HEADERFILE = YES -SHOW_INCLUDE_FILES = YES -SHOW_GROUPED_MEMB_INC = NO -FORCE_LOCAL_INCLUDES = NO -INLINE_INFO = YES -SORT_MEMBER_DOCS = NO -SORT_BRIEF_DOCS = NO -SORT_MEMBERS_CTORS_1ST = NO -SORT_GROUP_NAMES = NO -SORT_BY_SCOPE_NAME = NO -STRICT_PROTO_MATCHING = NO -GENERATE_TODOLIST = YES -GENERATE_TESTLIST = YES -GENERATE_BUGLIST = YES -GENERATE_DEPRECATEDLIST= YES -ENABLED_SECTIONS = QTOOLS -MAX_INITIALIZER_LINES = 30 -SHOW_USED_FILES = YES -SHOW_FILES = YES -SHOW_NAMESPACES = YES -FILE_VERSION_FILTER = -LAYOUT_FILE = -CITE_BIB_FILES = -#--------------------------------------------------------------------------- -# Configuration options related to warning and progress messages -#--------------------------------------------------------------------------- -QUIET = NO -WARNINGS = YES -WARN_IF_UNDOCUMENTED = YES -WARN_IF_DOC_ERROR = YES -WARN_IF_INCOMPLETE_DOC = YES -WARN_NO_PARAMDOC = NO -WARN_AS_ERROR = NO -WARN_FORMAT = "$file:$line: $text" -WARN_LINE_FORMAT = "at line $line of file $file" -WARN_LOGFILE = -#--------------------------------------------------------------------------- -# Configuration options related to the input files -#--------------------------------------------------------------------------- -INPUT = main.dox \ - gs.dox \ - qpspy.dox \ - qs.dox \ - qspy.dox \ - qutest.dox \ - qutest_tut.dox \ - qutest_ref.dox \ - qview.dox \ - qwin.dox \ - qcalc.dox \ - qclean.dox \ - qfsgen.dox \ - history.dox \ - ../../ql-doxygen/help.dox \ - macros.h \ - ../qspy/include/qspy.h \ - ../qspy/include/qpc_qs.h \ - ../qspy/include/qpc_qs_pkg.h \ - ../qutest/qutest_dsl.py \ - ../qview/qview.py \ - ../qwin/qwin_gui.h \ - ../qwin/qwin_gui.c -INPUT_ENCODING = UTF-8 -INPUT_FILE_ENCODING = -FILE_PATTERNS = *.dox \ - *.h \ - *.hpp \ - *.c \ - *.cpp \ - *.py -RECURSIVE = YES -EXCLUDE = -EXCLUDE_SYMLINKS = NO -EXCLUDE_PATTERNS = -EXCLUDE_SYMBOLS = _*Dialog -EXAMPLE_PATH = snippets -EXAMPLE_PATTERNS = * -EXAMPLE_RECURSIVE = NO -IMAGE_PATH = images \ - ../../ql-doxygen/images -INPUT_FILTER = -FILTER_PATTERNS = -FILTER_SOURCE_FILES = NO -FILTER_SOURCE_PATTERNS = -USE_MDFILE_AS_MAINPAGE = -FORTRAN_COMMENT_AFTER = 72 -#--------------------------------------------------------------------------- -# Configuration options related to source browsing -#--------------------------------------------------------------------------- -SOURCE_BROWSER = YES -INLINE_SOURCES = NO -STRIP_CODE_COMMENTS = NO -REFERENCED_BY_RELATION = NO -REFERENCES_RELATION = NO -REFERENCES_LINK_SOURCE = YES -SOURCE_TOOLTIPS = YES -USE_HTAGS = NO -VERBATIM_HEADERS = YES -CLANG_ASSISTED_PARSING = NO -CLANG_ADD_INC_PATHS = YES -CLANG_OPTIONS = -CLANG_DATABASE_PATH = -#--------------------------------------------------------------------------- -# Configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- -ALPHABETICAL_INDEX = YES -IGNORE_PREFIX = -#--------------------------------------------------------------------------- -# Configuration options related to the HTML output -#--------------------------------------------------------------------------- -GENERATE_HTML = YES -HTML_OUTPUT = ../html -HTML_FILE_EXTENSION = .html -HTML_HEADER = ../../ql-doxygen/ql-header-awesome.html -HTML_FOOTER = ../../ql-doxygen/ql-footer-awesome.html -HTML_STYLESHEET = -HTML_EXTRA_STYLESHEET = ../../ql-doxygen/doxygen-awesome.css \ - ../../ql-doxygen/doxygen-awesome-sidebar-only.css \ - ../../ql-doxygen/doxygen-awesome-sidebar-only-darkmode-toggle.css \ - ../../ql-doxygen/ql-awesome.css -HTML_EXTRA_FILES = ../../ql-doxygen/doxygen-awesome-darkmode-toggle.js \ - ../../ql-doxygen/doxygen-awesome-fragment-copy-button.js \ - ../../ql-doxygen/doxygen-awesome-paragraph-link.js \ - ../../ql-doxygen/ql-preview.js -HTML_COLORSTYLE = AUTO_LIGHT -HTML_COLORSTYLE_HUE = 209 -HTML_COLORSTYLE_SAT = 255 -HTML_COLORSTYLE_GAMMA = 113 -HTML_TIMESTAMP = NO -HTML_DYNAMIC_MENUS = YES -HTML_DYNAMIC_SECTIONS = NO -HTML_INDEX_NUM_ENTRIES = 100 -GENERATE_DOCSET = NO -DOCSET_FEEDNAME = "Doxygen generated docs" -DOCSET_FEEDURL = -DOCSET_BUNDLE_ID = com.state-machine.doc -DOCSET_PUBLISHER_ID = com.state-machine.doc -DOCSET_PUBLISHER_NAME = QuantumLeaps -GENERATE_HTMLHELP = NO -CHM_FILE = ../qtools.chm -HHC_LOCATION = -GENERATE_CHI = NO -CHM_INDEX_ENCODING = -BINARY_TOC = YES -TOC_EXPAND = NO -GENERATE_QHP = NO -QCH_FILE = -QHP_NAMESPACE = com.state-machine.qp -QHP_VIRTUAL_FOLDER = doc -QHP_CUST_FILTER_NAME = -QHP_CUST_FILTER_ATTRS = -QHP_SECT_FILTER_ATTRS = -QHG_LOCATION = -GENERATE_ECLIPSEHELP = NO -ECLIPSE_DOC_ID = com.state-machine.qp -DISABLE_INDEX = NO -GENERATE_TREEVIEW = YES -FULL_SIDEBAR = NO -ENUM_VALUES_PER_LINE = 4 -TREEVIEW_WIDTH = 335 -EXT_LINKS_IN_WINDOW = NO -OBFUSCATE_EMAILS = NO -HTML_FORMULA_FORMAT = png -FORMULA_FONTSIZE = 10 -FORMULA_MACROFILE = -USE_MATHJAX = NO -MATHJAX_VERSION = MathJax_2 -MATHJAX_FORMAT = HTML-CSS -MATHJAX_RELPATH = https://cdn.jsdelivr.net/npm/mathjax@2 -MATHJAX_EXTENSIONS = -MATHJAX_CODEFILE = -SEARCHENGINE = YES -SERVER_BASED_SEARCH = NO -EXTERNAL_SEARCH = NO -SEARCHENGINE_URL = -SEARCHDATA_FILE = searchdata.xml -EXTERNAL_SEARCH_ID = QTOOLS -EXTRA_SEARCH_MAPPINGS = -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- -ENABLE_PREPROCESSING = YES -MACRO_EXPANSION = NO -EXPAND_ONLY_PREDEF = NO -SEARCH_INCLUDES = YES -INCLUDE_PATH = -INCLUDE_FILE_PATTERNS = -PREDEFINED = Q_SPY \ - Q_UTEST \ - QS_OBJ_PTR_SIZE=4U \ - QS_FUN_PTR_SIZE=4U \ - Q_SIGNAL_SIZE=2U -EXPAND_AS_DEFINED = -SKIP_FUNCTION_MACROS = YES diff --git a/doxygen/Doxyfile-CHM b/doxygen/Doxyfile-CHM deleted file mode 100644 index 75b0149..0000000 --- a/doxygen/Doxyfile-CHM +++ /dev/null @@ -1,12 +0,0 @@ -# Doxyfile 1.9.5 - -@INCLUDE = Doxyfile - -PROJECT_LOGO = images/logo_ql-comp.png - -HTML_OUTPUT = tmp -HTML_HEADER = ../../ql-doxygen/ql-header.html -HTML_FOOTER = ../../ql-doxygen/ql-footer.html -HTML_EXTRA_STYLESHEET = ../../ql-doxygen/ql.css -HTML_EXTRA_FILES = ../../ql-doxygen/ql-preview.js -GENERATE_HTMLHELP = YES diff --git a/doxygen/Doxyfile-LATEX b/doxygen/Doxyfile-LATEX deleted file mode 100644 index f4b4479..0000000 --- a/doxygen/Doxyfile-LATEX +++ /dev/null @@ -1,11 +0,0 @@ -# Doxyfile 1.9.5 - -@INCLUDE = Doxyfile - -GENERATE_HTML = NO -GENERATE_LATEX = YES -ENABLED_SECTIONS += LATEX - -# no source code in latex -SOURCE_BROWSER = NO -VERBATIM_HEADERS = NO diff --git a/doxygen/gs.dox b/doxygen/gs.dox deleted file mode 100644 index 7ea5bdd..0000000 --- a/doxygen/gs.dox +++ /dev/null @@ -1,89 +0,0 @@ -/*! @page gs Getting Started -@nav{index,qpspy} - -@section gs_obtain Downloading & Installing QTools™ -

The recommended way of obtaining QTools™ is by downloading the QP-bundle™, which includes QTools™ as well as all QP frameworks and also the QM™ modeling tool. The main advantage of obtaining QTools™ bundled together like that is that you get all components, tools and examples ready to go. - -@note -QP-bundle™ is the recommended way of downloading and installing QTools™.
-It is also highly recommended that you keep checking the QP-bundle™ download page for newer releases. - - -Alternatively, you can download QTools™ separately as described below. - - - -@section install_win32 Installing QTools™ on Windows -On Windows, you simply unzip the `qtools-windows_.zip` archive to the installation folder of your choice; (`C:\qp\qtools` is the recommended default). After the installation, you still need to: - -- add the `\bin` and `\MinGW\bin` directories to the global `PATH` on your system, where `` denotes the directory where you have installed QTools (e.g., `C:\qp\qtools\bin;C:\qp\qtools\MinGW\bin`). - -@note -Adding `\bin` and `\MinGW\bin` directories to your `PATH` will enable you to invoke all QTools utilities (like @ref qspy "QSpy" or @ref qclean "QClean") by simply typing `qspy` or `qclean` at the command prompt, regardless of your current directory. This will come in handy, because typically you will not invoke `qspy` or `qclean` from the `\bin` directory. - -- define the `QTOOLS` environment variable, for example: - -@verbatim -set QTOOLS=C:\qp\qtools -@endverbatim - -@note -Defining the `QTOOLS` environment variable is required to run @ref qutest "QUTest Unit Testing" and the @ref qview "QView Visualization and Monitoring" utilities. - - - -@section install_posix Installing QTools™ on POSIX (Linux/MacOS) -On POSIX (Linux/MacOS), you simply unzip the `qtools-posix_.zip` archive to the installation folder of your choice (`~/qp/qtools` is the recommended default). After the installation, you still need to: - -- add the `/bin` directory to the global `PATH` on your system, where `` denotes the directory where you have installed QTools (e.g., `~/qp/qtools`). - -@note -Adding `/bin` to your `PATH` will enable you to invoke all QTools utilities (like @ref qspy "QSpy" or @ref qclean "QClean") by simply typing `qspy` or `qclean` at the command prompt, regardless of your current directory. This will come handy, because typically you will not invoke `qspy` or `qclean` from the `/bin` directory. - -- define the `QTOOLS` environment variable, for example: - -@verbatim -export QTOOLS=~/qp/qtools -@endverbatim - -@note -Defining the `QTOOLS` environment variable is required to run @ref qutest "QUTest Unit Testing" and @ref qview "QView Visualization and Monitoring" utilities. - - - -@section files Directories and Files -The following annotated directory tree in the standard QTools™ distribution lists the top-level directories and files: - -

- -@nav{index,qpspy} -*/ - diff --git a/doxygen/history.dox b/doxygen/history.dox deleted file mode 100644 index e239367..0000000 --- a/doxygen/history.dox +++ /dev/null @@ -1,691 +0,0 @@ -/** -@page history Revision History - -@section qtools_7_2_1 Version 7.2.1, 2023-01-11 -Introduced the @ref qutest_inter "QUTest interactive mode". - - -@section qtools_7_2_0 Version 7.2.0, 2022-12-22 -@ref qutest "QUTest testing framework":
-This release represents a significant overhaul of the @ref qutest_use "qutest.py test runner". - -- re-designed the @ref qutest_command "qutest.py command-line interface" (with the [Python argparse library](https://docs.python.org/3/library/argparse.html)) and added several new options. - -@attention -The `qutest.py` script runner @ref qutest_command "qutest.py command-line options" have been expanded and changed. Unfortunately, it was not possible to preserve the backwards compatibility with the earlier versions. **This means that various Makefiles for building and running tests need to be updated.** - -- added generation of @ref qutest_log "test logs" (feature required for safety certification efforts) - -- added generation of @ref qutest_qspy_log "QSPY logs) (might be also helpful in documenting tests for safety certification.) - -- changed the format of the output generated by `qutest.py` to better match the more verbose output generated by test scripts. (The minimal one-line-per test output could not be reconciled with various notes now generated by test scripts.) - -- changed the policy of handling **assertion failures** inside test fixtures (to match changes in QP/C/C++ 7.2.0). Specifically, now an assertion failure causes an automatic reset of the target, without waiting on the test script to trigger the reset. This minimizes the expectations placed on the compromised target system, which might be unable to receive any external commands. - -- added generation of "notes" from tests in the QSPY output to improve its readability and enable easier correlation of the QSPY output to the test scripts. - -- added new @ref qutest_dsl::note() "note()" command for generating notes from test scripts (These notes appear in the QUTest output and in the QSPY output. Also they are added to the test log files, if logging is enabled.) - -- added new @ref qutest_dsl::scenario() "scenario()" command (alias for @ref qutest_dsl::test() "test()") to support the BDD (Behavior-Driven Development) style of writing "scenarios". - -- added new @ref qutest_dsl::tag() "tag()" command (alias for @ref qutest_dsl::note() "note()") to support the BDD (Behavior-Driven Development) style of writing "scenarios". - - -@ref qspy "QSPY host application": -- added "Enum Dictionaries" and parsing of the Enum data item -- changed dictionaries for QUTest @ref qutest_dsl::command() "command()" from "User" dictionaries to "Enum Dictionaries" for enum-group 7 (#QS_CMD_ENUM). This change affects only QP 7.1.4 and newer. For backwards compatibility, older versions of QP still use the "User" dictionaries for commands. -- implemented [feature request #197](https://sourceforge.net/p/qpc/feature-requests/197) for displaying of "notes" from QUTest or QView in the QSPY output. This includes rendering special test notes now produced by QUTest 7.2.0. -- implemented [feature request #199](https://sourceforge.net/p/qpc/feature-requests/199) for truncating state annotations in sequence diagrams. - -@ref qview "QView visualization and monitoring": -- added generation of "notes" in the QSPY output from the Commands menu. -- updated the QView interface to QSPY to toggle various output formats (text, binary, Matlab, sequence) - -__Documentation__ --Updated the QTools documentation. - - -@section qtools_7_1_3 Version 7.1.3, 2022-11-18 -@ref qspy "QSPY host application": -- Implemented feature request [#199 "Extend state name character length in qspy sequence diagrams."](https://sourceforge.net/p/qpc/feature-requests/199). - -@ref qclean "QCLEAN host application": -- Added new file types and changing some cleaning rules for white-space cleaning. - -__Documentation__ -- Modified the `doxygen/` folder for generation of QM Manual in LaTeX (enables generation of PDF) - - -@section qtools_7_1_2 Version 7.1.2, 2022-09-28 -__QSPY host application:__ -- Added pre-defined "Scheduler" records: - + `QS_SCHED_PREEMPT` replaces deprecated `QS_MUTEX_LOCK` - + `QS_SCHED_RESTORE` replaces deprecated `QS_MUTEX_UNLOCK` -- Increased the default version for backwards compatibility from 6.6 to 7.0 -(@ref qspy_command "command-line option -v", now defaults to 7.0) -- Increased the default for QTimeEvt counter size from 2 to 4 -(@ref qspy_command "command-line option -C", now defaults to 4). -This corresponds to the change of the default value -of `QF_TIMEEVT_CTR_SIZE` to 4 in QP/C and QP/C. - - -@section qtools_7_1_1 Version 7.1.1, 2022-09-03 -Slightly restructured QSPY source code to better integrate directly with QP applications. Specifically, moved QSPY_cleanup() to qspy.c, so it is available to the applications. - - -@section qtools_7_1_0 Version 7.1.0, 2022-08-22 -__Changes in QSpy__ -- QSpy 7.1.0 has been updated for QP version 7.1.0. Specifically new predefined QS trace records have been added: -@code{.c} -/* [71] Semaphore (SEM) records */ -QS_SEM_TAKE, /*!< a semaphore was taken by a thread */ -QS_SEM_BLOCK, /*!< a semaphore blocked a thread */ -QS_SEM_SIGNAL, /*!< a semaphore was signaled*/ -QS_SEM_BLOCK_ATTEMPT, /*!< a semaphore blocked was attempted */ - -/* [75] Mutex (MTX) records */ -QS_MTX_LOCK, /*!< a mutex was locked */ -QS_MTX_BLOCK, /*!< a mutex blocked a thread */ -QS_MTX_UNLOCK, /*!< a mutex was unlocked */ -QS_MTX_LOCK_ATTEMPT, /*!< a mutex lock was attempted */ -QS_MTX_BLOCK_ATTEMPT, /*!< a mutex blocking was attempted */ -QS_MTX_UNLOCK_ATTEMPT,/*!< a mutex unlock was attempted */ -@endcode -the following QS trace records are now deprecated: -@code{.c} -/* [48] old Mutex records, deprecated in QP 7.1.0 */ -QS_MUTEX_LOCK, /*!< @deprecated */ -QS_MUTEX_UNLOCK, /*!< @deprecated */ -@endcode -Also, the following new groups for QS global filter have been added: -@code{.c} - QS_SEM_RECORDS, /*!< Semaphore QS records */ - QS_MTX_RECORDS, /*!< Mutex QS records */ -@endcode - -__Changes in QUTest__ -- `qutest.py` has been updated to include new QS trace records and global filters for them. The following QS record groups have been added to the "QUTest DSL": -@code{.c} -GRP_SEM - Semaphore QS records -GRP_MTX - Mutex QS records -@endcode - -__Changes in QUView__ -- `qview.py` has been updated to include new QS trace records and global filters for them. The following QS record groups have been added to QView: -@code{.c} -GRP_SEM - Semaphore QS records -GRP_MTX - Mutex QS records -@endcode - - -@section qtools_7_0_0 Version 7.0.0, 2022-01-31 -__Changes in QSpy__ -- The QSpy 7.0.0 implementation has been re-factored to modularize it in order to better support building host-based applications for executing embedded code on the host. Specifically, the new QSpy design better separates the "QSpy parser" of the QS records from the rendering engine and from other functionality of the QSpy host application. -- Also, this release introduces semantic coloring of the @ref qspy "QSPY output", which improves its readability. This feature is now controlled by the added @ref qspy_command "command-line option" `-r`. - -__Changes in QUTest__ -- added command last_rec() to access the last received QS trace record. -- improved semantic coloring of the output. - -__Changes in QCalc__ -- added "batch mode" in which an expression can be provided on the command-line to `qcalc.py`. -- added semantic coloring of the output. - -__Updated GNU-ARM Toolchain for Windows__ -- The GNU-ARM toolchain included in QTools for Windows has been updated to the latest Version 10.3-2021.10 released on October 21, 2021. - -__Updated Python for Windows__ -- The Python interpreter included in QTools for Windows has been updated to Python 3.10.1 (32-bit). - - -@section qtools_6_9_3 Version 6.9.3, 2021-04-09 - -__Changes in QSpy__ -- Moved function `QSPY_printInfo()` to `qspy.c`, to enable direct QSPY output to the console. Please see also discussion thread [QSPY to console in win32-qv and posix-qv ports] https://sourceforge.net/p/qpc/discussion/668726/thread/92e56e9480), - - -__Changes in QUTest__ -- Corrected the @ref qutest_command "DEBUG mode", where the Enter key now correctly skips a test. -- Added new command include() and provided examples of its use. -- Improved error reporting from test scripts. Specifically, the content of the Python stack has been expanded to encompass all the relevant calls. - - -__Changes in QView__ -- Modified the Python implementation to run correctly after [installing with pip](https://pypi.org/project/qview/). - - -__Changes in QWin__ -- Modified the example code to correctly handle regular buttons alongside the "owner-drawn" buttons. - - -__Changes in QCalc__ -- Modified the Python implementation to run correctly after [installing with pip](https://pypi.org/project/qcalc/). - - -__Updated Python for Windows__ -- The Python interpreter in QTools for Windows has been updated to Python 3.9.4. - - - -@section qtools_6_9_2 Version 6.9.2, 2021-01-18 - -__Changes in QUTest and QView__ - -The UDP socket binding (for connection to QSPY host application) has been changed from "localhost" to "0.0.0.0". This is to improve access to QSPY running on remote hosts. This fixes the following bug: - -- [bug#283 QUTest 6.9.1. broken](https://sourceforge.net/p/qpc/bugs/283/). - - -__Changes in QView__ - -Changed the "Local Filter" dialog box to show "QS_id=..." instead of "AO-prio=..." for QS-IDs above 64. - - -__Added QCalc__ - -A new version of the popular QCalc Programmer's Calculator has been added again. This version is based on Python (whereas the previous was based on Tcl/Tk). The new version is console based and, among other enhancements, adds support for 64-bit range. - - -__Updated GNU-ARM Toolchain for Windows__ - -The GNU-ARM toolchain in QTools for Windows has been updated to the latest Version 10-2020-q4-major, released on December 11, 2020. - - -__Updated Python for Windows__ - -The Python interpreter in QTools for Windows has been updated to Python 3.9. - - -@section qtools_6_9_1 Version 6.9.1, 2020-09-28 - -The main purpose of this release is to adjust @ref qutest and @ref qview to the new @ref qs_local "QS Local Filter" design implemented in [QP/C](https://www.state-machine.com/qpc) and [QP/C++](https://www.state-machine.com/qpcpp) 6.9.1. Specifically, the loc_filter() and ao_filter() functions in @ref qutest_script "QUTest scripts" and in @ref qview_script "QView scripts" has been re-designed. Additionally, the @ref qview_loc "QView Local Filter menu" have been adjusted accordingly. - -@note -The change in the loc_filter() command has implications for existing @ref qutest_script "QUTest scripts". Specifically, the parameters of loc_filter() are no longer object names but rather "QS-IDs" (see the documentation to loc_filter()). - -__Changes in QSPY__ - -The @ref qspy "QSPY host application" has been updated to handle the redesigned local-filters and the new predefined #QS_QF_NEW_ATTEMPT trace record. Also the default version compatibility with the @ref qs "QS target-resident component" (the `-v` @ref qspy_command "command-line option") has been increased from 6.2 to 6.6. - -Additionally, the QS_U64() and QS_I64() data elements have been made available for all types of CPUs, whereas previously they were available only on 64-bit CPUs (see also [feature#181](https://sourceforge.net/p/qpc/feature-requests/181)). - -Additionally, QSPY now can format @ref qs_app "application-specific data elements" in hexadecimal. Here are a few examples of QS trace records in the Target and the generated QSPY output: - -@code{c} -QS_U8(QS_HEX_FMT, 0xABU); // --> 0xAB -QS_U16(QS_HEX_FMT, 0xDEADU); // --> 0xDEAD -QS_U32(QS_HEX_FMT, 0xDEADBEEFU); // --> 0xDEADBEEF -QS_U64(QS_HEX_FMT, 0xDEADBEEF12345678LL); // --> 0xDEADBEEF12345678 -@endcode - - -__Implemented Feature Requests__ - -- [feature#181 "use of QS_U64() on 32 bit machine"](https://sourceforge.net/p/qpc/feature-requests/181). - - -@section qtools_6_9_0 Version 6.9.0, 2020-08-21 - -This release brings the new @ref qview component, which replaces QSpyView written originally in Tcl/Tk. The new @ref qview "QView" is written in **Python** (3.3.+) and brings much commonality with the @ref qutest, which has also been re-structured and improved. - -@note -Starting with this version, both @ref qview and @ref qutest require **Python3** (3.3+) and are **no longer compatible** with Python2. The support for Tcl/Tk has been dropped entirely in QTools. - - -__Changes in Directory Structure__ - -The new @ref qview "QView" and the updated @ref qutest "QUTest" components are now located directly under the `qtools` folder and are no longer in the `qtools\qspy` folder. Here is the new `qtools` directory structure: - -@code{py} -qtools/ -+---bin/ -+---gnu_arm-none-eabi/ -+---matlab/ -+---mingw32/ -+---Python38/ -+---qclean/ -+---qspy/ -+---qutest/ # <== new qutest location -+---qview/ # <== new qview location -+---qwin/ -+---Unity/ -@endcode - -@note -The changes in the QTools directory structure have impact on QUTest testing, because the Makefiles (or any other build tools you might be using) need to be adjusted to the new location of the `qutest.py` script. - - -__Changes in QSPY:__ - -- The @ref qspy "QSPY host utility" has been extended with @ref qspy_seq "Sequence Diagram Output". This new feature replaces the previous support for MscGen and is no longer reliant on any such external tools. - -- QSPY now recognizes the new QS trace record #QS_QF_RUN. - -@note -The #QS_QF_RUN record is now generated in @ref qutest "QUTest", which requires adjustments in existing @ref qutest_script "test scripts". Specifically, the test scripts that provide their own on_reset() callback must now also call expect_run(). - - -__Bug Fixes:__ - -- [bug#153 QSPY Creating corrupt MscGen files](https://sourceforge.net/p/qpc/bugs/153/). - - -@section qtools_6_8_2 Version 6.8.2, 2020-07-17 - -- Changed the QS trace record name QS_QF_ACTIVE_POST_FIFO to ::QS_QF_ACTIVE_POST and QS_QF_EQUEUE_POST_FIFO to ::QS_QF_EQUEUE_POST. This refactoring now better matches the QP/C/C++ API QACTIVE_POST() and QEQueue_post(). -- Fixed errors in the Doxygen documentation, such as: missing documentation for parameters, wrong parameter names, unresolved references, etc. -- Applied new, clearer styling to the Doxygen documentation. - - -@section qtools_6_8_1 Version 6.8.1, 2020-04-04 - -__Bug Fixes:__ -- [bug#263 QSPY handles incorrectly empty strings ](https://sourceforge.net/p/qpc/bugs/263/). - -Also, improved some comments in QUTest scripting documentation (qutest.py). - - - -@section qtools_6_8_0 Version 6.8.0, 2020-03-21 -- Adapted the QSPY host application to the changes in QP/C/C++ 6.8.0. -- Added color to the qutest.py Python script console output. Specifically, failing test scripts are shown in RED, while passing test scripts are shown in GREEN. - - - -@section qtools_6_7_0 Version 6.7.0, 2019-12-30 -This QTools release changes the build process for the QSPY, QCLEAN, and QFSGEN utilities on Windows. Specifically, these programs are now built using Visual Studio 2019 instead of the MinGW compiler for Windows. Also, the source code of all Quantum Leaps utilities has been reviewed and all "unsafe" calls to standard C library have been replaced with their "safe" counterparts (e.g., strcpy()->strcpy_s(), strcat()->strcat_s(),fprintf()->fprintf_s(), etc.) All these changes were made to avoid the malware warnings that were issued by some anti-virus software against executables built with MinGW. - -This release also replaces the MinGW toolchain (8.2.0) with the latest mingw32 (9.2.0) installed with MSYS2 (see also https://sourceforge.net/p/qpc/discussion/668726/thread/06b89ba2d5/ ). - -Finally, this release updates the QWIN Prototyping Toolkit (`qtools\qwin` directory) to work with the latest Visual Studio 2019 and specifically with the Resource Editor now available in VS 2019. The qwin-demo project has been updated to build with Visual Studio 2019. - - - -@section qtools_6_6_0 Version 6.6.0, 2019-08-30 -The main purpose of this release is the change in distribution of the QTools collection, which is now bundled together with the QP frameworks (QP/C, QP/C++ and QP-nano) as well as QM into "QP-bundle". This "QP-bundle" provides a single, streamlined and simplified download and installation of all QP frameworks and all the accompanying tools. - -Also this release brings significant changes to QTools for Windows. Specifically, the locations of the MinGW compiler and Tcl/Tk have been changed to separate directories (as opposed to being co-located in the `qtools/bin` directory). This facilitates easier upgrades of these third-party tools, and indeed, they have been upgraded in this QTools/Windows release as follows: - -- MinGW-32-bit **8.2.0**. -- Tcl/Tk **8.6**. - -@note -The directory reorganization means that the MinGW compiler is no longer available in the `qtools/bin` directory and therefore the QTools installer for Windows adds to the PATH both the `qtools/bin` and `qtools/MinGW/bin` directories. - -Also, this release makes the following changes to the @ref qspy "QSPY host application": - -- The @ref qspy_command "command-line" defaults have been changed such that `qspy` is equivalent to the former `qspy -u -t`. In other words, QSPY by default opens the UDP port and opens the TCP/IP port for Target connection. -- The QSPY host application now supports a new QP-compatibility version 6.6.0, in which the @ref qs_app "Application-Specific QS Trace Records" start at offset 100 instead of 70. This is only activated with the `-v 660` @ref qspy_command "command-line" option, but is in preparation for the future changes in QP/C and QP/C++ frameworks (the upcoming QP/C/C++ 6.6.0). - - - -@section qtools_6_5_1 Version 6.5.1, 2019-06-08 -This release adds **debug mode** to @ref qutest_script "QUTest scripting" (in Python). Specifically, you can now provide a special value `DEBUG` to the `qutest.py` Python script launcher, in which case `qutest.py` will start in **debug mode**, in which it will **not** launch the host executable and will **not** reset the Target. Instead, `qutest.py` will wait for the Target reset and other responses from the Target. - -Additionally, this release improves the @ref install_win32 "QTools installation on Windows". Specifically the Windows installer now installs Python and has been re-designed to automatically set up the `QTOOLS` environment variable and add `%QTOOLS%\bin;%QTOOLS%\python` to the PATH. The uninstaller reverses these changes. - - - -@section qtools_6_4_0 Version 6.4.0, 2019-02-10 -This release speeds up the QSPY host application by tweaking the timing constants in the TCP and UDP communication interfaces. The resulting QSPY 6.4.0 runs QUTest tests significantly faster (at least twice as fast) as before. - - - -@section qtools_6_3_8 Version 6.3.8, 2018-12-31 -The main purpose of this release is the update of the GNU-ARM toolchain (included in QTools for Windows) to the latest GCC 8. Specifically, this QTools release switches to the official [GNU-ARM Embedded Toolchain for Arm Cortex-M and Cortex-R processors maintained by ARM Ltd.](https://developer.arm.com/open-source/gnu-toolchain/gnu-rm). - -@note -For consistency with the [GNU-ARM Embedded Toolchain](https://developer.arm.com/open-source/gnu-toolchain/gnu-rm), the toolchain is now located in the directory `qtools\gnu_arm-none-eabi` and contains tools with the prefix **arm-none-eabi-**. This is *different* from the GNU-ARM toolchain used previously (which was located in `qtools\gnu_arm-eabi` and used the tools prefix **arm-eabi-**). This change requires adjusting existing `Makefiles` and other build commands for the GNU-ARM toolchain, which has been done in the matching QP/C/C++/nano release 6.3.8. - - -Additionally, this release makes further improvements to the "qutest.py" Python interface. Specifically, the skip() command can now be used anywhere in the test scripts to skip the commands. (Previously, the skip() command could only legitimately be used just before the test() command). - - - -@section qtools_6_3_7 Version 6.3.7, 2018-11-19 -This release brings a completely re-designed and simplified Python interface for the @ref qutest "QUTest unit testing harness". Specifically, this release adds a new scripting engine called simply @ref qutest_script "qutest.py", which replaces the previous "qspypy". - -@note -The new interface @ref qutest_script "qutest.py" is now the primary supported QUTest scripting interface. The older interfaces, such as TCL ("qutest.tcl") and "qspypy" are still provided in this release, but they are considered *obsolete* and are **not recommended** for writing new test scripts. - - -The new @ref qutest_script "qutest.py Python interface" is a simple single-threaded application that no longer requires PyTest or other such external Python packages, as did "qspypy" previously. The new Python interface is now also compatible with both Python 2 (2.7+) and Python 3 (3.4+), which means that virtually any contemporary Python version without extensions can be used for running QUTest Python scripts. - -@note -The new Python interface "qutest.py" implements a **different** (simpler) structure of @ref qutest_script "QUTest test scripts" than "qspypy" before. Examples of the new Python @ref qutest_tut "test scripts" are provided in the matching QP/C/C++ release 6.3.7. - - -Additionally, this release fixes the problem in the @ref "QSPY host utility" to correctly format signed integers (I8, I16, I32), which didn't work correctly on 64-bit Linux platforms. Also, the QSPY utility on Windows now uses the newer Windows socket library "ws2_32", which replaced the old "wsock32". - -Finally, the QTools release for Windows updates the provided MinGW GNU-C/C++ compiler to version 6.3.0. - - - -@section qtools_6_3_6 Version 6.3.6, 2018-10-03 -The main purpose of this release is to improve @ref qutest "QUTest" support. Specifically, this release adds a feature of querying and reporting the status of the @ref current_obj() "current objects", such as the current State-Machine (SM), Active-Object (AO), current Memory-Pool (MP), current Event-Queue (EQ), and current Time-Event (TE). The feature impacts the following facilities: - -- the @ref qspy "QSPY host utility" now processes the new #QS_QUERY_DATA packet -- the QUTest **Tcl** scripting implements the new command command `query_curr()` -- the QUTest **Python** scripting implements the new command command `qutest.query_curr()`. - -@note -This feature requires matching QP/C/C++ 6.3.6. - - -Also, the following bugs related to Python scripting have been fixed in the @ref qtools_qspypy "qspypy 6.3.6" included in this release: - -- [bug#224 QUTest/Python implementation of qutest.expect() is incomplete](https://sourceforge.net/p/qpc/bugs/224). This improved `qutest.expect()` implementation more closely matches the behavior of the `expect()` directive from Tcl scripting. The modified `qutest.expect()` compares correctly the `%timestamp` fields (as opposed to ignoring them) and also handles special character sequences '?', '*', and [chars] (like the Tcl `string match` command). - -- [bug#225 QUTest/Python ignores the Target-info configuration](https://sourceforge.net/p/qpc/bugs/225). - -- [bug#223 QUTest/Python hangs when attaching to QSPY fails](https://sourceforge.net/p/qpc/bugs/223). - - -@note -If you already have the previous version of @ref qtools_qspypy "qspypy", you need to re-install it by means of the following command:
-
-`pip install %%QTOOLS%\qspy` - - -Finally, this release of the QTools collection contains the [Unity unit testing harness (framework)](https://github.com/ThrowTheSwitch/Unity). - - - -@section qtools_6_3_4 Version 6.3.4, 2018-08-16 -This release adds official support for writing QUTest test scripts in Python. -Also, this release fixes some minor typos in error messages generated by QSpy. - - - -@section qtools_6_3_1 Version 6.3.1, 2018-05-24 -This minor release corrects the QSPY utility. Specifically, the @ref qs_app "application-specific output" from the macros QS_FUN(), QS_OBJ() and QS_SIG() contained extra space (' ') before the function/object/signal name. This extra space has been now removed. - -@note -The change might impact existing QUTest test scripts which parse the QS_FUN(), QS_OBJ() or QS_SIG() output. - -@note -The corrected QS_FUN(), QS_OBJ() and QS_SIG() output (without the extra space) is assumed in the QUTest examples that ship in QP/C/C++ 6.3.1. - - - -@section qtools_6_3_0 Version 6.3.0, 2018-05-10 -This release simplifies the usage of the QUTest (qutest.tcl) and QSpyView (qspyview.tcl) utilities by reducing the number of parameters required by these scripts. Specifically, the "local_port" parameter might now be omitted and still every instance of qutest.tcl / qspyview.tcl will be given a unique local UDP port. Additionally, the "port" parameter has been combined with the "host" parameter in the form host[:port]. - -Here is the new usage of the qutest.tcl script: -@code -tclsh qutest.tcl [test-scripts] [host_exe] [host[:port]] [local_port] -@endcode - -Here is the new usage of the qspyview.tcl script: -@code -wish qspyview.tcl [extension_script] [host[:port]] [local_port] -@endcode - -For example, to attach to QSPY running on the host 192.168.1.100 and port 7705, you now can launch these scripts as follows: - -@code -tclsh qutest.tcl *.tcl test_fixture.exe 192.168.1.100:7705 -wish qspyview.tcl dpp.tcl 192.168.1.100:7705 -@endcode - -Modified files: -- qspy.tcl -- qspyview.tcl -- qutest.tcl. - -Also, this release adds the LMFlash utility to QTools for Windows for flash programming of TM4C MCUs. - -@note -The changes should be transparent for most existing QSpyView and QUTest projects (this includes all examples shipped in QP/C and QP/C++). However, projects that run QSPY at non-default UDP ports might need to be adjusted. - - - -@section qtools_6_2_0 Version 6.2.0, 2018-03-13 -This release updates the QSPY host utility as well as the `qutest.tcl` and `qspyview.tcl` scripts for the following new QS records introduced in QP/C/C++ 6.2.0: - -- #QS_QF_ACTIVE_DEFER (replaces QS_QF_ACTIVE_ADD) -- #QS_QF_ACTIVE_RECALL (replaces QS_QF_ACTIVE_REMOVE) -- #QS_QF_ACTIVE_RECALL_ATTEMPT (replaces QS_QF_EQUEUE_INIT) -- QS_QF_RESERVED2 (replaces QS_QF_MPOOL_INIT) -- #QS_QF_NEW_REF (replaces QS_QF_TIMEEVT_CTR) -- #QS_MUTEX_LOCK (replaces QS_QF_RESERVED1) -- #QS_MUTEX_UNLOCK (replaces QS_QF_RESERVED0). - -The global filter settings in the `qutest.tcl` and `qspyview.tcl` scripts have been updated to the augmented and re-organized QS trace records. - -Additionally, the new commands post() and publish() have been added to the QUTest "testing DSL" (`qutest.tcl` script). Examples of use of these new commands are provided in the QP/C/C++ directory `\examples\qutest\defer\`. - - - -@section qtools_6_1_1 Version 6.1.1, 2018-02-06 -This release fixes the following bug in QSPY: - -- [bug#202 QSPY 6.1.0 fails to report target communication errors](https://sourceforge.net/p/qpc/bugs/202). - -Additionally, this release simplifies the format of the external dictionary files, so that they can potentially be generated from .map files or .elf files. The new format no longer requires storing the number of entries in the dictionary and the entries don't need to be sorted by the key-value. The new dictionary format also allows adding comments and empty lines between the dictionary blocks. - -Additionally, the QSPY for POSIX (Linux, MacOS, etc.) corrects the problem with reading input from a file (-f[bin_file] command-line option). - -Finally, this release increases the QCLEAN maximum size limit to 10MB per file. - - - -@section qtools_6_1_0 Version 6.1.0, 2018-01-20 -This release improves the @ref qspy_command "QSPY command-line" option processing by allowing option parameters to be separated by spaces from the option letter (including the optional parameters). For example, the following command-line would not work in the previous version, but will work now: - -qspy -t 6602 - -At the same time, the option parameters can follow immediately the option letter, so the following command line will work as well (backwards compatiblity): - -qspy -t6602 - -This release also improves the handling of external dictionary files in @ref qspy "QSPY host application". Specifically, the `-d` @ref qspy_command "command-line option" has been extended to allow no parameter, in which case an external dictionary file is opened automatically as soon as QSPY receives the target reset or target information. When the `-d ` option is used, the provided dictionary file is used right away, but the dictionary information might get discarded when the target information does not match the configuration and time-stamp obtained from the dictionary file. - - - -@section qtools_6_0_3 Version 6.0.3, 2017-12-12 -Fixed compilation and linkage on MacOS for qspy, qclean, qfsgen. - -Fixed [bug#180 qspyview.tcl for peek is not in sync with the qs_rx parsing of peek](https://sourceforge.net/p/qpc/bugs/180/). - -Used unsigned integer math in qcalc.tcl. - -In QTools for Windows, updated the GNU-ARM toolchain to the latest available GCC 7.2.0 adapted from SysProgs Prebuilt GNU toolchain for arm-eabi: - -http://gnutoolchains.com/arm-eabi/. - - - -@section qtools_5_9_3 Version 5.9.3, 2017-07-04 -Fixed bug#175 "QS_QF_ACTIVE_GET & QS_QF_EQUEUE_GET Record Mislabeled in -QSPY Output" (https://sourceforge.net/p/qpc/bugs/175/ ). - -Added bin/qcalc.tcl to the GIT repository (so that it shows up on GitHub). - - - -@section qtools_5_9_1 Version 5.9.1, 2017-05-19 -Added the GNU-ARM (EABI) toolset to the QTools Collection for Windows in the directory `qtools/gnu_arm-eabi`. The addition of the GNU-ARM toolset matches the changes made to Makefiles in QP/C/C++/nano 5.9.2. - -To reduce the size of the QTools for Windows download, the self-extracting archive file `qtools_win32_.exe` has been prepared with the 7-Zip utility. - - - -@section qtools_5_9_0 Version 5.9.0, 2017-05-19 -This release adds the @ref qutest "QUTest" (pronounced 'cutest') Unit Testing support to QP/Spy software tracing. Specifically, this release adds a new head-less (console-based) QSPY front-end, which runs unit tests. - -This release also adapts the @ref qspy "QSPY" host utility to support @ref qutest "QUTest" unit testing. Several new commands have been added and the structure of the code has been expanded. - -Also, the @ref qspyview "QSpyView" Visualization extension has been moved to the tcl\ sub-directory (the Tcl script tcl\qspyview.tcl). - -The other Quantum Leaps utilities, like @ref qclean "QClean", @ref qfsgen "QFSGen", and QCalc, have been updated and greatly improved. - -Finally, all utilities in the QTools collection have been documented in the new QTools Manual, available online at -https://www.state-machine.com/qtools. - - - -@section qtools_5_7_0 Version 5.7.0, 2016-09-08 -Corrected the QSPY software tracing host application to properly display floating point numbers in user-defined trace records (QS_F32() and QS_F64() macros). The problem was incompatibility between Microsoft VC++ and GCC floating-point format specifications. In the GCC software build (which produces the QSPY executable in the qtools/bin directory), the MS-VC++ floating point format resulted in all zeros (e.g., 0.0000e+000). - - - -@section qtools_5_6_4 Version 5.6.4, 2016-05-04 -Added QWIN GUI to the collection (sub-directory qwin_gui). - -Updated the QSPY software tracing host application for the QS trace record name changes introduced in QP 5.6.2. - - - -@section qtools_5_5_0 Version 5.5.0, 2015-08-21 -Extended the QSPY software tracing host application for **bi-directional** communication with embedded targets (output and *input* into the target). Added a @ref qspy_udp "UDP socket" to QSPY, as an extensibility mechanism for adding external unit testing, GUIs and other "front-ends" to control the embedded targets. - -Provided new QSpyView Tcl/Tk extension of the QSPY host application for control testing, and visualization of the real-time tracing data from embedded targets at real-time. QSpyView enables developers to rapidly build both GUI-based and "headless" scripts for their specific applications (see https://www.state-machine.com/qpc/arm-cm_dpp_ek-tm4c123gxl.html). - - - -@section qtools_5_3_1 Version 5.3.1, 2014-04-21 -Corrected the version representation from hex to decimal, to match the change in the QP framework. The version representation missmatch caused problems in parsing newly modified trace records, when the qspy.c implementation was inserted directly into the projects. - - - -@section qtools_5_3_0 Version 5.3.0, 2014-03-31 -Added new trace records to the QSPY host application: QS_QEP_TRAN_HIST, QS_QEP_TRAN_EP, and QS_QEP_TRAN_XP. Changed labels for standard records from Q_ENTRY, Q_EXIT, Q_INIT to ENTRY, EXIT, INIT. - - - -@section qtools_5_1_1 Version 5.1.1, 2013-10-15 -Fixed the bug in the QSPY host application, which didn't handle -correctly object/functions/signal names longer than 32 characters. The name limit has been raised to 64 characters and this version also correctly truncates the names at the limit without printing any garbage characters. - - - -@section qtools_5_1_0a Version 5.1.0a, 2013-09-18 -Modified QSPY utility to support changes in QP 5.1.x: - --improved handling of target resets by adding an empty QS record - before the QS_QP_RESET record. The empty record provides the frame - delimiter in case the last record in incomplete, so that the - following QS_QP_RESET record can be recognized. - --improved handling of internal object/function/signal dictionaries - so that symbolic information is displayed for all occurrences of an - object/function/signal, for which a dictionary record was received. - - - -@section qtools_5_0_0a Version 5.0.0a, 2013-09-08 -Modified the QSPY utility to support changes in QP 5.0.x: - --modified the standard trace records QS_QF_TICK and QS_QF_TIMEEVT_* to contain the tick-rate number. - --added trace records QS_TEST_RUN and QS_TEST_FAIL for unit testing. - --added version compatibility level 5.0, whereas specifying version - -v 4.5 runs qspy in compatibility mode with QP 4.5.x. - --added Find And Replace Text (FART) utility for Windows. - - - -@section qtools_4_5_02 Version 4.5.02, 2012-07-21 -Re-designed the QSPY interface to support more flexible parsing -of the trace records in desktop-based simulations (such as Windows -or Qt). Users can provide a custom parsing callback function to -QSPY_config(). Also added QS_RESET() macro to reset the internal -dictionaries (and other cleanup in the future) when the target -resets. - - - -@section qtools_4_5_01 Version 4.5.01, 2012-06-25 -Added the QS_USR_DICTIONARY() entry for storing dictionaries of -the user trace records. Replaced all remaining sprintf() calls -with snprintf(). - - - -@section qtools_4_5_00 Version 4.5.00, 2012-05-26 -Re-designed the implementation of the QSPY host application, so that it can be convenienty included as part of the QP library. This allows direct QS tracing output to the screen for QP applications running on the desktop. The QSPY application has been converted from C++ to plain C for easier integration with QP/C. - - - -@section qtools_4_3_00 Version 4.3.00, 2011-11-03 -This QSPY version matches the changes to the critical section macros made in QP 4.3.00. The QS record names QS_QF_INT_LOCK and QS_QF_INT_UNLOCK have been replaced with QS_QF_CRIT_ENTRY and QS_QF_CRIT_EXIT, respectively. - - - -@section qtools_4_2_04 Version 4.2.04, 2011-09-27 -This QSPY version fixes the bug of incorrect reporting function -or object pointers for which the dictionary records are not -provided and which are repeated in one format line (bug #3405904). -For example, trace record AO.FIFO would report (incorrectly) as -follows: - -0014004078 AO.FIFO: Sndr=200009B4 Obj=200009B4 -Evt(Sig=00000009,Obj=200009B4, Pool= 0, Ref= 0) -Queue(nFree= 5, nMin= 5) - -The Sndr= and Obj= are reported to be the same, but they were not. - - - -@section qtools_4_2_01 Version 4.2.01, 2011-08-01 -This QSPY version adds generation of sequence diagrams as files to be processed by MscGen (www.mcternan.me.uk/mscgen/). This version adds the option -g to generate a .msc file. - -Also, this version of QSPY for Windows allows COM ports larger than COM9. - - - -@section qtools_4_2_00 Version 4.2.00, 2011-07-13 -This QSPY version matches the changes made to QS target code in -QP/C/C++ 4.2.xx. These changes include sending the additional byte -of sender priority in trace records: - -- QS_QF_ACTIVE_POST_FIFO, -- QS_QF_ACTIVE_POST_LIFO. - -Additional changes include sending the poolID and refCtr of events -in two bytes instead of just one byte. The changes affect the -following trace records: - -- QS_QF_ACTIVE_POST_FIFO, -- QS_QF_ACTIVE_POST_LIFO, -- QS_QF_ACTIVE_GET, -- QS_QF_EQUEUE_GET, -- QS_QF_ACTIVE_GET_LAST, -- QS_QF_EQUEUE_GET_LAST, -- QS_QF_EQUEUE_POST_FIFO, -- QS_QF_EQUEUE_POST_LIFO, -- QS_QF_PUBLISH, -- QS_QF_GC_ATTEMPT, and -- QS_QF_GC. - -Also, for compatibility with QP 4.2.xx, this version changes -the defaults as follows: - -signal size (-S) from 1 byte to 2 bytes, and - -baud rate (-b) from 38400 to 115200. - -This version adds the following trace record: - -QS_QF_TIMEEVT_CTR. - -The version also adds compatiblity with 64-bit targets (such as 64-bit linux). This version can accept 8-byte pointers (both object pointers and function pointers) as well as 64-bit integers sent in user-defined trace records. - -This version also adds the hex format for uint32_t integers sent in user-defined trace records. - -Finally, this version adds a command-line option -v to specify the corresponding QP version running on the target. The default version is -v4.2, but specifying version -v4.1 or -v4.0 will switch QSPY into backwards-compatibility mode with the earlier versions of QP. - - - -@section qtools_4_1_06 Version 4.1.06, 2011-02-09 -This is the initial standalone release of the QSPY host pplication. -QSPY is still available in the QP/C and QP/C++ distributions, but -other rapid prototyping platforms (such as mbed or Arduino) do not -use the standard QP distributions and have no easy access to the -QSPY tool. For these users, this pre-compiled standalone release -is more convenient. - -*/ diff --git a/doxygen/images/FigQSPY.01.jpg b/doxygen/images/FigQSPY.01.jpg deleted file mode 100644 index 9e1cb76..0000000 Binary files a/doxygen/images/FigQSPY.01.jpg and /dev/null differ diff --git a/doxygen/images/FigQSPY.02.jpg b/doxygen/images/FigQSPY.02.jpg deleted file mode 100644 index 9cf7e34..0000000 Binary files a/doxygen/images/FigQSPY.02.jpg and /dev/null differ diff --git a/doxygen/images/FigQSPY.03.jpg b/doxygen/images/FigQSPY.03.jpg deleted file mode 100644 index 3a2d837..0000000 Binary files a/doxygen/images/FigQSPY.03.jpg and /dev/null differ diff --git a/doxygen/images/FigQSPY.04.jpg b/doxygen/images/FigQSPY.04.jpg deleted file mode 100644 index 9c2a86d..0000000 Binary files a/doxygen/images/FigQSPY.04.jpg and /dev/null differ diff --git a/doxygen/images/FigQSPY.05.jpg b/doxygen/images/FigQSPY.05.jpg deleted file mode 100644 index 5c1ddb5..0000000 Binary files a/doxygen/images/FigQSPY.05.jpg and /dev/null differ diff --git a/doxygen/images/TDDbook-cover.jpg b/doxygen/images/TDDbook-cover.jpg deleted file mode 100644 index 22e42f8..0000000 Binary files a/doxygen/images/TDDbook-cover.jpg and /dev/null differ diff --git a/doxygen/images/blinky_state_off.png b/doxygen/images/blinky_state_off.png deleted file mode 100644 index 7d34c64..0000000 Binary files a/doxygen/images/blinky_state_off.png and /dev/null differ diff --git a/doxygen/images/github-star.jpg b/doxygen/images/github-star.jpg deleted file mode 100644 index c230ace..0000000 Binary files a/doxygen/images/github-star.jpg and /dev/null differ diff --git a/doxygen/images/header_logo_ql.png b/doxygen/images/header_logo_ql.png deleted file mode 100644 index 987822a..0000000 Binary files a/doxygen/images/header_logo_ql.png and /dev/null differ diff --git a/doxygen/images/laptop.jpg b/doxygen/images/laptop.jpg deleted file mode 100644 index 147c61c..0000000 Binary files a/doxygen/images/laptop.jpg and /dev/null differ diff --git a/doxygen/images/ledbar5.gif b/doxygen/images/ledbar5.gif deleted file mode 100644 index e2e4c4d..0000000 Binary files a/doxygen/images/ledbar5.gif and /dev/null differ diff --git a/doxygen/images/ledbar5.psd b/doxygen/images/ledbar5.psd deleted file mode 100644 index 71e06f1..0000000 Binary files a/doxygen/images/ledbar5.psd and /dev/null differ diff --git a/doxygen/images/ledbar5_big.gif b/doxygen/images/ledbar5_big.gif deleted file mode 100644 index a591769..0000000 Binary files a/doxygen/images/ledbar5_big.gif and /dev/null differ diff --git a/doxygen/images/logo_python27-python3.gif b/doxygen/images/logo_python27-python3.gif deleted file mode 100644 index f39e509..0000000 Binary files a/doxygen/images/logo_python27-python3.gif and /dev/null differ diff --git a/doxygen/images/logo_python27-python3.jpg b/doxygen/images/logo_python27-python3.jpg deleted file mode 100644 index 2a5b96a..0000000 Binary files a/doxygen/images/logo_python27-python3.jpg and /dev/null differ diff --git a/doxygen/images/logo_python3.png b/doxygen/images/logo_python3.png deleted file mode 100644 index 4188a41..0000000 Binary files a/doxygen/images/logo_python3.png and /dev/null differ diff --git a/doxygen/images/logo_ql-comp.png b/doxygen/images/logo_ql-comp.png deleted file mode 100644 index 77d4e4e..0000000 Binary files a/doxygen/images/logo_ql-comp.png and /dev/null differ diff --git a/doxygen/images/logo_ql.png b/doxygen/images/logo_ql.png deleted file mode 100644 index dab80d0..0000000 Binary files a/doxygen/images/logo_ql.png and /dev/null differ diff --git a/doxygen/images/logo_ql_TM.jpg b/doxygen/images/logo_ql_TM.jpg deleted file mode 100644 index 9963117..0000000 Binary files a/doxygen/images/logo_ql_TM.jpg and /dev/null differ diff --git a/doxygen/images/logo_qp.gif b/doxygen/images/logo_qp.gif deleted file mode 100644 index 885a685..0000000 Binary files a/doxygen/images/logo_qp.gif and /dev/null differ diff --git a/doxygen/images/logo_qspy.gif b/doxygen/images/logo_qspy.gif deleted file mode 100644 index 050e26a..0000000 Binary files a/doxygen/images/logo_qspy.gif and /dev/null differ diff --git a/doxygen/images/logo_qspy.png b/doxygen/images/logo_qspy.png deleted file mode 100644 index cc0297a..0000000 Binary files a/doxygen/images/logo_qspy.png and /dev/null differ diff --git a/doxygen/images/logo_qspy128.gif b/doxygen/images/logo_qspy128.gif deleted file mode 100644 index e2035bd..0000000 Binary files a/doxygen/images/logo_qspy128.gif and /dev/null differ diff --git a/doxygen/images/logo_qwin256.jpg b/doxygen/images/logo_qwin256.jpg deleted file mode 100644 index 9a67951..0000000 Binary files a/doxygen/images/logo_qwin256.jpg and /dev/null differ diff --git a/doxygen/images/mscgen_dpp.gif b/doxygen/images/mscgen_dpp.gif deleted file mode 100644 index 8ea355b..0000000 Binary files a/doxygen/images/mscgen_dpp.gif and /dev/null differ diff --git a/doxygen/images/mscgen_dpp.png b/doxygen/images/mscgen_dpp.png deleted file mode 100644 index 7fa5af4..0000000 Binary files a/doxygen/images/mscgen_dpp.png and /dev/null differ diff --git a/doxygen/images/platforms.png b/doxygen/images/platforms.png deleted file mode 100644 index 8ef044f..0000000 Binary files a/doxygen/images/platforms.png and /dev/null differ diff --git a/doxygen/images/qcalc.png b/doxygen/images/qcalc.png deleted file mode 100644 index 8bf9c34..0000000 Binary files a/doxygen/images/qcalc.png and /dev/null differ diff --git a/doxygen/images/qcalc_lnk.png b/doxygen/images/qcalc_lnk.png deleted file mode 100644 index ed529cb..0000000 Binary files a/doxygen/images/qcalc_lnk.png and /dev/null differ diff --git a/doxygen/images/qclean.png b/doxygen/images/qclean.png deleted file mode 100644 index 0ec9dee..0000000 Binary files a/doxygen/images/qclean.png and /dev/null differ diff --git a/doxygen/images/qclean_dirty.png b/doxygen/images/qclean_dirty.png deleted file mode 100644 index dfee514..0000000 Binary files a/doxygen/images/qclean_dirty.png and /dev/null differ diff --git a/doxygen/images/qclean_posix.png b/doxygen/images/qclean_posix.png deleted file mode 100644 index 49accba..0000000 Binary files a/doxygen/images/qclean_posix.png and /dev/null differ diff --git a/doxygen/images/qclean_run.png b/doxygen/images/qclean_run.png deleted file mode 100644 index ad356e7..0000000 Binary files a/doxygen/images/qclean_run.png and /dev/null differ diff --git a/doxygen/images/qfsgen_run.png b/doxygen/images/qfsgen_run.png deleted file mode 100644 index e344909..0000000 Binary files a/doxygen/images/qfsgen_run.png and /dev/null differ diff --git a/doxygen/images/qhsmtst_qm.png b/doxygen/images/qhsmtst_qm.png deleted file mode 100644 index bcdeae5..0000000 Binary files a/doxygen/images/qhsmtst_qm.png and /dev/null differ diff --git a/doxygen/images/qpspy0.gif b/doxygen/images/qpspy0.gif deleted file mode 100644 index e63f518..0000000 Binary files a/doxygen/images/qpspy0.gif and /dev/null differ diff --git a/doxygen/images/qpspy1.gif b/doxygen/images/qpspy1.gif deleted file mode 100644 index 0c3ac40..0000000 Binary files a/doxygen/images/qpspy1.gif and /dev/null differ diff --git a/doxygen/images/qpspy_exa.gif b/doxygen/images/qpspy_exa.gif deleted file mode 100644 index 788129c..0000000 Binary files a/doxygen/images/qpspy_exa.gif and /dev/null differ diff --git a/doxygen/images/qpspy_exa.png b/doxygen/images/qpspy_exa.png deleted file mode 100644 index 4e99472..0000000 Binary files a/doxygen/images/qpspy_exa.png and /dev/null differ diff --git a/doxygen/images/qspy-funnel.png b/doxygen/images/qspy-funnel.png deleted file mode 100644 index 4a8a114..0000000 Binary files a/doxygen/images/qspy-funnel.png and /dev/null differ diff --git a/doxygen/images/qspy.png b/doxygen/images/qspy.png deleted file mode 100644 index de6a36e..0000000 Binary files a/doxygen/images/qspy.png and /dev/null differ diff --git a/doxygen/images/qspy1.gif b/doxygen/images/qspy1.gif deleted file mode 100644 index 8d7be51..0000000 Binary files a/doxygen/images/qspy1.gif and /dev/null differ diff --git a/doxygen/images/qspy10.gif b/doxygen/images/qspy10.gif deleted file mode 100644 index f3253aa..0000000 Binary files a/doxygen/images/qspy10.gif and /dev/null differ diff --git a/doxygen/images/qspy11.gif b/doxygen/images/qspy11.gif deleted file mode 100644 index f6ea007..0000000 Binary files a/doxygen/images/qspy11.gif and /dev/null differ diff --git a/doxygen/images/qspy12.gif b/doxygen/images/qspy12.gif deleted file mode 100644 index 15d945f..0000000 Binary files a/doxygen/images/qspy12.gif and /dev/null differ diff --git a/doxygen/images/qspy2.gif b/doxygen/images/qspy2.gif deleted file mode 100644 index 82a1907..0000000 Binary files a/doxygen/images/qspy2.gif and /dev/null differ diff --git a/doxygen/images/qspy3.gif b/doxygen/images/qspy3.gif deleted file mode 100644 index 0ee5eff..0000000 Binary files a/doxygen/images/qspy3.gif and /dev/null differ diff --git a/doxygen/images/qspy4.gif b/doxygen/images/qspy4.gif deleted file mode 100644 index e3ae673..0000000 Binary files a/doxygen/images/qspy4.gif and /dev/null differ diff --git a/doxygen/images/qspy5.gif b/doxygen/images/qspy5.gif deleted file mode 100644 index 7e5874f..0000000 Binary files a/doxygen/images/qspy5.gif and /dev/null differ diff --git a/doxygen/images/qspy6.gif b/doxygen/images/qspy6.gif deleted file mode 100644 index 7d7132d..0000000 Binary files a/doxygen/images/qspy6.gif and /dev/null differ diff --git a/doxygen/images/qspy8.gif b/doxygen/images/qspy8.gif deleted file mode 100644 index e74e334..0000000 Binary files a/doxygen/images/qspy8.gif and /dev/null differ diff --git a/doxygen/images/qspy9.gif b/doxygen/images/qspy9.gif deleted file mode 100644 index bdb9a82..0000000 Binary files a/doxygen/images/qspy9.gif and /dev/null differ diff --git a/doxygen/images/qspy_app.gif b/doxygen/images/qspy_app.gif deleted file mode 100644 index a3b89b6..0000000 Binary files a/doxygen/images/qspy_app.gif and /dev/null differ diff --git a/doxygen/images/qspy_banner.jpg b/doxygen/images/qspy_banner.jpg deleted file mode 100644 index 0db821f..0000000 Binary files a/doxygen/images/qspy_banner.jpg and /dev/null differ diff --git a/doxygen/images/qspy_cat.png b/doxygen/images/qspy_cat.png deleted file mode 100644 index 403d6a2..0000000 Binary files a/doxygen/images/qspy_cat.png and /dev/null differ diff --git a/doxygen/images/qspy_comm.gif b/doxygen/images/qspy_comm.gif deleted file mode 100644 index fa471fc..0000000 Binary files a/doxygen/images/qspy_comm.gif and /dev/null differ diff --git a/doxygen/images/qspy_dir.gif b/doxygen/images/qspy_dir.gif deleted file mode 100644 index eb17468..0000000 Binary files a/doxygen/images/qspy_dir.gif and /dev/null differ diff --git a/doxygen/images/qspy_dpp.png b/doxygen/images/qspy_dpp.png deleted file mode 100644 index a744f84..0000000 Binary files a/doxygen/images/qspy_dpp.png and /dev/null differ diff --git a/doxygen/images/qspy_embed.gif b/doxygen/images/qspy_embed.gif deleted file mode 100644 index 13d9912..0000000 Binary files a/doxygen/images/qspy_embed.gif and /dev/null differ diff --git a/doxygen/images/qspy_help.gif b/doxygen/images/qspy_help.gif deleted file mode 100644 index f5cb304..0000000 Binary files a/doxygen/images/qspy_help.gif and /dev/null differ diff --git a/doxygen/images/qspy_qutest.gif b/doxygen/images/qspy_qutest.gif deleted file mode 100644 index 5ed45db..0000000 Binary files a/doxygen/images/qspy_qutest.gif and /dev/null differ diff --git a/doxygen/images/qspy_qview.gif b/doxygen/images/qspy_qview.gif deleted file mode 100644 index 9380b6e..0000000 Binary files a/doxygen/images/qspy_qview.gif and /dev/null differ diff --git a/doxygen/images/qspy_screen.gif b/doxygen/images/qspy_screen.gif deleted file mode 100644 index 38d155c..0000000 Binary files a/doxygen/images/qspy_screen.gif and /dev/null differ diff --git a/doxygen/images/qspy_screen.png b/doxygen/images/qspy_screen.png deleted file mode 100644 index 96e1b9f..0000000 Binary files a/doxygen/images/qspy_screen.png and /dev/null differ diff --git a/doxygen/images/qspy_tag_msg.png b/doxygen/images/qspy_tag_msg.png deleted file mode 100644 index 2d6f38d..0000000 Binary files a/doxygen/images/qspy_tag_msg.png and /dev/null differ diff --git a/doxygen/images/qspy_udp.gif b/doxygen/images/qspy_udp.gif deleted file mode 100644 index 8e92ccc..0000000 Binary files a/doxygen/images/qspy_udp.gif and /dev/null differ diff --git a/doxygen/images/qtools_banner.jpg b/doxygen/images/qtools_banner.jpg deleted file mode 100644 index c640936..0000000 Binary files a/doxygen/images/qtools_banner.jpg and /dev/null differ diff --git a/doxygen/images/qtools_env1.png b/doxygen/images/qtools_env1.png deleted file mode 100644 index 595d764..0000000 Binary files a/doxygen/images/qtools_env1.png and /dev/null differ diff --git a/doxygen/images/qtools_install.jpg b/doxygen/images/qtools_install.jpg deleted file mode 100644 index 9dd8a5b..0000000 Binary files a/doxygen/images/qtools_install.jpg and /dev/null differ diff --git a/doxygen/images/qutest-colors.png b/doxygen/images/qutest-colors.png deleted file mode 100644 index fad3d08..0000000 Binary files a/doxygen/images/qutest-colors.png and /dev/null differ diff --git a/doxygen/images/qutest-out.png b/doxygen/images/qutest-out.png deleted file mode 100644 index e346cab..0000000 Binary files a/doxygen/images/qutest-out.png and /dev/null differ diff --git a/doxygen/images/qutest_banner.jpg b/doxygen/images/qutest_banner.jpg deleted file mode 100644 index 5ec2981..0000000 Binary files a/doxygen/images/qutest_banner.jpg and /dev/null differ diff --git a/doxygen/images/qutest_blinky_qm.png b/doxygen/images/qutest_blinky_qm.png deleted file mode 100644 index f8ff0b3..0000000 Binary files a/doxygen/images/qutest_blinky_qm.png and /dev/null differ diff --git a/doxygen/images/qutest_complex.gif b/doxygen/images/qutest_complex.gif deleted file mode 100644 index 88c65db..0000000 Binary files a/doxygen/images/qutest_complex.gif and /dev/null differ diff --git a/doxygen/images/qutest_ex.gif b/doxygen/images/qutest_ex.gif deleted file mode 100644 index ab69f03..0000000 Binary files a/doxygen/images/qutest_ex.gif and /dev/null differ diff --git a/doxygen/images/qutest_ex.png b/doxygen/images/qutest_ex.png deleted file mode 100644 index a7524fe..0000000 Binary files a/doxygen/images/qutest_ex.png and /dev/null differ diff --git a/doxygen/images/qutest_host.gif b/doxygen/images/qutest_host.gif deleted file mode 100644 index 93b5945..0000000 Binary files a/doxygen/images/qutest_host.gif and /dev/null differ diff --git a/doxygen/images/qutest_mock.gif b/doxygen/images/qutest_mock.gif deleted file mode 100644 index 1235684..0000000 Binary files a/doxygen/images/qutest_mock.gif and /dev/null differ diff --git a/doxygen/images/qutest_noreset.gif b/doxygen/images/qutest_noreset.gif deleted file mode 100644 index 2fc0362..0000000 Binary files a/doxygen/images/qutest_noreset.gif and /dev/null differ diff --git a/doxygen/images/qutest_pause.gif b/doxygen/images/qutest_pause.gif deleted file mode 100644 index c5249a8..0000000 Binary files a/doxygen/images/qutest_pause.gif and /dev/null differ diff --git a/doxygen/images/qutest_reset.gif b/doxygen/images/qutest_reset.gif deleted file mode 100644 index 232ec7d..0000000 Binary files a/doxygen/images/qutest_reset.gif and /dev/null differ diff --git a/doxygen/images/qutest_rtc.gif b/doxygen/images/qutest_rtc.gif deleted file mode 100644 index 3650dbe..0000000 Binary files a/doxygen/images/qutest_rtc.gif and /dev/null differ diff --git a/doxygen/images/qutest_simple.gif b/doxygen/images/qutest_simple.gif deleted file mode 100644 index d5d1879..0000000 Binary files a/doxygen/images/qutest_simple.gif and /dev/null differ diff --git a/doxygen/images/qutest_targ.gif b/doxygen/images/qutest_targ.gif deleted file mode 100644 index 8cec03f..0000000 Binary files a/doxygen/images/qutest_targ.gif and /dev/null differ diff --git a/doxygen/images/qview.gif b/doxygen/images/qview.gif deleted file mode 100644 index 1f6b781..0000000 Binary files a/doxygen/images/qview.gif and /dev/null differ diff --git a/doxygen/images/qview.jpg b/doxygen/images/qview.jpg deleted file mode 100644 index 7935a37..0000000 Binary files a/doxygen/images/qview.jpg and /dev/null differ diff --git a/doxygen/images/qview.png b/doxygen/images/qview.png deleted file mode 100644 index 60c437d..0000000 Binary files a/doxygen/images/qview.png and /dev/null differ diff --git a/doxygen/images/qview1.png b/doxygen/images/qview1.png deleted file mode 100644 index b1a3b06..0000000 Binary files a/doxygen/images/qview1.png and /dev/null differ diff --git a/doxygen/images/qview_ao.png b/doxygen/images/qview_ao.png deleted file mode 100644 index a51c468..0000000 Binary files a/doxygen/images/qview_ao.png and /dev/null differ diff --git a/doxygen/images/qview_attach.gif b/doxygen/images/qview_attach.gif deleted file mode 100644 index 094a5c8..0000000 Binary files a/doxygen/images/qview_attach.gif and /dev/null differ diff --git a/doxygen/images/qview_banner.jpg b/doxygen/images/qview_banner.jpg deleted file mode 100644 index 02076c1..0000000 Binary files a/doxygen/images/qview_banner.jpg and /dev/null differ diff --git a/doxygen/images/qview_before.gif b/doxygen/images/qview_before.gif deleted file mode 100644 index 857acaf..0000000 Binary files a/doxygen/images/qview_before.gif and /dev/null differ diff --git a/doxygen/images/qview_canv_dpp.gif b/doxygen/images/qview_canv_dpp.gif deleted file mode 100644 index 547f430..0000000 Binary files a/doxygen/images/qview_canv_dpp.gif and /dev/null differ diff --git a/doxygen/images/qview_canvas.gif b/doxygen/images/qview_canvas.gif deleted file mode 100644 index 4216769..0000000 Binary files a/doxygen/images/qview_canvas.gif and /dev/null differ diff --git a/doxygen/images/qview_canvas.png b/doxygen/images/qview_canvas.png deleted file mode 100644 index a93a8fe..0000000 Binary files a/doxygen/images/qview_canvas.png and /dev/null differ diff --git a/doxygen/images/qview_cmd.gif b/doxygen/images/qview_cmd.gif deleted file mode 100644 index 35fc6b3..0000000 Binary files a/doxygen/images/qview_cmd.gif and /dev/null differ diff --git a/doxygen/images/qview_cmd.png b/doxygen/images/qview_cmd.png deleted file mode 100644 index eda2c19..0000000 Binary files a/doxygen/images/qview_cmd.png and /dev/null differ diff --git a/doxygen/images/qview_cmd_dlg.gif b/doxygen/images/qview_cmd_dlg.gif deleted file mode 100644 index c31d47c..0000000 Binary files a/doxygen/images/qview_cmd_dlg.gif and /dev/null differ diff --git a/doxygen/images/qview_cmd_peek.gif b/doxygen/images/qview_cmd_peek.gif deleted file mode 100644 index 4410dde..0000000 Binary files a/doxygen/images/qview_cmd_peek.gif and /dev/null differ diff --git a/doxygen/images/qview_cmd_poke.gif b/doxygen/images/qview_cmd_poke.gif deleted file mode 100644 index 90b13ac..0000000 Binary files a/doxygen/images/qview_cmd_poke.gif and /dev/null differ diff --git a/doxygen/images/qview_commands.gif b/doxygen/images/qview_commands.gif deleted file mode 100644 index cf0c7e4..0000000 Binary files a/doxygen/images/qview_commands.gif and /dev/null differ diff --git a/doxygen/images/qview_commands.png b/doxygen/images/qview_commands.png deleted file mode 100644 index e875fb3..0000000 Binary files a/doxygen/images/qview_commands.png and /dev/null differ diff --git a/doxygen/images/qview_curr.gif b/doxygen/images/qview_curr.gif deleted file mode 100644 index 93ba7bd..0000000 Binary files a/doxygen/images/qview_curr.gif and /dev/null differ diff --git a/doxygen/images/qview_curr_dlg.gif b/doxygen/images/qview_curr_dlg.gif deleted file mode 100644 index 4fe44c9..0000000 Binary files a/doxygen/images/qview_curr_dlg.gif and /dev/null differ diff --git a/doxygen/images/qview_cust.gif b/doxygen/images/qview_cust.gif deleted file mode 100644 index 1eaeb47..0000000 Binary files a/doxygen/images/qview_cust.gif and /dev/null differ diff --git a/doxygen/images/qview_custom.gif b/doxygen/images/qview_custom.gif deleted file mode 100644 index 1261b0e..0000000 Binary files a/doxygen/images/qview_custom.gif and /dev/null differ diff --git a/doxygen/images/qview_dpp-fedora.gif b/doxygen/images/qview_dpp-fedora.gif deleted file mode 100644 index cb8a1f1..0000000 Binary files a/doxygen/images/qview_dpp-fedora.gif and /dev/null differ diff --git a/doxygen/images/qview_event.gif b/doxygen/images/qview_event.gif deleted file mode 100644 index 3b7760e..0000000 Binary files a/doxygen/images/qview_event.gif and /dev/null differ diff --git a/doxygen/images/qview_event.png b/doxygen/images/qview_event.png deleted file mode 100644 index ca62be6..0000000 Binary files a/doxygen/images/qview_event.png and /dev/null differ diff --git a/doxygen/images/qview_events.gif b/doxygen/images/qview_events.gif deleted file mode 100644 index db29dc3..0000000 Binary files a/doxygen/images/qview_events.gif and /dev/null differ diff --git a/doxygen/images/qview_evt_dlg.gif b/doxygen/images/qview_evt_dlg.gif deleted file mode 100644 index fb7d9eb..0000000 Binary files a/doxygen/images/qview_evt_dlg.gif and /dev/null differ diff --git a/doxygen/images/qview_ex.gif b/doxygen/images/qview_ex.gif deleted file mode 100644 index 2cb54dc..0000000 Binary files a/doxygen/images/qview_ex.gif and /dev/null differ diff --git a/doxygen/images/qview_ex.png b/doxygen/images/qview_ex.png deleted file mode 100644 index 5440aac..0000000 Binary files a/doxygen/images/qview_ex.png and /dev/null differ diff --git a/doxygen/images/qview_file.gif b/doxygen/images/qview_file.gif deleted file mode 100644 index e9598d5..0000000 Binary files a/doxygen/images/qview_file.gif and /dev/null differ diff --git a/doxygen/images/qview_filters.gif b/doxygen/images/qview_filters.gif deleted file mode 100644 index fa98c6f..0000000 Binary files a/doxygen/images/qview_filters.gif and /dev/null differ diff --git a/doxygen/images/qview_glob.gif b/doxygen/images/qview_glob.gif deleted file mode 100644 index 2420636..0000000 Binary files a/doxygen/images/qview_glob.gif and /dev/null differ diff --git a/doxygen/images/qview_glob_dlg.gif b/doxygen/images/qview_glob_dlg.gif deleted file mode 100644 index 925c7b5..0000000 Binary files a/doxygen/images/qview_glob_dlg.gif and /dev/null differ diff --git a/doxygen/images/qview_global.gif b/doxygen/images/qview_global.gif deleted file mode 100644 index 6490d64..0000000 Binary files a/doxygen/images/qview_global.gif and /dev/null differ diff --git a/doxygen/images/qview_help.gif b/doxygen/images/qview_help.gif deleted file mode 100644 index 1f237e6..0000000 Binary files a/doxygen/images/qview_help.gif and /dev/null differ diff --git a/doxygen/images/qview_known.gif b/doxygen/images/qview_known.gif deleted file mode 100644 index 9dd1fc8..0000000 Binary files a/doxygen/images/qview_known.gif and /dev/null differ diff --git a/doxygen/images/qview_loc.gif b/doxygen/images/qview_loc.gif deleted file mode 100644 index 8351cd3..0000000 Binary files a/doxygen/images/qview_loc.gif and /dev/null differ diff --git a/doxygen/images/qview_loc_dlg.gif b/doxygen/images/qview_loc_dlg.gif deleted file mode 100644 index 2a6796b..0000000 Binary files a/doxygen/images/qview_loc_dlg.gif and /dev/null differ diff --git a/doxygen/images/qview_local.png b/doxygen/images/qview_local.png deleted file mode 100644 index 63ae24b..0000000 Binary files a/doxygen/images/qview_local.png and /dev/null differ diff --git a/doxygen/images/qview_menu.gif b/doxygen/images/qview_menu.gif deleted file mode 100644 index 79f0c53..0000000 Binary files a/doxygen/images/qview_menu.gif and /dev/null differ diff --git a/doxygen/images/qview_no_text.gif b/doxygen/images/qview_no_text.gif deleted file mode 100644 index b339569..0000000 Binary files a/doxygen/images/qview_no_text.gif and /dev/null differ diff --git a/doxygen/images/qview_peek.png b/doxygen/images/qview_peek.png deleted file mode 100644 index fdbc82e..0000000 Binary files a/doxygen/images/qview_peek.png and /dev/null differ diff --git a/doxygen/images/qview_poke.png b/doxygen/images/qview_poke.png deleted file mode 100644 index 75c1da9..0000000 Binary files a/doxygen/images/qview_poke.png and /dev/null differ diff --git a/doxygen/images/qview_screen.png b/doxygen/images/qview_screen.png deleted file mode 100644 index 15db68c..0000000 Binary files a/doxygen/images/qview_screen.png and /dev/null differ diff --git a/doxygen/images/qview_shortcut.gif b/doxygen/images/qview_shortcut.gif deleted file mode 100644 index 0606eff..0000000 Binary files a/doxygen/images/qview_shortcut.gif and /dev/null differ diff --git a/doxygen/images/qview_tag_dlg.png b/doxygen/images/qview_tag_dlg.png deleted file mode 100644 index b043ebe..0000000 Binary files a/doxygen/images/qview_tag_dlg.png and /dev/null differ diff --git a/doxygen/images/qview_unknonw.gif b/doxygen/images/qview_unknonw.gif deleted file mode 100644 index 770abb5..0000000 Binary files a/doxygen/images/qview_unknonw.gif and /dev/null differ diff --git a/doxygen/images/qview_unknown.gif b/doxygen/images/qview_unknown.gif deleted file mode 100644 index b7a61f4..0000000 Binary files a/doxygen/images/qview_unknown.gif and /dev/null differ diff --git a/doxygen/images/qview_view.gif b/doxygen/images/qview_view.gif deleted file mode 100644 index 86df474..0000000 Binary files a/doxygen/images/qview_view.gif and /dev/null differ diff --git a/doxygen/images/qwin_an.png b/doxygen/images/qwin_an.png deleted file mode 100644 index 47e2697..0000000 Binary files a/doxygen/images/qwin_an.png and /dev/null differ diff --git a/doxygen/images/qwin_ani.gif b/doxygen/images/qwin_ani.gif deleted file mode 100644 index 68d7265..0000000 Binary files a/doxygen/images/qwin_ani.gif and /dev/null differ diff --git a/doxygen/images/qwin_banner.jpg b/doxygen/images/qwin_banner.jpg deleted file mode 100644 index 5d3d630..0000000 Binary files a/doxygen/images/qwin_banner.jpg and /dev/null differ diff --git a/doxygen/images/seq_defer.gif b/doxygen/images/seq_defer.gif deleted file mode 100644 index 2141a7a..0000000 Binary files a/doxygen/images/seq_defer.gif and /dev/null differ diff --git a/doxygen/images/seq_dpp.gif b/doxygen/images/seq_dpp.gif deleted file mode 100644 index cadbe5f..0000000 Binary files a/doxygen/images/seq_dpp.gif and /dev/null differ diff --git a/doxygen/images/session.png b/doxygen/images/session.png deleted file mode 100644 index a8cab6a..0000000 Binary files a/doxygen/images/session.png and /dev/null differ diff --git a/doxygen/images/sprintf_qspy.png b/doxygen/images/sprintf_qspy.png deleted file mode 100644 index 73659b2..0000000 Binary files a/doxygen/images/sprintf_qspy.png and /dev/null differ diff --git a/doxygen/images/sprintf_qutest.png b/doxygen/images/sprintf_qutest.png deleted file mode 100644 index ad74604..0000000 Binary files a/doxygen/images/sprintf_qutest.png and /dev/null differ diff --git a/doxygen/images/svg.svg b/doxygen/images/svg.svg deleted file mode 100644 index 21c97e3..0000000 --- a/doxygen/images/svg.svg +++ /dev/null @@ -1,9 +0,0 @@ -1Штамп чертежаИзм.Лист№Докум.Подп.ДатаРазраб.Пров.Т.Контр.Н.Контр.Утв.Лит.МассаМасштабЛистЛистов1КопировалФормат A0Вид 1 diff --git a/doxygen/images/test_blinky.jpg b/doxygen/images/test_blinky.jpg deleted file mode 100644 index e5fb31a..0000000 Binary files a/doxygen/images/test_blinky.jpg and /dev/null differ diff --git a/doxygen/images/test_dpp.jpg b/doxygen/images/test_dpp.jpg deleted file mode 100644 index 91eedc7..0000000 Binary files a/doxygen/images/test_dpp.jpg and /dev/null differ diff --git a/doxygen/images/test_dpp_linux.png b/doxygen/images/test_dpp_linux.png deleted file mode 100644 index e098350..0000000 Binary files a/doxygen/images/test_dpp_linux.png and /dev/null differ diff --git a/doxygen/images/test_dpp_win.png b/doxygen/images/test_dpp_win.png deleted file mode 100644 index 4aa76e6..0000000 Binary files a/doxygen/images/test_dpp_win.png and /dev/null differ diff --git a/doxygen/images/test_leddriver.png b/doxygen/images/test_leddriver.png deleted file mode 100644 index b598b1d..0000000 Binary files a/doxygen/images/test_leddriver.png and /dev/null differ diff --git a/doxygen/images/test_qhsm.jpg b/doxygen/images/test_qhsm.jpg deleted file mode 100644 index f564ed9..0000000 Binary files a/doxygen/images/test_qhsm.jpg and /dev/null differ diff --git a/doxygen/images/tracing.png b/doxygen/images/tracing.png deleted file mode 100644 index 0f00102..0000000 Binary files a/doxygen/images/tracing.png and /dev/null differ diff --git a/doxygen/images/unity_ledbar_qutest.jpg b/doxygen/images/unity_ledbar_qutest.jpg deleted file mode 100644 index c8f3af3..0000000 Binary files a/doxygen/images/unity_ledbar_qutest.jpg and /dev/null differ diff --git a/doxygen/images/unity_ledbar_unity.jpg b/doxygen/images/unity_ledbar_unity.jpg deleted file mode 100644 index 0c3a435..0000000 Binary files a/doxygen/images/unity_ledbar_unity.jpg and /dev/null differ diff --git a/doxygen/images/unity_strlen_qutest.jpg b/doxygen/images/unity_strlen_qutest.jpg deleted file mode 100644 index 2960c8d..0000000 Binary files a/doxygen/images/unity_strlen_qutest.jpg and /dev/null differ diff --git a/doxygen/images/unity_strlen_unity.jpg b/doxygen/images/unity_strlen_unity.jpg deleted file mode 100644 index bdbc392..0000000 Binary files a/doxygen/images/unity_strlen_unity.jpg and /dev/null differ diff --git a/doxygen/img/AN_Q_SPY_Software_Tracing.jpg b/doxygen/img/AN_Q_SPY_Software_Tracing.jpg deleted file mode 100644 index 4ab1648..0000000 Binary files a/doxygen/img/AN_Q_SPY_Software_Tracing.jpg and /dev/null differ diff --git a/doxygen/img/board.png b/doxygen/img/board.png deleted file mode 100644 index ea9d183..0000000 Binary files a/doxygen/img/board.png and /dev/null differ diff --git a/doxygen/img/bug.gif b/doxygen/img/bug.gif deleted file mode 100644 index e508704..0000000 Binary files a/doxygen/img/bug.gif and /dev/null differ diff --git a/doxygen/img/bug.png b/doxygen/img/bug.png deleted file mode 100644 index ced6db5..0000000 Binary files a/doxygen/img/bug.png and /dev/null differ diff --git a/doxygen/img/checkboxoff.png b/doxygen/img/checkboxoff.png deleted file mode 100644 index a68a321..0000000 Binary files a/doxygen/img/checkboxoff.png and /dev/null differ diff --git a/doxygen/img/checkboxon.png b/doxygen/img/checkboxon.png deleted file mode 100644 index be666df..0000000 Binary files a/doxygen/img/checkboxon.png and /dev/null differ diff --git a/doxygen/img/extern.png b/doxygen/img/extern.png deleted file mode 100644 index acf260f..0000000 Binary files a/doxygen/img/extern.png and /dev/null differ diff --git a/doxygen/img/file.png b/doxygen/img/file.png deleted file mode 100644 index d2ce7dd..0000000 Binary files a/doxygen/img/file.png and /dev/null differ diff --git a/doxygen/img/file_c.png b/doxygen/img/file_c.png deleted file mode 100644 index 15aaa86..0000000 Binary files a/doxygen/img/file_c.png and /dev/null differ diff --git a/doxygen/img/file_cpp.png b/doxygen/img/file_cpp.png deleted file mode 100644 index a324196..0000000 Binary files a/doxygen/img/file_cpp.png and /dev/null differ diff --git a/doxygen/img/file_doc.png b/doxygen/img/file_doc.png deleted file mode 100644 index 803bd08..0000000 Binary files a/doxygen/img/file_doc.png and /dev/null differ diff --git a/doxygen/img/file_h.png b/doxygen/img/file_h.png deleted file mode 100644 index 6fe57c8..0000000 Binary files a/doxygen/img/file_h.png and /dev/null differ diff --git a/doxygen/img/file_mak.png b/doxygen/img/file_mak.png deleted file mode 100644 index 2fe5cc4..0000000 Binary files a/doxygen/img/file_mak.png and /dev/null differ diff --git a/doxygen/img/file_pdf.png b/doxygen/img/file_pdf.png deleted file mode 100644 index 44d3acd..0000000 Binary files a/doxygen/img/file_pdf.png and /dev/null differ diff --git a/doxygen/img/file_py.png b/doxygen/img/file_py.png deleted file mode 100644 index 6e01e7f..0000000 Binary files a/doxygen/img/file_py.png and /dev/null differ diff --git a/doxygen/img/file_qm.png b/doxygen/img/file_qm.png deleted file mode 100644 index d1e90ae..0000000 Binary files a/doxygen/img/file_qm.png and /dev/null differ diff --git a/doxygen/img/file_qmp.png b/doxygen/img/file_qmp.png deleted file mode 100644 index 5cffd8f..0000000 Binary files a/doxygen/img/file_qmp.png and /dev/null differ diff --git a/doxygen/img/file_tcl.png b/doxygen/img/file_tcl.png deleted file mode 100644 index 8f5e337..0000000 Binary files a/doxygen/img/file_tcl.png and /dev/null differ diff --git a/doxygen/img/file_wish.png b/doxygen/img/file_wish.png deleted file mode 100644 index 54630ce..0000000 Binary files a/doxygen/img/file_wish.png and /dev/null differ diff --git a/doxygen/img/folder.png b/doxygen/img/folder.png deleted file mode 100644 index 78ad6cd..0000000 Binary files a/doxygen/img/folder.png and /dev/null differ diff --git a/doxygen/img/forbidden.png b/doxygen/img/forbidden.png deleted file mode 100644 index c00505d..0000000 Binary files a/doxygen/img/forbidden.png and /dev/null differ diff --git a/doxygen/img/github-corner.png b/doxygen/img/github-corner.png deleted file mode 100644 index 4ce398e..0000000 Binary files a/doxygen/img/github-corner.png and /dev/null differ diff --git a/doxygen/img/github-qt.png b/doxygen/img/github-qt.png deleted file mode 100644 index 7618c55..0000000 Binary files a/doxygen/img/github-qt.png and /dev/null differ diff --git a/doxygen/img/header_bg.png b/doxygen/img/header_bg.png deleted file mode 100644 index 6d266d9..0000000 Binary files a/doxygen/img/header_bg.png and /dev/null differ diff --git a/doxygen/img/help_dark.png b/doxygen/img/help_dark.png deleted file mode 100644 index aa30b97..0000000 Binary files a/doxygen/img/help_dark.png and /dev/null differ diff --git a/doxygen/img/help_light.png b/doxygen/img/help_light.png deleted file mode 100644 index 85e8f4b..0000000 Binary files a/doxygen/img/help_light.png and /dev/null differ diff --git a/doxygen/img/img.htm b/doxygen/img/img.htm deleted file mode 100644 index 576aaf8..0000000 --- a/doxygen/img/img.htm +++ /dev/null @@ -1,53 +0,0 @@ - - - - - -QP built-in images - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/doxygen/img/key_down.png b/doxygen/img/key_down.png deleted file mode 100644 index 3d28614..0000000 Binary files a/doxygen/img/key_down.png and /dev/null differ diff --git a/doxygen/img/key_ret.png b/doxygen/img/key_ret.png deleted file mode 100644 index fba9065..0000000 Binary files a/doxygen/img/key_ret.png and /dev/null differ diff --git a/doxygen/img/key_up.png b/doxygen/img/key_up.png deleted file mode 100644 index 6666a4c..0000000 Binary files a/doxygen/img/key_up.png and /dev/null differ diff --git a/doxygen/img/logo_github.png b/doxygen/img/logo_github.png deleted file mode 100644 index 99b3839..0000000 Binary files a/doxygen/img/logo_github.png and /dev/null differ diff --git a/doxygen/img/logo_linux48.png b/doxygen/img/logo_linux48.png deleted file mode 100644 index b71bb3d..0000000 Binary files a/doxygen/img/logo_linux48.png and /dev/null differ diff --git a/doxygen/img/logo_macos48.png b/doxygen/img/logo_macos48.png deleted file mode 100644 index 5f9440d..0000000 Binary files a/doxygen/img/logo_macos48.png and /dev/null differ diff --git a/doxygen/img/logo_ql-compact.png b/doxygen/img/logo_ql-compact.png deleted file mode 100644 index d4c0233..0000000 Binary files a/doxygen/img/logo_ql-compact.png and /dev/null differ diff --git a/doxygen/img/logo_ql.png b/doxygen/img/logo_ql.png deleted file mode 100644 index d6d823f..0000000 Binary files a/doxygen/img/logo_ql.png and /dev/null differ diff --git a/doxygen/img/logo_win.png b/doxygen/img/logo_win.png deleted file mode 100644 index e761ad3..0000000 Binary files a/doxygen/img/logo_win.png and /dev/null differ diff --git a/doxygen/img/logo_win48.png b/doxygen/img/logo_win48.png deleted file mode 100644 index 0ae940c..0000000 Binary files a/doxygen/img/logo_win48.png and /dev/null differ diff --git a/doxygen/img/minus.png b/doxygen/img/minus.png deleted file mode 100644 index cd44ccc..0000000 Binary files a/doxygen/img/minus.png and /dev/null differ diff --git a/doxygen/img/model.png b/doxygen/img/model.png deleted file mode 100644 index d1e90ae..0000000 Binary files a/doxygen/img/model.png and /dev/null differ diff --git a/doxygen/img/movie.png b/doxygen/img/movie.png deleted file mode 100644 index 3468106..0000000 Binary files a/doxygen/img/movie.png and /dev/null differ diff --git a/doxygen/img/qp_link.png b/doxygen/img/qp_link.png deleted file mode 100644 index 2c4ff76..0000000 Binary files a/doxygen/img/qp_link.png and /dev/null differ diff --git a/doxygen/img/radiooff.png b/doxygen/img/radiooff.png deleted file mode 100644 index 41921e3..0000000 Binary files a/doxygen/img/radiooff.png and /dev/null differ diff --git a/doxygen/img/radioon.png b/doxygen/img/radioon.png deleted file mode 100644 index bf6c784..0000000 Binary files a/doxygen/img/radioon.png and /dev/null differ diff --git a/doxygen/img/splitbar.png b/doxygen/img/splitbar.png deleted file mode 100644 index 1b9ea10..0000000 Binary files a/doxygen/img/splitbar.png and /dev/null differ diff --git a/doxygen/img/tddbook.gif b/doxygen/img/tddbook.gif deleted file mode 100644 index 3f987f5..0000000 Binary files a/doxygen/img/tddbook.gif and /dev/null differ diff --git a/doxygen/img/tree-view_linked.png b/doxygen/img/tree-view_linked.png deleted file mode 100644 index 870c50a..0000000 Binary files a/doxygen/img/tree-view_linked.png and /dev/null differ diff --git a/doxygen/img/tree-view_unlinked.png b/doxygen/img/tree-view_unlinked.png deleted file mode 100644 index 8c8a653..0000000 Binary files a/doxygen/img/tree-view_unlinked.png and /dev/null differ diff --git a/doxygen/macros.h b/doxygen/macros.h deleted file mode 100644 index 0dc5ed7..0000000 --- a/doxygen/macros.h +++ /dev/null @@ -1,26 +0,0 @@ -/** -* \file -* \brief Command-line macros and macros for QS/QSPY -*/ - -/*! The preprocessor switch to activate the QS software tracing -* instrumentation in the code */ -/** -* When defined, Q_SPY activates the QS software tracing instrumentation. -* -* When Q_SPY is not defined, the QS instrumentation in the code does -* not generate any code. -*/ -#define Q_SPY - -/*! The preprocessor switch to activate the QUTEST unit testing -* instrumentation in the code */ -/** -* When defined, Q_UTEST activates the QUTEST unit testing facilities. -* -* When Q_UTEST unit testing is not defined, the unit testing macros -* expand to nothing and do not generate any code. -*/ -#define Q_UTEST - - diff --git a/doxygen/main.dox b/doxygen/main.dox deleted file mode 100644 index cd77a62..0000000 --- a/doxygen/main.dox +++ /dev/null @@ -1,93 +0,0 @@ -/*! @mainpage Overview -@image html qtools_banner.jpg - -@remark - -To check what's new in QTools™, please see @ref history "QTools Revision History". You can also get the latest **QTools™ code**, with the recent enhancements and bug fixes, from the GitHub QTools™ repository. -
- - -@section qtools_about What is it? -QTools™ is a collection of open source tools for embedded software development on desktop platforms, such as Windows, Linux and macOS. The QTools collection contains the following tools developed by Quantum Leaps: - -- @ref qpspy "QP/Spy software tracing and testing for embedded systems", which includes: - + @ref qs "QS™ Target-Resident Component" - + @ref qspy "QSPY™ Host Application" -- @ref qutest "QUTest™ Unit Testing Harness" -- @ref qview "QView™ Visualization & Monitoring" -- @ref qwin "QWin GUI toolkit for prototyping embedded systems on Windows in C or C++" -- @ref qclean "QClean utility for cleaning the white space in the source code" -- @ref qcalc "QCalc programmer's calculator with C syntax" -- @ref qfsgen "QFSGen utility for building ROM-based file systems" - - -@section qtools_win QTools™ on Windows -The QTools Collection for Windows additionally contains the following open-source, third-party tools: - -- GNU-make for Windows (version 4.2.1) -- GNU C/C++ toolchain for Windows (MinGW version 9.2.0) -- GNU C/C++ toolchain for ARM Cortex-M (GNU Arm Embedded Toolchain) -- Python for Windows (version 3.9 with tkinter) - - -@section qtools_licensing Licensing QTools™ -Most tools included in the QTools™ collection are distributed under the terms of the GNU General Public License (GPL) as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. The text of GPL version 2 is included in the -file GPLv2.txt in the root directory of the QTools distribution. - -The Python package is distributed under the terms of the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2, included in the file LICENSE.txt in the Python38 sub-directory of the QTools distribution. - - -@section qtools_source Source Code -In compliance with the GPL, this distribution contains the source code for -the utilities contributed by Quantum Leaps in the `/source/` -subdirectory, except for the QSPY source code, which is provided in the -`/qspy/source/` directory. All tools with names starting with 'q' -have been developed and are copyrighted by Quantum Leaps. - - -@subsection qtools_mingw The MinGW C and C++ compilers for Windows -Have been taken from the MinGW project at: - -https://www.mingw-w64.org/ - -The installer `mingw-get-setup.exe` has been used and after the -installation, the files have been pruned to reduce the size of the -distribution. Please refer to the MinGW project for the source code. - - -@subsection qtools_gnu-arm The GNU-ARM (NONE-EABI) compilers for Windows -Have been taken from: - -https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads - -The source code is available from the download page under "Source Invariant". - - -@subsection qtools_make The GNU make executable for Windows -Has been taken from the MinGW project at: - -https://www.mingw-w64.org/ - -The "GNU Make" manual (make.pdf) has been copied from the GNU make -project at: - -http://www.gnu.org/software/make - - -@subsection qtools_util The file and diff utilities -Have been taken from the GOW project at GitHub: - -https://github.com/bmatzelle/gow - - -@section qtools_help 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](https://www.state-machine.com/licensing/#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](https://www.state-machine.com/support/training) services are also available from Quantum Leaps. - - -@nav_next{gs} -*/ diff --git a/doxygen/make.bat b/doxygen/make.bat deleted file mode 100644 index 5eb9af3..0000000 --- a/doxygen/make.bat +++ /dev/null @@ -1,94 +0,0 @@ -@echo off -:: ========================================================================== -:: Product: batch script for generating Doxygen documentation -:: Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -:: -:: SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial -:: -:: This software is dual-licensed under the terms of the open source GNU -:: General Public License version 3 (or any later version), or alternatively, -:: under the terms of one of the closed source Quantum Leaps commercial -:: licenses. -:: -:: The terms of the open source GNU General Public License version 3 -:: can be found at: -:: -:: The terms of the closed source Quantum Leaps commercial licenses -:: can be found at: -:: -:: Redistributions in source code must retain this top-level comment block. -:: Plagiarizing this software to sidestep the license obligations is illegal. -:: -:: Contact information: -:: -:: -:: ========================================================================== -@setlocal - -@echo usage: -@echo make -@echo make -CHM -@echo make -LATEX - -:: tools (adjust to your system)--------------------------------------------- -:: Doxygen tool -@set DOXYGEN=doxygen - -:: HTML Help tool (needed only with the -CHM option) . -@set HHC="C:\tools\HTML Help Workshop\hhc.exe" - -:: QTOOLS directory .......................................................... -@set QTOOLS=.. - -:: HTML outut directory ...................................................... -@set HTML_OUT=%QTOOLS%\html - -:: Generate Doxygen Documentation ------------------------------------------- -if "%1"=="-CHM" ( - - @echo Generating HTML... - %DOXYGEN% Doxyfile-CHM - - @echo Adding custom images... - xcopy img tmp\img\ - @echo img\img.htm >> tmp\index.hhp - - @echo Generating CHM... - %HHC% tmp\index.hhp - - @echo. - @echo Cleanup... - @rmdir /S /Q tmp - @echo CHM file generated - -) else if "%1"=="-LATEX" ( - - @echo. - @echo Cleanup... - rmdir /S /Q %LATEX_OUT% - - @echo Generating LATEX... - %DOXYGEN% Doxyfile-LATEX - - @echo Adding custom files... - xcopy img %LATEX_OUT%\img\ - - @cd %LATEX_OUT% - @call make.bat - -) else ( - - @echo. - @echo Cleanup... - rmdir /S /Q %HTML_OUT% - - @echo Generating HTML... - %DOXYGEN% Doxyfile%1 - - @echo Adding custom files... - xcopy img %HTML_OUT%\img\ - xcopy /Y ..\..\ql-doxygen\jquery.js %HTML_OUT% - @qclean %HTML_OUT% -) - -@endlocal diff --git a/doxygen/qcalc.dox b/doxygen/qcalc.dox deleted file mode 100644 index aa976b4..0000000 --- a/doxygen/qcalc.dox +++ /dev/null @@ -1,117 +0,0 @@ -/*! @page qcalc QCalc Programmer's Calculator -@nav{qwin,qclean} - -

QCalc is a powerful, cross-platform calculator specifically designed for embedded systems programmers. The calculator accepts *whole expressions* in the @ref qcalc_expr "C-syntax" and displays results simultaneously in decimal, hexadecimal, and binary without the need to explicitly convert the result to these bases. -

- -@image html qcalc.png "QCalc user interface" - -@note -The calculator is a console application, where you can type **complete C expressions**. You can also **copy-and-paste** expressions into and from the calculator console to use them almost directly in **your C code**. - - -@section qcalc_usage QCalc Usage -QCalc is included in the QTools Collection in the sub-directory qtools/qcalc/ and consists of a single file qcalc.py. To launch QCalc, you need to open this file with python. - -You use QCalc by typing (or pasting) an expression at the `> ` prompt and pressing Enter to evaluate the expression. You can conveniently edit any expression already inside the *user input* field, and you can @ref qcacl_hist "recall the previous expressions" by means of the Up and Down keys. - -@note -You **quit** the calculator by Enter without entering an expression. - - -@subsection qcalc_batch Batch Mode -If you provide the optional [expression] argument, QCalc will evaluate the expression, print the result and terminate. For example: - -@verbatim -qcalc "2*3 + (1 << 3)" -QCalc Programmer's Calculator 6.9.4 running on Python 3.9.1 -(c) 2005-2021 Quantum Leaps, www.state-machine.com - -2*3 + (1 << 3) -= 14 | 0x0000'000E | 0b00000000'00000000'00000000'00001110 - -@endverbatim - -@subsection qcalc_interact Interactive Mode -Otherwise, if no [expression] argument is provided, QCalc will start in the interactive mode, where you can enter expressions via your keyboard. - - -@subsection qcalc_win QCalc on Windows -The python interpreter is included in the QTools collection for Windows. The `%QTOOLS%\bin` directory also contains the `qcalc.bat` batch file and a shortcut qcalc, which you can copy to your desktop: - -@image html qcalc_lnk.png "Shortcut for launching QCalc" - - -@section qcalc_features QCalc Features - -@subsection qcalc_expr Expressions in C-Syntax -The most important feature of QCalc is that it accepts expressions in the **C-syntax**—with the same operands and precedence rules as in the C or C++ source code. Among others, the expressions can contain all bit-wise operators (`<<`, `>>`, `|`, `&`, `^`, `~`) as well as mixed decimal, **hexadecimal** and even @ref qcalc_bin "binary" constants. QCalc is also a powerful floating-point scientific calculator and supports all mathematical functions (`sin()`, `cos()`, `tan()`, `exp()`, `ln()`, ...). Some examples of acceptable expressions are: - -`((0xBEEF << 16) | 1280) & ~0xFF`—binary operators, mixed hex and decimal numbers@n -`($1011 << 24) | (1280 >> 8) ^ 0xFFF0`—mixed @ref qcalc_bin "binary", dec and hex numbers@n -`(1234 % 55) + 4321//33`—remainder, integer division (note the `//` integer division operator@n -`pi/6`—pi-constant@n -`pow(sin(ans),2) + pow(cos(ans),2)`—scientific floating-point calculations, @ref qcalc_ans "ans-variable"
- - -@note -QCalc internally uses the Python command eval to evaluate the expressions. Please refer to the documentation of Python math expressions for more details of supported syntax and features. - - -@subsection qcalc_conv Automatic Conversion to Hexadecimal and Binary -If the result of expression evaluation is integer (as opposed to floating point), QCalc automatically displays the result in hexadecimal and binary formats (see QCalc screenshot). For better readability, the hex display shows an apostrophe between the two 16-bit half-words (e.g., `0xDEAD'BEEF`). Similarly, the binary output shows an apostrophe between the four 8-bit bytes (e.g., `0b11011110'10101101'10111110'11101111`). - - -@subsection qcalc_base Hexadecimal and Binary Numbers -As an extension to the C-syntax, QCalc supports both **hexadecimal numbers** and **binary numbers**. These numbers are represented as `0x...` and`0b...`, respectively, and can be mixed into expressions. Here are a few examples of such expressions: - -@verbatim -(0b0110011 << 14) & 0xDEADBEEF -(0b0010 | 0b10000) * 123 -@endverbatim - - -@subsection qcalc_hist History of Inputs -As a console application QCalc "remembers" the history of the recently entered expressions. You can recall and navigate the history of previously entered expressions by pressing the Up / Down keys. - - -@subsection qcalc_ans The ans Variable -QCalc stores the result of the last computation in the `ans` variable. Here are some examples of expressions with the `ans` variable: - -`1/ans`—find the inverse of the last computation@n -`log(ans)/log(2)`—find log-base-2 of the last computation@n - - -@subsection qcalc_64bit 64-bit Range -QCalc supports the 64-bit range and switches to 64-bit arithmetic automatically when an **integer** result of a computation exceeds the 32-bit range. Here are some examples of the 64-bit output: - -@verbatim -> 0xDEADBEEF << 27 -= 501427843159293952 | 0x06F5'6DF7'7800'0000 -= 0b00000110'11110101'01101101'11110111'01111000'00000000'00000000'00000000 -> 0xDEADBEEF << 24 -= 62678480394911744 | 0x00DE'ADBE'EF00'0000 -= 0b00000000'11011110'10101101'10111110'11101111'00000000'00000000'00000000 -> 0xDEADBEEF << 34 -! out of range -> -@endverbatim - - -@subsection qcalc_error Error handling -Expressions that you enter into QCalc might have all kinds of errors: syntax errors, computation errors (e.g., division by zero), etc. In each of these cases, QCalc responds with the `Error` message and an explanation of the error: - -@verbatim -> (2*4) + ) -Traceback (most recent call last): - File "C:\qp\qtools\qcalc\qcalc.py", line 54, in _main - result = eval(expr) - File "", line 1 - (2*4) + ) - ^ -SyntaxError: unmatched ')' -> -@endverbatim - -@nav{qwin,qclean} -*/ diff --git a/doxygen/qclean.dox b/doxygen/qclean.dox deleted file mode 100644 index 2442341..0000000 --- a/doxygen/qclean.dox +++ /dev/null @@ -1,126 +0,0 @@ -/*! @page qclean QClean Code Whitespace Cleanup -@nav{qcalc,qfsgen} - -

Many programmers pay little attention to the **whitespace** in their source code, such as spaces, tabs, new-lines, etc. The common thinking is that compilers (C, C++, etc.) ignore whitespace anyway, so why bother? But, as a *professional* software developer you should not ignore whitespace, because it can cause all sorts of problems, some of them illustrated in the figure below: -

- -@image html qclean_dirty.png "Examples of problematic whitespace in source code" - -
    -
  • 1 Trailing whitespace after the last printable character in line can cause **bugs**. For example, trailing whitespace after the C/C++ macro-continuation character '\\' can confuse the C pre-processor and can result in a **program error**, as indicated by the bug icons. -
  • -
  • 2 Similarly, inconsistent use of End-Of-Line (EOL) convention can cause **bugs**. For example, mixing the DOS EOL Convention (0x0D,0x0A) with Unix EOL Convention (0x0A) can confuse the C pre-processor and can result in a **program error**, as indicated by the bug icons. -
  • -
  • 3 Inconsistent use of tabs and spaces can cause unnecessary churn in the version control system (VCS) in source files that otherwise should be identical. Also inconsistent use of whitespace can lead to different rendering of the source code by different editors and printers. -
  • -
- -@attention -The problems caused by whitespace in the source code are particularly insidious, because you **don't see** the culprit. By using an **automated** whitespace cleanup utility you can save yourself hours of frustration and significantly improve your code quality. - - - -

QClean Source Code Cleanup Utility

-QClean is a simple and blazingly fast command-line utility to **automatically clean whitespace** in your source code. QClean is deployed as a natively compiled executable and is located in the sub-directory qtools/bin/. QClean is available in portable source code and can be compiled on all desktop platforms (Windows and POSIX—Linux, macOS...). - -@attention -QClean is very simple to use (no parameters are needed in most cases) and is blazingly fast (it can easily clean up hundreds of files per second). All this is designed so that you can use QClean frequently. In fact, the use of QClean after editing your code should become part of your **basic hygiene**—like washing hands after going to the bathroom. - - -@section qclean_usage QClean Usage -Typically, you invoke QClean from a command-line prompt without any parameters. In that case, QClean will clean up white space in the current directory and **recursively** in all its sub-directories. - -@note -If you have added the qtools/bin/ directory to your `PATH` environment variable (see @ref qtools_install "Installing QTools"), you can run `qclean` directly from your terminal window. - - -@image html qclean_run.png "Example run of the QClean utility" - -As you can see in the screen shot above, QClean processes the files and prints out the names of the cleaned up files. Also, you get information as to what has been cleaned, for example, "Trail-WS" means that trailing whitespace has been cleaned up. Other possibilities are: "CR" (cleaned up DOS/Windows (CR) end-of-lines), "LF" (cleaned up Unix (LF) end-of-lines), and "Tabs" (replaced Tabs with spaces). - - - -@subsection qclean_command QClean Command-Line Parameters -QClean takes the following command-line parameters: - -
-PARAMETER | DEFAULT | COMMENT -:--------------|:---------|:---------- -`[root-dir]` | `.` | root directory to clean (relative or absolute) -OPTIONS |   |   -`-h` |   | help (show help message and exit) -`-q` |   | query only (no cleanup when -q present) -`-r` |   | check also read-only files -`-l[limit]` | 80 | line length limit (not checked when -l absent) -
- - -@section qclean_features QClean Features -QClean fixes the following whitespace problems: - -- removing of all trailing whitespace (see figure above 1) -- applying consistent End-Of-Line convention (either Unix (LF) or DOS (CRLF) see figure above 2) -- replacing Tabs with spaces (untabify, see figure above 2) -- optionally, scan the source code for long lines exceeding the specified limit (`-l` option, default 80 characters per line). - -@note -QClean can optionally check the code for **long lines of code** that exceed a specified limit (80 characters by default) to reduce the need to either wrap the long lines (which destroys indentation), or to scroll the text horizontally. (All GUI usability guidelines universally agree that horizontal scrolling of text is always a bad idea.) In practice, the source code is very often copied-and-pasted and then modified, rather than created from scratch. For this style of editing, it’s very advantageous to see simultaneously and side-by-side both the original and the modified copy. Also, differencing the code is a routinely performed action of any VCS (Version Control System) whenever you check-in or merge the code. Limiting the line length allows us to use the horizontal screen real estate much more efficiently for side-by-side-oriented text windows instead of much less convenient and error-prone top-to-bottom differencing. - - -@subsection qclean_files QClean File Types - -QClean applies the following rules for cleaning the whitespace depending on the file types: - -
-FILE TYPE | END-OF-LINE | TRAILING WS | TABS | LONG-LINES -:---------------|:------------|:-----------:|:--------:|:------------: -`.c` | Unix (LF) | remove | replace | check -`.h` | Unix (LF) | remove | replace | check -`.cpp` | Unix (LF) | remove | replace | check -`.hpp` | Unix (LF) | remove | replace | check -`.s/.S` | Unix (LF) | remove | replace | check -`.asm` | Unix (LF) | remove | replace | check -`.txt` | Unix (LF) | remove | replace | don't check -`.xml` | Unix (LF) | remove | replace | don't check -`.dox` | Unix (LF) | remove | replace | don't check -`.md` | Unix (LF) | remove | replace | don't check -`.bat` | Unix (LF) | remove | replace | don't check -`.ld` | Unix (LF) | remove | replace | check -`.py` | Unix (LF) | remove | replace | check -`.pyw` | Unix (LF) | remove | replace | check -`.java` | Unix (LF) | remove | replace | check -`Makefile` | Unix (LF) | remove | leave | check -`mak_*` | Unix (LF) | remove | leave | check -`.mak` | Unix (LF) | remove | leave | check -`.make` | Unix (LF) | remove | leave | check -`.html` | Unix (LF) | remove | replace | don't check -`.htm` | Unix (LF) | remove | replace | don't check -`.css` | Unix (LF) | remove | replace | don't check -`.eww` | Unix (LF) | remove | replace | don't check -`.ewp` | Unix (LF) | remove | replace | don't check -`.ewd` | Unix (LF) | remove | replace | don't check -`.icf` | Unix (LF) | remove | replace | don't check -`.sln` | Unix (LF) | remove | replace | don't check -`.vcxproj` | Unix (LF) | remove | replace | don't check -`.filters` | Unix (LF) | remove | replace | don't check -`.vcxproj.filters` | Unix (LF) | remove | replace | don't check -`.project` | Unix (LF) | remove | replace | don't check -`.cproject` | Unix (LF) | remove | replace | don't check -`.pro` | Unix (LF) | remove | replace | don't check -`.m` | Unix (LF) | remove | replace | check -`.lnt` | Unix (LF) | remove | replace | check -`.cfg` | Unix (LF) | remove | replace | don't check -`.properties` | Unix (LF) | remove | replace | don't check -
- -
-@note -The cleanup rules specified in the table above can be easily customized by editing the array `l_fileTypes` in the `qclean/source/main.c` file. Also, you can change the **Tab size** by modifying the `TAB_SIZE` constant (currently set to 4) as well as the default **line-limit** by modifying the `LINE_LIMIT` constant (currently set to 80) at the top of the `qclean/source/main.c` file. Of course, after any such modification, you need to re-build the QClean executable and copy it into the qtools/bin directory. - - -
-@attention -For best code portability, QClean enforces the consistent use of the specified End-Of-Line convention (typically Unix (LF)), **regardless of the native EOL of the platform**. The DOS/Windows EOL convention (CR,LF) is typically not applied because it causes compilation problems on Unix-like systems (Specifically, the C preprocessor doesn't correctly parse the multi-line macros.) On the other hand, most DOS/Windows compilers seem to tolerate the Unix EOL convention without problems. - -@nav{qcalc,qfsgen} -*/ diff --git a/doxygen/qfsgen.dox b/doxygen/qfsgen.dox deleted file mode 100644 index 810df69..0000000 --- a/doxygen/qfsgen.dox +++ /dev/null @@ -1,148 +0,0 @@ -/*! @page qfsgen QFSGen ROM File-System Generator -@nav{qclean,history} - -

QFSGen is a cross-platform, command-line utility that generates a ROM-based file system, which can be incorporated in a C source. Specifically, the QFSGen utility generates a C header file that contains multiple constant byte arrays representing your files and directories. This generated header file (named `fsdata.h` by default) can be subsequently included in a ROM-Based File System implementation. -

- -QFSGen is deployed as a natively compiled executable and is located in the sub-directory qtools/bin/. QFSGen is available in portable source code and can be compiled on all desktop platforms (Windows and POSIX—Linux, macOS...). - -@note -The main motivation for the QFSGen utility is to generate ROM-based file systems for embedded HTTP servers. However, the utility can be used for any ROM-based file systems. - - -@section qfsgen_usage QFSGen Usage -You use the QFSGen utility from a command-prompt. First, change the current directory to the directory where you wish to generate the C header file (named `fsdata.h` by default) and type: - -@verbatim -qfsgen website -h -@endverbatim - -where `website` is a directory which contains the files and sub-directories you wish to include into your ROM-based file system. This particular QFSGen invocation will generate the file-system found in the directory `website` with HTTP headers (`-h` option). - -@image html qfsgen_run.png "Example run of the QFSGen utility" - - - -@subsection qfsgen_command QFSGen Command-Line Parameters -QFSGen takes the following command-line parameters: - -
-PARAMETER | DEFAULT | COMMENT -:--------------|:---------|:---------- -`fs-dir` | | file system directory (relative or absolute) -`[output-flie]`|`fsdata.h`| output file name (optional) -OPTIONS |   |   -`-h` |   | generate HTTP headers -
- - - -@section qfsgen_works How QFSGen Works -QFSGen recursively scans the provided directory and **recursively** encodes any file and sub-directory into an array in the generated header file. For example, here is the content of the `website` directory: - -@verbatim -+-website/ - +-img/ - | +-AN_QP_and_lwIP.jpg - | +-arrow.gif - | +-favicon.ico - | +-footer.jpg - | +-logo_lwip_qp.jpg - | +-logo_ql.jpg - | +-logo_sics.gif - | +-PSiCC2.gif - | +-QP_datasheet.gif - +-404.htm - +-bg_footer.gif - +-cgi_demo.htm - +-index.htm - +-ssi_demo.shtm - +-style.css - +-thank_you.htm - +-udp_demo.htm -@endverbatim - -This directory structure is then encoded into the following header file `fsdata.h`: - -@code -/* This file has been generated with the qfsgen utility. */ - -/* /404.htm */ -static unsigned char const data_404_htm[] = { - /* name: */ - 0x2F, 0x34, 0x30, 0x34, 0x2E, 0x68, 0x74, 0x6D, 0x00, - /* HTTP header: */ - 0x48, 0x54, 0x54, 0x50, 0x2F, 0x31, 0x2E, 0x30, 0x20, 0x34, - . . . - 0x6D, 0x6C, 0x0D, 0x0A, 0x0D, 0x0A, - /* data: */ - 0x3C, 0x21, 0x44, 0x4F, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, - 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0A -}; - -struct fsdata_file const file_404_htm[] = { - { - (struct fsdata_file *)0, - data_404_htm, - data_404_htm + 9, - sizeof(data_404_htm) - 9 - } -}; - -/* /thank_you.htm */ -static unsigned char const data_thank_you_htm[] = { - /* name: */ - 0x2F, 0x74, 0x68, 0x61, 0x6E, 0x6B, 0x5F, 0x79, 0x6F, 0x75, - 0x2E, 0x68, 0x74, 0x6D, 0x00, - /* HTTP header: */ - 0x48, 0x54, 0x54, 0x50, 0x2F, 0x31, 0x2E, 0x30, 0x20, 0x32, - . . . - 0x0D, 0x0A, 0x0D, 0x0A, - /* data: */ - 0x3C, 0x21, 0x44, 0x4F, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, - - 0x4D, 0x4C, 0x3E, 0x0A -}; - -struct fsdata_file const file_thank_you_htm[] = { - { - file_style_css, - data_thank_you_htm, - data_thank_you_htm + 15, - sizeof(data_thank_you_htm) - 15 - } -}; - -/* /udp_demo.htm */ -static unsigned char const data_udp_demo_htm[] = { - /* name: */ - 0x2F, 0x75, 0x64, 0x70, 0x5F, 0x64, 0x65, 0x6D, 0x6F, 0x2E, - 0x68, 0x74, 0x6D, 0x00, - /* HTTP header: */ - 0x48, 0x54, 0x54, 0x50, 0x2F, 0x31, 0x2E, 0x30, 0x20, 0x32, - . . . - 0x0D, 0x0A, 0x0D, 0x0A, - /* data: */ - 0x3C, 0x21, 0x44, 0x4F, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, - . . . - 0x3E, 0x0A -}; - -struct fsdata_file const file_udp_demo_htm[] = { - { - file_thank_you_htm, - data_udp_demo_htm, - data_udp_demo_htm + 14, - sizeof(data_udp_demo_htm) - 14 - } -}; - -#define FS_ROOT file_udp_demo_htm - -#define FS_NUMFILES 17 -@endcode - -Subsequently, the `fsdata.h` header file is included in the ROM file-system implementation file `fs.c`, which is included in the `qfsgen/source` directory. - -@nav{qclean,history} -*/ diff --git a/doxygen/qpspy.dox b/doxygen/qpspy.dox deleted file mode 100644 index 4d3f053..0000000 --- a/doxygen/qpspy.dox +++ /dev/null @@ -1,153 +0,0 @@ -/*! @page qpspy QP/Spy™ Software Tracing - -![](qspy_banner.jpg) - -In any real-life project, getting the code written, compiled, and successfully linked is only the first step. The system still needs to be tested, validated, and optimized for best performance and resource consumption. A single-step debugger is frequently not helpful because it stops the system and exactly hinders seeing **live interactions** within the application. Clogging up high-performance code with `printf` statements is usually too intrusive and simply unworkable in many embedded systems, because `printf` formatting and output via a serial port happen exactly in the most time-critical paths through the code. - -So the questions are: How can you monitor the behavior of a running real-time system without degrading the system itself? How can you discover and document elusive, intermittent bugs that are caused by subtle interactions among concurrent components? How do you design and execute repeatable @ref qutest "unit tests" and **integration tests** of your system? How do you ensure that a system runs reliably for long periods of time and achieves optimal performance? - -Techniques based on **software tracing** can answer many of these questions. Software tracing is a method for obtaining diagnostic information in a live environment without the need to stop the application to get system feedback. Software tracing always involves some form of target system instrumentation to log interesting discrete events for subsequent retrieval from the system and analysis. - -@anchor qpspy_framework -@remarks -Software tracing is particularly effective and powerful in combination with the event-driven **reactive programming** model, such as the one implemented in QP™ real-time frameworks. Due to the inversion of control, a real-time framework controls almost all interesting interactions in the system, so an instrumented real-time framework can provide much **more comprehensive** and detailed information than can any traditional RTOS kernel.
-![Comprehensive tracing information available in a Real-Time Embedded Framework](qspy-funnel.png) - - -@section ab_about What is it? -QP/Spy™ is a @ref qpspy "software tracing and testing system" specifically designed for embedded systems, such as single chip microcontrollers. The job of QP/Spy is to capture information about an embedded code's execution and send it to the host computer with minimal impact on the real-time performance of the embedded code. - -@image html qpspy0.gif "Software tracing data records flowing from Target to the Host" - -@remarks -QP/Spy can also (optionally) send commands and data **to the embedded target** (see @ref qpspy_rx "Bi-Directional QP/Spy"), which serves as the basis for @ref qutest "Unit Testing" and for @ref qview "Visualization and Monitoring" subsystems of the QP/Spy system. - - -@section ab_how How does it work? -In a nutshell, working with QP/Spy™ is similar to peppering the code with `printf` or similar (like `sprintf`) statements for logging and debugging, except that QP/Spy™ is much less intrusive, more lightweight, portable and @ref qs_filters "selective" than the primitive `printf`. Additionally, unlike the `printf` output, the data produced by QP/Spy™ contains the data *integrity* and *continuity* checks, so the host computer can tell if it receives corrupt or incomplete data. - -The main advantages of the QP/Spy™ tracing system over peppering the code with `printf` statements are: - -- When you use `printf`s, the data formatting and sending occur in the *time-critical* paths through the embedded code. In contrast, QP/Spy produces raw *binary data*, so all the time-consuming formatting is removed from the embedded system and is done after the fact in the host computer. - -- in QP/Spy, data logging and sending to the host are **separated** so that the embedded system can typically perform the transmission outside of the time-critical path, for example in the *idle processing* of the embedded CPU. - -- Data produced by `printf` gives you no clue if the data gets corrupted or lost in transmission. In contrast, the @ref qpspy_proto "QP/Spy transmission protocol" checks for data **integrity** and **continuity**. - -- The QP/Spy tracing provides flexible @ref qs_filters "filtering" mechanisms, which allow you to selectively trace only the aspects of the system that you choose, and to suppress the data that is not interesting at the moment. - -- The QP/Spy tracing is implemented as macros that are active only in the "Spy" build configuration and are inactive in the Release or Debug build configurations. This means that you can safely leave the instrumentation in the code for future maintenance, development and testing. - -- The QP/Spy trace data contains precise, high-granularity **timestamps**, so you can tie the data to the common timeline. - -- The code size of the @ref qs "target-resident component" in QP/Spy is merely a few hundred bytes, which contrasts with several kilobytes of code required by a full-blown `printf` formatter. - - -The picture below shows a typical setup for software tracing. The embedded Target system is executing instrumented code, which logs the trace data into a RAM buffer inside the Target. From that buffer the trace data is sent over a data link to a Host computer, which stores, displays, and analyzes the information. This configuration means that software tracing always requires two components: a "Target resident component" for generating and sending the trace data (@ref qs "QS" in QP/Spy™), and a "Host resident component" to receive, decompress, visualize, and analyze the data (@ref qspy "QSPY" in QP/SPy™). - -@image html qspy1.gif "Typical setup for software tracing with QP/Spy™" - -@note -Software tracing instrumentation logs interesting discrete events that occur in the target system. These discrete events will be called **trace records**, to avoid confusing them with the application-level events. - - -A good tracing solution, such as QP/Spy, is minimally intrusive, which means that it can provide visibility into the running code with minimal impact on the target system behavior. Properly implemented and used, it will let you diagnose a live system without interrupting or significantly altering the behavior of the system under investigation. - -Of course, it's always possible that the overhead of software tracing, no matter how small, will have some effect on the target system behavior, which is known as the probe effect (a.k.a. the "Heisenberg effect"). To help you determine whether that is occurring, you must be able to configure the instrumentation in and out, both at compile-time as well as at run-time. - -To minimize the "probe effect", a good trace system performs efficient, selective logging of trace records using as little processing and memory resources of the target as possible. Selective logging means that the tracing system provides user-definable, fine-granularity filters so that the target-resident component only collects events of interest, and you can filter as many or as few instrumented events as you need. That way you can make the tracing as noninvasive as necessary. - -To minimize RAM usage, the target-resident trace component typically uses a circular trace buffer that is continuously updated, and new data overwrites the old when the buffer "wraps around" due to limited size or transmission rate to the host. This reflects the typically applied last-is-best policy in collecting the trace data. In order to focus on certain periods of time, software trace provides configurable software triggers that can start and stop trace collection before the new data overwrites the old data of interest in the circular buffer. - -To further maximize the amount of data collected in the trace buffer, the Target-resident component typically applies some form of data compression to squeeze more trace information into the buffer and to minimize the bandwidth required to uplink the data to the Host. - -However, perhaps the most important characteristic of a flexible software tracing system is the separation of trace logging (what is being traced) from the data transmission mechanism (how and when exactly the data is sent to the Host). This separation of concerns allows the transmissions to occur in the least time-critical paths of the code, such as the idle loop. Also, clients should be able to employ any data transmission mechanism available on the Target, meaning both the physical transport layer (e.g., serial port, SPI, USB, Ethernet, etc.) as well as implementation strategy (polling, interrupt, DMA, etc.). The tracing facility should tolerate and be able to detect any RAM buffer overruns due to bursts of tracing data production rate or insufficient transmission rate to the host. - -Finally, the tracing facility must allow consolidating data from all parts of the system, including concurrently executing threads and interrupts. This means that the instrumentation facilities must be *reentrant* (i.e., both thread-safe and interrupt-safe). Also, to be able to correlate all this data, most tracing systems provide precise @ref qs_tstamp "time-stamping" of the trace records. - - -@subsection qpspy_rx Bi-Directional Connection to the Target -While traditional software tracing systems support only uni-directional output of trace data from the embedded Target to a Host computer, QP/Spy supports bi-directional communication to the target as well. This capability allows users to send commands and data to the Target and form the basis for @ref qutest "Unit Testing" and @ref qview "Visualization and Monitoring" of embedded Targets. - -@image html qpspy1.gif "Bi-directional data exchange between the Target and the Host" - - -@subsection qpspy_udp UDP Socket Extension -The QP/Spy system provides a @ref qspy_udp "UDP socket", which is open for communication with various Front-Ends (GUI-based or "headless"). Currently, the UDP connection point is used by the @ref qutest "QUTest" headless (console-based) front-end and the GUI-based @ref qview "QView" front-end. - - -@subsection qpspy_exa QP/Spy Session Example -To give you a better idea how QP/Spy works, the listing below shows some example output from a QP/Spy session. The left-hand side shows the raw, @ref qpspy_proto "binary output" generated by the target-resident component (@ref qs "QS"). The right-hand side shows the @ref qspy_text "human-readable format" generated from the same data by the host-resident component (@ref qspy "QSPY"). The compression ratio between the binary and textual outputs in this data sample is about 3.7. - -@image html qpspy_exa.png "Example of the QP/Spy output" - - -The following sections explain the concepts and components of QP/Spy™: -- @subpage qpspy_proto -- @subpage qs -- @subpage qspy - -@nav{gs,qpspy_proto} -*/ -/****************************************************************************/ -/*! @page qpspy_proto QP/Spy™ Data Protocol -@nav{qpspy,qs} - -

One of the greatest strengths of the QP/Spy™ tracing system is the data transmission protocol. The QP/Spy protocol is very lightweight, but contains the mechanisms for checking both data **integrity** and **continuity**. -

- -The QP/Spy™ data protocol has many elements of the High Level Data Link Control (HDLC) protocol defined by the International Standards Organization (ISO). The QP/Spy protocol has been specifically designed to simplify the data management overhead in the target, yet to allow detection of any data dropouts due to trace buffer overruns. The protocol not only has provisions for detecting gaps in the data and other errors, but it allows for instantaneous re-synchronization after any buffering or transmission error to minimize loss of useful data. - -@image html qspy6.gif "QP/Spy transmission protocol" - -The QS protocol transmits each trace record in an HDLC-like frame. The upper part of the figure above shows the serial data stream transmitted from the target containing frames of different lengths. The bottom part of the figure above shows the details of a single frame: - -1. Each frame starts with the Frame **Sequence-No** byte. The target QS component increments the Frame Sequence Number for every frame inserted into the circular buffer. The Sequence Number naturally rolls-over from 255 to 0. The Frame Sequence Number allows the QSPY host component to detect any data discontinuities. - -2. Following the Frame Sequence Number is the **Record-Type** byte, which is one of the predefined QS records, or an application-specific record. - -3. Following the Record-Type is zero or more **Data** bytes. - -4. Following the data is the **Checksum**. The Checksum is computed over the Frame Sequence Number, the Record ID, and all the Data bytes. The next section gives the detailed Checksum computation formula. - -5. Following the Checksum is the **HDLC Flag**, which delimits the frame. The HDLC flag is the `01111110` binary string (`0x7E` hexadecimal). Please note that the QP/Spy protocol uses only one HDLC Flag at the end of each frame and no HDLC Flag at the beginning of a frame. In other words, only one Flag is inserted between frames. - -The QS target component performs the HDLC-like framing described above at the time the bytes are inserted into the circular trace buffer. This means that the data in the buffer is already cleanly divided into frames and can be transmitted in any chunks, typically not aligned with the frame boundaries. - - -@section qspy_transparent Transparency -One of the most important characteristics of HDLC-type protocols is establishing very easily identifiable frames in the serial data stream. Any receiver of such a protocol can instantaneously synchronize to the frame boundary by simply finding the Flag byte. This is because the special Flag byte can never occur within the content of a frame. To avoid confusing unintentional Flag bytes that can naturally occur in the data stream with an intentionally sent Flag, HDLC uses a technique known as transparency (a.k.a. byte-stuffing or escaping) to make the Flag bytes transparent during the transmission. Whenever the transmitter encounters a Flag byte in the data, it inserts a two-byte escape sequence to the output stream. The first byte is the Escape byte, defined as binary `01111101` (hexadecimal `0x7D`). The second byte is the original byte XOR-ed with `0x20`. - -Of course, now the Escape byte itself must also be transparent to avoid interpreting an unintentional Escape byte as the two-byte escape sequence. The procedure of escaping the Escape byte is identical to that of escaping the Flag byte. - -The transparency of the Flag and Escape bytes complicates slightly the computation of the Checksum. The transmitter computes the Checksum over the Frame Sequence Number, the Record-Type, and all Data bytes before performing any “byte-stuffing”. The receiver must apply the exact reversed procedure of performing the “byte-un-stuffing” before computing the Checksum. - -An example may make this clearer. Suppose that the following trace record needs to be inserted into the trace buffer (the transparent bytes are shown in in `code` format): - -     Record-Type = `0x7D`, Record Data = `0x7D` 0x08 0x01 - -Assuming that the current Frame Sequence Number is, say `0x7E`, the Checksum will be computed over the following bytes: - -     Checksum == (uint8_t)(~(0x7E + `0x7D` + `0x7D` + 0x08 + 0x01)) == 0x7E - -and the actual frame inserted into the QS trace buffer will be as follows: - -     0x7D `0x5E` 0x7D `0x5D` 0x7D `0x5D` 0x08 0x01 0x7D `0x5E` 0x7E - -@note -This is a degenerate example, where the Frame Sequence Number, the Record-Type, a Data byte, and the Checksum itself turned out to be the transparent bytes. A more typical overhead of transparency with real trace data is one escape sequence per several trace records. - - -@section qpspy_endianness Endianness -In addition to the HDLC-like framing, the QS transmission protocol specifies the endianness of the data to be little-endian. All multi-byte data elements, such as 16-, 32-, or 64-bit integers, pointers, and floating point numbers are inserted into the QS trace buffer in the little-endian byte order (least-significant byte first). The QS data inserting macros place the data in the trace buffer in a platform-neutral manner, meaning that the data is inserted into the buffer in the little-endian order regardless of the endianness of the CPU. Also, the data-inserting macros copy the data to the buffer one byte at a time, thus avoiding any potential data misalignment problems. Many embedded CPUs, such as ARM, require certain alignment of 16-, 32-, or 64-bit quantities. - - -@section qpspy_last_is_best Last-is-Best Data Policy -The QS Trace Buffers (transmit QS buffer and receive QS-RX buffer) store only complete HDLC frames, which is the pivotal point in the design of the QS target component and has two important consequences. - -First, the use of HDLC frames in the buffers enables the last is best tracing policy. The QS transmission protocol maintains both the Frame Sequence Number and the Checksum over each trace record, which means that any data corruption caused by overrunning the old data with the new data can be always reliably detected. Therefore, the new trace data is simply inserted into the circular trace buffers, regardless if it perhaps overwrites the old data that hasn't been sent out yet, or is in the process of being sent. The burden of detecting any data corruption is placed on the QSPY host component. When you start missing frames (which the host component easily detects by discontinuities in the Frame Sequence Number), you have several options. You can apply some additional filtering, increase the size of the buffer, or improve the data transfer throughput. - -Second, the use of HDLC-formatted data in the trace buffers allows decoupling data insertion into the trace buffers from data removal out of the trace buffers. You can simply remove the data in whichever chunks you like, without any consideration for frame boundaries. You can employ just about any available physical data link available on the target for transferring the trace data from the target to the host. - -@nav{qpspy,qs} -*/ diff --git a/doxygen/qs.dox b/doxygen/qs.dox deleted file mode 100644 index e8927fb..0000000 --- a/doxygen/qs.dox +++ /dev/null @@ -1,339 +0,0 @@ -/*! @page qs QS Target Component -@nav{qpspy_proto,qspy} - -

The target-resident component of the QP/Spy™ tracing system is called **QS**. The purpose of QS is to provide facilities for **instrumenting** the target code so it will produce an interesting real-time trace from code execution. In this sense it is similar to peppering the code with `printf` statements. However, the main difference between QS and `printf` is *where* the data **formatting** and **sending** is done. When you use `printf`s, the data formatting and sending occur in the time-critical paths through your embedded code. In contrast, the QS target-resident component inserts raw binary data into the QS ring buffer, so all the time-consuming formatting is removed from the Target system and is done *after* the fact in the Host. Additionally, in QS, data logging and sending to the Host are separated so that the target system can typically perform the transmission outside of the time-critical path, for example in the *idle processing* of the target CPU. -

- -The QS target component consists of the QS ring buffer, the QS filters, as well as the instrumentation added to the QP framework and the application, as shown in figure below. Additionally, the QS target component contains the receive-channel (@ref qs_rx "QS-RX") with its own receive buffer, which can receive data from the QSPY host component. - -@anchor fig_struct -@image html qspy5.gif "Structure of the QP/Spy software tracing system" - -A nice byproduct of removing the data formatting from the Target is a natural **data compression**. For example, formatted output of a single byte takes two hexadecimal digits (and 3 decimal digits), so avoiding the formatting gives at least a factor of two in data density. On top of this natural compression, QS uses such techniques as data dictionaries, and compressed format information, which in practice result in a compression factor of 4-5 compared to the expanded human-readable format. - -@attention -The QS instrumentation is designed such that it is active only in the *Spy build configuration* (when the external macro #Q_SPY is defined) and is **inactive** otherwise. This means that you don't need to comment-out or remove the instrumentation in the Debug or Release build configurations, but rather you can **leave** the instrumentation in your code for its future development, testing, profiling and maintenance. - - -@section qs_tstamp Target Time-Stamps -Most QS trace records produced by QS are **time-stamped** with a high-resolution counter (the resolution depends on the availability of a hardware timer-counter in the Target, but typically provides sub-microsecond granularity). QS provides an efficient API for obtaining platform-specific timestamp information. Given the right timer-counter resource in your Target system, you can provide QS with as precise timestamp information as required. The size of the timestamp is configurable to be 1, 2, or 4 bytes (see #QS_TIME_SIZE). - -@note -The QS **timestamps** are used differently in @ref qutest "QUTest™" unit testing. In that case the timestamps are used to count the QS records produced. - - - -@section qs_pre Predefined QS Trace Records -The QP/C and QP/C++ frameworks contain the QS instrumentation for tracing the interesting occurrences within the frameworks, such as state machine activity (dispatching events, entering/exiting a state, executing transitions, etc.), active object activity (allocating events, posting/publishing events, time events, etc.), and more. All this instrumentation reserves 100 **predefined** QS trace records, which are enumerated in ::QSpyRecords. These QS records have predefined (hard-coded) structure both in the QS target-resident component and in the @ref qspy "QSPY" host-based application. See also the documentation of the @ref qspy_pre "human-readable output" generated from the predefined QS records. - - - -@section qs_app Application-Specific QS Trace Records -In addition to the predefined QS records, you can add your own, flexible, **application-specific** trace records, which are not known in advance to the @ref qspy "QSPY" host-resident component. You can think of the application-specific records as an equivalent to `printf()` but with much less overhead. The following code snippet shows an example of an application-specific QS record from your embedded code: - -@code -enum MyAppRecords { - PHILO_STAT = QS_USER, /* offset for User QS Records */ - COMMAND_STAT, - ~ ~ ~ -}; -~ ~ ~ -QS_BEGIN_ID(PHILO_STAT, AO_Philo[n]->prio) /* application-specific record begin */ - QS_U8(1, n); /* application-specific data element (Philo number) */ - QS_STR(stat); /* application-specific data element (Philo status) */ -QS_END() /* application-specific record end */ -@endcode - -As you can see from the example above, an application-specific trace record always begins with QS_BEGIN_ID(), followed by a number of @ref qs_app_el "application-specific data elements", followed by QS_END(). - -@attention -The application-specific records use the 25 @ref qpspy_proto "Record-Types" in the range #QS_USER .. 124 (see also User-All group in @ref qs_global "Global Filter"). Therefore, you need to **offset** your application-specific trace records by the #QS_USER constant to avoid overlap with the @ref qs_pre "predefined QS records" already instrumented into the QP components. - -@note -As with all QS trace records, the application-specific records are produced in a critical section of code (with interrupts disabled). Therefore, you should keep the number of @ref qs_app_el "application-specific data elements" of the record reasonably short. - - -@subsection qs_app_rep Application-Specific Record Representation -The biggest challenge in supporting flexible "application-specific" trace records is to provide the data type information with the data itself, so that @ref qspy "QSPY" "knows" how to parse such records and move on to the next data element within the record. The figure below shows the encoding of the application-specific trace record from the previous listing. - -@image html qspy_app.gif "Structure of an Application-Specific trace record" - -The application-specific trace record, like all @ref qpspy_proto "QS records", starts with the Sequence Number and the -Record-Type. Every application-specific trace record also contains the @ref qs_tstamp "timestamp" immediately following the Record Type. The number of bytes used by the timestamp is configurable by the macro #QS_TIME_SIZE. After the timestamp, you see the data elements, such as a byte (QS_U8()) and a string (QS_STR()). Each of these data elements starts with a fmt (format) byte, which actually contains both the data-type information (in the lower nibble) and the format width for displaying that element (in the upper nibble). For example, the data element QS_U8(1, n) will cause the value 'n' to be encoded as u`int8_t` with the format width of 1 decimal digit. - -@remark -The maximum allowed format width is 15 decimal digits, while a format width of 0 means that a numeric value should be formatted in the minimum number of digits. - - -As shown in the listing above, typically the application-specific records are enclosed with the QS_BEGIN_ID() / QS_END() pair of macros. This pair of macros disables interrupts at the beginning and enables them again at the end of each record. Occasionally you might want to generate trace data from within already-established critical sections or ISRs. In such rare occasions, you would use the macros QS_BEGIN_NOCRIT() / QS_END_NOCRIT() to avoid nesting of critical sections. - -The record-begin macro QS_BEGIN_ID() takes two arguments. The first argument (e.g., `PHILO_STAT`) is the enumerated @ref qpspy_proto "Record-Type", which is used in the @ref qs_global "global filter" and is part of each record header. - -The second argument (e.g., `AO_Philo[n]->prio` in the example above) is used for the @ref qs_local "local filter", which allows you to selectively log only specific objects. The code snippet shows an example of an application-specific trace record, including use of the second parameter of the QS_BEGIN_ID() macro. - - -@subsection qs_app_exa Application-Specific Record Examples -The following examples show the QS application-specific trace records as C code on the left, and the output generated by the @ref qspy "QSPY" host application from these records on the right. The examples assume that the @ref qs_dict "QS dictionaries" have been produced for the Record-Types and function/object pointers used. - - - - - - - - - - - - - - - - - - - - - - - - - - -
Trace RecordQSPY output
-@code -QS_BEGIN_ID(PHILO_STAT, AO_Philo[n]->prio) - QS_U8(1, n); - QS_STR(stat); -QS_END() -@endcode - -`1018004718 PHILO_STAT 1 thinking`
-NOTE: produced only when `AO_Philo[n]` is enabled in the @ref qs_local "QS Local Filter" -
-@code -QS_BEGIN_ID(IO_CALL, 0U) - QS_FUN(&IO_Read); - QS_I16(0, ret); - QS_U32(0, offset); -QS_END() -@endcode - -`1055004424 IO_CALL IO_Read -129 0` -
-@code -QS_BEGIN_ID(DATA_RX, 0U) - QS_OBJ(me); - QS_U16(data_len); - QS_MEM(data_buf, 16); -QS_END() -@endcode - -`0207024814 DATA_RX l_uart2 10 17 84 BB 40 FD 15 00 00 99 0B 00 00 90 0D 00 20` -
-@code -QS_BEGIN_ID(FP_DATA, QS_AP_ID + 1U) - QS_F32(6, 3141.5F); - QS_F64(10, -2.718281828e5); -QS_END() -@endcode - -`0991501750 FP_DATA 3.141500e+003 -2.7182818280e+005`
-NOTE: produced only when QS-ID `QS_AP_ID + 1` is enabled in the @ref qs_local "QS Local Filter" -
- - -@subsection qs_app_el Application-Specific Data Elements -The following table summarizes the supported data elements that can be used inside the Application-Specific trace records: - -
-Data Element | Example | Comments -----------------|-----------------|--------- -QS_U8() | `QS_U8(0, n);` | Outputs a `uint8_t` integer with format `"%u"` -QS_I8() | `QS_I8(3, m);` | Outputs a `int8_t` integer with format `"%3d"` -QS_U16() | `QS_U16(5, n);` | Outputs a `uint16_t` integer with format `"%5u"` -QS_I16() | `QS_I16(0, m);` | Outputs a `int16_t` integer with format `"%d"` -QS_U32() | `QS_U32(QS_HEX_FMT, n);` | Outputs a `uint32_t` integer with format `"%8X"` -QS_I32() | `QS_I32(0, m);` | Outputs a `int32_t` integer with format `"%d"` -QS_U64() | `QS_U32(0, n);` | Outputs a `uint32_t` integer with format `"%2"PRIi64` -QS_F32() | `QS_F32(0, 3.1415F);` | Outputs a 32-bit `float` with format `"%7.0e"`
(zero digits after the comma) -QS_F64() | `QS_F64(4, sqrt(2.0));` | Outputs a 64-bit `double` with format `"%12.4e"`
(4 digits after the comma) -QS_STR() | `QS_STR("Hello")` | Outputs a zero-terminated string with format `"%s"` -QS_MEM() | `QS_MEM(&my_struct, 16)` | Outputs 16 bytes of memory starting from `&my_struct`.
The bytes are output using the hex format `"%02X"` -QS_OBJ() | `QS_OBJ(&my_obj);` | Outputs an object pointer.
If an object dictionary for the object exists,
@ref qspy "QSPY" will display the symbolic name of the object -QS_FUN() | `QS_OBJ(&foo);` | Outputs a function pointer.
If a function dictionary for the function exists,
@ref qspy "QSPY" will display the symbolic name of the function -QS_SIG() | `QS_SIG(TIMEOUT_SIG, (void*)0);` | Outputs a signal.
If signal dictionary for the signal exists,
@ref qspy "QSPY" will display the symbolic name of the signal -
- - -@section qs_filters QS Filters -Obviously, QS cannot completely eliminate the overhead of software tracing. But with the fine-granularity __filters__ available in QS, you can make this impact as small as necessary. For greatest flexibility, QS uses two complementary levels of filters: @ref qs_global "Global Filter" and @ref qs_local "Local Filter" described below. The combination of such two complementary filtering criteria results in very selective tracing capabilities. - -@note -The Global and Local filters are initialized in the QS_INIT() macro. Subsequently, the QP application can change the filters __at runtime__ by means of the QS_GLB_FILTER() and QS_LOC_FILTER() macros. Also, if the QS receive channel is enabled (@ref qs_rx "QS-RX"), the filters can be changed from the @ref qutest "QUTest" or @ref qview "QView" front-ends. - - -@subsection qs_global Global Filter -The Global Filter is based on trace @ref qpspy_proto "Record-Types" associated with each QS record (see ::QSpyRecords). This filter allows you to disable or enable each individual Record-Type or a whole group of QS records. For example, you might enable or disable #QS_QEP_STATE_ENTRY (entry to a state), #QS_QEP_STATE_EXIT (exit from a state), #QS_QEP_INIT_TRAN (state transition), #QS_QF_ACTIVE_POST (event posting), #QS_QF_PUBLISH (event publishing), and all other pre-defined and application-specific event types. This level works globally for all state machines, active objects, and time event objects in the entire system. - -QS provides a simple interface, QS_GLB_FILTER(), for setting and clearing individual Record-Types as well as groups of Record-Types in the Target code. The following table summarizes the Record-Types and groups of Record-Types that you can use as arguments to QS_GLB_FILTER(). - -
-
-Record-Type
/Group | Example | Applies to QS Records -----------------|---------|---------------------- -All Record-Types | QS_GLB_FILTER(QS_ALL_RECORDS);
QS_GLB_FILTER(-QS_ALL_RECORDS); | all Record-Types -State
Machine
Group | QS_GLB_FILTER(QS_SM_RECORDS);
QS_GLB_FILTER(-QS_SM_RECORDS); | #QS_QEP_STATE_ENTRY,
#QS_QEP_STATE_EXIT,
#QS_QEP_STATE_INIT,
#QS_QEP_INIT_TRAN,
#QS_QEP_INTERN_TRAN,
#QS_QEP_TRAN,
#QS_QEP_IGNORED,
#QS_QEP_TRAN_HIST,
#QS_QEP_TRAN_EP,
#QS_QEP_TRAN_XP -Active
Object
Group | QS_GLB_FILTER(QS_AO_RECORDS);
QS_GLB_FILTER(-QS_AO_RECORDS); | #QS_QF_ACTIVE_SUBSCRIBE,
#QS_QF_ACTIVE_UNSUBSCRIBE,
#QS_QF_ACTIVE_POST,
#QS_QF_ACTIVE_POST_LIFO,
#QS_QF_ACTIVE_GET,
#QS_QF_ACTIVE_GET_LAST -Event
Queue
Group | QS_GLB_FILTER(QS_EQ_RECORDS);
QS_GLB_FILTER(-QS_EQ_RECORDS); | #QS_QF_EQUEUE_POST,
#QS_QF_EQUEUE_POST_LIFO,
#QS_QF_EQUEUE_GET,
#QS_QF_EQUEUE_GET_LAST -Memory
Pool
Group | QS_GLB_FILTER(QS_MP_RECORDS);
QS_GLB_FILTER(-QS_MP_RECORDS); | #QS_QF_MPOOL_GET,
#QS_QF_MPOOL_PUT -Time
Event
Group | QS_GLB_FILTER(QS_TE_RECORDS);
QS_GLB_FILTER(-QS_TE_RECORDS); | #QS_QF_TICK,
#QS_QF_TIMEEVT_ARM,
#QS_QF_TIMEEVT_AUTO_DISARM,
#QS_QF_TIMEEVT_DISARM_ATTEMPT,
#QS_QF_TIMEEVT_DISARM,
#QS_QF_TIMEEVT_REARM,
#QS_QF_TIMEEVT_POST -QF Group
Event
Management| QS_GLB_FILTER(QS_QF_RECORDS);
QS_GLB_FILTER(-QS_QF_RECORDS); | #QS_QF_NEW,
#QS_QF_NEW_ATTEMPT,
#QS_QF_GC_ATTEMPT,
#QS_QF_GC,
#QS_QF_TIMEEVT_DISARM_ATTEMPT,
#QS_QF_TICK,
-Scheduler
Group | QS_GLB_FILTER(QS_SC_RECORDS);
QS_GLB_FILTER(-QS_SC_RECORDS); | #QS_SCHED_LOCK,
#QS_SCHED_UNLOCK,
#QS_SCHED_NEXT,
#QS_SCHED_IDLE,
#QS_SCHED_RESUME,
#QS_QF_TIMEEVT_DISARM_ATTEMPT,
#QS_QF_TICK,
-User Group-0 | QS_GLB_FILTER(QS_U0_RECORDS);
QS_GLB_FILTER(-QS_U0_RECORDS); | #QS_USER+0 .. #QS_USER+4 -User Group-1 | QS_GLB_FILTER(QS_U1_RECORDS);
QS_GLB_FILTER(-QS_U1_RECORDS); | #QS_USER+5 .. #QS_USER+9 -User Group-2 | QS_GLB_FILTER(QS_U2_RECORDS);
QS_GLB_FILTER(-QS_U2_RECORDS); | #QS_USER+10 .. #QS_USER+14 -User Group-3 | QS_GLB_FILTER(QS_U3_RECORDS);
QS_GLB_FILTER(-QS_U3_RECORDS); | #QS_USER+15 .. #QS_USER+19 -User Group-4 | QS_GLB_FILTER(QS_U4_RECORDS);
QS_GLB_FILTER(-QS_U4_RECORDS); | #QS_USER+20 .. #QS_USER+24 -User-All Group | QS_GLB_FILTER(QS_UA_RECORDS);
QS_GLB_FILTER(-QS_UA_RECORDS); | #QS_USER+0 .. #QS_USER+24 -Non-Maskable | | #QS_SIG_DICT,
#QS_OBJ_DICT,
#QS_FUN_DICT,
#QS_USR_DICT,
#QS_TARGET_INFO,
#QS_TARGET_DONE,
#QS_EMPTY,
#QS_TEST_PAUSED,
#QS_TEST_PROBE_GET,
#QS_RX_STATUS,
#QS_QUERY_DATA,
#QS_PEEK_DATA,
#QS_ASSERT_FAIL,
#QS_QF_RUN -
-
- -@attention -The QS Global Filter is initialized in the QS_INIT() macro to __all OFF__. - - -Here are some examples of setting and clearing the QS Global Filter with QS_GLB_FILTER(): - -@code{c} -void BSP_init(int argc, char *argv[]) { - ~ ~ ~ - if (!QS_INIT(argv)) { /* Initialize QS target component */ - Q_ERROR(); /* unable to initialize QSpy */ - } - ~ ~ ~ - /* apply the QS Global Filter... */ - QS_GLB_FILTER(QS_QF_RECORDS); /* turn QF-group ON */ - QS_GLB_FILTER(-QS_QF_TICK); /* turn #QS_QF_TICK OFF */ - ~ ~ ~ -} -@endcode - - -@subsection qs_local Local Filter -The Local Filter is based on __QS-IDs__ associated with various objects in the Target memory. The __QS-IDs__ are small integer numbers, such as the unique __priorities__ assigned to QP Active Objects, but there are more such QS-IDs which _you_ can assign to various objects. Then, you can set up the QS Local Filter to trace only a specific groups of such QS-IDs. - -The main use case for QS Local Filter is an application where certain active objects are very "noisy", and would overwhelm your trace. The QS Local Filter allows you to silence the "noisy" active objects and let the others through. - -Please note that the @ref qs_global "QS Global Filter" will not do the trick, because you don't want to suppress all QS records of a given Record-Type. Instead, you want to suppress only __specific objects__. - -QS provides a simple interface, QS_LOC_FILTER(), for setting and clearing individual QS-IDs as well as groups of QS-IDs in the Target code. The following table summarizes the QS-IDs and groups of QS_IDs that you can use as arguments to QS_LOC_FILTER(). - - -
-QS-ID
/Group| Range | Example | Comments ----------------|---------|--------------------|------------- -0 | 0 | | always enabled -#QS_AO_IDS | 1..64 | QS_LOC_FILTER(QS_AO_IDS);
QS_LOC_FILTER(-QS_AO_IDS);
QS_LOC_FILTER(6);
QS_LOC_FILTER(-6);
QS_LOC_FILTER(AO_Table->prio)| Active Object priorities -#QS_EP_IDS | 65..80 | QS_LOC_FILTER(QS_EP_ID + 1U); | enable Event-Pool #1 -#QS_EQ_IDS | 81..96 | QS_LOC_FILTER(QS_EQ_ID + 1U); | enable Event-Queue #1 -#QS_AP_IDS | 97..127 | QS_LOC_FILTER(QS_AP_ID + 1U); | enable Application Specific QS_ID -
- -@attention -The QS Local Filter is initialized in the QS_INIT() macro to __all ON__. - - -Here are some examples of setting and clearing QS Local Filter with QS_LOC_FILTER(): - -@code{c} -void BSP_init(int argc, char *argv[]) { - ~ ~ ~ - if (!QS_INIT(argv)) { /* Initialize QS target component */ - Q_ERROR(); /* unable to initialize QSpy */ - } - ~ ~ ~ - /* apply the QS Local Filter... */ - QS_LOC_FILTER(-QS_EP_IDS); /* turn EP (Event-Pool) group OFF */ - QS_LOC_FILTER(3); /* turn AO with prioity 3 ON */ - QS_LOC_FILTER(AO_Table->prio); /* turn AO_Table ON */ - ~ ~ ~ -} -@endcode - - -@section qs_curr Current Objects -QS maintains a set of **Current Objects** to which it applies commands received through the @ref qs_rx "QS-RX channel". For example, the event-post operation is applied to the current Active Object, while the peek/poke/fill operations are applied to the current Application Object. QS maintains the following Current Objects: -- ::SM_OBJ — State Machine object -- ::AO_OBJ — Active Object object -- ::MP_OBJ — Memory Pool object -- ::EQ_OBJ — Event Queue object -- ::TE_OBJ — Time Event object - -@note -Current Objects can be set only by sending commands to the @ref qs_rx "QS-RX receive channel". - - -@section qs_dict QS Dictionaries -By the time you compile and load your application image to the Target, the symbolic names of various objects, function names, and event signal names are stripped from the code. Therefore, if you want to have the symbolic information available to the @ref qspy "QSPY" host-resident component, you need to supply it somehow to the software tracing system. - -The QS Target-resident component provides special **dictionary trace records** designed expressly for providing the symbolic information about the target code in the trace itself. These "dictionary records" are very much like the symbolic information embedded in the object files for the traditional single-step debugger. QS can supply four types of dictionary trace records: - -- object dictionary ( QS_OBJ_DICTIONARY() ) -- function dictionary ( QS_FUN_DICTIONARY() ) -- signal dictionary ( QS_SIG_DICTIONARY() ) -- user dictionary ( QS_USR_DICTIONARY() ) -- enumeration dictionary ( QS_ENUM_DICTIONARY() ) - -The dictionary trace records are typically generated during the system initialization and this is the only time they are sent to the @ref qspy "QSPY" host component. It is **your** responsibility to code them in (by means of the `QS_???_DICTIONARY()` macros). The following code snippet provides some examples of generating QS dictionaries: - - -@code{c} -void BSP_init(int argc, char *argv[]) { - ~ ~ ~ - if (!QS_INIT(argv)) { /* Initialize QS target component */ - Q_ERROR(); /* unable to initialize QSpy */ - } - - /* dictionaries... */ - QS_OBJ_DICTIONARY(&myObject); - QS_OBJ_DICTIONARY(AO_Table); /* opaque pointer */ - QS_FUN_DICTIONARY(&myFun); - QS_SIG_DICTIONARY(TIMEOUT_SIG, (void*)0); - - QS_USR_DICTIONARY(ON_TEST_SETUP); - QS_USR_DICTIONARY(ON_TEST_TEARDOWN); - - QS_ENUM_DICTIONARY(COMMAND_X, QS_CMD); /* for command */ - ~ ~ ~ -} -@endcode -
- -@remarks -The dictionary trace records are not absolutely required to generate the human-readable output, in the same way that the symbolic information in the object files is not absolutely required to debug your code. However, in both cases, the availability of the symbolic information greatly improves productivity in working with the software trace or the debugger. - - -@section qs_rx QS-RX Receive-Channel -The QS target component contains the receive-channel (QS-RX), which can receive data from the @ref qspy "QSPY" host application. The QS-RX channel provides the following services: -- Remotely reset the Target -- Request target information (version, all sizes of objects, build time-stamp) -- Execute a user-defined command inside the Target with arguments supplied from @ref qspy "QSPY" -- Inject an arbitrary event to the Target (dispatch, post or publish) -- Set @ref qs_global "QS Global Filter" inside the Target -- Set @ref qs_local "QS Local Filter" inside the Target -- Set @ref qs_curr "current QS object" inside the Target -- Peek data inside the Target and send to @ref qspy "QSPY" -- Poke data (supplied from @ref qspy "QSPY") into the Target -- Fill a specified memory area in the Target with a bit pattern supplied from @ref qspy "QSPY" -- Execute clock tick inside the Target -- Execute test setup inside the Target -- Execute test teardown inside the Target -- Store a @ref qutest_fixture-probe "Test Probe" supplied from @ref qspy "QSPY" inside the Target - -@note -The QS-RX channel is the backbone for interacting with the target system and implementing such features as @ref qutest "Unit Testing" and @ref qview "Visualization/Monitoring" of the target system. - -@nav{qpspy_proto,qspy} -*/ diff --git a/doxygen/qspy.dox b/doxygen/qspy.dox deleted file mode 100644 index 8aeee71..0000000 --- a/doxygen/qspy.dox +++ /dev/null @@ -1,1508 +0,0 @@ -/*! @page qspy QSPY Host Application -@nav{qs,qspy_text} - -@section qspy_about About QSPY -

As described in the @ref qpspy "previous section", **QSPY** is the host-resident component in the QP/Spy software tracing system. QSPY is a simple console application without a GUI, because its main purpose is to provide @ref qspy_link "communication" with the @ref qs "QS target-resident component", parsing of the @ref qpspy_proto "QP/Spy Data Protocol", and displaying the data in a simple @ref qspy_text "human-readable format". -

- -![QSPY host application](qspy.png) - - -QSPY can also export the data in various other formats, such as a format suitable for @ref qspy_matlab "MATLAB/GNU-Octave", and a format suitable for generating @ref qspy_seq "sequence diagrams". Additionally, QSPY can also save the symbolic information about the Target objects in the form of @ref qspy_dict "QSPY dictionaries". An example of a @ref qpspy_exa "QSPY session" is shown in the Introduction to QP/Spy. - -Finally, QSPY also supports an extensible @ref qspy_udp "UDP-socket" connection, which allows it to serve as a "Back-End" for attaching various "Front-Ends" (such as the @ref qutest "QUTest" Front-End and @ref qview "QView" Front-End). - -@remark -QSPY is written in portable C with ports to Windows and POSIX (Linux, macOS) provided. QSPY is also designed to be adaptable to various target-host communication links. Out of the box, the QSPY host application supports serial (RS232), TCP/IP, and file communication links. Adding other communication links is straightforward, because the data link is accessed only through a generic Platform Abstraction Layer (PAL). - - -@section qspy_command QSPY Command-Line Parameters -

The QSPY application accepts several command-line parameters to configure the data link to the Target, backwards-compatibly with previous versions, and target dependencies, such as pointer sizes, signal sizes, etc. This means that the single QSPY host application can process data from any Target running the QS component. QSPY has been tested with a wide range of 8-, 16-, 32-, and 64-bit CPUs. -

- -The general form of invoking QSPY is as follows: - -@verbatim -qspy [options] -@endverbatim - -where `options` are described in the following table: - -@verbatim -Usage: qspy [options] = required, [arg] = optional -@endverbatim - - -
Option Example Default (key) Must match
QP macro
Comments -
-h -h (key-h) Help. Prints the summary of options -
-q [num] -q 99 (key-q) Quiet mode (reduced stdout output) -
-u [UDP_port|0] -u 7701 UDP socket for "Front-Ends".
`-u0` suppresses opening the UDP socket -
-v <QS_version> -v 6.2 7.0 Enforce backwards-compatibility with the specific QS version -
-r <c0|c1|c2> -r c2 c1 Rendering options (c0=no-color|c1-color1|c2-color2) -
-k -k suppress keyboard input -
-o -o (key-o) Produce output to the specified file -
-s -s (key-s) Save the binary input to a file. Not compatible with `-f` -
-m -m (key-m) Produce @ref qspy_matlab "MATLAB/GNU-Octave output" to a file -
-g [object-list] -g obj1,obj2 (key-g) Produce @ref qspy_seq "Sequence diagram output" to a file -
-t [TCP-port] -t 6601 TCP/IP input selection. Not compatible with `-c`, `-b`, `-f` -
-c <port> -c COM2 COM1 COM port selection. Not compatible with `-t`, `-p`, `-f` -
-b <baud> -b 38400 115200 Baud rate selection. Not compatible with `-t`, `-p`, `-f` -
-f <file> -f qs.spy File input selection. Not compatible with `-c`, `-b`, `-t`, `-p` -
-d [file] -d my_app.dic Read @ref qspy_dict "dictionaries" from a file. -
Options for configuring Target object sizes: -The Target can **report** its configuration to QSPY, which means that you don't need to provide any upper-case options (such as: `-T`, `-O`, `-F`, etc.). -
Option Example Default (key) Must match QP macro Comments -
-T <size> -T 2 4 `QS_TIME_SIZE` Time stamp size in bytes. Valid values: 1, 2, 4 -
-O <size> -O 2 4 `QS_OBJ_PTR_SIZE` Object pointer size in bytes. Valid values: 1, 2, 4, 8 -
-F <size> -F 2 4 `QS_FUN_PTR_SIZE` Function pointer size in bytes. Valid values: 1, 2, 4, 8 -
-S <size> -S 1 2 `Q_SIGNAL_SIZE` Signal size in bytes. Valid values: 1, 2, 4 -
-E <size> -E 1 2 `QF_EVENT_SIZ_SIZE` Event-size size in bytes (i.e., the size of variables that hold - event size). Valid values: 1, 2, 4 -
-Q <size> -Q 2 1 `QF_EQUEUE_CTR_SIZE` Queue counter size in bytes. Valid values 1, 2, 4 -
-P <size> -P 4 2 `QF_MPOOL_CTR_SIZE` Pool counter size in bytes. Valid values: 1, 2, 4 -
-B <size> -B 1 2 `QF_MPOOL_SIZ_SIZE` Block size size in bytes. (i.e., the size of variables that hold - memory block size). Valid values 1, 2, 4 -
-C <size> -C 2 4 `QF_TIMEEVT_CTR_SIZE` Time event counter size. Valid values: 1, 2, 4 -
- - -Your main concern when invoking QSPY is to match exactly the target system you are using. The fourth column of the table above lists the configuration macros used by the target system as well as the platform-specific QP header files where those macros are defined. You need to use the corresponding QSPY command-line option only when the QP macro differs from the default. The default values assumed by QSPY are consistent with the defaults used in QP. - -@note -When you do not match the QSPY host application with the QS target -component, the QSPY application will be unable to parse correctly the -mismatched trace records and will start generating the following errors:
-
-@verbatim - ~ ~ ~ - ERROR 4 bytes unused in Rec=QS_QEP_INTERN_TRAN - ~ ~ ~ - ERROR 2 bytes unused in Rec=QS_QEP_DISPATCH -@endverbatim -
-The name after `Rec=` indicates the Record ID of the trace record that failed to be parsed. - - -@subsection qspy_default Default Configuration -The QSPY application invoked **without any parameters** defaults to the following configuration: - -@verbatim -C:\tmp>qspy -QSPY 6.6.0 Copyright (c) 2005-2019 Quantum Leaps -Documentation: https://www.state-machine.com/qtools/qspy.html -Current timestamp: 190811_124028 --u 7701 --t 6601 --v 660 --T 4 --O 4 --F 4 --S 2 --E 2 --Q 1 --P 2 --B 2 --C 2 -@endverbatim - -Specifically, by default QSPY **opens the UDP socket** at the default port (`-u 7701`) for "back-ends" (such as @ref qutest "QUTest") and **opens the TCP/IP socket** at the default port (`-t 6601`) for communication with the Targets. - - -The other parameters correspond to 32-bit Target CPUs, such as ARM and x86 compiled in 32-bit mode. The x86 is relevant for running the embedded software on host machines based on x86 processors. - -@remark -The default QSPY configuration is specifically designed for running @ref qutest "QUTest" tests on x86-based hosts with target executables compiled in 32-bit x86 mode. This default configuration also matches 32-bit ARM CPUs, but typically requires the single `-c ` parameter to communicate with the embedded Target via a serial port.
-
-The default QSPY configuration (without any parameters) is also backwards-compatible with the following invocation: `qspy -u -t`, which is recommended for running QUTest tests on the host computer. Starting with QSPY version 7.x.y, you can use the simpler `qspy` invocation. - - -@section qspy_terminating Terminating QSPY -The QSPY host application can be terminated in the following ways: - -- by typing `x` or `X` key (works only in the absence of the __-k__ @ref qspy_command "command-line option") -- by typing `Esc` key (works only in the absence of the __-k__ @ref qspy_command "command-line option") -- by typing `Ctrl-C` (works also with the `-k` option) -- by sending the Kill signal to the process running QSPY. - - -@section qspy_keyboard QSPY Keyboard Commands -In the __absence of the -k (suppress keyboard) command-line option__, the QSPY console application accepts keyboard input. The following table shows the currently supported key-strokes: - - -Key | Action -----|--------- -`<Esc>` | Exit QSPY -`h` | display keyboard help and QSPY status -`c` | clear the screen -`q` | toggle quiet mode (no Target output to the screen) -`r` | send RESET command to the Target -`i` | send INFO request to the Target (see also @ref qspy_dict) -`t` | send TIKC[0] command to the Target -`u` | send TICK[1] command to the Target -`d` | save @ref qspy_dict "QP/Spy Dictionaries" to a file -`o` | toggle @ref qspy_text "QSPY Human-Readable Output" to a file (open/close) -`s`/`b` | toggle binary file output (open/close) -`m` | toggle @ref qspy_matlab "MATLAB Output" to a file (open/close) -`g` | toggle @ref qspy_seq "Sequence Output" to a file (open/close) - - -
-@note -QSPY can send many more sophisticated commands to the Target by means of the @ref qview "Front-End extension mechanism". - - -@section qspy_link QSPY Communication with the Target -QSPY currently provides the following communication links to the @ref qs "QS target-resident component": - - -Communication Link | Command-Line Option -:------------------|:-------------------- -TCP/IP | `-t [TCP_port]` (default) -Serial port | `-c ` and `-b` -Binary File | `-f ` -Other link
(e.g., JTAG debug probe) | can be added to the QSPY Platform Abstraction Layer - - -@section qspy_saving Saving Files from QSPY - -QSPY can save the tracing data from the Target in various formats into files. QSPY assigns file names **automatically**. Also, QSPY can open/close various files multiple times in a single session, so it is no longer necessary to exit QSPY and launch it again with different command-line parameters to save data to a different file. - -@attention -QSPY saves all files into the current directory from which `qspy` has been launched. - -QSPY uses a very simple naming convention to assign file names. All names start with `qspy`, where the time-stamp format is: `YYMMDD_hhmmss`, where `YY` is 2-digit year, `MM` is a 2-digit month, `DD` is a 2-digit day of the month, `hh` is a 2-digit hour, `mm` is a 2-digit minute, and `ss` is a 2-digit second. The time-stamp is accurate to a one second, so it's virtually impossible to have name conflicts for files generated on the same machine. The various types of files are distinguished by the following extensions: - -Command-Line
Option | Keyboard
Option| File
Extension | Example | Comment -:-------------------:|:-----------------:|:-------------------:|----------|---------- -`-o` | `o` | `.txt` | `qspy150914_132234.txt`| @ref qspy_text "text (screen) output" -`-s` | `s` | `.qs` | `qspy150914_132234.qs` | @ref qpspy_proto "raw binary output" -`-d` | `d` | `.dic` | `qspy150901_101203.dic` | @ref qspy_dict "dictionary output" -`-m` | `m` | `.mat` | `qspy150914_132234.mat` | @ref qspy_matlab "MATLAB output" -`-g` | `g` | `.seq` | `qspy150914_132234.seq` | @ref qspy_seq "Sequence diagram output" - -@note -All files except the dictionary output are time-stamped with the local time of the Host. The **dictionary** output is time-stamped with the build-time of the Target image. - - -The following sub-sections explain the following QSPY features: - -- @subpage qspy_text "text (screen) output" -- @subpage qspy_dict "dictionary output" -- @subpage qspy_udp "UDP socket interface" -- @subpage qspy_seq "Sequence diagram output" -- @subpage qspy_matlab "MATLAB output" - -
-@nav{qs,qspy_text} -*/ -/*###########################################################################*/ -/** -@page qspy_text QSPY Screen Output -@nav{qspy,qspy_dict} - -

QSPY provides a simple, consolidated, human-readable textual output to the screen. The readability of this output depends strongly on the availability of the symbolic information about the various objects in the Target code, called @ref qspy_dict "dictionaries". If the "dictionaries" are not available, QSPY can output only the hexadecimal values of various object addresses and event signals. However, if QSPY has acquired the @ref qs_dict "dictionaries" from the Target, or has @ref qspy_dict "read them from a file", it can apply the symbolic information to output the provided identifiers for objects, signals, and states. -

- -@note -In the process of adapting QSPY to support @ref qutest "QUTest Unit Testing", the QSPY human-readable output has been changed to avoid any special characters used in regular expressions, such as `*, [, ], ?, !`. This is because the QUTest scripts use regular expressions to match QSPY textual output with the expected output. - - -@section qspy_text_exa Screen Output Example -For example, the following listing shows the QSPY text output when the @ref qs_dict "dictionaries" **are** available: - -
-@verbatim -QSPY 6.9.0 Copyright (c) 2005-2020 Quantum Leaps -Documentation: https://www.state-machine.com/qtools/qspy.html -Current timestamp: 200827_093625 --c COM7 --u 7701 --v 660 --T 4 --O 4 --F 4 --S 2 --E 2 --Q 1 --P 2 --B 2 --C 2 - -########## Trg-RST QP-Ver=690,Build=200824_123230 - Obj-Dict 0x20001048->QS_RX - Obj-Dict 0x08004009->l_SysTick_Handler - Usr-Dict 00000100->PHILO_STAT - Obj-Dict 0x20000EE0->AO_Table - Obj-Dict 0x20000DDC->AO_Philo[0] - Obj-Dict 0x20000E10->AO_Philo[1] - . . . . . - Obj-Dict 0x20000F94->EvtPool1 - Obj-Dict 0x20000DDC->Philo_inst[0] - Obj-Dict 0x20000E00->Philo_inst[0].timeEvt - Obj-Dict 0x20000E10->Philo_inst[1] - Obj-Dict 0x20000E34->Philo_inst[1].timeEvt - Obj-Dict 0x20000E44->Philo_inst[2] - . . . . . - Fun-Dict 0x080006A9->Philo_initial - Fun-Dict 0x08000915->Philo_thinking - Fun-Dict 0x08000871->Philo_hungry - Fun-Dict 0x080007C5->Philo_eating - Sig-Dict 00000010,Obj=0x20000DDC->HUNGRY_SIG - Sig-Dict 00000011,Obj=0x20000DDC->TIMEOUT_SIG -0000000000 AO-Subsc Obj=Philo_inst[0],Sig=00000004,Obj=0x20000DDC -0000000000 AO-Subsc Obj=Philo_inst[0],Sig=00000008,Obj=0x20000DDC -===RTC===> St-Init Obj=Philo_inst[0],State=0x08001099->Philo_thinking -0000000000 TE0-Arm Obj=Philo_inst[0].timeEvt,AO=Philo_inst[0],Tim=84,Int=0 -===RTC===> St-Entry Obj=Philo_inst[0],State=Philo_thinking -0000000000 Init===> Obj=Philo_inst[0],State=Philo_thinking - Sig-Dict 00000010,Obj=0x20000E10->HUNGRY_SIG - Sig-Dict 00000011,Obj=0x20000E10->TIMEOUT_SIG - . . . . . - . . . . . -===RTC===> St-Init Obj=Table_inst,State=0x08001099->Table_serving -===RTC===> St-Entry Obj=Table_inst,State=Table_serving -0000000000 Init===> Obj=Table_inst,State=Table_serving - QF_RUN -4294946722 QF-Pub Sdr=l_SysTick_Handler,Evt -4294947277 AO-Post Sdr=l_SysTick_Handler,Obj=Table_inst,Evt,Que -4294948158 Sch-Next Pri=0->6 -4294948490 AO-GetL Obj=Table_inst,Evt -4294949010 Disp===> Obj=Table_inst,Sig=SERVE_SIG,State=Table_serving -4294949660 =>Ignore Obj=Table_inst,Sig=SERVE_SIG,State=Table_serving -4294950254 Sch-Idle Pri=6->0 - TE0-ADis Obj=Philo_inst[4].timeEvt,AO=Philo_inst[4] -4294946907 TE0-Post Obj=Philo_inst[4].timeEvt,Sig=TIMEOUT_SIG,AO=Philo_inst[4] -4294947535 AO-Post Sdr=l_SysTick_Handler,Obj=Philo_inst[4],Evt,Que -4294948568 Sch-Next Pri=0->5 -4294948900 AO-GetL Obj=Philo_inst[4],Evt -4294949419 Disp===> Obj=Philo_inst[4],Sig=TIMEOUT_SIG,State=Philo_thinking -4294950135 TE0-DisA Obj=Philo_inst[4].timeEvt,AO=Philo_inst[4] -===RTC===> St-Exit Obj=Philo_inst[4],State=Philo_thinking -4294951090 QF-New Sig=HUNGRY_SIG,Size=6 -4294951506 MP-Get Obj=EvtPool1,Free=9,Min=9 -4294952081 AO-Post Sdr=Philo_inst[4],Obj=Table_inst,Evt,Que -4294952841 Sch-Next Pri=5->6 -4294953173 AO-GetL Obj=Table_inst,Evt -4294953692 Disp===> Obj=Table_inst,Sig=HUNGRY_SIG,State=Table_serving -4294954299 PHILO_STAT 4 hungry -4294954817 QF-New Sig=EAT_SIG,Size=6 -4294955233 MP-Get Obj=EvtPool1,Free=8,Min=8 -4294955759 QF-Pub Sdr=Table_inst,Evt -4294956277 Sch-Lock Ceil=0->5 -4294956667 AO-Post Sdr=Table_inst,Obj=Philo_inst[4],Evt,Que -4294957464 AO-Post Sdr=Table_inst,Obj=Philo_inst[3],Evt,Que -4294958261 AO-Post Sdr=Table_inst,Obj=Philo_inst[2],Evt,Que -4294959058 AO-Post Sdr=Table_inst,Obj=Philo_inst[1],Evt,Que -4294959855 AO-Post Sdr=Table_inst,Obj=Philo_inst[0],Evt,Que -4294960624 Sch-Unlk Ceil=5->0 -. . . . . . -@endverbatim -
- -The QS trace log shown in the listing above contains quite detailed information, because most QS records are enabled (are not blocked in the @ref qs_filters "QS filters"). The following bullet items highlight the most interesting parts of the trace and illustrate how you can interpret the trace data: - -- The QS output starts with the QSPY application version number, the date and time of the run (run time-stamp), and all the options explicitly provided to the QSPY host application. - -- The first trace records in the log are typically @ref qspy_dict "dictionary trace records" that provide a mapping between addresses of various objects in memory and their symbolic names. - -- After the dictionaries, you see the active object initialization. For example, the `===RTC===> St-Init` record indicates that the top-most initial transition in the active object `l_table` has been taken. After this, the `===RTC===> St-Entry` record informs you that the state `Table_serving` has been entered, and finally the record `==>Init` tells you that the top-most initial transition sequence has completed. This trace record has a high-resolution @ref qs_tstamp "time-stamp" (the first 10-digit number) generated by the Target. The time units used by this time-stamp depend on the specific hardware timer used in the Target, but typically it is sub-microsecond. - -- After this you see that at time-stamp `0000380805` an event was dispatched (`Disp===>` record) to `l_table`, but it was subsequently `Ignored`, while `l_table` was in the state `Table_serving`. - - -@section qspy_pre Predefined Trace Records -The following table summarizes the text output format used for all predefined QS trace records (see ::QSpyRecords). - -@note -To better adapt QSPY to support @ref qutest "QUTest Unit Testing", the QSPY human-readable output has been changed at @ref qtools_5_9_0 "version 5.9.0" to avoid any special characters used in regular expressions, such as `*, [, ], ?, !`. This is because the QUTest scripts use regular expressions to match QSPY textual output with the expected output. - - -
State Machine Trace Records (QEP) -
Rec.
Num
Rec.
Enum
Start of record Comment -
1 #QS_QEP_STATE_ENTRY `===RTC===> St-Entry` a state was entered -
2 #QS_QEP_STATE_EXIT `===RTC===> St-Exit` a state was exited -
3 #QS_QEP_STATE_INIT ` St-Init` an initial transition was taken in a state -
4 #QS_QEP_INIT_TRAN ` Init===>` the top-most initial transition was taken -
5 #QS_QEP_INTERN_TRAN ` =>Intern` an internal transition was taken -
6 #QS_QEP_TRAN ` ===>Tran ` a regular transition was taken -
7 #QS_QEP_IGNORED ` =>Ignore` an event was ignored (silently discarded) -
8 #QS_QEP_DISPATCH ` Disp===>` an event was dispatched (begin of RTC step) -
9 #QS_QEP_UNHANDLED `===RTC===> St-Unhnd` a guard prevented handling of an event -
55 #QS_QEP_TRAN_HIST `===RTC===> St-Hist` a transition to history was taken -
56 #QS_QEP_TRAN_EP `===RTC===> St-EP` a transition was taken to an entry point into a submachine -
57 #QS_QEP_TRAN_XP `===RTC===> St-XP` a transition was taken to an exit point out of a submachine -
Active Object Trace Records -
Rec.
Num
Rec.
Enum
Start of record Comment -
12 #QS_QF_ACTIVE_SUBSCRIBE ` AO-Subsc` an AO subscribed to an event -
13 #QS_QF_ACTIVE_UNSUBSCRIBE ` AO-Unsub` an AO unsubscribed from an event -
14 #QS_QF_ACTIVE_POST ` AO-Post` an event was posted (FIFO) directly to AO -
15 #QS_QF_ACTIVE_POST_LIFO ` AO-LIFO` an event was posted (LIFO) directly to AO -
16 #QS_QF_ACTIVE_GET ` AO-Get` AO got an event and its queue is still not empty -
17 #QS_QF_ACTIVE_GET_LAST ` AO-GetL` AO got an event and its queue is empty -
45 #QS_QF_ACTIVE_POST_ATTEMPT ` AO-PostA` attempt to post an event to AO failed -
Raw Event Queue Trace Records -
Rec.
Num
Rec.
Enum
Start of record Comment -
19 #QS_QF_EQUEUE_POST ` EQ-Post` an event was posted (FIFO) to a raw queue -
20 #QS_QF_EQUEUE_POST_LIFO ` EQ-LIFO` an event was posted (LIFO) to a raw queue -
21 #QS_QF_EQUEUE_GET ` EQ-Get` got an event and queue still not empty -
22 #QS_QF_EQUEUE_GET_LAST ` EQ-GetL` got the last event from the queue -
46 #QS_QF_EQUEUE_POST_ATTEMPT ` EQ-PostA` attempt to post an event to QEQueue failed -
Raw Memory Pool Trace Records -
Rec.
Num
Rec.
Enum
Start of record Comment -
24 #QS_QF_MPOOL_GET ` MP-Get` a memory block was removed from a memory pool -
25 #QS_QF_MPOOL_PUT ` MP-Put` a memory block was returned to a memory pool -
47 #QS_QF_MPOOL_GET_ATTEMPT ` MP-GetA` attempt to get a memory block failed -
Event Management (QF) -
Rec.
Num
Rec.
Enum
Start of record Comment -
26 #QS_QF_PUBLISH ` QF-Pub` an event was published -
27 #QS_QF_NEW_REF ` New-Ref` new event reference was created -
28 #QS_QF_NEW ` QF-New` new event creation -
29 #QS_QF_GC_ATTEMPT ` QF-gcA` garbage collection attempt -
30 #QS_QF_GC ` QF-gc` garbage collection performed -
31 #QS_QF_TICK `Tick`QF system clock tick processing was called -
39 #QS_QF_CRIT_ENTRY ` QF-CritE` critical section was entered -
40 #QS_QF_CRIT_EXIT ` QF-CritX` critical section was exited -
41 #QS_QF_ISR_ENTRY ` QF-IsrE` an ISR was entered -
42 #QS_QF_ISR_EXIT ` QF-IsrX` an ISR was exited -
Time Events (TE) -
Rec.
Num
Rec.
Enum
Start of record Comment -
32 #QS_QF_TIMEEVT_ARM ` TE-Arm` a time event was armed -
33 #QS_QF_TIMEEVT_AUTO_DISARM ` TE-ADis` a time event expired and was disarmed -
34 #QS_QF_TIMEEVT_DISARM_ATTEMPT ` TE-DisA` attempt to disarm a disarmed Time Event -
35 #QS_QF_TIMEEVT_DISARM ` TE-Dis` successful disarming of an armed time event -
36 #QS_QF_TIMEEVT_REARM ` TE-Rarm` rearming of a time event -
37 #QS_QF_TIMEEVT_POST ` TE-Post` a time event posted itself directly to an AO -
38 #QS_QF_DELETE_REF ` QF-DelRf` an event reference is about to be deleted -
Scheduler Trace Records -
Rec.
Num
Rec.
Enum
Start of record Comment -
50 #QS_SCHED_LOCK ` Sch-Lock` scheduler was locked -
51 #QS_SCHED_UNLOCK ` Sch-Unlk` scheduler was unlocked -
52 #QS_SCHED_NEXT ` Sch-Next` scheduler found next task to execute -
53 #QS_SCHED_IDLE ` Sch-Idle` scheduler became idle -
54 #QS_ENUM_DICT `Enum-Dict` Enumeration record dictionary entry -
Miscellaneous Trace Records
NOT MASKABLE WITH THE @ref qs_global "QS GLOBAL FILTER"!
-
Rec.
Num
Rec.
Enum
Start of record Comment -
58 #QS_TEST_PAUSED `TstPause` test has been paused -
59 #QS_TEST_PROBE_GET ` TstProbe` reports that Test-Probe has been used -
60 #QS_SIG_DICTIONARY `Sig-Dict` signal dictionary entry -
61 #QS_OBJ_DICTIONARY `Obj-Dict` object dictionary entry -
62 #QS_FUN_DICTIONARY `Fun-Dict` function dictionary entry -
63 #QS_USR_DICTIONARY `Usr-Dict` User record dictionary entry -
64 #QS_TARGET_INFO `########## Trg-Info` reports the Target information -
65 #QS_TARGET_DONE ` Trg-Done` reports completion of a user callback -
66 #QS_RX_STATUS `Trg-Ack` reports QS data receive status -
67 #QS_QUERY_DATA ` Query-xxx` reports the data from "current object" query -
68 #QS_PEEK_DATA `Trg-Peek` reports the data from the PEEK query -
69 #QS_ASSERT_FAIL ` =ASSERT=` Assertion failed in the target -
70 #QS_QF_RUN `QF RUN` `QF_run()` called -
User Records (@ref qs_app "Application Specific") -
100 #QS_USER + xxx ` USER+xxx` @ref qs_app "application-specific" (user) QS records (100..124) -
- -
-@nav{qspy,qspy_dict} -*/ -/*###########################################################################*/ -/** -@page qspy_dict QSPY Dictionaries -@nav{qspy_text,qspy_udp} - -@section qspy_dict_about About QSPY Dictionaries -By the time you compile and load your application image to the Target, the symbolic names of various objects, function names, and event signal names are stripped from the code. Therefore, if you want to have the symbolic information available to the QSPY host-resident component, you need to supply it somehow to the software tracing system. - -The QS Target-resident component provides special @ref qs_dict "dictionary trace records" designed expressly for providing the symbolic information about the target code in the trace itself. These "dictionary records" are very much like the symbolic information embedded in the object files for the traditional single-step debugger. QS can supply four types of dictionary trace records: - -- object dictionary — for identifying objects (HSMs, AOs, Time events, etc.) -- function dictionary — for identifying functions (state-handlers) -- signal dictionary — for identifying event signals -- user dictionary — for identifying @ref qs_app "application-specific" (user) records - -@note -QSPY does not absolutely require the presence of dictionary trace records to generate the human-readable output, in the same way that the symbolic information in the object files is not absolutely required to be able to debug code. However, in both cases, the availability of the symbolic information greatly improves the readability of the disassembly code shown in the debugger. - - -For instance, the following listing shows an example of the QSPY text output when the "dictionaries" are **not** available. (NOTE: dictionaries might not be available because (1) the Target does not produce @ref qs_dict "dictionary trace records" for all relevant objects or (2) the Target does produce all dictionaries, but QSPY has never seen them, because it was attached to the Target after the dictionaries have been transmitted): -
-@verbatim -. . . . . . -0009692721 Disp===> Obj=0x2000133C,Sig=00000010,Obj=0x2000133C,State=0x000010C5 -0009693389 USER+000 4 hungry -0009695383 USER+000 4 eating -0009695932 =>Intern Obj=0x2000133C,Sig=00000010,Obj=0x2000133C,State=0x000010C5 -===RTC===> St-Entry Obj=0x200012F8,State=0x00000D49 -0009697188 ===>Tran Obj=0x200012F8,Sig=00000011,Obj=0x200012F8,State=0x00000DD5->0x00000D49 -0009698052 Disp===> Obj=0x200012F8,Sig=00000004,Obj=0x200012F8,State=0x00000D49 -===RTC===> St-Entry Obj=0x200012F8,State=0x00000CA9 -0009699697 ===>Tran Obj=0x200012F8,Sig=00000004,Obj=0x200012F8,State=0x00000D49->0x00000CA9 -0009700602 Disp===> Obj=0x200012B8,Sig=00000004,Obj=0x200012B8,State=0x00000DD5 -0009701247 =>Intern Obj=0x200012B8,Sig=00000004,Obj=0x200012B8,State=0x00000DD5 -0009702038 Disp===> Obj=0x20001278,Sig=00000004,Obj=0x20001278,State=0x00000DD5 -0009702677 =>Intern Obj=0x20001278,Sig=00000004,Obj=0x20001278,State=0x00000DD5 -0009703468 Disp===> Obj=0x20001238,Sig=00000004,Obj=0x20001238,State=0x00000DD5 -0009704107 =>Intern Obj=0x20001238,Sig=00000004,Obj=0x20001238,State=0x00000DD5 -0009704899 Disp===> Obj=0x200011F8,Sig=00000004,Obj=0x200011F8,State=0x00000DD5 -0009705538 =>Intern Obj=0x200011F8,Sig=00000004,Obj=0x200011F8,State=0x00000DD5 -0015961105 Disp===> Obj=0x200011F8,Sig=00000011,Obj=0x200011F8,State=0x00000DD5 -===RTC===> St-Exit Obj=0x200011F8,State=0x00000DD5 -0015962823 Disp===> Obj=0x2000133C,Sig=00000010,Obj=0x2000133C,State=0x000010C5 -0015963491 USER+000 0 hungry -. . . . . . -@endverbatim - -And here is the exact same trace data when the "dictionaries" **are** available: - -@verbatim -. . . . . . -0009692721 Disp===> Obj=l_table,Sig=HUNGRY_SIG,State=Table_serving -0009693389 PHILO_STAT 4 hungry -0009695383 PHILO_STAT 4 eating -0009695932 =>Intern Obj=l_table,Sig=HUNGRY_SIG,State=Table_serving -===RTC===> St-Entry Obj=l_philo[4],State=Philo_hungry -0009697188 ===>Tran Obj=l_philo[4],Sig=TIMEOUT_SIG,State=Philo_thinking->Philo_hungry -0009698052 Disp===> Obj=l_philo[4],Sig=EAT_SIG,State=Philo_hungry -===RTC===> St-Entry Obj=l_philo[4],State=Philo_eating -0009699697 ===>Tran Obj=l_philo[4],Sig=EAT_SIG,State=Philo_hungry->Philo_eating -0009700602 Disp===> Obj=l_philo[3],Sig=EAT_SIG,State=Philo_thinking -0009701247 =>Intern Obj=l_philo[3],Sig=EAT_SIG,State=Philo_thinking -0009702038 Disp===> Obj=l_philo[2],Sig=EAT_SIG,State=Philo_thinking -0009702677 =>Intern Obj=l_philo[2],Sig=EAT_SIG,State=Philo_thinking -0009703468 Disp===> Obj=l_philo[1],Sig=EAT_SIG,State=Philo_thinking -0009704107 =>Intern Obj=l_philo[1],Sig=EAT_SIG,State=Philo_thinking -0009704899 Disp===> Obj=l_philo[0],Sig=EAT_SIG,State=Philo_thinking -0009705538 =>Intern Obj=l_philo[0],Sig=EAT_SIG,State=Philo_thinking -0015961105 Disp===> Obj=l_philo[0],Sig=TIMEOUT_SIG,State=Philo_thinking -===RTC===> St-Exit Obj=l_philo[0],State=Philo_thinking -0015962823 Disp===> Obj=l_table,Sig=HUNGRY_SIG,State=Table_serving -0015963491 PHILO_STAT 0 hungry -. . . . . . -@endverbatim - -As you can see, the difference in readability is quite dramatic. - - -@section qspy_dict_get Acquiring Dictionaries -The QS Target-resident component generates the dictionary trace records during the initialization of active object components in the Target code, that is, typically right after the reset. Consequently, the best way to acquire the dictionaries is to capture the trace when the Target performs the reset. This can be done in a couple of ways: -- Start QSPY **before** the Target resets -- Manually reset the Target while QSPY is running (e.g., press a Reset button on the Target board) -- Send the @ref qspy_keyboard "RESET command" to the Target from QSPY while it is running - -Either way, the dictionary records should be produced and acquired by the Target. The following listing shows the dictionary records sent by the DPP example application running on a STM32 NUCLEO board: - -
-@verbatim -C:\qp\qpc\examples\arm-cm\dpp_nucleo-l152re\qk\gnu>qspy -cCOM7 -QQSPY 6.9.0 Copyright (c) 2005-2020 Quantum Leaps -Documentation: https://www.state-machine.com/qtools/qspy.html -Current timestamp: 200827_093625 --c COM7 --u 7701 --v 620 --T 4 --O 4 --F 4 --S 2 --E 2 --Q 1 --P 2 --B 2 --C 2 - -########## Trg-RST QP-Ver=690,Build=200824_123230 - Obj-Dict 0x20001048->QS_RX - Obj-Dict 0x08004009->l_SysTick_Handler - Usr-Dict 00000100->PHILO_STAT - Obj-Dict 0x20000EE0->AO_Table - Obj-Dict 0x20000DDC->AO_Philo[0] - Obj-Dict 0x20000E10->AO_Philo[1] - Obj-Dict 0x20000E44->AO_Philo[2] - Obj-Dict 0x20000E78->AO_Philo[3] - Obj-Dict 0x20000EAC->AO_Philo[4] - Obj-Dict 0x20000F94->EvtPool1 - Obj-Dict 0x20000DDC->Philo_inst[0] - Obj-Dict 0x20000E00->Philo_inst[0].timeEvt - Obj-Dict 0x20000E10->Philo_inst[1] - Obj-Dict 0x20000E34->Philo_inst[1].timeEvt - Obj-Dict 0x20000E44->Philo_inst[2] - Obj-Dict 0x20000E68->Philo_inst[2].timeEvt - Obj-Dict 0x20000E78->Philo_inst[3] - Obj-Dict 0x20000E9C->Philo_inst[3].timeEvt - Obj-Dict 0x20000EAC->Philo_inst[4] - Obj-Dict 0x20000ED0->Philo_inst[4].timeEvt - Fun-Dict 0x080006A9->Philo_initial - Fun-Dict 0x08000915->Philo_thinking - Fun-Dict 0x08000871->Philo_hungry - Fun-Dict 0x080007C5->Philo_eating - Sig-Dict 00000010,Obj=0x20000DDC->HUNGRY_SIG - Sig-Dict 00000011,Obj=0x20000DDC->TIMEOUT_SIG -0000000000 AO-Subsc Obj=Philo_inst[0],Sig=00000004,Obj=0x20000DDC -0000000000 AO-Subsc Obj=Philo_inst[0],Sig=00000008,Obj=0x20000DDC -===RTC===> St-Init Obj=Philo_inst[0],State=0x08001099->Philo_thinking -0000000000 TE0-Arm Obj=Philo_inst[0].timeEvt,AO=Philo_inst[0],Tim=84,Int=0 -===RTC===> St-Entry Obj=Philo_inst[0],State=Philo_thinking -0000000000 Init===> Obj=Philo_inst[0],State=Philo_thinking - Sig-Dict 00000010,Obj=0x20000E10->HUNGRY_SIG - Sig-Dict 00000011,Obj=0x20000E10->TIMEOUT_SIG -0000000000 AO-Subsc Obj=Philo_inst[1],Sig=00000004,Obj=0x20000E10 -0000000000 AO-Subsc Obj=Philo_inst[1],Sig=00000008,Obj=0x20000E10 -===RTC===> St-Init Obj=Philo_inst[1],State=0x08001099->Philo_thinking -0000000000 TE0-Arm Obj=Philo_inst[1].timeEvt,AO=Philo_inst[1],Tim=107,Int=0 -===RTC===> St-Entry Obj=Philo_inst[1],State=Philo_thinking -0000000000 Init===> Obj=Philo_inst[1],State=Philo_thinking - Sig-Dict 00000010,Obj=0x20000E44->HUNGRY_SIG - Sig-Dict 00000011,Obj=0x20000E44->TIMEOUT_SIG -0000000000 AO-Subsc Obj=Philo_inst[2],Sig=00000004,Obj=0x20000E44 -0000000000 AO-Subsc Obj=Philo_inst[2],Sig=00000008,Obj=0x20000E44 -===RTC===> St-Init Obj=Philo_inst[2],State=0x08001099->Philo_thinking -0000000000 TE0-Arm Obj=Philo_inst[2].timeEvt,AO=Philo_inst[2],Tim=102,Int=0 -===RTC===> St-Entry Obj=Philo_inst[2],State=Philo_thinking -0000000000 Init===> Obj=Philo_inst[2],State=Philo_thinking - Sig-Dict 00000010,Obj=0x20000E78->HUNGRY_SIG - Sig-Dict 00000011,Obj=0x20000E78->TIMEOUT_SIG -0000000000 AO-Subsc Obj=Philo_inst[3],Sig=00000004,Obj=0x20000E78 -0000000000 AO-Subsc Obj=Philo_inst[3],Sig=00000008,Obj=0x20000E78 -===RTC===> St-Init Obj=Philo_inst[3],State=0x08001099->Philo_thinking -0000000000 TE0-Arm Obj=Philo_inst[3].timeEvt,AO=Philo_inst[3],Tim=148,Int=0 -===RTC===> St-Entry Obj=Philo_inst[3],State=Philo_thinking -0000000000 Init===> Obj=Philo_inst[3],State=Philo_thinking - Sig-Dict 00000010,Obj=0x20000EAC->HUNGRY_SIG - Sig-Dict 00000011,Obj=0x20000EAC->TIMEOUT_SIG -0000000000 AO-Subsc Obj=Philo_inst[4],Sig=00000004,Obj=0x20000EAC -0000000000 AO-Subsc Obj=Philo_inst[4],Sig=00000008,Obj=0x20000EAC -===RTC===> St-Init Obj=Philo_inst[4],State=0x08001099->Philo_thinking -0000000000 TE0-Arm Obj=Philo_inst[4].timeEvt,AO=Philo_inst[4],Tim=51,Int=0 -===RTC===> St-Entry Obj=Philo_inst[4],State=Philo_thinking -0000000000 Init===> Obj=Philo_inst[4],State=Philo_thinking - Obj-Dict 0x20000EE0->Table_inst - Sig-Dict 00000005,Obj=0x00000000->DONE_SIG - Sig-Dict 00000004,Obj=0x00000000->EAT_SIG - Sig-Dict 00000006,Obj=0x00000000->PAUSE_SIG - Sig-Dict 00000007,Obj=0x00000000->SERVE_SIG - Sig-Dict 00000008,Obj=0x00000000->TEST_SIG - Sig-Dict 00000010,Obj=0x20000EE0->HUNGRY_SIG -0000000000 AO-Subsc Obj=Table_inst,Sig=DONE_SIG -0000000000 AO-Subsc Obj=Table_inst,Sig=PAUSE_SIG -0000000000 AO-Subsc Obj=Table_inst,Sig=SERVE_SIG -0000000000 AO-Subsc Obj=Table_inst,Sig=TEST_SIG -0000000000 PHILO_STAT 0 thinking -0000000000 PHILO_STAT 1 thinking -0000000000 PHILO_STAT 2 thinking -0000000000 PHILO_STAT 3 thinking -0000000000 PHILO_STAT 4 thinking - Fun-Dict 0x08000BB5->Table_active - Fun-Dict 0x08000BDD->Table_serving - Fun-Dict 0x08000AD1->Table_paused -===RTC===> St-Init Obj=Table_inst,State=0x08001099->Table_serving -===RTC===> St-Entry Obj=Table_inst,State=Table_serving -0000000000 Init===> Obj=Table_inst,State=Table_serving - QF_RUN -@endverbatim -
- -Once QSPY acquires the dictionaries, it keeps them in memory and applies them to display the data in symbolic form rather than hex addresses. - -@note -The dictionaries do not need to be complete to be useful. QSPY simply applies the symbolic information whenever it can find a match in the dictionaries acquired so far. When a dictionary entry is not available, QSPY displays only hex addresses. - - -@section qspy_dict_save Saving Dictionaries to a File - -QSPY can save the dictionaries acquired thus far into a file. This is triggered by the #QS_QF_RUN trace record from the Target, but it can also be triggered by the user (by means of the `d` @ref qspy_keyboard "keyboard command" or from @ref qview_file "QView menu File->Save Dictionaries"), because QSPY does not "know" when the dictionaries are "complete", therefore it cannot know when to save them automatically. - -@note -In order for dictionaries to be saved to a file, the QSPY host application must be launched with the `-d` @ref qspy_command "command-line option", with or without the optional `[file]` parameter. - - -On the other hand, QSPY automatically generates the file name for saving dictionaries. This file name always has the form `qspy.dic`, where `` unambiguously identifies the Target build date and time. For example, the Target code last built on August 31, 2015 at 14:42:29 will have the name `qspy150831_144229.dic`. - -@attention -The internal addresses of objects can change with every code re-build, so dictionaries are applicable only to the specific Target build and must be freshly re-acquired after every new Target code build. - - -The dictionaries are saved to a file in ASCII format. The following listing shows the dictionaries from the DPP example application running on a STM32 NUCLEO board: - -
-@verbatim --v690 --T4 --O4 --F4 --S2 --E2 --Q1 --P2 --B2 --C2 --t200824_123230 - -Obj-Dic: -4 -0x08004009 l_SysTick_Handler -0x20000DDC Philo_inst[0] -0x20000E00 Philo_inst[0].timeEvt -0x20000E10 Philo_inst[1] -0x20000E34 Philo_inst[1].timeEvt -0x20000E44 Philo_inst[2] -0x20000E68 Philo_inst[2].timeEvt -0x20000E78 Philo_inst[3] -0x20000E9C Philo_inst[3].timeEvt -0x20000EAC Philo_inst[4] -0x20000ED0 Philo_inst[4].timeEvt -0x20000EE0 Table_inst -0x20000F94 EvtPool1 -0x20001048 QS_RX -*** -Fun-Dic: -4 -0x080006A9 Philo_initial -0x080007C5 Philo_eating -0x08000871 Philo_hungry -0x08000915 Philo_thinking -0x08000AD1 Table_paused -0x08000BB5 Table_active -0x08000BDD Table_serving -*** -Usr-Dic: -1 -0x00000064 PHILO_STAT -0x0000007C QUTEST_ON_POST -*** -Sig-Dic: -4 -00000004 0x00000000 EAT_SIG -00000005 0x00000000 DONE_SIG -00000006 0x00000000 PAUSE_SIG -00000007 0x00000000 SERVE_SIG -00000008 0x00000000 TEST_SIG -00000010 0x20000E44 HUNGRY_SIG -00000010 0x20000EAC HUNGRY_SIG -00000010 0x20000E78 HUNGRY_SIG -00000010 0x20000DDC HUNGRY_SIG -00000010 0x20000E10 HUNGRY_SIG -00000010 0x20000EE0 HUNGRY_SIG -00000011 0x20000E78 TIMEOUT_SIG -00000011 0x20000EAC TIMEOUT_SIG -00000011 0x20000E44 TIMEOUT_SIG -00000011 0x20000DDC TIMEOUT_SIG -00000011 0x20000E10 TIMEOUT_SIG -*** -@endverbatim -
- - -@section qspy_dict_use Using the Dictionary File -The dictionary file saved in previous QSPY sessions can be used in two ways: - -- you can specify the dictionary file in the `-d ` @ref qspy_command "command-line option" to QSPY. In this case QSPY reads the dictionaries from the provided `` before processing any trace records from the Target. (**NOTE:** in this case you don't need to provide any of the upper-case command-line options, because they are read from the dictionary file.) For example: the command line `qspy -d qspy180117_155932.dic` will attempt to read the dictionaries from the specified file. - -- you can specify the dictionary option without the dictionary file `-d` @ref qspy_command "command-line option" to QSPY. Subsequently, once you run QSPY, you can query the Target information (by means of the `i` or `r` @ref qspy_keyboard "keyboard command" or from @ref qview_menu "QView menu Commands->Query Target Info"). When the Target replies and provides its build-time-stamp, QSPY looks for the corresponding dictionary file in the current directory, and if such a file is found, QSPY reads the dictionaries from it. - - -@note -That last option requires that the Target implements the @ref qs_rx "QS receive channel, QS-RX" so that it can receive commands from QSPY. - - -
-@nav{qspy_text,qspy_udp} -*/ -/*##########################################################################*/ -/** -@page qspy_udp QSPY UDP Interface -@nav{qspy_dict,qspy_seq} - -

This section describes the structure of the UDP packets exchanged between the QSPY Back-End and the various front-ends, such as @ref qutest "QUTest" and @ref qview "QView" (blue arrows in the sequence diagram below). -

- -@image html qspy_comm.gif "Communication between Target, QSPY, and QView" -
- - -@section udp_top General UDP Packet Structure - -@image html qspy_udp.gif "UDP packet structure" - -The UDP packets exchanged between the QSPY Back-End and the `QView` Front-End consist of: - -- 1-byte **Sequence-No**, which increments by 1 for every packet and wraps naturally from 0xFF to 0. The sequence number allows `QView` to detect any data discontinuities. - -- 1-byte **Record-ID**. The Record-IDs are divided into two categories: - - Records to and from the Target have Record-IDs in the range 0..127. Specifically, QS records originated from the Target are enumerated in ::QSpyRecords. Records destined to the Target are enumerated in ::QSpyRxRecords. - - Records to and from the QSPY Back-End have record-IDs in the range 128..255. Specifically, records destined to QSPY are enumerated in ::QSpyCommands. - -- optional **Data Payload**, which can be either text or binary, depending on the @ref udp_channel "UDP Channel" to which the front-end attaches. The various Data Payloads for different packets are described in the separate sections below. - - - -@subsection udp_channel UDP Data Channels -The QSPY UDP socket supports two "channels": -- **binary channel** (channel 1), in which the *Data Payload* is sent in binary, but after removing @ref qspy_transparent "escaping" and checksum; -- **text channel** (channel 2), in which the *Data Payload* is sent in the @ref qspy_text "QSPY Textual Format"; - -A Front-End can choose the "data channels" when "attaching" to the QSPY host application (see qspy::attach()). The data channels are not exclusive, meaning that a front-end can "attach" simultaneously to both binary and text channels. In this case, the front-end would receive each packet as both binary and text formats. - -@remark -The binary-channel (0x01) is used by the @ref qview "QView" GUI front-end, while the text-channel (0x02) is used by the @ref qutest "QUTest" Unit Testing front-end. - - -@section udp_Target Records to the Target - - -@subsection udp_INFO Query Target Info (INFO) -This packet has Record-ID==INFO and has no Data Payload. - -@note -To understand the following detailed UDP packet descriptions, it is highly recommended to read the Python documentation for the Python struct.pack() command.
-
-All data to and from the Target is sent according to the @ref qpspy_proto "QP/Spy™ Data Protocol" in **little endian**. - - -Code Example: -@code -::qspy::sendPkt [binary format c $::qspy::QS_RX(INFO)] -@endcode - - -@subsection udp_COMMAND Execute a User-Defined Command in the Target (COMMAND) -This packet has Record-ID==COMMAND and Data Payload of the form: - -Data item | binary format | description ------------|-----------------------------|------------- -Command-ID | B (byte) | command number -Command-Par| I (unsigned 4-byte integer) | command parameter - - -@subsection udp_RESET Reset the Target (RESET) -This packet has Record-ID==RESET and has no Data Payload. - - -@subsection udp_TICK Call QF_TICK_X() in the Target (TICK) - -Data item | binary format | description ------------|---------------|------------- -Tick-rate | B (byte) | system tick rate number - - -@subsection udp_PEEK Peek Target Memory (PEEK) -This packet has Record-ID==PEEK and Data Payload of the form: - -Data item | binary format | description ------------|---------------|------------- -Peek-addr | Target-dependent
Typically I | Address of the data in the Target -Peek-length| B (byte) | Number of bytes to peek - - -@subsection udp_POKE Poke Target Memory (POKE) -This packet has Record-ID==POKE and Data Payload of the form: - -Data item | binary format | description ------------|---------------|------------- -Poke-addr | Target-dependent
Typically I | Address of the data in the Target -Poke-length| B (byte) | Number of bytes to poke (<= 8) -Poke-data | user-defined | Binary data to poke to the Target (8 bytes maximum) - -@note -The Poke-data part of the Data Payload must be formatted with the particular endianness of the Target and with any padding required for proper alignment of objects in the Target memory. - - -@subsection udp_GLB_FILTER Set Global Filters in the Target (GLB_FILTER) -This packet has Record-ID==GLB_FILTER and Data Payload of the form: - -Data item | binary format | description ------------|---------------|------------- -Data Len | B (byte) | Number of bytes sent (currently 16) -Filters | 16B | 8-bit bytes (128-bits), each bit corresponding to Global Filter - - -@subsection udp_LOC_FILTER Set Local Filters in the Target (LOC_FILTER) -This packet has Record-ID==LOC_FILTER and Data Payload of the form: - -Data item | binary format | description ------------|---------------|------------- -Local filter #| B (byte) | The Number of the Local Filter -Object-addr | Target-dependent
Typically I | Address of the object in the Target - -The Local filters are numbered as follows: - -0. State Machine Local Filter (SM) -1. Active Object Local Filter (AO) -2. Memory Pool Local Filter (MP) -3. Event Queue Local Filter (EQ) -4. Time Event Local Filter (TE) -5. Application-Specific Local Filter (AP) - - -@subsection udp_AO_FILTER Set Local AO Filter in the Target (AO_FILTER) -This packet provides a shortcut for setting the Active Object Local Filter by providing just the unique priority of the AO. -The packet has Record-ID==AO_FILTER and Data Payload of the form: - -Data item | binary format | description ------------|---------------|------------- -AO prio | B (byte) | Priority of the AO to filter (0 to disable the AO filter) - - - -@subsection udp_EVENT Inject an Event to the Target (EVENT) -This packet has Record-ID==EVENT and Data Payload of the form: - -Data item | binary format | description ------------|---------------|------------- -AO prio | B (byte) | Priority of the recipient AO (0 to publish the event) -signal | Target-dependent
Typically H | signal of the event -parameters | user-defined | Binary data corresponding to all event parameters - -The Event signal `sig` must be formatted according to the Target configuration (see Q_SIGNAL_SIZE). - -The Event **parameters** must be formatted with the particular **endianness** of the Target and with any padding required for proper alignment of objects in the Target memory. - -The parameters need to match exactly the event memory layout in your Target, including the endianness and any padding that the Target compiler might be using. (To test the correct binary format and padding, you can use the @ref qview_events "Generate Event..." command). - -For example, let's assume that the parameters of your event are: a byte, followed by a 2-byte integer, followed by a 4-byte integer. Also, let's assume that your Target is little endian. From the @ref qview_events "Generate Event..." command you discover that to format this event correctly you need to use the following event parameters: - -Par # | format | data (example) -------|--------|------------- -par1: | B | 0x11 -par2: | B | 0x00 -par3: | H | 0x1122 -par4: | I | 0x11223344 - - -@section udp_QSPY Packets to the QSPY Back-End - -@subsection udp_ATTACH Attach to the QSPY Back-End (QSPY_ATTACH) -This packet has Record-ID==ATTACH and Data Payload of the form: - -Data item | binary format | description ------------|---------------|------------- -channels | B (byte) | Binary bitmask of @ref udp_channel "QSPY channels" to attach to - - -@subsection udp_DETACH Detach from the QSPY Back-End (QSPY_DETACH) -This packet has Record-ID==DETACH and has no Data Payload. - - -@subsection udp_SAVE_DIC Save Dictionaries to a File in QSPY (QSPY_SAVE_DICT) -This packet has Record-ID==SAVE_DIC and has no Data Payload. - - -@subsection udp_TEXT_OUT Text Output to a File in QSPY (QSPY_TEXT_OUT) -This packet has Record-ID==SCREEN_OUT and may have (optionally) one byte of Data Payload -(Data-Byte==0 means turn text output off, Data-Byte!=0 means turn text output on). -In case no Data Payload is provided, the command toggles the output from its current sate. - - -@subsection udp_BIN_OUT Binary Output to a File in QSPY (QSPY_BIN_OUT) -This packet has Record-ID==BIN_OUT and may have (optionally) one byte of Data Payload -(Data-Byte==0 means turn binary output off, Data-Byte!=0 means turn binary output on). -In case no Data Payload is provided, the command toggles the output from its current sate. - - -@subsection udp_MATLAB_OUT MATLAB Output to a File in QSPY (QSPY_MATLAB_OUT) -This packet has Record-ID==MATLAB_OUT and may have (optionally) one byte of Data Payload -(Data-Byte==0 means turn Matlab output off, Data-Byte!=0 means turn Matlab output on). -In case no Data Payload is provided, the command toggles the output from its current sate. - - -@subsection udp_SEQUENCE_OUT Sequence Output to a File in QSPY (QSPY_SEQUENCE_OUT) -This packet has Record-ID==SEQUENCE_OUT and may have (optionally) one byte of Data Payload -(Data-Byte==0 means turn sequence output off, Data-Byte!=0 means turn sequence output on). -In case no Data Payload is provided, the command toggles the output from its current sate. - - -@subsection udp_SEND_EVT Send Event to the Target (QSPY_SEND_EVENT) -This packet has Record-ID==SEND_EVENT and contains the event as Data Payload. - - -@subsection udp_SEND_CURR_OBJ Send Current Object to the Target (QSPY_SEND_CURR_OBJ) -This packet has Record-ID==SEND_CURR_OBJ and contains the current object (address) as Data Payload. - - -@subsection udp_SEND_COMMAND Send Command to the Target (QSPY_SEND_COMMAND) -This packet has Record-ID==SEND_COMMAND and contains the command (including parameters) as Data Payload. - - -@subsection udp_SEND_TEST_PROBE Send Test Probe to the Target (QSPY_SEND_TEST_PROBE) -This packet has Record-ID==SEND_TEST_PROBE and contains the test-probe as Data Payload. - - -@subsection udp_SHOW_NOTE Send and Show a Note to QSPY (QSPY_SHOW_NOTE) -This packet has Record-ID==SHOW_NOTE and contains the note (text) as Data Payload. - -@subsection udp_CLEAR_SCREEN Clear QSPY Screen (QSPY_CLEAR_SCREEN) -This packet has Record-ID==SAVE_DIC and has no Data Payload. - - -@section udp_from Packets from the QSPY Back-End - -@subsection udp_from_ATTACH Attach Response from the QSPY Back-End (ATTACH) -This packet has Record-ID==ATTACH and has no Data Payload. - - -@subsection udp_from_DETACH Detach Request from the QSPY Back-End (DETACH) -This packet has Record-ID==DETACH and has no Data Payload. - -@nav{qspy_dict,qspy_seq} -*/ -/*###########################################################################*/ -/** -@page qspy_seq QSPY Sequence Output -@nav{qspy_udp,qspy_matlab} - -

The QSPY host application can also present the tracing data as a **sequence diagram**. To generate a Sequence file, you need to invoke QSPY with the `-g [obj-list]` @ref qspy_command "command-line option". -

- -The `[obj-list]` is a comma-separated list of objects shown in the desired sequence. The names in the list must correspond exactly to the @ref qs_dict "object dictionaries" produced by the Target. Examples of the valid `-g` options are shown below: - -- `-g -g l_SysTick_Handler,Table::inst,Philo::inst[0],Philo::inst[1]` -- `-g l_QF_onClockTick,TServer::inst` - -Additionally, the list could include a `?` (question mark), which denotes @ref qspy_seq_sys "System Border". - -- `-g -g Table::inst,Philo::inst[0],Philo::inst[1],?` -- `-g ?,l_QF_onClockTick,TServer::inst` - - -@note -The Sequence diagram can show only information actually sent from the Target. Therefore, by adjusting @ref qs_filters "QS filters" you can control the kind of information displayed in the sequence. - - -The following QS trace records produce the most interesting output: -- #QS_QF_ACTIVE_POST, -- #QS_QF_ACTIVE_POST_ATTEMPT, -- #QS_QF_ACTIVE_POST_LIFO, -- #QS_QF_PUBLISH, and -- #QS_QF_TICK. - - -Additional annotations of the sequence diagrams are also available if the following QS trace records are enabled: -- #QS_QEP_TRAN, -- #QS_QF_ACTIVE_DEFER, -- #QS_QF_ACTIVE_RECALL, and -- #QS_QF_ACTIVE_RECALL_ATTEMPT. - - - -@section qspy_seq_ref Sequence Elements -The main elements of the QSPY sequence diagram shown in the following sequence output are marked with the `[xx]` labels, which are explained below the listing. - -@note -The sequence output generated by QSPY is a **simple ASCII file**, which you can browse even with the most basic text editor, or a web browser. **No special tools are needed to view the sequence diagrams produced from your data**. - - -@verbatim -[1] -g ?,l_QF_onClockTick,TServer::inst - - +-------+-------+ +-------+-------+ +-------+-------+ -[2] | ? | |l_QF_onClockTic| | TServer::inst | - +-------+-------+ +-------+-------+ +-------+-------+ -[3] 3115372171 / | | -[4] 3127751904 *--NEW_REQUEST_SIG--+------------------>| -[5] 3127792184 / | - 3144424365 / *--RECEIVED_SIG---->| - 3144429488 / | - 3177742936 / *--AUTHORIZED_SIG-->| -[6] 3177796020 / | (RcallA) - 3177816231 / | - 3190753295 *--NEW_REQUEST_SIG--+------------------>| - 3190792988 / | - 3200126862 *--NEW_REQUEST_SIG--+------------------>| -[7] 3200127346 / | (Defer) - 3207429692 / *--RECEIVED_SIG---->| - 3207435638 / | - 3240835283 / *--AUTHORIZED_SIG-->| -[8] 3240884412 / | *<=NEW_REQUEST_SIG] - 3240884486 / | (RCall) - 3240902469 / | - . . . . . . . . . . . . . . -@endverbatim - -`[1]` The sequence diagram starts with repeating the `-g [obj-list]` option, so that you can conveniently copy-and-paste this option to run the same sequence again. - -`[2]` Below that, you can see the header containing the boxes of participating objects from the `[obj-list]`. From each box descends a **lifeline** that runs vertically down the page and represents the ordering of exchanged events and other interesting occurrences involving the object. -@remark -This first object in this particular sequence diagram, denoted as `?', is @ref qspy_seq_sys explained below. -
-The names in the sequence diagram are **truncated** to the first 15 characters. -
-The sequence header is **repeated** every 100 lines of the sequence output. - -`[3]` Each output line starts with the **timestamp** followed by the lifelines of all participating objects with event arrows or annotations. - -`[4]` This line shows an **event posting** (with FIFO policy), which corresponds to the QS records #QS_QF_ACTIVE_POST and #QS_QF_ACTIVE_POST_ATTEMPT. The event **source** is marked with `*`, the event **target** is pointed to with `>` or `<`. The source and target are connected with a line `*----->`. The line is annotated with the **signal** of the posted event. - -`[5]` This line shows a **state change**, which corresponds to the QS record #QS_QEP_TRAN. The lifeline of the object is annotated with the new **state** assumed by the object. The state-name is placed between `<` or `>`. -@remark -This **state** annotation it shortened to better fit in the allotted space. For example, state names "MyStateMachine_active_123" (in C) or "MyStateMachine::active_123" (in C++) are displayed as ``. - -`[6]` This line shows an **event recall**, which corresponds to the QS records #QS_QF_ACTIVE_RECALL, and #QS_QF_ACTIVE_RECALL_ATTEMPT. The lifeline of the object is annotated with `(Rcall)` or `(RcallA)`, respectively. - -`[7]` This line shows an **event deferral**, which corresponds to the QS record #QS_QF_ACTIVE_DEFER. The lifeline of the object is annotated with `(Defer)`. - -`[8]` This line shows an **event self-posting** with LIFO policy, which corresponds to the QS record #QS_QF_ACTIVE_POST_LIFO. The event **source/target** is marked with `*<`; the LIFO policy of the event posting is denoted by the `=` line right before the **signal** of the posted event. - - -@section qspy_seq_sys The System Border Object -As mentioned before, the `[obj-list]` that specifies objects participating in the sequence might include `?` (question mark), which denotes @ref qspy_seq_sys "System Border". The system border is the "environment" that can produce and consume events. The "System Border" denotes possibly **multiple objects** that are not explicitly listed in the `[obj-list]`, including even objects without @ref qs_dict "object dictionaries". The sequence diagram in the previous section shows the "System Border", labeled as `?` and lifeline shown as `//////`. - -@note -You can place the "System Border" (the `?`) anywhere in the `[obj-list]`. However, it is customary to place it either as the very first or the very last object in the list, as shown in the sequence diagram below: - - -The listing below shows a sequence output (`.seq`) generated from the Deferred Event example application with the following `-g` option: - -`-g ?,l_QF_onClockTick,TServer::inst` - - - -@section qspy_seq_exa More Involved Example -The listing below shows an example of a more involved sequence diagram output (`.seq`) generated from the Dining Philosophers Problem (DPP) application with the following `-g` option: - -`-g l_SysTick_Handler,Table::inst,Philo::inst[0],Philo::inst[1],Philo::inst[2],Philo::inst[3],Philo::inst[4]` - - -In addition to the elements described above, this sequence diagram illustrates **event publishing**, which corresponds to the #QS_QF_PUBLISH trace record. The event multicasting is represented as a horizontal line `. . . .`, with the event **source** marked as `*`. - - -
-@verbatim --g l_SysTick_Handler,Table::inst,Philo::inst[0],Philo::inst[1],Philo::inst[2],Philo::inst[3],Philo::inst[4] - - +-------+-------+ +-------+-------+ +-------+-------+ +-------+-------+ +-------+-------+ +-------+-------+ +-------+-------+ - |l_SysTick_Handl| | Table::inst | |Philo::inst[0] | |Philo::inst[1] | |Philo::inst[2] | |Philo::inst[3] | |Philo::inst[4] | - +-------+-------+ +-------+-------+ +-------+-------+ +-------+-------+ +-------+-------+ +-------+-------+ +-------+-------+ -0000042339 . . . . * .SERVE_SIG. . . . | . . . . . . . . . | . . . . . . . . . | . . . . . . . . . | . . . . . . . . . | . . . . . . . . . | . . . -0000042896 *--SERVE_SIG------->| | | | | | -0001070723 *--TIMEOUT_SIG------+-------------------+-------------------+-------------------+-------------------+------------------>| -0001075362 | |<------------------+-------------------+-------------------+-------------------+-------HUNGRY_SIG--* -0001079065 . . . . | . . . . . . . . . * .EAT_SIG. . . . . | . . . . . . . . . | . . . . . . . . . | . . . . . . . . . | . . . . . . . . . | . . . -0001079975 | *--EAT_SIG----------+-------------------+-------------------+-------------------+------------------>| -0001080774 | *--EAT_SIG----------+-------------------+-------------------+------------------>| | -0001081583 | *--EAT_SIG----------+-------------------+------------------>| | | -0001082382 | *--EAT_SIG----------+------------------>| | | | -0001083181 | *--EAT_SIG--------->| | | | | -0001087412 | | | | | | -0001091293 | | | | | | -0001762885 *--TIMEOUT_SIG------+------------------>| | | | | -0001767416 | |<------HUNGRY_SIG--* | | | | -0001772368 | | | | | | -0002097460 . . . . * .PAUSE_SIG. . . . | . . . . . . . . . | . . . . . . . . . | . . . . . . . . . | . . . . . . . . . | . . . . . . . . . | . . . -0002098016 *--PAUSE_SIG------->| | | | | | -0002101049 | | | | | | -0002140275 *--TIMEOUT_SIG------+-------------------+-------------------+------------------>| | | -0002144842 | |<------------------+-------------------+-------HUNGRY_SIG--* | | -0002149765 | | | | | | -0002245145 *--TIMEOUT_SIG------+-------------------+------------------>| | | | -0002249676 | |<------------------+-------HUNGRY_SIG--* | | | -0002254599 | | | | | | -0003104906 *--TIMEOUT_SIG------+-------------------+-------------------+-------------------+------------------>| | -0003109447 | |<------------------+-------------------+-------------------+-------HUNGRY_SIG--* | -0003114370 | | | | | | -0005013277 *--TIMEOUT_SIG------+-------------------+-------------------+-------------------+-------------------+------------------>| -0005016745 . . . . | . . . . . . . . . | . . . . . . . . . | . . . . . . . . . | . . . . . . . . . | . . . . . . . . . | . . . . DONE_SIG. * . . . -0005017655 | |<------------------+-------------------+-------------------+-------------------+---------DONE_SIG--* -0005025076 | | | | | | -0007760487 *--TIMEOUT_SIG------+-------------------+-------------------+-------------------+-------------------+------------------>| -0007764998 | |<------------------+-------------------+-------------------+-------------------+-------HUNGRY_SIG--* -0007769921 | | | | | | -0011827861 . . . . * .SERVE_SIG. . . . | . . . . . . . . . | . . . . . . . . . | . . . . . . . . . | . . . . . . . . . | . . . . . . . . . | . . . -0011828417 *--SERVE_SIG------->| | | | | | -0011832381 . . . . | . . . . . . . . . * .EAT_SIG. . . . . | . . . . . . . . . | . . . . . . . . . | . . . . . . . . . | . . . . . . . . . | . . . -0011833291 | *--EAT_SIG----------+-------------------+-------------------+-------------------+------------------>| -0011834089 | *--EAT_SIG----------+-------------------+-------------------+------------------>| | -0011834887 | *--EAT_SIG----------+-------------------+------------------>| | | -0011835685 | *--EAT_SIG----------+------------------>| | | | -0011836483 | *--EAT_SIG--------->| | | | | -0011839510 . . . . | . . . . . . . . . * .EAT_SIG. . . . . | . . . . . . . . . | . . . . . . . . . | . . . . . . . . . | . . . . . . . . . | . . . -0011840421 | *--EAT_SIG----------+-------------------+-------------------+-------------------+------------------>| -0011841199 | *--EAT_SIG----------+-------------------+-------------------+------------------>| | -0011841977 | *--EAT_SIG----------+-------------------+------------------>| | | -0011842755 | *--EAT_SIG----------+------------------>| | | | -0011843533 | *--EAT_SIG--------->| | | | | -0011846001 | | | | | | -0011864225 | | | | | | -0011874191 | | | | | | -0015268086 *--TIMEOUT_SIG------+-------------------+-------------------+------------------>| | | -0015271590 . . . . | . . . . . . . . . | . . . . . . . . . | . . . . . . . . . | . . . . . . . . . * .DONE_SIG . . . . | . . . . . . . . . | . . . -0015272500 | |<------------------+-------------------+---------DONE_SIG--* | | -0015276635 . . . . | . . . . . . . . . * .EAT_SIG. . . . . | . . . . . . . . . | . . . . . . . . . | . . . . . . . . . | . . . . . . . . . | . . . -0015277545 | *--EAT_SIG----------+-------------------+-------------------+-------------------+------------------>| -0015278343 | *--EAT_SIG----------+-------------------+-------------------+------------------>| | -0015279141 | *--EAT_SIG----------+-------------------+------------------>| | | -0015279939 | *--EAT_SIG----------+------------------>| | | | -0015280737 | *--EAT_SIG--------->| | | | | -0015289641 | | | | | | -0015294035 | | | | | | -0015540732 *--TIMEOUT_SIG------+------------------>| | | | | -0015544272 . . . . | . . . . . . . . . | . . . . . . . . . * .DONE_SIG . . . . | . . . . . . . . . | . . . . . . . . . | . . . . . . . . . | . . . -0015545182 | |<--------DONE_SIG--* | | | | -0015549317 . . . . | . . . . . . . . . * .EAT_SIG. . . . . | . . . . . . . . . | . . . . . . . . . | . . . . . . . . . | . . . . . . . . . | . . . -0015550227 | *--EAT_SIG----------+-------------------+-------------------+-------------------+------------------>| -0015551025 | *--EAT_SIG----------+-------------------+-------------------+------------------>| | -0015551823 | *--EAT_SIG----------+-------------------+------------------>| | | -0015552621 | *--EAT_SIG----------+------------------>| | | | -0015553419 | *--EAT_SIG--------->| | | | | -0015567245 | | | | | | -0015571639 | | | | | | -@endverbatim -
- -
-@nav{qspy_udp,qspy_matlab} -*/ -/*###########################################################################*/ -/** -@page qspy_matlab QSPY MATLAB Support -@nav{qspy_seq,qutest} - -

The QSPY host application can also export trace data to MATLAB®, which is a popular numerical computing environment and a high-level technical programming language. Created by The MathWorks, Inc., MATLAB allows easy manipulation and plotting of data represented as matrices. -

- -@note -The QSPY MATLAB interface is also compatible with the GNU Octave environment, which is an open source alternative to MATLAB and is compatible with the QSPY MATLAB interface described below. - -The following sections provide a reference manual for all 11 of the MATLAB matrices generated by the @c qspy.m script. By MATLAB convention, the different variables are put into columns, allowing observations to vary down -through the rows. Therefore, a data set consisting of twenty-four time samples of six variables is stored in a matrix of size 24-by-6. The pound sign '#' in a given cell of the matrix represents data available from the target. Other values represent data added by the @c qspy.m script to allow unambiguous identification of the trace records. - -- @ref MATLAB_Q_STATE -- @ref MATLAB_Q_ACTIVE -- @ref MATLAB_Q_EQUEUE -- @ref MATLAB_Q_MPOOL -- @ref MATLAB_Q_NEW -- @ref MATLAB_Q_PUB -- @ref MATLAB_Q_TIME -- @ref MATLAB_Q_INT -- @ref MATLAB_Q_ISR -- @ref MATLAB_Q_MUTEX -- @ref MATLAB_Q_SCHED - - -@section MATLAB_Q_STATE Q_STATE Matrix -

The N-by-6 @c Q_STATE matrix stores all QS records generated by the QEP hierarchical event processor and pertaining to all the state machines in the system. The following table summarizes how the QS records are stored in the matrix: -

- -
- -
 MATLAB index --> 1 2 3 4 5 6 -
QS Record Time
Stamp
Signal State
Machine
Object
Source
State
New
State
Event
Handler -
#QS_QEP_STATE_ENTRY NaN 1 #(2) # NaN 1 -
#QS_QEP_STATE_EXIT NaN 2 #(2) # NaN 1 -
#QS_QEP_STATE_INIT NaN 3 # # # 1 -
#QS_QEP_INIT_TRAN # 3 #(2) NaN # 1 -
#QS_QEP_INTERN_TRAN # #(1) #(2) # NaN 1 -
#QS_QEP_TRAN # #(1) #(2) # # 1 -
#QS_QEP_IGNORED # #(1) #(2) # NaN 0 -
#QS_QEP_DISPATCH # #(1) #(2) # NaN 0 -
#QS_QEP_UNHANDLED NaN #(1) #(2) # NaN 0 -
-
- -(1) The valid USER signal is > 3 - -(2) Per inheritance, an active object is a state machine object as well - - -The following criteria (index matrices in MATLAB) unambiguously select the QS -records from the @c Q_STATE matrix: - -
- -
QS Record MATLAB Matrix Index -
#QS_QEP_STATE_ENTRY `Q_STATE(:,2) == 1` -
#QS_QEP_STATE_EXIT `Q_STATE(:,2) == 2` -
#QS_QEP_STATE_INIT `Q_STATE(:,2) == 3` -
#QS_QEP_INIT_TRAN `isnan(Q_STATE(:,4))` -
#QS_QEP_INTERN_TRAN `Q_STATE(:,2) > 3 & isnan(Q_STATE(:,5))` -
#QS_QEP_TRAN `Q_STATE(:,2) > > & ~isnan(Q_STATE(:,5))` -
#QS_QEP_IGNORED `~Q_STATE(:,6)` -
-
- -For example, the following MATLAB plot shows the timing diagrams for all Philo state machines in the DPP example application made by the `philo_timing.m` script located in the directory `qtools/qspy/matlab` (see Section @ref qspy_files). The vertical axis represents states "thinking" (lowest), "hungry" (middle), and "eating" (top). - -@image html FigQSPY.01.jpg "Timing diagrams for all Philo state machines." - - -@section MATLAB_Q_ACTIVE Q_ACTIVE Matrix -

The N-by-5 @c Q_ACTIVE matrix stores QS records pertaining to adding/removing active objects and subscribing to/unsubscribing from events from active objects. The following table summarizes how the QS records are stored in the matrix: -

- -
- -
 MATLAB index --> 1 2 3 4 5 -
QS Record Time
Stamp
Signal Active
Object
QF
Priority
Delta -
#QS_QF_ACTIVE_SUBSCRIBE # # # NaN +1 -
#QS_QF_ACTIVE_UNSUBSCRIBE # # # NaN -1 -
-
- -The following criteria (index matrices in MATLAB) unambiguously select the QS records from the @c Q_ACTIVE matrix: - -
- -
QS Record MATLAB Matrix Index -
#QS_QF_ACTIVE_SUBSCRIBE `isnan(Q_ACTIVE(:,4)) & Q_ACTIVE(:,5) > 0` -
#QS_QF_ACTIVE_UNSUBSCRIBE `isnan(Q_ACTIVE(:,4)) & Q_ACTIVE(:,5) < 0` -
-
- - -@section MATLAB_Q_EQUEUE Q_EQUEUE Matrix -

The N-by-10 @c Q_EQUEUE matrix stores QS records pertaining to queuing events in the QF. Both the active object event queues and the "raw" thread-safe queues are included. The 'nUsed' field denotes the current number of used entries in the queue. The 'Maximum nUsed' field denotes the maximum number of used entries since initialization (high watermark). Both fields contain the number of used entries in the queue's ring-buffer plus one, to account for the extra location at the front of the queue. The following table summarizes how the QS records are stored in the matrix: -

- -
- -
 MATLAB index --> 1 2 3 4 5 6 7 8 9 10 -
QS Record Time
Stamp
Sender Event
Queue (1)
nFree Minimum
Used
Signal Pool ID Ref.
Count
LIFO Delta -
#QS_QF_ACTIVE_POST # # # # # # # # 0 +1 -
#QS_QF_ACTIVE_POST_LIFO # # # # # # # # 1 +1 -
#QS_QF_ACTIVE_GET # NaN # # NaN # # # 0 -1 -
#QS_QF_ACTIVE_GET_LAST # NaN # NaN NaN # # # 0 -1 -
#QS_QF_EQUEUE_POST # NaN # # # # 1 # 0 +1 -
#QS_QF_EQUEUE_POST_LIFO # NaN # # # # # # 1 +1 -
#QS_QF_EQUEUE_GET # NaN # # # # # # 0 -1 -
#QS_QF_EQUEUE_GET_LAST # NaN # NaN NaN # # # 0 -1 -
-
- -(1) This field (index 3) is actually the pointer to the ring buffer of the queue. - -The following criteria (index matrices in MATLAB) unambiguously select the QS records from the @c Q_EQUEUE matrix: - -
- -
QS Record MATLAB Matrix Index -
#QS_QF_ACTIVE_POST `Q_EQUEUE(:,3) == <active obj> & ~Q_EQUEUE(:,9) & Q_EQUEUE(:,10) > 0` -
#QS_QF_ACTIVE_POST_LIFO `Q_EQUEUE(:,3) == <active obj> & Q_EQUEUE(:,9) & Q_EQUEUE(:,10) > 0` -
#QS_QF_ACTIVE_GET `Q_EQUEUE(:,3) == <active obj> & ~isnan(Q_EQUEUE(:,4) & Q_EQUEUE(:,10) < 0` -
#QS_QF_ACTIVE_GET_LAST `Q_EQUEUE(:,3) == <active obj> & isnan(Q_EQUEUE(:,4) & Q_EQUEUE(:,10) < 0` -
#QS_QF_EQUEUE_POST `Q_EQUEUE(:,3) == <raw queue> & ~Q_EQUEUE(:,9) & Q_EQUEUE(:,10) > 0` -
#QS_QF_EQUEUE_POST_LIFO `Q_EQUEUE(:,3) == <raw queue> & Q_EQUEUE(:,9) & Q_EQUEUE(:,10) > 0` -
#QS_QF_EQUEUE_GET `Q_EQUEUE(:,3) == <raw queue> & ~isnan(Q_EQUEUE(:,4) & Q_EQUEUE(:,10) < 0` -
#QS_QF_EQUEUE_GET_LAST `Q_EQUEUE(:,3) == <raw queue> & isnan(Q_EQUEUE(:,4) & Q_EQUEUE(:,10) < 0` -
-
- - -@section MATLAB_Q_MPOOL Q_MPOOL Matrix -

The N-by-5 @c Q_MPOOL matrix stores QS records pertaining to memory pools in the QF. The 'nFree' field denotes the current number of free blocks in the event pool. The 'Minimum nFree' field denotes the minimum number of free blocks since initialization (low watermark). The following table summarizes how the QS records are stored in the matrix: -

- -
- -
 MATLAB index --> 1 2 3 4 5 -
QS Record Time
Stamp
Pool
Object
nFree Minimal
nFree
Delta -
#QS_QF_MPOOL_GET # # # # -1 -
#QS_QF_MPOOL_PUT # # # NaN +1 -
-
- -The cumulative sum over the 'Delta' column should not have any long-time trends, because this would indicate a leak from the pool. The following picture shows the plot for the test data. - -@image html FigQSPY.02.jpg "Plot stairs(Q_MPOOL(:,1), cumsum(Q_MPOOL(:,5)))" - -The following criteria (index matrices in MATLAB) unambiguously select the QS -records from the @c Q_MPOOL matrix: - -
- -
QS Record MATLAB Matrix Index -
#QS_QF_MPOOL_GET `Q_MPOOL(:,5) < 0` -
#QS_QF_MPOOL_PUT `Q_MPOOL(:,5) > 0` -
-
- - -@section MATLAB_Q_NEW Q_NEW Matrix -

The N-by-6 @c Q_NEW matrix stores QS records pertaining to dynamic event allocation and automatic event recycling (garbage collection) in the QF. The following table summarizes how the QS records are stored in the matrix: -

- -
- -
 MATLAB index --> 1 2 3 4 5 6 -
QS Record Time
Stamp
Signal PoolID Ref.
Count
Event
Size
Delta -
#QS_QF_NEW # # NaN NaN # +1 -
#QS_QF_GC_ATTEMPT # # # # NaN 0 -
#QS_QF_GC # # # NaN NaN -1 -
-
- -The cumulative sum over the 'Delta' column should not have any long-time trends, because this would indicate event leak. The following picture shows the plot for the test data. - -@image html FigQSPY.03.jpg "Plot stairs(Q_NEW(:,1), cumsum(Q_NEW(:,6)))" - -The following criteria (index matrices in MATLAB) unambiguously select the QS -records from the @c Q_NEW matrix: - -
- -
QS Record MATLAB Matrix Index -
#QS_QF_NEW `Q_NEW(:,6) > 0` -
#QS_QF_GC_ATTEMPT `Q_NEW(:,6) == 0` -
#QS_QF_GC `Q_NEW(:,6) < 0` -
-
- - -@section MATLAB_Q_PUB Q_PUB Matrix -

The N-by-7 @c Q_PUB matrix stores QS records pertaining to publishing events in QF. The following table summarizes how the QS records are stored in the matrix: -

- -
- -
 MATLAB index --> 1 2 3 4 5 6 7 -
QS Record Time
Stamp
Sender Signal PoolID Ref.
Count
# Events
Multicast
Delta -
#QS_QF_PUBLISH # # # # # # # -
-
- -The following criteria (index matrices in MATLAB) unambiguously select the QS -records from the @c Q_PUB matrix: - -
- -
QS Record MATLAB Matrix Index -
#QS_QF_PUBLISH `Q_PUB(:,7) > 0` -
-
- - -@section MATLAB_Q_TIME Q_TIME Matrix -

The N-by-7 @c Q_TIME matrix stores QS records pertaining to time events in QF. The following table summarizes how the QS records are stored in the matrix: -

- -
- -
 MATLAB index --> 1 2 3 4 5 6 7 -
QS Record Time
Stamp
QTimeEvt
Object
Signal QActive
Object
QTimeEvt
Counter
QTimeEvt
Interval
QTimeEvt
Delta -
#QS_QF_TICK NaN NaN NaN NaN #(1) NaN 0 -
#QS_QF_TIMEEVT_ARM # # NaN # # # +1 -
#QS_QF_TIMEEVT_DISARM # # NaN # # # -1 -
#QS_QF_TIMEEVT_AUTO_DISARM NaN # NaN # NaN NaN -1 -
#QS_QF_TIMEEVT_DISARM_ATTEMPT # # NaN # NaN NaN 0 -
#QS_QF_TIMEEVT_REARM # # NaN # # # #(2) -
#QS_QF_TIMEEVT_POST # # # # NaN NaN 0 -
-
- -(1) For #QS_QF_TICK record this matrix element contains the Tick Counter. - -(2) For #QS_QF_TIMEEVT_REARM event this matrix element is 0 if the time event was disarmed and rearmed again, and 1 if the time event was only armed. - -The cumulative sum over the 'Delta' column indicates the total number of armed time events at any given time. The following picture shows the plot for the test data: - -@image html FigQSPY.04.jpg "Plot stairs(Q_TIME(:,1), cumsum(Q_TIME(:,7)))" - -The following criteria (index matrices in MATLAB) unambiguously select the QS -records from the @c Q_TIME matrix: - -
- -
QS Record MATLAB Matrix Index -
#QS_QF_TICK `isnan(Q_TIME(:,2))` -
#QS_QF_TIMEEVT_ARM `Q_TIME(:,7) > 0` -
#QS_QF_TIMEEVT_DISARM `~isnan(Q_TIME(:,1)) & Q_TIME(:,7) < 0` -
#QS_QF_TIMEEVT_AUTO_DISARM `isnan(Q_TIME(:,1)) & Q_TIME(:,7) < 0` -
#QS_QF_TIMEEVT_DISARM_ATTEMPT `isnan(Q_TIME(:,3)) & isnan(Q_TIME(:,5)) & Q_TIME(:,7) == 0` -
#QS_QF_TIMEEVT_REARM `isnan(Q_TIME(:,3)) & ~isnan(Q_TIME(:,5))` -
#QS_QF_TIMEEVT_POST `~isnan(Q_TIME(:,3)) & ~isnan(Q_TIME(:,4))` -
-
- -@section MATLAB_Q_INT Q_INT Matrix -

The N-by-3 @c Q_INT matrix stores QS records pertaining to interrupt disabling and enabling. The following table summarizes how the QS records are stored in the matrix: -

- -
- -
 MATLAB index -->1 2 3 -
QS Record Time
Stamp
Interrupt
Nesting
Nesting
Delta -
#QS_QF_INT_DISABLE# # +1 -
#QS_QF_INT_ENABLE # # -1 -
-
- -The cumulative sum over the 'Delta' column indicates interrupt lock nesting -and should closely follow column 2. - -The following criteria (index matrices in MATLAB) unambiguously select the QS -records from the @c Q_INT matrix: - -
- -
QS Record MATLAB Matrix Index -
#QS_QF_INT_DISABLE `Q_INT(:,3) > 0` -
#QS_QF_INT_ENABLE `Q_INT(:,3) < 0` -
-
- - -@section MATLAB_Q_ISR Q_ISR Matrix -

The N-by-4 @c Q_ISR matrix stores QS records pertaining to interrupt entry and exit. The following table summarizes how the QS records are stored in the matrix: -

- -
- -
 MATLAB index --> 1 2 3 4 -
QS Record Time
Stamp
Interrupt
Nesting
ISR
Priority
Nesting
Delta -
#QS_QF_ISR_ENTRY # # # +1 -
#QS_QF_ISR_EXIT # # # -1 -
-
- -The cumulative sum over the 'Delta' column indicates interrupt nesting level and should closely follow column 2. - -The following criteria (index matrices in MATLAB) unambiguously select the QS records from the @c Q_ISR matrix: - -
- -
QS Record MATLAB Matrix Index -
#QS_QF_ISR_ENTRY `Q_ISR(:,4) > 0` -
#QS_QF_ISR_EXIT `Q_ISR(:,4) < 0` -
-
- - -@section MATLAB_Q_MUTEX Q_MUTEX Matrix -

The N-by-4 @c Q_MUTEX matrix stores QS records pertaining to the priority-ceiling mutex activity in QK. The following table summarizes how the QS records are stored in the matrix: -

- -
- -
 MATLAB index --> 1 2 3 4 -
QS Record Time
Stamp
Original
Priority
Priority
Ceiling
Nesting
Delta -
#QS_MUTEX_LOCK # # # +1 -
#QS_MUTEX_UNLOCK # # # -1 -
-
- - -The cumulative sum over the 'Delta' column indicates the QK scheduler lock nesting level. - -@image html FigQSPY.05.jpg "Plot stairs(Q_MUTEX(:,1), cumsum(Q_MUTEX(:,4)), 'r') (red)" - - -The following criteria (index matrices in MATLAB) unambiguously select the QS records from the @c Q_ISR matrix: - -
- -
QS Record MATLAB Matrix Index -
#QS_MUTEX_LOCK `Q_MUTEX(:,4) > 0` -
#QS_MUTEX_UNLOCK `Q_MUTEX(:,4) < 0` -
-
- - -@section MATLAB_Q_SCHED Q_SCHED Matrix -

The N-by-3 @c Q_SCHED matrix stores QS records pertaining to scheduling the next task in QK. The following table summarizes how the QS records are stored in the matrix: -

- -
- -
 MATLAB index --> 1 2 3 -
QS Record Time
Stamp
Preempted
Priority
New
Priority -
#QS_SCHED_NEXT # # # -
-
- -
-@nav{qspy_seq,qutest} -*/ diff --git a/doxygen/qutest.dox b/doxygen/qutest.dox deleted file mode 100644 index b8c9df3..0000000 --- a/doxygen/qutest.dox +++ /dev/null @@ -1,689 +0,0 @@ -/*! @page qutest QUTest™ Unit Testing Harness - -@image html qutest_banner.jpg -@image latex qutest_banner.jpg width=6.5in - -@subpage qutest_use " " -@subpage qutest_conc " " -@subpage qutest_tut " " -@subpage qutest_fixture " " -@subpage qutest_script " " - -@section qutest_about About QUTest™ -QUTest™ (pronounced "cutest") is a **unit testing harness** (a.k.a. *unit testing framework*), which is specifically designed for deeply embedded systems, but also supports unit testing of embedded code on host computers ("dual targeting"). QUTest™ is the fundamental tooling for Test-Driven Development (TDD) of QP/C/C++ applications, which is a highly recommended best-practice. - -@note -Even though QUTest™ has been primarily designed for testing of event-driven systems, it can also be used to test **any embedded C or C++ code**. To demonstrate this capability, QUTest™ comes with a few examples from the conventional Unity testing framework, which among others demonstrates such techniques as using test doubles and mocks with QUTest™. - - -@subsection qutest_how How does it work? -In a nutshell, working with QUTest™ is similar to "debugging with printf" (or `sprintf` or similar), where you instrument the code to output information about its execution. You then run the code with a controlled set of inputs, and examine the produced output from the `printf`s to determine whether the code under test operates correctly. The main differences from using `printf`s are: (1) the much more efficient @ref qpspy "QP/Spy" output mechanism is used instead and (2) both generating the inputs and checking of the test outputs are **automated**. - -The process of testing embedded code with QUTest™ involves the following components: - --# The **Target**, which runs an instrumented @ref qutest_fixture "test fixture" code, whose job is to exercise your Code Under Test (CUT). Please note that a @ref qutest_fixture "test fixture" only exercises the CUT and reports the results to the host using @ref qpspy "QP/Spy", but the @ref qutest_fixture "test fixture" does **not** check if the CUT operates "correctly".
-@note Of course, the @ref qutest_fixture "test fixture" is written in the same programming language as the CUT (C or C++) and it links statically with the CUT. Several examples of *test fixtures* are explained in the @ref qutest_tut "QUTest Tutorial". The details of *test fixtures* are described in @ref qutest_fixture "QUTest Fixture Reference". - --# The @ref qspy "QSPY" "back-end" application running on the host, which receives the tracing data from the Target and also opens a communication channel for the QUTest "front-end". - --# The **QUTest** "front-end" also running on the host that executes @ref qutest_script "test scripts". The *test scripts* (written in Python) drive the tests and check the QSPY output against the expectations ("test-assertions").
-@note -Several examples of *test scripts* are explained in the @ref qutest_tut "QUTest Tutorial". The details of *test scripts* are described in @ref qutest_script "QUTest Script Reference". - -
-![Communication between Target, QSPY, and QUTest](qutest_targ.gif) - - -@remark -The separation between CUT execution and checking the test results has many benefits. One of the most important ones is that CUT execution (@ref qutest_fixture "test fixture") and checking the results (@ref qutest_script "test script") can be done in *different programming languages*. To this end QUTest™ provides support for writing the @ref qutest_script "test scripts in Python". -
-@image html logo_python3.png -@image latex logo_python3.png width=5.0in - - -The general QUTest™ structure just described corresponds to running tests on an embedded Target. But QUTest™ can also execute tests on the **host computer**. In that case (shown in the figure below), the *@ref qutest_fixture "test fixture"* is a host executable that communicates with the @ref qspy_command "QSPY host application" via a TCP/IP socket. In this case all QUTest™ components execute on the host computer. - -![QUTest with Host Executable](qutest_host.gif) - - -@remark -To work effectively with QUTest™, you need to understand **how much output to expect from any given input**. Additionally, you need to understand how QUTest ensures that for every input to the @ref qutest_fixture "test fixture", the generated QSPY output matches all test expectations and that there are no extra expectations or missing expectations after every command from the @ref qutest_script "test script". These subjects are explained in the section @ref qutest_conc "Run-to-Completion Processing". - - -@subsection qutest_special What's Special about QUTest™? -Unlike other existing unit testing harnesses for embedded systems (e.g., Unity or CppUTest) QUTest™ is **not based on** xUnit, which was originally designed to run tests on host computers. Instead, QUTest™ is geared towards unit testing of **deeply embedded systems**. Here is a list of QUTest™ unique features, specifically designed for this purpose: - -- QUTest™ separates *execution* of the CUT (Code Under Test) from *checking* of the "test assertions". The embedded target is concerned only with running a @ref qutest_fixture "test fixture" that exercises the CUT and produces the QP/Spy™ trace, but it does *not* check the "test assertions". Checking the "test assertions" against the expectations is performed on the host computer by means of @ref qutest_script "test scripts". - -- The QUTest™ approach is more **intuitive for embedded developers**, because it is conceptually like automated "debugging by printf" that most embedded developers use extensively. As it turns out, this approach also simplifies the development of all sorts of test doubles, including mocks, *without breaking encapsulation* of the CUT. - -- QUTest™ is a unique test harness on the embedded market that supports **scripting**. QUTest @ref qutest_script "test scripts" run on the Host, which skips compiling and uploading the code to the Target and thus shortens the TDD micro-cycle. - -@note -QUTest™ supports *test scripts* written in [Python](https://www.python.org) (3.3+). - - -- QUTest™ supports **resetting the Target** for each individual test, if needed. This goes far beyond providing test `setup()` and `teardown()` functions that other test fixtures offer (and of course QUTest supports as well). Clean reset of the Target avoids erroneous tests that implicitly rely on side effects from previously executed code. This is particularly important for embedded systems and for state machines, so that each test can start from a known reset condition. - -- QUTest™ supports **testing Design by Contract** (assertions in C or C++, not to be confused with "test assertions") in the CUT. This is a carefully designed, unique feature of QUTest not available in other test harnesses. A successful test of DbC might actually mean breaking an assertion in the Target code. - -- QUTest™ @ref qutest_fixture "test fixtures" that run on the Target **do not require dynamic memory** allocation (`malloc()/free()` in C or `new/delete` in C++). This means that you don't need to commit any of your precious embedded RAM to the heap (you can set the heap size to zero) and you don't need to link the heap management code. Avoiding dynamic memory allocation is one of the best practices of real-time embedded programming, which you don't need to compromise to run QUTest. - -- QUTest™ @ref qutest_fixture "test fixtures" that run on the Target **do not require non-local jumps** (`setjmp()()/longjmp()` in C or `throw/catch` in C++), which are needed by other test harnesses to discontinue failing tests. QUTest™ *test fixtures* do not need to discontinue failing tests, because they don't check "testing assertions", so a *test fixture does* not "know" if it is failing or passing. Should a test fixture crash on the Target, it simply waits for the target reset commanded by a @ref qutest_script "test script". - -- QUTest™ @ref qutest_fixture "test fixtures" can be based on the actual **application code**. For example, you can reuse the same `main()` function in a @ref qutest_fixture "test fixture" and in your final application. This means that you can either grow your @ref qutest_fixture "test fixture" into a final application through TDD, or you can more easily add unit tests to an existing application. - -@note -Even though QUTest™ is particularly suitable for running tests on deeply embedded targets, it also fully supports running *the same* tests on your **host computer** (Windows, Linux, and MacOS are supported). In fact, running the tests as much as possible on the host and thus avoiding the target-hardware bottleneck is the highly recommended best-practice of embedded TDD. QUTest™ supports **fully-automated** unit testing, both on the embedded target and on the host computer. - - -@nav_next{qutest_use} -*/ - -/*###########################################################################*/ -/*! @page qutest_use Installation & Use -@nav{qutest,qutest_conc} - -In order to run tests in the QUTest test system, you need the following three components: - -1. The @ref qutest_fixture "test fixture" running on a remote target (or the host computer) -2. The @ref qspy "QSPY host application" running and connected to the target -3. The @ref qutest_script "qutest.py script runner" and some test scripts - -This section describes how to install and use the "qutest.py script runner" component. - -@section qutest_inst Installation -The "qutest.py script runner" can be used standalone, without installation in your Python system (see @ref qutest_exa below). - -@note -The qutest.py script is included in the @ref qtools_about "QTools™ collection". Also, the @ref qtools_win "QTools™ collection for Windows" already includes Python (3.8), so you don't need to install anything extra. - - -Alternatively, you can use **your own Python** installation, into which you can install the latest QUTest™ with `pip` from the [PyPi index](https://pypi.org/project/qutest/) by executing the following command: - -@verbatim -pip install qutest -@endverbatim - -If you are using QUTest™ as a standalone Python script, you invoke it as follows: - -@verbatim -python3 /qutest.py -@endverbatim - -Alternatively, if you've installed `qutest.py` with `pip`, you invoke it as follows: - -@verbatim -qutest -@endverbatim - - -@section qutest_command Command-line Options -The Python test scripts are executed by the QUTest test script runner `qutest.py` (located in `qtools/qutest/` folder), with the following usage: - -@attention -The `qutest.py` script runner command-line options have been expanded and changed at @ref qtools_7_2_0 "version 7.2.0". Unfortunately, it was not possible to preserve the backwards compatibility with the earlier versions. - -@verbatim -usage: python qutest.py [-h] [-v] [-e [EXE]] [-q [QSPY]] [-l [LOG]] [-o [OPT]] [scripts ...] - -QUTest test script runner - -positional arguments: - scripts List (comma-separated) of test scripts to run - -options: - -h, --help show this help message and exit - -v, --version Display QUTest version - -e [EXE], --exe [EXE] - Optional host executable or debug/DEBUG - -q [QSPY], --qspy [QSPY] - optional qspy host, [:ud_port][:tcp_port] - -l [LOG], --log [LOG] - Optional log directory (might not exist yet) - -o [OPT], --opt [OPT] - xciob: x:exit-on-fail,i:inter,c:qspy-clear,o:qspy-save-txt,b:qspy-save-bin - -More info: https://www.state-machine.com/qtools/qutest.html -@endverbatim - -where:
- -@param [scripts] optional specification of the Python test scripts to run. - If not specified, `qutest.py` will try to run all *.py files - in the current directory as test scripts. - -@param -e[exe] optional specification of the host executable to - launch for testing embedded code on the host computer. - If `exe` is **not** specified a remote (embedded) target is assumed. - The special value `debug` or `DEBUG` means that `qutest.py` - will start in the **debug mode**, in which it will NOT launch - the host executable and it will wait for the Target reset - and other responses from the Target. - -@param -q[host][:ud_port][:tcp_port] optional host-name/IP-address:udp_port:tcp_port - for the machine running the QSpy utility. If not specified, - the default is `localhost:7701:6601`. - -@param -l[log] Optional directory for output of the log file - (directory will be created if it does not exist yet). - -@param -o[opt] options for the QUTest script runner to perform the - following actions:
- x : exit on first failed test
- i : interactive mode
- c : clear the QSPY screen just after attaching
- o : save the QSPY text output to a file (in the QSPY launch directory)
- b : save the QSPY binary output to a file (in the QSPY launch directory) - -@note -For reliable operation it is recommended to apply the short options *without* a space between the option and the parameter (e.g., `-q192.168.1.100`, `-oci`). - - -@section qutest_exa Examples - -@subsection qutest_exa_win Windows Hosts -
- -@verbatim -[1] python3 %QTOOLS%\qutest\qutest.py -[2] python3 %QTOOLS%\qutest\qutest.py -- test_mpu.py -[3] python3 %QTOOLS%\qutest\qutest.py -ebuild/test_dpp.exe -[4] python3 %QTOOLS%\qutest\qutest.py -ebuild/test_dpp.exe -q192.168.1.100 -l../log -oco -[5] qutest -qlocalhost:7702 -oxc -- test_qk.py,test_mpu.py -[6] python3 %QTOOLS%\qutest\qutest.py -eDEBUG -- test_mpu.py -@endverbatim - -`[1]` runs all test scripts (`*.py`) in the current directory on a remote target connected to QSPY host utility. - -`[2]` runs the test script `test_mpu.py` in the current directory on a remote target connected to QSPY host utility. - -`[3]` runs all test scripts (`*.py`) in the current directory and uses the host executable `build/test_dpp.exe` (test fixture). - -`[4]` runs all test scripts (`*.py`) in the current directory, uses the host executable `build/test_dpp.exe` (test fixture), and connects to QSPY running on a machine with IP address `192.168.1.100`. Also produces QUTest log (-l) in the directory `../log`. Also clears the QUTest screen before the run (-oc) and causes QSPY to save the text output to a file (-oo) - -`[5]` runs "qutest" (**installed with pip**) to execute the test scripts `test_qk.py,test_mpu.py` in the current directory, and connects to QSPY at UDP-host:port `localhost:7701`. - -`[6]` runs "qutest" in the DEBUG mode to execute the test script `test_mpu.py` in the current directory. - -
- - -@subsection qutest_exa_posiz Linux/macOS Hosts -
- -@verbatim -[1] python3 $(QTOOLS)/qutest/qutest.py -[2] python3 $(QTOOLS)/qutest/qutest.py -- test_mpu.py -[3] python3 $(QTOOLS)/qutest/qutest.py -ebuild/test_dpp -[4] python3 $(QTOOLS)/qutest/qutest.py -ebuild/test_dpp -q192.168.1.100 -l../log -oco -[5] qutest -qlocalhost:7702 -oxc -- test_qk.py,test_mpu.py -[6] python3 $(QTOOLS)/qutest/qutest.py -eDEBUG -- test_mpu.py -@endverbatim - -`[1]` runs all test scripts (`*.py`) in the current directory on a remote target connected to QSPY host utility. - -`[2]` runs the test script `test_mpu.py` in the current directory on a remote target connected to QSPY host utility. - -`[3]` runs all test scripts (`*.py`) in the current directory and uses the host executable `build/test_dpp` (test fixture). - -`[4]` runs all test scripts (`*.py`) in the current directory, uses the host executable `build/test_dpp` (test fixture), and connects to QSPY running on a machine with IP address `192.168.1.100`. Also produces QUTest log (-l) in the directory `../log`. Also clears the QUTest screen before the run (-oc) and causes QSPY to save the text output to a file (-oo) - -`[5]` runs "qutest" (**installed with pip**) to execute the test scripts `test_qk.py,test_mpu.py` in the current directory, and connects to QSPY at UDP-host:port `localhost:7701`. - -`[6]` runs "qutest" in the DEBUG mode to execute the test script `test_mpu.py` in the current directory. - - -@section qutest_inter Interactive Mode -Similar to the Python interpreter itself, the `qutest.py` test runner has two basic modes: script (default) and interactive. In the default script mode, the test runner executes the test scripts as fast as possible and exits. In the interactive mode, the test runner pauses and executes commands *interactively* @ref from the terminal input. The interactive mode is activated by providing the `-oi` @ref qutest_command "command-line option". Interactive mode is a good way to play around and try the system's response to various commands. Also, interactive mode can be used to provide stimuli for debugging the @ref qutest_fixture "test fixture". - -Once activated, the interactive mode works as follows: - -- If any test scripts are provided, after each test group (test script) the test runner enters an interactive session, where the user can manually enter any supported test commands. These commands are executed in the context of the *last test in the group*. It is also possible to start a new test interactively (by providing the @ref qutest_dsl::test() "test()" command). In that case, the interactively entered commands will be executed in the context of the new test. - -- If no test scripts are provided, the test runner enters an interactive session immediately. In that case, the user must provide the @ref qutest_dsl::test() "test()" command manually (perhaps after defining the @ref qutest_dsl-preamble "test callbacks"). - -In either case, the interactive mode is shown by the presence of the `>>> ` command prompt. During an interactive session the output produced by the text fixture is displayed after each interactive command entered. The output is **not** checked against any expectations. In fact, the @ref qutest_dsl::expect() "expect()" command itself makes no sense in the interactive mode. Also, all tests that are interactive are considered "SIKPPED" and are not evaluated as "PASS" or "FAIL". - -@note -You can use the `Up-arrow` and `Down-arrow` keys on your keyboard to navigate through the list of previous commands. You end the interactive session by providing an "empty" command, that is by pressing the `` key right at the `>>> ` command prompt - -Here is an example of an interactive session with test scripts provided. (Note the annotations added after the `//` comments). - -@verbatim -C:\qp\qpc\examples\qutest\qhsmtst\test>make OPT=i // <--- NOTE OPT=i - -python3 C:\qp\qtools/qutest/qutest.py -ebuild/test_qhsmtst.exe -q -l -oci -- - -QUTest unit testing front-end 7.2.1 running on Python 3.10.1 -Copyright (c) 2005-2022 Quantum Leaps, www.state-machine.com -Attaching to QSpy (localhost:7701) ... OK - -Run ID : 230111_174610 -Target : build/test_qhsmtst.exe - -==================================[Group 1]================================== -test_qhsm-funct.py -[ 1]-------------------------------------------------------------------------- -QHsmTst_init - [ PASS ( 0.1s) ] -[ 2]^------------------------------------------------------------------------- -QHsmTst dispatch ->>> dispatch('A_SIG') // <--- interactive command -0000000127 BSP_DISPLAY s1-A; -0000000128 BSP_DISPLAY s11-EXIT; -0000000129 BSP_DISPLAY s1-EXIT; -0000000130 BSP_DISPLAY s1-ENTRY; -0000000131 BSP_DISPLAY s1-INIT; -0000000132 BSP_DISPLAY s11-ENTRY; -0000000133 Trg-Done QS_RX_EVENT ->>> dispatch('B_SIG') // <--- interactive command -0000000134 BSP_DISPLAY s1-B; -0000000135 BSP_DISPLAY s11-EXIT; -0000000136 BSP_DISPLAY s11-ENTRY; -0000000137 Trg-Done QS_RX_EVENT ->>> // <--- end of interactive session - interactive test shows as "skipped" ---> [ SKIPPED ] - -==================================[Group 2]================================== -test_qhsm-struct.py -[ 3]-------------------------------------------------------------------------- -QHsmTst init - [ PASS ( 0.1s) ] -[ 4]^------------------------------------------------------------------------- -QHsmTst dispatch ->>> // <--- end of interactive session - [ SKIPPED ] - -==================================[ SUMMARY ]================================= - -Target ID : 230111_170758 (QP-Ver=721) -Log file : -Groups : 2 -Tests : 4 -Skipped : 2 [ 2 4 ] -Failed : 0 - -==============================[ OK ( 20.1s) ]=============================== -@endverbatim - - -@section qutest_log Generating Test Logs -As required for safety certification, the `qutest.py` test runner can generate permanent records of the runs by producing **log files**. This feature is enabled by the `-l` command-line option. - -@remark -The various make-files supplied in QP/C and QP/C++ allow you to supply the command-line options for saving QUTest logs (by defining the `LOG=` symbol while invoking `make`), for example: -@verbatim -[1] make LOG=. -[2] make LOG=../log -[3] make LOG=c:/cert/logs -@endverbatim -`[1]` generates QUTest log file in the current directory (`.`) - -`[2]` generates QUTest log file in the `../log` directory (relative to the current directory) - -`[3]` generates QUTest log file in the absolute directory `c:/cert/logs` - -The following following listing shows the generated log file: - -The following screen shot shows the qutest.py screen output in which a log file has been produced (with the `-l.` command-line option): - -@image html qutest-out.png -@image latex qutest-out.png with=4.0in - -And the following listing shows the generated log file: - -@verbatim -Run ID : 221221_161550 -Target : build/test_qutest.exe - -===================================[group]==================================== -test_assert.py - -This test group contains tests that intenionally FAIL, -to exercise failure modes of the QUTest system. - -[ 1]-------------------------------------------------------------------------- -Expected assertion - [ PASS ( 0.1s) ] -[ 2]-------------------------------------------------------------------------- -Unexpected assertion (should FAIL!) - @test_assert.py:22 -exp: "0000000002 COMMAND CMD_A 0" -got: "0000000002 =ASSERT= Mod=test_qutest,Loc=100" -! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ![ FAIL ( 0.2s) ] -[ 3]-------------------------------------------------------------------------- -Simple passing test - [ PASS ( 0.1s) ] -[ 4]-------------------------------------------------------------------------- -Wrong assertion expectation (should FAIL!) - @test_assert.py:32 -exp: "0000000002 =ASSERT= Mod=test_qutest,Loc=200" -got: "0000000002 =ASSERT= Mod=test_qutest,Loc=100" -! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ![ FAIL ( 1.1s) ] -[ 5]-------------------------------------------------------------------------- -Simple passing test - [ PASS ( 0.1s) ] - -=================================[ SUMMARY ]================================== - -Target ID : 221221_161031 (QP-Ver=720) -Log file : ./qutest221221_161550.txt -Groups : 1 -Tests : 5 -Skipped : 0 -FAILED : 2 [ 2 4 ] - -==============================[ FAIL ( 2.7s) ]=============================== -@endverbatim - - -@section qutest_qspy_log Generating QSPY Logs -Additionally, it is also possible to generate logs files from the QSPY output. This feature is enabled by the `-oo` and `-ob` command-line options. - -- the option `-oo` saves the QSPY text output generated during the qutest.py run. QSPY saves the output in the directory from which it was launched. - -- the option `-ob` saves the QSPY raw binary output received from the test fixture during the qutest.py run. QSPY saves the output in the directory from which it was launched. - -@remark -The various make-files supplied in QP/C and QP/C++ allow you to supply the command-line options for saving QSPY logs (by defining the `OPT=` symbol while invoking `make`), for example: -@verbatim -[1] make OPT=o -[2] make OPT=b -[3] make OPT=ob -@endverbatim -`[1]` generates QSPY text output (in the QSPY launch directory)
-`[2]` generates QSPY binary output (in the QSPY launch directory)
-`[3]` generates both QSPY text and binary outputs (in the QSPY launch directory) - -@nav{qutest,qutest_conc} -*/ - -/*###########################################################################*/ -/*! @page qutest_conc QUTest Concepts -@nav{qutest_use,qutest_tut} - -@section qutest_rtc Run-to-Completion Processing -The central concept applied in QUTest is **Run-to-Completion (RTC)** processing, both in the @ref qutest_fixture "test fixture" (Target) and in the @ref qutest_script "test script" (Host). RTC processing means that the code progresses in discrete, uninterruptible steps and that new inputs (commands) are recognized only *after* the current RTC step completes. - -@attention -RTC Processing is the key to understanding **how much output to expect from any given input** as well as **when a given input will be processed**. - - -Of course, it is not a coincidence that the RTC processing of QUTest exactly matches the RTC processing in event-driven systems of state machines. And the good news here is that for all interactions with state machines, the RTC output generated by a @ref qutest_fixture "test fixture" will correspond exactly to the RTC step in the state machine. - -However, a bit more tricky parts are the system reset, test initialization, and general processing of @ref qutest_dsl-commands "commands" issued by @ref qutest_script "test scripts". The following sections explain these parts by means of annotated sequence diagrams. - -@remark -For simplicity, the sequence diagrams in this section omit the QSPY intermediary from the communication between a @ref qutest_fixture "test fixture" (Target) and a @ref qutest_script "test script". It is understood that every command from the @ref qutest_script "test script" goes to QSPY first and then is forwarded to the Target, and that every output from the Target goes through QSPY to reach the @ref qutest_script "test script". - - -@section qutest_reset Target Reset -Most individual tests in a @ref qutest_script "test script" start with a clean **target reset**. The following sequence diagram shows the details of this process. The explanation section following the diagram clarifies the interesting points (labeled with `[xx]`). : - -![Target reset](qutest_reset.gif) - - -`[0]` A @ref qutest_script "test script" executes the @ref qutest_dsl::test() "test()" command. - -`[1]` By default, each test starts with calling an internal function `reset()` to reset the Target. This `reset()` function sends the ::QS_RX_RESET request to the @ref qutest_fixture "test fixture". After this, the @ref qutest_script "test script" enters a wait state in which it waits for ::QS_TARGET_INFO reply from the Target. -
-The Target reset can be suppressed by the `NORESET` option given in the @ref qutest_dsl::test() "test()" command, which is illustrated in the @ref qutest_noreset "NORESET Tests" sequence diagram. Please note, however, that the first test in a @ref qutest_script "test script" (test group) and any test immediately following an "assertion-test" **must** cleanly reset the Target (therefore it cannot use the `NORESET` option). - -`[2]` The @ref qutest_fixture "test fixture" processes the ::QS_RX_RESET request immediately by calling the QS_onReset() callback inside the Target. -
-Embedded Targets reboot automatically after resetting. In case of a **host executable**, however, QUTest™ (qutest.py) launches it again.
- -`[3]` The Target starts executing the @ref qutest_fixture "test fixture" code from the beginning. After QS gets initialized (QS_INIT()), the @ref qutest_fixture "test fixture" sends the ::QS_TARGET_INFO reply to the @ref qutest_script "test script". - -`[4]` Upon reception of the awaited ::QS_TARGET_INFO reply, the @ref qutest_script "test script" attempts to execute the @ref qutest_dsl::on_reset() "on_reset()" procedure. If @ref qutest_dsl::on_reset() "on_reset()" is defined in the script, it runs at this time. (This scenario assumes that @ref qutest_dsl::on_reset() "on_reset()" is defined and runs until step `[8]`). - -`[5]` A @ref qutest_fixture "test fixture" continues the initialization RTC step and typically produces some @ref qs_dict "QS dictionaries". -
-The @ref qs_dict "QS dictionaries" are consumed by QSPY and are **not** forwarded to the @ref qutest_script "test script". - -`[6]` The @ref qutest_fixture "test fixture" might also produce some output that **is** forwarded to the @ref qutest_script "test script". - -`[7]` Any such output needs to be explicitly expected by the @ref qutest_script "test script". The @ref qutest_dsl::on_reset() "on_reset()" procedure is the ideal place to handle such output. -
-The main purpose of the @ref qutest_dsl::on_reset() "on_reset()"` procedure is to consume any output generated during the reset RTC step as well as to perform any setup that should follow the Target reset. In principle, instead of coding @ref qutest_dsl::on_reset() "on_reset()", you could place all this code directly at every test, but this would be repetitious. Defining @ref qutest_dsl::on_reset() "on_reset()" allows you to avoid such repetitions. - -`[8]` The @ref qutest_dsl::on_reset() "on_reset()" procedure ends and the @ref qutest_script "test script" sends ::QS_RX_TEST_SETUP to the Target. - -`[9]` ::QS_RX_TEST_SETUP typically arrives while the @ref qutest_fixture "test fixture" still runs the initialization RTC. Therefore, ::QS_RX_TEST_SETUP is **not** processed immediately and its processing is delayed until the end of the current RTC step. - -`[10]` A @ref qutest_fixture "test fixture" continues the initialization RTC step and might still produce some @ref qs_dict "QS dictionaries". - -`[11]` Finally, the @ref qutest_fixture "test fixture" completes the initialization RTC by calling `QF_run()`. `QF_run()` runs an event loop, in which it processes commands that have accumulated from the @ref qutest_script "test script". - -`[12]` The first such command is ::QS_RX_TEST_SETUP, which has been waiting in the input buffer. - -`[13]` The acknowledgment for the ::QS_RX_TEST_SETUP is sent back to the @ref qutest_script "test script". - -`[14]` Upon reception of `Trg-Ack QS_RX_TEST_SETUP`, the @ref qutest_script "test script" attempts to execute the @ref qutest_dsl::on_setup() "on_setup()" procedure. If @ref qutest_dsl::on_setup() "on_setup()" is defined in the script, it runs at this time. -
-The main purpose of the @ref qutest_dsl::on_setup() "on_setup()" procedure is to consume any output generated from the QS_onTestSetup() callback in the @ref qutest_fixture "test fixture" invoked in the next step [15]. Note also the QS_onTestSetup() runs in all tests, including @ref qutest_noreset "NORESET tests". - -`[15]` The @ref qutest_fixture "test fixture" calls the QS_onTestSetup() callback function in the Target. - -`[16]` The @ref qutest_script "test script" proceeds with commands defined after the @ref qutest_dsl::test() "test()" command. Processing of these commands is explained in sections @ref qutest_simple and @ref qutest_complex. - - -@section qutest_pause Pausing the Reset -As explained in the previous section, the initialization RTC step in the @ref qutest_fixture "test fixture" extends throughout `main()`, from the beginning till the final call to `QF_run()`. The @ref qutest_fixture "test fixture" is unable to process any commands from the @ref qutest_script "test script" until the end of this long RTC step, which can limit the flexibility of the @ref qutest_fixture "test fixture". - -For example, consider the @ref qutest_fixture "test fixture" in the DPP example for QUTest (directory `qpc/examples/qutest/dpp/test`). This @ref qutest_fixture "test fixture" reuses the `main()` function from the actual DPP application, which starts multiple active objects. To enable unit testing of a specific single active object, it would be very convenient if the @ref qutest_script "test script" could set up the @ref qs_local "QS Local Filter" for the chosen active object component. Such a local filter would then select the output, such as initialization from a given AO. But the problem is that such a local filter requires the @ref qs_dict "QS object dictionary" to be already transmitted to QSPY. On the other hand, the local filter needs to take effect before the AOs are started. In other words, the initialization RTC step needs to be split into shorter pieces, right after sending the dictionaries, but before starting active objects. - -For such situations, QUTest provides the QS_TEST_PAUSE() macro, which pauses the execution of an RTC step and enters an event loop within the @ref qutest_fixture "test fixture". This, in turn, allows the @ref qutest_fixture "test fixture" to process any commands from the @ref qutest_script "test script", before the RTC continues to completion (or to another QS_TEST_PAUSE(), if needed). - -The following @ref qutest_fixture "test fixture" code illustrates the use of the QS_TEST_PAUSE() macro: - -@code - int main(int argc, char *argv[]) { - static QEvt const *tableQueueSto[N_PHILO]; - static QEvt const *philoQueueSto[N_PHILO][N_PHILO]; - ~ ~ ~ - - QF_init(); /* initialize the framework and the underlying RT kernel */ - BSP_init(argc, argv); /* NOTE: calls QS_INIT() */ - - /* object dictionaries... */ - QS_OBJ_DICTIONARY(AO_Table); - QS_OBJ_DICTIONARY(AO_Philo[0]); - QS_OBJ_DICTIONARY(AO_Philo[1]); - QS_OBJ_DICTIONARY(AO_Philo[2]); - ~ ~ ~ - - /* pause execution of the test and wait for the test script to continue */ - [1] QS_TEST_PAUSE(); - - /* initialize publish-subscribe... */ - QF_psInit(subscrSto, Q_DIM(subscrSto)); - - /* initialize event pools... */ - QF_poolInit(smlPoolSto, sizeof(smlPoolSto), sizeof(smlPoolSto[0])); - - /* start the active objects... */ - Philo_ctor(); /* instantiate all Philosopher active objects */ - for (n = 0U; n < N_PHILO; ++n) { - QACTIVE_START(AO_Philo[n], /* AO to start */ - (n + 1), /* QP priority of the AO */ - philoQueueSto[n], /* event queue storage */ - Q_DIM(philoQueueSto[n]), /* queue length [events] */ - (void *)0, /* stack storage (not used) */ - 0U, /* size of the stack [bytes] */ - (QEvt *)0); /* initialization event */ - } - ~ ~ ~ - - [2] return QF_run(); /* run the QF application */ - } -@endcode - - -`[1]` The QS_TEST_PAUSE() macro pauses the initialization RTC after producing QS dictionaries, but before starting active objects. - -`[2]` The QF_run() function completes the initialization RTC. - -The following sequence diagram shows the details of pausing a test. The explanation section following the diagram clarifies the interesting points (labeled with `[xx]`): - -![Pausing a test](qutest_pause.gif) - - -`[1]` The target reset proceeds as before and produces the ::QS_TARGET_INFO trace record. - -`[2]` At some point, however, the @ref qutest_fixture "test fixture" executes QS_TEST_PAUSE(), which sends the ::QS_TEST_PAUSED record to the @ref qutest_script "test script". At this point, the @ref qutest_fixture "test fixture" enters the event loop, so the initialization RTC finishes and the @ref qutest_fixture "test fixture" is now responsive to commands. - -`[3]` At this point, the @ref qutest_script "test script" must be explicitily expecting QS_TEST_PAUSE by means of the @ref qutest_dsl::expect_pause() "expect_pause()" command. -
-The best place to put @ref qutest_dsl::expect_pause() "expect_pause()" is the on_reset() callback function, which should be defined in *test scripts* corresponding to *test fixtures* that call QS_TEST_PAUSE(). - -`[4]` The @ref qutest_dsl::on_reset() "on_reset()" callback can now execute commands that are processed **immediately** in the @ref qutest_fixture "test fixture". - -`[5]` Eventually the@ref qutest_dsl:on_reset() "on_reset()" callback releases the @ref qutest_fixture "test fixture" from the pause by executing the @ref qutest_dsl::continue_test() "continue_test()" command. This command sends ::QS_RX_TEST_CONTINUE to the @ref qutest_fixture "test fixture". - -`[6]` Upon reception of ::QS_RX_TEST_CONTINUE, the @ref qutest_fixture "test fixture" continues the initialization in another RTC step. - -`[7]` The @ref qutest_dsl::on_reset() "on_reset()" callback ends and the test script sends ::QS_RX_TEST_SETUP to the Target. - -`[8]` The test proceeds as before. - - -The following @ref qutest_script "test script" code illustrates the use of the @ref qutest_dsl::expect_pause() "expect_pause()" and @ref qutest_dsl::continue_test() "continue_test()" commands: - -@code - def on_reset(): - [1] expect_pause() - [2] glb_filter(GRP_SM) - loc_filter(OBJ_SM_AO, "AO_Philo<2>") - [3] continue_test() - [4] expect("===RTC===> St-Init Obj=AO_Philo<2>,State=QHsm_top->Philo_thinking") - expect("===RTC===> St-Entry Obj=AO_Philo<2>,State=Philo_thinking") - expect("@timestamp Init===> Obj=AO_Philo<2>,State=Philo_thinking") - glb_filter(GRP_SM_AO, GRP_UA) - current_obj(OBJ_SM_AO, "AO_Philo<2>") - } -@endcode - -@section qutest_noreset NORESET Tests -In some tests, you specifically don't want to reset the Target, but rather you want to pick up exactly where the previous test left off. For example, you wish to test a specific state of your state machine, which you reached by dispatching or posting a specific sequence of events to it in the previous tests. - -For such tests, you can suppress the target reset by following the @ref qutest_dsl::test() "test()" command with the ::NORESET option. Such tests are called @ref qutest_noreset "NORESET Tests". - -@note -A ::NORESET test is not allowed as the first test of a *test group* and also not after an @ref qutest_assert. - - -The following sequence diagram shows the details of this process. The explanation section following the diagram clarifies the interesting points (labeled with `[xx]`): - -![NORESET Test](qutest_noreset.gif) - - -`[0]` The @ref qutest_fixture "test fixture" is done processing commands from any previous test(s) and is running an event loop. - -`[1]` The @ref qutest_script "test script" executes the @ref qutest_dsl::test() "test(..., NORESET)" command. - -`[2]` The @ref qutest_dsl::test() "test(..., NORESET)" command sends the ::QS_RX_TEST_SETUP command to the @ref qutest_fixture "test fixture". - -`[3]` The @ref qutest_fixture "test fixture" processes ::QS_RX_TEST_SETUP immediately, because it is running the event loop. - -`[4]` The @ref qutest_fixture "test fixture" responds with Trg-Ack ::QS_RX_TEST_SETUP. - -`[5]` Upon reception of Trg-Ack ::QS_RX_TEST_SETUP, the @ref qutest_script "test script" attempts to execute the @ref qutest_dsl::on_setup() "on_setup()" callback. If @ref qutest_dsl::on_setup() "on_setup()" is defined in the script, it runs at this time. -
-The main purpose of the @ref qutest_dsl::on_setup() "on_setup()" callback is to consume any output generated from the QS_onTestSetup() callback in the test fixture invoked in the next step [6]. - -`[6]` The @ref qutest_fixture "test fixture" calls the QS_onTestSetup() callback function in the Target. - -`[7]` The @ref qutest_script "test script" proceeds with commands defined after the qutest_dsl::test() "test()" command. Processing of these commands is explained in sections @ref qutest_simple and @ref qutest_complex. - - -@section qutest_assert Assertion Tests -The use of assertions in embedded code (and especially in safety-critical code) is considered one of the **best practices** and the QP frameworks provide assertion facilities specifically designed for deeply embedded systems. - -Assuming that you are using QP assertions in your code, an assertion failure can happen during a unit test. When it happens, the @ref qutest_fixture "test fixture" will produce the non-maskable ::QS_ASSERT_FAIL trace record. When this record arrives during a regular test, it will not be expected, so the test will fail. This is exactly what you want, because a failing assertion represents an error which needs to be fixed. - -@note -The QP assertion handler Q_onAssert() is defined in the @ref qutest_stub "QUTest Stub". This assertion handler is instrumented to produce the ::QS_ASSERT_FAIL trace record. - - -However, sometimes you specifically want to test the assertion code itself, so you intentionally force an assertion in your test. In that case an assertion failure is expected and the test passes when the assertion fails. Such tests are called "Assertion Tests" and QUTest™ has been specifically designed to support such tests. - -Here is an example of an "Assertion Test": - -@code{.py} -test("TIMEOUT->Philo_thinking (ASSERT)") -probe("QActive_post_", 1) -dispatch("TIMEOUT_SIG") -expect("@timestamp Disp===> Obj=AO_Philo<2>,Sig=TIMEOUT_SIG,State=Philo_thinking") -expect("===RTC===> St-Exit Obj=AO_Philo<2>,State=Philo_thinking") -expect("@timestamp TstProbe Fun=QActive_post_,Data=1") -expect("@timestamp =ASSERT= Mod=qf_actq,Loc=110") -@endcode - -As you can see, the test ends with an explicit expectation of an assertion failure: @ref qutest_dsl::expect() "expect('@timestamp =ASSERT= Mod=qf_actq,Loc=...')". This is very easy and natural in QUTest. - -@note -The only special treatment required here is that a test immediately following such an "Assertion Test" must necessarily reset the Target (it cannot be a @ref qutest_noreset "NORESET-Test"). - - -@section qutest_qspy Categories of QSPY Output -To write effective *test scripts* you need to understand the main categories of QSPY output, which are illustrated in the picture below: - -@image html qspy_cat.png -@image latex qspy_cat.png width=5.0in -@caption{Categories of QSPY output} - -`[0]` Information output generated internally by QSPY. This output is *not* sent to *test scripts*. - -`[1]` Dictionary trace records generated by the Target. This output is *not* forwarded to *test scripts*. - -`[2]` Acknowledgement trace records generated by the Target. This output *is* forwarded to *test scripts*, but is checked automatically and implicitly by the *test commands*. - -`[3]` Trace records generated by the Target. This output *is* forwarded to *test scripts* and must be checked **explicitly** by test expectations. - - -@section qutest_simple Simple Commands -Simple @ref qutest_script "test script" commands do not produce any output from the Target, except for the `Trg-Ack` (acknowledgement). Examples of `` include @ref qutest_dsl::glb_filter() "glb_filter()", @ref qutest_dsl::loc_filter() "loc_filter()" and @ref qutest_dsl::current_obj() "current_obj()". - -![Simple command processing](qutest_simple.gif) - - -`[1]` A @ref qutest_script "test script" sends a `` to the @ref qutest_fixture "test fixture". - -`[2]` The @ref qutest_fixture "test fixture" receives the command and immediately starts processing it. - - -`[3]` Processing of a command triggers an RTC step and produces only the `Trg-Ack ` (acknowledgement of the specific ``). - -`[4]` Immediately after sending the ``, the @ref qutest_script "test script" enters an implicit expect state, in which it waits for the `Trg-Ack ` output from the Target. The processing of the `` ends when the next output received from the Target exactly matches the expected output. - - -@section qutest_complex Complex Commands -Complex @ref qutest_script "test script" commands might produce some output from the Target, not just the `Trg-Ack` (acknowledgement). Examples of `` include @ref qutest_dsl::command() "command()", @ref qutest_dsl::dispatch() "dispatch()", @ref qutest_dsl::post() "post()" and @ref qutest_dsl::tick() "tick()". - -![Complex command processing](qutest_complex.gif) - - -`[1]` A @ref qutest_script "test script" sends a `` to the @ref qutest_fixture "test fixture". - -`[2]` The @ref qutest_fixture "test fixture" receives the command and immediately starts processing it. - -`[3]` Processing of a command triggers an RTC step and produces only the `Trg-Ack ` (acknowledgement of the specific ``). - -`[4]` The `` must be followed in the @ref qutest_script "test script" by the explicit @ref qutest_dsl::expect() "expect()" commands that consume any output produced by the command. - -`[5-6]` The @ref qutest_fixture "test fixture" produces some output. - -`[7]` Each such ouput is consumed by the matching @ref qutest_dsl::expect() "expect()" command. - -`[8]` The @ref qutest_fixture "test fixture" sends the additional QS record `Trg-Done `, which explicitly delimits the output from this particular command. - -`[9]` The @ref qutest_script "test script" must consume the `Trg-Done ` record by an explicit @ref qutest_dsl::expect() "expect()" command. - - -@attention -Any events posted inside the Target in the course of processing a command (Simple or Complex) are also handled in the **same** RTC step. This extends the RTC step until all event queues of all Active Objects inside the Target are empty. - -@nav{qutest_use,qutest_tut} -*/ diff --git a/doxygen/qutest_ref.dox b/doxygen/qutest_ref.dox deleted file mode 100644 index 1734a23..0000000 --- a/doxygen/qutest_ref.dox +++ /dev/null @@ -1,138 +0,0 @@ -F/*###########################################################################*/ -/*! @page qutest_fixture QUTest™ Fixture Reference -@nav{qutest_conc,qutest_script} - -

A QUTest *test fixture* is a regular C or C++ program that contains the @c %main() function as well as a few @ref qs "QS" callback functions (to implement test commands as well as test startup and teardown). The main job of a *test fixture* is to exercise the CUT (Code Under Test). -

- -The CUT called from a *test fixture* can be any code you wish to unit-test and does **not** need to be based on the [QP framework](https://www.state-machine.com/products/#QP). That way of applying QUTest is illustrated in the first lessons of the @ref qutest_tut "QUTest Tutorial". - -However, QUTest is particularly useful for testing QP applications, which is illustrated in the later lessons of the @ref qutest_tut "QUTest Tutorial". In this case, the *test fixture* needs to initialize all used QP services, such as event pools to dispatch/post events to your state machines and active objects. - - - -@section qutest_stub QUTest™ QP Stub -The QP API implementation linked with the *test fixture* is **not** the actual QP framework, but instead just a **QUTest QP Stub**, which differs from the real QP implementation in the following aspects: - -- the `QActive_start()` implementation initializes the event queue for the AO and registers it with the QP framework, but it does **not** start a new thread for the AO. -- the `QF_run()` implementation calls the `QS_onTestLoop()` to wait for the commands from the @ref qutest_script "test script". -- the stub provides the `QActiveDummy` class for instantiating "dummy" active objects for testing. - -@note -The **QUTest QP Stub** is implemented in the file qutest.c as well as Target-specific QUTest port `qutest_port.c`. - - -@section qutest_fixture-callbacks QUTest™ Fixture Callbacks - -- QS_onTestSetup() -- QS_onTestTeardown() -- QS_onCommand() -- QS_onTestEvt() -- QS_onTestPost() -- QS_onFlush() -- QS_onTestLoop() - - -@section qutest_fixture-pause Pausing Test Fixtures -- QS_TEST_PAUSE() - - -@section qutest_fixture-probe Test Probes -QUTest "Test Probes" are a very flexible mechanism to alter the behavior of code from the @ref qutest_script "test scripts". This alteration of behavior can be used for a variety of reasons: - -- to alter the flow of control to execute paths through the code otherwise hard to reach (to improve the test coverage of the code) -- to cause various error conditions -- to alter return values from functions -- many others. - - -The "Test Probes" are just 32-bit values (`uint32_t`) sent from the test script to the Target (see the probe() command), where they are stored in the FIFO (First-In-First-Out) data structure. The "Test Probes" can be then retrieved from C or C++ code on the Target, by means of the following macros: - -- @ref QS_TEST_PROBE_DEF() "QS_TEST_PROBE_DEF( function_pointer )" -- @ref QS_TEST_PROBE() "QS_TEST_PROBE( code )" -- @ref QS_TEST_PROBE_ID() "QS_TEST_PROBE_ID( ID, code )". - -@note -The QUTest Test Probes macros can be used both in **production code** and in **test code** (intended for testing only). These macros are active only when #Q_UTEST is defined, and otherwise resolve to nothing, which means that you can **leave** the Test Probe macros in your production code. - -The typical use of the "Test Probe" macros is as follows: - -A C or C++ function calls the macro QS_TEST_PROBE_DEF(), which defines the test-probe variable `qs_tp_` of type `uint32_t`. If any test probes **for this function** have been sent from the test script, the test-probe is retrieved and assigned to the test-probe variable. Otherwise the test-probe variable is initialized to zero. - -Once the test-probe variable is defined and initialized, it can be tested with the QS_TEST_PROBE() and QS_TEST_PROBE_ID() macros. The QS_TEST_PROBE() macro executes the code snippet specified as the parameter to the macro when the test probe is not zero. The QS_TEST_PROBE_ID() executes the specified code snippet only when the test-probe has a given ID value. - - -@nav{qutest_conc,qutest_script} -*/ - -/*###########################################################################*/ -/*! @page qutest_script QUTest™ Script Reference -@nav{qutest_fixture,qview} - -A QUTest *test script* contains a group of related tests (a *test group*). The basic job of these tests is to send commands to the @ref qutest_fixture "test fixture" running in the Target and to compare the @ref qspy_text "QSPY textual output" produced by the Target with the *test expectations*. - -The QUTest **test scripts** are executed in the host by the @ref qutest_use "QUTest script runner" that communicates with the @ref qspy "QSPY host application" via the @ref qspy_udp "UDP interface". The QUTest script runner is itself implemented in a Python module @ref qutest_use "qutest.py". - -@section qutest_dsl QUTest™ Testing DSL -The Python module qtools/qspy/py/qutest.py defines a small Domain Specific Language (DSL) for writing test scripts in Python. The structure of this DSL is very simple. Each test script consists of two sections: - - -@subsection qutest_dsl-preamble Preamble -The "preamble" section of a test script file specifies include scripts and defines callback functions common to all tests in this file. It can contain the following functions: - -- @ref qutest_dsl::include() "include()" -- @ref qutest_dsl::on_reset() "on_reset()" -- @ref qutest_dsl::on_setup() "on_setup()" -- @ref qutest_dsl::on_teardown() "on_teardown()" - -The `on_...()` callback functions can call any of the @ref qutest_dsl-commands "test commands". - - -@subsection qutest_dsl-tests Tests -The "tests" section of a test script file contains the actual tests. Each test starts with the test() command and can contain any number of the @ref qutest_dsl-commands "test commands". The test continues until another test() command, or the skip() command. - -- @ref qutest_dsl::test() "test()" -- @ref qutest_dsl::scenario() "scenario()" -- @ref qutest_dsl::skip() "skip()" - - -@subsection qutest_dsl-commands Commands -The commands that you can place in the tests (as well as inside the callback functions) are: - -@ref qutest_simple "Simple Commands": - -- @ref qutest_dsl::glb_filter() "glb_filter()" -- @ref qutest_dsl::loc_filter() "loc_filter()" -- @ref qutest_dsl::ao_filter() "ao_filter()" -- @ref qutest_dsl::current_obj() "current_obj()" -- @ref qutest_dsl::poke() "poke()" -- @ref qutest_dsl::fill() "fill()" -- @ref qutest_dsl::continue_test() "continue_test()" - - -@ref qutest_complex "Complex Commands": - -- @ref qutest_dsl::command() "command()" -- @ref qutest_dsl::query_curr() "query_curr()" -- @ref qutest_dsl::init() "init()" -- @ref qutest_dsl::dispatch() "dispatch()" -- @ref qutest_dsl::post() "post()" -- @ref qutest_dsl::publish() "publish()" -- @ref qutest_dsl::probe() "probe()" -- @ref qutest_dsl::tick() "tick()" -- @ref qutest_dsl::peek() "peek()" - - -Commands that don't communicate with the Target: - -- @ref qutest_dsl::expect() "expect()" -- @ref qutest_dsl::expect_pause() "expect_pause()" -- @ref qutest_dsl::test_file() "test_file()" -- @ref qutest_dsl::test_dir() "test_dir()" -- @ref qutest_dsl::last_rec() "last_rec()" -- @ref qutest_dsl::pack() "pack()" -- @ref qutest_dsl::note() "note()" -- @ref qutest_dsl::tag() "tag()" - -@nav{qutest_fixture,qview} -*/ diff --git a/doxygen/qutest_tut.dox b/doxygen/qutest_tut.dox deleted file mode 100644 index 623d212..0000000 --- a/doxygen/qutest_tut.dox +++ /dev/null @@ -1,1275 +0,0 @@ -/*! @page qutest_tut QUTest™ Tutorial - -@nav{qutest_conc,qutest_unity} - -

This Tutorial describes how to use the QUTest™ unit test harness in a series of progressively advancing examples. The first examples pertain to generic C code completely unrelated to the QP frameworks. These examples are adaptations of tests shipping with the Unity test framework. Later examples in this Tutorial show how to test hierarchical state machines and active objects. 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 tests. -

- -As mentioned in the Section \"@ref qutest_how "How does it work?"\", testing with QUTest™ always involves two components: (1) a @ref qutest_fixture "test fixture" code written in C (or C++) that runs on the target and (2) one or more @ref qutest_script "test scripts" that are written in Python and run on the host. This Tutorial starts each example with the description of how to run the tests and then explains the *test fixture* and the *test scripts* comprising the test. - -@note -This Tutorial should run on any host computer (Windows, Linux, or MacOS), where both QTools™ and [QP/C framework](/qpc) have been installed and also the **QTOOLS** environment variable has been defined. Please refer to the @ref gs_obtain "QTools Installation" section for more information about downloading and installing QTools™. - - -This Tutorial consists of the following lessons: - -- @subpage qutest_unity -- @subpage qutest_mock -- @subpage qutest_qhsm -- @subpage qutest_blinky -- @subpage qutest_dpp - -
-@nav{qutest_conc,qutest_unity} -*/ - -/*###########################################################################*/ -/*! @page qutest_unity Basic Unity Example -@nav{qutest_tut,qutest_mock} - -

This example is based on the simple `example_1` that ships with the Unity unit testing framework. This simplest example of Unity has nothing to do with the QP frameworks. The purpose is to illustrate that QUTest™ can be used with generic C code and to compare QUTest™ with Unity. -

- -@remark -This simple example runs QUTest tests on the host (Windows, Linux, or macOS) for both Unity and QUTest. The QUTest version also runs on embedded boards (NUCLEO-L053R8 from ST, EFM32 Pearl-Gecko board from Silicon Labs and TivaC LaunchPad from Texas Instruments and ). The instructions for building and running the code on the embedded boards are located at the end of this lesson. -
-![Targets for this example](platforms.png) - - -@section qutest_unity-cut Code Under Test (CUT) - -@note -Because it uses pure C code, the Basic Unity example is only available in the [QP/C framework](https://www.state-machine.com/qpc), and is **not** available in the [QP/C++ framework](https://www.state-machine.com/qpcpp). - - -The CUT in this example is the file `my_strlen.c` located in the directory `C:\qp\qpc\examples\qutest\unity_strlen\src`: - -@anchor qutest_tut_basic-cut -@includelineno my_strlen.c - - -@section qutest_unity-run0 Running the Test with Unity -The complete code for the basic Unity example is provided in the QP/C framework directory `C:\qp\qpc\examples\qutest\unity_strlen\test`. To run the basic Unity test (on Windows), open a command-prompt and type: -@verbatim -cd C:\qp\qpc\examples\qutest\unity_strlen\test -make -@endverbatim - -@note -The provided `Makefile` will also work on Linux and macOS. The only difference from Windows is that you open a terminal window and change the directory to `~/qp/qpc/examples/qutest/unity_strlen/test`. - - -This will build the @ref qutest_unity-fixture "test fixture" as a host executable and then it will run it. The screen shot below shows the output produced from the make command. - -![Unity example_1 test build and run with Unity](unity_strlen_unity.jpg) - - -@section qutest_unity-run Running the Test with QUTest -The complete code for the basic Unity example is provided in the QP/C framework directory `C:\qp\qpc\examples\qutest\unity_strlen\qutest`. To run the basic test (on Windows), open a command prompt and type: - -@verbatim -qspy -@endverbatim - -This will start the @ref qspy "QSPY host utility" with the TCP/IP connection to the Target. - -Next, open a **second** command prompt window and type: - -@verbatim -cd C:\qp\qpc\examples\qutest\unity_strlen\qutest -make -@endverbatim - -@note -The provided `Makefile` will also work on Linux and MacOS. The only difference from Windows is that you open a terminal window and change the directory to `~/qp/qpc/examples/qutest/unity_strlen/qutest`. - - -This will build the @ref qutest_unity-fixture "test fixture" as a host executable and then it will run the @ref qutest_unity-script "test script" (in Python). The screen shot below shows the output produced in these two command-prompt windows. - -![Unity example_1 test build and run with QUTest (right) and QSPY output (left)](unity_strlen_qutest.jpg) - - -@section qutest_unity-fixture Test Fixture -The job of a @ref qutest_fixture "test fixture" is to exercise the **CUT** (`my_strlen.c` in this case) and report the results back to the @ref qspy "QSPY host application". Note that a *test fixture* in QUTest™ is **not** supposed to perform any checks whether the CUT operates "correctly". Instead, your *test fixture* should only provide facilities to thoroughly exercise the **CUT** remotely from the @ref qutest_unity-script "test script"(s). A properly written test fixture can typically be used for many tests (implemented in multiple test scripts). - -@remark -Coming up with a "good" *test fixture* requires some practice, but when you study the examples in this Tutorial, you will see some instances of flexible *test fixtures* that allow you to to run a wide variety of tests on them. - - -The following listing shows the complete QUTest *test fixture* for the basic tests (file `test_strlen.c` in the directory `C:\qp\qpc\examples\qutest\unity_strlen\qutest`). The explanation section following the listing clarifies the interesting lines of code (lines starting with `[xx]` labels). - -@code - [1] #include "qpc.h" /* QUTest interface */ - [2] #include "my_strlen.h" /* CUT interface */ - - [3] Q_DEFINE_THIS_FILE - - /*--------------------------------------------------------------------------*/ - [4] static char string[128]; - - /*--------------------------------------------------------------------------*/ - [5] int main(int argc, char *argv[]) { - - [6] QF_init(); /* initialize the framework */ - - /* initialize the QS software tracing */ - [7] Q_ALLEGE(QS_INIT(argc > 1 ? argv[1] : (void *)0)); - - /* dictionaries... */ - [8] QS_FUN_DICTIONARY(&my_strlen); - [9] QS_OBJ_DICTIONARY(string); - - /* filter setup... */ -[10] QS_GLB_FILTER(QS_ALL_RECORDS); -[11] QS_setCurrObj(AP_OBJ, string); - -[12] return QF_run(); /* run the tests */ - } - - /*--------------------------------------------------------------------------*/ -[13] void QS_onTestSetup(void) { - } - /*..........................................................................*/ -[14] void QS_onTestTeardown(void) { - } - - /*..........................................................................*/ -[15] void QS_onCommand(uint8_t cmdId, - uint32_t param1, uint32_t param2, uint32_t param3) - { - switch (cmdId) { - case 0: { /* call the CUT: my_strlen(string) */ -[16] uint16_t ret = my_strlen(string); -[17] QS_BEGIN_ID(QS_USER + cmdId, 0U) /* app-specific record */ -[18] QS_FUN(&my_strlen); /* function called */ -[19] QS_U16(0, ret); /* value returned */ -[20] QS_STR(string); /* the current string */ -[21] QS_END() - break; - } - default: - break; - } - - /* unused parameters... */ - (void)param1; - (void)param2; - (void)param3; - } - /*..........................................................................*/ - /* host callback function to "massage" the event, if necessary */ -[22] void QS_onTestEvt(QEvt *e) { - (void)e; - #ifdef Q_HOST /* is this test compiled for a desktop Host computer? */ - #else /* this test is compiled for an embedded Target system */ - #endif - } - /*..........................................................................*/ - /*! callback function to output the posted QP events (not used here) */ -[23] void QS_onTestPost(void const *sender, QActive *recipient, - QEvt const *e, bool status) - { - (void)sender; - (void)recipient; - (void)e; - (void)status; - } -@endcode - -
-
1
The `"qpc.h"` header file contains the [QP/C framework](https://www.state-machine.com/qpc/) API, which includes the QUTest interface. Typically, you need to include this header file in QUTest test doubles. -> **NOTE:** for test fixtures based on the [QP/C++ framework](https://www.state-machine.com/qpcpp/), you need to include the `"qpcpp.h"` header file. -
-
2
You also need to include the interface to the CUT, which is `my_strlen.h` in this case. -
-
3
The macro `Q_DEFINE_THIS_FILE` is needed for "DbC assertions" (they have nothing to do with "test assertions"). Later in this file, a "DbC assertion" is used to guard against failure in the initialization of the @ref qs "QS" target-resident component (see step [7]). -
-
4
The variable `string` is used to control the parameter passed into the CUT. -
5
A QUTest *test fixture* code needs the `main()` function, which has the usual structure of a QP/C application (and in fact in the more advanced tests it can be *the same* function as used by the actual QP/C application). But here, it contains the bare minimum function calls, as described below. -
-
6
The `main()` function must start with calling `QF_init()` to initialize the QP framework. -
-
7
Next, you need to initialize the @ref qs "QS" target-resident component (QS_INIT()). This macro is wrapped with the Q_ALLEGE() assertion, which will fire if the QS initialization fails (in which case continuation of the test makes no sense). -
-
8-9
Next, you produce @ref qs_dict "QS dictionaries" for all functions you wish to test as well as objects you might need to inspect. -> NOTE: you need to do this so that the test scripts can refer to the functions and objects by the same symbolic names as the CUT/test-fixture. -
-
10
The QS_GLB_FILTER() macro sets the @ref qs_global "global filter" in the Target. Here all output is enabled (::QS_ALL_RECORDS). -
-
11
The QS_setCurrObj(AP_OBJ) function sets the "current Application Object" in the Target. Subsequently, commands sent to the Target from the test script will pertain to that "current Application Object". -
-
12
Finally, at the end of `main()` you need to call `QF_run()` to run the tests. -
-
13
The callback function `QS_onTestSetup()` allows you to include code that will be run at the beginning of each test. Here this simple CUT does not need any setup, but you still need to provide (an empty) implementation to satisfy the linker. -
-
14
The callback function `QS_onTestTeardown()` allows you to include code that will be run at the end of each test. Here this simple CUT does not need any teardown, but you still need to provide (an empty) implementation to satisfy the linker. -
-
15
The callback function `QS_onCommand()` allows you to remotely execute commands inside the Target. Here is where you execute the CUT and report results back to QSPY. -
-
16
The command with `cmdId==0` will be used to call the `my_strlen()` CUT. -> NOTE: You can use other `cmdId`s to call other pieces of CUT or to provide different variants of calling the same CUT, as you see fit. Much of the art of writing *test fixtures* lies in constructing flexible remote commands that exercise your CUT. -
-
17
The `QS_BEGIN()` macro starts the @ref qs_app "application-specific" trace record that will report results of calling the `my_strlen()` CUT to the test script. -
-
18
The `QS_FUN()` macro sends the address of the function to the test script. This address will be converted to the name of the function, because the dictionary for this function has been generated in step 8. -
-
19
The `QS_U16()` macro sends a 16-bit unsigned integer (`uint16_t`) to the test script. Here you output the return value from `my_strlen()`. -
-
20
The `QS_STR()` macro sends a zero-terminated string to the test script. Here you output the argument passed to `my_strlen()`. -
-
21
The `QS_END()` macro ends the @ref qs_app "application-specific" trace record. -
-
22
The `QS_onTestEvt()` callback function is not used in this test, but needs to be provided to satisfy the linker. -
-
23
The `QS_onTestPost()` callback function is not used in this test, but needs to be provided to satisfy the linker. -
-
-
- - -@section qutest_unity-script Test Script -A **test script** contains a group of related tests (a "test group"). The basic job of these tests is to send inputs to the *test fixture* running in the Target and to compare the @ref qspy_text "QSPY textual output" produced with the expectations of the test. The following listing shows the *test script* (Python) for the Unity basic tests (file `test_strlen.py`). The explanation section following the listing clarifies the interesting lines of code (lines starting with `[xx]` labels). - -@remark -Even though a *test script* uses **Python** under the hood, you don't need to be a Python expert to write effective test scripts. The actual set of commands that you use and need to know about forms a small @ref qutest_script "Domain Specific Language (DSL) for unit testing", which just happens to be implemented with Python as a command interpreter. - -@note -The following test script performs the same tests as the Unity test fixture `test_strlen.c` in the directory `qpc\examples\qutest\unity_strlen\qutest`. - - -@code{.py} - [1] # test-script for QUTest unit testing harness - # see https://www.state-machine.com/qtools/qutest.html - - # preambe... - [2] #def on_reset(): - [3] # expect_run() - [4] # current_obj(OBJ_AP,"string") - - # tests... - [5] test("my_strlen 0 for_empty_string") - [6] poke(0,1,b"\0") - [7] command(0) - [8] expect("@timestamp USER+000 my_strlen 0 ''") - [9] expect("@timestamp Trg-Done QS_RX_COMMAND") - - -[10] test("my_strlen n for various strings", NORESET) - poke(0,1,b"Foo\0") - command(0) - expect("@timestamp USER+000 my_strlen 3 Foo") - expect("@timestamp Trg-Done QS_RX_COMMAND") - poke(0,1,b" Foo\0") - command(0) - expect("@timestamp USER+000 my_strlen 4 Foo") - expect("@timestamp Trg-Done QS_RX_COMMAND") - - - test("my_strlen n for unprintable chars", NORESET) - poke(0,1,b"\tFoo\0") - command(0) - expect("@timestamp USER+000 my_strlen 4 \tFoo") - expect("@timestamp Trg-Done QS_RX_COMMAND") - poke(0,1,b"\a\b\n\0") - command(0) - expect("@timestamp USER+000 my_strlen 3 \a\b\n") - expect("@timestamp Trg-Done QS_RX_COMMAND") -@endcode - -
-
1
Lines starting with a pound sign ('#') or empty lines are comments which are ignored by QUTest. -
-
-
- - -"preamble" defines the on-reset code common to all tests in the group: -
-
2
The function on_reset() is executed after Target reset. -
-
3
The `expect_run()` directive consumes the QF-RUN trace record produced after Target reset. -
-
4
The current_obj() command sets the "current object" of the application-specific kind (`OBJ_AP`) in the Target. Subsequent commands (such as poke() in the next step) will act on this "current object". -
-
-
- - -"tests" performs various tests: -
-
5
The test() directive starts a test and gives it a name (in double quotes). The name of the test will be displayed as the test is executed and should be a quick reminder about the objective of this test. This test command also @ref qutest_reset "resets the Target", which brings the Target into a well-defined initial state and produces the @ref qs_dict "QS dictionary records" (see @ref qutest_unity-fixture "test-fixture"[12]). -> NOTE: The ability to perform the full Target reset is a unique feature of QUTest. Other unit testing frameworks, including Unity and CppUTest, don't reset the Target. They merely call the test `setup() / tearDown()` functions at the beginning and end of the test, respectively. QUTest also calls `onReset() / onSetup() / onTeardown()`, but obviously the full Target reset is a much better guarantee that the Target starts in exactly the same state. -
-
6
The poke() directive pokes the specified "Application Current Object" starting with the specified offset from the beginning of the object in memory (which here is 0) with the data elements of size 4 (the second argument) with the data provided in the third argument `pack()` "pack(" -
7
The command() directive causes the invocation of the `QS_onCommand()` callback inside the Target. The argument 0 is the `cmdId` parameter (see @ref qutest_unity-fixture "test-fixture"[16]). -> **NOTE:** The first parameter of command() "command" here is just a number (0), but it is also possible to use a **symbolic name** for the first parameter. This symbolic name will be looked up in the user dictionary (QS_USR_DICTIONARY()). -
-
8
The expect() command represents an expectation of this "test assertion". This is the expected output generated by the `command(0)` command from the previous step. You need to consult the test fixture to determine what you should expect in this case. -> NOTE: the expected string starts with a number `0000000001`, which is the @ref qs_tstamp "Target Time-Stamp". In QUTest, the "timestamp" simply counts all the QS trace records produced, so that you know that no entries have been lost. In the later tests you will see how you can count the steps automatically with the `@timestamp` placeholder. -
-
8
The test finishes with the expectation for the `Trg-Done QS_RX_COMMAND` trace record, which means that all output generated by command() has been generated. -
-
9
This expectation consumes the "Trg-Done QS_RX_COMMAND" trace record, which ensures that *all* output for this command has been produced. -
-
-
- -@attention -The QSPY host application limits the @ref qs_dict "QS dictionaries" to the **first 63 characters**. This means that longer names of functions or objects will be **truncated** to this limit. Please keep this limit in mind when choosing various names in your application. - - -@section qutest_unity-embed Running the Test on Embedded Targets -As mentioned in the initial description of this example, the directory `C:\qp\qpc\examples\qutest\unity_strlen\qutest` contains makefiles to build the code and run the tests on the embedded boards (TivaC LaunchPad from Texas Instruments and EFM32 Pearl-Gecko board from Silicon Labs). Both these boards open a virtual COM port on the machine they are attached to via the USB cable. This virtual COM port provides an ideal connection for the @ref qs "QS communication" with the @ref qspy "QSPY host utility". - - -![Targets for running QUTests. From the left: host computer, TivaC LaunchPad and EFM32 Pearl-Gecko](platforms.png) - - -For example, to test the EFM32 Pearl-Gecko board (ARM Cortex-M4), open a command prompt (on Windows) and type: - -@verbatim -qspy -c COM6 -@endverbatim - - -This will start the QSPY host utility with com-port connection to the embedded board. Of course, you need to adjust the serial port number to the actual number of the virtual COM port on your machine. - -Next, open a **second** command prompt window and type: - -@verbatim -cd C:\qp\qpc\examples\qutest\unity_strlen\qutest -make -f make_efm32 -@endverbatim - -The rest of the test is then exactly the same as with the host executable described @ref qutest_unity-run "above", except that the @ref qutest_unity-fixture "test fixture" runs on the embedded board. - -To run the tests on the TivaC LaunchPad (TM4C123 board), you use the `make_tm4c123` in the last step. - -
-@nav{qutest_tut,qutest_mock} -*/ - -/*###########################################################################*/ -/*! @page qutest_mock Unity Mock Example -@nav{qutest_unity,qutest_qhsm} - -

This example is loosely based on Matt Chernosky's video blog post "Test-driving with mocks instead of hardware". In this video blog, Matt presents a technique called the mock object, which in the traditional unit testing approach is needed to verify complex, multi-stage interactions between the CUT and the collaborator impersonated by the mock object. -

- -@note -To better understand this QUTest example, it is highly recommended to watch Chernosky's video blog. - - -The main purpose of this example is to show the traditional approach (with the mock object) and contrast it with the much simpler solution enabled by the QUTest approach. Of course, to make comparisons meaningful, both approaches test the @ref qutest_mock-cut "same CUT". - -@note -Because of the different design philosophy of QUTest, which is *not* based on xUnit, the classic "mock object" is actually not needed and can be replaced with a simpler "spy" test double. To dynamically alter the behavior of this "spy" test double, this example applies @ref qutest_fixture-probe "QUTest Test Probes". Test Probes can be changed interactively from the @ref qutest_mock-script "test script". - - -@remark -Since the @ref qutest_mock-cut "CUT" is in C, the Mock Unity example is only available in the [QP/C framework](https://www.state-machine.com/qpc) (and is **not** available in the [QP/C++ framework](https://www.state-machine.com/qpcpp)).
-
-This simple example runs QUTest tests on the host (Windows, Linux, or macOS) for both Unity and QUTest. The QUTest version also runs on embedded boards (NUCLEO-L053R8 from ST, EFM32 Pearl-Gecko board from Silicon Labs and TivaC LaunchPad from Texas Instruments and ). The instructions for building and running the code on the embedded boards are located at the end of this lesson. -
-![Targets for this example](platforms.png) - - -@section qutest_mock-cut Code Under Test (CUT) -The CUT in this example implements a simple bar of 5 LEDs that displays percentage, as shown in the animation below. The "LedBar device" interacts with the discrete LEDs by turning them on and off to achieve the desired effect. The main objective of this example is to demonstrate how to verify the **collaboration** with the discrete LEDs, even without the actual hardware. - -![Bar of 5 LEDs displaying the percentage](ledbar5.gif) - - -The LedBar CUT is located in the file `LedBar.c` in the directory `qpc\examples\qutest\unity_ledbar\src`. The CUT consists of just one function `LedBar_setPercent()`, which turns the individual LEDs on and off such that they display the desired `percent` parameter. The function `LedBar_setPercent()` returns the total power consumption (in microwatts) of all LEDs that are turned on. - -@anchor qutest_tut_mock-cut -@includelineno LedBar.c -@caption{file LedBar.c} - - -The low-level interface to the LEDs is defined below (`Led.h`). The individual LEDs are selected by an `index` parameter. Each individual LED can be turned on by means of the `LED_on()` function. The `LED_on()` function returns a value, which corresponds to power consumption of this LED while on. The LED can be turned off by the `LED_off()` function, which returns `void`. - -@includelineno Led.h -@caption{file Led.h} - - -The diagram below shows the relationships between the CUT and the test code: Unity case on the left and QUTest case on the right. In both cases, the `LedBar` CUT interacts with the hardware through the `Led.h` interface. The explanation section below the diagram clarifies the interesting elements of the diagram. - -![Components of the Unity Mock test: Unity left and QUTest right](qutest_mock.gif) - -Center: Code Under Test - -
-
1
The `LedBar.c` file contains the @ref qutest_mock-cut "Code Under Test (CUT)". -
-
2
The CUT interacts with the hardware through the `Led.h` interface. This interface abstracts the LEDs and is all that the CUT needs to "know" about the hardware. -
-
-
- - -@anchor qutest_mock-unity -Left: Unity testing framework (traditional approach) -
- -
3
The `TestLedBar.c` file implements the Unity test fixture, which calls the CUT and verifies that it performs as expected. - -> NOTE: A Unity test fixture for a mock requires a special "test runner", which initializes and cleans up after the mock. This "test runner" must typically be generated automatically, as it is too complex to code manually. -
-
4
-The Unity test fixture uses the `MockLed.c` implementation of the `Led.h` interface. The mock object implemented in `MockLed.c` needs to be "programmed" for each expected scenario **before** calling the CUT. Thus the structure of conventional tests with a mock is "backwards", meaning that you first specify the expectations and the test ends with a call to the CUT. - -> NOTE: This mock-object must typically be generated automatically, as it is too complex to code manually. Here, the mock- object was generated by means of the CMock tool, which is included with Unity, but requires installation of the ruby programming language. -
-
-
- - -Right: QUTest testing framework (simplified approach) -
-
5
-The `test_LedBar.c` file implements the @ref qutest_mock-fixture "QUTest test fixture", which calls the CUT, but it does **NOT** check whether it performs as expected. -
-
6
-The QUTest test fixture uses the `spy_Led.c` implementation of the `Led.h` interface. This spy test double is much simpler than the mock-object used by Unity, so it can easily be @ref qutest_mock-spy "coded manually". -
-
7
-The QUTest test is driven by the `test_LedBar.py` @ref qutest_mock-script "test script". This test script sends commands to the `test_LedBar.c` fixture and verifies the generated output against the expectations of the test. -
-
-
- - -@section qutest_mock-run0 Running the Test with Unity -The complete code for the mock Unity example is provided in the QP/C framework directory `C:\qp\qpc\examples\qutest\unity_ledbar\test_unity`. To run the mock Unity test (on Windows), open a command-prompt and type: -@verbatim -cd C:\qp\qpc\examples\qutest\unity_ledbar\test_unity -make -@endverbatim - -@note -The provided `Makefile` will also work on Linux and macOS. The only difference from Windows is that you open a terminal window and change the directory to `~/qp/qpc/examples/qutest/unity_ledbar/test`. - - -This will build the @ref qutest_mock-fixture "test fixture" as a host executable and then it will run it. The screen shot below shows the output produced from the make command. - -![Unity mock test build and run with Unity](unity_ledbar_unity.jpg) - - -@section qutest_mock-run Running the Test with QUTest -The complete code for the mock Unity example is provided in the QP/C framework, directory `C:\qp\qpc\examples\qutest\unity_ledbar\test`. To run the mock test (on Windows), open a command prompt and type: - -@verbatim -qspy -@endverbatim - -This will start the @ref qspy "QSPY host utility" with the TCP/IP connection to the Target. - -Next, open a **second** command prompt window and type: - -@verbatim -cd C:\qp\qpc\examples\qutest\unity_ledbar\test -make -@endverbatim - -@note -The provided `Makefile` will also work on Linux and macOS. The only difference from Windows is that you open a terminal window and change the directory to `~/qp/qpc/examples/qutest/unity_ledbar/qutest`. - - -This will build the @ref qutest_mock-fixture "test fixture" as a host executable and then it will run the @ref qutest_mock-script "test script" (in Python). The screen shot below shows the output produced in these two command-prompt windows. - -![Unity mock test build and run with QUTest (right) and QSPY output (left)](unity_ledbar_qutest.jpg) - - -@section qutest_mock-spy Spy Object (Mock Replacement) -The following listing shows the "spy-object" (file `spy_led.c`) test-double for the low-level LED module. The explanation section following the listing clarifies the interesting lines of code (lines starting with [xx] labels). - -@code{.c} - [1] #include "qpc.h" /* QUTest interface */ - [2] #include "Led.h" /* original interface */ - - //Q_DEFINE_THIS_FILE - - enum { - [3] LED_MOD = QS_USER1 /* QS app-specific record for the LED module */ - }; - - [4] static uint32_t led_power[MAX_LED] = { - 10, 20, 10, 20, 10 - }; - - /*--------------------------------------------------------------------------*/ - [5] void Led_DICTIONARY(void) { - QS_FUN_DICTIONARY(&Led_on); - QS_FUN_DICTIONARY(&Led_off); - QS_USR_DICTIONARY(LED_MOD); - QS_OBJ_DICTIONARY(&led_power); - } - - /*--------------------------------------------------------------------------*/ - /* turns a given LED off */ - [6] void Led_off(uint8_t index) { - QS_BEGIN(LED_MOD, (void *)0) /* user-specific record */ - QS_FUN(&Led_off); /* function called */ - QS_U8 (0, index); /* parameter */ - QS_END() - } - - /* turns a given LED on and returns the power drawn by it in uW */ - [7] uint32_t Led_on(uint8_t index) { - [8] uint32_t ret = led_power[index]; /* assume default power */ - [9] QS_TEST_PROBE_DEF(&Led_on) - - /* tweak the returned power draw from the test probe */ -[10] QS_TEST_PROBE( -[11] ret = (uint32_t)qs_tp_; - ) - -[12] QS_BEGIN(LED_MOD, (void *)0) /* user-specific record */ - QS_FUN(&Led_on); /* function called */ - QS_U32(0, ret); /* value returned */ - QS_U8 (0, index); /* parameter */ - QS_END() - -[13] return ret; - } -@endcode - -
-
1
The `"qpc.h"` header file includes the QP/C framework, which contains the QUTest interface. Typically, you need to include this header file in QUTest test doubles. -
-
2
The `"Led.h"` header file specifies the interface to the code being impersonated by this "spy-object". The whole purpose of the spy-object is to implement this interface such that the CUT can call use it as its collaborator. - -> NOTE: The CUT does not "know" that it is collaborating with a _test double_ (the spy-object in this case). -
3
This enumeration lists the @ref qs_app "application-specific QS trace records" that will be produced by the fake LED operations. The enumeration starts with #QS_USER1 offset, which is the second group of user-specific records. The first group (#QS_USER0 offset) is used by the main @ref qutest_mock-fixture "test fixture". -
-
4
The `led_power[]` array contains the default power ratings for the individual LEDs in the LED-bar. These values will be returned from the fake `Led_on()` implementation (if not overridden by the "Test Probe"). -
-
5
The `Led_DICTIONARY()` function produces the dictionaries for the spy-object. This function is not part of the real LED interface (see `Led.h` in the `src` directory), but is needed only for testing. -
-
6
This is a fake `Led_off()` implementation, which generates an @ref qs_app "application-specific QS trace record" to report the call and the parameter to QSPY. -
-
7
This is a fake `Led_on()` implementation. -
-
8
The `ret` variable will be the power rating for this LED returned from this function. The variable is initialized from the `led_power[]` array, which contains the default power rating for the LEDs. -
-
9
The macro `QS_TEST_PROBE_DEF()` defines a @ref qutest_fixture-probe "Test Probe" for this function (notice the @c &Led_on function-pointer parameter). This Test Probe retrieves a value set for this function from the test-script. (If no value has been set, the `QS_TEST_PROBE_DEF()` retrieves value 0). -
-
10
The `QS_TEST_PROBE()` macro executes the enclosed snipped of code only if the Test Probe (defined at label [9]) is not zero. -
-
11
If the Test Probe is not zero (it has been set from the test script), the `ret` value is updated from the value of the Test Probe `qs_tp_`. -
- -> NOTE: This demonstrates how to program a **return value** in a spy-object. This corresponds directly to the same capability of traditional mock-objects. - -> NOTE: Test Probe is just one way in which a pre-programmed value can be returned from a fake function. This option is illustrated in @ref qutest_mock-script25 "test script [25]". Another way in QUTest is to use the poke() test command to alter the values in the `led_power[]` array. This option is illustrated in @ref qutest_mock-script21 "test script [21]". - -
-
12
An @ref qs_app "application-specific QS trace record" is generated to report the call, the parameter, and the return value to QSPY. -
-
13
The `ret` value is returned to the caller (CUT). -
-
-
- - -@section qutest_mock-fixture Test Fixture -The following listing shows the test fixture for the LedBar tests (file `test_ledbar.c`). The explanation section following the listing clarifies the interesting lines of code (lines starting with [xx] labels). - -@code - [1] #include "qpc.h" /* QUTest interface */ - [2] #include "LedBar.h" /* CUT interface */ - - Q_DEFINE_THIS_FILE - - /*--------------------------------------------------------------------------*/ - [3] void Led_DICTIONARY(void); /* dictionaries for the Led "spy " test double */ - - /*--------------------------------------------------------------------------*/ - int main(int argc, char *argv[]) { - - [4] QF_init(); /* initialize the framework */ - - /* initialize the QS software tracing */ - [5] Q_ALLEGE(QS_INIT(argc > 1 ? argv[1] : (void *)0)); - - /* dictionaries... */ - [6] Led_DICTIONARY(); - [7] QS_FUN_DICTIONARY(&LedBar_setPercent); - - /* filter setup... */ - [8] QS_FILTER_ON(QS_ALL_RECORDS); - - [9] return QF_run(); /* run the tests */ - } - - /*--------------------------------------------------------------------------*/ - void QS_onTestSetup(void) { - } - /*..........................................................................*/ - void QS_onTestTeardown(void) { - } - - /*..........................................................................*/ - void QS_onCommand(uint8_t cmdId, - uint32_t param1, uint32_t param2, uint32_t param3) - { - switch (cmdId) { -[10] case 0: { /* call the CUT: LedBar_setPercent */ -[11] uint32_t ret = LedBar_setPercent((uint8_t)param1); -[12] QS_BEGIN(QS_USER + cmdId, (void *)0) /* user-specific record */ -[13] QS_FUN(&LedBar_setPercent); /* function called */ -[14] QS_U32(0, ret); /* value returned */ -[15] QS_U8 (0, (uint8_t)param1); /* parameter */ - QS_END() - break; - } - default: - break; - } - - /* unused parameters... */ - //(void)param1; - (void)param2; - (void)param3; - } - /*..........................................................................*/ - /* host callback function to "massage" the event, if necessary */ - void QS_onTestEvt(QEvt *e) { - (void)e; - #ifdef Q_HOST /* is this test compiled for a desktop Host computer? */ - #else /* this test is compiled for an embedded Target system */ - #endif - } - /*..........................................................................*/ - /*! callback function to output the posted QP events (not used here) */ - void QS_onTestPost(void const *sender, QActive *recipient, - QEvt const *e, bool status) - { - (void)sender; - (void)recipient; - (void)e; - (void)status; - } -@endcode - -
-
1
The `"qpc.h"` header file includes the [QP/C framework](https://www.state-machine.com/qpc/), which contains the QUTest interface. Typically, you need to include this header file in QUTest test doubles. -> **NOTE:** for test fixtures based on the [QP/C++ framework](https://www.state-machine.com/qpcpp/), you need to include the `"qpcpp.h"` header file. -
-
2
The `"LedBar.h"` header file specifies the interface to the CUT. -
-
3
The `Led_DICTIONARY()` function prototype is declared directly in the test fixture. This is the only extension from the `"Led.h"` interface implemented in the @ref qutest_mock-spy "spy-object". -
-
4
As usual the `main()` function of the test fixture initialzies the QF framework. -
-
5
As usual the `main()` function of the test fixture initalizes the QS software tracing. -
-
6
The call to the `Led_DICTIONARY()` function outputs the @ref qs_dict "QS dictionaries" for the @ref qutest_mock-spy "spy-object". -
-
7
The @ref qs_dict "QS dictionary" for the `LedBar_setPercentn()` CUT is produced as well. -
-
8
The @ref qs_global "QS global filter" is set up to output all QS records. -
-
9
The `QF_run()` function enters the event loop to wait for commands from the @ref qutest_mock-script "test script". -
-
-
- -@section qutest_mock-script Test Script -The following listing shows the *test script* for the LedBar tests (file `test_LedBar.py`). The explanation section following the listing clarifies the interesting lines of code (lines starting with `[xx]` labels). - -@note -The following test script performs the same tests as the `TestLedBar.c` Unity test fixture. Compared to the mock-object approach, however, the QUTest test script has the more intuitive structure, in which a command triggering CUT is **followed** by the expecations. In contrast, the traditional @ref qutest_mock-unity "Unity tests with mock-object" were structured "backwards" (the expectations **preceded** the call to CUT). - -@code{py} - [1] # preamble... - - # tests... - [2] test("LedBar 0% all off") - [3] command(0, 0) - [4] expect("@timestamp LED_MOD Led_off 0") - expect("@timestamp LED_MOD Led_off 1") - expect("@timestamp LED_MOD Led_off 2") - expect("@timestamp LED_MOD Led_off 3") - expect("@timestamp LED_MOD Led_off 4") - [5] expect("@timestamp USER+000 LedBar_setPercent 0 0") - [6] expect("@timestamp Trg-Done QS_RX_COMMAND") - - [7] test("LedBar 100% all on", NORESET) - [8] command(0, 100) - [9] expect("@timestamp LED_MOD Led_on 10 0") - expect("@timestamp LED_MOD Led_on 20 1") - expect("@timestamp LED_MOD Led_on 10 2") - expect("@timestamp LED_MOD Led_on 20 3") - expect("@timestamp LED_MOD Led_on 10 4") -[10] expect("@timestamp USER+000 LedBar_setPercent 70 100") -[11] expect("@timestamp Trg-Done QS_RX_COMMAND") - -[12] test("LedBar 19% all off", NORESET) -[13] command(0, 19) -[14] expect("@timestamp LED_MOD Led_off 0") - expect("@timestamp LED_MOD Led_off 1") - expect("@timestamp LED_MOD Led_off 2") - expect("@timestamp LED_MOD Led_off 3") - expect("@timestamp LED_MOD Led_off 4") -[15] expect("@timestamp USER+000 LedBar_setPercent 0 19") - expect("@timestamp Trg-Done QS_RX_COMMAND") - -[16] test("LedBar 20% one on", NORESET) -[17] command(0, 20) - expect("@timestamp LED_MOD Led_on 10 0") - expect("@timestamp LED_MOD Led_off 1") - expect("@timestamp LED_MOD Led_off 2") - expect("@timestamp LED_MOD Led_off 3") - expect("@timestamp LED_MOD Led_off 4") -[18] expect("@timestamp USER+000 LedBar_setPercent 10 20") - expect("@timestamp Trg-Done QS_RX_COMMAND") - -[19] test("LedBar 50% two on", NORESET) -[20] current_obj(OBJ_AP, "led_power") -[21] poke(0, 4, pack(" -
1
The preamble is empty, because no special actions are needed on reset/setup/teardown. -
-
-
- - -Test: "LedBar 0% all off" checks that all LEDs are turned off to display 0% -
-
2
The test() command starts the test. -
-
3
The @ref command() "command(0, 0)" calls the `LedBar_setPercent()` CUT with the 0 percent argument. -
-
4
This expect() command verifies the output produced by calling the `LED_off()` function from the spy-object. -
-
5
This expect() command verifies the output produced by calling the `LedBar_setPercent()` function from the CUT. Note that the returned total power consumption is zero. -
-
6
This expect() command verifies that all output from the original @ref command() "command(0, 0)" has been produced. -
-
-
- - -Test: "LedBar 100% all on" checks that all LEDs are turned on to display 100% -
-
8
The test() command starts the test. -
-
9
The @ref command() "command(0, 100)" calls the `LedBar_setPercent()` CUT with the 100 percent argument. -
-
10
This expect() command verifies the output produced by calling the `LedBar_setPercent()` function from the CUT. Note that the returned total power consumption is 70. -
-
11
This expect() command verifies that all output from the original @ref command() "command(0, 100)" has been produced. -
-
-
- - -Test: "LedBar 19% all off" checks that all LEDs are turned off to display 19% -
-
12
The test() command starts the test (NOTE: this is a NORESET test). -
-
13
The @ref command() "command(0, 19)" calls the `LedBar_setPercent()` CUT with the 19 percent argument. -
-
14
This expect() command verifies the output produced by calling the `LED_off()` function from the spy-object. -
-
15
This expect() command verifies the output produced by calling the `LedBar_setPercent()` function from the CUT. Note that the returned total power consumption is 0. -
-
-
- -Test: "LedBar 20% one on" checks that one LED is turned on to display 20% -
-
16
The test() command starts the test (NOTE: this is a NORESET test). -
-
17
The @ref command() "command(0, 20)" calls the `LedBar_setPercent()` CUT with the 20 percent argument. -
-
18
This expect() command verifies the output produced by calling the `LedBar_setPercent()` function from the CUT. Note that the returned total power consumption is 10. -
-
-
- - -Test: "LedBar 50% two on" checks that two LEDs are turned on to display 50% -
-
19
The test() command starts the test (NOTE: this is a NORESET test). -
-
20
The @ref current_obj() "current_obj(OBJ_AP, "led_power")" command sets the "current application object" to "led_power" (see @ref qutest_mock-spy "spy-object"[4]). -
-
21
-@anchor qutest_mock-script21 -
The @ref poke() "poke(0, 4, pack(" -
22
The @ref command() "command(0, 50)" calls the `LedBar_setPercent()` CUT with the 50 percent argument. -
-
23
This expect() command verifies the output produced by calling the `LedBar_setPercent()` function from the CUT. Note that the returned total power consumption is 40, which is due to poking the data into the `led_power` array. -
-
-
- - -Test: "LedBar 99% two on" checks that two LEDs are turned on to display 99% -
-
24
The test() command starts the test (NOTE: this is a NORESET test). -
-
25
-@anchor qutest_mock-script25 -
The @ref probe() "probe("Led_on", 17)" command sends the @ref qutest_fixture-probe "test-probe" value 17 for function `Led_on` -
-
26
The @ref probe() "probe("Led_on", 13)" command sends the @ref qutest_fixture-probe "test-probe" another value 13 for function `Led_on` -
-
27
The @ref command() "command(0, 99)" calls the `LedBar_setPercent()` CUT with the 99 percent argument. -
-
28
This expect() command verifies the test-probe sent at step [25] has been retrieved. -
-
29
This expect() command verifies the function `Led_on` has been called, and that it returned 17. -
-
30
This expect() command verifies the test-probe sent at step [26] has been retrieved. -
-
31
This expect() command verifies the function `Led_on` has been called, and that it returned 13. -
-
32
This expect() command verifies the output produced by calling the `LedBar_setPercent()` function from the CUT. Note that the returned total power consumption is 60, which is due to using test-probes to alter the return values returned from `Led_on()`. -
-
-
- -
-@nav{qutest_unity,qutest_qhsm} -*/ - -/*###########################################################################*/ -/*! @page qutest_qhsm Hierarchical State Machine Example -@nav{qutest_mock,qutest_blinky} - -

This example shows how to apply QUTest for unit-testing [Hierarchical State Machines](https://www.state-machine.com/doc/concepts.php#HSM). This example illustrates two testing strategies for state machines: -

- -- **Functional tests** focus on the *actions* performed by the state machine. - -> NOTE: As described in the @ref qutest_mock, testing of complex, multi-stage interactions (such as a state machine) typically requires application of a "mock object" test double. However, the QUTest design philosophy allows you to use a much simpler "spy object" test double instead. The **functional testing** strategy illustrates this approach. - -- **Structural tests** focus on the state machine structure, such as entering/exiting *states* and executing *state transitions*. - -> NOTE: Unlike the previous examples (@ref qutest_unity "Unity-basic" and @ref qutest_mock "Unity-mock"), which pertained to generic C code, the **structural testing** of state machine makes use of the specific state machine instrumentation that is provided in QP. - -@remark -In practice, unit-testing of state machines typically involves a mixture of functional and structural testing strategies. - - -@section qutest_qhsm-cut Code Under Test (CUT) -This example is available in both [QP/C](https://www.state-machine.com/qpc) as well as in [QP/C++](https://www.state-machine.com/qpcpp) frameworks.The complete code for the `qhsm` example is provided in the directory `\examples\qutest\qhsmtst`. - -The hierarchical state machine used in this example is artificial, but it has been specifically designed to contain all possible state transition topologies for up to 4 levels of state nesting. The code representing this state machine (the CUT here), has been generated automatically by the [QM modeling tool](https://www.state-machine.com/qm/) from the model shown in the screen-shot below: - -![QHsmTst state machine in QM](qhsmtst_qm.png) - -The state machine executes actions on every entry/exit to states, on state transitions and on internal state transitions. These actions are all implemented by calling the `BSP_display()` function that outputs a succinct message about the location of the action within the state machine. For example, the entry action to state "s2" calls `BSP_display("s2-ENTRY;")` and the exit action from state "s2" calls `BSP_display("s2-EXIT;")`. These actions then are used for @ref qutest_qhsm-funct-script "functional testing" of the state machine. - - -@section qutest_qhsm-run Running the Test -To run the `qhsm` tests (on Windows), open a command prompt and type: - -@verbatim -qspy -@endverbatim - -This will start the @ref qspy "QSPY" host application with the TCP/IP connection to the Target. - -Next, open another command prompt window and type: - -@verbatim -cd C:\qp\\examples\qutest\qhsmtst\test -make -@endverbatim - -This will build the @ref qutest_qhsm-fixture "test fixture" as a Windows executable and then it will run the @ref qutest_qhsm-funct-script "test script". The screen shot below shows the output produced in these two command-prompt windows. - -![QUTest QHsm test run](test_qhsm.jpg) - - -@section qutest_qhsm-fixture Test Fixture -The following listing shows the test fixture for the QHsm tests (file `test_qhsm.c`). This test fixture is used in both @ref qutest_qhsm-funct-script "functional" and @ref qutest_qhsm-struct-script "structural" tests. The explanation section following the listing clarifies the interesting lines of code (lines starting with [xx] labels). - -@code - #include "qpc.h" /* QUTest interface */ - #include "qhsmtst.h" /* CUT */ - - Q_DEFINE_THIS_FILE - - enum { - [1] BSP_DISPLAY = QS_USER, - }; - - /*--------------------------------------------------------------------------*/ - int main(int argc, char *argv[]) { - static QF_MPOOL_EL(QEvt) smlPoolSto[10]; /* small pool */ - - QF_init(); /* initialize the framework */ - - /* initialize the QS software tracing */ - Q_ALLEGE(QS_INIT(argc > 1 ? argv[1] : (void *)0)); - - /* initialize event pools... */ - QF_poolInit(smlPoolSto, sizeof(smlPoolSto), sizeof(smlPoolSto[0])); - - /* dictionaries... */ - [2] QS_FUN_DICTIONARY(&QHsm_top); - [3] QS_OBJ_DICTIONARY(the_hsm); - [4] QS_USR_DICTIONARY(BSP_DISPLAY); - - [5] QHsmTst_ctor(); /* instantiate the QHsmTst object */ - - return QF_run(); - } - - /*--------------------------------------------------------------------------*/ - [6] void BSP_display(char const *msg) { - [7] QS_BEGIN(BSP_DISPLAY, (void *)0) /* application-specific record */ - [8] QS_STR(msg); - QS_END() - } - - /*..........................................................................*/ - void BSP_exit(void) { - } - - /*--------------------------------------------------------------------------*/ - void QS_onTestSetup(void) { - } - /*..........................................................................*/ - void QS_onTestTeardown(void) { - } - /*..........................................................................*/ - void QS_onCommand(uint8_t cmdId, - uint32_t param1, uint32_t param2, uint32_t param3) - { - (void)param1; - (void)param2; - (void)param3; - - switch (cmdId) { - case 0U: { - break; - } - default: - break; - } - } - - /*..........................................................................*/ - #ifdef Q_HOST /* is this test compiled for a desktop Host computer? */ - /*! host callback function to "massage" the event, if necessary */ - void QS_onTestEvt(QEvt *e) { - (void)e; - } - #else /* this test is compiled for an embedded Target system */ - void QS_onTestEvt(QEvt *e) { - (void)e; - } - #endif -@endcode -
-
1
The `BSP_DISPLAY` enumeration will be used as the record-ID for the @ref qs_app "application-specific trace record". -
-> **NOTE:** The record-ID is offset by #QS_USER. -
2
This line produces a @ref qs_dict "function dictionary" for the [QHsm_top() function](https://www.state-machine.com/qpc/qep_8h.html#ac8ae4728dfab5ce26a907fc624f6e104). -
-
3
This line produces a @ref qs_dict "object dictionary" for the `l_hsm` state machine object to test. -
-
4
This line produces a @ref qs_dict "user dictionary" for the application-specific trace record defined at label [1]. -
-
5
The "constructor" of the state machine object is called. -
-> **NOTE:** The explicit "constructor" call is needed only in C. In C++, static constructors are called automatically as part of the startup sequence. - -
-
- - -@subsection qutest_qhsm-act Action Functions Test Doubles -For functional testing, which is focused on the **actions** performed by a state machine, the actions must generate some QS output. This QS instrumentation can be added either directly to the state machine model, or indirectly to the functions called from the state machine actions. The test fixture above illustrates the second option, because it was more convenient in this case (see `BSP_display()` implementation starting at label [6] above). - -
-
6
The function `BSP_display()` is called from all actions of the state machine. Inside the test fixture, this function is defined to produce QS output. This is a classic example of a "spy" test double. -
-
7
The QS output is produced with an @ref qs_app "application-specific trace record" enumerated at label [1]. The second argument to the QS_BEGIN() macro is zero, which means that this record does not use any @ref qs_local "local filter". -
-
8
The QS_STR() data element outputs the message string. -
-
-
-
- -@remark -In practice, you will likely use both functional and structural testing at the same time. Simple actions that do not perform any hardware-specific operations could be instrumented (with @ref qs_app "QS application-specific trace records") directly in the CUT (your state machines). The hardware-specific actions need to be abstracted anyway (in the BSP for "dual targeting"), in which case you can place the QS instrumentation in the BSP only. - - -@section qutest_qhsm-funct-script Test Script (Functional Testing) -The following listing shows the *test script* for the QHsm tests (file `test_qhsm-funct.py`). The explanation section following the listing clarifies the interesting lines of code (lines starting with `[xx]` labels). - -@code - # preamble... - [1] def on_reset(): - [2] glb_filter(GRP_UA) - [3] current_obj(OBJ_SM, "the_hsm") - - # tests... - [4] test("QHsmTst init") - [5] init() - [6] expect("@timestamp BSP_DISPLAY top-INIT;") - expect("@timestamp BSP_DISPLAY s-ENTRY;") - expect("@timestamp BSP_DISPLAY s2-ENTRY;") - expect("@timestamp BSP_DISPLAY s2-INIT;") - expect("@timestamp BSP_DISPLAY s21-ENTRY;") - expect("@timestamp BSP_DISPLAY s211-ENTRY;") - expect("@timestamp Trg-Done QS_RX_EVENT") - - #------------------ - [7] test("QHsmTst dispatch", NORESET) - [8] dispatch("A_SIG") - [9] expect("@timestamp BSP_DISPLAY s21-A;") - expect("@timestamp BSP_DISPLAY s211-EXIT;") - expect("@timestamp BSP_DISPLAY s21-EXIT;") - expect("@timestamp BSP_DISPLAY s21-ENTRY;") - expect("@timestamp BSP_DISPLAY s21-INIT;") - expect("@timestamp BSP_DISPLAY s211-ENTRY;") -[10] expect("@timestamp Trg-Done QS_RX_EVENT") - - dispatch("B_SIG") - expect("@timestamp BSP_DISPLAY s21-B;") - expect("@timestamp BSP_DISPLAY s211-EXIT;") - expect("@timestamp BSP_DISPLAY s211-ENTRY;") - expect("@timestamp Trg-Done QS_RX_EVENT") - - ~ ~ ~ -@endcode - -
-
1
The script procedure `on_reset()` is executed after each reset of the target. This is in contrast to the procedure `on_setup()`, which is executed at the beginning of all tests, including tests that don't reset the target. -
-
2
The @ref qs_global "global filter" is set to `GRP_UA`, which means «group-user-all» trace records. This filter setting determines the character of the test to be a **functional** test, because the focus is on the trace records produced by actions (@ref qs_app "user-defined" records) rather than the @ref qs_pre "pre-defined records" generated by executing a state machine. -
-
3
The command current_obj() sets the current state machine object to `"the_hsm"`. Because this is performed in the on_reset() callback, this current object will be set before every test (except the NORESET-tests, which do not call on_reset()). -
-
-
- - -Test: "QHsmTst init" tests the top-most initial transition -
-
4
The test() command starts the test. -
-
5
The init() command triggers the initial transition in the current state-machine object (see label [3]). -
-
6
The following expect() commands verify that all steps of the top-most initial transition are taken in the right order. -
-
-
- - -Test: "QHsmTst dispatch" tests dispatching various events to the state machine -
-
7
The test() command starts the test. -
-
8
The dispatch() command dispatches a given event to the state machine. -
-
9
The expect() commands verify that the state machine **actions** (`BSP_display()` function) happened. -
-
10
This expect() command verifies that the processing of the event (see dispatch() at label [8]) has completed. -
-
-
- - -@section qutest_qhsm-struct-script Test Script (Structural Testing) -The following listing shows the *test script* for the QHsm tests (file `test_qhsm-struct.py`). The explanation section following the listing clarifies the interesting lines of code (lines starting with `[xx]` labels). - -@code - # preamble... - [1] def on_reset(): - [2] glb_filter(GRP_SM) - [3] current_obj(OBJ_SM, "the_hsm") - - - # tests... - [4] test("QHsmTst init") - [5] init() - [6] expect("===RTC===> St-Init Obj=the_hsm,State=QHsm_top->QHsmTst_s2") - expect("===RTC===> St-Entry Obj=the_hsm,State=QHsmTst_s") - expect("===RTC===> St-Entry Obj=the_hsm,State=QHsmTst_s2") - expect("===RTC===> St-Init Obj=the_hsm,State=QHsmTst_s2->QHsmTst_s211") - expect("===RTC===> St-Entry Obj=the_hsm,State=QHsmTst_s21") - expect("===RTC===> St-Entry Obj=the_hsm,State=QHsmTst_s211") - expect("@timestamp Init===> Obj=the_hsm,State=QHsmTst_s211") - expect("@timestamp Trg-Done QS_RX_EVENT") - - #------------------ - [7] test("QHsmTst dispatch", NORESET) - [8] dispatch("A_SIG") - [9] expect("@timestamp Disp===> Obj=the_hsm,Sig=A_SIG,State=QHsmTst_s211") - expect("===RTC===> St-Exit Obj=the_hsm,State=QHsmTst_s211") - expect("===RTC===> St-Exit Obj=the_hsm,State=QHsmTst_s21") - expect("===RTC===> St-Entry Obj=the_hsm,State=QHsmTst_s21") - expect("===RTC===> St-Init Obj=the_hsm,State=QHsmTst_s21->QHsmTst_s211") - expect("===RTC===> St-Entry Obj=the_hsm,State=QHsmTst_s211") - expect("@timestamp ===>Tran Obj=the_hsm,Sig=A_SIG,State=QHsmTst_s21->QHsmTst_s211") -[10] expect("@timestamp Trg-Done QS_RX_EVENT") - - dispatch("B_SIG") - expect("@timestamp Disp===> Obj=the_hsm,Sig=B_SIG,State=QHsmTst_s211") - expect("===RTC===> St-Exit Obj=the_hsm,State=QHsmTst_s211") - expect("===RTC===> St-Entry Obj=the_hsm,State=QHsmTst_s211") - expect("@timestamp ===>Tran Obj=the_hsm,Sig=B_SIG,State=QHsmTst_s21->QHsmTst_s211") - expect("@timestamp Trg-Done QS_RX_EVENT") - - ~ ~ ~ -@endcode - -
-
1
The script procedure `on_reset()` is executed after each reset of the target. This is in contrast to the procedure `on_setup()`, which is executed at the beginning of all tests, including tests that don't reset the target. -
-
2
The @ref qs_global "global filter" is set to `GRP_SM`, which means «group-state-machine» trace records. This filter setting determines the character of the test to be a **structural** test, because the focus is on the @ref qs_pre "pre-defined records" generated by executing a state machine, rather than trace records produced by actions (user trace records). -
-
3
The command current_obj() sets the current state machine object to `"the_hsm"`. Because this is performed in the on_reset() callback, this current object will be set before every test (except the NORESET-tests, which do not call on_reset()). -
-
-
- - -Test: "QHsmTst init" tests the top-most initial transition -
-
4
The test() command starts the test. -
-
5
The init() command triggers the initial transition in the current state-machine object (see label [3]). -
-
6
The following expect() commands verify that all steps of the top-most initial transition are taken in the right order. -
-
-
- - -Test: "QHsmTst dispatch" tests dispatching various events to the state machine -
-
7
The test() command starts the test. -
-
8
The dispatch() command dispatches a given event to the state machine -
-
9
The expect() commands verify that the state machine RTC (Run-To-Completion) steps have been executed. -
-
10
This expect() command verifies that the processing of the event (see dispatch() at label [8]) has completed. -
-
-
- -
-@nav{qutest_mock,qutest_blinky} -*/ - -/*###########################################################################*/ -/*! @page qutest_blinky Blinky Example -@nav{qutest_qhsm,qutest_dpp} - -

This example shows how to unit-test a simple active object (AO) called "Blinky". This Blinky AO, which is driven by a [QP time event](https://www.state-machine.com/qpc/qf_8h.html#struct_q_time_evt), turns on and off an LED. -

- - -@section qutest_blinky-cut Code Under Test (CUT) -This example is available in both the [QP/C](https://www.state-machine.com/qpc) as well as the [QP/C++](https://www.state-machine.com/qpcpp) frameworks. The complete code for the Blinky example is provided in the directory `\examples\qutest\blinky\test`. - -![Blinky model in QM.](qutest_blinky_qm.png) - - -@section qutest_blinky-run Running the Test with QUTest -To run the `Blinky` test (on Windows), open a command prompt and type: - -@verbatim -qspy -@endverbatim - -This will start the @ref qspy "QSPY host utility" with the TCP/IP connection to the Target. - -Next, open a **second** command prompt window and type: - -@verbatim -cd C:\qp\\examples\qutest\blinky\test -make -@endverbatim - -@note -The provided `Makefile` will also work on Linux and MacOS. The only difference from Windows is that you open a terminal window and change the directory to `~/qp//examples/qutest/blinky/test`. - - -This will build the @ref qutest_fixture "test fixture" as a host executable and then it will run the @ref qutest_script "test script" (in Python). The screen shot below shows the output produced in these two command-prompt windows. - - -![Blinky test build and run with QUTest (right) and QSPY output (left)](test_blinky.jpg) - -
-@nav{qutest_qhsm,qutest_dpp} -*/ - -/*###########################################################################*/ -/*! @page qutest_dpp DPP Example -@nav{qutest_blinky,qutest_fixture} - -

The DPP (Dining Philosophers Problem) example shows how to use QUTest in various stages of application development, including not only unit testing, but **integration testing** as well. -

- - -@section qutest_dpp-cut Code Under Test (CUT) -This example is available in both the [QP/C](https://www.state-machine.com/qpc) as well as the [QP/C++](https://www.state-machine.com/qpcpp) frameworks. The complete code for the DPP example is provided in the directory `\examples\qutest\dpp\test`. - - -@section qutest_dpp-run Running the Test with QUTest -To run the DPP test (on Windows), open a command prompt and type: - -@verbatim -qspy -@endverbatim - -This will start the @ref qspy "QSPY host utility" with the TCP/IP connection to the Target. - -Next, open a **second** command prompt window and type: - -@verbatim -cd C:\qp\\examples\qutest\dpp\test_philo -make -@endverbatim - -@note -The provided `Makefile` will also work on Linux and MacOS. The only difference from Windows is that you open a terminal window and change the directory to `~/qp//examples/qutest/blinky/test`. - - -This will build the @ref qutest_fixture "test fixture" as a host executable and then it will run the @ref qutest_script "test script" (in Python). The screen shot below shows the output produced in these two command-prompt windows. - -![DPP test build and run with QUTest (right) and QSPY output (left).](test_dpp.jpg) - -
-@nav{qutest_blinky,qutest_fixture} -*/ diff --git a/doxygen/qview.dox b/doxygen/qview.dox deleted file mode 100644 index 333e332..0000000 --- a/doxygen/qview.dox +++ /dev/null @@ -1,713 +0,0 @@ -/*! @page qview QView™ Visualization & Monitoring - -![](qview_banner.jpg) - -@subpage qview_ui " " -@subpage qview_cust " " - - -@section qview_about About QView™ - -@htmlonly - -@endhtmlonly - -

QView™ is a powerful **Visualization and Monitoring** facility, which allows embedded developers to rapidly create **remote graphical user-interfaces** to monitor and control their embedded devices from a host (desktop) computer. The interfaces created by QView™ can visualize the tracing data produced by @ref qpspy "QP/Spy" and can also **interact with the target** by sending commands and injecting events to the embedded target. -

- -As you can see in the screen shots below, a QView™ user interface consists of a text box with extensible menus plus a **customizable canvas** that can serve as a remote graphical user-interface to your embedded device. The canvas can contain various "widgets", such as buttons, sliders, gauges, graphs, animations, etc. The actual functionality of the _virtual GUI_ obviously depends on the target system and the embedded code it is running. Therefore, the QView™ provides only a skeleton, which is then @ref qview_cust "customized" by user-supplied scripts written in Python (version 3). - -
- -@image html qview_ex.gif "Example of a QView™ session on an embedded board (Windows host)" - -
-@image html qview_dpp-fedora.gif "Example of a QView™ session (Linux host)" - - -@subsection qview_special What's Special About It? - -QView™ has been specifically designed for extensibility, so that you can quickly @ref qview_cust "customize its GUI and behavior" to your specific embedded project, so that you can use QView™ as a powerful custom Human-Machine Interface (HMI) for your projects. The cusomization is accomplished in Python (version 3), which means that it is naturally platform-neutral and runs without any changes on Windows, Linux, or macOS. - -Out of the box, QView™ supports the following @ref qview_ui "commands" (NOTE: This basic functionality can be extended in the @ref qview_cust "QView™ customization"): - -- Set @ref qs_global "global QS filters" inside the Target -- Set @ref qs_local "local QS filters" inside the Target -- Inject an arbitrary event to the Target (direct post or publish) -- Execute a user-defined command function inside the Target with arguments supplied from QView™ -- Peek data inside the Target and send to QView™ -- Poke data (supplied from QView™) into the Target -- Execute clock tick inside the Target -- Remotely reset the Target. - -@note -A visualization and monitoring system like QView™ can be used in all stages of development, during manufacturing, and also after deployment for in-field servicing of embedded devices. - - -@section qview_struct QView™ Structure -The sequence diagram below shows the general structure of QView™. The embedded Target is running an instrumented code that communicates with the @ref qspy "QSPY Host application" over the @ref qspy_link "Target data link" (red arrows). This communication is based on the @ref qpspy_proto "QP/Spy Protocol". - -@attention -The Target must be running the "Spy" build configuration, in which the @ref qpspy is enabled. Additionally, the QP/Spy implementation in the Target must support @ref qpspy_rx "bi-directional" communication with @ref qspy "QSPY". - - -The QView™ (Python script) attaches to the QSPY host application by means of the @ref qspy_udp "UDP socket" that QSPY opens specifically for attaching various "front-ends". This communication (blue arrows) uses the same packet structure as the @ref qpspy_proto "QP/Spy Protocol", but without the HDLC framing, without transparency (escaping), and without the checksum. - - -@image html qspy_qview.gif "Communication between Target, QSPY, and QView" - -
-
A
A Target produces QS trace records, which the @ref qspy "QSPY Back-End" forwards to the @ref qpspy_udp "UDP Socket", so that any attached Front-End (such as QView™) receives all this data. -
- -
B
The Front-End (QView™) sends commands as @ref qpspy_udp "UDP packets to QSPY". For some of those packets, the @ref qspy "QSPY Back-End" supplies additional information (e.g., translation between symbolic names and binary addresses according to the @ref qs_dict "QS dictionaries" collected from the Target). -
- -
C
The @ref qspy "QSPY Back-End" then forwards the modified packets to the Target. -
-
-
- -@remark -Why UDP? The @ref qspy_udp "communication between QSPY and QView" is based on UDP, because UDP is inherently packet-oriented (as opposed to TCP, which is stream-oriented) and preserves the packet boundaries. - - -@section qview_use Installation & Use -The qview.py script can be used standalone, without any installation in your Python system (see @ref qview_run below). - -@note -The qview.py script is included in the @ref qtools_about "QTools™ collection". Also, the @ref qtools_win "QTools™ collection for Windows" already includes Python (3.8), so you don't need to install anything extra. - - -Alternatively, you can use **your own Python** installation, into which you can install the latest QView™ with `pip` from the [PyPi index](https://pypi.org/project/qview/) by executing the following command: - -@verbatim -pip install qview -@endverbatim - - -@subsection qview_run Running QView™ -If you are using QView™ as a standalone Python script, you invoke it as follows: - -@verbatim -python3 /qview.py [ [ []]] -@endverbatim - -Alternatively, if you've installed QView™ with `pip`, you invoke it as follows: - -@verbatim -qview [cust_script] [qspy_host[:udp_port]] [local_port] -@endverbatim - - -@subsection qview_command Command-line Options -- `cust_script` — optional @ref qview_cust "customization Python script" for your specific target system. If not specified, qview will provide only the @ref qview_ui "generic user interface" for interacting with the target (e.g., reset, setting QS filters, posting events, etc.). - -- `qspy_host[:udp_port]` — optional host-name/IP-address:port for the host running the QSPY host utility. If not specified, the default is 'localhost:7701'. - -- `local_port` — optional local UDP port to be used by "qview". If not specified, the default is '0', which means that the operating system will choose an open port. - - -@subsection qview_exa Examples - - - -@verbatim -python3 %QTOOLS%\qview\qview.py -@endverbatim - -opens the generic (not customized) "qview". - -@verbatim -python3 %QTOOLS%\qview\qview.py dpp.py -@endverbatim - -opens "qview" with the customization provided in the dpp.py script located in the current directory. - -@verbatim -qview ..\qview\dpp.py localhost:7701 -@endverbatim - -opens "qview" (**installed with pip**) with the customization provided in the dpp.py script located in the directory ..\qview. The "qview" will attach to the QSPY utility running at localhost:7701. - -@verbatim -qview dpp.py 192.168.1.100:7705 -@endverbatim - -opens "qview" (**installed with pip**) with the customization provided in the dpp.py script located in the current directory. The "qview" will attach to the QSPY utility running remotely at IP address 192.168.1.100:7705. - - - - -@verbatim -python3 $(QTOOLS)/qview/qview.py -@endverbatim - -opens the generic (not customized) "qview". - -@verbatim -python3 $(QTOOLS)/qview/qview.py dpp.py -@endverbatim - -opens "qview" with the customization provided in the dpp.py script located in the current directory. - -@verbatim -qview *.py ../qview/dpp.py localhost:7701 -@endverbatim - -opens "qview" (**installed with pip**) with the customization provided in the dpp.py script located in the directory ../qview. The "qview" will attach to the QSPY utility running at localhost:7701. - -@verbatim -qview dpp.py 192.168.1.100:7705 -@endverbatim - -opens "qview" (**installed with pip**) with the customization provided in the dpp.py script located in the current directory. The "qview" will attach to the QSPY utility running remotely at IP address 192.168.1.100:7705. - - -@note -In practice, the easiest way to launch QView™ is to define a shortcut, like the one provided with the DPP example:
@n -@image html qview_shortcut.gif "qview shortcut properties" - - -@section qview_attaching Attaching QView to QSPY -In contrast to TCP, which is stream-oriented, UDP is packet-oriented, so the only way to "attach" two ends of communication is to exchange packets. Consequently, immediately after QView™ is launched, it tries to **attach** by sending the @ref udp_ATTACH "ATTACH" packet to QSPY. If QSPY responds with the @ref udp_in_ATTACH "ATTACH" response, QView™ considers that it is "attached". - -However, if the @ref udp_in_ATTACH "ATTACH" response does not arrive within a second or two (perhaps because QSPY is not running), QView™ opens a modal dialog box that reminds you to run QSPY, as shown in the screen-shot below: - -@image html qview_attach.gif "Attach to QSPY dialog box" - -Depending how you start @ref qspy "QSPY", the dialog box might close automatically, which means that QView has successfully **attached** to QSPY. However, if the dialog box does not close, you need to click the **Attach** button to send @ref udp_ATTACH "ATTACH" packets to QSPY, until QView™ receives the @ref udp_in_ATTACH "ATTACH" response from QSPY. If you can't "attach", you can click the **Close** button to close QView™. - -@note -Because UDP works over networks, the QSPY Back-End can run on a **different machine** (e.g., a lab computer) than the QView™ Front-End (e.g., office computer). These two machines can even run different operating systems, for example Linux on the lab computer and Windows in the office, or vice versa. All you need to do is to provide the host-name parameter as the third command-line argument to the qview.py script (e.g., `python3 qview.py dpp.py 192.168.1.101`). - - -@subsection qview_tstamp Recognizing the Target -Before QView™ can correctly interpret any data from the Target, it needs to obtain certain information about the Target, such as the sizes of object pointers, function pointers, event signals, etc. This information is provided in the ::QS_TARGET_INFO trace record coming from the Target. - -To inform you about the Target status, QView™ displays the **Target: UNKNOWN** in the status bar when the target is "unknown": - -@image html qview_unknown.gif "Target UNKNOWN status" - -If this happens, you can explicitly request the Target information by means of the "Commands->Query Target Info" menu: - -@image html qview_known.gif "Target KNOWN status (build time-stamp)" - -After the Target information is received, the QView™ status bar shows the build time-stamp of the Target image. - -@nav{qutest_script,qview_ui} -*/ -/*###########################################################################*/ -/** -@page qview_ui QView User Interface -@nav{qutest_script,qview_cust} - -

The qview.py script provides a Graphical User Interface (GUI) consisting of the main menu, the text view, the status bar, and the customizable canvas view. -

- -@image html qview.jpg "QView user interface" - -The **main menu** includes several useful commands, which are quickly reviewed and the following sections. The main menu might subsequently be augmented in your own @ref qview_cust "customizations". - - - -@section qview_file File Menu -The File menu provides an interface to the @ref qspy_saving "QSPY saving files" feature. This menu allows you to trigger QSPY to save @ref qspy_dict "dictionaries", as well as to open/close all other file formats supported by QSPY. - -@image html qview_file.gif - - -@section qview_view View Menu -The View menu allows you to toggle (show/hide) the Canvas view. - -@image html qview_view.gif "Text-view and Canvas-view menus" - -@image html qview_canvas.gif "Canvas-view enabled" - -@note -The provided screen shot of the Canvas-view is specific to the DPP example application (see @ref qview_cust). - - -@section qview_glob Global Filters Menu -The Filters menu opens dialog boxes through which you can set the @ref qs_global "QS Global Filter" for QS Record-Types. - -The Global Filter menu opens dialog boxes for each *group* of global filters. For example, the screen shot below shows the "SM Group" (State Machine Group). In this "SM Group" dialog box you can check/uncheck the individual filters, or you can "Select ALL" or "Clear ALL" filters in the group. - -@image html qview_glob_dlg.gif "Global Filter SM-Group Dialog Box" - -@note -The Global-Filters menu reflects the status of the whole group by the following status-indicators: -- `[-]` — no filters in the group are selected -- `[+-]` — some filters in the group are selected -- `[+]` — all filters in the group are selected. - - -@section qview_loc Local Filters Menu -The Filters menu opens dialog boxes through which you can set the @ref qs_local "QS Local Filter" for QS QS-IDs. - -The Local Filter menu opens dialog boxes for each *group* of local filters. For example, the screen shot below shows the "AO-IDs" (Active Object Group). In this "AO-IDs" dialog box you can check/uncheck the individual QS-IDs (which are AO priorities in this case), or you can "Select ALL" or "Clear ALL" filters in the group. - -@image html qview_loc_dlg.gif "Local Filter AO_OBJ Dialog Box" - -@note -The Local-Filters menu reflects the status of the whole group by the following status-indicators: -- `[-]` — no filters in the group are selected -- `[+-]` — some filters in the group are selected -- `[+]` — all filters in the group are selected. - - -@section qview_curr Current-Obj Menu -The Curr-Obj menu opens dialog boxes through which you can set the @ref qs_curr "QS Current Objects". - -The Curr-Obj menu opens dialog boxes for each local current object. For example, the screen shot below shows the "AO_OBJ" (current Active Object). In this "Curr-Obj" dialog box you can specify the object either by its name (must match the QS dictionary), or as addresses of the objects in decimal and in hexadecimal (with the `0x` prefix). - -@image html qview_curr_dlg.gif "Current Object AO_OBJ Dialog Box" - -@note -The Curr-Obj menu reflects the selected current objects, which are listed to the right of the filter (e.g., `Table_inst`). - - -@section qview_commands Commands Menu -The Commands menu allows you to execute simple commands (without parameters) in the Target, such as Reset the Target, Query the Target, and clock Tick at rate 0 and rate 1. Also, this menu allows you to execute commands with parameters, which are briefly discussed below. - -@image html qview_cmd.png -@image latex qview_cmd.png with=5.0in -@caption{Commands Menu} - - -@subsection qview_tag Displaying Tag Messages in QSPY -The "Tag Message..." menu allows you to display a tag message in the QSPY output. - -@image html qview_tag_dlg.png "Tag Message Dialog and QSPY output" - - -@subsection qview_user Executing User Command -The "User Command..." menu allows you to invoke a command in the Target and pass up to three parameters to this command. (**NOTE:** a command is an application-specific callback function that the QS-RX component executes in the Target). - -@image html qview_cmd_dlg.gif "Command Dialog Box" - -The screen shot above shows how to execute User Command number `0` with the parameters `12345`, `0xDEADBEEF` and `0` (default). Both the command number and the parameters can be specified in hexadecimal (with the `0x` prefix). - - -@subsection qview_peek Peek Command -The Peek Obj/Addr... command opens a dialog box, in which you can provide the Target object or address (RAM or ROM) (**NOTE:** You can provide either the object name, which must be known by its object-dictionary, or numerical address, which **must** be a valid RAM/ROM address, or the Target might crash.) - -@attention -The "Peek..." menu requires the "Current-Obj AP_OBJ" to be set in the @ref qview_curr, because this is the object within the Target which will be "peeked". The "Peek..." menu is **inactive** (grayed-out) when the "Current-Obj AP_OBJ" is not specified. - - -@note -The Peek Command can be used to view any **readable** address, such as ROM, RAM, and also **peripheral registers** in your Target. - - -As shown in the screen shot below, the PEEK command takes additionally the offset into the object [bytes] (offset of 0 is default if not specified), the size of the item [8-bit, 16-bit, 32-bit] and the number of units (n-units) [1..255] you wish to "peek". - -@image html qview_cmd_peek.gif "Peek Command Dialog Box" -
- -The Target responds with a #QS_PEEK_DATA trace record, which you can view in QSPY human-readable output (the packet is also sent to QView, where you can react to it in your @ref qview_cust "customization"). - -@verbatim -4294965703 Trg-Peek Offs=0,Size=4,Num=4,Data=<20000D2C,20000D2C,20000D74,000A0008> -@endverbatim - - -@subsection qview_poke Poke Command -The "Poke Obj/Addr..." command allows you to write data to the specified object or address in Target's RAM (**NOTE:** You can provide either the object name, which must be known by its object-dictionary, or numerical address, which **must** be a valid RAM address, or the Target might crash.) - -@attention -The "Poke..." menu requires the "Current-Obj AP_OBJ" to be set in the @ref qview_curr, because this is the object within the Target which will be "poked". The "Poke..." menu is **inactive** (grayed-out) when the "Current-Obj AP_OBJ" is not specified. - - -@note -The Poke Command can be used to change any **writable** address, such as RAM, but also **peripheral registers** in your Target. - - -As shown in the screen shot below, the POKE command takes additionally the offset into the object [bytes], the size of the item [8-bit, 16-bit, 32-bit], and the data to "poke", which can be either decimal or hexadecimal (`0x` prefix). - -@image html qview_cmd_poke.gif "Poke Command Dialog Box" -
- -The Target responds with `Trg-Ack QS_RX_POKE`: - -@verbatim - Trg-Ack QS_RX_POKE -@endverbatim - - -@section qview_events Events Menu -The "Events" menu allows you to Publish, Post, or Dispatch an event to the Target. Additionally, you can also "Initialize" a state machine by triggering the top-most initial transition in it. - -@attention -The "Post..." menu requires the "Current-Obj AO_OBJ" to be set in the @ref qview_curr, because this is the Active Object within the Target which will be "posted". The "Dispatch..." and "Init SM..." menus require the "Current-Obj SM_OBJ" to be set in the @ref qview_curr, because this is the State Machine within the Target which will be "dispatched" or "initialized". These menus are **inactive** (grayed-out) when the expected "Current-Objects" are not specified. - -@image html qview_evt_dlg.gif "Events Menu with Post-Event Dialog Box" - -As shown in the screen-shot above, you define the custom event by providing the sig (signal), which can be either its symbolic name (must correspond to the Signal Dictionary) or a numerical value. - -The signal is followed by up to 9 optional event parameters par1..par9. Each parameter is specified as a pair of the size of the parameter [8-bit, 16-bit, 32-bit], and the value of the parameter, which can be either decimal or hexadecimal (`0x` prefix). - -@attention -The parameters are sent using the **endianness** reported by the Target. Also, all the specified parameters are packed in the exact order without any "alignment". If the event structure is represented in the Target memory with some **padding**, you need to provide such padding explicitly (as one of the parameters). - - -@section qview_custom Custom Menu -This top-level menu is provided for your customization. Its intent is to let you add your own commands in your script. - -@image html qview_cust.gif - - -@section qview_help Help Menu -This menu allows you to access the online Q-SPY help in HTML, and also allows you to open the "About" dialog box. - -@image html qview_help.gif - -@nav{qutest_script,qview_cust} -*/ -/*###########################################################################*/ -/** -@page qview_cust Customizing & Extending QView™ -@nav{qview_ui,qwin} - -QView™ has been specifically designed for extensibility, so that you can customize its behavior to your specific project. In fact, as mentioned in the section about @ref qview_run "running QView", the qview.py script takes the `` @ref qview_command "command-line parameter", which is another Python script designed specifically to extend and customize the basic functionality. This section describes how to write this @ref qview_script "customization script", so that you can turn QView™ into a powerful remote **Human-Machine Interface** (HMI) for your embedded system. - -@remark -You don't need to change the qview.py script to customize and extend it for your project. The customizations you make go into a separate script, which is specific to your project. That way, you can have many different customization scripts and you don't pollute (and possibly break) the original code. - - -@section qview_cust_menu Custom Menu -The simple way of customizing QView™ is to add **custom menus**. - -@image html qview_cust.gif - - -@section qview_canvas Custom Canvas -The main part of the QView™ interface that you customize for your specific embedded system is the **custom Canvas**. The custom Canvas can show a complete custom Human-Machine Interface (HMI) to your embedded Target. The Canvas can display the changing status of the application and also it can provide **actuators**, like buttons, sliders, etc. to **interact** with the embedded Target. The following animation shows the custom Canvas for the DPP example (dpp.py script explained later). Please note that the button in the center of the screen allows you to interact with the Target by posting events to it. Please refer to this script code for the details of how various effects have been achieved. - -@image html qview_canv_dpp.gif "Custom Canvas for the DPP Application" - -
-@note -QView™ GUI is based on [Tkinter](https://docs.python.org/3/library/tkinter.html) and therefore it is highly recommended that you get familiar with this Python library. Specifically of interest for customizing QView™ is the [Tkinter Canvas](https://www.tutorialspoint.com/python/tk_canvas.htm).
-
-Many Python widget libraries (e.g., [tk_tools](https://github.com/slightlynybbled/tk_tools), etc.) are available to aid you in developing your custom canvas. With such widget libraries, you can display the data in an attractive form: as gauges, bars, graphs, and sliders. The attractiveness of the GUI is limited only by your creativity. - - -@section qview_script Customization Script -The easiest way to customize QView is to copy the provided example script (dpp.py, located in /examples/workstation/dpp/qview folder), rename it, and add your own extensions. The explanation section following the listing clarifies the interesting lines of code (lines starting with `[xx]` labels). - -@code{py} -[1] class DPP: -[2] def __init__(self): - - # request target reset on startup... -[3] reset_target() - - # add commands to the Custom menu... -[4] QView.custom_menu.add_command(label="Custom command", - command=self.cust_command) - - # configure the custom QView.canvas... -[5] QView.show_canvas() # make the canvas visible -[6] QView.canvas.configure(width=400, height=260) - - # tuple of activity images (correspond to self._philo_state) -[7] self._act_img = ( -[8] PhotoImage(file=HOME_DIR + "/img/thinking.gif"), - PhotoImage(file=HOME_DIR + "/img/hungry.gif"), - PhotoImage(file=HOME_DIR + "/img/eating.gif"), - ) - # tuple of philo canvas images (correspond to self._philo_obj) - self._philo_img = (\ - QView.canvas.create_image(190, 57, image=self._act_img[0]), - QView.canvas.create_image(273, 100, image=self._act_img[0]), - QView.canvas.create_image(237, 185, image=self._act_img[0]), - QView.canvas.create_image(146, 185, image=self._act_img[0]), - QView.canvas.create_image(107, 100, image=self._act_img[0]) - ) - - # button images for UP and DOWN - self.img_UP = PhotoImage(file=HOME_DIR + "/img/BTN_UP.gif") - self.img_DWN = PhotoImage(file=HOME_DIR + "/img/BTN_DWN.gif") - - # images of a button for pause/serve - self.btn = QView.canvas.create_image(200, 120, image=self.img_UP) -[9] QView.canvas.tag_bind(self.btn, "", self.cust_pause) - - - # on_reset() callback -[10] def on_reset(self): - # clear the lists -[11] self._philo_obj = [0, 0, 0, 0, 0] - self._philo_state = [0, 0, 0] - - # on_run() callback -[20] def on_run(self): -[21] glb_filter("QS_USER_00") - - # NOTE: the names of objects for loc_filter() and current_obj() - # must match the QS Object Dictionaries produced by the application. -[22] current_obj(OBJ_AO, "Table_inst") -[23] loc_filter(IDS_AO) - - # turn lists into tuples for better performance -[24] self._philo_obj = tuple(self._philo_obj) - self._philo_state = tuple(self._philo_state) - - - # example of a custom command -[30] def cust_command(self): -[31] command(1, 12345) - - # example of a custom interaction with a canvas object (pause/serve) -[40] def cust_pause(self, event): -[41] if QView.canvas.itemcget(self.btn, "image") != str(self.img_UP): -[42] QView.canvas.itemconfig(self.btn, image=self.img_UP) -[43] post("SERVE_SIG") -[44] QView.print_text("Table SERVING") - else: - QView.canvas.itemconfig(self.btn, image=self.img_DWN) - post("PAUSE_SIG") - QView.print_text("Table PAUSED") - - # intercept the QS_USER_00 application-specific packet - # this packet has the following structure (see bsp.c:displayPhilStat()): - # record-ID, seq-num, Timestamp, format-byte, Philo-num, - # format-bye, Zero-terminated string (status) -[50] def QS_USER_00(self, packet): - # unpack: Timestamp->data[0], Philo-num->data[1], status->data[3] -[51] data = qunpack("xxTxBxZ", packet) - i = data[1] - j = ("t", "h", "e").index(data[2][0]) # the first letter - - # animate the given philo image according to its activity - QView.canvas.itemconfig(self._philo_img[i], image=self._act_img[j]) - - # print a message to the text view - QView.print_text("%010d Philo %1d is %s"%(data[0], i, data[2])) - - #============================================================================= -[60] QView.customize(DPP()) # set the QView customization - -@endcode - -@subsection qview_cust_init Initialization - -
-
1
Every QView™ customization consists of a Python __class__ which does not extend any other class and can be called with any name you see fit. -
-
2
The constructor of your customization class sets up the GUI and optionally resets the target. -
-
3
The reset_target() command allows you to remotely reset the embedded Target. -> **NOTE:** Normally for an embedded application, you would like to start with resetting the Target, to start clean with @ref qs_dict "QS dictionaries", etc. However, if you run your application on the **host** (e.g., `/examples/workstation/dpp`), you typically *don't* want to reset the target. Instead, you simply launch the host executable *after* opening QView™, so that it will "see" all the QS dictionaries, etc. This alternative is shown in the DPP example for the host located in `/examples/workstation/dpp`). -
-
4
The @ref qview.QView.custom_menu "QView.custom_menu" object allows you to extend the @ref qview_custom "Custom Menu" with your own commands. Here, you just add the command "Custom command". Later you will write the function that handles this menu item. -> **NOTE:** The @ref qview.QView.custom_menu "QView.custom_menu" object uses the [Tkinter Menu interface](https://www.tutorialspoint.com/python/tk_menu.htm). -
-
-
- - -@subsection qview_cust_canvas Setting Up the Canvas -The Custom Canvas is set up in the **constructor** of the customization class `__init__(self)`) using the @ref qview.QView.canvas "QView.canvas" object: - -
-
5
The @ref qview.QView.show_canvas() "QView.show_canvas()" function lets you @ref show the canvas from the beginning. This corresponds to setting the Canvas checkbox in the @ref qview_view. -
-
6
The @ref qview.QView.canvas "QView.canvas" object can be configured to the desired size using the standard Tkinter functionality. -> **NOTE:** The @ref qview.QView.canvas "QView.canvas" object uses the [Tkinter Canvas interface](https://www.tutorialspoint.com/python/tk_canvas.htm). -
-
7-8
You need to organize the GUI elements for the canvas, so that they easily map to your specific customization. Here, the images representing the Dining Philosophers activities and Philosophers themselves sitting around the table are represented as [Python tuples](https://www.tutorialspoint.com/python/python_tuples.htm). -> **NOTE:** The proper design of the data structures for your application can vastly simplify the customization script. Please remember to take advantage of the rich Python data structures, such as lists, tuples, dictionaries and arrays. -
-
9
This line demonstrates how to provide a **keyboard binding** to a canvas element (the center button `self.btn` in this case). -
-
-
- - -@subsection qview_cust_reset The on_reset() Callback -The main qview.py script calls the on_reset() callback function in your customization script when it receives the @ref #QS_TARGET_INFO "reset packet" from the Target. This gives you an opportunity to clear your internal data structures to get them ready for new data coming from the Target (e.g., @ref qs_dict). - -
-
10
The @ref on_reset() callback must be a member of the customization class (note the `self` parameter). -
-
11
Here, the callback clears the internal lists used by customization. -
-
-
- - -@subsection qview_cust_run The on_run() Callback -The main qview.py script calls the on_run() callback function in your customization script when it receives the @ref #QS_QF_RUN trace record from the Target. This record typically marks the end of the Target initialization and, specifically, the completion of the @ref qs_dict. This gives you an opportunity to set the @ref qs_filters, @ref qs_curr, using their **symbolic names**. - -@note -The **symbolic names** inside the Target are known to QSPY only *after* the Target produces the @ref qs_dict. - - -
-
20
The @ref on_run() callback must be a member of the customization class (note the `self` parameter). -
-
21
Here, the callback sets the @ref qs_global "Global Filter" by means of the glb_filter() facility provided in the qview.py script. -
-
22
Here, the callback sets the @ref qs_curr "Current Objects" by means of the current_obj() facility provided in the qview.py script. -
-
23
Here, the callback sets the @ref qs_local "Local Filter" by means of the loc_filter() facility provided in the qview.py script. -
-
-
- -@note -The glb_filter(), current_obj(), and loc_filter() facilities in QView™ are **identical** to those in the @ref qutest "QUTest". This commonality between @ref qview "QView™" and @ref qutest "QUTest™" is intentional. - - -@subsection qview_cust_cmd Custom Commands -The Custom Commands, added either to the @ref qview.QView.custom_menu "QView.custom_menu" or attached to the Canvas elements, need to be implemented as member functions of the customization class: - -
-
30
The function name must match the `command=self.cust_command` parameter in the `menu.add_command()` (see step [4] of the script). -
-
31
Here, the function invokes the command() facility provided in the qview.py script. -
-
  -
-
40
The function name must match the `...tag_bind(... self.cust_pause)` parameter (see step [9] of the script). -
-
41
Here, the function **checks the Canvas elements** (using the standard Tkinter functionality). -
-
42
Here, the function **configures the Canvas elements** (using the standard Tkinter functionality). -
-
43
Here, the function **posts an event** to the Target by means of the post() facility provided in the qview.py script. -
-
43
Here, the function **prints text** to the @ref qview_ui "Text View" by means of the @ref qview.QView.print_text() "QView.print_text()" facility provided in the qview.py script. -
-
-
- -@note -The command() and post() facilities in QView™ are **identical** to those in the @ref qutest "QUTest". This commonality between @ref qview "QView™" and @ref qutest "QUTest™" is intentional. - - -@subsection qview_cust_handler Custom Packet Handlers -The most important feature of QView™ is that it can display the **live** status of the embedded system. QView™ achieves it by receiving the QS software tracing packets from the Target. Consequently, one of the most important activities of the customization script is to intercept and parse the incoming packets. - - -To this end, the qview.py script provides special accumulations: - -- the qview.py script provides a **packet-specific callback** for every QS trace record from the Target. The name of the callback is identical to the enumerated names of the #QSpyRecords of the trace records. For example, the packet-handler for the QS trace record #QS_QEP_TRAN is named `QS_QEP_TRAN()`. - -- the qview.py script provides the qunpack() facility, specifically designed to parse and unpack the QS trace records. - - -
-
50
The packet-handler name must match the enumeration #QSpyRecords. Here, the packet-handler is for the #QS_USER_00 trace record. -
-
51
Here, the packet-handler calls the qunpack() facility to "unpack" the binary data from the received packet into the Python tuple `data`. Each element in this tuple corresponds to the explicitly specified format. For example, with the format "xxTxBxZ": the "T" format (timestamp) is unpacked into `data[0]`, the "B" format (byte) is unpacked into `data[1]`, and the "Z" format (zero-terminated ASCII string) is unpacked into `data[2]`. Subsequently, in the body of the function, the `data[]` elements are used according to their meaning. -
-
-
- -@note -The qunpack() facility "understands" all formats supported by the Python `struct.unpack()` plus formats specific to QP/Spy, such as: "T" for timestamp, "S" for event signal, "" - - -@subsection qview_cust_set Registering Customization in QView™ - -
-
60
Every QView™ customization script must end with a call to the @ref qview.QView.customize() "QView.customize()" function, to which you need to pass the instance of your Customization class (here, your `DPP` class). -
-
-
- - -@subsection qview_pre App-Specific vs. Predefined Trace Records -The customization script discussed in the previous section was based on the @ref qs_app "application-specific trace record" (`QS_USER_00`), which was specifically produced by the DPP application. This trace record delivered the information about the changing status of the Dining Philosophers, which allowed the customization script to animate the Philosopher images on the custom canvas. - -However, it is also possible to use a different strategy based on the @ref qs_pre "predefined QS trace records". The advantage is that **no additional instrumentation** is needed in the application, because the information is already produced by the framework. All you need to do is to enable (in the global filter) the appropriate QS trace record. - -This alternative strategy is illustrated in the dpp1.py script (located in the same directory as the dpp.py script discussed earlier). The dpp1.py script is based on the predefined QS record #QS_QEP_TRAN, which provides the information about the **state changes** in the Philo objects in the application. - -The most tricky part in this approach is to correctly unpack the predefined record. And here, the biggest challenge is to translate the binary addresses of the objects to their **symbolic names**. For that, the dpp1.py script intercepts the @ref qs_dict "QS dictionary" records #QS_OBJ_DICT and #QS_FUN_DICT, from which the script retrieves the binary addresses of the specific objects. Below are the relevant snippets from the dpp.py script. Please note the use of Python lists, tuples, and dictionaries to organize the data for easy access by the index number of the Philo objects or by the state name. - -@code{py} -class DPP: - . . . - # intercept the QS_OBJ_DICT stadard packet - # this packet has the following structure: - # record-ID, seq-num, Object-ptr, Zero-terminated string - def QS_OBJ_DICT(self, packet): - data = qunpack("xxOZ", packet) - try: - # NOTE: the names of objects must match the QS Object Dictionaries - # produced by the application. - i = ("Philo_inst[0]", - "Philo_inst[1]", - "Philo_inst[2]", - "Philo_inst[3]", - "Philo_inst[4]").index(data[1]) - self._philo_obj[i] = data[0] - except: - pass # dictionary for a different object - - # intercept the QS_FUN_DICT stadard packet - # this packet has the following structure: - # record-ID, seq-num, Function-ptr, Zero-terminated string - def QS_FUN_DICT(self, packet): - data = qunpack("xxFZ", packet) - try: - # NOTE: the names of states must match the QS Object Dictionaries - # produced by the application. - j = ("Philo_thinking", - "Philo_hungry", - "Philo_eating").index(data[1]) - self._philo_state[j] = data[0] - except: - pass # dictionary for a different state - - # intercept the QS_QEP_TRAN stadard packet - # this packet has the following structure: - # record-ID, seq-num, Timestamp, Signal, Object-ptr, - # Function-ptr (source state), Function-ptr (new active state) - def QS_QEP_TRAN(self, packet): - data = qunpack("xxTSOFF", packet) - try: - i = self._philo_obj.index(data[2]) - j = self._philo_state.index(data[4]) - - # animate the given philo image according to its activity - QView.canvas.itemconfig(self._philo_img[i], - image=self._act_img[j]) - # print a message to the text view - QView.print_text("%010d Philo %d is %s"\ - %(data[0], i, ("thinking", "hungry", "eating")[j])) - except: - pass # state-entry in a different object - . . . -@endcode - -
-@note -The presented strategy of intercepting the @ref qs_dict "QS dictionary" records #QS_OBJ_DICT and #QS_FUN_DICT is quite generic and can be easily adapted in your own customization scripts. - - -@subsection qview_dsl-commands QView Script Commands -Here is the summary of commands that you can use in the QView scripts: - -- reset_target() -- command() -- peek() -- poke() -- tick() -- glb_filter() -- loc_filter() -- ao_filter() -- current_obj() -- query_curr() -- post() -- publish() -- init() -- dispatch() -- qunpack(). - -@nav{qutest,qwin} -*/ diff --git a/doxygen/qwin.dox b/doxygen/qwin.dox deleted file mode 100644 index 4154518..0000000 --- a/doxygen/qwin.dox +++ /dev/null @@ -1,54 +0,0 @@ -/*! @page qwin QWin™ GUI Prototyping Toolkit - -![QWin GUI Prototyping Toolkit](qwin_banner.jpg) - -When developing embedded code for devices with non-trivial user interfaces, it often pays off to build a prototype (virtual prototype) of the embedded system on a PC. The strategy is called "dual targeting", because you develop software on one machine (e.g., Windows PC) and run it on a deeply embedded target, as well as on the PC. Dual targeting is the main strategy for avoiding the "target system bottleneck" in the agile embedded software development. - -@note -Please note that dual targeting does not mean that the embedded device has anything to do with the PC or Windows. Neither does it mean that the simulation must be cycle-exact with the embedded target CPU. Instead, dual targeting simply means that from day one, your embedded code (typically in C or C++) is designed to run on at least two platforms: the final target hardware and your PC. All you really need for this is two C/C++ compilers: one for the PC and another for the embedded device. - - -

QWin™ GUI Prototyping Toolkit

-QWin™ is a free GUI toolkit for prototyping embedded systems on Windows in the C or C++ programming language, including building realistic embedded front panels consisting of LCD displays (both graphic and segmented), LEDs, buttons, knobs, sliders, etc. The implementation is based on the **raw Win32 API** to provide simple direct mapping to C/C++ for easy integration with your embedded code. - -@image html qwin_ani.gif "Example of a QWIN Prototype with graphic LCD, buttons, LEDs, and segmented display" -
- -@remark -The problem of building GUI prototypes of embedded devices on the desktop is very common, yet it seems that most developers try to use C#, .NET, VisualBasic or other such environments to build prototypes of their embedded devices. The main shortcoming of all such solutions is that they don't provide direct binding to C/C++, which complicates the build process and the **debugging of the C/C++ code** on the host. - - - -@section qwin_usage QWin™ Usage -QWin™ is included in the QTools™ Collection in the sub-directory qtools/qwin/ and consists of just two files: qwin_gui.h containing the interface and qwin_gui.c providing the implementation. You use QWin™ by including these files in your projects. - -@note -QWin™ is also already included in the [QP/C](https://www.state-machine.com/qpc/), [QP/C++](https://www.state-machine.com/qpcpp/), and [QP-nano](https://www.state-machine.com/qpn/) frameworks (in the `\ports\win32` and `\ports\win32-qv` directories), so if you use any of these frameworks, you don't need to include QWin™ from the QTools Collection. - - - -@section qwin_features QWin™ Features -Currently QWin™ provides the following facilities: - -- Graphic displays (pixel-addressable) such as graphical LCDs, OLEDs, etc. with up to 24-bit color. -- Segmented displays such as segment LCDs, and segment LEDs with generic custom bitmaps for -the segments. -- Owner-drawn buttons with custom “depressed” and “released” bitmaps and capable of generating -separate events when depressed and when released. -Additionally, the provided code shows how to handle input sources: -- Keyboard events. -- Mouse move events and mouse-wheel events. - - - -@section qwin_doc QWin™ Documentation -The QWin™ GUI Prototyping Toolkit is described in the Application Note: Application Note: QWIN GUI Kit for Prototyping Embedded Systems on Windows. - -![AppNote: QWin GUI Prototyping Toolkit](qwin_an.png) -@caption{Application Note: QWIN GUI Kit for Prototyping Embedded Systems on Windows} - - -Regarding the size and complexity of the “QWin™ GUI Toolkit“, the implementation of the aforementioned GUI elements takes only about 250 lines of C. The example with all sources of input and a lot of comments amounts to some 300 lines of C. The toolkit has been tested with the free MinGW compiler (included in the @ref qtools_win "QTools™ Collection for Windows"), the free Visual C++ Express, and the free ResEdit resource editor. - -@nav{qview_cust,qcalc} -*/ diff --git a/doxygen/snippets/Led.h b/doxygen/snippets/Led.h deleted file mode 100644 index 246c36a..0000000 --- a/doxygen/snippets/Led.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef LED_H -#define LED_H - -enum { MAX_LED = 5 }; - -/* turns a given LED on and retruns the power drawn by it in uW */ -uint32_t Led_on(uint8_t index); - -/* turns a given LED off */ -void Led_off(uint8_t index); - -#endif /* LED_H */ \ No newline at end of file diff --git a/doxygen/snippets/LedBar.c b/doxygen/snippets/LedBar.c deleted file mode 100644 index 7dc6fe2..0000000 --- a/doxygen/snippets/LedBar.c +++ /dev/null @@ -1,49 +0,0 @@ -#include -#include "LedBar.h" -#include "Led.h" - -#include "qassert.h" /* for embedded systems-friendly assertions */ - -Q_DEFINE_THIS_MODULE("LedBar") - -/* - Example sequence diagram for the LedBar_setPercent() implementation: - - +----------+ +-----+ - | LedBar | | LED | - +----------+ +-----+ - | | - +-+ Led_on(0) | - | |------------->| - | | | - | | Led_on(1) | - | |------------->| - | | | - | | Led_on(2) | - | |------------->| - | | | - | | Led_off(3) | - | |------------->| - | | | - | | Led_off(4) | - | |------------->| - | | | - +-+ | - | | -*/ -uint32_t LedBar_setPercent(uint8_t const percent) { - uint8_t const n_on = (uint8_t)((percent * MAX_LED) / 100U); - - /*! @pre percent must not exceed 100 */ - Q_REQUIRE_ID(100, n_on <= MAX_LED); - - uint32_t p = 0U; /* power draw in [uW] */ - uint8_t i; - for (i = 0U; i < n_on; ++i) { - p += Led_on(i); - } - for (i = n_on; i < MAX_LED; ++i) { - Led_off(i); - } - return p; -} diff --git a/doxygen/snippets/ao_filter.py b/doxygen/snippets/ao_filter.py deleted file mode 100644 index fde94db..0000000 --- a/doxygen/snippets/ao_filter.py +++ /dev/null @@ -1,7 +0,0 @@ -ao_filter(6) # enables AO of priority 6 in the Target - -ao_filter(-6) # disables AO of priority 6 in the Target - -ao_filter("AO_Table") # enables "AO_Table" in the Target - -ao_filter("-AO_Table") # disables "AO_Table" in the Target diff --git a/doxygen/snippets/command.py b/doxygen/snippets/command.py deleted file mode 100644 index a3cfbf2..0000000 --- a/doxygen/snippets/command.py +++ /dev/null @@ -1,11 +0,0 @@ -test("...") -... -command(0, 78) # <=== -expect("...") -... # output generated by this command -expect("@timestamp Trg-Done QS_RX_COMMAND") - -command("MY_CMD", 123, 456, 789) # <=== -... # output generated by this command -expect("@timestamp Trg-Done QS_RX_COMMAND") - diff --git a/doxygen/snippets/continue_test.py b/doxygen/snippets/continue_test.py deleted file mode 100644 index ed2bc3c..0000000 --- a/doxygen/snippets/continue_test.py +++ /dev/null @@ -1,6 +0,0 @@ -def on_reset(): - expect_pause() - glb_filter(GRP_UA) - current_obj(OBJ_SM_AO, "AO_MyAO") - continue_test() # <==== - expect_run() diff --git a/doxygen/snippets/current_obj.py b/doxygen/snippets/current_obj.py deleted file mode 100644 index bf6e67f..0000000 --- a/doxygen/snippets/current_obj.py +++ /dev/null @@ -1,9 +0,0 @@ -current_obj(OBJ_SM, "my_state_machine") - -current_obj(OBJ_MP, "EvtPool1") - -current_obj(OBJ_AP, "my_object") - -current_obj(OBJ_SM_AO, "Philo[2]") - -current_obj(OBJ_AP, 0x20001234) diff --git a/doxygen/snippets/ensure.py b/doxygen/snippets/ensure.py deleted file mode 100644 index 56a7b51..0000000 --- a/doxygen/snippets/ensure.py +++ /dev/null @@ -1,10 +0,0 @@ -test("Ensure") -command("COMMAND_B", 123, 23456, 3456789) -expect("@timestamp COMMAND_B *") -last = last_rec().split() -p1 = int(last[2]) -p2 = int(last[4]) - -ensure(123 == p1) # <--- -ensure(3456789 == p2) # <--- - diff --git a/doxygen/snippets/expect.py b/doxygen/snippets/expect.py deleted file mode 100644 index 79ea0e0..0000000 --- a/doxygen/snippets/expect.py +++ /dev/null @@ -1,7 +0,0 @@ -expect("0000000001 USER+000 FindFunction_WhichIsBroken 0 78") - -expect("@timestamp Trg-Done QS_RX_COMMAND") - -expect(" Tick<0> Ctr=*") - -expect("@timestamp IO_CALL IO_Write %d %d" %(CommandReg, ProgramCmd)) diff --git a/doxygen/snippets/expect_pause.py b/doxygen/snippets/expect_pause.py deleted file mode 100644 index da13159..0000000 --- a/doxygen/snippets/expect_pause.py +++ /dev/null @@ -1,6 +0,0 @@ -def on_reset(): - expect_pause() # <==== - glb_filter(GRP_UA) - current_obj(OBJ_SM_AO, "AO_MyAO") - continue_test() - expect_run() diff --git a/doxygen/snippets/expect_run.py b/doxygen/snippets/expect_run.py deleted file mode 100644 index 39482cf..0000000 --- a/doxygen/snippets/expect_run.py +++ /dev/null @@ -1,6 +0,0 @@ -def on_reset(): - expect_pause() - glb_filter(GRP_UA) - current_obj(OBJ_SM_AO, "AO_MyAO") - continue_test() - expect_run() # <==== diff --git a/doxygen/snippets/glb_filter.py b/doxygen/snippets/glb_filter.py deleted file mode 100644 index e6c0eb2..0000000 --- a/doxygen/snippets/glb_filter.py +++ /dev/null @@ -1,13 +0,0 @@ -glb_filter() # clears all global filters - -glb_filter(GRP_ALL) # sets all global filters - -glb_filter(GRP_SM, GRP_AO) # sets SM-group and AO-group - -glb_filter(GRP_ALL, -GRP_SC) # sets all global filters, but clears the SC-group - -glb_filter(GRP_QF, "-QS_QF_TICK") # sets the QF-group, but clears the QS_QF_TICK filter - -glb_filter(GRP_AO, 78)` # sets the AO-group and the QS record 78 - -filters = glb_filter(GRP_AO, 78) # store the 128-bit bitmask returned diff --git a/doxygen/snippets/inc_file.py b/doxygen/snippets/inc_file.py deleted file mode 100644 index 11e3ecd..0000000 --- a/doxygen/snippets/inc_file.py +++ /dev/null @@ -1,11 +0,0 @@ -# file test_inc.pyi (include file) - -# common on_reset() callback -def on_reset(): - expect_pause() - glb_filter(GRP_ALL) - continue_test() - -def my_test_snippet(): - query_curr(OBJ_SM) - expect("@timestamp Query-SM Obj=Blinky::inst,State=Blinky::off") diff --git a/doxygen/snippets/inc_test.py b/doxygen/snippets/inc_test.py deleted file mode 100644 index 2f3cec5..0000000 --- a/doxygen/snippets/inc_test.py +++ /dev/null @@ -1,7 +0,0 @@ -# file test_blinky.py (actual test script) - -include("test_inc.pyi") #<--- include common code - -test("my test xyz") -my_test_snippet() -... diff --git a/doxygen/snippets/loc_filter.py b/doxygen/snippets/loc_filter.py deleted file mode 100644 index 90b15ab..0000000 --- a/doxygen/snippets/loc_filter.py +++ /dev/null @@ -1,14 +0,0 @@ -loc_filter(IDS_ALL) # enables all QS-IDs - -loc_filter(-IDS_ALL) # disables all QS-IDs - -loc_filter(IDS_AO) # enables all active objcts - -loc_filter(IDS_AO, -6) # enables all active objcts, - # but disables AO with priority 6 - -loc_filter(IDS_AO, IDS_EP) # enables all active objects and event pools - -loc_filter(IDS_AP) # enables all app-specific QS_IDs - -filters = loc_filter(IDS_AO, IDS_EP) # store the 128-bit bitmask returned diff --git a/doxygen/snippets/my_strlen.c b/doxygen/snippets/my_strlen.c deleted file mode 100644 index 8f5f0ac..0000000 --- a/doxygen/snippets/my_strlen.c +++ /dev/null @@ -1,9 +0,0 @@ -#include "my_strlen.h" - -uint16_t my_strlen(char const *str) { - uint16_t len = 0U; - for (; *str != '\0'; ++str) { - ++len; - } - return len; -} diff --git a/doxygen/snippets/qs_ap.c b/doxygen/snippets/qs_ap.c deleted file mode 100644 index 0f349a9..0000000 --- a/doxygen/snippets/qs_ap.c +++ /dev/null @@ -1,24 +0,0 @@ -enum UserSpyRecords { - . . . - PHILO_STAT = QS_USER, /* define a user QS record types */ - . . . -}; - -void displyPhilStat(uint8_t n, char const *stat) { - . . . - - /* application-specific record */ - QS_BEGIN_ID(PHILO_STAT, AO_Philo[n]->prio); - QS_U8(0, n); /* Philosopher number */ - QS_STR(stat); /* Philosopher status */ - QS_U8(QS_HEX_FMT, 0xABU); /* test */ - QS_U16(QS_HEX_FMT, 0xDEADU); /* test */ - QS_U32(QS_HEX_FMT, 0xDEADBEEFU); /* test */ - QS_U64(QS_HEX_FMT, 0xDEADBEEF12345678LL); /* test */ - QS_END(); -} - -QSPY ouptut produced: - -4294954639 PHILO_STAT 3 thinking 0xAB 0xDEAD 0xDEADBEEF 0xDEADBEEF12345678 - diff --git a/doxygen/snippets/qs_filter.c b/doxygen/snippets/qs_filter.c deleted file mode 100644 index 706690e..0000000 --- a/doxygen/snippets/qs_filter.c +++ /dev/null @@ -1,25 +0,0 @@ -int main(int arc, char *argv[]) { - . . . - - if (!QS_INIT(argv)) { /* Initialize QS target component */ - return -1; /* unable to initialize QSpy */ - } - - /* apply the global QS filters~~~ */ - /* NOTE: global filters start as being all OFF */ - QS_GLB_FILTER(QS_QF_RECORDS); /* turn QF-group ON */ - QS_GLB_FILTER(-QS_QF_TICK); /* turn #QS_QF_TICK OFF */ - - /* apply the local QS filters~~~ */ - /* NOTE: local filters start as being all ON */ - QS_LOC_FILTER(-QS_EP_IDS); /* turn EP (Event-Pool) group OFF */ - QS_LOC_FILTER(3); /* turn AO with prioity 3 ON */ - - /* start the active objects~~~ */ - . . . - - /* NOTE: the following will work only after AO_Table has been started */ - QS_LOC_FILTER(-AO_Table->prio); /* turn AO_Table OFF */ - - . . . -} diff --git a/doxygen/snippets/qs_objArrDic.c b/doxygen/snippets/qs_objArrDic.c deleted file mode 100644 index 1d465f4..0000000 --- a/doxygen/snippets/qs_objArrDic.c +++ /dev/null @@ -1,6 +0,0 @@ -Philo Philo_inst[N_PHILO]; -. . . -for (uint8_t n = 0U; n < N_PHILO; ++n) { - QS_OBJ_ARR_DICTIONARY(&Philo_inst[n], n); - QS_OBJ_ARR_DICTIONARY(&Philo_inst[n].timeEvt, n); -} diff --git a/doxygen/snippets/qs_objDic.c b/doxygen/snippets/qs_objDic.c deleted file mode 100644 index 32bb780..0000000 --- a/doxygen/snippets/qs_objDic.c +++ /dev/null @@ -1,9 +0,0 @@ -Table Table_inst; /* the instance of the Table Active Object */ - -/* top-most initial transition */ -static QState Table_initial(Table * const me, QEvt const * const e) { - . . . - /* provide object dictionary for Table */ - QS_OBJ_DICTIONARY(&Table_inst); /* <--- */ - . . . -} diff --git a/doxygen/snippets/qs_sigDic.c b/doxygen/snippets/qs_sigDic.c deleted file mode 100644 index 3d357a5..0000000 --- a/doxygen/snippets/qs_sigDic.c +++ /dev/null @@ -1,14 +0,0 @@ -QState Table_initial(Table * const me, QEvt const *) { - - /* signals for all state machines~~~ */ - QS_SIG_DICTIONARY(EAT_SIG, (void *)0); - . . . - - - /* signals for this specific state machine "me"~~~ */ - QS_SIG_DICTIONARY(HUNGRY_SIG, me); - QS_SIG_DICTIONARY(DONE_SIG, me); - . . . - - return Q_TRAN(&Table_serving); -} diff --git a/doxygen/snippets/qs_sigLog.txt b/doxygen/snippets/qs_sigLog.txt deleted file mode 100644 index f94a305..0000000 --- a/doxygen/snippets/qs_sigLog.txt +++ /dev/null @@ -1,78 +0,0 @@ -qspy -fqs.bin -S2 -Q2 -P4 -p4 -T4 -QSpy 1.1.03 -Thu Nov 17 09:56:10 2005 --f qs.bin --S 2 --Q 2 --P 4 --p 4 --T 4 -. . . . . . - Obj Dic: 00419048->table - EQ.INIT: Obj=00419050 Len= 5 -0000000000 AO.ADD : Active=table Prio=51 - Fun Dic: 00401CEE->Table_serving - Sig Dic: 00000004,Obj=00419048 ->HUNGRY_SIG - Sig Dic: 00000005,Obj=00419048 ->DONE_SIG - Sig Dic: 00000006,Obj=00000000 ->EAT_SIG -0000000000 AO.SUB : Active=table Sig=HUNGRY_SIG -0000000000 AO.SUB : Active=table Sig=DONE_SIG -0000000000 AO.SUB : Active=table Sig=00000007,Obj=00419048 - Q_INIT : Obj=table Source=00403CE0 Target=Table_serving -0000000000 ==>Init: Obj=table New=Table_serving -. . . . . . - -// the Philosophers become hungry... - - -0000000007 AO.FIFO: Obj=table Evt(Sig=HUNGRY_SIG, Pool=1, Ref= 1) - Queue(nUsed= 0, nMax= 0) -0000000007 AO.FIFO: Obj=table Evt(Sig=HUNGRY_SIG, Pool=1, Ref= 1) - Queue(nUsed= 0, nMax= 0) -0000000007 AO.FIFO: Obj=table Evt(Sig=HUNGRY_SIG, Pool=1, Ref= 1) - Queue(nUsed= 1, nMax= 1) -0000000007 AO.FIFO: Obj=table Evt(Sig=HUNGRY_SIG, Pool=1, Ref= 1) - Queue(nUsed= 2, nMax= 2) - Q_ENTRY: Obj=philo[2] State=Philosopher_hungry -0000000007 AO.GET : Active= table Evt(Sig=HUNGRY_SIG, Pool=1, Ref= 1) - Queue(nUsed= 2) -0000000007 AO.FIFO: Obj=table Evt(Sig=HUNGRY_SIG, Pool=1, Ref= 1) - Queue(nUsed= 2, nMax= 3) - Q_ENTRY: Obj=philo[4] State=Philosopher_hungry - Q_ENTRY: Obj=philo[1] State=Philosopher_hungry - Q_ENTRY: Obj=philo[3] State=Philosopher_hungry -0000000007 ==>Tran: Obj=philo[2] Sig=TIMEOUT_SIG Source=Philosopher_thinking - New=Philosopher_hungry -0000000007 ==>Tran: Obj=philo[4] Sig=TIMEOUT_SIG Source=Philosopher_thinking - New=Philosopher_hungry -0000000007 ==>Tran: Obj=philo[3] Sig=TIMEOUT_SIG Source=Philosopher_thinking - New=Philosopher_hungry -0000000007 ==>Tran: Obj=philo[1] Sig=TIMEOUT_SIG Source=Philosopher_thinking - New=Philosopher_hungry - Q_ENTRY: Obj=philo[0] State=Philosopher_hungry -0000000007 ==>Tran: Obj=philo[0] Sig=TIMEOUT_SIG Source=Philosopher_thinking - New=Philosopher_hungry - -// user record output -0000000007 User070: 2 hungry - -// Table grants permissions to eat -0000000007 NEW : Evt(Sig=EAT_SIG, size= 6) -0000000007 MP.GET : Obj=00418E18 nFree= 5 nMin= 5 -0000000007 AO.FIFO: Obj=philo[4] Evt(Sig=EAT_SIG, Pool=1, Ref= 0) - Queue(nUsed= 0, nMax= 0) -0000000007 AO.FIFO: Obj=philo[3] Evt(Sig=EAT_SIG, Pool=1, Ref= 0) - Queue(nUsed= 0, nMax= 0) -0000000007 AO.FIFO: Obj=philo[2] Evt(Sig=EAT_SIG, Pool=1, Ref= 0) - Queue(nUsed= 0, nMax= 0) -0000000007 AO.FIFO: Obj=philo[1] Evt(Sig=EAT_SIG, Pool=1, Ref= 0) - Queue(nUsed= 0, nMax= 0) -0000000007 AO.FIFO: Obj=philo[0] Evt(Sig=EAT_SIG, Pool=1, Ref= 0) - Queue(nUsed= 0, nMax= 0) -0000000007 PUBLISH: Evt(Sig=EAT_SIG, Pool=1, Ref= 5) nSubsr= 5 -0000000007 AO.GETL: Active= philo[4] Evt(Sig=EAT_SIG, Pool=1, Ref= 5) -0000000007 AO.GETL: Active= philo[2] Evt(Sig=EAT_SIG, Pool=1, Ref= 5) -0000000007 AO.GETL: Active= philo[3] Evt(Sig=EAT_SIG, Pool=1, Ref= 5) -0000000007 AO.GETL: Active= philo[1] Evt(Sig=EAT_SIG, Pool=1, Ref= 5) -0000000007 AO.GETL: Active= philo[0] Evt(Sig=EAT_SIG, Pool=1, Ref= 5) -. . . . . . diff --git a/doxygen/snippets/qunpack.py b/doxygen/snippets/qunpack.py deleted file mode 100644 index a40427a..0000000 --- a/doxygen/snippets/qunpack.py +++ /dev/null @@ -1,6 +0,0 @@ -data = qunpack("xxTxBxZ", packet) - -# returns: -# data[0], corresponds to 'T' format (QP/Spy timestamp) -# data[1], corresponds to 'B' format (standard struct.unpack()) -# data[2], corresponds to 'Z' format (QP/Spy zero-terminated string) diff --git a/doxygen/snippets/tick.py b/doxygen/snippets/tick.py deleted file mode 100644 index c042edb..0000000 --- a/doxygen/snippets/tick.py +++ /dev/null @@ -1,7 +0,0 @@ -# tests... -test("tick") -glb_filter(GRP_ALL) -current_obj(OBJ_TE, "l_philo<2>.timeEvt") -tick() # <==== -expect("...") -... diff --git a/qfsgen/posix/Makefile b/qfsgen/posix/Makefile index 477b443..3a594eb 100644 --- a/qfsgen/posix/Makefile +++ b/qfsgen/posix/Makefile @@ -95,7 +95,7 @@ ifeq (dbg, $(CONF)) # Debug configuration .................................... BIN_DIR := dbg -CFLAGS = -c -g -std=c11 -ffunction-sections -fdata-sections \ +CFLAGS = -c -g -std=gnu11 -ffunction-sections -fdata-sections \ -O -Wall -Wextra -Wpedantic $(INCLUDES) $(DEFINES) CPPFLAGS = -c -g -ffunction-sections -fdata-sections \ @@ -105,7 +105,7 @@ else # default Release configuration ........................................ BIN_DIR := rel -CFLAGS = -c -std=c11 -ffunction-sections -fdata-sections \ +CFLAGS = -c -std=gnu11 -ffunction-sections -fdata-sections \ -O3 -Wall -Wextra -Wpedantic $(INCLUDES) $(DEFINES) -DNDEBUG CPPFLAGS = -c -ffunction-sections -fdata-sections \ diff --git a/qspy/include/pal.h b/qspy/include/pal.h index ea1cef1..7595cf9 100644 --- a/qspy/include/pal.h +++ b/qspy/include/pal.h @@ -23,8 +23,8 @@ * ============================================================================*/ /*! -* @date Last updated on: 2022-01-12 -* @version Last updated for version: 7.0.0 +* @date Last updated on: 2023-08-22 +* @version Last updated for version: 7.3.0 * * @file * @brief Platform Abstraction Layer (PAL) @@ -91,9 +91,9 @@ void PAL_updateReadySet(int targetConn); #define Q_ASSERT(test_) ((void)0) #else /* assertion checking enabled */ #define Q_ASSERT(test_) ((test_) \ - ? (void)0 : Q_onAssert(__FILE__, __LINE__)) + ? (void)0 : Q_onError(__FILE__, __LINE__)) -void Q_onAssert(char const* const module, int location); +void Q_onError(char const * const module, int const id); #endif #endif /* PAL_H_ */ diff --git a/qspy/include/qpc_qs.h b/qspy/include/qpc_qs.h index f3361b9..d492185 100644 --- a/qspy/include/qpc_qs.h +++ b/qspy/include/qpc_qs.h @@ -1,1704 +1,975 @@ -/*$file${include::qs.h} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/* -* Model: qpc.qm -* File: ${include::qs.h} -* -* This code has been generated by QM 5.2.4 . -* DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. -* -* This code is covered by the following QP license: -* License # : LicenseRef-QL-dual -* Issued to : Any user of the QP/C real-time embedded framework -* Framework(s) : qpc -* Support ends : 2023-12-31 -* License scope: -* -* Copyright (C) 2005 Quantum Leaps, LLC . -* -* SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial -* -* This software is dual-licensed under the terms of the open source GNU -* General Public License version 3 (or any later version), or alternatively, -* under the terms of one of the closed source Quantum Leaps commercial -* licenses. -* -* The terms of the open source GNU General Public License version 3 -* can be found at: -* -* The terms of the closed source Quantum Leaps commercial licenses -* can be found at: -* -* Redistributions in source code must retain this top-level comment block. -* Plagiarizing this software to sidestep the license obligations is illegal. -* -* Contact information: -* -* -*/ -/*$endhead${include::qs.h} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -/*! @file -* @brief QS/C platform-independent public interface. -*/ -#ifndef QP_INC_QS_H_ -#define QP_INC_QS_H_ +//$file${include::qs.h} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +// +// Model: qpc.qm +// File: ${include::qs.h} +// +// This code has been generated by QM 5.3.0 . +// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. +// +// This code is covered by the following QP license: +// License # : LicenseRef-QL-dual +// Issued to : Any user of the QP/C real-time embedded framework +// Framework(s) : qpc +// Support ends : 2024-12-31 +// License scope: +// +// Copyright (C) 2005 Quantum Leaps, LLC . +// +// Q u a n t u m L e a P s +// ------------------------ +// Modern Embedded Software +// +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial +// +// This software is dual-licensed under the terms of the open source GNU +// General Public License version 3 (or any later version), or alternatively, +// under the terms of one of the closed source Quantum Leaps commercial +// licenses. +// +// The terms of the open source GNU General Public License version 3 +// can be found at: +// +// The terms of the closed source Quantum Leaps commercial licenses +// can be found at: +// +// Redistributions in source code must retain this top-level comment block. +// Plagiarizing this software to sidestep the license obligations is illegal. +// +// Contact information: +// +// +// +//$endhead${include::qs.h} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#ifndef QS_H_ +#define QS_H_ #ifndef Q_SPY - #error "Q_SPY must be defined to include qs.h" +#error "Q_SPY must be defined to include qs.h" #endif -/*==========================================================================*/ -/*$declare${QS-config} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ +//============================================================================ +//! @cond INTERNAL -/*${QS-config::QS_CTR_SIZE} ................................................*/ #ifndef QS_CTR_SIZE -/*! The size [bytes] of the internal QS buffer-counters. Valid values: 2U or 4U; -* default 2U. -* -* @details -* This macro can be defined in the QS port file (qs_port.h) to -* configure the ::QSCtr type. Here the macro is not defined so the -* default of 2 byte is chosen. -*/ #define QS_CTR_SIZE 2U -#endif /* ndef QS_CTR_SIZE */ - -/*${QS-config::QS_CTR_SIZE defined incorrectly,~} ..........................*/ -#if (QS_CTR_SIZE != 2U) && (QS_CTR_SIZE != 4U) -#error QS_CTR_SIZE defined incorrectly, expected 2U or 4U; -#endif /* (QS_CTR_SIZE != 2U) && (QS_CTR_SIZE != 4U) */ +#endif -/*${QS-config::QS_TIME_SIZE} ...............................................*/ #ifndef QS_TIME_SIZE -/*! The size [bytes] of the QS time stamp. Valid values: 1U, 2U, or 4U; -* default 4U. -* -* @details -* This macro can be defined in the QS port file (qs_port.h) to -* configure the ::QSTimeCtr type. Here the macro is not defined so the -* default of 4 byte is chosen. -*/ #define QS_TIME_SIZE 4U -#endif /* ndef QS_TIME_SIZE */ - -/*${QS-config::QS_TIME_SIZE defined incorrectly~} ..........................*/ -#if (QS_TIME_SIZE != 1U) && (QS_TIME_SIZE != 2U) && (QS_TIME_SIZE != 4U) -#error QS_TIME_SIZE defined incorrectly, expected 1U, 2U, or 4U; -#endif /* (QS_TIME_SIZE != 1U) && (QS_TIME_SIZE != 2U) && (QS_TIME_SIZE != 4U) */ -/*$enddecl${QS-config} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ - -/*==========================================================================*/ -/*$declare${QS} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ - -/*${QS::QSCtr} .............................................................*/ -#if (QS_CTR_SIZE == 2U) -/*! QS ring buffer counter and offset type */ -typedef uint_fast16_t QSCtr; -#endif /* (QS_CTR_SIZE == 2U) */ - -/*${QS::QSCtr} .............................................................*/ -#if (QS_CTR_SIZE == 4U) -typedef uint_fast32_t QSCtr; -#endif /* (QS_CTR_SIZE == 4U) */ - -/*${QS::QSTimeCtr} .........................................................*/ -#if (QS_TIME_SIZE == 4U) -/*! QS time stamp type, which determines the dynamic range of QS time stamps */ -typedef uint32_t QSTimeCtr; -#endif /* (QS_TIME_SIZE == 4U) */ - -/*${QS::QSTimeCtr} .........................................................*/ -#if (QS_TIME_SIZE == 2U) -typedef uint16_t QSTimeCtr; -#endif /* (QS_TIME_SIZE == 2U) */ +#endif -/*${QS::QSTimeCtr} .........................................................*/ -#if (QS_TIME_SIZE == 1U) -typedef uint8_t QSTimeCtr; -#endif /* (QS_TIME_SIZE == 1U) */ +//! @endcond +//============================================================================ -/*${QS::QSFun} .............................................................*/ -#if (QS_FUN_PTR_SIZE == 4U) -/*! QS function pointer type (for serializing function pointers) */ -typedef uint32_t QSFun; -#endif /* (QS_FUN_PTR_SIZE == 4U) */ +//$declare${QS::types} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -/*${QS::QSFun} .............................................................*/ -#if (QS_FUN_PTR_SIZE == 8U) -typedef uint64_t QSFun; -#endif /* (QS_FUN_PTR_SIZE == 8U) */ +//${QS::types::QS} ........................................................... +//! @class QS +typedef struct QS { + //! @cond INTERNAL + uint8_t dummy; + //! @endcond +} QS; -/*${QS::QSFun} .............................................................*/ -#if (QS_FUN_PTR_SIZE == 2U) -typedef uint16_t QSFun; -#endif /* (QS_FUN_PTR_SIZE == 2U) */ - -/*${QS::QSFun} .............................................................*/ -#if (QS_FUN_PTR_SIZE == 1U) -typedef uint8_t QSFun; -#endif /* (QS_FUN_PTR_SIZE == 1U) */ - -/*${QS::QSpyPre} ...........................................................*/ -/*! QS pre-defined record types (TX channel) -* @static @public @memberof QS_tx -* -* @details -* This enumeration specifies the record types used in the QP components. -* You can specify your own record types starting from ::QS_USER offset. -* Currently, the maximum of all records cannot exceed 125. -* -* @note -* The QS records labeled as "not maskable" are always enabled and cannot -* be turend off with the QS_GLB_FILTER() macro. Other QS trace records -* can be disabled by means of the "global filters" -* -* @sa QS_GLB_FILTER() macro -*/ +//${QS::types::QSpyPre} ...................................................... +//! @static @public @memberof QS +//! pre-defined QS record IDs enum QSpyPre { - /* [0] QS session (not maskable) */ - QS_EMPTY, /*!< QS record for cleanly starting a session */ - - /* [1] SM records */ - QS_QEP_STATE_ENTRY, /*!< a state was entered */ - QS_QEP_STATE_EXIT, /*!< a state was exited */ - QS_QEP_STATE_INIT, /*!< an initial transition was taken in a state */ - QS_QEP_INIT_TRAN, /*!< the top-most initial transition was taken */ - QS_QEP_INTERN_TRAN, /*!< an internal transition was taken */ - QS_QEP_TRAN, /*!< a regular transition was taken */ - QS_QEP_IGNORED, /*!< an event was ignored (silently discarded) */ - QS_QEP_DISPATCH, /*!< an event was dispatched (begin of RTC step) */ - QS_QEP_UNHANDLED, /*!< an event was un-handled due to a guard */ - - /* [10] Active Object (AO) records */ - QS_QF_ACTIVE_DEFER, /*!< AO deferred an event */ - QS_QF_ACTIVE_RECALL, /*!< AO recalled an event */ - QS_QF_ACTIVE_SUBSCRIBE, /*!< an AO subscribed to an event */ - QS_QF_ACTIVE_UNSUBSCRIBE, /*!< an AO unsubscribed to an event */ - QS_QF_ACTIVE_POST, /*!< an event was posted (FIFO) directly to AO */ - QS_QF_ACTIVE_POST_LIFO, /*!< an event was posted (LIFO) directly to AO */ - QS_QF_ACTIVE_GET, /*!< AO got an event and its queue is not empty */ - QS_QF_ACTIVE_GET_LAST,/*!< AO got an event and its queue is empty */ - QS_QF_ACTIVE_RECALL_ATTEMPT, /*!< AO attempted to recall an event */ - - /* [19] Event Queue (EQ) records */ - QS_QF_EQUEUE_POST, /*!< an event was posted (FIFO) to a raw queue */ - QS_QF_EQUEUE_POST_LIFO, /*!< an event was posted (LIFO) to a raw queue */ - QS_QF_EQUEUE_GET, /*!< get an event and queue still not empty */ - QS_QF_EQUEUE_GET_LAST,/*!< get the last event from the queue */ - - /* [23] Framework (QF) records */ - QS_QF_NEW_ATTEMPT, /*!< an attempt to allocate an event failed */ - - /* [24] Memory Pool (MP) records */ - QS_QF_MPOOL_GET, /*!< a memory block was removed from memory pool */ - QS_QF_MPOOL_PUT, /*!< a memory block was returned to memory pool */ - - /* [26] Additional Framework (QF) records */ - QS_QF_PUBLISH, /*!< an event was published to active objects */ - QS_QF_NEW_REF, /*!< new event reference was created */ - QS_QF_NEW, /*!< new event was created */ - QS_QF_GC_ATTEMPT, /*!< garbage collection attempt */ - QS_QF_GC, /*!< garbage collection */ - QS_QF_TICK, /*!< QTimeEvt_tick_() was called */ - - /* [32] Time Event (TE) records */ - QS_QF_TIMEEVT_ARM, /*!< a time event was armed */ - QS_QF_TIMEEVT_AUTO_DISARM, /*!< a time event expired and was disarmed */ - QS_QF_TIMEEVT_DISARM_ATTEMPT,/*!< attempt to disarm a disarmed QTimeEvt */ - QS_QF_TIMEEVT_DISARM, /*!< true disarming of an armed time event */ - QS_QF_TIMEEVT_REARM, /*!< rearming of a time event */ - QS_QF_TIMEEVT_POST, /*!< a time event posted itself directly to an AO */ - - /* [38] Additional Framework (QF) records */ - QS_QF_DELETE_REF, /*!< an event reference is about to be deleted */ - QS_QF_CRIT_ENTRY, /*!< critical section was entered */ - QS_QF_CRIT_EXIT, /*!< critical section was exited */ - QS_QF_ISR_ENTRY, /*!< an ISR was entered */ - QS_QF_ISR_EXIT, /*!< an ISR was exited */ - QS_QF_INT_DISABLE, /*!< interrupts were disabled */ - QS_QF_INT_ENABLE, /*!< interrupts were enabled */ - - /* [45] Additional Active Object (AO) records */ - QS_QF_ACTIVE_POST_ATTEMPT,/*!< attempt to post an evt to AO failed */ - - /* [46] Additional Event Queue (EQ) records */ - QS_QF_EQUEUE_POST_ATTEMPT,/*!< attempt to post evt to QEQueue failed */ - - /* [47] Additional Memory Pool (MP) records */ - QS_QF_MPOOL_GET_ATTEMPT, /*!< attempt to get a memory block failed */ - - /* [48] Scheduler (SC) records */ - QS_SCHED_PREEMPT, /*!< scheduler asynchronously preempted a task */ - QS_SCHED_RESTORE, /*!< scheduler restored preempted task */ - QS_SCHED_LOCK, /*!< scheduler was locked */ - QS_SCHED_UNLOCK, /*!< scheduler was unlocked */ - QS_SCHED_NEXT, /*!< scheduler started new task */ - QS_SCHED_IDLE, /*!< scheduler restored the idle task */ - - /* [54] Miscellaneous QS records (not maskable) */ - QS_ENUM_DICT, /*!< enumeration dictionary entry */ - - /* [55] Additional QEP records */ - QS_QEP_TRAN_HIST, /*!< a tran to history was taken */ - QS_QEP_TRAN_EP, /*!< a tran to entry point into a submachine */ - QS_QEP_TRAN_XP, /*!< a tran to exit point out of a submachine */ - - /* [58] Miscellaneous QS records (not maskable) */ - QS_TEST_PAUSED, /*!< test has been paused */ - QS_TEST_PROBE_GET, /*!< reports that Test-Probe has been used */ - QS_SIG_DICT, /*!< signal dictionary entry */ - QS_OBJ_DICT, /*!< object dictionary entry */ - QS_FUN_DICT, /*!< function dictionary entry */ - QS_USR_DICT, /*!< user QS record dictionary entry */ - QS_TARGET_INFO, /*!< reports the Target information */ - QS_TARGET_DONE, /*!< reports completion of a user callback */ - QS_RX_STATUS, /*!< reports QS data receive status */ - QS_QUERY_DATA, /*!< reports the data from "current object" query */ - QS_PEEK_DATA, /*!< reports the data from the PEEK query */ - QS_ASSERT_FAIL, /*!< assertion failed in the code */ - QS_QF_RUN, /*!< QF_run() was entered */ - - /* [71] Semaphore (SEM) records */ - QS_SEM_TAKE, /*!< a semaphore was taken by a thread */ - QS_SEM_BLOCK, /*!< a semaphore blocked a thread */ - QS_SEM_SIGNAL, /*!< a semaphore was signaled */ - QS_SEM_BLOCK_ATTEMPT, /*!< a semaphore blocked was attempted */ - - /* [75] Mutex (MTX) records */ - QS_MTX_LOCK, /*!< a mutex was locked */ - QS_MTX_BLOCK, /*!< a mutex blocked a thread */ - QS_MTX_UNLOCK, /*!< a mutex was unlocked */ - QS_MTX_LOCK_ATTEMPT, /*!< a mutex lock was attempted */ - QS_MTX_BLOCK_ATTEMPT, /*!< a mutex blocking was attempted */ - QS_MTX_UNLOCK_ATTEMPT,/*!< a mutex unlock was attempted */ - - /* [81] */ - QS_PRE_MAX /*!< the number of predefined signals */ + // [0] QS session (not maskable) + QS_EMPTY, //!< QS record for cleanly starting a session + + // [1] SM records + QS_QEP_STATE_ENTRY, //!< a state was entered + QS_QEP_STATE_EXIT, //!< a state was exited + QS_QEP_STATE_INIT, //!< an initial transition was taken in a state + QS_QEP_INIT_TRAN, //!< the top-most initial transition was taken + QS_QEP_INTERN_TRAN, //!< an internal transition was taken + QS_QEP_TRAN, //!< a regular transition was taken + QS_QEP_IGNORED, //!< an event was ignored (silently discarded) + QS_QEP_DISPATCH, //!< an event was dispatched (begin of RTC step) + QS_QEP_UNHANDLED, //!< an event was un-handled due to a guard + + // [10] Active Object (AO) records + QS_QF_ACTIVE_DEFER, //!< AO deferred an event + QS_QF_ACTIVE_RECALL, //!< AO recalled an event + QS_QF_ACTIVE_SUBSCRIBE, //!< an AO subscribed to an event + QS_QF_ACTIVE_UNSUBSCRIBE, //!< an AO unsubscribed to an event + QS_QF_ACTIVE_POST, //!< an event was posted (FIFO) directly to AO + QS_QF_ACTIVE_POST_LIFO, //!< an event was posted (LIFO) directly to AO + QS_QF_ACTIVE_GET, //!< AO got an event and its queue is not empty + QS_QF_ACTIVE_GET_LAST,//!< AO got an event and its queue is empty + QS_QF_ACTIVE_RECALL_ATTEMPT, //!< AO attempted to recall an event + + // [19] Event Queue (EQ) records + QS_QF_EQUEUE_POST, //!< an event was posted (FIFO) to a raw queue + QS_QF_EQUEUE_POST_LIFO, //!< an event was posted (LIFO) to a raw queue + QS_QF_EQUEUE_GET, //!< get an event and queue still not empty + QS_QF_EQUEUE_GET_LAST,//!< get the last event from the queue + + // [23] Framework (QF) records + QS_QF_NEW_ATTEMPT, //!< an attempt to allocate an event failed + + // [24] Memory Pool (MP) records + QS_QF_MPOOL_GET, //!< a memory block was removed from memory pool + QS_QF_MPOOL_PUT, //!< a memory block was returned to memory pool + + // [26] Additional Framework (QF) records + QS_QF_PUBLISH, //!< an event was published to active objects + QS_QF_NEW_REF, //!< new event reference was created + QS_QF_NEW, //!< new event was created + QS_QF_GC_ATTEMPT, //!< garbage collection attempt + QS_QF_GC, //!< garbage collection + QS_QF_TICK, //!< QTimeEvt tick was called + + // [32] Time Event (TE) records + QS_QF_TIMEEVT_ARM, //!< a time event was armed + QS_QF_TIMEEVT_AUTO_DISARM, //!< a time event expired and was disarmed + QS_QF_TIMEEVT_DISARM_ATTEMPT,//!< attempt to disarm a disarmed QTimeEvt + QS_QF_TIMEEVT_DISARM, //!< true disarming of an armed time event + QS_QF_TIMEEVT_REARM, //!< rearming of a time event + QS_QF_TIMEEVT_POST, //!< a time event posted itself directly to an AO + + // [38] Additional Framework (QF) records + QS_QF_DELETE_REF, //!< an event reference is about to be deleted + QS_QF_CRIT_ENTRY, //!< critical section was entered + QS_QF_CRIT_EXIT, //!< critical section was exited + QS_QF_ISR_ENTRY, //!< an ISR was entered + QS_QF_ISR_EXIT, //!< an ISR was exited + QS_QF_INT_DISABLE, //!< interrupts were disabled + QS_QF_INT_ENABLE, //!< interrupts were enabled + + // [45] Additional Active Object (AO) records + QS_QF_ACTIVE_POST_ATTEMPT,//!< attempt to post an evt to AO failed + + // [46] Additional Event Queue (EQ) records + QS_QF_EQUEUE_POST_ATTEMPT,//!< attempt to post evt to QEQueue failed + + // [47] Additional Memory Pool (MP) records + QS_QF_MPOOL_GET_ATTEMPT, //!< attempt to get a memory block failed + + // [48] Scheduler (SC) records + QS_SCHED_PREEMPT, //!< scheduler asynchronously preempted a task + QS_SCHED_RESTORE, //!< scheduler restored preempted task + QS_SCHED_LOCK, //!< scheduler was locked + QS_SCHED_UNLOCK, //!< scheduler was unlocked + QS_SCHED_NEXT, //!< scheduler started next task + QS_SCHED_IDLE, //!< scheduler restored the idle task + + // [54] Miscellaneous QS records (not maskable) + QS_ENUM_DICT, //!< enumeration dictionary entry + + // [55] Additional QEP records + QS_QEP_TRAN_HIST, //!< a tran to history was taken + QS_QEP_TRAN_EP, //!< a tran to entry point into a submachine + QS_QEP_TRAN_XP, //!< a tran to exit point out of a submachine + + // [58] Miscellaneous QS records (not maskable) + QS_TEST_PAUSED, //!< test has been paused + QS_TEST_PROBE_GET, //!< reports that Test-Probe has been used + QS_SIG_DICT, //!< signal dictionary entry + QS_OBJ_DICT, //!< object dictionary entry + QS_FUN_DICT, //!< function dictionary entry + QS_USR_DICT, //!< user QS record dictionary entry + QS_TARGET_INFO, //!< reports the Target information + QS_TARGET_DONE, //!< reports completion of a user callback + QS_RX_STATUS, //!< reports QS data receive status + QS_QUERY_DATA, //!< reports the data from "current object" query + QS_PEEK_DATA, //!< reports the data from the PEEK query + QS_ASSERT_FAIL, //!< assertion failed in the code + QS_QF_RUN, //!< QF_run() was entered + + // [71] Semaphore (SEM) records + QS_SEM_TAKE, //!< a semaphore was taken by a thread + QS_SEM_BLOCK, //!< a semaphore blocked a thread + QS_SEM_SIGNAL, //!< a semaphore was signaled + QS_SEM_BLOCK_ATTEMPT, //!< a semaphore blocked was attempted + + // [75] Mutex (MTX) records + QS_MTX_LOCK, //!< a mutex was locked + QS_MTX_BLOCK, //!< a mutex blocked a thread + QS_MTX_UNLOCK, //!< a mutex was unlocked + QS_MTX_LOCK_ATTEMPT, //!< a mutex lock was attempted + QS_MTX_BLOCK_ATTEMPT, //!< a mutex blocking was attempted + QS_MTX_UNLOCK_ATTEMPT,//!< a mutex unlock was attempted + + // [81] + QS_PRE_MAX //!< the # predefined signals }; -/*${QS::QSpyGroups} ........................................................*/ -/*! QS record groups for QS_GLB_FILTER() -* @static @public @memberof QS_tx -*/ +//${QS::types::QSpyGroups} ................................................... +//! @static @public @memberof QS +//! QS-TX record groups for QS_GLB_FILTER() enum QSpyGroups { - QS_ALL_RECORDS = 0xF0,/*!< all maskable QS records */ - QS_SM_RECORDS, /*!< State Machine QS records */ - QS_AO_RECORDS, /*!< Active Object QS records */ - QS_EQ_RECORDS, /*!< Event Queues QS records */ - QS_MP_RECORDS, /*!< Memory Pools QS records */ - QS_TE_RECORDS, /*!< Time Events QS records */ - QS_QF_RECORDS, /*!< QF QS records */ - QS_SC_RECORDS, /*!< Scheduler QS records */ - QS_SEM_RECORDS, /*!< Semaphore QS records */ - QS_MTX_RECORDS, /*!< Mutex QS records */ - QS_U0_RECORDS, /*!< User Group 100-104 records */ - QS_U1_RECORDS, /*!< User Group 105-109 records */ - QS_U2_RECORDS, /*!< User Group 110-114 records */ - QS_U3_RECORDS, /*!< User Group 115-119 records */ - QS_U4_RECORDS, /*!< User Group 120-124 records */ - QS_UA_RECORDS /*!< All User records */ + QS_ALL_RECORDS = 0xF0,//!< all maskable QS records + QS_SM_RECORDS, //!< State Machine QS records + QS_AO_RECORDS, //!< Active Object QS records + QS_EQ_RECORDS, //!< Event Queues QS records + QS_MP_RECORDS, //!< Memory Pools QS records + QS_TE_RECORDS, //!< Time Events QS records + QS_QF_RECORDS, //!< QF QS records + QS_SC_RECORDS, //!< Scheduler QS records + QS_SEM_RECORDS, //!< Semaphore QS records + QS_MTX_RECORDS, //!< Mutex QS records + QS_U0_RECORDS, //!< User Group 100-104 records + QS_U1_RECORDS, //!< User Group 105-109 records + QS_U2_RECORDS, //!< User Group 110-114 records + QS_U3_RECORDS, //!< User Group 115-119 records + QS_U4_RECORDS, //!< User Group 120-124 records + QS_UA_RECORDS //!< All User records }; -/*${QS::QSpyUserOffsets} ...................................................*/ -/*! QS user record group offsets for QS_GLB_FILTER() -* @static @public @memberof QS_tx -*/ +//${QS::types::QSpyUserOffsets} .............................................. +//! @static @public @memberof QS +//! QS user record group offsets for QS_GLB_FILTER() enum QSpyUserOffsets { - QS_USER = 100, /*!< the first record available to QS users */ - QS_USER0 = (enum_t)QS_USER, /*!< offset for User Group 0 */ - QS_USER1 = (enum_t)QS_USER0 + 5, /*!< offset for User Group 1 */ - QS_USER2 = (enum_t)QS_USER1 + 5, /*!< offset for User Group 2 */ - QS_USER3 = (enum_t)QS_USER2 + 5, /*!< offset for User Group 3 */ - QS_USER4 = (enum_t)QS_USER3 + 5 /*!< offset for User Group 4 */ + QS_USER = 100, //!< the first record available to QS users + QS_USER0 = QS_USER, //!< offset for User Group 0 + QS_USER1 = (enum_t)QS_USER0 + 5, //!< offset for User Group 1 + QS_USER2 = (enum_t)QS_USER1 + 5, //!< offset for User Group 2 + QS_USER3 = (enum_t)QS_USER2 + 5, //!< offset for User Group 3 + QS_USER4 = (enum_t)QS_USER3 + 5 //!< offset for User Group 4 }; -/*${QS::QSpyIdOffsets} .....................................................*/ -/*! QS ID offsets for QS_LOC_FILTER() -* @static @public @memberof QS_tx -*/ +//${QS::types::QSpyIdOffsets} ................................................ +//! @static @public @memberof QS +//! QS ID offsets for QS_LOC_FILTER() enum QSpyIdOffsets { - QS_AO_ID = 0, /*!< offset for AO priorities */ - QS_EP_ID = 64, /*!< offset for event-pool IDs */ - QS_EQ_ID = 80, /*!< offset for event-queue IDs */ - QS_AP_ID = 96 /*!< offset for Application-specific IDs */ + QS_AO_ID = 0, //!< offset for AO priorities + QS_EP_ID = 64, //!< offset for event-pool IDs + QS_EQ_ID = 80, //!< offset for event-queue IDs + QS_AP_ID = 96 //!< offset for Application-specific IDs }; -/*${QS::QSpyIdGroups} ......................................................*/ -/*! QS ID groups for QS_LOC_FILTER() -* @static @public @memberof QS_tx -*/ +//${QS::types::QSpyIdGroups} ................................................. +//! @static @public @memberof QS +//! QS ID groups for QS_LOC_FILTER() enum QSpyIdGroups { - QS_ALL_IDS = 0xF0, /*!< all QS IDs */ - QS_AO_IDS = (0x80 + (enum_t)QS_AO_ID), /*!< AO IDs (priorities) */ - QS_EP_IDS = (0x80 + (enum_t)QS_EP_ID), /*!< event-pool IDs */ - QS_EQ_IDS = (0x80 + (enum_t)QS_EQ_ID), /*!< event-queue IDs */ - QS_AP_IDS = (0x80 + (enum_t)QS_AP_ID) /*!< Application-specific IDs */ + QS_ALL_IDS = 0xF0, //!< all QS IDs + QS_AO_IDS = 0x80 + (enum_t)QS_AO_ID, //!< AO IDs (priorities) + QS_EP_IDS = 0x80 + (enum_t)QS_EP_ID, //!< event-pool IDs + QS_EQ_IDS = 0x80 + (enum_t)QS_EQ_ID, //!< event-queue IDs + QS_AP_IDS = 0x80 + (enum_t)QS_AP_ID //!< Application-specific IDs }; -/*${QS::QSpyFunPtr} ........................................................*/ -/*! function pointer type for QS_fun_dict_pre_() -* @static @private @memberof QS_tx -*/ -typedef void (* QSpyFunPtr )(void); - -/*${QS::QSpyId} ............................................................*/ -/*! @brief QS ID type for applying local filtering -* @static @public @memberof QS_tx -*/ +//${QS::types::QSpyId} ....................................................... +//! @struct QSpyId typedef struct { uint8_t prio; } QSpyId; -/*${QS::QS-tx::tx} .........................................................*/ -/*! @brief Software tracing, output QS-TX -* -* @details -* This class groups together QS services. -*/ -typedef struct { -/* public: */ - - /*! global on/off QS filter */ - uint8_t glbFilter[16]; - - /*! local on/off QS filter */ - uint8_t locFilter[16]; - - /*! @deprecated old local QS filter */ - void const * locFilter_AP; - - /*! pointer to the start of the QS-TX ring buffer */ - uint8_t * buf; - - /*! offset of the end of the ring buffer */ - QSCtr end; - - /*! offset to where next byte will be inserted */ - QSCtr volatile head; - - /*! offset of where next record will be extracted */ - QSCtr volatile tail; - - /*! number of bytes currently in the ring buffer */ - QSCtr volatile used; - - /*! sequence number of the last inserted QS record */ - uint8_t volatile seq; - - /*! checksum of the currently inserted record */ - uint8_t volatile chksum; - - /*! critical section nesting level */ - uint8_t volatile critNest; - - /* flags for internal use */ - uint8_t flags; -} QS_tx; - -/*${QS::QS-tx::preType} ....................................................*/ -/*! Enumerates data elements for app-specific trace records */ -enum QS_preType { - QS_I8_ENUM_T, /*!< signed 8-bit integer or enum format */ - QS_U8_T, /*!< unsigned 8-bit integer format */ - QS_I16_T, /*!< signed 16-bit integer format */ - QS_U16_T, /*!< unsigned 16-bit integer format */ - QS_I32_T, /*!< signed 32-bit integer format */ - QS_U32_T, /*!< unsigned 32-bit integer format */ - QS_F32_T, /*!< 32-bit floating point format */ - QS_F64_T, /*!< 64-bit floating point format */ - QS_STR_T, /*!< zero-terminated ASCII string format */ - QS_MEM_T, /*!< up to 255-bytes memory block format */ - QS_SIG_T, /*!< event signal format */ - QS_OBJ_T, /*!< object pointer format */ - QS_FUN_T, /*!< function pointer format */ - QS_I64_T, /*!< signed 64-bit integer format */ - QS_U64_T /*!< unsigned 64-bit integer format */ -}; - -/*${QS::QS-tx::priv_} ......................................................*/ -/*! the only instance of the QS-TX object (Singleton) */ -extern QS_tx QS_priv_; - -/*${QS::QS-tx::initBuf} ....................................................*/ -/*! Initialize the QS-TX data buffer -* @static @public @memberof QS_tx -* -* @details -* This function should be called from QS_onStartup() to provide -* QS with the data buffer. The first argument `sto` is the address -* of the memory block, and the second argument `stoSize` is the size -* of this block [in bytes]. Currently the size of the QS buffer cannot -* exceed 64KB. -* -* @param[in] sto pointer to the storage for the transmit buffer -* @param[in] stoSize size in [bytes] of the storage buffer -* -* @remark -* QS can work with quite small data buffers, but you will start losing -* data if the buffer is too small for the bursts of tracing activity. -* The right size of the buffer depends on the data production rate and -* the data output rate. QS offers flexible filtering to reduce the data -* production rate. -* -* @note -* If the data output rate cannot keep up with the production rate, -* QS will start overwriting the older data with newer data. This is -* consistent with the "last-is-best" QS policy. The record sequence -* counters and check sums on each record allow the QSPY host utility -* to easily detect any data loss. -*/ -void QS_initBuf( - uint8_t * const sto, - uint_fast32_t const stoSize); - -/*${QS::QS-tx::getByte} ....................................................*/ -/*! Byte-oriented interface to the QS-TX data buffer -* @static @public @memberof QS_tx -* -* @details -* This function delivers one byte at a time from the QS data buffer. -* -* @returns -* the byte in the least-significant 8-bits of the 16-bit return -* value if the byte is available. If no more data is available at the -* time, the function returns ::QS_EOD (End-Of-Data). -* -* @note -* QS_getByte() is NOT protected with a critical section. -*/ -uint16_t QS_getByte(void); - -/*${QS::QS-tx::getBlock} ...................................................*/ -/*! Block-oriented interface to the QS-TX data buffer -* @static @public @memberof QS_tx -* -* @details -* This function delivers a contiguous block of data from the QS data -* buffer. The function returns the pointer to the beginning of the -* block, and writes the number of bytes in the block to the location -* pointed to by `pNbytes`. The argument `pNbytes` is also used as -* input to provide the maximum size of the data block that the caller -* can accept. -* -* @param[in,out] pNbytes pointer to the number of bytes to send. -* On input, `pNbytes` specifies the maximum number -* of bytes that the function can provide. -* On output, `pNbytes` contains the actual number -* of bytes available. -* @returns -* if data is available, the function returns pointer to the -* contiguous block of data and sets the value pointed to by `pNbytes` -* to the # available bytes. If data is available at the time the -* function is called, the function returns NULL pointer and sets the -* value pointed to by `pNbytes` to zero. -* -* @note -* Only the NULL return from QS_getBlock() indicates that the QS -* buffer is empty at the time of the call. The non-NULL return often -* means that the block is at the end of the buffer and you need to call -* QS_getBlock() again to obtain the rest of the data that -* "wrapped around" to the beginning of the QS data buffer. -* -* @note QS_getBlock() is **not** protected with a critical section. -*/ -uint8_t const * QS_getBlock(uint16_t * const pNbytes); - -/*${QS::QS-tx::glbFilter_} .................................................*/ -/*! Set/clear the global Filter for a given QS record or a group -* of records -* @static @public @memberof QS_tx -* -* @details -* This function sets up the QS filter to enable record types specified -* in the `filter` parameter. The value #QS_ALL_RECORDS specifies to -* filter-in all records. This function should be called indirectly -* through the macro QS_GLB_FILTER() -* -* @param[in] filter the QS record-d or group to enable in the filter, -* if positive or disable, if negative. The record-id -* numbers must be in the range -127..127. -* @note -* Filtering based on the record-type is only the first layer of -* filtering. The second layer is based on the object-type. Both filter -* layers must be enabled for the QS record to be inserted in the -* QS buffer. -* -* @sa QS_locFilter_() -*/ -void QS_glbFilter_(int_fast16_t const filter); - -/*${QS::QS-tx::locFilter_} .................................................*/ -/*! Set/clear the local Filter for a given object-id -* or a group of object-ids -* @static @public @memberof QS_tx -* -* @details -* This function sets up the local QS filter to enable or disable the -* given QS object-id or a group of object-ids @a filter. -* This function should be called indirectly through the macro -* QS_LOC_FILTER() -* -* @param[in] filter the QS object-id or group to enable in the filter, -* if positive or disable, if negative. The qs_id numbers -* must be in the range 1..127. -* @note -* Filtering based on the object-id (local filter) is the second layer -* of filtering. The first layer is based on the QS record-type (global -* filter). Both filter layers must be enabled for the QS record to be -* inserted into the QS buffer. -* -* @sa QS_glbFilter_() -*/ -void QS_locFilter_(int_fast16_t const filter); - -/*${QS::QS-tx::doOutput} ...................................................*/ -/*! Perform the QS-TX output (implemented in some QS ports) -* @static @public @memberof QS_tx -*/ -void QS_doOutput(void); - -/*${QS::QS-tx::beginRec_} ..................................................*/ -/*! Mark the begin of a QS record `rec` -* @static @private @memberof QS_tx -* -* @details -* This function must be called at the beginning of each QS record. -* This function should be called indirectly through the macro QS_BEGIN_ID(), -* or QS_BEGIN_NOCRIT(), depending if it's called in a normal code or from -* a critical section. -*/ -void QS_beginRec_(uint_fast8_t const rec); - -/*${QS::QS-tx::endRec_} ....................................................*/ -/*! Mark the end of a QS record `rec` -* @static @private @memberof QS_tx -* -* @details -* This function must be called at the end of each QS record. -* This function should be called indirectly through the macro QS_END(), -* or QS_END_NOCRIT(), depending if it's called in a normal code or from -* a critical section. -*/ -void QS_endRec_(void); - -/*${QS::QS-tx::u8_raw_} ....................................................*/ -/*! output uint8_t data element without format information -* @static @private @memberof QS_tx -*/ -void QS_u8_raw_(uint8_t const d); - -/*${QS::QS-tx::2u8_raw_} ...................................................*/ -/*! output two uint8_t data elements without format information -* @static @private @memberof QS_tx -*/ -void QS_2u8_raw_( - uint8_t const d1, - uint8_t const d2); - -/*${QS::QS-tx::u16_raw_} ...................................................*/ -/*! output uint16_t data element without format information -* @static @private @memberof QS_tx -*/ -void QS_u16_raw_(uint16_t const d); - -/*${QS::QS-tx::u32_raw_} ...................................................*/ -/*! output uint32_t data element without format information -* @static @private @memberof QS_tx -*/ -void QS_u32_raw_(uint32_t const d); - -/*${QS::QS-tx::obj_raw_} ...................................................*/ -/*! Output obj pointer data element without format information -* @static @private @memberof QS_tx -* -* @note This function is only to be used through macros, never in the -* client code directly. -*/ -void QS_obj_raw_(void const * const obj); - -/*${QS::QS-tx::str_raw_} ...................................................*/ -/*! Output raw zero-terminated string element (without format information) -* @static @private @memberof QS_tx -* -* @note This function is only to be used through macros, never in the -* client code directly. -*/ -void QS_str_raw_(char const * const str); - -/*${QS::QS-tx::u8_fmt_} ....................................................*/ -/*! Output uint8_t data element with format information -* @static @private @memberof QS_tx -* -* @details -* @note This function is only to be used through macros, never in the -* client code directly. -*/ -void QS_u8_fmt_( - uint8_t const format, - uint8_t const d); - -/*${QS::QS-tx::u16_fmt_} ...................................................*/ -/*! output uint16_t data element with format information -* @static @private @memberof QS_tx -* -* @details -* This function is only to be used through macros, never in the -* client code directly. -*/ -void QS_u16_fmt_( - uint8_t const format, - uint16_t const d); - -/*${QS::QS-tx::u32_fmt_} ...................................................*/ -/*! Output uint32_t data element with format information -* @static @private @memberof QS_tx -* -* @note This function is only to be used through macros, never in the -* client code directly. -*/ -void QS_u32_fmt_( - uint8_t const format, - uint32_t const d); - -/*${QS::QS-tx::str_fmt_} ...................................................*/ -/*! Output formatted zero-terminated ASCII string to the QS record -* @static @private @memberof QS_tx -*/ -void QS_str_fmt_(char const * const str); - -/*${QS::QS-tx::mem_fmt_} ...................................................*/ -/*! Output formatted memory block of up to 255 bytes to the QS record -* @static @private @memberof QS_tx -*/ -void QS_mem_fmt_( - uint8_t const * const blk, - uint8_t const size); - -/*${QS::QS-tx::sig_dict_pre_} ..............................................*/ -/*! Output predefined signal-dictionary record -* @static @private @memberof QS_tx -* -* @note This function is only to be used through macro QS_SIG_DICTIONARY() -*/ -void QS_sig_dict_pre_( - enum_t const sig, - void const * const obj, - char const * const name); - -/*${QS::QS-tx::obj_dict_pre_} ..............................................*/ -/*! Output predefined object-dictionary record -* @static @private @memberof QS_tx -* -* @note This function is only to be used through macro QS_OBJ_DICTIONARY() -*/ -void QS_obj_dict_pre_( - void const * const obj, - char const * const name); - -/*${QS::QS-tx::obj_arr_dict_pre_} ..........................................*/ -/*! Output predefined object-array dictionary record -* @static @private @memberof QS_tx -* -* @note This function is only to be used through macro QS_OBJ_ARR_DICTIONARY() -*/ -void QS_obj_arr_dict_pre_( - void const * const obj, - uint_fast16_t const idx, - char const * const name); - -/*${QS::QS-tx::fun_dict_pre_} ..............................................*/ -/*! Output predefined function-dictionary record -* @static @private @memberof QS_tx -* -* @note This function is only to be used through macro QS_FUN_DICTIONARY() -*/ -void QS_fun_dict_pre_( - QSpyFunPtr const fun, - char const * const name); - -/*${QS::QS-tx::usr_dict_pre_} ..............................................*/ -/*! Output predefined user-dictionary record -* @static @private @memberof QS_tx -* -* @note This function is only to be used through macro QS_USR_DICTIONARY() -*/ -void QS_usr_dict_pre_( - enum_t const rec, - char const * const name); - -/*${QS::QS-tx::enum_dict_pre_} .............................................*/ -/*! Output predefined enum-dictionary record -* @static @private @memberof QS_tx -* -* @note This function is only to be used through macro QS_ENUM_DICTIONARY() -*/ -void QS_enum_dict_pre_( - enum_t const value, - uint8_t const group, - char const * const name); +//${QS::types::QSpyFunPtr} ................................................... +//! @static @private @memberof QS +typedef void (* QSpyFunPtr )(void); -/*${QS::QS-tx::ASSERTION} ..................................................*/ -/*! Output the predefined assertion failure trace record -* @static @public @memberof QS_tx -* -* @details -* This trace record is intended to use from the Q_onAssert() callback. -*/ -void QS_ASSERTION( - char const * const module, - int_t const loc, - uint32_t const delay); +//${QS::types::QSCtr} ........................................................ +#if (QS_CTR_SIZE == 2U) +typedef uint16_t QSCtr; +#endif // (QS_CTR_SIZE == 2U) -/*${QS::QS-tx::target_info_pre_} ...........................................*/ -/*! Helper function to output the predefined Target-info trace record -* @static @private @memberof QS_tx -*/ -void QS_target_info_pre_(uint8_t const isReset); +//${QS::types::QSCtr} ........................................................ +#if (QS_CTR_SIZE == 4U) +typedef uint32_t QSCtr; +#endif // (QS_CTR_SIZE == 4U) -/*${QS::QS-tx::onStartup} ..................................................*/ -/*! Callback to startup the QS facility -* @static @public @memberof QS_tx -*/ -uint8_t QS_onStartup(void const * arg); +//${QS::types::QSTimeCtr} .................................................... +#if (QS_TIME_SIZE == 2U) +typedef uint16_t QSTimeCtr; +#endif // (QS_TIME_SIZE == 2U) -/*${QS::QS-tx::onCleanup} ..................................................*/ -/*! Callback to cleanup the QS facility -* @static @public @memberof QS_tx -*/ -void QS_onCleanup(void); +//${QS::types::QSTimeCtr} .................................................... +#if (QS_TIME_SIZE == 4U) +typedef uint32_t QSTimeCtr; +#endif // (QS_TIME_SIZE == 4U) -/*${QS::QS-tx::onFlush} ....................................................*/ -/*! Callback to flush the QS trace data to the host -* @static @public @memberof QS_tx -*/ -void QS_onFlush(void); +//${QS::types::QSFun} ........................................................ +#if (QS_FUN_PTR_SIZE == 2U) +typedef uint16_t QSFun; +#endif // (QS_FUN_PTR_SIZE == 2U) -/*${QS::QS-tx::onGetTime} ..................................................*/ -/*! Callback to obtain a timestamp for a QS record -* @static @public @memberof QS_tx -*/ -QSTimeCtr QS_onGetTime(void); +//${QS::types::QSFun} ........................................................ +#if (QS_FUN_PTR_SIZE == 4U) +typedef uint32_t QSFun; +#endif // (QS_FUN_PTR_SIZE == 4U) -/*${QS::QS-tx-64bit::u64_raw_} .............................................*/ -/*! Output uint64_t data element without format information -* @static @private @memberof QS_tx -*/ -void QS_u64_raw_(uint64_t d); - -/*${QS::QS-tx-64bit::u64_fmt_} .............................................*/ -/*! Output uint64_t data element with format information -* @static @private @memberof QS_tx -* -* @sa QS_U64(), QS_I64() -*/ -void QS_u64_fmt_( - uint8_t format, - uint64_t d); - -/*${QS::QS-tx-fp::f32_fmt_} ................................................*/ -/*! Output 32-bit floating point data element with format information -* @static @private @memberof QS_tx -* -* @sa QS_F32() -*/ -void QS_f32_fmt_( - uint8_t const format, - float32_t const d); - -/*${QS::QS-tx-fp::f64_fmt_} ................................................*/ -/*! Output 64-bit floating point data element with format information -* @static @private @memberof QS_tx -* -* @sa QS_F64() -*/ -void QS_f64_fmt_( - uint8_t const format, - float64_t const d); +//${QS::types::QSFun} ........................................................ +#if (QS_FUN_PTR_SIZE == 8U) +typedef uint64_t QSFun; +#endif // (QS_FUN_PTR_SIZE == 8U) +//$enddecl${QS::types} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//$declare${QS::filters} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -/*${QS::QS-rx::rx} .........................................................*/ -/*! @brief QS software tracing parameters for QS input (QS-RX) */ +//${QS::filters::Filter} ..................................................... +//! @struct QS_Filter typedef struct { -/* public: */ - void * currObj[8]; - uint8_t * buf; - QSCtr end; - QSCtr volatile head; - QSCtr volatile tail; - -#ifdef Q_UTEST - bool inTestLoop; -#endif /* def Q_UTEST */ -} QS_rx; - -/*${QS::QS-rx::rxPriv_} ....................................................*/ -/*! the only instance of the QS-RX object (Singleton) -* @static @private @memberof QS_rx -*/ -extern QS_rx QS_rxPriv_; - -/*${QS::QS-rx::QSpyObjKind} ................................................*/ -/*! Kinds of objects used in QS_setCurrObj() and QS_queryCurrObj() -* @static @public @memberof QS_rx -*/ -enum QS_QSpyObjKind { - SM_OBJ, /*!< state machine object */ - AO_OBJ, /*!< active object */ - MP_OBJ, /*!< event pool object */ - EQ_OBJ, /*!< raw queue object */ - TE_OBJ, /*!< time event object */ - AP_OBJ, /*!< generic Application-specific object */ - MAX_OBJ -}; - -/*${QS::QS-rx::OSpyObjCombnation} ..........................................*/ -/*! Object combinations for QS_setCurrObj() and QS_queryCurrObj() -* @static @public @memberof QS_rx -*/ -enum QS_OSpyObjCombnation { - SM_AO_OBJ = (enum_t)MAX_OBJ /*!< combination of SM and AO */ -}; - -/*${QS::QS-rx::rxInitBuf} ..................................................*/ -/*! Initialize the QS-RX data buffer -* @static @public @memberof QS_rx -* -* @details -* This function should be called from QS::onStartup() to provide QS-RX -* with the receive data buffer. -* -* @param[in] sto pointer to the memory block for input buffer -* @param[in] stoSize the size of this block [bytes]. The size of the -* QS-RX buffer cannot exceed 64KB. -* -* @note -* QS-RX can work with quite small data buffers, but you will start -* losing data if the buffer is not drained fast enough (e.g., in the -* idle task). -* -* @note -* If the data input rate exceeds the QS-RX processing rate, the data -* will be lost, but the QS protocol will notice that: -* (1) that the checksum in the incomplete QS records will fail; and -* (2) the sequence counter in QS records will show discontinuities. -* -* The QS-RX channel will report any data errors by sending the -* QS_RX_DATA_ERROR trace record. -*/ -void QS_rxInitBuf( - uint8_t * const sto, - uint16_t const stoSize); - -/*${QS::QS-rx::rxPut} ......................................................*/ -/*! Put one byte into the QS-RX lock-free buffer -* @static @public @memberof QS_rx -*/ -static inline bool QS_rxPut(uint8_t const b) { - QSCtr head = QS_rxPriv_.head + 1U; - if (head == QS_rxPriv_.end) { - head = 0U; - } - if (head != QS_rxPriv_.tail) { /* buffer NOT full? */ - QS_rxPriv_.buf[QS_rxPriv_.head] = b; - QS_rxPriv_.head = head; /* update the head to a *valid* index */ - return true; /* byte placed in the buffer */ - } - else { - return false; /* byte NOT placed in the buffer */ - } -} - -/*${QS::QS-rx::rxGetNfree} .................................................*/ -/*! Obtain the number of free bytes in the QS-RX data buffer -* @static @public @memberof QS_rx -* -* @details -* This function is intended to be called from the ISR that reads the -* QS-RX bytes from the QSPY application. The function returns the -* conservative number of free bytes currently available in the buffer, -* assuming that the head pointer is not being moved concurrently. -* The tail pointer might be moving, meaning that bytes can be -* concurrently removed from the buffer. -*/ -uint16_t QS_rxGetNfree(void); - -/*${QS::QS-rx::doInput} ....................................................*/ -/*! Perform the QS-RX input (implemented in some QS ports) -* @static @public @memberof QS_rx -*/ -void QS_doInput(void); - -/*${QS::QS-rx::setCurrObj} .................................................*/ -/*! Set the "current object" in the Target -* @static @public @memberof QS_rx -* -* @details -* This function sets the "current object" in the Target. -*/ -void QS_setCurrObj( - uint8_t const obj_kind, - void * const obj_ptr); - -/*${QS::QS-rx::queryCurrObj} ...............................................*/ -/*! Query the "current object" in the Target -* @static @public @memberof QS_rx -* -* @details -* This function programmatically generates the response to the query for -* a "current object". -*/ -void QS_queryCurrObj(uint8_t const obj_kind); - -/*${QS::QS-rx::rxParse} ....................................................*/ -/*! Parse all bytes present in the QS-RX data buffer -* @static @public @memberof QS_rx -*/ -void QS_rxParse(void); - -/*${QS::QS-rx::rxHandleGoodFrame_} .........................................*/ -/*! internal function to handle incoming (QS-RX) packet -* @static @private @memberof QS_rx -*/ -void QS_rxHandleGoodFrame_(uint8_t const state); - -/*${QS::QS-rx::onReset} ....................................................*/ -/*! callback function to reset the Target (to be implemented in the BSP) -* @static @public @memberof QS_rx -*/ -void QS_onReset(void); - -/*${QS::QS-rx::onCommand} ..................................................*/ -/*! Callback function to execute user commands (to be implemented in BSP) -* @static @public @memberof QS_rx -*/ -void QS_onCommand( - uint8_t cmdId, - uint32_t param1, - uint32_t param2, - uint32_t param3); - -/*${QS::QS-rx::RX_PUT} .....................................................*/ -/*! Put one byte into the QS RX lock-free buffer -* @static @public @memberof QS_rx -*/ -bool QS_RX_PUT(uint8_t const b); -/*$enddecl${QS} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ - -/*==========================================================================*/ -/*$declare${QS-macros} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ - -/*${QS-macros::QS_INIT} ....................................................*/ -/*! Initialize the QS facility -* -* @details -* This macro provides an indirection layer to invoke the QS initialization -* routine if #Q_SPY is defined, or do nothing if #Q_SPY is not defined. -* @sa QS_onStartup(), example of setting up a QS filter in -* QS_GLB_FILTER() -*/ +// public: + uint8_t glb[16]; + uint8_t loc[16]; +} QS_Filter; + +//${QS::filters::filt_} ...................................................... +//! @static @private @memberof QS +extern QS_Filter QS_filt_; +//$enddecl${QS::filters} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//$declare${QS-macros} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + +//${QS-macros::QS_INIT} ...................................................... #define QS_INIT(arg_) (QS_onStartup(arg_)) -/*${QS-macros::QS_EXIT} ....................................................*/ -/*! Cleanup the QS facility -* -* @details -* This macro provides an indirection layer to invoke the QS cleanup -* routine if #Q_SPY is defined, or do nothing if #Q_SPY is not defined. -* @sa QS_onCleanup() -*/ +//${QS-macros::QS_EXIT} ...................................................... #define QS_EXIT() (QS_onCleanup()) -/*${QS-macros::QS_OUTPUT} ..................................................*/ -/*! macro to handle the QS output from the application -* -* @note -* If this macro is used, the application must define QS_output(). -*/ +//${QS-macros::QS_OUTPUT} .................................................... #define QS_OUTPUT() (QS_output()) -/*${QS-macros::QS_RX_INPUT} ................................................*/ -/*! macro to handle the QS-RX input to the application -* -* @note -* If this macro is used, the application must define QS_doInput(). -*/ +//${QS-macros::QS_RX_INPUT} .................................................. #define QS_RX_INPUT() (QS_rx_input()) -/*${QS-macros::QS_GLB_FILTER} ..............................................*/ -/*! Global Filter ON for a given record type `rec_` -* -* @details -* This macro provides an indirection layer to call QS_filterOn() -* if #Q_SPY is defined, or do nothing if #Q_SPY is not defined. -* -* @sa -* - enum QSpyGroups - QS record groups that can be used as `rec_` -* - enum QSpyPre - predefined QS records that can be used as `rec_` -* -* @usage -* The following example shows how to use QS filters: -* @include qs_filter.c -*/ +//${QS-macros::QS_GLB_FILTER} ................................................ #define QS_GLB_FILTER(rec_) (QS_glbFilter_((int_fast16_t)(rec_))) -/*${QS-macros::QS_LOC_FILTER} ..............................................*/ -/*! Local Filter for a given state machine object `qs_id` -* -* @details -* This macro provides an indirection layer to call QS_locFilter_() -* if #Q_SPY is defined, or do nothing if #Q_SPY is not defined. -* -* @sa -* - enum QSpyIdGroups - QS ID groups that can be used as `qs_id_` -* - enum QSpyIdOffsets - QS ID offsets for `qs_id_` (e.g., QS_AP_IDS + 5) -* -* The following example shows how to use QS filters: -* @include qs_filter.c -*/ +//${QS-macros::QS_LOC_FILTER} ................................................ #define QS_LOC_FILTER(qs_id_) (QS_locFilter_((int_fast16_t)(qs_id_))) -/*${QS-macros::QS_BEGIN_ID} ................................................*/ -/*! Begin an application-specific QS record with entering critical section -* -* @details -* The following example shows how to build a user QS record using the -* macros QS_BEGIN_ID(), QS_END(), and the formatted output macros: -* QS_U8(), QS_STR(), etc. -* -* @note -* Must always be used in pair with QS_END() -* -* @include qs_ap.c -*/ +//${QS-macros::QS_BEGIN_ID} .................................................. #define QS_BEGIN_ID(rec_, qs_id_) \ if (QS_GLB_CHECK_(rec_) && QS_LOC_CHECK_(qs_id_)) { \ - QS_CRIT_STAT_ \ - QS_CRIT_E_(); \ + QS_CRIT_STAT \ + QS_CRIT_ENTRY(); \ + QS_MEM_SYS(); \ QS_beginRec_((uint_fast8_t)(rec_)); \ QS_TIME_PRE_(); { -/*${QS-macros::QS_END} .....................................................*/ -/*! End an application-specific QS record with exiting critical section. -* -* @sa example for QS_BEGIN_ID() -* @note Must always be used in pair with QS_BEGIN_ID() -*/ +//${QS-macros::QS_END} ....................................................... #define QS_END() } \ QS_endRec_(); \ - QS_CRIT_X_(); \ + QS_MEM_APP(); \ + QS_CRIT_EXIT(); \ } -/*${QS-macros::QS_FLUSH} ...................................................*/ -/*! Flush the QS trace data to the host -* -* @details -* This macro invokes the QS_flush() platform-dependent callback -* function to flush the QS trace buffer to the host. The function -* typically busy-waits until all the data in the buffer is sent to -* the host. This is acceptable only in the initial transient. -*/ +//${QS-macros::QS_FLUSH} ..................................................... #define QS_FLUSH() (QS_onFlush()) -/*${QS-macros::QS_BEGIN_NOCRIT} ............................................*/ -/*! Begin an application-specific QS record WITHOUT entering critical section */ -#define QS_BEGIN_NOCRIT(rec_, qs_id_) \ +//${QS-macros::QS_BEGIN_INCRIT} .............................................. +#define QS_BEGIN_INCRIT(rec_, qs_id_) \ if (QS_GLB_CHECK_(rec_) && QS_LOC_CHECK_(qs_id_)) { \ QS_beginRec_((uint_fast8_t)(rec_)); \ QS_TIME_PRE_(); { -/*${QS-macros::QS_END_NOCRIT} ..............................................*/ -/*! End an application-specific QS record WITHOUT exiting critical section */ -#define QS_END_NOCRIT() } \ - QS_endRec_();\ +//${QS-macros::QS_END_INCRIT} ................................................ +#define QS_END_INCRIT() } \ + QS_endRec_(); \ } -/*${QS-macros::QS_GLB_CHECK_} ..............................................*/ -/*! Helper macro for checking the global QS filter */ +//${QS-macros::QS_GLB_CHECK_} ................................................ #define QS_GLB_CHECK_(rec_) \ - (((uint_fast8_t)QS_priv_.glbFilter[(uint_fast8_t)(rec_) >> 3U] \ + (((uint_fast8_t)QS_filt_.glb[(uint_fast8_t)(rec_) >> 3U] \ & ((uint_fast8_t)1U << ((uint_fast8_t)(rec_) & 7U))) != 0U) -/*${QS-macros::QS_LOC_CHECK_} ..............................................*/ -/*! Helper macro for checking the local QS filter */ +//${QS-macros::QS_LOC_CHECK_} ................................................ #define QS_LOC_CHECK_(qs_id_) \ - (((uint_fast8_t)QS_priv_.locFilter[(uint_fast8_t)(qs_id_) >> 3U] \ + (((uint_fast8_t)QS_filt_.loc[(uint_fast8_t)(qs_id_) >> 3U] \ & ((uint_fast8_t)1U << ((uint_fast8_t)(qs_id_) & 7U))) != 0U) -/*${QS-macros::QS_REC_DONE} ................................................*/ +//${QS-macros::QS_REC_DONE} .................................................. #ifndef QS_REC_DONE -/*! Macro to execute user code when a QS record is produced -* -* @note -* This is a dummy definition in case this macro is undefined. -*/ #define QS_REC_DONE() ((void)0) -#endif /* ndef QS_REC_DONE */ +#endif // ndef QS_REC_DONE -/*${QS-macros::QS_I8} ......................................................*/ -/*! Output formatted int8_t to the QS record */ +//${QS-macros::QS_I8} ........................................................ #define QS_I8(width_, data_) \ (QS_u8_fmt_((uint8_t)(((width_) << 4U) & 0x7U) | (uint8_t)QS_I8_ENUM_T, \ (data_))) -/*${QS-macros::QS_U8} ......................................................*/ -/*! Output formatted uint8_t to the QS record */ +//${QS-macros::QS_U8} ........................................................ #define QS_U8(width_, data_) \ (QS_u8_fmt_((uint8_t)(((width_) << 4)) | (uint8_t)QS_U8_T, (data_))) -/*${QS-macros::QS_I16} .....................................................*/ -/*! Output formatted int16_t to the QS record */ +//${QS-macros::QS_I16} ....................................................... #define QS_I16(width_, data_) \ (QS_u16_fmt_((uint8_t)(((width_) << 4)) | (uint8_t)QS_I16_T, (data_))) -/*${QS-macros::QS_U16} .....................................................*/ -/*! Output formatted uint16_t to the QS record */ +//${QS-macros::QS_U16} ....................................................... #define QS_U16(width_, data_) \ (QS_u16_fmt_((uint8_t)(((width_) << 4)) | (uint8_t)QS_U16_T, (data_))) -/*${QS-macros::QS_I32} .....................................................*/ -/*! Output formatted int32_t to the QS record */ +//${QS-macros::QS_I32} ....................................................... #define QS_I32(width_, data_) \ (QS_u32_fmt_((uint8_t)(((width_) << 4)) | (uint8_t)QS_I32_T, (data_))) -/*${QS-macros::QS_U32} .....................................................*/ -/*! Output formatted uint32_t to the QS record */ +//${QS-macros::QS_U32} ....................................................... #define QS_U32(width_, data_) \ (QS_u32_fmt_((uint8_t)(((width_) << 4)) | (uint8_t)QS_U32_T, (data_))) -/*${QS-macros::QS_I64} .....................................................*/ -/*! Output formatted int64_t to the QS record */ +//${QS-macros::QS_I64} ....................................................... #define QS_I64(width_, data_) \ (QS_u64_fmt_((uint8_t)(((width_) << 4)) | (uint8_t)QS_I64_T, (data_))) -/*${QS-macros::QS_U64} .....................................................*/ -/*! Output formatted uint64_t to the QS record */ +//${QS-macros::QS_U64} ....................................................... #define QS_U64(width_, data_) \ (QS_u64_fmt_((uint8_t)(((width_) << 4)) | (uint8_t)QS_U64_T, (data_))) -/*${QS-macros::QS_F32} .....................................................*/ -/*! Output formatted 32-bit floating point number to the QS record */ +//${QS-macros::QS_F32} ....................................................... #define QS_F32(width_, data_) \ (QS_f32_fmt_((uint8_t)(((width_) << 4)) | (uint8_t)QS_F32_T, (data_))) -/*${QS-macros::QS_F64} .....................................................*/ -/*! Output formatted 64-bit floating point number to the QS record */ +//${QS-macros::QS_F64} ....................................................... #define QS_F64(width_, data_) \ (QS_f64_fmt_((uint8_t)(((width_) << 4)) | (uint8_t)QS_F64_T, (data_))) -/*${QS-macros::QS_STR} .....................................................*/ -/*! Output formatted zero-terminated ASCII string to the QS record */ +//${QS-macros::QS_STR} ....................................................... #define QS_STR(str_) (QS_str_fmt_((str_))) -/*${QS-macros::QS_MEM} .....................................................*/ -/*! Output formatted memory block of up to 255 bytes to the QS record */ +//${QS-macros::QS_MEM} ....................................................... #define QS_MEM(mem_, size_) (QS_mem_fmt_((mem_), (size_))) -/*${QS-macros::QS_ENUM} ....................................................*/ -/*! Output formatted enumeration to the QS record */ +//${QS-macros::QS_ENUM} ...................................................... #define QS_ENUM(group_, value_) \ (QS_u8_fmt_((uint8_t)(0x80U | ((group_) << 4U)) | (uint8_t)QS_I8_ENUM_T,\ (uint8_t)(value_))) -/*${QS-macros::QS_TIME_PRE_} ...............................................*/ -#if (QS_TIME_SIZE == 4U) -/*! Output time stamp to a QS record (used in predefined -* and application-specific trace records) -*/ -#define QS_TIME_PRE_() (QS_u32_raw_(QS_onGetTime())) -#endif /* (QS_TIME_SIZE == 4U) */ - -/*${QS-macros::QS_TIME_PRE_} ...............................................*/ +//${QS-macros::QS_TIME_PRE_} ................................................. #if (QS_TIME_SIZE == 2U) #define QS_TIME_PRE_() (QS_u16_raw_(QS_onGetTime())) -#endif /* (QS_TIME_SIZE == 2U) */ - -/*${QS-macros::QS_TIME_PRE_} ...............................................*/ -#if (QS_TIME_SIZE == 1U) -#define QS_TIME_PRE_() (QS_u8_raw_(QS_onGetTime())) -#endif /* (QS_TIME_SIZE == 1U) */ +#endif // (QS_TIME_SIZE == 2U) -/*${QS-macros::QS_OBJ} .....................................................*/ -#if (QS_OBJ_PTR_SIZE == 4U) -/*! Output formatted object pointer to the QS record */ -#define QS_OBJ(obj_) (QS_u32_fmt_(QS_OBJ_T, (uint32_t)(obj_))) -#endif /* (QS_OBJ_PTR_SIZE == 4U) */ +//${QS-macros::QS_TIME_PRE_} ................................................. +#if (QS_TIME_SIZE == 4U) +#define QS_TIME_PRE_() (QS_u32_raw_(QS_onGetTime())) +#endif // (QS_TIME_SIZE == 4U) -/*${QS-macros::QS_OBJ} .....................................................*/ +//${QS-macros::QS_OBJ} ....................................................... #if (QS_OBJ_PTR_SIZE == 2U) #define QS_OBJ(obj_) (QS_u16_fmt_(QS_OBJ_T, (uint16_t)(obj_))) -#endif /* (QS_OBJ_PTR_SIZE == 2U) */ +#endif // (QS_OBJ_PTR_SIZE == 2U) -/*${QS-macros::QS_OBJ} .....................................................*/ -#if (QS_OBJ_PTR_SIZE == 1U) -#define QS_OBJ(obj_) (QS_u8_fmt_(QS_OBJ_T, (uint8_t)(obj_))) -#endif /* (QS_OBJ_PTR_SIZE == 1U) */ +//${QS-macros::QS_OBJ} ....................................................... +#if (QS_OBJ_PTR_SIZE == 4U) +#define QS_OBJ(obj_) (QS_u32_fmt_(QS_OBJ_T, (uint32_t)(obj_))) +#endif // (QS_OBJ_PTR_SIZE == 4U) -/*${QS-macros::QS_OBJ} .....................................................*/ +//${QS-macros::QS_OBJ} ....................................................... #if (QS_OBJ_PTR_SIZE == 8U) #define QS_OBJ(obj_) (QS_u64_fmt_(QS_OBJ_T, (uint64_t)(obj_))) -#endif /* (QS_OBJ_PTR_SIZE == 8U) */ +#endif // (QS_OBJ_PTR_SIZE == 8U) -/*${QS-macros::QS_FUN} .....................................................*/ -#if (QS_FUN_PTR_SIZE == 4U) -/* Output formatted function pointer to the QS record */ -#define QS_FUN(fun_) (QS_u32_fmt_(QS_FUN_T, (uint32_t)(fun_))) -#endif /* (QS_FUN_PTR_SIZE == 4U) */ - -/*${QS-macros::QS_FUN} .....................................................*/ +//${QS-macros::QS_FUN} ....................................................... #if (QS_FUN_PTR_SIZE == 2U) #define QS_FUN(fun_) (QS_u16_fmt_(QS_FUN_T, (uint16_t)(fun_))) -#endif /* (QS_FUN_PTR_SIZE == 2U) */ +#endif // (QS_FUN_PTR_SIZE == 2U) -/*${QS-macros::QS_FUN} .....................................................*/ -#if (QS_FUN_PTR_SIZE == 1U) -#define QS_FUN(fun_) (QS_u8_fmt_(QS_FUN_T, (uint8_t)(fun_))) -#endif /* (QS_FUN_PTR_SIZE == 1U) */ +//${QS-macros::QS_FUN} ....................................................... +#if (QS_FUN_PTR_SIZE == 4U) +#define QS_FUN(fun_) (QS_u32_fmt_(QS_FUN_T, (uint32_t)(fun_))) +#endif // (QS_FUN_PTR_SIZE == 4U) -/*${QS-macros::QS_FUN} .....................................................*/ +//${QS-macros::QS_FUN} ....................................................... #if (QS_FUN_PTR_SIZE == 8U) #define QS_FUN(fun_) (QS_u64_fmt_(QS_FUN_T, (uint64_t)(fun_))) -#endif /* (QS_FUN_PTR_SIZE == 8U) */ +#endif // (QS_FUN_PTR_SIZE == 8U) -/*${QS-macros::QS_SIG} .....................................................*/ -#if (Q_SIGNAL_SIZE == 4U) -/*! Output formatted event signal (of type ::QSignal) and -* the state machine object to the user QS record -*/ +//${QS-macros::QS_SIG} ....................................................... +#if (Q_SIGNAL_SIZE == 1U) #define QS_SIG(sig_, obj_) \ - QS_u32_fmt_(QS_SIG_T, (sig_)); \ + QS_u8_fmt_(QS_SIG_T, (sig_)); \ QS_obj_raw_(obj_) -#endif /* (Q_SIGNAL_SIZE == 4U) */ +#endif // (Q_SIGNAL_SIZE == 1U) -/*${QS-macros::QS_SIG} .....................................................*/ +//${QS-macros::QS_SIG} ....................................................... #if (Q_SIGNAL_SIZE == 2U) #define QS_SIG(sig_, obj_) \ QS_u16_fmt_(QS_SIG_T, (sig_)); \ QS_obj_raw_(obj_) -#endif /* (Q_SIGNAL_SIZE == 2U) */ +#endif // (Q_SIGNAL_SIZE == 2U) -/*${QS-macros::QS_SIG} .....................................................*/ -#if (Q_SIGNAL_SIZE == 1U) +//${QS-macros::QS_SIG} ....................................................... +#if (Q_SIGNAL_SIZE == 4U) #define QS_SIG(sig_, obj_) \ - QS_u8_fmt_(QS_SIG_T, (sig_)); \ + QS_u32_fmt_(QS_SIG_T, (sig_)); \ QS_obj_raw_(obj_) -#endif /* (Q_SIGNAL_SIZE == 1U) */ - -/*${QS-macros::QS_SIG_DICTIONARY} ..........................................*/ -/*! Output QS signal dictionary record -* -* @details -* A signal dictionary record associates the numerical value of the signal -* and the binary address of the state machine that consumes that signal -* with the human-readable name of the signal. -* -* @param[in] sig_ event signal (typically enumerated, e.g. `TIMEOUT_SIG`) -* @param[in] obj_ pointer to the associated state machine object -* (might be `(void*)0` for globally recognized signals) -* -* A signal dictionary entry is associated with both the signal value `sig_` -* and the state machine `obj_`, because signals are required to be unique -* only within a given state machine and therefore the same numerical values -* can represent different signals in different state machines. -* -* For the "global" signals that have the same meaning in many state machines -* (such as globally published signals), you can specify a signal dictionary -* entry with the `obj_` parameter set to `(void*)0`. -* -* The following example shows the definition of signal dictionary entries -* in the initial transition of the Table active object. Please note that -* signals HUNGRY_SIG and DONE_SIG are associated with the Table state -* machine only ("me" `obj_` pointer). The EAT_SIG signal, on the other -* hand, is global (0 `obj_` pointer): -* @include qs_sigDic.c -* -* The following QSpy log example shows the signal dictionary records -* generated from the Table initial transition and subsequent records that -* show human-readable names of the signals: -* @include qs_sigLog.txt -*/ +#endif // (Q_SIGNAL_SIZE == 4U) + +//${QS-macros::QS_SIG_DICTIONARY} ............................................ #define QS_SIG_DICTIONARY(sig_, obj_) \ - (QS_sig_dict_pre_((sig_), (obj_), #sig_)) - -/*${QS-macros::QS_OBJ_DICTIONARY} ..........................................*/ -/*! Output object dictionary record -* -* @details -* An object dictionary record associates the binary address of an object -* in the target's memory with the human-readable name of the object. -* -* @param[in] obj_ pointer to the object (any object) -* -* The following example shows the definition of object dictionary entry -* for the Table active object: -* @include qs_objDic.c -*/ + (QS_sig_dict_pre_((QSignal)(sig_), (obj_), #sig_)) + +//${QS-macros::QS_OBJ_DICTIONARY} ............................................ #define QS_OBJ_DICTIONARY(obj_) \ (QS_obj_dict_pre_((obj_), #obj_)) -/*${QS-macros::QS_OBJ_ARR_DICTIONARY} ......................................*/ -/*! Output object-array dictionary record -* -* @details -* An object array dictionary record associates the binary address of the -* object element in the target's memory with the human-readable name -* of the object. -* -* @param[in] obj_ pointer to the object (any object) -* @param[in] idx_ array index -* -* The following example shows the definition of object array dictionary -* for `Philo::inst[n]` and `Philo::inst[n].m_timeEvt`: -* @include qs_objArrDic.c -*/ +//${QS-macros::QS_OBJ_ARR_DICTIONARY} ........................................ #define QS_OBJ_ARR_DICTIONARY(obj_, idx_) \ (QS_obj_arr_dict_pre_((obj_), (idx_), #obj_)) -/*${QS-macros::QS_FUN_DICTIONARY} ..........................................*/ -/*! Output function dictionary record -* -* @details -* A function dictionary record associates the binary address of a function -* in the target's memory with the human-readable name of the function. -* -* Providing a function dictionary QS record can vastly improve readability -* of the QS log, because instead of dealing with cryptic machine addresses -* the QSpy host utility can display human-readable function names. -* -* The example from #QS_SIG_DICTIONARY shows the definition of a function -* dictionary. -*/ +//${QS-macros::QS_FUN_DICTIONARY} ............................................ #define QS_FUN_DICTIONARY(fun_) \ (QS_fun_dict_pre_((void (*)(void))(fun_), #fun_)) -/*${QS-macros::QS_USR_DICTIONARY} ..........................................*/ -/*! Output user QS record dictionary record -* -* @details -* A user QS record dictionary record associates the numerical value of a -* user record with the human-readable identifier. -*/ +//${QS-macros::QS_USR_DICTIONARY} ............................................ #define QS_USR_DICTIONARY(rec_) \ (QS_usr_dict_pre_((rec_), #rec_)) -/*${QS-macros::QS_ENUM_DICTIONARY} .........................................*/ -/*! Output enumeration dictionary record -* -* @details -* An enum QS record dictionary record associates the numerical value of -* an enumeration with the human-readable identifier. -*/ +//${QS-macros::QS_ENUM_DICTIONARY} ........................................... #define QS_ENUM_DICTIONARY(value_, group_) \ (QS_enum_dict_pre_((value_), (group_), #value_)) -/*${QS-macros::QF_QS_CRIT_ENTRY} ...........................................*/ -/*! Output the critical section entry record */ -void QF_QS_CRIT_ENTRY(void); +//${QS-macros::QS_RX_PUT} .................................................... +#define QS_RX_PUT(b_) (QS_rxPut((b_))) + +//${QS-macros::QS_TR_CRIT_ENTRY} ............................................. +#define QS_TR_CRIT_ENTRY() -/*${QS-macros::QF_QS_CRIT_EXIT} ............................................*/ -/*! Output the critical section exit record */ -void QF_QS_CRIT_EXIT(void); +//${QS-macros::QS_TR_CRIT_EXIT} .............................................. +#define QS_TR_CRIT_EXIT() -/*${QS-macros::QF_QS_ISR_ENTRY} ............................................*/ -/*! Output the interrupt entry record */ -void QF_QS_ISR_ENTRY( - uint_fast8_t const isrnest, - uint_fast8_t const prio_); +//${QS-macros::QS_TR_ISR_ENTRY} .............................................. +#define QS_TR_ISR_ENTRY(isrnest, prio) do { \ + QS_BEGIN_PRE_(QS_QF_ISR_ENTRY, 0U) \ + QS_TIME_PRE_(); \ + QS_2u8_raw_(isrnest, prio); \ + QS_END_PRE_() \ +} -/*${QS-macros::QF_QS_ISR_EXIT} .............................................*/ -/*! Output the ISR exit trace record */ -void QF_QS_ISR_EXIT( +//${QS-macros::QS_TR_ISR_EXIT} ............................................... +void QS_TR_ISR_EXIT( uint_fast8_t isrnest, uint_fast8_t prio); -/*${QS-macros::QF_QS_ACTION} ...............................................*/ -/*! Execute an action that is only necessary for QS output */ -#define QF_QS_ACTION(act_) (act_) +//${QS-macros::QS_ONLY} ...................................................... +#define QS_ONLY(code_) (code_) + +//${QS-macros::QS_ASSERTION} ................................................. +#define QS_ASSERTION(module_, id_, delay_) \ + (QS_assertion_pre_((module_), (id_), (delay_))) -/*${QS-macros::QS_EOD} .....................................................*/ -/*! Constant representing End-Of-Data condition returned from the -* QS_getByte() function. -*/ +//${QS-macros::QS_EOD} ....................................................... #define QS_EOD ((uint16_t)0xFFFFU) -/*${QS-macros::QS_CMD} .....................................................*/ -/*! Constant representing command enumeration group -* in QS_ENUM_DICTIONARY() and QS_ENUM() -* @sa QS_onCommand() -*/ +//${QS-macros::QS_CMD} ....................................................... #define QS_CMD ((uint8_t)7U) -/*${QS-macros::QS_HEX_FMT} .................................................*/ -/*! Constant representing HEX format for the "width" filed -* in QS_U8(), QS_U16(), QS_U32(), and QS_U64(). -*/ +//${QS-macros::QS_HEX_FMT} ................................................... #define QS_HEX_FMT ((uint8_t)0x0FU) -/*$enddecl${QS-macros} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ - -/*==========================================================================*/ -/* Facilities for QS critical section */ - -/* QS-specific critical section */ -#ifdef QS_CRIT_ENTRY /* separate QS critical section defined? */ - -#ifndef QS_CRIT_STAT_TYPE - #define QS_CRIT_STAT_ - #define QS_CRIT_E_() QS_CRIT_ENTRY(dummy) - #define QS_CRIT_X_() QS_CRIT_EXIT(dummy); QS_REC_DONE() -#else - #define QS_CRIT_STAT_ QS_CRIT_STAT_TYPE critStat_; - #define QS_CRIT_E_() QS_CRIT_ENTRY(critStat_) - #define QS_CRIT_X_() QS_CRIT_EXIT(critStat_); QS_REC_DONE() -#endif /* QS_CRIT_STAT_TYPE */ - -#else /* separate QS critical section not defined--use the QF definition */ - -#ifndef QF_CRIT_STAT_TYPE - /*! This is an internal macro for defining the critical section - * status type. - * @details - * The purpose of this macro is to enable writing the same code for the - * case when critical section status type is defined and when it is not. - * If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro - * provides the definition of the critical section status variable. - * Otherwise this macro is empty. - * @sa #QF_CRIT_STAT_TYPE - */ - #define QS_CRIT_STAT_ - - /*! This is an internal macro for entering a critical section. - * @details - * The purpose of this macro is to enable writing the same code for the - * case when critical section status type is defined and when it is not. - * If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro - * invokes QF_CRIT_ENTRY() passing the key variable as the parameter. - * Otherwise QF_CRIT_ENTRY() is invoked with a dummy parameter. - * @sa QF_CRIT_ENTRY() - */ - #define QS_CRIT_E_() QF_CRIT_ENTRY(dummy) - - /*! This is an internal macro for exiting a critical section. - * @details - * The purpose of this macro is to enable writing the same code for the - * case when critical section status type is defined and when it is not. - * If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro - * invokes QF_CRIT_EXIT() passing the key variable as the parameter. - * Otherwise QF_CRIT_EXIT() is invoked with a dummy parameter. - * @sa QF_CRIT_EXIT() - */ - #define QS_CRIT_X_() QF_CRIT_EXIT(dummy); QS_REC_DONE() - -#elif (!defined QS_CRIT_STAT_) - - #define QS_CRIT_STAT_ QF_CRIT_STAT_TYPE critStat_; - #define QS_CRIT_E_() QF_CRIT_ENTRY(critStat_) - #define QS_CRIT_X_() QF_CRIT_EXIT(critStat_); QS_REC_DONE() - -#endif /* simple unconditional interrupt disabling used */ - -#endif /* separate QS critical section not defined */ - -/*==========================================================================*/ -/* Macros for use in QUTest only */ + +//${QS-macros::QS_CRIT_STAT} ................................................. +#ifndef QS_CRIT_STAT +#define QS_CRIT_STAT QF_CRIT_STAT +#endif // ndef QS_CRIT_STAT + +//${QS-macros::QS_CRIT_ENTRY} ................................................ +#ifndef QS_CRIT_ENTRY +#define QS_CRIT_ENTRY() QF_CRIT_ENTRY() +#endif // ndef QS_CRIT_ENTRY + +//${QS-macros::QS_CRIT_EXIT} ................................................. +#ifndef QS_CRIT_EXIT +#define QS_CRIT_EXIT() QF_CRIT_EXIT() +#endif // ndef QS_CRIT_EXIT + +//${QS-macros::QS_MEM_SYS} ................................................... +#ifndef QS_MEM_SYS +#define QS_MEM_SYS() QF_MEM_SYS() +#endif // ndef QS_MEM_SYS + +//${QS-macros::QS_MEM_APP} ................................................... +#ifndef QS_MEM_APP +#define QS_MEM_APP() QF_MEM_APP() +#endif // ndef QS_MEM_APP +//$enddecl${QS-macros} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +//============================================================================ +//! @cond INTERNAL + +typedef struct { + void const * locFilter_AP; //!< @deprecated + uint8_t * buf; + QSCtr end; + QSCtr volatile head; + QSCtr volatile tail; + QSCtr volatile used; + uint8_t volatile seq; + uint8_t volatile chksum; + uint8_t volatile critNest; + uint8_t flags; +} QS_Attr; + +extern QS_Attr QS_priv_; + +void QS_glbFilter_(int_fast16_t const filter); +void QS_locFilter_(int_fast16_t const filter); + +void QS_beginRec_(uint_fast8_t const rec); +void QS_endRec_(void); + +void QS_u8_raw_(uint8_t const d); +void QS_2u8_raw_( + uint8_t const d1, + uint8_t const d2); +void QS_u16_raw_(uint16_t const d); +void QS_u32_raw_(uint32_t const d); +void QS_u64_raw_(uint64_t const d); +void QS_obj_raw_(void const * const obj); +void QS_str_raw_(char const * const str); + +void QS_u8_fmt_( + uint8_t const format, + uint8_t const d); +void QS_u16_fmt_( + uint8_t const format, + uint16_t const d); +void QS_u32_fmt_( + uint8_t const format, + uint32_t const d); +void QS_u64_fmt_( + uint8_t const format, + uint64_t const d); +void QS_f32_fmt_( + uint8_t const format, + float32_t const f); +void QS_f64_fmt_( + uint8_t const format, + float64_t const d); +void QS_str_fmt_(char const * const str); +void QS_mem_fmt_( + uint8_t const * const blk, + uint8_t const size); + +void QS_sig_dict_pre_( + QSignal const sig, + void const * const obj, + char const * const name); +void QS_obj_dict_pre_( + void const * const obj, + char const * const name); +void QS_obj_arr_dict_pre_( + void const * const obj, + uint_fast16_t const idx, + char const * const name); +void QS_fun_dict_pre_( + QSpyFunPtr const fun, + char const * const name); +void QS_usr_dict_pre_( + enum_t const rec, + char const * const name); +void QS_enum_dict_pre_( + enum_t const value, + uint8_t const group, + char const * const name); + +void QS_assertion_pre_( + char const * const module, + int_t const id, + uint32_t const delay); + +void QS_target_info_pre_(uint8_t const isReset); + +//! @endcond +//============================================================================ + +//$declare${QS::QS-TX} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + +//${QS::QS-TX::preType} ...................................................... +//! Enumerates data elements for app-specific trace records +enum QS_preType { + QS_I8_ENUM_T, //!< signed 8-bit integer or enum format + QS_U8_T, //!< unsigned 8-bit integer format + QS_I16_T, //!< signed 16-bit integer format + QS_U16_T, //!< unsigned 16-bit integer format + QS_I32_T, //!< signed 32-bit integer format + QS_U32_T, //!< unsigned 32-bit integer format + QS_F32_T, //!< 32-bit floating point format + QS_F64_T, //!< 64-bit floating point format + QS_STR_T, //!< zero-terminated ASCII string format + QS_MEM_T, //!< up to 255-bytes memory block format + QS_SIG_T, //!< event signal format + QS_OBJ_T, //!< object pointer format + QS_FUN_T, //!< function pointer format + QS_I64_T, //!< signed 64-bit integer format + QS_U64_T //!< unsigned 64-bit integer format +}; + +//${QS::QS-TX::initBuf} ...................................................... +//! @static @public @memberof QS +void QS_initBuf( + uint8_t * const sto, + uint_fast32_t const stoSize); + +//${QS::QS-TX::getByte} ...................................................... +//! @static @public @memberof QS +uint16_t QS_getByte(void); + +//${QS::QS-TX::getBlock} ..................................................... +//! @static @public @memberof QS +uint8_t const * QS_getBlock(uint16_t * const pNbytes); + +//${QS::QS-TX::doOutput} ..................................................... +//! @static @public @memberof QS +void QS_doOutput(void); + +//${QS::QS-TX::onStartup} .................................................... +//! @static @public @memberof QS +uint8_t QS_onStartup(void const * arg); + +//${QS::QS-TX::onCleanup} .................................................... +//! @static @public @memberof QS +void QS_onCleanup(void); + +//${QS::QS-TX::onFlush} ...................................................... +//! @static @public @memberof QS +void QS_onFlush(void); + +//${QS::QS-TX::onGetTime} .................................................... +//! @static @public @memberof QS +QSTimeCtr QS_onGetTime(void); +//$enddecl${QS::QS-TX} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +//============================================================================ +//! @cond INTERNAL + +typedef struct { + void * currObj[8]; + uint8_t * buf; + QSCtr end; + QSCtr volatile head; + QSCtr volatile tail; #ifdef Q_UTEST + bool inTestLoop; +#endif +} QS_RxAttr; -/*$declare${QUTest} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ +//! @static @private @memberof QS +extern QS_RxAttr QS_rxPriv_; -/*${QUTest::QS::TProbe} ....................................................*/ -/*! @brief Test Probe attributes */ -struct QS_TProbe { - QSFun addr; - uint32_t data; - uint8_t idx; +//! @endcond +//============================================================================ + +//$declare${QS::QS-RX} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + +//${QS::QS-RX::QSpyObjKind} .................................................. +//! @static @public @memberof QS +//! Kinds of objects used in QS-RX +enum QS_QSpyObjKind { + SM_OBJ, //!< state machine object + AO_OBJ, //!< active object + MP_OBJ, //!< event pool object + EQ_OBJ, //!< raw queue object + TE_OBJ, //!< time event object + AP_OBJ, //!< generic Application-specific object + MAX_OBJ }; -/*${QUTest::QS::TestData} ..................................................*/ -/*! @brief QUTest data */ -struct QS_TestData { - struct QS_TProbe tpBuf[16]; /*!< buffer of Test-Probes received so far */ - uint8_t tpNum; /*!< current number of Test-Probes */ - QSTimeCtr testTime; /*!< test time (tick counter) */ +//${QS::QS-RX::OSpyObjComb} .................................................. +//! @static @public @memberof QS +//! Object combinations for QS-RX +enum QS_OSpyObjComb { + SM_AO_OBJ = (enum_t)MAX_OBJ //!< combination of SM and AO }; -/*${QUTest::QS::testData} ..................................................*/ -/*! QUTest data */ -extern struct QS_TestData QS_testData; +//${QS::QS-RX::rxInitBuf} .................................................... +//! @static @public @memberof QS +void QS_rxInitBuf( + uint8_t * const sto, + uint16_t const stoSize); -/*${QUTest::QS::test_pause_} ...............................................*/ -/*! internal function to pause test and enter the test event loop */ -void QS_test_pause_(void); +//${QS::QS-RX::rxPut} ........................................................ +//! @static @public @memberof QS +static inline bool QS_rxPut(uint8_t const b) { + // NOTE: does not need critical section + // But requires system-level memory access (QF_MEM_SYS()). -/*${QUTest::QS::getTestProbe_} .............................................*/ -/*! get the test probe data for the given API */ -uint32_t QS_getTestProbe_(QSpyFunPtr const api); + QSCtr head = QS_rxPriv_.head + 1U; + if (head == QS_rxPriv_.end) { + head = 0U; + } + if (head != QS_rxPriv_.tail) { // buffer NOT full? + QS_rxPriv_.buf[QS_rxPriv_.head] = b; + QS_rxPriv_.head = head; // update the head to a *valid* index + return true; // byte placed in the buffer + } + else { + return false; // byte NOT placed in the buffer + } +} -/*${QUTest::QS::onTestSetup} ...............................................*/ -/*! callback to setup a unit test inside the Target */ +//${QS::QS-RX::rxParse} ...................................................... +//! @static @public @memberof QS +void QS_rxParse(void); + +//${QS::QS-RX::rxGetNfree} ................................................... +//! @static @public @memberof QS +uint16_t QS_rxGetNfree(void); + +//${QS::QS-RX::doInput} ...................................................... +//! @static @public @memberof QS +void QS_doInput(void); + +//${QS::QS-RX::onReset} ...................................................... +//! @static @public @memberof QS +void QS_onReset(void); + +//${QS::QS-RX::onCommand} .................................................... +//! @static @public @memberof QS +void QS_onCommand( + uint8_t cmdId, + uint32_t param1, + uint32_t param2, + uint32_t param3); +//$enddecl${QS::QS-RX} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +//============================================================================ +#ifdef Q_UTEST + +//$declare${QS::QUTest} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + +//${QS::QUTest::TProbe} ...................................................... +// @struct TProbe +struct QS_TProbe { + QSFun addr; + uint32_t data; + uint8_t idx; +}; + +//${QS::QUTest::onTestSetup} ................................................. +//! @static @public @memberof QS void QS_onTestSetup(void); -/*${QUTest::QS::onTestTeardown} ............................................*/ -/*! callback to teardown after a unit test inside the Target */ +//${QS::QUTest::onTestTeardown} .............................................. +//! @static @public @memberof QS void QS_onTestTeardown(void); -/*${QUTest::QS::onTestEvt} .................................................*/ -/*! callback to "massage" the test event before dispatching/posting it */ +//${QS::QUTest::onTestEvt} ................................................... +//! @static @public @memberof QS void QS_onTestEvt(QEvt * e); -/*${QUTest::QS::onTestPost} ................................................*/ -/*! callback to examine an event that is about to be posted */ +//${QS::QUTest::onTestPost} .................................................. +//! @static @public @memberof QS void QS_onTestPost( void const * sender, QActive * recipient, QEvt const * e, bool status); -/*${QUTest::QS::onTestLoop} ................................................*/ -/*! callback to run the test loop */ +//${QS::QUTest::onTestLoop} .................................................. +//! @static @public @memberof QS void QS_onTestLoop(void); +//$enddecl${QS::QUTest} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -/*${QUTest::QUTEST_ON_POST} ................................................*/ -/*! record-ID for posting events */ #define QUTEST_ON_POST 124 -/*$enddecl${QUTest} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ - -/*--------------------------------------------------------------------------*/ -/* QP-stub for QUTest -* NOTE: The QP-stub is needed for unit testing QP applications, -* but might NOT be needed for testing QP itself. -*/ -#if Q_UTEST != 0 -/*$declare${QUTest-stub::QS} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ - -/*${QUTest-stub::QS::processTestEvts_} .....................................*/ -/*! internal function to process posted events during test */ -void QS_processTestEvts_(void); -/*$enddecl${QUTest-stub::QS} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -/*$declare${QUTest-stub::QHsmDummy} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ - -/*${QUTest-stub::QHsmDummy} ................................................*/ -/*! @brief QHsmDummy class -* @class QHsmDummy -* @extends QHsm -* -* @details -* ::QHsmDummy is a test double for the role of "Orthogonal Components" -* HSM objects in QUTest unit testing. -*/ + +//============================================================================ +//! @cond INTERNAL + +typedef struct { + struct QS_TProbe tpBuf[16]; + uint8_t tpNum; + QSTimeCtr testTime; + QPSet readySet; + QPSet readySet_dis; + uint_fast8_t intLock; +} QSTestAttr; + +extern QSTestAttr QS_tstPriv_; + +void QS_test_pause_(void); +uint32_t QS_getTestProbe_(QSpyFunPtr const api); + +//! @endcond +//============================================================================ + +// QP-stub for QUTest +// NOTE: The QP-stub is needed for unit testing QP applications, +// but might NOT be needed for testing QP itself. +#if (Q_UTEST != 0) + +//$declare${QS::QUTest-stub::QHsmDummy} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + +//${QS::QUTest-stub::QHsmDummy} .............................................. +//! @class QHsmDummy +//! @extends QHsm typedef struct { -/* protected: */ - QHsm super; +// protected: + QAsm super; } QHsmDummy; -/* public: */ +// public: -/*! Constructor of the QHsmDummy HSM class -* @public @memberof QHsmDummy -*/ +//! @public @memberof QHsmDummy void QHsmDummy_ctor(QHsmDummy * const me); -/*! override for QHsm_init_() -* @private @memberof QHsmDummy -*/ +//! @private @memberof QHsmDummy void QHsmDummy_init_( - QHsm * const me, + QAsm * const me, void const * const par, uint_fast8_t const qs_id); -/*! override for QHsm_dispatch_() -* @private @memberof QHsmDummy -*/ +// private: + +//! @private @memberof QHsmDummy void QHsmDummy_dispatch_( - QHsm * const me, + QAsm * const me, QEvt const * const e, uint_fast8_t const qs_id); -/*$enddecl${QUTest-stub::QHsmDummy} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -/*$declare${QUTest-stub::QActiveDummy} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ - -/*${QUTest-stub::QActiveDummy} .............................................*/ -/*! @brief QActiveDummy Object class -* @class QActiveDummy -* @extends QActive -* -* @details -* QActiveDummy is a test double for the role of collaborating active -* objects in QUTest unit testing. -*/ +//$enddecl${QS::QUTest-stub::QHsmDummy} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//$declare${QS::QUTest-stub::QActiveDummy} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + +//${QS::QUTest-stub::QActiveDummy} ........................................... +//! @class QActiveDummy +//! @extends QActive typedef struct { -/* protected: */ +// protected: QActive super; } QActiveDummy; -/* public: */ +// public: -/*! Constructor of the QActiveDummy Active Object class -* @public @memberof QActiveDummy -*/ +//! @public @memberof QActiveDummy void QActiveDummy_ctor(QActiveDummy * const me); -/*! override for QHsm_init_() -* @private @memberof QActiveDummy -*/ +// private: + +//! @private @memberof QActiveDummy void QActiveDummy_init_( - QHsm * const me, + QAsm * const me, void const * const par, uint_fast8_t const qs_id); -/*! override for QHsm_dispatch_() -* @private @memberof QActiveDummy -*/ +//! @private @memberof QActiveDummy void QActiveDummy_dispatch_( - QHsm * const me, + QAsm * const me, QEvt const * const e, uint_fast8_t const qs_id); -/*! override for QActive_start_() -* @private @memberof QActiveDummy -*/ -void QActiveDummy_start_( - QActive * const me, - QPrioSpec const prioSpec, - QEvt const * * const qSto, - uint_fast16_t const qLen, - void * const stkSto, - uint_fast16_t const stkSize, - void const * const par); - -/*! override for QActive_post_() -* @private @memberof QActiveDummy -*/ -bool QActiveDummy_post_( +//! @private @memberof QActiveDummy +bool QActiveDummy_fakePost_( QActive * const me, QEvt const * const e, uint_fast16_t const margin, void const * const sender); -/*! override for QActive_postLIFO_() -* @private @memberof QActiveDummy -*/ -void QActiveDummy_postLIFO_( +//! @private @memberof QActiveDummy +void QActiveDummy_fakePostLIFO_( QActive * const me, QEvt const * const e); -/*$enddecl${QUTest-stub::QActiveDummy} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -#endif /* Q_UTEST != 0 */ +//$enddecl${QS::QUTest-stub::QActiveDummy} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +#endif // Q_UTEST != 0 -/*! QS macro to define the Test-Probe for a given `fun_` */ #define QS_TEST_PROBE_DEF(fun_) \ uint32_t const qs_tp_ = QS_getTestProbe_((void (*)(void))(fun_)); -/*! QS macro to apply a Test-Probe */ #define QS_TEST_PROBE(code_) \ if (qs_tp_ != 0U) { code_ } -/*! QS macro to apply a Test-Probe */ #define QS_TEST_PROBE_ID(id_, code_) \ if (qs_tp_ == (uint32_t)(id_)) { code_ } -/*! QS macro to pause test execution and enter the test event-loop */ #define QS_TEST_PAUSE() (QS_test_pause_()) -#else /* Q_UTEST not defined */ +#else // Q_UTEST not defined -/* dummy definitions when not building for QUTEST */ +// dummy definitions when not building for QUTEST #define QS_TEST_PROBE_DEF(fun_) #define QS_TEST_PROBE(code_) #define QS_TEST_PROBE_ID(id_, code_) #define QS_TEST_PAUSE() ((void)0) -#endif /* Q_UTEST */ +#endif // Q_UTEST -#endif /* def QP_INC_QS_H_ */ +#endif // QS_H_ diff --git a/qspy/include/qpc_qs_pkg.h b/qspy/include/qpc_qs_pkg.h index 1d977a3..71bdcd4 100644 --- a/qspy/include/qpc_qs_pkg.h +++ b/qspy/include/qpc_qs_pkg.h @@ -1,156 +1,93 @@ -/*$file${include::qs_pkg.h} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/* -* Model: qpc.qm -* File: ${include::qs_pkg.h} -* -* This code has been generated by QM 5.2.3 . -* DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. -* -* This code is covered by the following QP license: -* License # : LicenseRef-QL-dual -* Issued to : Any user of the QP/C real-time embedded framework -* Framework(s) : qpc -* Support ends : 2023-12-31 -* License scope: -* -* Copyright (C) 2005 Quantum Leaps, LLC . -* -* SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial -* -* This software is dual-licensed under the terms of the open source GNU -* General Public License version 3 (or any later version), or alternatively, -* under the terms of one of the closed source Quantum Leaps commercial -* licenses. -* -* The terms of the open source GNU General Public License version 3 -* can be found at: -* -* The terms of the closed source Quantum Leaps commercial licenses -* can be found at: -* -* Redistributions in source code must retain this top-level comment block. -* Plagiarizing this software to sidestep the license obligations is illegal. -* -* Contact information: -* -* -*/ -/*$endhead${include::qs_pkg.h} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -/*! @file -* @brief Internal (package scope) QS/C interface. -*/ -#ifndef QP_INC_QS_PKG_H_ -#define QP_INC_QS_PKG_H_ - -/*==========================================================================*/ - -/*! QS received record types (RX channel) -* @details -* This enumeration specifies the record types for the QS receive channel -*/ +//$file${include::qs_pkg.h} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +// +// Model: qpc.qm +// File: ${include::qs_pkg.h} +// +// This code has been generated by QM 5.3.0 . +// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. +// +// This code is covered by the following QP license: +// License # : LicenseRef-QL-dual +// Issued to : Any user of the QP/C real-time embedded framework +// Framework(s) : qpc +// Support ends : 2024-12-31 +// License scope: +// +// Copyright (C) 2005 Quantum Leaps, LLC . +// +// Q u a n t u m L e a P s +// ------------------------ +// Modern Embedded Software +// +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial +// +// This software is dual-licensed under the terms of the open source GNU +// General Public License version 3 (or any later version), or alternatively, +// under the terms of one of the closed source Quantum Leaps commercial +// licenses. +// +// The terms of the open source GNU General Public License version 3 +// can be found at: +// +// The terms of the closed source Quantum Leaps commercial licenses +// can be found at: +// +// Redistributions in source code must retain this top-level comment block. +// Plagiarizing this software to sidestep the license obligations is illegal. +// +// Contact information: +// +// +// +//$endhead${include::qs_pkg.h} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#ifndef QS_PKG_H_ +#define QS_PKG_H_ + +//============================================================================ +//! @cond INTERNAL + +//! QS received record types (RX channel) enum QSpyRxRecords { - QS_RX_INFO, /*!< query Target info (ver, config, tstamp) */ - QS_RX_COMMAND, /*!< execute a user-defined command in the Target */ - QS_RX_RESET, /*!< reset the Target */ - QS_RX_TICK, /*!< call QTIMEEVT_TICK_X() in the Target */ - QS_RX_PEEK, /*!< peek Target memory */ - QS_RX_POKE, /*!< poke Target memory */ - QS_RX_FILL, /*!< fill Target memory */ - QS_RX_TEST_SETUP, /*!< test setup */ - QS_RX_TEST_TEARDOWN, /*!< test teardown */ - QS_RX_TEST_PROBE, /*!< set a Test-Probe in the Target */ - QS_RX_GLB_FILTER, /*!< set global filters in the Target */ - QS_RX_LOC_FILTER, /*!< set local filters in the Target */ - QS_RX_AO_FILTER, /*!< set local AO filter in the Target */ - QS_RX_CURR_OBJ, /*!< set the "current-object" in the Target */ - QS_RX_TEST_CONTINUE, /*!< continue a test after QS_TEST_PAUSE() */ - QS_RX_QUERY_CURR, /*!< query the "current object" in the Target */ - QS_RX_EVENT /*!< inject an event to the Target */ + QS_RX_INFO, //!< query Target info (ver, config, tstamp) + QS_RX_COMMAND, //!< execute a user-defined command in the Target + QS_RX_RESET, //!< reset the Target + QS_RX_TICK, //!< call system clock tick in the Target + QS_RX_PEEK, //!< peek Target memory + QS_RX_POKE, //!< poke Target memory + QS_RX_FILL, //!< fill Target memory + QS_RX_TEST_SETUP, //!< test setup + QS_RX_TEST_TEARDOWN, //!< test teardown + QS_RX_TEST_PROBE, //!< set a Test-Probe in the Target + QS_RX_GLB_FILTER, //!< set global filters in the Target + QS_RX_LOC_FILTER, //!< set local filters in the Target + QS_RX_AO_FILTER, //!< set local AO filter in the Target + QS_RX_CURR_OBJ, //!< set the "current-object" in the Target + QS_RX_TEST_CONTINUE, //!< continue a test after QS_TEST_PAUSE() + QS_RX_QUERY_CURR, //!< query the "current object" in the Target + QS_RX_EVENT //!< inject an event to the Target }; -/*==========================================================================*/ -/*! Frame character of the QS output protocol */ -#define QS_FRAME (0x7EU) - -/*! Escape character of the QS output protocol */ -#define QS_ESC (0x7DU) - -/*! The expected checksum value over a correct QS record */ -#define QS_GOOD_CHKSUM (0xFFU) +//---------------------------------------------------------------------------- +#define QS_FRAME 0x7EU +#define QS_ESC 0x7DU +#define QS_ESC_XOR 0x20U +#define QS_GOOD_CHKSUM 0xFFU -/*! Escape modifier of the QS output protocol */ -/** -* @details -* The escaped byte is XOR-ed with the escape modifier before it is inserted -* into the QS buffer. -*/ -#define QS_ESC_XOR (0x20U) - -/*==========================================================================*/ -/*! Internal QS macro to begin a predefined QS record with -* entering critical section. -* -* @note This macro is intended to use only inside QP components and NOT -* at the application level. -* @sa QS_BEGIN_ID() -*/ -#define QS_BEGIN_PRE_(rec_, qs_id_) \ +//---------------------------------------------------------------------------- +#define QS_BEGIN_PRE_(rec_, qs_id_) \ if (QS_GLB_CHECK_(rec_) && QS_LOC_CHECK_(qs_id_)) { \ - QS_CRIT_E_(); \ QS_beginRec_((uint_fast8_t)(rec_)); +#define QS_END_PRE_() QS_endRec_(); } -/*! Internal QS macro to end a predefined QS record with -* exiting critical section. -* -* @note This macro is intended to use only inside QP components and NOT -* at the application level. -* @sa QS_END() -*/ -#define QS_END_PRE_() \ - QS_endRec_(); \ - QS_CRIT_X_(); \ - } - -/*! Internal macro to begin a predefined QS record without -* entering critical section. -* -* @note This macro is intended to use only inside QP components and NOT -* at the application level. -* @sa QS_BEGIN_NOCRIT() -*/ -#define QS_BEGIN_NOCRIT_PRE_(rec_, qs_id_) \ - if (QS_GLB_CHECK_(rec_) && QS_LOC_CHECK_(qs_id_)) { \ - QS_beginRec_((uint_fast8_t)(rec_)); - -/*! Internal QS macro to end a predefined QS record without -* exiting critical section -* -* @note This macro is intended to use only inside QP components and NOT -* at the application level. @sa #QS_END_NOCRIT -*/ -#define QS_END_NOCRIT_PRE_() QS_endRec_(); } - -/*! Internal QS macro to output a predefined uint8_t data element */ #define QS_U8_PRE_(data_) (QS_u8_raw_((uint8_t)(data_))) - -/*! Internal QS macro to output 2 predefined uint8_t data elements */ #define QS_2U8_PRE_(data1_, data2_) \ (QS_2u8_raw_((uint8_t)(data1_), (uint8_t)(data2_))) - -/*! Internal QS macro to output an predefined uint16_t data element */ #define QS_U16_PRE_(data_) (QS_u16_raw_((uint16_t)(data_))) - -/*! Internal QS macro to output a predefined uint32_t data element */ #define QS_U32_PRE_(data_) (QS_u32_raw_((uint32_t)(data_))) - -/*! Internal QS macro to output a predefined zero-terminated string element */ #define QS_STR_PRE_(msg_) (QS_str_raw_((msg_))) +#define QS_OBJ_PRE_(obj_) (QS_obj_raw_(obj_)) #if (!defined Q_SIGNAL_SIZE || (Q_SIGNAL_SIZE == 1U)) - /*! Internal macro to output an unformatted event signal data element */ - /** - * @note the size of the pointer depends on the macro #Q_SIGNAL_SIZE. - */ #define QS_SIG_PRE_(sig_) (QS_u8_raw_((uint8_t)sig_)) #elif (Q_SIGNAL_SIZE == 2U) #define QS_SIG_PRE_(sig_) (QS_u16_raw_((uint16_t)sig_)) @@ -158,97 +95,58 @@ enum QSpyRxRecords { #define QS_SIG_PRE_(sig_) (QS_u32_raw_((uint32_t)sig_)) #endif -#define QS_OBJ_PRE_(obj_) (QS_obj_raw_(obj_)) - -#if (!defined QS_FUN_PTR_SIZE || (QS_FUN_PTR_SIZE == 1U)) - #define QS_FUN_PRE_(fun_) (QS_u8_raw_((uint8_t)(fun_))) -#elif (QS_FUN_PTR_SIZE == 2U) +#if (!defined QS_FUN_PTR_SIZE || (QS_FUN_PTR_SIZE == 2U)) #define QS_FUN_PRE_(fun_) (QS_u16_raw_((uint16_t)(fun_))) #elif (QS_FUN_PTR_SIZE == 4U) #define QS_FUN_PRE_(fun_) (QS_u32_raw_((uint32_t)(fun_))) #elif (QS_FUN_PTR_SIZE == 8U) #define QS_FUN_PRE_(fun_) (QS_u64_raw_((uint64_t)(fun_))) #else - /*! Internal macro to output an unformatted function pointer */ - /** @note the size of the pointer depends on the macro #QS_FUN_PTR_SIZE. - * If the size is not defined the size of pointer is assumed 4-bytes. - */ #define QS_FUN_PRE_(fun_) (QS_u32_raw_((uint32_t)(fun_))) #endif -/*==========================================================================*/ +//---------------------------------------------------------------------------- #if (!defined QF_EQUEUE_CTR_SIZE || (QF_EQUEUE_CTR_SIZE == 1U)) - - /*! Internal QS macro to output an unformatted event queue counter - * data element. */ - /** - * @note the counter size depends on the macro #QF_EQUEUE_CTR_SIZE. - */ - #define QS_EQC_PRE_(ctr_) QS_u8_raw_((uint8_t)(ctr_)) + #define QS_EQC_PRE_(ctr_) QS_u8_raw_((uint8_t)(ctr_)) #elif (QF_EQUEUE_CTR_SIZE == 2U) - #define QS_EQC_PRE_(ctr_) QS_u16_raw_((uint16_t)(ctr_)) + #define QS_EQC_PRE_(ctr_) QS_u16_raw_((uint16_t)(ctr_)) #elif (QF_EQUEUE_CTR_SIZE == 4U) - #define QS_EQC_PRE_(ctr_) QS_u32_raw_((uint32_t)(ctr_)) + #define QS_EQC_PRE_(ctr_) QS_u32_raw_((uint32_t)(ctr_)) #endif #if (!defined QF_EVENT_SIZ_SIZE || (QF_EVENT_SIZ_SIZE == 1U)) - - /*! Internal QS macro to output an unformatted event size - * data element. */ - /** - * @note the event size depends on the macro #QF_EVENT_SIZ_SIZE. - */ - #define QS_EVS_PRE_(size_) QS_u8_raw_((uint8_t)(size_)) + #define QS_EVS_PRE_(size_) QS_u8_raw_((uint8_t)(size_)) #elif (QF_EVENT_SIZ_SIZE == 2U) - #define QS_EVS_PRE_(size_) QS_u16_raw_((uint16_t)(size_)) + #define QS_EVS_PRE_(size_) QS_u16_raw_((uint16_t)(size_)) #elif (QF_EVENT_SIZ_SIZE == 4U) - #define QS_EVS_PRE_(size_) QS_u32_raw_((uint32_t)(size_)) + #define QS_EVS_PRE_(size_) QS_u32_raw_((uint32_t)(size_)) #endif #if (!defined QF_MPOOL_SIZ_SIZE || (QF_MPOOL_SIZ_SIZE == 1U)) - - /*! Internal QS macro to output an unformatted memory pool - * block-size data element */ - /** - * @note the block-size depends on the macro #QF_MPOOL_SIZ_SIZE. - */ - #define QS_MPS_PRE_(size_) QS_u8_raw_((uint8_t)(size_)) + #define QS_MPS_PRE_(size_) QS_u8_raw_((uint8_t)(size_)) #elif (QF_MPOOL_SIZ_SIZE == 2U) - #define QS_MPS_PRE_(size_) QS_u16_raw_((uint16_t)(size_)) + #define QS_MPS_PRE_(size_) QS_u16_raw_((uint16_t)(size_)) #elif (QF_MPOOL_SIZ_SIZE == 4U) - #define QS_MPS_PRE_(size_) QS_u32_raw_((uint32_t)(size_)) + #define QS_MPS_PRE_(size_) QS_u32_raw_((uint32_t)(size_)) #endif #if (!defined QF_MPOOL_CTR_SIZE || (QF_MPOOL_CTR_SIZE == 1U)) - - /*! Internal QS macro to output an unformatted memory pool - * block-counter data element. */ - /** - * @note the counter size depends on the macro #QF_MPOOL_CTR_SIZE. - */ - #define QS_MPC_PRE_(ctr_) QS_u8_raw_((uint8_t)(ctr_)) + #define QS_MPC_PRE_(ctr_) QS_u8_raw_((uint8_t)(ctr_)) #elif (QF_MPOOL_CTR_SIZE == 2U) - #define QS_MPC_PRE_(ctr_) QS_u16_raw_((uint16_t)(ctr_)) + #define QS_MPC_PRE_(ctr_) QS_u16_raw_((uint16_t)(ctr_)) #elif (QF_MPOOL_CTR_SIZE == 4U) - #define QS_MPC_PRE_(ctr_) QS_u32_raw_((uint16_t)(ctr_)) + #define QS_MPC_PRE_(ctr_) QS_u32_raw_((uint16_t)(ctr_)) #endif #if (!defined QF_TIMEEVT_CTR_SIZE || (QF_TIMEEVT_CTR_SIZE == 1U)) - - /*! Internal QS macro to output an unformatted time event - * tick-counter data element */ - /** - * @note the counter size depends on the macro #QF_TIMEEVT_CTR_SIZE. - */ - #define QS_TEC_PRE_(ctr_) QS_u8_raw_((uint8_t)(ctr_)) + #define QS_TEC_PRE_(ctr_) QS_u8_raw_((uint8_t)(ctr_)) #elif (QF_TIMEEVT_CTR_SIZE == 2U) - #define QS_TEC_PRE_(ctr_) QS_u16_raw_((uint16_t)(ctr_)) + #define QS_TEC_PRE_(ctr_) QS_u16_raw_((uint16_t)(ctr_)) #elif (QF_TIMEEVT_CTR_SIZE == 4U) - #define QS_TEC_PRE_(ctr_) QS_u32_raw_((uint32_t)(ctr_)) + #define QS_TEC_PRE_(ctr_) QS_u32_raw_((uint32_t)(ctr_)) #endif -/*==========================================================================*/ -/*! Internal QS macro to insert an un-escaped byte into the QS buffer */ +//---------------------------------------------------------------------------- #define QS_INSERT_BYTE_(b_) \ buf[head] = (b_); \ ++head; \ @@ -256,7 +154,6 @@ enum QSpyRxRecords { head = 0U; \ } -/*! Internal QS macro to insert an escaped byte into the QS buffer */ #define QS_INSERT_ESC_BYTE_(b_) \ chksum = (uint8_t)(chksum + (b_)); \ if (((b_) != QS_FRAME) && ((b_) != QS_ESC)) { \ @@ -268,4 +165,12 @@ enum QSpyRxRecords { ++QS_priv_.used; \ } -#endif /* QP_INC_QS_PKG_H_ */ +//---------------------------------------------------------------------------- +#if (defined Q_UTEST) && (Q_UTEST != 0) +void QS_processTestEvts_(void); +#endif // Q_UTEST != 0 + +//! @endcond +//============================================================================ + +#endif // QS_PKG_H_ diff --git a/qspy/include/qspy.h b/qspy/include/qspy.h index 3654fb8..816b551 100644 --- a/qspy/include/qspy.h +++ b/qspy/include/qspy.h @@ -23,8 +23,8 @@ * ============================================================================*/ /*! -* @date Last updated on: 2023-01-19 -* @version Last updated for version: 7.2.1 +* @date Last updated on: 2023-08-20 +* @version Last updated for version: 7.3.0 * * @file * @brief Host API @@ -32,7 +32,7 @@ #ifndef QSPY_H_ #define QSPY_H_ -#define QSPY_VER "7.2.1" +#define QSPY_VER "7.3.0" #ifdef __cplusplus extern "C" { @@ -44,6 +44,9 @@ typedef enum { QSPY_SUCCESS } QSpyStatus; +/*! typedef for inclusion of qpc_qs.h */ +typedef uint16_t QSignal; + /*! QSPY record being processed */ typedef struct { uint8_t const *start; /*!< start of the record */ diff --git a/qspy/posix/qspy_pal.c b/qspy/posix/qspy_pal.c index 492dbcd..54b04e9 100644 --- a/qspy/posix/qspy_pal.c +++ b/qspy/posix/qspy_pal.c @@ -23,13 +23,13 @@ * ============================================================================*/ /*! -* @date Last updated on: 2022-01-25 -* @version Last updated for version: 7.0.0 +* @date Last updated on: 2023-03-12 +* @version Last updated for version: 7.2.2 * * @file * @brief QSPY PAL implementation for POSIX */ -#include /* for system() */ +#include /* for system() */ #include #include #include @@ -746,6 +746,12 @@ QSPYEvtType PAL_receiveBe(unsigned char *buf, uint32_t *pBytes) { return QSPY_ERROR_EVT; } else if (l_feAddrSize == 0) { /* not attached yet? */ + if (feAddrSize > sizeof(l_feAddr)) { + SNPRINTF_LINE(" ERROR UDP address error size=%d", + feAddrSize); + QSPY_printError(); + return QSPY_ERROR_EVT; + } memcpy(&l_feAddr, &feAddr, feAddrSize); l_feAddrSize = feAddrSize; /* attach connection */ *pBytes = nBytes; diff --git a/qspy/source/qspy.c b/qspy/source/qspy.c index 03d2244..88ae79f 100644 --- a/qspy/source/qspy.c +++ b/qspy/source/qspy.c @@ -23,8 +23,8 @@ * ============================================================================*/ /*! -* @date Last updated on: 2023-01-19 -* @version Last updated for version: 7.2.1 +* @date Last updated on: 2023-08-20 +* @version Last updated for version: 7.3.0 * * @file * @brief QSPY host utility: main parser diff --git a/qspy/source/qspy_main.c b/qspy/source/qspy_main.c index b500404..e7c0285 100644 --- a/qspy/source/qspy_main.c +++ b/qspy/source/qspy_main.c @@ -23,8 +23,8 @@ * ============================================================================*/ /*! -* @date Last updated on: 2023-01-11 -* @version Last updated for version: 7.2.0 +* @date Last updated on: 2023-08-22 +* @version Last updated for version: 7.3.0 * * @file * @brief main for QSPY host utility @@ -234,9 +234,9 @@ static void cleanup(void) { } /*..........................................................................*/ -void Q_onAssert(char const * const module, int loc) { +void Q_onError(char const * const module, int const id) { PRINTF_S("\n QSPY ASSERTION failed in Module=%s:%d\n", - module, loc); + module, id); cleanup(); exit(-1); } @@ -340,6 +340,7 @@ static QSpyStatus configure(int argc, char *argv[]) { case 'u': { /* UDP control port */ if (optarg != NULL) { /* is optional argument provided? */ l_bePort = (int)strtoul(optarg, NULL, 10); + PRINTF_S("-u %d\n", l_bePort); } else { /* apply the default */ l_bePort = 7701; @@ -550,7 +551,6 @@ static QSpyStatus configure(int argc, char *argv[]) { /* configure QSPY ......................................................*/ /* open Back-End link. NOTE: must happen *before* opening Target link */ if (l_bePort != 0) { - PRINTF_S("-u %d\n", l_bePort); if (PAL_openBE(l_bePort) == QSPY_ERROR) { return QSPY_ERROR; } @@ -558,9 +558,7 @@ static QSpyStatus configure(int argc, char *argv[]) { /* open Target link... */ switch (l_link) { - case NO_LINK: - PRINTF_S("-t %d\n", l_tcpPort); /* -t is the default link */ - /* fall through */ + case NO_LINK: /* fall through */ case TCP_LINK: { /* connect to the Target via TCP socket */ if (PAL_openTargetTcp(l_tcpPort) != QSPY_SUCCESS) { return QSPY_ERROR; diff --git a/qspy/win32/qspy_pal.c b/qspy/win32/qspy_pal.c index bfa6ce0..dd2d91f 100644 --- a/qspy/win32/qspy_pal.c +++ b/qspy/win32/qspy_pal.c @@ -23,8 +23,8 @@ * ============================================================================*/ /*! -* @date Last updated on: 2022-01-25 -* @version Last updated for version: 7.0.0 +* @date Last updated on: 2023-03-12 +* @version Last updated for version: 7.2.2 * * @file * @brief QSPY PAL implementation for Win32 @@ -708,6 +708,12 @@ QSPYEvtType PAL_receiveBe(unsigned char *buf, uint32_t *pBytes) { } } else if (l_feAddrSize == 0) { /* not attached yet? */ + if (feAddrSize > sizeof(l_feAddr)) { + SNPRINTF_LINE(" ERROR UDP address error size=%d", + feAddrSize); + QSPY_printError(); + return QSPY_ERROR_EVT; + } memcpy(&l_feAddr, &feAddr, feAddrSize); l_feAddrSize = feAddrSize; /* attach connection */ *pBytes = (uint32_t)status; diff --git a/qutest/qutest_dsl.py b/qutest/qutest_dsl.py index b77218c..8598af6 100644 --- a/qutest/qutest_dsl.py +++ b/qutest/qutest_dsl.py @@ -42,7 +42,7 @@ # **relative** to the test script. # # @usage -# @code{.py} +# @code{py} # include("test_include.pyi") # file in the same directory as the script # ~ ~ ~ # include("../my_include/test_include.pyi") # relative directory @@ -63,7 +63,7 @@ def include(fname): # executed test script ("test group"). # # @usage -# @code{.py} +# @code{py} # file_name = test_file() # @endcode def test_file(): @@ -74,7 +74,7 @@ def test_file(): # the directory name of the currently executed test script ("test group"). # # @usage -# @code{.py} +# @code{py} # dir_name = test_dir() # @endcode def test_dir(): @@ -88,7 +88,7 @@ def test_dir(): # @param[in] opt options {0=default, NORESET} # # @usage -# @code{.py} +# @code{py} # test("my first test") # test with title and with full target reset # ~ ~ ~ # test("my second test", NORESET) # test without target reset @@ -115,7 +115,7 @@ def scenario(title, opt=0): # errors, such as commands and parameters coded in the skipped tests. # # @usage -# @code{.py} +# @code{py} # test("my first test") # ~ ~ ~ # skip(1) # skip one subsequent test @@ -185,7 +185,7 @@ def ensure(bool_expr): # it is positive, and cleared with it is preceded with the minus (`-`) sign. #
# The filter list can contain the following: -# @code{.py} +# @code{py} # GRP_ALL # all Record-Types # GRP_SM # State Machine Record-Types # GRP_AO # Active Object Record-Types @@ -230,7 +230,7 @@ def glb_filter(*args): # cleared with it is preceded with the minus (`-`) sign.
# # This parameter can take one of the following values: -# @code{.py} +# @code{py} # IDS_ALL # all QS-IDs # IDS_AO # Active Object QS-IDs (1..64) # IDS_EP # Event Pool QS-IDs (65-80) @@ -284,7 +284,7 @@ def ao_filter(obj_id): # @param[in] obj_kind Kind of object to set
# # This parameter can take one of the following values: -# @code{.py} +# @code{py} # OBJ_SM # State Machine object # OBJ_AO # Active Object object # OBJ_MP # Memory Pool object @@ -315,7 +315,7 @@ def current_obj(obj_kind, obj_id): # @param[in] obj_kind Kind of object to query # # This parameter can take one of the following values: -# @code{.py} +# @code{py} # OBJ_SM # State Machine object # OBJ_AO # Active Object object # OBJ_MP # Memory Pool object @@ -326,7 +326,7 @@ def current_obj(obj_kind, obj_id): # @usage # The queries for various objects generate the following QS trace records # from the Target -# @code{.py} +# @code{py} # query_curr(OBJ_SM) # "@timestamp Query-SM Obj=,State=" # query_curr(OBJ_AO) @@ -446,7 +446,7 @@ def command(cmdId, param1=0, param2=0, param3=0): # @param[in] params the parameters of the "initialization event" # # @usage -# @code{.py} +# @code{py} # init() # init("MY_SIG") # init("MY_SIG", pack("C-SPY 2 - 28 + 32 1 1 - - + + + + + @@ -486,7 +498,7 @@ IJET_ID 2 - 8 + 9 1 1 + + + + + + + + + + + + + @@ -916,7 +980,7 @@ LMIFTDI_ID 2 - 2 + 3 1 1 + + + + + + + NULINK_ID + 2 + + 0 + 1 + 1 + + + @@ -974,7 +1072,7 @@ STLINK_ID 2 - 4 + 8 1 1 + + + + @@ -1185,7 +1300,7 @@ XDS100_ID 2 - 6 + 9 1 1 + + + + @@ -1362,6 +1493,18 @@ $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin 0 + + $TOOLKIT_DIR$\plugins\rtos\FreeRtos\FreeRtosArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin2.ENU.ewplugin + 0 + $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin 0 @@ -1371,11 +1514,15 @@ 0 - $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin + $TOOLKIT_DIR$\plugins\rtos\SMX\smxAwareIarArm9.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SMX\smxAwareIarArm9BE.ewplugin 0 - $TOOLKIT_DIR$\plugins\rtos\TI-RTOS\tirtosplugin.ewplugin + $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin 0 @@ -1391,11 +1538,11 @@ 0 - $EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin - 1 + $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin + 0 - $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin + $EW_DIR$\common\plugins\TargetAccessServer\TargetAccessServer.ENU.ewplugin 0 @@ -1414,7 +1561,7 @@ C-SPY 2 - 28 + 32 1 0 - - + + + + + @@ -1889,7 +2048,7 @@ IJET_ID 2 - 8 + 9 1 0 + + + + + + + + + + + + + @@ -2319,7 +2530,7 @@ LMIFTDI_ID 2 - 2 + 3 1 0 + + + + + + + NULINK_ID + 2 + + 0 + 1 + 0 + + + @@ -2377,7 +2622,7 @@ STLINK_ID 2 - 4 + 8 1 0 + + + + @@ -2588,7 +2850,7 @@ XDS100_ID 2 - 6 + 9 1 0 + + + + @@ -2765,6 +3043,18 @@ $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin 0 + + $TOOLKIT_DIR$\plugins\rtos\FreeRtos\FreeRtosArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\Mbed\MbedArmPlugin2.ENU.ewplugin + 0 + $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin 0 @@ -2774,11 +3064,15 @@ 0 - $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin + $TOOLKIT_DIR$\plugins\rtos\SMX\smxAwareIarArm9.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SMX\smxAwareIarArm9BE.ewplugin 0 - $TOOLKIT_DIR$\plugins\rtos\TI-RTOS\tirtosplugin.ewplugin + $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin 0 @@ -2794,11 +3088,11 @@ 0 - $EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin - 1 + $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin + 0 - $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin + $EW_DIR$\common\plugins\TargetAccessServer\TargetAccessServer.ENU.ewplugin 0 diff --git a/qwin/ek-lm3s811/qwin_demo.ewp b/qwin/ek-lm3s811/qwin_demo.ewp index a1aa0d2..2bfff69 100644 --- a/qwin/ek-lm3s811/qwin_demo.ewp +++ b/qwin/ek-lm3s811/qwin_demo.ewp @@ -11,9 +11,13 @@ General 3 - 28 + 35 1 1 + - - - - - + + + + + + + + ICCARM 2 - 34 + 37 1 1 - - - + + AARM 2 - 10 + 11 1 1 + @@ -653,13 +666,9 @@ 0 + inputOutputBased - - BICOMP - 0 - - BUILDACTION 1 @@ -672,17 +681,13 @@ ILINK 0 - 20 + 27 1 1 - + + + + + + + + + + + + + + + @@ -1008,7 +1073,7 @@ - BILINK + Coder 0 @@ -1023,9 +1088,13 @@ General 3 - 28 + 35 1 0 + - - - - - + + + + + + + + ICCARM 2 - 34 + 37 1 0 - - - + + AARM 2 - 10 + 11 1 0 + @@ -1666,13 +1744,9 @@ 0 + inputOutputBased - - BICOMP - 0 - - BUILDACTION 1 @@ -1685,17 +1759,13 @@ ILINK 0 - 20 + 27 1 0 - + + + + + + + + + + + + + + + @@ -2021,7 +2151,7 @@ - BILINK + Coder 0