#include "config.h"
#endif
-/* system includes */
-#include <errno.h>
-#include <string.h>
-#include <usb.h>
-#include <stdint.h>
-
/* project specific includes */
-#include "log.h"
-#include "types.h"
#include "jtag.h"
-#include "configuration.h"
#include "rlink.h"
#include "st7.h"
#include "ep1_cmd.h"
#include "dtc_cmd.h"
+/* system includes */
+#include <usb.h>
+
/* This feature is made useless by running the DTC all the time. When automatic, the LED is on whenever the DTC is running. Otherwise, USB messages are sent to turn it on and off. */
#undef AUTOMATIC_BUSY_LED
#define DTC_STATUS_POLL_BYTE (ST7_USB_BUF_EP0OUT + 0xff)
-/* Symbolic names for some pins */
-#define ST7_PA_NJTAG_TRST ST7_PA1
-#define ST7_PA_NRLINK_RST ST7_PA3
-#define ST7_PA_NLINE_DRIVER_ENABLE ST7_PA5
-
-/* mask for negative-logic pins */
-#define ST7_PA_NUNASSERTED (0 \
- | ST7_PA_NJTAG_TRST \
- | ST7_PA_NRLINK_RST \
- | ST7_PA_NLINE_DRIVER_ENABLE \
-)
-
#define ST7_PD_NBUSY_LED ST7_PD0
-#define ST7_PD_NERROR_LED ST7_PD1
-#define ST7_PD_NRUN_LED ST7_PD7
+#define ST7_PD_NRUN_LED ST7_PD1
+/* low enables VPP at adapter header, high connects it to GND instead */
+#define ST7_PD_VPP_SEL ST7_PD6
+/* low: VPP = 12v, high: VPP <= 5v */
+#define ST7_PD_VPP_SHDN ST7_PD7
+/* These pins are connected together */
#define ST7_PE_ADAPTER_SENSE_IN ST7_PE3
#define ST7_PE_ADAPTER_SENSE_OUT ST7_PE4
+/* Symbolic mapping between port pins and numbered IO lines */
+#define ST7_PA_IO1 ST7_PA1
+#define ST7_PA_IO2 ST7_PA2
+#define ST7_PA_IO4 ST7_PA4
+#define ST7_PA_IO8 ST7_PA6
+#define ST7_PA_IO10 ST7_PA7
+#define ST7_PB_IO5 ST7_PB5
+#define ST7_PC_IO9 ST7_PC1
+#define ST7_PC_IO3 ST7_PC2
+#define ST7_PC_IO7 ST7_PC3
+#define ST7_PE_IO6 ST7_PE5
+
+/* Symbolic mapping between numbered IO lines and adapter signals */
+#define ST7_PA_RTCK ST7_PA_IO0
+#define ST7_PA_NTRST ST7_PA_IO1
+#define ST7_PC_TDI ST7_PC_IO3
+#define ST7_PA_DBGRQ ST7_PA_IO4
+#define ST7_PB_NSRST ST7_PB_IO5
+#define ST7_PE_TMS ST7_PE_IO6
+#define ST7_PC_TCK ST7_PC_IO7
+#define ST7_PC_TDO ST7_PC_IO9
+#define ST7_PA_DBGACK ST7_PA_IO10
+
static usb_dev_handle *pHDev;
*usb_buffer_p++ = va_arg(ap, int);
length--;
}
-
+
memset(
usb_buffer_p,
0,
usb_buffer[2] = addr;
usb_buffer[3] = length;
- usb_ret = usb_bulk_write(
+ usb_ret = usb_bulk_write(
pHDev, USB_EP1OUT_ADDR,
usb_buffer, sizeof(usb_buffer),
USB_TIMEOUT_MS
if(usb_ret < sizeof(usb_buffer)) {
break;
}
-
+
usb_ret = usb_bulk_read(
pHDev, USB_EP1IN_ADDR,
buffer, length,
if(usb_ret < length) {
break;
}
-
+
addr += length;
buffer += length;
count += length;
sizeof(usb_buffer) - 4 - length
);
- usb_ret = usb_bulk_write(
+ usb_ret = usb_bulk_write(
pHDev, USB_EP1OUT_ADDR,
(char *)usb_buffer, sizeof(usb_buffer),
USB_TIMEOUT_MS
);
- if(usb_ret < sizeof(usb_buffer)) {
+ if((size_t)usb_ret < sizeof(usb_buffer)) {
break;
}
-
+
addr += length;
buffer += length;
count += length;
LOG_ERROR("Malformed DTC image\n");
exit(1);
}
-
+
header = (struct header_s *)buffer;
buffer += sizeof(*header);
length -= sizeof(*header);
- if(length < header->length + 1) {
+ if(length < (size_t)header->length + 1) {
LOG_ERROR("Malformed DTC image\n");
exit(1);
}
-
+
switch(header->type) {
case DTCLOAD_COMMENT:
break;
break;
case DTCLOAD_LOAD:
- /* Send the DTC program to ST7 RAM. */
+ /* Send the DTC program to ST7 RAM. */
usb_err = ep1_memory_write(
pHDev,
DTC_LOAD_BUFFER,
case DTCLOAD_LUT_START:
lut_start = buffer[0];
break;
-
+
case DTCLOAD_LUT:
- usb_err = ep1_memory_write(
+ usb_err = ep1_memory_write(
pHDev,
ST7_USB_BUF_EP0OUT + lut_start,
header->length + 1, buffer
exit(1);
break;
}
-
+
buffer += (header->length + 1);
length -= (header->length + 1);
}
*/
static
int
-dtc_start_download(
-) {
+dtc_start_download(void) {
int usb_err;
u8 ep2txr;
/* set up for download mode and make sure EP2 is set up to transmit */
usb_err = ep1_generic_commandl(
pHDev, 7,
-
+
EP1_CMD_DTC_STOP,
EP1_CMD_SET_UPLOAD,
EP1_CMD_SET_DOWNLOAD,
usb_err = ep1_generic_commandl(
pHDev, 13,
-
+
EP1_CMD_MEMORY_WRITE, /* preinitialize poll byte */
DTC_STATUS_POLL_BYTE >> 8,
DTC_STATUS_POLL_BYTE,
/* Wait for DTC to finish running command buffer */
- for(i = 5;;) {
+ for(i = 10;;) {
usb_err = ep1_generic_commandl(
pHDev, 4,
struct {
dtc_reply_queue_entry_t *rq_head;
dtc_reply_queue_entry_t *rq_tail;
- int cmd_index;
- int reply_index;
+ u32 cmd_index;
+ u32 reply_index;
u8 cmd_buffer[USB_EP2BANK_SIZE];
} dtc_queue;
static
struct {
- int length;
+ u32 length;
u32 buffer;
} tap_state_queue;
static
int
-dtc_queue_init(
-) {
+dtc_queue_init(void) {
dtc_queue.rq_head = NULL;
dtc_queue.rq_tail = NULL;
dtc_queue.cmd_index = 0;
static
int
-dtc_queue_run(
-) {
+dtc_queue_run(void) {
dtc_reply_queue_entry_t *rq_p, *rq_next;
int retval;
int usb_err;
usb_err = dtc_run_download(pHDev,
dtc_queue.cmd_buffer, dtc_queue.cmd_index,
NULL, 0
- );
+ );
if(usb_err < 0) {
LOG_ERROR("dtc_run_download: %s\n", usb_strerror());
exit(1);
usb_err = dtc_run_download(pHDev,
dtc_queue.cmd_buffer, dtc_queue.cmd_index,
reply_buffer, dtc_queue.reply_index
- );
+ );
if(usb_err < 0) {
LOG_ERROR("dtc_run_download: %s\n", usb_strerror());
exit(1);
} else {
*tdo_p &=~ tdo_mask;
}
-
+
dtc_mask >>= 1;
if(dtc_mask == 0) {
dtc_p++;
tdo_p++;
tdo_mask = 1;
}
-
+
}
}
static
int
-tap_state_queue_init(
-) {
+tap_state_queue_init(void) {
tap_state_queue.length = 0;
tap_state_queue.buffer = 0;
return(0);
static
int
-tap_state_queue_run(
-) {
+tap_state_queue_run(void) {
int i;
int bits;
u8 byte;
bits = 1;
byte = 0;
for(i = tap_state_queue.length; i--;) {
-
+
byte <<= 1;
if(tap_state_queue.buffer & 1) {
byte |= 1;
static
-void rlink_end_state(enum tap_state state)
+void rlink_end_state(tap_state_t state)
{
- if (tap_move_map[state] != -1)
- end_state = state;
+ if (tap_is_state_stable(state))
+ tap_set_end_state(state);
else
{
LOG_ERROR("BUG: %i is not a valid end state", state);
void rlink_state_move(void) {
int i=0, tms=0;
- u8 tms_scan = TAP_MOVE(cur_state, end_state);
+ u8 tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state());
+ int tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
- for (i = 0; i < 7; i++)
+ for (i = 0; i < tms_count; i++)
{
tms = (tms_scan >> i) & 1;
tap_state_queue_append(tms);
}
- cur_state = end_state;
+ tap_set_state(tap_get_end_state());
}
static
state_count = 0;
while (num_states)
{
- if (tap_transitions[cur_state].low == cmd->path[state_count])
+ if (tap_state_transition(tap_get_state(), false) == cmd->path[state_count])
{
tms = 0;
}
- else if (tap_transitions[cur_state].high == cmd->path[state_count])
+ else if (tap_state_transition(tap_get_state(), true) == cmd->path[state_count])
{
tms = 1;
}
else
{
- LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", jtag_state_name(cur_state), jtag_state_name(cmd->path[state_count]));
+ LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(tap_get_state()), tap_state_name(cmd->path[state_count]));
exit(-1);
}
tap_state_queue_append(tms);
- cur_state = cmd->path[state_count];
+ tap_set_state(cmd->path[state_count]);
state_count++;
num_states--;
}
- end_state = cur_state;
+ tap_set_end_state(tap_get_state());
}
{
int i;
- enum tap_state saved_end_state = end_state;
+ tap_state_t saved_end_state = tap_get_end_state();
/* only do a state_move when we're not already in RTI */
- if (cur_state != TAP_IDLE)
+ if (tap_get_state() != TAP_IDLE)
{
rlink_end_state(TAP_IDLE);
rlink_state_move();
/* finish in end_state */
rlink_end_state(saved_end_state);
- if (cur_state != end_state)
+ if (tap_get_state() != tap_get_end_state())
rlink_state_move();
}
u8 bitmap;
int usb_err;
- bitmap = ((~(ST7_PA_NLINE_DRIVER_ENABLE)) & ST7_PA_NUNASSERTED);
+ /* Read port A for bit op */
+ usb_err = ep1_generic_commandl(
+ pHDev, 4,
+ EP1_CMD_MEMORY_READ,
+ ST7_PADR >> 8,
+ ST7_PADR,
+ 1
+ );
+ if(usb_err < 0) {
+ LOG_ERROR("%s", usb_strerror());
+ exit(1);
+ }
+
+ usb_err = usb_bulk_read(
+ pHDev, USB_EP1IN_ADDR,
+ (char *)&bitmap, 1,
+ USB_TIMEOUT_MS
+ );
+ if(usb_err < 1) {
+ LOG_ERROR("%s", usb_strerror());
+ exit(1);
+ }
if(trst) {
- bitmap &= ~ST7_PA_NJTAG_TRST;
+ bitmap &= ~ST7_PA_NTRST;
+ } else {
+ bitmap |= ST7_PA_NTRST;
+ }
+
+ /* Write port A and read port B for bit op */
+ /* port B has no OR, and we want to emulate open drain on NSRST, so we initialize DR to 0 and assert NSRST by setting DDR to 1. */
+ usb_err = ep1_generic_commandl(
+ pHDev, 9,
+ EP1_CMD_MEMORY_WRITE,
+ ST7_PADR >> 8,
+ ST7_PADR,
+ 1,
+ bitmap,
+ EP1_CMD_MEMORY_READ,
+ ST7_PBDDR >> 8,
+ ST7_PBDDR,
+ 1
+ );
+ if(usb_err < 0) {
+ LOG_ERROR("%s", usb_strerror());
+ exit(1);
}
+
+ usb_err = usb_bulk_read(
+ pHDev, USB_EP1IN_ADDR,
+ (char *)&bitmap, 1,
+ USB_TIMEOUT_MS
+ );
+ if(usb_err < 1) {
+ LOG_ERROR("%s", usb_strerror());
+ exit(1);
+ }
+
if(srst) {
- bitmap &= ~ST7_PA_NRLINK_RST;
+ bitmap |= ST7_PB_NSRST;
+ } else {
+ bitmap &= ~ST7_PB_NSRST;
}
+ /* write port B and read dummy to ensure completion before returning */
usb_err = ep1_generic_commandl(
pHDev, 6,
-
EP1_CMD_MEMORY_WRITE,
- ST7_PADR >> 8,
- ST7_PADR,
+ ST7_PBDDR >> 8,
+ ST7_PBDDR,
1,
bitmap,
EP1_CMD_DTC_GET_CACHED_STATUS
);
if(usb_err < 0) {
- LOG_ERROR("%s: %s\n", __func__, usb_strerror());
+ LOG_ERROR("%s", usb_strerror());
exit(1);
}
usb_err = usb_bulk_read(
pHDev, USB_EP1IN_ADDR,
- &bitmap, 1,
+ (char *)&bitmap, 1,
USB_TIMEOUT_MS
);
if(usb_err < 1) {
- LOG_ERROR("%s: %s\n", __func__, usb_strerror());
+ LOG_ERROR("%s", usb_strerror());
exit(1);
}
}
u8 *buffer,
int scan_size
) {
- int ir_scan;
- enum tap_state saved_end_state;
+ bool ir_scan;
+ tap_state_t saved_end_state;
int byte_bits;
int extra_bits;
int chunk_bits;
/* Move to the proper state before starting to shift TDI/TDO. */
if (!(
- (!ir_scan && (cur_state == TAP_DRSHIFT))
+ (!ir_scan && (tap_get_state() == TAP_DRSHIFT))
||
- (ir_scan && (cur_state == TAP_IRSHIFT))
+ (ir_scan && (tap_get_state() == TAP_IRSHIFT))
)) {
- saved_end_state = end_state;
+ saved_end_state = tap_get_end_state();
rlink_end_state(ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT);
rlink_state_move();
rlink_end_state(saved_end_state);
x = 0;
dtc_mask = 1 << (extra_bits - 1);
-
+
while(extra_bits--) {
if(*tdi_p & tdi_mask) {
x |= dtc_mask;
LOG_ERROR("enqueuing DTC reply entry: %s\n", strerror(errno));
exit(1);
}
-
+
tdi_bit_offset += chunk_bits;
}
if(type != SCAN_IN) {
x = 0;
dtc_mask = 1 << (8 - 1);
-
+
while(chunk_bits--) {
if(*tdi_p & tdi_mask) {
x |= dtc_mask;
}
-
+
dtc_mask >>= 1;
if(dtc_mask == 0) {
dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = x;
x = 0;
dtc_mask = 1 << (8 - 1);
}
-
+
tdi_mask <<= 1;
if(tdi_mask == 0) {
tdi_p++;
LOG_ERROR("enqueuing DTC reply entry: %s\n", strerror(errno));
exit(1);
}
-
+
tdi_bit_offset += extra_bits;
if(type == SCAN_IN) {
x = 0;
dtc_mask = 1 << (8 - 1);
-
+
while(extra_bits--) {
if(*tdi_p & tdi_mask) {
x |= dtc_mask;
}
-
+
dtc_mask >>= 1;
-
+
tdi_mask <<= 1;
if(tdi_mask == 0) {
tdi_p++;
LOG_ERROR("enqueuing DTC reply entry: %s\n", strerror(errno));
exit(1);
}
-
- dtc_queue.cmd_buffer[dtc_queue.cmd_index++] =
+
+ dtc_queue.cmd_buffer[dtc_queue.cmd_index++] =
DTC_CMD_SHIFT_TMS_TDI_BIT_PAIR(1, (*tdi_p & tdi_mask), 1);
dtc_queue.reply_index++;
/* Move to pause state */
tap_state_queue_append(0);
- cur_state = ir_scan ? TAP_IRPAUSE : TAP_DRPAUSE;
- if (cur_state != end_state) rlink_state_move();
+ tap_set_state(ir_scan ? TAP_IRPAUSE : TAP_DRPAUSE);
+ if (tap_get_state() != tap_get_end_state()) rlink_state_move();
return(0);
}
#endif
if ((cmd->cmd.reset->trst == 1) || (cmd->cmd.reset->srst && (jtag_reset_config & RESET_SRST_PULLS_TRST)))
{
- cur_state = TAP_RESET;
+ tap_set_state(TAP_RESET);
}
rlink_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
break;
LOG_ERROR("An error occurred while trying to load DTC code for speed \"%d\".\n", speed);
exit(1);
}
-
+
if(dtc_start_download() < 0) {
LOG_ERROR("%s, %d: starting DTC: %s",
__FILE__, __LINE__,
/* usb_set_configuration required under win32 */
usb_set_configuration(pHDev, dev->config[0].bConfigurationValue);
-
+
retries = 3;
do
{
ST7_PEDR >> 8,
ST7_PEDR,
3,
- 0x00,
- ST7_PE_ADAPTER_SENSE_OUT,
- ST7_PE_ADAPTER_SENSE_OUT,
+ 0x00, /* DR */
+ ST7_PE_ADAPTER_SENSE_OUT, /* DDR */
+ ST7_PE_ADAPTER_SENSE_OUT, /* OR */
EP1_CMD_MEMORY_READ, /* Read back */
ST7_PEDR >> 8,
ST7_PEDR,
ST7_PEDR >> 8,
ST7_PEDR,
3,
- 0x00,
- 0x00,
- 0x00
+ 0x00, /* DR */
+ 0x00, /* DDR */
+ 0x00 /* OR */
);
usb_bulk_read(
LOG_WARNING("target not plugged in\n");
}
- /* float port A, make sure DTC is stopped, set upper 2 bits of port D, and set up port A */
+ /* float ports A and B */
ep1_generic_commandl(
- pHDev, 15,
+ pHDev, 11,
EP1_CMD_MEMORY_WRITE,
ST7_PADDR >> 8,
ST7_PADDR,
2,
0x00,
0x00,
+ EP1_CMD_MEMORY_WRITE,
+ ST7_PBDDR >> 8,
+ ST7_PBDDR,
+ 1,
+ 0x00
+ );
+
+ /* make sure DTC is stopped, set VPP control, set up ports A and B */
+ ep1_generic_commandl(
+ pHDev, 14,
EP1_CMD_DTC_STOP,
- EP1_CMD_SET_PORTD_UPPER,
- ~(ST7_PD_NRUN_LED),
+ EP1_CMD_SET_PORTD_VPP,
+ ~(ST7_PD_VPP_SHDN),
EP1_CMD_MEMORY_WRITE,
ST7_PADR >> 8,
ST7_PADR,
2,
- ((~(ST7_PA_NLINE_DRIVER_ENABLE)) & ST7_PA_NUNASSERTED),
- (ST7_PA_NLINE_DRIVER_ENABLE | ST7_PA_NRLINK_RST | ST7_PA_NJTAG_TRST)
+ ((~(0)) & (ST7_PA_NTRST)),
+ (ST7_PA_NTRST),
+ /* port B has no OR, and we want to emulate open drain on NSRST, so we set DR to 0 here and later assert NSRST by setting DDR bit to 1. */
+ EP1_CMD_MEMORY_WRITE,
+ ST7_PBDR >> 8,
+ ST7_PBDR,
+ 1,
+ 0x00
);
/* set LED updating mode and make sure they're unlit */
EP1_CMD_LEDUE_NONE,
EP1_CMD_SET_PORTD_LEDS,
~0,
- EP1_CMD_SET_PORTD_UPPER,
+ EP1_CMD_SET_PORTD_VPP,
~0
);