/** * bus->driver->(*read_start) * */ static int avr32_bus_read_start (urj_bus_t *bus, uint32_t addr) { addr &= ADDR_MASK; DBG (DBG_BASIC, _("%s:addr=%08lx\n"), __FUNCTION__, (long unsigned) addr); switch (MODE) { case BUS_MODE_OCD: case BUS_MODE_HSBC: case BUS_MODE_HSBU: urj_part_set_instruction (bus->part, "MEMORY_WORD_ACCESS"); mwa_scan_in_instr (bus); mwa_scan_in_addr (bus, SLAVE, addr, ACCESS_MODE_READ); break; case BUS_MODE_x8: case BUS_MODE_x16: case BUS_MODE_x32: urj_part_set_instruction (bus->part, "NEXUS_ACCESS"); nexus_access_start (bus); nexus_memacc_set_addr (bus, addr, RWCS_RD); break; } return URJ_STATUS_OK; }
static int bfin_set_scan (urj_part_t *part, int scan) { if (is_bfin_part (part)) { if (BFIN_PART_SCAN (part) != scan) { urj_part_set_instruction (part, scans[scan]); if (part->active_instruction == NULL) { urj_log (URJ_LOG_LEVEL_ERROR, _("%s: unable to load instruction '%s'\n"), "bfin", scans[scan]); return -1; } BFIN_PART_SCAN (part) = scan; return 1; } else return 0; } else { urj_part_set_instruction (part, scans[scan]); return 1; } }
static void arm9tdmi_select_scanchain(urj_bus_t *bus, unsigned int chain) { int i; urj_part_set_instruction (bus->part, "SCAN_N"); urj_tap_chain_shift_instructions (bus->chain); for (i = 0; i < scann->in->len; i++) scann->in->data[i] = (chain >> i) & 1; urj_tap_chain_shift_data_registers (bus->chain, 0); }
/** * bus->driver->(*write) * */ static void avr32_bus_write (urj_bus_t *bus, uint32_t addr, uint32_t data) { addr &= ADDR_MASK; switch (MODE) { case BUS_MODE_OCD: case BUS_MODE_HSBC: case BUS_MODE_HSBU: urj_part_set_instruction (bus->part, "MEMORY_WORD_ACCESS"); mwa_write_word (bus, SLAVE, addr, data); break; case BUS_MODE_x8: case BUS_MODE_x16: case BUS_MODE_x32: urj_part_set_instruction (bus->part, "NEXUS_ACCESS"); nexus_access_start (bus); nexus_memacc_write (bus, addr, data, RWCS_WR); nexus_access_end (bus); break; } }
/** * bus->driver->(*initbus) * */ static int arm9tdmi_bus_init (urj_bus_t *bus) { unsigned int i, status, success; if (urj_tap_state (bus->chain) != URJ_TAP_STATE_RUN_TEST_IDLE) { /* silently skip initialization if TAP isn't in RUNTEST/IDLE state this is required to avoid interfering with detect when initbus is contained in the part description file URJ_BUS_INIT() will be called latest by URJ_BUS_PREPARE() */ return URJ_STATUS_OK; } if (scann == NULL) scann = urj_part_find_data_register (bus->part, "SCANN"); if (scan1 == NULL) scan1 = urj_part_find_data_register (bus->part, "SCAN1"); if (scan2 == NULL) scan2 = urj_part_find_data_register (bus->part, "SCAN2"); if (!(scann)) { urj_error_set (URJ_ERROR_NOTFOUND, _("SCANN register")); return URJ_STATUS_FAIL; } if (!(scan1)) { urj_error_set (URJ_ERROR_NOTFOUND, _("SCAN1 register")); return URJ_STATUS_FAIL; } if (!(scan2)) { urj_error_set (URJ_ERROR_NOTFOUND, _("SCAN2 register")); return URJ_STATUS_FAIL; } /* * select scan chain 2 -- EmbeddedICE-RT */ arm9tdmi_select_scanchain(bus, 2); urj_part_set_instruction (bus->part, "INTEST2"); urj_tap_chain_shift_instructions (bus->chain); arm9tdmi_ice_write(bus, ARM9TDMI_ICE_DBGCTL, 0x3); urj_part_set_instruction (bus->part, "RESTART"); urj_tap_chain_shift_instructions (bus->chain); i = 0; success = 0; status = 0; while (i++ < 10) { urj_part_set_instruction (bus->part, "INTEST2"); urj_tap_chain_shift_instructions (bus->chain); arm9tdmi_ice_read(bus, ARM9TDMI_ICE_DBGSTAT, &status); if (status & 0x01) { success = 1; break; } urj_part_set_instruction (bus->part, "RESTART"); urj_tap_chain_shift_instructions (bus->chain); usleep(100); } if (!success) { urj_error_set (URJ_ERROR_TIMEOUT, _("Failed to enter debug mode, ctrl=%s"), urj_tap_register_get_string (scan2->out)); return URJ_STATUS_FAIL; } arm9tdmi_ice_write(bus, ARM9TDMI_ICE_DBGCTL, 0x00); urj_log (URJ_LOG_LEVEL_NORMAL, _("The target is halted in ")); if (status & 0x10) urj_log (URJ_LOG_LEVEL_NORMAL, _("THUMB mode.\n")); else urj_log (URJ_LOG_LEVEL_NORMAL, _("ARM mode.\n")); /* select scan chain 1, and use INTEST instruction */ arm9tdmi_select_scanchain(bus, 1); urj_part_set_instruction (bus->part, "INTEST1"); urj_tap_chain_shift_instructions_mode (bus->chain, 0, 1, URJ_CHAIN_EXITMODE_UPDATE); bus->initialized = 1; return URJ_STATUS_OK; }
/** * low level memory read * */ static unsigned int arm9tdmi_read (urj_bus_t *bus, unsigned int addr, unsigned int sz) { unsigned int c1_inst, c1_data, result, i; /* * Load R0 with the address to read */ c1_inst = 0xE59F0000; /* LDR R0, [PC] */ c1_data = 0; arm9tdmi_exec_instruction(bus, c1_inst, c1_data, DEBUG_SPEED); c1_inst = ARM_NOP; c1_data = 0; arm9tdmi_exec_instruction(bus, c1_inst, c1_data, DEBUG_SPEED); arm9tdmi_exec_instruction(bus, c1_inst, c1_data, DEBUG_SPEED); c1_data = addr; arm9tdmi_exec_instruction(bus, c1_inst, c1_data, DEBUG_SPEED); c1_data = 0; arm9tdmi_exec_instruction(bus, c1_inst, c1_data, DEBUG_SPEED); if (sz == 32) c1_inst = 0xE5901000; /* LDR R1, [R0] */ else if (sz == 16) c1_inst = 0xE1D010B0; /* LDRH R1, [R0] */ else if (sz == 8) c1_inst = 0xE5D01000; /* LDRB R1, [R0] */ c1_data = 0; arm9tdmi_exec_instruction(bus, c1_inst, c1_data, DEBUG_SPEED); /* * Execute instruction at SYSTEM_SPEED as we need to access memory */ c1_inst = ARM_NOP; arm9tdmi_exec_instruction(bus, c1_inst, c1_data, SYSTEM_SPEED); urj_tap_chain_flush(bus->chain); /* Write RESTART instruction into the TAP controller. * When the state machine enters the Run-Test/Idle state, * the ARM9TDMI core will revert back to system mode, * and it will resynchronize clock to MCLK. */ urj_part_set_instruction (bus->part, "RESTART"); urj_tap_chain_shift_instructions (bus->chain); /* * Now, the ARM9TDMI core re-entered the debug state. * Before the debug session continues, we must load the * TAP controller with the INTEST instruction. We can use * the instruction "STR R1, [PC]" running at debug-speed to * read out the contents of register R1. */ urj_part_set_instruction (bus->part, "INTEST1"); urj_tap_chain_shift_instructions_mode (bus->chain, 0, 1, URJ_CHAIN_EXITMODE_UPDATE); c1_inst = 0xE58F1000; /* STR R1, [PC] */ c1_data = 0; arm9tdmi_exec_instruction(bus, c1_inst, c1_data, DEBUG_SPEED); c1_inst = ARM_NOP; c1_data = 0; arm9tdmi_exec_instruction(bus, c1_inst, c1_data, DEBUG_SPEED); arm9tdmi_exec_instruction(bus, c1_inst, c1_data, DEBUG_SPEED); arm9tdmi_exec_instruction(bus, c1_inst, c1_data, DEBUG_SPEED); result = 0; for (i = 0; i < 32; i++) { if (scan1->out->data[i]) result |= (1 << i); } arm9tdmi_exec_instruction(bus, c1_inst, c1_data, DEBUG_SPEED); return result; }
static uint32_t ejtag_run_pracc (urj_bus_t *bus, const uint32_t *code, unsigned int len) { urj_data_register_t *ejaddr, *ejdata, *ejctrl; int i, pass; uint32_t addr, data, retval; ejaddr = urj_part_find_data_register (bus->part, "EJADDRESS"); ejdata = urj_part_find_data_register (bus->part, "EJDATA"); ejctrl = urj_part_find_data_register (bus->part, "EJCONTROL"); if (!(ejaddr && ejdata && ejctrl)) { urj_error_set (URJ_ERROR_NOTFOUND, _("EJADDRESS, EJDATA or EJCONTROL register not found")); return 0; } urj_part_set_instruction (bus->part, "EJTAG_CONTROL"); urj_tap_chain_shift_instructions (bus->chain); pass = 0; retval = 0; for (;;) { ejctrl->in->data[PrAcc] = 1; urj_tap_chain_shift_data_registers (bus->chain, 0); urj_tap_chain_shift_data_registers (bus->chain, 1); urj_log (URJ_LOG_LEVEL_ALL, "ctrl=%s\n", urj_tap_register_get_string (ejctrl->out)); if (ejctrl->out->data[Rocc]) { urj_error_set (URJ_ERROR_BUS, _("Reset occurred, ctrl=%s"), urj_tap_register_get_string (ejctrl->out)); bus->initialized = 0; break; } if (!ejctrl->out->data[PrAcc]) { urj_error_set (URJ_ERROR_BUS, _("No processor access, ctrl=%s"), urj_tap_register_get_string (ejctrl->out)); bus->initialized = 0; break; } urj_part_set_instruction (bus->part, "EJTAG_ADDRESS"); urj_tap_chain_shift_instructions (bus->chain); urj_tap_chain_shift_data_registers (bus->chain, 1); addr = reg_value (ejaddr->out); if (addr & 3) { urj_error_set (URJ_ERROR_BUS, _("PrAcc bad alignment: addr=0x%08lx"), (long unsigned) addr); addr &= ~3; } urj_part_set_instruction (bus->part, "EJTAG_DATA"); urj_tap_chain_shift_instructions (bus->chain); urj_tap_register_fill (ejdata->in, 0); if (ejctrl->out->data[PRnW]) { urj_tap_chain_shift_data_registers (bus->chain, 1); data = reg_value (ejdata->out); urj_log (URJ_LOG_LEVEL_ALL, _("%s(%d) PrAcc write: addr=0x%08lx data=0x%08lx\n"), __FILE__, __LINE__, (long unsigned) addr, (long unsigned) data); if (addr == UINT32_C (0xff200000)) { /* Return value from the target CPU. */ retval = data; } else { urj_error_set (URJ_ERROR_BUS, _("Unknown write addr=0x%08lx data=0x%08lx"), (long unsigned) addr, (long unsigned) data); } } else { if (addr == UINT32_C (0xff200200) && pass++) break; data = 0; if (addr >= 0xff200200 && addr < 0xff200200 + (len << 2)) { data = code[(addr - 0xff200200) >> 2]; for (i = 0; i < 32; i++) ejdata->in->data[i] = (data >> i) & 1; } urj_log (URJ_LOG_LEVEL_ALL, "%s(%d) PrAcc read: addr=0x%08lx data=0x%08lx\n", __FILE__, __LINE__, (long unsigned) addr, (long unsigned) data); urj_tap_chain_shift_data_registers (bus->chain, 0); } urj_part_set_instruction (bus->part, "EJTAG_CONTROL"); urj_tap_chain_shift_instructions (bus->chain); ejctrl->in->data[PrAcc] = 0; urj_tap_chain_shift_data_registers (bus->chain, 0); }
/** * low level dma read operation * */ static unsigned int ejtag_dma_read (urj_bus_t *bus, unsigned int addr, int sz) { static urj_data_register_t *ejctrl = NULL; static urj_data_register_t *ejaddr = NULL; static urj_data_register_t *ejdata = NULL; int i = 0; int timeout = 5; unsigned int ret; if (ejctrl == NULL) ejctrl = urj_part_find_data_register (bus->part, "EJCONTROL"); if (ejaddr == NULL) ejaddr = urj_part_find_data_register (bus->part, "EJADDRESS"); if (ejdata == NULL) ejdata = urj_part_find_data_register (bus->part, "EJDATA"); urj_part_set_instruction (bus->part, "EJTAG_ADDRESS"); urj_tap_chain_shift_instructions (bus->chain); for (i = 0; i < 32; i++) ejaddr->in->data[i] = (addr >> i) & 1; urj_tap_chain_shift_data_registers (bus->chain, 0); /* Push the address to read */ urj_log (URJ_LOG_LEVEL_COMM, "Wrote to ejaddr->in =%s %08lX\n", urj_tap_register_get_string (ejaddr->in), (long unsigned) reg_value (ejaddr->in)); urj_part_set_instruction (bus->part, "EJTAG_CONTROL"); urj_tap_chain_shift_instructions (bus->chain); urj_tap_register_fill (ejctrl->in, 0); ejctrl->in->data[PrAcc] = 1; // Processor access ejctrl->in->data[ProbEn] = 1; ejctrl->in->data[DmaAcc] = 1; // DMA operation request */ ejctrl->in->data[DstRt] = 1; if (sz) ejctrl->in->data[sz] = 1; // Size : can be WORD/HALFWORD or nothing for byte ejctrl->in->data[DmaRwn] = 1; // This is a read urj_tap_chain_shift_data_registers (bus->chain, 0); /* Do the operation */ urj_log (URJ_LOG_LEVEL_ALL, "Wrote to ejctrl->in =%s %08lX\n", urj_tap_register_get_string (ejctrl->in), (long unsigned) reg_value (ejctrl->in)); do { urj_part_set_instruction (bus->part, "EJTAG_CONTROL"); urj_tap_chain_shift_instructions (bus->chain); urj_tap_register_fill (ejctrl->in, 0); ejctrl->in->data[PrAcc] = 1; ejctrl->in->data[ProbEn] = 1; ejctrl->in->data[DmaAcc] = 1; urj_tap_chain_shift_data_registers (bus->chain, 1); urj_log (URJ_LOG_LEVEL_ALL, "Wrote to ejctrl->in =%s %08lX\n", urj_tap_register_get_string (ejctrl->in), (long unsigned) reg_value (ejctrl->in)); urj_log (URJ_LOG_LEVEL_ALL, "Read from ejctrl->out =%s %08lX\n", urj_tap_register_get_string (ejctrl->out), (long unsigned) reg_value (ejctrl->out)); timeout--; if (!timeout) break; } while (ejctrl->out->data[DstRt] == 1); // This flag tell us the processor has completed the op urj_part_set_instruction (bus->part, "EJTAG_DATA"); urj_tap_chain_shift_instructions (bus->chain); urj_tap_register_fill (ejdata->in, 0); urj_tap_chain_shift_data_registers (bus->chain, 1); ret = reg_value (ejdata->out); urj_log (URJ_LOG_LEVEL_COMM, "Read from ejdata->out(%c) =%s %08lX\n", siz_ (sz), urj_tap_register_get_string (ejdata->out), (long unsigned) reg_value (ejdata->out)); urj_part_set_instruction (bus->part, "EJTAG_CONTROL"); urj_tap_chain_shift_instructions (bus->chain); urj_tap_register_fill (ejctrl->in, 0); ejctrl->in->data[PrAcc] = 1; ejctrl->in->data[ProbEn] = 1; urj_tap_chain_shift_data_registers (bus->chain, 1); // Disable DMA, reset state to previous one. urj_log (URJ_LOG_LEVEL_ALL, "Wrote to ejctrl->in =%s %08lX\n", urj_tap_register_get_string (ejctrl->in), (long unsigned) reg_value (ejctrl->in)); urj_log (URJ_LOG_LEVEL_ALL, "Read from ejctrl->out =%s %08lX\n", urj_tap_register_get_string (ejctrl->out), (long unsigned) reg_value(ejctrl->out)); if (ejctrl->out->data[Derr] == 1) { // Check for DMA error, i.e. incorrect address urj_error_set (URJ_ERROR_BUS_DMA, _("dma read (dma transaction failed)")); } switch (sz) { case DMA_HALFWORD: if (addr & 2) ret = (ret >> 16) & 0xffff; else ret = ret & 0xffff; break; case DMA_BYTE: if ((addr & 3) == 3) ret = (ret >> 24) & 0xff; else if ((addr & 3) == 2)
/** * low-level dma write * */ static void ejtag_dma_write (urj_bus_t *bus, unsigned int addr, unsigned int data, int sz) { static urj_data_register_t *ejctrl = NULL; static urj_data_register_t *ejaddr = NULL; static urj_data_register_t *ejdata = NULL; int i = 0; int timeout = 5; if (ejctrl == NULL) ejctrl = urj_part_find_data_register (bus->part, "EJCONTROL"); if (ejaddr == NULL) ejaddr = urj_part_find_data_register (bus->part, "EJADDRESS"); if (ejdata == NULL) ejdata = urj_part_find_data_register (bus->part, "EJDATA"); switch (sz) { /* Fill the other bytes with copy of the current */ case DMA_BYTE: data &= 0xff; data |= (data << 8) | (data << 16) | (data << 24); break; case DMA_HALFWORD: data &= 0xffff; data |= (data << 16); break; default: break; } urj_part_set_instruction (bus->part, "EJTAG_ADDRESS"); urj_tap_chain_shift_instructions (bus->chain); for (i = 0; i < 32; i++) ejaddr->in->data[i] = (addr >> i) & 1; urj_tap_chain_shift_data_registers (bus->chain, 0); /* Push the address to write */ urj_log (URJ_LOG_LEVEL_COMM, "Wrote to ejaddr->in =%s %08lX\n", urj_tap_register_get_string (ejaddr->in), (long unsigned) reg_value (ejaddr->in)); urj_part_set_instruction (bus->part, "EJTAG_DATA"); urj_tap_chain_shift_instructions (bus->chain); for (i = 0; i < 32; i++) ejdata->in->data[i] = (data >> i) & 1; urj_tap_chain_shift_data_registers (bus->chain, 0); /* Push the data to write */ urj_log (URJ_LOG_LEVEL_COMM, "Wrote to edata->in(%c) =%s %08lX\n", siz_ (sz), urj_tap_register_get_string (ejdata->in), (long unsigned) reg_value (ejdata->in)); urj_part_set_instruction (bus->part, "EJTAG_CONTROL"); urj_tap_chain_shift_instructions (bus->chain); urj_tap_register_fill (ejctrl->in, 0); ejctrl->in->data[PrAcc] = 1; // Processor access ejctrl->in->data[ProbEn] = 1; ejctrl->in->data[DmaAcc] = 1; // DMA operation request */ ejctrl->in->data[DstRt] = 1; if (sz) ejctrl->in->data[sz] = 1; // Size : can be WORD/HALFWORD or nothing for byte urj_tap_chain_shift_data_registers (bus->chain, 0); /* Do the operation */ urj_log (URJ_LOG_LEVEL_ALL, "Wrote to ejctrl->in =%s %08lX\n", urj_tap_register_get_string (ejctrl->in), (long unsigned) reg_value (ejctrl->in)); do { urj_part_set_instruction (bus->part, "EJTAG_CONTROL"); urj_tap_chain_shift_instructions (bus->chain); urj_tap_register_fill (ejctrl->in, 0); ejctrl->in->data[PrAcc] = 1; ejctrl->in->data[ProbEn] = 1; ejctrl->in->data[DmaAcc] = 1; urj_tap_chain_shift_data_registers (bus->chain, 1); timeout--; if (!timeout) break; } while (ejctrl->out->data[DstRt] == 1); // This flag tell us the processor has completed the op urj_part_set_instruction (bus->part, "EJTAG_CONTROL"); urj_tap_chain_shift_instructions (bus->chain); urj_tap_register_fill (ejctrl->in, 0); ejctrl->in->data[PrAcc] = 1; ejctrl->in->data[ProbEn] = 1; urj_tap_chain_shift_data_registers (bus->chain, 1); // Disable DMA, reset state to previous one. if (ejctrl->out->data[Derr] == 1) { // Check for DMA error, i.e. incorrect address urj_error_set (URJ_ERROR_BUS_DMA, _("dma write (dma transaction failed)")); } return; }