]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/portable/IAR/ARM_CM4F_MPU/portasm.s
Add "is inside interrupt" function to MPU ports.
[freertos] / FreeRTOS / Source / portable / IAR / ARM_CM4F_MPU / portasm.s
1 /*\r
2  * FreeRTOS Kernel V10.2.1\r
3  * Copyright (C) 2019 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 /* Including FreeRTOSConfig.h here will cause build errors if the header file\r
28 contains code not understood by the assembler - for example the 'extern' keyword.\r
29 To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so\r
30 the code is included in C files but excluded by the preprocessor in assembly\r
31 files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */\r
32 #include <FreeRTOSConfig.h>\r
33 \r
34         RSEG    CODE:CODE(2)\r
35         thumb\r
36 \r
37         EXTERN pxCurrentTCB\r
38         EXTERN vTaskSwitchContext\r
39         EXTERN vPortSVCHandler_C\r
40 \r
41         PUBLIC xPortPendSVHandler\r
42         PUBLIC vPortSVCHandler\r
43         PUBLIC vPortStartFirstTask\r
44         PUBLIC vPortEnableVFP\r
45         PUBLIC vPortRestoreContextOfFirstTask\r
46         PUBLIC xIsPrivileged\r
47         PUBLIC vResetPrivilege\r
48 \r
49 /*-----------------------------------------------------------*/\r
50 \r
51 xPortPendSVHandler:\r
52         mrs r0, psp\r
53         isb\r
54         /* Get the location of the current TCB. */\r
55         ldr     r3, =pxCurrentTCB\r
56         ldr     r2, [r3]\r
57 \r
58         /* Is the task using the FPU context?  If so, push high vfp registers. */\r
59         tst r14, #0x10\r
60         it eq\r
61         vstmdbeq r0!, {s16-s31}\r
62 \r
63         /* Save the core registers. */\r
64         mrs r1, control\r
65         stmdb r0!, {r1, r4-r11, r14}\r
66 \r
67         /* Save the new top of stack into the first member of the TCB. */\r
68         str r0, [r2]\r
69 \r
70         stmdb sp!, {r0, r3}\r
71         mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY\r
72         msr basepri, r0\r
73         dsb\r
74         isb\r
75         bl vTaskSwitchContext\r
76         mov r0, #0\r
77         msr basepri, r0\r
78         ldmia sp!, {r0, r3}\r
79 \r
80         /* The first item in pxCurrentTCB is the task top of stack. */\r
81         ldr r1, [r3]\r
82         ldr r0, [r1]\r
83         /* Move onto the second item in the TCB... */\r
84         add r1, r1, #4\r
85 \r
86         dmb                                     /* Complete outstanding transfers before disabling MPU. */\r
87         ldr r2, =0xe000ed94     /* MPU_CTRL register. */\r
88         ldr r3, [r2]            /* Read the value of MPU_CTRL. */\r
89         bic r3, r3, #1          /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */\r
90         str r3, [r2]            /* Disable MPU. */\r
91 \r
92         /* Region Base Address register. */\r
93         ldr r2, =0xe000ed9c\r
94         /* Read 4 sets of MPU registers. */\r
95         ldmia r1!, {r4-r11}\r
96         /* Write 4 sets of MPU registers. */\r
97         stmia r2!, {r4-r11}\r
98 \r
99         ldr r2, =0xe000ed94     /* MPU_CTRL register. */\r
100         ldr r3, [r2]            /* Read the value of MPU_CTRL. */\r
101         orr r3, r3, #1          /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */\r
102         str r3, [r2]            /* Enable MPU. */\r
103         dsb                                     /* Force memory writes before continuing. */\r
104 \r
105         /* Pop the registers that are not automatically saved on exception entry. */\r
106         ldmia r0!, {r3-r11, r14}\r
107         msr control, r3\r
108 \r
109         /* Is the task using the FPU context?  If so, pop the high vfp registers\r
110         too. */\r
111         tst r14, #0x10\r
112         it eq\r
113         vldmiaeq r0!, {s16-s31}\r
114 \r
115         msr psp, r0\r
116         isb\r
117 \r
118         bx r14\r
119 \r
120 \r
121 /*-----------------------------------------------------------*/\r
122 \r
123 vPortSVCHandler:\r
124         #ifndef USE_PROCESS_STACK       /* Code should not be required if a main() is using the process stack. */\r
125                 tst lr, #4\r
126                 ite eq\r
127                 mrseq r0, msp\r
128                 mrsne r0, psp\r
129         #else\r
130                 mrs r0, psp\r
131         #endif\r
132                 b vPortSVCHandler_C\r
133 \r
134 /*-----------------------------------------------------------*/\r
135 \r
136 vPortStartFirstTask:\r
137         /* Use the NVIC offset register to locate the stack. */\r
138         ldr r0, =0xE000ED08\r
139         ldr r0, [r0]\r
140         ldr r0, [r0]\r
141         /* Set the msp back to the start of the stack. */\r
142         msr msp, r0\r
143         /* Clear the bit that indicates the FPU is in use in case the FPU was used\r
144         before the scheduler was started - which would otherwise result in the\r
145         unnecessary leaving of space in the SVC stack for lazy saving of FPU\r
146         registers. */\r
147         mov r0, #0\r
148         msr control, r0\r
149         /* Call SVC to start the first task. */\r
150         cpsie i\r
151         cpsie f\r
152         dsb\r
153         isb\r
154         svc 0\r
155 \r
156 /*-----------------------------------------------------------*/\r
157 \r
158 vPortRestoreContextOfFirstTask:\r
159         /* Use the NVIC offset register to locate the stack. */\r
160         ldr r0, =0xE000ED08\r
161         ldr r0, [r0]\r
162         ldr r0, [r0]\r
163         /* Set the msp back to the start of the stack. */\r
164         msr msp, r0\r
165         /* Restore the context. */\r
166         ldr     r3, =pxCurrentTCB\r
167         ldr r1, [r3]\r
168         /* The first item in the TCB is the task top of stack. */\r
169         ldr r0, [r1]\r
170         /* Move onto the second item in the TCB... */\r
171         add r1, r1, #4\r
172 \r
173         dmb                                     /* Complete outstanding transfers before disabling MPU. */\r
174         ldr r2, =0xe000ed94     /* MPU_CTRL register. */\r
175         ldr r3, [r2]            /* Read the value of MPU_CTRL. */\r
176         bic r3, r3, #1          /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */\r
177         str r3, [r2]            /* Disable MPU. */\r
178 \r
179         /* Region Base Address register. */\r
180         ldr r2, =0xe000ed9c\r
181         /* Read 4 sets of MPU registers. */\r
182         ldmia r1!, {r4-r11}\r
183         /* Write 4 sets of MPU registers. */\r
184         stmia r2!, {r4-r11}\r
185 \r
186         ldr r2, =0xe000ed94     /* MPU_CTRL register. */\r
187         ldr r3, [r2]            /* Read the value of MPU_CTRL. */\r
188         orr r3, r3, #1          /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */\r
189         str r3, [r2]            /* Enable MPU. */\r
190         dsb                                     /* Force memory writes before continuing. */\r
191 \r
192         /* Pop the registers that are not automatically saved on exception entry. */\r
193         ldmia r0!, {r3-r11, r14}\r
194         msr control, r3\r
195         /* Restore the task stack pointer. */\r
196         msr psp, r0\r
197         mov r0, #0\r
198         msr     basepri, r0\r
199         bx r14\r
200 \r
201 /*-----------------------------------------------------------*/\r
202 \r
203 vPortEnableVFP:\r
204         /* The FPU enable bits are in the CPACR. */\r
205         ldr.w r0, =0xE000ED88\r
206         ldr     r1, [r0]\r
207 \r
208         /* Enable CP10 and CP11 coprocessors, then save back. */\r
209         orr     r1, r1, #( 0xf << 20 )\r
210         str r1, [r0]\r
211         bx      r14\r
212 \r
213 /*-----------------------------------------------------------*/\r
214 \r
215 xIsPrivileged:\r
216         mrs r0, control         /* r0 = CONTROL. */\r
217         tst r0, #1                      /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */\r
218         ite ne\r
219         movne r0, #0            /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */\r
220         moveq r0, #1            /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */\r
221         bx lr                           /* Return. */\r
222 /*-----------------------------------------------------------*/\r
223 \r
224 vResetPrivilege:\r
225         mrs r0, control         /* r0 = CONTROL. */\r
226         orr r0, r0, #1          /* r0 = r0 | 1. */\r
227         msr control, r0         /* CONTROL = r0. */\r
228         bx lr                           /* Return to the caller. */\r
229 /*-----------------------------------------------------------*/\r
230 \r
231         END\r