flashing, test program
This commit is contained in:
parent
ad046185d3
commit
d4e34bb742
|
@ -1 +1,2 @@
|
|||
build/
|
||||
dat/
|
||||
|
|
76
src/main.c
76
src/main.c
|
@ -9,10 +9,20 @@
|
|||
#include "tap.h"
|
||||
#include "msp430dbg.h"
|
||||
|
||||
void printbuf(const uint8_t* buf, size_t size) {
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
printf("%02x%c", buf[i], i % 16 == 15 ? '\n' : ' ');
|
||||
}
|
||||
static uint16_t DATA_text[0x24] = {
|
||||
0xc232,0x43c2,0x0000,0x4031,0x02fe,0x40f2,0x00ff,0x002a,0x40b2,0x5a10,0x0120,
|
||||
0x43d2,0x0000,0xd232,0xd032,0x0018,0x3ffd,0xc3d2,0x0002,0xd3d2,0x0000,0xe3d2,
|
||||
0x0029,0x4130,0x1300,0x1300,0x1300,0x1300,0x1300,0x1300,0x12b0,0xf822,0x1300,
|
||||
0x1300,0x1300,0x3fdc
|
||||
};
|
||||
static uint16_t DATA_vectors[0x10] = {
|
||||
0xf830,0xf830,0xf832,0xf834,0xf836,0xf830,0xf830,0xf830,
|
||||
0xf838,0xf83a,0xf83c,0xf842,0xf830,0xf830,0xf844,0xf846
|
||||
};
|
||||
|
||||
// 2k/8k flash, 256b RAM
|
||||
static uint16_t dumpmem_ram[256>>1];
|
||||
static uint16_t dumpmem_flash[8192>>1];
|
||||
|
||||
int main() {
|
||||
gpio_init(PINOUT_SBW_TCK);
|
||||
|
@ -83,5 +93,63 @@ int main() {
|
|||
uint32_t initv = msp430_device_get(200e3);
|
||||
printf("init -> %08lx\n", initv);
|
||||
|
||||
/*msp430_memory_read_block(0x0f00, 16>>1, dumpmem_ram);
|
||||
printf("info dump:\n");
|
||||
for (size_t i = 0; i < ( 16>>1); i += 4) {
|
||||
printf("%04zx: %04x %04x %04x %04x\n",
|
||||
0x0f00+(i<<1), dumpmem_ram[i+0], dumpmem_ram[i+1],
|
||||
dumpmem_ram[i+2], dumpmem_ram[i+3]
|
||||
);
|
||||
}
|
||||
|
||||
msp430_memory_read_block(0x0200, 256>>1, dumpmem_ram);
|
||||
|
||||
printf("RAM dump:\n");
|
||||
for (size_t i = 0; i < (256>>1); i += 4) {
|
||||
printf("%04zx: %04x %04x %04x %04x\n",
|
||||
0x0200+(i<<1), dumpmem_ram[i+0], dumpmem_ram[i+1],
|
||||
dumpmem_ram[i+2], dumpmem_ram[i+3]
|
||||
);
|
||||
}
|
||||
|
||||
msp430_memory_read_block(0xe000, 8192>>1, dumpmem_flash);
|
||||
|
||||
printf("flash dump:\n");
|
||||
for (size_t i = 0; i < (8192>>1); i += 4) {
|
||||
printf("%04zx: %04x %04x %04x %04x\n",
|
||||
0xe000+(i<<1), dumpmem_flash[i+0], dumpmem_flash[i+1],
|
||||
dumpmem_flash[i+2], dumpmem_flash[i+3]
|
||||
);
|
||||
}*/
|
||||
|
||||
/*printf("flashing text...\n");
|
||||
for (size_t i = 0; i < 0x24; ++i) {
|
||||
printf("%zu : %04x\n", DATA_text[i]);
|
||||
msp430_flash_write(0xf800 + (i*2), 1, &DATA_text[i]);
|
||||
}
|
||||
printf("flashing vectors...\n");
|
||||
for (size_t i = 0; i < 0x10; ++i) {
|
||||
msp430_flash_write(0xffe0 + (i*2), 1, &DATA_vectors[i]);
|
||||
}*/
|
||||
|
||||
/*printf("dumping for check...\n");
|
||||
msp430_memory_read_block(0xf800, 0x0800>>1, dumpmem_flash);
|
||||
|
||||
printf("flash dump:\n");
|
||||
for (size_t i = 0; i < (2048>>1); i += 4) {
|
||||
printf("%04zx: %04x %04x %04x %04x\n",
|
||||
0xf800+(i<<1), dumpmem_flash[i+0], dumpmem_flash[i+1],
|
||||
dumpmem_flash[i+2], dumpmem_flash[i+3]
|
||||
);
|
||||
}*/
|
||||
|
||||
/*msp430_memory_write8(0x0024, 0x00); // P2IE =0x00 (no irq)
|
||||
msp430_memory_write8(0x002e, 0x00); // P2SEL=0x00 (gpio)
|
||||
msp430_memory_write8(0x0042, 0x00); // P2SEL2=0 (gpio)
|
||||
msp430_memory_write8(0x002a, 0xff); // P2DIR=0xff (all out)
|
||||
msp430_memory_write8(0x0029, 0x01); // P2OUT=0x01 (P2.0 hi)*/
|
||||
|
||||
msp430_device_release(0xfffe/*0xf800*/);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
198
src/msp430dbg.c
198
src/msp430dbg.c
|
@ -274,7 +274,8 @@ uint32_t msp430_device_get(float freq) {
|
|||
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(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
|
||||
|
@ -301,5 +302,200 @@ uint32_t msp430_device_get(float freq) {
|
|||
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();
|
||||
}
|
||||
|
||||
|
|
130
src/msp430dbg.h
130
src/msp430dbg.h
|
@ -5,43 +5,103 @@
|
|||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// also seen: 8D 91 95 99
|
||||
#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,
|
||||
//!all these // EMEX == EEM
|
||||
msp430_ir_emex_data_exchange = 0x09,
|
||||
msp430_ir_emex_read_trigger = 0x0a, // unused? / unknown
|
||||
msp430_ir_emex_read_control = 0x0b,
|
||||
msp430_ir_emex_write_control = 0x0c,
|
||||
msp430_ir_emex_data_exchange32 = 0x0d, // 430X/Xv2-only
|
||||
|
||||
msp430_ir_data_to_addr = 0x85,
|
||||
msp430_ir_data_16bit = 0x41,
|
||||
msp430_ir_data_quick = 0x43,
|
||||
// overlaps with EMEX!
|
||||
msp430_ir_bp_cntl_16bit = 0x09, // unused? / unknown // == data_exchange
|
||||
msp430_ir_bp_cntl_capture = 0x0a, // unused? / unknown
|
||||
msp430_ir_bp1_16bit = 0x0b, // unused? / unknown
|
||||
msp430_ir_bp1_capture = 0x0c, // unused? / unknown
|
||||
msp430_ir_bp2_16bit = 0x0d, // unused? / unknown
|
||||
msp430_ir_bp2_capture = 0x0e, // unused? / unknown
|
||||
|
||||
msp430_ir_ctrl_sig_16bit = 0x13,
|
||||
msp430_ir_ctrl_sig_capture = 0x14, // 0010 1000 <=> 0x28
|
||||
msp430_ir_ctrl_sig_release = 0x15,
|
||||
msp430_ir_ctrl_sig_high_byte = 0x11,
|
||||
msp430_ir_ctrl_sig_low_byte = 0x12,
|
||||
msp430_ir_ctrl_sig_16bit = 0x13,
|
||||
msp430_ir_ctrl_sig_capture = 0x14,
|
||||
msp430_ir_ctrl_sig_release = 0x15,
|
||||
msp430_ir_coreip_id = 0x17, // pointer to more data on non-0x89 JTAG IDs?
|
||||
msp430_ir_jstate_id = 0x18, // JState is Xv2 stuff so eh // NOTE: 64-bit DRshift!
|
||||
|
||||
msp430_ir_data_psa = 0x44,
|
||||
msp430_ir_shift_out_psa = 0x46,
|
||||
msp430_ir_flash_16bit_update = 0x19, // "disable flash test mode"?
|
||||
msp430_ir_flash_capture = 0x1a, // unused? / unknown
|
||||
msp430_ir_flash_16bit_in = 0x1b, // unused? / unknown
|
||||
msp430_ir_flash_update = 0x1c, // unused? / unknown
|
||||
// sesel = 0x0080, tmr = 0x0800
|
||||
|
||||
msp430_ir_cntrl = 0x21, // unused? / unknown
|
||||
msp430_ir_fuse_prepare_blow = 0x22,
|
||||
msp430_ir_fuse_ex_blow = 0x24,
|
||||
msp430_ir_config_fuses = 0x29, // get fuse state? uses 8-bit DRshift!
|
||||
|
||||
msp43_ir_test_reg = 0x2a, // Xv2-only
|
||||
msp43_ir_test_v3_reg = 0x2f,
|
||||
// TODO: what is LPM? something with power? related to LPMx.5
|
||||
|
||||
// "embedded signal processing cell" control
|
||||
msp430_ir_dual_8bit = 0x31,
|
||||
msp430_ir_dual_capture = 0x32,
|
||||
msp430_ir_select_main = 0x33,
|
||||
msp430_ir_select_esp = 0x34,
|
||||
|
||||
msp430_ir_tclk_toggle_inst = 0x39, // unused? / unknown
|
||||
msp430_ir_tclk_0_inst = 0x3a, // unused? / unknown
|
||||
msp430_ir_tclk_1_inst = 0x3b, // unused? / unknown
|
||||
|
||||
msp430_ir_data_16bit = 0x41,
|
||||
msp430_ir_data_capture = 0x42,//! // reads from data bus?
|
||||
msp430_ir_data_quick = 0x43,
|
||||
msp430_ir_data_psa = 0x44,
|
||||
msp430_ir_data_16bit_opt = 0x45, // unused? / unknown
|
||||
msp430_ir_shift_out_psa = 0x46,
|
||||
msp430_ir_dta = 0x47, // unused? / unknown
|
||||
|
||||
msp430_ir_accept_key = 0x59, // unused? / unknown
|
||||
|
||||
msp430_ir_jmb_exchange = 0x61,
|
||||
|
||||
msp430_ir_tdo_event = 0x64, // unused? / unknown
|
||||
msp430_ir_tdo_event_ctl = 0x65, // unused? / unknown
|
||||
|
||||
msp430_ir_addr_high_byte = 0x81,
|
||||
msp430_ir_addr_low_byte = 0x82,
|
||||
msp430_ir_addr_16bit = 0x83,
|
||||
msp430_ir_addr_capture = 0x84,
|
||||
msp430_ir_data_to_addr = 0x85,
|
||||
msp430_ir_capture_cpu_reg = 0x86, // unused? / unknown
|
||||
msp430_ir_device_id = 0x87, // "device ip pointer" for non-0x89 JTAG IDs
|
||||
|
||||
msp430_ir_jmb_write_32bit_mode = 0x88,//!
|
||||
|
||||
msp430_ir_bypass = 0xff
|
||||
};
|
||||
|
||||
enum msp430_ctrl {
|
||||
msp430_ctrl_RnW = 1<< 0,
|
||||
msp430_ctrl_cpu_halt = 1<< 1,
|
||||
msp430_ctrl_intr_req = 1<< 2,
|
||||
msp430_ctrl_halt_jtag = 1<< 3,
|
||||
msp430_ctrl_byte = 1<< 4,
|
||||
msp430_ctrl_cpu_off = 1<< 5,
|
||||
msp430_ctrl_mclk_on = 1<< 6,
|
||||
msp430_ctrl_instr_load = 1<< 7,
|
||||
msp430_ctrl_tmode = 1<< 8,
|
||||
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,
|
||||
msp430_ctrl_stop_sel = 1<<15,
|
||||
};
|
||||
|
||||
bool msp430_check_fuse_blown(void);
|
||||
|
@ -57,18 +117,60 @@ 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);
|
||||
void msp430_memory_read_block(uint16_t srcaddr, uint16_t numwords, uint16_t* dest);
|
||||
void msp430_memory_write_block(uint16_t dstaddr, uint16_t numwords, const uint16_t* src);
|
||||
bool msp430_memory_verify(uint16_t startaddr, uint16_t length, const uint16_t* copy);
|
||||
|
||||
#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);//
|
||||
|
||||
// TODO: erase routine needs to be redone
|
||||
void msp430_flash_erase_seg(uint16_t startaddr, bool is_infosegA);//
|
||||
void msp430_flash_erase_mass(bool withinfomem); // false: only main flash
|
||||
|
||||
uint32_t msp430_device_get(float freq);
|
||||
|
||||
// TODO: from non-slau320aj src
|
||||
uint16_t msp430_read_jmb(void);
|
||||
void msp430_write_jmb(uint16_t v);
|
||||
|
||||
uint16_t msp430_cpureg_read(short regno);
|
||||
void msp430_cpureg_write(short regno, uint16_t value);
|
||||
|
||||
// TODO:
|
||||
// 430X and Xv2 versions of the above routines
|
||||
//
|
||||
// EnableLpmx5
|
||||
// DisableLpmx5
|
||||
// what do these do? it's something about power mode, it's disabled when
|
||||
// starting JTAG, and reenabled when releasing JTAG
|
||||
// only MSP430Xv2, though, so we're not going to care for now. (I don't
|
||||
// have such chips, only an MSP430G2212 and a G2452)
|
||||
// uses test_reg and test_reg_3V
|
||||
//
|
||||
// jstate_read
|
||||
// what is this for? (Xv2-only -> let's not care for this either now)
|
||||
// uses 64-bit DRshift!
|
||||
// -> PollJStateReg, HilCommand, SingleStepJState
|
||||
//
|
||||
// eem_write_control
|
||||
// used in save & restore context stuff / jtag start & release
|
||||
// eem_read_control
|
||||
// used where write_control is used, but also "wait for eem" and single-step
|
||||
// eem_data_exchange
|
||||
// used in a lot of places: write_control places, single-step, wait for storage, "eemdataexchange", execute funclet
|
||||
//
|
||||
// what is EEM? what is its sub-command stuff?
|
||||
//
|
||||
// wait for EEM
|
||||
// JTAG release with context restore
|
||||
// JTAG start with context save
|
||||
// single-step
|
||||
// wait for storage(?)
|
||||
// execute funclet
|
||||
// get dco frequency // annoying
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
trace.log
|
||||
*.bin
|
||||
*.h
|
||||
*.elf
|
||||
*.map
|
||||
*.o
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
AS := msp430-gcc
|
||||
CC := msp430-gcc
|
||||
LD := msp430-gcc
|
||||
OBJCOPY := msp430-objcopy
|
||||
|
||||
all: test.bin
|
||||
|
||||
test.S.o: test.S
|
||||
$(AS) -c -o "$@" "$<"
|
||||
|
||||
test.elf test.elf.map: test.S.o link.ld
|
||||
$(LD) -o "$@" "$<" -T link.ld -Wl,-Map="$@.map" -nostdlib -nostartfiles
|
||||
|
||||
test.bin: test.elf
|
||||
$(OBJCOPY) -O binary "$<" "$@"
|
||||
|
||||
clean:
|
||||
@$(RM) -v test.bin test.bin.h test.elf test.elf.map test.S.o
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import os, re, sys, struct
|
||||
import textwrap
|
||||
import traceback
|
||||
|
||||
|
||||
def sanitize_name(name):
|
||||
# replace special characters with underscores
|
||||
name = re.sub('[^a-zA-Z0-9_]', '_', name)
|
||||
# clean up
|
||||
name = name.strip('_')
|
||||
|
||||
# not needed: 'DATA_' prefix
|
||||
#if name[0] in "0123456789": name = '_' + name
|
||||
|
||||
return name
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Convert data files into byte arrays in a C header")
|
||||
|
||||
parser.add_argument('input', nargs='*', action='append',
|
||||
help="Input data file to convert to a header file. If "
|
||||
+"none are specified, data is read from standard input.")
|
||||
parser.add_argument('--output', type=str, default=None,
|
||||
help="Output header file path, standard output if none specified")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
#print(repr(args), file=sys.stderr)
|
||||
|
||||
inputfiles = args.input[0]
|
||||
datafiles = {}
|
||||
|
||||
if len(inputfiles) == 0:
|
||||
# need to read from stdio
|
||||
datafiles['data'] = sys.stdin.buffer.read()
|
||||
else:
|
||||
for path in inputfiles:
|
||||
# cannot use os.access, POSIX-only
|
||||
if not os.path.exists(path) or os.path.isdir(path):
|
||||
print("ERROR: input path '%s' does not exist, or is not a file" % path)
|
||||
sys.exit(1)
|
||||
|
||||
# get base name of the path (no folder names, no extension)
|
||||
name = os.path.splitext(os.path.split(path)[1])[0]
|
||||
# make it usable for C code names
|
||||
name = sanitize_name(name)
|
||||
|
||||
# now read the data
|
||||
data = None
|
||||
try:
|
||||
with open(path, 'rb') as f:
|
||||
data = f.read()
|
||||
except IOError:
|
||||
print("ERROR: input file '%s' not readable" % path)
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
|
||||
data = struct.unpack('<'+('H'*(len(data)//2)), data)
|
||||
|
||||
# add it to the list
|
||||
datafiles[name] = data
|
||||
|
||||
#print(repr(datafiles), file=sys.stderr)
|
||||
|
||||
outname = "hardcoded_data"
|
||||
if args.output is not None:
|
||||
outname = os.path.splitext(os.path.split(args.output)[1])[0]
|
||||
outname = sanitize_name(outname)
|
||||
|
||||
# generate the C source code: one uint8_t array for each data file
|
||||
# variable name is "DATA_<datafile>"
|
||||
# (width=84 is the equivalent of 16 bytes/line)
|
||||
headersrc = '\n\n'.join(
|
||||
"static uint16_t DATA_%s[%d] = {\n%s\n};" % (name, len(data), \
|
||||
textwrap.fill(','.join("0x%04x" % b for b in data), width=81,
|
||||
initial_indent=" ", subsequent_indent=" ")
|
||||
) for name, data in datafiles.items()
|
||||
)
|
||||
|
||||
# a C header needs include guards
|
||||
headersrc = """
|
||||
#ifndef AUTOGEN_{0}_H_
|
||||
#define AUTOGEN_{0}_H_
|
||||
|
||||
{1}
|
||||
|
||||
#endif
|
||||
""".format(outname.upper(), headersrc)
|
||||
|
||||
#print(headersrc, file=sys.stderr)
|
||||
|
||||
if args.output is None:
|
||||
# no output specified -> output to stdout
|
||||
sys.stdout.write(headersrc)
|
||||
else:
|
||||
try:
|
||||
with open(args.output, 'w') as f:
|
||||
f.write(headersrc)
|
||||
except IOError:
|
||||
print("ERROR: output file '%s' not writable" % args.output)
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
OUTPUT_FORMAT("elf32-msp430","elf32-msp430","elf32-msp430")
|
||||
OUTPUT_ARCH(msp:14)
|
||||
ENTRY(_start)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
data (rwx) : ORIGIN = 0x0200, LENGTH = 0x100
|
||||
text (rx) : ORIGIN = 0xf800, LENGTH = 0x800 - 0x20
|
||||
vectors (rw) : ORIGIN = 0xffe0, LENGTH = 0x20
|
||||
}
|
||||
|
||||
SECTIONS {
|
||||
/* Internal text space. */
|
||||
.text :
|
||||
{
|
||||
. = ALIGN(2);
|
||||
*(SORT_NONE(.init))
|
||||
*(SORT_NONE(.init0)) /* Start here after reset. */
|
||||
*(SORT_NONE(.init1))
|
||||
*(SORT_NONE(.init2)) /* Copy data loop */
|
||||
*(SORT_NONE(.init3))
|
||||
*(SORT_NONE(.init4)) /* Clear bss */
|
||||
*(SORT_NONE(.init5))
|
||||
*(SORT_NONE(.init6)) /* C++ constructors. */
|
||||
*(SORT_NONE(.init7))
|
||||
*(SORT_NONE(.init8))
|
||||
*(SORT_NONE(.init9)) /* Call main(). */
|
||||
__ctors_start = . ;
|
||||
*(.ctors)
|
||||
__ctors_end = . ;
|
||||
__dtors_start = . ;
|
||||
*(.dtors)
|
||||
__dtors_end = . ;
|
||||
. = ALIGN(2);
|
||||
*(.lower.text.* .lower.text)
|
||||
. = ALIGN(2);
|
||||
*(.text)
|
||||
. = ALIGN(2);
|
||||
*(.text.*)
|
||||
. = ALIGN(2);
|
||||
*(.text:*)
|
||||
. = ALIGN(2);
|
||||
*(SORT_NONE(.fini9))
|
||||
*(SORT_NONE(.fini8))
|
||||
*(SORT_NONE(.fini7))
|
||||
*(SORT_NONE(.fini6)) /* C++ destructors. */
|
||||
*(SORT_NONE(.fini5))
|
||||
*(SORT_NONE(.fini4))
|
||||
*(SORT_NONE(.fini3))
|
||||
*(SORT_NONE(.fini2))
|
||||
*(SORT_NONE(.fini1))
|
||||
*(SORT_NONE(.fini0)) /* Infinite loop after program termination. */
|
||||
*(SORT_NONE(.fini))
|
||||
_etext = .;
|
||||
} > text =0xff
|
||||
|
||||
.rodata :
|
||||
{
|
||||
. = ALIGN(2);
|
||||
*(.lower.rodata.* .lower.rodata)
|
||||
. = ALIGN(2);
|
||||
*(.plt)
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.* .const .const:*)
|
||||
*(.rodata1)
|
||||
*(.eh_frame_hdr)
|
||||
KEEP (*(.eh_frame))
|
||||
KEEP (*(.gcc_except_table)) *(.gcc_except_table.*)
|
||||
PROVIDE (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE (__preinit_array_end = .);
|
||||
PROVIDE (__init_array_start = .);
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array))
|
||||
PROVIDE (__init_array_end = .);
|
||||
PROVIDE (__fini_array_start = .);
|
||||
KEEP (*(.fini_array))
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
PROVIDE (__fini_array_end = .);
|
||||
LONG(0); /* Sentinel. */
|
||||
/* gcc uses crtbegin.o to find the start of the constructors, so
|
||||
we make sure it is first. Because this is a wildcard, it
|
||||
doesn't matter if the user does not actually link against
|
||||
crtbegin.o; the linker won't look for a file to match a
|
||||
wildcard. The wildcard also means that it doesn't matter which
|
||||
directory crtbegin.o is in. */
|
||||
KEEP (*crtbegin*.o(.ctors))
|
||||
/* We don't want to include the .ctor section from from the
|
||||
crtend.o file until after the sorted ctors. The .ctor section
|
||||
from the crtend file contains the end of ctors marker and it
|
||||
must be last */
|
||||
KEEP (*(EXCLUDE_FILE (*crtend*.o ) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
KEEP (*crtbegin*.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
} > text =0xff
|
||||
|
||||
.vectors :
|
||||
{
|
||||
PROVIDE (__vectors_start = .) ;
|
||||
*(.vectors*)
|
||||
_vectors_end = . ;
|
||||
} > vectors =0xff
|
||||
|
||||
.data :
|
||||
{
|
||||
PROVIDE (__data_start = .) ;
|
||||
PROVIDE (__datastart = .) ;
|
||||
. = ALIGN(2);
|
||||
KEEP (*(.jcr))
|
||||
*(.data.rel.ro.local) *(.data.rel.ro*)
|
||||
*(.dynamic)
|
||||
. = ALIGN(2);
|
||||
*(.lower.data.* .lower.data)
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d*)
|
||||
KEEP (*(.gnu.linkonce.d.*personality*))
|
||||
*(.data1)
|
||||
*(.got.plt) *(.got)
|
||||
. = ALIGN(2);
|
||||
*(.sdata .sdata.* .gnu.linkonce.s.*)
|
||||
. = ALIGN(2);
|
||||
_edata = . ;
|
||||
} > data AT> text
|
||||
.bss SIZEOF(.data) + ADDR(.data) :
|
||||
{
|
||||
. = ALIGN(2);
|
||||
PROVIDE (__bss_start = .) ;
|
||||
*(.lower.bss.* .lower.bss)
|
||||
. = ALIGN(2);
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
PROVIDE (__bss_end = .) ;
|
||||
_end = . ;
|
||||
} > data
|
||||
.noinit SIZEOF(.bss) + ADDR(.bss) :
|
||||
{
|
||||
PROVIDE (__noinit_start = .) ;
|
||||
*(.noinit)
|
||||
*(COMMON)
|
||||
PROVIDE (__noinit_end = .) ;
|
||||
_end = . ;
|
||||
} > data
|
||||
|
||||
|
||||
.fill :
|
||||
{
|
||||
FILL(0xffffffff);
|
||||
. = ORIGIN(vectors);
|
||||
} > text
|
||||
|
||||
.MP430.attributes 0 :
|
||||
{
|
||||
KEEP (*(.MSP430.attributes))
|
||||
KEEP (*(.gnu.attributes))
|
||||
KEEP (*(__TI_build_attributes))
|
||||
}
|
||||
PROVIDE (__stack = 0x2fe) ;
|
||||
PROVIDE (__data_start_rom = _etext) ;
|
||||
PROVIDE (__data_end_rom = _etext + SIZEOF (.data)) ;
|
||||
PROVIDE (__noinit_start_rom = _etext + SIZEOF (.data)) ;
|
||||
PROVIDE (__noinit_end_rom = _etext + SIZEOF (.data) + SIZEOF (.noinit)) ;
|
||||
PROVIDE (__subdevice_has_heap = 0) ;
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
; vim: set ft=gas:
|
||||
|
||||
#define CPUOFF (1<<4)
|
||||
#define GIE (1<<3)
|
||||
|
||||
#define IE1 0x0000
|
||||
#define IFG1 0x0002
|
||||
|
||||
#define WDTCTL 0x0120
|
||||
|
||||
#define USICTL0 0x0078
|
||||
#define USICTL1 0x0079
|
||||
#define USICKCTL 0x007a
|
||||
#define USICNT 0x007b
|
||||
#define USISR 0x007c
|
||||
|
||||
#define BCSCTL3 0x0053
|
||||
#define BCSCTL2 0x0058
|
||||
#define BCSCTL1 0x0057
|
||||
#define DCOCTL 0x0056
|
||||
|
||||
#define P2SEL2 0x0042
|
||||
#define P2REN 0x002f
|
||||
#define P2SEL 0x002e
|
||||
#define P2IE 0x002d
|
||||
#define P2IES 0x002c
|
||||
#define P2IFG 0x002b
|
||||
#define P2DIR 0x002a
|
||||
#define P2OUT 0x0029
|
||||
#define P2IN 0x0028
|
||||
|
||||
#define P1SEL2 0x0041
|
||||
#define P1REN 0x0027
|
||||
#define P1SEL 0x0026
|
||||
#define P1IE 0x0024
|
||||
#define P1IES 0x0024
|
||||
#define P1IFG 0x0023
|
||||
#define P1DIR 0x0022
|
||||
#define P1OUT 0x0021
|
||||
#define P1IN 0x0020
|
||||
|
||||
.section ".text.startup._start", "ax", %progbits
|
||||
|
||||
.global _start
|
||||
_start:
|
||||
dint
|
||||
|
||||
mov.b #0, &IE1
|
||||
|
||||
mov.w #__stack, sp
|
||||
|
||||
mov.b #0, &P2IE
|
||||
mov.b #0, &P2SEL
|
||||
mov.b #0, &P2SEL2
|
||||
mov.b #0xff, &P2DIR
|
||||
|
||||
; TODO: configure wdt
|
||||
mov.w #((0x5a<<8)|(1<<4)), &WDTCTL
|
||||
|
||||
mov.b #1, &IE1
|
||||
|
||||
eint
|
||||
|
||||
lockup:
|
||||
|
||||
; enter LPM0 for power save stuff
|
||||
bis #(GIE|CPUOFF), sr
|
||||
|
||||
jmp lockup
|
||||
|
||||
|
||||
.section ".text.callback", "ax", %progbits
|
||||
|
||||
wdt_callback:
|
||||
bic.b #1, &IFG1
|
||||
bis.b #1, &IE1
|
||||
|
||||
xor.b #1, &P2OUT
|
||||
|
||||
ret
|
||||
|
||||
|
||||
.section ".vectors", "ax", %progbits
|
||||
|
||||
_VECTORS:
|
||||
|
||||
.2byte ISR_unk ; ffe0
|
||||
.2byte ISR_unk ; ffe2
|
||||
.2byte ISR_port1 ; ffe4
|
||||
.2byte ISR_port2 ; ffe6
|
||||
.2byte ISR_USI ; ffe8
|
||||
.2byte ISR_unk ; ffea ; (ADC10, not on this chip)
|
||||
.2byte ISR_unk ; ffec
|
||||
.2byte ISR_unk ; ffee
|
||||
.2byte ISR_timer0 ; fff0
|
||||
.2byte ISR_timer1 ; fff2
|
||||
.2byte ISR_wdt ; fff4
|
||||
.2byte ISR_cmpA ; fff6
|
||||
.2byte ISR_unk ; fff8
|
||||
.2byte ISR_unk ; fffa
|
||||
.2byte ISR_NMI ; fffc
|
||||
.2byte ISR_RST ; fffe
|
||||
|
||||
.section ".text.isr.unk", "ax", %progbits
|
||||
ISR_unk:
|
||||
reti
|
||||
|
||||
.section ".text.isr.port1", "ax", %progbits
|
||||
ISR_port1:
|
||||
reti
|
||||
|
||||
.section ".text.isr.port2", "ax", %progbits
|
||||
ISR_port2:
|
||||
reti
|
||||
|
||||
.section ".text.isr.usi", "ax", %progbits
|
||||
ISR_USI:
|
||||
reti
|
||||
|
||||
.section ".text.isr.timer0", "ax", %progbits
|
||||
ISR_timer0:
|
||||
reti
|
||||
|
||||
.section ".text.isr.timer1", "ax", %progbits
|
||||
ISR_timer1:
|
||||
reti
|
||||
|
||||
.section ".text.isr.wdt", "ax", %progbits
|
||||
ISR_wdt:
|
||||
call #wdt_callback
|
||||
reti
|
||||
|
||||
.section ".text.isr.cmpA", "ax", %progbits
|
||||
ISR_cmpA:
|
||||
reti
|
||||
|
||||
.section ".text.isr.nmi", "ax", %progbits
|
||||
ISR_NMI:
|
||||
reti
|
||||
|
||||
.section ".text.isr.rst", "ax", %progbits
|
||||
ISR_RST:
|
||||
jmp _start
|
||||
|
Loading…
Reference in New Issue