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 /*@}*/