Go to the source code of this file.
Data Structures | |
| struct | QActive |
| Active Object struct. More... | |
| struct | QActiveCB |
| QActive Control Block. More... | |
Defines | |
| #define | Q_ROM_BYTE(rom_var_) (rom_var_) |
| Macro to access a byte allocated in ROM. | |
| #define | Q_ROM_PTR(rom_var_) (rom_var_) |
| Macro to access a pointer allocated in ROM. | |
| #define | QActive_ctor(me_, initial_) QHsm_ctor(&(me_)->super, initial_) |
| Active object constructor. | |
Typedefs | |
| typedef uint16_t | QTimeEvtCtr |
| type of the Time Event counter, which determines the dynamic range of the time delays measured in clock ticks. | |
Functions | |
| void | QActive_post (QActive *me, QSignal sig, QParam par) |
| Posts an event e directly to the event queue of the acitve object prio using the First-In-First-Out (FIFO) policy. This function briefly locks and unlocks interrupts to protect the queue integrity. | |
| void | QActive_postISR (QActive *me, QSignal sig, QParam par) |
| Posts an event e directly to the event queue of the acitve object prio using the First-In-First-Out (FIFO) policy. This function does NOT lock/unlock interrupts when nesting of interrupts is not allowed. Also, this function never calls the QK-nano scheduler, because synchronous task preemptions are never necessary inside ISRs. | |
| void | QF_tick (void) |
| Processes all armed time events at every clock tick. | |
| void | QActive_arm (QActive *me, QTimeEvtCtr tout) |
| Arm the QP-nano one-shot time event. Since the tick counter is a multi-byte variable in this case, the operation must be performed inside a critical section. | |
| void | QActive_disarm (QActive *me) |
| Disarm a time event. Since the tick counter is a multi-byte variable in this case, the operation must be performed inside a critical section. | |
| void | QF_stop (void) |
| QF-nano termination. | |
| void | QF_onStartup (void) |
| Startup QF-nano callback. | |
| void | QF_run (void) |
| Transfers control to QF to run the application. | |
| void | QF_onIdle (void) |
| QF idle callback (customized in BSPs for QF). | |
Variables | |
| QActiveCB const Q_ROM Q_ROM_VAR | QF_active [] |
| uint8_t volatile | QF_readySet_ |
| Ready set of QF-nano. | |
This header file must be included in all modules that use QP-nano. Typically, this header file is included indirectly through the header file qpn_port.h.
Definition in file qfn.h.
| #define Q_ROM_BYTE | ( | rom_var_ | ) | (rom_var_) |
Macro to access a byte allocated in ROM.
Some compilers for Harvard-architecture MCUs, such as gcc for AVR, do not generate correct code for accessing data allocated in the program space (ROM). The workaround for such compilers is to explictly add assembly code to access each data element allocated in the program space. The macro Q_ROM_BYTE() retrieves a byte from the given ROM address.
The Q_ROM_BYTE() macro should be defined in the qpn_port.h header file for each compiler that cannot handle correctly data allocated in ROM (such as the gcc). If the macro is left undefined, the default definition simply returns the argument and lets the compiler synthesize the correct code.
| #define Q_ROM_PTR | ( | rom_var_ | ) | (rom_var_) |
Macro to access a pointer allocated in ROM.
Some compilers for Harvard-architecture MCUs, such as gcc for AVR, do not generate correct code for accessing data allocated in the program space (ROM). The workaround for such compilers is to explictly add assembly code to access each data element allocated in the program space. The macro Q_ROM_PTR() retrieves an object-pointer from the given ROM address. Please note that the pointer can be pointing to the object in RAM or ROM.
The Q_ROM_PTR() macro should be defined in the qpn_port.h header file for each compiler that cannot handle correctly data allocated in ROM (such as the gcc). If the macro is left undefined, the default definition simply returns the argument and lets the compiler synthesize the correct code.
| #define QActive_ctor | ( | me_, | |||
| initial_ | ) | QHsm_ctor(&(me_)->super, initial_) |
| typedef uint16_t QTimeEvtCtr |
type of the Time Event counter, which determines the dynamic range of the time delays measured in clock ticks.
This typedef is configurable via the preprocessor switch QF_TIMEEVT_CTR_SIZE. The other possible values of this type are as follows:
none when (QF_TIMEEVT_CTR_SIZE not defined or == 0),
uint8_t when (QF_TIMEEVT_CTR_SIZE == 1);
uint16_t when (QF_TIMEEVT_CTR_SIZE == 2); and
uint32_t when (QF_TIMEEVT_CTR_SIZE == 4).
| void QActive_arm | ( | QActive * | me, | |
| QTimeEvtCtr | tout | |||
| ) |
Arm the QP-nano one-shot time event. Since the tick counter is a multi-byte variable in this case, the operation must be performed inside a critical section.
Arms the time event of the active object me to expire in tout clock ticks (one-shot time event). Upon the expiration, the time event posts the reserved signal Q_TIMEOUT_SIG directly into the event queue of the active object me.
After posting, the time event gets automatically disarmed.
The time event can be disarmed (stoped) at any time by calling the QActive_disarm() function. Also, a one-shot time event can be re-armed to fire in a different number of clock ticks by calling QActive_arm() again.
The following example shows how to arm a one-shot time event from a state machine of an active object:
QState Pelican_carsGreen(Pelican *me) { switch (Q_SIG(me)) { case Q_ENTRY_SIG: { QActive_arm((QActive *)me, CARS_GREEN_MIN_TOUT); /* arm timer */ BSP_signalCars(CARS_GREEN); return Q_HANDLED(); } case Q_INIT_SIG: { return Q_TRAN(&Pelican_carsGreenNoPed); } } return Q_SUPER(&Pelican_carsEnabled); }
Definition at line 151 of file qfn.c.
References QF_INT_LOCK, and QActive::tickCtr.
| void QActive_disarm | ( | QActive * | me | ) |
Disarm a time event. Since the tick counter is a multi-byte variable in this case, the operation must be performed inside a critical section.
The time event of the active object me gets disarmed (stopped).
Posts an event e directly to the event queue of the acitve object prio using the First-In-First-Out (FIFO) policy. This function briefly locks and unlocks interrupts to protect the queue integrity.
Direct event posting is the only asynchronous communication method available in QF-nano. The following example illustrates how the Ped active object posts directly the PED_WAITING event to the PELICAN crossing active object.
QState Ped_wait(Ped *me) { switch (Q_SIG(me)) { case Q_ENTRY_SIG: { BSP_showState(me->super.prio, "wait"); me->retryCtr = N_ATTEMPTS; QActive_arm((QActive *)me, WAIT_TOUT); return Q_HANDLED(); } case Q_TIMEOUT_SIG: { if ((--me->retryCtr) != 0) { QActive_arm((QActive *)me, WAIT_TOUT); QActive_post((QActive *)&AO_Pelican, PEDS_WAITING_SIG, 0); } else { return Q_TRAN(&Ped_off); } return Q_HANDLED(); } } return Q_SUPER(&QHsm_top); }
The producer of the event (Ped in this case) must only "know" a pointer recipient (&AO_Pelican), but the specific definition of the Pelican structure is not required.
Direct event posting should not be confused with direct event dispatching. In contrast to asynchronous event posting through event queues, direct event dispatching is synchronous. Direct event dispatching occurs when you call QHsm_dispatch(), or QFsm_dispatch() function.
Definition at line 48 of file qfn.c.
References QActiveCB::end, QActive::head, QActive::nUsed, QActive::prio, Q_ASSERT, Q_PAR, Q_PARAM_SIZE, Q_ROM_BYTE, Q_ROM_PTR, Q_SIG, QActive_post(), QF_active, QF_INT_LOCK, QF_INT_UNLOCK, QF_readySet_, QK_schedule_(), and QActiveCB::queue.
Referenced by QActive_post().
Posts an event e directly to the event queue of the acitve object prio using the First-In-First-Out (FIFO) policy. This function does NOT lock/unlock interrupts when nesting of interrupts is not allowed. Also, this function never calls the QK-nano scheduler, because synchronous task preemptions are never necessary inside ISRs.
Definition at line 83 of file qfn.c.
References QActiveCB::end, QActive::head, QActive::nUsed, QActive::prio, Q_ASSERT, Q_PAR, Q_PARAM_SIZE, Q_ROM_BYTE, Q_ROM_PTR, Q_SIG, QF_active, QF_INT_LOCK, QF_INT_UNLOCK, QF_readySet_, and QActiveCB::queue.
Referenced by QF_tick().
| void QF_onIdle | ( | void | ) |
QF idle callback (customized in BSPs for QF).
QF_onIdle() is called by the non-preemptive scheduler built into QF-nano when the QF-nano detects that no events are available for active objects (the idle condition). This callback gives the application an opportunity to enter a power-saving CPU mode, or perform some other idle processing.
QF_onIdle() is not used in the PREEMPTIVE configuration. When QK_PREEMPTIVE macro is defined, the preemptive kernel QK-nano is used instead of the non-preemptive QF-nano scheduler. QK-nano uses a different idle callback
| void QF_onStartup | ( | void | ) |
Startup QF-nano callback.
The timeline for calling QF_onStartup() depends on the particular QF port. In most cases, QF_onStartup() is called from QF_run(), right before starting any multitasking kernel or the background loop.
Referenced by QF_run().
| void QF_run | ( | void | ) |
Transfers control to QF to run the application.
QF_run() implemetns the simple non-preemptive scheduler. QF_run() must be called from your startup code after you initialize the QF and define at least one active object control block in QF_active[].
Definition at line 58 of file qkn.c.
References QActive::prio, Q_ASSERT, Q_ROM_PTR, QF_active, QF_INT_LOCK, QF_INT_UNLOCK, QF_MAX_ACTIVE, QF_onStartup(), QFsm_init(), QHsm_init(), QK_onIdle(), and QK_SCHEDULE_.
| void QF_stop | ( | void | ) |
QF-nano termination.
This function terminates QF and performs any necessary cleanup. In QF-nano this function is defined in the BSP. Many QF ports might not require implementing QF_stop() at all, because many embedded applications don't have anything to exit to.
| void QF_tick | ( | void | ) |
Processes all armed time events at every clock tick.
/* the system time tick ISR for C8051 from Silicon Labs ....................*/ #pragma vector=0x2B __interrupt void timer2_ISR(void) { TMR2CN &= ~(1 << 7); /* Clear Timer2 interrupt flag */ QF_tick(); /* handle all armed time events in QF-nano */ } /* the system time tick ISR for MSP430 from TI (non-preemptive case) .......*/ #pragma vector = TIMERA0_VECTOR __interrupt void timerA_ISR(void) { __low_power_mode_off_on_exit(); QF_tick(); /* handle all armed time events in QF-nano */ } /* the system time tick ISR for MSP430 from TI (preemptive case QK-nano) ...*/ #pragma vector = TIMERA0_VECTOR __interrupt void timerA_ISR(void) { QK_ISR_ENTRY(); /* inform QK-nano about entering the ISR */ QF_tick(); /* handle all armed time events in QF-nano */ QK_ISR_EXIT(); /* inform QK-nano about exiting the ISR */ }
Definition at line 132 of file qfn.c.
References Q_ROM_PTR, Q_TIMEOUT_SIG, QActive_postISR(), QF_active, QF_MAX_ACTIVE, and QActive::tickCtr.
active object control blocks
Referenced by QActive_post(), QActive_postISR(), QF_run(), QF_tick(), and QK_schedule_().
| uint8_t volatile QF_readySet_ |
Ready set of QF-nano.
The QF-nano ready set keeps track of active objects that are ready to run. The ready set represents each active object as a bit, with the bits assigned according to priorities of the active objects. The bit is set if the corresponding active object is ready to run (i.e., has one or more events in its event queue) and zero if the event queue is empty. The QF-nano ready set is one byte-wide, which corresponds to 8 active objects maximum.
Definition at line 39 of file qfn.c.
Referenced by QActive_post(), QActive_postISR(), and QK_schedule_().
1.5.4