mirror of
https://github.com/ole00/afterburner.git
synced 2026-01-16 00:19:18 +00:00
Afterburner's features / PLD chip support can now be disabled to reduce the flash memory footprint. This allows to run Afterburner on Arduinos based on Atmega32u4 MCU, like Leonardo, Yun, Micro while scrificing some functionality which may not be important to the user.
998 lines
29 KiB
C
998 lines
29 KiB
C
#ifndef _JTAG_XSVF_PLAYER_H_
|
|
#define _JTAG_XSVF_PLAYER_H_
|
|
|
|
#if USE_JTAG_PLAYER
|
|
|
|
/*
|
|
Arduino JTAG Player for Afterburner GAL project
|
|
---------------------------------------
|
|
Adapted from JTAG library 1.0.15 by Marcelo Jimenez
|
|
https://github.com/mrjimenez/JTAG
|
|
|
|
This port:
|
|
* improves flash size on AVR MCU (about 6.5kb vs 11kb)
|
|
|
|
* allows to allocate JTAG internal buffers temporarily within a shared
|
|
global buffer (heap). Define XSVF_HEAP to enable such feature:
|
|
uint8_t heap[900];
|
|
#define XSVF_HEAP heap
|
|
#include "jtag_xsvf_player.h"
|
|
|
|
* reduces the code to a single .h file
|
|
|
|
Use the original JTAG libray python scripts to upload XSVF files
|
|
from your PC:
|
|
./xsvf -p /dev/ttyACM0 my_file.xsvf
|
|
|
|
Arduino usage:
|
|
jtag_port_t jport;
|
|
|
|
Serial.begin(115200);
|
|
|
|
//assign jtag pins (vref pin checks the cable is plugged in)
|
|
jport.tms = 12;
|
|
jport.tdi = 2;
|
|
jport.tdo = 4;
|
|
jport.tck = 3;
|
|
jport.vref = 10;
|
|
|
|
//process XSVF data received from serial port
|
|
jtag_play_xsvf(&jport);
|
|
|
|
*/
|
|
|
|
//value bigger than 63 may cause reading errors on AVR MCUs.
|
|
#define XSVF_BUF_SIZE 62
|
|
|
|
#define XSVF_DEBUG 0
|
|
#define XSVF_CALC_CSUM 1
|
|
#define XSVF_IGNORE_NOMATCH 0
|
|
|
|
#define XCOMPLETE 0
|
|
#define XTDOMASK 1
|
|
#define XSIR 2
|
|
#define XSDR 3
|
|
#define XRUNTEST 4
|
|
#define XRESERVED_5 5
|
|
#define XRESERVED_6 6
|
|
#define XREPEAT 7
|
|
#define XSDRSIZE 8
|
|
#define XSDRTDO 9
|
|
#define XSETSDRMASKS 10
|
|
#define XSDRINC 11
|
|
#define XSDRB 12
|
|
#define XSDRC 13
|
|
#define XSDRE 14
|
|
#define XSDRTDOB 15
|
|
#define XSDRTDOC 16
|
|
#define XSDRTDOE 17
|
|
#define XSTATE 18
|
|
#define XENDIR 19
|
|
#define XENDDR 20
|
|
#define XSIR2 21
|
|
#define XCOMMENT 22
|
|
#define XWAIT 23
|
|
#define XWAITSTATE 24
|
|
#define XTRST 28
|
|
|
|
#define S_MAX_CHAIN_SIZE_BYTES 129
|
|
#define S_MAX_CHAIN_SIZE_BITS (S_MAX_CHAIN_SIZE_BYTES * 8)
|
|
|
|
#define STATE_RUN_TEST_IDLE 1
|
|
#define STATE_PAUSE_DR 6
|
|
#define STATE_PAUSE_IR 13
|
|
|
|
#define ERR_IO 1
|
|
#define ERR_XSIR_SIZE 2
|
|
#define ERR_XSDRSIZE 3
|
|
#define ERR_XENDIR 4
|
|
#define ERR_XENDDR 5
|
|
#define ERR_XSDR 6
|
|
#define ERR_INSTR_NOT_IMPLEMENTED 99
|
|
#define ERR_DR_CHECK_FAILED 101
|
|
|
|
|
|
/*
|
|
* Low nibble : TMS == 0
|
|
* High nibble: TMS == 1
|
|
*/
|
|
|
|
#define TMS_T(TMS_HIGH_STATE, TMS_LOW_STATE) (((TMS_HIGH_STATE) << 4) | (TMS_LOW_STATE))
|
|
|
|
#define XSTATE_TEST_LOGIC_RESET 0
|
|
#define XSTATE_RUN_TEST_IDLE 1
|
|
#define XSTATE_SELECT_DR_SCAN 2
|
|
#define XSTATE_CAPTURE_DR 3
|
|
#define XSTATE_SHIFT_DR 4
|
|
#define XSTATE_EXIT1_DR 5
|
|
#define XSTATE_PAUSE_DR 6
|
|
#define XSTATE_EXIT2_DR 7
|
|
#define XSTATE_UPDATE_DR 8
|
|
#define XSTATE_SELECT_IR_SCAN 9
|
|
#define XSTATE_CAPTURE_IR 10
|
|
#define XSTATE_SHIFT_IR 11
|
|
#define XSTATE_EXIT1_IR 12
|
|
#define XSTATE_PAUSE_IR 13
|
|
#define XSTATE_EXIT2_IR 14
|
|
#define XSTATE_UPDATE_IR 15
|
|
|
|
#define TMS_T00 /* STATE_TEST_LOGIC_RESET */ TMS_T(XSTATE_TEST_LOGIC_RESET, XSTATE_RUN_TEST_IDLE)
|
|
#define TMS_T01 /* STATE_RUN_TEST_IDLE */ TMS_T(XSTATE_SELECT_DR_SCAN, XSTATE_RUN_TEST_IDLE)
|
|
#define TMS_T02 /* STATE_SELECT_DR_SCAN */ TMS_T(XSTATE_SELECT_IR_SCAN, XSTATE_CAPTURE_DR)
|
|
#define TMS_T03 /* STATE_CAPTURE_DR */ TMS_T(XSTATE_EXIT1_DR, XSTATE_SHIFT_DR)
|
|
#define TMS_T04 /* STATE_SHIFT_DR */ TMS_T(XSTATE_EXIT1_DR, XSTATE_SHIFT_DR)
|
|
#define TMS_T05 /* STATE_EXIT1_DR */ TMS_T(XSTATE_UPDATE_DR, XSTATE_PAUSE_DR)
|
|
#define TMS_T06 /* STATE_PAUSE_DR */ TMS_T(XSTATE_EXIT2_DR, XSTATE_PAUSE_DR)
|
|
#define TMS_T07 /* STATE_EXIT2_DR */ TMS_T(XSTATE_UPDATE_DR, XSTATE_SHIFT_DR)
|
|
#define TMS_T08 /* STATE_UPDATE_DR */ TMS_T(XSTATE_SELECT_DR_SCAN, XSTATE_RUN_TEST_IDLE)
|
|
#define TMS_T09 /* STATE_SELECT_IR_SCAN */ TMS_T(XSTATE_TEST_LOGIC_RESET, XSTATE_CAPTURE_IR)
|
|
#define TMS_T10 /* STATE_CAPTURE_IR */ TMS_T(XSTATE_EXIT1_IR, XSTATE_SHIFT_IR)
|
|
#define TMS_T11 /* STATE_SHIFT_IR */ TMS_T(XSTATE_EXIT1_IR, XSTATE_SHIFT_IR)
|
|
#define TMS_T12 /* STATE_EXIT1_IR */ TMS_T(XSTATE_UPDATE_IR, XSTATE_PAUSE_IR)
|
|
#define TMS_T13 /* STATE_PAUSE_IR */ TMS_T(XSTATE_EXIT2_IR, XSTATE_PAUSE_IR)
|
|
#define TMS_T14 /* STATE_EXIT2_IR */ TMS_T(XSTATE_UPDATE_IR, XSTATE_SHIFT_IR)
|
|
#define TMS_T15 /* STATE_UPDATE_IR */ TMS_T(XSTATE_SELECT_DR_SCAN, XSTATE_RUN_TEST_IDLE)
|
|
|
|
|
|
#define BITSTR(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) ( \
|
|
((uint16_t)(A) << 15) | \
|
|
((uint16_t)(B) << 14) | \
|
|
((uint16_t)(C) << 13) | \
|
|
((uint16_t)(D) << 12) | \
|
|
((uint16_t)(E) << 11) | \
|
|
((uint16_t)(F) << 10) | \
|
|
((uint16_t)(G) << 9) | \
|
|
((uint16_t)(H) << 8) | \
|
|
((uint16_t)(I) << 7) | \
|
|
((uint16_t)(J) << 6) | \
|
|
((uint16_t)(K) << 5) | \
|
|
((uint16_t)(L) << 4) | \
|
|
((uint16_t)(M) << 3) | \
|
|
((uint16_t)(N) << 2) | \
|
|
((uint16_t)(O) << 1) | \
|
|
((uint16_t)(P) << 0) )
|
|
|
|
/*
|
|
* The index of this vector is the current state. The i-th bit tells you the
|
|
* value TMS must assume in order to go to state "i".
|
|
|
|
------------------------------------------------------------------------------------------------------------
|
|
| | || F | E | D | C || B | A | 9 | 8 || 7 | 6 | 5 | 4 || 3 | 2 | 1 | 0 || HEX |
|
|
------------------------------------------------------------------------------------------------------------
|
|
| STATE_TEST_LOGIC_RESET | 0 || 0 | 0 | 0 | 0 || 0 | 0 | 0 | 0 || 0 | 0 | 0 | 0 || 0 | 0 | 0 | 1 || 0x0001 |
|
|
| STATE_RUN_TEST_IDLE | 1 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 1 | 1 | 0 | 1 || 0xFFFD |
|
|
| STATE_SELECT_DR_SCAN | 2 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 0 || 0 | 0 | 0 | 0 || 0 | x | 1 | 1 || 0xFE03 |
|
|
| STATE_CAPTURE_DR | 3 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 0 || x | 1 | 1 | 1 || 0xFFE7 |
|
|
| STATE_SHIFT_DR | 4 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 0 || 1 | 1 | 1 | 1 || 0xFFEF |
|
|
| STATE_EXIT1_DR | 5 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 0 | 0 | x | 0 || 1 | 1 | 1 | 1 || 0xFF0F |
|
|
| STATE_PAUSE_DR | 6 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 1 | 0 | 1 | 1 || 1 | 1 | 1 | 1 || 0xFFBF |
|
|
| STATE_EXIT2_DR | 7 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || x | 0 | 0 | 0 || 1 | 1 | 1 | 1 || 0xFF0F |
|
|
| STATE_UPDATE_DR | 8 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | x || 1 | 1 | 1 | 1 || 1 | 1 | 0 | 1 || 0xFEFD |
|
|
| STATE_SELECT_IR_SCAN | 9 || 0 | 0 | 0 | 0 || 0 | 0 | x | 1 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 0x01FF |
|
|
| STATE_CAPTURE_IR | A || 1 | 1 | 1 | 1 || 0 | x | 1 | 1 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 0xF3FF |
|
|
| STATE_SHIFT_IR | B || 1 | 1 | 1 | 1 || 0 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 0xF7FF |
|
|
| STATE_EXIT1_IR | C || 1 | 0 | 0 | x || 0 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 0x87FF |
|
|
| STATE_PAUSE_IR | D || 1 | 1 | 0 | 1 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 0xDFFF |
|
|
| STATE_EXIT2_IR | E || 1 | x | 0 | 0 || 0 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 0x87FF |
|
|
| STATE_UPDATE_IR | F || x | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 1 | 1 | 0 | 1 || 0x7FFD |
|
|
------------------------------------------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#define BS00 /* STATE_TEST_LOGIC_RESET */ BITSTR( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 )
|
|
#define BS01 /* STATE_RUN_TEST_IDLE */ BITSTR( 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1 )
|
|
#define BS02 /* STATE_SELECT_DR_SCAN */ BITSTR( 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1 )
|
|
#define BS03 /* STATE_CAPTURE_DR */ BITSTR( 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1 )
|
|
#define BS04 /* STATE_SHIFT_DR */ BITSTR( 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1 )
|
|
#define BS05 /* STATE_EXIT1_DR */ BITSTR( 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1 )
|
|
#define BS06 /* STATE_PAUSE_DR */ BITSTR( 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1 )
|
|
#define BS07 /* STATE_EXIT2_DR */ BITSTR( 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1 )
|
|
#define BS08 /* STATE_UPDATE_DR */ BITSTR( 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1 )
|
|
#define BS09 /* STATE_SELECT_IR_SCAN */ BITSTR( 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 )
|
|
#define BS10 /* STATE_CAPTURE_IR */ BITSTR( 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 )
|
|
#define BS11 /* STATE_SHIFT_IR */ BITSTR( 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 )
|
|
#define BS12 /* STATE_EXIT1_IR */ BITSTR( 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 )
|
|
#define BS13 /* STATE_PAUSE_IR */ BITSTR( 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 )
|
|
#define BS14 /* STATE_EXIT2_IR */ BITSTR( 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 )
|
|
#define BS15 /* STATE_UPDATE_IR */ BITSTR( 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1 )
|
|
|
|
|
|
typedef struct xsvf_t {
|
|
uint8_t* xsvf_tdo_mask;
|
|
uint8_t* xsvf_tdi;
|
|
uint8_t* xsvf_tdo;
|
|
uint8_t* xsvf_tdo_expected;
|
|
uint8_t* xsvf_address_mask;
|
|
uint8_t* xsvf_data_mask;
|
|
|
|
uint32_t rdpos;
|
|
uint32_t wrpos;
|
|
|
|
#if XSVF_CALC_CSUM
|
|
uint32_t csum;
|
|
#endif
|
|
|
|
uint16_t instruction_counter;
|
|
uint8_t error;
|
|
uint8_t xcomplete;
|
|
|
|
uint16_t sirsize_bits;
|
|
uint16_t sirsize_bytes;
|
|
|
|
uint32_t sdrsize_bits;
|
|
uint32_t sdrsize_bytes;
|
|
uint32_t runtest;
|
|
|
|
uint8_t repeat;
|
|
uint8_t next_state;
|
|
uint8_t endir_state;
|
|
uint8_t enddr_state;
|
|
|
|
uint32_t wait_time_usecs;
|
|
uint8_t wait_start_state;
|
|
uint8_t wait_end_state;
|
|
uint8_t jtag_current_state;
|
|
|
|
} xsvf_t;
|
|
|
|
#ifdef XSVF_HEAP
|
|
// variables will be allocated on heap
|
|
uint8_t* xsvf_buf;
|
|
xsvf_t* xsvf;
|
|
uint8_t* xsvf_tms_transitions;
|
|
uint16_t* xsvf_tms_map;
|
|
#else /* XSVF_HEAP */
|
|
// variables allocated globally
|
|
uint8_t xsvf_buf[XSVF_BUF_SIZE];
|
|
uint8_t xsvf_tdo_mask[S_MAX_CHAIN_SIZE_BYTES];
|
|
uint8_t xsvf_tdi[S_MAX_CHAIN_SIZE_BYTES];
|
|
uint8_t xsvf_tdo[S_MAX_CHAIN_SIZE_BYTES];
|
|
uint8_t xsvf_tdo_expected[S_MAX_CHAIN_SIZE_BYTES];
|
|
uint8_t xsvf_address_mask[S_MAX_CHAIN_SIZE_BYTES];
|
|
uint8_t xsvf_data_mask[S_MAX_CHAIN_SIZE_BYTES];
|
|
xsvf_t xsvf_context;
|
|
xsvf_t* xsvf = &xsvf_context;
|
|
|
|
static const uint8_t xsvf_tms_transitions[] = {
|
|
TMS_T00, TMS_T01, TMS_T02, TMS_T03, TMS_T04, TMS_T05, TMS_T06, TMS_T07,
|
|
TMS_T08, TMS_T09, TMS_T10, TMS_T11, TMS_T12, TMS_T13, TMS_T14, TMS_T15,
|
|
};
|
|
static const uint16_t xsvf_tms_map[] = {
|
|
BS00, BS01, BS02, BS03, BS04, BS05, BS06, BS07,
|
|
BS08, BS09, BS10, BS11, BS12, BS13, BS14, BS15
|
|
};
|
|
#endif
|
|
|
|
|
|
|
|
typedef struct jtag_port_t {
|
|
uint8_t tms;
|
|
uint8_t tdi;
|
|
uint8_t tdo;
|
|
uint8_t tck;
|
|
uint8_t vref;
|
|
} jtag_port_t;
|
|
|
|
static void jtag_port_init(jtag_port_t* port) {
|
|
pinMode(port->tms, OUTPUT);
|
|
pinMode(port->tdi, OUTPUT);
|
|
pinMode(port->tck, OUTPUT);
|
|
pinMode(port->tdo, INPUT);
|
|
pinMode(port->vref, INPUT);
|
|
}
|
|
|
|
static void jtag_port_pulse_clock(jtag_port_t* port) {
|
|
digitalWrite(port->tck, 0);
|
|
delayMicroseconds(1);
|
|
digitalWrite(port->tck, 1);
|
|
}
|
|
|
|
static uint8_t jtag_port_pulse_clock_read_tdo(jtag_port_t* port) {
|
|
uint8_t val;
|
|
digitalWrite(port->tck, 0);
|
|
delayMicroseconds(1);
|
|
val = digitalRead(port->tdo);
|
|
digitalWrite(port->tck, 1);
|
|
return val;
|
|
}
|
|
|
|
static inline void jtag_port_set_tms(jtag_port_t* port, uint8_t val) {
|
|
digitalWrite(port->tms, val);
|
|
}
|
|
static inline void jtag_port_set_tdi(jtag_port_t* port, uint8_t val) {
|
|
digitalWrite(port->tdi, val);
|
|
}
|
|
|
|
static inline uint8_t jtag_port_get_veref(jtag_port_t* port) {
|
|
return digitalRead(port->vref);
|
|
}
|
|
|
|
|
|
static uint8_t xsvf_player_next_byte(void) {
|
|
uint8_t retry = 16;
|
|
uint8_t pos = xsvf->rdpos % XSVF_BUF_SIZE;
|
|
|
|
if (xsvf->wrpos == xsvf->rdpos) {
|
|
size_t r = 0;
|
|
while (r == 0) {
|
|
#if XSVF_DEBUG
|
|
Serial.println("D<<< req read"); // request to receive BUF size bytes
|
|
#endif
|
|
Serial.println(F("$062")); // request to receive BUF size bytes
|
|
r = Serial.readBytes(xsvf_buf + pos, XSVF_BUF_SIZE - pos);
|
|
#if XSVF_DEBUG
|
|
Serial.print("D<<< read "); // request to receive BUF size bytes
|
|
Serial.println(r, DEC); // request to receive BUF size bytes
|
|
#endif
|
|
if (r == 0) {
|
|
retry --;
|
|
if (retry == 0) {
|
|
xsvf->error = 1;
|
|
return 0;
|
|
}
|
|
delay(1);
|
|
} else {
|
|
xsvf->wrpos += r;
|
|
}
|
|
}
|
|
}
|
|
|
|
xsvf->rdpos++;
|
|
#if XSVF_DEBUG
|
|
Serial.print(F("D BYTE "));
|
|
Serial.print(xsvf_buf[pos], DEC);
|
|
Serial.print(F(" 0x"));
|
|
Serial.println(xsvf_buf[pos], HEX);
|
|
#endif
|
|
#if XSVF_CALC_CSUM
|
|
xsvf->csum += xsvf_buf[pos];
|
|
#endif
|
|
|
|
return xsvf_buf[pos];
|
|
}
|
|
|
|
static uint8_t xsvf_player_get_next_byte(void) {
|
|
return xsvf_player_next_byte();
|
|
}
|
|
/*
|
|
static uint16_t xsvf_player_get_next_word(void) {
|
|
uint16_t i = xsvf_player_next_byte();
|
|
i <<= 8;
|
|
i |= xsvf_player_next_byte();
|
|
return i;
|
|
}
|
|
*/
|
|
|
|
static uint32_t xsvf_player_get_next_long(void) {
|
|
uint32_t i = xsvf_player_next_byte();
|
|
i <<= 8;
|
|
i |= xsvf_player_next_byte();
|
|
i <<= 8;
|
|
i |= xsvf_player_next_byte();
|
|
i <<= 8;
|
|
i |= xsvf_player_next_byte();
|
|
return i;
|
|
}
|
|
|
|
static void xsvf_player_get_next_bytes(uint8_t* data, uint32_t count) {
|
|
while(count--) {
|
|
*data++ = xsvf_player_next_byte();
|
|
}
|
|
}
|
|
|
|
#ifdef XSVF_HEAP
|
|
static uint32_t xsvf_heap_pos(uint32_t* pos, uint16_t size) {
|
|
uint32_t heap_pos = *pos;
|
|
//allocate on 4 byte boundaries
|
|
heap_pos = (heap_pos + 3) & 0xFFFFFFFC;
|
|
*pos = heap_pos + size;
|
|
return heap_pos;
|
|
}
|
|
#endif
|
|
|
|
static void xsvf_clear() {
|
|
uint16_t i;
|
|
uint8_t* d = (uint8_t*) xsvf;
|
|
//clear the xsvf data in RAM
|
|
i = sizeof(xsvf_t);
|
|
while(i) {
|
|
i--;
|
|
d[i] = 0;
|
|
}
|
|
}
|
|
|
|
static void xsvf_player_init(jtag_port_t* port) {
|
|
jtag_port_init(port);
|
|
|
|
#ifdef XSVF_HEAP
|
|
{
|
|
// variables allocated on the heap
|
|
uint32_t heap_pos = (uint32_t) XSVF_HEAP;
|
|
|
|
xsvf = (xsvf_t*) xsvf_heap_pos(&heap_pos, sizeof(xsvf_t));
|
|
xsvf_buf = (uint8_t*) xsvf_heap_pos(&heap_pos, XSVF_BUF_SIZE);
|
|
|
|
xsvf_clear();
|
|
|
|
xsvf->xsvf_tdo_mask = (uint8_t*) xsvf_heap_pos(&heap_pos, S_MAX_CHAIN_SIZE_BYTES);
|
|
xsvf->xsvf_tdi = (uint8_t*) xsvf_heap_pos(&heap_pos, S_MAX_CHAIN_SIZE_BYTES);
|
|
xsvf->xsvf_tdo = (uint8_t*) xsvf_heap_pos(&heap_pos, S_MAX_CHAIN_SIZE_BYTES);
|
|
xsvf->xsvf_tdo_expected = (uint8_t*) xsvf_heap_pos(&heap_pos, S_MAX_CHAIN_SIZE_BYTES);
|
|
xsvf->xsvf_address_mask = (uint8_t*) xsvf_heap_pos(&heap_pos, S_MAX_CHAIN_SIZE_BYTES);
|
|
xsvf->xsvf_data_mask = (uint8_t*) xsvf_heap_pos(&heap_pos, S_MAX_CHAIN_SIZE_BYTES);
|
|
xsvf_tms_transitions = (uint8_t*) xsvf_heap_pos(&heap_pos, 16);
|
|
xsvf_tms_map = (uint16_t*) xsvf_heap_pos(&heap_pos, 32);
|
|
|
|
if (heap_pos - ((uint32_t)XSVF_HEAP) > sizeof(XSVF_HEAP)) {
|
|
Serial.print(F("Q-1,ERROR: Heap is small:"));
|
|
Serial.println(heap_pos - ((uint32_t)XSVF_HEAP), DEC);
|
|
return;
|
|
}
|
|
|
|
//set up TM transitions
|
|
xsvf_tms_transitions[0] = TMS_T00;
|
|
xsvf_tms_transitions[1] = TMS_T01;
|
|
xsvf_tms_transitions[2] = TMS_T02;
|
|
xsvf_tms_transitions[3] = TMS_T03;
|
|
xsvf_tms_transitions[4] = TMS_T04;
|
|
xsvf_tms_transitions[5] = TMS_T05;
|
|
xsvf_tms_transitions[6] = TMS_T06;
|
|
xsvf_tms_transitions[7] = TMS_T07;
|
|
xsvf_tms_transitions[8] = TMS_T08;
|
|
xsvf_tms_transitions[9] = TMS_T09;
|
|
xsvf_tms_transitions[10] = TMS_T10;
|
|
xsvf_tms_transitions[11] = TMS_T11;
|
|
xsvf_tms_transitions[12] = TMS_T12;
|
|
xsvf_tms_transitions[13] = TMS_T13;
|
|
xsvf_tms_transitions[14] = TMS_T14;
|
|
xsvf_tms_transitions[15] = TMS_T15;
|
|
|
|
//set up bitstream map
|
|
xsvf_tms_map[0] = BS00;
|
|
xsvf_tms_map[1] = BS01;
|
|
xsvf_tms_map[2] = BS02;
|
|
xsvf_tms_map[3] = BS03;
|
|
xsvf_tms_map[4] = BS04;
|
|
xsvf_tms_map[5] = BS05;
|
|
xsvf_tms_map[6] = BS06;
|
|
xsvf_tms_map[7] = BS07;
|
|
xsvf_tms_map[8] = BS08;
|
|
xsvf_tms_map[9] = BS09;
|
|
xsvf_tms_map[10] = BS10;
|
|
xsvf_tms_map[11] = BS11;
|
|
xsvf_tms_map[12] = BS12;
|
|
xsvf_tms_map[13] = BS13;
|
|
xsvf_tms_map[14] = BS14;
|
|
xsvf_tms_map[15] = BS15;
|
|
|
|
}
|
|
#else
|
|
{
|
|
xsvf_clear();
|
|
|
|
xsvf->xsvf_tdo_mask = xsvf_tdo_mask;
|
|
xsvf->xsvf_tdi = xsvf_tdi;
|
|
xsvf->xsvf_tdo = xsvf_tdo;
|
|
xsvf->xsvf_tdo_expected = xsvf_tdo_expected;
|
|
xsvf->xsvf_address_mask = xsvf_address_mask;
|
|
xsvf->xsvf_data_mask = xsvf_data_mask;
|
|
}
|
|
#endif
|
|
|
|
xsvf->repeat = 32;
|
|
xsvf->endir_state = XSTATE_RUN_TEST_IDLE;
|
|
xsvf->enddr_state = STATE_RUN_TEST_IDLE;
|
|
}
|
|
|
|
|
|
static void xsvf_jtagtap_state_ack(uint8_t tms) {
|
|
tms <<= 2; // either 0 or 4
|
|
xsvf->jtag_current_state = (xsvf_tms_transitions[xsvf->jtag_current_state] >> tms) & 0xf;
|
|
}
|
|
|
|
static void xsvf_jtagtap_shift_td(
|
|
jtag_port_t* port,
|
|
uint8_t *input_data,
|
|
uint8_t *output_data,
|
|
uint32_t data_bits,
|
|
uint8_t must_end)
|
|
{
|
|
uint32_t i, j;
|
|
uint32_t bit_count = data_bits;
|
|
uint32_t byte_count = (data_bits+ 7) >> 3;
|
|
|
|
for (i = 0; i < byte_count; ++i) {
|
|
uint8_t byte_out = input_data[byte_count - 1 - i];
|
|
uint8_t tdo_byte = 0;
|
|
for (j = 0; j < 8 && bit_count-- > 0; ++j) {
|
|
uint8_t tdo;
|
|
if (bit_count == 0 && must_end) {
|
|
jtag_port_set_tms(port, 1);
|
|
xsvf_jtagtap_state_ack(1);
|
|
}
|
|
jtag_port_set_tdi(port, byte_out & 1);
|
|
byte_out >>= 1;
|
|
tdo = jtag_port_pulse_clock_read_tdo(port);
|
|
tdo_byte |= tdo << j;
|
|
}
|
|
output_data[byte_count - 1 - i] = tdo_byte;
|
|
}
|
|
}
|
|
|
|
static void xsvf_jtagtap_state_step(jtag_port_t* port, uint8_t tms) {
|
|
jtag_port_set_tms(port, tms);
|
|
jtag_port_pulse_clock(port);
|
|
xsvf_jtagtap_state_ack(tms);
|
|
}
|
|
|
|
static void xsvf_jtagtap_state_goto(jtag_port_t* port, uint8_t state) {
|
|
if (xsvf->error) {
|
|
return;
|
|
}
|
|
if (state == XSTATE_TEST_LOGIC_RESET) {
|
|
uint8_t i;
|
|
for (i = 0; i < 5; ++i) {
|
|
xsvf_jtagtap_state_step(port, 1);
|
|
}
|
|
} else {
|
|
while (xsvf->jtag_current_state != state) {
|
|
xsvf_jtagtap_state_step(port, (xsvf_tms_map[xsvf->jtag_current_state] >> state) & 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void xsvf_jtagtap_wait_time(jtag_port_t* port, uint32_t microseconds, uint8_t wait_clock) {
|
|
uint32_t until;
|
|
|
|
if (xsvf->error) {
|
|
return;
|
|
}
|
|
|
|
until = micros() + microseconds;
|
|
if (wait_clock) {
|
|
while (microseconds--) {
|
|
jtag_port_pulse_clock(port);
|
|
}
|
|
}
|
|
while (micros() < until) {
|
|
jtag_port_pulse_clock(port);
|
|
}
|
|
}
|
|
|
|
static void xsvf_jtag_sir(jtag_port_t* port) {
|
|
if (xsvf->error) {
|
|
return;
|
|
}
|
|
xsvf_jtagtap_state_goto(port, XSTATE_SHIFT_IR);
|
|
xsvf_jtagtap_shift_td(port, xsvf->xsvf_tdi, xsvf->xsvf_tdo, xsvf->sirsize_bits, 1);
|
|
if (xsvf->runtest) {
|
|
xsvf_jtagtap_state_goto(port, xsvf->endir_state);
|
|
} else {
|
|
xsvf_jtagtap_state_goto(port, XSTATE_RUN_TEST_IDLE);
|
|
xsvf_jtagtap_wait_time(port, xsvf->runtest, 1);
|
|
}
|
|
}
|
|
|
|
|
|
static uint8_t xsvf_jtag_is_tdo_as_expected(uint8_t use_mask)
|
|
{
|
|
uint32_t i;
|
|
for (i = 0; i < xsvf->sdrsize_bytes; ++i) {
|
|
uint8_t expected = xsvf->xsvf_tdo_expected[i];
|
|
uint8_t actual = xsvf->xsvf_tdo[i];
|
|
if (use_mask) {
|
|
uint8_t mask = xsvf->xsvf_tdo_mask[i];
|
|
expected &= mask;
|
|
actual &= mask;
|
|
}
|
|
#if XSVF_IGNORE_NOMATCH != 1
|
|
if (expected != actual) {
|
|
#if XSVF_DEBUG
|
|
Serial.println(F("D...NO MATCH!"));
|
|
#endif
|
|
return 0;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#if XSVF_DEBUG
|
|
Serial.println(F("D...match!"));
|
|
#endif
|
|
return 1;
|
|
}
|
|
|
|
|
|
#define SDR_MUST_BEGIN (flags & 0b1000)
|
|
#define SDR_MUST_CHECK (flags & 0b0100)
|
|
#define SDR_USE_MASK (flags & 0b0010)
|
|
#define SDR_MUST_END (flags & 0b0001)
|
|
|
|
static uint8_t xsvf_jtag_sdr(jtag_port_t* port, uint8_t flags)
|
|
{
|
|
int16_t attempts_left = xsvf->repeat;
|
|
uint8_t matched = 0;
|
|
uint8_t must_end = SDR_MUST_END;
|
|
uint8_t must_check = SDR_MUST_CHECK;
|
|
uint8_t use_mask = SDR_USE_MASK;
|
|
|
|
if (xsvf->error) {
|
|
return 0;
|
|
}
|
|
|
|
if (SDR_MUST_BEGIN) {
|
|
xsvf_jtagtap_state_goto(port, XSTATE_SHIFT_DR);
|
|
}
|
|
while (!matched && attempts_left-- >= 0) {
|
|
xsvf_jtagtap_shift_td(port, xsvf->xsvf_tdi, xsvf->xsvf_tdo, xsvf->sdrsize_bits, must_end);
|
|
if (!must_check) {
|
|
break;
|
|
}
|
|
matched = xsvf_jtag_is_tdo_as_expected(use_mask);
|
|
if (!matched) {
|
|
// XAP058, page 14
|
|
xsvf_jtagtap_state_goto(port, XSTATE_PAUSE_DR);
|
|
xsvf_jtagtap_state_goto(port, XSTATE_SHIFT_DR);
|
|
xsvf_jtagtap_state_goto(port, XSTATE_RUN_TEST_IDLE);
|
|
xsvf_jtagtap_wait_time(port, xsvf->runtest, 1);
|
|
//
|
|
xsvf_jtagtap_state_goto(port, XSTATE_SHIFT_DR);
|
|
#if XSVF_DEBUG
|
|
if (attempts_left >= 0) {
|
|
Serial.print(F("D...repeating: "));
|
|
Serial.println(xsvf->repeat - attempts_left, DEC);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
if (must_check && !matched) {
|
|
xsvf->error = ERR_DR_CHECK_FAILED;
|
|
Serial.println(F("D!DR check failed!"));
|
|
}
|
|
if (must_end && matched) {
|
|
if (!xsvf->runtest) {
|
|
xsvf_jtagtap_state_goto(port, xsvf->enddr_state);
|
|
} else {
|
|
xsvf_jtagtap_state_goto(port, XSTATE_RUN_TEST_IDLE);
|
|
xsvf_jtagtap_wait_time(port, xsvf->runtest, 1);
|
|
}
|
|
}
|
|
|
|
return !must_check || (must_check && matched);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Reads the next instruction from the serial port. Also reads any
|
|
* remaining instruction parameters into the instruction buffer.
|
|
*/
|
|
static uint8_t xsvf_player_handle_next_instruction(jtag_port_t* port) {
|
|
uint8_t instruction = xsvf_player_next_byte();
|
|
if (xsvf->error) {
|
|
return ERR_IO; // failure
|
|
}
|
|
xsvf->instruction_counter++;
|
|
|
|
#if XSVF_DEBUG
|
|
Serial.print(F("D INSTR "));
|
|
Serial.print(xsvf->instruction_counter, DEC);
|
|
Serial.print(F(" (0x"));
|
|
Serial.print(instruction, HEX);
|
|
Serial.print(F("): "));
|
|
#endif
|
|
|
|
//do not use switch as it uses RAM
|
|
// ---[COMPLETE ] --------------------------------------------
|
|
if (instruction == XCOMPLETE) {
|
|
#if XSVF_DEBUG
|
|
Serial.println(F("XCOMPLETE"));
|
|
#endif
|
|
xsvf->xcomplete = 1;
|
|
} else
|
|
|
|
// ---[TDO MASK] --------------------------------------------
|
|
if (instruction == XTDOMASK) {
|
|
#if XSVF_DEBUG
|
|
Serial.println(F("XTDOMASK"));
|
|
#endif
|
|
xsvf_player_get_next_bytes(xsvf->xsvf_tdo_mask, xsvf->sdrsize_bytes);
|
|
} else
|
|
|
|
// ---[SIR SIR2] --------------------------------------------
|
|
if (instruction == XSIR || instruction == XSIR2) {
|
|
#if XSVF_DEBUG
|
|
Serial.println(instruction == XSIR ? F("XSIR") : F("XSIR2"));
|
|
#endif
|
|
xsvf->sirsize_bits = xsvf_player_get_next_byte();
|
|
if (instruction == XSIR2) {
|
|
xsvf->sirsize_bits <= 8;
|
|
xsvf->sirsize_bits |= xsvf_player_get_next_byte();
|
|
}
|
|
xsvf->sirsize_bytes = (xsvf->sirsize_bits + 7) >> 3;
|
|
if (xsvf->sirsize_bytes > S_MAX_CHAIN_SIZE_BYTES) {
|
|
return ERR_XSIR_SIZE;
|
|
}
|
|
xsvf_player_get_next_bytes(xsvf->xsvf_tdi, xsvf->sirsize_bytes);
|
|
xsvf_jtag_sir(port);
|
|
} else
|
|
|
|
// ---[SDR ] --------------------------------------------
|
|
if (instruction == XSDR || (instruction >= XSDRB && instruction <= XSDRE)) {
|
|
uint8_t flags = 0b1111;
|
|
#if XSVF_DEBUG
|
|
Serial.println(F("XSDRx"));
|
|
#endif
|
|
xsvf_player_get_next_bytes(xsvf->xsvf_tdi, xsvf->sdrsize_bytes);
|
|
if (instruction != XSDR) {
|
|
flags = (instruction == XSDRB) ? 0b1000 : (instruction == XSDRC) ? 0b0000 : 0b0001;
|
|
}
|
|
if (!xsvf_jtag_sdr(port, flags)) {
|
|
xsvf->error = ERR_XSDR;
|
|
}
|
|
} else
|
|
|
|
// ---[RUN TEST ] --------------------------------------------
|
|
if (instruction == XRUNTEST) {
|
|
#if XSVF_DEBUG
|
|
Serial.println(F("XRUNTEST"));
|
|
#endif
|
|
xsvf->runtest = xsvf_player_get_next_long();
|
|
} else
|
|
// ---[REPEAT ] --------------------------------------------
|
|
if (instruction == XREPEAT) {
|
|
#if XSVF_DEBUG
|
|
Serial.println(F("XREPEAT"));
|
|
#endif
|
|
xsvf->repeat = xsvf_player_get_next_byte();
|
|
} else
|
|
|
|
// ---[SDRSIZE ] --------------------------------------------
|
|
if (instruction == XSDRSIZE) {
|
|
#if XSVF_DEBUG
|
|
Serial.println(F("XSDRSIZE"));
|
|
#endif
|
|
xsvf->sdrsize_bits = xsvf_player_get_next_long();
|
|
xsvf->sdrsize_bytes = (xsvf->sdrsize_bits + 7) >> 3;
|
|
if (xsvf->sdrsize_bytes > S_MAX_CHAIN_SIZE_BYTES) {
|
|
return ERR_XSDRSIZE;
|
|
}
|
|
} else
|
|
|
|
// ---[SDRTDO ] --------------------------------------------
|
|
if (instruction == XSDRTDO || (instruction >= XSDRTDOB && instruction <= XSDRTDOE)) {
|
|
uint8_t flags = 0b1111;
|
|
#if XSVF_DEBUG
|
|
Serial.println(F("XSDRTDOx"));
|
|
#endif
|
|
xsvf_player_get_next_bytes(xsvf->xsvf_tdi, xsvf->sdrsize_bytes);
|
|
xsvf_player_get_next_bytes(xsvf->xsvf_tdo_expected, xsvf->sdrsize_bytes);
|
|
if (instruction != XSDRTDO) {
|
|
flags = (instruction == XSDRTDOB) ? 0b1100 : (instruction == XSDRTDOC) ? 0b0100 : 0b0101;
|
|
}
|
|
if (!xsvf_jtag_sdr(port, flags)) {
|
|
xsvf->error = ERR_XSDR;
|
|
}
|
|
} else
|
|
|
|
// ---[SET SDR MASKS ] --------------------------------------------
|
|
if (instruction == XSETSDRMASKS) {
|
|
#if XSVF_DEBUG
|
|
Serial.println(F("XSETSDRMASKS"));
|
|
#endif
|
|
xsvf_player_get_next_bytes(xsvf->xsvf_address_mask, xsvf->sdrsize_bytes);
|
|
xsvf_player_get_next_bytes(xsvf->xsvf_data_mask, xsvf->sdrsize_bytes);
|
|
} else
|
|
|
|
// ---[SDR INC ] --------------------------------------------
|
|
if (instruction == XSDRINC) {
|
|
#if XSVF_DEBUG
|
|
Serial.println(F("XSDRINC"));
|
|
#endif
|
|
xsvf_player_get_next_bytes(xsvf->xsvf_tdi, xsvf->sdrsize_bytes);
|
|
// TODO - check: return false?
|
|
} else
|
|
|
|
// ---[STATE ] --------------------------------------------
|
|
if (instruction == XSTATE) {
|
|
#if XSVF_DEBUG
|
|
Serial.println(F("XSTATE"));
|
|
#endif
|
|
xsvf->next_state = xsvf_player_get_next_byte();
|
|
xsvf_jtagtap_state_goto(port, xsvf->next_state);
|
|
} else
|
|
|
|
// ---[END IR ] --------------------------------------------
|
|
if (instruction == XENDIR) {
|
|
uint8_t s;
|
|
#if XSVF_DEBUG
|
|
Serial.println(F("XENDIR"));
|
|
#endif
|
|
s = xsvf_player_get_next_byte();
|
|
if (s == 0) {
|
|
xsvf->endir_state = STATE_RUN_TEST_IDLE;
|
|
} else
|
|
if (s == 1) {
|
|
xsvf->endir_state = STATE_PAUSE_IR;
|
|
} else {
|
|
return ERR_XENDIR;
|
|
}
|
|
} else
|
|
|
|
// ---[END DR ] --------------------------------------------
|
|
if (instruction == XENDDR) {
|
|
uint8_t s;
|
|
#if XSVF_DEBUG
|
|
Serial.println(F("XENDDR"));
|
|
#endif
|
|
|
|
s = xsvf_player_get_next_byte();
|
|
if (s == 0) {
|
|
xsvf->enddr_state = STATE_RUN_TEST_IDLE;
|
|
} else
|
|
if (s == 1) {
|
|
xsvf->enddr_state = STATE_PAUSE_DR;
|
|
} else {
|
|
return ERR_XENDDR;
|
|
}
|
|
} else
|
|
|
|
// ---[COMMENT ] --------------------------------------------
|
|
if (instruction == XCOMMENT) {
|
|
uint8_t c;
|
|
#if XSVF_DEBUG
|
|
Serial.println(F("XCOMMENT"));
|
|
#endif
|
|
Serial.print(F("D"));//debug message preamble
|
|
//read the comment bytes
|
|
do {
|
|
c = xsvf_player_get_next_byte();
|
|
// special feature: dump the TDO data
|
|
if (c == '#') {
|
|
uint8_t cnt = 0;
|
|
uint8_t size = xsvf_player_get_next_byte() - '0';
|
|
//dump the tdo buffer bytes
|
|
while(cnt < size) {
|
|
char t[4];
|
|
uint8_t v = xsvf->xsvf_tdo[cnt];
|
|
uint8_t x1 = v >> 4;
|
|
v &= 0xF;
|
|
// DEC to HEX conversion with leading zero
|
|
t[0] = (char) (x1 < 10 ? '0' + x1 : 55 + x1 );
|
|
t[1] = (char) (v < 10 ? '0' + v : 55 + v );
|
|
t[2] = 0;
|
|
Serial.print(t);
|
|
cnt++;
|
|
}
|
|
} else if (c) {
|
|
Serial.print((char)c);
|
|
}
|
|
} while(c);
|
|
Serial.println();
|
|
} else
|
|
|
|
// ---[WAIT ] --------------------------------------------
|
|
if (instruction == XWAIT || instruction == XWAITSTATE) {
|
|
uint32_t clock_cnt = 0;
|
|
uint8_t wait_clock = 1;
|
|
#if XSVF_DEBUG
|
|
Serial.println(instruction == XWAIT ? F("XWAIT") : F("XWAITSTATE"));
|
|
#endif
|
|
//TOOD - do we need these states to be global?
|
|
xsvf->wait_start_state = xsvf_player_get_next_byte();
|
|
xsvf->wait_end_state = xsvf_player_get_next_byte();
|
|
if (instruction == XWAITSTATE) {
|
|
clock_cnt = xsvf_player_get_next_long();
|
|
wait_clock = clock_cnt > 0 ? 1 : 0;
|
|
}
|
|
#if XSVF_DEBUG
|
|
Serial.print(F("Dclock:"));
|
|
Serial.println(clock_cnt, DEC);
|
|
#endif
|
|
xsvf->wait_time_usecs = xsvf_player_get_next_long();
|
|
#if XSVF_DEBUG
|
|
Serial.print(F("Dmicros:"));
|
|
Serial.println( xsvf->wait_time_usecs, DEC);
|
|
#endif
|
|
|
|
xsvf_jtagtap_state_goto(port, xsvf->wait_start_state);
|
|
// happens only during XWAITSTATE
|
|
while (clock_cnt) {
|
|
jtag_port_pulse_clock(port);
|
|
clock_cnt--;
|
|
}
|
|
xsvf_jtagtap_wait_time(port, xsvf->wait_time_usecs, wait_clock);
|
|
xsvf_jtagtap_state_goto(port, xsvf->wait_end_state);
|
|
|
|
} else
|
|
// ---[TRST - test line reset] --------------------------------------------
|
|
if (instruction == XTRST) {
|
|
#if XSVF_DEBUG
|
|
Serial.println(F("XTRST"));
|
|
#endif
|
|
//read test reset mode (0-on, 1-off, 2-Z, 3-Absent)
|
|
xsvf_player_get_next_byte();
|
|
} else
|
|
// ---[UNKNOWN ] --------------------------------------------
|
|
{
|
|
#if XSVF_DEBUG
|
|
Serial.print(F("XUNKNOWN:"));
|
|
Serial.println(instruction, DEC);
|
|
#endif
|
|
//unimplemented instruction
|
|
return ERR_INSTR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
if (xsvf->error) {
|
|
return xsvf->error; // failure
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
static void jtag_play_xsvf(jtag_port_t* port)
|
|
{
|
|
uint32_t n = 0;
|
|
uint8_t ret;
|
|
|
|
xsvf_player_init(port);
|
|
|
|
//check xref is high
|
|
if (!jtag_port_get_veref(port)) {
|
|
Serial.println(F("Q-255,JTAG not connected"));
|
|
return;
|
|
}
|
|
|
|
Serial.println(F("RXSVF")); //announce ready to receive XSVF stream
|
|
|
|
while(1) {
|
|
n++;
|
|
ret = xsvf_player_handle_next_instruction(port);
|
|
if (ret) {
|
|
Serial.print(F("Q-"));
|
|
Serial.print(ret, DEC );
|
|
Serial.println(F(",Fail"));
|
|
break;
|
|
} else {
|
|
if (xsvf->xcomplete) {
|
|
Serial.println(F("!Success"));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
Serial.print(F("!Processed instr:"));
|
|
Serial.println(xsvf->instruction_counter, DEC);
|
|
|
|
#if XSVF_CALC_CSUM
|
|
Serial.print(F("!sum: 0x"));
|
|
// print leading zeros in the check sum hex value
|
|
{
|
|
uint32_t i = 0xF0000000;
|
|
while((!(xsvf->csum & i)) && i) {
|
|
Serial.print(F("0"));
|
|
i >>= 4;
|
|
}
|
|
}
|
|
Serial.print(xsvf->csum, HEX);
|
|
Serial.print(F("/"));
|
|
Serial.println(xsvf->rdpos, DEC);
|
|
#endif /* XSVF_CALC_CSUM */
|
|
|
|
if (xsvf->xcomplete) {
|
|
Serial.println(F("Q-0,OK"));
|
|
}
|
|
//the 3 pins must be low or else the vref might be triggered next time
|
|
digitalWrite(port->tms, 0);
|
|
digitalWrite(port->tdi, 0);
|
|
digitalWrite(port->tck, 0);
|
|
delay(100);
|
|
|
|
// put the jtag port pins into High-Z (vref already is input)
|
|
pinMode(port->tms, INPUT);
|
|
pinMode(port->tdi, INPUT);
|
|
pinMode(port->tck, INPUT);
|
|
pinMode(port->tdo, INPUT);
|
|
}
|
|
#endif /* USE_JTAG_PLAYER */
|
|
|
|
#endif /*_JTAG_XSVF_PLAYER_H_*/
|