xsvfexec.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  1. /*
  2. * Copyright (C) 2004-2007 by egnite Software GmbH
  3. * Copyright (C) 2008 by egnite GmbH
  4. *
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. * 3. Neither the name of the copyright holders nor the names of
  17. * contributors may be used to endorse or promote products derived
  18. * from this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  23. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  24. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  25. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  26. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  27. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  28. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  29. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  30. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. *
  33. * For additional information see http://www.ethernut.de/
  34. * and Xilinx Application Note XAPP058.
  35. */
  36. /*
  37. * $Log$
  38. * Revision 1.1 2008/10/20 13:10:05 haraldkipp
  39. * Checked in.
  40. *
  41. */
  42. #ifdef _MSC_VER
  43. #include <winsock2.h>
  44. #endif
  45. #include "xsvf.h"
  46. #include "host.h"
  47. #include "tapsm.h"
  48. #include <stdio.h>
  49. /*!
  50. * \file xsvfexec.c
  51. *
  52. * \brief Executor main file.
  53. */
  54. /*!
  55. * \addtogroup xgBitString
  56. */
  57. /*@{*/
  58. /*!
  59. * \brief Compare two bit string using an optional bit mask.
  60. *
  61. * \param len Number of bits in the bit strings.
  62. * \param op1 Pointer to the first bit string.
  63. * \param op2 Pointer to the second bit string.
  64. * \param mask Pointer to the mask. Bits are compared only if the corresponding
  65. * bit in the mask is set. If this pointer is set to NULL, all
  66. * bits will be compared.
  67. *
  68. * \return 0 if equal, 1 otherwise.
  69. */
  70. static int BitStringCmp(int len, uint8_t *op1, uint8_t *op2, uint8_t *mask)
  71. {
  72. int rc = 0;
  73. #if !defined(_WIN32)
  74. int i;
  75. uint8_t diff;
  76. for (i = 0; i < len; i += 8) {
  77. diff = *op1++ ^ *op2++;
  78. if (mask) {
  79. diff &= *mask++;
  80. }
  81. if (diff) {
  82. rc = 1;
  83. break;
  84. }
  85. }
  86. #endif
  87. return rc;
  88. }
  89. /*!
  90. * \brief Numeric addition of two bit string.
  91. *
  92. * \param len Number of bits in the bit strings.
  93. * \param op1 Pointer to the first bit string, which will also receive
  94. * the final result.
  95. * \param op2 Pointer to the second bit string. Will be added to the first.
  96. */
  97. static void BitStringAdd(int len, uint8_t *op1, uint8_t *op2)
  98. {
  99. int i;
  100. uint16_t sum;
  101. uint8_t ovr = 0;
  102. i = (int)((len + 7UL) / 8UL);
  103. while (i--) {
  104. if((sum = (uint16_t)((uint16_t)op1[i] + (uint16_t)op2[i] + ovr)) > (uint16_t)255) {
  105. ovr = 1;
  106. }
  107. else {
  108. ovr = 0;
  109. }
  110. op1[i] = (uint8_t)sum;
  111. }
  112. }
  113. /*!
  114. * \brief Count the number of bits set to one in a bit string.
  115. *
  116. * \param len Number of bits in the bit string.
  117. * \param op Pointer to the bit string.
  118. *
  119. * \return The number of bits set to one.
  120. */
  121. static int BitStringOnes(int len, uint8_t *op)
  122. {
  123. int rc = 0;
  124. uint8_t mask;
  125. int i = (int)((len + 7UL) / 8UL);
  126. while (i--) {
  127. for(mask = op[i]; mask; mask >>= 1) {
  128. rc += mask & 1;
  129. }
  130. }
  131. return rc;
  132. }
  133. /*@}*/
  134. /*!
  135. * \addtogroup xgXsvfExec
  136. */
  137. /*@{*/
  138. /*!
  139. * \brief Prepare the next TDI value for iterating XSDR.
  140. *
  141. * \param len Number of bits in the first TDI value.
  142. * \param tdi_val First TDI value, the one which will be updated.
  143. * \param len2 Number of bits in the second TDI value.
  144. * \param tdi_val2 Second TDI value.
  145. * \param data_mask The data mask used for the update.
  146. */
  147. static void UpdateTdi(int len, uint8_t *tdi_val, int len2, uint8_t *tdi_val2, uint8_t *data_mask)
  148. {
  149. uint8_t tdibit;
  150. uint8_t mask;
  151. int i;
  152. uint8_t d = 0;
  153. uint8_t m = 0;
  154. for (i = len - 1; i >= 0; --i) {
  155. mask = data_mask[i];
  156. if (mask) {
  157. tdibit = 1;
  158. while (mask) {
  159. if (mask & 1) {
  160. if (m == 0) {
  161. d = tdi_val2[--len2];
  162. m = 1;
  163. }
  164. if (d & m) {
  165. tdi_val[i] |= tdibit;
  166. } else {
  167. tdi_val[i] &= ~tdibit;
  168. }
  169. m <<= 1;
  170. }
  171. tdibit <<= 1;
  172. mask >>= 1;
  173. }
  174. }
  175. }
  176. }
  177. /*!
  178. * \brief Repeat shifting out a TDI value until an expected TDO value appears.
  179. *
  180. * \param len Number of bits to shift.
  181. * \param tdi_val TDI value to shift out.
  182. * \param tdo_exp Expected TDO value. Set to NULL if not available.
  183. * \param tdo_msk Used to mask out don't care TDO values.
  184. * \param sState TAP state during shift operation, either SHIFT-DR or SHIFT-IR. No
  185. * retries are allowed with SHIFT-IR.
  186. * \param eState TAP state after shift operation.
  187. * \param delay Idle time (in microseconds) after each shift.
  188. * \param retries Maximum number of retries. Ignored if expected TDO value is not available.
  189. *
  190. * \return Zero on success, otherwise an error code is returned.
  191. */
  192. static int ReShift(int len, uint8_t *tdi_val, uint8_t *tdo_exp, uint8_t *tdo_msk,
  193. uint8_t sState, uint8_t eState, long delay, uint8_t retries)
  194. {
  195. int rc = 0;
  196. uint8_t tdo_val[MAX_BITVEC_BYTES];
  197. if (len == 0) {
  198. if (delay) {
  199. TapStateChange(RUN_TEST_IDLE);
  200. XsvfDelay(delay);
  201. }
  202. } else {
  203. int last_byte = (int)((len + 7UL) / 8UL - 1UL);
  204. /*
  205. * Retry loop.
  206. */
  207. do {
  208. uint8_t *tdi = &tdi_val[last_byte];
  209. uint8_t *tdo = &tdo_val[last_byte];
  210. int bitcnt;
  211. uint8_t bitmsk;
  212. TapStateChange(sState);
  213. /*
  214. * Byte loop.
  215. */
  216. for(bitcnt = len; bitcnt;) {
  217. *tdo = 0;
  218. /*
  219. * Bit loop. LSB is shifted first.
  220. */
  221. for (bitmsk = 1; bitmsk && bitcnt; bitmsk <<= 1) {
  222. if (sState != eState && bitcnt == 1) {
  223. /* Exit Shift state with last bit. */
  224. SET_TMS();
  225. TapStateInc();
  226. }
  227. /* Shift TDI in and TDO out. */
  228. if(*tdi & bitmsk) {
  229. SET_TDI();
  230. }
  231. else {
  232. CLR_TDI();
  233. }
  234. CLR_TCK();
  235. /*
  236. * This is time critical, because TDO may be delayed.
  237. * The following decrement of our int value consumes
  238. * some CPU cycles.
  239. */
  240. bitcnt--;
  241. if(GET_TDO()) {
  242. *tdo |= bitmsk;
  243. }
  244. SET_TCK();
  245. }
  246. tdi--;
  247. tdo--;
  248. }
  249. /*
  250. * Compare captured with expected TDO result.
  251. */
  252. if (tdo_exp) {
  253. if(BitStringCmp(len, tdo_exp, tdo_val, tdo_msk)) {
  254. rc = XE_TDOMISMATCH;
  255. }
  256. else {
  257. rc = 0;
  258. }
  259. }
  260. /*
  261. * Update TAP controller state.
  262. */
  263. if (sState != eState) {
  264. if (rc && delay && retries) {
  265. /* The TDO value does not match the expected value. */
  266. TapStateChange(PAUSE_DR);
  267. TapStateChange(SHIFT_DR);
  268. } else {
  269. TapStateChange(eState);
  270. }
  271. /*
  272. * If the XRUNTEST time is non-zero, go to the Run-Test/Idle state
  273. * and wait for the specified number of microseconds.
  274. */
  275. if (delay) {
  276. TapStateChange(RUN_TEST_IDLE);
  277. XsvfDelay(delay);
  278. /* In case of another retry, increase idle time by 25%. */
  279. delay += (delay >> 2);
  280. }
  281. }
  282. } while (rc && retries--);
  283. }
  284. return rc;
  285. }
  286. /*!
  287. * \brief Shift next TDI value out and optionally capture TDO value.
  288. *
  289. * No delays and no retries are performed.
  290. *
  291. * \param len Number of bits to shift.
  292. * \param tdi_val Pointer to TDI value buffer.
  293. * \param tdo_exp Pointer to expected TDO value buffer. If NULL, no TDO value will
  294. * be read from the XSVF buffer and no comparision will take place.
  295. * \param sState TAP state during shift operation, either SHIFT-DR or SHIFT-IR.
  296. * \param eState TAP state after shift operation.
  297. *
  298. * \return Zero on success, otherwise an error code is returned.
  299. */
  300. static int Shift(int len, uint8_t *tdi_val, uint8_t *tdo_exp, uint8_t sState, uint8_t eState)
  301. {
  302. XsvfReadBitString(tdi_val, len);
  303. if(tdo_exp) {
  304. XsvfReadBitString(tdo_exp, len);
  305. }
  306. return ReShift(len, tdi_val, tdo_exp, 0, sState, eState, 0, 0);
  307. }
  308. /*!
  309. * \brief TDI value buffer.
  310. */
  311. static uint8_t tdiVal[MAX_BITVEC_BYTES];
  312. /*!
  313. * \brief TDI value 2 buffer.
  314. */
  315. static uint8_t tdiVal2[MAX_BITVEC_BYTES];
  316. /*!
  317. * \brief Expected TDO value buffer.
  318. */
  319. static uint8_t tdoExp[MAX_BITVEC_BYTES];
  320. /*!
  321. * \brief TDO mask buffer.
  322. */
  323. static uint8_t tdoMask[MAX_BITVEC_BYTES];
  324. /*!
  325. * \brief Data mask buffer.
  326. */
  327. static uint8_t dataMask[MAX_BITVEC_BYTES];
  328. /*!
  329. * \brief Address mask buffer.
  330. */
  331. static uint8_t addrMask[MAX_BITVEC_BYTES];
  332. /*!
  333. * \brief Execute an XSVF buffer.
  334. *
  335. * This routine interprets a compressed SVF command sequence following
  336. * the Xilinx application note XAPP503.
  337. *
  338. * \return Zero on success, otherwise an error code is returned.
  339. */
  340. static int Execute(void)
  341. {
  342. int rc = 0;
  343. uint8_t cmd;
  344. uint8_t endIr = RUN_TEST_IDLE;
  345. uint8_t endDr = RUN_TEST_IDLE;
  346. uint8_t retries = DEFAULT_REPEAT;
  347. long delay = 0;
  348. int drSize = 0;
  349. int drSize2 = 0;
  350. int irSize;
  351. TapStateInit();
  352. /* Process the XSVF commands */
  353. while (rc == 0) {
  354. cmd = XsvfGetCmd();
  355. if(cmd == XCOMPLETE) {
  356. /*
  357. * Normal end of the XSVF buffer reached.
  358. */
  359. break;
  360. }
  361. switch(cmd) {
  362. case XTDOMASK:
  363. /*
  364. * Set the TDO mask. Length has been specified by the last XSDRSIZE command.
  365. */
  366. XsvfReadBitString(tdoMask, drSize);
  367. break;
  368. case XRUNTEST:
  369. /*
  370. * Set the number of microseconds the device should stay in the Run-Test-Idle
  371. * state after each visit to the SDR state.
  372. */
  373. delay = XsvfGetLong();
  374. break;
  375. case XREPEAT:
  376. /*
  377. * Set the number of times that TDO is tested against the expected value before
  378. * the programming operation is considered a failure.
  379. */
  380. retries = XsvfGetByte();
  381. break;
  382. case XSDRSIZE:
  383. /*
  384. * Set the length of the next XSDR/XSDRTDO records that follow.
  385. */
  386. drSize = (int)XsvfGetLong();
  387. if ((drSize + 7) / 8 > MAX_BITVEC_BYTES) {
  388. rc = XE_DATAOVERFLOW;
  389. }
  390. break;
  391. case XSIR:
  392. case XSIR2:
  393. /*
  394. * Go to the Shift-IR state and shift in the TDI value. XSIR uses
  395. * a single byte for the TDI size, while XSIR2 uses two bytes.
  396. */
  397. if(cmd == XSIR) {
  398. irSize = XsvfGetByte();
  399. }
  400. else {
  401. irSize = XsvfGetShort();
  402. }
  403. XsvfReadBitString(tdiVal, irSize);
  404. rc = ReShift(irSize, tdiVal, 0, 0, SHIFT_IR, endIr, delay, 0);
  405. break;
  406. case XSDRTDO:
  407. /*
  408. * Go to the Shift-DR state and shift in the TDI value; compare the expected
  409. * value against the TDO value that was shifted out. Use the TDO mask which
  410. * was generated by the last XTDOMASK command.
  411. *
  412. * The expected TDO value is re-used in successive XSDR commands.
  413. */
  414. XsvfReadBitString(tdiVal, drSize);
  415. XsvfReadBitString(tdoExp, drSize);
  416. rc = ReShift(drSize, tdiVal, tdoExp, tdoMask, SHIFT_DR, endDr, delay, retries);
  417. break;
  418. case XSDR:
  419. /*
  420. * Go to the Shift-DR state and shift in the TDI value; compare the expected
  421. * value from the last XSDRTDO command against the TDO value that was
  422. * shifted out. Use the TDO mask which was generated by the last XTDOMASK
  423. * instruction.
  424. */
  425. XsvfReadBitString(tdiVal, drSize);
  426. rc = ReShift(drSize, tdiVal, tdoExp, tdoMask, SHIFT_DR, endDr, delay, retries);
  427. break;
  428. case XSDRB:
  429. case XSDRC:
  430. /*
  431. * Go to the Shift-DR state and shift in the TDI value. No comparison of TDO
  432. * value with the last specified expected value is performed.
  433. */
  434. rc = Shift(drSize, tdiVal, 0, SHIFT_DR, SHIFT_DR);
  435. break;
  436. case XSDRE:
  437. /*
  438. * Continue to stay in Shift-DR state and shift in the TDI value. At the end
  439. * of the operation, go to the state specified in the last XENDDR command. No
  440. * comparison of TDO value with the last specified expected value is performed.
  441. */
  442. rc = Shift(drSize, tdiVal, 0, SHIFT_DR, endDr);
  443. break;
  444. case XSDRTDOB:
  445. case XSDRTDOC:
  446. /*
  447. * Go to the Shift-DR state and shift in the TDI value. Compare all bits of the
  448. * expected value against the TDO value that is shifted out. No retries are
  449. * performed.
  450. */
  451. rc = Shift(drSize, tdiVal, tdoExp, SHIFT_DR, SHIFT_DR);
  452. break;
  453. case XSDRTDOE:
  454. /*
  455. * Continue to stay in Shift-DR state and shift in the TDI value. Compare all
  456. * bits of the expected value against the TDO value that is shifted out. At the
  457. * end of the operation, go to the state specified in the last XENDDR command.
  458. * No retries are performed.
  459. */
  460. rc = Shift(drSize, tdiVal, tdoExp, SHIFT_DR, endDr);
  461. break;
  462. case XSTATE:
  463. /*
  464. * Immediately set the TAP controller to Test-Logic-Reset (0) or Run-Test_idle (1).
  465. */
  466. rc = TapStateChange(XsvfGetState(TEST_LOGIC_RESET, RUN_TEST_IDLE));
  467. break;
  468. case XENDIR:
  469. /*
  470. * Set the XSIR end state to Run-Test-Idle (0) or Pause-IR (1).
  471. */
  472. endIr = XsvfGetState(RUN_TEST_IDLE, PAUSE_IR);
  473. break;
  474. case XENDDR:
  475. /*
  476. * Set the XSDR/XSDRTDO end state to Run-Test-Idle (0) or Pause-DR (1).
  477. */
  478. endDr = XsvfGetState(RUN_TEST_IDLE, PAUSE_DR);
  479. break;
  480. case XSETSDRMASKS:
  481. /*
  482. * Set SDR address and data masks for interatin XSDR commands.
  483. */
  484. XsvfReadBitString(addrMask, drSize);
  485. XsvfReadBitString(dataMask, drSize);
  486. drSize2 = BitStringOnes(drSize, dataMask);
  487. break;
  488. case XSDRINC:
  489. /*
  490. * Do iterating XSDR commands.
  491. */
  492. XsvfReadBitString(tdiVal, drSize);
  493. rc = ReShift(drSize, tdiVal, tdoExp, tdoMask, SHIFT_DR, endDr, delay, retries);
  494. if (rc == 0) {
  495. int num = XsvfGetByte();
  496. while(num-- && rc == 0) {
  497. XsvfReadBitString(tdiVal2, drSize2);
  498. BitStringAdd(drSize, tdiVal, addrMask);
  499. UpdateTdi(drSize, tdiVal, drSize2, tdiVal2, dataMask);
  500. rc = ReShift(drSize, tdiVal, tdoExp, tdoMask, SHIFT_DR, endDr, delay, retries);
  501. }
  502. }
  503. break;
  504. case XCOMMENT:
  505. /*
  506. * Skip comment string.
  507. */
  508. XsvfSkipComment();
  509. break;
  510. default:
  511. rc = XE_ILLEGALCMD;
  512. break;
  513. }
  514. /* Check for errors in the platform dependant interface. */
  515. if(rc == 0) {
  516. rc = XsvfGetError();
  517. }
  518. }
  519. return rc;
  520. }
  521. /*!
  522. * \brief XSVF Executor.
  523. *
  524. * Program entry point.
  525. */
  526. int main(void)
  527. {
  528. int rc;
  529. /* Platform dependant initialization. */
  530. rc = XsvfInit();
  531. if(rc == 0) {
  532. /* Execute XSVF commands. */
  533. rc = Execute();
  534. }
  535. /* Platform dependant clean up. */
  536. XsvfExit(rc);
  537. return rc;
  538. }
  539. /*@}*/