get stuff to work, mostly. Programming command etc. are still a hazard

This commit is contained in:
Triss 2021-11-15 15:31:56 +01:00
parent a5a3a99fa4
commit bbd127da3f
23 changed files with 704 additions and 39 deletions

View File

@ -29,6 +29,30 @@ static uint16_t DATA_vectors[0x10] = {
static uint16_t dumpmem_ram[256>>1];
static uint16_t dumpmem_flash[8192>>1];*/
static uint8_t DATA_test_rom[256] = { // RL78
0xce, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x7f, 0xe8,
0x85, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xd9,
0x00, 0xfd, 0xdd, 0x00, 0xfd, 0xee, 0x00, 0xef, 0xfe, 0x71, 0x7b, 0xfa, 0xd7,
0x71, 0x38, 0x23, 0xff, 0x71, 0x38, 0x33, 0x00, 0x71, 0x68, 0x77, 0x00, 0x71,
0x38, 0x53, 0x00, 0xd7, 0x71, 0x30, 0x03, 0xff, 0x00, 0x00, 0x71, 0x38, 0x03,
0xff, 0xef, 0xf4, 0xd7, 0xd7, 0xff, 0xff, 0xff, 0xff
};
static void test_sbw(void) {
gpio_init(PINOUT_SBW_TCK);
gpio_set_function(PINOUT_SBW_TCK, GPIO_FUNC_SIO);
@ -178,9 +202,11 @@ static void tool78_testtest() {
}
static void tool78_prototest() {
struct tool78_hw* hw = &tool78_hw_rl78_uart1;
tool78_silicon_sig_t sig;
memset(&sig, 0, sizeof sig);
enum tool78_stat st = tool78_init(&tool78_hw_rl78_uart1, &sig);
enum tool78_stat st = tool78_init_sfp(&tool78_hw_rl78_uart1, &sig);
printf("result: 0x%02x. sig:\n", st);
for (size_t i = 0; i < sizeof(struct tool78_silicon_sig_rl78); ++i)
printf("0x%02x ", ((const uint8_t*)&sig)[i]);
@ -196,12 +222,31 @@ static void tool78_prototest() {
printf("secget: 0x%02x\n", st);
printf("sec: flg=%02x bot=%02x fsws=%04x fswe=%04x\n", sec.flg, sec.bot, sec.fsws, sec.fswe);
//st = tool78_do_security_release(&tool78_hw_rl78_uart1);
//printf("sec rel: 0x%02x\n", st);
/*st = tool78_do_block_blank_check(hw, 0, 0x0ff, false);
printf("blank check: 0x%02x\n", st);
st = tool78_do_programming(hw, 0, 0x000ff, DATA_test_rom);
printf("programming: 0x%02x\n", st);*/
st = tool78_do_verify(hw, 0, 0x0ff, DATA_test_rom);
printf("verify: 0x%02x\n", st);
}
static void tool78_ocdtest() {
uint8_t passwd[10] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
uint16_t ver=0;
enum tool78_stat st = tool78_init_ocd(&tool78_hw_rl78_uart1, &ver, passwd);
printf("result: 0x%02x ver=%04x\n", st, ver);
}
int main() {
stdio_init_all();
//tool78_testtest();
tool78_prototest();
//tool78_ocdtest();
//piotest();
return 0;
}

View File

@ -106,14 +106,15 @@ static const struct delayvalues delays[23] = {
static enum tool78_stat tool78_data_send(struct tool78_hw* hw,
int len, const uint8_t* data, bool final_block) {
//printf("datasend: len=%d data=%02x %02x %02x ...\n", len, data[0], data[1], data[2]);
if (len == 0) return tool78_stat_ack;
if (len > 0x100) return tool78_stat_internal_error;
len &= 0xff;
uint8_t lenfield = len & 0xff;
uint8_t pre[2], // soh, len
post[2]; // cksum, etx
pre[0] = tool78_frame_soh;
pre[1] = len;
uint8_t pre[2], // stx, len
post[2]; // cksum, etx/etb
pre[0] = tool78_frame_stx;
pre[1] = lenfield;
post[0] = 0; // checksum
post[1] = final_block ? tool78_frame_etx : tool78_frame_etb;
@ -122,12 +123,17 @@ static enum tool78_stat tool78_data_send(struct tool78_hw* hw,
if (len) r = tool78_digest_checksum8(r, len, data);
post[0] = r;
//printf("data cksum=%02x\n", r);
int rr = hw->send(2, pre, -1);
if (rr != 3) return tool78_stat_internal_error;
if (rr != 2) return tool78_stat_internal_error;
if (len) {
rr = hw->send(len, data, -1);
if (rr != len) return tool78_stat_internal_error;
if (rr != len) {
//printf("data not sent properly: %d\n", r);
return tool78_stat_internal_error;
}
}
rr = hw->send(2, post, -1);
@ -138,7 +144,7 @@ static enum tool78_stat tool78_data_send(struct tool78_hw* hw,
static enum tool78_stat tool78_cmd_send(struct tool78_hw* hw, uint8_t cmd,
int len, const uint8_t* data) {
if (len > 0x100) return tool78_stat_internal_error;
if (len >= 0x100) return tool78_stat_internal_error;
uint8_t lenfield = len &= 0xff;
busy_wait_us_32(tCOM); // aka tSN6(/tDN6?) (reset?) or tMB (others?)
@ -315,14 +321,24 @@ enum tool78_stat tool78_do_baud_rate_set(struct tool78_hw* hw) {
st = tool78_wait_status(hw, 3, tWT10); // aka tCS6
//printf("brs stat=0x%02x\n", st);
if (st != tool78_stat_ack) return st;
// let's ignore the two data bytes for now
// now at 115.2kbaud, so let the physical layer switch to it
hw->set_baudrate(115200);
hw->flags |= tool78_hw_flag_done_reset;
// let's ignore the two data bytes for now
if (hw->flags & tool78_hw_flag_do_ocd) {
// wait for ack 0x00 byte
uint8_t byte = 0xff;
int rr = hw->recv(1, &byte, 10000);
if (rr != 1) st = tool78_stat_timeout_error;
else if (byte != 0) st = tool78_stat_protocol_error;
else st = tool78_stat_ack;
} else {
st = tool78_do_reset(hw);
}
break;
case tool78_mcu_78k0: default:
return tool78_stat_bad_mcu_for_cmd;
@ -374,6 +390,8 @@ enum tool78_stat tool78_do_chip_erase(struct tool78_hw* hw) {
enum tool78_stat tool78_do_block_erase(struct tool78_hw* hw, uint32_t start, uint32_t end) {
bool isrl78 = (hw->target & tool78_mcu_mask) == tool78_mcu_rl78;
if (isrl78) end = 0xffffff;
if (start >= end) return 0;
uint8_t data[6];
// on the rl78, the end address is ignored/unused and it's little-endian
@ -403,6 +421,7 @@ enum tool78_stat tool78_do_block_erase(struct tool78_hw* hw, uint32_t start, uin
enum tool78_stat tool78_do_programming(struct tool78_hw* hw, uint32_t start,
uint32_t end, const uint8_t* src) {
if (start >= end) return 0;
bool isrl78 = (hw->target & tool78_mcu_mask) == tool78_mcu_rl78;
uint8_t data[6];
@ -428,17 +447,20 @@ enum tool78_stat tool78_do_programming(struct tool78_hw* hw, uint32_t start,
st = tool78_wait_status(hw, 1, tWT3); // aka tCS5
if (st != tool78_stat_ack) return st;
int nblocks = ((end - start + 255) / 256);
for (size_t off = 0; off < end - start; off += 256) {
size_t nbytes = end - start + 1;
int nblocks = ((nbytes + 255) / 256);
for (size_t off = 0; off < nbytes; off += 256) {
busy_wait_us_32(tSD5); // aka tFD3
size_t todo = (end - start) - off;
size_t todo = nbytes - off;
if (todo > 256) todo = 256;
bool finalblk = off + 256 >= (end - start);
bool finalblk = off + 256 >= nbytes;
//printf("prgmdata@%zu = %02x %02x %02x ...\n", off, src[off], src[off+1], src[off+2]);
st = tool78_data_send(hw, todo, &src[off], finalblk);
if (st != tool78_stat_ack) return st;
st = tool78_wait_status(hw, 2, tWT4); // aka tDS5
st = tool78_wait_status(hw, 2, tWT4*10); // aka tDS5
printf("prgm %zu st=%02x %02x fin=%c\n", off, st, databuf[1], finalblk?'t':'f');
if (st != tool78_stat_ack) return st;
st = databuf[1];
if (st != tool78_stat_ack) return st;
@ -452,6 +474,7 @@ enum tool78_stat tool78_do_programming(struct tool78_hw* hw, uint32_t start,
enum tool78_stat tool78_do_verify(struct tool78_hw* hw, uint32_t start,
uint32_t end, const uint8_t* src) {
if (start >= end) return 0;
bool isrl78 = (hw->target & tool78_mcu_mask) == tool78_mcu_rl78;
uint8_t data[6];
@ -477,13 +500,14 @@ enum tool78_stat tool78_do_verify(struct tool78_hw* hw, uint32_t start,
st = tool78_wait_status(hw, 1, tWT6); // aka tCS2
if (st != tool78_stat_ack) return st;
//int nblocks = ((end - start + 255) / 256);
size_t nbytes = end - start + 1;
//int nblocks = ((nbytes + 255) / 256);
for (size_t off = 0; off < end - start; off += 256) {
busy_wait_us_32(tSD2); // aka tFD3
size_t todo = (end - start) - off;
size_t todo = nbytes - off;
if (todo > 256) todo = 256;
bool finalblk = off + 256 >= (end - start);
bool finalblk = off + 256 >= nbytes;
st = tool78_data_send(hw, todo, &src[off], finalblk);
if (st != tool78_stat_ack) return st;
@ -498,6 +522,7 @@ enum tool78_stat tool78_do_verify(struct tool78_hw* hw, uint32_t start,
enum tool78_stat tool78_do_block_blank_check(struct tool78_hw* hw,
uint32_t start, uint32_t end, bool check_flash_opt /* RL78 only */) {
if (start >= end) return 0;
bool isrl78 = (hw->target & tool78_mcu_mask) == tool78_mcu_rl78;
uint8_t data[7];
@ -518,7 +543,8 @@ enum tool78_stat tool78_do_block_blank_check(struct tool78_hw* hw,
data[5] = (end >> 0) & 0xff;
}
int nblocks = ((end - start + 255) / 256);
size_t nbytes = end - start + 1;
int nblocks = ((nbytes + 255) / 256);
enum tool78_stat st = tool78_cmd_send(hw, tool78_cmd_block_blank_check,
isrl78 ? 7 : 6, data);
if (st != tool78_stat_ack) return st;
@ -563,10 +589,7 @@ enum tool78_stat tool78_do_silicon_signature(struct tool78_hw* hw,
if (st != tool78_stat_ack) return st;
//gpio_put(18, false);
// TODO: tool78_data_wait()
//do {
st = tool78_data_recv(hw, (uint8_t*)sig_dest, nbyte, tFD2); // aka tSD11
//} while (st == tool78_stat_busy);
//gpio_put(18, true);
//printf("silisig: data 0x%02x\n", st);
if (st != tool78_stat_ack) return st;
@ -604,6 +627,7 @@ enum tool78_stat tool78_do_version_get(struct tool78_hw* hw, tool78_version_t* v
enum tool78_stat tool78_do_checksum(struct tool78_hw* hw, uint32_t start,
uint32_t end, uint16_t* ckout) {
if (end <= start) return 0;
bool isrl78 = (hw->target & tool78_mcu_mask) == tool78_mcu_rl78;
uint8_t data[6];
@ -733,9 +757,114 @@ enum tool78_stat tool78_do_security_release(struct tool78_hw* hw) {
// ----
enum tool78_stat tool78_init(struct tool78_hw* hw, tool78_silicon_sig_t* sig) {
int tool78_ocd_version(struct tool78_hw* hw, uint16_t* ver) {
busy_wait_ms(1);
uint8_t bytes[3];
bytes[0] = tool78ocd_cmd_version;
int rr = hw->send(1, &bytes[0], -1);
// bytes[0] is tool78ocd_cmd_version echoed back
rr = hw->recv(3, bytes, 100000);
if (rr != 3) return -1;
*ver = bytes[1] | ((uint16_t)bytes[2] << 8);
printf("ver=%04x\n", *ver);
return 0;
}
int tool78_ocd_connect(struct tool78_hw* hw, const uint8_t passwd[10], uint8_t ck_off) {
busy_wait_ms(1);
uint8_t stuff[11];
uint8_t connst, cksum;
stuff[0] = tool78ocd_cmd_connect;
int rr = hw->send(1, &stuff[0], -1);
// stuff[1] is tool78ocd_cmd_connect echoed back
rr = hw->recv(2, &stuff[1], 100000);
connst=stuff[2];
if (rr != 2) return -1;
memcpy(stuff, passwd, 10);
cksum = stuff[10] = tool78_calc_ocd_checksum8(10, passwd) + ck_off;
busy_wait_ms(1);
rr = hw->send(11, stuff, -1);
// stuff[9] is the checksum byte echoed back
rr = hw->recv(2, &stuff[9], 100000);
if (rr != 2) return -2;
printf("cksum=0x%02x conn=%02x pw=%02x\n",
cksum, connst, stuff[10]);
return (uint32_t)connst | ((uint32_t)stuff[10] << 8);
}
int tool78_ocd_read(struct tool78_hw* hw, uint16_t off, uint8_t len,
uint8_t* data) {
busy_wait_ms(1);
uint8_t hdr[4];
hdr[0] = tool78ocd_cmd_read;
hdr[1] = off & 0xff;
hdr[2] = off >> 8;
hdr[3] = len;
int rr = hw->send(sizeof hdr, hdr, -1);
rr = hw->recv(len, data, 1000*len);
printf("ocd read %d\n", rr);
return (rr == len) ? 0 : -1;
}
int tool78_ocd_write(struct tool78_hw* hw, uint16_t addr, uint8_t len,
const uint8_t* data) {
busy_wait_ms(1);
uint8_t hdr[4];
hdr[0] = tool78ocd_cmd_write;
hdr[1] = addr & 0xff;
hdr[2] = addr >> 8;
hdr[3] = len;
int rr = hw->send(sizeof hdr, hdr, -1);
rr = hw->send(len, data, -1);
rr = hw->recv(1, hdr, 1000*len);
if (rr != 1) return -1;
return (hdr[0] == tool78ocd_cmd_write) ? 0 : -2;
}
int tool78_ocd_exec(struct tool78_hw* hw) {
busy_wait_ms(1);
uint8_t hdr[1];
hdr[0] = tool78ocd_cmd_exec;
int rr = hw->send(sizeof hdr, hdr, -1);
rr = hw->recv(1, hdr, 1000);
if (rr != 1) return -1;
return (hdr[0] == tool78ocd_cmd_exec) ? 0 : -2;
}
int tool78_ocd_leave(struct tool78_hw* hw, bool exit_to_ram) {
busy_wait_ms(1);
uint8_t hdr[2];
hdr[0] = exit_to_ram ? tool78ocd_cmd_exit_ram : tool78ocd_cmd_exit_reti;
int rr = hw->send(1, hdr, -1);
rr = hw->recv(1, &hdr[1], 1000);
if (rr != 1) return -1;
return (hdr[0] == hdr[1]) ? 0 : -2;
}
// ----
static enum tool78_stat tool78_init_common(struct tool78_hw* hw) {
if (!hw) return tool78_stat_internal_error;
hw->flags = 0;
hw->flags &= ~tool78_hw_flag_done_reset;
enum tool78_stat st = tool78_stat_ack;
for (size_t i = 0; i < 16; ++i) {
@ -745,7 +874,7 @@ enum tool78_stat tool78_init(struct tool78_hw* hw, tool78_silicon_sig_t* sig) {
if ((hw->target & tool78_mcu_mask) != tool78_mcu_rl78) {
st = tool78_do_reset(hw);
printf("done reset st=0x%02x\n", st);
} //else printf("no reset to do (rl78)\n");
}
if (st == tool78_stat_timeout_error) {
hw->deinit();
continue;
@ -759,6 +888,13 @@ enum tool78_stat tool78_init(struct tool78_hw* hw, tool78_silicon_sig_t* sig) {
printf("baudrate result=0x%02x\n", st);
if (st != tool78_stat_ack) return st;
return st;
}
enum tool78_stat tool78_init_sfp(struct tool78_hw* hw, tool78_silicon_sig_t* sig) {
enum tool78_stat st = tool78_init_common(hw);
if (st != tool78_stat_ack) return st;
st = tool78_do_silicon_signature(hw, sig);
printf("sig result=0x%02x\n", st);
if (st != tool78_stat_ack) return st;
@ -766,3 +902,22 @@ enum tool78_stat tool78_init(struct tool78_hw* hw, tool78_silicon_sig_t* sig) {
return st;
}
enum tool78_stat tool78_init_ocd(struct tool78_hw* hw, uint16_t* ver,
const uint8_t passwd[10]) {
hw->flags |= tool78_hw_flag_do_ocd;
int st = tool78_init_common(hw);
if (st != tool78_stat_ack) return st;
st = tool78_ocd_version(hw, ver);
uint8_t i = 0;
do {
st = tool78_ocd_connect(hw, passwd, i);
++i;
if (i == 0) break;
} while ((st & 0xff00) == 0xf300 && (st & 0xff) == 0xf1);
return st;
}

View File

@ -40,7 +40,23 @@ enum tool78_stat tool78_do_security_release(struct tool78_hw* hw);
// ----
enum tool78_stat tool78_init(struct tool78_hw* hw, tool78_silicon_sig_t* sig);
//int tool78_ocd_reset(struct tool78_hw* hw);
int tool78_ocd_version(struct tool78_hw* hw, uint16_t* ver);
int tool78_ocd_connect(struct tool78_hw* hw, const uint8_t passwd[10], uint8_t ck_off);
int tool78_ocd_read(struct tool78_hw* hw, uint16_t off, uint8_t len,
uint8_t* data); // only is able to read from 0xf0000
int tool78_ocd_write(struct tool78_hw* hw, uint16_t addr, uint8_t len,
const uint8_t* data);
int tool78_ocd_exec(struct tool78_hw* hw); // call 0xf07e0
int tool78_ocd_leave(struct tool78_hw* hw, bool exit_to_ram);
// ----
enum tool78_stat tool78_init_sfp(struct tool78_hw* hw, tool78_silicon_sig_t* sig);
enum tool78_stat tool78_init_ocd(struct tool78_hw* hw, uint16_t* ver,
const uint8_t passwd[10]);
#endif

View File

@ -125,10 +125,9 @@ enum tool78_stat {
// these commands use a checksum that is the bitwise complement from the usual
// checksum (used in the flash programming protocol)
enum tool78ocd_cmd {
tool78ocd_cmd_reset = 0x00,
//tool78ocd_cmd_reset = 0x00,
tool78ocd_cmd_version = 0x90, // also called "ping"
// also called "unlock", as it *always* required a 10-byte passphrase (but
// not always checked, depending on protection status)
// also called "unlock", as it requires a 10-byte passphrase
tool78ocd_cmd_connect = 0x91,
// read from memory?
tool78ocd_cmd_read = 0x92,
@ -163,7 +162,13 @@ static inline uint8_t tool78_calc_checksum8(size_t len, const uint8_t* data) {
return tool78_digest_checksum8(0, len, data);
}
static inline uint8_t tool78_calc_ocd_checksum8(size_t len, const uint8_t* data) {
return ~tool78_calc_checksum8(len, data);
//return /*~*/(tool78_calc_checksum8(len, data)/*+1*/)&0xff;
uint8_t r = 0;
for (size_t i = 0; i < len; ++i) r = r + data[i];
r = (r - 1) & 0xff;
// if corrupt checksum:
r = (r + 1) & 0xff;
return r;
}
static inline uint16_t tool78_digest_checksum16(uint16_t r, size_t len, const uint8_t* data) {

View File

@ -10,6 +10,7 @@
enum tool78_hw_flags {
tool78_hw_flag_done_reset = 1<<0,
tool78_hw_flag_do_ocd = 1<<1,
};
struct tool78_hw {

View File

@ -54,6 +54,8 @@ end:
static bool t78k0_spi_init(void) {
if (!tool78_hw_init_help(NULL, &tool78_spi_program, &vars)) return false;
if (tool78_hw_rl78_uart2.flags & tool78_hw_flag_do_ocd)
return false; // OCD not supported with this phy
vars.exclusive = false;
vars.bitswap = false;

View File

@ -18,6 +18,8 @@ static bool t78k0_uart2_init(void) {
if (!tool78_hw_init_help(&tool78_uart_tx_program, &tool78_uart_rx_program,
&vars)) return false;
if (tool78_hw_rl78_uart2.flags & tool78_hw_flag_do_ocd)
return false; // OCD not supported with this phy
vars.exclusive = false;
vars.bitswap = true;

View File

@ -19,6 +19,8 @@ static bool t78k0_uart2_extclk_init(void) {
if (!tool78_hw_init_help(&tool78_uart_tx_program, &tool78_uart_rx_program,
&vars)) return false;
if (tool78_hw_rl78_uart2.flags & tool78_hw_flag_do_ocd)
return false; // OCD not supported with this phy
vars.exclusive = false;
vars.bitswap = true;

View File

@ -20,6 +20,8 @@ static bool t78k0r_uart1_init(void) {
if (!tool78_hw_init_help(&tool78_uart_tx_program, &tool78_uart_rx_program,
&vars)) return false;
if (tool78_hw_rl78_uart2.flags & tool78_hw_flag_do_ocd)
return false; // OCD not supported with this phy
vars.exclusive = true;
vars.bitswap = true;

View File

@ -18,18 +18,20 @@ static bool trl78_uart1_init(void) {
if (!tool78_hw_init_help(&tool78_uart_tx_program, &tool78_uart_rx_program,
&vars)) return false;
tool78_hw_rl78_uart1.flags = 0; // TODO: also in all other hw impls!
vars.exclusive = true;
vars.bitswap = true;
tool78_entryseq_rl78(tool78_entry_rl78_uart1);
enum tool78_entry typ = (tool78_hw_rl78_uart1.flags & tool78_hw_flag_do_ocd)
? tool78_entry_rl78_ocd : tool78_entry_rl78_uart1;
tool78_entryseq_rl78(typ);
tool78_uart_rx_program_init(PINOUT_TOOL78_PIO, vars.smrx, vars.rxoff,
PINOUT_TOOL78_RL78_TOOL0, 115200, true);
tool78_uart_tx_program_init(PINOUT_TOOL78_PIO, vars.smtx, vars.txoff,
PINOUT_TOOL78_RL78_TOOL0, 115200, true);
uint8_t byte = (uint8_t)tool78_entry_rl78_uart1;
uint8_t byte = (uint8_t)typ;
trl78_uart1_send(1, &byte, -1);
busy_wait_us_32(70); // tMB

View File

@ -18,6 +18,8 @@ static bool trl78_uart2_init(void) {
if (!tool78_hw_init_help(&tool78_uart_tx_program, &tool78_uart_rx_program,
&vars)) return false;
if (tool78_hw_rl78_uart2.flags & tool78_hw_flag_do_ocd)
return false; // OCD not supported with this phy
vars.exclusive = false;
vars.bitswap = true;

View File

@ -22,6 +22,7 @@ def main():
parser = argparse.ArgumentParser(
description="Convert data files into byte arrays in a C header")
parser.add_argument('--width', type=int, default=16, help="data width")
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.")
@ -60,7 +61,9 @@ def main():
traceback.print_exc()
sys.exit(1)
data = struct.unpack('<'+('H'*(len(data)//2)), data)
wlut = {8:'B',16:'H',32:'I',64:'Q'}
denom= args.width//8
data = struct.unpack('<'+((wlut[args.width])*(len(data)//denom)), data)
# add it to the list
datafiles[name] = data
@ -76,8 +79,8 @@ def main():
# 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,
"static uint%d_t DATA_%s[%d] = {\n%s\n};" % (args.width, name, len(data), \
textwrap.fill(', '.join(("0x%0"+str(args.width//4)+"x") % b for b in data), width=81,
initial_indent=" ", subsequent_indent=" ")
) for name, data in datafiles.items()
)

6
test/rl78/.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
trace.log
*.bin
*.h
*.elf
*.map
*.o

24
test/rl78/Makefile Normal file
View File

@ -0,0 +1,24 @@
AS := rl78-elf-gcc
LD := rl78-elf-gcc
OBJCOPY := rl78-elf-objcopy
all: test-rom.bin test-dbg.bin
test.S.o: test.S
$(AS) -c -o "$@" "$<"
romhdr.S.o: romhdr.S
$(AS) -c -o "$@" "$<"
OBJFILES := test.S.o romhdr.S.o
test-%.elf test-%.elf.map: $(OBJFILES) link-%.ld
$(LD) -o "$@" $(OBJFILES) -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
.KEEP: test-rom.elf test-dbg.elf

72
test/rl78/hw.S Normal file
View File

@ -0,0 +1,72 @@
#define P0 0xfff00
#define P2 0xfff02
#define P3 0xfff03
#define P12 0xfff0c
#define P13 0xfff0d
#define PM0 0xfff20
#define PM2 0xfff22
#define PM3 0xfff23
#define TXD1 0xfff44
#define SDR02 0xfff44
#define RXD1 0xfff46
#define SDR03 0xfff46
; PMC: processor mode control
#define PU0 0xf0030
#define PU3 0xf0033
#define PU12 0xf003c
#define PIM0 0xf0040
#define PIM3 0xf0043
#define POM0 0xf0050
#define POM3 0xf0053
#define PMC0 0xf0060
#define PMC2 0xf0062
#define PMC3 0xf0063
#define NFEN0 0xf0070
#define NFEN1 0xf0071
#define PIOR0 0xf0077
#define PIOR1 0xf0079
#define PIOR2 0xf0075
#define PIOR3 0xf007c
#define IAWCTL 0xf0078
#define PMS 0xf007b
#define DFLCTL 0xf0090
#define PER0 0xf00f0
#define PRR0 0xf00f1
#define PER1 0xf00fa
#define PRR1 0xf00fb
#define PER2 0xf00fc
#define PRR2 0xf00fd
#define SSR02 0xf0104
#define SSR03 0xf0106
#define SIR02 0xf010c
#define SIR03 0xf010e
#define SMR02 0xf0114
#define SMR03 0xf0116
#define SCR02 0xf011c
#define SCR03 0xf011e
#define SE0 0xf0120
#define SS0 0xf0122
#define ST0 0xf0124
#define SPS0 0xf0126
#define SO0 0xf0128
#define SOE0 0xf012a
#define SOL0 0xf0134
#define SSC0 0xf0138
#define INTFE 0xf0448

34
test/rl78/link-dbg.ld Normal file
View File

@ -0,0 +1,34 @@
OUTPUT_FORMAT("elf32-rl78","elf32-rl78","elf32-rl78")
OUTPUT_ARCH(rl78)
ENTRY(_start)
MEMORY
{
ram (rwx) : ORIGIN = 0xf07e0, LENGTH = 0x100/*idk*/
}
SECTIONS {
.hdr :
{
BYTE(0xe0); BYTE(0x07); /* address */
BYTE(SIZEOF(.text));
} > ram
.text :
{
/*ABSOLUTE(.) = 0xf07e3;*/
*(.text* .rodata* .data*)
} > ram
.bss :
{
*(.bss)
} > ram =0x00
/DISCARD/ :
{
*(.vectors)
*(.callt)
*(.option)
*(.password)
*(.plt)
}
}

166
test/rl78/link-rom.ld Normal file
View File

@ -0,0 +1,166 @@
OUTPUT_FORMAT("elf32-rl78","elf32-rl78","elf32-rl78")
OUTPUT_ARCH(rl78)
ENTRY(_start)
MEMORY
{
/*data (rwx) : ORIGIN = 0x0200, LENGTH = 0x100
text (rx) : ORIGIN = 0xf800, LENGTH = 0x800 - 0x20
vectors (rw) : ORIGIN = 0xffe0, LENGTH = 0x20*/
rom (rx) : ORIGIN = 0x00000, LENGTH = 0x04000
/* vectors, boot clusters, etc.: part of ^ */
ram (rwx) : ORIGIN = 0xff900, LENGTH = (0xffee0 - 0xff900)
/*
* 16k code flash: 00000..03FFF
* 2k data flash: F1000..F17FF
* 1.5k ram: FF900..FFEDF
*
* boot clusters: +00000; +01000
* vectors: 00000..0007F
* callt: 00080..000BF
* option byte: 000C0..000C3
* debugpasswd: 000C4..000CD
*
* flash block = 0x400 bytes => 0x10 blocks
*
* vectors:
* 000: RESET/POR/WDT/TRAP/RPE/...
* 004: INTWDTI/INTSRO
* 006: INTLVI
* 008: INTP0
* 00A: INTP1
* ...
* .14: INTP6
* 016: INTST0/INTCSI00/INTIIC00
* 018: INTSR0/INTCSI01/INTIIC01
* 01e: INTSRE0
* 020: INTTM00
* 022: INTST1/INTCSI10/INTIIC10
* 024: INTSR1/INTCSI11/INTIIC11
* 026: INTSRE1
* bluh bluh not really interesting
* 07E: BRK
*
* 02000..03FFF mirrored to F2000..F3FFF (if enabmed in PMC)
*
* IO regs:
* serial data reg 00: TXD0/SIO00/SDR00 = 0xfff10
* serial data reg 01: RXD0/SIO01/SDR01 = 0xfff12
* serial data reg 02: TXD1/SIO10/SDR02 = 0xfff44
* serial data reg 03: RXD1/SIO11/SDR03 = 0xfff42
*
* port mode reg? PMx = 0xFFF2x
*
* port input mode PIMx = 0xF004x
* port output mode POMx = 0xF005x
* port mode control PMCx = 0xF006x
* port mode select PMS = 0xF007B
* peripheral io redirection regs?
* flash operating mode FLMODE = 0xF00AA
* serial status reg SSR0x = F010(x*2)
* serial mode reg SMR0x = F011(x*2)
* serial comm ops setting SCR0x = F011(8+x*2)
* + channel enable, start stop, clocksel, output, output enable, output level, standby control
* interrupt stuff at 0xF0441+...
*
* F0090: rom enable flag etc : DFLCTL bit 0 (enable dataflash access?)
* F0800: request data etc (not interesting here)
* F0803=1
* F0880=4
* F0880: also rom enable bit?
* FLMODE (voltages stuff, bluh), FLMWRP(?) (enable prev reg), PMMC (also voltages)
*
* TXD1 enable = PMC20=0 PM20=0 P20=1
* RXD1 enable = PMC31=0 PM31=1
*
* WDT: WDTE (enable reg) + option byte C0: set WDTON bit to 0 (bit 4)
*
* serial: UART1: ch2
* 8n1 lsbfirst
* PER0: bit 2 hi
* PRR0: bit 2 lo
* SPSm: 0b0100<<4 (125kbaud?)
* SMRmn:
* SEm SSm STm SOEm SOm SOLm SSCm ISC
*
* opt C1: 0b00000010 // 0x1a?
* opt C2: 0b11101001 // 0x2d?
* opt C3: 0b10000101 == 0x85
* C4..CD: 00 ...
*/
}
SECTIONS {
.btc0 :
{
. = 0x00000;
KEEP(*(.vectors))
. = 0x00080;
KEEP(*(.callt))
. = 0x000c0;
KEEP(*(.option))
. = 0x000c4;
KEEP(*(.password))
. = 0x000ce;
*(.text.btc0)
} > rom =0xff
/* TODO: btc1? */
.text :
{
. = ALIGN(2);
*(.text .rodata* .eh_frame_hdr)
. = ALIGN(256);
/*KEEP(*(.eh_frame) *(.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))*/
} > rom =0xff
.data :
{
__data_vma_start = ABSOLUTE(.);
__data_lma_start = SIZEOF(.text);
*(.data)
}
__data_size = SIZEOF(.data);
.bss :
{
__bss_start = ABSOLUTE(.);
*(.bss .sbss)
} >ram
__bss_size = SIZEOF(.bss);
/DISCARD/ :
{
*(.plt)
}
}

33
test/rl78/romhdr.S Normal file
View File

@ -0,0 +1,33 @@
.section .vectors, "a", %progbits
_VECTORS:
_vtor_RST:
.2byte _start
/* other vectors... */
.2byte 0xffff
.section .callt, "a", %progbits
_CALLT:
.2byte 0xffff
.section .option, "a", %progbits
/* option bytes */
_OPTION:
/* 0x000C0: wdt settings */
.byte 0x6e /* wdt disable */
/* 0x000C1: */
.byte 0x7f /* LVD reset, 2.81V */
/* 0x000C2: */
.byte 0xe8 /* HSmode, HOCO@32MHz */
/* 0x000C3: debug settings */
.byte 0x85
.section .password, "a", %progbits
/* debugger password: ten 0xff bytes */
_PASSWORD:
.byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff

93
test/rl78/test.S Normal file
View File

@ -0,0 +1,93 @@
/*#include "romhdr.S"*/
#include "hw.S"
/*
ch2&3: TxD1,RxD1
*/
/* allegedly there's a subroutine at 0xEFFA1 that sends a single byte over the TOOL0 line */
.global _start
_start:
call !hw_init
call !port_init
call !port_toggle
1: br $1b
hw_init:
di
; systeminit
; PIOR = 0
; ADPC = 1
; PMC bit = 0
; PM1 = 6(?)
; CMC = 0
; MSTOP,XTSTOP bits = 1,1
; MCM0 bit = 0 ; hi-speed OCO clock as main clock
; CSS bit = 0 ; main system clock = periph clock
; PER0 SAU1EN bit (3) = 1
; SPS0 = 0x44 ; or *12? ; CK00,CK01 @ 2MHz
; ST0 = 0xf ; stop all channels
; STMK0,STIF0 bits = 1,0 ; disable interrupts
; SRMK0,SRIF0 bits = 1,0 ; disable interrupts
; SREK0,SREF0 bits = 1,0 ; disable interrupts
; SMR00 = 0x22 ; ch0clock = CK00, start trig=sw falling edge, UART mode, xferend irq en
; SCR00 = 0x8297 ; tx only, clock type 1, error irq en, even parity, lsbfirst, 8bit data, 1bit stop
; SDR00 = 0xce00 ; opclk/208
; NFEN0 = 0x0001 ; RxD noise filter enable
; SIR01 = 0x0007 ; clear error
; SMR01 = 0x0122 ; ch1clock = CK00; start trig=RxD falling edge, UART mode, xferend irq en
; SCR01 = 0x4697 ; rx only, clock type 1, error irq en, even parity, lsbfirst, 8bit data, 1bit stop
; SDR01 = 0xce00 ; opclk/208 ; use opclk/17 (0x0f00) instead for 115.2kbaud?
; SO00,SOE00 bits = 1,1 ; prepare using ch0
; PM1 PM11 bit = 1 ; RxD pin as input
; P1,PM1 P12,PM12 bits = 1,0 ; TxD as output
; SO00 bit = 1 ; TxD output level
; SOE00 bit = 1 ; enable UART
; SS00,SS01 bits = 1,1 ; enable UART
; TXD0 = data ; xmit
;ei ; nah
ret
port_init:
; P33 as output using GPIO
; PM3 bit 3 = 0
; PU3 bit 3 = 0 (no pullup)
; PMC3 bit 3 = 0 (digital IO)
; PIOR0 bit 6 = 0
; POM3 bit 3 = 0
; toggle P3 bit 3
clr1 !PM3.3
clr1 !PU3.3
clr1 !PIOR0.6
clr1 !POM3.3
ret
port_toggle:
set1 !P3.3
nop
nop
clr1 !P3.3
br $port_toggle
uart_init:
;; PMC00=0 PM00=1 ; RxD1 en
; PIO2.3 = 1
; PMC20=0 PM20=0 P20=1 ; TxD1 en
ret
uart_send_byte:
; todo
; TODO: wait for sent?
ret