Main Page | Modules | File List | Globals | Related Pages

tapsm.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004 by egnite Software GmbH. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holders nor the names of
00014  *    contributors may be used to endorse or promote products derived
00015  *    from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00018  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00021  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00023  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00024  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00025  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00026  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00027  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * For additional information see http://www.ethernut.de/
00031  */
00032 
00033 /*
00034  * $Log$
00035  */
00036 
00037 #ifdef _MSC_VER
00038 #include <winsock2.h>
00039 #endif
00040 
00041 #include "xsvf.h"   /* Error codes. */
00042 #include "host.h"   /* Hardware access. */
00043 
00044 #include "tapsm.h"
00045 
00046 /*!
00047  * \file tapsm.c
00048  * \brief TAP controller state handler.
00049  */
00050 
00051 /*!
00052  * \addtogroup xgTAP
00053  */
00054 /*@{*/
00055 
00056 /*!
00057  * \brief Current state of the TAP controller.
00058  */
00059 static u_char tapState;
00060 
00061 /*!
00062  * \brief TAP controller initialization.
00063  *
00064  * Must be called prior any other routine in this module.
00065  */
00066 void TapStateInit(void)
00067 {
00068     tapState = TEST_LOGIC_RESET;
00069     SET_TMS();
00070 }
00071 
00072 /*!
00073  * \brief State transition with TMS set to high.
00074  */
00075 static void TmsHighTransition(void)
00076 {
00077     SET_TMS();
00078     CLR_TCK();
00079     SET_TCK();
00080 }
00081 
00082 /*!
00083  * \brief State transition with TMS set to low.
00084  */
00085 static void TmsLowTransition(void)
00086 {
00087     CLR_TMS();
00088     CLR_TCK();
00089     SET_TCK();
00090 }
00091 
00092 
00093 /*!
00094  * \brief Change TAP state.
00095  *
00096  * Moves the TAP (Test Access Port) controller of the target to the
00097  * specified state.
00098  *
00099  * Trying to enter Exit2-DR or Exit2-IR from any other state except
00100  * Pause-DR or Pause-IR resp. will result in an error.
00101  *
00102  * \param state Requested TAP controller state.
00103  *
00104  * \return Zero on success, otherwise an error code is returned.
00105  */
00106 int TapStateChange(u_char state)
00107 {
00108     int i;
00109     int rc = 0;
00110 
00111     /*
00112      * No state change. However, XSVF expects us to terminate a Pause state.
00113      */
00114     if (state == tapState) {
00115         if (state == PAUSE_DR) {
00116             TmsHighTransition();
00117             tapState = EXIT2_DR;
00118         } else if (state == PAUSE_IR) {
00119             TmsHighTransition();
00120             tapState = EXIT2_IR;
00121         }
00122     }
00123 
00124     /*
00125      * Keeping TMS high for 5 or more consecutive state transition will put 
00126      * the TAP controller in Test-Logic-Reset state.
00127      */
00128     else if (state == TEST_LOGIC_RESET) {
00129         for (i = 0; i < 5; ++i) {
00130             TmsHighTransition();
00131         }
00132         tapState = TEST_LOGIC_RESET;
00133     }
00134 
00135     /*
00136      * Check for illegal state transisiton.
00137      */
00138     else if ((state == EXIT2_DR && tapState != PAUSE_DR) || (state == EXIT2_IR && tapState != PAUSE_IR) ) {
00139         rc = XE_ILLEGALSTATE;
00140     }
00141 
00142     else {
00143         /*
00144          * Walk through the state tree until we reach the requested state.
00145          */
00146         while (rc == 0 && state != tapState) {
00147             switch (tapState) {
00148             case TEST_LOGIC_RESET:
00149                 TmsLowTransition();
00150                 tapState = RUN_TEST_IDLE;
00151                 break;
00152             case RUN_TEST_IDLE:
00153                 TmsHighTransition();
00154                 tapState = SELECT_DR_SCAN;
00155                 break;
00156             case SELECT_DR_SCAN:
00157                 if (state >= SELECT_IR_SCAN) {
00158                     TmsHighTransition();
00159                     tapState = SELECT_IR_SCAN;
00160                 } else {
00161                     TmsLowTransition();
00162                     tapState = CAPTURE_DR;
00163                 }
00164                 break;
00165             case CAPTURE_DR:
00166                 if (state == SHIFT_DR) {
00167                     TmsLowTransition();
00168                     tapState = SHIFT_DR;
00169                 } else {
00170                     TmsHighTransition();
00171                     tapState = EXIT1_DR;
00172                 }
00173                 break;
00174             case SHIFT_DR:
00175                 TmsHighTransition();
00176                 tapState = EXIT1_DR;
00177                 break;
00178             case EXIT1_DR:
00179                 if (state == PAUSE_DR) {
00180                     TmsLowTransition();
00181                     tapState = PAUSE_DR;
00182                 } else {
00183                     TmsHighTransition();
00184                     tapState = UPDATE_DR;
00185                 }
00186                 break;
00187             case PAUSE_DR:
00188                 TmsHighTransition();
00189                 tapState = EXIT2_DR;
00190                 break;
00191             case EXIT2_DR:
00192                 if (state == SHIFT_DR) {
00193                     TmsLowTransition();
00194                     tapState = SHIFT_DR;
00195                 } else {
00196                     TmsHighTransition();
00197                     tapState = UPDATE_DR;
00198                 }
00199                 break;
00200             case UPDATE_DR:
00201                 if (state == RUN_TEST_IDLE) {
00202                     TmsLowTransition();
00203                     tapState = RUN_TEST_IDLE;
00204                 } else {
00205                     TmsHighTransition();
00206                     tapState = SELECT_DR_SCAN;
00207                 }
00208                 break;
00209             case SELECT_IR_SCAN:
00210                 TmsLowTransition();
00211                 tapState = CAPTURE_IR;
00212                 break;
00213             case CAPTURE_IR:
00214                 if (state == SHIFT_IR) {
00215                     TmsLowTransition();
00216                     tapState = SHIFT_IR;
00217                 } else {
00218                     TmsHighTransition();
00219                     tapState = EXIT1_IR;
00220                 }
00221                 break;
00222             case SHIFT_IR:
00223                 TmsHighTransition();
00224                 tapState = EXIT1_IR;
00225                 break;
00226             case EXIT1_IR:
00227                 if (state == PAUSE_IR) {
00228                     TmsLowTransition();
00229                     tapState = PAUSE_IR;
00230                 } else {
00231                     TmsHighTransition();
00232                     tapState = UPDATE_IR;
00233                 }
00234                 break;
00235             case PAUSE_IR:
00236                 TmsHighTransition();
00237                 tapState = EXIT2_IR;
00238                 break;
00239             case EXIT2_IR:
00240                 if (state == SHIFT_IR) {
00241                     TmsLowTransition();
00242                     tapState = SHIFT_IR;
00243                 } else {
00244                     TmsHighTransition();
00245                     tapState = UPDATE_IR;
00246                 }
00247                 break;
00248             case UPDATE_IR:
00249                 if (state == RUN_TEST_IDLE) {
00250                     TmsLowTransition();
00251                     tapState = RUN_TEST_IDLE;
00252                 } else {
00253                     TmsHighTransition();
00254                     tapState = SELECT_DR_SCAN;
00255                 }
00256                 break;
00257             default:
00258                 rc = XE_ILLEGALSTATE;
00259                 break;
00260             }
00261         }
00262     }
00263     return rc;
00264 }
00265 
00266 /*!
00267  * \brief Increment the TAP state.
00268  *
00269  * This routine will be used by the caller to update the
00270  * current TAP state, if the last shift included a state
00271  * transition.
00272  */
00273 void TapStateInc(void)
00274 {
00275     tapState++;
00276 }
00277 
00278 /*@}*/

© 2004 by egnite Software GmbH - visit http://www.ethernut.de/