|
QP-nano
|
00001 /***************************************************************************** 00002 * Product: QEP-nano implemenation 00003 * Last Updated for Version: 4.1.05 00004 * Date of the Last Update: Oct 27, 2010 00005 * 00006 * Q u a n t u m L e a P s 00007 * --------------------------- 00008 * innovating embedded systems 00009 * 00010 * Copyright (C) 2002-2010 Quantum Leaps, LLC. All rights reserved. 00011 * 00012 * This software may be distributed and modified under the terms of the GNU 00013 * General Public License version 2 (GPL) as published by the Free Software 00014 * Foundation and appearing in the file GPL.TXT included in the packaging of 00015 * this file. Please note that GPL Section 2[b] requires that all works based 00016 * on this software must also be made publicly available under the terms of 00017 * the GPL ("Copyleft"). 00018 * 00019 * Alternatively, this software may be distributed and modified under the 00020 * terms of Quantum Leaps commercial licenses, which expressly supersede 00021 * the GPL and are specifically designed for licensees interested in 00022 * retaining the proprietary status of their code. 00023 * 00024 * Contact information: 00025 * Quantum Leaps Web site: http://www.quantum-leaps.com 00026 * e-mail: info@quantum-leaps.com 00027 *****************************************************************************/ 00028 #include "qpn_port.h" /* QP-nano port */ 00029 00030 #ifndef Q_NHSM 00031 Q_DEFINE_THIS_MODULE(qepn) 00032 #endif 00033 00041 #define QEP_EMPTY_SIG_ 0 00042 00044 #define QEP_MAX_NEST_DEPTH_ 5 00045 00046 /*..........................................................................*/ 00047 /*lint -e970 -e971 */ /* ignore MISRA rules 13 and 14 in this function */ 00048 char const Q_ROM * Q_ROM_VAR QP_getVersion(void) { 00049 static char const Q_ROM Q_ROM_VAR version[] = { 00050 ((QP_VERSION >> 12) & 0xF) + '0', 00051 '.', 00052 ((QP_VERSION >> 8) & 0xF) + '0', 00053 '.', 00054 ((QP_VERSION >> 4) & 0xF) + '0', 00055 (QP_VERSION & 0xF) + '0', 00056 '\0' 00057 }; 00058 return version; 00059 } 00060 00061 #ifndef Q_NFSM 00062 /*..........................................................................*/ 00063 void QFsm_init(QFsm *me) { 00064 (void)(*me->state)(me); /* execute the top-most initial transition */ 00065 00066 Q_SIG(me) = (QSignal)Q_ENTRY_SIG; 00067 (void)(*me->state)(me); /* enter the target */ 00068 } 00069 /*..........................................................................*/ 00070 #ifndef QK_PREEMPTIVE 00071 void QFsm_dispatch(QFsm *me) { 00072 #else 00073 void QFsm_dispatch(QFsm *me) Q_REENTRANT { 00074 #endif 00075 QStateHandler s = me->state; 00076 00077 if ((*s)(me) == Q_RET_TRAN) { /* transition taken? */ 00078 Q_SIG(me) = (QSignal)Q_EXIT_SIG; 00079 (void)(*s)(me); /* exit the source */ 00080 00081 Q_SIG(me) = (QSignal)Q_ENTRY_SIG; 00082 (void)(*me->state)(me); /* enter the target */ 00083 } 00084 } 00085 #endif /* Q_NFSM */ 00086 00087 #ifndef Q_NHSM 00088 /*..........................................................................*/ 00089 QState QHsm_top(QHsm *me) { 00090 (void)me; /* supress the "unused argument" compiler warning */ 00091 return Q_IGNORED(); /* the top state ignores all events */ 00092 } 00093 /*..........................................................................*/ 00094 void QHsm_init(QHsm *me) { 00095 QStateHandler t; 00096 00097 Q_ALLEGE((*me->state)(me) == Q_RET_TRAN);/* initial tran. must be taken */ 00098 00099 t = (QStateHandler)&QHsm_top; /* an HSM starts in the top state */ 00100 do { /* drill into the target hierarchy... */ 00101 QStateHandler path[QEP_MAX_NEST_DEPTH_]; 00102 int8_t ip = (int8_t)0; 00103 00104 path[0] = me->state; 00105 Q_SIG(me) = (QSignal)QEP_EMPTY_SIG_; 00106 (void)(*me->state)(me); 00107 while (me->state != t) { 00108 ++ip; 00109 path[ip] = me->state; 00110 (void)(*me->state)(me); 00111 } 00112 me->state = path[0]; 00113 /* entry path must not overflow */ 00114 Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_); 00115 00116 Q_SIG(me) = (QSignal)Q_ENTRY_SIG; 00117 do { /* retrace the entry path in reverse (correct) order... */ 00118 (void)(*path[ip])(me); /* enter path[ip] */ 00119 --ip; 00120 } while (ip >= (int8_t)0); 00121 00122 t = path[0]; 00123 Q_SIG(me) = (QSignal)Q_INIT_SIG; 00124 } while ((*t)(me) == Q_RET_TRAN); /* initial transition handled? */ 00125 me->state = t; 00126 } 00127 /*..........................................................................*/ 00128 #ifndef QK_PREEMPTIVE 00129 void QHsm_dispatch(QHsm *me) { 00130 #else 00131 void QHsm_dispatch(QHsm *me) Q_REENTRANT { 00132 #endif 00133 QStateHandler path[QEP_MAX_NEST_DEPTH_]; 00134 QStateHandler s; 00135 QStateHandler t; 00136 QState r; 00137 00138 t = me->state; /* save the current state */ 00139 00140 do { /* process the event hierarchically... */ 00141 s = me->state; 00142 r = (*s)(me); /* invoke state handler s */ 00143 } while (r == Q_RET_SUPER); 00144 00145 if (r == Q_RET_TRAN) { /* transition taken? */ 00146 int8_t ip = (int8_t)(-1); /* transition entry path index */ 00147 int8_t iq; /* helper transition entry path index */ 00148 00149 path[0] = me->state; /* save the target of the transition */ 00150 path[1] = t; 00151 00152 while (t != s) { /* exit current state to transition source s... */ 00153 Q_SIG(me) = (QSignal)Q_EXIT_SIG; /* find superstate of t */ 00154 if ((*t)(me) == Q_RET_HANDLED) { /* exit action handled? */ 00155 Q_SIG(me) = (QSignal)QEP_EMPTY_SIG_; 00156 (void)(*t)(me); /* find superstate of t */ 00157 } 00158 t = me->state; /* me->state holds the superstate */ 00159 } 00160 00161 t = path[0]; /* target of the transition */ 00162 00163 if (s == t) { /* (a) check source==target (transition to self) */ 00164 Q_SIG(me) = (QSignal)Q_EXIT_SIG; 00165 (void)(*s)(me); /* exit the source */ 00166 ip = (int8_t)0; /* enter the target */ 00167 } 00168 else { 00169 Q_SIG(me) = (QSignal)QEP_EMPTY_SIG_; 00170 (void)(*t)(me); /* find superstate of target */ 00171 t = me->state; 00172 if (s == t) { /* (b) check source==target->super */ 00173 ip = (int8_t)0; /* enter the target */ 00174 } 00175 else { 00176 Q_SIG(me) = (QSignal)QEP_EMPTY_SIG_; 00177 (void)(*s)(me); /* find superstate of source */ 00178 00179 /* (c) check source->super==target->super */ 00180 if (me->state == t) { 00181 Q_SIG(me) = (QSignal)Q_EXIT_SIG; 00182 (void)(*s)(me); /* exit the source */ 00183 ip = (int8_t)0; /* enter the target */ 00184 } 00185 else { 00186 /* (d) check source->super==target */ 00187 if (me->state == path[0]) { 00188 Q_SIG(me) = (QSignal)Q_EXIT_SIG; 00189 (void)(*s)(me); /* exit the source */ 00190 } 00191 else { /* (e) check rest of source==target->super->super.. 00192 * and store the entry path along the way 00193 */ 00194 iq = (int8_t)0; /* indicate that LCA not found */ 00195 ip = (int8_t)1; /* enter target and its superstate */ 00196 path[1] = t; /* save the superstate of target */ 00197 t = me->state; /* save source->super */ 00198 00199 Q_SIG(me) = (QSignal)QEP_EMPTY_SIG_; 00200 r = (*path[1])(me); /* find target->super->super */ 00201 while (r == Q_RET_SUPER) { 00202 path[++ip] = me->state; /* store the entry path */ 00203 if (me->state == s) { /* is it the source? */ 00204 iq = (int8_t)1; /* indicate that LCA found */ 00205 /* entry path must not overflow */ 00206 Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_); 00207 --ip; /* do not enter the source */ 00208 r = Q_RET_HANDLED; /* terminate the loop */ 00209 } 00210 else { /* it is not the source, keep going up */ 00211 r = (*me->state)(me); /* superstate of t */ 00212 } 00213 } 00214 if (iq == (int8_t)0) { /* the LCA not found yet? */ 00215 00216 /* entry path must not overflow */ 00217 Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_); 00218 00219 Q_SIG(me) = (QSignal)Q_EXIT_SIG; 00220 (void)(*s)(me); /* exit the source */ 00221 00222 /* (f) check the rest of source->super 00223 * == target->super->super... 00224 */ 00225 iq = ip; 00226 r = Q_RET_IGNORED; /* indicate LCA NOT found */ 00227 do { 00228 s = path[iq]; 00229 if (t == s) { /* is this the LCA? */ 00230 r = Q_RET_HANDLED;/* indicate LCA found */ 00231 ip = (int8_t)(iq - 1);/*do not enter LCA*/ 00232 iq = (int8_t)(-1);/* terminate the loop */ 00233 } 00234 else { 00235 --iq; /* try lower superstate of target */ 00236 } 00237 } while (iq >= (int8_t)0); 00238 00239 if (r != Q_RET_HANDLED) { /* LCA not found yet? */ 00240 /* (g) check each source->super->... 00241 * for each target->super... 00242 */ 00243 r = Q_RET_IGNORED; /* keep looping */ 00244 do { 00245 /* exit t unhandled? */ 00246 Q_SIG(me) = (QSignal)Q_EXIT_SIG; 00247 if ((*t)(me) == Q_RET_HANDLED) { 00248 Q_SIG(me) = (QSignal)QEP_EMPTY_SIG_; 00249 (void)(*t)(me); /* find super of t */ 00250 } 00251 t = me->state; /* set to super of t */ 00252 iq = ip; 00253 do { 00254 s = path[iq]; 00255 if (t == s) { /* is this LCA? */ 00256 /* do not enter LCA */ 00257 ip = (int8_t)(iq - 1); 00258 iq = (int8_t)(-1);/*break inner */ 00259 r = Q_RET_HANDLED;/*break outer */ 00260 } 00261 else { 00262 --iq; 00263 } 00264 } while (iq >= (int8_t)0); 00265 } while (r != Q_RET_HANDLED); 00266 } 00267 } 00268 } 00269 } 00270 } 00271 } 00272 /* retrace the entry path in reverse (desired) order... */ 00273 Q_SIG(me) = (QSignal)Q_ENTRY_SIG; 00274 for (; ip >= (int8_t)0; --ip) { 00275 (void)(*path[ip])(me); /* enter path[ip] */ 00276 } 00277 t = path[0]; /* stick the target into register */ 00278 me->state = t; /* update the current state */ 00279 00280 /* drill into the target hierarchy... */ 00281 Q_SIG(me) = (QSignal)Q_INIT_SIG; 00282 while ((*t)(me) == Q_RET_TRAN) { 00283 ip = (int8_t)0; 00284 00285 path[0] = me->state; 00286 Q_SIG(me) = (QSignal)QEP_EMPTY_SIG_; 00287 (void)(*me->state)(me); /* find the superstate */ 00288 while (me->state != t) { 00289 ++ip; 00290 path[ip] = me->state; 00291 (void)(*me->state)(me); /* find the superstate */ 00292 } 00293 me->state = path[0]; 00294 /* entry path must not overflow */ 00295 Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_); 00296 00297 Q_SIG(me) = (QSignal)Q_ENTRY_SIG; 00298 do { /* retrace the entry path in reverse (correct) order... */ 00299 (void)(*path[ip])(me); /* enter path[ip] */ 00300 --ip; 00301 } while (ip >= (int8_t)0); 00302 00303 t = path[0]; 00304 Q_SIG(me) = (QSignal)Q_INIT_SIG; 00305 } 00306 } 00307 me->state = t; /* set new state or restore the current state */ 00308 } 00309 00310 #endif /* Q_NHSM */
1.7.5.1