I love this channel. Thank you, Miro Samek, for providing all of these lectures for free, and also for the QP framework. You have been a kind of mentor to me, and I have learned a lot of things from you. Currently, I am developing my embedded system project as part of my thesis. It is related to DSP, more precisely, a digital paragraphic equalizer implemented on a DSC ARM Cortex M7 with a DPI interface display and capacitive touch panel. The entire project is developed in C language, and I am using your framework. Thank you so much, and you will definitely be part of my thesis acknowledgments. regards. Javier Leyva.
@StateMachineCOM Жыл бұрын
Thank you, Javier! I'm glad my videos and the QP framework have helped you. I hope that you'll get even more mileage out of your deeper understanding of embedded programming in your future career. Best of luck! ---MMS
@psykjavier Жыл бұрын
@@StateMachineCOM by the way, I don't have any intentions of bothering you. I would like to know the best way to describe embedded systems in terms of their functionality, considering both hardware and software aspects. I'm aware of the existence of OSEK, AUTOSAR, UML, and the IEEE std 830-1998, but I'm curious to hear your response. I apologize for this question, but I'm genuinely intrigued by your perspective. regards.
@StateMachineCOM Жыл бұрын
@@psykjavier Any method to "describe embedded system functionality" comes with costs and benefits. But to be genuinely useful in the long run, the benefits of a method must outweigh its costs. It turns out that the costs of OSEK/AUTOSAR and UML are pretty high, and the benefits are low unless the method gives you production-quality code. That's exactly why the free QM modeling tool and the open-source QP frameworks have been invented. They provide many (not all) benefits, including code generation, for a tiny fraction of the cost. --MMS
@psykjavier Жыл бұрын
@@StateMachineCOM ok, i get it. Thank you again i appreciate your time and knowledge in this academic or let me say mentoring way. Best regards.
@technics62152 жыл бұрын
What a great course for free... Thank you guys!
@paulchui37394 жыл бұрын
Thank you very much for your amazing lectures
@GabrielofDalle2 жыл бұрын
Hi Miro and fellow embedded programmers, Since I watched this video almost a year ago, I've utilized the FreeAct+FreeRTOS in different projects with very good results. One thing still bothers me that is serial drivers (I2C, SPI). As asked and replied by Miro here, using interrupts is really ideal in this situation. The callback function can generate an event signal, so the Active Object can process it, out of the ISR. It works. My issue is when i have multiple components sharing the same bus (I2C or SPI). If the Active Object knows exatcly when the comunication should happen, it is ok, but the issue starts when the events overlap, i.e user input requesting data of multiple sensors that share the same I2C bus. The AO can request data of the 1st sensor in interrupt mode and be free to do other stuff, but if a request to the 2nd sensor comes when the I2C is still busy with the 1st one, it is bad. How is the ideal solution here? A new AO that manage just the serial interface in pulling mode works, but then it is no different than the sequential thinking of Tasks in FreeRTOS. Putting in interrupt mode create the same issue again. My solution until now is to create a (very primitive one) queue as part of the AO. The queue dispatches the next one in line after the interrupt callback of the 1st request, managing the overlap. Another solution, when the application allows it, it is just to ignore the following requests... I could not think of a better architecture beyond the queue system inside the AO (like an AO inside an AO...). I would love to hear different designs and solutions. Thanks
@StateMachineCOM2 жыл бұрын
Hi Gabriel: I'm glad to hear that you actually tried out some of the presented ideas. You came to the right place because the answers to all your questions are provided in the video presentation from this year: kzbin.info/www/bejne/npDYamWrgdimetE . Specifically, when you watch that video, you'll see that the main principle is to *avoid* any sharing of resources among the Active Objects ("share nothing principle). For example, you can encapsulate I2C in one AO (let's call it I2C_Manager), and SPI in another AO (say, SPI_Broker). The point is that only the resource Manager (or Broker) can access a given resource directly. Other AOs in the system must *post* events to the Manager AO (or the Manger can post events received by the comms channel). That way, the Manager can resolve any conflicts. Please note that events can carry data, such as whole data packets to be sent over I2C. Finally, please note that FreeACT (github.com/QuantumLeaps/FreeAct ) is only a teaching aid and currently it does not support events with parameters or state machines. A professional framework that does support all these features and much more is called QP/C and is also available from GitHub: github.com/QuantumLeaps/qpc . --MMS
@GabrielofDalle2 жыл бұрын
@@StateMachineCOM Hello, thanks for the great answer. The video clarifies some doubts that I had, like if it was good practice to have an Object inside the AO how to do it. The Game Example with the "Mines" as part of the "Tunnel" AO explains this concept. As FreeAct is not a complete framework, I was struggling when faced to more complex systems. I will definetly give it a go on the QP/C in a next private project where licesing is not an issue. For my work, as the company uses FreeRtos, I am stuck with it.
@pabloabraham72844 жыл бұрын
Great work! Congrats.
@xbreyy257 ай бұрын
I really like the idea of event driven, I completely understand the idea of immutable events in flash memory as consts. But what about mutable events (like your ethernet example).In this scenario I don't understand who is respobsible of saving all payloads queue( framework or application) as blinkyButtonqueue is only array of pointers to structs. can anybody show me some code where events are mutable? Perhaps in this case blinkyButtonqueue should not be an array of a pointers, but be a variable in global ram
@StateMachineCOM7 ай бұрын
Yes, I realize that the management of mutable events with parameters hasn't been explained in this presentation. And yes, you are right that this is very important and indeed, the most valuable feature of the QP framework. You can find more information about it here: www.state-machine.com/qpc/srs-qp_emm.html and www.state-machine.com/qpc/sas-qp_emm.html
@xbreyy257 ай бұрын
@@StateMachineCOM It would be great to see a video or have github repo where freeact and qp framework would be in the same project example. (or freeact lib could be extended) I see in your other video that for mutable object you control led blink frequency creating event parameters with q_new function.
@StateMachineCOM7 ай бұрын
At this point, FreeACT is a "minimal active object framework" that demonstrates the main principles of implementing the event-driven paradigm with a traditional RTOS. The FreeACT project ( github.com/QuantumLeaps/FreeACT ) could become more complete (e.g., by providing true management of mutable events), but this requires work. The project is licensed under the permissive MIT license (the same as the FreeRTOS kernel), but so far there have been no community contributions. In contrast, QP/C framework ( github.com/QuantumLeaps/qpc ) is a mature and full-featured active object framework that can work with many RTOS kernels (among others with FreeRTOS). QP is dually-licensed under the restrictive GPL license and commercial licenses. This different licensing model prevents combining QP and FreeACT in the same repository. --MMS
@xbreyy257 ай бұрын
@@StateMachineCOM I will definitely check complete framework, thx
@ayushkothari49404 жыл бұрын
Hi sir, these are very helpful videos. It will be great if you could make a video where you are using event driven programming for communicating with I2c chips and Spi chips simultaneously.I'm asking you this because I don't know how should I use event driven programming for I2c and Spi. Thanks in advance.
@ariansuarez15714 жыл бұрын
First I want to say thank you for sharing this is a great video. Second I have a question on the proper way to query the state of an active object. In my applications, I am a fan of building command-line gui's that show the state of each thread. With active objects is this possible without blocking on some shared variables since the whole point of the pattern is to share as little as possible?
@StateMachineCOM4 жыл бұрын
The state of an active object is obviously changing asynchronously to any of your queries. Therefore, it typically is not very reliable to query such information. Instead, in the QP frameworks the framework itself can report changes in the state of any state machine via the QP/Spy software tracing mechanism (please see www.state-machine.com/qtools/qpspy.html ). So, if you like command-line utilities, the QP/Spy system comes with the QSPY host utility, as well as extensions, such as QView (for Visualization and Monitoring) and QUTest for unit testing. --MMS
@BDYH-ey8kd4 жыл бұрын
What about super loop and multi state-machines (no rtos), or is this in part 4?
@StateMachineCOM4 жыл бұрын
Part 4 will first of all explain what an event-driven state machine is and then you'll see how a state machine could control the behavior of each active object. That way, you'll have multi state machines in the system, because you can have multiple AOs in the system. But you probably mean state machines embedded directly within the superloop architecture without any RTOS. These are, most likely, state machines of a different kind (called "input-driven" state machines or "polled" state machines). They are not event-driven in the sense that they run "all the time", not just when an event is available. Such "polled" state machines run thousands of times per second, constantly *looking for events* by checking conditions. In the diagrams, you can easily distinguish such input-driven state machines, because instead of event signals, they have only (guard) conditions listed on the transitions (e.g., temp > 100 && overheat_button == DEPRESSED). I plan to explain all types of state machines in the upcoming new segment in the "Modern Embedded Programming" course (kzbin.info/aero/PLPW8O6W-1chwyTzI3BHwBLbGQoPFxPAPM ). The first lesson in the "State Machines" segment is coming out pretty soon. Stay tuned! --MMS
@BDYH-ey8kd4 жыл бұрын
@@StateMachineCOM i really like this polling method tho, it can be modular with every module having a 'handler'. Feel like i have total control and that i can fake parallelism by blocking handlers on critical moment like a semaphore would.. I have a library which does message queues and rtos (i think its exactly what you mention in this video), but i never tried to master it yet.. Also rtos has idle tasks which is still a cpu afterall..
@mrk3ma14 жыл бұрын
Correct me if I am wrong but I think the problem with Purely event-driven system is the RTC aspect. What if I have a process that needs to be done every 100us and it takes 10us to be completed. Another process which takes 1ms to complete and triggers whenever I press a button. So when I press the button microcontroller is going to process the data for 1ms while the 100us periodic task waits (and fail to meet the real-time requirement). I feel like purely event-driven system can fail at "hard" real-time requirements since it does not have any priority based mechanism.
@StateMachineCOM4 жыл бұрын
It is very important to clearly distinguish the notion of RTC from the concept of thread preemption. In particular, RTC does *NOT* mean that the event-handler thread has to monopolize the CPU until the RTC step is complete. Under a preemptive multitasking kernel, an RTC step can be preempted by another thread executing on the same CPU. This is determined by the scheduling policy of the underlying multitasking kernel, not by the event-loop. When the suspended thread is assigned CPU time again, it resumes its event processing from the point of preemption and, eventually, completes its event processing. As long as the preempting and the preempted threads don’t share any resources, there are no concurrency hazards. So, translating this into your specific example: if your long 1ms RTC runs in a thread of lower priority, your fast 100us thread can preempt it ten times, no problem. Such preemptions will *not* violate the RTC semantics of the 1ms RTC step. It will eventually complete and only then it will start with the next event. In fact, the FreeAO framework running on top of FreeRTOS will exhibit this behavior. (Why don't you try it!) By the way, the event-driven, *non-blocking* way of processing events combined with preemptive, priority-based kernel *is* fully compatible with RMA/RMS (Rate-Monotonic Analysis/Scheduling). In fact, the lack of blocking makes it much easier to apply RMA/RMS than in a traditional RTOS with willy-nilly blocking threads.
@markotikvic4 жыл бұрын
Hve you, by any chance, planned to do a video about how serial drivers (UART, SPI, I2C) are meant to be implemented (or integrated) with the active object design? Since these drivers are usually ISR-heavy and often don't play well with time critical parts of firmware/software. Do you leave the transmitters blocking, do you sacrifice data rate and make them non-blocking? I guess it would be application specific (as always), but what are some of the "guidelines" when using active object design? Thank you for this fantastic video series. From the quality of information all the way to the organized presentation, it's golden.
@StateMachineCOM4 жыл бұрын
Actually, event-driven device drivers are more natural than blocking ones. The job of ISRs is really to produce *events* to the rest of the system. And also, there is really no data rate to "sacrifice" by making a device driver non-blocking. Just think about, why would it be? If anything, a blocking device driver could be less efficient due to more complex and expensive context switching. I hope this makes sense... --MMS
@10e9994 жыл бұрын
Hi Mr. Samek. Firstly, thanks for your videos. They are brilliant. I'm still having trouble with how to structure code for bigger projects. For example, let say I have a system that needs to periodically get data from a GNSS (like GPS). In the non-modern way of programming, I would have 2 tasks: - Task 1 will manage the GNSS chip and will update an internal structure with the most up-to-date geolocalization data - Task 2: Will get the data from task 1 with a mutex and consumes it. How would you avoid this data sharing in an event-driven way? Regards
@StateMachineCOM4 жыл бұрын
You replace sharing with sending events with *parameters* . In your case, you still can have two active objects: GNSS-Manager and the other guy. But this time, the GNSS-Manager simply sends the periodic GNSS_UPDATE event with the position/time encoded as the event *parameters* . The nice thing about it is that the AO framework now takes care of passing the event in a *thread-safe* manner from the producer to the consumer. The event passing can be deterministic and you don't need to worry about adding a mutex (or mutexes) in all the right places or about the additional blocking on those mutexes and potentially screwing your timing... In fact, you don't need to know what a mutex is... BTW, the simplistic "FreeAO" does not implement passing mutable events with parameters. This is one of the most tricky and valuable part of an AO framework. The QP frameworks from Quantum Leaps implement this feature (see www.state-machine.com/products/#QP ). --MMS
@10e9994 жыл бұрын
@@StateMachineCOM Thanks for your great answer.
@Picpizza3 жыл бұрын
Regarding the Event structure: Because a uint16_t is used as the Signal, wouldn't that produce an unaligned data structure for a 32bit machine? Is there any performance to be gained using a uint32_t instead? Thanks for the lecture!
@StateMachineCOM3 жыл бұрын
The compiler will take care of any potential misalignments, so you don't need to worry about such things. A 16-bit signal space (uint16_t) gives you 64K of different signals, which is more than adequate for most applications. Smaller events can potentially save precious RAM, because you typically need a number of them. Finally, in the more advanced framework, events contain more than just the signal. They also carry the "bookkeeping" information, such as reference counter and pool-ID. All this can then be conveniently packed into 32-bits, but only if the signal is just 16-bits. --MMS
@abdelrahmanbakr34974 жыл бұрын
very helpful tutorial
@vidaljuanp3 жыл бұрын
Do you have an example where you pass events with data buffers? e.g Send an event that contains a text message to an Active Object
@StateMachineCOM3 жыл бұрын
The little "FreeACT" framework does not show passing events with parameters. To do so in a thread-safe manner, you would need to allocate an event from a deterministic fixed-size pool. Then you can post the event (pointer) to an event queue. After receiving the event and processing it, the recipient will have to explicitly recycle the event back to the pool. If the event is not recycled, it will "leak". But it is also possible to automate the process and make the framework do the recycling automatically. This is done in the professional-grade QP framework from Quantum Leaps (see state-machine.com). --MMS
@vidaljuanp3 жыл бұрын
@@StateMachineCOM Is there any example in the framework that implements passing events with parameters ?
@StateMachineCOM3 жыл бұрын
@@vidaljuanp The simplistic "FreeAct" framework does not support event with parameters. You could emulate it by: (1) allocating a block of memory for the event, (2) filling it up with event parameters, (3) posting it to the queue and (4) freeing the buffer after the event is used. This is obviously complex and is vulnerable to mistakes (e.g., forgetting to free the buffer or freeing it prematurely). The professional QP/C and QP/C++ frameworks automate this process and provide thread-safe management for dynamic events with parameters. Among others, the QP/C/C++ frameworks have been ported to the FreeRTOS kernel, if you are married to this RTOS. The [QP/C/C++ frameworks](www.state-machine.com/products/qp/) come with plenty of examples of passing events with parameters. --MMS
@bm8308104 жыл бұрын
It might be a good idea if you git commit your changes at different stages of the tutorial, this way we would have the starting code, end code and between steps as well
@StateMachineCOM4 жыл бұрын
Yes, this is indeed a good idea. I'll keep it in mind for my future videos, especially that all projects for the "Modern Embedded Programming" video course have been recently posted on GitHub at: github.com/QuantumLeaps/modern-embedded-programming-course
@abder54534 жыл бұрын
I still can't understand why you are considering the while loop inside the thread as "sequential/blocking programming", when it's really not ! Excuse me if I'm wrong, but here is what I think : We are using a RTOS, with the basic idea of threads running concurrently (by a scheduler) on a CPU. If I take your Blinky example : for my understanding, the delay function is NOT blocking. When the thread waits for the specified time, the scheduler will immediately preempt it and put it in a WAIT state, so a READY state can take the CPU (if there is any) and resume after the delay ends (or preempt it completely if a high priority thread wants the CPU). Can you please explain to me what do you mean by : the Blinky thread is unresponsive to new events (23:26). About the event driven programming, is there any comparison vis-a-vis the traditional/"sequential" programming, namely for memory footprint, CPU usage & Hard RT delivery. As, the AO methodology will add additional burden to the CPU (more variables for the context, more if's and more memory queues basically) especially for a hybrid implementation. Not to forget thanking you for sharing this great content, as always 👍🎩
@DisciplinedMusings19844 жыл бұрын
Regarding the unresponsive thread question, the CPU can do other work, but while this exact thread waits between blinks, no other 'system' event can interrupt this thread. What if the requirements were 'the LED blinks, but a button press toggles the blinking on and off' (like illustrated [here](raw.githubusercontent.com/mryndzionek/esm/master/apps/blink/umlet/blink.png )? In threaded implementation it would be possible to 'react' to button presses only after delay/sleep finishes, so worst case reaction time would be the blinking period. Let's say the LED toggles every 5 seconds. If the button press occurs just after LED changes state, the reaction to the button will happen in ~5 seconds!!!! Event driven design avoids this problem. Also even for this simple example the threaded design will require code duplication (reacting to button after each sleep/delay and there are 2: loop(led_on;sleep;led_off;sleep)). Regarding memory footprint in my experience event-driven design trades memory needed for stack(s), for memory needed for queues. The explicit state that needs to be stored is almost always negligible. Ordinary sequential/blocking encourages a programming style with deeply nested function calls and then when blocking occurs a lot of 'context' needs to be stored/preserved. In event-driven programming only the essential/minimal state is stored. Overall I would say less memory is needed. Also, QP framework comes in different versions (page 17 here -> www.state-machine.com/doc/QP-QM_Overview_Slides.pdf). Then only problem is interacting with traditional blocking code (TCP stacks and other 'bigger' components), but recent QP versions have a special kernel for this: QXK (www.state-machine.com/qpcpp/struct.html).
@abder54534 жыл бұрын
@Mariusz Ryndzionek I disagree with your reply to my first question. In fact, when the blinking thread calls the delay function, the scheduler will preempt it immediately, allowing other ready threads to be run (the button thread in your example), and its status will change from RUNNING to BLOCKED/WAIT (In lesson 25 of MIRO's course, he elegantly showed why & how this is implemented. This is mentioned also in part1 of this presentation). What you said is True for sequential implementations (polling), but when using RTOS's this problem is well addressed. (also, as a side note, code duplication has no correlation with adopting a while loop inside the thread. For the Blinky example you can use just two functions : delay + led_toggle). As an answer to my first question about threads unresponsiveness, I found an elegant explanation in this article by David M.Cummings : " Managing concurrency in complex embedded systems " www.state-machine.com/doc/Cummings2006.pdf (it is referenced in part2 of this presentation kzbin.info/www/bejne/i2LTeYahm9mtntk ). This problem of threads being unable to respond to multiple events can be more encountered in multithreaded complex embedded systems, and the way to mitigate its multiple risks, is by adopting the three key "best practices" mentioned in the part2 video and to not give in to the temptations of taking shortcuts using in-line blocking. It's true that following those principles can result in a seemingly more complex code, but it is a small tradeoff compared to the resulting subtle bugs that can be very hard to track down and fix. The way i see AO design pattern now, is more of an elegant way to apply those best practices and also to ease the implementation of state-machine based designs. I Think it was just difficult for me to visualize this problem at the beginning, through the Blinky example, in fact, it's not possible, as this type of problems may never occur in such simple implementations. The example used in the article was straight on the spot and it would be better if Miro Samek used it instead of the Blinky one. Anyway, it is an enlightening presentation.
@DisciplinedMusings19844 жыл бұрын
@@abder5453 I wasn't talking about the example from the course where button and LED threads are independent. Please look at the state machine diagram I linked. In my example blinking depends on the button and there is no way to implement his elegantly with two separate threads. a separate button thread would be run, but so what? In order to stop the blinking it would need to interact someway with the blinking thread. Some RTOSes provide a way to asynchronously cancel a thread, but in most cases it's not recommended and there is no guarantee that the task will be stopped ASAP. To reiterate, the scheduler will preempt immediately and other tasks can run, but the preempted task's control flow is stopped for the duration of the delay/sleep. Regarding David M.Cummings article I know it since around 2012 and it explains exactly what I tried to explain here.
@abder54534 жыл бұрын
@@DisciplinedMusings1984 I thought you were using the same example in the video. gotcha now!, you're example is also great. thanks
@StateMachineCOM4 жыл бұрын
@@abder5453 Apparently I wasn't precise enough in my reply to your question about unresponsiveness of a blocked thread, so let me try again. You are right to notice that "when the blinking thread calls the delay function, the scheduler will preempt it immediately...". But the whole point is that the delayed (blocked) thread will be preempted by a *different* thread. The *blocked* thread itself will not run until the delay elapses. This is what I mean that the thread is unresponsive. You can now contrast this with an Active Object (also a thread), which is waiting on the TIMEOUT event. Such an AO *remains* responsive to other events, such as button-press (see the BlinkyButton example in the video). I hope that this clarifies my previous response. --MMS
@nhanNguyen-wo8fy9 ай бұрын
7:00 usage
@riyaziskhan4 жыл бұрын
Hi , can you give idea about noinit section of Ram
@StateMachineCOM4 жыл бұрын
Please watch my videos about the startup code (starting with lesson 13, kzbin.info/www/bejne/sHekn4ptid-oarc ) --MMS
@JonitoFischer4 жыл бұрын
"because of the bizarre design of FreeRTOS..." 🤣🤣🤣
@StateMachineCOM4 жыл бұрын
I know, it's sacrilegious to say anything critical about FreeRTOS. After all, it has this magical word "Free" in its name... But really, this duplication of "FromISR" APIs and "regular" APIs, as well as quadruplication of the APIs for "static" and "heap-based" RTOS objects and many other things are real pain in the neck... This doesn't need to be that way and in fact most RTOSes out there are cleaner and easier to use. It just seems such a lost opportunity that the community has settled on FreeRTOS. Please note that I don't have any dog in this fight. It's just that FreeRTOS is below average... --MMS
@abominabletruthman2 жыл бұрын
@@StateMachineCOM Of all the RTOSs that you have chosen (or been forced against your will) to use over the years, which ones do you consider to be your "go-tos", or ones that stand out in terms of their design, performance, etc.? Were any of them of particular influence when developing QXK? I ask because I am currently halfway through your book and would like to complement it with more general study of the real-time concepts associated with a traditional RTOS. Thanks! (P. S. - Might we also be blessed with the possibility of a 3rd Edition book in the pipeline covering your updated QP?)
@StateMachineCOM2 жыл бұрын
@@abominabletruthman If you're interested with "more general study of real-time concepts associated with a traditional RTOS", I'd recommend that you watch the "RTOS Playlist" from the "Modern Embedded Systems Programming" video course: kzbin.info/aero/PLPW8O6W-1chyrd_Msnn4LD6LBs2slJITs . There are 7 lessons on the traditional RTOS there. --MMS
@StateMachineCOM2 жыл бұрын
@@abominabletruthman Regarding the 3rd Edition of the "Practical Statecharts in C/C++" book, it's not planned and definitely not in paper format. Instead, the updated documentation of QP will contain the "Certification Pack". This "Certification Pack" will provide Software Requirement Specification (SRS), Software Architecture Specification (SAS), Software Design Specification (SDS/SDD), MISRA Compliance Matrix, Tests and more. The "Cert-Pack" is the most requested feature, because the users need to certify QP to various safety-related standards, like IEC-61508, etc. --MMS