1 /*----------------------------------------------------------------------------
3 *----------------------------------------------------------------------------
5 * Purpose: Hardware Abstraction Layer for Cortex-A9
7 *----------------------------------------------------------------------------
9 * Copyright (c) 2012 - 2013 ARM Limited
10 * All rights reserved.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions are met:
13 * - Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * - Neither the name of ARM nor the names of its contributors may be used
19 * to endorse or promote products derived from this software without
20 * specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *---------------------------------------------------------------------------*/
35 #include "rt_TypeDef.h"
36 #include "RTX_Config.h"
37 #include "rt_System.h"
40 #include "rt_MemBox.h"
41 #include "rt_HAL_CA.h"
44 /*----------------------------------------------------------------------------
46 *---------------------------------------------------------------------------*/
48 //For A-class, set USR/SYS stack
49 __asm
void rt_set_PSP (U32 stack
) {
53 CPS
#MODE_SYS ;no effect in USR mode
56 MSR CPSR_c
, R1
;no effect in USR mode
62 //For A-class, get USR/SYS stack
63 __asm U32
rt_get_PSP (void) {
67 CPS
#MODE_SYS ;no effect in USR mode
70 MSR CPSR_c
, R1
;no effect in USR mode
75 /*--------------------------- _alloc_box ------------------------------------*/
76 __asm
void *_alloc_box (void *box_mem
) {
77 /* Function wrapper for Unprivileged/Privileged mode. */
80 LDR R12
,=__cpp(rt_alloc_box
)
89 /*--------------------------- _free_box -------------------------------------*/
90 __asm
int _free_box (void *box_mem
, void *box
) {
91 /* Function wrapper for Unprivileged/Privileged mode. */
94 LDR R12
,=__cpp(rt_free_box
)
103 /*-------------------------- SVC_Handler -----------------------------------*/
107 __asm
void SVC_Handler (void) {
120 SRSFD SP
!, #Mode_SVC ; Push LR_SVC and SPRS_SVC onto SVC mode stack
121 PUSH
{R4
} ; Push R4 so we can use it as a temp
123 MRS R4
,SPSR
; Get SPSR
124 TST R4
,#CPSR_T_BIT ; Check Thumb Bit
125 LDRNEH R4
,[LR
,#-2] ; Thumb: Load Halfword
126 BICNE R4
,R4
,#0xFF00 ; Extract SVC Number
127 LDREQ R4
,[LR
,#-4] ; ARM: Load Word
128 BICEQ R4
,R4
,#0xFF000000 ; Extract SVC Number
130 /* Lock out systick and re-enable interrupts */
133 AND R12
, SP
, #4 ; Ensure stack is 8-byte aligned
134 SUB SP
, SP
, R12
; Adjust stack
135 PUSH
{R12
, LR
} ; Store stack adjustment
and dummy LR to SVC stack
140 POP
{R12
, LR
} ; Get stack adjustment
& discard dummy LR
141 ADD SP
, SP
, R12
; Unadjust stack
149 PUSH
{R4
} ; Push R4 so we can use it as a temp
150 AND R4
, SP
, #4 ; Ensure stack is 8-byte aligned
151 SUB SP
, SP
, R4
; Adjust stack
152 PUSH
{R4
, LR
} ; Store stack adjustment
and dummy LR
154 POP
{R4
, LR
} ; Get stack adjustment
& discard dummy LR
155 ADD SP
, SP
, R4
; Unadjust stack
156 POP
{R4
} ; Restore R4
159 /* Here we will be in SVC mode (even if coming in from PendSV_Handler or OS_Tick_Handler) */
161 LDR LR
,=__cpp(&os_tsk
)
162 LDM LR
,{R4
,LR
} ; os_tsk
.run
, os_tsk
.new
168 AND R12
, SP
, #4 ; Ensure stack is 8-byte aligned
169 SUB SP
, SP
, R12
; Adjust stack
170 PUSH
{R12
, LR
} ; Store stack adjustment
and dummy LR to SVC stack
175 POP
{R12
, LR
} ; Get stack adjustment
& discard dummy LR
176 ADD SP
, SP
, R12
; Unadjust stack
180 RFEFD SP
! ; Return from exception
, no task
switch
185 ADDEQ SP
,SP
,#12 ; Original R4, LR & SPSR do not need to be popped when we are paging in a different task
186 BEQ SVC_Next
; Runtask deleted
?
189 PUSH
{R8
-R11
} //R4 and LR already stacked
190 MOV R10
,R4
; Preserve os_tsk
.run
191 MOV R11
,LR
; Preserve os_tsk
.new
193 ADD R8
,SP
,#16 ; Unstack R4,LR
196 SUB SP
,SP
,#4 ; Make space on the stack for the next instn
197 STMIA SP
,{SP
}^ ; Put User SP onto stack
198 POP
{R8
} ; Pop User SP into R8
201 STMDB R8
!,{R9
} ; User CPSR
202 STMDB R8
!,{LR
} ; User PC
203 STMDB R8
,{LR
}^ ; User LR
204 SUB R8
,R8
,#4 ; No writeback for store of User LR
205 STMDB R8
!,{R0
-R3
,R12
} ; User R0
-R3
,R12
206 MOV R3
,R10
; os_tsk
.run
207 MOV LR
,R11
; os_tsk
.new
209 ADD SP
,SP
,#12 ; Fix up SP for unstack of R4, LR & SPSR
210 STMDB R8
!,{R4
-R7
,R9
-R12
} ; User R4
-R11
212 //If applicable, stack VFP state
213 MRC p15
,0,R1
,c1
,c0
,2 ; VFP
/NEON access enabled
? (CPACR
)
214 AND R2
,R1
,#0x00F00000
218 STMDB R8
!,{R2
,R4
} ; Push FPSCR
, maintain
8-byte alignment
220 LDRB R2
,[R3
,#TCB_STACKF] ; Record in TCB that VFP state is stacked
222 STRB R2
,[R3
,#TCB_STACKF]
225 STR R8
,[R3
,#TCB_TSTACK]
228 PUSH
{R4
} ; Push R4 so we can use it as a temp
229 AND R4
, SP
, #4 ; Ensure stack is 8-byte aligned
230 SUB SP
, SP
, R4
; Adjust stack
231 PUSH
{R4
, LR
} ; Store stack adjustment
and dummy LR to SVC stack
235 POP
{R4
, LR
} ; Get stack adjustment
& discard dummy LR
236 ADD SP
, SP
, R4
; Unadjust stack
237 POP
{R4
} ; Restore R4
241 SVC_Next
//R4 == os_tsk.run, LR == os_tsk.new, R0-R3, R5-R12 corruptible
242 LDR R1
,=__cpp(&os_tsk
) ; os_tsk
.run
= os_tsk
.new
244 LDRB R1
,[LR
,#TCB_TID] ; os_tsk.run->task_id
245 LSL R1
,#8 ; Store PROCID
246 MCR p15
,0,R1
,c13
,c0
,1 ; Write CONTEXTIDR
248 LDR R0
,[LR
,#TCB_TSTACK] ; os_tsk.run->tsk_stack
250 //Does incoming task have VFP state in stack?
251 LDRB R3
,[LR
,#TCB_STACKF]
253 MRC p15
,0,R1
,c1
,c0
,2 ; Read CPACR
254 ANDEQ R1
,R1
,#0xFF0FFFFF ; Disable VFP access if incoming task does not have stacked VFP state
255 ORRNE R1
,R1
,#0x00F00000 ; Enable VFP access if incoming task does have stacked VFP state
256 MCR p15
,0,R1
,c1
,c0
,2 ; Write CPACR
258 ISB
; We only need the sync
if we enabled
, otherwise we will context
switch before next VFP instruction anyway
265 LDR R1
,[R0
,#60] ; Restore User CPSR
267 LDMIA R0
!,{R4
-R11
} ; Restore User R4
-R11
268 ADD R0
,R0
,#4 ; Restore User R1-R3,R12
269 LDMIA R0
!,{R1
-R3
,R12
}
270 LDMIA R0
,{LR
}^ ; Restore User LR
271 ADD R0
,R0
,#4 ; No writeback for load to user LR
272 LDMIA R0
!,{LR
} ; Restore User PC
273 ADD R0
,R0
,#4 ; Correct User SP for unstacked user CPSR
275 PUSH
{R0
} ; Push R0 onto stack
276 LDMIA SP
,{SP
}^ ; Get R0 off stack into User SP
277 ADD SP
,SP
,#4 ; Put SP back
279 LDR R0
,[R0
,#-32] ; Restore R0
283 AND R12
, SP
, #4 ; Ensure stack is 8-byte aligned
284 SUB SP
, SP
, R12
; Adjust stack
285 PUSH
{R12
, LR
} ; Store stack adjustment
and dummy LR to SVC stack
290 POP
{R12
, LR
} ; Get stack adjustment
& discard dummy LR
291 ADD SP
, SP
, R12
; Unadjust stack
295 MOVS PC
,LR
; Return from exception
298 /*------------------- User SVC -------------------------------*/
303 CMP R4
,R12
; Check
for overflow
307 LDR R12
,[R12
,R4
,LSL
#2] ; Load SVC Function Address
308 MRS R4
,SPSR
; Save SPSR
309 PUSH
{R4
} ; Push R4 so we can use it as a temp
310 AND R4
, SP
, #4 ; Ensure stack is 8-byte aligned
311 SUB SP
, SP
, R4
; Adjust stack
312 PUSH
{R4
, LR
} ; Store stack adjustment
and dummy LR
313 BLX R12
; Call SVC Function
314 POP
{R4
, LR
} ; Get stack adjustment
& discard dummy LR
315 ADD SP
, SP
, R4
; Unadjust stack
316 POP
{R4
} ; Restore R4
317 MSR SPSR_CXSF
,R4
; Restore SPSR
322 PUSH
{R4
} ; Push R4 so we can use it as a temp
323 AND R4
, SP
, #4 ; Ensure stack is 8-byte aligned
324 SUB SP
, SP
, R4
; Adjust stack
325 PUSH
{R4
, LR
} ; Store stack adjustment
and dummy LR
330 POP
{R4
, LR
} ; Get stack adjustment
& discard dummy LR
331 ADD SP
, SP
, R4
; Unadjust stack
332 POP
{R4
} ; Restore R4
336 RFEFD SP
! ; Return from exception
342 __asm
void PendSV_Handler (U32 IRQn
) {
348 ADD SP
,SP
,#8 //fix up stack pointer (R0 has been pushed and will never be popped, R1 was pushed for stack alignment)
350 //Disable systick interrupts, then write EOIR. We want interrupts disabled before we enter the context switcher.
354 LDR R1
, =__cpp(&GICInterface_BASE
)
358 LDR R0
, =IRQNestLevel
; Get address of nesting counter
360 SUB R1
, R1
, #1 ; Decrement nesting counter
363 BLX
__cpp(rt_pop_req
)
365 POP
{R1
, LR
} ; Get stack adjustment
& discard dummy LR
366 ADD SP
, SP
, R1
; Unadjust stack
370 POP
{R0
-R3
,R12
} ; Leave SPSR
& LR on the stack
379 __asm
void OS_Tick_Handler (U32 IRQn
) {
385 ADD SP
,SP
,#8 //fix up stack pointer (R0 has been pushed and will never be popped, R1 was pushed for stack alignment)
390 LDR R1
, =__cpp(&GICInterface_BASE
)
394 LDR R0
, =IRQNestLevel
; Get address of nesting counter
396 SUB R1
, R1
, #1 ; Decrement nesting counter
399 BLX
__cpp(os_tick_irqack
)
400 BLX
__cpp(rt_systick
)
402 POP
{R1
, LR
} ; Get stack adjustment
& discard dummy LR
403 ADD SP
, SP
, R1
; Unadjust stack
407 POP
{R0
-R3
,R12
} ; Leave SPSR
& LR on the stack
414 /*----------------------------------------------------------------------------
416 *---------------------------------------------------------------------------*/