]> git.sur5r.net Git - freertos/blob - Source/portable/MPLAB/PIC32MX/port_asm.S
Start to re-arrange files to include FreeRTOS+ in main download.
[freertos] / Source / portable / MPLAB / PIC32MX / port_asm.S
1 /*\r
2     FreeRTOS V7.1.1 - Copyright (C) 2012 Real Time Engineers Ltd.\r
3         \r
4 \r
5     ***************************************************************************\r
6      *                                                                       *\r
7      *    FreeRTOS tutorial books are available in pdf and paperback.        *\r
8      *    Complete, revised, and edited pdf reference manuals are also       *\r
9      *    available.                                                         *\r
10      *                                                                       *\r
11      *    Purchasing FreeRTOS documentation will not only help you, by       *\r
12      *    ensuring you get running as quickly as possible and with an        *\r
13      *    in-depth knowledge of how to use FreeRTOS, it will also help       *\r
14      *    the FreeRTOS project to continue with its mission of providing     *\r
15      *    professional grade, cross platform, de facto standard solutions    *\r
16      *    for microcontrollers - completely free of charge!                  *\r
17      *                                                                       *\r
18      *    >>> See http://www.FreeRTOS.org/Documentation for details. <<<     *\r
19      *                                                                       *\r
20      *    Thank you for using FreeRTOS, and thank you for your support!      *\r
21      *                                                                       *\r
22     ***************************************************************************\r
23 \r
24 \r
25     This file is part of the FreeRTOS distribution.\r
26 \r
27     FreeRTOS is free software; you can redistribute it and/or modify it under\r
28     the terms of the GNU General Public License (version 2) as published by the\r
29     Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
30     >>>NOTE<<< The modification to the GPL is included to allow you to\r
31     distribute a combined work that includes FreeRTOS without being obliged to\r
32     provide the source code for proprietary components outside of the FreeRTOS\r
33     kernel.  FreeRTOS is distributed in the hope that it will be useful, but\r
34     WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
35     or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
36     more details. You should have received a copy of the GNU General Public\r
37     License and the FreeRTOS license exception along with FreeRTOS; if not it\r
38     can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
39     by writing to Richard Barry, contact details for whom are available on the\r
40     FreeRTOS WEB site.\r
41 \r
42     1 tab == 4 spaces!\r
43     \r
44     ***************************************************************************\r
45      *                                                                       *\r
46      *    Having a problem?  Start by reading the FAQ "My application does   *\r
47      *    not run, what could be wrong?                                      *\r
48      *                                                                       *\r
49      *    http://www.FreeRTOS.org/FAQHelp.html                               *\r
50      *                                                                       *\r
51     ***************************************************************************\r
52 \r
53     \r
54     http://www.FreeRTOS.org - Documentation, training, latest information, \r
55     license and contact details.\r
56     \r
57     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
58     including FreeRTOS+Trace - an indispensable productivity tool.\r
59 \r
60     Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell \r
61     the code with commercial support, indemnification, and middleware, under \r
62     the OpenRTOS brand: http://www.OpenRTOS.com.  High Integrity Systems also\r
63     provide a safety engineered and independently SIL3 certified version under \r
64     the SafeRTOS brand: http://www.SafeRTOS.com.\r
65 */\r
66  \r
67 #include <p32xxxx.h>\r
68 #include <sys/asm.h>\r
69 #include "ISR_Support.h"\r
70  \r
71 \r
72         .set    nomips16\r
73         .set    noreorder\r
74         \r
75         .extern pxCurrentTCB\r
76         .extern vTaskSwitchContext\r
77         .extern vPortIncrementTick\r
78         .extern xISRStackTop\r
79         \r
80         .global vPortStartFirstTask\r
81         .global vPortYieldISR\r
82         .global vT1InterruptHandler\r
83 \r
84 \r
85 /******************************************************************/\r
86 \r
87         .set            noreorder\r
88         .set            noat\r
89         .ent            vT1InterruptHandler\r
90         \r
91 vT1InterruptHandler:\r
92 \r
93         portSAVE_CONTEXT\r
94 \r
95         jal             vPortIncrementTick\r
96         nop\r
97 \r
98         portRESTORE_CONTEXT\r
99 \r
100         .end vT1InterruptHandler\r
101 \r
102 /******************************************************************/\r
103 \r
104         .set            noreorder\r
105         .set            noat\r
106         .ent            xPortStartScheduler\r
107 \r
108 vPortStartFirstTask:\r
109 \r
110         /* Simply restore the context of the highest priority task that has been\r
111         created so far. */\r
112         portRESTORE_CONTEXT\r
113 \r
114         .end xPortStartScheduler\r
115 \r
116 \r
117 \r
118 /*******************************************************************/\r
119 \r
120         .set            noreorder\r
121         .set            noat\r
122         .ent            vPortYieldISR\r
123 \r
124 vPortYieldISR:\r
125 \r
126         /* Make room for the context. First save the current status so we can \r
127         manipulate it, and the cause and EPC registers so we capture their \r
128         original values in case of interrupt nesting. */\r
129         mfc0            k0, _CP0_CAUSE\r
130         addiu           sp,     sp, -portCONTEXT_SIZE\r
131         mfc0            k1, _CP0_STATUS\r
132 \r
133         /* Also save s6 and s5 so we can use them during this interrupt.  Any\r
134         nesting interrupts should maintain the values of these registers\r
135         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         /* Enable interrupts above the current priority. */\r
141         srl                     k0, k0, 0xa\r
142         ins             k1, k0, 10, 6\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. */\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         mfc0            s7, _CP0_STATUS\r
214         ins             s7, $0, 10, 6\r
215         ori                     s6, s7, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 ) | 1\r
216 \r
217         /* This mtc0 re-enables interrupts, but only above \r
218         configMAX_SYSCALL_INTERRUPT_PRIORITY. */\r
219         mtc0            s6, _CP0_STATUS\r
220 \r
221         /* Clear the software interrupt in the core. */\r
222         mfc0            s6, _CP0_CAUSE\r
223         addiu       s4,zero,-257\r
224         and                     s6, s6, s4\r
225         mtc0            s6, _CP0_CAUSE\r
226 \r
227         /* Clear the interrupt in the interrupt controller. */\r
228         la                      s6, IFS0CLR\r
229         addiu           s4, zero, 2\r
230         sw                      s4, (s6)\r
231 \r
232         jal                     vTaskSwitchContext\r
233         nop\r
234 \r
235         /* Clear the interrupt mask again.  The saved status value is still in s7. */\r
236         mtc0            s7, _CP0_STATUS\r
237 \r
238         /* Restore the stack pointer from the TCB. */\r
239         la                      s0, pxCurrentTCB\r
240         lw                      s0, (s0)\r
241         lw                      s5, (s0)\r
242 \r
243         /* Restore the rest of the context. */\r
244         lw                      s0, 8(s5)\r
245         mtlo            s0\r
246         lw                      s0, 12(s5)\r
247         mthi            s0\r
248         lw                      $1, 16(s5)\r
249         lw                      s0, 20(s5)\r
250         lw                      s1, 24(s5)\r
251         lw                      s2, 28(s5)\r
252         lw                      s3, 32(s5)\r
253         lw                      s4, 36(s5)\r
254         /* s5 is loaded later. */\r
255         lw                      s6, 44(s5)\r
256         lw                      s7, 48(s5)\r
257         lw                      v0, 52(s5)\r
258         lw                      v1, 56(s5)\r
259         lw                      a0, 60(s5)\r
260         lw                      a1, 64(s5)\r
261         lw                      a2, 68(s5)\r
262         lw                      a3, 72(s5)\r
263         lw                      t0, 76(s5)\r
264         lw                      t1, 80(s5)\r
265         lw                      t2, 84(s5)\r
266         lw                      t3, 88(s5)\r
267         lw                      t4, 92(s5)\r
268         lw                      t5, 96(s5)\r
269         lw                      t6, 100(s5)\r
270         lw                      t7, 104(s5)\r
271         lw                      t8, 108(s5)\r
272         lw                      t9, 112(s5)\r
273         lw                      s8, 116(s5)\r
274         lw                      ra, 120(s5)\r
275 \r
276         /* Protect access to the k registers, and others. */\r
277         di\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