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