502 lines
12 KiB
C
502 lines
12 KiB
C
|
|
#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;
|
|
}
|
|
|
|
void msp430_pc_set(uint16_t pc) {
|
|
if (!msp430_insn_fetch()) ;//printf("aaa no fetch\n");
|
|
|
|
sbw_tap_shift_ir(msp430_ir_ctrl_sig_16bit);
|
|
sbw_tap_shift_dr(0x3401);
|
|
sbw_tap_shift_ir(msp430_ir_data_16bit);
|
|
sbw_tap_shift_dr(0x4030); // "load pc"
|
|
sbw_clr_tclk();
|
|
sbw_set_tclk();
|
|
sbw_tap_shift_dr(pc);
|
|
sbw_clr_tclk();
|
|
sbw_set_tclk();
|
|
sbw_tap_shift_ir(msp430_ir_addr_capture);
|
|
sbw_clr_tclk();
|
|
sbw_tap_shift_ir(msp430_ir_ctrl_sig_16bit);
|
|
sbw_tap_shift_dr(0x2401);
|
|
}
|
|
|
|
void msp430_device_release(uint16_t addr) {
|
|
if (addr == 0xfffe) { // reset vector
|
|
sbw_tap_shift_ir(msp430_ir_ctrl_sig_16bit);
|
|
sbw_tap_shift_dr(0x2c01);
|
|
sbw_tap_shift_dr(0x2401);
|
|
} else {
|
|
msp430_pc_set(addr);
|
|
}
|
|
|
|
sbw_tap_shift_ir(msp430_ir_ctrl_sig_release);
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
void msp430_memory_read_block(uint16_t srcaddr, uint16_t num, uint16_t* dest) {
|
|
msp430_pc_set(srcaddr - 4);
|
|
msp430_cpu_halt();
|
|
|
|
sbw_clr_tclk();
|
|
sbw_tap_shift_ir(msp430_ir_ctrl_sig_16bit);
|
|
sbw_tap_shift_dr(0x2409);
|
|
sbw_tap_shift_ir(msp430_ir_data_quick);
|
|
|
|
for (size_t i = 0; i < num; ++i) {
|
|
sbw_set_tclk();
|
|
dest[i] = sbw_tap_read_dr();
|
|
sbw_clr_tclk();
|
|
}
|
|
|
|
msp430_cpu_release();
|
|
}
|
|
void msp430_memory_write_block(uint16_t dstaddr, uint16_t num, const uint16_t* src) {
|
|
msp430_pc_set(dstaddr - 4);
|
|
msp430_cpu_halt();
|
|
|
|
sbw_clr_tclk();
|
|
sbw_tap_shift_ir(msp430_ir_ctrl_sig_16bit);
|
|
sbw_tap_shift_dr(0x2408);
|
|
sbw_tap_shift_ir(msp430_ir_data_quick);
|
|
|
|
for (size_t i = 0; i < num; ++i) {
|
|
sbw_tap_shift_dr(src[i]);
|
|
sbw_set_tclk();
|
|
sbw_clr_tclk();
|
|
}
|
|
|
|
msp430_cpu_release();
|
|
}
|
|
bool msp430_memory_verify(uint16_t startaddr, uint16_t length, const uint16_t* copy) {
|
|
const uint16_t poly = 0x0805;
|
|
|
|
msp430_cpu_reset();
|
|
|
|
if (false/*device has enhanced verify*/) {
|
|
msp430_pc_set(startaddr - 4);
|
|
msp430_cpu_halt();
|
|
sbw_clr_tclk();
|
|
sbw_tap_shift_ir(msp430_ir_data_16bit);
|
|
sbw_tap_shift_dr(startaddr - 2);
|
|
} else {
|
|
msp430_pc_set(startaddr - 2);
|
|
sbw_set_tclk();
|
|
sbw_clr_tclk();
|
|
}
|
|
|
|
sbw_tap_shift_ir(msp430_ir_data_psa);
|
|
|
|
for (size_t i = 0; i < length; ++i) {
|
|
sbw_set_tclk();
|
|
|
|
const uint8_t tms_seq = 0x19; // 100110
|
|
// go through drscan/capturedr/shiftdr/updatedr without actually shifting data
|
|
sbw_tms_sequence(6, true, &tms_seq);
|
|
|
|
sbw_clr_tclk();
|
|
}
|
|
|
|
sbw_tap_shift_ir(msp430_ir_shift_out_psa);
|
|
uint16_t psa_out = sbw_tap_read_dr();
|
|
sbw_set_tclk();
|
|
|
|
if (false/*device has enhanced verify*/) {
|
|
msp430_cpu_release();
|
|
}
|
|
msp430_cpu_reset();
|
|
|
|
uint16_t psa_crc = startaddr - 2;
|
|
for (size_t i = 0; i < length; ++i) {
|
|
if (psa_crc & 0x8000) {
|
|
psa_crc ^= poly;
|
|
psa_crc <<= 1;
|
|
psa_crc |= 1;
|
|
} else psa_crc <<= 1;
|
|
|
|
if (copy) psa_crc ^= copy[i];
|
|
else psa_crc ^= 0xffff;
|
|
}
|
|
|
|
return psa_out == psa_crc;
|
|
}
|
|
|
|
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;
|
|
|
|
//sbw_set_freq(false, freq); // TODO: store freq? for programming stuff (needs different baudrate for tclk)
|
|
sbw_set_freq(true, 350e3);
|
|
|
|
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;
|
|
}
|
|
|
|
// TODO
|
|
void msp430_flash_write(uint16_t startaddr, uint16_t num, const uint16_t* src) {
|
|
msp430_cpu_halt();
|
|
|
|
sbw_clr_tclk();
|
|
sbw_tap_shift_ir(msp430_ir_ctrl_sig_16bit);
|
|
sbw_tap_shift_dr(0x2408);
|
|
sbw_tap_shift_ir(msp430_ir_addr_16bit);
|
|
sbw_tap_shift_dr(0x0128); // FCTL1
|
|
sbw_tap_shift_ir(msp430_ir_data_to_addr);
|
|
sbw_tap_shift_dr(0xa540); // enable flash write
|
|
sbw_set_tclk();
|
|
|
|
sbw_clr_tclk();
|
|
sbw_tap_shift_ir(msp430_ir_addr_16bit);
|
|
sbw_tap_shift_dr(0x012a); // FCTL2
|
|
sbw_tap_shift_ir(msp430_ir_data_to_addr);
|
|
sbw_tap_shift_dr(0xa540); // MCLK source, DIV=1
|
|
sbw_set_tclk();
|
|
|
|
sbw_clr_tclk();
|
|
sbw_tap_shift_ir(msp430_ir_addr_16bit);
|
|
sbw_tap_shift_dr(0x012c); // FCTL3
|
|
sbw_tap_shift_ir(msp430_ir_data_to_addr);
|
|
sbw_tap_shift_dr(0xa540); // unlock
|
|
sbw_set_tclk();
|
|
|
|
sbw_clr_tclk();
|
|
sbw_tap_shift_ir(msp430_ir_ctrl_sig_16bit);
|
|
|
|
//sbw_set_freq(true, 350e3);
|
|
|
|
for (uint16_t i = 0, addr = startaddr; i < num; ++i, addr += 2) {
|
|
sbw_tap_shift_dr(0x2408);
|
|
|
|
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(src[i]);
|
|
|
|
sbw_set_tclk();
|
|
sbw_clr_tclk();
|
|
|
|
sbw_tap_shift_ir(msp430_ir_ctrl_sig_16bit);
|
|
sbw_tap_shift_dr(0x2409);
|
|
|
|
sbw_tclk_burst(35*4);
|
|
printf("%04x gets %04x\n", addr, src[i]);
|
|
}
|
|
|
|
sbw_tap_shift_ir(msp430_ir_ctrl_sig_16bit);
|
|
sbw_tap_shift_dr(0x2408);
|
|
sbw_tap_shift_ir(msp430_ir_addr_16bit);
|
|
sbw_tap_shift_dr(0x0128); // FCTL1
|
|
sbw_tap_shift_ir(msp430_ir_data_to_addr);
|
|
sbw_tap_shift_dr(0xa500); // disable flash write
|
|
sbw_set_tclk();
|
|
|
|
sbw_clr_tclk();
|
|
sbw_tap_shift_ir(msp430_ir_addr_16bit);
|
|
sbw_tap_shift_dr(0x012c); // FCTL3
|
|
sbw_tap_shift_ir(msp430_ir_data_to_addr);
|
|
sbw_tap_shift_dr(0xa550); // set lock
|
|
sbw_set_tclk();
|
|
|
|
msp430_cpu_release();
|
|
}
|
|
void msp430_flash_erase_seg(uint16_t startaddr, bool is_infosegA) {
|
|
(void)is_infosegA;
|
|
|
|
msp430_cpu_halt();
|
|
|
|
sbw_clr_tclk();
|
|
|
|
sbw_clr_tclk();
|
|
sbw_tap_shift_ir(msp430_ir_ctrl_sig_16bit);
|
|
sbw_tap_shift_dr(0x2408);
|
|
sbw_tap_shift_ir(msp430_ir_addr_16bit);
|
|
sbw_tap_shift_dr(0x0128); // FCTL1
|
|
sbw_tap_shift_ir(msp430_ir_data_to_addr);
|
|
sbw_tap_shift_dr(0xa502); // enable flash erase, single segment
|
|
sbw_set_tclk();
|
|
|
|
sbw_clr_tclk();
|
|
sbw_tap_shift_ir(msp430_ir_addr_16bit);
|
|
sbw_tap_shift_dr(0x012a); // FCTL2
|
|
sbw_tap_shift_ir(msp430_ir_data_to_addr);
|
|
sbw_tap_shift_dr(0xa540); // MCLK source, DIV=1
|
|
sbw_set_tclk();
|
|
|
|
sbw_clr_tclk();
|
|
sbw_tap_shift_ir(msp430_ir_addr_16bit);
|
|
sbw_tap_shift_dr(0x012c); // FCTL3
|
|
sbw_tap_shift_ir(msp430_ir_data_to_addr);
|
|
sbw_tap_shift_dr(0xa500); // unlock
|
|
sbw_set_tclk();
|
|
|
|
sbw_clr_tclk();
|
|
sbw_tap_shift_ir(msp430_ir_addr_16bit);
|
|
sbw_tap_shift_dr(startaddr);
|
|
sbw_tap_shift_ir(msp430_ir_data_to_addr);
|
|
sbw_tap_shift_dr(0x55aa);
|
|
sbw_set_tclk();
|
|
|
|
sbw_clr_tclk();
|
|
sbw_tap_shift_ir(msp430_ir_ctrl_sig_16bit);
|
|
sbw_tap_shift_dr(0x2409);
|
|
|
|
sbw_tclk_burst(4820);
|
|
|
|
sbw_tap_shift_ir(msp430_ir_ctrl_sig_16bit);
|
|
sbw_tap_shift_dr(0x2408);
|
|
sbw_tap_shift_ir(msp430_ir_addr_16bit);
|
|
sbw_tap_shift_dr(0x0128); // FCTL1
|
|
sbw_tap_shift_ir(msp430_ir_data_to_addr);
|
|
sbw_tap_shift_dr(0xa500); // lock flash
|
|
sbw_set_tclk();
|
|
|
|
sbw_clr_tclk();
|
|
sbw_tap_shift_ir(msp430_ir_addr_16bit);
|
|
sbw_tap_shift_dr(0x012c); // FCTL3
|
|
sbw_tap_shift_ir(msp430_ir_data_to_addr);
|
|
sbw_tap_shift_dr(0xa510); // set lock
|
|
sbw_set_tclk();
|
|
|
|
msp430_cpu_release();
|
|
}
|
|
void msp430_flash_erase_mass(bool withinfomem) {
|
|
uint16_t addr = withinfomem ? 0x1002 : 0xfffe;
|
|
uint16_t mode = withinfomem ? 0xa506 : 0xa504;
|
|
|
|
(void)addr; (void)mode; // nah, not yet
|
|
}
|
|
|
|
// mwhahahah
|
|
|
|
// TODO
|
|
/*uint16_t msp430_read_jmb(void) {
|
|
return 0;
|
|
}
|
|
void msp430_write_jmb(uint16_t v) {
|
|
|
|
}*/
|
|
|
|
uint16_t msp430_cpureg_read(short regid) {
|
|
sbw_tap_shift_ir(msp430_ir_ctrl_sig_16bit);
|
|
sbw_tap_shift_dr(0x3401);
|
|
|
|
sbw_tap_shift_ir(msp430_ir_data_16bit);
|
|
sbw_tap_shift_dr((regid & 0xf) << 8 | 0x4082);
|
|
|
|
sbw_clr_tclk();
|
|
sbw_tap_shift_ir(msp430_ir_data_capture);
|
|
sbw_set_tclk();
|
|
sbw_tap_shift_ir(msp430_ir_data_16bit);
|
|
sbw_tap_shift_dr(0x00fe);
|
|
sbw_clr_tclk();
|
|
sbw_tap_shift_ir(msp430_ir_data_capture);
|
|
sbw_set_tclk();
|
|
sbw_clr_tclk();
|
|
sbw_set_tclk();
|
|
uint16_t reg = sbw_tap_read_dr();
|
|
|
|
sbw_clr_tclk();
|
|
sbw_tap_shift_ir(msp430_ir_ctrl_sig_16bit);
|
|
sbw_tap_shift_dr(0x2401);
|
|
sbw_set_tclk();
|
|
|
|
return reg;
|
|
}
|
|
void msp430_cpureg_write(short regid, uint16_t value) {
|
|
sbw_tap_shift_ir(msp430_ir_ctrl_sig_16bit);
|
|
sbw_tap_shift_dr(0x3401);
|
|
|
|
sbw_tap_shift_ir(msp430_ir_data_16bit);
|
|
sbw_tap_shift_dr((regid & 0xf) | 0x4030);
|
|
|
|
sbw_clr_tclk();
|
|
sbw_tap_shift_ir(msp430_ir_data_capture);
|
|
sbw_set_tclk();
|
|
sbw_tap_shift_ir(msp430_ir_data_16bit);
|
|
sbw_tap_shift_dr(value);
|
|
sbw_clr_tclk();
|
|
sbw_tap_shift_ir(msp430_ir_data_capture);
|
|
sbw_set_tclk();
|
|
sbw_tap_shift_ir(msp430_ir_data_16bit);
|
|
sbw_tap_shift_dr(0x3ffd);
|
|
sbw_clr_tclk();
|
|
sbw_tap_shift_ir(msp430_ir_data_capture);
|
|
sbw_set_tclk();
|
|
|
|
sbw_clr_tclk();
|
|
sbw_tap_shift_ir(msp430_ir_ctrl_sig_16bit);
|
|
sbw_tap_shift_dr(0x2401);
|
|
sbw_set_tclk();
|
|
}
|
|
|