]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/portable/MPLAB/PIC32MX/port_asm.S
Update version number to 9.0.0rc2.
[freertos] / FreeRTOS / Source / portable / MPLAB / PIC32MX / port_asm.S
1 /*\r
2     FreeRTOS V9.0.0rc2 - Copyright (C) 2016 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     This file is part of the FreeRTOS distribution.\r
8 \r
9     FreeRTOS is free software; you can redistribute it and/or modify it under\r
10     the terms of the GNU General Public License (version 2) as published by the\r
11     Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.\r
12 \r
13     ***************************************************************************\r
14     >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
15     >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
16     >>!   obliged to provide the source code for proprietary components     !<<\r
17     >>!   outside of the FreeRTOS kernel.                                   !<<\r
18     ***************************************************************************\r
19 \r
20     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
21     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
22     FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
23     link: http://www.freertos.org/a00114.html\r
24 \r
25     ***************************************************************************\r
26      *                                                                       *\r
27      *    FreeRTOS provides completely free yet professionally developed,    *\r
28      *    robust, strictly quality controlled, supported, and cross          *\r
29      *    platform software that is more than just the market leader, it     *\r
30      *    is the industry's de facto standard.                               *\r
31      *                                                                       *\r
32      *    Help yourself get started quickly while simultaneously helping     *\r
33      *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
34      *    tutorial book, reference manual, or both:                          *\r
35      *    http://www.FreeRTOS.org/Documentation                              *\r
36      *                                                                       *\r
37     ***************************************************************************\r
38 \r
39     http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
40     the FAQ page "My application does not run, what could be wrong?".  Have you\r
41     defined configASSERT()?\r
42 \r
43     http://www.FreeRTOS.org/support - In return for receiving this top quality\r
44     embedded software for free we request you assist our global community by\r
45     participating in the support forum.\r
46 \r
47     http://www.FreeRTOS.org/training - Investing in training allows your team to\r
48     be as productive as possible as early as possible.  Now you can receive\r
49     FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
50     Ltd, and the world's leading authority on the world's leading RTOS.\r
51 \r
52     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
53     including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
54     compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
55 \r
56     http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
57     Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
58 \r
59     http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
60     Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
61     licenses offer ticketed support, indemnification and commercial middleware.\r
62 \r
63     http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
64     engineered and independently SIL3 certified version for use in safety and\r
65     mission critical applications that require provable dependability.\r
66 \r
67     1 tab == 4 spaces!\r
68 */\r
69 \r
70 #include <xc.h>\r
71 #include <sys/asm.h>\r
72 #include "ISR_Support.h"\r
73 \r
74 \r
75         .set    nomips16\r
76         .set    noreorder\r
77 \r
78         .extern pxCurrentTCB\r
79         .extern vTaskSwitchContext\r
80         .extern vPortIncrementTick\r
81         .extern xISRStackTop\r
82 \r
83         .global vPortStartFirstTask\r
84         .global vPortYieldISR\r
85         .global vPortTickInterruptHandler\r
86 \r
87 \r
88 /******************************************************************/\r
89 \r
90         .set            noreorder\r
91         .set            noat\r
92         .ent            vPortTickInterruptHandler\r
93 \r
94 vPortTickInterruptHandler:\r
95 \r
96         portSAVE_CONTEXT\r
97 \r
98         jal             vPortIncrementTick\r
99         nop\r
100 \r
101         portRESTORE_CONTEXT\r
102 \r
103         .end vPortTickInterruptHandler\r
104 \r
105 /******************************************************************/\r
106 \r
107         .set            noreorder\r
108         .set            noat\r
109         .ent            vPortStartFirstTask\r
110 \r
111 vPortStartFirstTask:\r
112 \r
113         /* Simply restore the context of the highest priority task that has been\r
114         created so far. */\r
115         portRESTORE_CONTEXT\r
116 \r
117         .end vPortStartFirstTask\r
118 \r
119 \r
120 \r
121 /*******************************************************************/\r
122 \r
123         .set            noreorder\r
124         .set            noat\r
125         .ent            vPortYieldISR\r
126 \r
127 vPortYieldISR:\r
128 \r
129         /* Make room for the context. First save the current status so it can be\r
130         manipulated. */\r
131         addiu           sp, sp, -portCONTEXT_SIZE\r
132         mfc0            k1, _CP0_STATUS\r
133 \r
134         /* Also save s6 and s5 so they can be used.  Any nesting interrupts should\r
135         maintain the values of these registers across the ISR. */\r
136         sw                      s6, 44(sp)\r
137         sw                      s5, 40(sp)\r
138         sw                      k1, portSTATUS_STACK_LOCATION(sp)\r
139 \r
140         /* Prepare to re-enabled interrupt above the kernel priority. */\r
141         ins             k1, zero, 10, 6\r
142         ori                     k1, k1, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 )\r
143         ins                     k1, zero, 1, 4\r
144 \r
145         /* s5 is used as the frame pointer. */\r
146         add                     s5, zero, sp\r
147 \r
148         /* Swap to the system stack.  This is not conditional on the nesting\r
149         count as this interrupt is always the lowest priority and therefore\r
150         the nesting is always 0. */\r
151         la                      sp, xISRStackTop\r
152         lw                      sp, (sp)\r
153 \r
154         /* Set the nesting count. */\r
155         la                      k0, uxInterruptNesting\r
156         addiu           s6, zero, 1\r
157         sw                      s6, 0(k0)\r
158 \r
159         /* s6 holds the EPC value, this is saved with the rest of the context\r
160         after interrupts are enabled. */\r
161         mfc0            s6, _CP0_EPC\r
162 \r
163         /* Re-enable interrupts above configMAX_SYSCALL_INTERRUPT_PRIORITY. */\r
164         mtc0            k1, _CP0_STATUS\r
165 \r
166         /* Save the context into the space just created.  s6 is saved again\r
167         here as it now contains the EPC value. */\r
168         sw                      ra, 120(s5)\r
169         sw                      s8, 116(s5)\r
170         sw                      t9, 112(s5)\r
171         sw                      t8, 108(s5)\r
172         sw                      t7, 104(s5)\r
173         sw                      t6, 100(s5)\r
174         sw                      t5, 96(s5)\r
175         sw                      t4, 92(s5)\r
176         sw                      t3, 88(s5)\r
177         sw                      t2, 84(s5)\r
178         sw                      t1, 80(s5)\r
179         sw                      t0, 76(s5)\r
180         sw                      a3, 72(s5)\r
181         sw                      a2, 68(s5)\r
182         sw                      a1, 64(s5)\r
183         sw                      a0, 60(s5)\r
184         sw                      v1, 56(s5)\r
185         sw                      v0, 52(s5)\r
186         sw                      s7, 48(s5)\r
187         sw                      s6, portEPC_STACK_LOCATION(s5)\r
188         /* s5 and s6 has already been saved. */\r
189         sw                      s4, 36(s5)\r
190         sw                      s3, 32(s5)\r
191         sw                      s2, 28(s5)\r
192         sw                      s1, 24(s5)\r
193         sw                      s0, 20(s5)\r
194         sw                      $1, 16(s5)\r
195 \r
196         /* s7 is used as a scratch register as this should always be saved across\r
197         nesting interrupts. */\r
198         mfhi            s7\r
199         sw                      s7, 12(s5)\r
200         mflo            s7\r
201         sw                      s7, 8(s5)\r
202 \r
203         /* Save the stack pointer to the task. */\r
204         la                      s7, pxCurrentTCB\r
205         lw                      s7, (s7)\r
206         sw                      s5, (s7)\r
207 \r
208         /* Set the interrupt mask to the max priority that can use the API.  The\r
209         yield handler will only be called at configKERNEL_INTERRUPT_PRIORITY which\r
210         is below configMAX_SYSCALL_INTERRUPT_PRIORITY - so this can only ever\r
211         raise the IPL value and never lower it. */\r
212         di\r
213         ehb\r
214         mfc0            s7, _CP0_STATUS\r
215         ins             s7, zero, 10, 6\r
216         ori                     s6, s7, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 ) | 1\r
217 \r
218         /* This mtc0 re-enables interrupts, but only above\r
219         configMAX_SYSCALL_INTERRUPT_PRIORITY. */\r
220         mtc0            s6, _CP0_STATUS\r
221         ehb\r
222 \r
223         /* Clear the software interrupt in the core. */\r
224         mfc0            s6, _CP0_CAUSE\r
225         ins                     s6, zero, 8, 1\r
226         mtc0            s6, _CP0_CAUSE\r
227         ehb\r
228 \r
229         /* Clear the interrupt in the interrupt controller. */\r
230         la                      s6, IFS0CLR\r
231         addiu           s4, zero, 2\r
232         sw                      s4, (s6)\r
233 \r
234         jal                     vTaskSwitchContext\r
235         nop\r
236 \r
237         /* Clear the interrupt mask again.  The saved status value is still in s7. */\r
238         mtc0            s7, _CP0_STATUS\r
239         ehb\r
240 \r
241         /* Restore the stack pointer from the TCB. */\r
242         la                      s0, pxCurrentTCB\r
243         lw                      s0, (s0)\r
244         lw                      s5, (s0)\r
245 \r
246         /* Restore the rest of the context. */\r
247         lw                      s0, 8(s5)\r
248         mtlo            s0\r
249         lw                      s0, 12(s5)\r
250         mthi            s0\r
251         lw                      $1, 16(s5)\r
252         lw                      s0, 20(s5)\r
253         lw                      s1, 24(s5)\r
254         lw                      s2, 28(s5)\r
255         lw                      s3, 32(s5)\r
256         lw                      s4, 36(s5)\r
257         /* s5 is loaded later. */\r
258         lw                      s6, 44(s5)\r
259         lw                      s7, 48(s5)\r
260         lw                      v0, 52(s5)\r
261         lw                      v1, 56(s5)\r
262         lw                      a0, 60(s5)\r
263         lw                      a1, 64(s5)\r
264         lw                      a2, 68(s5)\r
265         lw                      a3, 72(s5)\r
266         lw                      t0, 76(s5)\r
267         lw                      t1, 80(s5)\r
268         lw                      t2, 84(s5)\r
269         lw                      t3, 88(s5)\r
270         lw                      t4, 92(s5)\r
271         lw                      t5, 96(s5)\r
272         lw                      t6, 100(s5)\r
273         lw                      t7, 104(s5)\r
274         lw                      t8, 108(s5)\r
275         lw                      t9, 112(s5)\r
276         lw                      s8, 116(s5)\r
277         lw                      ra, 120(s5)\r
278 \r
279         /* Protect access to the k registers, and others. */\r
280         di\r
281         ehb\r
282 \r
283         /* Set nesting back to zero.  As the lowest priority interrupt this\r
284         interrupt cannot have nested. */\r
285         la                      k0, uxInterruptNesting\r
286         sw                      zero, 0(k0)\r
287 \r
288         /* Switch back to use the real stack pointer. */\r
289         add                     sp, zero, s5\r
290 \r
291         /* Restore the real s5 value. */\r
292         lw                      s5, 40(sp)\r
293 \r
294         /* Pop the status and epc values. */\r
295         lw                      k1, portSTATUS_STACK_LOCATION(sp)\r
296         lw                      k0, portEPC_STACK_LOCATION(sp)\r
297 \r
298         /* Remove stack frame. */\r
299         addiu           sp, sp, portCONTEXT_SIZE\r
300 \r
301         mtc0            k1, _CP0_STATUS\r
302         mtc0            k0, _CP0_EPC\r
303         ehb\r
304         eret\r
305         nop\r
306 \r
307         .end            vPortYieldISR\r
308 \r
309 \r
310 \r