Skip to content

Lib: SMF: Add return code to signal event propagation #83854

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

glenn-andrews
Copy link
Collaborator

@glenn-andrews glenn-andrews commented Jan 11, 2025

See Discussion #83659 for information about the purpose of this change.

Modifies run actions of state machines to return a value indicating if the event was handled by the run action or should be propagated up to the parent run action.

smf_set_handled() has been removed and replaced by this return value. smf_set_state() will not propagate events regardless of the return value as the transition is considered to have occurred.

Documentation, tests and samples have been updated, as has the hawkBit and USB-C subsystems.

@glenn-andrews glenn-andrews force-pushed the smf_state_fn_return_codes branch 2 times, most recently from 18f011e to 8cd0ac3 Compare January 11, 2025 20:07
@henrikbrixandersen henrikbrixandersen self-requested a review January 11, 2025 20:08
@glenn-andrews glenn-andrews force-pushed the smf_state_fn_return_codes branch 2 times, most recently from fa73a26 to 0a6b01b Compare January 11, 2025 22:14
@zephyrbot zephyrbot added area: USB Universal Serial Bus area: USB-C labels Jan 11, 2025
@glenn-andrews glenn-andrews force-pushed the smf_state_fn_return_codes branch from 0a6b01b to e438134 Compare January 11, 2025 23:05
@glenn-andrews glenn-andrews force-pushed the smf_state_fn_return_codes branch 8 times, most recently from 0d8b648 to 80edfef Compare January 13, 2025 15:43
@@ -1293,13 +1293,14 @@ static void s_probe(void *o)
hawkbit_event_raise(HAWKBIT_EVENT_NO_UPDATE);
smf_set_state(SMF_CTX(s), &hawkbit_states[S_HAWKBIT_TERMINATE]);
}
return SMF_EVENT_PROPAGATE;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why SMF_EVENT_PROPAGATE and not SMF_EVENT_HANDLED, like in all other cases?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because it's at the end of the function and anything at that point which is not handled should be propagated.

To be honest, since smf_set_state() will block propagation, anywhere we do not explicitly use smf_set_handled() can use SMF_EVENT_PROPAGATE and still work the same.

.run = _run, \
.exit = _exit, \
IF_ENABLED(CONFIG_SMF_ANCESTOR_SUPPORT, (.parent = _parent,)) \
IF_ENABLED(CONFIG_SMF_INITIAL_TRANSITION, (.initial = _initial,)) }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this line should not be intended more than the one above, clang format should more be seen as a suggestion and not a a mandatory change.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If everyone used clang-format I'd not have needed the first two commits, and every future commit would be clean of formatting changes.

I'd rather machine-assisted uniformity, than others making it 'pretty' and me breaking it every time I want to ensure my code meets compliance.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-format is not perfect, that's why it is only described as a helper for formation in the docs. For the styling we have the Coding Style, which is enforced by CI and Reviewers. When making commits and editing files, it is normally not a good idea, to run clang-format on the whole file as it will change things that are fine to ugly.

Apply clang-format in preparation for code changes.

Signed-off-by: Glenn Andrews <[email protected]>
Comment on lines 40 to 63
#define P05_ENTRY_BIT (1 << 0)
#define P04_ENTRY_BIT (1 << 1)
#define P03_ENTRY_BIT (1 << 2)
#define P02_ENTRY_BIT (1 << 3)
#define P01_ENTRY_BIT (1 << 4)
#define A_ENTRY_BIT (1 << 5)
#define A_RUN_BIT (1 << 6)
#define A_EXIT_BIT (1 << 7)
#define B_ENTRY_BIT (1 << 8)
#define B_RUN_BIT (1 << 9)
#define P01_RUN_BIT (1 << 10)
#define P02_RUN_BIT (1 << 11)
#define P03_RUN_BIT (1 << 12)
#define P04_RUN_BIT (1 << 13)
#define P05_RUN_BIT (1 << 14)
#define B_EXIT_BIT (1 << 15)
#define P01_EXIT_BIT (1 << 16)
#define P02_EXIT_BIT (1 << 17)
#define P03_EXIT_BIT (1 << 18)
#define P04_EXIT_BIT (1 << 19)
#define P05_EXIT_BIT (1 << 20)
#define C_ENTRY_BIT (1 << 21)
#define C_RUN_BIT (1 << 22)
#define C_EXIT_BIT (1 << 23)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you are changing it already please use BIT()

