RL78/G10 proto (untested)

This commit is contained in:
Triss 2022-04-15 04:44:32 +02:00
parent 26c5bb0d36
commit d523de69b7
5 changed files with 243 additions and 12 deletions

View File

@ -104,6 +104,16 @@ static const struct delayvalues delays[23] = {
#define tCS9 tWT12 #define tCS9 tWT12
#define tG23 (1000*1000) /* RL78/G23 datasheet just says "everything 1ms lol" */ #define tG23 (1000*1000) /* RL78/G23 datasheet just says "everything 1ms lol" */
// G10 proto
#define tDTR 1
#define tDRT 1
#define tCRC 1000
#define tPRO 1000
#define tVER 20000
#define tERA (350*1000)
#define tDT 1
/*#define tDR 1*/
static enum tool78_stat tool78_data_send(struct tool78_hw* hw, static enum tool78_stat tool78_data_send(struct tool78_hw* hw,
int len, const uint8_t* data, bool final_block) { int len, const uint8_t* data, bool final_block) {
@ -902,6 +912,141 @@ enum tool78_stat tool78_do_fsw_get(struct tool78_hw* hw,
// ---- // ----
enum tool78_stat tool78_do_g10_get_flash_size(struct tool78_hw* hw,
enum tool78_g10_flash_size* fsz) {
busy_wait_us_32(tDTR);
// start crc calc cmd
uint8_t data[2];
data[0] = tool78_cmd_crc_check;
int rr = hw->send(1, data, -1);
if (rr != 1) return tool78_stat_internal_error;
enum tool78_stat st = tool78_data_recv(hw, data, 2, tDT+tDRT);
if (st != tool78_stat_ack) return st;
if (data[0] != tool78_stat_ack) return data[0];
*fsz = data[1];
busy_wait_us_32(tDTR);
data[0] = tool78_stat_nak; // should send ack here, but send nak to stop crc calc
rr = hw->send(1, data, -1);
if (rr != 1) return tool78_stat_internal_error;
/*st =*/ tool78_data_recv(hw, data, 1, tCRC);
// ignore status of this stuff
//if (st != tool78_stat_ack) return st;
return tool78_stat_ack;
}
enum tool78_stat tool78_do_g10_check_crc(struct tool78_hw* hw,
enum tool78_g10_flash_size fsz, uint16_t* crc) {
busy_wait_us_32(tDTR);
uint8_t data[2];
data[0] = tool78_cmd_crc_check;
int rr = hw->send(1, data, -1);
if (rr != 1) return tool78_stat_internal_error;
enum tool78_stat st = tool78_data_recv(hw, data, 2, tDT+tDRT);
if (st != tool78_stat_ack) return st;
if (data[0] != tool78_stat_ack) return data[0];
busy_wait_us_32(tDTR);
if (data[1] != fsz) {
data[0] = tool78_stat_nak; // should send ack here, but send nak to stop crc calc
rr = hw->send(1, data, -1);
if (rr != 1) return tool78_stat_internal_error;
/*st =*/ tool78_data_recv(hw, data, 1, tCRC);
// ignore status of this stuff
//if (st != tool78_stat_ack) return st;
return tool78_stat_bad_flash_size;
} else {
data[0] = tool78_stat_ack;
rr = hw->send(1, data, -1);
if (rr != 1) return tool78_stat_internal_error;
st = tool78_data_recv(hw, data, 1, tCRC);
if (st != tool78_stat_ack) return st;
st = data[0];
if (st != tool78_stat_ack) return st;
st = tool78_data_recv(hw, data, 2, tDT*2);
if (st != tool78_stat_ack) return st;
*crc = data[0] | ((uint16_t)data[1] << 8);
return tool78_stat_ack;
}
}
enum tool78_stat tool78_do_g10_erase_then_write(struct tool78_hw* hw,
enum tool78_g10_flash_size fsz, const uint8_t* data_to_wr) {
busy_wait_us_32(tDTR);
uint8_t data[4];
data[0] = tool78_cmd_write_after_erase;
int rr = hw->send(1, data, -1);
if (rr != 1) return tool78_stat_internal_error;
enum tool78_stat st = tool78_data_recv(hw, data, 2, tDT+tDRT);
if (st != tool78_stat_ack) return st;
if (data[0] != tool78_stat_ack) return data[0];
busy_wait_us_32(tDTR);
if (data[1] != fsz) {
data[0] = tool78_stat_nak; // should send ack here, but send nak to stop crc calc
rr = hw->send(1, data, -1);
if (rr != 1) return tool78_stat_internal_error;
/*st =*/ tool78_data_recv(hw, data, 1, tERA);
// ignore status of this stuff
//if (st != tool78_stat_ack) return st;
return tool78_stat_bad_flash_size;
} else {
data[0] = tool78_stat_ack;
rr = hw->send(1, data, -1);
if (rr != 1) return tool78_stat_internal_error;
st = tool78_data_recv(hw, data, 1, tERA);
if (st != tool78_stat_ack) return st;
st = data[0];
if (st != tool78_stat_ack) return st;
size_t flash_sz = (fsz + 1) * 256;
for (size_t i = 0; i < flash_sz; i += 4) {
busy_wait_us_32(tDTR);
rr = hw->send(1, &data_to_wr[i+0], -1);
if (rr != 1) return tool78_stat_internal_error;
busy_wait_us_32(tDRT);
rr = hw->send(1, &data_to_wr[i+1], -1);
if (rr != 1) return tool78_stat_internal_error;
busy_wait_us_32(tDRT);
rr = hw->send(1, &data_to_wr[i+2], -1);
if (rr != 1) return tool78_stat_internal_error;
busy_wait_us_32(tDRT);
rr = hw->send(1, &data_to_wr[i+3], -1);
if (rr != 1) return tool78_stat_internal_error;
st = tool78_data_recv(hw, data, 1, tPRO);
if (st != tool78_stat_ack) return st;
st = data[0];
if (st != tool78_stat_ack) return st;
}
st = tool78_data_recv(hw, data, 1, tVER);
if (st != tool78_stat_ack) return st;
return tool78_stat_ack;
}
}
// ----
int tool78_ocd_version(struct tool78_hw* hw, uint16_t* ver) { int tool78_ocd_version(struct tool78_hw* hw, uint16_t* ver) {
busy_wait_ms(1); busy_wait_ms(1);
@ -1052,7 +1197,8 @@ static enum tool78_stat tool78_init_common(struct tool78_hw* hw) {
if (!hw->init()) return tool78_stat_fatal_hw_error; if (!hw->init()) return tool78_stat_fatal_hw_error;
//printf("init %zu ok\n", i); //printf("init %zu ok\n", i);
if ((hw->target & tool78_mcu_mask) != tool78_mcu_rl78) { if ((hw->target & tool78_mcu_mask) != tool78_mcu_rl78
&& (hw->target & tool78_mcu_mask) != tool78_mcu_rl78g10) {
st = tool78_do_reset(hw); st = tool78_do_reset(hw);
//printf("done reset st=0x%02x\n", st); //printf("done reset st=0x%02x\n", st);
} }
@ -1065,9 +1211,16 @@ static enum tool78_stat tool78_init_common(struct tool78_hw* hw) {
if (st != tool78_stat_ack) return st; if (st != tool78_stat_ack) return st;
//printf("hw inited\n"); //printf("hw inited\n");
if ((hw->target & tool78_mcu_mask) != tool78_mcu_rl78g10) {
st = tool78_do_generic_baudrate(hw); st = tool78_do_generic_baudrate(hw);
//printf("baudrate result=0x%02x\n", st); //printf("baudrate result=0x%02x\n", st);
if (st != tool78_stat_ack) return st; if (st != tool78_stat_ack) return st;
} else {
enum tool78_stat st2;
st = tool78_data_recv(hw, &st2, 1, 1000);
if (st != tool78_stat_ack) return st;
st = st2;
}
return st; return st;
} }
@ -1078,9 +1231,11 @@ enum tool78_stat tool78_init_sfp(struct tool78_hw* hw, tool78_silicon_sig_t* sig
enum tool78_stat st = tool78_init_common(hw); enum tool78_stat st = tool78_init_common(hw);
if (st != tool78_stat_ack) return st; if (st != tool78_stat_ack) return st;
if ((hw->target & tool78_mcu_mask) != tool78_mcu_rl78g10) {
st = tool78_do_silicon_signature(hw, sig); st = tool78_do_silicon_signature(hw, sig);
//printf("sig result=0x%02x\n", st); //printf("sig result=0x%02x\n", st);
if (st != tool78_stat_ack) return st; if (st != tool78_stat_ack) return st;
}
return st; return st;
} }

View File

@ -38,6 +38,16 @@ enum tool78_stat tool78_do_security_get(struct tool78_hw* hw, // RL78 only
struct tool78_security* sec); struct tool78_security* sec);
enum tool78_stat tool78_do_security_release(struct tool78_hw* hw); enum tool78_stat tool78_do_security_release(struct tool78_hw* hw);
// RL78/G10,G1M,G1N commands
// this one is very hacky
enum tool78_stat tool78_do_g10_get_flash_size(struct tool78_hw*,
enum tool78_g10_flash_size* fsz);
enum tool78_stat tool78_do_g10_check_crc(struct tool78_hw*,
enum tool78_g10_flash_size fsz, uint16_t* crc);
enum tool78_stat tool78_do_g10_erase_then_write(struct tool78_hw*,
enum tool78_g10_flash_size fsz, const uint8_t* data);
// new commands from the RL78/G23 (Proto C) // new commands from the RL78/G23 (Proto C)
// 0xA0 // 0xA0
@ -61,7 +71,6 @@ enum tool78_stat tool78_do_fsw_set(struct tool78_hw* hw,
// 0xAD // 0xAD
enum tool78_stat tool78_do_fsw_get(struct tool78_hw* hw, enum tool78_stat tool78_do_fsw_get(struct tool78_hw* hw,
struct tool78_fsw_settings* fswopt); struct tool78_fsw_settings* fswopt);
// TODO: also new secget/secset!
// ---- // ----

View File

@ -31,11 +31,13 @@ enum tool78_target {
tool78rl_uart1 = 0x31, tool78rl_uart1 = 0x31,
tool78rl_uart2 = 0x32, tool78rl_uart2 = 0x32,
tool78rl_ocd = 0x38, // FIXME: do this in a better way tool78rl_ocd = 0x38, // FIXME: do this in a better way
tool78rlg10_uart1 = 0x41,
tool78_mcu_mask = 0xf0, tool78_mcu_mask = 0xf0,
tool78_mcu_78k0 = 0x10, tool78_mcu_78k0 = 0x10,
tool78_mcu_78k0r = 0x20, tool78_mcu_78k0r = 0x20,
tool78_mcu_rl78 = 0x30, tool78_mcu_rl78 = 0x30,
tool78_mcu_rl78g10 = 0x40,
tool78_phy_mask = 0x0f, tool78_phy_mask = 0x0f,
tool78_phy_uart1 = 0x01, tool78_phy_uart1 = 0x01,
@ -76,6 +78,10 @@ enum tool78_cmd {
tool78_cmd_block_erase = 0x22, tool78_cmd_block_erase = 0x22,
tool78_cmd_block_blank_check = 0x32, tool78_cmd_block_blank_check = 0x32,
tool78_cmd_programming = 0x40, tool78_cmd_programming = 0x40,
// RL78/G10 only
tool78_cmd_crc_check = 0x53,
// RL78/G10 only
tool78_cmd_write_after_erase = 0x60,
// 78k0/Kx2 SPI only // 78k0/Kx2 SPI only
tool78_cmd_status = 0x70, tool78_cmd_status = 0x70,
// 78k0/Kx2 only // 78k0/Kx2 only
@ -131,9 +137,11 @@ enum tool78_stat {
tool78_stat_timeout_error = 0xc3, tool78_stat_timeout_error = 0xc3,
tool78_stat_fatal_hw_error = 0xc4, tool78_stat_fatal_hw_error = 0xc4,
tool78_stat_parity_error = 0xc5, tool78_stat_parity_error = 0xc5,
tool78_stat_bad_flash_size = 0xc6,
// TODO: OCD status stuff (for 0x91)
}; };
// TODO: only known for RL78 from fail0overflow. verify!
// these commands use a checksum that is the bitwise complement from the usual // these commands use a checksum that is the bitwise complement from the usual
// checksum (used in the flash programming protocol) // checksum (used in the flash programming protocol)
enum tool78ocd_cmd { enum tool78ocd_cmd {
@ -281,5 +289,14 @@ struct tool78_fsw_settings {
bool fsw_area_invert; bool fsw_area_invert;
}; };
enum tool78_g10_flash_size {
tool78_g10_flash_16k = 0x3f,
tool78_g10_flash_8k = 0x1f,
tool78_g10_flash_4k = 0x0f,
tool78_g10_flash_2k = 0x07,
tool78_g10_flash_1k = 0x03,
tool78_g10_flash_512 = 0x01,
};
#endif #endif

View File

@ -46,7 +46,9 @@ extern struct tool78_hw
tool78_hw_78k0r_uart1, tool78_hw_78k0r_uart1,
tool78_hw_rl78_uart1, tool78_hw_rl78_uart1,
tool78_hw_rl78_uart2; tool78_hw_rl78_uart2,
tool78_hw_rl78g10_uart1;
#endif #endif

View File

@ -43,6 +43,34 @@ static bool trl78_uart1_init(void) {
return true; // all is well! return true; // all is well!
} }
static bool trl78g10_uart1_init(void) {
if (!tool78_hw_init_help(&tool78_uart_tx_program, &tool78_uart_rx_program,
&vars)) return false;
vars.exclusive = true;
vars.bitswap = true;
enum tool78_entry typ = 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)typ;
trl78_uart1_send(1, &byte, -1);
//busy_wait_us_32(70); // tMB
busy_wait_ms(4);
// now a baudrate set command needs to be sent, but we leave that to the
// upper (command processing) layer as it has to know about those timings
// anyway
return true; // all is well!
}
static void trl78_uart1_deinit(void) { static void trl78_uart1_deinit(void) {
tool78_hw_deinit_help(&tool78_uart_tx_program, &tool78_uart_rx_program, tool78_hw_deinit_help(&tool78_uart_tx_program, &tool78_uart_rx_program,
&vars); &vars);
@ -63,6 +91,12 @@ static int trl78_uart1_send(int len, const uint8_t* data, int32_t timeout_us) {
/*inter-byte delay (us) tDR = 90/8M s */, /*inter-byte delay (us) tDR = 90/8M s */,
len, data, timeout_us); len, data, timeout_us);
} }
static int trl78g10_uart1_send(int len, const uint8_t* data, int32_t timeout_us) {
return tool78_hw_help_send(&vars,
(tool78_hw_rl78g10_uart1.flags & tool78_hw_flag_done_reset) ? 0 : 190
/*inter-byte delay (us) tDR = 90/8M s */,
len, data, timeout_us);
}
static void trl78_uart1_set_baudrate(uint32_t baudrate) { static void trl78_uart1_set_baudrate(uint32_t baudrate) {
float div = (float)clock_get_hz(clk_sys) / (8*baudrate); float div = (float)clock_get_hz(clk_sys) / (8*baudrate);
@ -93,4 +127,18 @@ struct tool78_hw tool78_hw_rl78_uart1 = {
//.rx_set_stop_bit = trl78_uart1_rx_set_stop_bit //.rx_set_stop_bit = trl78_uart1_rx_set_stop_bit
}; };
struct tool78_hw tool78_hw_rl78g10_uart1 = {
.target = tool78rlg10_uart1,
.init = trl78_uart1_init,
.deinit = trl78_uart1_deinit,
.set_baudrate = trl78_uart1_set_baudrate,
.has_available = trl78_uart1_has_available,
.recv = trl78_uart1_recv,
.send = trl78g10_uart1_send,
//.rx_set_stop_bit = trl78_uart1_rx_set_stop_bit
};