Line data Source code
1 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 1 : #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 1 : #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 1 : typedef void (*state_execution)(void *obj); 64 : 65 : /** General state that can be used in multiple state machines. */ 66 1 : struct smf_state { 67 : /** Optional method that will be run when this state is entered */ 68 1 : const state_execution entry; 69 : /** 70 : * Optional method that will be run repeatedly during state machine 71 : * loop. 72 : */ 73 1 : const state_execution run; 74 : /** Optional method that will be run when this state exists */ 75 1 : 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 1 : struct smf_ctx { 100 : /** Current state the state machine is executing. */ 101 1 : const struct smf_state *current; 102 : /** Previous state the state machine executed */ 103 1 : 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 1 : 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 1 : 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 1 : 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 1 : 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 1 : 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 1 : 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 1 : 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_ */