X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fjtag%2Fdrivers%2FOpenULINK%2Fsrc%2Fjtag.c;h=812d4f73a8cdfbbb0aa0163fb30900ad22373011;hp=cf126ed274344859986e98155e0391630adb8fbe;hb=6446dbaacbf7c0607ea571ed7f5a4f32745544eb;hpb=3c3f3c42472faa0414a8096133cb9b8a9ab37c86 diff --git a/src/jtag/drivers/OpenULINK/src/jtag.c b/src/jtag/drivers/OpenULINK/src/jtag.c index cf126ed274..812d4f73a8 100644 --- a/src/jtag/drivers/OpenULINK/src/jtag.c +++ b/src/jtag/drivers/OpenULINK/src/jtag.c @@ -26,10 +26,16 @@ #include -/** Delay value for SCAN operations with less than maximum TCK frequency */ -u8 delay_scan = 0; +/** Delay value for SCAN_IN operations with less than maximum TCK frequency */ +u8 delay_scan_in = 0; -/** Delay value for CLOCK_TCK operations */ +/** Delay value for SCAN_OUT operations with less than maximum TCK frequency */ +u8 delay_scan_out = 0; + +/** Delay value for SCAN_IO operations with less than maximum TCK frequency */ +u8 delay_scan_io = 0; + +/** Delay value for CLOCK_TCK operations with less than maximum frequency */ u8 delay_tck = 0; /** Delay value for CLOCK_TMS operations with less than maximum frequency */ @@ -41,6 +47,8 @@ u8 delay_tms = 0; * Dummy data is shifted into the JTAG chain via TDI, TDO data is sampled and * stored in the EP2 IN buffer. * + * Maximum achievable TCK frequency is 182 kHz for ULINK clocked at 24 MHz. + * * @param out_offset offset in OUT2BUF where payload data starts */ void jtag_scan_in(u8 out_offset, u8 in_offset) @@ -72,8 +80,8 @@ void jtag_scan_in(u8 out_offset, u8 in_offset) for (j = 0; j < 8; j++) { OUTB = outb_buffer; /* TCK changes here */ - OUTB = (outb_buffer | PIN_TCK); tdo_data = tdo_data >> 1; + OUTB = (outb_buffer | PIN_TCK); if (GET_TDO()) { tdo_data |= 0x80; @@ -96,8 +104,8 @@ void jtag_scan_in(u8 out_offset, u8 in_offset) } OUTB = outb_buffer; /* TCK change here */ - OUTB = (outb_buffer | PIN_TCK); tdo_data = tdo_data >> 1; + OUTB = (outb_buffer | PIN_TCK); if (GET_TDO()) { tdo_data |= 0x80; @@ -114,6 +122,93 @@ void jtag_scan_in(u8 out_offset, u8 in_offset) } } +/** + * Perform JTAG SCAN-IN operation at variable TCK frequency. + * + * Dummy data is shifted into the JTAG chain via TDI, TDO data is sampled and + * stored in the EP2 IN buffer. + * + * Maximum achievable TCK frequency is 113 kHz for ULINK clocked at 24 MHz. + * + * @param out_offset offset in OUT2BUF where payload data starts + */ +void jtag_slow_scan_in(u8 out_offset, u8 in_offset) +{ + u8 scan_size_bytes, bits_last_byte; + u8 tms_count_start, tms_count_end; + u8 tms_sequence_start, tms_sequence_end; + u8 tdo_data, i, j, k; + + u8 outb_buffer; + + /* Get parameters from OUT2BUF */ + scan_size_bytes = OUT2BUF[out_offset]; + bits_last_byte = OUT2BUF[out_offset + 1]; + tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F; + tms_count_end = OUT2BUF[out_offset + 2] & 0x0F; + tms_sequence_start = OUT2BUF[out_offset + 3]; + tms_sequence_end = OUT2BUF[out_offset + 4]; + + if (tms_count_start > 0) { + jtag_slow_clock_tms(tms_count_start, tms_sequence_start); + } + + outb_buffer = OUTB & ~(PIN_TDI | PIN_TCK | PIN_TMS); + + /* Shift all bytes except the last byte */ + for (i = 0; i < scan_size_bytes - 1; i++) { + tdo_data = 0; + + for (j = 0; j < 8; j++) { + OUTB = outb_buffer; /* TCK changes here */ + for (k = 0; k < delay_scan_in; k++); + tdo_data = tdo_data >> 1; + + OUTB = (outb_buffer | PIN_TCK); + for (k = 0; k < delay_scan_in; k++); + + if (GET_TDO()) { + tdo_data |= 0x80; + } + } + + /* Copy TDO data to IN2BUF */ + IN2BUF[i + in_offset] = tdo_data; + } + + tdo_data = 0; + + /* Shift the last byte */ + for (j = 0; j < bits_last_byte; j++) { + /* Assert TMS signal if requested and this is the last bit */ + if ((j == bits_last_byte - 1) && (tms_count_end > 0)) { + outb_buffer |= PIN_TMS; + tms_count_end--; + tms_sequence_end = tms_sequence_end >> 1; + } + + OUTB = outb_buffer; /* TCK change here */ + for (k = 0; k < delay_scan_in; k++); + tdo_data = tdo_data >> 1; + + OUTB = (outb_buffer | PIN_TCK); + for (k = 0; k < delay_scan_in; k++); + + if (GET_TDO()) { + tdo_data |= 0x80; + } + } + tdo_data = tdo_data >> (8 - bits_last_byte); + + /* Copy TDO data to IN2BUF */ + IN2BUF[i + in_offset] = tdo_data; + + /* Move to correct end state */ + if (tms_count_end > 0) { + jtag_slow_clock_tms(tms_count_end, tms_sequence_end); + } +} + /** * Perform JTAG SCAN-OUT operation at maximum TCK frequency. * @@ -121,6 +216,8 @@ void jtag_scan_in(u8 out_offset, u8 in_offset) * data is not sampled. * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state. * + * Maximum achievable TCK frequency is 142 kHz for ULINK clocked at 24 MHz. + * * @param out_offset offset in OUT2BUF where payload data starts */ void jtag_scan_out(u8 out_offset) @@ -193,6 +290,93 @@ void jtag_scan_out(u8 out_offset) } } +/** + * Perform JTAG SCAN-OUT operation at maximum TCK frequency. + * + * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO + * data is not sampled. + * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state. + * + * Maximum achievable TCK frequency is 97 kHz for ULINK clocked at 24 MHz. + * + * @param out_offset offset in OUT2BUF where payload data starts + */ +void jtag_slow_scan_out(u8 out_offset) +{ + u8 scan_size_bytes, bits_last_byte; + u8 tms_count_start, tms_count_end; + u8 tms_sequence_start, tms_sequence_end; + u8 tdi_data, i, j, k; + + u8 outb_buffer; + + /* Get parameters from OUT2BUF */ + scan_size_bytes = OUT2BUF[out_offset]; + bits_last_byte = OUT2BUF[out_offset + 1]; + tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F; + tms_count_end = OUT2BUF[out_offset + 2] & 0x0F; + tms_sequence_start = OUT2BUF[out_offset + 3]; + tms_sequence_end = OUT2BUF[out_offset + 4]; + + if (tms_count_start > 0) { + jtag_slow_clock_tms(tms_count_start, tms_sequence_start); + } + + outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS); + + /* Shift all bytes except the last byte */ + for (i = 0; i < scan_size_bytes - 1; i++) { + tdi_data = OUT2BUF[i + out_offset + 5]; + + for (j = 0; j < 8; j++) { + if (tdi_data & 0x01) { + outb_buffer |= PIN_TDI; + } + else { + outb_buffer &= ~PIN_TDI; + } + + OUTB = outb_buffer; /* TDI and TCK change here */ + for (k = 0; k < delay_scan_out; k++); + tdi_data = tdi_data >> 1; + + OUTB = (outb_buffer | PIN_TCK); + for (k = 0; k < delay_scan_out; k++); + } + } + + tdi_data = OUT2BUF[i + out_offset + 5]; + + /* Shift the last byte */ + for (j = 0; j < bits_last_byte; j++) { + if (tdi_data & 0x01) { + outb_buffer |= PIN_TDI; + } + else { + outb_buffer &= ~PIN_TDI; + } + + /* Assert TMS signal if requested and this is the last bit */ + if ((j == bits_last_byte - 1) && (tms_count_end > 0)) { + outb_buffer |= PIN_TMS; + tms_count_end--; + tms_sequence_end = tms_sequence_end >> 1; + } + + OUTB = outb_buffer; /* TDI and TCK change here */ + for (k = 0; k < delay_scan_out; k++); + tdi_data = tdi_data >> 1; + + OUTB = (outb_buffer | PIN_TCK); + for (k = 0; k < delay_scan_out; k++); + } + + /* Move to correct end state */ + if (tms_count_end > 0) { + jtag_slow_clock_tms(tms_count_end, tms_sequence_end); + } +} + /** * Perform bidirectional JTAG SCAN operation at maximum TCK frequency. * @@ -200,6 +384,8 @@ void jtag_scan_out(u8 out_offset) * data is sampled and stored in the EP2 IN buffer. * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state. * + * Maximum achievable TCK frequency is 100 kHz for ULINK clocked at 24 MHz. + * * @param out_offset offset in OUT2BUF where payload data starts */ void jtag_scan_io(u8 out_offset, u8 in_offset) @@ -291,27 +477,155 @@ void jtag_scan_io(u8 out_offset, u8 in_offset) } } +/** + * Perform bidirectional JTAG SCAN operation at maximum TCK frequency. + * + * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO + * data is sampled and stored in the EP2 IN buffer. + * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state. + * + * Maximum achievable TCK frequency is 78 kHz for ULINK clocked at 24 MHz. + * + * @param out_offset offset in OUT2BUF where payload data starts + */ +void jtag_slow_scan_io(u8 out_offset, u8 in_offset) +{ + u8 scan_size_bytes, bits_last_byte; + u8 tms_count_start, tms_count_end; + u8 tms_sequence_start, tms_sequence_end; + u8 tdi_data, tdo_data, i, j, k; + + u8 outb_buffer; + + /* Get parameters from OUT2BUF */ + scan_size_bytes = OUT2BUF[out_offset]; + bits_last_byte = OUT2BUF[out_offset + 1]; + tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F; + tms_count_end = OUT2BUF[out_offset + 2] & 0x0F; + tms_sequence_start = OUT2BUF[out_offset + 3]; + tms_sequence_end = OUT2BUF[out_offset + 4]; + + if (tms_count_start > 0) { + jtag_slow_clock_tms(tms_count_start, tms_sequence_start); + } + + outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS); + + /* Shift all bytes except the last byte */ + for (i = 0; i < scan_size_bytes - 1; i++) { + tdi_data = OUT2BUF[i + out_offset + 5]; + tdo_data = 0; + + for (j = 0; j < 8; j++) { + if (tdi_data & 0x01) { + outb_buffer |= PIN_TDI; + } + else { + outb_buffer &= ~PIN_TDI; + } + + OUTB = outb_buffer; /* TDI and TCK change here */ + for (k = 0; k < delay_scan_io; k++); + tdi_data = tdi_data >> 1; + + OUTB = (outb_buffer | PIN_TCK); + for (k = 0; k < delay_scan_io; k++); + tdo_data = tdo_data >> 1; + + if (GET_TDO()) { + tdo_data |= 0x80; + } + } + + /* Copy TDO data to IN2BUF */ + IN2BUF[i + in_offset] = tdo_data; + } + + tdi_data = OUT2BUF[i + out_offset + 5]; + tdo_data = 0; + + /* Shift the last byte */ + for (j = 0; j < bits_last_byte; j++) { + if (tdi_data & 0x01) { + outb_buffer |= PIN_TDI; + } + else { + outb_buffer &= ~PIN_TDI; + } + + /* Assert TMS signal if requested and this is the last bit */ + if ((j == bits_last_byte - 1) && (tms_count_end > 0)) { + outb_buffer |= PIN_TMS; + tms_count_end--; + tms_sequence_end = tms_sequence_end >> 1; + } + + OUTB = outb_buffer; /* TDI and TCK change here */ + for (k = 0; k < delay_scan_io; k++); + tdi_data = tdi_data >> 1; + + OUTB = (outb_buffer | PIN_TCK); + for (k = 0; k < delay_scan_io; k++); + tdo_data = tdo_data >> 1; + + if (GET_TDO()) { + tdo_data |= 0x80; + } + } + tdo_data = tdo_data >> (8 - bits_last_byte); + + /* Copy TDO data to IN2BUF */ + IN2BUF[i + in_offset] = tdo_data; + + /* Move to correct end state */ + if (tms_count_end > 0) { + jtag_slow_clock_tms(tms_count_end, tms_sequence_end); + } +} + /** * Generate TCK clock cycles. * + * Maximum achievable TCK frequency is 375 kHz for ULINK clocked at 24 MHz. + * * @param count number of TCK clock cyclces to generate. */ void jtag_clock_tck(u16 count) { u16 i; - u8 j; + u8 outb_buffer = OUTB & ~(PIN_TCK); for ( i = 0; i < count; i++ ) { - SET_TCK_LOW(); - for(j = 0; j < delay_tck; j++); + OUTB = outb_buffer; + OUTB = outb_buffer | PIN_TCK; + } +} + +/** + * Generate TCK clock cycles at variable frequency. + * + * Maximum achieveable TCK frequency is 166.6 kHz for ULINK clocked at 24 MHz. + * + * @param count number of TCK clock cyclces to generate. + */ +void jtag_slow_clock_tck(u16 count) +{ + u16 i; + u8 j; + u8 outb_buffer = OUTB & ~(PIN_TCK); - SET_TCK_HIGH(); - for(j = 0; j < delay_tck; j++); + for ( i = 0; i < count; i++ ) { + OUTB = outb_buffer; + for (j = 0; j < delay_tck; j++); + OUTB = outb_buffer | PIN_TCK; + for (j = 0; j < delay_tck; j++); } } /** - * Perform TAP-FSM state transitions at maximum TCK frequency. + * Perform TAP FSM state transitions at maximum TCK frequency. + * + * Maximum achievable TCK frequency is 176 kHz for ULINK clocked at 24 MHz. * * @param count the number of state transitions to perform. * @param sequence the TMS pin levels for each state transition, starting with @@ -319,11 +633,9 @@ void jtag_clock_tck(u16 count) */ void jtag_clock_tms(u8 count, u8 sequence) { - volatile u8 outb_buffer; + u8 outb_buffer = OUTB & ~(PIN_TCK); u8 i; - outb_buffer = OUTB & ~(PIN_TCK); - for ( i = 0; i < count; i++ ) { /* Set TMS pin according to sequence parameter */ if ( sequence & 0x1 ) { @@ -342,13 +654,32 @@ void jtag_clock_tms(u8 count, u8 sequence) /** * Perform TAP-FSM state transitions at less than maximum TCK frequency. * + * Maximum achievable TCK frequency is 117 kHz for ULINK clocked at 24 MHz. + * * @param count the number of state transitions to perform. * @param sequence the TMS pin levels for each state transition, starting with * the least-significant bit. */ void jtag_slow_clock_tms(u8 count, u8 sequence) { + u8 outb_buffer = OUTB & ~(PIN_TCK); + u8 i, j; + + for (i = 0; i < count; i++) { + /* Set TMS pin according to sequence parameter */ + if ( sequence & 0x1 ) { + outb_buffer |= PIN_TMS; + } + else { + outb_buffer &= ~PIN_TMS; + } + OUTB = outb_buffer; + for (j = 0; j < delay_tms; j++); + sequence = sequence >> 1; + OUTB = outb_buffer | PIN_TCK; + for (j = 0; j < delay_tms; j++); + } } /** @@ -402,13 +733,18 @@ void jtag_set_signals(u8 low, u8 high) /** * Configure TCK delay parameters. * - * @param scan number of delay cycles in shift operations. + * @param scan_in number of delay cycles in scan_in operations. + * @param scan_out number of delay cycles in scan_out operations. + * @param scan_io number of delay cycles in scan_io operations. * @param tck number of delay cycles in clock_tck operations. * @param tms number of delay cycles in clock_tms operations. */ -void jtag_configure_tck_delay(u8 scan, u8 tck, u8 tms) +void jtag_configure_tck_delay(u8 scan_in, u8 scan_out, u8 scan_io, u8 tck, + u8 tms) { - delay_scan = scan; + delay_scan_in = scan_in; + delay_scan_out = scan_out; + delay_scan_io = scan_io; delay_tck = tck; delay_tms = tms; }