1 /*****************************************************************************
2 * Product: QEP-nano implemenation
3 * Last Updated for Version: 4.0.03
4 * Date of the Last Update: Dec 26, 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 *****************************************************************************/
28 #include "qpn_port.h" /* QP-nano port */
31 Q_DEFINE_THIS_MODULE(qepn)
37 * QEP-nano implementation.
40 /** empty signal for internal use only */
41 #define QEP_EMPTY_SIG_ 0
43 /** maximum depth of state nesting (including the top level), must be >= 2 */
44 #define QEP_MAX_NEST_DEPTH_ 5
46 /*..........................................................................*/
47 /*lint -e970 -e971 */ /* ignore MISRA rules 13 and 14 in this function */
48 char const Q_ROM * Q_ROM_VAR QP_getVersion(void) {
49 static char const Q_ROM Q_ROM_VAR version[] = "4.0.03";
54 /*..........................................................................*/
55 void QFsm_init(QFsm *me) {
56 (void)(*me->state)(me); /* execute the top-most initial transition */
58 Q_SIG(me) = (QSignal)Q_ENTRY_SIG;
59 (void)(*me->state)(me); /* enter the target */
61 /*..........................................................................*/
63 void QFsm_dispatch(QFsm *me) {
65 void QFsm_dispatch(QFsm *me) Q_REENTRANT {
67 QStateHandler s = me->state;
69 if ((*s)(me) == Q_RET_TRAN) { /* transition taken? */
70 Q_SIG(me) = (QSignal)Q_EXIT_SIG;
71 (void)(*s)(me); /* exit the source */
73 Q_SIG(me) = (QSignal)Q_ENTRY_SIG;
74 (void)(*me->state)(me); /* enter the target */
80 /*..........................................................................*/
81 QState QHsm_top(QHsm *me) {
82 (void)me; /* supress the "unused argument" compiler warning */
83 return Q_IGNORED(); /* the top state ignores all events */
85 /*..........................................................................*/
86 void QHsm_init(QHsm *me) {
89 Q_ALLEGE((*me->state)(me) == Q_RET_TRAN);/* initial tran. must be taken */
91 t = (QStateHandler)&QHsm_top; /* an HSM starts in the top state */
92 do { /* drill into the target hierarchy... */
93 QStateHandler path[QEP_MAX_NEST_DEPTH_];
94 int8_t ip = (int8_t)0;
97 Q_SIG(me) = (QSignal)QEP_EMPTY_SIG_;
98 (void)(*me->state)(me);
99 while (me->state != t) {
100 path[++ip] = me->state;
101 (void)(*me->state)(me);
104 /* entry path must not overflow */
105 Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_);
107 Q_SIG(me) = (QSignal)Q_ENTRY_SIG;
108 do { /* retrace the entry path in reverse (correct) order... */
109 (void)(*path[ip])(me); /* enter path[ip] */
110 } while ((--ip) >= (int8_t)0);
113 Q_SIG(me) = (QSignal)Q_INIT_SIG;
114 } while ((*t)(me) == Q_RET_TRAN); /* initial transition handled? */
117 /*..........................................................................*/
118 #ifndef QK_PREEMPTIVE
119 void QHsm_dispatch(QHsm *me) {
121 void QHsm_dispatch(QHsm *me) Q_REENTRANT {
123 QStateHandler path[QEP_MAX_NEST_DEPTH_];
128 t = me->state; /* save the current state */
130 do { /* process the event hierarchically... */
132 r = (*s)(me); /* invoke state handler s */
133 } while (r == Q_RET_SUPER);
135 if (r == Q_RET_TRAN) { /* transition taken? */
136 int8_t ip = (int8_t)(-1); /* transition entry path index */
137 int8_t iq; /* helper transition entry path index */
139 path[0] = me->state; /* save the target of the transition */
142 while (t != s) { /* exit current state to transition source s... */
143 Q_SIG(me) = (QSignal)Q_EXIT_SIG; /* find superstate of t */
144 if ((*t)(me) == Q_RET_HANDLED) { /* exit action handled? */
145 Q_SIG(me) = (QSignal)QEP_EMPTY_SIG_;
146 (void)(*t)(me); /* find superstate of t */
148 t = me->state; /* me->state holds the superstate */
151 t = path[0]; /* target of the transition */
153 if (s == t) { /* (a) check source==target (transition to self) */
154 Q_SIG(me) = (QSignal)Q_EXIT_SIG;
155 (void)(*s)(me); /* exit the source */
156 ip = (int8_t)0; /* enter the target */
159 Q_SIG(me) = (QSignal)QEP_EMPTY_SIG_;
160 (void)(*t)(me); /* find superstate of target */
162 if (s == t) { /* (b) check source==target->super */
163 ip = (int8_t)0; /* enter the target */
166 Q_SIG(me) = (QSignal)QEP_EMPTY_SIG_;
167 (void)(*s)(me); /* find superstate of source */
169 /* (c) check source->super==target->super */
170 if (me->state == t) {
171 Q_SIG(me) = (QSignal)Q_EXIT_SIG;
172 (void)(*s)(me); /* exit the source */
173 ip = (int8_t)0; /* enter the target */
176 /* (d) check source->super==target */
177 if (me->state == path[0]) {
178 Q_SIG(me) = (QSignal)Q_EXIT_SIG;
179 (void)(*s)(me); /* exit the source */
181 else { /* (e) check rest of source==target->super->super..
182 * and store the entry path along the way
184 iq = (int8_t)0; /* indicate that LCA not found */
185 ip = (int8_t)1; /* enter target and its superstate */
186 path[1] = t; /* save the superstate of target */
187 t = me->state; /* save source->super */
189 Q_SIG(me) = (QSignal)QEP_EMPTY_SIG_;
190 r = (*path[1])(me); /* find target->super->super */
191 while (r == Q_RET_SUPER) {
192 path[++ip] = me->state; /* store the entry path */
193 if (me->state == s) { /* is it the source? */
194 iq = (int8_t)1; /* indicate that LCA found */
195 /* entry path must not overflow */
196 Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_);
197 --ip; /* do not enter the source */
198 r = Q_RET_HANDLED; /* terminate the loop */
200 else { /* it is not the source, keep going up */
201 r = (*me->state)(me); /* superstate of t */
204 if (iq == (int8_t)0) { /* the LCA not found yet? */
206 /* entry path must not overflow */
207 Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_);
209 Q_SIG(me) = (QSignal)Q_EXIT_SIG;
210 (void)(*s)(me); /* exit the source */
212 /* (f) check the rest of source->super
213 * == target->super->super...
216 r = Q_RET_IGNORED; /* indicate LCA NOT found */
219 if (t == s) { /* is this the LCA? */
220 r = Q_RET_HANDLED;/* indicate LCA found */
221 ip = (int8_t)(iq - 1);/*do not enter LCA*/
222 iq = (int8_t)(-1);/* terminate the loop */
225 --iq; /* try lower superstate of target */
227 } while (iq >= (int8_t)0);
229 if (r != Q_RET_HANDLED) { /* LCA not found yet? */
230 /* (g) check each source->super->...
231 * for each target->super...
233 r = Q_RET_IGNORED; /* keep looping */
235 /* exit t unhandled? */
236 Q_SIG(me) = (QSignal)Q_EXIT_SIG;
237 if ((*t)(me) == Q_RET_HANDLED) {
238 Q_SIG(me) = (QSignal)QEP_EMPTY_SIG_;
239 (void)(*t)(me); /* find super of t */
241 t = me->state; /* set to super of t */
245 if (t == s) { /* is this LCA? */
246 /* do not enter LCA */
247 ip = (int8_t)(iq - 1);
248 iq = (int8_t)(-1);/*break inner */
249 r = Q_RET_HANDLED;/*break outer */
254 } while (iq >= (int8_t)0);
255 } while (r != Q_RET_HANDLED);
262 /* retrace the entry path in reverse (desired) order... */
263 Q_SIG(me) = (QSignal)Q_ENTRY_SIG;
264 for (; ip >= (int8_t)0; --ip) {
265 (void)(*path[ip])(me); /* enter path[ip] */
267 t = path[0]; /* stick the target into register */
268 me->state = t; /* update the current state */
270 /* drill into the target hierarchy... */
271 Q_SIG(me) = (QSignal)Q_INIT_SIG;
272 while ((*t)(me) == Q_RET_TRAN) {
276 Q_SIG(me) = (QSignal)QEP_EMPTY_SIG_;
277 (void)(*me->state)(me); /* find the superstate */
278 while (me->state != t) {
279 path[++ip] = me->state;
280 (void)(*me->state)(me); /* find the superstate */
283 /* entry path must not overflow */
284 Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_);
286 Q_SIG(me) = (QSignal)Q_ENTRY_SIG;
287 do { /* retrace the entry path in reverse (correct) order... */
288 (void)(*path[ip])(me); /* enter path[ip] */
289 } while ((--ip) >= (int8_t)0);
292 Q_SIG(me) = (QSignal)Q_INIT_SIG;
295 me->state = t; /* set new state or restore the current state */