From 13795e55a9e5630682e2d8e254f3dcf46c210df0 Mon Sep 17 00:00:00 2001 From: Jack Gallegos Date: Sun, 31 Mar 2024 21:20:11 -0700 Subject: [PATCH 1/3] Add of hardware reset and CTS monitoring reset functionality --- src/main.c | 19 +++++++++- src/rl78.c | 101 ++++++++++++++++++++++++++++++++++++++++++--------- src/rl78.h | 6 ++- src/serial.c | 18 +++++++++ src/serial.h | 1 + 5 files changed, 126 insertions(+), 19 deletions(-) diff --git a/src/main.c b/src/main.c index f339727..0c8ac90 100644 --- a/src/main.c +++ b/src/main.c @@ -53,6 +53,7 @@ const char *usage = "\t\t\tn=2 Two-wire UART, Reset by DTR\n" "\t\t\tn=3 Single-wire UART, Reset by RTS\n" "\t\t\tn=4 Two-wire UART, Reset by RTS\n" + "\t\t\tn=5 Single-wire UART, Hardware Reset, reset state read by CTS (modified mode 1/3)\n" "\t\t\tdefault: n=1\n" "\t-P n\tSet protocol version\n" "\t\t\tn=-1 Try to autodetect the protocol version from the unit's Silicon Signature\n" @@ -117,14 +118,21 @@ int main(int argc, char *argv[]) break; case 'm': mode = strtol(optarg, &endp, 10) - 1; + // mode = desired communication mode from terminal input - 1 if (optarg == endp || MODE_MAX_VALUE < mode || MODE_MIN_VALUE > mode) { fprintf(stderr, "Invalid mode\n"); printf("%s", usage); + // For debug + //printf("Communication mode passed to rl78 funcs: %i\r\n", mode); + //printf("Mode value expression: %i\r\n",mode_val_expr); return EINVAL; } + // For debug + //printf("Communication mode passed to rl78 funcs: %i\r\n", mode); + //printf("Mode value expression: %i\r\n",mode_val_expr); break; case 't': terminal = 1; @@ -222,7 +230,16 @@ int main(int argc, char *argv[]) if (invert_reset) { - mode |= MODE_INVERT_RESET; + if (mode == 4) + { + mode = 4; + printf("Using mode 5. INVERT RESET command will not be applied.\r\n"); + } + else + { + mode |= MODE_INVERT_RESET; + } + } char *portname = NULL; char *filename = NULL; diff --git a/src/rl78.c b/src/rl78.c index 7fd235b..49a9cce 100644 --- a/src/rl78.c +++ b/src/rl78.c @@ -21,6 +21,8 @@ #include #include #include "wait_kbhit.h" +#include +#include #include "serial.h" #include "rl78.h" @@ -29,7 +31,13 @@ extern int verbose_level; static unsigned char communication_mode; static void rl78_set_reset(port_handle_t fd, int mode, int value) +// Set reset signal for MCU based on mode (not applicable for mode 5 with hardware switch) { + if (mode == 4) // operating in mode 5 + { + printf("No GPIO SW reset available, must use switch\r\n"); + } + else { int level = (mode & MODE_INVERT_RESET) ? !value : value; if (MODE_RESET_RTS == (mode & MODE_RESET)) @@ -40,16 +48,22 @@ static void rl78_set_reset(port_handle_t fd, int mode, int value) { serial_set_dtr(fd, level); } + } } int rl78_reset_init(port_handle_t fd, int wait, int baud, int mode, float voltage) +// Routine for resetting RL78 and initializing it in programming mode { unsigned char r; + //(mode = desired communication mode from terminal input - 1) + + // Determine UART mode from mode value if (MODE_UART_1 == (mode & MODE_UART)) { r = SET_MODE_1WIRE_UART; communication_mode = 1; } + else { r = SET_MODE_2WIRE_UART; @@ -57,25 +71,71 @@ int rl78_reset_init(port_handle_t fd, int wait, int baud, int mode, float voltag } if (4 <= verbose_level) { + if (mode == 4) // Special case for mode 5 + { + printf("Using communication mode 5 (HW RESET with CTS reading RESET)\n"); + } + else + { printf("Using communication mode %u%s\n", (mode & (MODE_UART | MODE_RESET)) + 1, (mode & MODE_INVERT_RESET) ? " with RESET inversion" : ""); + } } - rl78_set_reset(fd, mode, 0); /* RESET -> 0 */ - serial_set_txd(fd, 0); /* TOOL0 -> 0 */ - if (wait) + serial_set_rts(fd, 0); // TOOL0 -> 0 + // Begin reset procedure + if (mode == 4) // sequencing for mode 5 { - printf("Turn MCU's power on and press any key..."); - wait_kbhit(); - printf("\n"); + printf("Press and let go of RESET."); + int reset = serial_get_cts(fd); + if (reset == 1) + { + while (1) // while CTS/RESET is high, wait + { + reset = serial_get_cts(fd); + if (reset == 0) + { + printf("\nGot reset press."); + break; + } + } + } + + while (1) // while CTS/RESET is low, wait + { + reset = serial_get_cts(fd); + if (reset == 1) + { + printf("\nGot reset release. Setting TOOL0 to 1.\n"); + break; + } + } + // Reset is now high + serial_flush(fd); + usleep(3000); + serial_set_txd(fd,1); // TOOL0 -> 1 + usleep(1000); + serial_flush(fd); + + } + else + { // sequencing for mode 1,2,3,4 + rl78_set_reset(fd, mode, 0); /* RESET -> 0 */ + serial_set_txd(fd, 0); /* TOOL0 -> 0 */ + if (wait) + { + printf("Turn MCU's power on and press any key..."); + wait_kbhit(); + printf("\n"); + } + serial_flush(fd); + usleep(1000); + rl78_set_reset(fd, mode, 1); /* RESET -> 1 */ + usleep(3000); + serial_set_txd(fd, 1); /* TOOL0 -> 1 */ + usleep(1000); + serial_flush(fd); } - serial_flush(fd); - usleep(1000); - rl78_set_reset(fd, mode, 1); /* RESET -> 1 */ - usleep(3000); - serial_set_txd(fd, 1); /* TOOL0 -> 1 */ - usleep(1000); - serial_flush(fd); if (3 <= verbose_level) { printf("Send 1-byte data for setting mode\n"); @@ -91,11 +151,18 @@ int rl78_reset_init(port_handle_t fd, int wait, int baud, int mode, float voltag int rl78_reset(port_handle_t fd, int mode) { - serial_set_txd(fd, 1); /* TOOL0 -> 1 */ - rl78_set_reset(fd, mode, 0); /* RESET -> 0 */ - usleep(10000); - rl78_set_reset(fd, mode, 1); /* RESET -> 1 */ + if (mode == 4) // operating in mode 5 + { + printf("Force reset with SW not available \r\n"); + } + else { + serial_set_txd(fd, 1); /* TOOL0 -> 1 */ + rl78_set_reset(fd, mode, 0); /* RESET -> 0 */ + usleep(10000); + rl78_set_reset(fd, mode, 1); /* RESET -> 1 */ + } return 0; + } static diff --git a/src/rl78.h b/src/rl78.h index 8405b0a..490f11b 100644 --- a/src/rl78.h +++ b/src/rl78.h @@ -63,19 +63,23 @@ #define RESPONSE_FORMAT_ERROR (-2) #define RESPONSE_EXPECTED_LENGTH_ERROR (-3) +// serial command data to tell RL78 which serial mode to use for programming #define SET_MODE_1WIRE_UART 0x3A #define SET_MODE_2WIRE_UART 0x00 #define RL78_MIN_VOLTAGE 1.8f #define RL78_MAX_VOLTAGE 5.5f +// Communication modes passed to RL78 funcs +// Mode 1: MODE #define MODE_UART 1 #define MODE_UART_1 0 #define MODE_UART_2 MODE_UART #define MODE_RESET 2 #define MODE_RESET_DTR 0 #define MODE_RESET_RTS MODE_RESET -#define MODE_MAX_VALUE (MODE_UART | MODE_RESET) +#define MODE_MAX_VALUE 4 +//#define MODE_MAX_VALUE (MODE_UART | MODE_RESET) #define MODE_MIN_VALUE 0 #define MODE_INVERT_RESET 0x80 diff --git a/src/serial.c b/src/serial.c index 20caa35..0d1d713 100644 --- a/src/serial.c +++ b/src/serial.c @@ -24,6 +24,7 @@ #include #include #include +#include extern int verbose_level; @@ -145,6 +146,23 @@ int serial_set_dtr(port_handle_t fd, int level) return ioctl(fd, command, &dtr); } +int serial_get_cts(port_handle_t fd) +{ + int status, flag = 0; + if (ioctl(fd, TIOCMGET, &status) == -1) + { + printf("TIOCMGET failed\n"); + } + else { + flag = !(status & TIOCM_CTS); + // if (flag) + // printf("CTS is set\n"); + // else + // printf("CTS is not set\n"); + } + return(flag); +} + int serial_set_rts(port_handle_t fd, int level) { unsigned long command; diff --git a/src/serial.h b/src/serial.h index 5e6395a..1590c33 100644 --- a/src/serial.h +++ b/src/serial.h @@ -41,6 +41,7 @@ port_handle_t serial_open(const char *port); int serial_set_baud(port_handle_t fd, int baud); int serial_set_parity(port_handle_t fd, int enable, int odd_parity); int serial_set_dtr(port_handle_t fd, int level); +int serial_get_cts(port_handle_t fd); int serial_set_rts(port_handle_t fd, int level); int serial_set_txd(port_handle_t fd, int level); int serial_flush(port_handle_t fd); From 3a1cba02dbe8a1cec70f9e2dfd41b9407960788a Mon Sep 17 00:00:00 2001 From: Jack Gallegos Date: Tue, 2 Apr 2024 22:56:49 -0700 Subject: [PATCH 2/3] Bug fixes confirmed operation works with reading CTS (mode 5) --- README.md | 3 ++- src/main.c | 13 +++++++++++-- src/rl78.c | 27 +++++++++++++-------------- src/serial.c | 15 +++++++++------ 4 files changed, 35 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 58e4428..67ff001 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,8 @@ Features: * Only S-record image files are accepted as input files; * RL78/G10 parts can be programmed only in 1-wire mode, other RL78 parts support both modes (1-wire and 2-wire); -* Reset signal is controlled by DTR or RTS signal. +* Supports software control of reset signal by DTR or RTS signal. +* Supports hardware monitoring of reset signal by observing CTS signal. # Thanks to diff --git a/src/main.c b/src/main.c index 0c8ac90..bd805e4 100644 --- a/src/main.c +++ b/src/main.c @@ -490,9 +490,18 @@ int main(int argc, char *argv[]) { if (1 <= verbose_level) { - printf("Reset MCU\n"); + if (mode == 4) // operating in mode 5 + { + printf("Done! Use HW reset switch to reset MCU.\r\n"); + } + else { + printf("Resetting MCU...\n"); + } + } + if (mode != 4) // Case for HW reset switch + { + rl78_reset(fd, mode); } - rl78_reset(fd, mode); } } while (0); diff --git a/src/rl78.c b/src/rl78.c index 49a9cce..70c0747 100644 --- a/src/rl78.c +++ b/src/rl78.c @@ -57,7 +57,7 @@ int rl78_reset_init(port_handle_t fd, int wait, int baud, int mode, float voltag unsigned char r; //(mode = desired communication mode from terminal input - 1) - // Determine UART mode from mode value + // Determine UART mode from mode argument if (MODE_UART_1 == (mode & MODE_UART)) { r = SET_MODE_1WIRE_UART; @@ -73,6 +73,7 @@ int rl78_reset_init(port_handle_t fd, int wait, int baud, int mode, float voltag { if (mode == 4) // Special case for mode 5 { + communication_mode = 5; printf("Using communication mode 5 (HW RESET with CTS reading RESET)\n"); } else @@ -82,11 +83,13 @@ int rl78_reset_init(port_handle_t fd, int wait, int baud, int mode, float voltag (mode & MODE_INVERT_RESET) ? " with RESET inversion" : ""); } } - serial_set_rts(fd, 0); // TOOL0 -> 0 // Begin reset procedure if (mode == 4) // sequencing for mode 5 { - printf("Press and let go of RESET."); + //printf("Turn MCU's power on with RESET low. Press any key to continue...\n"); + //wait_kbhit(); + serial_set_txd(fd, 0); + printf("Press and hold RESET.\n"); int reset = serial_get_cts(fd); if (reset == 1) { @@ -95,7 +98,9 @@ int rl78_reset_init(port_handle_t fd, int wait, int baud, int mode, float voltag reset = serial_get_cts(fd); if (reset == 0) { - printf("\nGot reset press."); + printf("Got reset press. Hang on...\n"); + usleep(100000); + printf("Let go of RESET.\n"); break; } } @@ -106,7 +111,7 @@ int rl78_reset_init(port_handle_t fd, int wait, int baud, int mode, float voltag reset = serial_get_cts(fd); if (reset == 1) { - printf("\nGot reset release. Setting TOOL0 to 1.\n"); + printf("Got reset release. Attempting to set communication mode...\n"); break; } } @@ -118,7 +123,7 @@ int rl78_reset_init(port_handle_t fd, int wait, int baud, int mode, float voltag serial_flush(fd); } - else + else if ((mode == 0) | (mode == 1) | (mode == 2)) { // sequencing for mode 1,2,3,4 rl78_set_reset(fd, mode, 0); /* RESET -> 0 */ serial_set_txd(fd, 0); /* TOOL0 -> 0 */ @@ -141,7 +146,7 @@ int rl78_reset_init(port_handle_t fd, int wait, int baud, int mode, float voltag printf("Send 1-byte data for setting mode\n"); } serial_write(fd, &r, 1); - if (1 == communication_mode) + if ((1 == communication_mode) | (5 == communication_mode)) { serial_read(fd, &r, 1); } @@ -151,16 +156,10 @@ int rl78_reset_init(port_handle_t fd, int wait, int baud, int mode, float voltag int rl78_reset(port_handle_t fd, int mode) { - if (mode == 4) // operating in mode 5 - { - printf("Force reset with SW not available \r\n"); - } - else { serial_set_txd(fd, 1); /* TOOL0 -> 1 */ rl78_set_reset(fd, mode, 0); /* RESET -> 0 */ usleep(10000); rl78_set_reset(fd, mode, 1); /* RESET -> 1 */ - } return 0; } @@ -198,7 +197,7 @@ int rl78_send_cmd(port_handle_t fd, int cmd, const void *data, int len) buf[len + 4] = ETX; int ret = serial_write(fd, buf, sizeof buf); // Read back echo - if (1 == communication_mode) + if ((1 == communication_mode) | (5 == communication_mode)) { serial_read(fd, buf, sizeof buf); } diff --git a/src/serial.c b/src/serial.c index 0d1d713..f0abcf4 100644 --- a/src/serial.c +++ b/src/serial.c @@ -153,13 +153,14 @@ int serial_get_cts(port_handle_t fd) { printf("TIOCMGET failed\n"); } - else { + else { flag = !(status & TIOCM_CTS); - // if (flag) - // printf("CTS is set\n"); - // else - // printf("CTS is not set\n"); - } + if (flag == 32) { + + flag = 1; + + } + } return(flag); } @@ -183,10 +184,12 @@ int serial_set_txd(port_handle_t fd, int level) unsigned long command; if (level) { + // stop sending zero bits (logic high) command = TIOCCBRK; } else { + // start sending zero bits (logic low) command = TIOCSBRK; } return ioctl(fd, command); From 896538f228282e681d2fbbbe8fe6e2811490988d Mon Sep 17 00:00:00 2001 From: Jack Gallegos Date: Wed, 10 Apr 2024 22:59:13 -0700 Subject: [PATCH 3/3] Code cleanup to address comments in PR - Replaced references to mode numerically with references to bitmap - Style fixes --- src/main.c | 27 +++++++-------------------- src/rl78.c | 51 ++++++++++++++++++++++++--------------------------- src/rl78.h | 6 ++++-- 3 files changed, 35 insertions(+), 49 deletions(-) diff --git a/src/main.c b/src/main.c index bd805e4..796532e 100644 --- a/src/main.c +++ b/src/main.c @@ -53,7 +53,8 @@ const char *usage = "\t\t\tn=2 Two-wire UART, Reset by DTR\n" "\t\t\tn=3 Single-wire UART, Reset by RTS\n" "\t\t\tn=4 Two-wire UART, Reset by RTS\n" - "\t\t\tn=5 Single-wire UART, Hardware Reset, reset state read by CTS (modified mode 1/3)\n" + "\t\t\tn=5 Single-wire UART, Manual Reset Button\n" + "\t\t\tn=6 Two-wire UART, Manual Reset Button\n" "\t\t\tdefault: n=1\n" "\t-P n\tSet protocol version\n" "\t\t\tn=-1 Try to autodetect the protocol version from the unit's Silicon Signature\n" @@ -118,6 +119,7 @@ int main(int argc, char *argv[]) break; case 'm': mode = strtol(optarg, &endp, 10) - 1; + //int mode_reset = mode & MODE_RESET_INPUT; // mode = desired communication mode from terminal input - 1 if (optarg == endp || MODE_MAX_VALUE < mode @@ -125,14 +127,8 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Invalid mode\n"); printf("%s", usage); - // For debug - //printf("Communication mode passed to rl78 funcs: %i\r\n", mode); - //printf("Mode value expression: %i\r\n",mode_val_expr); return EINVAL; } - // For debug - //printf("Communication mode passed to rl78 funcs: %i\r\n", mode); - //printf("Mode value expression: %i\r\n",mode_val_expr); break; case 't': terminal = 1; @@ -230,16 +226,7 @@ int main(int argc, char *argv[]) if (invert_reset) { - if (mode == 4) - { - mode = 4; - printf("Using mode 5. INVERT RESET command will not be applied.\r\n"); - } - else - { - mode |= MODE_INVERT_RESET; - } - + mode |= MODE_INVERT_RESET; } char *portname = NULL; char *filename = NULL; @@ -490,15 +477,15 @@ int main(int argc, char *argv[]) { if (1 <= verbose_level) { - if (mode == 4) // operating in mode 5 + if (MODE_RESET_INPUT_TRUE) { - printf("Done! Use HW reset switch to reset MCU.\r\n"); + printf("Done! Use HW reset button to reset MCU.\r\n"); } else { printf("Resetting MCU...\n"); } } - if (mode != 4) // Case for HW reset switch + if (MODE_RESET_INPUT_TRUE == (mode & MODE_RESET_INPUT)) // Case for HW reset { rl78_reset(fd, mode); } diff --git a/src/rl78.c b/src/rl78.c index 70c0747..25b8b24 100644 --- a/src/rl78.c +++ b/src/rl78.c @@ -33,11 +33,6 @@ static unsigned char communication_mode; static void rl78_set_reset(port_handle_t fd, int mode, int value) // Set reset signal for MCU based on mode (not applicable for mode 5 with hardware switch) { - if (mode == 4) // operating in mode 5 - { - printf("No GPIO SW reset available, must use switch\r\n"); - } - else { int level = (mode & MODE_INVERT_RESET) ? !value : value; if (MODE_RESET_RTS == (mode & MODE_RESET)) @@ -48,7 +43,6 @@ static void rl78_set_reset(port_handle_t fd, int mode, int value) { serial_set_dtr(fd, level); } - } } int rl78_reset_init(port_handle_t fd, int wait, int baud, int mode, float voltage) @@ -57,37 +51,41 @@ int rl78_reset_init(port_handle_t fd, int wait, int baud, int mode, float voltag unsigned char r; //(mode = desired communication mode from terminal input - 1) - // Determine UART mode from mode argument + // Determine UART mode from mode argument if (MODE_UART_1 == (mode & MODE_UART)) { r = SET_MODE_1WIRE_UART; - communication_mode = 1; + if (MODE_RESET_INPUT_TRUE == (mode & MODE_RESET_INPUT)) // sequencing for mode 5 and 6 + { + communication_mode = 5; + } + else { + communication_mode = 1; + } + } else { r = SET_MODE_2WIRE_UART; - communication_mode = 2; + if (MODE_RESET_INPUT_TRUE == (mode & MODE_RESET_INPUT)) // sequencing for mode 5 and 6 + { + communication_mode = 6; + } + else { + communication_mode = 2; + } + //communication_mode = 2; } if (4 <= verbose_level) { - if (mode == 4) // Special case for mode 5 - { - communication_mode = 5; - printf("Using communication mode 5 (HW RESET with CTS reading RESET)\n"); - } - else - { printf("Using communication mode %u%s\n", - (mode & (MODE_UART | MODE_RESET)) + 1, + (mode & (MODE_UART | MODE_RESET | MODE_RESET_INPUT)) + 1, (mode & MODE_INVERT_RESET) ? " with RESET inversion" : ""); - } - } + } // Begin reset procedure - if (mode == 4) // sequencing for mode 5 + if (MODE_RESET_INPUT_TRUE == (mode & MODE_RESET_INPUT)) // sequencing for mode 5 and 6 { - //printf("Turn MCU's power on with RESET low. Press any key to continue...\n"); - //wait_kbhit(); serial_set_txd(fd, 0); printf("Press and hold RESET.\n"); int reset = serial_get_cts(fd); @@ -123,8 +121,7 @@ int rl78_reset_init(port_handle_t fd, int wait, int baud, int mode, float voltag serial_flush(fd); } - else if ((mode == 0) | (mode == 1) | (mode == 2)) - { // sequencing for mode 1,2,3,4 + else { // sequencing for mode 1,2,3,4 rl78_set_reset(fd, mode, 0); /* RESET -> 0 */ serial_set_txd(fd, 0); /* TOOL0 -> 0 */ if (wait) @@ -146,7 +143,7 @@ int rl78_reset_init(port_handle_t fd, int wait, int baud, int mode, float voltag printf("Send 1-byte data for setting mode\n"); } serial_write(fd, &r, 1); - if ((1 == communication_mode) | (5 == communication_mode)) + if (((1 | 5) == communication_mode)) { serial_read(fd, &r, 1); } @@ -197,7 +194,7 @@ int rl78_send_cmd(port_handle_t fd, int cmd, const void *data, int len) buf[len + 4] = ETX; int ret = serial_write(fd, buf, sizeof buf); // Read back echo - if ((1 == communication_mode) | (5 == communication_mode)) + if ((1 | 5) == communication_mode) { serial_read(fd, buf, sizeof buf); } @@ -218,7 +215,7 @@ int rl78_send_data(port_handle_t fd, const void *data, int len, int last) buf[len + 3] = last ? ETX : ETB; int ret = serial_write(fd, buf, sizeof buf); // Read back echo - if (1 == communication_mode) + if ((1 | 5) == communication_mode) { serial_read(fd, buf, sizeof buf); } diff --git a/src/rl78.h b/src/rl78.h index 490f11b..ab34ae0 100644 --- a/src/rl78.h +++ b/src/rl78.h @@ -78,8 +78,10 @@ #define MODE_RESET 2 #define MODE_RESET_DTR 0 #define MODE_RESET_RTS MODE_RESET -#define MODE_MAX_VALUE 4 -//#define MODE_MAX_VALUE (MODE_UART | MODE_RESET) +#define MODE_RESET_INPUT 4 +#define MODE_RESET_INPUT_FALSE 0 +#define MODE_RESET_INPUT_TRUE MODE_RESET_INPUT +#define MODE_MAX_VALUE (MODE_UART | MODE_RESET | MODE_RESET_INPUT) #define MODE_MIN_VALUE 0 #define MODE_INVERT_RESET 0x80