I know that's a lot to ask, but I was stucked in some bugs in my driver.The driver is very simple, it saves the tms sequences, and send whenever needed. It's about 500 lines, and it's very easy to be understanded. My adapter side of code is also simple, it's about 100-200 lines. If you are familar with debugger driver. Please help me out. I'll be very thankful.I can recognize my arm9ejs chip with my driver. But I can't halt it. So this bug might be a subtle one.

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <helper/log.h>
#include <helper/binarybuffer.h>
#include <helper/command.h>
#include <jtag/interface.h>
#include "usb_common.h"

#define USBMZ_USB_VID       0xffff
#define USBMZ_USB_PID       0xffff
#define USBMZ_USB_BUFSIZE   64
#define USBMZ_USB_TIMEOUT   10000
#define USBMZ_USB_EP_WRITE  0x05
#define USBMZ_USB_EP_READ   0x85

#define USBMZ_CMD_UNKOWN    0x00
#define USBMZ_CMD_INIT      0x01
#define USBMZ_CMD_RESET     0x02
#define USBMZ_CMD_TMS       0x03
#define USBMZ_CMD_IO        0x04
#define USBMZ_CMD_STEP      0x05

#define USBMZ_IO_MODE_W     0x1
#define USBMZ_IO_MODE_R     0x2
#define USBMZ_IO_MODE_L     0x4

#define USBMZ_MAX_TMS_SIZE  (USBMZ_USB_BUFSIZE - 3)
#define USBMZ_MAX_IO_SIZE   (USBMZ_USB_BUFSIZE - 4)

static const uint16_t usbmz_vid[] = { 0xffff, 0 };
static const uint16_t usbmz_pid[] = { 0xffff, 0 };

struct usbmz_jtag {
	struct usb_dev_handle *udev;
	uint8_t buffer[USBMZ_USB_BUFSIZE];
	int count;
	uint8_t tms[USBMZ_MAX_TMS_SIZE];
	uint16_t tms_nbits;
};

static struct usbmz_jtag usbmz_ins;

static int usbmz_usb_send(void);
static int usbmz_usb_recv(void);

static void usbmz_print_buf(const void *_buf, uint16_t nbits)
{
  const uint8_t *buf = (const uint8_t *)_buf;
  for (int i=0; i<nbits; i++)
  {
    int ibyte = i >> 3;
    int ibit = i & 0b111;
    int value = (buf[ibyte] >> ibit) & 0x1;
    LOG_DEBUG("%d", value);
  }
}

static int usbmz_commit_tms(void)
{
  LOG_DEBUG("usbmz -> tms commit %d", usbmz_ins.tms_nbits);
  // send tms
  if (usbmz_ins.tms_nbits == 0)
    return ERROR_OK;
  
  usbmz_ins.buffer[0] = USBMZ_CMD_TMS;
  usbmz_ins.buffer[1] = (uint8_t)(usbmz_ins.tms_nbits >> 8);
  usbmz_ins.buffer[2] = (uint8_t)usbmz_ins.tms_nbits;
  int count = DIV_ROUND_UP(usbmz_ins.tms_nbits, 8);
  buf_set_buf(usbmz_ins.tms, 0,
    usbmz_ins.buffer + 3, 0, usbmz_ins.tms_nbits);
  
  usbmz_print_buf(usbmz_ins.buffer + 3, usbmz_ins.tms_nbits);
  usbmz_ins.count = count + 3;
  usbmz_ins.tms_nbits = 0;
  assert(usbmz_ins.count > 0 ||
    usbmz_ins.count <= USBMZ_USB_BUFSIZE);
  int ret = usbmz_usb_send();
  return ret;
}

