]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/portable/MPLAB/PIC32MX/port_asm.S
Update to MIT licensed FreeRTOS V10.0.0 - see https://www.freertos.org/History.txt
[freertos] / FreeRTOS / Source / portable / MPLAB / PIC32MX / port_asm.S
1 /*\r
2  * FreeRTOS Kernel V10.0.0\r
3  * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software. If you wish to use our Amazon\r
14  * FreeRTOS name, please do so in a fair use way that does not cause confusion.\r
15  *\r
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
18  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
19  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
20  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
22  *\r
23  * http://www.FreeRTOS.org\r
24  * http://aws.amazon.com/freertos\r
25  *\r
26  * 1 tab == 4 spaces!\r
27  */\r
28 \r
29 #include <xc.h>\r
30 #include <sys/asm.h>\r
31 #include "ISR_Support.h"\r
32 \r
33 \r
34         .set    nomips16\r
35         .set    noreorder\r
36 \r
37         .extern pxCurrentTCB\r
38         .extern vTaskSwitchContext\r
39         .extern vPortIncrementTick\r
40         .extern xISRStackTop\r
41 \r
42         .global vPortStartFirstTask\r
43         .global vPortYieldISR\r
44         .global vPortTickInterruptHandler\r
45 \r
46 \r
47 /******************************************************************/\r
48 \r
49         .set            noreorder\r
50         .set            noat\r
51         .ent            vPortTickInterruptHandler\r
52 \r
53 vPortTickInterruptHandler:\r
54 \r
55         portSAVE_CONTEXT\r
56 \r
57         jal             vPortIncrementTick\r
58         nop\r
59 \r
60         portRESTORE_CONTEXT\r
61 \r
62         .end vPortTickInterruptHandler\r
63 \r
64 /******************************************************************/\r
65 \r
66         .set            noreorder\r
67         .set            noat\r
68         .ent            vPortStartFirstTask\r
69 \r
70 vPortStartFirstTask:\r
71 \r
72         /* Simply restore the context of the highest priority task that has been\r
73         created so far. */\r
74         portRESTORE_CONTEXT\r
75 \r
76         .end vPortStartFirstTask\r
77 \r
78 \r
79 \r
80 /*******************************************************************/\r
81 \r
82         .set            noreorder\r
83         .set            noat\r
84         .ent            vPortYieldISR\r
85 \r
86 vPortYieldISR:\r
87 \r
88         /* Make room for the context. First save the current status so it can be\r
89         manipulated. */\r
90         addiu           sp, sp, -portCONTEXT_SIZE\r
91         mfc0            k1, _CP0_STATUS\r
92 \r
93         /* Also save s6 and s5 so they can be used.  Any nesting interrupts should\r
94         maintain the values of these registers across the ISR. */\r
95         sw                      s6, 44(sp)\r
96         sw                      s5, 40(sp)\r
97         sw                      k1, portSTATUS_STACK_LOCATION(sp)\r
98 \r
99         /* Prepare to re-enabled interrupt above the kernel priority. */\r
100         ins             k1, zero, 10, 6\r
101         ori                     k1, k1, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 )\r
102         ins                     k1, zero, 1, 4\r
103 \r
104         /* s5 is used as the frame pointer. */\r
105         add                     s5, zero, sp\r
106 \r
107         /* Swap to the system stack.  This is not conditional on the nesting\r
108         count as this interrupt is always the lowest priority and therefore\r
109         the nesting is always 0. */\r
110         la                      sp, xISRStackTop\r
111         lw                      sp, (sp)\r
112 \r
113         /* Set the nesting count. */\r
114         la                      k0, uxInterruptNesting\r
115         addiu           s6, zero, 1\r
116         sw                      s6, 0(k0)\r
117 \r
118         /* s6 holds the EPC value, this is saved with the rest of the context\r
119         after interrupts are enabled. */\r
120         mfc0            s6, _CP0_EPC\r
121 \r
122         /* Re-enable interrupts above configMAX_SYSCALL_INTERRUPT_PRIORITY. */\r
123         mtc0            k1, _CP0_STATUS\r
124 \r
125         /* Save the context into the space just created.  s6 is saved again\r
126         here as it now contains the EPC value. */\r
127         sw                      ra, 120(s5)\r
128         sw                      s8, 116(s5)\r
129         sw                      t9, 112(s5)\r
130         sw                      t8, 108(s5)\r
131         sw                      t7, 104(s5)\r
132         sw                      t6, 100(s5)\r
133         sw                      t5, 96(s5)\r
134         sw                      t4, 92(s5)\r
135         sw                      t3, 88(s5)\r
136         sw                      t2, 84(s5)\r
137         sw                      t1, 80(s5)\r
138         sw                      t0, 76(s5)\r
139         sw                      a3, 72(s5)\r
140         sw                      a2, 68(s5)\r
141         sw                      a1, 64(s5)\r
142         sw                      a0, 60(s5)\r
143         sw                      v1, 56(s5)\r
144         sw                      v0, 52(s5)\r
145         sw                      s7, 48(s5)\r
146         sw                      s6, portEPC_STACK_LOCATION(s5)\r
147         /* s5 and s6 has already been saved. */\r
148         sw                      s4, 36(s5)\r
149         sw                      s3, 32(s5)\r
150         sw                      s2, 28(s5)\r
151         sw                      s1, 24(s5)\r
152         sw                      s0, 20(s5)\r
153         sw                      $1, 16(s5)\r
154 \r
155         /* s7 is used as a scratch register as this should always be saved across\r
156         nesting interrupts. */\r
157         mfhi            s7\r
158         sw                      s7, 12(s5)\r
159         mflo            s7\r
160         sw                      s7, 8(s5)\r
161 \r
162         /* Save the stack pointer to the task. */\r
163         la                      s7, pxCurrentTCB\r
164         lw                      s7, (s7)\r
165         sw                      s5, (s7)\r
166 \r
167         /* Set the interrupt mask to the max priority that can use the API.  The\r
168         yield handler will only be called at configKERNEL_INTERRUPT_PRIORITY which\r
169         is below configMAX_SYSCALL_INTERRUPT_PRIORITY - so this can only ever\r
170         raise the IPL value and never lower it. */\r
171         di\r
172         ehb\r
173         mfc0            s7, _CP0_STATUS\r
174         ins             s7, zero, 10, 6\r
175         ori                     s6, s7, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 ) | 1\r
176 \r
177         /* This mtc0 re-enables interrupts, but only above\r
178         configMAX_SYSCALL_INTERRUPT_PRIORITY. */\r
179         mtc0            s6, _CP0_STATUS\r
180         ehb\r
181 \r
182         /* Clear the software interrupt in the core. */\r
183         mfc0            s6, _CP0_CAUSE\r
184         ins                     s6, zero, 8, 1\r
185         mtc0            s6, _CP0_CAUSE\r
186         ehb\r
187 \r
188         /* Clear the interrupt in the interrupt controller. */\r
189         la                      s6, IFS0CLR\r
190         addiu           s4, zero, 2\r
191         sw                      s4, (s6)\r
192 \r
193         jal                     vTaskSwitchContext\r
194         nop\r
195 \r
196         /* Clear the interrupt mask again.  The saved status value is still in s7. */\r
197         mtc0            s7, _CP0_STATUS\r
198         ehb\r
199 \r
200         /* Restore the stack pointer from the TCB. */\r
201         la                      s0, pxCurrentTCB\r
202         lw                      s0, (s0)\r
203         lw                      s5, (s0)\r
204 \r
205         /* Restore the rest of the context. */\r
206         lw                      s0, 8(s5)\r
207         mtlo            s0\r
208         lw                      s0, 12(s5)\r
209         mthi            s0\r
210         lw                      $1, 16(s5)\r
211         lw                      s0, 20(s5)\r
212         lw                      s1, 24(s5)\r
213         lw                      s2, 28(s5)\r
214         lw                      s3, 32(s5)\r
215         lw                      s4, 36(s5)\r
216         /* s5 is loaded later. */\r
217         lw                      s6, 44(s5)\r
218         lw                      s7, 48(s5)\r
219         lw                      v0, 52(s5)\r
220         lw                      v1, 56(s5)\r
221         lw                      a0, 60(s5)\r
222         lw                      a1, 64(s5)\r
223         lw                      a2, 68(s5)\r
224         lw                      a3, 72(s5)\r
225         lw                      t0, 76(s5)\r
226         lw                      t1, 80(s5)\r
227         lw                      t2, 84(s5)\r
228         lw                      t3, 88(s5)\r
229         lw                      t4, 92(s5)\r
230         lw                      t5, 96(s5)\r
231         lw                      t6, 100(s5)\r
232         lw                      t7, 104(s5)\r
233         lw                      t8, 108(s5)\r
234         lw                      t9, 112(s5)\r
235         lw                      s8, 116(s5)\r
236         lw                      ra, 120(s5)\r
237 \r
238         /* Protect access to the k registers, and others. */\r
239         di\r
240         ehb\r
241 \r
242         /* Set nesting back to zero.  As the lowest priority interrupt this\r
243         interrupt cannot have nested. */\r
244         la                      k0, uxInterruptNesting\r
245         sw                      zero, 0(k0)\r
246 \r
247         /* Switch back to use the real stack pointer. */\r
248         add                     sp, zero, s5\r
249 \r
250         /* Restore the real s5 value. */\r
251         lw                      s5, 40(sp)\r
252 \r
253         /* Pop the status and epc values. */\r
254         lw                      k1, portSTATUS_STACK_LOCATION(sp)\r
255         lw                      k0, portEPC_STACK_LOCATION(sp)\r
256 \r
257         /* Remove stack frame. */\r
258         addiu           sp, sp, portCONTEXT_SIZE\r
259 \r
260         mtc0            k1, _CP0_STATUS\r
261         mtc0            k0, _CP0_EPC\r
262         ehb\r
263         eret\r
264         nop\r
265 \r
266         .end            vPortYieldISR\r
267 \r
268 \r
269 \r