]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/portable/MPLAB/PIC32MZ/port_asm.S
Update version number to 8.1.2 after moving the defaulting of configUSE_PORT_OPTIMISE...
[freertos] / FreeRTOS / Source / portable / MPLAB / PIC32MZ / port_asm.S
1 /*\r
2     FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.\r
3     All rights reserved\r
4 \r
5     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
6 \r
7     ***************************************************************************\r
8      *                                                                       *\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
12      *                                                                       *\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
16      *                                                                       *\r
17      *    Thank you!                                                         *\r
18      *                                                                       *\r
19     ***************************************************************************\r
20 \r
21     This file is part of the FreeRTOS distribution.\r
22 \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
26 \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
31 \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
36 \r
37     1 tab == 4 spaces!\r
38 \r
39     ***************************************************************************\r
40      *                                                                       *\r
41      *    Having a problem?  Start by reading the FAQ "My application does   *\r
42      *    not run, what could be wrong?"                                     *\r
43      *                                                                       *\r
44      *    http://www.FreeRTOS.org/FAQHelp.html                               *\r
45      *                                                                       *\r
46     ***************************************************************************\r
47 \r
48     http://www.FreeRTOS.org - Documentation, books, training, latest versions,\r
49     license and Real Time Engineers Ltd. contact details.\r
50 \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
54 \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
58 \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
62 \r
63     1 tab == 4 spaces!\r
64 */\r
65 \r
66 #include <xc.h>\r
67 #include <sys/asm.h>\r
68 #include "FreeRTOSConfig.h"\r
69 #include "ISR_Support.h"\r
70 \r
71 \r
72         .extern pxCurrentTCB\r
73         .extern vTaskSwitchContext\r
74         .extern vPortIncrementTick\r
75         .extern xISRStackTop\r
76 \r
77         .global vPortStartFirstTask\r
78         .global vPortYieldISR\r
79         .global vPortTickInterruptHandler\r
80 \r
81 \r
82 /******************************************************************/\r
83 \r
84         .set  nomips16\r
85         .set  nomicromips\r
86         .set  noreorder\r
87         .set  noat\r
88 \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
134                 #endif\r
135         #else\r
136                 .equ     __vector_dispatch_4, vPortTickInterruptHandler\r
137                 .global  __vector_dispatch_4\r
138                 .section .vector_4, code, keep\r
139         #endif\r
140 \r
141         .ent            vPortTickInterruptHandler\r
142 \r
143 vPortTickInterruptHandler:\r
144 \r
145         portSAVE_CONTEXT\r
146 \r
147         jal             vPortIncrementTick\r
148         nop\r
149 \r
150         portRESTORE_CONTEXT\r
151 \r
152         .end vPortTickInterruptHandler\r
153 \r
154 /******************************************************************/\r
155 \r
156         .set            noreorder\r
157         .set            noat\r
158         .section .text, code\r
159         .ent            vPortStartFirstTask\r
160 \r
161 vPortStartFirstTask:\r
162 \r
163         /* Simply restore the context of the highest priority task that has been\r
164         created so far. */\r
165         portRESTORE_CONTEXT\r
166 \r
167         .end vPortStartFirstTask\r
168 \r
169 \r
170 \r
171 /*******************************************************************/\r
172 \r
173         .set  nomips16\r
174         .set  nomicromips\r
175         .set  noreorder\r
176         .set  noat\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
184 \r
185         .ent  vPortYieldISR\r
186 vPortYieldISR:\r
187 \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
190         captured. */\r
191         addiu           sp, sp, -portCONTEXT_SIZE\r
192         mfc0            k1, _CP0_STATUS\r
193 \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
196         sw                      s6, 44(sp)\r
197         sw                      s5, 40(sp)\r
198         sw                      k1, portSTATUS_STACK_LOCATION(sp)\r
199 \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
205 \r
206         /* s5 is used as the frame pointer. */\r
207         add                     s5, zero, sp\r
208 \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
213         lw                      sp, (sp)\r
214 \r
215         /* Set the nesting count. */\r
216         la                      k0, uxInterruptNesting\r
217         addiu           s6, zero, 1\r
218         sw                      s6, 0(k0)\r
219 \r
220         /* s6 holds the EPC value, this is saved with the rest of the context\r
221         after interrupts are enabled. */\r
222         mfc0            s6, _CP0_EPC\r
223 \r
224         /* Re-enable interrupts above configMAX_SYSCALL_INTERRUPT_PRIORITY. */\r
225         mtc0            k1, _CP0_STATUS\r
226 \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
229         sw                      ra, 120(s5)\r
230         sw                      s8, 116(s5)\r
231         sw                      t9, 112(s5)\r
232         sw                      t8, 108(s5)\r
233         sw                      t7, 104(s5)\r
234         sw                      t6, 100(s5)\r
235         sw                      t5, 96(s5)\r
236         sw                      t4, 92(s5)\r
237         sw                      t3, 88(s5)\r
238         sw                      t2, 84(s5)\r
239         sw                      t1, 80(s5)\r
240         sw                      t0, 76(s5)\r
241         sw                      a3, 72(s5)\r
242         sw                      a2, 68(s5)\r
243         sw                      a1, 64(s5)\r
244         sw                      a0, 60(s5)\r
245         sw                      v1, 56(s5)\r
246         sw                      v0, 52(s5)\r
247         sw                      s7, 48(s5)\r
248         sw                      s6, portEPC_STACK_LOCATION(s5)\r
249         /* s5 and s6 has already been saved. */\r
250         sw                      s4,     36(s5)\r
251         sw                      s3, 32(s5)\r
252         sw                      s2, 28(s5)\r
253         sw                      s1, 24(s5)\r
254         sw                      s0, 20(s5)\r
255         sw                      $1, 16(s5)\r
256 \r
257         /* s7 is used as a scratch register as this should always be saved across\r
258         nesting interrupts. */\r
259 \r
260         /* Save the AC0, AC1, AC2 and AC3. */\r
261         mfhi            s7, $ac1\r
262         sw                      s7, 128(s5)\r
263         mflo            s7, $ac1\r
264         sw                      s7, 124(s5)\r
265 \r
266         mfhi            s7, $ac2\r
267         sw                      s7, 136(s5)\r
268         mflo            s7, $ac2\r
269         sw                      s7, 132(s5)\r
270 \r
271         mfhi            s7, $ac3\r
272         sw                      s7, 144(s5)\r
273         mflo            s7, $ac3\r
274         sw                      s7, 140(s5)\r
275 \r
276         rddsp           s7\r
277         sw                      s7, 148(s5)\r
278 \r
279         mfhi            s7, $ac0\r
280         sw                      s7, 12(s5)\r
281         mflo            s7, $ac0\r
282         sw                      s7, 8(s5)\r
283 \r
284         /* Save the stack pointer to the task. */\r
285         la                      s7, pxCurrentTCB\r
286         lw                      s7, (s7)\r
287         sw                      s5, (s7)\r
288 \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
293         di\r
294         ehb\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
299 \r
300         /* This mtc0 re-enables interrupts, but only above\r
301         configMAX_SYSCALL_INTERRUPT_PRIORITY. */\r
302         mtc0            s6, _CP0_STATUS\r
303         ehb\r
304 \r
305         /* Clear the software interrupt in the core. */\r
306         mfc0            s6, _CP0_CAUSE\r
307         ins                     s6, zero, 8, 1\r
308         mtc0            s6, _CP0_CAUSE\r
309         ehb\r
310 \r
311         /* Clear the interrupt in the interrupt controller. */\r
312         la                      s6, IFS0CLR\r
313         addiu           s4, zero, 2\r
314         sw                      s4, (s6)\r
315 \r
316         jal                     vTaskSwitchContext\r
317         nop\r
318 \r
319         /* Clear the interrupt mask again.  The saved status value is still in s7. */\r
320         mtc0            s7, _CP0_STATUS\r
321         ehb\r
322 \r
323         /* Restore the stack pointer from the TCB. */\r
324         la                      s0, pxCurrentTCB\r
325         lw                      s0, (s0)\r
326         lw                      s5, (s0)\r
327 \r
328         /* Restore the rest of the context. */\r
329         lw                      s0, 128(s5)\r
330         mthi            s0, $ac1\r
331         lw                      s0, 124(s5)\r
332         mtlo            s0, $ac1\r
333 \r
334         lw                      s0, 136(s5)\r
335         mthi            s0, $ac2\r
336         lw                      s0, 132(s5)\r
337         mtlo            s0, $ac2\r
338 \r
339         lw                      s0, 144(s5)\r
340         mthi            s0, $ac3\r
341         lw                      s0, 140(s5)\r
342         mtlo            s0, $ac3\r
343 \r
344         lw                      s0, 148(s5)\r
345         wrdsp           s0\r
346 \r
347         lw                      s0, 8(s5)\r
348         mtlo            s0, $ac0\r
349         lw                      s0, 12(s5)\r
350         mthi            s0, $ac0\r
351 \r
352         lw                      $1, 16(s5)\r
353         lw                      s0, 20(s5)\r
354         lw                      s1, 24(s5)\r
355         lw                      s2, 28(s5)\r
356         lw                      s3, 32(s5)\r
357         lw                      s4, 36(s5)\r
358 \r
359         /* s5 is loaded later. */\r
360         lw                      s6, 44(s5)\r
361         lw                      s7, 48(s5)\r
362         lw                      v0, 52(s5)\r
363         lw                      v1, 56(s5)\r
364         lw                      a0, 60(s5)\r
365         lw                      a1, 64(s5)\r
366         lw                      a2, 68(s5)\r
367         lw                      a3, 72(s5)\r
368         lw                      t0, 76(s5)\r
369         lw                      t1, 80(s5)\r
370         lw                      t2, 84(s5)\r
371         lw                      t3, 88(s5)\r
372         lw                      t4, 92(s5)\r
373         lw                      t5, 96(s5)\r
374         lw                      t6, 100(s5)\r
375         lw                      t7, 104(s5)\r
376         lw                      t8, 108(s5)\r
377         lw                      t9, 112(s5)\r
378         lw                      s8, 116(s5)\r
379         lw                      ra, 120(s5)\r
380 \r
381         /* Protect access to the k registers, and others. */\r
382         di\r
383         ehb\r
384 \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
388         sw                      zero, 0(k0)\r
389 \r
390         /* Switch back to use the real stack pointer. */\r
391         add                     sp, zero, s5\r
392 \r
393         /* Restore the real s5 value. */\r
394         lw                      s5, 40(sp)\r
395 \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
399 \r
400         /* Remove stack frame. */\r
401         addiu           sp, sp, portCONTEXT_SIZE\r
402 \r
403         mtc0            k1, _CP0_STATUS\r
404         mtc0            k0, _CP0_EPC\r
405         ehb\r
406         eret\r
407         nop\r
408 \r
409         .end            vPortYieldISR\r
410 \r
411 \r
412 \r