static int usbmz_cache_tms(const uint8_t *tms, uint16_t nbits)
{
  LOG_DEBUG("usbmz -> tms cache");
  usbmz_print_buf(tms, nbits);
  int bit_index=0;
  while (nbits > 0)
  {
    uint32_t bsz = MIN(USBMZ_MAX_TMS_SIZE*8 - usbmz_ins.tms_nbits,
      nbits);
    buf_set_buf(tms, bit_index,
      usbmz_ins.tms, usbmz_ins.tms_nbits, bsz);
    nbits -= bsz;
    bit_index += bsz;
    usbmz_ins.tms_nbits += bsz;
    if (usbmz_ins.tms_nbits == USBMZ_MAX_TMS_SIZE*8)
    {
      int ret = usbmz_commit_tms();
      if (ret != ERROR_OK)
        return ERROR_FAIL;
    }
  }
  return ERROR_OK;
}

static int usbmz_pathmove(tap_state_t *path,
  int num_states)
{
  LOG_DEBUG("usbmz -> tms pathmove");
  int tms = 0;
  for (int i=0; i<num_states; i++)
  {
    if (tap_state_transition(tap_get_state(), 1)
      == path[i])
      tms |= (1 << i);
    else if (tap_state_transition(tap_get_state(), 0)
      == path[i])
      tms &= ~(1 << i);
    else
    {
      LOG_ERROR("usbmz -> can't transit from %s to %s",
        tap_state_name(tap_get_state()),
        tap_state_name(path[i]));
    }
    tap_set_state(path[i]);
  }  
  
  int ret = usbmz_cache_tms((uint8_t *)&tms, num_states);
  if (ret != ERROR_OK)
    return ret;
  tap_set_end_state(tap_get_state());
  return ERROR_OK;
}

static int usbmz_statemove(tap_state_t new_state)
{
  tap_set_end_state(new_state);
  
  if (tap_get_end_state() == TAP_RESET)
  {
    LOG_DEBUG("usbmz -> transit from %s to %s",
      tap_state_name(tap_get_state()),
      tap_state_name(tap_get_end_state()));
    int tms = 0xff;
    int len = 7;
    int ret = usbmz_cache_tms((uint8_t *)&tms, len);
    if (ret != ERROR_OK)
      return ret;
    tap_set_state(tap_get_end_state());
	}
  else if (tap_get_state() != tap_get_end_state())
  {
    LOG_DEBUG("usbmz -> transit from %s to %s",
        tap_state_name(tap_get_state()),
        tap_state_name(tap_get_end_state()));
    int tms = tap_get_tms_path(
      tap_get_state(), new_state);
    int len = tap_get_tms_path_len(
      tap_get_state(), new_state);
    int ret = usbmz_cache_tms((uint8_t *)&tms, len);
    if (ret != ERROR_OK)
      return ret;
    tap_set_state(tap_get_end_state());
  }
  return ERROR_OK;
}

static int usbmz_tms(const uint8_t *tms, int num_bits)
{
  int ret = usbmz_cache_tms(tms, num_bits);
  if (ret != ERROR_OK)
    return ret;
  return ERROR_OK;
}

