lib: smf: Fix handled bug causing events to not propagate.

When using the SMF for a project discovered that events would sometimes
 not propagate to parent states correctly. Could not create a minimum
reproducable test case for this, but it was found that these changes fixed
the bug. This commit creates a new function to reset internal state,
which is called on entry to smf_set_initial() and smf_set_state().

Closes #81300.

Signed-off-by: Geoffrey Hunter <gbmhunter@gmail.com>
This commit is contained in:
Geoffrey Hunter 2025-01-09 21:19:27 +13:00 committed by Benjamin Cabé
parent 1e75491cdb
commit fa795f4912

View file

@ -148,8 +148,6 @@ static bool smf_execute_ancestor_run_actions(struct smf_ctx *ctx)
/* The child state either transitioned or handled it. Either way, stop propagating. */ /* The child state either transitioned or handled it. Either way, stop propagating. */
if (internal->new_state || internal->handled) { if (internal->new_state || internal->handled) {
internal->new_state = false;
internal->handled = false;
return false; return false;
} }
@ -173,9 +171,6 @@ static bool smf_execute_ancestor_run_actions(struct smf_ctx *ctx)
} }
} }
internal->new_state = false;
internal->handled = false;
/* All done executing the run actions */ /* All done executing the run actions */
return false; return false;
@ -209,10 +204,24 @@ static bool smf_execute_all_exit_actions(struct smf_ctx *const ctx, const struct
} }
#endif /* CONFIG_SMF_ANCESTOR_SUPPORT */ #endif /* CONFIG_SMF_ANCESTOR_SUPPORT */
void smf_set_initial(struct smf_ctx *ctx, const struct smf_state *init_state) /**
* @brief Reset the internal state of the state machine back to default values.
* Should be called on entry to smf_set_initial() and smf_set_state().
*
* @param ctx State machine context.
*/
static void smf_clear_internal_state(struct smf_ctx *ctx)
{ {
struct internal_ctx *const internal = (void *)&ctx->internal; struct internal_ctx *const internal = (void *)&ctx->internal;
internal->is_exit = false;
internal->terminate = false;
internal->handled = false;
internal->new_state = false;
}
void smf_set_initial(struct smf_ctx *ctx, const struct smf_state *init_state)
{
#ifdef CONFIG_SMF_INITIAL_TRANSITION #ifdef CONFIG_SMF_INITIAL_TRANSITION
/* /*
* The final target will be the deepest leaf state that * The final target will be the deepest leaf state that
@ -223,15 +232,14 @@ void smf_set_initial(struct smf_ctx *ctx, const struct smf_state *init_state)
} }
#endif #endif
internal->is_exit = false; smf_clear_internal_state(ctx);
internal->terminate = false;
internal->handled = false;
internal->new_state = false;
ctx->current = init_state; ctx->current = init_state;
ctx->previous = NULL; ctx->previous = NULL;
ctx->terminate_val = 0; ctx->terminate_val = 0;
#ifdef CONFIG_SMF_ANCESTOR_SUPPORT #ifdef CONFIG_SMF_ANCESTOR_SUPPORT
struct internal_ctx *const internal = (void *)&ctx->internal;
ctx->executing = init_state; ctx->executing = init_state;
const struct smf_state *topmost = get_last_of(init_state); const struct smf_state *topmost = get_last_of(init_state);
@ -389,6 +397,11 @@ int32_t smf_run_state(struct smf_ctx *const ctx)
return ctx->terminate_val; return ctx->terminate_val;
} }
/* Executing a states run function could cause a transition, so clear the
* internal state to ensure that the transition is handled correctly.
*/
smf_clear_internal_state(ctx);
#ifdef CONFIG_SMF_ANCESTOR_SUPPORT #ifdef CONFIG_SMF_ANCESTOR_SUPPORT
ctx->executing = ctx->current; ctx->executing = ctx->current;
#endif #endif