QP-nano
qepn.c
Go to the documentation of this file.
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 */