static int usbmz_scan(const struct scan_command *cmd)
{
  int ret;
  uint8_t *buffer;
  enum scan_type type = jtag_scan_type(cmd);
  int nbits;
  bool ir_scan = cmd->ir_scan;
  uint8_t mode;
  tap_state_t end_state = cmd->end_state;
  
  if (type == SCAN_OUT)
    mode = USBMZ_IO_MODE_W;
  else if (type == SCAN_IN)
    mode = USBMZ_IO_MODE_R;
  else if (type == SCAN_IO)
    mode = USBMZ_IO_MODE_R | USBMZ_IO_MODE_W;
  else
  {
    LOG_ERROR("usbmz -> wrong scan type");
    return ERROR_FAIL;
  }
  LOG_DEBUG("usbmz -> scan mode %d", mode);
  
	ret = usbmz_statemove(ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT);
	if (ret != ERROR_OK)
		return ERROR_FAIL;
	
	ret = usbmz_commit_tms();
  if (ret != ERROR_OK)
    return ERROR_FAIL;
  
	nbits = jtag_build_buffer(cmd, &buffer);
	if (buffer == NULL || nbits <= 0)
  {
    LOG_ERROR("usbmz -> fail to build scan buffer");
    return ERROR_FAIL;
  }
  bool should_transfer = end_state != tap_get_state();

  uint32_t bit_index = 0;
  while (nbits > 0)
  {
    uint32_t bsz = MIN(USBMZ_MAX_IO_SIZE * 8, nbits);
    usbmz_ins.count = 0;
    usbmz_ins.buffer[usbmz_ins.count++] = USBMZ_CMD_IO;
    usbmz_ins.buffer[usbmz_ins.count++] = (uint8_t)(bsz >> 8);
    usbmz_ins.buffer[usbmz_ins.count++] = (uint8_t)bsz;
    usbmz_ins.buffer[usbmz_ins.count++] = 
      mode | ((should_transfer && nbits == (int)bsz) ? USBMZ_IO_MODE_L : 0);
    usbmz_ins.count += DIV_ROUND_UP(bsz, 8);
    if (mode & USBMZ_IO_MODE_W)
    {
      buf_set_buf(buffer, bit_index,
        usbmz_ins.buffer+4, 0, bsz);
    }
    
    if (usbmz_usb_send() != ERROR_OK)
      return ERROR_FAIL;
    
    if (mode & USBMZ_IO_MODE_R)
    {
      usleep(1);
      if (usbmz_usb_recv() != ERROR_OK)
        return ERROR_FAIL;
      if (usbmz_ins.count != (int)DIV_ROUND_UP(bsz, 8)+4 ||
        usbmz_ins.buffer[0] != USBMZ_CMD_IO || 
        usbmz_ins.buffer[1] != (uint8_t)(bsz >> 8) || 
        usbmz_ins.buffer[2] != (uint8_t)bsz)
      {
        LOG_ERROR("usbmz -> scan recv packet err");
        return ERROR_FAIL;
      }
      buf_set_buf(usbmz_ins.buffer+4, 0,
        buffer, bit_index, bsz);
    }
      
    nbits -= bsz;
    bit_index += bsz;    
  }
  
  //uint8_t tms = 0b01;
  //ret = usbmz_cache_tms(&tms, 2);
  //if (ret != ERROR_OK)
  //  return ret;
  if (should_transfer)
  {
    if (ir_scan)
		  tap_set_state(TAP_IRPAUSE);
	  else
		  tap_set_state(TAP_DRPAUSE);
		ret = usbmz_statemove(end_state);
		if (ret != ERROR_OK)
    {
      free(buffer);
      return ERROR_FAIL;
    }
  }
  
  
  ret = jtag_read_buffer(buffer, cmd);
  
  free(buffer);
  return ret;
}

static int usbmz_stableclocks(int count)
{
  if (!tap_is_state_stable(tap_get_state()))
  {
		LOG_ERROR("usbmz -> not stable current state (%s)",
			tap_state_name(tap_get_state()));
		return ERROR_FAIL;
	}
	uint32_t fill = 0;
	
	if (tap_get_state() == TAP_RESET)
    fill = ~fill;
  
  while (count > 0)
  {
    int bsz = MIN(sizeof(uint8_t)*32, count);
    int ret = usbmz_cache_tms((uint8_t *)&fill, bsz);
    if (ret != ERROR_OK)
      return ret;
    count -= bsz;
  }
	return ERROR_OK;
}

static int usbmz_runtest(int num_cycles,
  tap_state_t end_state)
{
  if (usbmz_statemove(TAP_IDLE) != ERROR_OK)
    return ERROR_FAIL;

  if (usbmz_stableclocks(num_cycles) != ERROR_OK)
    return ERROR_FAIL;

  if (usbmz_statemove(end_state) != ERROR_OK)
    return ERROR_FAIL;

  return ERROR_OK;
}

