30.12.2014 Views

QDK PIC24/dsPIC-C30 - Quantum Leaps

QDK PIC24/dsPIC-C30 - Quantum Leaps

QDK PIC24/dsPIC-C30 - Quantum Leaps

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

<strong>QDK</strong><br />

<strong>PIC24</strong>/<strong>dsPIC</strong>-<strong>C30</strong><br />

www.state-machine.com/pic<br />

3.4 QP Idle Loop Customization in QF_onIdle()<br />

The cooperative “vanilla” kernel can very easily detect the situation when no events are available, in<br />

which case QF_run() calls the QF_onIdle() callback. You can use QF_onIdle() to suspended the CPU<br />

to save power, if your CPU supports such a power-saving mode. Please note that QF_onIdle() is called<br />

repetitively from the event loop whenever the event loop has no more events to process, in which case<br />

only an interrupt can provide new events. The QF_onIdle() callback is called with interrupts locked,<br />

because the determination of the idle condition might change by any interrupt posting an event.<br />

The <strong>PIC24</strong>-<strong>dsPIC</strong> CPU supports several power-saving levels (consult the data sheets of particular<br />

<strong>PIC24</strong>/<strong>dsPIC</strong> devices for details). The following piece of code shows the QF_onIdle() callback that puts<br />

Pic24-dspic DSP into the IDLE power-saving mode. Please note that Pic24-dspic architecture allows for<br />

an atomic setting the low-power mode and enabling interrupts at the same time.<br />

Listing 6: QF_onIdle() for the non-preemptive (“vanilla”) QP port to <strong>PIC24</strong>/<strong>dsPIC</strong><br />

(1) void QF_onIdle(void) { /* entered with int disabled, NOTE01 */<br />

(2) LED_ON (IDLE_LED); /* blink the IDLE LED, see NOTE02 */<br />

(3) LED_OFF(IDLE_LED);<br />

(4) #ifdef Q_SPY<br />

. . . /* output Q-SPY trace data to the UART (see Section 7) */<br />

(5) #elif defined NDEBUG<br />

(6) __asm__ volatile("disi #0x0001");<br />

(7) Idle(); /* transition to Idle mode, see NOTE03 */<br />

#else<br />

(8) QF_INT_ENABLE(); /* enable interrupts, see NOTE01 */<br />

#endif<br />

}<br />

(1) The QF_onIdle() callback is always called with interrupts disabled to prevent any race condition<br />

between posting events from ISRs and transitioning to the sleep mode.<br />

(2-3) The LED D10 on the Explorer 16 board is used to visualize the idle loop activity. The LED is toggled<br />

on and off, which causes the LED to “glow” at the intensity proportional to the rate of invocations of<br />

the idle callback. The idle LED is toggled with interrupts still disabled, which means that the intensity<br />

of the LED “glow” is not skewed by preemptions from interrupts or tasks.<br />

(4) If QSPY software tracing is enabled, the QF_onIdle() callback tries to output one byte from the<br />

trace buffer to the SCI. See Section 7 for more information about QSPY software tracing.<br />

(5) The low-power mode stops the CPU clock, so it can interfere with the debugger. Here, the lowpower<br />

mode is activated only in the Release build configuration when the macro NDEBUG is<br />

defined.<br />

(6) Interrupts are locked for just one following machine instruction, which ensures that interrupts will<br />

unlock after the IDLE mode.<br />

(7) The IDLE mode is activated by executing the IDLE instruction.<br />

NOTE: The <strong>PIC24</strong>-<strong>dsPIC</strong> allows for atomic transition to the Idle or Sleep modes with interrupts<br />

locked, as it should be done for a deterministic transition to the low-power mode (see [Samek 07a]).<br />

(8) When the idle/sleep mode is not used, interrupts are simply enabled.<br />

Copyright © <strong>Quantum</strong> <strong>Leaps</strong>, LLC. All Rights Reserved.<br />

16 of 35

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!