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

xsvfexec.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"
00042 #include "host.h"
00043 #include "tapsm.h"
00044 
00045 /*!
00046  * \file xsvfexec.c
00047  *
00048  * \brief Executor main file.
00049  */
00050 
00051 /*!
00052  * \addtogroup xgBitString
00053  */
00054 /*@{*/
00055 
00056 /*!
00057  * \brief Compare two bit string using an optional bit mask.
00058  *
00059  * \param len  Number of bits in the bit strings.
00060  * \param op1  Pointer to the first bit string.
00061  * \param op2  Pointer to the second bit string.
00062  * \param mask Pointer to the mask. Bits are compared only if the corresponding
00063  *             bit in the mask is set. If this pointer is set to NULL, all
00064  *             bits will be compared.
00065  *
00066  * \return 0 if equal, 1 otherwise.
00067  */
00068 static int BitStringCmp(int len, u_char *op1, u_char *op2, u_char *mask)
00069 {
00070     int rc = 0;
00071 
00072 #if !defined(_WIN32)
00073     int i;
00074     u_char diff;
00075 
00076     for (i = 0; i < len; i += 8) {
00077         diff = *op1++ ^ *op2++;
00078         if (mask) {
00079             diff &= *mask++;
00080         }
00081         if (diff) {
00082             rc = 1;
00083             break;
00084         }
00085     }
00086 #endif
00087 
00088     return rc;
00089 }
00090 
00091 /*!
00092  * \brief Numeric addition of two bit string.
00093  *
00094  * \param len Number of bits in the bit strings.
00095  * \param op1 Pointer to the first bit string, which will also receive
00096  *            the final result.
00097  * \param op2 Pointer to the second bit string. Will be added to the first.
00098  */
00099 static void BitStringAdd(int len, u_char *op1, u_char *op2)
00100 {
00101     int i;
00102     u_short sum;
00103     u_char ovr = 0;
00104 
00105     i = (int)((len + 7UL) / 8UL);
00106     while (i--) {
00107         if((sum = (u_short)((u_short)op1[i] + (u_short)op2[i] + ovr)) > (u_short)255) {
00108             ovr = 1;
00109         }
00110         else {
00111             ovr = 0;
00112         }
00113         op1[i] = (u_char)sum;
00114     }
00115 }
00116 
00117 /*!
00118  * \brief Count the number of bits set to one in a bit string.
00119  *
00120  * \param len Number of bits in the bit string.
00121  * \param op  Pointer to the bit string.
00122  *
00123  * \return The number of bits set to one.
00124  */
00125 static int BitStringOnes(int len, u_char *op)
00126 {
00127     int rc = 0;
00128     u_char mask;
00129     int i = (int)((len + 7UL) / 8UL);
00130 
00131     while (i--) {
00132         for(mask = op[i]; mask; mask >>= 1) {
00133             rc += mask & 1;            
00134         }
00135     }
00136     return rc;
00137 }
00138 
00139 /*@}*/
00140 
00141 /*!
00142  * \addtogroup xgXsvfExec
00143  */
00144 /*@{*/
00145 
00146 
00147 /*!
00148  * \brief Prepare the next TDI value for iterating XSDR.
00149  *
00150  * \param len       Number of bits in the first TDI value.
00151  * \param tdi_val   First TDI value, the one which will be updated.
00152  * \param len2      Number of bits in the second TDI value.
00153  * \param tdi_val2  Second TDI value.
00154  * \param data_mask The data mask used for the update.
00155  */
00156 static void UpdateTdi(int len, u_char *tdi_val, int len2, u_char *tdi_val2, u_char *data_mask)
00157 {
00158     u_char tdibit;
00159     u_char mask;
00160     int i;
00161     u_char d = 0;
00162     u_char m = 0;
00163 
00164     for (i = len - 1; i >= 0; --i) {
00165         mask = data_mask[i];
00166         if (mask) {
00167             tdibit = 1;
00168             while (mask) {
00169                 if (mask & 1) {
00170                     if (m == 0) {
00171                         d = tdi_val2[--len2];
00172                         m = 1;
00173                     }
00174                     if (d & m) {
00175                         tdi_val[i] |= tdibit;
00176                     } else {
00177                         tdi_val[i] &= ~tdibit;
00178                     }
00179                     m <<= 1;
00180                 }
00181                 tdibit <<= 1;
00182                 mask >>= 1;
00183             }
00184         }
00185     }
00186 }
00187 
00188 
00189 /*!
00190  * \brief Repeat shifting out a TDI value until an expected TDO value appears.
00191  *
00192  * \param len     Number of bits to shift.
00193  * \param tdi_val TDI value to shift out.
00194  * \param tdo_exp Expected TDO value. Set to NULL if not available.
00195  * \param tdo_msk Used to mask out don't care TDO values.
00196  * \param sState  TAP state during shift operation, either SHIFT-DR or SHIFT-IR. No
00197  *                retries are allowed with SHIFT-IR.
00198  * \param eState  TAP state after shift operation.
00199  * \param delay   Idle time (in microseconds) after each shift.
00200  * \param retries Maximum number of retries. Ignored if expected TDO value is not available.
00201  *
00202  * \return Zero on success, otherwise an error code is returned.
00203  */
00204 static int ReShift(int len, u_char *tdi_val, u_char *tdo_exp, u_char *tdo_msk, 
00205                    u_char sState, u_char eState, long delay, u_char retries)
00206 {
00207     int rc = 0;
00208     u_char tdo_val[MAX_BITVEC_BYTES];
00209 
00210     if (len == 0) {
00211         if (delay) {
00212             TapStateChange(RUN_TEST_IDLE);
00213             XsvfDelay(delay);
00214         }
00215     } else {
00216         int last_byte = (int)((len + 7UL) / 8UL - 1UL);
00217 
00218         /* 
00219          * Retry loop. 
00220          */
00221         do {
00222             u_char *tdi = &tdi_val[last_byte];
00223             u_char *tdo = &tdo_val[last_byte];
00224             int bitcnt;
00225             u_char bitmsk;
00226 
00227             TapStateChange(sState);
00228 
00229             /* 
00230              * Byte loop. 
00231              */
00232             for(bitcnt = len; bitcnt;) {
00233                 *tdo = 0;
00234 
00235                 /* 
00236                  * Bit loop. LSB is shifted first.
00237                  */
00238                 for (bitmsk = 1; bitmsk && bitcnt; bitmsk <<= 1) {
00239                     if (sState != eState && bitcnt == 1) {
00240                         /* Exit Shift state with last bit. */
00241                         SET_TMS();
00242                         TapStateInc();
00243                     }
00244 
00245                     /* Shift TDI in and TDO out. */
00246                     if(*tdi & bitmsk) {
00247                         SET_TDI();
00248                     }
00249                     else {
00250                         CLR_TDI();
00251                     }
00252                     CLR_TCK();
00253 
00254                     /*
00255                      * This is time critical, because TDO may be delayed.
00256                      * The following decrement of our int value consumes
00257                      * some CPU cycles.
00258                      */
00259                     bitcnt--;
00260                     if(GET_TDO()) {
00261                         *tdo |= bitmsk;
00262                     }
00263                     SET_TCK();
00264                 }
00265                 tdi--;
00266                 tdo--;
00267             }
00268 
00269             /*
00270              * Compare captured with expected TDO result.
00271              */
00272             if (tdo_exp) {
00273                 if(BitStringCmp(len, tdo_exp, tdo_val, tdo_msk)) {
00274                     rc = XE_TDOMISMATCH;
00275                 }
00276                 else {
00277                     rc = 0;
00278                 }
00279             }
00280 
00281             /*
00282              * Update TAP controller state.
00283              */
00284             if (sState != eState) {
00285                 if (rc && delay && retries) {
00286                     /* The TDO value does not match the expected value. */
00287                     TapStateChange(PAUSE_DR);
00288                     TapStateChange(SHIFT_DR);
00289                 } else {
00290                     TapStateChange(eState);
00291                 }
00292 
00293                 /*
00294                  * If the XRUNTEST time is non-zero, go to the Run-Test/Idle state 
00295                  * and wait for the specified number of microseconds.
00296                  */
00297                 if (delay) {
00298                     TapStateChange(RUN_TEST_IDLE);
00299                     XsvfDelay(delay);
00300                     /* In case of another retry, increase idle time by 25%. */
00301                     delay += (delay >> 2);
00302                 }
00303             }
00304         } while (rc && retries--);
00305     }
00306     return rc;
00307 }
00308 
00309 
00310 /*!
00311  * \brief Shift next TDI value out and optionally capture TDO value.
00312  *
00313  * No delays and no retries are performed.
00314  *
00315  * \param len     Number of bits to shift.
00316  * \param tdi_val Pointer to TDI value buffer.
00317  * \param tdo_exp Pointer to expected TDO value buffer. If NULL, no TDO value will
00318  *                be read from the XSVF buffer and no comparision will take place.
00319  * \param sState  TAP state during shift operation, either SHIFT-DR or SHIFT-IR.
00320  * \param eState  TAP state after shift operation.
00321  *
00322  * \return Zero on success, otherwise an error code is returned.
00323  */
00324 static int Shift(int len, u_char *tdi_val, u_char *tdo_exp, u_char sState, u_char eState)
00325 {
00326     XsvfReadBitString(tdi_val, len);
00327     if(tdo_exp) {
00328         XsvfReadBitString(tdo_exp, len);
00329     }
00330     return ReShift(len, tdi_val, tdo_exp, 0, sState, eState, 0, 0);
00331 }
00332 
00333 /*!
00334  * \brief TDI value buffer.
00335  */
00336 static u_char tdiVal[MAX_BITVEC_BYTES];
00337 
00338 /*!
00339  * \brief TDI value 2 buffer.
00340  */
00341 static u_char tdiVal2[MAX_BITVEC_BYTES];
00342 
00343 /*!
00344  * \brief Expected TDO value buffer.
00345  */
00346 static u_char tdoExp[MAX_BITVEC_BYTES];
00347 
00348 /*!
00349  * \brief TDO mask buffer.
00350  */
00351 static u_char tdoMask[MAX_BITVEC_BYTES];
00352 
00353 /*!
00354  * \brief Data mask buffer.
00355  */
00356 static u_char dataMask[MAX_BITVEC_BYTES];
00357 
00358 /*!
00359  * \brief Address mask buffer.
00360  */
00361 static u_char addrMask[MAX_BITVEC_BYTES];
00362 
00363 /*!
00364  * \brief Execute an XSVF buffer.
00365  *
00366  * This routine interprets a compressed SVF command sequence following
00367  * the Xilinx application note XAPP503.
00368  *
00369  * \return Zero on success, otherwise an error code is returned.
00370  */
00371 static int Execute(void)
00372 {
00373     int rc = 0;
00374     u_char cmd;
00375     u_char endIr = RUN_TEST_IDLE;
00376     u_char endDr = RUN_TEST_IDLE;
00377     u_char retries = DEFAULT_REPEAT;
00378     long delay = 0;
00379     int drSize = 0;
00380     int drSize2 = 0;
00381     int irSize;
00382 
00383     TapStateInit();
00384 
00385     /* Process the XSVF commands */
00386     while (rc == 0) {
00387         cmd = XsvfGetCmd();
00388         
00389         if(cmd == XCOMPLETE) {
00390             /* 
00391              * Normal end of the XSVF buffer reached. 
00392              */
00393             break;
00394         }
00395         switch(cmd) {
00396 
00397         case XTDOMASK:
00398             /* 
00399              * Set the TDO mask. Length has been specified by the last XSDRSIZE command.
00400              */
00401             XsvfReadBitString(tdoMask, drSize);
00402             break;
00403 
00404         case XRUNTEST:
00405             /*
00406              * Set the number of microseconds the device should stay in the Run-Test-Idle 
00407              * state after each visit to the SDR state.
00408              */
00409             delay = XsvfGetLong();
00410             break;
00411 
00412         case XREPEAT:
00413             /*
00414              * Set the number of times that TDO is tested against the expected value before 
00415              * the programming operation is considered a failure.
00416              */
00417             retries = XsvfGetByte();
00418             break;
00419 
00420         case XSDRSIZE:
00421             /*
00422              * Set the length of the next XSDR/XSDRTDO records that follow.
00423              */
00424             drSize = (int)XsvfGetLong();
00425             if ((drSize + 7) / 8 > MAX_BITVEC_BYTES) {
00426                 rc = XE_DATAOVERFLOW;
00427             }
00428             break;
00429 
00430         case XSIR:
00431         case XSIR2:
00432             /*
00433              * Go to the Shift-IR state and shift in the TDI value. XSIR uses
00434              * a single byte for the TDI size, while XSIR2 uses two bytes.
00435              */
00436             if(cmd == XSIR) {
00437                 irSize = XsvfGetByte();
00438             }
00439             else {
00440                 irSize = XsvfGetShort();
00441             }
00442             XsvfReadBitString(tdiVal, irSize);
00443             rc = ReShift(irSize, tdiVal, 0, 0, SHIFT_IR, endIr, delay, 0);
00444             break;
00445 
00446         case XSDRTDO:
00447             /*
00448              * Go to the Shift-DR state and shift in the TDI value; compare the expected
00449              * value against the TDO value that was shifted out. Use the TDO mask which 
00450              * was generated by the last XTDOMASK command.
00451              *
00452              * The expected TDO value is re-used in successive XSDR commands.
00453              */
00454             XsvfReadBitString(tdiVal, drSize);
00455             XsvfReadBitString(tdoExp, drSize);
00456             rc = ReShift(drSize, tdiVal, tdoExp, tdoMask, SHIFT_DR, endDr, delay, retries);
00457             break;
00458 
00459         case XSDR:
00460             /*
00461              * Go to the Shift-DR state and shift in the TDI value; compare the expected 
00462              * value from the last XSDRTDO command against the TDO value that was 
00463              * shifted out. Use the TDO mask which was generated by the last XTDOMASK 
00464              * instruction.
00465              */
00466             XsvfReadBitString(tdiVal, drSize);
00467             rc = ReShift(drSize, tdiVal, tdoExp, tdoMask, SHIFT_DR, endDr, delay, retries);
00468             break;
00469 
00470         case XSDRB:
00471         case XSDRC:
00472             /*
00473              * Go to the Shift-DR state and shift in the TDI value. No comparison of TDO 
00474              * value with the last specified expected value is performed.
00475              */
00476             rc = Shift(drSize, tdiVal, 0, SHIFT_DR, SHIFT_DR);
00477             break;
00478 
00479         case XSDRE:
00480             /*
00481              * Continue to stay in Shift-DR state and shift in the TDI value. At the end 
00482              * of the operation, go to the state specified in the last XENDDR command. No
00483              * comparison of TDO value with the last specified expected value is performed.
00484              */
00485             rc = Shift(drSize, tdiVal, 0, SHIFT_DR, endDr);
00486             break;
00487 
00488         case XSDRTDOB:
00489         case XSDRTDOC:
00490             /*
00491              * Go to the Shift-DR state and shift in the TDI value. Compare all bits of the 
00492              * expected value against the TDO value that is shifted out. No retries are
00493              * performed.
00494              */
00495             rc = Shift(drSize, tdiVal, tdoExp, SHIFT_DR, SHIFT_DR);
00496             break;
00497 
00498         case XSDRTDOE:
00499             /*
00500              * Continue to stay in Shift-DR state and shift in the TDI value. Compare all 
00501              * bits of the expected value against the TDO value that is shifted out. At the 
00502              * end of the operation, go to the state specified in the last XENDDR command.
00503              * No retries are performed.
00504              */
00505             rc = Shift(drSize, tdiVal, tdoExp, SHIFT_DR, endDr);
00506             break;
00507 
00508         case XSTATE:
00509             /*
00510              * Immediately set the TAP controller to Test-Logic-Reset (0) or Run-Test_idle (1).
00511              */
00512             rc = TapStateChange(XsvfGetState(TEST_LOGIC_RESET, RUN_TEST_IDLE));
00513             break;
00514 
00515         case XENDIR:
00516             /* 
00517              * Set the XSIR end state to Run-Test-Idle (0) or Pause-IR (1).
00518              */
00519             endIr = XsvfGetState(RUN_TEST_IDLE, PAUSE_IR);
00520             break;
00521 
00522         case XENDDR:
00523             /*
00524              * Set the XSDR/XSDRTDO end state to Run-Test-Idle (0) or Pause-DR (1).
00525              */
00526             endDr = XsvfGetState(RUN_TEST_IDLE, PAUSE_DR);
00527             break;
00528 
00529         case XSETSDRMASKS:
00530             /*
00531              * Set SDR address and data masks for interatin XSDR commands.
00532              */
00533             XsvfReadBitString(addrMask, drSize);
00534             XsvfReadBitString(dataMask, drSize);
00535             drSize2 = BitStringOnes(drSize, dataMask);
00536             break;
00537 
00538         case XSDRINC:
00539             /*
00540              * Do iterating XSDR commands.
00541              */
00542             XsvfReadBitString(tdiVal, drSize);
00543             rc = ReShift(drSize, tdiVal, tdoExp, tdoMask, SHIFT_DR, endDr, delay, retries);
00544             if (rc == 0) {
00545                 int num = XsvfGetByte();
00546 
00547                 while(num-- && rc == 0) {
00548                     XsvfReadBitString(tdiVal2, drSize2);
00549                     BitStringAdd(drSize, tdiVal, addrMask);
00550                     UpdateTdi(drSize, tdiVal, drSize2, tdiVal2, dataMask);
00551                     rc = ReShift(drSize, tdiVal, tdoExp, tdoMask, SHIFT_DR, endDr, delay, retries);
00552                 }
00553             }
00554             break;
00555 
00556         case XCOMMENT:
00557             /*
00558              * Skip comment string.
00559              */
00560             XsvfSkipComment();
00561             break;
00562 
00563         default:
00564             rc = XE_ILLEGALCMD;
00565             break;
00566         }
00567 
00568         /* Check for errors in the platform dependant interface. */
00569         if(rc == 0) {
00570             rc = XsvfGetError();
00571         }
00572     }
00573     return rc;
00574 }
00575 
00576 /*!
00577  * \brief XSVF Executor.
00578  *
00579  * Program entry point.
00580  */
00581 int main(void)
00582 {
00583     int rc;
00584 
00585     /* Platform dependant initialization. */
00586     rc = XsvfInit();
00587 
00588     if(rc == 0) {
00589         /* Execute XSVF commands. */
00590         rc = Execute();
00591     }
00592 
00593     /* Platform dependant clean up. */
00594     XsvfExit(rc);
00595 
00596     return rc;
00597 }
00598 
00599 /*@}*/

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