int urj_tap_cable_get_signal_late (urj_cable_t *cable, urj_pod_sigsel_t sig) { int i; urj_tap_cable_flush (cable, URJ_TAP_CABLE_TO_OUTPUT); i = urj_tap_cable_get_queue_item (cable, &cable->done); if (i >= 0) { if (cable->done.data[i].action != URJ_TAP_CABLE_GET_SIGNAL) { urj_warning ( _("Internal error: Got wrong type of result from queue (%d? %p.%d)\n"), cable->done.data[i].action, &cable->done, i); urj_tap_cable_purge_queue (&cable->done, 1); } else if (cable->done.data[i].arg.value.sig != sig) { urj_warning ( _("Internal error: Got wrong signal's value from queue (%d? %p.%d)\n"), cable->done.data[i].action, &cable->done, i); urj_tap_cable_purge_queue (&cable->done, 1); } else { return cable->done.data[i].arg.value.val; } } return cable->driver->get_signal (cable, sig); }
static int arduiggler_init (urj_cable_t *cable) { params_t *params = cable->params; urj_tap_cable_cx_cmd_root_t *cmd_root = ¶ms->cmd_root; if (urj_tap_usbconn_open (cable->link.usb) != URJ_STATUS_OK) return URJ_STATUS_FAIL; /* need to change the default baud rate from libftdi.c * to the actual one used by the cable */ /* ftdi_param_t *fp = cable->link.usb->params; int r = ftdi_set_baudrate(fp->fc, BAUD_RATE); if (r != 0) { urj_warning (_("cannot change baud rate\n")); return URJ_STATUS_FAIL; } */ urj_tap_cable_cx_cmd_queue (cmd_root, 0); urj_tap_cable_cx_cmd_push (cmd_root, CMD_RESET); urj_tap_cable_cx_xfer (cmd_root, NULL, cable, URJ_TAP_CABLE_COMPLETELY); int ar_status = arduiggler_get_status(cable); if (ar_status != STATUS_OK) { urj_warning (_("cable not initialized properly\n")); return URJ_STATUS_FAIL; } urj_tap_cable_cx_cmd_queue (cmd_root, 0); urj_tap_cable_cx_cmd_push (cmd_root, CMD_GETVER); urj_tap_cable_cx_xfer (cmd_root, NULL, cable, URJ_TAP_CABLE_COMPLETELY); char ar_swver[] = " "; for (int i = 0; i < strlen(ar_swver); i++) { ar_swver[i] = urj_tap_cable_cx_xfer_recv (cable); } urj_log (URJ_LOG_LEVEL_NORMAL, "Arduiggler firmware: %s\n", ar_swver); ar_status = arduiggler_get_status(cable); if (ar_status != STATUS_OK) { urj_warning (_("cable not initialized properly\n")); return URJ_STATUS_FAIL; } //arduiggler_set_frequency (cable, 0); return URJ_STATUS_OK; }
static void bfin_part_init (urj_part_t *part) { int i; if (!part || !part->params) goto error; part->params->free = free; part->params->wait_ready = bfin_wait_ready; part->params->data = malloc (sizeof (struct bfin_part_data)); *BFIN_PART_DATA (part) = bfin_part_data_initializer; if (!part->active_instruction) goto error; for (i = 0; i < NUM_SCANS; i++) if (strcmp (part->active_instruction->name, scans[i]) == 0) break; if (i == NUM_SCANS) goto error; BFIN_PART_SCAN (part) = i; return; error: urj_warning (_("Blackfin part is missing instructions\n")); }
void urj_tap_cable_generic_usbconn_help_ex (urj_log_level_t ll, const char *cablename, const char *ex_short, const char *ex_desc) { int i; const urj_usbconn_cable_t *conn; for (i = 0; urj_tap_cable_usbconn_cables[i]; ++i) { conn = urj_tap_cable_usbconn_cables[i]; if (strcasecmp (conn->name, cablename) == 0) break; } if (!urj_tap_cable_usbconn_cables[i]) { urj_warning (_("Unable to locate cable %s"), cablename); return; } urj_log (ll, _("Usage: cable %s %s %s\n" "\n" "%s%s" "\n" "Default: vid=%x pid=%x driver=%s\n" "\n"), cablename, URJ_TAP_CABLE_GENERIC_USBCONN_HELP_SHORT, ex_short, URJ_TAP_CABLE_GENERIC_USBCONN_HELP_DESC, ex_desc, conn->vid, conn->pid, conn->driver); }
static void bfin_wait_ready (void *data) { urj_chain_t *chain = (urj_chain_t *) data; /* The following default numbers of wait clock for various cables are tested on a BF537 stamp board, on which U-Boot is running. CCLK is set to 62MHz and SCLK is set to 31MHz, which is the lowest frequency I can set in BF537 stamp Linux kernel. The test is done by dumping memory from 0x20000000 to 0x20000010 using GDB and gdbproxy: (gdb) dump memory u-boot.bin 0x20000000 0x20000010 (gdb) shell hexdump -C u-boot.bin With an incorrect number of wait clocks, the first 4 bytes will be duplicated by the second 4 bytes. */ if (bfin_wait_clocks == -1) { urj_cable_t *cable = chain->cable; uint32_t frequency = cable->frequency; const char *name = cable->driver->name; if (strcmp (name, "gnICE+") == 0) { if (frequency <= 6000000) bfin_wait_clocks = 5; else if (frequency <= 15000000) bfin_wait_clocks = 12; else /* <= 30MHz */ bfin_wait_clocks = 21; } else if (strcmp (name, "gnICE") == 0) bfin_wait_clocks = 3; else if (strcmp (name, "ICE-100B") == 0) { if (frequency <= 5000000) bfin_wait_clocks = 5; else if (frequency <= 10000000) bfin_wait_clocks = 11; else if (frequency <= 17000000) bfin_wait_clocks = 19; else /* <= 25MHz */ bfin_wait_clocks = 30; } if (bfin_wait_clocks == -1) { bfin_wait_clocks = 30; urj_warning (_("%s: untested cable, set wait_clocks to %d\n"), name, bfin_wait_clocks); } } urj_tap_chain_defer_clock (chain, 0, 0, bfin_wait_clocks); }
static void usbblaster_set_frequency (urj_cable_t *cable, uint32_t new_frequency) { if (new_frequency != FIXED_FREQUENCY) urj_warning (_("USB-Blaster frequency is fixed to %ld Hz\n"), FIXED_FREQUENCY); cable->frequency = FIXED_FREQUENCY; }
int urj_tap_cable_transfer_late (urj_cable_t *cable, char *out) { int i; urj_tap_cable_flush (cable, URJ_TAP_CABLE_TO_OUTPUT); i = urj_tap_cable_get_queue_item (cable, &cable->done); if (i >= 0 && cable->done.data[i].action == URJ_TAP_CABLE_TRANSFER) { #if 0 urj_log (URJ_LOG_LEVEL_DEBUG, "Got queue item (%p.%d) len=%d out=%p\n", &cable->done, i, cable->done.data[i].arg.xferred.len, cable->done.data[i].arg.xferred.out); #endif if (out) memcpy (out, cable->done.data[i].arg.xferred.out, cable->done.data[i].arg.xferred.len); free (cable->done.data[i].arg.xferred.out); return cable->done.data[i].arg.xferred.res; } if (cable->done.data[i].action != URJ_TAP_CABLE_TRANSFER) { urj_warning ( _("Internal error: Got wrong type of result from queue (#%d %p.%d)\n"), cable->done.data[i].action, &cable->done, i); urj_tap_cable_purge_queue (&cable->done, 1); } else { urj_warning ( _("Internal error: Wanted transfer result but none was queued\n")); } return 0; }
int urj_tap_cable_get_tdo_late (urj_cable_t *cable) { int i; urj_tap_cable_flush (cable, URJ_TAP_CABLE_TO_OUTPUT); i = urj_tap_cable_get_queue_item (cable, &cable->done); if (i >= 0) { if (cable->done.data[i].action != URJ_TAP_CABLE_GET_TDO) { urj_warning ( _("Internal error: Got wrong type of result from queue (%d? %p.%d)\n"), cable->done.data[i].action, &cable->done, i); urj_tap_cable_purge_queue (&cable->done, 1); } else { return cable->done.data[i].arg.value.val; } } return cable->driver->get_tdo (cable); }
static void arduiggler_set_frequency (urj_cable_t *cable, uint32_t new_frequency) { urj_warning (_("Arduiggler does not support configurable frequency\n")); }
static int cmd_bfin_run (urj_chain_t *chain, char *params[]) { int num_params; num_params = urj_cmd_params (params); if (num_params < 2) { urj_error_set (URJ_ERROR_SYNTAX, "#parameters should be >= 2, not %d", num_params); return URJ_STATUS_FAIL; } /* The remaining commands require cable or parts. */ if (urj_cmd_test_cable (chain) != URJ_STATUS_OK) return URJ_STATUS_FAIL; if (!chain->parts) { urj_error_set (URJ_ERROR_ILLEGAL_STATE, "no parts, Run '%s' first", "detect"); return URJ_STATUS_FAIL; } if (chain->active_part >= chain->parts->len) { urj_error_set (URJ_ERROR_ILLEGAL_STATE, "no active part"); return URJ_STATUS_FAIL; } if (!part_is_bfin (chain, chain->active_part)) { urj_error_set (URJ_ERROR_ILLEGAL_STATE, "not a Blackfin part"); return URJ_STATUS_FAIL; } assert (chain->active_part >= 0 && chain->active_part < chain->parts->len); if (strcmp (params[1], "emulation") == 0) { if (num_params != 3) { urj_error_set (URJ_ERROR_BFIN, "'bfin emulation' requires 1 parameter, not %d", num_params - 2); return URJ_STATUS_FAIL; } if (strcmp (params[2], "enable") == 0) { part_emulation_enable (chain, chain->active_part); } else if (strcmp (params[2], "trigger") == 0) { part_emulation_trigger (chain, chain->active_part); } else if (strcmp (params[2], "enter") == 0) { part_emulation_enable (chain, chain->active_part); part_emulation_trigger (chain, chain->active_part); } else if (strcmp (params[2], "return") == 0) { part_emulation_return (chain, chain->active_part); } else if (strcmp (params[2], "disable") == 0) { part_emulation_disable (chain, chain->active_part); } else if (strcmp (params[2], "exit") == 0) { part_emulation_return (chain, chain->active_part); part_emulation_disable (chain, chain->active_part); } else if (strcmp (params[2], "status") == 0) { uint16_t dbgstat, excause; const char *str_excause; urj_part_t *part; part_dbgstat_get (chain, chain->active_part); part = chain->parts->parts[chain->active_part]; dbgstat = BFIN_PART_DBGSTAT (part); excause = part_dbgstat_emucause (chain, chain->active_part); switch (excause) { case 0x0: str_excause = "EMUEXCPT was executed"; break; case 0x1: str_excause = "EMUIN pin was asserted"; break; case 0x2: str_excause = "Watchpoint event occurred"; break; case 0x4: str_excause = "Performance Monitor 0 overflowed"; break; case 0x5: str_excause = "Performance Monitor 1 overflowed"; break; case 0x8: str_excause = "Emulation single step"; break; default: str_excause = "Reserved??"; break; } urj_log (URJ_LOG_LEVEL_NORMAL, "Core [%d] DBGSTAT = 0x%"PRIx16"\n", chain->active_part, dbgstat); urj_log (URJ_LOG_LEVEL_NORMAL, "\tEMUDOF = %u\n" "\tEMUDIF = %u\n" "\tEMUDOOVF = %u\n" "\tEMUDIOVF = %u\n" "\tEMUREADY = %u\n" "\tEMUACK = %u\n" "\tEMUCAUSE = 0x%x (%s)\n" "\tBIST_DONE = %u\n" "\tLPDEC0 = %u\n" "\tIN_RESET = %u\n" "\tIDLE = %u\n" "\tCORE_FAULT = %u\n" "\tLPDEC1 = %u\n", part_dbgstat_is_emudof (chain, chain->active_part), part_dbgstat_is_emudif (chain, chain->active_part), part_dbgstat_is_emudoovf (chain, chain->active_part), part_dbgstat_is_emudiovf (chain, chain->active_part), part_dbgstat_is_emuready (chain, chain->active_part), part_dbgstat_is_emuack (chain, chain->active_part), excause, str_excause, part_dbgstat_is_bist_done (chain, chain->active_part), part_dbgstat_is_lpdec0 (chain, chain->active_part), part_dbgstat_is_in_reset (chain, chain->active_part), part_dbgstat_is_idle (chain, chain->active_part), part_dbgstat_is_core_fault (chain, chain->active_part), part_dbgstat_is_lpdec1 (chain, chain->active_part)); } else if (strcmp (params[2], "singlestep") == 0) { part_dbgstat_get (chain, chain->active_part); if (!part_dbgstat_is_emuready (chain, chain->active_part)) { urj_error_set (URJ_ERROR_BFIN, "Run '%s' first", "bfin emulation enter"); return URJ_STATUS_FAIL; } /* TODO Allow an argument to specify how many single steps. */ part_scan_select (chain, chain->active_part, DBGCTL_SCAN); part_dbgctl_bit_set_esstep (chain, chain->active_part); urj_tap_chain_shift_data_registers_mode (chain, 0, 1, URJ_CHAIN_EXITMODE_UPDATE); part_emuir_set (chain, chain->active_part, INSN_RTE, URJ_CHAIN_EXITMODE_IDLE); part_scan_select (chain, chain->active_part, DBGCTL_SCAN); part_dbgctl_bit_clear_esstep (chain, chain->active_part); urj_tap_chain_shift_data_registers_mode (chain, 0, 1, URJ_CHAIN_EXITMODE_UPDATE); } else { urj_error_set (URJ_ERROR_BFIN, "unknown emulation subcommand '%s'", params[2]); return URJ_STATUS_FAIL; } return URJ_STATUS_OK; } else if (strcmp (params[1], "execute") == 0) { int execute_ret = URJ_STATUS_FAIL; part_dbgstat_get (chain, chain->active_part); if (!part_dbgstat_is_emuready (chain, chain->active_part)) { urj_error_set (URJ_ERROR_BFIN, "Run '%s' first", "bfin emulation enter"); return URJ_STATUS_FAIL; } if (num_params > 2) { int i; struct bfin_insn *insns = NULL; struct bfin_insn **last = &insns; char tmp[8]; char *tmpfile = NULL; for (i = 2; i < num_params; i++) { if (params[i][0] == '[' && params[i][1] == '0') { uint64_t n; if (sscanf (params[i], "[0%[xX]%"PRIx64"]", tmp, &n) != 2) goto execute_cleanup; *last = (struct bfin_insn *) malloc (sizeof (struct bfin_insn)); if (*last == NULL) goto execute_cleanup; (*last)->i = n; (*last)->type = BFIN_INSN_SET_EMUDAT; (*last)->next = NULL; last = &((*last)->next); } else if (params[i][0] == '0') { uint64_t n; if (sscanf (params[i], "0%[xX]%"PRIx64, tmp, &n) != 2) goto execute_cleanup; *last = (struct bfin_insn *) malloc (sizeof (struct bfin_insn)); if (*last == NULL) goto execute_cleanup; (*last)->i = n; (*last)->type = BFIN_INSN_NORMAL; (*last)->next = NULL; last = &((*last)->next); } else { #ifndef HAVE_SYS_WAIT_H urj_error_set (URJ_ERROR_BFIN, "Sorry, dynamic code not available for your platform"); goto execute_cleanup; #else unsigned char raw_insn[4]; char *tmp_buf; char *tuples[] = {"uclinux", "linux-uclibc", "elf"}; size_t t; FILE *fp; /* 1024 should be plenty. */ char insns_string[1024]; char *p = insns_string; for (; i < num_params; i++) { p += snprintf (p, sizeof (insns_string) - (p - insns_string), "%s ", params[i]); if (params[i][strlen (params[i]) - 1] == '"') break; if (params[i][strlen (params[i]) - 1] == ';') break; } if (i == num_params) { urj_error_set (URJ_ERROR_BFIN, "unbalanced double quotes"); goto execute_cleanup; } /* p points past the '\0'. p - 1 points to the ending '\0'. p - 2 points to the last double quote. */ *(p - 2) = ';'; if (insns_string[0] == '"') insns_string[0] = ' '; /* HRM states that branches and hardware loop setup results in undefined behavior. Should check opcode instead? */ if (strcasestr(insns_string, "jump") || strcasestr(insns_string, "call") || strcasestr(insns_string, "lsetup")) urj_warning (_("jump/call/lsetup insns may not work in emulation\n")); /* get a temporary file to work with -- a little racy */ if (!tmpfile) { tmpfile = tmpnam (NULL); if (!tmpfile) goto execute_cleanup; tmpfile = strdup (tmpfile); if (!tmpfile) goto execute_cleanup; } /* try to find a toolchain in $PATH */ for (t = 0; t < ARRAY_SIZE(tuples); ++t) { int ret; /* TODO Pass -mcpu= to gas. */ ret = asprintf (&tmp_buf, "bfin-%3$s-as --version >/dev/null 2>&1 || exit $?;" "echo '%1$s' | bfin-%3$s-as - -o \"%2$s\"" " && bfin-%3$s-objcopy -O binary \"%2$s\"", insns_string, tmpfile, tuples[t]); if (ret == -1) { urj_error_set (URJ_ERROR_OUT_OF_MEMORY, _("asprintf() failed")); goto execute_cleanup; } ret = system (tmp_buf); free (tmp_buf); if (WIFEXITED(ret)) { if (WEXITSTATUS(ret) == 0) break; /* 127 -> not found in $PATH */ else if (WEXITSTATUS(ret) == 127) continue; else { urj_error_set (URJ_ERROR_BFIN, "GAS failed parsing: %s", insns_string); goto execute_cleanup; } } } if (t == ARRAY_SIZE(tuples)) { urj_error_set (URJ_ERROR_BFIN, "unable to find Blackfin toolchain in $PATH\n"); goto execute_cleanup; } /* Read the binary blob from the toolchain */ fp = fopen (tmpfile, FOPEN_R); if (fp == NULL) goto execute_cleanup; /* Figure out how many instructions there are */ t = 0; p = insns_string; while ((p = strchr(p, ';')) != NULL) { ++t; ++p; } while (t-- && fread (raw_insn, 1, 2, fp) == 2) { uint16_t iw = raw_insn[0] | (raw_insn[1] << 8); uint64_t n = iw; int is_multiinsn = INSN_IS_MULTI (raw_insn[1]); if ((iw & 0xf000) >= 0xc000) { if (fread (raw_insn, 1, 2, fp) != 2) goto execute_cleanup; iw = raw_insn[0] | (raw_insn[1] << 8); n = (n << 16) | iw; } if (is_multiinsn) { if (fread (raw_insn, 1, 4, fp) != 4) goto execute_cleanup; n = (n << 32) | ((uint64_t)raw_insn[0] << 16) | ((uint64_t)raw_insn[1] << 24) | raw_insn[2] | (raw_insn[3] << 8); } *last = (struct bfin_insn *) malloc (sizeof (struct bfin_insn)); if (*last == NULL) goto execute_cleanup; (*last)->i = n; (*last)->type = BFIN_INSN_NORMAL; (*last)->next = NULL; last = &((*last)->next); } fclose (fp); #endif } } part_execute_instructions (chain, chain->active_part, insns); execute_ret = URJ_STATUS_OK; execute_cleanup: if (tmpfile) { unlink (tmpfile); free (tmpfile); } while (insns) { struct bfin_insn *tmp = insns->next; free (insns); insns = tmp; } } if (execute_ret == URJ_STATUS_OK) { uint64_t emudat; emudat = part_emudat_get (chain, chain->active_part, URJ_CHAIN_EXITMODE_UPDATE); urj_log (URJ_LOG_LEVEL_NORMAL, "EMUDAT = 0x%"PRIx64"\n", emudat); part_dbgstat_get (chain, chain->active_part); if (part_dbgstat_is_core_fault (chain, chain->active_part)) urj_warning (_("core fault detected\n")); } return execute_ret; } else if (strcmp (params[1], "reset") == 0) { int reset_what = 0; part_dbgstat_get (chain, chain->active_part); if (!part_dbgstat_is_emuready (chain, chain->active_part)) { urj_error_set (URJ_ERROR_BFIN, "Run '%s' first", "bfin emulation enter"); return URJ_STATUS_FAIL; } if (num_params == 3) { if (!strcmp (params[2], "core")) reset_what |= 0x1; else if (!strcmp (params[2], "system")) reset_what |= 0x2; else { urj_error_set (URJ_ERROR_BFIN, "bad parameter '%s'", params[2]); return URJ_STATUS_FAIL; } } else if (num_params == 2) reset_what = 0x1 | 0x2; else { urj_error_set (URJ_ERROR_BFIN, "'bfin emulation' requires 0 or 1 parameter, not %d", num_params - 2); return URJ_STATUS_FAIL; } urj_log (URJ_LOG_LEVEL_NORMAL, _("%s: reseting processor ... "), "bfin"); fflush (stdout); if (reset_what == 0x3) software_reset (chain, chain->active_part); else if (reset_what & 0x1) bfin_core_reset (chain, chain->active_part); else if (reset_what & 0x2) chain_system_reset (chain); urj_log (URJ_LOG_LEVEL_NORMAL, _("OK\n")); return URJ_STATUS_OK; } else { urj_error_set (URJ_ERROR_BFIN, "unknown command '%s'", params[1]); return URJ_STATUS_FAIL; } return URJ_STATUS_OK; }