JTAG ID scanning works!

This commit is contained in:
Triss 2021-09-27 17:58:53 +02:00
parent f96243eb80
commit 9ca6ae61c0
5 changed files with 150 additions and 7 deletions

View File

@ -32,6 +32,7 @@ if(FAMILY STREQUAL "rp2040")
target_sources(${PROJECT} PUBLIC target_sources(${PROJECT} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
${CMAKE_CURRENT_SOURCE_DIR}/src/pio_sbw.c ${CMAKE_CURRENT_SOURCE_DIR}/src/pio_sbw.c
${CMAKE_CURRENT_SOURCE_DIR}/src/tap.c
) )
# Example include # Example include

View File

@ -9,7 +9,9 @@
#include <hardware/gpio.h> #include <hardware/gpio.h>
#include <pico/stdlib.h> #include <pico/stdlib.h>
#include <pico/binary_info.h> #include <pico/binary_info.h>
#include "pio_sbw.h" #include "pio_sbw.h"
#include "tap.h"
void printbuf(const uint8_t* buf, size_t size) { void printbuf(const uint8_t* buf, size_t size) {
for (size_t i = 0; i < size; ++i) for (size_t i = 0; i < size; ++i)
@ -30,7 +32,7 @@ int main() {
bool s = sbw_init(); bool s = sbw_init();
printf("%s\n", s ? "inited" : "failure"); printf("%s\n", s ? "inited" : "failure");
uint8_t tdi = 0x0f, tdo = 0; /*uint8_t tdi = 0x0f, tdo = 0;
sbw_sequence(8, true, &tdi, &tdo); sbw_sequence(8, true, &tdi, &tdo);
printf("seq done, tdo=%02x\n", tdo); printf("seq done, tdo=%02x\n", tdo);
@ -49,7 +51,14 @@ int main() {
printf("doing a tclk burst now!\n"); printf("doing a tclk burst now!\n");
sbw_tclk_burst(16); sbw_tclk_burst(16);
printf("done.\n"); printf("done.\n");*/
sbw_tap_reset();
sbw_check_fuse();
uint8_t id = sbw_tap_shift_ir(0xff/*IR_BYPASS*/);
printf("JTAG ID=%02x\n", id);
return 0; return 0;
} }

View File

@ -24,24 +24,50 @@ void sbw_preinit(void) {
// TEST low for >0.025us <7us: latch on "we want SBW" signal // TEST low for >0.025us <7us: latch on "we want SBW" signal
// TEST high again for >1 us: ready to SBW // TEST high again for >1 us: ready to SBW
gpio_put(PINOUT_SBW_TCK , false); //gpio_put(PINOUT_SBW_TCK , false);
gpio_put(PINOUT_SBW_TDIO, true );
gpio_put(PINOUT_SBW_TDIO, false); gpio_put(PINOUT_SBW_TDIO, false);
gpio_set_dir(PINOUT_SBW_TCK , true); gpio_set_dir(PINOUT_SBW_TCK , true);
gpio_set_dir(PINOUT_SBW_TDIO, true); gpio_set_dir(PINOUT_SBW_TDIO, true);
gpio_set_function(PINOUT_SBW_TCK , GPIO_FUNC_SIO); gpio_set_function(PINOUT_SBW_TCK , GPIO_FUNC_SIO);
gpio_set_function(PINOUT_SBW_TDIO, GPIO_FUNC_SIO); gpio_set_function(PINOUT_SBW_TDIO, GPIO_FUNC_SIO);
// TCK, TDIO now low /*// TCK, TDIO now low
busy_wait_us_32(150); // reset debug state while keeping CPU in reset busy_wait_ms(4);//busy_wait_us_32(150); // reset debug state while keeping CPU in reset
gpio_put(PINOUT_SBW_TCK , true ); // we want a debugger gpio_put(PINOUT_SBW_TCK , true ); // we want a debugger
busy_wait_us_32(1); busy_wait_us_32(1);
gpio_put(PINOUT_SBW_TDIO, true ); // we want SBW gpio_put(PINOUT_SBW_TDIO, true ); // we want SBW
busy_wait_us_32(1); busy_wait_ms(20);//busy_wait_us_32(1);
gpio_put(PINOUT_SBW_TCK , false); // latch "we want SBW" gpio_put(PINOUT_SBW_TCK , false); // latch "we want SBW"
busy_wait_us_32(3); busy_wait_us_32(3);
gpio_put(PINOUT_SBW_TCK , true ); // start SBW stuff gpio_put(PINOUT_SBW_TCK , true ); // start SBW stuff
busy_wait_us_32(100); // wait a bit more busy_wait_ms(5);//busy_wait_us_32(100); // wait a bit more*/
gpio_put(PINOUT_SBW_TCK , false);
gpio_put(PINOUT_SBW_TDIO, true);
busy_wait_ms(4); // reset TEST logic
gpio_put(PINOUT_SBW_TDIO, true);
busy_wait_us_32(1);
gpio_put(PINOUT_SBW_TCK , true);
busy_wait_ms(20); // activate TEST logic
// "phase 1"
gpio_put(PINOUT_SBW_TDIO, true);
busy_wait_us_32(60);
// "phase 2"
gpio_put(PINOUT_SBW_TCK , false);
// "phase 3"
busy_wait_us_32(1);
// "phase 4"
gpio_put(PINOUT_SBW_TCK , true);
busy_wait_us_32(60);
// "phase 5"
busy_wait_ms(5);
} }
int sbw_piosm = -1, sbw_offset = -1; int sbw_piosm = -1, sbw_offset = -1;

