we can read from memory now!
This commit is contained in:
parent
377733b191
commit
f0ba450435
36
src/main.c
36
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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -1,4 +1,6 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <hardware/clocks.h>
|
||||
#include <hardware/dma.h>
|
||||
#include <hardware/gpio.h>
|
||||
|
@ -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
|
||||
}
|
||||
|
|
19
src/sbw.pio
19
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;
|
||||
}*/
|
||||
|
||||
%}
|
||||
|
||||
|
|
Loading…
Reference in New Issue