📄 rlink.c
字号:
tdi_mask = 1; } } } } if(extra_bits && (type != SCAN_OUT)) { /* Schedule any extra bits into the DTC command buffer */ /* make sure there's room for stop, byte op, and one byte */ if( (dtc_queue.cmd_index >= sizeof(dtc_queue.cmd_buffer) - (1 + 1 + 1)) || (dtc_queue.reply_index >= USB_EP2IN_SIZE - (1)) ) { dtc_queue_run(); } if(dtc_queue_enqueue_reply( type, buffer, scan_size, tdi_bit_offset, extra_bits, cmd ) == NULL) { LOG_ERROR("enqueuing DTC reply entry: %s\n", strerror(errno)); exit(1); } tdi_bit_offset += extra_bits; if(type == SCAN_IN) { dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = DTC_CMD_SHIFT_TDO_BYTES(1); } else { dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = DTC_CMD_SHIFT_TDIO_BITS(extra_bits); 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++; tdi_mask = 1; } } dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = x; } dtc_queue.reply_index++; } /* Schedule the last bit into the DTC command buffer */ { /* make sure there's room for stop, and bit pair command */ if( (dtc_queue.cmd_index >= sizeof(dtc_queue.cmd_buffer) - (1 + 1)) || (dtc_queue.reply_index >= USB_EP2IN_SIZE - (1)) ) { dtc_queue_run(); } if(type == SCAN_OUT) { dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = DTC_CMD_SHIFT_TMS_TDI_BIT_PAIR(1, (*tdi_p & tdi_mask), 0); } else { if(dtc_queue_enqueue_reply( type, buffer, scan_size, tdi_bit_offset, 1, cmd ) == NULL) { LOG_ERROR("enqueuing DTC reply entry: %s\n", strerror(errno)); exit(1); } 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(); return(0);}staticint rlink_execute_queue(void){ jtag_command_t *cmd = jtag_command_queue; /* currently processed command */ int scan_size; enum scan_type type; u8 *buffer; int retval, tmp_retval; /* return ERROR_OK, unless something goes wrong */ retval = ERROR_OK;#ifndef AUTOMATIC_BUSY_LED /* turn LED on */ ep1_generic_commandl(pHDev, 2, EP1_CMD_SET_PORTD_LEDS, ~(ST7_PD_NBUSY_LED) );#endif while (cmd) { switch (cmd->type) { case JTAG_END_STATE: case JTAG_RUNTEST: case JTAG_STATEMOVE: case JTAG_PATHMOVE: case JTAG_SCAN: break; default: /* some events, such as resets, need a queue flush to ensure consistency */ tap_state_queue_run(); dtc_queue_run(); break; } switch (cmd->type) { case JTAG_END_STATE:#ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("end_state: %i", cmd->cmd.end_state->end_state);#endif if (cmd->cmd.end_state->end_state != -1) rlink_end_state(cmd->cmd.end_state->end_state); break; case JTAG_RESET:#ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);#endif if ((cmd->cmd.reset->trst == 1) || (cmd->cmd.reset->srst && (jtag_reset_config & RESET_SRST_PULLS_TRST))) { cur_state = TAP_RESET; } rlink_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); break; case JTAG_RUNTEST:#ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);#endif if (cmd->cmd.runtest->end_state != -1) rlink_end_state(cmd->cmd.runtest->end_state); rlink_runtest(cmd->cmd.runtest->num_cycles); break; case JTAG_STATEMOVE:#ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);#endif if (cmd->cmd.statemove->end_state != -1) rlink_end_state(cmd->cmd.statemove->end_state); rlink_state_move(); break; case JTAG_PATHMOVE:#ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);#endif rlink_path_move(cmd->cmd.pathmove); break; case JTAG_SCAN:#ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("%s scan end in %i", (cmd->cmd.scan->ir_scan) ? "IR" : "DR", cmd->cmd.scan->end_state);#endif if (cmd->cmd.scan->end_state != -1) rlink_end_state(cmd->cmd.scan->end_state); scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer); type = jtag_scan_type(cmd->cmd.scan); if(rlink_scan(cmd, type, buffer, scan_size) != ERROR_OK) { retval = ERROR_FAIL; } break; case JTAG_SLEEP:#ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("sleep %i", cmd->cmd.sleep->us);#endif jtag_sleep(cmd->cmd.sleep->us); break; default: LOG_ERROR("BUG: unknown JTAG command type encountered"); exit(-1); } cmd = cmd->next; } /* Flush the DTC queue to make sure any pending reads have been done before exiting this function */ tap_state_queue_run(); tmp_retval = dtc_queue_run(); if(tmp_retval != ERROR_OK) { retval = tmp_retval; }#ifndef AUTOMATIC_BUSY_LED /* turn LED onff */ ep1_generic_commandl(pHDev, 2, EP1_CMD_SET_PORTD_LEDS, ~0 );#endif return retval;}/* Using an unindexed table because it is infrequently accessed and it is short. The table must be in order of ascending speed (and descending prescaler), as it is scanned in reverse. */staticint rlink_speed(int speed){ int i; if(speed == 0) { /* fastest speed */ speed = rlink_speed_table[rlink_speed_table_size - 1].prescaler; } for(i = rlink_speed_table_size; i--; ) { if(rlink_speed_table[i].prescaler == speed) { if(dtc_load_from_buffer(pHDev, rlink_speed_table[i].dtc, rlink_speed_table[i].dtc_size) != 0) { 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_strerror() ); exit(1); } return ERROR_OK; } } LOG_ERROR("%d is not a supported speed", speed); return(ERROR_FAIL);}staticint rlink_speed_div( int speed, int *khz) { int i; for(i = rlink_speed_table_size; i--; ) { if(rlink_speed_table[i].prescaler == speed) { *khz = rlink_speed_table[i].khz; return(ERROR_OK); } } LOG_ERROR("%d is not a supported speed", speed); return(ERROR_FAIL);}staticint rlink_khz( int khz, int *speed) { int i; if(khz == 0) { LOG_ERROR("RCLK not supported"); return ERROR_FAIL; } for(i = rlink_speed_table_size; i--; ) { if(rlink_speed_table[i].khz <= khz) { *speed = rlink_speed_table[i].prescaler; return(ERROR_OK); } } LOG_WARNING("The lowest supported JTAG speed is %d KHz", rlink_speed_table[0].khz); *speed = rlink_speed_table[0].prescaler; return(ERROR_OK);}#if 0staticinthandle_dtc_directory_command( struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { if(argc != 1) { LOG_ERROR("expected exactly one argument to rlink_dtc_directory <directory-path>"); return(ERROR_INVALID_ARGUMENTS); } printf("handle_dtc_directory_command called with \"%s\"\n", args[0]); return(ERROR_OK);}#endifstaticint rlink_register_commands(struct command_context_s *cmd_ctx){#ifdef _DEBUG_JTAG_IO_ LOG_DEBUG("rlink_register_commands called with cmd_ctx=%p\n", cmd_ctx);#endif#if 0 register_command( cmd_ctx, NULL, "rlink_dtc_directory", handle_dtc_directory_command, COMMAND_CONFIG, "The directory in which to search for DTC load images" );#endif return ERROR_OK;}staticint rlink_init(void){ struct usb_bus *busses; struct usb_bus *bus; int i, j, retries; int found=0; int success=0; u8 reply_buffer[USB_EP1IN_SIZE]; usb_init(); usb_find_busses(); usb_find_devices(); busses = usb_get_busses(); for(bus = busses; bus; bus = bus->next) { struct usb_device *dev; for(dev = bus->devices; dev; dev = dev->next) { if( (dev->descriptor.idVendor == USB_IDVENDOR) && (dev->descriptor.idProduct == USB_IDPRODUCT) ) { found = 1; LOG_DEBUG("Found device on bus.\n"); do { if( dev->descriptor.bNumConfigurations > 1 ) { LOG_ERROR("Whoops! NumConfigurations is not 1, don't know what to do...\n"); break; } if( dev->config->bNumInterfaces > 1 ) { LOG_ERROR("Whoops! NumInterfaces is not 1, don't know what to do...\n"); break; } pHDev=usb_open(dev); if( !pHDev ) LOG_ERROR ("Failed to open device.\n"); else { LOG_DEBUG("Opened device, pHDev = %p\n",pHDev); /* usb_set_configuration required under win32 */ usb_set_configuration(pHDev, dev->config[0].bConfigurationValue); retries = 3; do { i = usb_claim_interface(pHDev,0); if(i) { LOG_ERROR("usb_claim_interface: %s", usb_strerror());#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP j = usb_detach_kernel_driver_np(pHDev, 0); if(j) LOG_ERROR("detach kernel driver: %s", usb_strerror());#endif } else { LOG_DEBUG("interface claimed!\n"); break; } } while(--retries); if(!i) { if( usb_set_altinterface(pHDev,0) ) { LOG_ERROR("Failed to set interface.\n"); break; } else success=1; } } } while(0); } } } if( !found ) { LOG_ERROR("No device found on bus.\n"); exit(1); } if( !success ) { LOG_ERROR("Initialisation failed."); exit(1); } /* The device starts out in an unknown state on open. As such, result reads time out, and it's not even known whether the command was accepted. So, for this first command, we issue it repeatedly until its response doesn't time out. Also, if sending a command is going to time out, we'll find that out here. */ /* It must be possible to open the device in such a way that this special magic isn't needed, but, so far, it escapes us. */ for(i = 0; i < 5; i++) { j = ep1_generic_commandl( pHDev, 1, EP1_CMD_GET_FWREV ); if(j < USB_EP1OUT_SIZE) { LOG_ERROR("USB write error: %s", usb_strerror()); return(ERROR_FAIL); } j = usb_bulk_read( pHDev, USB_EP1IN_ADDR, (char *)reply_buffer, sizeof(reply_buffer), 200 ); if(j != -ETIMEDOUT) break; } if(j < (int)sizeof(reply_buffer)) { LOG_ERROR("USB read error: %s", usb_strerror()); return(ERROR_FAIL); } LOG_DEBUG(INTERFACE_NAME" firmware version: %d.%d.%d\n", reply_buffer[0], reply_buffer[1], reply_buffer[2]); if((reply_buffer[0] != 0) || (reply_buffer[1] != 0) || (reply_buffer[2] != 3)) { LOG_WARNING("The rlink device is not of the version that the developers have played with. It may or may not work.\n"); } /* Probe port E for adapter presence */ ep1_generic_commandl( pHDev, 16, EP1_CMD_MEMORY_WRITE, /* Drive sense pin with 0 */ ST7_PEDR >> 8, ST7_PEDR, 3, 0x00, ST7_PE_ADAPTER_SENSE_OUT, ST7_PE_ADAPTER_SENSE_OUT, EP1_CMD_MEMORY_READ, /* Read back */ ST7_PEDR >> 8, ST7_PEDR, 1, EP1_CMD_MEMORY_WRITE, /* Drive sense pin with 1 */ ST7_PEDR >> 8, ST7_PEDR, 1, ST7_PE_ADAPTER_SENSE_OUT ); usb_bulk_read( pHDev, USB_EP1IN_ADDR, (char *)reply_buffer, 1, USB_TIMEOUT_MS ); if((reply_buffer[0] & ST7_PE_ADAPTER_SENSE_IN) != 0) { LOG_WARNING("target detection problem\n"); } ep1_generic_commandl( pHDev, 11, EP1_CMD_MEMORY_READ, /* Read back */ ST7_PEDR >> 8, ST7_PEDR, 1, EP1_CMD_MEMORY_WRITE, /* float port E */ ST7_PEDR >> 8, ST7_PEDR, 3, 0x00, 0x00, 0x00 ); usb_bulk_read( pHDev, USB_EP1IN_ADDR, (char *)reply_buffer, 1, USB_TIMEOUT_MS ); if((reply_buffer[0] & ST7_PE_ADAPTER_SENSE_IN) == 0) { 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 */ ep1_generic_commandl( pHDev, 15, EP1_CMD_MEMORY_WRITE, ST7_PADDR >> 8, ST7_PADDR, 2, 0x00, 0x00, EP1_CMD_DTC_STOP, EP1_CMD_SET_PORTD_UPPER, ~(ST7_PD_NRUN_LED), 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) ); /* set LED updating mode and make sure they're unlit */ ep1_generic_commandl( pHDev, 3,#ifdef AUTOMATIC_BUSY_LED EP1_CMD_LEDUE_BUSY,#else EP1_CMD_LEDUE_NONE,#endif EP1_CMD_SET_PORTD_LEDS, ~0 ); tap_state_queue_init(); dtc_queue_init(); rlink_speed(jtag_speed); rlink_reset(0, 0); return ERROR_OK;}staticint rlink_quit(void){ /* stop DTC and make sure LEDs are off */ ep1_generic_commandl( pHDev, 6, EP1_CMD_DTC_STOP, EP1_CMD_LEDUE_NONE, EP1_CMD_SET_PORTD_LEDS, ~0, EP1_CMD_SET_PORTD_UPPER, ~0 ); usb_release_interface(pHDev,0); usb_close(pHDev); return ERROR_OK;}jtag_interface_t rlink_interface ={ .name = "rlink", .init = rlink_init, .quit = rlink_quit, .register_commands = rlink_register_commands, .speed = rlink_speed, .speed_div = rlink_speed_div, .khz = rlink_khz, .execute_queue = rlink_execute_queue,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -