--- /dev/null
+/*
+ bug 1938300
+*/
+
+#include <testfwk.h>
+
+#if (defined PORT_HOST) || defined (SDCC_STACK_AUTO)
+
+/*****************************************************************************
+* Product; Jongle Reconfigurable USB hardware
+* Last Updated for Version;
+* Date of the Last Update;
+*
+* Q u a n t u m L e a P s
+* ---------------------------
+* innovating embedded systems
+*
+* Copyright (C) 2002-2007 Quantum Leaps, LLC. All rights reserved.
+*
+* This software may be distributed and modified under the terms of the GNU
+* General Public License version 2 (GPL) as published by the Free Software
+* Foundation and appearing in the file GPL.TXT included in the packaging of
+* this file. Please note that GPL Section 2[b] requires that all works based
+* on this software must also be made publicly available under the terms of
+* the GPL ("Copyleft").
+*
+* Alternatively, this software may be distributed and modified under the
+* terms of Quantum Leaps commercial licenses, which expressly supersede
+* the GPL and are specifically designed for licensees interested in
+* retaining the proprietary status of their code.
+*
+* Contact information;
+* Quantum Leaps Web site; http;//www.quantum-leaps.com
+* e-mail; info@quantum-leaps.com
+*****************************************************************************/
+#ifndef qpn_port_h
+#define qpn_port_h
+
+/* #include "ezusbfx2.h" */
+
+#define NEAR near
+#define IDATA idata
+#define XDATA xdata
+#define CODE code
+#define SFR_T sfr
+#define BIT_T bit
+
+#define QF_ISR_NEST
+/* #define Q_ROM_VAR CODE */
+/* #define Q_ROM_PTR(X) (X) */
+#define Q_REENTRANT /* __reentrant */
+#define Q_ROM CODE
+#define Q_PARAM_SIZE 0
+#define QF_TIMEEVT_CTR_SIZE 2
+#define Q_NFSM
+/*#define QF_FSM_ACTIVE*/
+#define QF_MAX_ACTIVE 4
+#define QF_TIMEEVT_CTR_SIZE 2
+
+ /* interrupt locking policy for task level */
+#define QF_INT_LOCK() EA = 0
+#define QF_INT_UNLOCK() EA = 1
+
+#define __disable_interrupt() EA = 0
+#define __enable_interrupt() EA = 1
+
+ /* interrupt locking policy for interrupt level */
+/* #define QF_ISR_NEST */ /* nesting of ISRs not allowed */
+
+/*#include <intrinsics.h> * contains prototypes for the intrinsic functions */
+#include <stdint.h> /* Exact-width integer types. WG14/N843 C99 Standard */
+
+#endif /* qpn_port_h */
+
+
+
+/*****************************************************************************
+* Product; QEP-nano public interface
+* Last Updated for Version; 3.4.01
+* Date of the Last Update; Sep 24, 2007
+*
+* Q u a n t u m L e a P s
+* ---------------------------
+* innovating embedded systems
+*
+* Copyright (C) 2002-2007 Quantum Leaps, LLC. All rights reserved.
+*
+* This software may be distributed and modified under the terms of the GNU
+* General Public License version 2 (GPL) as published by the Free Software
+* Foundation and appearing in the file GPL.TXT included in the packaging of
+* this file. Please note that GPL Section 2[b] requires that all works based
+* on this software must also be made publicly available under the terms of
+* the GPL ("Copyleft").
+*
+* Alternatively, this software may be distributed and modified under the
+* terms of Quantum Leaps commercial licenses, which expressly supersede
+* the GPL and are specifically designed for licensees interested in
+* retaining the proprietary status of their code.
+*
+* Contact information;
+* Quantum Leaps Web site; http;//www.quantum-leaps.com
+* e-mail; info@quantum-leaps.com
+*****************************************************************************/
+#ifndef qepn_h
+#define qepn_h
+
+/** \ingroup qepn qfn qkn
+* \file qepn.h
+* \brief Public QEP-nano interface.
+*
+* This header file must be included in all modules that use QP-nano.
+* Typically, this header file is included indirectly through the
+* header file qpn_port.h.
+*/
+
+#ifndef Q_ROM /* if NOT defined, provide the default definition */
+
+ /** \brief Macro to specify compiler-specific directive for placing a
+ * constant object in ROM.
+ *
+ * Many compilers for 8-bit Harvard-architecture MCUs provide non-stanard
+ * extensions to support placement of objects in different memories.
+ * In order to conserve the precious RAM, QP-nano uses the Q_ROM macro for
+ * all constant objects that can be allocated in ROM.
+ *
+ * To override the following empty definition, you need to define the
+ * Q_ROM macro in the qpn_port.h header file. Some examples of valid
+ * Q_ROM macro definitions are; __code (IAR 8051 compiler), code (Keil
+ * 8051 compiler), PROGMEM (gcc for AVR), __flash (IAR for AVR).
+ */
+ #define Q_ROM
+#endif
+#ifndef Q_ROM_VAR /* if NOT defined, provide the default definition */
+
+ /** \brief Macro to specify compiler-specific directive for accessing a
+ * constant object in ROM.
+ *
+ * Many compilers for 8-bit MCUs provide different size pointers for
+ * accessing objects in various memories. Constant objects allocated
+ * in ROM (see #Q_ROM macro) often mandate the use of specific-size
+ * pointers (e.g., far pointers) to get access to ROM objects. The
+ * macro Q_ROM_VAR specifies the kind of the pointer to be used to access
+ * the ROM objects.
+ *
+ * To override the following empty definition, you need to define the
+ * Q_ROM_VAR macro in the qpn_port.h header file. An example of valid
+ * Q_ROM_VAR macro definition is; __far (Freescale HC(S)08 compiler).
+ */
+ #define Q_ROM_VAR
+#endif
+#ifndef Q_REENTRANT /* if NOT defined, provide the default definition */
+
+ /** \brief Macro to specify compiler-specific directive for generating
+ * reentrant function.
+ *
+ * Some compilers for 8-bit MCUs provide, most notably the Keil C51
+ * compiler for 8051, don't generate ANSI-C compliant reentrant functions
+ * by default, due to the limited hardware architecture. These compilers
+ * allow to dedicate specific functions to be reentrant with a special
+ * extended keyword (such as "reentrant" for Keil C51). The macro
+ * Q_REENTRANT is defined to nothing by default, to work with ANSI-C
+ * compiliant compilers, but can be defined to "reentrant" to work with
+ * Keil C51 and perhpas other compilers.
+ */
+ #define Q_REENTRANT
+#endif
+
+/****************************************************************************/
+/** helper macro to calculate static dimension of a 1-dim array \a array_ */
+#define Q_DIM(array_) (sizeof(array_) / sizeof(array_[0]))
+
+/****************************************************************************/
+/** \brief get the current QP version number string
+*
+* \return version of the QP as a constant 6-character string of the form
+* x.y.zz, where x is a 1-digit major version number, y is a 1-digit minor
+* version number, and zz is a 2-digit release number.
+*/
+char const Q_ROM * Q_ROM_VAR QP_getVersion(void);
+
+/** \brief Scalar type describing the signal of an event.
+*/
+typedef uint8_t QSignal;
+
+/****************************************************************************/
+#ifndef Q_PARAM_SIZE
+ /** \brief macro to define the size of event parameter.
+ * Valid values 0, 1, 2, or 4; default 0
+ */
+ #define Q_PARAM_SIZE 0
+#endif
+#if (Q_PARAM_SIZE == 0)
+#elif (Q_PARAM_SIZE == 1)
+
+ /** \brief type of the event parameter.
+ *
+ * This typedef is configurable via the preprocessor switch #Q_PARAM_SIZE.
+ * The other possible values of this type are as follows; \n
+ * none when (Q_PARAM_SIZE == 0); \n
+ * uint8_t when (Q_PARAM_SIZE == 1); \n
+ * uint16_t when (Q_PARAM_SIZE == 2); and \n
+ * uint32_t when (Q_PARAM_SIZE == 4).
+ */
+ typedef uint8_t QParam;
+#elif (Q_PARAM_SIZE == 2)
+ typedef uint16_t QParam;
+#elif (Q_PARAM_SIZE == 4)
+ typedef uint32_t QParam;
+#else
+ #error "Q_PARAM_SIZE defined incorrectly, expected 0, 1, 2, or 4"
+#endif
+
+/** \brief Event structure.
+*
+* QEvent represents events, optionally with a single scalar parameter.
+* \sa Q_PARAM_SIZE
+* \sa ;;QParam
+*/
+typedef struct QEventTag {
+ QSignal sig; /**< signal of the event */
+
+#if (Q_PARAM_SIZE != 0)
+ QParam par; /**< scalar parameter of the event */
+#endif
+} QEvent;
+
+/****************************************************************************/
+/** \brief QP reserved signals */
+enum QReservedSignals {
+ Q_ENTRY_SIG = 1, /**< signal for coding entry actions */
+ Q_EXIT_SIG, /**< signal for coding exit actions */
+ Q_INIT_SIG, /**< signal for coding nested initial transitions */
+ Q_TIMEOUT_SIG, /**< signal used by time events */
+ Q_USER_SIG /**< first signal that can be used in user applications */
+};
+
+/****************************************************************************/
+struct QFsmTag; /* forward declaration */
+
+ /** \brief the signature of non-hierarchical state handler function */
+typedef void (*QState)(NEAR struct QFsmTag *me);
+
+/** \brief Finite State Machine.
+*
+* QFsm represents a traditional non-hierarchical Finite State Machine (FSM)
+* without state hierarchy, but with entry/exit actions.
+*
+* \note QFsm is not intended to be instantiated directly, but rather serves
+* as the base structure for derivation of state machines in the application
+* code.
+*
+* The following example illustrates how to derive a state machine structure
+* from QFsm. Please note that the QFsm member super_ is defined as the FIRST
+* member of the derived struct.
+* \include qepn_qfsm.c
+*
+* \sa \ref derivation
+*/
+typedef struct QFsmTag {
+ QState state; /**< current active state of the FSM (private) */
+ QEvent evt; /**< currently processed event in the FSM (protected) */
+} QFsm;
+
+/** \brief macro to access the signal of the current event of a state machine
+*
+* \sa ;;QFsm ;;QHsm
+*/
+#define Q_SIG(me_) (((QFsm *)(me_))->evt.sig)
+
+#if (Q_PARAM_SIZE != 0)
+/** \brief macro to access the parameter of the current event of
+* a state machine
+*
+* \sa ;;QFsm ;;QHsm Q_PARAM_SIZE
+*/
+#define Q_PAR(me_) (((QFsm *)(me_))->evt.par)
+#endif
+
+#ifndef Q_NFSM
+
+/** \brief State machine constructor.
+*
+* \param me_ pointer the state machine structure derived from ;;QHsm.
+* \param initial_ is the pointer to the initial state of the state machine.
+* \note Must be called only ONCE before taking the initial transition
+* with QFsm_init() and dispatching any events via QFsm_dispatch().
+*/
+#define QFsm_ctor(me_, initial_) do { \
+ ((QFsm *)me_)->state = (QState)(initial_); \
+ Q_SIG(me_) = (QSignal)Q_INIT_SIG; \
+} while (0)
+
+/** \brief Initializes a FSM
+*
+* Takes the top-most initial transition in a FSM.
+* \param me is the pointer the state machine structure derived from ;;FHsm.
+*
+* \note Must be called only ONCE after QFsm_ctor() and before any calls
+* to QFsm_dispatch().
+*/
+void QFsm_init(NEAR QFsm *me);
+
+/** \brief Dispatches an event to a FSM
+*
+* Processes one event at a time in Run-to-Completion fashion. The argument
+* \a me is the pointer the state machine structure derived from ;;QFsm.
+*
+* \note Must be called after QFsm_init().
+*/
+void QFsm_dispatch(NEAR QFsm *me) Q_REENTRANT;
+
+/* protected methods */
+
+/** \brief Returns current active state of a FSM.
+*
+* \note this is a protected function to be used only inside state handler
+* functions.
+*/
+#define QFsm_getState(me_) ((QState const)((QFsm *)(me_))->state)
+
+#endif /* Q_NFSM */
+
+/** \brief Designates a target for an initial or regular transition.
+*
+* Q_TRAN() can be used both in the FSMs and HSMs;
+*
+* \include qepn_qtran.c
+*/
+#define Q_TRAN(target_) do { \
+ ((QFsm *)me)->state = (QState)(target_); \
+ ((QFsm *)me)->evt.sig = (QSignal)0; \
+} while (0)
+
+/****************************************************************************/
+#ifndef Q_NHSM
+
+struct QHsmTag; /* forward declaration */
+
+ /** \brief the signature of state handler function for HSM */
+typedef QState (*QHsmState)(NEAR struct QHsmTag *me);
+
+ /** \brief a name for the return type from the HSM state handler function */
+typedef QState QSTATE;
+
+/** \brief a Hierarchical State Machine.
+*
+* QHsm represents a Hierarchical Finite State Machine (HSM). QHsm
+* extends the capabilities of a basic FSM with state hierarchy.
+*
+* \note QHsm is not intended to be instantiated directly, but rather serves
+* as the base structure for derivation of state machines in the application
+* code.
+*
+* The following example illustrates how to derive a state machine structure
+* from QHsm. Please note that the QHsm member super_ is defined as the FIRST
+* member of the derived struct.
+* \include qepn_qhsm.c
+*
+* \sa \ref derivation
+*/
+typedef struct QHsmTag {
+ QHsmState state; /**< current active state of the HSM (private) */
+ QEvent evt; /**< currently processed event in the HSM (protected) */
+} QHsm;
+
+/* public methods */
+/** \brief State machine constructor.
+*
+* \param me_ pointer the state machine structure derived from ;;QHsm.
+* \param initial_ is the pointer to the initial state of the state machine.
+* \note Must be called only ONCE before taking the initial transition
+* with QHsm_init() and dispatching any events via QHsm_dispatch().
+*/
+#define QHsm_ctor(me_, initial_) do { \
+ ((QHsm *)me_)->state = (QHsmState)(initial_); \
+ Q_SIG(me_) = (QSignal)Q_INIT_SIG; \
+} while (0)
+
+/** \brief Initializes a HSM.
+*
+* Takes the top-most initial transition in a HSM.
+* \param me is the pointer the state machine structure derived from ;;QHsm.
+*
+* \note Must be called only ONCE after QHsm_ctor() and before any calls
+* to QHsm_dispatch().
+*/
+void QHsm_init(NEAR QHsm *me);
+
+/** \brief Dispatches an event to a HSM
+*
+* Processes one event at a time in Run-to-Completion fashion.
+* \param me is the pointer the state machine structure derived from ;;QHsm.
+*
+* \note Must be called repetitively for each event after QHsm_init().
+*/
+void QHsm_dispatch(NEAR QHsm *me) Q_REENTRANT;
+
+/* protected methods... */
+
+/** \brief The top-state.
+*
+* QHsm_top() is the ultimate root of state hierarchy in all HSMs derived
+* from ;;QHsm. This state handler always returns (QSTATE)0, which means
+* that it "handles" all events.
+*
+* \sa Example of the QCalc_on() state handler for Q_INIT().
+*/
+QSTATE QHsm_top(NEAR QHsm *me) Q_REENTRANT;
+
+/** \return the current active state of the \a me_ state machine */
+#define QHsm_getState(me_) ((QHsmState const)((QHsm *)(me_))->state)
+
+#endif /* Q_NHSM */
+
+
+/****************************************************************************/
+/* DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED */
+
+/* If QPN compatibility level not defined or the level is lower than v3.4 */
+#if (!defined(QPN_COMP_LEVEL) || (QPN_COMP_LEVEL < 34))
+
+/** signal for coding the top-most initial transition (deprecated) */
+#define Q_TOP_INIT_SIG Q_INIT_SIG
+
+/** \brief Designates a target for an initial transition.
+*
+* \note DEPRECATED
+* \sa Q_TRAN()
+*/
+#define Q_INIT(target_) Q_TRAN(target_)
+
+/** \brief Returns current active state of a FSM.
+*
+* \note DEPRECATED
+* \sa QFsm_getState()
+*/
+#define QFsm_getState_(me_) QFsm_getState(me_)
+
+/** \brief Returns current active state of a HSM.
+*
+* \note DEPRECATED
+* \sa QHsm_getState()
+*/
+#define QHsm_getState_(me_) QHsm_getState(me_)
+
+#endif /* QPN_COMP_LEVEL < 34 */
+
+
+#endif /* qepn_h */
+
+
+
+/*****************************************************************************
+* Product; QF-nano public interface
+* Last Updated for Version; 3.4.01
+* Date of the Last Update; Sep 18, 2007
+*
+* Q u a n t u m L e a P s
+* ---------------------------
+* innovating embedded systems
+*
+* Copyright (C) 2002-2007 Quantum Leaps, LLC. All rights reserved.
+*
+* This software may be distributed and modified under the terms of the GNU
+* General Public License version 2 (GPL) as published by the Free Software
+* Foundation and appearing in the file GPL.TXT included in the packaging of
+* this file. Please note that GPL Section 2[b] requires that all works based
+* on this software must also be made publicly available under the terms of
+* the GPL ("Copyleft").
+*
+* Alternatively, this software may be distributed and modified under the
+* terms of Quantum Leaps commercial licenses, which expressly supersede
+* the GPL and are specifically designed for licensees interested in
+* retaining the proprietary status of their code.
+*
+* Contact information;
+* Quantum Leaps Web site; http;//www.quantum-leaps.com
+* e-mail; info@quantum-leaps.com
+*****************************************************************************/
+#ifndef qfn_h
+#define qfn_h
+
+/** \ingroup qepn qfn qkn
+* \file qfn.h
+* \brief Public QF-nano interface.
+*
+* This header file must be included in all modules that use QP-nano.
+* Typically, this header file is included indirectly through the
+* header file qpn_port.h.
+*/
+
+#ifndef QF_TIMEEVT_CTR_SIZE
+ /** \brief macro to override the default QTimeEvtCtr size.
+ * Valid values 0, 1, 2, or 4; default 0
+ */
+ #define QF_TIMEEVT_CTR_SIZE 0
+#endif
+#if (QF_TIMEEVT_CTR_SIZE == 0)
+#elif (QF_TIMEEVT_CTR_SIZE == 1)
+ typedef uint8_t QTimeEvtCtr;
+#elif (QF_TIMEEVT_CTR_SIZE == 2)
+ /** \brief type of the Time Event counter, which determines the dynamic
+ * range of the time delays measured in clock ticks.
+ *
+ * This typedef is configurable via the preprocessor switch
+ * #QF_TIMEEVT_CTR_SIZE. The other possible values of this type are
+ * as follows; \n
+ * none when (QF_TIMEEVT_CTR_SIZE not defined or == 0), \n
+ * uint8_t when (QF_TIMEEVT_CTR_SIZE == 1); \n
+ * uint16_t when (QF_TIMEEVT_CTR_SIZE == 2); and \n
+ * uint32_t when (QF_TIMEEVT_CTR_SIZE == 4).
+ */
+ typedef uint16_t QTimeEvtCtr;
+#elif (QF_TIMEEVT_CTR_SIZE == 4)
+ typedef uint32_t QTimeEvtCtr;
+#else
+ #error "QF_TIMER_SIZE defined incorrectly, expected 1, 2, or 4"
+#endif
+
+/** \brief Active Object struct
+*
+* QActive is the base structure for derivation of active objects. Active
+* objects in QF-nano are encapsulated tasks (each embedding a state machine
+* and an event queue) that communicate with one another asynchronously by
+* sending and receiving events. Within an active object, events are
+* processed sequentially in a run-to-completion (RTC) fashion, while QF
+* encapsulates all the details of thread-safe event exchange and queuing.
+*
+* \note ;;QActive is not intended to be instantiated directly, but rather
+* serves as the base structure for derivation of active objects in the
+* application code.
+*
+* The following example illustrates how to derive an active object from
+* QActive. Please note that the QActive member super_ is defined as the
+* FIRST member of the derived struct.
+* \include qfn_qactive.c
+*
+* \sa ;;QActiveTag for the description of the data members \n \ref derivation
+*/
+typedef struct QActiveTag {
+
+#if (!defined(QF_FSM_ACTIVE) && !defined(Q_NHSM))
+ QHsm super; /**< derives from the ;;QHsm base structure */
+#else
+ QFsm super; /**< derives from the ;;QFsm base structure */
+#endif
+
+ /** \brief offset to where next event will be inserted into the buffer
+ */
+ uint8_t head;
+
+ /** \brief offset of where next event will be extracted from the buffer
+ */
+ uint8_t tail;
+
+ /** \brief number of events currently present in the ring buffer
+ */
+ uint8_t nUsed;
+
+#if (QF_TIMEEVT_CTR_SIZE != 0)
+ /** \brief Time Event tick counter for the active object
+ */
+ QTimeEvtCtr tickCtr;
+#endif
+} QActive;
+
+#if (!defined(QF_FSM_ACTIVE) && !defined(Q_NHSM))
+ /** \brief Active object constructor.
+ *
+ * \param me_ pointer the active object structure derived from ;;QActive.
+ * \param initial_ is the pointer to the initial state of the active
+ * object.
+ * \note Must be called exactly ONCE for each active object
+ * in the application before calling QF_run().
+ */
+ #define QActive_ctor(me_, initial_) do { \
+ QHsm_ctor(me_, initial_); \
+ ((QActive *)(me_))->nUsed = (uint8_t)0; \
+ } while (0)
+#else
+ #define QActive_ctor(me_, initial_) do { \
+ QFsm_ctor(me_, initial_); \
+ ((QActive *)(me_))->nUsed = (uint8_t)0; \
+ } while (0)
+#endif
+
+
+#if (Q_PARAM_SIZE != 0)
+ /** \brief Posts an event \a e directly to the event queue of the acitve
+ * object \a prio using the First-In-First-Out (FIFO) policy. This
+ * function briefly locks and unlocks interrupts to protect the
+ * queue integrity.
+ *
+ * Direct event posting is the only asynchronous communication method
+ * available in QF-nano. The following example illustrates how the
+ * Ped active object posts directly the PED_WAITING event to the PELICAN
+ * crossing active object.
+ * \include qfn_post.c
+ *
+ * \note The producer of the event (Ped in this case) must only "know"
+ * the recipient's priority (Pelican), but the specific definition of
+ * the Pelican structure is not required.
+ *
+ * \note Direct event posting should not be confused with direct event
+ * dispatching. In contrast to asynchronous event posting through event
+ * queues, direct event dispatching is synchronous. Direct event
+ * dispatching occurs when you call QHsm_dispatch(), or QFsm_dispatch()
+ * function.
+ */
+ void QF_post(uint8_t prio, QSignal sig, QParam par) Q_REENTRANT;
+
+ /** \brief Posts an event \a e directly to the event queue of the acitve
+ * object \a prio using the First-In-First-Out (FIFO) policy. This
+ * function does NOT lock/unlock interrupts and is intended only
+ * to be used inside critical sections (such as inside ISRs that cannot
+ * nest).
+ *
+ * \sa QF_post()
+ */
+ void QF_postISR(uint8_t prio, QSignal sig, QParam par) Q_REENTRANT;
+#else
+ void QF_post(uint8_t prio, QSignal sig) Q_REENTRANT;
+ void QF_postISR(uint8_t prio, QSignal sig) Q_REENTRANT;
+#endif
+
+/****************************************************************************/
+/** \brief QActive Control Block
+*
+* QActiveCB represents the constant information that the QF-nano needs
+* to manage the active object. QActiveCB objects are grouped in the
+* array QF_active[], which typically can be placed in ROM.
+*
+* The following example illustrates how to allocate and initialize the
+* QActive control blocks in the array QF_active[].
+* \include qfn_main.c
+*/
+typedef struct QActiveCBTag {
+ QActive *act; /**< \brief pointer to the active object structure */
+ QEvent *queue; /**< \brief pointer to the event queue buffer */
+ uint8_t end; /**< \brief the length of the ring buffer */
+} QActiveCB;
+
+#if (QF_TIMEEVT_CTR_SIZE != 0)
+
+#if (QF_TIMEEVT_CTR_SIZE > 1)
+
+/** \brief Arm a one-shot time event for direct event posting.
+*
+* Arms a time event \a me to fire in \a tout clock ticks
+* (one-shot time event). The timeout signal Q_TIMEOUT_SIG gets directly
+* posted (using the FIFO policy) into the event queue of the active object
+* \a me.
+*
+* After posting, the time event gets automatically disarmed and can be reused.
+*
+* A one-shot time event can be disarmed at any time by calling the
+* QActive_disarm() function. Also, a one-shot time event can be re-armed
+* to fire in a different number of clock ticks by calling QActive_arm() again.
+*
+* The following example shows how to arm a one-shot time event from a state
+* machine of an active object;
+* \include qfn_arm.c
+*/
+void QActive_arm(NEAR QActive *me, QTimeEvtCtr tout) Q_REENTRANT;
+
+/** \brief Disarm a time event.
+*
+* The time event \a me gets disarmed and can be reused.
+*/
+void QActive_disarm(NEAR QActive *me) Q_REENTRANT;
+
+#else /* QF_TIMEEVT_CTR_SIZE must be == 1 */
+
+/** \brief Arm a one-shot time event for direct event posting.
+*
+* Arms a time event \param me_ to fire in \param tout_ clock ticks
+* (one-shot time event). The timeout signal Q_TIMEOUT_SIG gets directly
+* posted (using the FIFO policy) into the event queue of the active object
+* \param me_.
+*
+* After posting, the time event gets automatically disarmed and can be reused.
+*
+* A one-shot time event can be disarmed at any time by calling the
+* QActive_disarm() function. Also, a one-shot time event can be re-armed
+* to fire in a different number of clock ticks by calling QActive_arm() again.
+*
+* The following example shows how to arm a one-shot time event from a state
+* machine of an active object;
+* \include qfn_arm.c
+*/
+#define QActive_arm(me_, tout_) ((me_)->tickCtr = (QTimeEvtCtr)(tout_))
+
+/** \brief Disarm a time event.
+*
+* The time event \param me_ gets disarmed and can be reused.
+*/
+#define QActive_disarm(me_) ((me_)->tickCtr = (QTimeEvtCtr)0)
+
+#endif /* QF_TIMEEVT_CTR_SIZE > 1 */
+
+/** \brief Processes all armed time events at every clock tick.
+*
+* This function must be called periodically from a time-tick ISR or from
+* the highest-priority task so that QF can manage the timeout events.
+*
+* \note The QF_tick() function is not reentrant meaning that it must run to
+* completion before it is called again. Also, QF_tick() assumes that it
+* never will get preempted by a task, which is always the case when it is
+* called from an ISR or the highest-priority task.
+*
+* The following example illustrates the call to QF_tick();
+* \include qfn_tick.c
+*/
+void QF_tick(void);
+
+#endif /* (QF_TIMEEVT_CTR_SIZE != 0) */
+
+/* protected methods ...*/
+
+/** \brief QF initialization.
+*
+* This function initializes QF and must be called exactly once before any
+* other QF function. In QF-nano this function is defined in the BSP.
+*/
+void QF_init(void);
+
+/** \brief Starts the interrupts and initializes other critical resources
+* that might interact with the QF application.
+*
+* QF_start() is called from QF_run(), right before starting the non-preemptive
+* multitasking in the background loop.
+*
+* \note This function is strongly platform-dependent and is not implemented
+* in the QF, but either in the QF port or in the Board Support Package (BSP)
+* for the given application.
+*
+* \sa QF initialization example for ;;QActiveCB.
+*/
+void QF_start(void);
+
+/** \brief Transfers control to QF to run the application.
+*
+* QF_run() implemetns the simple non-preemptive scheduler. QF_run() must be
+* called from your startup code after you initialize the QF and define at
+* least one active object control block in QF_active[].
+*
+* \note When the Quantum Kernel (QK) is used as the underlying real-time
+* kernel for the QF, all platfrom dependencies are handled in the QK, so
+* no porting of QF is necessary. In other words, you only need to recompile
+* the QF platform-independent code with the compiler for your platform, but
+* you don't need to provide any platform-specific implementation (so, no
+* qf_port.c file is necessary). Moreover, QK implements the function QF_run()
+* in a platform-independent way, in the modile qk.c.
+*/
+void QF_run(void);
+
+#ifndef QK_PREEMPTIVE
+ /** \brief QF idle callback (customized in BSPs for QF)
+ *
+ * QF_onIdle() is called by the non-preemptive scheduler built into QF-nano
+ * when the QF-nano detects that no events are available for active objects
+ * (the idle condition). This callback gives the application an opportunity
+ * to enter a power-saving CPU mode, or perform some other idle processing.
+ *
+ * \note QF_onIdle() is invoked with interrupts LOCKED because the idle
+ * condition can be asynchronously changed at any time by an interrupt.
+ * QF_onIdle() MUST unlock the interrupts internally, but not before
+ * putting the CPU into the low-power mode. (Ideally, unlocking interrupts
+ * and low-power mode should happen atomically). At the very least, the
+ * function MUST unlock interrupts, otherwise interrups will be locked
+ * permanently.
+ *
+ * \note QF_onIdle() is not used in the PREEMPTIVE configuration. When
+ * QK_PREEMPTIVE macro is defined, the preemptive kernel QK-nano is used
+ * instead of the non-preemptive QF-nano scheduler. QK-nano uses a
+ * different idle callback \sa QK_onIdle().
+ */
+void QF_onIdle(void);
+#endif
+
+/** \brief Exits the QF application and returns control to the OS/Kernel.
+*
+* This function exits the framework. After calling this function, QF is no
+* longer in control of the application. The typical use of this method is
+* for exiting the QF application to return back to the operating system
+* or for handling fatal errors that require resetting the system.
+*
+* This function is strongly platform-dependent and is not implemented in
+* QF-nano, but either in the QF port or in the Board Support Package (BSP)
+* for the given application. Some QF ports might not require implementing
+* QF_exit() at all, because many embedded application don't have anything
+* to exit to.
+*/
+void QF_exit(void);
+
+ /** active object control blocks */
+extern QActiveCB const Q_ROM Q_ROM_VAR QF_active[];
+
+ /** the number of control blocks */
+extern uint8_t const Q_ROM Q_ROM_VAR QF_activeNum;
+
+/** \brief Ready set of QF-nano.
+*
+* The QF-nano ready set keeps track of active objects that are ready to run.
+* The ready set represents each active object as a bit, with the bits
+* assigned according to priorities of the active objects. The bit is set
+* if the corresponding active object is ready to run (i.e., has one or
+* more events in its event queue) and zero if the event queue is empty.
+* The QF-nano ready set is one byte-wide, which corresponds to 8 active
+* objects maximum.
+*/
+extern uint8_t volatile QF_readySet_;
+
+#endif /* qfn_h */
+
+
+
+/*****************************************************************************
+* Product; QP-nano
+* Last Updated for Version; 3.4.00
+* Date of the Last Update; Aug 20, 2007
+*
+* Q u a n t u m L e a P s
+* ---------------------------
+* innovating embedded systems
+*
+* Copyright (C) 2002-2007 Quantum Leaps, LLC. All rights reserved.
+*
+* This software may be distributed and modified under the terms of the GNU
+* General Public License version 2 (GPL) as published by the Free Software
+* Foundation and appearing in the file GPL.TXT included in the packaging of
+* this file. Please note that GPL Section 2[b] requires that all works based
+* on this software must also be made publicly available under the terms of
+* the GPL ("Copyleft").
+*
+* Alternatively, this software may be distributed and modified under the
+* terms of Quantum Leaps commercial licenses, which expressly supersede
+* the GPL and are specifically designed for licensees interested in
+* retaining the proprietary status of their code.
+*
+* Contact information;
+* Quantum Leaps Web site; http;//www.quantum-leaps.com
+* e-mail; info@quantum-leaps.com
+*****************************************************************************/
+#ifndef qassert_h
+#define qassert_h
+
+/** \ingroup qepn qfn
+* \file qassert.h
+* \brief Customizable assertions.
+*
+* Defines customizable and memory-efficient assertions applicable to
+* embedded systems. This header file can be used in C, C++, and mixed C/C++
+* programs.
+*
+* \note The preprocessor switch Q_NASSERT disables checking assertions.
+* In particular macros \ref Q_ASSERT, \ref Q_REQUIRE, \ref Q_ENSURE,
+* \ref Q_INVARIANT, and \ref Q_ERROR do NOT evaluate the test condition
+* passed as the argument to these macros. One notable exception is the
+* macro \ref Q_ALLEGE, that still evaluates the test condition, but does
+* not report assertion failures when the switch Q_NASSERT is defined.
+*/
+#ifdef Q_NASSERT /* Q_NASSERT defined--assertion checking disabled */
+
+ #define Q_DEFINE_THIS_FILE
+ #define Q_DEFINE_THIS_MODULE(name_)
+ #define Q_ASSERT(ignore_) ((void)0)
+ #define Q_ALLEGE(test_) ((void)(test_))
+ #define Q_ERROR() ((void)0)
+
+#else /* Q_NASSERT not defined--assertion checking enabled */
+
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
+ /** callback invoked in case the condition passed to \ref Q_ASSERT,
+ * \ref Q_REQUIRE, \ref Q_ENSURE, \ref Q_ERROR, or \ref Q_ALLEGE
+ * evaluates to FALSE.
+ *
+ * \param file file name where the assertion failed
+ * \param line line number at which the assertion failed
+ */
+ /*lint -sem(Q_assert_handler, r_no) Q_assert_handler() never returns */
+ void Q_assert_handler(char const Q_ROM * const Q_ROM_VAR file, int line);
+
+ #ifdef __cplusplus
+ }
+ #endif
+
+ /** Place this macro at the top of each C/C++ module to define the file
+ * name string using __FILE__ (NOTE; __FILE__ might contain lengthy path
+ * name). This file name will be used in reporting assertions in this file.
+ */
+ #define Q_DEFINE_THIS_FILE \
+ static char const Q_ROM Q_ROM_VAR l_this_file[] = __FILE__;
+
+ /** Place this macro at the top of each C/C++ module to define the module
+ * name as the argument \a name_. This file name will be used in reporting
+ * assertions in this file.
+ */
+ #define Q_DEFINE_THIS_MODULE(name_) \
+ static char const Q_ROM Q_ROM_VAR l_this_file[] = #name_;
+
+ /** General purpose assertion that makes sure the \a test_ argument is
+ * TRUE. Calls the Q_assert_handler() callback if the \a test_ evaluates
+ * to FALSE.
+ * \note the \a test_ is NOT evaluated if assertions are
+ * disabled with the Q_NASSERT switch.
+ */
+ #define Q_ASSERT(test_) \
+ if (test_) { \
+ } \
+ else (Q_assert_handler(l_this_file, __LINE__))
+
+ /** General purpose assertion that ALWAYS evaluates the \a test_
+ * argument and calls the Q_assert_handler() callback if the \a test_
+ * evaluates to FALSE.
+ * \note the \a test_ argument IS always evaluated even when assertions are
+ * disabled with the Q_NASSERT macro. When the Q_NASSERT macro is
+ * defined, the Q_assert_handler() callback is NOT called, even if the
+ * \a test_ evaluates to FALSE.
+ */
+ #define Q_ALLEGE(test_) Q_ASSERT(test_)
+
+ /** Assertion that always calls the Q_assert_handler() callback if
+ * ever executed.
+ * \note can be disabled with the Q_NASSERT switch.
+ */
+ #define Q_ERROR() \
+ (Q_assert_handler(l_this_file, __LINE__))
+
+#endif /* NASSERT */
+
+/** Assertion that checks for a precondition. This macro is equivalent to
+* \ref Q_ASSERT, except the name provides a better documentation of the
+* intention of this assertion.
+*/
+#define Q_REQUIRE(test_) Q_ASSERT(test_)
+
+/** Assertion that checks for a postcondition. This macro is equivalent to
+* \ref Q_ASSERT, except the name provides a better documentation of the
+* intention of this assertion.
+*/
+#define Q_ENSURE(test_) Q_ASSERT(test_)
+
+/** Assertion that checks for an invariant. This macro is equivalent to
+* \ref Q_ASSERT, except the name provides a better documentation of the
+* intention of this assertion.
+*/
+#define Q_INVARIANT(test_) Q_ASSERT(test_)
+
+/** Compile-time assertion exploits the fact that in C/C++ a dimension of
+ * an array must be non-zero. The following declaration causes a compilation
+ * error if the compile-time expression (\a test_) is not TRUE. The assertion
+ * has no runtime side effects.
+ */
+#define Q_ASSERT_COMPILE(test_) \
+ extern char Q_assert_compile[(test_)]
+
+#endif /* qassert_h */
+
+
+
+/*****************************************************************************
+* Product; QEP-nano implemenation
+* Last Updated for Version; 3.4.01
+* Date of the Last Update; Sep 18, 2007
+*
+* Q u a n t u m L e a P s
+* ---------------------------
+* innovating embedded systems
+*
+* Copyright (C) 2002-2007 Quantum Leaps, LLC. All rights reserved.
+*
+* This software may be distributed and modified under the terms of the GNU
+* General Public License version 2 (GPL) as published by the Free Software
+* Foundation and appearing in the file GPL.TXT included in the packaging of
+* this file. Please note that GPL Section 2[b] requires that all works based
+* on this software must also be made publicly available under the terms of
+* the GPL ("Copyleft").
+*
+* Alternatively, this software may be distributed and modified under the
+* terms of Quantum Leaps commercial licenses, which expressly supersede
+* the GPL and are specifically designed for licensees interested in
+* retaining the proprietary status of their code.
+*
+* Contact information;
+* Quantum Leaps Web site; http;//www.quantum-leaps.com
+* e-mail; info@quantum-leaps.com
+*****************************************************************************/
+
+Q_DEFINE_THIS_MODULE(qepn)
+
+/** \ingroup qepn qfn
+* \file qepn.c
+* QEP-nano implementation.
+*/
+
+/** empty signal for internal use only */
+#define QEP_EMPTY_SIG 0
+
+/** maximum depth of state nesting (including the top level), must be >= 2 */
+#define QEP_MAX_NEST_DEPTH 5
+
+#ifndef Q_NHSM
+/*..........................................................................*/
+void QHsm_dispatch(NEAR QHsm *me) Q_REENTRANT {
+ QHsmState path[QEP_MAX_NEST_DEPTH];
+ QHsmState s;
+ QHsmState t = me->state;
+
+ path[1] = t; /* save the current state in case a transition is taken */
+
+ do { /* process the event hierarchically... */
+ s = t;
+ t = (QHsmState)((*s)(me)); /* invoke state handler s */
+ } while (t != (QHsmState)0);
+
+ if (me->evt.sig == (QSignal)0) { /* transition taken? */
+ QHsmState src = s; /* the source of the transition */
+ int8_t ip = (int8_t)(-1); /* transition entry path index */
+ int8_t iq; /* helper transition entry path index */
+
+ path[0] = me->state; /* save the new state */
+ me->state = path[1]; /* restore the current state */
+
+ /* exit current state to the transition source src... */
+ for (s = path[1]; s != src; ) {
+ Q_SIG(me) = (QSignal)Q_EXIT_SIG;
+ t = (QHsmState)(*s)(me); /* find superstate of s */
+ if (t != (QHsmState)0) { /* exit action unhandled */
+ s = t; /* t points to superstate */
+ }
+ else { /* exit action handled */
+ Q_SIG(me) = (QSignal)QEP_EMPTY_SIG;
+ s = (QHsmState)(*s)(me); /* find superstate of s */
+ }
+ }
+
+ t = path[0]; /* target of the transition */
+
+ if (src == t) { /* (a) check source==target (transition to self) */
+ Q_SIG(me) = (QSignal)Q_EXIT_SIG;
+ (void)(*src)(me); /* exit the source */
+ ip = (int8_t)0; /* enter the target */
+ }
+ else {
+ Q_SIG(me) = (QSignal)QEP_EMPTY_SIG;
+ t = (QHsmState)(*t)(me); /* find superstate of target */
+ if (src == t) { /* (b) check source==target->super */
+ ip = (int8_t)0; /* enter the target */
+ }
+ else {
+ Q_SIG(me) = (QSignal)QEP_EMPTY_SIG;
+ s = (QHsmState)(*src)(me); /* find superstate of src */
+ if (s == t) { /* (c) check source->super==target->super */
+ Q_SIG(me) = (QSignal)Q_EXIT_SIG;
+ (void)(*src)(me); /* exit the source */
+ ip = (int8_t)0; /* enter the target */
+ }
+ else {
+ if (s == path[0]) { /* (d) check source->super==target */
+ Q_SIG(me) = (QSignal)Q_EXIT_SIG;
+ (void)(*src)(me); /* exit the source */
+ }
+ else { /* (e) check rest of source==target->super->super..
+ * and store the entry path along the way
+ */
+ iq = (int8_t)0; /* indicate that LCA not found */
+ ip = (int8_t)1; /* enter target and its superstate */
+ path[1] = t; /* save the superstate of target */
+ Q_SIG(me) = (QSignal)QEP_EMPTY_SIG;
+ t = (QHsmState)(*t)(me); /* find superstate of t */
+ while (t != (QHsmState)0) {
+ path[++ip] = t; /* store the entry path */
+ if (t == src) { /* is it the source? */
+ iq = (int8_t)1; /* indicate that LCA found */
+ /* entry path must not overflow */
+ Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH);
+ --ip; /* do not enter the source */
+ t = (QHsmState)0; /* terminate the loop */
+ }
+ else { /* it is not the source, keep going up */
+ Q_SIG(me) = (QSignal)QEP_EMPTY_SIG;
+ t = (QHsmState)(*t)(me); /* superstate of t */
+ }
+ }
+ if (iq == (int8_t)0) { /* the LCA not found yet? */
+
+ /* entry path must not overflow */
+ Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH);
+
+ Q_SIG(me) = (QSignal)Q_EXIT_SIG;
+ (void)(*src)(me); /* exit the source */
+
+ /* (f) check the rest of source->super
+ * == target->super->super...
+ */
+ iq = ip;
+ do {
+ if (s == path[iq]) { /* is this the LCA? */
+ t = s; /* indicate that LCA is found */
+ ip = (int8_t)(iq - 1);/*do not enter LCA*/
+ iq = (int8_t)(-1);/* terminate the loop */
+ }
+ else {
+ --iq; /* try lower superstate of target */
+ }
+ } while (iq >= (int8_t)0);
+
+ if (t == (QHsmState)0) { /* LCA not found yet? */
+ /* (g) check each source->super->...
+ * for each target->super...
+ */
+ do {
+ Q_SIG(me) = (QSignal)Q_EXIT_SIG;
+ t = (QHsmState)(*s)(me); /* exit s */
+ if (t != (QHsmState)0) { /* unhandled? */
+ s = t; /* t points to super of s */
+ }
+ else { /* exit action handled */
+ Q_SIG(me) = (QSignal)QEP_EMPTY_SIG;
+ s = (QHsmState)(*s)(me);/*super of s*/
+ }
+ iq = ip;
+ do {
+ if (s == path[iq]) {/* is this LCA? */
+ /* do not enter LCA */
+ ip = (int8_t)(iq - 1);
+ iq = (int8_t)(-1);/*break inner */
+ s = (QHsmState)0; /*break outer */
+ }
+ else {
+ --iq;
+ }
+ } while (iq >= (int8_t)0);
+ } while (s != (QHsmState)0);
+ }
+ }
+ }
+ }
+ }
+ }
+ /* retrace the entry path in reverse (desired) order... */
+ for (; ip >= (int8_t)0; --ip) {
+ Q_SIG(me) = (QSignal)Q_ENTRY_SIG;
+ (void)(*path[ip])(me); /* enter path[ip] */
+ }
+ s = path[0]; /* stick the target into register */
+ me->state = s; /* update the current state */
+
+ /* drill into the target hierarchy... */
+ Q_SIG(me) = (QSignal)Q_INIT_SIG;
+ while ((*s)(me) == (QState)0) {
+ t = me->state;
+ path[0] = t;
+ ip = (int8_t)0;
+ Q_SIG(me) = (QSignal)QEP_EMPTY_SIG;
+ t = (QHsmState)(*t)(me); /* find superstate of t */
+ while (t != s) {
+ ++ip;
+ path[ip] = t;
+ Q_SIG(me) = (QSignal)QEP_EMPTY_SIG;
+ t = (QHsmState)(*t)(me); /* find superstate of t */
+ }
+ /* entry path must not overflow */
+ Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH);
+
+ do { /* retrace the entry path in reverse (correct) order... */
+ Q_SIG(me) = (QSignal)Q_ENTRY_SIG;
+ (void)(*path[ip])(me); /* enter path[ip] */
+ --ip;
+ } while (ip >= (int8_t)0);
+ s = me->state;
+ Q_SIG(me) = (QSignal)Q_INIT_SIG;
+ }
+ }
+}
+
+void Q_assert_handler(char const Q_ROM * const Q_ROM_VAR file, int line)
+{
+ file;
+ line;
+}
+
+#endif /* Q_NHSM */
+
+#endif //(defined PORT_HOST) || defined (SDCC_STACK_AUTO)
+
+void
+testDummy(void)
+{
+}