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 f339727..796532e 100644 --- a/src/main.c +++ b/src/main.c @@ -53,6 +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, 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" @@ -117,6 +119,8 @@ 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 || MODE_MIN_VALUE > mode) @@ -222,7 +226,7 @@ int main(int argc, char *argv[]) if (invert_reset) { - mode |= MODE_INVERT_RESET; + mode |= MODE_INVERT_RESET; } char *portname = NULL; char *filename = NULL; @@ -473,9 +477,18 @@ int main(int argc, char *argv[]) { if (1 <= verbose_level) { - printf("Reset MCU\n"); + if (MODE_RESET_INPUT_TRUE) + { + printf("Done! Use HW reset button to reset MCU.\r\n"); + } + else { + printf("Resetting MCU...\n"); + } + } + if (MODE_RESET_INPUT_TRUE == (mode & MODE_RESET_INPUT)) // Case for HW reset + { + rl78_reset(fd, mode); } - rl78_reset(fd, mode); } } while (0); diff --git a/src/rl78.c b/src/rl78.c index 7fd235b..25b8b24 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,6 +31,7 @@ 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) { int level = (mode & MODE_INVERT_RESET) ? !value : value; @@ -43,45 +46,104 @@ static void rl78_set_reset(port_handle_t fd, int mode, int value) } 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 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) { 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" : ""); - } - rl78_set_reset(fd, mode, 0); /* RESET -> 0 */ - serial_set_txd(fd, 0); /* TOOL0 -> 0 */ - if (wait) + } + // Begin reset procedure + if (MODE_RESET_INPUT_TRUE == (mode & MODE_RESET_INPUT)) // sequencing for mode 5 and 6 { - printf("Turn MCU's power on and press any key..."); - wait_kbhit(); - printf("\n"); + serial_set_txd(fd, 0); + printf("Press and hold RESET.\n"); + 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("Got reset press. Hang on...\n"); + usleep(100000); + printf("Let go of RESET.\n"); + break; + } + } + } + + while (1) // while CTS/RESET is low, wait + { + reset = serial_get_cts(fd); + if (reset == 1) + { + printf("Got reset release. Attempting to set communication mode...\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"); } serial_write(fd, &r, 1); - if (1 == communication_mode) + if (((1 | 5) == communication_mode)) { serial_read(fd, &r, 1); } @@ -91,11 +153,12 @@ 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 */ + 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 @@ -131,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) + if ((1 | 5) == communication_mode) { serial_read(fd, buf, sizeof buf); } @@ -152,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 8405b0a..ab34ae0 100644 --- a/src/rl78.h +++ b/src/rl78.h @@ -63,19 +63,25 @@ #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_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 diff --git a/src/serial.c b/src/serial.c index 20caa35..f0abcf4 100644 --- a/src/serial.c +++ b/src/serial.c @@ -24,6 +24,7 @@ #include #include #include +#include extern int verbose_level; @@ -145,6 +146,24 @@ 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 == 32) { + + flag = 1; + + } + } + return(flag); +} + int serial_set_rts(port_handle_t fd, int level) { unsigned long command; @@ -165,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); 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);