]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/portable/MPLAB/PIC32MX/ISR_Support.h
d0dcee33f25a1806a4b0490447e4c2929a8e8d80
[freertos] / FreeRTOS / Source / portable / MPLAB / PIC32MX / ISR_Support.h
1 /*\r
2  * FreeRTOS Kernel V10.1.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.\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 /******************************************************************/\r
35 .macro  portSAVE_CONTEXT\r
36 \r
37         /* Make room for the context. First save the current status so it can be\r
38         manipulated, and the cause and EPC registers so their original values are\r
39         captured. */\r
40         mfc0            k0, _CP0_CAUSE\r
41         addiu           sp,     sp, -portCONTEXT_SIZE\r
42         mfc0            k1, _CP0_STATUS\r
43 \r
44         /* Also save s6 and s5 so they can be used.  Any nesting interrupts should\r
45         maintain the values of these registers across the ISR. */\r
46         sw                      s6, 44(sp)\r
47         sw                      s5, 40(sp)\r
48         sw                      k1, portSTATUS_STACK_LOCATION(sp)\r
49 \r
50         /* Prepare to enable interrupts above the current priority. */\r
51         srl                     k0, k0, 0xa\r
52         ins             k1, k0, 10, 6\r
53         ins                     k1, zero, 1, 4\r
54 \r
55         /* s5 is used as the frame pointer. */\r
56         add                     s5, zero, sp\r
57 \r
58         /* Check the nesting count value. */\r
59         la                      k0, uxInterruptNesting\r
60         lw                      s6, (k0)\r
61 \r
62         /* If the nesting count is 0 then swap to the the system stack, otherwise\r
63         the system stack is already being used. */\r
64         bne                     s6, zero, 1f\r
65         nop\r
66 \r
67         /* Swap to the system stack. */\r
68         la                      sp, xISRStackTop\r
69         lw                      sp, (sp)\r
70 \r
71         /* Increment and save the nesting count. */\r
72 1:      addiu           s6, s6, 1\r
73         sw                      s6, 0(k0)\r
74 \r
75         /* s6 holds the EPC value, this is saved after interrupts are re-enabled. */\r
76         mfc0            s6, _CP0_EPC\r
77 \r
78         /* Re-enable interrupts. */\r
79         mtc0            k1, _CP0_STATUS\r
80 \r
81         /* Save the context into the space just created.  s6 is saved again\r
82         here as it now contains the EPC value.  No other s registers need be\r
83         saved. */\r
84         sw                      ra, 120(s5)\r
85         sw                      s8, 116(s5)\r
86         sw                      t9, 112(s5)\r
87         sw                      t8, 108(s5)\r
88         sw                      t7, 104(s5)\r
89         sw                      t6, 100(s5)\r
90         sw                      t5, 96(s5)\r
91         sw                      t4, 92(s5)\r
92         sw                      t3, 88(s5)\r
93         sw                      t2, 84(s5)\r
94         sw                      t1, 80(s5)\r
95         sw                      t0, 76(s5)\r
96         sw                      a3, 72(s5)\r
97         sw                      a2, 68(s5)\r
98         sw                      a1, 64(s5)\r
99         sw                      a0, 60(s5)\r
100         sw                      v1, 56(s5)\r
101         sw                      v0, 52(s5)\r
102         sw                      s6, portEPC_STACK_LOCATION(s5)\r
103         sw                      $1, 16(s5)\r
104 \r
105         /* s6 is used as a scratch register. */\r
106         mfhi            s6\r
107         sw                      s6, 12(s5)\r
108         mflo            s6\r
109         sw                      s6, 8(s5)\r
110 \r
111         /* Update the task stack pointer value if nesting is zero. */\r
112         la                      s6, uxInterruptNesting\r
113         lw                      s6, (s6)\r
114         addiu           s6, s6, -1\r
115         bne                     s6, zero, 1f\r
116         nop\r
117 \r
118         /* Save the stack pointer. */\r
119         la                      s6, uxSavedTaskStackPointer\r
120         sw                      s5, (s6)\r
121 1:\r
122         .endm\r
123 \r
124 /******************************************************************/\r
125 .macro  portRESTORE_CONTEXT\r
126 \r
127         /* Restore the stack pointer from the TCB.  This is only done if the\r
128         nesting count is 1. */\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         la                      s6, uxSavedTaskStackPointer\r
135         lw                      s5, (s6)\r
136 \r
137         /* Restore the context. */\r
138 1:      lw                      s6, 8(s5)\r
139         mtlo            s6\r
140         lw                      s6, 12(s5)\r
141         mthi            s6\r
142         lw                      $1, 16(s5)\r
143         /* s6 is loaded as it was used as a scratch register and therefore saved\r
144         as part of the interrupt context. */\r
145         lw                      s6, 44(s5)\r
146         lw                      v0, 52(s5)\r
147         lw                      v1, 56(s5)\r
148         lw                      a0, 60(s5)\r
149         lw                      a1, 64(s5)\r
150         lw                      a2, 68(s5)\r
151         lw                      a3, 72(s5)\r
152         lw                      t0, 76(s5)\r
153         lw                      t1, 80(s5)\r
154         lw                      t2, 84(s5)\r
155         lw                      t3, 88(s5)\r
156         lw                      t4, 92(s5)\r
157         lw                      t5, 96(s5)\r
158         lw                      t6, 100(s5)\r
159         lw                      t7, 104(s5)\r
160         lw                      t8, 108(s5)\r
161         lw                      t9, 112(s5)\r
162         lw                      s8, 116(s5)\r
163         lw                      ra, 120(s5)\r
164 \r
165         /* Protect access to the k registers, and others. */\r
166         di\r
167         ehb\r
168 \r
169         /* Decrement the nesting count. */\r
170         la                      k0, uxInterruptNesting\r
171         lw                      k1, (k0)\r
172         addiu           k1, k1, -1\r
173         sw                      k1, 0(k0)\r
174 \r
175         lw                      k0, portSTATUS_STACK_LOCATION(s5)\r
176         lw                      k1, portEPC_STACK_LOCATION(s5)\r
177 \r
178         /* Leave the stack in its original state.  First load sp from s5, then\r
179         restore s5 from the stack. */\r
180         add                     sp, zero, s5\r
181         lw                      s5, 40(sp)\r
182         addiu           sp, sp, portCONTEXT_SIZE\r
183 \r
184         mtc0            k0, _CP0_STATUS\r
185         mtc0            k1, _CP0_EPC\r
186         ehb\r
187         eret\r
188         nop\r
189 \r
190         .endm\r
191 \r