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