Skip to content

Commit

Permalink
Allow queuing of CMD_XFER (dirtyjtag#102)
Browse files Browse the repository at this point in the history
Change required for OpenOCD integration
  • Loading branch information
phdussud authored and jeanthom committed Dec 13, 2022
1 parent 1fb19e3 commit 5fd9822
Showing 1 changed file with 52 additions and 47 deletions.
99 changes: 52 additions & 47 deletions src/cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ enum SignalIdentifier {
*
* @param usbd_dev USB device
*/
static void cmd_info(usbd_device *usbd_dev);
static uint32_t cmd_info(uint8_t *buffer);

/**
* @brief Handle CMD_FREQ command
Expand All @@ -86,7 +86,7 @@ static void cmd_freq(const uint8_t *commands);
* @param usbd_dev USB device
* @param commands Command data
*/
static void cmd_xfer(usbd_device *usbd_dev, const uint8_t *commands, bool extend_length, bool no_read);
static uint32_t cmd_xfer(const uint8_t *commands, bool extend_length, bool no_read, uint8_t *output_buffer);

/**
* @brief Handle CMD_SETSIG command
Expand All @@ -104,7 +104,7 @@ static void cmd_setsig(const uint8_t *commands);
*
* @param usbd_dev USB device
*/
static void cmd_getsig(usbd_device *usbd_dev);
static uint32_t cmd_getsig(uint8_t *output_buffer);

/**
* @brief Handle CMD_CLK command
Expand All @@ -115,15 +115,21 @@ static void cmd_getsig(usbd_device *usbd_dev);
* @param commands Command data
* @param readout Enable TDO readout
*/
static void cmd_clk(usbd_device *usbd_dev, const uint8_t *commands, bool readout);
static uint32_t cmd_clk(const uint8_t *commands, bool readout, uint8_t *output_buffer);

static uint8_t tx_buffer[64];

uint8_t cmd_handle(usbd_device *usbd_dev, const usbd_transfer *transfer) {
uint8_t *commands= (uint8_t*)transfer->buffer;
uint8_t *rxbuf = (uint8_t *)transfer->buffer;
uint32_t count = transfer->transferred;
uint8_t *commands = rxbuf;
uint8_t *output_buffer = tx_buffer;

while (*commands != CMD_STOP) {
while ((commands < (rxbuf + count)) && (*commands != CMD_STOP))
{
switch ((*commands)&0x0F) {
case CMD_INFO:
cmd_info(usbd_dev);
output_buffer += cmd_info(output_buffer);
break;

case CMD_FREQ:
Expand All @@ -132,8 +138,10 @@ uint8_t cmd_handle(usbd_device *usbd_dev, const usbd_transfer *transfer) {
break;

case CMD_XFER:
cmd_xfer(usbd_dev, commands, *commands & EXTEND_LENGTH, *commands & NO_READ);
return !!(*commands & NO_READ);
bool no_read = *commands & NO_READ;
uint32_t trbytes = cmd_xfer(commands, *commands & EXTEND_LENGTH, no_read, output_buffer);
commands += 1 + trbytes;
output_buffer += (no_read ? 0 : trbytes);
break;

case CMD_SETSIG:
Expand All @@ -142,64 +150,59 @@ uint8_t cmd_handle(usbd_device *usbd_dev, const usbd_transfer *transfer) {
break;

case CMD_GETSIG:
cmd_getsig(usbd_dev);
return 0;
output_buffer += cmd_getsig(output_buffer);
break;

case CMD_CLK:
cmd_clk(usbd_dev, commands, !!(*commands & READOUT));
if (*commands & READOUT) {
return 0;
} else {
commands += 2;
}
output_buffer += cmd_clk(commands, !!(*commands & READOUT), output_buffer);
commands += 2;
break;

default:
return 1; /* Unsupported command, halt */
break;
}

commands++;
}

/* Send the transfer response back to host */
if (tx_buffer != output_buffer)
usb_send(usbd_dev, tx_buffer, output_buffer - tx_buffer);
return 1;
}

static void cmd_info(usbd_device *usbd_dev) {
char info_string[64] = "DJTAG2\n";

usb_send(usbd_dev, (uint8_t*)info_string, 64);
static uint32_t cmd_info(uint8_t *buffer) {
char info_string[10] = "DJTAG2\n";
memcpy(buffer, info_string, 10);
return 10;
}

static void cmd_freq(const uint8_t *commands) {
jtag_set_frequency((commands[1] << 8) | commands[2]);
}

static void cmd_xfer(usbd_device *usbd_dev, const uint8_t *commands, bool extend_length, bool no_read) {
uint16_t transferred_bits;
uint8_t output_buffer[64];

/* Fill the output buffer with zeroes */
if (!no_read) {
memset(output_buffer, 0, sizeof(output_buffer));
}
static uint32_t cmd_xfer(const uint8_t *commands, bool extend_length, bool no_read, uint8_t *output_buffer) {
uint16_t transferred_bits = commands[1];


/* This is the number of transfered bits in one transfer command */
transferred_bits = commands[1];
if (extend_length) {
if (extend_length)
transferred_bits += 256;
// Ensure we don't do over-read
if (transferred_bits > 62*8) {
return;
}
// Ensure we don't do over-read
if (transferred_bits > 62 * 8)
{
transferred_bits = 62 * 8;
}
jtag_transfer(transferred_bits, commands+2, output_buffer);

/* Send the transfer response back to host */
if (!no_read) {
usb_send(usbd_dev, output_buffer, (transferred_bits + 7)/8);
/* Fill the output buffer with zeroes */
if (!no_read)
{
memset(output_buffer, 0, (transferred_bits + 7) / 8);
}

jtag_transfer(transferred_bits, commands+2, output_buffer);
return (transferred_bits + 7) / 8;
}

static void cmd_setsig(const uint8_t *commands) {
Expand Down Expand Up @@ -229,25 +232,27 @@ static void cmd_setsig(const uint8_t *commands) {
}
}

static void cmd_getsig(usbd_device *usbd_dev) {
static uint32_t cmd_getsig(uint8_t *output_buffer) {
uint8_t signal_status = 0;

if (jtag_get_tdo()) {
signal_status |= SIG_TDO;
}

usb_send(usbd_dev, &signal_status, 1);
output_buffer[0] = signal_status;
return 1;
}

static void cmd_clk(usbd_device *usbd_dev, const uint8_t *commands, bool readout) {
static uint32_t cmd_clk(const uint8_t *commands, bool readout, uint8_t *output_buffer) {
uint8_t signals, clk_pulses;

signals = commands[1];
clk_pulses = commands[2];

uint8_t readout_val = jtag_strobe(clk_pulses, signals & SIG_TMS, signals & SIG_TDI);
bool readout_val = jtag_strobe(clk_pulses, signals & SIG_TMS, signals & SIG_TDI);

if (readout) {
usb_send(usbd_dev, &readout_val, 1);
if (readout)
{
output_buffer[0] = readout_val ? 0xFF : 0;
}
return readout ? 1 : 0;
}

0 comments on commit 5fd9822

Please sign in to comment.