static int usbmz_reset(int srst, int trst)
{
  usbmz_commit_tms();
  usbmz_ins.count = 0;
  usbmz_ins.buffer[usbmz_ins.count++] = USBMZ_CMD_RESET;
  usbmz_ins.buffer[usbmz_ins.count++] = srst;
  usbmz_ins.buffer[usbmz_ins.count++] = trst;
  
  if (usbmz_usb_send() != ERROR_OK)
    return ERROR_FAIL;
  if (usbmz_usb_recv() != ERROR_OK)
    return ERROR_FAIL;
  if (usbmz_ins.count != 3 ||
    usbmz_ins.buffer[0] != USBMZ_CMD_RESET ||
    usbmz_ins.buffer[1] || usbmz_ins.buffer[2])
    return ERROR_FAIL;
    
  return ERROR_OK;
}

static int usbmz_execute_queue(void)
{
  struct jtag_command *cmd = jtag_command_queue;
  int ret = ERROR_OK;
  while (cmd && ret == ERROR_OK)
  {
    LOG_DEBUG("usbmz -> process (%d)", cmd->type);
    switch (cmd->type)
    {
    case JTAG_SCAN:
			ret = usbmz_scan(cmd->cmd.scan);
      break;
    case JTAG_TLR_RESET:
      ret = usbmz_statemove(
        cmd->cmd.statemove->end_state);
      break;
    case JTAG_RUNTEST:
      ret = usbmz_runtest(cmd->cmd.runtest->num_cycles,
        cmd->cmd.runtest->end_state);
      break;
    case JTAG_RESET:
      ret = usbmz_reset(cmd->cmd.reset->srst,
        cmd->cmd.reset->trst);
      break;
    case JTAG_PATHMOVE:
      ret = usbmz_pathmove(cmd->cmd.pathmove->path,
        cmd->cmd.pathmove->num_states);
      break;
    case JTAG_SLEEP:
      ret = usbmz_commit_tms();
      if (ret == ERROR_OK)
        jtag_sleep(cmd->cmd.sleep->us);
      break;
    case JTAG_STABLECLOCKS:
      ret = usbmz_stableclocks(
        cmd->cmd.stableclocks->num_cycles);
      break;
    case JTAG_TMS:
      ret = usbmz_tms(cmd->cmd.tms->bits,
        cmd->cmd.tms->num_bits);
      break;
    default:
      LOG_ERROR("usbmz -> unknown jtag cmd");
      break;
    }
    cmd = cmd->next;
  }
  if (ret != ERROR_OK)
    exit(-1);
  ret = usbmz_commit_tms();
  if (ret != ERROR_OK)
    exit(-1);
  return ret;
}

static int usbmz_usb_send(void)
{
  int count;
  if (usbmz_ins.count <= 0)
    return ERROR_OK;
  count = usb_bulk_write(usbmz_ins.udev,
    USBMZ_USB_EP_WRITE, (char *)usbmz_ins.buffer,
    usbmz_ins.count, USBMZ_USB_TIMEOUT);
  if (count != usbmz_ins.count)
  {
    LOG_ERROR("usbmz -> write error");
    return ERROR_FAIL;
  }
  return ERROR_OK;
}

static int usbmz_usb_recv(void)
{
  usbmz_ins.count = usb_bulk_read(usbmz_ins.udev,
    USBMZ_USB_EP_READ, (char *)usbmz_ins.buffer,
    USBMZ_USB_BUFSIZE, USBMZ_USB_TIMEOUT);
  if (usbmz_ins.count < 2)
  {
    LOG_ERROR("usbmz -> read packet error");
    return ERROR_FAIL;
  }
  return ERROR_OK;
}

static int usbmz_init(void)
{
  usb_init();
  memset(&usbmz_ins, 0, sizeof(usbmz_ins));
  if (jtag_usb_open(usbmz_vid, usbmz_pid,
    &usbmz_ins.udev) != ERROR_OK)
  {
    LOG_ERROR("usbmz -> can't open usb dev");
    return ERROR_FAIL;
  }
  usb_set_configuration(usbmz_ins.udev, 0);
  usb_claim_interface(usbmz_ins.udev, 4);
  usb_set_altinterface(usbmz_ins.udev, 0);
  usbmz_ins.count = 0;
  usbmz_ins.buffer[usbmz_ins.count++] = USBMZ_CMD_INIT;
  
  if (usbmz_usb_send() != ERROR_OK)
    return ERROR_FAIL;
  return ERROR_OK;
}

