QP/C 6.9.1
ARM7/ARM9

Preemptive QK Kernel

1 /*****************************************************************************
2 * Product: QK port to ARM7-9, GNU-ARM assembler
3 * Last Updated for Version: 6.3.6
4 * Date of the Last Update: 2018-10-29
5 *
6 * Q u a n t u m L e a P s
7 * ------------------------
8 * Modern Embedded Software
9 *
10 * Copyright (C) Quantum Leaps, LLC. All rights reserved.
11 *
12 * This program is open source software: you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as published
14 * by the Free Software Foundation, either version 3 of the License, or
15 * (at your option) any later version.
16 *
17 * Alternatively, this program may be distributed and modified under the
18 * terms of Quantum Leaps commercial licenses, which expressly supersede
19 * the GNU General Public License and are specifically designed for
20 * licensees interested in retaining the proprietary status of their code.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program. If not, see <http://www.gnu.org/licenses/>.
29 *
30 * Contact information:
31 * <www.state-machine.com/licensing>
32 * <info@state-machine.com>
33 *****************************************************************************/
34 
35  .equ NO_IRQ, 0x80 /* mask to disable interrupts (IRQ) */
36  .equ NO_FIQ, 0x40 /* mask to disable interrupts (FIQ) */
37  .equ FIQ_MODE, 0x11
38  .equ IRQ_MODE, 0x12
39  .equ SYS_MODE, 0x1F
40 
41  /* NOTE: keep in synch with the QK_Attr struct in "qk.h" !!! */
42  .equ QK_INT_NEST, 4
43 
44  .text
45  .arm
46 
47  /* use the special section (.text.fastcode), to enable fine-tuning
48  * of the placement of this section inside the linker script
49  */
50  .section .text.fastcode
51 
52 /*****************************************************************************
53 * unsigned int QF_int_disable_SYS(void);
54 */
55  .global QF_int_disable_SYS
56  .func QF_int_disable_SYS
57 QF_int_disable_SYS:
58  MRS r0,cpsr /* get the original CPSR in r0 to return */
59  MSR cpsr_c,#(SYS_MODE | NO_IRQ) /* disable IRQ only, FIQ enabled! */
60  BX lr /* return the original CPSR in r0 */
61 
62  .size QF_int_disable_SYS, . - QF_int_disable_SYS
63  .endfunc
64 
65 
66 /*****************************************************************************
67 * void QF_int_enable_SYS(unsigned int key);
68 */
69  .global QF_int_enable_SYS
70  .func QF_int_enable_SYS
71 QF_int_enable_SYS:
72  MSR cpsr_c,r0 /* restore the original CPSR from r0 */
73  BX lr /* return to ARM or THUMB */
74 
75  .size QF_int_enable_SYS, . - QF_int_enable_SYS
76  .endfunc
77 
78 
79 /*****************************************************************************
80 * void QK_init();
81 */
82  .global QK_init
83  .func QK_init
84 QK_init:
85  BX lr /* return to ARM or THUMB */
86 
87  .size QK_init, . - QK_init
88  .endfunc
89 
90 
91 /*****************************************************************************
92 * void QK_irq(void);
93 */
94  .global QK_irq
95  .func QK_irq
96  .align 3
97 QK_irq:
98 /* IRQ entry {{{ */
99  MOV r13,r0 /* save r0 in r13_IRQ */
100  SUB r0,lr,#4 /* put return address in r0_SYS */
101  MOV lr,r1 /* save r1 in r14_IRQ (lr) */
102  MRS r1,spsr /* put the SPSR in r1_SYS */
103 
104  MSR cpsr_c,#(SYS_MODE | NO_IRQ) /* SYSTEM, no IRQ, but FIQ enabled! */
105  STMFD sp!,{r0,r1} /* save SPSR and PC on SYS stack */
106  STMFD sp!,{r2-r3,r12,lr} /* save APCS-clobbered regs on SYS stack */
107  MOV r0,sp /* make the sp_SYS visible to IRQ mode */
108  SUB sp,sp,#(2*4) /* make room for stacking (r0_SYS, r1_SYS) */
109 
110  MSR cpsr_c,#(IRQ_MODE | NO_IRQ) /* IRQ mode, IRQ disabled */
111  STMFD r0!,{r13,r14} /* finish saving the context (r0_SYS,r1_SYS)*/
112 
113  MSR cpsr_c,#(SYS_MODE | NO_IRQ) /* SYSTEM mode, IRQ disabled */
114 /* IRQ entry }}} */
115 
116  LDR r0,=QK_attr_ /* load address in already saved r0 */
117  LDRB r12,[r0,#QK_INT_NEST] /* load QK_attr_.intNest into saved r12 */
118  ADD r12,r12,#1 /* increment the nesting level */
119  STRB r12,[r0,#QK_INT_NEST] /* store the value in QK_attr_.intNest */
120 
121  /* MSR cpsr_c,#(SYS_MODE | NO_IRQ) ; enable FIQ
122  * NOTE: BSP_irq might re-enable IRQ interrupts (the FIQ is enabled
123  * already), if IRQs are prioritized by the interrupt controller.
124  */
125  LDR r12,=BSP_irq
126  MOV lr,pc /* copy the return address to link register */
127  BX r12 /* call the C IRQ-handler (ARM/THUMB) */
128 
129  MSR cpsr_c,#(SYS_MODE | NO_IRQ) /* make sure IRQs are disabled */
130  LDR r0,=QK_attr_ /* load address */
131  LDRB r12,[r0,#QK_INT_NEST] /* load QK_attr_.intNest into saved r12 */
132  SUBS r12,r12,#1 /* decrement the nesting level */
133  STRB r12,[r0,#QK_INT_NEST] /* store the value in QK_attr_.intNest */
134  BNE QK_irq_exit /* branch if interrupt nesting not zero */
135 
136  LDR r12,=QK_sched_
137  MOV lr,pc /* copy the return address to link register */
138  BX r12 /* call QK_sched_ (ARM/THUMB) */
139  CMP r0,#0 /* check the returned priority */
140  BEQ QK_irq_exit /* branch if priority zero */
141 
142  LDR r12,=QK_activate_
143  MOV lr,pc /* copy the return address to link register */
144  BX r12 /* call QK_activate_ (ARM/THUMB) */
145 
146 QK_irq_exit:
147 /* IRQ exit {{{ */ /* IRQ/FIQ disabled--return from scheduler */
148  MOV r0,sp /* make sp_SYS visible to IRQ mode */
149  ADD sp,sp,#(8*4) /* fake unstacking 8 registers from sp_SYS */
150 
151  MSR cpsr_c,#(IRQ_MODE | NO_IRQ) /* IRQ mode, IRQ disabled */
152  MOV sp,r0 /* copy sp_SYS to sp_IRQ */
153  LDR r0,[sp,#(7*4)] /* load the saved SPSR from the stack */
154  MSR spsr_cxsf,r0 /* copy it into spsr_IRQ */
155 
156  LDMFD sp,{r0-r3,r12,lr}^ /* unstack all saved USER/SYSTEM registers */
157  NOP /* can't access banked reg immediately */
158  LDR lr,[sp,#(6*4)] /* load return address from the SYS stack */
159  MOVS pc,lr /* return restoring CPSR from SPSR */
160 /* IRQ exit }}} */
161 
162  .size QK_irq, . - QK_irq
163  .endfunc
164 
165 
166 /*****************************************************************************
167 * void QF_reset(void);
168 */
169  .global QF_reset
170  .func QF_reset
171  .align 3
172 QF_reset:
173  LDR r0,=Csting_reset
174  B QF_except
175  .size QF_reset, . - QF_reset
176  .endfunc
177 
178 /*****************************************************************************
179 * void QF_undef(void);
180 */
181  .global QF_undef
182  .func QF_undef
183  .align 3
184 QF_undef:
185  LDR r0,=Csting_undef
186  B QF_except
187  .size QF_undef, . - QF_undef
188  .endfunc
189 
190 /*****************************************************************************
191 * void QF_swi(void);
192 */
193  .global QF_swi
194  .func QF_swi
195  .align 3
196 QF_swi:
197  LDR r0,=Csting_swi
198  B QF_except
199  .size QF_swi, . - QF_swi
200  .endfunc
201 
202 /*****************************************************************************
203 * void QF_pAbort(void);
204 */
205  .global QF_pAbort
206  .func QF_pAbort
207  .align 3
208 QF_pAbort:
209  LDR r0,=Csting_pAbort
210  B QF_except
211  .size QF_pAbort, . - QF_pAbort
212  .endfunc
213 
214 /*****************************************************************************
215 * void QF_dAbort(void);
216 */
217  .global QF_dAbort
218  .func QF_dAbort
219  .align 3
220 QF_dAbort:
221  LDR r0,=Csting_dAbort
222  B QF_except
223  .size QF_dAbort, . - QF_dAbort
224  .endfunc
225 
226 /*****************************************************************************
227 * void QF_reserved(void);
228 */
229  .global QF_reserved
230  .func QF_reserved
231  .align 3
232 QF_reserved:
233  LDR r0,=Csting_reserved
234  B QF_except
235  .size QF_reserved, . - QF_reserved
236  .endfunc
237 
238 /*****************************************************************************
239 * void QF_fiq_dummy(void);
240 */
241  .global QF_fiq_dummy
242  .func QF_fiq_dummy
243  .align 3
244 QF_fiq_dummy:
245  LDR r0,=Csting_fiq
246  B QF_except
247  .size QF_fiq_dummy, . - QF_fiq_dummy
248  .endfunc
249 
250 /*****************************************************************************
251 * void QF_except(void);
252 */
253  .global QF_except
254  .func QF_except
255  .align 3
256 QF_except:
257  /* r0 is set to the string with the exception name */
258  SUB r1,lr,#4 /* set line number to the exception address */
259  MSR cpsr_c,#(SYS_MODE | NO_IRQ | NO_FIQ) /* SYSTEM,IRQ/FIQ disabled */
260  LDR r12,=Q_onAssert
261  MOV lr,pc /* store the return address */
262  BX r12 /* call the assertion-handler (ARM/THUMB) */
263  /* the assertion handler should not return, but in case it does
264  * hang up the machine in this endless loop
265  */
266  B .
267 
268 Csting_reset: .string "Reset"
269 Csting_undef: .string "Undefined"
270 Csting_swi: .string "Software Int"
271 Csting_pAbort: .string "Prefetch Abort"
272 Csting_dAbort: .string "Data Abort"
273 Csting_reserved: .string "Reserved"
274 Csting_fiq: .string "FIQ dummy"
275 
276  .size QF_except, . - QF_except
277  .endfunc
278 
279  .end
280 
281 

Cooperative QV Kernel


Next: MSP430