2 FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
\r
5 VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
\r
7 ***************************************************************************
\r
9 * FreeRTOS provides completely free yet professionally developed, *
\r
10 * robust, strictly quality controlled, supported, and cross *
\r
11 * platform software that has become a de facto standard. *
\r
13 * Help yourself get started quickly and support the FreeRTOS *
\r
14 * project by purchasing a FreeRTOS tutorial book, reference *
\r
15 * manual, or both from: http://www.FreeRTOS.org/Documentation *
\r
19 ***************************************************************************
\r
21 This file is part of the FreeRTOS distribution.
\r
23 FreeRTOS is free software; you can redistribute it and/or modify it under
\r
24 the terms of the GNU General Public License (version 2) as published by the
\r
25 Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
\r
27 >>! NOTE: The modification to the GPL is included to allow you to !<<
\r
28 >>! distribute a combined work that includes FreeRTOS without being !<<
\r
29 >>! obliged to provide the source code for proprietary components !<<
\r
30 >>! outside of the FreeRTOS kernel. !<<
\r
32 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
\r
33 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
\r
34 FOR A PARTICULAR PURPOSE. Full license text is available from the following
\r
35 link: http://www.freertos.org/a00114.html
\r
39 ***************************************************************************
\r
41 * Having a problem? Start by reading the FAQ "My application does *
\r
42 * not run, what could be wrong?" *
\r
44 * http://www.FreeRTOS.org/FAQHelp.html *
\r
46 ***************************************************************************
\r
48 http://www.FreeRTOS.org - Documentation, books, training, latest versions,
\r
49 license and Real Time Engineers Ltd. contact details.
\r
51 http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
\r
52 including FreeRTOS+Trace - an indispensable productivity tool, a DOS
\r
53 compatible FAT file system, and our tiny thread aware UDP/IP stack.
\r
55 http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
\r
56 Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
\r
57 licenses offer ticketed support, indemnification and middleware.
\r
59 http://www.SafeRTOS.com - High Integrity Systems also provide a safety
\r
60 engineered and independently SIL3 certified version for use in safety and
\r
61 mission critical applications that require provable dependability.
\r
67 #include <sys/asm.h>
\r
68 #include "FreeRTOSConfig.h"
\r
69 #include "ISR_Support.h"
\r
72 .extern pxCurrentTCB
\r
73 .extern vTaskSwitchContext
\r
74 .extern vPortIncrementTick
\r
75 .extern xISRStackTop
\r
77 .global vPortStartFirstTask
\r
78 .global vPortYieldISR
\r
79 .global vPortTickInterruptHandler
\r
82 /******************************************************************/
\r
89 /***************************************************************
\r
90 * The following is needed to locate the
\r
91 * vPortTickInterruptHandler function into the correct vector
\r
92 ***************************************************************/
\r
93 #ifdef configTICK_INTERRUPT_VECTOR
\r
94 #if (configTICK_INTERRUPT_VECTOR == _CORE_TIMER_VECTOR)
\r
95 .equ __vector_dispatch_0, vPortTickInterruptHandler
\r
96 .global __vector_dispatch_0
\r
97 .section .vector_0, code, keep
\r
98 #elif (configTICK_INTERRUPT_VECTOR == _TIMER_1_VECTOR)
\r
99 .equ __vector_dispatch_4, vPortTickInterruptHandler
\r
100 .global __vector_dispatch_4
\r
101 .section .vector_4, code, keep
\r
102 #elif (configTICK_INTERRUPT_VECTOR == _TIMER_2_VECTOR)
\r
103 .equ __vector_dispatch_9, vPortTickInterruptHandler
\r
104 .global __vector_dispatch_9
\r
105 .section .vector_9, code, keep
\r
106 #elif (configTICK_INTERRUPT_VECTOR == _TIMER_3_VECTOR)
\r
107 .equ __vector_dispatch_14, vPortTickInterruptHandler
\r
108 .global __vector_dispatch_14
\r
109 .section .vector_14, code, keep
\r
110 #elif (configTICK_INTERRUPT_VECTOR == _TIMER_4_VECTOR)
\r
111 .equ __vector_dispatch_19, vPortTickInterruptHandler
\r
112 .global __vector_dispatch_19
\r
113 .section .vector_19, code, keep
\r
114 #elif (configTICK_INTERRUPT_VECTOR == _TIMER_5_VECTOR)
\r
115 .equ __vector_dispatch_24, vPortTickInterruptHandler
\r
116 .global __vector_dispatch_24
\r
117 .section .vector_24, code, keep
\r
118 #elif (configTICK_INTERRUPT_VECTOR == _TIMER_6_VECTOR)
\r
119 .equ __vector_dispatch_28, vPortTickInterruptHandler
\r
120 .global __vector_dispatch_28
\r
121 .section .vector_28, code, keep
\r
122 #elif (configTICK_INTERRUPT_VECTOR == _TIMER_7_VECTOR)
\r
123 .equ __vector_dispatch_32, vPortTickInterruptHandler
\r
124 .global __vector_dispatch_32
\r
125 .section .vector_32, code, keep
\r
126 #elif (configTICK_INTERRUPT_VECTOR == _TIMER_8_VECTOR)
\r
127 .equ __vector_dispatch_36, vPortTickInterruptHandler
\r
128 .global __vector_dispatch_36
\r
129 .section .vector_36, code, keep
\r
130 #elif (configTICK_INTERRUPT_VECTOR == _TIMER_9_VECTOR)
\r
131 .equ __vector_dispatch_40, vPortTickInterruptHandler
\r
132 .global __vector_dispatch_40
\r
133 .section .vector_40, code, keep
\r
136 .equ __vector_dispatch_4, vPortTickInterruptHandler
\r
137 .global __vector_dispatch_4
\r
138 .section .vector_4, code, keep
\r
141 .ent vPortTickInterruptHandler
\r
143 vPortTickInterruptHandler:
\r
147 jal vPortIncrementTick
\r
150 portRESTORE_CONTEXT
\r
152 .end vPortTickInterruptHandler
\r
154 /******************************************************************/
\r
158 .section .text, code
\r
159 .ent vPortStartFirstTask
\r
161 vPortStartFirstTask:
\r
163 /* Simply restore the context of the highest priority task that has been
\r
165 portRESTORE_CONTEXT
\r
167 .end vPortStartFirstTask
\r
171 /*******************************************************************/
\r
177 /***************************************************************
\r
178 * The following is needed to locate the vPortYieldISR function
\r
179 * into the correct vector
\r
180 ***************************************************************/
\r
181 .equ __vector_dispatch_1, vPortYieldISR
\r
182 .global __vector_dispatch_1
\r
183 .section .vector_1, code
\r
188 /* Make room for the context. First save the current status so it can be
\r
189 manipulated, and the cause and EPC registers so thier original values are
\r
191 addiu sp, sp, -portCONTEXT_SIZE
\r
192 mfc0 k1, _CP0_STATUS
\r
194 /* Also save s6 and s5 so they can be used. Any nesting interrupts should
\r
195 maintain the values of these registers across the ISR. */
\r
198 sw k1, portSTATUS_STACK_LOCATION(sp)
\r
200 /* Prepare to re-enabled interrupts above the kernel priority. */
\r
201 ins k1, zero, 10, 7 /* Clear IPL bits 0:6. */
\r
202 ins k1, zero, 18, 1 /* Clear IPL bit 7. It would be an error here if this bit were set anyway. */
\r
203 ori k1, k1, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 )
\r
204 ins k1, zero, 1, 4 /* Clear EXL, ERL and UM. */
\r
206 /* s5 is used as the frame pointer. */
\r
209 /* Swap to the system stack. This is not conditional on the nesting
\r
210 count as this interrupt is always the lowest priority and therefore
\r
211 the nesting is always 0. */
\r
212 la sp, xISRStackTop
\r
215 /* Set the nesting count. */
\r
216 la k0, uxInterruptNesting
\r
220 /* s6 holds the EPC value, this is saved with the rest of the context
\r
221 after interrupts are enabled. */
\r
224 /* Re-enable interrupts above configMAX_SYSCALL_INTERRUPT_PRIORITY. */
\r
225 mtc0 k1, _CP0_STATUS
\r
227 /* Save the context into the space just created. s6 is saved again
\r
228 here as it now contains the EPC value. */
\r
248 sw s6, portEPC_STACK_LOCATION(s5)
\r
249 /* s5 and s6 has already been saved. */
\r
257 /* s7 is used as a scratch register as this should always be saved across
\r
258 nesting interrupts. */
\r
260 /* Save the AC0, AC1, AC2 and AC3. */
\r
284 /* Save the stack pointer to the task. */
\r
285 la s7, pxCurrentTCB
\r
289 /* Set the interrupt mask to the max priority that can use the API. The
\r
290 yield handler will only be called at configKERNEL_INTERRUPT_PRIORITY which
\r
291 is below configMAX_SYSCALL_INTERRUPT_PRIORITY - so this can only ever
\r
292 raise the IPL value and never lower it. */
\r
295 mfc0 s7, _CP0_STATUS
\r
296 ins s7, zero, 10, 7
\r
297 ins s7, zero, 18, 1
\r
298 ori s6, s7, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 ) | 1
\r
300 /* This mtc0 re-enables interrupts, but only above
\r
301 configMAX_SYSCALL_INTERRUPT_PRIORITY. */
\r
302 mtc0 s6, _CP0_STATUS
\r
305 /* Clear the software interrupt in the core. */
\r
306 mfc0 s6, _CP0_CAUSE
\r
308 mtc0 s6, _CP0_CAUSE
\r
311 /* Clear the interrupt in the interrupt controller. */
\r
316 jal vTaskSwitchContext
\r
319 /* Clear the interrupt mask again. The saved status value is still in s7. */
\r
320 mtc0 s7, _CP0_STATUS
\r
323 /* Restore the stack pointer from the TCB. */
\r
324 la s0, pxCurrentTCB
\r
328 /* Restore the rest of the context. */
\r
359 /* s5 is loaded later. */
\r
381 /* Protect access to the k registers, and others. */
\r
385 /* Set nesting back to zero. As the lowest priority interrupt this
\r
386 interrupt cannot have nested. */
\r
387 la k0, uxInterruptNesting
\r
390 /* Switch back to use the real stack pointer. */
\r
393 /* Restore the real s5 value. */
\r
396 /* Pop the status and epc values. */
\r
397 lw k1, portSTATUS_STACK_LOCATION(sp)
\r
398 lw k0, portEPC_STACK_LOCATION(sp)
\r
400 /* Remove stack frame. */
\r
401 addiu sp, sp, portCONTEXT_SIZE
\r
403 mtc0 k1, _CP0_STATUS
\r