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

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

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

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

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

The solution used in this QK port is to use the __preprologue__ attribute of the compiler-generated ISR<br />

to check the stacked SR before the compiler pushes any registers to the stack and alters the stack<br />

pointer. The IPL extracted from the stacked SR is then stored in the global variable QK_intNest_, which<br />

in this case is not used as the interrupt nesting counter, but rather as a bitmask (a set) of preempted IPL<br />

levels. More precisely, the QK-specific ISR entry code added before any compiler-generated code checks<br />

the stacked IPL level in SR and sets the bit corresponding to the preempted IPL in the<br />

QK_intNest_ bitmask, as illustrated in Figure 7. In the QK-specific ISR exit code, the current IPL is<br />

extracted from the SR and the bit corresponding to the current IPL is cleared in the QK_intNest_<br />

bitmask.<br />

Figure 7: Storing the preempted IPLs in the QK_intNest_ bitmask<br />

Bit number<br />

7<br />

6<br />

5<br />

4<br />

3<br />

2<br />

1<br />

0<br />

0<br />

0<br />

1<br />

0<br />

0<br />

0<br />

1<br />

1<br />

QK_intNest_<br />

Unused level (IPL = 7)<br />

Preempted IPL = 5<br />

Preempted IPL = 1<br />

Preempted IPL = 0<br />

The QK-specific interrupt entry and exit sequence defined in the header file qk_port.h shown in Listing 7<br />

demonstrates one possible solution to this problem. The QK port header file for the <strong>PIC24</strong>/<strong>dsPIC</strong> port is<br />

located in \ports\pic24-dspic\qk\mplab-c30\qk_port.h. The upcoming Section “ISRs with the<br />

Preemptive QK Kernel” explains how to use the macros QK_ISR_ENTRY() / QK_ISR_EXIT() and how<br />

these macros work at the assembly level.<br />

Listing 7: qk_port.h header file for the preemptive QP port with QK<br />

/* QK interrupt entry and exit */<br />

(1) #define QK_ISR(psv_) \<br />

(2) void __attribute__((__interrupt__(__preprologue__( \<br />

"push RCOUNT \n" \<br />

"push.d w0 \n" \<br />

"mov.w [w15-8],w0 \n" \<br />

"lsr.w w0,#13,w1 \n" \<br />

"mov.w #1,w0 \n" \<br />

"sl w0,w1,w0 \n" \<br />

"ior.b _QK_intNest_\n" \<br />

"bra .+6 ")) \<br />

, psv_))<br />

(3) #define QK_ISR_EXIT() do { \<br />

register uint16_t this_sr; \<br />

__asm__ volatile ( \<br />

"mov.w SR,%0 \n" \<br />

"lsr %0,#5,w0 \n" \<br />

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

18 of 35

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

Saved successfully!

Ooh no, something went wrong!