diff --git a/src/tool78/tool78_cmds.c b/src/tool78/tool78_cmds.c index 07b804a..175db5f 100644 --- a/src/tool78/tool78_cmds.c +++ b/src/tool78/tool78_cmds.c @@ -102,6 +102,7 @@ static const struct delayvalues delays[23] = { #define tCS8 tWT9 #define tSD8 tWT1 #define tCS9 tWT12 +#define tG23 (1000*1000) /* RL78/G23 datasheet just says "everything 1ms lol" */ static enum tool78_stat tool78_data_send(struct tool78_hw* hw, @@ -761,6 +762,144 @@ enum tool78_stat tool78_do_security_release(struct tool78_hw* hw) { return st; } +// new RL78/G23 stuff +enum tool78_stat tool78_do_g23_security_set(struct tool78_hw* hw, + const struct tool78_security* sec) { + bool isrl78 = (hw->target & tool78_mcu_mask) == tool78_mcu_rl78; + if (!isrl78) + return tool78_stat_bad_mcu_for_cmd; + + uint8_t data[2]; + data[0] = sec->flg | 0xe9; + data[1] = sec->flg2 | 0xfa; + + enum tool78_stat st = tool78_cmd_send(hw, tool78_cmd_security_set, 2, data); + if (st != tool78_stat_ack) return st; + + st = tool78_wait_status(hw, 1, tWT13 + tWT14); + if (st != tool78_stat_ack) return st; + + return st; +} + +enum tool78_stat tool78_do_g23_security_get(struct tool78_hw* hw, + struct tool78_security* sec) { + bool isrl78 = (hw->target & tool78_mcu_mask) == tool78_mcu_rl78; + if (!isrl78) + return tool78_stat_bad_mcu_for_cmd; + + uint8_t data[2]; + + enum tool78_stat st = tool78_cmd_send(hw, tool78_cmd_security_get, 0, NULL); + if (st != tool78_stat_ack) return st; + + st = tool78_wait_status(hw, 1, tCS8); + if (st != tool78_stat_ack) return st; + + st = tool78_data_recv(hw, data, 2, tSD8); + if (st != tool78_stat_ack) return st; + + sec->flg = data[0]; + sec->flg2 = data[1]; + + return st; +} + +enum tool78_stat tool78_do_security_idauth(struct tool78_hw* hw, + const uint8_t passwd[static 10]) { + if ((hw->target & tool78_mcu_mask) != tool78_mcu_rl78) + return tool78_stat_bad_mcu_for_cmd; + + enum tool78_stat st = tool78_cmd_send(hw, tool78_cmd_security_idauth, 10, passwd); + if (st != tool78_stat_ack) return st; + + st = tool78_wait_status(hw, 1, tG23); + if (st != tool78_stat_ack) return st; + + return st; +} + +enum tool78_stat tool78_do_exopt_set(struct tool78_hw* hw, + const uint8_t exopt[static 14]) { + if ((hw->target & tool78_mcu_mask) != tool78_mcu_rl78) + return tool78_stat_bad_mcu_for_cmd; + + enum tool78_stat st = tool78_cmd_send(hw, tool78_cmd_exopts_set, 14, exopt); + if (st != tool78_stat_ack) return st; + + st = tool78_wait_status(hw, 1, tG23); + if (st != tool78_stat_ack) return st; + + return st; +} + +enum tool78_stat tool78_do_flash_rdp_set(struct tool78_hw* hw, + uint16_t block_start, uint16_t block_end, bool rdp_rw_allow) { + if ((hw->target & tool78_mcu_mask) != tool78_mcu_rl78) + return tool78_stat_bad_mcu_for_cmd; + + uint8_t data[4]; + data[0] = block_start & 0xff; + data[1] = (block_start >> 8) | 0xfe; + data[2] = block_end & 0xff; + data[3] = ((block_end >> 8) & 1) | 0x7e | (rdp_rw_allow ? 0x80 : 0); + + enum tool78_stat st = tool78_cmd_send(hw, tool78_cmd_flash_rdp_set, 4, data); + if (st != tool78_stat_ack) return st; + + st = tool78_wait_status(hw, 1, tG23); + if (st != tool78_stat_ack) return st; + + return st; +} + +enum tool78_stat tool78_do_fsw_set(struct tool78_hw* hw, + const struct tool78_fsw_settings* fswopt) { + if ((hw->target & tool78_mcu_mask) != tool78_mcu_rl78) + return tool78_stat_bad_mcu_for_cmd; + + uint8_t data[4]; + data[0] = fswopt->block_start & 0xff; + data[1] = ((fswopt->block_start >> 8) & 1) | 0x7e + | (fswopt->fswopt_rw_allow ? 0x80 : 0); + data[2] = fswopt->block_end & 0xff; + data[3] = ((fswopt->block_end >> 8) & 1) | 0x7e + | (fswopt->fsw_area_invert ? 0x80 : 0); + + enum tool78_stat st = tool78_cmd_send(hw, tool78_cmd_fsw_set, 4, data); + if (st != tool78_stat_ack) return st; + + st = tool78_wait_status(hw, 1, tG23); + if (st != tool78_stat_ack) return st; + + return st; +} + +enum tool78_stat tool78_do_fsw_get(struct tool78_hw* hw, + struct tool78_fsw_settings* fswopt) { + bool isrl78 = (hw->target & tool78_mcu_mask) == tool78_mcu_rl78; + if (!isrl78) + return tool78_stat_bad_mcu_for_cmd; + + uint8_t data[4]; + + enum tool78_stat st = tool78_cmd_send(hw, tool78_cmd_fsw_get, 0, NULL); + if (st != tool78_stat_ack) return st; + + st = tool78_wait_status(hw, 1, tG23); + if (st != tool78_stat_ack) return st; + + st = tool78_data_recv(hw, data, 4, tG23); + if (st != tool78_stat_ack) return st; + + fswopt->block_start = data[0] | ((data[1] & 1) << 8); + fswopt->block_end = data[2] | ((data[3] & 1) << 8); + fswopt->fswopt_rw_allow = data[1] & 0x80; + fswopt->fsw_area_invert = data[3] & 0x80; + + return st; +} + // ---- int tool78_ocd_version(struct tool78_hw* hw, uint16_t* ver) { diff --git a/src/tool78/tool78_cmds.h b/src/tool78/tool78_cmds.h index 2c73175..6bda508 100644 --- a/src/tool78/tool78_cmds.h +++ b/src/tool78/tool78_cmds.h @@ -34,10 +34,35 @@ enum tool78_stat tool78_do_silicon_signature(struct tool78_hw* hw, enum tool78_stat tool78_do_version_get(struct tool78_hw* hw, tool78_version_t* vout); enum tool78_stat tool78_do_security_set(struct tool78_hw* hw, const struct tool78_security* sec); -enum tool78_stat tool78_do_security_get(struct tool78_hw* hw, +enum tool78_stat tool78_do_security_get(struct tool78_hw* hw, // RL78 only struct tool78_security* sec); enum tool78_stat tool78_do_security_release(struct tool78_hw* hw); +// new commands from the RL78/G23 (Proto C) + +// 0xA0 +enum tool78_stat tool78_do_g23_security_set(struct tool78_hw* hw, + const struct tool78_security* sec); +// 0xA1 +enum tool78_stat tool78_do_g23_security_get(struct tool78_hw* hw, // RL78 only + struct tool78_security* sec); +// 0x9C: payload = passwd; ack/nak +enum tool78_stat tool78_do_security_idauth(struct tool78_hw* hw, + const uint8_t passwd[static 10]); +// 0xA5: payload = exopt; ack/nak +enum tool78_stat tool78_do_exopt_set(struct tool78_hw* hw, + const uint8_t exopt[static 14]); +// 0xAB: payload = block_start || block_end (little-endian); ack/nak +enum tool78_stat tool78_do_flash_rdp_set(struct tool78_hw* hw, + uint16_t block_start, uint16_t block_end, bool rdp_rw_allow); +// 0xAC +enum tool78_stat tool78_do_fsw_set(struct tool78_hw* hw, + const struct tool78_fsw_settings* fswopt); +// 0xAD +enum tool78_stat tool78_do_fsw_get(struct tool78_hw* hw, + struct tool78_fsw_settings* fswopt); +// TODO: also new secget/secset! + // ---- //int tool78_ocd_reset(struct tool78_hw* hw); diff --git a/src/tool78/tool78_defs.h b/src/tool78/tool78_defs.h index e9e680e..64ae469 100644 --- a/src/tool78/tool78_defs.h +++ b/src/tool78/tool78_defs.h @@ -82,12 +82,22 @@ enum tool78_cmd { tool78_cmd_osc_freq_set = 0x90, // not on 78k0/Kx2. arguments are different for 78K0R/Kx3-L and RL78! tool78_cmd_baud_rate_set = 0x9a, - // 78K0R/Kx3-L and RL78: also sets flash shield window + tool78_cmd_security_idauth = 0x9c, + // RL78/G23 only + // 78K0R/Kx3-L and RL78/x1y: also sets flash shield window tool78_cmd_security_set = 0xa0, // RL78 only tool78_cmd_security_get = 0xa1, // RL78 only tool78_cmd_security_release = 0xa2, + tool78_cmd_exopts_set = 0xa5, + // RL78/G23 only + tool78_cmd_flash_rdp_set = 0xab, + // RL78/G23 only + tool78_cmd_fsw_set = 0xac, + // RL78/G23 only + tool78_cmd_fsw_get = 0xad, + // RL78/G23 only tool78_cmd_checksum = 0xb0, // response format & length differ between all MCU versions! // length & first few bytes can be used to discern between MCUs @@ -242,6 +252,16 @@ enum tool78_sec_flag { // 78k0/78k0r tool78_sec_flag_boot_xchg = 1<<0 // rl78 only }; +enum tool78_sec_flag12 { // RL78/G23 + tool78_sec_flag1_boot_rw_allow = 1<<1, + tool78_sec_flag1_blk_erase_allow = 1<<2, + tool78_sec_flag1_prog_allow = 1<<4, + + tool78_sec_flag2_idauth_disable = 1<<0, + tool78_sec_flag2_debug_enable = 1<<2, + tool78_sec_flag2_rdp_write_allow = 1<<3, // NOTE: must be 1 when writing + tool78_sec_flag2_option_write_allow = 1<<4 // NOTE: must be 1 when writing +}; struct tool78_security { uint8_t flg; @@ -249,6 +269,16 @@ struct tool78_security { // ^ only these 2 used for 78k0 uint16_t fsws; uint16_t fswe; + // ^ these two used for RL78/x1y + uint8_t flg2; + // ^ used in RL78/G23 +}; + +struct tool78_fsw_settings { + uint16_t block_start; + uint16_t block_end; + bool fswopt_rw_allow; + bool fsw_area_invert; }; #endif