]> begriffs open source - cmsis-freertos/blob - Source/portable/IAR/ARM_CM4F_MPU/portasm.s
Updated pack to FreeRTOS 10.4.4
[cmsis-freertos] / Source / portable / IAR / ARM_CM4F_MPU / portasm.s
1 /*
2  * FreeRTOS Kernel V10.4.4
3  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * SPDX-License-Identifier: MIT
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy of
8  * this software and associated documentation files (the "Software"), to deal in
9  * the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11  * the Software, and to permit persons to whom the Software is furnished to do so,
12  * subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in all
15  * copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * https://www.FreeRTOS.org
25  * https://github.com/FreeRTOS
26  *
27  */
28 /* Including FreeRTOSConfig.h here will cause build errors if the header file
29 contains code not understood by the assembler - for example the 'extern' keyword.
30 To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so
31 the code is included in C files but excluded by the preprocessor in assembly
32 files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */
33 #include <FreeRTOSConfig.h>
34
35         RSEG    CODE:CODE(2)
36         thumb
37
38         EXTERN pxCurrentTCB
39         EXTERN vTaskSwitchContext
40         EXTERN vPortSVCHandler_C
41
42         PUBLIC xPortPendSVHandler
43         PUBLIC vPortSVCHandler
44         PUBLIC vPortStartFirstTask
45         PUBLIC vPortEnableVFP
46         PUBLIC vPortRestoreContextOfFirstTask
47         PUBLIC xIsPrivileged
48         PUBLIC vResetPrivilege
49
50 /*-----------------------------------------------------------*/
51
52 xPortPendSVHandler:
53         mrs r0, psp
54         isb
55         /* Get the location of the current TCB. */
56         ldr     r3, =pxCurrentTCB
57         ldr     r2, [r3]
58
59         /* Is the task using the FPU context?  If so, push high vfp registers. */
60         tst r14, #0x10
61         it eq
62         vstmdbeq r0!, {s16-s31}
63
64         /* Save the core registers. */
65         mrs r1, control
66         stmdb r0!, {r1, r4-r11, r14}
67
68         /* Save the new top of stack into the first member of the TCB. */
69         str r0, [r2]
70
71         stmdb sp!, {r0, r3}
72         mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
73         msr basepri, r0
74         dsb
75         isb
76         bl vTaskSwitchContext
77         mov r0, #0
78         msr basepri, r0
79         ldmia sp!, {r0, r3}
80
81         /* The first item in pxCurrentTCB is the task top of stack. */
82         ldr r1, [r3]
83         ldr r0, [r1]
84         /* Move onto the second item in the TCB... */
85         add r1, r1, #4
86
87         dmb                                     /* Complete outstanding transfers before disabling MPU. */
88         ldr r2, =0xe000ed94     /* MPU_CTRL register. */
89         ldr r3, [r2]            /* Read the value of MPU_CTRL. */
90         bic r3, r3, #1          /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */
91         str r3, [r2]            /* Disable MPU. */
92
93         /* Region Base Address register. */
94         ldr r2, =0xe000ed9c
95         /* Read 4 sets of MPU registers [MPU Region # 4 - 7]. */
96         ldmia r1!, {r4-r11}
97         /* Write 4 sets of MPU registers [MPU Region # 4 - 7]. */
98         stmia r2, {r4-r11}
99
100         #ifdef configTOTAL_MPU_REGIONS
101                 #if ( configTOTAL_MPU_REGIONS == 16 )
102                         /* Read 4 sets of MPU registers [MPU Region # 8 - 11]. */
103                         ldmia r1!, {r4-r11}
104                         /* Write 4 sets of MPU registers. [MPU Region # 8 - 11]. */
105                         stmia r2, {r4-r11}
106                         /* Read 4 sets of MPU registers [MPU Region # 12 - 15]. */
107                         ldmia r1!, {r4-r11}
108                         /* Write 4 sets of MPU registers. [MPU Region # 12 - 15]. */
109                         stmia r2, {r4-r11}
110                 #endif /* configTOTAL_MPU_REGIONS == 16. */
111         #endif /* configTOTAL_MPU_REGIONS */
112
113         ldr r2, =0xe000ed94     /* MPU_CTRL register. */
114         ldr r3, [r2]            /* Read the value of MPU_CTRL. */
115         orr r3, r3, #1          /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */
116         str r3, [r2]            /* Enable MPU. */
117         dsb                                     /* Force memory writes before continuing. */
118
119         /* Pop the registers that are not automatically saved on exception entry. */
120         ldmia r0!, {r3-r11, r14}
121         msr control, r3
122
123         /* Is the task using the FPU context?  If so, pop the high vfp registers
124         too. */
125         tst r14, #0x10
126         it eq
127         vldmiaeq r0!, {s16-s31}
128
129         msr psp, r0
130         isb
131
132         bx r14
133
134
135 /*-----------------------------------------------------------*/
136
137 vPortSVCHandler:
138         #ifndef USE_PROCESS_STACK       /* Code should not be required if a main() is using the process stack. */
139                 tst lr, #4
140                 ite eq
141                 mrseq r0, msp
142                 mrsne r0, psp
143         #else
144                 mrs r0, psp
145         #endif
146                 b vPortSVCHandler_C
147
148 /*-----------------------------------------------------------*/
149
150 vPortStartFirstTask:
151         /* Use the NVIC offset register to locate the stack. */
152         ldr r0, =0xE000ED08
153         ldr r0, [r0]
154         ldr r0, [r0]
155         /* Set the msp back to the start of the stack. */
156         msr msp, r0
157         /* Clear the bit that indicates the FPU is in use in case the FPU was used
158         before the scheduler was started - which would otherwise result in the
159         unnecessary leaving of space in the SVC stack for lazy saving of FPU
160         registers. */
161         mov r0, #0
162         msr control, r0
163         /* Call SVC to start the first task. */
164         cpsie i
165         cpsie f
166         dsb
167         isb
168         svc 0
169
170 /*-----------------------------------------------------------*/
171
172 vPortRestoreContextOfFirstTask:
173         /* Use the NVIC offset register to locate the stack. */
174         ldr r0, =0xE000ED08
175         ldr r0, [r0]
176         ldr r0, [r0]
177         /* Set the msp back to the start of the stack. */
178         msr msp, r0
179         /* Restore the context. */
180         ldr     r3, =pxCurrentTCB
181         ldr r1, [r3]
182         /* The first item in the TCB is the task top of stack. */
183         ldr r0, [r1]
184         /* Move onto the second item in the TCB... */
185         add r1, r1, #4
186
187         dmb                                     /* Complete outstanding transfers before disabling MPU. */
188         ldr r2, =0xe000ed94     /* MPU_CTRL register. */
189         ldr r3, [r2]            /* Read the value of MPU_CTRL. */
190         bic r3, r3, #1          /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */
191         str r3, [r2]            /* Disable MPU. */
192
193         /* Region Base Address register. */
194         ldr r2, =0xe000ed9c
195         /* Read 4 sets of MPU registers [MPU Region # 4 - 7]. */
196         ldmia r1!, {r4-r11}
197         /* Write 4 sets of MPU registers [MPU Region # 4 - 7]. */
198         stmia r2, {r4-r11}
199
200         #ifdef configTOTAL_MPU_REGIONS
201                 #if ( configTOTAL_MPU_REGIONS == 16 )
202                         /* Read 4 sets of MPU registers [MPU Region # 8 - 11]. */
203                         ldmia r1!, {r4-r11}
204                         /* Write 4 sets of MPU registers. [MPU Region # 8 - 11]. */
205                         stmia r2, {r4-r11}
206                         /* Read 4 sets of MPU registers [MPU Region # 12 - 15]. */
207                         ldmia r1!, {r4-r11}
208                         /* Write 4 sets of MPU registers. [MPU Region # 12 - 15]. */
209                         stmia r2, {r4-r11}
210                 #endif /* configTOTAL_MPU_REGIONS == 16. */
211         #endif /* configTOTAL_MPU_REGIONS */
212
213         ldr r2, =0xe000ed94     /* MPU_CTRL register. */
214         ldr r3, [r2]            /* Read the value of MPU_CTRL. */
215         orr r3, r3, #1          /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */
216         str r3, [r2]            /* Enable MPU. */
217         dsb                                     /* Force memory writes before continuing. */
218
219         /* Pop the registers that are not automatically saved on exception entry. */
220         ldmia r0!, {r3-r11, r14}
221         msr control, r3
222         /* Restore the task stack pointer. */
223         msr psp, r0
224         mov r0, #0
225         msr     basepri, r0
226         bx r14
227
228 /*-----------------------------------------------------------*/
229
230 vPortEnableVFP:
231         /* The FPU enable bits are in the CPACR. */
232         ldr.w r0, =0xE000ED88
233         ldr     r1, [r0]
234
235         /* Enable CP10 and CP11 coprocessors, then save back. */
236         orr     r1, r1, #( 0xf << 20 )
237         str r1, [r0]
238         bx      r14
239
240 /*-----------------------------------------------------------*/
241
242 xIsPrivileged:
243         mrs r0, control         /* r0 = CONTROL. */
244         tst r0, #1                      /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
245         ite ne
246         movne r0, #0            /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
247         moveq r0, #1            /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
248         bx lr                           /* Return. */
249 /*-----------------------------------------------------------*/
250
251 vResetPrivilege:
252         mrs r0, control         /* r0 = CONTROL. */
253         orr r0, r0, #1          /* r0 = r0 | 1. */
254         msr control, r0         /* CONTROL = r0. */
255         bx lr                           /* Return to the caller. */
256 /*-----------------------------------------------------------*/
257
258         END