7 #if (defined PORT_HOST) || defined (__SDCC_STACK_AUTO)
9 /*****************************************************************************
10 * Product; Jongle Reconfigurable USB hardware
11 * Last Updated for Version;
12 * Date of the Last Update;
14 * Q u a n t u m L e a P s
15 * ---------------------------
16 * innovating embedded systems
18 * Copyright (C) 2002-2007 Quantum Leaps, LLC. All rights reserved.
20 * This software may be distributed and modified under the terms of the GNU
21 * General Public License version 2 (GPL) as published by the Free Software
22 * Foundation and appearing in the file GPL.TXT included in the packaging of
23 * this file. Please note that GPL Section 2[b] requires that all works based
24 * on this software must also be made publicly available under the terms of
25 * the GPL ("Copyleft").
27 * Alternatively, this software may be distributed and modified under the
28 * terms of Quantum Leaps commercial licenses, which expressly supersede
29 * the GPL and are specifically designed for licensees interested in
30 * retaining the proprietary status of their code.
32 * Contact information;
33 * Quantum Leaps Web site; http;//www.quantum-leaps.com
34 * e-mail; info@quantum-leaps.com
35 *****************************************************************************/
39 /* #include "ezusbfx2.h" */
49 /* #define Q_ROM_VAR CODE */
50 /* #define Q_ROM_PTR(X) (X) */
51 #define Q_REENTRANT /* __reentrant */
53 #define Q_PARAM_SIZE 0
54 #define QF_TIMEEVT_CTR_SIZE 2
56 /*#define QF_FSM_ACTIVE*/
57 #define QF_MAX_ACTIVE 4
58 #define QF_TIMEEVT_CTR_SIZE 2
60 /* interrupt locking policy for task level */
61 #define QF_INT_LOCK() EA = 0
62 #define QF_INT_UNLOCK() EA = 1
64 #define __disable_interrupt() EA = 0
65 #define __enable_interrupt() EA = 1
67 /* interrupt locking policy for interrupt level */
68 /* #define QF_ISR_NEST */ /* nesting of ISRs not allowed */
70 /*#include <intrinsics.h> * contains prototypes for the intrinsic functions */
71 #include <stdint.h> /* Exact-width integer types. WG14/N843 C99 Standard */
73 #endif /* qpn_port_h */
77 /*****************************************************************************
78 * Product; QEP-nano public interface
79 * Last Updated for Version; 3.4.01
80 * Date of the Last Update; Sep 24, 2007
82 * Q u a n t u m L e a P s
83 * ---------------------------
84 * innovating embedded systems
86 * Copyright (C) 2002-2007 Quantum Leaps, LLC. All rights reserved.
88 * This software may be distributed and modified under the terms of the GNU
89 * General Public License version 2 (GPL) as published by the Free Software
90 * Foundation and appearing in the file GPL.TXT included in the packaging of
91 * this file. Please note that GPL Section 2[b] requires that all works based
92 * on this software must also be made publicly available under the terms of
93 * the GPL ("Copyleft").
95 * Alternatively, this software may be distributed and modified under the
96 * terms of Quantum Leaps commercial licenses, which expressly supersede
97 * the GPL and are specifically designed for licensees interested in
98 * retaining the proprietary status of their code.
100 * Contact information;
101 * Quantum Leaps Web site; http;//www.quantum-leaps.com
102 * e-mail; info@quantum-leaps.com
103 *****************************************************************************/
107 /** \ingroup qepn qfn qkn
109 * \brief Public QEP-nano interface.
111 * This header file must be included in all modules that use QP-nano.
112 * Typically, this header file is included indirectly through the
113 * header file qpn_port.h.
116 #ifndef Q_ROM /* if NOT defined, provide the default definition */
118 /** \brief Macro to specify compiler-specific directive for placing a
119 * constant object in ROM.
121 * Many compilers for 8-bit Harvard-architecture MCUs provide non-stanard
122 * extensions to support placement of objects in different memories.
123 * In order to conserve the precious RAM, QP-nano uses the Q_ROM macro for
124 * all constant objects that can be allocated in ROM.
126 * To override the following empty definition, you need to define the
127 * Q_ROM macro in the qpn_port.h header file. Some examples of valid
128 * Q_ROM macro definitions are; __code (IAR 8051 compiler), code (Keil
129 * 8051 compiler), PROGMEM (gcc for AVR), __flash (IAR for AVR).
133 #ifndef Q_ROM_VAR /* if NOT defined, provide the default definition */
135 /** \brief Macro to specify compiler-specific directive for accessing a
136 * constant object in ROM.
138 * Many compilers for 8-bit MCUs provide different size pointers for
139 * accessing objects in various memories. Constant objects allocated
140 * in ROM (see #Q_ROM macro) often mandate the use of specific-size
141 * pointers (e.g., far pointers) to get access to ROM objects. The
142 * macro Q_ROM_VAR specifies the kind of the pointer to be used to access
145 * To override the following empty definition, you need to define the
146 * Q_ROM_VAR macro in the qpn_port.h header file. An example of valid
147 * Q_ROM_VAR macro definition is; __far (Freescale HC(S)08 compiler).
151 #ifndef Q_REENTRANT /* if NOT defined, provide the default definition */
153 /** \brief Macro to specify compiler-specific directive for generating
154 * reentrant function.
156 * Some compilers for 8-bit MCUs provide, most notably the Keil C51
157 * compiler for 8051, don't generate ANSI-C compliant reentrant functions
158 * by default, due to the limited hardware architecture. These compilers
159 * allow to dedicate specific functions to be reentrant with a special
160 * extended keyword (such as "reentrant" for Keil C51). The macro
161 * Q_REENTRANT is defined to nothing by default, to work with ANSI-C
162 * compliant compilers, but can be defined to "reentrant" to work with
163 * Keil C51 and perhaps other compilers.
168 /****************************************************************************/
169 /** helper macro to calculate static dimension of a 1-dim array \a array_ */
170 #define Q_DIM(array_) (sizeof(array_) / sizeof(array_[0]))
172 /****************************************************************************/
173 /** \brief get the current QP version number string
175 * \return version of the QP as a constant 6-character string of the form
176 * x.y.zz, where x is a 1-digit major version number, y is a 1-digit minor
177 * version number, and zz is a 2-digit release number.
179 char const Q_ROM
* Q_ROM_VAR
QP_getVersion(void);
181 /** \brief Scalar type describing the signal of an event.
183 typedef uint8_t QSignal
;
185 /****************************************************************************/
187 /** \brief macro to define the size of event parameter.
188 * Valid values 0, 1, 2, or 4; default 0
190 #define Q_PARAM_SIZE 0
192 #if (Q_PARAM_SIZE == 0)
193 #elif (Q_PARAM_SIZE == 1)
195 /** \brief type of the event parameter.
197 * This typedef is configurable via the preprocessor switch #Q_PARAM_SIZE.
198 * The other possible values of this type are as follows; \n
199 * none when (Q_PARAM_SIZE == 0); \n
200 * uint8_t when (Q_PARAM_SIZE == 1); \n
201 * uint16_t when (Q_PARAM_SIZE == 2); and \n
202 * uint32_t when (Q_PARAM_SIZE == 4).
204 typedef uint8_t QParam
;
205 #elif (Q_PARAM_SIZE == 2)
206 typedef uint16_t QParam
;
207 #elif (Q_PARAM_SIZE == 4)
208 typedef uint32_t QParam
;
210 #error "Q_PARAM_SIZE defined incorrectly, expected 0, 1, 2, or 4"
213 /** \brief Event structure.
215 * QEvent represents events, optionally with a single scalar parameter.
219 typedef struct QEventTag
{
220 QSignal sig
; /**< signal of the event */
222 #if (Q_PARAM_SIZE != 0)
223 QParam par
; /**< scalar parameter of the event */
227 /****************************************************************************/
228 /** \brief QP reserved signals */
229 enum QReservedSignals
{
230 Q_ENTRY_SIG
= 1, /**< signal for coding entry actions */
231 Q_EXIT_SIG
, /**< signal for coding exit actions */
232 Q_INIT_SIG
, /**< signal for coding nested initial transitions */
233 Q_TIMEOUT_SIG
, /**< signal used by time events */
234 Q_USER_SIG
/**< first signal that can be used in user applications */
237 /****************************************************************************/
238 struct QFsmTag
; /* forward declaration */
240 /** \brief the signature of non-hierarchical state handler function */
241 typedef void (*QState
)(NEAR
struct QFsmTag
*me
);
243 /** \brief Finite State Machine.
245 * QFsm represents a traditional non-hierarchical Finite State Machine (FSM)
246 * without state hierarchy, but with entry/exit actions.
248 * \note QFsm is not intended to be instantiated directly, but rather serves
249 * as the base structure for derivation of state machines in the application
252 * The following example illustrates how to derive a state machine structure
253 * from QFsm. Please note that the QFsm member super_ is defined as the FIRST
254 * member of the derived struct.
255 * \include qepn_qfsm.c
257 * \sa \ref derivation
259 typedef struct QFsmTag
{
260 QState state
; /**< current active state of the FSM (private) */
261 QEvent evt
; /**< currently processed event in the FSM (protected) */
264 /** \brief macro to access the signal of the current event of a state machine
268 #define Q_SIG(me_) (((QFsm *)(me_))->evt.sig)
270 #if (Q_PARAM_SIZE != 0)
271 /** \brief macro to access the parameter of the current event of
274 * \sa ;;QFsm ;;QHsm Q_PARAM_SIZE
276 #define Q_PAR(me_) (((QFsm *)(me_))->evt.par)
281 /** \brief State machine constructor.
283 * \param me_ pointer the state machine structure derived from ;;QHsm.
284 * \param initial_ is the pointer to the initial state of the state machine.
285 * \note Must be called only ONCE before taking the initial transition
286 * with QFsm_init() and dispatching any events via QFsm_dispatch().
288 #define QFsm_ctor(me_, initial_) do { \
289 ((QFsm *)me_)->state = (QState)(initial_); \
290 Q_SIG(me_) = (QSignal)Q_INIT_SIG; \
293 /** \brief Initializes a FSM
295 * Takes the top-most initial transition in a FSM.
296 * \param me is the pointer the state machine structure derived from ;;FHsm.
298 * \note Must be called only ONCE after QFsm_ctor() and before any calls
299 * to QFsm_dispatch().
301 void QFsm_init(NEAR QFsm
*me
);
303 /** \brief Dispatches an event to a FSM
305 * Processes one event at a time in Run-to-Completion fashion. The argument
306 * \a me is the pointer the state machine structure derived from ;;QFsm.
308 * \note Must be called after QFsm_init().
310 void QFsm_dispatch(NEAR QFsm
*me
) Q_REENTRANT
;
312 /* protected methods */
314 /** \brief Returns current active state of a FSM.
316 * \note this is a protected function to be used only inside state handler
319 #define QFsm_getState(me_) ((QState const)((QFsm *)(me_))->state)
323 /** \brief Designates a target for an initial or regular transition.
325 * Q_TRAN() can be used both in the FSMs and HSMs;
327 * \include qepn_qtran.c
329 #define Q_TRAN(target_) do { \
330 ((QFsm *)me)->state = (QState)(target_); \
331 ((QFsm *)me)->evt.sig = (QSignal)0; \
334 /****************************************************************************/
337 struct QHsmTag
; /* forward declaration */
339 /** \brief the signature of state handler function for HSM */
340 typedef QState (*QHsmState
)(NEAR
struct QHsmTag
*me
);
342 /** \brief a name for the return type from the HSM state handler function */
343 typedef QState QSTATE
;
345 /** \brief a Hierarchical State Machine.
347 * QHsm represents a Hierarchical Finite State Machine (HSM). QHsm
348 * extends the capabilities of a basic FSM with state hierarchy.
350 * \note QHsm is not intended to be instantiated directly, but rather serves
351 * as the base structure for derivation of state machines in the application
354 * The following example illustrates how to derive a state machine structure
355 * from QHsm. Please note that the QHsm member super_ is defined as the FIRST
356 * member of the derived struct.
357 * \include qepn_qhsm.c
359 * \sa \ref derivation
361 typedef struct QHsmTag
{
362 QHsmState state
; /**< current active state of the HSM (private) */
363 QEvent evt
; /**< currently processed event in the HSM (protected) */
367 /** \brief State machine constructor.
369 * \param me_ pointer the state machine structure derived from ;;QHsm.
370 * \param initial_ is the pointer to the initial state of the state machine.
371 * \note Must be called only ONCE before taking the initial transition
372 * with QHsm_init() and dispatching any events via QHsm_dispatch().
374 #define QHsm_ctor(me_, initial_) do { \
375 ((QHsm *)me_)->state = (QHsmState)(initial_); \
376 Q_SIG(me_) = (QSignal)Q_INIT_SIG; \
379 /** \brief Initializes a HSM.
381 * Takes the top-most initial transition in a HSM.
382 * \param me is the pointer the state machine structure derived from ;;QHsm.
384 * \note Must be called only ONCE after QHsm_ctor() and before any calls
385 * to QHsm_dispatch().
387 void QHsm_init(NEAR QHsm
*me
);
389 /** \brief Dispatches an event to a HSM
391 * Processes one event at a time in Run-to-Completion fashion.
392 * \param me is the pointer the state machine structure derived from ;;QHsm.
394 * \note Must be called repetitively for each event after QHsm_init().
396 void QHsm_dispatch(NEAR QHsm
*me
) Q_REENTRANT
;
398 /* protected methods... */
400 /** \brief The top-state.
402 * QHsm_top() is the ultimate root of state hierarchy in all HSMs derived
403 * from ;;QHsm. This state handler always returns (QSTATE)0, which means
404 * that it "handles" all events.
406 * \sa Example of the QCalc_on() state handler for Q_INIT().
408 QSTATE
QHsm_top(NEAR QHsm
*me
) Q_REENTRANT
;
410 /** \return the current active state of the \a me_ state machine */
411 #define QHsm_getState(me_) ((QHsmState const)((QHsm *)(me_))->state)
416 /****************************************************************************/
417 /* DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED */
419 /* If QPN compatibility level not defined or the level is lower than v3.4 */
420 #if (!defined(QPN_COMP_LEVEL) || (QPN_COMP_LEVEL < 34))
422 /** signal for coding the top-most initial transition (deprecated) */
423 #define Q_TOP_INIT_SIG Q_INIT_SIG
425 /** \brief Designates a target for an initial transition.
430 #define Q_INIT(target_) Q_TRAN(target_)
432 /** \brief Returns current active state of a FSM.
435 * \sa QFsm_getState()
437 #define QFsm_getState_(me_) QFsm_getState(me_)
439 /** \brief Returns current active state of a HSM.
442 * \sa QHsm_getState()
444 #define QHsm_getState_(me_) QHsm_getState(me_)
446 #endif /* QPN_COMP_LEVEL < 34 */
453 /*****************************************************************************
454 * Product; QF-nano public interface
455 * Last Updated for Version; 3.4.01
456 * Date of the Last Update; Sep 18, 2007
458 * Q u a n t u m L e a P s
459 * ---------------------------
460 * innovating embedded systems
462 * Copyright (C) 2002-2007 Quantum Leaps, LLC. All rights reserved.
464 * This software may be distributed and modified under the terms of the GNU
465 * General Public License version 2 (GPL) as published by the Free Software
466 * Foundation and appearing in the file GPL.TXT included in the packaging of
467 * this file. Please note that GPL Section 2[b] requires that all works based
468 * on this software must also be made publicly available under the terms of
469 * the GPL ("Copyleft").
471 * Alternatively, this software may be distributed and modified under the
472 * terms of Quantum Leaps commercial licenses, which expressly supersede
473 * the GPL and are specifically designed for licensees interested in
474 * retaining the proprietary status of their code.
476 * Contact information;
477 * Quantum Leaps Web site; http;//www.quantum-leaps.com
478 * e-mail; info@quantum-leaps.com
479 *****************************************************************************/
483 /** \ingroup qepn qfn qkn
485 * \brief Public QF-nano interface.
487 * This header file must be included in all modules that use QP-nano.
488 * Typically, this header file is included indirectly through the
489 * header file qpn_port.h.
492 #ifndef QF_TIMEEVT_CTR_SIZE
493 /** \brief macro to override the default QTimeEvtCtr size.
494 * Valid values 0, 1, 2, or 4; default 0
496 #define QF_TIMEEVT_CTR_SIZE 0
498 #if (QF_TIMEEVT_CTR_SIZE == 0)
499 #elif (QF_TIMEEVT_CTR_SIZE == 1)
500 typedef uint8_t QTimeEvtCtr
;
501 #elif (QF_TIMEEVT_CTR_SIZE == 2)
502 /** \brief type of the Time Event counter, which determines the dynamic
503 * range of the time delays measured in clock ticks.
505 * This typedef is configurable via the preprocessor switch
506 * #QF_TIMEEVT_CTR_SIZE. The other possible values of this type are
508 * none when (QF_TIMEEVT_CTR_SIZE not defined or == 0), \n
509 * uint8_t when (QF_TIMEEVT_CTR_SIZE == 1); \n
510 * uint16_t when (QF_TIMEEVT_CTR_SIZE == 2); and \n
511 * uint32_t when (QF_TIMEEVT_CTR_SIZE == 4).
513 typedef uint16_t QTimeEvtCtr
;
514 #elif (QF_TIMEEVT_CTR_SIZE == 4)
515 typedef uint32_t QTimeEvtCtr
;
517 #error "QF_TIMER_SIZE defined incorrectly, expected 1, 2, or 4"
520 /** \brief Active Object struct
522 * QActive is the base structure for derivation of active objects. Active
523 * objects in QF-nano are encapsulated tasks (each embedding a state machine
524 * and an event queue) that communicate with one another asynchronously by
525 * sending and receiving events. Within an active object, events are
526 * processed sequentially in a run-to-completion (RTC) fashion, while QF
527 * encapsulates all the details of thread-safe event exchange and queuing.
529 * \note ;;QActive is not intended to be instantiated directly, but rather
530 * serves as the base structure for derivation of active objects in the
533 * The following example illustrates how to derive an active object from
534 * QActive. Please note that the QActive member super_ is defined as the
535 * FIRST member of the derived struct.
536 * \include qfn_qactive.c
538 * \sa ;;QActiveTag for the description of the data members \n \ref derivation
540 typedef struct QActiveTag
{
542 #if (!defined(QF_FSM_ACTIVE) && !defined(Q_NHSM))
543 QHsm super
; /**< derives from the ;;QHsm base structure */
545 QFsm super
; /**< derives from the ;;QFsm base structure */
548 /** \brief offset to where next event will be inserted into the buffer
552 /** \brief offset of where next event will be extracted from the buffer
556 /** \brief number of events currently present in the ring buffer
560 #if (QF_TIMEEVT_CTR_SIZE != 0)
561 /** \brief Time Event tick counter for the active object
567 #if (!defined(QF_FSM_ACTIVE) && !defined(Q_NHSM))
568 /** \brief Active object constructor.
570 * \param me_ pointer the active object structure derived from ;;QActive.
571 * \param initial_ is the pointer to the initial state of the active
573 * \note Must be called exactly ONCE for each active object
574 * in the application before calling QF_run().
576 #define QActive_ctor(me_, initial_) do { \
577 QHsm_ctor(me_, initial_); \
578 ((QActive *)(me_))->nUsed = (uint8_t)0; \
581 #define QActive_ctor(me_, initial_) do { \
582 QFsm_ctor(me_, initial_); \
583 ((QActive *)(me_))->nUsed = (uint8_t)0; \
588 #if (Q_PARAM_SIZE != 0)
589 /** \brief Posts an event \a e directly to the event queue of the active
590 * object \a prio using the First-In-First-Out (FIFO) policy. This
591 * function briefly locks and unlocks interrupts to protect the
594 * Direct event posting is the only asynchronous communication method
595 * available in QF-nano. The following example illustrates how the
596 * Ped active object posts directly the PED_WAITING event to the PELICAN
597 * crossing active object.
598 * \include qfn_post.c
600 * \note The producer of the event (Ped in this case) must only "know"
601 * the recipient's priority (Pelican), but the specific definition of
602 * the Pelican structure is not required.
604 * \note Direct event posting should not be confused with direct event
605 * dispatching. In contrast to asynchronous event posting through event
606 * queues, direct event dispatching is synchronous. Direct event
607 * dispatching occurs when you call QHsm_dispatch(), or QFsm_dispatch()
610 void QF_post(uint8_t prio
, QSignal sig
, QParam par
) Q_REENTRANT
;
612 /** \brief Posts an event \a e directly to the event queue of the active
613 * object \a prio using the First-In-First-Out (FIFO) policy. This
614 * function does NOT lock/unlock interrupts and is intended only
615 * to be used inside critical sections (such as inside ISRs that cannot
620 void QF_postISR(uint8_t prio
, QSignal sig
, QParam par
) Q_REENTRANT
;
622 void QF_post(uint8_t prio
, QSignal sig
) Q_REENTRANT
;
623 void QF_postISR(uint8_t prio
, QSignal sig
) Q_REENTRANT
;
626 /****************************************************************************/
627 /** \brief QActive Control Block
629 * QActiveCB represents the constant information that the QF-nano needs
630 * to manage the active object. QActiveCB objects are grouped in the
631 * array QF_active[], which typically can be placed in ROM.
633 * The following example illustrates how to allocate and initialize the
634 * QActive control blocks in the array QF_active[].
635 * \include qfn_main.c
637 typedef struct QActiveCBTag
{
638 QActive
*act
; /**< \brief pointer to the active object structure */
639 QEvent
*queue
; /**< \brief pointer to the event queue buffer */
640 uint8_t end
; /**< \brief the length of the ring buffer */
643 #if (QF_TIMEEVT_CTR_SIZE != 0)
645 #if (QF_TIMEEVT_CTR_SIZE > 1)
647 /** \brief Arm a one-shot time event for direct event posting.
649 * Arms a time event \a me to fire in \a tout clock ticks
650 * (one-shot time event). The timeout signal Q_TIMEOUT_SIG gets directly
651 * posted (using the FIFO policy) into the event queue of the active object
654 * After posting, the time event gets automatically disarmed and can be reused.
656 * A one-shot time event can be disarmed at any time by calling the
657 * QActive_disarm() function. Also, a one-shot time event can be re-armed
658 * to fire in a different number of clock ticks by calling QActive_arm() again.
660 * The following example shows how to arm a one-shot time event from a state
661 * machine of an active object;
664 void QActive_arm(NEAR QActive
*me
, QTimeEvtCtr tout
) Q_REENTRANT
;
666 /** \brief Disarm a time event.
668 * The time event \a me gets disarmed and can be reused.
670 void QActive_disarm(NEAR QActive
*me
) Q_REENTRANT
;
672 #else /* QF_TIMEEVT_CTR_SIZE must be == 1 */
674 /** \brief Arm a one-shot time event for direct event posting.
676 * Arms a time event \param me_ to fire in \param tout_ clock ticks
677 * (one-shot time event). The timeout signal Q_TIMEOUT_SIG gets directly
678 * posted (using the FIFO policy) into the event queue of the active object
681 * After posting, the time event gets automatically disarmed and can be reused.
683 * A one-shot time event can be disarmed at any time by calling the
684 * QActive_disarm() function. Also, a one-shot time event can be re-armed
685 * to fire in a different number of clock ticks by calling QActive_arm() again.
687 * The following example shows how to arm a one-shot time event from a state
688 * machine of an active object;
691 #define QActive_arm(me_, tout_) ((me_)->tickCtr = (QTimeEvtCtr)(tout_))
693 /** \brief Disarm a time event.
695 * The time event \param me_ gets disarmed and can be reused.
697 #define QActive_disarm(me_) ((me_)->tickCtr = (QTimeEvtCtr)0)
699 #endif /* QF_TIMEEVT_CTR_SIZE > 1 */
701 /** \brief Processes all armed time events at every clock tick.
703 * This function must be called periodically from a time-tick ISR or from
704 * the highest-priority task so that QF can manage the timeout events.
706 * \note The QF_tick() function is not reentrant meaning that it must run to
707 * completion before it is called again. Also, QF_tick() assumes that it
708 * never will get preempted by a task, which is always the case when it is
709 * called from an ISR or the highest-priority task.
711 * The following example illustrates the call to QF_tick();
712 * \include qfn_tick.c
716 #endif /* (QF_TIMEEVT_CTR_SIZE != 0) */
718 /* protected methods ...*/
720 /** \brief QF initialization.
722 * This function initializes QF and must be called exactly once before any
723 * other QF function. In QF-nano this function is defined in the BSP.
727 /** \brief Starts the interrupts and initializes other critical resources
728 * that might interact with the QF application.
730 * QF_start() is called from QF_run(), right before starting the non-preemptive
731 * multitasking in the background loop.
733 * \note This function is strongly platform-dependent and is not implemented
734 * in the QF, but either in the QF port or in the Board Support Package (BSP)
735 * for the given application.
737 * \sa QF initialization example for ;;QActiveCB.
741 /** \brief Transfers control to QF to run the application.
743 * QF_run() implemetns the simple non-preemptive scheduler. QF_run() must be
744 * called from your startup code after you initialize the QF and define at
745 * least one active object control block in QF_active[].
747 * \note When the Quantum Kernel (QK) is used as the underlying real-time
748 * kernel for the QF, all platform dependencies are handled in the QK, so
749 * no porting of QF is necessary. In other words, you only need to recompile
750 * the QF platform-independent code with the compiler for your platform, but
751 * you don't need to provide any platform-specific implementation (so, no
752 * qf_port.c file is necessary). Moreover, QK implements the function QF_run()
753 * in a platform-independent way, in the modile qk.c.
757 #ifndef QK_PREEMPTIVE
758 /** \brief QF idle callback (customized in BSPs for QF)
760 * QF_onIdle() is called by the non-preemptive scheduler built into QF-nano
761 * when the QF-nano detects that no events are available for active objects
762 * (the idle condition). This callback gives the application an opportunity
763 * to enter a power-saving CPU mode, or perform some other idle processing.
765 * \note QF_onIdle() is invoked with interrupts LOCKED because the idle
766 * condition can be asynchronously changed at any time by an interrupt.
767 * QF_onIdle() MUST unlock the interrupts internally, but not before
768 * putting the CPU into the low-power mode. (Ideally, unlocking interrupts
769 * and low-power mode should happen atomically). At the very least, the
770 * function MUST unlock interrupts, otherwise interrupts will be locked
773 * \note QF_onIdle() is not used in the PREEMPTIVE configuration. When
774 * QK_PREEMPTIVE macro is defined, the preemptive kernel QK-nano is used
775 * instead of the non-preemptive QF-nano scheduler. QK-nano uses a
776 * different idle callback \sa QK_onIdle().
778 void QF_onIdle(void);
781 /** \brief Exits the QF application and returns control to the OS/Kernel.
783 * This function exits the framework. After calling this function, QF is no
784 * longer in control of the application. The typical use of this method is
785 * for exiting the QF application to return back to the operating system
786 * or for handling fatal errors that require resetting the system.
788 * This function is strongly platform-dependent and is not implemented in
789 * QF-nano, but either in the QF port or in the Board Support Package (BSP)
790 * for the given application. Some QF ports might not require implementing
791 * QF_exit() at all, because many embedded application don't have anything
796 /** active object control blocks */
797 extern QActiveCB
const Q_ROM Q_ROM_VAR QF_active
[];
799 /** the number of control blocks */
800 extern uint8_t const Q_ROM Q_ROM_VAR QF_activeNum
;
802 /** \brief Ready set of QF-nano.
804 * The QF-nano ready set keeps track of active objects that are ready to run.
805 * The ready set represents each active object as a bit, with the bits
806 * assigned according to priorities of the active objects. The bit is set
807 * if the corresponding active object is ready to run (i.e., has one or
808 * more events in its event queue) and zero if the event queue is empty.
809 * The QF-nano ready set is one byte-wide, which corresponds to 8 active
812 extern uint8_t volatile QF_readySet_
;
818 /*****************************************************************************
820 * Last Updated for Version; 3.4.00
821 * Date of the Last Update; Aug 20, 2007
823 * Q u a n t u m L e a P s
824 * ---------------------------
825 * innovating embedded systems
827 * Copyright (C) 2002-2007 Quantum Leaps, LLC. All rights reserved.
829 * This software may be distributed and modified under the terms of the GNU
830 * General Public License version 2 (GPL) as published by the Free Software
831 * Foundation and appearing in the file GPL.TXT included in the packaging of
832 * this file. Please note that GPL Section 2[b] requires that all works based
833 * on this software must also be made publicly available under the terms of
834 * the GPL ("Copyleft").
836 * Alternatively, this software may be distributed and modified under the
837 * terms of Quantum Leaps commercial licenses, which expressly supersede
838 * the GPL and are specifically designed for licensees interested in
839 * retaining the proprietary status of their code.
841 * Contact information;
842 * Quantum Leaps Web site; http;//www.quantum-leaps.com
843 * e-mail; info@quantum-leaps.com
844 *****************************************************************************/
848 /** \ingroup qepn qfn
850 * \brief Customizable assertions.
852 * Defines customizable and memory-efficient assertions applicable to
853 * embedded systems. This header file can be used in C, C++, and mixed C/C++
856 * \note The preprocessor switch Q_NASSERT disables checking assertions.
857 * In particular macros \ref Q_ASSERT, \ref Q_REQUIRE, \ref Q_ENSURE,
858 * \ref Q_INVARIANT, and \ref Q_ERROR do NOT evaluate the test condition
859 * passed as the argument to these macros. One notable exception is the
860 * macro \ref Q_ALLEGE, that still evaluates the test condition, but does
861 * not report assertion failures when the switch Q_NASSERT is defined.
863 #ifdef Q_NASSERT /* Q_NASSERT defined--assertion checking disabled */
865 #define Q_DEFINE_THIS_FILE
866 #define Q_DEFINE_THIS_MODULE(name_)
867 #define Q_ASSERT(ignore_) ((void)0)
868 #define Q_ALLEGE(test_) ((void)(test_))
869 #define Q_ERROR() ((void)0)
871 #else /* Q_NASSERT not defined--assertion checking enabled */
877 /** callback invoked in case the condition passed to \ref Q_ASSERT,
878 * \ref Q_REQUIRE, \ref Q_ENSURE, \ref Q_ERROR, or \ref Q_ALLEGE
879 * evaluates to FALSE.
881 * \param file file name where the assertion failed
882 * \param line line number at which the assertion failed
884 /*lint -sem(Q_assert_handler, r_no) Q_assert_handler() never returns */
885 void Q_assert_handler(char const Q_ROM
* const Q_ROM_VAR file
, int line
);
891 /** Place this macro at the top of each C/C++ module to define the file
892 * name string using __FILE__ (NOTE; __FILE__ might contain lengthy path
893 * name). This file name will be used in reporting assertions in this file.
895 #define Q_DEFINE_THIS_FILE \
896 static char const Q_ROM Q_ROM_VAR l_this_file[] = __FILE__;
898 /** Place this macro at the top of each C/C++ module to define the module
899 * name as the argument \a name_. This file name will be used in reporting
900 * assertions in this file.
902 #define Q_DEFINE_THIS_MODULE(name_) \
903 static char const Q_ROM Q_ROM_VAR l_this_file[] = #name_;
905 /** General purpose assertion that makes sure the \a test_ argument is
906 * TRUE. Calls the Q_assert_handler() callback if the \a test_ evaluates
908 * \note the \a test_ is NOT evaluated if assertions are
909 * disabled with the Q_NASSERT switch.
911 #define Q_ASSERT(test_) \
914 else (Q_assert_handler(l_this_file, __LINE__))
916 /** General purpose assertion that ALWAYS evaluates the \a test_
917 * argument and calls the Q_assert_handler() callback if the \a test_
918 * evaluates to FALSE.
919 * \note the \a test_ argument IS always evaluated even when assertions are
920 * disabled with the Q_NASSERT macro. When the Q_NASSERT macro is
921 * defined, the Q_assert_handler() callback is NOT called, even if the
922 * \a test_ evaluates to FALSE.
924 #define Q_ALLEGE(test_) Q_ASSERT(test_)
926 /** Assertion that always calls the Q_assert_handler() callback if
928 * \note can be disabled with the Q_NASSERT switch.
931 (Q_assert_handler(l_this_file, __LINE__))
935 /** Assertion that checks for a precondition. This macro is equivalent to
936 * \ref Q_ASSERT, except the name provides a better documentation of the
937 * intention of this assertion.
939 #define Q_REQUIRE(test_) Q_ASSERT(test_)
941 /** Assertion that checks for a postcondition. This macro is equivalent to
942 * \ref Q_ASSERT, except the name provides a better documentation of the
943 * intention of this assertion.
945 #define Q_ENSURE(test_) Q_ASSERT(test_)
947 /** Assertion that checks for an invariant. This macro is equivalent to
948 * \ref Q_ASSERT, except the name provides a better documentation of the
949 * intention of this assertion.
951 #define Q_INVARIANT(test_) Q_ASSERT(test_)
953 /** Compile-time assertion exploits the fact that in C/C++ a dimension of
954 * an array must be non-zero. The following declaration causes a compilation
955 * error if the compile-time expression (\a test_) is not TRUE. The assertion
956 * has no runtime side effects.
958 #define Q_ASSERT_COMPILE(test_) \
959 extern char Q_assert_compile[(test_)]
961 #endif /* qassert_h */
965 /*****************************************************************************
966 * Product; QEP-nano implementation
967 * Last Updated for Version; 3.4.01
968 * Date of the Last Update; Sep 18, 2007
970 * Q u a n t u m L e a P s
971 * ---------------------------
972 * innovating embedded systems
974 * Copyright (C) 2002-2007 Quantum Leaps, LLC. All rights reserved.
976 * This software may be distributed and modified under the terms of the GNU
977 * General Public License version 2 (GPL) as published by the Free Software
978 * Foundation and appearing in the file GPL.TXT included in the packaging of
979 * this file. Please note that GPL Section 2[b] requires that all works based
980 * on this software must also be made publicly available under the terms of
981 * the GPL ("Copyleft").
983 * Alternatively, this software may be distributed and modified under the
984 * terms of Quantum Leaps commercial licenses, which expressly supersede
985 * the GPL and are specifically designed for licensees interested in
986 * retaining the proprietary status of their code.
988 * Contact information;
989 * Quantum Leaps Web site; http;//www.quantum-leaps.com
990 * e-mail; info@quantum-leaps.com
991 *****************************************************************************/
993 Q_DEFINE_THIS_MODULE(qepn
)
995 /** \ingroup qepn qfn
997 * QEP-nano implementation.
1000 /** empty signal for internal use only */
1001 #define QEP_EMPTY_SIG 0
1003 /** maximum depth of state nesting (including the top level), must be >= 2 */
1004 #define QEP_MAX_NEST_DEPTH 5
1007 /*..........................................................................*/
1008 void QHsm_dispatch(NEAR QHsm
*me
) Q_REENTRANT
{
1009 QHsmState path
[QEP_MAX_NEST_DEPTH
];
1011 QHsmState t
= me
->state
;
1013 path
[1] = t
; /* save the current state in case a transition is taken */
1015 do { /* process the event hierarchically... */
1017 t
= (QHsmState
)((*s
)(me
)); /* invoke state handler s */
1018 } while (t
!= (QHsmState
)0);
1020 if (me
->evt
.sig
== (QSignal
)0) { /* transition taken? */
1021 QHsmState src
= s
; /* the source of the transition */
1022 int8_t ip
= (int8_t)(-1); /* transition entry path index */
1023 int8_t iq
; /* helper transition entry path index */
1025 path
[0] = me
->state
; /* save the new state */
1026 me
->state
= path
[1]; /* restore the current state */
1028 /* exit current state to the transition source src... */
1029 for (s
= path
[1]; s
!= src
; ) {
1030 Q_SIG(me
) = (QSignal
)Q_EXIT_SIG
;
1031 t
= (QHsmState
)(*s
)(me
); /* find superstate of s */
1032 if (t
!= (QHsmState
)0) { /* exit action unhandled */
1033 s
= t
; /* t points to superstate */
1035 else { /* exit action handled */
1036 Q_SIG(me
) = (QSignal
)QEP_EMPTY_SIG
;
1037 s
= (QHsmState
)(*s
)(me
); /* find superstate of s */
1041 t
= path
[0]; /* target of the transition */
1043 if (src
== t
) { /* (a) check source==target (transition to self) */
1044 Q_SIG(me
) = (QSignal
)Q_EXIT_SIG
;
1045 (void)(*src
)(me
); /* exit the source */
1046 ip
= (int8_t)0; /* enter the target */
1049 Q_SIG(me
) = (QSignal
)QEP_EMPTY_SIG
;
1050 t
= (QHsmState
)(*t
)(me
); /* find superstate of target */
1051 if (src
== t
) { /* (b) check source==target->super */
1052 ip
= (int8_t)0; /* enter the target */
1055 Q_SIG(me
) = (QSignal
)QEP_EMPTY_SIG
;
1056 s
= (QHsmState
)(*src
)(me
); /* find superstate of src */
1057 if (s
== t
) { /* (c) check source->super==target->super */
1058 Q_SIG(me
) = (QSignal
)Q_EXIT_SIG
;
1059 (void)(*src
)(me
); /* exit the source */
1060 ip
= (int8_t)0; /* enter the target */
1063 if (s
== path
[0]) { /* (d) check source->super==target */
1064 Q_SIG(me
) = (QSignal
)Q_EXIT_SIG
;
1065 (void)(*src
)(me
); /* exit the source */
1067 else { /* (e) check rest of source==target->super->super..
1068 * and store the entry path along the way
1070 iq
= (int8_t)0; /* indicate that LCA not found */
1071 ip
= (int8_t)1; /* enter target and its superstate */
1072 path
[1] = t
; /* save the superstate of target */
1073 Q_SIG(me
) = (QSignal
)QEP_EMPTY_SIG
;
1074 t
= (QHsmState
)(*t
)(me
); /* find superstate of t */
1075 while (t
!= (QHsmState
)0) {
1076 path
[++ip
] = t
; /* store the entry path */
1077 if (t
== src
) { /* is it the source? */
1078 iq
= (int8_t)1; /* indicate that LCA found */
1079 /* entry path must not overflow */
1080 Q_ASSERT(ip
< (int8_t)QEP_MAX_NEST_DEPTH
);
1081 --ip
; /* do not enter the source */
1082 t
= (QHsmState
)0; /* terminate the loop */
1084 else { /* it is not the source, keep going up */
1085 Q_SIG(me
) = (QSignal
)QEP_EMPTY_SIG
;
1086 t
= (QHsmState
)(*t
)(me
); /* superstate of t */
1089 if (iq
== (int8_t)0) { /* the LCA not found yet? */
1091 /* entry path must not overflow */
1092 Q_ASSERT(ip
< (int8_t)QEP_MAX_NEST_DEPTH
);
1094 Q_SIG(me
) = (QSignal
)Q_EXIT_SIG
;
1095 (void)(*src
)(me
); /* exit the source */
1097 /* (f) check the rest of source->super
1098 * == target->super->super...
1102 if (s
== path
[iq
]) { /* is this the LCA? */
1103 t
= s
; /* indicate that LCA is found */
1104 ip
= (int8_t)(iq
- 1);/*do not enter LCA*/
1105 iq
= (int8_t)(-1);/* terminate the loop */
1108 --iq
; /* try lower superstate of target */
1110 } while (iq
>= (int8_t)0);
1112 if (t
== (QHsmState
)0) { /* LCA not found yet? */
1113 /* (g) check each source->super->...
1114 * for each target->super...
1117 Q_SIG(me
) = (QSignal
)Q_EXIT_SIG
;
1118 t
= (QHsmState
)(*s
)(me
); /* exit s */
1119 if (t
!= (QHsmState
)0) { /* unhandled? */
1120 s
= t
; /* t points to super of s */
1122 else { /* exit action handled */
1123 Q_SIG(me
) = (QSignal
)QEP_EMPTY_SIG
;
1124 s
= (QHsmState
)(*s
)(me
);/*super of s*/
1128 if (s
== path
[iq
]) {/* is this LCA? */
1129 /* do not enter LCA */
1130 ip
= (int8_t)(iq
- 1);
1131 iq
= (int8_t)(-1);/*break inner */
1132 s
= (QHsmState
)0; /*break outer */
1137 } while (iq
>= (int8_t)0);
1138 } while (s
!= (QHsmState
)0);
1145 /* retrace the entry path in reverse (desired) order... */
1146 for (; ip
>= (int8_t)0; --ip
) {
1147 Q_SIG(me
) = (QSignal
)Q_ENTRY_SIG
;
1148 (void)(*path
[ip
])(me
); /* enter path[ip] */
1150 s
= path
[0]; /* stick the target into register */
1151 me
->state
= s
; /* update the current state */
1153 /* drill into the target hierarchy... */
1154 Q_SIG(me
) = (QSignal
)Q_INIT_SIG
;
1155 while ((*s
)(me
) == (QState
)0) {
1159 Q_SIG(me
) = (QSignal
)QEP_EMPTY_SIG
;
1160 t
= (QHsmState
)(*t
)(me
); /* find superstate of t */
1164 Q_SIG(me
) = (QSignal
)QEP_EMPTY_SIG
;
1165 t
= (QHsmState
)(*t
)(me
); /* find superstate of t */
1167 /* entry path must not overflow */
1168 Q_ASSERT(ip
< (int8_t)QEP_MAX_NEST_DEPTH
);
1170 do { /* retrace the entry path in reverse (correct) order... */
1171 Q_SIG(me
) = (QSignal
)Q_ENTRY_SIG
;
1172 (void)(*path
[ip
])(me
); /* enter path[ip] */
1174 } while (ip
>= (int8_t)0);
1176 Q_SIG(me
) = (QSignal
)Q_INIT_SIG
;
1181 void Q_assert_handler(char const Q_ROM
* const Q_ROM_VAR file
, int line
)
1189 #endif //(defined PORT_HOST) || defined (SDCC_STACK_AUTO)