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 *---------------------------------------------------------------------------*/
39 .global PendSV_Handler
40 .global OS_Tick_Handler
54 .EQU TCB_TID, 3 /* 'task id' offset */
55 .EQU TCB_STACKF, 32 /* 'stack_frame' offset */
56 .EQU TCB_TSTACK, 36 /* 'tsk_stack' offset */
60 .extern GICInterface_BASE
62 .extern os_tick_irqack
65 /*----------------------------------------------------------------------------
67 *---------------------------------------------------------------------------*/
69 @ For A-class, set USR/SYS stack
70 @ __asm void rt_set_PSP (U32 stack) {
75 CPS #MODE_SYS @no effect in USR mode
78 MSR CPSR_c, R1 @no effect in USR mode
84 @ For A-class, get USR/SYS stack
85 @ __asm U32 rt_get_PSP (void) {
90 CPS #MODE_SYS @no effect in USR mode
93 MSR CPSR_c, R1 @no effect in USR mode
99 /*--------------------------- _alloc_box ------------------------------------*/
100 @ __asm void *_alloc_box (void *box_mem) {
102 /* Function wrapper for Unprivileged/Privileged mode. */
105 LDR R12,=rt_alloc_box @ __cpp(rt_alloc_box)
114 /*--------------------------- _free_box -------------------------------------*/
115 @ __asm int _free_box (void *box_mem, void *box) {
117 /* Function wrapper for Unprivileged/Privileged mode. */
120 LDR R12,=rt_free_box @ __cpp(rt_free_box)
129 /*-------------------------- SVC_Handler -----------------------------------*/
133 @ __asm void SVC_Handler (void) {
135 .type SVC_Handler, %function
141 .extern rt_tsk_unlock
149 SRSDB SP!, #Mode_SVC @ Push LR_SVC and SPRS_SVC onto SVC mode stack
150 PUSH {R4} @ Push R4 so we can use it as a temp
153 MRS R4,SPSR @ Get SPSR
154 TST R4,#CPSR_T_BIT @ Check Thumb Bit
155 LDRNEH R4,[LR,#-2] @ Thumb: Load Halfword
156 BICNE R4,R4,#0xFF00 @ Extract SVC Number
157 LDREQ R4,[LR,#-4] @ ARM: Load Word
158 BICEQ R4,R4,#0xFF000000 @ Extract SVC Number
160 /* Lock out systick and re-enable interrupts */
163 AND R12, SP, #4 @ Ensure stack is 8-byte aligned
164 SUB SP, SP, R12 @ Adjust stack
165 PUSH {R12, LR} @ Store stack adjustment and dummy LR to SVC stack
170 POP {R12, LR} @ Get stack adjustment & discard dummy LR
171 ADD SP, SP, R12 @ Unadjust stack
179 PUSH {R4} @ Push R4 so we can use it as a temp
180 AND R4, SP, #4 @ Ensure stack is 8-byte aligned
181 SUB SP, SP, R4 @ Adjust stack
182 PUSH {R4, LR} @ Store stack adjustment and dummy LR
184 POP {R4, LR} @ Get stack adjustment & discard dummy LR
185 ADD SP, SP, R4 @ Unadjust stack
186 POP {R4} @ Restore R4
189 /* Here we will be in SVC mode (even if coming in from PendSV_Handler or OS_Tick_Handler) */
191 LDR LR,=os_tsk @ __cpp(&os_tsk)
192 LDM LR,{R4,LR} @ os_tsk.run, os_tsk.new
198 AND R12, SP, #4 @ Ensure stack is 8-byte aligned
199 SUB SP, SP, R12 @ Adjust stack
200 PUSH {R12, LR} @ Store stack adjustment and dummy LR to SVC stack
205 POP {R12, LR} @ Get stack adjustment & discard dummy LR
206 ADD SP, SP, R12 @ Unadjust stack
210 RFEFD SP! @ Return from exception, no task switch
215 ADDEQ SP,SP,#12 @ Original R4, LR & SPSR do not need to be popped when we are paging in a different task
216 BEQ SVC_Next @ Runtask deleted?
219 PUSH {R8-R11} @ R4 and LR already stacked
220 MOV R10,R4 @ Preserve os_tsk.run
221 MOV R11,LR @ Preserve os_tsk.new
223 ADD R8,SP,#16 @ Unstack R4,LR
226 SUB SP,SP,#4 @ Make space on the stack for the next instn
227 STMIA SP,{SP}^ @ Put User SP onto stack
228 POP {R8} @ Pop User SP into R8
231 STMDB R8!,{R9} @ User CPSR
232 STMDB R8!,{LR} @ User PC
233 STMDB R8,{LR}^ @ User LR
234 SUB R8,R8,#4 @ No writeback for store of User LR
235 STMDB R8!,{R0-R3,R12} @ User R0-R3,R12
236 MOV R3,R10 @ os_tsk.run
237 MOV LR,R11 @ os_tsk.new
239 ADD SP,SP,#12 @ Fix up SP for unstack of R4, LR & SPSR
240 STMDB R8!,{R4-R7,R9-R12} @ User R4-R11
242 @ If applicable, stack VFP state
243 MRC p15,0,R1,c1,c0,2 @ VFP/NEON access enabled? (CPACR)
244 AND R2,R1,#0x00F00000
248 STMDB R8!,{R2,R4} @ Push FPSCR, maintain 8-byte alignment
250 LDRB R2,[R3,#TCB_STACKF] @ Record in TCB that VFP state is stacked
252 STRB R2,[R3,#TCB_STACKF]
255 STR R8,[R3,#TCB_TSTACK]
258 PUSH {R4} @ Push R4 so we can use it as a temp
259 AND R4, SP, #4 @ Ensure stack is 8-byte aligned
260 SUB SP, SP, R4 @ Adjust stack
261 PUSH {R4, LR} @ Store stack adjustment and dummy LR to SVC stack
265 POP {R4, LR} @ Get stack adjustment & discard dummy LR
266 ADD SP, SP, R4 @ Unadjust stack
267 POP {R4} @ Restore R4
271 SVC_Next: @ R4 == os_tsk.run, LR == os_tsk.new, R0-R3, R5-R12 corruptible
272 LDR R1,=os_tsk @ __cpp(&os_tsk), os_tsk.run = os_tsk.new
274 LDRB R1,[LR,#TCB_TID] @ os_tsk.run->task_id
275 LSL R1,#8 @ Store PROCID
276 MCR p15,0,R1,c13,c0,1 @ Write CONTEXTIDR
278 LDR R0,[LR,#TCB_TSTACK] @ os_tsk.run->tsk_stack
280 @ Does incoming task have VFP state in stack?
281 LDRB R3,[LR,#TCB_STACKF]
283 MRC p15,0,R1,c1,c0,2 @ Read CPACR
284 ANDEQ R1,R1,#0xFF0FFFFF @ Disable VFP access if incoming task does not have stacked VFP state
285 ORRNE R1,R1,#0x00F00000 @ Enable VFP access if incoming task does have stacked VFP state
286 MCR p15,0,R1,c1,c0,2 @ Write CPACR
288 ISB @ We only need the sync if we enabled, otherwise we will context switch before next VFP instruction anyway
295 LDR R1,[R0,#60] @ Restore User CPSR
297 LDMIA R0!,{R4-R11} @ Restore User R4-R11
298 ADD R0,R0,#4 @ Restore User R1-R3,R12
299 LDMIA R0!,{R1-R3,R12}
300 LDMIA R0,{LR}^ @ Restore User LR
301 ADD R0,R0,#4 @ No writeback for load to user LR
302 LDMIA R0!,{LR} @ Restore User PC
303 ADD R0,R0,#4 @ Correct User SP for unstacked user CPSR
305 PUSH {R0} @ Push R0 onto stack
306 LDMIA SP,{SP}^ @ Get R0 off stack into User SP
307 ADD SP,SP,#4 @ Put SP back
309 LDR R0,[R0,#-32] @ Restore R0
313 AND R12, SP, #4 @ Ensure stack is 8-byte aligned
314 SUB SP, SP, R12 @ Adjust stack
315 PUSH {R12, LR} @ Store stack adjustment and dummy LR to SVC stack
320 POP {R12, LR} @ Get stack adjustment & discard dummy LR
321 ADD SP, SP, R12 @ Unadjust stack
325 MOVS PC,LR @ Return from exception
328 /*------------------- User SVC -------------------------------*/
333 CMP R4,R12 @ Check for overflow
337 LDR R12,[R12,R4,LSL #2] @ Load SVC Function Address
338 MRS R4,SPSR @ Save SPSR
339 PUSH {R4} @ Push R4 so we can use it as a temp
340 AND R4, SP, #4 @ Ensure stack is 8-byte aligned
341 SUB SP, SP, R4 @ Adjust stack
342 PUSH {R4, LR} @ Store stack adjustment and dummy LR
343 BLX R12 @ Call SVC Function
344 POP {R4, LR} @ Get stack adjustment & discard dummy LR
345 ADD SP, SP, R4 @ Unadjust stack
346 POP {R4} @ Restore R4
347 MSR SPSR_cxsf,R4 @ Restore SPSR
352 PUSH {R4} @ Push R4 so we can use it as a temp
353 AND R4, SP, #4 @ Ensure stack is 8-byte aligned
354 SUB SP, SP, R4 @ Adjust stack
355 PUSH {R4, LR} @ Store stack adjustment and dummy LR
360 POP {R4, LR} @ Get stack adjustment & discard dummy LR
361 ADD SP, SP, R4 @ Unadjust stack
362 POP {R4} @ Restore R4
366 RFEFD SP! @ Return from exception
375 @ __asm void PendSV_Handler (U32 IRQn) {
382 ADD SP,SP,#8 @ fix up stack pointer (R0 has been pushed and will never be popped, R1 was pushed for stack alignment)
384 @ Disable systick interrupts, then write EOIR. We want interrupts disabled before we enter the context switcher.
388 LDR R1, =GICInterface_BASE @ __cpp(&GICInterface_BASE)
392 LDR R0, =IRQNestLevel @ Get address of nesting counter
394 SUB R1, R1, #1 @ Decrement nesting counter
397 BLX rt_pop_req @ __cpp(rt_pop_req)
399 POP {R1, LR} @ Get stack adjustment & discard dummy LR
400 ADD SP, SP, R1 @ Unadjust stack
404 POP {R0-R3,R12} @ Leave SPSR & LR on the stack
412 @ __asm void OS_Tick_Handler (U32 IRQn) {
416 ADD SP,SP,#8 @ fix up stack pointer (R0 has been pushed and will never be popped, R1 was pushed for stack alignment)
421 LDR R1, =GICInterface_BASE @ __cpp(&GICInterface_BASE)
425 LDR R0, =IRQNestLevel @ Get address of nesting counter
427 SUB R1, R1, #1 @ Decrement nesting counter
430 BLX os_tick_irqack @ __cpp(os_tick_irqack)
431 BLX rt_systick @ __cpp(rt_systick)
433 POP {R1, LR} @ Get stack adjustment & discard dummy LR
434 ADD SP, SP, R1 @ Unadjust stack
438 POP {R0-R3,R12} @ Leave SPSR & LR on the stack
445 @ __STATIC_ASM void __set_PSP(uint32_t topOfProcStack)
451 BIC R0, R0, #7 @ensure stack is 8-byte aligned
453 CPS #MODE_SYS @no effect in USR mode
455 MSR CPSR_c, R1 @no effect in USR mode
461 .global __set_CPS_USR
462 @ __STATIC_ASM void __set_CPS_USR(void)
472 /*----------------------------------------------------------------------------
474 *---------------------------------------------------------------------------*/