This is an automated email from Gerrit. "Antonio Borneo <borneo.anto...@gmail.com>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/7134
-- gerrit commit d30abaf36c3b874485370865547f1f8dd33557bd Author: Antonio Borneo <borneo.anto...@gmail.com> Date: Thu Aug 18 01:29:33 2022 +0200 jtag: rewrite the state machine for power drop and srst deassert The current state machine looks broken. Rewrite it in a trivial way and document it through a diagram. While there, use boolean type in place of integers. Change-Id: I25b11e52a69d397e832724e01d18beb9770cc4b7 Signed-off-by: Antonio Borneo <borneo.anto...@gmail.com> diff --git a/src/jtag/core.c b/src/jtag/core.c index 806ee89265..e41b60d60d 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -1707,7 +1707,7 @@ bool jtag_will_verify_capture_ir(void) return jtag_verify_capture_ir; } -int jtag_power_dropout(int *dropout) +int jtag_power_dropout(bool *dropout) { if (!is_adapter_initialized()) { /* TODO: as the jtag interface is not valid all @@ -1718,16 +1718,16 @@ int jtag_power_dropout(int *dropout) if (adapter_driver->power_dropout) return adapter_driver->power_dropout(dropout); - *dropout = 0; /* by default we can't detect power dropout */ + *dropout = false; /* by default we can't detect power dropout */ return ERROR_OK; } -int jtag_srst_asserted(int *srst_asserted) +int jtag_srst_asserted(bool *srst_asserted) { if (adapter_driver->srst_asserted) return adapter_driver->srst_asserted(srst_asserted); - *srst_asserted = 0; /* by default we can't detect srst asserted */ + *srst_asserted = false; /* by default we can't detect srst asserted */ return ERROR_OK; } diff --git a/src/jtag/interface.h b/src/jtag/interface.h index a8d9ee47e9..1a64e093ff 100644 --- a/src/jtag/interface.h +++ b/src/jtag/interface.h @@ -293,7 +293,7 @@ struct adapter_driver { * * @returns ERROR_OK on success, or an error code on failure. */ - int (*power_dropout)(int *power_dropout); + int (*power_dropout)(bool *power_dropout); /** * Read and clear the srst asserted detection flag. @@ -307,7 +307,7 @@ struct adapter_driver { * been asserted. * @returns ERROR_OK on success, or an error code on failure. */ - int (*srst_asserted)(int *srst_asserted); + int (*srst_asserted)(bool *srst_asserted); /** * Configure trace parameters for the adapter diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h index 4f94e99135..d5757d7a53 100644 --- a/src/jtag/jtag.h +++ b/src/jtag/jtag.h @@ -525,8 +525,8 @@ int jtag_get_flush_queue_count(void); void jtag_notify_event(enum jtag_event); /* can be implemented by hw + sw */ -int jtag_power_dropout(int *dropout); -int jtag_srst_asserted(int *srst_asserted); +int jtag_power_dropout(bool *dropout); +int jtag_srst_asserted(bool *srst_asserted); /* JTAG support functions */ diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c index 37a0285ce1..d7721492b6 100644 --- a/src/jtag/tcl.c +++ b/src/jtag/tcl.c @@ -1239,7 +1239,7 @@ COMMAND_HANDLER(handle_wait_srst_deassert) } LOG_USER("Waiting for srst assert + deassert for at most %dms", timeout_ms); - int asserted_yet; + bool asserted_yet; int64_t then = timeval_ms(); while (jtag_srst_asserted(&asserted_yet) == ERROR_OK) { if ((timeval_ms() - then) > timeout_ms) { diff --git a/src/target/target.c b/src/target/target.c index 10a25efde6..83769cd087 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -2908,63 +2908,118 @@ COMMAND_HANDLER(handle_targets_command) return retval; } -/* every 300ms we check for reset & powerdropout and issue a "reset halt" if so. */ +/* + * Periodic check for reset & power dropout. + * + * State diagram for power dropout detection. + * Similar diagram applies to srst detection. + * + * (START) + * v ------------ ----------- + * | | | | | + * v v | v | + * ----------- no-drop | ----------- drop | + * | |>--------- | |>-------- + * | POWER | | POWER | + * | ON | drop (run-dropout) | OFF | no-drop + * | |>------------------->| |>-------- + * ----------- ----------- | + * ^ ^ | + * | | | + * | | v + * | yes (run-restore) | drop ----------- + * _/^\_ --------<| | + * _/ \_ | POWER | + * / \ no-drop | WAIT ON | + * | TIMEOUT |<-------------------------------<| | + * \_ ? _/ ----------- + * \_ _/ ^ + * \v/ | + * | no | + * -------------------------------------------- + */ -static int power_dropout; -static int srst_asserted; +#define SENSE_TIMEOUT_MS 2000 -static int run_power_restore; -static int run_power_dropout; -static int run_srst_asserted; -static int run_srst_deasserted; +enum sense_state { + POWER_STATE_ON = 0, + POWER_STATE_OFF, + POWER_STATE_WAIT_ON, + + SRST_STATE_DEASSERTED = 0, + SRST_STATE_ASSERTED, + SRST_STATE_WAIT_DEASSERTED, +}; + +static bool run_power_restore, run_power_dropout; +static bool run_srst_asserted, run_srst_deasserted; + +static enum sense_state power_state = POWER_STATE_ON; +static enum sense_state srst_state = SRST_STATE_DEASSERTED; static int sense_handler(void) { - static int prev_srst_asserted; - static int prev_power_dropout; + static int64_t power_on_deadline, srst_deasserted_deadline; + bool power_dropout, srst_asserted; int retval = jtag_power_dropout(&power_dropout); if (retval != ERROR_OK) return retval; - int power_restored; - power_restored = prev_power_dropout && !power_dropout; - if (power_restored) - run_power_restore = 1; - - int64_t current = timeval_ms(); - static int64_t last_power; - bool wait_more = last_power + 2000 > current; - if (power_dropout && !wait_more) { - run_power_dropout = 1; - last_power = current; + switch (power_state) { + case POWER_STATE_OFF: + if (!power_dropout) { + power_state = POWER_STATE_WAIT_ON; + power_on_deadline = timeval_ms() + SENSE_TIMEOUT_MS; + } + break; + case POWER_STATE_WAIT_ON: + if (power_dropout) { + power_state = POWER_STATE_OFF; + break; + } + if (timeval_ms() > power_on_deadline) { + power_state = POWER_STATE_ON; + run_power_restore = true; + } + break; + case POWER_STATE_ON: + default: + if (power_dropout) { + power_state = POWER_STATE_OFF; + run_power_dropout = true; + } + break; } retval = jtag_srst_asserted(&srst_asserted); if (retval != ERROR_OK) return retval; - int srst_deasserted; - srst_deasserted = prev_srst_asserted && !srst_asserted; - - static int64_t last_srst; - wait_more = last_srst + 2000 > current; - if (srst_deasserted && !wait_more) { - run_srst_deasserted = 1; - last_srst = current; - } - - if (!prev_srst_asserted && srst_asserted) - run_srst_asserted = 1; - - prev_srst_asserted = srst_asserted; - prev_power_dropout = power_dropout; - - if (srst_deasserted || power_restored) { - /* Other than logging the event we can't do anything here. - * Issuing a reset is a particularly bad idea as we might - * be inside a reset already. - */ + switch (srst_state) { + case SRST_STATE_ASSERTED: + if (!srst_asserted) { + srst_state = SRST_STATE_WAIT_DEASSERTED; + srst_deasserted_deadline = timeval_ms() + SENSE_TIMEOUT_MS; + } + break; + case SRST_STATE_WAIT_DEASSERTED: + if (srst_asserted) { + srst_state = SRST_STATE_ASSERTED; + break; + } + if (timeval_ms() > srst_deasserted_deadline) { + srst_state = SRST_STATE_DEASSERTED; + run_srst_deasserted = true; + } + break; + case SRST_STATE_DEASSERTED: + default: + if (srst_asserted) { + srst_state = SRST_STATE_ASSERTED; + run_srst_asserted = true; + } + break; } return ERROR_OK; @@ -2982,32 +3037,32 @@ static int handle_target(void *priv) } /* we do not want to recurse here... */ - static int recursive; + static bool recursive; if (!recursive) { - recursive = 1; + recursive = true; sense_handler(); /* danger! running these procedures can trigger srst assertions and power dropouts. * We need to avoid an infinite loop/recursion here and we do that by * clearing the flags after running these events. */ - int did_something = 0; + bool did_something = false; if (run_srst_asserted) { LOG_INFO("srst asserted detected, running srst_asserted proc."); Jim_Eval(interp, "srst_asserted"); - did_something = 1; + did_something = true; } if (run_srst_deasserted) { Jim_Eval(interp, "srst_deasserted"); - did_something = 1; + did_something = true; } if (run_power_dropout) { LOG_INFO("Power dropout detected, running power_dropout proc."); Jim_Eval(interp, "power_dropout"); - did_something = 1; + did_something = true; } if (run_power_restore) { Jim_Eval(interp, "power_restore"); - did_something = 1; + did_something = true; } if (did_something) { @@ -3016,13 +3071,12 @@ static int handle_target(void *priv) } /* clear action flags */ + run_srst_asserted = false; + run_srst_deasserted = false; + run_power_restore = false; + run_power_dropout = false; - run_srst_asserted = 0; - run_srst_deasserted = 0; - run_power_restore = 0; - run_power_dropout = 0; - - recursive = 0; + recursive = false; } /* Poll targets for state changes unless that's globally disabled. @@ -3046,7 +3100,7 @@ static int handle_target(void *priv) target->backoff.count = 0; /* only poll target if we've got power and srst isn't asserted */ - if (!power_dropout && !srst_asserted) { + if (power_state == POWER_STATE_ON && srst_state == SRST_STATE_DEASSERTED) { /* polling may fail silently until the target has been examined */ retval = target_poll(target); if (retval != ERROR_OK) { --