From f0ba4504354873bf12bef0f6a83fe313602556bb Mon Sep 17 00:00:00 2001 From: sys64738 Date: Wed, 29 Sep 2021 17:18:18 +0200 Subject: [PATCH] we can read from memory now! --- src/main.c | 36 ++++++++-- src/msp430dbg.c | 186 ++++++++++++++++++++++++++++++++++++++++++++++++ src/msp430dbg.h | 73 +++++++++++++++++++ src/pio_sbw.c | 32 +++++---- src/sbw.pio | 19 +++-- 5 files changed, 318 insertions(+), 28 deletions(-) create mode 100644 src/msp430dbg.c create mode 100644 src/msp430dbg.h diff --git a/src/main.c b/src/main.c index 2e8978d..9561d8f 100644 --- a/src/main.c +++ b/src/main.c @@ -49,12 +49,36 @@ int main() { sbw_tclk_burst(16); 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); + /*sbw_tap_reset(); + sbw_check_fuse(); + + uint8_t id = sbw_tap_shift_ir(msp430_ir_bypass); + printf("JTAG ID=%02x\n", id); + + sbw_tap_shift_ir(msp430_ir_ctrl_sig_16bit); + uint16_t dr = sbw_tap_read_dr(); + printf("dr.0 = %04x\n", dr); + sbw_clr_tclk(); // FIXME: looks very bad + sbw_set_tclk(); // FIXME: looks very bad + dr = sbw_tap_read_dr(); + printf("dr.1 = %04x\n", dr); + sbw_clr_tclk(); // FIXME: looks very bad + sbw_set_tclk(); // FIXME: looks very bad + dr = sbw_tap_read_dr(); + printf("dr.2 = %04x\n", dr); + sbw_clr_tclk(); // FIXME: looks very bad + sbw_set_tclk(); // FIXME: looks very bad + + sbw_tap_shift_ir(msp430_ir_data_16bit); + dr = sbw_tap_shift_dr(0x3fff); // "jmp ." + printf("dr.10 = %04x\n", dr); + sbw_clr_tclk(); // looks ok here? + sbw_tap_shift_ir(msp430_ir_ctrl_sig_16bit); // FIXME: a + dr = sbw_tap_shift_dr(0x2409); // JTAG halt // FIXME: a + printf("dr.11 = %04x\n", dr); + sbw_set_tclk(); // looks ok here? + + printf("test done\n");*/ uint32_t initv = msp430_device_get(200e3); printf("init -> %08lx\n", initv); diff --git a/src/msp430dbg.c b/src/msp430dbg.c new file mode 100644 index 0000000..24cd713 --- /dev/null +++ b/src/msp430dbg.c @@ -0,0 +1,186 @@ + +#include +#include + +#include "pio_sbw.h" +#include "tap.h" + +#include "msp430dbg.h" + +bool msp430_check_fuse_blown(void) { + for (size_t i = 0; i < 3; ++i) { + sbw_tap_shift_ir(msp430_ir_ctrl_sig_capture); + uint16_t dr = sbw_tap_shift_dr(0xaaaa); + //printf("fuse dr=%04x\n", dr); + if (dr == 0x5555) return true; + } + + return false; +} + +bool msp430_insn_fetch(void) { + sbw_tap_shift_ir(msp430_ir_ctrl_sig_capture); + // shouldn't it set the insn fetch bit here? + for (size_t i = 0; i < 50; ++i) { + uint16_t dr = sbw_tap_read_dr(); + //printf("[%zu] wait fetch dr=%04x\n", i, dr); + if (dr & 0x0080) return true; + + sbw_clr_tclk(); + sbw_set_tclk(); + } + + return false; +} + +void msp430_cpu_halt(void) { + if (!msp430_insn_fetch()) ;//printf("aaa no fetch\n"); + sbw_tap_shift_ir(msp430_ir_data_16bit); + sbw_tap_shift_dr(0x3fff); // "jmp ." + sbw_clr_tclk(); + sbw_tap_shift_ir(msp430_ir_ctrl_sig_16bit); + sbw_tap_shift_dr(0x2409); // JTAG halt + sbw_set_tclk(); +} +void msp430_cpu_release(void) { + sbw_clr_tclk(); + sbw_tap_shift_ir(msp430_ir_ctrl_sig_16bit); + sbw_tap_shift_dr(0x2401); + sbw_tap_shift_ir(msp430_ir_addr_capture); + sbw_set_tclk(); +} + +bool msp430_cpu_reset(void) { + sbw_tap_shift_ir(msp430_ir_ctrl_sig_16bit); + sbw_tap_shift_dr(0x2C01); + sbw_tap_shift_dr(0x2401); + sbw_clr_tclk(); + sbw_set_tclk(); + sbw_clr_tclk(); + sbw_set_tclk(); + sbw_clr_tclk(); + uint8_t jtagid = sbw_tap_shift_ir(msp430_ir_addr_capture); + sbw_set_tclk(); + + //printf("reset: watchdog disable\n"); + msp430_memory_write(16, 0x0120, 0x5A80); // disable watchdog + + return jtagid == MSP430_JTAG_TAP_ID; +} + +uint16_t msp430_memory_read16(uint16_t addr) { + msp430_cpu_halt(); + + sbw_clr_tclk(); + sbw_tap_shift_ir(msp430_ir_ctrl_sig_16bit); + sbw_tap_shift_dr(0x2409); // 2419 for 8bit + sbw_tap_shift_ir(msp430_ir_addr_16bit); + sbw_tap_shift_dr(addr); + sbw_tap_shift_ir(msp430_ir_data_to_addr); + sbw_set_tclk(); + sbw_clr_tclk(); + uint16_t r = sbw_tap_read_dr(); + //printf("read16 result=%04x\n", r); + + msp430_cpu_release(); + + return r; +} + +uint8_t msp430_memory_read8 (uint16_t addr) { + msp430_cpu_halt(); + + sbw_clr_tclk(); + sbw_tap_shift_ir(msp430_ir_ctrl_sig_16bit); + sbw_tap_shift_dr(0x2419); // 2409 for 16bit + sbw_tap_shift_ir(msp430_ir_addr_16bit); + sbw_tap_shift_dr(addr); + sbw_tap_shift_ir(msp430_ir_data_to_addr); + sbw_set_tclk(); + sbw_clr_tclk(); + uint16_t r = sbw_tap_read_dr(); + + msp430_cpu_release(); + + return r; +} + +void msp430_memory_write16(uint16_t addr, uint16_t value) { + msp430_cpu_halt(); + + sbw_clr_tclk(); + sbw_tap_shift_ir(msp430_ir_ctrl_sig_16bit); + sbw_tap_shift_dr(0x2408); // 2418 for 8bit + sbw_tap_shift_ir(msp430_ir_addr_16bit); + sbw_tap_shift_dr(addr); + sbw_tap_shift_ir(msp430_ir_data_to_addr); + sbw_tap_shift_dr(value); + sbw_set_tclk(); + + msp430_cpu_release(); +} + +void msp430_memory_write8 (uint16_t addr, uint8_t value) { + msp430_cpu_halt(); + + sbw_clr_tclk(); + sbw_tap_shift_ir(msp430_ir_ctrl_sig_16bit); + sbw_tap_shift_dr(0x2418); + sbw_tap_shift_ir(msp430_ir_addr_16bit); + sbw_tap_shift_dr(addr); + sbw_tap_shift_ir(msp430_ir_data_to_addr); + sbw_tap_shift_dr(value); + sbw_set_tclk(); + + msp430_cpu_release(); +} + +uint32_t msp430_device_get(float freq) { + uint8_t jtagid = 0; + for (size_t i = 0; i < 7; ++i) { + sbw_preinit(); + + bool s = sbw_init(); + if (!s) return 0xff<<24; + + sbw_tap_reset(); + sbw_check_fuse(); + + jtagid = sbw_tap_shift_ir(msp430_ir_bypass); + //printf("[%zu] get jtag id= %02x\n", i, jtagid); + + if (jtagid == MSP430_JTAG_TAP_ID) break; + + sbw_deinit(); + } + + if (jtagid != MSP430_JTAG_TAP_ID) return 0<<24; + if (msp430_check_fuse_blown()) return 1<<24; + + // TODO: set frequency here + + sbw_tap_shift_ir(msp430_ir_ctrl_sig_16bit); + uint16_t dr = sbw_tap_shift_dr(0x2401); // JTAG mode, read + //printf("olddr=%04x\n", dr); + + if (sbw_tap_shift_ir(msp430_ir_ctrl_sig_16bit) != jtagid) { + return 2<<24; + } + + uint16_t devid = 0; + for (size_t i = 0; i < 50; ++i) { + dr = sbw_tap_read_dr(); + //printf("[%zu] wait jtag sync: dr=%04x\n", i, dr); + if (dr & 0x0200) { + devid = msp430_memory_read(16, 0x0FF0); + break; + } + } + + if (devid == 0) return 3<<24; + + if (!msp430_cpu_reset()) return 4<<24; + + return ((uint32_t)jtagid << 24) | devid; +} + diff --git a/src/msp430dbg.h b/src/msp430dbg.h new file mode 100644 index 0000000..3d28e8c --- /dev/null +++ b/src/msp430dbg.h @@ -0,0 +1,73 @@ + +#ifndef MSP430DBG_H_ +#define MSP430DBG_H_ + +#include +#include + +#define MSP430_JTAG_TAP_ID 0x89 + +enum msp430_ir { + // lsb-first transfer + // DR: msb-first transfer... + msp430_ir_addr_16bit = 0x83, + msp430_ir_addr_capture = 0x84, + + msp430_ir_data_to_addr = 0x85, + msp430_ir_data_16bit = 0x41, + msp430_ir_data_quick = 0x43, + + msp430_ir_ctrl_sig_16bit = 0x13, + msp430_ir_ctrl_sig_capture = 0x14, // 0010 1000 <=> 0x28 + msp430_ir_ctrl_sig_release = 0x15, + + msp430_ir_data_psa = 0x44, + msp430_ir_shift_out_psa = 0x46, + + msp430_ir_fuse_prepare_blow = 0x22, + msp430_ir_fuse_ex_blow = 0x24, + + msp430_ir_jmb_exchange = 0x61, + + msp430_ir_bypass = 0xff +}; + +enum msp430_ctrl { + msp430_ctrl_RnW = 1<< 0, + msp430_ctrl_halt_jtag = 1<< 3, + msp430_ctrl_instr_load = 1<< 7, + msp430_ctrl_tce0 = 1<< 9, + msp430_ctrl_tce1 = 1<<10, + msp430_ctrl_por = 1<<11, + msp430_release_lbyte0 = 1<<12, + msp430_tagfuncsat = 1<<13, + msp430_switch = 1<<14, +}; + +bool msp430_check_fuse_blown(void); +void msp430_jtag_ctrl(void); +bool msp430_insn_fetch(void);// +void msp430_pc_set(uint16_t pc); +void msp430_cpu_halt(void); +void msp430_cpu_release(void); +bool msp430_cpu_reset(void); // POR +void msp430_device_release(void); +uint16_t msp430_memory_read16(uint16_t addr); +uint8_t msp430_memory_read8 (uint16_t addr); +void msp430_memory_write16(uint16_t addr, uint16_t value); +void msp430_memory_write8 (uint16_t addr, uint8_t value); +void msp430_memory_read_block(uint16_t srcaddr, uint16_t num, uint16_t* dest); +void msp430_memory_write_block(uint16_t dstaddr, uint16_t num, const uint16_t* src); + +#define msp430_memory_read(bits, addr) (msp430_memory_read##bits (addr)) +#define msp430_memory_write(bit, a, v) (msp430_memory_write##bit (a, v)) + +void msp430_flash_write(uint16_t startaddr, uint16_t num, const uint16_t* src); +void msp430_flash_erase_seg(uint16_t startaddr, bool is_infosegA); +void msp430_flash_erase_mass(bool withinfomem); // false: only main flash +bool msp430_flash_verify(uint16_t startaddr, uint16_t length, const uint16_t* copy); + +uint32_t msp430_device_get(float freq); + +#endif + diff --git a/src/pio_sbw.c b/src/pio_sbw.c index d95e72f..34b3291 100644 --- a/src/pio_sbw.c +++ b/src/pio_sbw.c @@ -1,4 +1,6 @@ +#include + #include #include #include @@ -67,7 +69,7 @@ void sbw_preinit(void) { int sbw_piosm = -1, sbw_offset = -1; -static uint last_tclk = 1; +static bool last_tclk = true; static uint8_t last_tdi = 0xff, last_tms = 0xff; bool sbw_init(void) { @@ -92,7 +94,7 @@ bool sbw_init(void) { PINOUT_SBW_TCK, PINOUT_SBW_TDIO); last_tdi = last_tms = 0xff; - last_tclk = 1; + last_tclk = true; return true; } @@ -180,7 +182,7 @@ void sbw_sequence(uint32_t ncyc, bool tms, const uint8_t* tdi, uint8_t* tdo) { } } - while (!sbw_pio_is_idle(PINOUT_SBW_PIO, sbw_piosm)) tight_loop_contents(); + //while (!sbw_pio_is_idle(PINOUT_SBW_PIO, sbw_piosm, sbw_offset)) tight_loop_contents(); if (tdi) last_tdi = (tdi[nbytes - 1] & (1 << (ncyc & 7))) ? 0xff : 0; last_tms = tms ? 0xff : 0; @@ -214,18 +216,18 @@ void sbw_tms_sequence(uint32_t ncyc, bool tdi, const uint8_t* tms) { } } - while (!sbw_pio_is_idle(PINOUT_SBW_PIO, sbw_piosm)) tight_loop_contents(); + //while (!sbw_pio_is_idle(PINOUT_SBW_PIO, sbw_piosm, sbw_offset)) tight_loop_contents(); last_tdi = tdi ? 0xff : 0; last_tms = (tms[nbytes - 1] & (1 << (ncyc & 7))) ? 0xff : 0; } void sbw_clrset_tclk(bool value) { - sbw_pio_loadbearing_set_setpins(PINOUT_SBW_PIO, value ? 1 : 0); // new value + //sbw_pio_loadbearing_set_setpins(PINOUT_SBW_PIO, value ? 1 : 0); // new value // pre-TCLK value piosm_txf_wait(); - piosm_txf(16) = sbw_pio_gen_sety(last_tclk); + piosm_txf(16) = sbw_pio_gen_sety(last_tclk ? 1 : 0); // only one TCLK piosm_txf_wait(); @@ -235,14 +237,19 @@ void sbw_clrset_tclk(bool value) { piosm_txf_wait(); piosm_txf(16) = sbw_pio_gen_jmp(sbw_offset_sbw_tclk_burst + sbw_offset); - // wait until done - while (!sbw_pio_is_idle(PINOUT_SBW_PIO, sbw_piosm)) tight_loop_contents(); + // always use out pins, 1 + piosm_txf_wait(); + piosm_txf(8) = value ? 0xff : 0; - last_tclk = value ? 1 : 0; + // wait until done + /*while ( sbw_pio_is_idle(PINOUT_SBW_PIO, sbw_piosm, sbw_offset)) tight_loop_contents(); + while (!sbw_pio_is_idle(PINOUT_SBW_PIO, sbw_piosm, sbw_offset)) tight_loop_contents();*/ + + last_tclk = value; } void sbw_tclk_burst(uint32_t ncyc) { - sbw_pio_loadbearing_set_outpins(PINOUT_SBW_PIO); + //sbw_pio_loadbearing_set_outpins(PINOUT_SBW_PIO); uint32_t txremain = ((ncyc + 7) >> 3) * 2; @@ -251,7 +258,7 @@ void sbw_tclk_burst(uint32_t ncyc) { // pre-TCLK value piosm_txf_wait(); - piosm_txf(16) = sbw_pio_gen_sety(last_tclk); + piosm_txf(16) = sbw_pio_gen_sety(last_tclk ? 1 : 0); // number of TCLK half-cycles in x piosm_txf_wait(); @@ -271,7 +278,8 @@ void sbw_tclk_burst(uint32_t ncyc) { } // wait until done - while (!sbw_pio_is_idle(PINOUT_SBW_PIO, sbw_piosm)) tight_loop_contents(); + /*while ( sbw_pio_is_idle(PINOUT_SBW_PIO, sbw_piosm, sbw_offset)) tight_loop_contents(); + while (!sbw_pio_is_idle(PINOUT_SBW_PIO, sbw_piosm, sbw_offset)) tight_loop_contents();*/ // last_tclk doesn't change - always an even number of TCLK half-cycles } diff --git a/src/sbw.pio b/src/sbw.pio index 8b98fd4..578e8bd 100644 --- a/src/sbw.pio +++ b/src/sbw.pio @@ -80,8 +80,8 @@ PUBLIC sbw_tms_seq: ; ; a full cycle takes 13 cycles, a single slot 4 ; the SM divider should be sysclk/(4*baudrate) -; baudrate shouldn't exceed 20 MHz (typical value is 1.8 MHz?) -; SBWTCK LOW phases shouldn't exceed 7us, so the baudrate should be at least 72 kHz +; baudrate shouldn't exceed 20 MHz (typical value is 18 MHz?) +; SBWTCK LOW phases shouldn't exceed 7us, so the baudrate should be at least 40 kHz ; y: initial/previous TCLK value ; x: number of TCLK *half*-cycles minus one! @@ -99,7 +99,7 @@ PUBLIC sbw_tclk_burst: ; tdi slot: nop side 1 [12] ; wait a bit burst_loop: -PUBLIC sbw_tclk_burst_loadbearing_insn: +;PUBLIC sbw_tclk_burst_loadbearing_insn: out pins, 1 side 1 [12] ; in the middle of TDI hiphase: do TCLK jmp x--, burst_loop side 1 [12] nop side 0 [1] ; need a low clock edge for TDO @@ -186,7 +186,8 @@ static inline uint16_t sbw_pio_gen_outx(uint bits) { static inline uint16_t sbw_pio_gen_jmp(uint subroutine) { return pio_encode_jmp(subroutine) | pio_encode_sideset(1, 1) | (1<<12); } -static inline uint16_t sbw_pio_loadbearing_gen_outpins(void) { + +/*static inline uint16_t sbw_pio_loadbearing_gen_outpins(void) { return pio_encode_out(pio_pins, 1) | pio_encode_sideset(1, 1) | pio_encode_delay(12) | (1<<12); } static inline uint16_t sbw_pio_loadbearing_gen_setpins(uint value) { @@ -194,19 +195,17 @@ static inline uint16_t sbw_pio_loadbearing_gen_setpins(uint value) { } static inline void sbw_pio_loadbearing_set_outpins(PIO pio) { - // FIXME: writes 32 bits!!! pio->instr_mem[sbw_offset_sbw_tclk_burst_loadbearing_insn] = sbw_pio_loadbearing_gen_outpins(); } static inline void sbw_pio_loadbearing_set_setpins(PIO pio, uint value) { - // FIXME: writes 32 bits!!! pio->instr_mem[sbw_offset_sbw_tclk_burst_loadbearing_insn] = sbw_pio_loadbearing_gen_setpins(value); -} +}*/ -static inline bool sbw_pio_is_idle(PIO pio, uint value) { - return pio_sm_get_pc(pio, value) < sbw_offset_sbw_seq; -} +/*static inline bool sbw_pio_is_idle(PIO pio, uint sm, uint offset) { + return pio_sm_get_pc(pio, sm) < sbw_offset_sbw_seq + offset; +}*/ %}