Comment on lines 46 to 61
#define PARENT_AB_ENTRY_BIT (1 << 0)
#define STATE_A_ENTRY_BIT (1 << 1)
#define STATE_A_RUN_BIT (1 << 2)
#define PARENT_AB_RUN_BIT (1 << 3)
#define STATE_A_EXIT_BIT (1 << 4)

#define STATE_B_ENTRY_BIT (1 << 5)
#define STATE_B_RUN_BIT (1 << 6)
#define STATE_B_EXIT_BIT (1 << 7)
#define PARENT_AB_EXIT_BIT (1 << 8)
#define STATE_B_ENTRY_BIT (1 << 5)
#define STATE_B_RUN_BIT (1 << 6)
#define STATE_B_EXIT_BIT (1 << 7)
#define PARENT_AB_EXIT_BIT (1 << 8)

#define PARENT_C_ENTRY_BIT (1 << 9)
#define STATE_C_ENTRY_BIT (1 << 10)
#define STATE_C_RUN_BIT (1 << 11)
#define STATE_C_EXIT_BIT (1 << 12)
#define PARENT_C_EXIT_BIT (1 << 13)
#define PARENT_C_ENTRY_BIT (1 << 9)
#define STATE_C_ENTRY_BIT (1 << 10)
#define STATE_C_RUN_BIT (1 << 11)
#define STATE_C_EXIT_BIT (1 << 12)
#define PARENT_C_EXIT_BIT (1 << 13)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here too

@glenn-andrews glenn-andrews force-pushed the smf_state_fn_return_codes branch from ae2e0ca to 6df4056 Compare June 5, 2025 13:03
@maass-hamburg
Copy link
Collaborator

@glenn-andrews smf ci tests are failing

@glenn-andrews
Copy link
Collaborator Author

@glenn-andrews smf ci tests are failing

Yep, and on Windows the qemu_cortex_r5/zynqmp_rpu fails to build entirely so I have no idea what's going on.

Can someone run west twister -p qemu_cortex_r5/zynqmp_rpu -s sample.smf.hsm_psicc2 --no-detailed-test-id under Linux and see what the failure is?

The tests are passing for other qemu targets.

(.venv) PS C:\Users\glenn\zephyrproject_latest\zephyr\tests\lib\smf> west twister -p qemu_cortex_r5/zynqmp_rpu -s sample.smf.hsm_psicc2 --no-detailed-test-id --short-build-path
INFO    - Using Ninja..
INFO    - Zephyr version: v4.1.0-5262-g6df4056ba214
INFO    - Using 'zephyr' toolchain.
INFO    - Building initial testsuite list...
INFO    - Writing JSON report C:\Users\glenn\zephyrproject_latest\zephyr\tests\lib\smf\twister-out\testplan.json
Junction created for C:\Users\glenn\zephyrproject_latest\zephyr\tests\lib\smf\twister-out\twister_links\test_0 <<===>> C:\Users\glenn\zephyrproject_latest\zephyr\tests\lib\smf\twister-out\qemu_cortex_r5_zynqmp_rpu\zephyr\samples\subsys\smf\hsm_psicc2\sample.smf.hsm_psicc2
INFO    - Adding tasks to the queue...
INFO    - Added initial list of jobs to queue
ERROR   - General exception: 'NoneType' object cannot be interpreted as an integer
Traceback (most recent call last):
  File "C:\Users\glenn\zephyrproject_latest\zephyr\scripts\pylib\twister\twisterlib\runner.py", line 2023, in pipeline_mgr
    pb.process(pipeline, done_queue, task, lock, results)
  File "C:\Users\glenn\zephyrproject_latest\zephyr\scripts\pylib\twister\twisterlib\runner.py", line 1129, in process
    self.run()
  File "C:\Users\glenn\zephyrproject_latest\zephyr\scripts\pylib\twister\twisterlib\runner.py", line 1790, in run
    instance.handler.handle(harness)
  File "C:\Users\glenn\zephyrproject_latest\zephyr\scripts\pylib\twister\twisterlib\handlers.py", line 1427, in handle
    os.close(self.pipe_handle)
TypeError: 'NoneType' object cannot be interpreted as an integer

@brandon-exact
Copy link
Contributor

brandon-exact commented Jun 5, 2025

@glenn-andrews smf ci tests are failing

Yep, and on Windows the qemu_cortex_r5/zynqmp_rpu fails to build entirely so I have no idea what's going on.

Can someone run west twister -p qemu_cortex_r5/zynqmp_rpu -s sample.smf.hsm_psicc2 --no-detailed-test-id under Linux and see what the failure is?

The tests are passing for other qemu targets.

