]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/portable/MPLAB/PIC32MX/port_asm.S
Update version number to 8.1.2 after moving the defaulting of configUSE_PORT_OPTIMISE...
[freertos] / FreeRTOS / Source / portable / MPLAB / PIC32MX / 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 "ISR_Support.h"\r
69 \r
70 \r
71         .set    nomips16\r
72         .set    noreorder\r
73 \r
74         .extern pxCurrentTCB\r
75         .extern vTaskSwitchContext\r
76         .extern vPortIncrementTick\r
77         .extern xISRStackTop\r
78 \r
79         .global vPortStartFirstTask\r
80         .global vPortYieldISR\r
81         .global vPortTickInterruptHandler\r
82 \r
83 \r
84 /******************************************************************/\r
85 \r
86         .set            noreorder\r
87         .set            noat\r
88         .ent            vPortTickInterruptHandler\r
89 \r
90 vPortTickInterruptHandler:\r
91 \r
92         portSAVE_CONTEXT\r
93 \r
94         jal             vPortIncrementTick\r
95         nop\r
96 \r
97         portRESTORE_CONTEXT\r
98 \r
99         .end vPortTickInterruptHandler\r
100 \r
101 /******************************************************************/\r
102 \r
103         .set            noreorder\r
104         .set            noat\r
105         .ent            vPortStartFirstTask\r
106 \r
107 vPortStartFirstTask:\r
108 \r
109         /* Simply restore the context of the highest priority task that has been\r
110         created so far. */\r
111         portRESTORE_CONTEXT\r
112 \r
113         .end vPortStartFirstTask\r
114 \r
115 \r
116 \r
117 /*******************************************************************/\r
118 \r
119         .set            noreorder\r
120         .set            noat\r
121         .ent            vPortYieldISR\r
122 \r
123 vPortYieldISR:\r
124 \r
125         /* Make room for the context. First save the current status so it can be\r
126         manipulated. */\r
127         addiu           sp, sp, -portCONTEXT_SIZE\r
128         mfc0            k1, _CP0_STATUS\r
129 \r
130         /* Also save s6 and s5 so they can be used.  Any nesting interrupts should\r
131         maintain the values of these registers across the ISR. */\r
132         sw                      s6, 44(sp)\r
133         sw                      s5, 40(sp)\r
134         sw                      k1, portSTATUS_STACK_LOCATION(sp)\r
135 \r
136         /* Prepare to re-enabled interrupt above the kernel priority. */\r
137         ins             k1, zero, 10, 6\r
138         ori                     k1, k1, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 )\r
139         ins                     k1, zero, 1, 4\r
140 \r
141         /* s5 is used as the frame pointer. */\r
142         add                     s5, zero, sp\r
143 \r
144         /* Swap to the system stack.  This is not conditional on the nesting\r
145         count as this interrupt is always the lowest priority and therefore\r
146         the nesting is always 0. */\r
147         la                      sp, xISRStackTop\r
148         lw                      sp, (sp)\r
149 \r
150         /* Set the nesting count. */\r
151         la                      k0, uxInterruptNesting\r
152         addiu           s6, zero, 1\r
153         sw                      s6, 0(k0)\r
154 \r
155         /* s6 holds the EPC value, this is saved with the rest of the context\r
156         after interrupts are enabled. */\r
157         mfc0            s6, _CP0_EPC\r
158 \r
159         /* Re-enable interrupts above configMAX_SYSCALL_INTERRUPT_PRIORITY. */\r
160         mtc0            k1, _CP0_STATUS\r
161 \r
162         /* Save the context into the space just created.  s6 is saved again\r
163         here as it now contains the EPC value. */\r
164         sw                      ra, 120(s5)\r
165         sw                      s8, 116(s5)\r
166         sw                      t9, 112(s5)\r
167         sw                      t8, 108(s5)\r
168         sw                      t7, 104(s5)\r
169         sw                      t6, 100(s5)\r
170         sw                      t5, 96(s5)\r
171         sw                      t4, 92(s5)\r
172         sw                      t3, 88(s5)\r
173         sw                      t2, 84(s5)\r
174         sw                      t1, 80(s5)\r
175         sw                      t0, 76(s5)\r
176         sw                      a3, 72(s5)\r
177         sw                      a2, 68(s5)\r
178         sw                      a1, 64(s5)\r
179         sw                      a0, 60(s5)\r
180         sw                      v1, 56(s5)\r
181         sw                      v0, 52(s5)\r
182         sw                      s7, 48(s5)\r
183         sw                      s6, portEPC_STACK_LOCATION(s5)\r
184         /* s5 and s6 has already been saved. */\r
185         sw                      s4, 36(s5)\r
186         sw                      s3, 32(s5)\r
187         sw                      s2, 28(s5)\r
188         sw                      s1, 24(s5)\r
189         sw                      s0, 20(s5)\r
190         sw                      $1, 16(s5)\r
191 \r
192         /* s7 is used as a scratch register as this should always be saved across\r
193         nesting interrupts. */\r
194         mfhi            s7\r
195         sw                      s7, 12(s5)\r
196         mflo            s7\r
197         sw                      s7, 8(s5)\r
198 \r
199         /* Save the stack pointer to the task. */\r
200         la                      s7, pxCurrentTCB\r
201         lw                      s7, (s7)\r
202         sw                      s5, (s7)\r
203 \r
204         /* Set the interrupt mask to the max priority that can use the API.  The\r
205         yield handler will only be called at configKERNEL_INTERRUPT_PRIORITY which\r
206         is below configMAX_SYSCALL_INTERRUPT_PRIORITY - so this can only ever\r
207         raise the IPL value and never lower it. */\r
208         di\r
209         ehb\r
210         mfc0            s7, _CP0_STATUS\r
211         ins             s7, zero, 10, 6\r
212         ori                     s6, s7, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 ) | 1\r
213 \r
214         /* This mtc0 re-enables interrupts, but only above\r
215         configMAX_SYSCALL_INTERRUPT_PRIORITY. */\r
216         mtc0            s6, _CP0_STATUS\r
217         ehb\r
218 \r
219         /* Clear the software interrupt in the core. */\r
220         mfc0            s6, _CP0_CAUSE\r
221         ins                     s6, zero, 8, 1\r
222         mtc0            s6, _CP0_CAUSE\r
223         ehb\r
224 \r
225         /* Clear the interrupt in the interrupt controller. */\r
226         la                      s6, IFS0CLR\r
227         addiu           s4, zero, 2\r
228         sw                      s4, (s6)\r
229 \r
230         jal                     vTaskSwitchContext\r
231         nop\r
232 \r
233         /* Clear the interrupt mask again.  The saved status value is still in s7. */\r
234         mtc0            s7, _CP0_STATUS\r
235         ehb\r
236 \r
237         /* Restore the stack pointer from the TCB. */\r
238         la                      s0, pxCurrentTCB\r
239         lw                      s0, (s0)\r
240         lw                      s5, (s0)\r
241 \r
242         /* Restore the rest of the context. */\r
243         lw                      s0, 8(s5)\r
244         mtlo            s0\r
245         lw                      s0, 12(s5)\r
246         mthi            s0\r
247         lw                      $1, 16(s5)\r
248         lw                      s0, 20(s5)\r
249         lw                      s1, 24(s5)\r
250         lw                      s2, 28(s5)\r
251         lw                      s3, 32(s5)\r
252         lw                      s4, 36(s5)\r
253         /* s5 is loaded later. */\r
254         lw                      s6, 44(s5)\r
255         lw                      s7, 48(s5)\r
256         lw                      v0, 52(s5)\r
257         lw                      v1, 56(s5)\r
258         lw                      a0, 60(s5)\r
259         lw                      a1, 64(s5)\r
260         lw                      a2, 68(s5)\r
261         lw                      a3, 72(s5)\r
262         lw                      t0, 76(s5)\r
263         lw                      t1, 80(s5)\r
264         lw                      t2, 84(s5)\r
265         lw                      t3, 88(s5)\r
266         lw                      t4, 92(s5)\r
267         lw                      t5, 96(s5)\r
268         lw                      t6, 100(s5)\r
269         lw                      t7, 104(s5)\r
270         lw                      t8, 108(s5)\r
271         lw                      t9, 112(s5)\r
272         lw                      s8, 116(s5)\r
273         lw                      ra, 120(s5)\r
274 \r
275         /* Protect access to the k registers, and others. */\r
276         di\r
277         ehb\r
278 \r
279         /* Set nesting back to zero.  As the lowest priority interrupt this\r
280         interrupt cannot have nested. */\r
281         la                      k0, uxInterruptNesting\r
282         sw                      zero, 0(k0)\r
283 \r
284         /* Switch back to use the real stack pointer. */\r
285         add                     sp, zero, s5\r
286 \r
287         /* Restore the real s5 value. */\r
288         lw                      s5, 40(sp)\r
289 \r
290         /* Pop the status and epc values. */\r
291         lw                      k1, portSTATUS_STACK_LOCATION(sp)\r
292         lw                      k0, portEPC_STACK_LOCATION(sp)\r
293 \r
294         /* Remove stack frame. */\r
295         addiu           sp, sp, portCONTEXT_SIZE\r
296 \r
297         mtc0            k1, _CP0_STATUS\r
298         mtc0            k0, _CP0_EPC\r
299         ehb\r
300         eret\r
301         nop\r
302 \r
303         .end            vPortYieldISR\r
304 \r
305 \r
306 \r