]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/portable/MPLAB/PIC32MEC14xx/ISR_Support.h
727f2dc6db377f5b9fd42c579f9d46a5346dcac9
[freertos] / FreeRTOS / Source / portable / MPLAB / PIC32MEC14xx / ISR_Support.h
1 /*\r
2  * FreeRTOS Kernel V10.0.1\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.\r
14  *\r
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
21  *\r
22  * http://www.FreeRTOS.org\r
23  * http://aws.amazon.com/freertos\r
24  *\r
25  * 1 tab == 4 spaces!\r
26  */\r
27 \r
28 #include "FreeRTOSConfig.h"\r
29 \r
30 #define portCONTEXT_SIZE 132\r
31 #define portEPC_STACK_LOCATION 124\r
32 #define portSTATUS_STACK_LOCATION 128\r
33 \r
34 #ifdef __LANGUAGE_ASSEMBLY__\r
35 \r
36 /******************************************************************/\r
37 .macro  portSAVE_CONTEXT\r
38 \r
39         /* Make room for the context. First save the current status so it can be\r
40         manipulated, and the cause and EPC registers so their original values are\r
41         captured. */\r
42         mfc0    k0, _CP0_CAUSE\r
43         addiu   sp, sp, -portCONTEXT_SIZE\r
44         mfc0    k1, _CP0_STATUS\r
45 \r
46         /* Also save s6 and s5 so they can be used.  Any nesting interrupts should\r
47         maintain the values of these registers across the ISR. */\r
48         sw              s6, 44(sp)\r
49         sw              s5, 40(sp)\r
50         sw              k1, portSTATUS_STACK_LOCATION(sp)\r
51 \r
52         /* Prepare to enable interrupts above the current priority.\r
53         k0 = k0 >> 10. Moves RIPL[17:10] to [7:0] */\r
54         srl             k0, k0, 0xa\r
55 \r
56         /* Insert bit field. 7 bits k0[6:0] to k1[16:10] */\r
57         ins             k1, k0, 10, 7\r
58 \r
59         /* Sets CP0.Status.IPL = CP0.Cause.RIPL\r
60         Copy the MSB of the IPL, but it would be an error if it was set anyway. */\r
61         srl             k0, k0, 0x7\r
62 \r
63         /* MSB of IPL is bit[18] of CP0.Status */\r
64         ins             k1, k0, 18, 1\r
65 \r
66         /* CP0.Status[5:1] = 0 b[5]=Rsvd, b[4]=UM,\r
67            b[3]=Rsvd, b[2]=ERL, b[1]=EXL\r
68            Setting EXL=0 allows higher priority interrupts\r
69            to preempt this handler */\r
70         ins             k1, zero, 1, 4\r
71 \r
72 \r
73         /* s5 is used as the frame pointer. */\r
74         add             s5, zero, sp\r
75 \r
76         /* Check the nesting count value. */\r
77         la              k0, uxInterruptNesting\r
78         lw              s6, (k0)\r
79 \r
80         /* If the nesting count is 0 then swap to the the system stack, otherwise\r
81         the system stack is already being used. */\r
82         bne             s6, zero, 1f\r
83         nop\r
84 \r
85         /* Swap to the system stack. */\r
86         la              sp, xISRStackTop\r
87         lw              sp, (sp)\r
88 \r
89         /* Increment and save the nesting count. */\r
90 1:  addiu   s6, s6, 1\r
91         sw              s6, 0(k0)\r
92 \r
93         /* s6 holds the EPC value, this is saved after interrupts are re-enabled. */\r
94         mfc0    s6, _CP0_EPC\r
95 \r
96         /* Re-enable interrupts. */\r
97         mtc0    k1, _CP0_STATUS\r
98 \r
99         /* Save the context into the space just created.  s6 is saved again\r
100         here as it now contains the EPC value.  No other s registers need be\r
101         saved. */\r
102         sw              ra, 120(s5) /* Return address (RA=R31) */\r
103         sw              s8, 116(s5) /* Frame Pointer (FP=R30) */\r
104         sw              t9, 112(s5)\r
105         sw              t8, 108(s5)\r
106         sw              t7, 104(s5)\r
107         sw              t6, 100(s5)\r
108         sw              t5, 96(s5)\r
109         sw              t4, 92(s5)\r
110         sw              t3, 88(s5)\r
111         sw              t2, 84(s5)\r
112         sw              t1, 80(s5)\r
113         sw              t0, 76(s5)\r
114         sw              a3, 72(s5)\r
115         sw              a2, 68(s5)\r
116         sw              a1, 64(s5)\r
117         sw              a0, 60(s5)\r
118         sw              v1, 56(s5)\r
119         sw              v0, 52(s5)\r
120         sw              s6, portEPC_STACK_LOCATION(s5)\r
121         sw              $1, 16(s5)\r
122 \r
123         /* MEC14xx does not have DSP, removed 7 words */\r
124         mfhi    s6\r
125         sw              s6, 12(s5)\r
126         mflo    s6\r
127         sw              s6, 8(s5)\r
128 \r
129         /* Update the task stack pointer value if nesting is zero. */\r
130         la              s6, uxInterruptNesting\r
131         lw              s6, (s6)\r
132         addiu   s6, s6, -1\r
133         bne             s6, zero, 1f\r
134         nop\r
135 \r
136         /* Save the stack pointer. */\r
137         la              s6, uxSavedTaskStackPointer\r
138         sw              s5, (s6)\r
139 1:\r
140         .endm\r
141 \r
142 /******************************************************************/\r
143 .macro  portRESTORE_CONTEXT\r
144 \r
145         /* Restore the stack pointer from the TCB.  This is only done if the\r
146         nesting count is 1. */\r
147         la              s6, uxInterruptNesting\r
148         lw              s6, (s6)\r
149         addiu   s6, s6, -1\r
150         bne             s6, zero, 1f\r
151         nop\r
152         la              s6, uxSavedTaskStackPointer\r
153         lw              s5, (s6)\r
154 \r
155         /* Restore the context.\r
156         MCHP MEC14xx does not include DSP */\r
157 1:\r
158         lw              s6, 8(s5)\r
159         mtlo    s6\r
160         lw              s6, 12(s5)\r
161         mthi    s6\r
162         lw              $1, 16(s5)\r
163 \r
164         /* s6 is loaded as it was used as a scratch register and therefore saved\r
165         as part of the interrupt context. */\r
166         lw              s6, 44(s5)\r
167         lw              v0, 52(s5)\r
168         lw              v1, 56(s5)\r
169         lw              a0, 60(s5)\r
170         lw              a1, 64(s5)\r
171         lw              a2, 68(s5)\r
172         lw              a3, 72(s5)\r
173         lw              t0, 76(s5)\r
174         lw              t1, 80(s5)\r
175         lw              t2, 84(s5)\r
176         lw              t3, 88(s5)\r
177         lw              t4, 92(s5)\r
178         lw              t5, 96(s5)\r
179         lw              t6, 100(s5)\r
180         lw              t7, 104(s5)\r
181         lw              t8, 108(s5)\r
182         lw              t9, 112(s5)\r
183         lw              s8, 116(s5)\r
184         lw              ra, 120(s5)\r
185 \r
186         /* Protect access to the k registers, and others. */\r
187         di\r
188         ehb\r
189 \r
190         /* Decrement the nesting count. */\r
191         la              k0, uxInterruptNesting\r
192         lw              k1, (k0)\r
193         addiu   k1, k1, -1\r
194         sw              k1, 0(k0)\r
195 \r
196         lw              k0, portSTATUS_STACK_LOCATION(s5)\r
197         lw              k1, portEPC_STACK_LOCATION(s5)\r
198 \r
199         /* Leave the stack in its original state.  First load sp from s5, then\r
200         restore s5 from the stack. */\r
201         add             sp, zero, s5\r
202         lw              s5, 40(sp)\r
203         addiu   sp, sp, portCONTEXT_SIZE\r
204 \r
205         mtc0    k0, _CP0_STATUS\r
206         mtc0    k1, _CP0_EPC\r
207         ehb\r
208         eret\r
209         nop\r
210 \r
211         .endm\r
212 \r
213 #endif /* #ifdef __LANGUAGE_ASSEMBLY__ */\r
214 \r