]> begriffs open source - cmsis-freertos/blob - Source/portable/MPLAB/PIC32MEC14xx/port_asm.S
Correct memory allocation and access in osMemoryPoolNew (#142)
[cmsis-freertos] / Source / portable / MPLAB / PIC32MEC14xx / port_asm.S
1 /*
2  * FreeRTOS Kernel V11.2.0
3  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4  *
5  * SPDX-License-Identifier: MIT
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy of
8  * this software and associated documentation files (the "Software"), to deal in
9  * the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11  * the Software, and to permit persons to whom the Software is furnished to do so,
12  * subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in all
15  * copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * https://www.FreeRTOS.org
25  * https://github.com/FreeRTOS
26  *
27  */
28
29 /* FreeRTOS includes. */
30 #include "FreeRTOSConfig.h"
31 #include "ISR_Support.h"
32
33 /* Microchip includes. */
34 #include <xc.h>
35 #include <sys/asm.h>
36
37     .extern pxCurrentTCB
38     .extern vTaskSwitchContext
39     .extern vPortIncrementTick
40     .extern xISRStackTop
41
42     PORT_CPP_JTVIC_BASE = 0xBFFFC000
43     PORT_CCP_JTVIC_GIRQ24_SRC = 0xBFFFC100
44
45     .global vPortStartFirstTask .text
46     .global vPortYieldISR .text
47     .global vPortTickInterruptHandler .text
48
49
50 /******************************************************************/
51
52
53 /***************************************************************
54 *  The following is needed to locate the
55 *  vPortTickInterruptHandler function into the correct vector
56 *  MEC14xx - This ISR will only be used if HW timers' interrupts
57 *  in GIRQ23 are disaggregated.
58 *
59 ***************************************************************/
60
61     .set  noreorder
62     .set  noat
63     .set  micromips
64
65     .section .text, code
66     .ent    vPortTickInterruptHandler
67
68 #if configTIMERS_DISAGGREGATED_ISRS == 0
69
70     .globl girq23_isr
71
72 girq23_isr:
73 vPortTickInterruptHandler:
74
75     portSAVE_CONTEXT
76
77     jal     girq23_handler
78     nop
79
80     portRESTORE_CONTEXT
81
82 .end vPortTickInterruptHandler
83
84 #else
85
86     .globl girq23_b4
87
88 girq23_b4:
89 vPortTickInterruptHandler:
90
91     portSAVE_CONTEXT
92
93     jal     vPortIncrementTick
94     nop
95
96     portRESTORE_CONTEXT
97
98 .end vPortTickInterruptHandler
99
100 #endif /* #if configTIMERS_DISAGGREGATED_ISRS == 0 */
101
102 /******************************************************************/
103
104     .set    micromips
105     .set    noreorder
106     .set    noat
107
108     .section .text, code
109     .ent    vPortStartFirstTask
110
111 vPortStartFirstTask:
112
113     /* Simply restore the context of the highest priority task that has
114     been created so far. */
115     portRESTORE_CONTEXT
116
117 .end vPortStartFirstTask
118
119
120
121 /*******************************************************************/
122
123 /***************************************************************
124 *  The following is needed to locate the vPortYieldISR function into the correct
125 * vector.
126 ***************************************************************/
127
128     .set micromips
129     .set noreorder
130     .set noat
131
132     .section .text, code
133
134     .global vPortYieldISR
135
136
137 #if configCPU_DISAGGREGATED_ISRS == 0
138     .global girq24_isr
139     .ent girq24_isr
140 girq24_isr:
141     la      k0, PORT_CPP_JTVIC_BASE
142     lw      k0, 0x10C(k0)
143     andi    k1, k0, 0x2
144     bgtz    k1, vPortYieldISR
145     nop
146
147     portSAVE_CONTEXT
148
149     jal     girq24_b_0_2
150
151     portRESTORE_CONTEXT
152
153     .end girq24_isr
154
155 #else
156     .global girq24_b1
157 girq24_b1:
158 #endif
159         .ent  vPortYieldISR
160 vPortYieldISR:
161
162     /* Make room for the context. First save the current status so it can be
163     manipulated, and the cause and EPC registers so thier original values
164     are captured. */
165     addiu   sp, sp, -portCONTEXT_SIZE
166     mfc0    k1, _CP0_STATUS
167
168     /* Also save s6 and s5 so they can be used.  Any nesting interrupts should
169     maintain the values of these registers across the ISR. */
170     sw      s6, 44(sp)
171     sw      s5, 40(sp)
172     sw      k1, portSTATUS_STACK_LOCATION(sp)
173
174     /* Prepare to re-enable interrupts above the kernel priority. */
175     ins     k1, zero, 10, 7      /* Clear IPL bits 0:6. */
176     ins     k1, zero, 18, 1      /* Clear IPL bit 7  */
177     ori     k1, k1, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 )
178     ins     k1, zero, 1, 4        /* Clear EXL, ERL and UM. */
179
180     /* s5 is used as the frame pointer. */
181     add     s5, zero, sp
182
183     /* Swap to the system stack.  This is not conditional on the nesting
184     count as this interrupt is always the lowest priority and therefore
185     the nesting is always 0. */
186     la      sp, xISRStackTop
187     lw      sp, (sp)
188
189     /* Set the nesting count. */
190     la      k0, uxInterruptNesting
191     addiu   s6, zero, 1
192     sw      s6, 0(k0)
193
194     /* s6 holds the EPC value, this is saved with the rest of the context
195     after interrupts are enabled. */
196     mfc0    s6, _CP0_EPC
197
198     /* Re-enable interrupts above configMAX_SYSCALL_INTERRUPT_PRIORITY. */
199     mtc0    k1, _CP0_STATUS
200
201     /* Save the context into the space just created.  s6 is saved again
202     here as it now contains the EPC value. */
203     sw      ra, 120(s5)
204     sw      s8, 116(s5)
205     sw      t9, 112(s5)
206     sw      t8, 108(s5)
207     sw      t7, 104(s5)
208     sw      t6, 100(s5)
209     sw      t5, 96(s5)
210     sw      t4, 92(s5)
211     sw      t3, 88(s5)
212     sw      t2, 84(s5)
213     sw      t1, 80(s5)
214     sw      t0, 76(s5)
215     sw      a3, 72(s5)
216     sw      a2, 68(s5)
217     sw      a1, 64(s5)
218     sw      a0, 60(s5)
219     sw      v1, 56(s5)
220     sw      v0, 52(s5)
221     sw      s7, 48(s5)
222     sw      s6, portEPC_STACK_LOCATION(s5)
223     /* s5 and s6 has already been saved. */
224     sw      s4, 36(s5)
225     sw      s3, 32(s5)
226     sw      s2, 28(s5)
227     sw      s1, 24(s5)
228     sw      s0, 20(s5)
229     sw      $1, 16(s5)
230
231     /* s7 is used as a scratch register as this should always be saved acro ss
232     nesting interrupts. */
233     mfhi    s7
234     sw      s7, 12(s5)
235     mflo    s7
236     sw      s7, 8(s5)
237
238     /* Save the stack pointer to the task. */
239     la      s7, pxCurrentTCB
240     lw      s7, (s7)
241     sw      s5, (s7)
242
243     /* Set the interrupt mask to the max priority that can use the API.
244     The yield handler will only be called at configKERNEL_INTERRUPT_PRIORITY
245     which is below configMAX_SYSCALL_INTERRUPT_PRIORITY - so this can only
246     ever raise the IPL value and never lower it. */
247     di
248     ehb
249     mfc0    s7, _CP0_STATUS
250     ins     s7, zero, 10, 7
251     ins     s7, zero, 18, 1
252     ori     s6, s7, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 ) | 1
253
254     /* This mtc0 re-enables interrupts, but only above
255     configMAX_SYSCALL_INTERRUPT_PRIORITY. */
256     mtc0    s6, _CP0_STATUS
257     ehb
258
259     /* Clear the software interrupt in the core. */
260     mfc0    s6, _CP0_CAUSE
261     ins     s6, zero, 8, 1
262     mtc0    s6, _CP0_CAUSE
263     ehb
264
265     /* Clear the interrupt in the interrupt controller.
266     MEC14xx GIRQ24 Source bit[1] = 1 to clear */
267     la      s6, PORT_CCP_JTVIC_GIRQ24_SRC
268     addiu   s4, zero, 2
269     sw      s4, (s6)
270     jal     vTaskSwitchContext
271     nop
272
273     /* Clear the interrupt mask again. The saved status value is still in s7 */
274     mtc0    s7, _CP0_STATUS
275     ehb
276
277     /* Restore the stack pointer from the TCB. */
278     la      s0, pxCurrentTCB
279     lw      s0, (s0)
280     lw      s5, (s0)
281
282     /* Restore the rest of the context. */
283     lw      s0, 8(s5)
284     mtlo    s0
285     lw      s0, 12(s5)
286     mthi    s0
287
288     lw      $1, 16(s5)
289     lw      s0, 20(s5)
290     lw      s1, 24(s5)
291     lw      s2, 28(s5)
292     lw      s3, 32(s5)
293     lw      s4, 36(s5)
294
295     /* s5 is loaded later. */
296     lw      s6, 44(s5)
297     lw      s7, 48(s5)
298     lw      v0, 52(s5)
299     lw      v1, 56(s5)
300     lw      a0, 60(s5)
301     lw      a1, 64(s5)
302     lw      a2, 68(s5)
303     lw      a3, 72(s5)
304     lw      t0, 76(s5)
305     lw      t1, 80(s5)
306     lw      t2, 84(s5)
307     lw      t3, 88(s5)
308     lw      t4, 92(s5)
309     lw      t5, 96(s5)
310     lw      t6, 100(s5)
311     lw      t7, 104(s5)
312     lw      t8, 108(s5)
313     lw      t9, 112(s5)
314     lw      s8, 116(s5)
315     lw      ra, 120(s5)
316
317     /* Protect access to the k registers, and others. */
318     di
319     ehb
320
321     /* Set nesting back to zero.  As the lowest priority interrupt this
322     interrupt cannot have nested. */
323     la      k0, uxInterruptNesting
324     sw      zero, 0(k0)
325
326     /* Switch back to use the real stack pointer. */
327     add     sp, zero, s5
328
329     /* Restore the real s5 value. */
330     lw      s5, 40(sp)
331
332     /* Pop the status and epc values. */
333     lw      k1, portSTATUS_STACK_LOCATION(sp)
334     lw      k0, portEPC_STACK_LOCATION(sp)
335
336     /* Remove stack frame. */
337     addiu   sp, sp, portCONTEXT_SIZE
338
339     mtc0    k1, _CP0_STATUS
340     mtc0    k0, _CP0_EPC
341     ehb
342     eret
343     nop
344
345 .end    vPortYieldISR