1;/*
2; * FreeRTOS Kernel V11.1.0
3; * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4; *
5; * SPDX-License-Identifier: MIT
6; *
7; * Permission is hereby granted, free of charge, to any person obtaining a copy of
8; * this software and associated documentation files (the "Software"), to deal in
9; * the Software without restriction, including without limitation the rights to
10; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11; * the Software, and to permit persons to whom the Software is furnished to do so,
12; * subject to the following conditions:
13; *
14; * The above copyright notice and this permission notice shall be included in all
15; * copies or substantial portions of the Software.
16; *
17; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23; *
24; * https://www.FreeRTOS.org
25; * https://github.com/FreeRTOS
26; *
27; */
28
29    INCLUDE FreeRTOSConfig.h
30    INCLUDE portmacro.h
31
32    EXTERN  vApplicationIRQHandler
33    EXTERN  vTaskSwitchContext
34    EXTERN  ulPortYieldRequired
35    EXTERN  ulPortInterruptNesting
36
37    PUBLIC  FreeRTOS_SWI_Handler
38    PUBLIC  FreeRTOS_IRQ_Handler
39    PUBLIC  vPortRestoreTaskContext
40
41SYS_MODE            EQU     0x1f
42SVC_MODE            EQU     0x13
43IRQ_MODE            EQU     0x12
44
45
46    SECTION .text:CODE:ROOT(2)
47    ARM
48
49    INCLUDE portASM.h
50
51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
52; SVC handler is used to yield a task.
53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
54FreeRTOS_SWI_Handler
55
56    PRESERVE8
57
58    ; Save the context of the current task and select a new task to run.
59    portSAVE_CONTEXT
60    LDR R0, =vTaskSwitchContext
61    BLX R0
62    portRESTORE_CONTEXT
63
64;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
65; vPortRestoreTaskContext is used to start the scheduler.
66;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
67vPortRestoreTaskContext
68    ; Switch to system mode
69    CPS     #SYS_MODE
70    portRESTORE_CONTEXT
71
72;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
73; PL390 GIC interrupt handler
74;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
75FreeRTOS_IRQ_Handler
76
77    ; Return to the interrupted instruction.
78    SUB     lr, lr, #4
79
80    ; Push the return address and SPSR
81    PUSH    {lr}
82    MRS     lr, SPSR
83    PUSH    {lr}
84
85    ; Change to supervisor mode to allow reentry.
86    CPS     #SVC_MODE
87
88    ; Push used registers.
89    PUSH    {r0-r4, r12}
90
91    ; Increment nesting count.  r3 holds the address of ulPortInterruptNesting
92    ; for future use.  r1 holds the original ulPortInterruptNesting value for
93    ; future use.
94    LDR     r3, =ulPortInterruptNesting
95    LDR     r1, [r3]
96    ADD     r4, r1, #1
97    STR     r4, [r3]
98
99    ; Read value from the interrupt acknowledge register, which is stored in r0
100    ; for future parameter and interrupt clearing use.
101    LDR     r2, =portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS
102    LDR     r0, [r2]
103
104    ; Ensure bit 2 of the stack pointer is clear.  r2 holds the bit 2 value for
105    ; future use.  _RB_ Is this ever necessary if start of stack is 8-byte aligned?
106    MOV     r2, sp
107    AND     r2, r2, #4
108    SUB     sp, sp, r2
109
110    ; Call the interrupt handler.  r4 is pushed to maintain alignment.
111    PUSH    {r0-r4, lr}
112    LDR     r1, =vApplicationIRQHandler
113    BLX     r1
114    POP     {r0-r4, lr}
115    ADD     sp, sp, r2
116
117    CPSID   i
118
119    ; Write the value read from ICCIAR to ICCEOIR
120    LDR     r4, =portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS
121    STR     r0, [r4]
122
123    ; Restore the old nesting count
124    STR     r1, [r3]
125
126    ; A context switch is never performed if the nesting count is not 0
127    CMP     r1, #0
128    BNE     exit_without_switch
129
130    ; Did the interrupt request a context switch?  r1 holds the address of
131    ; ulPortYieldRequired and r0 the value of ulPortYieldRequired for future
132    ; use.
133    LDR     r1, =ulPortYieldRequired
134    LDR     r0, [r1]
135    CMP     r0, #0
136    BNE     switch_before_exit
137
138exit_without_switch
139    ; No context switch.  Restore used registers, LR_irq and SPSR before
140    ; returning.
141    POP     {r0-r4, r12}
142    CPS     #IRQ_MODE
143    POP     {LR}
144    MSR     SPSR_cxsf, LR
145    POP     {LR}
146    MOVS    PC, LR
147
148switch_before_exit
149    ; A context switch is to be performed.  Clear the context switch pending
150    ; flag.
151    MOV     r0, #0
152    STR     r0, [r1]
153
154    ; Restore used registers, LR-irq and SPSR before saving the context
155    ; to the task stack.
156    POP     {r0-r4, r12}
157    CPS     #IRQ_MODE
158    POP     {LR}
159    MSR     SPSR_cxsf, LR
160    POP     {LR}
161    portSAVE_CONTEXT
162
163    ; Call the function that selects the new task to execute.
164    ; vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD
165    ; instructions, or 8 byte aligned stack allocated data.  LR does not need
166    ; saving as a new LR will be loaded by portRESTORE_CONTEXT anyway.
167    LDR     r0, =vTaskSwitchContext
168    BLX     r0
169
170    ; Restore the context of, and branch to, the task selected to execute next.
171    portRESTORE_CONTEXT
172
173
174    END
175