2 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
\r
3 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\r
5 * SPDX-License-Identifier: MIT
\r
7 * Permission is hereby granted, free of charge, to any person obtaining a copy of
\r
8 * this software and associated documentation files (the "Software"), to deal in
\r
9 * the Software without restriction, including without limitation the rights to
\r
10 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
\r
11 * the Software, and to permit persons to whom the Software is furnished to do so,
\r
12 * subject to the following conditions:
\r
14 * The above copyright notice and this permission notice shall be included in all
\r
15 * copies or substantial portions of the Software.
\r
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
19 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
20 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
24 * https://www.FreeRTOS.org
\r
25 * https://github.com/FreeRTOS
\r
29 /* FreeRTOS includes. */
\r
30 #include "FreeRTOSConfig.h"
\r
32 /* Xilinx library includes. */
\r
33 #include "microblaze_exceptions_g.h"
\r
34 #include "xparameters.h"
\r
36 /* Offsets from the stack pointer at which saved registers are placed. */
\r
37 #define portR31_OFFSET 4
\r
38 #define portR30_OFFSET 8
\r
39 #define portR29_OFFSET 12
\r
40 #define portR28_OFFSET 16
\r
41 #define portR27_OFFSET 20
\r
42 #define portR26_OFFSET 24
\r
43 #define portR25_OFFSET 28
\r
44 #define portR24_OFFSET 32
\r
45 #define portR23_OFFSET 36
\r
46 #define portR22_OFFSET 40
\r
47 #define portR21_OFFSET 44
\r
48 #define portR20_OFFSET 48
\r
49 #define portR19_OFFSET 52
\r
50 #define portR18_OFFSET 56
\r
51 #define portR17_OFFSET 60
\r
52 #define portR16_OFFSET 64
\r
53 #define portR15_OFFSET 68
\r
54 #define portR14_OFFSET 72
\r
55 #define portR13_OFFSET 76
\r
56 #define portR12_OFFSET 80
\r
57 #define portR11_OFFSET 84
\r
58 #define portR10_OFFSET 88
\r
59 #define portR9_OFFSET 92
\r
60 #define portR8_OFFSET 96
\r
61 #define portR7_OFFSET 100
\r
62 #define portR6_OFFSET 104
\r
63 #define portR5_OFFSET 108
\r
64 #define portR4_OFFSET 112
\r
65 #define portR3_OFFSET 116
\r
66 #define portR2_OFFSET 120
\r
67 #define portCRITICAL_NESTING_OFFSET 124
\r
68 #define portMSR_OFFSET 128
\r
70 #if( XPAR_MICROBLAZE_USE_FPU != 0 )
\r
71 #define portFSR_OFFSET 132
\r
72 #if( XPAR_MICROBLAZE_USE_STACK_PROTECTION )
\r
73 #define portSLR_OFFSET 136
\r
74 #define portSHR_OFFSET 140
\r
76 #define portCONTEXT_SIZE 144
\r
77 #define portMINUS_CONTEXT_SIZE -144
\r
79 #define portCONTEXT_SIZE 136
\r
80 #define portMINUS_CONTEXT_SIZE -136
\r
83 #if( XPAR_MICROBLAZE_USE_STACK_PROTECTION )
\r
84 #define portSLR_OFFSET 132
\r
85 #define portSHR_OFFSET 136
\r
87 #define portCONTEXT_SIZE 140
\r
88 #define portMINUS_CONTEXT_SIZE -140
\r
90 #define portCONTEXT_SIZE 132
\r
91 #define portMINUS_CONTEXT_SIZE -132
\r
95 .extern pxCurrentTCB
\r
96 .extern XIntc_DeviceInterruptHandler
\r
97 .extern vTaskSwitchContext
\r
98 .extern uxCriticalNesting
\r
100 .extern ulTaskSwitchRequested
\r
101 .extern vPortExceptionHandler
\r
102 .extern pulStackPointerOnFunctionEntry
\r
104 .global _interrupt_handler
\r
105 .global VPortYieldASM
\r
106 .global vPortStartFirstTask
\r
107 .global vPortExceptionHandlerEntry
\r
110 .macro portSAVE_CONTEXT
\r
112 /* Make room for the context on the stack. */
\r
113 addik r1, r1, portMINUS_CONTEXT_SIZE
\r
115 /* Stack general registers. */
\r
116 swi r31, r1, portR31_OFFSET
\r
117 swi r30, r1, portR30_OFFSET
\r
118 swi r29, r1, portR29_OFFSET
\r
119 swi r28, r1, portR28_OFFSET
\r
120 swi r27, r1, portR27_OFFSET
\r
121 swi r26, r1, portR26_OFFSET
\r
122 swi r25, r1, portR25_OFFSET
\r
123 swi r24, r1, portR24_OFFSET
\r
124 swi r23, r1, portR23_OFFSET
\r
125 swi r22, r1, portR22_OFFSET
\r
126 swi r21, r1, portR21_OFFSET
\r
127 swi r20, r1, portR20_OFFSET
\r
128 swi r19, r1, portR19_OFFSET
\r
129 swi r18, r1, portR18_OFFSET
\r
130 swi r17, r1, portR17_OFFSET
\r
131 swi r16, r1, portR16_OFFSET
\r
132 swi r15, r1, portR15_OFFSET
\r
133 /* R14 is saved later as it needs adjustment if a yield is performed. */
\r
134 swi r13, r1, portR13_OFFSET
\r
135 swi r12, r1, portR12_OFFSET
\r
136 swi r11, r1, portR11_OFFSET
\r
137 swi r10, r1, portR10_OFFSET
\r
138 swi r9, r1, portR9_OFFSET
\r
139 swi r8, r1, portR8_OFFSET
\r
140 swi r7, r1, portR7_OFFSET
\r
141 swi r6, r1, portR6_OFFSET
\r
142 swi r5, r1, portR5_OFFSET
\r
143 swi r4, r1, portR4_OFFSET
\r
144 swi r3, r1, portR3_OFFSET
\r
145 swi r2, r1, portR2_OFFSET
\r
147 /* Stack the critical section nesting value. */
\r
148 lwi r18, r0, uxCriticalNesting
\r
149 swi r18, r1, portCRITICAL_NESTING_OFFSET
\r
153 swi r18, r1, portMSR_OFFSET
\r
155 #if( XPAR_MICROBLAZE_USE_FPU != 0 )
\r
158 swi r18, r1, portFSR_OFFSET
\r
161 #if( XPAR_MICROBLAZE_USE_STACK_PROTECTION )
\r
162 /* Save the stack limits */
\r
164 swi r18, r1, portSLR_OFFSET
\r
166 swi r18, r1, portSHR_OFFSET
\r
169 /* Save the top of stack value to the TCB. */
\r
170 lwi r3, r0, pxCurrentTCB
\r
175 .macro portRESTORE_CONTEXT
\r
177 /* Load the top of stack value from the TCB. */
\r
178 lwi r18, r0, pxCurrentTCB
\r
181 #if( XPAR_MICROBLAZE_USE_STACK_PROTECTION )
\r
182 /* Restore the stack limits -- must not load from r1 (Stack Pointer)
\r
183 because if the address of load or store instruction is out of range,
\r
184 it will trigger Stack Protection Violation exception. */
\r
186 lwi r12, r18, portSLR_OFFSET
\r
188 lwi r12, r18, portSHR_OFFSET
\r
192 /* Restore the general registers. */
\r
193 lwi r31, r1, portR31_OFFSET
\r
194 lwi r30, r1, portR30_OFFSET
\r
195 lwi r29, r1, portR29_OFFSET
\r
196 lwi r28, r1, portR28_OFFSET
\r
197 lwi r27, r1, portR27_OFFSET
\r
198 lwi r26, r1, portR26_OFFSET
\r
199 lwi r25, r1, portR25_OFFSET
\r
200 lwi r24, r1, portR24_OFFSET
\r
201 lwi r23, r1, portR23_OFFSET
\r
202 lwi r22, r1, portR22_OFFSET
\r
203 lwi r21, r1, portR21_OFFSET
\r
204 lwi r20, r1, portR20_OFFSET
\r
205 lwi r19, r1, portR19_OFFSET
\r
206 lwi r17, r1, portR17_OFFSET
\r
207 lwi r16, r1, portR16_OFFSET
\r
208 lwi r15, r1, portR15_OFFSET
\r
209 lwi r14, r1, portR14_OFFSET
\r
210 lwi r13, r1, portR13_OFFSET
\r
211 lwi r12, r1, portR12_OFFSET
\r
212 lwi r11, r1, portR11_OFFSET
\r
213 lwi r10, r1, portR10_OFFSET
\r
214 lwi r9, r1, portR9_OFFSET
\r
215 lwi r8, r1, portR8_OFFSET
\r
216 lwi r7, r1, portR7_OFFSET
\r
217 lwi r6, r1, portR6_OFFSET
\r
218 lwi r5, r1, portR5_OFFSET
\r
219 lwi r4, r1, portR4_OFFSET
\r
220 lwi r3, r1, portR3_OFFSET
\r
221 lwi r2, r1, portR2_OFFSET
\r
223 /* Reload the rmsr from the stack. */
\r
224 lwi r18, r1, portMSR_OFFSET
\r
227 #if( XPAR_MICROBLAZE_USE_FPU != 0 )
\r
228 /* Reload the FSR from the stack. */
\r
229 lwi r18, r1, portFSR_OFFSET
\r
233 /* Load the critical nesting value. */
\r
234 lwi r18, r1, portCRITICAL_NESTING_OFFSET
\r
235 swi r18, r0, uxCriticalNesting
\r
237 /* Test the critical nesting value. If it is non zero then the task last
\r
238 exited the running state using a yield. If it is zero, then the task
\r
239 last exited the running state through an interrupt. */
\r
241 bnei r18, exit_from_yield
\r
243 /* r18 was being used as a temporary. Now restore its true value from the
\r
245 lwi r18, r1, portR18_OFFSET
\r
247 /* Remove the stack frame. */
\r
248 addik r1, r1, portCONTEXT_SIZE
\r
250 /* Return using rtid so interrupts are re-enabled as this function is
\r
257 /* This function is used to exit portRESTORE_CONTEXT() if the task being
\r
258 returned to last left the Running state by calling taskYIELD() (rather than
\r
259 being preempted by an interrupt). */
\r
264 /* r18 was being used as a temporary. Now restore its true value from the
\r
266 lwi r18, r1, portR18_OFFSET
\r
268 /* Remove the stack frame. */
\r
269 addik r1, r1, portCONTEXT_SIZE
\r
271 /* Return to the task. */
\r
278 _interrupt_handler:
\r
282 /* Stack the return address. */
\r
283 swi r14, r1, portR14_OFFSET
\r
285 /* Switch to the ISR stack. */
\r
286 lwi r1, r0, pulISRStack
\r
288 #if( XPAR_MICROBLAZE_USE_STACK_PROTECTION )
\r
289 ori r18, r0, _stack_end
\r
291 ori r18, r0, _stack
\r
295 /* The parameter to the interrupt handler. */
\r
296 ori r5, r0, configINTERRUPT_CONTROLLER_TO_USE
\r
298 /* Execute any pending interrupts. */
\r
299 bralid r15, XIntc_DeviceInterruptHandler
\r
302 /* See if a new task should be selected to execute. */
\r
303 lwi r18, r0, ulTaskSwitchRequested
\r
306 /* If ulTaskSwitchRequested is already zero, then jump straight to
\r
307 restoring the task that is already in the Running state. */
\r
308 beqi r18, task_switch_not_requested
\r
310 /* Set ulTaskSwitchRequested back to zero as a task switch is about to be
\r
312 swi r0, r0, ulTaskSwitchRequested
\r
314 /* ulTaskSwitchRequested was not 0 when tested. Select the next task to
\r
316 bralid r15, vTaskSwitchContext
\r
319 task_switch_not_requested:
\r
321 /* Restore the context of the next task scheduled to execute. */
\r
322 portRESTORE_CONTEXT
\r
331 /* Modify the return address so a return is done to the instruction after
\r
332 the call to VPortYieldASM. */
\r
334 swi r14, r1, portR14_OFFSET
\r
336 /* Switch to use the ISR stack. */
\r
337 lwi r1, r0, pulISRStack
\r
339 #if( XPAR_MICROBLAZE_USE_STACK_PROTECTION )
\r
340 ori r18, r0, _stack_end
\r
342 ori r18, r0, _stack
\r
346 /* Select the next task to execute. */
\r
347 bralid r15, vTaskSwitchContext
\r
350 /* Restore the context of the next task scheduled to execute. */
\r
351 portRESTORE_CONTEXT
\r
355 vPortStartFirstTask:
\r
357 portRESTORE_CONTEXT
\r
361 #if ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 )
\r
365 vPortExceptionHandlerEntry:
\r
367 /* Take a copy of the stack pointer before vPortExecptionHandler is called,
\r
368 storing its value prior to the function stack frame being created. */
\r
369 swi r1, r0, pulStackPointerOnFunctionEntry
\r
370 bralid r15, vPortExceptionHandler
\r
373 #endif /* ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 ) */
\r