]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/portable/MPLAB/PIC32MX/port_asm.S
Update FreeRTOS version number to V7.5.3
[freertos] / FreeRTOS / Source / portable / MPLAB / PIC32MX / port_asm.S
1 /*\r
2     FreeRTOS V7.5.3 - Copyright (C) 2013 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 distribute\r
28     >>! a combined work that includes FreeRTOS without being obliged to provide\r
29     >>! the source code for proprietary components outside of the FreeRTOS\r
30     >>! 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, and the cause and EPC registers so thier original values are\r
127         captured. */\r
128         mfc0            k0, _CP0_CAUSE\r
129         addiu           sp,     sp, -portCONTEXT_SIZE\r
130         mfc0            k1, _CP0_STATUS\r
131 \r
132         /* Also save s6 and s5 so we can use them during this interrupt.  Any\r
133         nesting interrupts should maintain the values of these registers\r
134         across the ISR. */\r
135         sw                      s6, 44(sp)\r
136         sw                      s5, 40(sp)\r
137         sw                      k1, portSTATUS_STACK_LOCATION(sp)\r
138 \r
139         /* Interrupts above the kernel priority are going to be re-enabled. */\r
140         srl                     k0, k0, 0xa\r
141         ins             k1, k0, 10, 6\r
142         ins                     k1, zero, 1, 4\r
143 \r
144         /* s5 is used as the frame pointer. */\r
145         add                     s5, zero, sp\r
146 \r
147         /* Swap to the system stack.  This is not conditional on the nesting\r
148         count as this interrupt is always the lowest priority and therefore\r
149         the nesting is always 0. */\r
150         la                      sp, xISRStackTop\r
151         lw                      sp, (sp)\r
152 \r
153         /* Set the nesting count. */\r
154         la                      k0, uxInterruptNesting\r
155         addiu           s6, zero, 1\r
156         sw                      s6, 0(k0)\r
157 \r
158         /* s6 holds the EPC value, this is saved with the rest of the context\r
159         after interrupts are enabled. */\r
160         mfc0            s6, _CP0_EPC\r
161 \r
162         /* Re-enable interrupts. */\r
163         mtc0            k1, _CP0_STATUS\r
164 \r
165         /* Save the context into the space just created.  s6 is saved again\r
166         here as it now contains the EPC value. */\r
167         sw                      ra,     120(s5)\r
168         sw                      s8, 116(s5)\r
169         sw                      t9, 112(s5)\r
170         sw                      t8,     108(s5)\r
171         sw                      t7,     104(s5)\r
172         sw                      t6, 100(s5)\r
173         sw                      t5, 96(s5)\r
174         sw                      t4, 92(s5)\r
175         sw                      t3, 88(s5)\r
176         sw                      t2, 84(s5)\r
177         sw                      t1, 80(s5)\r
178         sw                      t0, 76(s5)\r
179         sw                      a3, 72(s5)\r
180         sw                      a2, 68(s5)\r
181         sw                      a1, 64(s5)\r
182         sw                      a0, 60(s5)\r
183         sw                      v1, 56(s5)\r
184         sw                      v0, 52(s5)\r
185         sw                      s7, 48(s5)\r
186         sw                      s6, portEPC_STACK_LOCATION(s5)\r
187         /* s5 and s6 has already been saved. */\r
188         sw                      s4,     36(s5)\r
189         sw                      s3, 32(s5)\r
190         sw                      s2, 28(s5)\r
191         sw                      s1, 24(s5)\r
192         sw                      s0, 20(s5)\r
193         sw                      $1, 16(s5)\r
194 \r
195         /* s7 is used as a scratch register as this should always be saved across\r
196         nesting interrupts. */\r
197         mfhi            s7\r
198         sw                      s7, 12(s5)\r
199         mflo            s7\r
200         sw                      s7, 8(s5)\r
201 \r
202         /* Save the stack pointer to the task. */\r
203         la                      s7, pxCurrentTCB\r
204         lw                      s7, (s7)\r
205         sw                      s5, (s7)\r
206 \r
207         /* Set the interrupt mask to the max priority that can use the API.  The\r
208         yield handler will only be called at configKERNEL_INTERRUPT_PRIORITY which\r
209         is below configMAX_SYSCALL_INTERRUPT_PRIORITY - so this can only ever\r
210         raise the IPL value and never lower it. */\r
211         di\r
212         mfc0            s7, _CP0_STATUS\r
213         ins             s7, $0, 10, 6\r
214         ori                     s6, s7, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 ) | 1\r
215 \r
216         /* This mtc0 re-enables interrupts, but only above\r
217         configMAX_SYSCALL_INTERRUPT_PRIORITY. */\r
218         mtc0            s6, _CP0_STATUS\r
219 \r
220         /* Clear the software interrupt in the core. */\r
221         mfc0            s6, _CP0_CAUSE\r
222         ins                     s6, zero, 8, 1\r
223         mtc0            s6, _CP0_CAUSE\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 \r
236         /* Restore the stack pointer from the TCB. */\r
237         la                      s0, pxCurrentTCB\r
238         lw                      s0, (s0)\r
239         lw                      s5, (s0)\r
240 \r
241         /* Restore the rest of the context. */\r
242         lw                      s0, 8(s5)\r
243         mtlo            s0\r
244         lw                      s0, 12(s5)\r
245         mthi            s0\r
246         lw                      $1, 16(s5)\r
247         lw                      s0, 20(s5)\r
248         lw                      s1, 24(s5)\r
249         lw                      s2, 28(s5)\r
250         lw                      s3, 32(s5)\r
251         lw                      s4, 36(s5)\r
252         /* s5 is loaded later. */\r
253         lw                      s6, 44(s5)\r
254         lw                      s7, 48(s5)\r
255         lw                      v0, 52(s5)\r
256         lw                      v1, 56(s5)\r
257         lw                      a0, 60(s5)\r
258         lw                      a1, 64(s5)\r
259         lw                      a2, 68(s5)\r
260         lw                      a3, 72(s5)\r
261         lw                      t0, 76(s5)\r
262         lw                      t1, 80(s5)\r
263         lw                      t2, 84(s5)\r
264         lw                      t3, 88(s5)\r
265         lw                      t4, 92(s5)\r
266         lw                      t5, 96(s5)\r
267         lw                      t6, 100(s5)\r
268         lw                      t7, 104(s5)\r
269         lw                      t8, 108(s5)\r
270         lw                      t9, 112(s5)\r
271         lw                      s8, 116(s5)\r
272         lw                      ra, 120(s5)\r
273 \r
274         /* Protect access to the k registers, and others. */\r
275         di\r
276 \r
277         /* Set nesting back to zero.  As the lowest priority interrupt this\r
278         interrupt cannot have nested. */\r
279         la                      k0, uxInterruptNesting\r
280         sw                      zero, 0(k0)\r
281 \r
282         /* Switch back to use the real stack pointer. */\r
283         add                     sp, zero, s5\r
284 \r
285         /* Restore the real s5 value. */\r
286         lw                      s5, 40(sp)\r
287 \r
288         /* Pop the status and epc values. */\r
289         lw                      k1, portSTATUS_STACK_LOCATION(sp)\r
290         lw                      k0, portEPC_STACK_LOCATION(sp)\r
291 \r
292         /* Remove stack frame. */\r
293         addiu           sp,     sp,     portCONTEXT_SIZE\r
294 \r
295         mtc0            k1, _CP0_STATUS\r
296         mtc0            k0, _CP0_EPC\r
297         eret\r
298         nop\r
299 \r
300         .end            vPortYieldISR\r
301 \r
302 \r
303 \r