(.venv) PS C:\Users\glenn\zephyrproject_latest\zephyr\tests\lib\smf> west twister -p qemu_cortex_r5/zynqmp_rpu -s sample.smf.hsm_psicc2 --no-detailed-test-id --short-build-path
INFO    - Using Ninja..
INFO    - Zephyr version: v4.1.0-5262-g6df4056ba214
INFO    - Using 'zephyr' toolchain.
INFO    - Building initial testsuite list...
INFO    - Writing JSON report C:\Users\glenn\zephyrproject_latest\zephyr\tests\lib\smf\twister-out\testplan.json
Junction created for C:\Users\glenn\zephyrproject_latest\zephyr\tests\lib\smf\twister-out\twister_links\test_0 <<===>> C:\Users\glenn\zephyrproject_latest\zephyr\tests\lib\smf\twister-out\qemu_cortex_r5_zynqmp_rpu\zephyr\samples\subsys\smf\hsm_psicc2\sample.smf.hsm_psicc2
INFO    - Adding tasks to the queue...
INFO    - Added initial list of jobs to queue
ERROR   - General exception: 'NoneType' object cannot be interpreted as an integer
Traceback (most recent call last):
  File "C:\Users\glenn\zephyrproject_latest\zephyr\scripts\pylib\twister\twisterlib\runner.py", line 2023, in pipeline_mgr
    pb.process(pipeline, done_queue, task, lock, results)
  File "C:\Users\glenn\zephyrproject_latest\zephyr\scripts\pylib\twister\twisterlib\runner.py", line 1129, in process
    self.run()
  File "C:\Users\glenn\zephyrproject_latest\zephyr\scripts\pylib\twister\twisterlib\runner.py", line 1790, in run
    instance.handler.handle(harness)
  File "C:\Users\glenn\zephyrproject_latest\zephyr\scripts\pylib\twister\twisterlib\handlers.py", line 1427, in handle
    os.close(self.pipe_handle)
TypeError: 'NoneType' object cannot be interpreted as an integer

@glenn-andrews

(.em3) ~/fork/zephyr/tests/lib/smf/build on  smf_state_fn_return_codes *! at 11:36:26 192.168.0.14 99%
❯ west build -t run
-- west build: running target run
[1/14] Generating include/generated/zephyr/version.h
-- Zephyr version: 4.1.99 (/home/brandon/fork/zephyr), build: v4.1.0-5262-g6df4056ba214
[13/14] Linking C executable zephyr/zephyr.elf
Memory region         Used Size  Region Size  %age Used
           FLASH:          0 GB        32 MB      0.00%
             RAM:       80288 B        64 MB      0.12%
             OCM:          0 GB       256 KB      0.00%
        IDT_LIST:          0 GB        32 KB      0.00%
Generating files from /home/brandon/fork/zephyr/tests/lib/smf/build/zephyr/zephyr.elf for board: qemu_cortex_r5
[13/14] To exit from QEMU enter: 'CTRL+a, x'[QEMU] CPU: cortex-r5
qemu-system-xilinx-aarch64: warning: nic gem0@0 has no peer
qemu-system-xilinx-aarch64: warning: nic gem1@0 has no peer
qemu-system-xilinx-aarch64: warning: nic gem2@0 has no peer
qemu-system-xilinx-aarch64: warning: nic gem3@0 has no peer

*** Booting Zephyr OS build v4.1.0-5262-g6df4056ba214 ***
State Machine Framework Demo
See PSiCC2 Fig 2.11 for the statechart
https://www.state-machine.com/psicc2

[00:00:00.000,000] <inf> hh<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> hm<inf> qemu-system-xilinx-aarch64: terminating on signal 2
ninja: build stopped: interrupted by user.

^^ hangs like that

❯ git diff
diff --git a/samples/subsys/smf/hsm_psicc2/src/hsm_psicc2_thread.c b/samples/subsys/smf/hsm_psicc2/src/hsm_psicc2_thread.c
index 977d003394a..27cb150db8f 100644
--- a/samples/subsys/smf/hsm_psicc2/src/hsm_psicc2_thread.c
+++ b/samples/subsys/smf/hsm_psicc2/src/hsm_psicc2_thread.c
@@ -302,7 +302,7 @@ static const struct smf_state demo_states[] = {
                SMF_CREATE_STATE(s211_entry, s211_run, s211_exit, &demo_states[STATE_S21], NULL),
 };
 
