mirror of
https://github.com/QuantumLeaps/qpc.git
synced 2025-01-28 07:03:10 +08:00
1602 lines
58 KiB
C
1602 lines
58 KiB
C
/*$file${include::qs.h} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
|
|
/*
|
|
* Model: qpc.qm
|
|
* File: ${include::qs.h}
|
|
*
|
|
* This code has been generated by QM 5.2.1 <www.state-machine.com/qm>.
|
|
* 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 <state-machine.com>.
|
|
*
|
|
* 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: <www.gnu.org/licenses/gpl-3.0>
|
|
*
|
|
* The terms of the closed source Quantum Leaps commercial licenses
|
|
* can be found at: <www.state-machine.com/licensing>
|
|
*
|
|
* Redistributions in source code must retain this top-level comment block.
|
|
* Plagiarizing this software to sidestep the license obligations is illegal.
|
|
*
|
|
* Contact information:
|
|
* <www.state-machine.com/licensing>
|
|
* <info@state-machine.com>
|
|
*/
|
|
/*$endhead${include::qs.h} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
|
|
/*!
|
|
* @date Last updated on: 2022-07-24
|
|
* @version Last updated for: @ref qpc_7_0_1
|
|
*
|
|
* @file
|
|
* @brief QS/C platform-independent public interface.
|
|
*/
|
|
#ifndef QS_H
|
|
#define QS_H
|
|
|
|
#ifndef Q_SPY
|
|
#error "Q_SPY must be defined to include qs.h"
|
|
#endif
|
|
|
|
/*==========================================================================*/
|
|
/*$declare${QS-config} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
|
|
|
|
/*${QS-config::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.
|
|
*/
|
|
#ifndef QS_TIME_SIZE
|
|
#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::QSTimeCtr} .........................................................*/
|
|
/*! QS time stamp type, which determines the dynamic range of QS time stamps */
|
|
#if (QS_TIME_SIZE == 4U)
|
|
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) */
|
|
|
|
/*${QS::QSTimeCtr} .........................................................*/
|
|
#if (QS_TIME_SIZE == 1U)
|
|
typedef uint8_t QSTimeCtr;
|
|
#endif /* (QS_TIME_SIZE == 1U) */
|
|
|
|
/*${QS::QSFun} .............................................................*/
|
|
/*! QS function pointer type (for serializing function pointers) */
|
|
#if (QS_FUN_PTR_SIZE == 4U)
|
|
typedef uint32_t QSFun;
|
|
#endif /* (QS_FUN_PTR_SIZE == 4U) */
|
|
|
|
/*${QS::QSFun} .............................................................*/
|
|
#if (QS_FUN_PTR_SIZE == 8U)
|
|
typedef uint64_t QSFun;
|
|
#endif /* (QS_FUN_PTR_SIZE == 8U) */
|
|
|
|
/*${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::QSCtr} .............................................................*/
|
|
/*! QS ring buffer counter and offset type */
|
|
typedef uint_fast16_t QSCtr;
|
|
|
|
/*${QS::QSpyPre} ...........................................................*/
|
|
/*! QS pre-defined record types (TX channel)
|
|
*
|
|
* @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
|
|
*/
|
|
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 an 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_MUTEX_LOCK, /*!< a mutex was locked */
|
|
QS_MUTEX_UNLOCK, /*!< a mutex was unlocked */
|
|
QS_SCHED_LOCK, /*!< scheduler was locked */
|
|
QS_SCHED_UNLOCK, /*!< scheduler was unlocked */
|
|
QS_SCHED_NEXT, /*!< scheduler found next task to execute */
|
|
QS_SCHED_IDLE, /*!< scheduler became idle */
|
|
QS_SCHED_RESUME, /*!< scheduler resumed previous task (not idle) */
|
|
|
|
/* [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 */
|
|
|
|
QS_MAX, /*!< the number of reserved signals */
|
|
};
|
|
|
|
/*${QS::QSpyGroups} ........................................................*/
|
|
/*! QS 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_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() */
|
|
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::QSpyIdOffsets} .....................................................*/
|
|
/*! 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::QSpyIdGroups} ......................................................*/
|
|
/*! 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::QSpyFunPtr} ........................................................*/
|
|
/*! function pointer type for QS_fun_dict_pre_() */
|
|
typedef void (* QSpyFunPtr )(void);
|
|
|
|
/*${QS::QS_EOD} ............................................................*/
|
|
/*! Constant representing End-Of-Data condition returned from the
|
|
* QS_getByte() function.
|
|
*/
|
|
#define QS_EOD ((uint16_t)0xFFFFU)
|
|
|
|
/*${QS::QSpyId} ............................................................*/
|
|
/*! @brief QS ID type for applying local filtering */
|
|
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;
|
|
} QS_tx;
|
|
|
|
/*${QS::QS-tx::preType} ....................................................*/
|
|
/*! Enumerates data formats recognized by QS
|
|
*
|
|
* @details
|
|
* QS uses this enumeration is used only internally for the formatted
|
|
* user data elements.
|
|
*/
|
|
enum QS_preType {
|
|
QS_I8_T, /*!< signed 8-bit integer 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_HEX_FMT /*!< HEX format for the "width" filed */
|
|
};
|
|
|
|
/*${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 data buffer
|
|
* @static @private @memberof QS
|
|
*
|
|
* @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.
|
|
*
|
|
* @note
|
|
* 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_fast16_t const stoSize);
|
|
|
|
/*${QS::QS-tx::getByte} ....................................................*/
|
|
/*! Byte-oriented interface to the QS data buffer
|
|
* @static @private @memberof QS
|
|
*
|
|
* @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 data buffer
|
|
* @static @private @memberof QS
|
|
*
|
|
* @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.
|
|
*
|
|
* @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 @private @memberof QS
|
|
*
|
|
* @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 @private @memberof QS
|
|
*
|
|
* @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 @private @memberof QS
|
|
*/
|
|
void QS_doOutput(void);
|
|
|
|
/*${QS::QS-tx::beginRec_} ..................................................*/
|
|
/*! Mark the begin of a QS record @p rec
|
|
* @static @private @memberof QS
|
|
*
|
|
* @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
|
|
*
|
|
* @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
|
|
*/
|
|
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
|
|
*/
|
|
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
|
|
*/
|
|
void QS_u16_raw_(uint16_t d);
|
|
|
|
/*${QS::QS-tx::u32_raw_} ...................................................*/
|
|
/*! output uint32_t data element without format information
|
|
* @static @private @memberof QS
|
|
*/
|
|
void QS_u32_raw_(uint32_t d);
|
|
|
|
/*${QS::QS-tx::obj_raw_} ...................................................*/
|
|
/*! Output obj pointer data element without format information
|
|
* @static @private @memberof QS
|
|
*
|
|
* @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
|
|
*
|
|
* @note This function is only to be used through macros, never in the
|
|
* client code directly.
|
|
*/
|
|
void QS_str_raw_(char const * str);
|
|
|
|
/*${QS::QS-tx::u8_fmt_} ....................................................*/
|
|
/*! Output uint8_t data element with format information
|
|
* @static @private @memberof QS
|
|
*
|
|
* @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
|
|
*
|
|
* @details
|
|
* This function is only to be used through macros, never in the
|
|
* client code directly.
|
|
*/
|
|
void QS_u16_fmt_(
|
|
uint8_t format,
|
|
uint16_t d);
|
|
|
|
/*${QS::QS-tx::u32_fmt_} ...................................................*/
|
|
/*! Output uint32_t data element with format information
|
|
* @static @private @memberof QS
|
|
*
|
|
* @note This function is only to be used through macros, never in the
|
|
* client code directly.
|
|
*/
|
|
void QS_u32_fmt_(
|
|
uint8_t format,
|
|
uint32_t d);
|
|
|
|
/*${QS::QS-tx::str_fmt_} ...................................................*/
|
|
/*! Output formatted zero-terminated ASCII string to the QS record
|
|
* @static @private @memberof QS
|
|
*/
|
|
void QS_str_fmt_(char const * str);
|
|
|
|
/*${QS::QS-tx::mem_fmt_} ...................................................*/
|
|
/*! Output formatted memory block of up to 255 bytes to the QS record
|
|
* @static @private @memberof QS
|
|
*/
|
|
void QS_mem_fmt_(
|
|
uint8_t const * blk,
|
|
uint8_t size);
|
|
|
|
/*${QS::QS-tx::sig_dict_pre_} ..............................................*/
|
|
/*! Output predefined signal-dictionary record
|
|
* @static @private @memberof QS
|
|
*
|
|
* @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
|
|
*
|
|
* @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
|
|
*
|
|
* @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
|
|
*
|
|
* @note This function is only to be used through macro QS_FUN_DICTIONARY()
|
|
*/
|
|
void QS_fun_dict_pre_(
|
|
QSpyFunPtr fun,
|
|
char const * const name);
|
|
|
|
/*${QS::QS-tx::usr_dict_pre_} ..............................................*/
|
|
/*! Output predefined user-dictionary record
|
|
* @static @private @memberof QS
|
|
*
|
|
* @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::ASSERTION} ..................................................*/
|
|
/*! Output the predefined assertion failure trace record
|
|
* @static @public @memberof QS
|
|
*
|
|
* @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::QS-tx::target_info_pre_} ...........................................*/
|
|
/*! Helper function to output the predefined Target-info trace record.
|
|
* @static @private @memberof QS
|
|
*/
|
|
void QS_target_info_pre_(uint8_t const isReset);
|
|
|
|
/*${QS::QS-tx::onStartup} ..................................................*/
|
|
/*! Callback to startup the QS facility
|
|
* @static @public @memberof QS
|
|
*/
|
|
uint8_t QS_onStartup(void const * arg);
|
|
|
|
/*${QS::QS-tx::onCleanup} ..................................................*/
|
|
void QS_onCleanup(void);
|
|
|
|
/*${QS::QS-tx::onFlush} ....................................................*/
|
|
void QS_onFlush(void);
|
|
|
|
/*${QS::QS-tx::onGetTime} ..................................................*/
|
|
QSTimeCtr QS_onGetTime(void);
|
|
|
|
/*${QS::QS-tx-64bit::u64_raw_} .............................................*/
|
|
/*! Output uint64_t data element without format information
|
|
* @static @private @memberof QS
|
|
*/
|
|
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
|
|
* @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
|
|
* @sa QS_F32()
|
|
*/
|
|
void QS_f32_fmt_(
|
|
uint8_t format,
|
|
float32_t d);
|
|
|
|
/*${QS::QS-tx-fp::f64_fmt_} ................................................*/
|
|
/*! Output 64-bit floating point data element with format information
|
|
* @static @private @memberof QS
|
|
* @sa QS_F64()
|
|
*/
|
|
void QS_f64_fmt_(
|
|
uint8_t format,
|
|
float64_t d);
|
|
|
|
/*${QS::QS-rx::rx} .........................................................*/
|
|
/*! @brief QS software tracing parameters for QS input (QS-RX) */
|
|
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) */
|
|
extern QS_rx QS_rxPriv_;
|
|
|
|
/*${QS::QS-rx::QSpyObjKind} ................................................*/
|
|
/*! Kinds of objects used in QS_setCurrObj() and QS_queryCurrObj() */
|
|
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() */
|
|
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 @private @memberof QS
|
|
*
|
|
* @details
|
|
* This function should be called from QS::onStartup() to provide QS-RX
|
|
* with the receive data buffer.
|
|
*
|
|
* @param[in] sto[] the address of the memory block
|
|
* @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 @private @memberof QS
|
|
*/
|
|
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 @private @memberof QS
|
|
*
|
|
* @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 @private @memberof QS
|
|
*/
|
|
void QS_doInput(void);
|
|
|
|
/*${QS::QS-rx::setCurrObj} .................................................*/
|
|
/*! Set the "current object" in the Target
|
|
* @static @private @memberof QS
|
|
*
|
|
* @details
|
|
* This function sets the "current object" in the Target.
|
|
*/
|
|
void QS_setCurrObj(
|
|
uint8_t obj_kind,
|
|
void * obj_ptr);
|
|
|
|
/*${QS::QS-rx::queryCurrObj} ...............................................*/
|
|
/*! Query the "current object" in the Target
|
|
* @static @public @memberof QS
|
|
*
|
|
* @details
|
|
* This function programmatically generates the response to the query for
|
|
* a "current object".
|
|
*/
|
|
void QS_queryCurrObj(uint8_t obj_kind);
|
|
|
|
/*${QS::QS-rx::rxParse} ....................................................*/
|
|
/*! Parse all bytes present in the QS RX data buffer
|
|
* @static @private @memberof QS
|
|
*/
|
|
void QS_rxParse(void);
|
|
|
|
/*${QS::QS-rx::rxHandleGoodFrame_} .........................................*/
|
|
/*! internal function to handle incoming (QS-RX) packet
|
|
* @static @private @memberof QS
|
|
*/
|
|
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
|
|
*/
|
|
void QS_onReset(void);
|
|
|
|
/*${QS::QS-rx::onCommand} ..................................................*/
|
|
/*! Callback function to execute user commands (to be implemented in BSP)
|
|
* @static @public @memberof QS
|
|
*/
|
|
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 QSrx
|
|
*/
|
|
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()
|
|
*/
|
|
#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()
|
|
*/
|
|
#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().
|
|
*/
|
|
#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().
|
|
*/
|
|
#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
|
|
* - ::QSpyRecordGroups - QS record groups that can be used as `rec_`
|
|
* - ::QSpyRecords - individual QS records that can be used as `rec_`
|
|
*
|
|
* @usage
|
|
* The following example shows how to use QS filters:
|
|
* @include qs_filter.c
|
|
*/
|
|
#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
|
|
* - ::QSpyIdGroups - QS ID groups that can be used as `qs_id_`
|
|
* - ::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
|
|
*/
|
|
#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_user.c
|
|
*/
|
|
#define QS_BEGIN_ID(rec_, qs_id_) \
|
|
if (QS_GLB_CHECK_(rec_) && QS_LOC_CHECK_(qs_id_)) { \
|
|
QS_CRIT_STAT_ \
|
|
QS_CRIT_E_(); \
|
|
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()
|
|
*/
|
|
#define QS_END() } \
|
|
QS_endRec_(); \
|
|
QS_CRIT_X_(); \
|
|
}
|
|
|
|
/*${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.
|
|
*/
|
|
#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_) \
|
|
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_GLB_CHECK_} ..............................................*/
|
|
/*! Helper macro for checking the global QS filter */
|
|
#define QS_GLB_CHECK_(rec_) \
|
|
(((uint_fast8_t)QS_priv_.glbFilter[(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 */
|
|
#define QS_LOC_CHECK_(qs_id_) \
|
|
(((uint_fast8_t)QS_priv_.locFilter[(uint_fast8_t)(qs_id_) >> 3U] \
|
|
& ((uint_fast8_t)1U << ((uint_fast8_t)(qs_id_) & 7U))) != 0U)
|
|
|
|
/*${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 */
|
|
|
|
/*${QS-macros::QS_I8} ......................................................*/
|
|
/*! Output formatted int8_t to the QS record */
|
|
#define QS_I8(width_, data_) \
|
|
(QS_u8_fmt_((uint8_t)(((width_) << 4)) | (uint8_t)QS_I8_T, (data_)))
|
|
|
|
/*${QS-macros::QS_U8} ......................................................*/
|
|
/*! Output formatted uint8_t to the QS record */
|
|
#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 */
|
|
#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 */
|
|
#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 */
|
|
#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 */
|
|
#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 */
|
|
#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 */
|
|
#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 */
|
|
#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 */
|
|
#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 */
|
|
#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 */
|
|
#define QS_MEM(mem_, size_) (QS_mem_fmt_((mem_), (size_)))
|
|
|
|
/*${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_} ...............................................*/
|
|
#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) */
|
|
|
|
/*${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_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) */
|
|
|
|
/*${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 == 8U)
|
|
#define QS_OBJ(obj_) (QS_u64_fmt_(QS_OBJ_T, (uint64_t)(obj_)))
|
|
#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} .....................................................*/
|
|
#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) */
|
|
|
|
/*${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 == 8U)
|
|
#define QS_FUN(fun_) (QS_u64_fmt_(QS_FUN_T, (uint64_t)(fun_)))
|
|
#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
|
|
*/
|
|
#define QS_SIG(sig_, obj_) \
|
|
QS_u32_fmt_(QS_SIG_T, (sig_)); \
|
|
QS_obj_raw_(obj_)
|
|
#endif /* (Q_SIGNAL_SIZE == 4U) */
|
|
|
|
/*${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) */
|
|
|
|
/*${QS-macros::QS_SIG} .....................................................*/
|
|
#if (Q_SIGNAL_SIZE == 1U)
|
|
#define QS_SIG(sig_, obj_) \
|
|
QS_u8_fmt_(QS_SIG_T, (sig_)); \
|
|
QS_obj_raw_(obj_)
|
|
#endif /* (Q_SIGNAL_SIZE == 1U) */
|
|
|
|
/*${QS-macros::QS_SIG_DICTIONARY} ..........................................*/
|
|
/*! Output 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.
|
|
*
|
|
* Providing a signal 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 names.
|
|
*
|
|
* 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 all state machines
|
|
* (such as globally published signals), you can specify a signal dictionary
|
|
* entry with the `obj_` parameter set to NULL.
|
|
*
|
|
* 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
|
|
*
|
|
* @note The QSpy log utility must capture the signal dictionary record
|
|
* in order to use the human-readable information. You need to connect to
|
|
* the target before the dictionary entries have been transmitted.
|
|
*
|
|
* 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
|
|
*
|
|
* The following QSpy log example shows the same sequence of records, but
|
|
* with dictionary records removed. The human-readable signal names are not
|
|
* available.
|
|
*/
|
|
#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.
|
|
*
|
|
* Providing an object 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 object names.
|
|
*
|
|
* The following example shows the definition of object dictionary entry
|
|
* for the Table active object:
|
|
* @include qs_objDic.c
|
|
*/
|
|
#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.
|
|
*
|
|
* Providing a 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 object names.
|
|
*
|
|
* The following example shows the definition of object array dictionary
|
|
* for `Philo::inst[n]` and `Philo::inst[n].m_timeEvt`:
|
|
* @include qs_objDic.c
|
|
*/
|
|
#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.
|
|
*/
|
|
#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.
|
|
*/
|
|
#define QS_USR_DICTIONARY(rec_) \
|
|
(QS_usr_dict_pre_((rec_), #rec_))
|
|
|
|
/*${QS-macros::QF_QS_CRIT_ENTRY} ...........................................*/
|
|
/*! Output the critical section entry record */
|
|
void QF_QS_CRIT_ENTRY(void);
|
|
|
|
/*${QS-macros::QF_QS_CRIT_EXIT} ............................................*/
|
|
/*! Output the critical section exit record */
|
|
void QF_QS_CRIT_EXIT(void);
|
|
|
|
/*${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::QF_QS_ISR_EXIT} .............................................*/
|
|
/*! Output the ISR exit
|
|
* @static @public @memberof QS
|
|
*/
|
|
void QF_QS_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_)
|
|
/*$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 */
|
|
#ifdef Q_UTEST
|
|
|
|
/*$declare${QUTest} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
|
|
|
|
/*${QUTest::QS::TProbe} ....................................................*/
|
|
/*! @brief Test Probe attributes */
|
|
struct QS_TProbe {
|
|
QSFun addr;
|
|
uint32_t data;
|
|
uint8_t idx;
|
|
};
|
|
|
|
/*${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) */
|
|
};
|
|
|
|
/*${QUTest::QS::testData} ..................................................*/
|
|
/*! QUTest data */
|
|
extern struct QS_TestData QS_testData;
|
|
|
|
/*${QUTest::QS::processTestEvts_} ..........................................*/
|
|
/*! internal function to process posted events during test
|
|
* @static @private @memberof QS
|
|
*/
|
|
void QS_processTestEvts_(void);
|
|
|
|
/*${QUTest::QS::test_pause_} ...............................................*/
|
|
/*! internal function to pause test and enter the test event loop
|
|
* @static @private @memberof QS
|
|
*/
|
|
void QS_test_pause_(void);
|
|
|
|
/*${QUTest::QS::getTestProbe_} .............................................*/
|
|
/*! get the test probe data for the given API
|
|
* @static @private @memberof QS
|
|
*/
|
|
uint32_t QS_getTestProbe_(QSpyFunPtr api);
|
|
|
|
/*${QUTest::QS::onTestSetup} ...............................................*/
|
|
/*! callback to setup a unit test inside the Target
|
|
* @static @public @memberof QS
|
|
*/
|
|
void QS_onTestSetup(void);
|
|
|
|
/*${QUTest::QS::onTestTeardown} ............................................*/
|
|
/*! callback to teardown after a unit test inside the Target
|
|
* @static @public @memberof QS
|
|
*/
|
|
void QS_onTestTeardown(void);
|
|
|
|
/*${QUTest::QS::onTestEvt} .................................................*/
|
|
/*! callback to "massage" the test event before dispatching/posting it
|
|
* @static @public @memberof QS
|
|
*/
|
|
void QS_onTestEvt(QEvt * e);
|
|
|
|
/*${QUTest::QS::onTestPost} ................................................*/
|
|
/*! callback to examine an event that is about to be posted
|
|
* @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
|
|
* @static @public @memberof QS
|
|
*/
|
|
void QS_onTestLoop(void);
|
|
|
|
/*${QUTest::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.
|
|
*/
|
|
typedef struct {
|
|
/* protected: */
|
|
QHsm super;
|
|
} QHsmDummy;
|
|
|
|
/* public: */
|
|
|
|
/*! Constructor of the QHsmDummy HSM class
|
|
* @public @memberof QHsmDummy
|
|
*/
|
|
void QHsmDummy_ctor(QHsmDummy * const me);
|
|
|
|
/*! override for QHsm_init_()
|
|
* @private @memberof QHsmDummy
|
|
*/
|
|
void QHsmDummy_init_(
|
|
QHsm * const me,
|
|
void const * const par,
|
|
uint_fast8_t const qs_id);
|
|
|
|
/*! override for QHsm_dispatch_()
|
|
* @private @memberof QHsmDummy
|
|
*/
|
|
void QHsmDummy_dispatch_(
|
|
QHsm * const me,
|
|
QEvt const * const e,
|
|
uint_fast8_t const qs_id);
|
|
|
|
/*${QUTest::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.
|
|
*/
|
|
typedef struct {
|
|
/* protected: */
|
|
QActive super;
|
|
} QActiveDummy;
|
|
|
|
/* public: */
|
|
|
|
/*! Constructor of the QActiveDummy Active Object class
|
|
* @public @memberof QActiveDummy
|
|
*/
|
|
void QActiveDummy_ctor(QActiveDummy * const me);
|
|
|
|
/*! override for QHsm_init_()
|
|
* @private @memberof QActiveDummy
|
|
*/
|
|
void QActiveDummy_init_(
|
|
QHsm * const me,
|
|
void const * const par,
|
|
uint_fast8_t const qs_id);
|
|
|
|
/*! override for QHsm_dispatch_()
|
|
* @private @memberof QActiveDummy
|
|
*/
|
|
void QActiveDummy_dispatch_(
|
|
QHsm * 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,
|
|
uint_fast8_t const prio,
|
|
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_(
|
|
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_(
|
|
QActive * const me,
|
|
QEvt const * const e);
|
|
|
|
/*${QUTest::QUTEST_ON_POST} ................................................*/
|
|
/*! record-ID for posting events */
|
|
#define QUTEST_ON_POST 124
|
|
/*$enddecl${QUTest} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
|
|
|
|
/*! QS macro to define the Test-Probe for a given @p 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 */
|
|
|
|
/* 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 /* def QS_H */
|