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