85
src/tap.c Normal file
View File

@ -0,0 +1,85 @@
#include "pio_sbw.h"
#include "tap.h"
// FIXME: TDI in run-test/idle ALWAYS TCLK value??
void sbw_tap_reset(void) {
// TDI always 1
// TMS=1,1,1,1,1,1 -- reset TAP state to initial
// TMS=0 -- test-logic-reset to run-test/idle
// TMS=1,0,1,0,1 -- perform fuse check
// TMS=1,0 -- back to run-test/idle
//const uint16_t tms_seq = 0x1abf;//0x3f | (0<<6) | (0x15 << 7) | (0x1 << 12);
const uint8_t tms_seq[2] = {0xbf,0x1a};
sbw_tms_sequence(14, true, tms_seq);
}
void sbw_check_fuse(void) {
// TDI always 1
// TMS=01010110
const uint8_t tms_seq = 0x6a;
sbw_tms_sequence(8, true, &tms_seq);
}
static uint8_t bitswap(uint8_t in) {
static const uint8_t lut[16] = {
0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf
};
return (lut[in&0xf] << 4) | lut[in>>4];
}
static inline uint16_t bitswap16(uint16_t in) {
return ((uint16_t)bitswap(in & 0xff) << 8) | bitswap(in >> 8);
}
uint16_t sbw_tap_shift_dr(uint16_t newdr) {
// DR content is MSB-first instead of LSB-first (IR is the latter)
// except the PIO already does bitswaps, so we need to do it for the IR instead
newdr = /*bitswap16(*/newdr/*)*/;
// 100: run-test/idle -> select-dr-scan -> capture-dr -> shift-dr
const uint8_t tms_seq = 0x01;
sbw_tms_sequence(3, true, &tms_seq);
// 15 data bits with TMS=0
// 1 data bit with TMS=1 (to exit1-dr)
uint16_t res = 0;
uint8_t newdr2 = newdr >> 15, resb = 0;
sbw_sequence(15, false, (const uint8_t*)&newdr, (uint8_t*)&res); // FIXME: little-endian-only
sbw_sequence( 1, true , &newdr2, &resb);
res |= (uint16_t)resb << 15;
// TMS=1 (to update-dr)
// TMS=0 (to run-test/idle)
const uint8_t tms_seq_2 = 0x01;
sbw_tms_sequence(2, true, &tms_seq_2);
return /*bitswap16(*/res/*)*/;
}
uint8_t sbw_tap_shift_ir(uint8_t newir) {
newir = bitswap(newir);
// 1100: run-test/idle -> select-dr-scan -> select-ir-scan -> capture-ir -> shift-ir
const uint8_t tms_seq = 0x03;
sbw_tms_sequence(4, true, &tms_seq);
// 7 data bits with TMS=0
// 1 data bit with TMS=1 (to exit1-ir)
uint8_t res = 0, resb = 0, newir2 = newir >> 7;
sbw_sequence(7, false, &newir , &res );
sbw_sequence(1, true , &newir2, &resb);
res |= resb << 7;
// TMS=1 (to update-ir)
// TMS=0 (to run-test/idle)
const uint8_t tms_seq_2 = 0x01;
sbw_tms_sequence(2, true, &tms_seq_2);
return bitswap(res);
}

22
src/tap.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef SBW_TAP_H_
#define SBW_TAP_H_
// move to run-test/idle. typically this is done by sending a single TMS=0
// cycle, but the MSP430 has an extra JTAG fuse check that needs to be done
void sbw_tap_reset(void);
// more fuse checking stuff
void sbw_check_fuse(void);
// write IR contents. starts and ends in run-test/idle
uint8_t sbw_tap_shift_ir(uint8_t newir);
// read current IR contents. starts and ends in run-test/idle
//uint8_t sbw_tap_read_ir(void);
// write DR contents. starts and ends in run-test/idle
uint16_t sbw_tap_shift_dr(uint16_t newdr);
// read current DR contents. starts and ends in run-test/idle
static inline uint16_t sbw_tap_read_dr(void) { return sbw_tap_shift_dr(0x0000); }
#endif