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