Hello!
I'm interested in QP framework, never used it before. I want to try to use QP Active objects with existing project written on bare metal with supper loop.
Is it possible to use QP without existing QV or QK kernels? How can i make it work?
QF component (Quantum Framework) - this component provides things like timers, active objects (with queues and threads), event posting, publish/subscribe, etc.
QSPY component (event tracing / logging)
QV / QK / QKX / RTOS / "roll your own" scheduler - determines what thread runs where
So I mentioned 2 parts to the answer.
The first answer is that you can use just the QEP part of the QP, and have as many QEP state machines as you want. How those state machines get events is up to you (the QEP provides an API to send an event to a state machine, but your superloop would still have to call it). So you can use the QEP part of the QP, and add first-class UML statecharts to your design without using QK, QV, etc.
The second part to the answer: you can also /replace/ or substitute any scheduler (your own, an RTOS, etc.) in place of QV, QK, etc. You just need to make sure that you have a way of ensuring that active object queues get serviced fast enough. In the example above, there were no threads, and thus no active objects -- your superloop was simply dispatching events to threads as needed based on your requirements. But if you pull in the QF part of the framework, you'll need to ensure that the system is running through the AOs in priority order (even if not under control of a preemptive scheduler)
Hope that helps.
👍
1
Last edit: Panopticon 2019-12-29
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Unfortunately, it doesn't quite work that way. QP is a framework and that means that QP calls your code and not you call QP. This is known as inversion of control and is the defining characteristics of a framework, as opposed to a library that you call.
Also, active objects are, well... "active", and that means that they run on their own whenever they have some events to process, and otherwise they don't run at all.
This is in contrast to the "superloop" architecture, where you call passive objects, which then run in your thread of control, whenever you decide (inside your "superloop").
Having said all that, the simplest cooperative QV kernel of QP runs active objects in a loop that is very much like your "superloop" (see the attached page from the PSiCC2 book). I would hihgly recommend that you start with running a simple "Blinky" example under the QV kernel (see qpc\examples\arm-cm\blinky_ek-tm4c123gxl\qv\gnu) .
When you understand how the simple "Blinky" works, you could convert your existing passive objects from your superloop into active objects that you add gradually to the working Blinky. I hope this suggestion makes sense to you.
Panopticon's comment is of course right, but it assumes high level of understanding of the underlying concepts and components of an active-object framework like QP.
To draw an analogy, this is like building your own car from parts. You want to take a car body (QP), but you want to use your own engine ("superloop") in it. Yes, it can be done, but it requires much more work, skill, and tools than simply taking the whole car "as-is", especially that the "car" (QP) comes with several "engines" (kernels) you can choose from.
With this analogy in mind, I hope you can see why I first recommended to take the "car" for a test drive and see how it works (play with the existing "Blinky" example). Only after you decide whether you actually like it, you could invest some more in playing with the engines... Again, I hope this makes sense to you.
--MMS
👍
1
Last edit: Quantum Leaps 2019-12-30
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I strongly agree with MMS' comment, and hesitated even to post about using only the QEP, because a) I cannot imagine why the original poster wouldn't want to use the QP as a whole, and b) it does require some understanding of the structure and underlying roles of the QP components.
Artem -- I don't mean this as a criticism, but your original question is kind of like, "I want to still use my horses to pull the vehicle, but how can I use a Tesla automobile to get from point A from point B." Of course, you /can/ force the horses to pull the Tesla while it is powered off, but the better approach is to move into 2020 and let the car propel itself (said another way: the better approach would be to move away from the superloop and its perils, and at a minimum move to using the QP under the non-preemptive QV kernel)
Please post back if you have further questions!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks for your kind reply.
Unfortunately, I haven't used any frameworks before.
All my devices works bare metal with superloop (as I showed i my first message).
Each task in supperloop polls the peripheral or software component for its own needs and makes some useful actions. Programs are written without using any hardware interrupts (except data transmission ) runing tightly in real time.
As i understood :
In QP framework each active object is waiting for an event. As soon as an event occurs, the active object wakes up and performs some actions.
In provided examples active objects that polls for peripherals or internal conditions, are woken by event from - xTicker each ms.
What if i need to wake my object faster than ms and not depend on timing conditions to provide an event loop?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Yes, your understanding seems correct. QP framewors (QP/C, QP/C++ and QP-nano) being active-object frameworks are purely event-driven. This means that active objects only run when there are events for them, otherwise they don't run at all. This is an ideal model for low-power applications, because when there are no events to process, the CPU and peripherals can be put to low-power sleep mode.
But this does not mean that you cannot run periodically and poll. You can setup periodic Time Events, which will then wake up the recipient active object to do stuff periodically. Of course, you can control the the interval of each Time Event, so you can poll at a rate that is opimal (not too fast).
But really, to take advantage of the event-driven model you should think more about using interrupts. The main purpose of interrupts in the context of QP framework is to generate events and post (or publish) them to active objects for processing.
In this respect, QP is similar to an RTOS, where also interrupts play critical role in context-switching between tasks. I would highly recommend that you watch my YouTube videos about the foreground/background architecture and about the RTOS.
--MMS
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hello!
I'm interested in QP framework, never used it before. I want to try to use QP Active objects with existing project written on bare metal with supper loop.
Is it possible to use QP without existing QV or QK kernels? How can i make it work?
e.g:
Regards.
Hi Artem,
Yes, in fact there are really 2 parts to the answer.
The QP is actually comprised of several components with (deliberately) well-defined interfaces. A typical QP application will make use of the QP's:
QEP component (Quantum Event Processor) - this component provides UML statechart functionality
QF component (Quantum Framework) - this component provides things like timers, active objects (with queues and threads), event posting, publish/subscribe, etc.
QSPY component (event tracing / logging)
QV / QK / QKX / RTOS / "roll your own" scheduler - determines what thread runs where
So I mentioned 2 parts to the answer.
The first answer is that you can use just the QEP part of the QP, and have as many QEP state machines as you want. How those state machines get events is up to you (the QEP provides an API to send an event to a state machine, but your superloop would still have to call it). So you can use the QEP part of the QP, and add first-class UML statecharts to your design without using QK, QV, etc.
The second part to the answer: you can also /replace/ or substitute any scheduler (your own, an RTOS, etc.) in place of QV, QK, etc. You just need to make sure that you have a way of ensuring that active object queues get serviced fast enough. In the example above, there were no threads, and thus no active objects -- your superloop was simply dispatching events to threads as needed based on your requirements. But if you pull in the QF part of the framework, you'll need to ensure that the system is running through the AOs in priority order (even if not under control of a preemptive scheduler)
Hope that helps.
Last edit: Panopticon 2019-12-29
Unfortunately, it doesn't quite work that way. QP is a framework and that means that QP calls your code and not you call QP. This is known as inversion of control and is the defining characteristics of a framework, as opposed to a library that you call.
Also, active objects are, well... "active", and that means that they run on their own whenever they have some events to process, and otherwise they don't run at all.
This is in contrast to the "superloop" architecture, where you call passive objects, which then run in your thread of control, whenever you decide (inside your "superloop").
Having said all that, the simplest cooperative QV kernel of QP runs active objects in a loop that is very much like your "superloop" (see the attached page from the PSiCC2 book). I would hihgly recommend that you start with running a simple "Blinky" example under the QV kernel (see
qpc\examples\arm-cm\blinky_ek-tm4c123gxl\qv\gnu
) .When you understand how the simple "Blinky" works, you could convert your existing passive objects from your superloop into active objects that you add gradually to the working Blinky. I hope this suggestion makes sense to you.
--MMS
Last edit: Quantum Leaps 2019-12-30
Panopticon's comment is of course right, but it assumes high level of understanding of the underlying concepts and components of an active-object framework like QP.
To draw an analogy, this is like building your own car from parts. You want to take a car body (QP), but you want to use your own engine ("superloop") in it. Yes, it can be done, but it requires much more work, skill, and tools than simply taking the whole car "as-is", especially that the "car" (QP) comes with several "engines" (kernels) you can choose from.
With this analogy in mind, I hope you can see why I first recommended to take the "car" for a test drive and see how it works (play with the existing "Blinky" example). Only after you decide whether you actually like it, you could invest some more in playing with the engines... Again, I hope this makes sense to you.
--MMS
Last edit: Quantum Leaps 2019-12-30
I strongly agree with MMS' comment, and hesitated even to post about using only the QEP, because a) I cannot imagine why the original poster wouldn't want to use the QP as a whole, and b) it does require some understanding of the structure and underlying roles of the QP components.
Artem -- I don't mean this as a criticism, but your original question is kind of like, "I want to still use my horses to pull the vehicle, but how can I use a Tesla automobile to get from point A from point B." Of course, you /can/ force the horses to pull the Tesla while it is powered off, but the better approach is to move into 2020 and let the car propel itself (said another way: the better approach would be to move away from the superloop and its perils, and at a minimum move to using the QP under the non-preemptive QV kernel)
Please post back if you have further questions!
Thanks for your kind reply.
Unfortunately, I haven't used any frameworks before.
All my devices works bare metal with superloop (as I showed i my first message).
Each task in supperloop polls the peripheral or software component for its own needs and makes some useful actions. Programs are written without using any hardware interrupts (except data transmission ) runing tightly in real time.
As i understood :
In QP framework each active object is waiting for an event. As soon as an event occurs, the active object wakes up and performs some actions.
In provided examples active objects that polls for peripherals or internal conditions, are woken by event from - xTicker each ms.
What if i need to wake my object faster than ms and not depend on timing conditions to provide an event loop?
Yes, your understanding seems correct. QP framewors (QP/C, QP/C++ and QP-nano) being active-object frameworks are purely event-driven. This means that active objects only run when there are events for them, otherwise they don't run at all. This is an ideal model for low-power applications, because when there are no events to process, the CPU and peripherals can be put to low-power sleep mode.
But this does not mean that you cannot run periodically and poll. You can setup periodic Time Events, which will then wake up the recipient active object to do stuff periodically. Of course, you can control the the interval of each Time Event, so you can poll at a rate that is opimal (not too fast).
But really, to take advantage of the event-driven model you should think more about using interrupts. The main purpose of interrupts in the context of QP framework is to generate events and post (or publish) them to active objects for processing.
In this respect, QP is similar to an RTOS, where also interrupts play critical role in context-switching between tasks. I would highly recommend that you watch my YouTube videos about the foreground/background architecture and about the RTOS.
--MMS