1 /*****************************************************************************
2 * Product: QEP-nano public interface
3 * Last Updated for Version: 4.0.02
4 * Date of the Last Update: Nov 11, 2008
6 * Q u a n t u m L e a P s
7 * ---------------------------
8 * innovating embedded systems
10 * Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
12 * This software may be distributed and modified under the terms of the GNU
13 * General Public License version 2 (GPL) as published by the Free Software
14 * Foundation and appearing in the file GPL.TXT included in the packaging of
15 * this file. Please note that GPL Section 2[b] requires that all works based
16 * on this software must also be made publicly available under the terms of
17 * the GPL ("Copyleft").
19 * Alternatively, this software may be distributed and modified under the
20 * terms of Quantum Leaps commercial licenses, which expressly supersede
21 * the GPL and are specifically designed for licensees interested in
22 * retaining the proprietary status of their code.
24 * Contact information:
25 * Quantum Leaps Web site: http://www.quantum-leaps.com
27 *****************************************************************************/
33 * \ingroup qepn qfn qkn
34 * \brief Public QEP-nano interface.
36 * This header file must be included in all modules that use QP-nano.
37 * Typically, this header file is included indirectly through the
38 * header file qpn_port.h.
41 /****************************************************************************/
42 #ifndef Q_ROM /* if NOT defined, provide the default definition */
44 /** \brief Macro to specify compiler-specific directive for placing a
45 * constant object in ROM.
47 * Many compilers for 8-bit Harvard-architecture MCUs provide non-stanard
48 * extensions to support placement of objects in different memories.
49 * In order to conserve the precious RAM, QP-nano uses the Q_ROM macro for
50 * all constant objects that can be allocated in ROM.
52 * To override the following empty definition, you need to define the
53 * Q_ROM macro in the qpn_port.h header file. Some examples of valid
54 * Q_ROM macro definitions are: __code (IAR 8051 compiler), code (Keil
55 * 8051 compiler), PROGMEM (gcc for AVR), __flash (IAR for AVR).
59 #ifndef Q_ROM_VAR /* if NOT defined, provide the default definition */
61 /** \brief Macro to specify compiler-specific directive for accessing a
62 * constant object in ROM.
64 * Many compilers for 8-bit MCUs provide different size pointers for
65 * accessing objects in various memories. Constant objects allocated
66 * in ROM (see #Q_ROM macro) often mandate the use of specific-size
67 * pointers (e.g., far pointers) to get access to ROM objects. The
68 * macro Q_ROM_VAR specifies the kind of the pointer to be used to access
71 * To override the following empty definition, you need to define the
72 * Q_ROM_VAR macro in the qpn_port.h header file. An example of valid
73 * Q_ROM_VAR macro definition is: __far (Freescale HC(S)08 compiler).
77 #ifndef Q_REENTRANT /* if NOT defined, provide the default definition */
79 /** \brief Macro to specify compiler-specific directive for generating
82 * Some compilers for 8-bit MCUs provide, most notably the Keil C51
83 * compiler for 8051, don't generate ANSI-C compliant reentrant functions
84 * by default, due to the limited CPU architecture. These compilers allow
85 * dedicating specific functions to be reentrant with a special extended
86 * keyword (such as "reentrant" for Keil C51). The macro Q_REENTRANT is
87 * defined to nothing by default, to work with ANSI-C compliant compilers,
88 * but can be defined to "reentrant" to work with Keil C51 and perhaps
89 * other embedded compilers.
94 /****************************************************************************/
95 /** helper macro to calculate static dimension of a 1-dim array \a array_ */
96 #define Q_DIM(array_) (sizeof(array_) / sizeof(array_[0]))
98 /****************************************************************************/
99 /** \brief get the current QP version number string
101 * \return version of the QP as a constant 6-character string of the form
102 * x.y.zz, where x is a 1-digit major version number, y is a 1-digit minor
103 * version number, and zz is a 2-digit release number.
105 char const Q_ROM * Q_ROM_VAR QP_getVersion(void);
107 /** \brief Scalar type describing the signal of an event.
109 typedef uint8_t QSignal;
111 /****************************************************************************/
113 /** \brief macro to define the size of event parameter.
114 * Valid values 0, 1, 2, or 4; default 0
116 #define Q_PARAM_SIZE 0
118 #if (Q_PARAM_SIZE == 0)
119 #elif (Q_PARAM_SIZE == 1)
121 /** \brief type of the event parameter.
123 * This typedef is configurable via the preprocessor switch #Q_PARAM_SIZE.
124 * The other possible values of this type are as follows: \n
125 * none when (Q_PARAM_SIZE == 0); \n
126 * uint8_t when (Q_PARAM_SIZE == 1); \n
127 * uint16_t when (Q_PARAM_SIZE == 2); and \n
128 * uint32_t when (Q_PARAM_SIZE == 4).
130 typedef uint8_t QParam;
131 #elif (Q_PARAM_SIZE == 2)
132 typedef uint16_t QParam;
133 #elif (Q_PARAM_SIZE == 4)
134 typedef uint32_t QParam;
136 #error "Q_PARAM_SIZE defined incorrectly, expected 0, 1, 2, or 4"
139 /** \brief Event structure.
141 * QEvent represents events, optionally with a single scalar parameter.
145 typedef struct QEventTag {
146 QSignal sig; /**< signal of the event */
147 #if (Q_PARAM_SIZE != 0)
148 QParam par; /**< scalar parameter of the event */
152 /****************************************************************************/
153 /** \brief QP reserved signals */
154 enum QReservedSignals {
155 Q_ENTRY_SIG = 1, /**< signal for coding entry actions */
156 Q_EXIT_SIG, /**< signal for coding exit actions */
157 Q_INIT_SIG, /**< signal for coding nested initial transitions */
158 Q_TIMEOUT_SIG, /**< signal used by time events */
159 Q_USER_SIG /**< first signal that can be used in user applications */
162 /****************************************************************************/
164 /** \brief Type returned from a state-handler function. */
165 typedef uint8_t QState;
167 /** \brief the signature of a state handler function */
168 typedef QState (*QStateHandler)(void *me);
170 /** \brief Finite State Machine.
172 * QFsm represents a traditional non-hierarchical Finite State Machine (FSM)
173 * without state hierarchy, but with entry/exit actions.
175 * \note QFsm is not intended to be instantiated directly, but rather serves
176 * as the base structure for derivation of state machines in the application
179 * The following example illustrates how to derive a state machine structure
180 * from QFsm. Please note that the QFsm member super_ is defined as the FIRST
181 * member of the derived struct.
182 * \include qepn_qfsm.c
184 * \sa \ref derivation
186 typedef struct QFsmTag {
187 QStateHandler state; /**< current active state (private) */
188 QEvent evt; /**< currently processed event in the FSM (protected) */
191 /** \brief macro to access the signal of the current event of a state machine
195 #define Q_SIG(me_) (((QFsm *)(me_))->evt.sig)
197 #if (Q_PARAM_SIZE != 0)
198 /** \brief macro to access the parameter of the current event of
201 * \sa ::QFsm ::QHsm Q_PARAM_SIZE
203 #define Q_PAR(me_) (((QFsm *)(me_))->evt.par)
208 /** \brief State machine constructor.
210 * \param me_ pointer the state machine structure derived from ::QHsm.
211 * \param initial_ is the pointer to the initial state of the state machine.
212 * \note Must be called only ONCE before taking the initial transition
213 * with QFsm_init() and dispatching any events via QFsm_dispatch().
215 #define QFsm_ctor(me_, initial_) ((me_)->state = (initial_))
217 /** \brief Initializes a FSM
219 * Takes the top-most initial transition in a FSM.
220 * \param me is the pointer the state machine structure derived from ::FHsm.
222 * \note Must be called only ONCE after QFsm_ctor() and before any calls
223 * to QFsm_dispatch().
225 void QFsm_init(QFsm *me);
227 #ifndef QK_PREEMPTIVE
228 /** \brief Dispatches an event to a FSM
230 * Processes one event at a time in Run-to-Completion fashion. The argument
231 * \a me is the pointer the state machine structure derived from ::QFsm.
233 * \note Must be called after QFsm_init().
235 void QFsm_dispatch(QFsm *me);
237 void QFsm_dispatch(QFsm *me) Q_REENTRANT;
243 /** \brief Value returned by a state-handler function when it handles
246 #define Q_RET_HANDLED ((QState)0)
248 /** \brief Value returned by a state-handler function when it handles
251 * You call that macro after the return statement (return Q_HANDLED();)
252 * Q_HANDLED() can be used both in the FSMs and HSMs.
254 * \include qepn_qfsm.c
256 #define Q_HANDLED() (Q_RET_HANDLED)
258 /** \brief Value returned by a non-hierarchical state-handler function when
259 * it ignores (does not handle) the event.
261 #define Q_RET_IGNORED ((QState)1)
263 /** \brief The macro returned from a non-hierarchical state-handler function
264 * when it ignores (does not handle) the event.
266 * You call that macro after the return statement (return Q_IGNORED();)
268 * \include qepn_qfsm.c
270 #define Q_IGNORED() (Q_RET_IGNORED)
272 /** \brief Value returned by a state-handler function when it takes a
273 * regular state transition.
275 #define Q_RET_TRAN ((QState)2)
277 /** \brief Designates a target for an initial or regular transition.
278 * Q_TRAN() can be used both in the FSMs and HSMs.
280 * \include qepn_qtran.c
282 /*lint -e960 */ /* ignore MISRA Rule 42 (comma operator) for this macro */
283 #define Q_TRAN(target_) \
284 (((QFsm *)me)->state = (QStateHandler)(target_), Q_RET_TRAN)
286 /** \brief Value returned by a state-handler function when it cannot
289 #define Q_RET_SUPER ((QState)3)
291 /** \brief Designates the superstate of a given state in an HSM.
293 * \include qepn_qhsm.c
295 /*lint -e960 */ /* ignore MISRA Rule 42 (comma operator) for this macro */
296 #define Q_SUPER(super_) \
297 (((QFsm *)me)->state = (QStateHandler)(super_), Q_RET_SUPER)
300 /****************************************************************************/
303 /** \brief a Hierarchical State Machine.
305 * QHsm represents a Hierarchical Finite State Machine (HSM). QHsm
306 * extends the capabilities of a basic FSM with state hierarchy.
308 * \note QHsm is not intended to be instantiated directly, but rather serves
309 * as the base structure for derivation of state machines in the application
312 * The following example illustrates how to derive a state machine structure
313 * from QHsm. Please note that the QHsm member super_ is defined as the FIRST
314 * member of the derived struct.
315 * \include qepn_qhsm.c
317 * \sa \ref derivation
319 typedef struct QFsmTag QHsm;
322 /** \brief State machine constructor.
324 * \param me_ pointer the state machine structure derived from ::QHsm.
325 * \param initial_ is the pointer to the initial state of the state machine.
326 * \note Must be called only ONCE before taking the initial transition
327 * with QHsm_init() and dispatching any events via QHsm_dispatch().
329 #define QHsm_ctor(me_, initial_) ((me_)->state = (initial_))
331 /** \brief Initializes a HSM.
333 * Takes the top-most initial transition in a HSM.
334 * \param me is the pointer the state machine structure derived from ::QHsm.
336 * \note Must be called only ONCE after QHsm_ctor() and before any calls
337 * to QHsm_dispatch().
339 void QHsm_init(QHsm *me);
341 #ifndef QK_PREEMPTIVE
342 /** \brief Dispatches an event to a HSM
344 * Processes one event at a time in Run-to-Completion fashion.
345 * \a me is the pointer the state machine structure derived from ::QHsm.
347 * \note Must be called repetitively for each event after QHsm_init().
349 void QHsm_dispatch(QHsm *me);
351 void QHsm_dispatch(QHsm *me) Q_REENTRANT;
354 /* protected methods... */
356 /** \brief The top-state.
358 * QHsm_top() is the ultimate root of state hierarchy in all HSMs derived
359 * from ::QHsm. This state handler always returns (QState)0, which means
360 * that it "handles" all events.
362 * \sa Example of the QCalc_on() state handler for Q_INIT().
364 QState QHsm_top(QHsm *me);
368 #include "qassert.h" /* include the QP-nano assertions (for DbC) */