static int usbmz_quit(void)
{
  return ERROR_OK;
}

static struct jtag_interface usbmz_interface = {
	.execute_queue = usbmz_execute_queue,
};

struct adapter_driver usbmz_adapter_driver = {
	.name = "usbmz",
	.transports = jtag_only,

	.init = usbmz_init,
	.quit = usbmz_quit,

	.jtag_ops = &usbmz_interface,
};


/*
code in adapter--->

case CMD_RESET:
  // n_Srst _usb_buf[1]
  if (_usb_buf[2] == 0) // n_Trst
    platform_gpio_set(&_trst);
  else
    platform_gpio_clr(&_trst);
  // if _usb_buf[1] set, return false
  platform_gpio_clr(&_tck);
  LL_mDelay(100);
  _usb_buf[2] = 0;
  send = 3;
  break;
case CMD_TMS:
{
  //printf("tms->\n");
  uint16_t nbits = ((uint16_t)_usb_buf[1] << 8) +
    _usb_buf[2];
  platform_gpio_set(&_tdi);
  for (int i=0; i<nbits; i++)
  {
    uint8_t ibyte = i >> 3;
    uint8_t ibit = i & 0b111;
    bool itms = (_usb_buf[3+ibyte] >> ibit) & 0x1;
    //printf("%d", itms);
    if (itms)
      platform_gpio_set(&_tms);
    else
      platform_gpio_clr(&_tms);
    platform_gpio_set(&_tck);
    for (volatile int k=0; k<JTAG_DELAY; k++)
      asm("nop");
    platform_gpio_clr(&_tck);
    for (volatile int k=0; k<JTAG_DELAY; k++)
      asm("nop");
  }
  //printf("\n");
  break;
}
case CMD_IO:
{
  //printf("io->\n");
  uint16_t nbits = ((uint16_t)_usb_buf[1] << 8) +
    _usb_buf[2];
  uint8_t mode = _usb_buf[3];
  if (mode & CMD_IO_R)
    send = len;
  //printf("\n\e[1A");
  platform_gpio_clr(&_tms);
  for (int i=0; i<nbits; i++)
  {
    uint8_t ibyte = i >> 3;
    uint8_t ibit = i & 0b111;
    if (mode & CMD_IO_W)
    {
      bool itdi = (_usb_buf[4+ibyte] >> ibit) & 0x1;
      if (itdi)
        platform_gpio_set(&_tdi);
      else
        platform_gpio_clr(&_tdi);
      //printf("%d\b", itdi);
    }

    if (i == nbits - 1 && (mode & CMD_IO_L))
      platform_gpio_set(&_tms);
    else
      platform_gpio_clr(&_tms);

    platform_gpio_set(&_tck);
    for (volatile int k=0; k<JTAG_DELAY; k++)
      asm("nop");
    if (mode & CMD_IO_R)
    {
      bool itdo = platform_gpio_get(&_tdo);
      if (itdo)
        _usb_buf[4+ibyte] |= 1 << ibit;
      else
        _usb_buf[4+ibyte] &= ~(1 << ibit);
      //printf("\e[1B%d\e[1A\b", itdo);
    }
    //printf("\e[1C");
    platform_gpio_clr(&_tck);
    for (volatile int k=0; k<JTAG_DELAY; k++)
      asm("nop");
  }
  //printf("\n\n");
  if (mode & CMD_IO_L)
  {
    platform_gpio_set(&_tdi);
    platform_gpio_clr(&_tms);
    platform_gpio_set(&_tck);
    for (volatile int k=0; k<JTAG_DELAY; k++)
      asm("nop");
    platform_gpio_clr(&_tck);
    for (volatile int k=0; k<JTAG_DELAY; k++)
      asm("nop");
  }
  break;
}
*/


Reply via email to