📄 xpc.c
字号:
r = xpcu_common_init( cable ); if (r<0) return r; cable->params = malloc(sizeof(xpc_cable_params_t)); if(cable->params == NULL) r = -1; xpcu = ((libusb_param_t*)(cable->link.usb->params))->handle; if (r>=0) r = xpcu_request_28(xpcu, 0x11); if (r>=0) r = xpcu_output_enable(xpcu, 1); if (r>=0) r = xpcu_shift(xpcu, 0xA6, 2, 2, zero, 0, NULL); if (r>=0) r = xpcu_request_28(xpcu, 0x12); if (r<0) { usb_close(xpcu); free(cable->params); cable->params = NULL; } return r;}/* ---------------------------------------------------------------------- */static voidxpc_ext_done( cable_t *cable ){ struct usb_dev_handle *xpcu; xpcu = ((libusb_param_t*)(cable->link.usb->params))->handle; xpcu_output_enable(xpcu, 0); generic_usbconn_done( cable );}/* ---------------------------------------------------------------------- */static voidxpc_ext_free( cable_t *cable ){ if(cable->params) { free(cable->params); cable->params = NULL; } generic_usbconn_free( cable );}/* ---------------------------------------------------------------------- */#define PROG 3#define TCK 2#define TMS 1#define TDI 0#define TDO 0static voidxpc_clock( cable_t *cable, int tms, int tdi, int n ){ int i; struct usb_dev_handle *xpcu; xpcu = ((libusb_param_t*)(cable->link.usb->params))->handle; tms = tms ? (1<<TMS) : 0; tdi = tdi ? (1<<TDI) : 0; if( xpcu_write_gpio(xpcu, (1<<PROG) | (0<<TCK) | tms | tdi)>=0) { cable_wait( cable ); for (i = 0; i < n; i++) { xpcu_write_gpio(xpcu, (1<<PROG) | (1<<TCK) | tms | tdi); cable_wait( cable ); xpcu_write_gpio(xpcu, (1<<PROG) | (0<<TCK) | tms | tdi); cable_wait( cable ); } }}/* ---------------------------------------------------------------------- */static intxpc_get_tdo( cable_t *cable ){ unsigned char d; struct usb_dev_handle *xpcu; xpcu = ((libusb_param_t*)(cable->link.usb->params))->handle; xpcu_read_gpio(xpcu, &d); return (d&(1<<TDO))?1:0;}/* ---------------------------------------------------------------------- */static intxpc_set_trst( cable_t *cable, int trst ){ return 1;}/* ---------------------------------------------------------------------- */static voidxpc_ext_clock( cable_t *cable, int tms, int tdi, int n ){ int i; uint8_t tdo[2]; uint8_t clock[2]; struct usb_dev_handle *xpcu; clock[0] = (tms?0x10:0) | (tdi?0x01:0); clock[1] = 0x11; /* clock'n read */ xpcu = ((libusb_param_t*)(cable->link.usb->params))->handle; for(i=0;i<n;i++) xpcu_shift(xpcu, 0xA6, 1, 2, clock, 2, tdo); last_tdo = tdo[1] ? 1:0; // ((xpc_cable_params_t*)(cable->params))->last_tdo = tdo[1] ? 1:0;}/* ---------------------------------------------------------------------- */static intxpc_ext_get_tdo( cable_t *cable ){ return last_tdo; // return ((xpc_cable_params_t*)(cable->params))->last_tdo;}/* ---------------------------------------------------------------------- *//* 16-bit words. More than 4 currently leads to bit errors; 13 to serious problems */#define XPC_A6_CHUNKSIZE 4typedef struct{ cable_t *cable; struct usb_dev_handle *xpcu; int in_bits; int out_bits; int out_done; uint8_t *out; uint8_t buf[XPC_A6_CHUNKSIZE*2];}xpc_ext_transfer_state_t;/* ---------------------------------------------------------------------- */static intxpcu_do_ext_transfer( xpc_ext_transfer_state_t *xts ){ int r; int in_len, out_len; // int last_tdo; in_len = 2 * (xts->in_bits >> 2); if ((xts->in_bits & 3) != 0) in_len += 2; out_len = 2 * (xts->out_bits >> 4); if ((xts->out_bits & 15) != 0) out_len += 2; if(xts->out != NULL) { r = xpcu_shift (xts->xpcu, 0xA6, xts->in_bits, in_len, xts->buf, out_len, xts->buf); } else { r = xpcu_shift (xts->xpcu, 0xA6, xts->in_bits, in_len, xts->buf, 0, NULL); } if(r >= 0 && xts->out_bits > 0) { int out_idx = 0; int out_rem = xts->out_bits; while (out_rem > 0) { uint32_t mask, rxw; rxw = (xts->buf[out_idx+1]<<8) | xts->buf[out_idx]; /* In the last (incomplete) word, the data isn't shifted completely to LSB */ mask = (out_rem >= 16) ? 1 : (1<<(16 - out_rem)); while(mask <= 32768 && out_rem > 0) { last_tdo = (rxw & mask) ? 1 : 0; xts->out[xts->out_done] = last_tdo; xts->out_done++; mask <<= 1; out_rem--; } out_idx += 2; } } xts->in_bits = 0; xts->out_bits = 0; // ((xpc_cable_params_t*)(xts->cable->params))->last_tdo = last_tdo; return r;}/* ---------------------------------------------------------------------- */static voidxpcu_add_bit_for_ext_transfer( xpc_ext_transfer_state_t *xts, char in, char is_real ){ int bit_idx = (xts->in_bits & 3); int buf_idx = (xts->in_bits - bit_idx) >> 1; if(bit_idx == 0) { xts->buf[buf_idx] = 0; xts->buf[buf_idx+1] = 0; }; xts->in_bits++; if(is_real) { if(in) xts->buf[buf_idx] |= (0x01<<bit_idx); if(xts->out) { xts->buf[buf_idx+1] |= (0x11<<bit_idx); xts->out_bits++; } else { xts->buf[buf_idx+1] |= (0x01<<bit_idx); } }} /* ---------------------------------------------------------------------- */static intxpc_ext_transfer( cable_t *cable, int len, char *in, char *out ){ int i,j; xpc_ext_transfer_state_t xts;#if VERBOSE printf("---\n"); printf("transfer size %d, %s output\n", len, (out!=NULL) ? "with" : "without"); printf("tdi: "); for(i=0;i<len;i++) printf("%c", in[i]?'1':'0'); printf("\n");#endif xts.xpcu = ((libusb_param_t*)(cable->link.usb->params))->handle; xts.out = (uint8_t*)out; xts.in_bits = 0; xts.out_bits = 0; xts.out_done = 0; xts.cable = cable; for(i=0,j=0; i<len && j>=0; i++) { xpcu_add_bit_for_ext_transfer( &xts, in[i], 1 ); if(xts.in_bits == (4*XPC_A6_CHUNKSIZE - 1)) { j = xpcu_do_ext_transfer( &xts ); } }; if(xts.in_bits > 0 && j>=0) { /* CPLD doesn't like multiples of 4; add one dummy bit */ if((xts.in_bits & 3) == 0) { xpcu_add_bit_for_ext_transfer( &xts, 0, 0 ); } j = xpcu_do_ext_transfer( &xts ); } return j;}/* ---------------------------------------------------------------------- */cable_driver_t xpc_int_cable_driver = { "xpc_int", N_("Xilinx Platform Cable USB internal chain"), generic_usbconn_connect, generic_disconnect, generic_usbconn_free, xpc_int_init, generic_usbconn_done, generic_set_frequency, xpc_clock, xpc_get_tdo, generic_transfer, xpc_set_trst, generic_get_trst, generic_flush_using_transfer, generic_usbconn_help};usbconn_cable_t usbconn_cable_xpc_int = { "xpc_int", /* cable name */ NULL, /* string pattern, not used */ "libusb", /* usbconn driver */ 0x03FD, /* VID (Xilinx) */ 0x0008 /* PID (8) */};cable_driver_t xpc_ext_cable_driver = { "xpc_ext", N_("Xilinx Platform Cable USB external chain"), generic_usbconn_connect, generic_disconnect, xpc_ext_free, xpc_ext_init, xpc_ext_done, generic_set_frequency, xpc_ext_clock, xpc_ext_get_tdo, xpc_ext_transfer, xpc_set_trst, generic_get_trst, generic_flush_using_transfer, generic_usbconn_help};usbconn_cable_t usbconn_cable_xpc_ext = { "xpc_ext", /* cable name */ NULL, /* string pattern, not used */ "libusb", /* usbconn driver */ 0x03FD, /* VID (Xilinx) */ 0x0008 /* PID (8) */};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -