Add Mode 5: Physical reset, for UARTS with only RTS, no DTR.#28
Add Mode 5: Physical reset, for UARTS with only RTS, no DTR.#28SmittyHalibut wants to merge 3 commits intomsalau:masterfrom
Conversation
| "\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" |
There was a problem hiding this comment.
It's all "hardware reset." I'd say "Manual reset button" instead.
There was a problem hiding this comment.
Will probably want to update this after seeing below about mode being a bitmap. n=5 is as you describe, but n=6 will be Two-wire UART, Manual Reset. (You get it for free when mode is a bitmap.)
| // 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); |
There was a problem hiding this comment.
Normally, you'd remove your temporary debugging code from the commit before issuing a PR. Or, wrap it in if (verbose_level > whatever) block.
| if (mode == 4) | ||
| { | ||
| mode = 4; |
There was a problem hiding this comment.
This code is only ever run if mode == 4 so assigning it to 4 is unnecessary.
There was a problem hiding this comment.
Actually, treating mode as a bitmap (see below), you might as well still allow this, and use it when detecting CTS.
That is, just remove this change and go back to the original code. It's ok if MODE_INVERT_RESET bit is set.
| { | ||
| if (mode == 4) // operating in mode 5 | ||
| { | ||
| printf("No GPIO SW reset available, must use switch\r\n"); |
There was a problem hiding this comment.
Pedantic Pet Peeve of mine: feel free to ignore. ;-)
Switches are latching and/or sliding/rotating, buttons are momentary and/or linear motion. This is a button, not a switch.
Yes, yes, this depends on how you implement the hardware. But I've never seen a Reset Switch, only ever Reset Buttons. Possibly a Reset Momentary Switch on front-panels of old mini-computers. But these are almost certainly going to be buttons.
| { | ||
| printf("No GPIO SW reset available, must use switch\r\n"); | ||
| } | ||
| else { |
There was a problem hiding this comment.
GitHub won't let me select the whole block here.
But fix the indentation below.
| { | ||
| serial_set_dtr(fd, level); | ||
| } | ||
| } |
There was a problem hiding this comment.
Indentation is broken down to here.
| unsigned char r; | ||
| //(mode = desired communication mode from terminal input - 1) | ||
|
|
||
| // Determine UART mode from mode argument |
There was a problem hiding this comment.
Indentation (just the one line)
| r = SET_MODE_1WIRE_UART; | ||
| communication_mode = 1; | ||
| } | ||
|
|
| 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_INVERT_RESET) ? " with RESET inversion" : ""); | ||
| } | ||
| } |
There was a problem hiding this comment.
This is why the behavior changes when you change your verbosity level. communication_mode = 5 shouldn't be inside if (4 <= verbose_level)
Or rather, you shouldn't be setting communication_mode at all, which is why it broke when you increased the verbosity. :-)
| 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; | ||
| } | ||
| } |
There was a problem hiding this comment.
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.
| } | ||
| serial_write(fd, &r, 1); | ||
| if (1 == communication_mode) | ||
| if ((1 == communication_mode) | (5 == communication_mode)) |
There was a problem hiding this comment.
communication_mode is just whether it's a 1-wire or 2-wire. Since mode 5 is a 1-wire, just test for 1 here. This is part of the treating mode as a bit-map change.
Read: Undo this change. Only test for (1 == communication_mode) as originally done.
| 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; |
There was a problem hiding this comment.
Too much indentation. Fix this.
| serial_flush(fd); | ||
|
|
||
| } | ||
| else if ((mode == 0) | (mode == 1) | (mode == 2)) |
There was a problem hiding this comment.
else if (MODE_RESET_INPUT_FALSE == (mode & MODE_RESET_INPUT))
Actually, this is just else.
| if (1 <= verbose_level) | ||
| { | ||
| printf("Reset MCU\n"); | ||
| if (mode == 4) // operating in mode 5 |
There was a problem hiding this comment.
When used to determine whether reset is controlled by the code, or triggered by the user, change if (mode == 4) to if (MODE_RESET_INPUT_TRUE == (mode & MODE_RESET_INPUT))
This happens in multiple places. I'll just say MODE_RESET_INPUT in future comments to mean the same thing.
| printf("Resetting MCU...\n"); | ||
| } | ||
| } | ||
| if (mode != 4) // Case for HW reset switch |
| 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 |
| else | ||
| { | ||
| printf("Using communication mode %u%s\n", | ||
| (mode & (MODE_UART | MODE_RESET)) + 1, |
There was a problem hiding this comment.
(mode & (MODE_UART | MODE_RESET | MODE_RESET_INPUT)) + 1
| else { | ||
| int level = (mode & MODE_INVERT_RESET) ? !value : value; | ||
|
|
||
| if (MODE_RESET_RTS == (mode & MODE_RESET)) |
There was a problem hiding this comment.
We shouldn't be messing with RTS or DTR if we are inputing the reset signal.
if ((MODE_RESET_RTS == (mode & MODE_RESET)) && (MODE_RESET_INPUT_FALSE == (mode && MOST_RESET_INPUT)))
| if (mode == 4) // Special case for mode 5 | ||
| { | ||
| communication_mode = 5; | ||
| printf("Using communication mode 5 (HW RESET with CTS reading RESET)\n"); | ||
| } |
There was a problem hiding this comment.
Don't change communication_mode here. I think we want this to stay either 1 or 2. You can still output the verbose message, but trigger that based on (mode & MODE_RESET_INPUT == MODE_RESET_INPUT_TRUE instead of mode == 4.
| serial_set_txd(fd, 0); /* TOOL0 -> 0 */ | ||
| if (wait) | ||
| // Begin reset procedure | ||
| if (mode == 4) // sequencing for mode 5 |
There was a problem hiding this comment.
if (MODE_RESET_INPUT_TRUE == (mode & MODE_RESET_INPUT))
(ngl, I don't understand putting the constant before the == thing. But maintaining code style is more important than using MY code style.)
| int ret = serial_write(fd, buf, sizeof buf); | ||
| // Read back echo | ||
| if (1 == communication_mode) | ||
| if ((1 == communication_mode) | (5 == communication_mode)) |
There was a problem hiding this comment.
Same as above. Only test for 1 ==
| // 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 |
There was a problem hiding this comment.
Ok this is the big "mode as a bit-map" thing I've been talking about above.
Bit 1 of mode is whether it's a 1-wire or 2-wire serial protocol.
Bit 2 of mode is whether RESET is on DTR or RTS.
We should make Bit 4 of mode be whether RESET is an INPUT or not. All my comments above are to change the code for this.
Here, we need these #defines to be:
...
#define MODE_RESET_RTS 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)
...
SmittyHalibut
left a comment
There was a problem hiding this comment.
whew! Ok.
There are a few style and formatting comments buried in here, don't lose those.
But the biggest change I'm requesting is that we continue to treat mode as a bit-map, instead of just a sequentially assigned arbitrary mode number. Modes 1 through 4 are actually a bit map of features, one of which matters to us. So I propose we keep with that bit map, and add another bit that is "Is Reset an input or not?" When we continue to use bit 1 to determine whether it's a 1-wire or 2-wire protocol, and bit 2 to determine which output pin to use for reset (which doesn't matter in our case).
OR! Possibly use that bit to select between CTR and DSR for the input pins. shrug or don't bother with that, and just stick to CTR.
In any case, most of my actual code changes in this review are to implement this change.
- Replaced references to mode numerically with references to bitmap - Style fixes
This is a draft pull request so I can comment on the sum of two commits.