-K_THREAD_STACK_DEFINE(hsm_psicc2_thread_stack, HSM_PSICC2_THREAD_STACK_SIZE);
+K_THREAD_STACK_DEFINE(hsm_psicc2_thread_stack, 2 * HSM_PSICC2_THREAD_STACK_SIZE);
 K_MSGQ_DEFINE(hsm_psicc2_msgq, sizeof(struct hsm_psicc2_event), HSM_PSICC2_THREAD_EVENT_QUEUE_SIZE,
              1);

^^ seems to fix it

we(.em3) ~/fork/zephyr/tests/lib/smf/build on  smf_state_fn_return_codes *! at 11:37:38 192.168.0.14 99%
❯ west build -t run
-- west build: running target run
[1/14] Generating include/generated/zephyr/version.h
-- Zephyr version: 4.1.99 (/home/brandon/fork/zephyr), build: v4.1.0-5262-g6df4056ba214
[13/14] Linking C executable zephyr/zephyr.elf
Memory region         Used Size  Region Size  %age Used
           FLASH:          0 GB        32 MB      0.00%
             RAM:       81312 B        64 MB      0.12%
             OCM:          0 GB       256 KB      0.00%
        IDT_LIST:          0 GB        32 KB      0.00%
Generating files from /home/brandon/fork/zephyr/tests/lib/smf/build/zephyr/zephyr.elf for board: qemu_cortex_r5
[13/14] To exit from QEMU enter: 'CTRL+a, x'[QEMU] CPU: cortex-r5
qemu-system-xilinx-aarch64: warning: nic gem0@0 has no peer
qemu-system-xilinx-aarch64: warning: nic gem1@0 has no peer
qemu-system-xilinx-aarch64: warning: nic gem2@0 has no peer
qemu-system-xilinx-aarch64: warning: nic gem3@0 has no peer

*** Booting Zephyr OS build v4.1.0-5262-g6df4056ba214 ***
State Machine Framework Demo
See PSiCC2 Fig 2.11 for the statechart
https://www.state-machine.com/psicc2

[00:00:00.000,000] <inf> hsm_psicc2_thread: initial_entry
[00:00:00.000,000] <inf> hsm_psicc2_thread: s_entry
[00:00:00.000,000] <inf> hsm_psicc2_thread: s2_entry
[00:00:00.000,000] <inf> hsm_psicc2_thread: s21_entry
[00:00:00.010,000] <inf> hsm_psicc2_thread: s211_entry
uart:~$ 

@glenn-andrews glenn-andrews force-pushed the smf_state_fn_return_codes branch from 6df4056 to 75419f1 Compare June 5, 2025 15:46
@glenn-andrews
Copy link
Collaborator Author

@brandon-exact Thank you so much!

@glenn-andrews
Copy link
Collaborator Author

@glenn-andrews smf ci tests are failing

@maass-hamburg CI should be passing now, thanks to @brandon-exact

maass-hamburg
maass-hamburg previously approved these changes Jun 5, 2025
@glenn-andrews glenn-andrews requested a review from carlescufi June 7, 2025 22:33
@henrikbrixandersen
Copy link
Member

@sambhurst, @keith-zephyr: Please take another look.

@keith-zephyr
Copy link
Collaborator

@sambhurst, @keith-zephyr: Please take another look.

I'm reviewing now. I have also pulled in this change locally to test with our downstream repo as we have a few uses of SMF in our application.

See Discussion zephyrproject-rtos#83659
for information about the purpose of this change.

Modifies run actions of hierarchical state machines
to return a value indicating if the event was handled
by the run action or should be propagated up to the
parent run action. Flat state machines are not affected,
and their run action returns void.

smf_set_handled() has been removed and replaced by
this return value. smf_set_state() will not propagate
events regardless of the return value as the transition
is considered to have occurred.

Documentation, tests, samples, has been updated.
USB-C and hawkBit use SMF and have been updated to use
the new return codes.

Signed-off-by: Glenn Andrews <[email protected]>
@glenn-andrews glenn-andrews force-pushed the smf_state_fn_return_codes branch from 75419f1 to ef41c25 Compare June 16, 2025 17:05
Copy link

@henrikbrixandersen henrikbrixandersen merged commit 94084e5 into zephyrproject-rtos:main Jun 17, 2025
26 checks passed
@github-project-automation github-project-automation bot moved this from In Progress to Done in Architecture Review Jun 17, 2025
@glenn-andrews
Copy link
Collaborator Author

Thank you everyone for making this happen!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: hawkBit area: Samples Samples area: State Machine Framework State Machine Framework area: USB Universal Serial Bus area: USB-C Release Notes To be mentioned in the release notes
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

10 participants