Use an explicit and declarative state machine in firmware - Page 1
Forum section: electronics / general

author: YTusername
author_rank: Regular Contributor
timestamp: March 11, 2024, 06:54:39 am
content: Hi,I've participated in discussions in this forum regarding firmware architecture, such asthis oneanthis one. Additionally, recently, I watched an interesting talk by C++ developer Kris Jusiak at Cpp Now 2019 titled "Rise of the State Machines."In his presentation, he introduced a library calledSML. All of this has encouraged me to create a two-part series promoting the adoption of a declarative and efficient state machine in our firmware designs. I published the first part yesterday.Please review it and share your thoughts on the SML library. For those who enjoy written content, please check out theassociated article.

author: Doctorandus_P
author_rank: Super Contributor
timestamp: March 11, 2024, 09:02:09 am
content: A method I like is to give each state it's own separate function, and then use a function pointer to remember the current state. Each of those function states can then modify this function pointer to set it to the next state. Especially in C++ this can be nicely encapsulated in a class. The class can also hold context information, and you can declare multiple instances of the class to run multiple state machines concurrently.I don't know if this method is mentiond in that video, but I don't have an hour and a half of patience for that.

author: YTusername
author_rank: Regular Contributor
timestamp: March 11, 2024, 10:14:54 am
content: Quote from: Doctorandus_P on March 11, 2024, 09:02:09 amI think the closest implementation is in the `inheritance/state pattern` method (here). It is not identical to your way, but each state has a class and all inherit a main class that has a `make_unique` pointer shared between all.

author: Doctorandus_P
author_rank: Super Contributor
timestamp: March 11, 2024, 12:51:47 pm
content: It's sort of like that, but I get lost in the details over there. I learned C a long time ago, and for me C++ is still a superset of C. I also do not do enough programming to be fluent in C++, and there are other... complications too.I once used a function pointer in C for a statemachine, and that worked reasonably well. The state machine was in it's own file, and the states declared as static functions, so they were not visible outside the file. Later, when I got interested in C++ I revised that and turned it into a single class.A problem with the programmatic approach is the lack of overview. I like the graphical view with round bubbles for the states and arrows (with conditions) for state changes. Such a diagram gives a quick overview of a whole statemachine. I once drew it in autocad (it was a long time ago) but that has the disadvantage that it complicates maintenance during revisions. The code and the picture easily get out of sync. I know there is generator software in which you can draw a state diagram and then it can compile it into code but I never used it. Such software probably has issues too...

author: JPortici
author_rank: Super Contributor
timestamp: March 11, 2024, 02:11:15 pm
content: Quote from: Doctorandus_P on March 11, 2024, 12:51:47 pmthat would be UML!or at least i find it much easier and faster to change one line in UML, whereas the graphic's guy and a contractor insist in using Miro. sigh. Though it supposedly now supports UML for generating charts and other it is not used

author: YTusername
author_rank: Regular Contributor
timestamp: March 11, 2024, 02:32:37 pm
content: You can check thePlantUML and SMLsection in my article. That is exactly what you are talking about, a scripting language for UML generation. The creator of SML library included a code in one of his workshops that converts the transition table expressed in SML library to PlantUML script.

author: tellurium
author_rank: Frequent Contributor
timestamp: March 12, 2024, 06:53:57 am
content: To me, C++ and simplicity are antagonists.Found that that SML library, saw tons of "template class ...", closed it. Unlikely to open it again.IMO, a C code which declares states explicitly and uses a simple switch/case or if/else, makes FSM easy to write and maintain.If the code becomes big - well, factor out big parts, and keep the FSM core small.Example: a single-pass JSON parser that uses no heap, implemented as an FSM with clearly defined states:https://github.com/cesanta/mongoose/blob/9f498d2eea27737bea2f8bce47107d328e881ad0/src/json.c#L129The whole function is less than 100 LoC, so it was not even broken down into a smaller functions - no need to.Every state has a clear transition points. For example, a ":" character transits the state to expect a JSON value:https://github.com/cesanta/mongoose/blob/9f498d2eea27737bea2f8bce47107d328e881ad0/src/json.c#L240-L242That's it. The only thing that I'd like to have here, is to visualise the FSM - and probably it can be done with a tool that parses the FSM code and spits out a graph.The SML approach described in the "SML Library: Simplified Overview" chapter of your article does not resonate as "simple" to me at all.

author: YTusername
author_rank: Regular Contributor
timestamp: March 12, 2024, 09:37:48 am
content: Quote from: tellurium on March 12, 2024, 06:53:57 amFor many firmware developers, that's true, but I would say it's mostly because we're not accustomed to the C++ style. This is an industry-wide phenomenon. I agree that, at some points understanding a complex C++ code can be very hard. It is very rare to have difficulties understanding C code. I can not judge as my main background is C. on the other hand, We cannot overlook the success of many C++ firmware projects like Mbed-OS, which is implemented entirely in C++. The debate about C vs. C++ will never end, I know. I still consider myself a C firmware developer rather than C++. But after attending several talks from Cpp Now event, I'm considering the C++.Quote from: tellurium on March 12, 2024, 06:53:57 amIndeed, it can be daunting, I cannot argue with that. However, I don't believe there is another way to create a similar library without using such intertwined template classes. I mean, if the library developers know what they're doing, performance is validated, and, most importantly, debugging is supported, then having complexity in its implementation isn't necessarily a bad thing. After all, we already place trust in many libraries and dependencies.Quote from: tellurium on March 12, 2024, 06:53:57 amNice example. Of course, SML is not a one-size-fits-all solution.Quote from: tellurium on March 12, 2024, 06:53:57 amThe cool thing about the SML library is that you have a clear transition table in one place, which you can later dump using code to convert it into a graph (mentioned the dumping code in the article).Quote from: tellurium on March 12, 2024, 06:53:57 amThanks for the feedback.