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 portmacro.inc
30
31    IMPORT  vApplicationIRQHandler
32    IMPORT  vTaskSwitchContext
33    IMPORT  ulPortYieldRequired
34    IMPORT  ulPortInterruptNesting
35    IMPORT  vTaskSwitchContext
36    IMPORT  ulICCIAR
37    IMPORT  ulICCEOIR
38
39    EXPORT  FreeRTOS_SWI_Handler
40    EXPORT  FreeRTOS_IRQ_Handler
41    EXPORT  vPortRestoreTaskContext
42
43    ARM
44    AREA    PORT_ASM, CODE, READONLY
45
46
47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
48; SVC handler is used to yield a task.
49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
50FreeRTOS_SWI_Handler
51
52    PRESERVE8
53
54    ; Save the context of the current task and select a new task to run.
55    portSAVE_CONTEXT
56    LDR R0, =vTaskSwitchContext
57    BLX R0
58    portRESTORE_CONTEXT
59
60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
61; vPortRestoreTaskContext is used to start the scheduler.
62;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
63vPortRestoreTaskContext
64    ; Switch to system mode
65    CPS     #SYS_MODE
66    portRESTORE_CONTEXT
67
68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
69; PL390 GIC interrupt handler
70;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
71FreeRTOS_IRQ_Handler
72
73    ; Return to the interrupted instruction.
74    SUB     lr, lr, #4
75
76    ; Push the return address and SPSR
77    PUSH    {lr}
78    MRS     lr, SPSR
79    PUSH    {lr}
80
81    ; Change to supervisor mode to allow reentry.
82    CPS     #SVC_MODE
83
84    ; Push used registers.
85    PUSH    {r0-r4, r12}
86
87    ; Increment nesting count.  r3 holds the address of ulPortInterruptNesting
88    ; for future use.  r1 holds the original ulPortInterruptNesting value for
89    ; future use.
90    LDR     r3, =ulPortInterruptNesting
91    LDR     r1, [r3]
92    ADD     r4, r1, #1
93    STR     r4, [r3]
94
95    ; Read value from the interrupt acknowledge register, which is stored in r0
96    ; for future parameter and interrupt clearing use.
97    LDR     r2, =ulICCIAR
98    LDR     r0, [r2]
99
100    ; Ensure bit 2 of the stack pointer is clear.  r2 holds the bit 2 value for
101    ; future use.  _RB_ Does this ever actually need to be done provided the
102    ; start of the stack is 8-byte aligned?
103    MOV     r2, sp
104    AND     r2, r2, #4
105    SUB     sp, sp, r2
106
107    ; Call the interrupt handler.  r4 is pushed to maintain alignment.
108    PUSH    {r0-r4, lr}
109    LDR     r1, =vApplicationIRQHandler
110    BLX     r1
111    POP     {r0-r4, lr}
112    ADD     sp, sp, r2
113
114    CPSID   i
115
116    ; Write the value read from ICCIAR to ICCEOIR
117    LDR     r4, =ulICCEOIR
118    STR     r0, [r4]
119
120    ; Restore the old nesting count
121    STR     r1, [r3]
122
123    ; A context switch is never performed if the nesting count is not 0
124    CMP     r1, #0
125    BNE     exit_without_switch
126
127    ; Did the interrupt request a context switch?  r1 holds the address of
128    ; ulPortYieldRequired and r0 the value of ulPortYieldRequired for future
129    ; use.
130    LDR     r1, =ulPortYieldRequired
131    LDR     r0, [r1]
132    CMP     r0, #0
133    BNE     switch_before_exit
134
135exit_without_switch
136    ; No context switch.  Restore used registers, LR_irq and SPSR before
137    ; returning.
138    POP     {r0-r4, r12}
139    CPS     #IRQ_MODE
140    POP     {LR}
141    MSR     SPSR_cxsf, LR
142    POP     {LR}
143    MOVS    PC, LR
144
145switch_before_exit
146    ; A context switch is to be performed.  Clear the context switch pending
147    ; flag.
148    MOV     r0, #0
149    STR     r0, [r1]
150
151    ; Restore used registers, LR-irq and SPSR before saving the context
152    ; to the task stack.
153    POP     {r0-r4, r12}
154    CPS     #IRQ_MODE
155    POP     {LR}
156    MSR     SPSR_cxsf, LR
157    POP     {LR}
158    portSAVE_CONTEXT
159
160    ; Call the function that selects the new task to execute.
161    ; vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD
162    ; instructions, or 8 byte aligned stack allocated data.  LR does not need
163    ; saving as a new LR will be loaded by portRESTORE_CONTEXT anyway.
164    LDR     r0, =vTaskSwitchContext
165    BLX     r0
166
167    ; Restore the context of, and branch to, the task selected to execute next.
168    portRESTORE_CONTEXT
169
170
171    END
172