QP-nano  6.9.0
Real-Time Embedded Framework
ARM7/ARM9

Preemptive QK Kernel

1;-----------------------------------------------------------------------------
2; Product: QK port to ARM7/9, IAR-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; https://www.state-machine.com
32; mailto:info@state-machine.com
33;-----------------------------------------------------------------------------
34
35NO_IRQ DEFINE 0x80 ; mask to disable interrupts (FIQ and IRQ)
36NO_FIQ DEFINE 0x40 ; mask to disable interrupts (FIQ and IRQ)
37FIQ_MODE DEFINE 0x11
38IRQ_MODE DEFINE 0x12
39SYS_MODE DEFINE 0x1F
40
41 ; NOTE: keep in synch with the QK_Attr struct in "qk.h" !!!
42QK_INT_NEST DEFINE 4
43
44;-----------------------------------------------------------------------------
45; Interrupt disabling/enabling and QK initialization
46;-----------------------------------------------------------------------------
47
48 SECTION .textrw:DATA:NOROOT(2)
49 PUBLIC QF_int_disable_SYS, QF_int_enable_SYS, QK_init
50 CODE32
51
52QF_int_disable_SYS:
53 MRS r0,cpsr ; get the original CPSR in r0 to return
54 MSR cpsr_c,#(SYS_MODE | NO_IRQ) ; disable IRQ only, FIQ enabled!
55 BX lr ; return the original CPSR in r0
56
57
58QF_int_enable_SYS:
59 MSR cpsr_c,r0 ; restore the original CPSR from r0
60 BX lr ; return to ARM or THUMB
61
62
63QK_init:
64 BX lr ; return to ARM or THUMB
65
66
67;-----------------------------------------------------------------------------
68; IRQ assembly wrapper
69;-----------------------------------------------------------------------------
70
71 SECTION .textrw:DATA:NOROOT(2)
72 PUBLIC QK_irq
73 EXTERN BSP_irq
74 EXTERN QK_attr_, QK_sched_, QK_activate_
75 CODE32
76
77QK_irq:
78; IRQ entry {{{
79 MOV r13,r0 ; save r0 in r13_IRQ
80 SUB r0,lr,#4 ; put return address in r0_SYS
81 MOV lr,r1 ; save r1 in r14_IRQ (lr)
82 MRS r1,spsr ; put the SPSR in r1_SYS
83
84 MSR cpsr_c,#(SYS_MODE | NO_IRQ) ; SYSTEM, no IRQ, but FIQ enabled!
85 STMFD sp!,{r0,r1} ; save SPSR and PC on SYS stack
86 STMFD sp!,{r2-r3,r12,lr} ; save APCS-clobbered regs on SYS stack
87 MOV r0,sp ; make the sp_SYS visible to IRQ mode
88 SUB sp,sp,#(2*4) ; make room for stacking (r0_SYS, r1_SYS)
89
90 MSR cpsr_c,#(IRQ_MODE | NO_IRQ) ; IRQ mode, IRQ disabled
91 STMFD r0!,{r13,r14} ; finish saving the context (r0_SYS,r1_SYS)
92
93 MSR cpsr_c,#(SYS_MODE | NO_IRQ) ; SYSTEM mode, IRQ disabled
94; IRQ entry }}}
95
96 LDR r0,=QK_attr_ ; load address in already saved r0
97 LDRB r12,[r0,#QK_INT_NEST] ; load QK_attr_.intNest into saved r12
98 ADD r12,r12,#1 ; increment the nesting level
99 STRB r12,[r0,#QK_INT_NEST] ; store the value in QK_attr_.intNest
100
101 ; MSR cpsr_c,#(SYS_MODE | NO_IRQ) ; enable FIQ
102 ; NOTE: BSP_irq might re-enable IRQ interrupts (the FIQ is enabled
103 ; already), if IRQs are prioritized by the interrupt controller.
104
105 LDR r12,=BSP_irq
106 MOV lr,pc ; copy the return address to link register
107 BX r12 ; call the C IRQ-handler (ARM/THUMB)
108
109
110 MSR cpsr_c,#(SYS_MODE | NO_IRQ) ; make sure IRQs are disabled
111 LDR r0,=QK_attr_ ; load address
112 LDRB r12,[r0,#QK_INT_NEST] ; load QK_attr_.intNest into saved r12
113 SUBS r12,r12,#1 ; decrement the nesting level
114 STRB r12,[r0,#QK_INT_NEST] ; store the value in QK_attr_.intNest
115 BNE QK_irq_exit ; branch if interrupt nesting not zero
116
117 LDR r12,=QK_sched_
118 MOV lr,pc ; copy the return address to link register
119 BX r12 ; call QK_sched_ (ARM/THUMB)
120 CMP r0,#0 ; check the returned priority
121 BEQ QK_irq_exit ; branch if priority zero
122
123 LDR r12,=QK_activate_
124 MOV lr,pc ; copy the return address to link register
125 BX r12 ; call QK_activate_ (ARM/THUMB)
126
127QK_irq_exit:
128; IRQ exit {{{ ; IRQ/FIQ disabled--return from scheduler
129 MOV r0,sp ; make sp_SYS visible to IRQ mode
130 ADD sp,sp,#(8*4) ; fake unstacking 8 registers from sp_SYS
131
132 MSR cpsr_c,#(IRQ_MODE | NO_IRQ) ; IRQ mode, IRQ disabled
133 MOV sp,r0 ; copy sp_SYS to sp_IRQ
134 LDR r0,[sp,#(7*4)] ; load the saved SPSR from the stack
135 MSR spsr_cxsf,r0 ; copy it into spsr_IRQ
136
137 LDMFD sp,{r0-r3,r12,lr}^ ; unstack all saved USER/SYSTEM registers
138 NOP ; can't access banked reg immediately
139 LDR lr,[sp,#(6*4)] ; load return address from the SYS stack
140 MOVS pc,lr ; return restoring CPSR from SPSR
141; IRQ exit }}}
142
143
144;-----------------------------------------------------------------------------
145; Exception assembler wrappers
146;-----------------------------------------------------------------------------
147
148 PUBLIC QF_reset
149 PUBLIC QF_undef
150 PUBLIC QF_swi
151 PUBLIC QF_pAbort
152 PUBLIC QF_dAbort
153 PUBLIC QF_reserved
154
155 EXTERN Q_onAssert
156
157 SECTION .text:CODE:NOROOT(2)
158 CODE32
159
160QF_reset:
161 LDR r0,=Csting_reset
162 B QF_except
163QF_undef:
164 LDR r0,=Csting_undef
165 B QF_except
166QF_swi:
167 LDR r0,=Csting_swi
168 B QF_except
169QF_pAbort:
170 LDR r0,=Csting_pAbort
171 B QF_except
172QF_dAbort:
173 LDR r0,=Csting_dAbort
174 B QF_except
175QF_reserved:
176 LDR r0,=Csting_reserved
177 B QF_except
178QF_except:
179 ; r0 is set to the string with the exception name
180 SUB r1,lr,#4 ; set line number to the exception address
181 MSR cpsr_c,#(SYS_MODE | NO_IRQ | NO_FIQ) ; SYSTEM, IRQ/FIQ disabled
182 LDR r12,=Q_onAssert
183 MOV lr,pc ; store the return address
184 BX r12 ; call the assertion-handler (ARM/THUMB)
185 ; the assertion handler should not return, but in case it does
186 ; hang up the machine in this endless loop
187 B .
188
189
190 LTORG ; strings enclosed in "" are zero-terminated
191Csting_reset: DC8 "Reset"
192Csting_undef: DC8 "Undefined"
193Csting_swi: DC8 "Software Int"
194Csting_pAbort: DC8 "Prefetch Abort"
195Csting_dAbort: DC8 "Data Abort"
196Csting_reserved: DC8 "Reserved"
197
198
199 END

Cooperative QV Kernel