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