1 /* 2 * Copyright 2021 The Chromium OS Authors 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 /** 8 * @file 9 * 10 * @brief State Machine Framework header file 11 */ 12 13 #ifndef ZEPHYR_INCLUDE_SMF_H_ 14 #define ZEPHYR_INCLUDE_SMF_H_ 15 16 #include <zephyr/sys/util.h> 17 18 /** 19 * @brief State Machine Framework API 20 * @defgroup smf State Machine Framework API 21 * @version 0.1.0 22 * @ingroup os_services 23 * @{ 24 */ 25 26 /** 27 * @brief Macro to create a hierarchical state with initial transitions. 28 * 29 * @param _entry State entry function or NULL 30 * @param _run State run function or NULL 31 * @param _exit State exit function or NULL 32 * @param _parent State parent object or NULL 33 * @param _initial State initial transition object or NULL 34 */ 35 #define SMF_CREATE_STATE(_entry, _run, _exit, _parent, _initial) \ 36 { \ 37 .entry = _entry, \ 38 .run = _run, \ 39 .exit = _exit, \ 40 IF_ENABLED(CONFIG_SMF_ANCESTOR_SUPPORT, (.parent = _parent,)) \ 41 IF_ENABLED(CONFIG_SMF_INITIAL_TRANSITION, (.initial = _initial,)) \ 42 } 43 44 /** 45 * @brief Macro to cast user defined object to state machine 46 * context. 47 * 48 * @param o A pointer to the user defined object 49 */ 50 #define SMF_CTX(o) ((struct smf_ctx *)o) 51 52 #ifdef __cplusplus 53 extern "C" { 54 #endif 55 56 #include <zephyr/kernel.h> 57 58 /** 59 * @brief Function pointer that implements a portion of a state 60 * 61 * @param obj pointer user defined object 62 */ 63 typedef void (*state_execution)(void *obj); 64 65 /** General state that can be used in multiple state machines. */ 66 struct smf_state { 67 /** Optional method that will be run when this state is entered */ 68 const state_execution entry; 69 /** 70 * Optional method that will be run repeatedly during state machine 71 * loop. 72 */ 73 const state_execution run; 74 /** Optional method that will be run when this state exists */ 75 const state_execution exit; 76 #ifdef CONFIG_SMF_ANCESTOR_SUPPORT 77 /** 78 * Optional parent state that contains common entry/run/exit 79 * implementation among various child states. 80 * entry: Parent function executes BEFORE child function. 81 * run: Parent function executes AFTER child function. 82 * exit: Parent function executes AFTER child function. 83 * 84 * Note: When transitioning between two child states with a shared 85 * parent, that parent's exit and entry functions do not execute. 86 */ 87 const struct smf_state *parent; 88 89 #ifdef CONFIG_SMF_INITIAL_TRANSITION 90 /** 91 * Optional initial transition state. NULL for leaf states. 92 */ 93 const struct smf_state *initial; 94 #endif /* CONFIG_SMF_INITIAL_TRANSITION */ 95 #endif /* CONFIG_SMF_ANCESTOR_SUPPORT */ 96 }; 97 98 /** Defines the current context of the state machine. */ 99 struct smf_ctx { 100 /** Current state the state machine is executing. */ 101 const struct smf_state *current; 102 /** Previous state the state machine executed */ 103 const struct smf_state *previous; 104 105 #ifdef CONFIG_SMF_ANCESTOR_SUPPORT 106 /** Currently executing state (which may be a parent) */ 107 const struct smf_state *executing; 108 #endif /* CONFIG_SMF_ANCESTOR_SUPPORT */ 109 /** 110 * This value is set by the set_terminate function and 111 * should terminate the state machine when its set to a 112 * value other than zero when it's returned by the 113 * run_state function. 114 */ 115 int32_t terminate_val; 116 /** 117 * The state machine casts this to a "struct internal_ctx" and it's 118 * used to track state machine context 119 */ 120 uint32_t internal; 121 }; 122 123 /** 124 * @brief Initializes the state machine and sets its initial state. 125 * 126 * @param ctx State machine context 127 * @param init_state Initial state the state machine starts in. 128 */ 129 void smf_set_initial(struct smf_ctx *ctx, const struct smf_state *init_state); 130 131 /** 132 * @brief Changes a state machines state. This handles exiting the previous 133 * state and entering the target state. For HSMs the entry and exit 134 * actions of the Least Common Ancestor will not be run. 135 * 136 * @param ctx State machine context 137 * @param new_state State to transition to (NULL is valid and exits all states) 138 */ 139 void smf_set_state(struct smf_ctx *ctx, const struct smf_state *new_state); 140 141 /** 142 * @brief Terminate a state machine 143 * 144 * @param ctx State machine context 145 * @param val Non-Zero termination value that's returned by the smf_run_state 146 * function. 147 */ 148 void smf_set_terminate(struct smf_ctx *ctx, int32_t val); 149 150 /** 151 * @brief Tell the SMF to stop propagating the event to ancestors. This allows 152 * HSMs to implement 'programming by difference' where substates can 153 * handle events on their own or propagate up to a common handler. 154 * 155 * @param ctx State machine context 156 */ 157 void smf_set_handled(struct smf_ctx *ctx); 158 159 /** 160 * @brief Runs one iteration of a state machine (including any parent states) 161 * 162 * @param ctx State machine context 163 * @return A non-zero value should terminate the state machine. This 164 * non-zero value could represent a terminal state being reached 165 * or the detection of an error that should result in the 166 * termination of the state machine. 167 */ 168 int32_t smf_run_state(struct smf_ctx *ctx); 169 170 #ifdef __cplusplus 171 } 172 #endif 173 174 /** 175 * @} 176 */ 177 178 #endif /* ZEPHYR_INCLUDE_SMF_H_ */ 179