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.2.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 : /* clang-format off */
36 1 : #define SMF_CREATE_STATE(_entry, _run, _exit, _parent, _initial) \
37 : { \
38 : .entry = _entry, \
39 : .run = _run, \
40 : .exit = _exit, \
41 : IF_ENABLED(CONFIG_SMF_ANCESTOR_SUPPORT, (.parent = _parent,)) \
42 : IF_ENABLED(CONFIG_SMF_INITIAL_TRANSITION, (.initial = _initial,)) \
43 : }
44 : /* clang-format on */
45 :
46 : /**
47 : * @brief Macro to cast user defined object to state machine
48 : * context.
49 : *
50 : * @param o A pointer to the user defined object
51 : */
52 1 : #define SMF_CTX(o) ((struct smf_ctx *)o)
53 :
54 : #ifdef __cplusplus
55 : extern "C" {
56 : #endif
57 :
58 : #include <zephyr/kernel.h>
59 :
60 : /**
61 : * @brief enum for the return value of a state_execution function
62 : */
63 0 : enum smf_state_result {
64 : SMF_EVENT_HANDLED,
65 : SMF_EVENT_PROPAGATE,
66 : };
67 :
68 : /**
69 : * @brief Function pointer that implements a entry and exit actions
70 : * of a state
71 : *
72 : * @param obj pointer user defined object
73 : */
74 1 : typedef void (*state_method)(void *obj);
75 :
76 : /**
77 : * @brief Function pointer that implements a the run action of a state
78 : *
79 : * @param obj pointer user defined object
80 : * @return If the event should be propagated to parent states or not
81 : * (Ignored when CONFIG_SMF_ANCESTOR_SUPPORT not defined)
82 : */
83 : typedef enum smf_state_result (*state_execution)(void *obj);
84 :
85 : /** General state that can be used in multiple state machines. */
86 1 : struct smf_state {
87 : /** Optional method that will be run when this state is entered */
88 1 : const state_method entry;
89 :
90 : /**
91 : * Optional method that will be run repeatedly during state machine
92 : * loop.
93 : */
94 1 : const state_execution run;
95 :
96 : /** Optional method that will be run when this state exists */
97 1 : const state_method exit;
98 : #ifdef CONFIG_SMF_ANCESTOR_SUPPORT
99 : /**
100 : * Optional parent state that contains common entry/run/exit
101 : * implementation among various child states.
102 : * entry: Parent function executes BEFORE child function.
103 : * run: Parent function executes AFTER child function.
104 : * exit: Parent function executes AFTER child function.
105 : *
106 : * Note: When transitioning between two child states with a shared
107 : * parent, that parent's exit and entry functions do not execute.
108 : */
109 : const struct smf_state *parent;
110 :
111 : #ifdef CONFIG_SMF_INITIAL_TRANSITION
112 : /**
113 : * Optional initial transition state. NULL for leaf states.
114 : */
115 : const struct smf_state *initial;
116 : #endif /* CONFIG_SMF_INITIAL_TRANSITION */
117 : #endif /* CONFIG_SMF_ANCESTOR_SUPPORT */
118 : };
119 :
120 : /** Defines the current context of the state machine. */
121 1 : struct smf_ctx {
122 : /** Current state the state machine is executing. */
123 1 : const struct smf_state *current;
124 : /** Previous state the state machine executed */
125 1 : const struct smf_state *previous;
126 :
127 : #ifdef CONFIG_SMF_ANCESTOR_SUPPORT
128 : /** Currently executing state (which may be a parent) */
129 : const struct smf_state *executing;
130 : #endif /* CONFIG_SMF_ANCESTOR_SUPPORT */
131 : /**
132 : * This value is set by the set_terminate function and
133 : * should terminate the state machine when its set to a
134 : * value other than zero when it's returned by the
135 : * run_state function.
136 : */
137 1 : int32_t terminate_val;
138 : /**
139 : * The state machine casts this to a "struct internal_ctx" and it's
140 : * used to track state machine context
141 : */
142 1 : uint32_t internal;
143 : };
144 :
145 : /**
146 : * @brief Initializes the state machine and sets its initial state.
147 : *
148 : * @param ctx State machine context
149 : * @param init_state Initial state the state machine starts in.
150 : */
151 1 : void smf_set_initial(struct smf_ctx *ctx, const struct smf_state *init_state);
152 :
153 : /**
154 : * @brief Changes a state machines state. This handles exiting the previous
155 : * state and entering the target state. For HSMs the entry and exit
156 : * actions of the Least Common Ancestor will not be run.
157 : *
158 : * @param ctx State machine context
159 : * @param new_state State to transition to (NULL is valid and exits all states)
160 : */
161 1 : void smf_set_state(struct smf_ctx *ctx, const struct smf_state *new_state);
162 :
163 : /**
164 : * @brief Terminate a state machine
165 : *
166 : * @param ctx State machine context
167 : * @param val Non-Zero termination value that's returned by the smf_run_state
168 : * function.
169 : */
170 1 : void smf_set_terminate(struct smf_ctx *ctx, int32_t val);
171 :
172 : /**
173 : * @brief Runs one iteration of a state machine (including any parent states)
174 : *
175 : * @param ctx State machine context
176 : * @return A non-zero value should terminate the state machine. This
177 : * non-zero value could represent a terminal state being reached
178 : * or the detection of an error that should result in the
179 : * termination of the state machine.
180 : */
181 1 : int32_t smf_run_state(struct smf_ctx *ctx);
182 :
183 : #ifdef __cplusplus
184 : }
185 : #endif
186 :
187 : /**
188 : * @}
189 : */
190 :
191 : #endif /* ZEPHYR_INCLUDE_SMF_H_ */
|