Home > Meetings >

Live Q&A - Modern Embedded Programming with Hierarchical State Machines and Active Objects

Miro Samek - Watch Now - Duration: 19:42

M↓ MARKDOWN HELP
italicssurround text with
*asterisks*
boldsurround text with
**two asterisks**
hyperlink
[hyperlink](https://example.com)
or just a bare URL
code
surround text with
`backticks`
strikethroughsurround text with
~~two tilde characters~~
quote
prefix with
>

MiroSpeaker
Score: 0 | 6 months ago | no reply

From Steve Wheeler : Do the QP frameworks generate timing/event diagrams such as the one you showed?

QP contains software tracing facility called QP/Spy. This can output all sorts of data about the system execution, because an active object framework like QP knows so much more about the application. For example, QP framework knows about state machine execution: transitions, state entry/exit, etc. This is much more than software tracing of an RTOS kernel.

So, from this tracing data, the QSPY host application can generate all sorts of outputs, including sequence diagrams. You can also generate output for MATLAB, to analyze your traces in very sophisticated ways.

MiroSpeaker
Score: 0 | 6 months ago | no reply

From Davy Baker : What is the minimum size of flash and ram you have seen work worth Active Objects ?

The code size (ROM) of QP RTEF can be about the same as bare-bones RTOS kernel (around 4KB on ARM Cortex-M). This is assuming that QP uses one of the built-in kernels (cooperative QV kernel, preemptive, non-blocking QK kernel, or the dual-mode QXK kernel).

But when it comes to RAM consumption, QP requires less RAM than any traditional RTOS, because the built-in QV and QK kernels use only single stack for all AOs and interrupts. For example, it makes sense to use QP with as little as 1KB or RAM total.

MiroSpeaker
Score: 0 | 6 months ago | no reply

From patelk5 : Are there any concurrency issues to be cognizant of even if Active Objects are used?

The traditional concurrency issues are all related to sharing of resources, so if you don't share anything you should not experience any of them.

The tradeoff with Active Objects is that you now use event passing. The good news is that event passing is handled by the framework (like QP) in a thread-safe manner. But still, there are limitations as to what you can and cannot do with these events. For example, you are not allowed to write to any received event. You are also not allowed to keep using an event after the RTC step. And there are some other restrictions.

Also, additional tradeoff is that queuing of events can sometimes lead to unexpected events being present in your queue, or events might get queued in unexpected order. For example, you might unsubscribe from an event and so you might not expect this event anymore. But the event might be already in your event queue, so it arrives seemingly after you've unsubscribed. Also, due to preemption some AOs might run and post events ahead of other AOs. So this can lead to re-ordering of events.

But all these issues are generally easier to deal with than the classic race conditions or data corruption. The main reason being that classic concurrency hazards do the damage before you can know about it. Here no damage is done until you process the event, so you can design your state machines to deal with the issues.

MiroSpeaker
Score: 0 | 6 months ago | no reply

From Radu Pralea : This approach (Active Objects, State Machines) seems a very elegant way of expressing the problem in a more optimal and robust way compared to a threading approach (eliminating sharing and (some) timing problems and overheads).
However,:

  • it seems (at least at a first glance) a less natural way of thinking about the problem domain (more indirect, i.e. designing the sequence diagram with its constraints (no sharing), compared to a closer to the problem domain modeling approach)

Whether or not a method seems "natural" depends entirely on familiarity. To people familiar with event-driven Active Objects it's exactly the other way around. The traditional "shared-state concurrency and blocking" seem completely unnatural and backwards. For example, Active Objects are closer to the problem domain than blocking threads and mutual exclusion. I was exactly hoping to convey this in my presentation, where the "Tunnel", "Ship" and "Missile" active objects modeled directly the behavior of their real-life counterparts.

  • it seems that the sequence diagram doesn't scale very well (I expect it to become less manageable with increasing size/number of concepts, compared to the task oriented design)

Sure, a single sequence diagram can hold only so much information. But who said that you can have only one sequence diagram? In fact, in any non-trivial project you will have many sequence diagrams, typically associated with use cases. Use-cases are in themselves a very useful concept, and I highly recommend to read about them.

Regarding "task oriented design", perhaps you could point me to some resources describing what that is. Do you mean flowcharts describing the sequential code? I know that Jean Labrosse introduced some quite expressive diagrams in his RTOS books, where he depicted semaphores, queues, mutexes, etc. But these are by no means standard, universally understood types of diagrams. In contrast: sequence diagrams and state diagrams (UML statechars) are standardized and have universally understood meaning.

  • it seems that it's a less agile way of partitioning the problem: it would work fine for a reasonably sized problem that's very well defined beforehand, but it would require very inconvenient redesigns as the requirements keep coming and/or changing

It is exactly the other way around! Event-driven components are much more extensible than traditional blocking threads, because you can add new events and new event sequences very easily. In contrast, traditional sequential RTOS threads block to wait for events, so adding new events is hard because the system is unresponsive to them. This means that you have to keep adding new threads, just to handle new events. I showed this in my last year's presentation, where I merged two threads into one active object, exactly because the AO was extensible.

I also blogged about it in my post "RTOS, TDD and the “O” in the S-O-L-I-D rules"

MiroSpeaker
Score: 0 | 6 months ago | no reply

From afwaanquadri : How do you suggest an AO to handle a blocking call? such as a HTTP request.

AO should not block internally, period. So if you have an inherently blocking API, you need to use a regular blocking thread to handle that. Please note that event-driven AOs and traditional blocking threads can be used in the same system and they can cooperate. But what you should never do is to mix event-driven and sequential programming styles within a single thread.

Having said that, HTTP can be handled in a pure event-driven fashion without any blocking. There is an App Note "QP™ and lwIP TCP/IP Stack", which shows an HTTP server running inside a non-blocking AO. There is also a companion video showing how this works.

MiroSpeaker
Score: 0 | 6 months ago | no reply

From Alex Burka : Why not use C++?

This presentation used QP/C RTEF and C as the primary language, because 70+% of embedded software is written in C, and it is typically not quite clear to C programmers how to use object-oriented design patterns like "Active Objects".

But QP/C++ RTEF is also available, where it is very clear how to implement object-orientation.

MiroSpeaker
Score: 0 | 6 months ago | no reply

From patelk5 : Is there any advantage of using a sequential code flow (like RTOS or foreground/background) over event-driven code flow (RTEF)? It seems like event-driven is superior in almost every scenario?

Sequential solution is good if the problem is sequential as well. By this I mean that the system needs to handle only a very limited number of event sequences. In that case hard-coding them in sequential code is the simplest.

Trouble is that most real life problems are NOT sequential and the system must handle many event sequences. But typically you don't know it, until you start building your system. This is very insidious, because initially every problem looks sequential, so you start that way. But inevitably you discover some other legitimate event sequences that need to be handled as well, so your sequential code degenerates...

So, yes, I agree that most of the time it is better to assume event-driven architecture that is exactly prepared to handle multiple event sequences.

MiroSpeaker
Score: 0 | 6 months ago | no reply

From Tim Michals : Is there a Linux version of all the tools and examples?

Yes, Linux is supported as both the target to run QP and as development host.

As target, two QP ports to Linux (POSIX) are available in the <qpc|qpcpp>/ports/posix and <qpc|qpcpp>/ports/posix-qv directories. There is an AppNote "QP and POSIX" that describes how QP can work with P-threads and within just one thread. Examples are provided in the <qpc|qpcpp>/examples/workstation directory. There are also videos showing how to run QP on Raspberry Pi (embedded Linux).

Linux as development host is supported as well. Specifically there is a Linux version of the QM modeling tool and other tools (e.g., QSPY) also run on Linux.

KushP
Score: 1 | 7 months ago | 1 reply

Are there any concurrency issues to be cognizant of even if Active Objects are used? I presume race conditions could still happen depending on order events are received.

MiroSpeaker
Score: 0 | 7 months ago | 1 reply

If you really avoid sharing of anything (except events) among active objects, then the classic race conditions and data corruption should NOT happen. They are replaced with "event-races" (due to active object threads preempting each other), which can lead to "unexpected" reordering of events . But event ordering issues are much more tractable than race conditions and corruption, where the damage is already done. In contrast, with re-ordered events no damage is done yet. But yes, you need to design your state machines to handle such unobvious event sequences. With some experience you will develop a sense when such "event races" can happen and when you need to prepare your state machines to handle them. I provide some examples of this in my PSiCC2 book (the section about Time Events).

KushP
Score: 0 | 6 months ago | no reply

Thank you Dr. Samek. I will have to complete your book.

KushP
Score: 0 | 7 months ago | no reply
This post has been deleted by the author
15:41:54	 From  Tim Michals : Is there a Linux version of all the tools and examples?
15:42:11	 From  Dave Nadler : Thanks Miro for a great talk. Youu mentioned puub/sub, but the example shows sending events to specific objects? Can you explain?
15:42:12	 From  patelk5 : Is there any advantage of using a sequential code flow (like RTOS or foreground/background) over event-driven code flow (RTEF)? It seems like event-driven is superior in almost every scenario?
15:42:13	 From  Alex Burka : Why not use C++?
15:42:20	 From  patelk5 : Thanks Miro!
15:42:35	 From  afwaanquadri : How do you suggest an AO to handle a blocking call? such as a HTTP request.
15:42:41	 From  Rocco Brandi : I have read Miro's book several years ago. the info were amazing, but are still valid today? are they a little out of date?
15:42:49	 From  Radu Pralea : This approach (Active Objects, State Machines) seems a very elegant way of expressing the problem in a more optimal and robust way compared to a threading approach (eliminating sharing and (some) timing problems and overheads).
However,:
- it seems (at least at a first glance) a less natural way of thinking about the problem domain (more indirect, i.e. designing the sequence diagram with its constraints (no sharing), compared to a closer to the problem domain modeling approach)
- it seems that the sequence diagram doesn't scale very well (I expect it to become less manageable with increasing size/number of concepts, compared to the task oriented design)
- it seems that it's a less agile way of partitioning the problem: it would work fine for a reasonably sized problem that's very well defined beforehand, but it would require very inconvenient redesigns as the requirements keep coming and/or changing
Could you please address (some of) these concerns, please?
15:43:06	 From  jvillasante : How expensive a new requirement (like we want the ship to be able to fire several missiles) would be to add to the current design?
15:43:10	 From  Roman Hvozd : Hi Miro.
Can QSPY traces be turned off, but ability to send (post/publish) commands (signal) to the aplication and trace used data still be available?
15:43:13	 From  Burak ŞEKER : Why not use C++? (I have same question with Alex)
15:43:40	 From  Charles Miller : Hello Miro.  Your first ed. of the book was in C++; the UML version went to C.  Was there pressure to move to the lesser language? (IMHO :-) )
15:44:24	 From  Davy Baker : is it feasible to interact with other visual code generation environments like say labview ?
15:51:35	 From  patelk5 : Are there any concurrency issues to be cognizant of even if Active Objects are used?
15:52:00	 From  Davy Baker : What is the minimum size of flash and ram you have seen work worth Active Objects ?
15:52:30	 From  afwaanquadri : How do you suggest an AO to handle a blocking call? such as a HTTP request.
15:53:24	 From  Gopinath : Great presentation, Dr. Samek. Can Active Objects and Hierarchical State Machines be implemented on bare metal systems? Or do they require RTOS?
15:54:30	 From  patelk5 : @Gopinath: I think the answer is yes. https://www.state-machine.com/qpc/ports_native.html
15:54:46	 From  patelk5 : I did it last weekend on a TI board :)
15:54:53	 From  Burak ŞEKER : To Gopinath: It is possible to use Active Object and Pub/Sub approach in bare metal just fine.
15:55:06	 From  Sam : Are there good SDD's out there that are available for download?
15:56:16	 From  Dave Nadler : Socially Distant Disease?
15:56:29	 From  Sam : software design document
15:57:28	 From  Keith J : What about GUI code generation tools like QT?
15:57:34	 From  Steve Wheeler : Do the QP frameworks generate timing/event diagrams such as the one you showed?
15:57:36	 From  Keith J : interactions
15:57:47	 From  javi : How are events sent and received? using queues.. mailboxes..
15:59:21	 From  Bob Dowling : To Patelk5: which TI board?
15:59:35	 From  patelk5 : TM4C123GXL
16:00:02	 From  Bob Dowling : Thanks! (We use C2000)
16:00:06	 From  patelk5 : If you download qpc, there are bunch of examples in the examples folder for many different boards
16:00:17	 From  Tim Michals : Some of the Q&A sessions need more time ;)
16:00:31	 From  patelk5 : I couldn't agree more :(
16:00:39	 From  Yuriy Kozhynov : Thanks!
16:00:40	 From  David : Thanks Miro!
16:00:41	 From  NateWelch : Thank you Miro
16:00:45	 From  patelk5 : Thank you!
16:00:45	 From  Christopher Long : Thank you Miro for the excellent presentation and Q&A! I am big fan of your YouTube content.
16:00:45	 From  Burak ŞEKER : Thanks a lot
16:00:51	 From  Raul Pando : Great work Miro
16:00:58	 From  javi : thanks!
16:01:03	 From  Gopinath : Thanks to Dr. Samek.

OUR SPONSORS