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  vTaskSwitchContext
33    EXTERN  ulPortYieldRequired
34    EXTERN  ulPortInterruptNesting
35    EXTERN  vApplicationIRQHandler
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    SECTION .text:CODE:ROOT(2)
46    ARM
47
48    INCLUDE portASM.h
49
50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
51; SVC handler is used to yield a task.
52;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
53FreeRTOS_SWI_Handler
54
55    PRESERVE8
56
57    ; Save the context of the current task and select a new task to run.
58    portSAVE_CONTEXT
59    LDR R0, =vTaskSwitchContext
60    BLX R0
61    portRESTORE_CONTEXT
62
63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
64; vPortRestoreTaskContext is used to start the scheduler.
65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
66vPortRestoreTaskContext
67
68    PRESERVE8
69
70    ; Switch to system mode
71    CPS     #SYS_MODE
72    portRESTORE_CONTEXT
73
74;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
75; IRQ interrupt handler used when individual priorities cannot be masked
76;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
77FreeRTOS_IRQ_Handler
78
79    PRESERVE8
80
81    ; Return to the interrupted instruction.
82    SUB     lr, lr, #4
83
84    ; Push the return address and SPSR
85    PUSH    {lr}
86    MRS     lr, SPSR
87    PUSH    {lr}
88
89    ; Change to supervisor mode to allow reentry.
90    CPS     #SVC_MODE
91
92    ; Push used registers.
93    PUSH    {r0-r4, r12}
94
95    ; Increment nesting count.  r3 holds the address of ulPortInterruptNesting
96    ; for future use.  r1 holds the original ulPortInterruptNesting value for
97    ; future use.
98    LDR     r3, =ulPortInterruptNesting
99    LDR     r1, [r3]
100    ADD     r4, r1, #1
101    STR     r4, [r3]
102
103    ; Ensure bit 2 of the stack pointer is clear.  r2 holds the bit 2 value for
104    ; future use.
105    MOV     r2, sp
106    AND     r2, r2, #4
107    SUB     sp, sp, r2
108
109    PUSH    {r0-r4, lr}
110
111    ; Call the port part specific handler.
112    LDR     r0, =vApplicationIRQHandler
113    BLX     r0
114    POP     {r0-r4, lr}
115    ADD     sp, sp, r2
116
117    CPSID   i
118
119    ; Write to the EOI register.
120    LDR     r4, =configEOI_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    END
174