Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Mode 5: Physical reset, for UARTS with only RTS, no DTR. #28

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
19 changes: 16 additions & 3 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
111 changes: 87 additions & 24 deletions src/rl78.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include <string.h>
#include <stdio.h>
#include "wait_kbhit.h"
#include <errno.h>
#include <sys/ioctl.h>

#include "serial.h"
#include "rl78.h"
Expand All @@ -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;

Expand All @@ -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;
}

}

Copy link
Author

@SmittyHalibut SmittyHalibut Apr 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove blank line.

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;
}
}
Comment on lines +91 to +115
Copy link
Author

@SmittyHalibut SmittyHalibut Apr 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is overly complex to read.

Also, lets allow for inverted reset here. Add:

bool active = (mode & MODE_INVERT_RESET) ? 0 : 1;

Test my active logic here. I might have it backwards.

Replace the first block with just:

while (serial_get_cts(fd) == active)
{
    usleep(1000);
}

Then move the printf(); usleep(); printf() block outside the while loop.

Replace the second block with:

while (serial_get_cts(fd) != active)
{
    usleep(1000);
}

Then move the printf() outside the while loop.

The usleep(1000) just keeps it from completely locking up a CPU while waiting.

// 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);
}
Expand All @@ -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;
Comment on lines 154 to 160
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Too much indentation. Fix this.


}

static
Expand Down Expand Up @@ -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);
}
Expand All @@ -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);
}
Expand Down
8 changes: 7 additions & 1 deletion src/rl78.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
21 changes: 21 additions & 0 deletions src/serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>

extern int verbose_level;

Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down
1 change: 1 addition & 0 deletions src/serial.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down