we can read from memory now!

This commit is contained in:
Triss 2021-09-29 17:18:18 +02:00
parent 377733b191
commit f0ba450435
5 changed files with 318 additions and 28 deletions

View File

@ -49,12 +49,36 @@ int main() {
sbw_tclk_burst(16); sbw_tclk_burst(16);
printf("done.\n");*/ printf("done.\n");*/
// sbw_tap_reset(); /*sbw_tap_reset();
// sbw_check_fuse(); sbw_check_fuse();
//
// uint8_t id = sbw_tap_shift_ir(0xff/*IR_BYPASS*/); uint8_t id = sbw_tap_shift_ir(msp430_ir_bypass);
// printf("JTAG ID=%02x\n", id);
// 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); uint32_t initv = msp430_device_get(200e3);
printf("init -> %08lx\n", initv); printf("init -> %08lx\n", initv);

186
src/msp430dbg.c Normal file
View File

@ -0,0 +1,186 @@
#include <stddef.h>
#include <stdio.h>
#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;
}

73
src/msp430dbg.h Normal file
View File

@ -0,0 +1,73 @@
#ifndef MSP430DBG_H_
#define MSP430DBG_H_
#include <stdint.h>
#include <stdbool.h>
#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

View File

@ -1,4 +1,6 @@
#include <stdio.h>
#include <hardware/clocks.h> #include <hardware/clocks.h>
#include <hardware/dma.h> #include <hardware/dma.h>
#include <hardware/gpio.h> #include <hardware/gpio.h>
@ -67,7 +69,7 @@ void sbw_preinit(void) {
int sbw_piosm = -1, sbw_offset = -1; 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; static uint8_t last_tdi = 0xff, last_tms = 0xff;
bool sbw_init(void) { bool sbw_init(void) {
@ -92,7 +94,7 @@ bool sbw_init(void) {
PINOUT_SBW_TCK, PINOUT_SBW_TDIO); PINOUT_SBW_TCK, PINOUT_SBW_TDIO);
last_tdi = last_tms = 0xff; last_tdi = last_tms = 0xff;
last_tclk = 1; last_tclk = true;
return 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; if (tdi) last_tdi = (tdi[nbytes - 1] & (1 << (ncyc & 7))) ? 0xff : 0;
last_tms = tms ? 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_tdi = tdi ? 0xff : 0;
last_tms = (tms[nbytes - 1] & (1 << (ncyc & 7))) ? 0xff : 0; last_tms = (tms[nbytes - 1] & (1 << (ncyc & 7))) ? 0xff : 0;
} }
void sbw_clrset_tclk(bool value) { 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 // pre-TCLK value
piosm_txf_wait(); 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 // only one TCLK
piosm_txf_wait(); piosm_txf_wait();
@ -235,14 +237,19 @@ void sbw_clrset_tclk(bool value) {
piosm_txf_wait(); piosm_txf_wait();
piosm_txf(16) = sbw_pio_gen_jmp(sbw_offset_sbw_tclk_burst + sbw_offset); piosm_txf(16) = sbw_pio_gen_jmp(sbw_offset_sbw_tclk_burst + sbw_offset);
// wait until done // always use out pins, 1
while (!sbw_pio_is_idle(PINOUT_SBW_PIO, sbw_piosm)) tight_loop_contents(); 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) { 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; uint32_t txremain = ((ncyc + 7) >> 3) * 2;
@ -251,7 +258,7 @@ void sbw_tclk_burst(uint32_t ncyc) {
// pre-TCLK value // pre-TCLK value
piosm_txf_wait(); 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 // number of TCLK half-cycles in x
piosm_txf_wait(); piosm_txf_wait();
@ -271,7 +278,8 @@ void sbw_tclk_burst(uint32_t ncyc) {
} }
// wait until done // 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 // last_tclk doesn't change - always an even number of TCLK half-cycles
} }

View File

@ -80,8 +80,8 @@ PUBLIC sbw_tms_seq:
; ;
; a full cycle takes 13 cycles, a single slot 4 ; a full cycle takes 13 cycles, a single slot 4
; the SM divider should be sysclk/(4*baudrate) ; the SM divider should be sysclk/(4*baudrate)
; baudrate shouldn't exceed 20 MHz (typical value is 1.8 MHz?) ; 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 72 kHz ; SBWTCK LOW phases shouldn't exceed 7us, so the baudrate should be at least 40 kHz
; y: initial/previous TCLK value ; y: initial/previous TCLK value
; x: number of TCLK *half*-cycles minus one! ; x: number of TCLK *half*-cycles minus one!
@ -99,7 +99,7 @@ PUBLIC sbw_tclk_burst:
; tdi slot: ; tdi slot:
nop side 1 [12] ; wait a bit nop side 1 [12] ; wait a bit
burst_loop: 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 out pins, 1 side 1 [12] ; in the middle of TDI hiphase: do TCLK
jmp x--, burst_loop side 1 [12] jmp x--, burst_loop side 1 [12]
nop side 0 [1] ; need a low clock edge for TDO 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) { static inline uint16_t sbw_pio_gen_jmp(uint subroutine) {
return pio_encode_jmp(subroutine) | pio_encode_sideset(1, 1) | (1<<12); 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); 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) { 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) { static inline void sbw_pio_loadbearing_set_outpins(PIO pio) {
// FIXME: writes 32 bits!!!
pio->instr_mem[sbw_offset_sbw_tclk_burst_loadbearing_insn] = pio->instr_mem[sbw_offset_sbw_tclk_burst_loadbearing_insn] =
sbw_pio_loadbearing_gen_outpins(); sbw_pio_loadbearing_gen_outpins();
} }
static inline void sbw_pio_loadbearing_set_setpins(PIO pio, uint value) { 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] = pio->instr_mem[sbw_offset_sbw_tclk_burst_loadbearing_insn] =
sbw_pio_loadbearing_gen_setpins(value); sbw_pio_loadbearing_gen_setpins(value);
} }*/
static inline bool sbw_pio_is_idle(PIO pio, uint value) { /*static inline bool sbw_pio_is_idle(PIO pio, uint sm, uint offset) {
return pio_sm_get_pc(pio, value) < sbw_offset_sbw_seq; return pio_sm_get_pc(pio, sm) < sbw_offset_sbw_seq + offset;
} }*/
%} %}