]> begriffs open source - freertos/blob - Source/portable/MPLAB/PIC32MX/ISR_Support.h
Prepare for V5.3.0 release.
[freertos] / Source / portable / MPLAB / PIC32MX / ISR_Support.h
1 /*\r
2         FreeRTOS.org V5.3.0 - Copyright (C) 2003-2009 Richard Barry.\r
3 \r
4         This file is part of the FreeRTOS.org distribution.\r
5 \r
6         FreeRTOS.org is free software; you can redistribute it and/or modify it\r
7         under the terms of the GNU General Public License (version 2) as published\r
8         by the Free Software Foundation and modified by the FreeRTOS exception.\r
9         **NOTE** The exception to the GPL is included to allow you to distribute a\r
10         combined work that includes FreeRTOS.org without being obliged to provide\r
11         the source code for any proprietary components.  Alternative commercial\r
12         license and support terms are also available upon request.  See the \r
13         licensing section of http://www.FreeRTOS.org for full details.\r
14 \r
15         FreeRTOS.org is distributed in the hope that it will be useful, but WITHOUT\r
16         ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
17         FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
18         more details.\r
19 \r
20         You should have received a copy of the GNU General Public License along\r
21         with FreeRTOS.org; if not, write to the Free Software Foundation, Inc., 59\r
22         Temple Place, Suite 330, Boston, MA  02111-1307  USA.\r
23 \r
24 \r
25         ***************************************************************************\r
26         *                                                                         *\r
27         * Get the FreeRTOS eBook!  See http://www.FreeRTOS.org/Documentation      *\r
28         *                                                                         *\r
29         * This is a concise, step by step, 'hands on' guide that describes both   *\r
30         * general multitasking concepts and FreeRTOS specifics. It presents and   *\r
31         * explains numerous examples that are written using the FreeRTOS API.     *\r
32         * Full source code for all the examples is provided in an accompanying    *\r
33         * .zip file.                                                              *\r
34         *                                                                         *\r
35         ***************************************************************************\r
36 \r
37         1 tab == 4 spaces!\r
38 \r
39         Please ensure to read the configuration and relevant port sections of the\r
40         online documentation.\r
41 \r
42         http://www.FreeRTOS.org - Documentation, latest information, license and\r
43         contact details.\r
44 \r
45         http://www.SafeRTOS.com - A version that is certified for use in safety\r
46         critical systems.\r
47 \r
48         http://www.OpenRTOS.com - Commercial support, development, porting,\r
49         licensing and training services.\r
50 */\r
51 \r
52 #include "FreeRTOSConfig.h"\r
53 \r
54 #define portCONTEXT_SIZE 132\r
55 #define portEPC_STACK_LOCATION  124\r
56 #define portSTATUS_STACK_LOCATION 128\r
57 \r
58 /******************************************************************/    \r
59 .macro  portSAVE_CONTEXT\r
60 \r
61         /* Make room for the context. First save the current status so we can \r
62         manipulate it, and the cause and EPC registers so we capture their \r
63         original values in case of interrupt nesting. */\r
64         mfc0            k0, _CP0_CAUSE\r
65         addiu           sp,     sp, -portCONTEXT_SIZE\r
66         mfc0            k1, _CP0_STATUS\r
67 \r
68         /* Also save s6 and s5 so we can use them during this interrupt.  Any\r
69         nesting interrupts should maintain the values of these registers\r
70         across the ISR. */\r
71         sw                      s6, 44(sp)\r
72         sw                      s5, 40(sp)\r
73         sw                      k1, portSTATUS_STACK_LOCATION(sp)\r
74 \r
75         /* Enable interrupts above the current priority. */\r
76         srl                     k0, k0, 0xa\r
77         ins             k1, k0, 10, 6\r
78         ins                     k1, zero, 1, 4\r
79 \r
80         /* s5 is used as the frame pointer. */\r
81         add                     s5, zero, sp\r
82 \r
83         /* Check the nesting count value. */\r
84         la                      k0, uxInterruptNesting\r
85         lw                      s6, (k0)\r
86 \r
87         /* If the nesting count is 0 then swap to the the system stack, otherwise\r
88         the system stack is already being used. */\r
89         bne                     s6, zero, .+20\r
90         nop\r
91 \r
92         /* Swap to the system stack. */\r
93         la                      sp, xISRStackTop\r
94         lw                      sp, (sp)\r
95 \r
96         /* Increment and save the nesting count. */\r
97         addiu           s6, s6, 1\r
98         sw                      s6, 0(k0)\r
99 \r
100         /* s6 holds the EPC value, this is saved after interrupts are re-enabled. */\r
101         mfc0            s6, _CP0_EPC\r
102 \r
103         /* Re-enable interrupts. */\r
104         mtc0            k1, _CP0_STATUS\r
105 \r
106         /* Save the context into the space just created.  s6 is saved again\r
107         here as it now contains the EPC value.  No other s registers need be\r
108         saved. */\r
109         sw                      ra,     120(s5)\r
110         sw                      s8, 116(s5)\r
111         sw                      t9, 112(s5)\r
112         sw                      t8,     108(s5)\r
113         sw                      t7,     104(s5)\r
114         sw                      t6, 100(s5)\r
115         sw                      t5, 96(s5)\r
116         sw                      t4, 92(s5)\r
117         sw                      t3, 88(s5)\r
118         sw                      t2, 84(s5)\r
119         sw                      t1, 80(s5)\r
120         sw                      t0, 76(s5)\r
121         sw                      a3, 72(s5)\r
122         sw                      a2, 68(s5)\r
123         sw                      a1, 64(s5)\r
124         sw                      a0, 60(s5)\r
125         sw                      v1, 56(s5)\r
126         sw                      v0, 52(s5)\r
127         sw                      s6, portEPC_STACK_LOCATION(s5)\r
128         sw                      $1, 16(s5)\r
129 \r
130         /* s6 is used as a scratch register. */\r
131         mfhi            s6\r
132         sw                      s6, 12(s5)\r
133         mflo            s6\r
134         sw                      s6, 8(s5)\r
135 \r
136         /* Update the task stack pointer value if nesting is zero. */\r
137         la                      s6, uxInterruptNesting\r
138         lw                      s6, (s6)\r
139         addiu           s6, s6, -1\r
140         bne                     s6, zero, .+20\r
141         nop\r
142 \r
143         /* Save the stack pointer. */\r
144         la                      s6, uxSavedTaskStackPointer\r
145         sw                      s5, (s6)\r
146 \r
147         .endm\r
148         \r
149 /******************************************************************/    \r
150 .macro  portRESTORE_CONTEXT\r
151 \r
152         /* Restore the stack pointer from the TCB.  This is only done if the\r
153         nesting count is 1. */\r
154         la                      s6, uxInterruptNesting\r
155         lw                      s6, (s6)\r
156         addiu           s6, s6, -1\r
157         bne                     s6, zero, .+20\r
158         nop\r
159         la                      s6, uxSavedTaskStackPointer\r
160         lw                      s5, (s6)\r
161         \r
162         /* Restore the context. */\r
163         lw                      s6, 8(s5)\r
164         mtlo            s6\r
165         lw                      s6, 12(s5)\r
166         mthi            s6\r
167         lw                      $1, 16(s5)\r
168         /* s6 is loaded as it was used as a scratch register and therefore saved\r
169         as part of the interrupt context. */\r
170         lw                      s6, 44(s5)\r
171         lw                      v0, 52(s5)\r
172         lw                      v1, 56(s5)\r
173         lw                      a0, 60(s5)\r
174         lw                      a1, 64(s5)\r
175         lw                      a2, 68(s5)\r
176         lw                      a3, 72(s5)\r
177         lw                      t0, 76(s5)\r
178         lw                      t1, 80(s5)\r
179         lw                      t2, 84(s5)\r
180         lw                      t3, 88(s5)\r
181         lw                      t4, 92(s5)\r
182         lw                      t5, 96(s5)\r
183         lw                      t6, 100(s5)\r
184         lw                      t7, 104(s5)\r
185         lw                      t8, 108(s5)\r
186         lw                      t9, 112(s5)\r
187         lw                      s8, 116(s5)\r
188         lw                      ra, 120(s5)\r
189 \r
190         /* Protect access to the k registers, and others. */\r
191         di\r
192 \r
193         /* Decrement the nesting count. */\r
194         la                      k0, uxInterruptNesting\r
195         lw                      k1, (k0)\r
196         addiu           k1, k1, -1\r
197         sw                      k1, 0(k0)\r
198 \r
199         lw                      k0, portSTATUS_STACK_LOCATION(s5)\r
200         lw                      k1, portEPC_STACK_LOCATION(s5)\r
201 \r
202         /* Leave the stack how we found it.  First load sp from s5, then restore\r
203         s5 from the stack. */\r
204         add                     sp, zero, s5\r
205         lw                      s5, 40(sp)\r
206         addiu           sp,     sp,     portCONTEXT_SIZE\r
207 \r
208         mtc0            k0, _CP0_STATUS\r
209         ehb\r
210         mtc0            k1, _CP0_EPC\r
211         eret \r
212         nop\r
213 \r
214         .endm\r
215 \r