1 /*
2  * FreeRTOS Kernel V11.1.0
3  * Copyright (C) 2024 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 
29 #ifndef PORTMACRO_ASM_H
30 #define PORTMACRO_ASM_H
31 
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
35 
36 #include "FreeRTOSConfig.h"
37 
38 #ifndef configTOTAL_MPU_REGIONS
39     #error "Set configTOTAL_MPU_REGIONS to the humber of MPU regions in FreeRTOSConfig.h"
40 #elif( configTOTAL_MPU_REGIONS == 12 )
41     #define portMPU_TOTAL_REGIONS ( 12UL )
42 #elif( configTOTAL_MPU_REGIONS == 16 )
43     #define portMPU_TOTAL_REGIONS ( 16UL )
44 #else
45     #error "Set configTOTAL_MPU_REGIONS to the number of MPU regions in FreeRTOSConfig.h"
46 #endif /* configTOTAL_MPU_REGIONS */
47 
48 /*
49  * The application write can disable Floating Point Unit (FPU) support by
50  * setting configENABLE_FPU to 0. Floating point context stored in TCB
51  * comprises of 32 floating point registers (D0-D31) and FPSCR register.
52  * Disabling FPU, therefore, reduces the per-task RAM usage by
53  * ( 32 + 1 ) * 4 = 132 bytes per task.
54  *
55  * BE CAREFUL DISABLING THIS: Certain standard library APIs try to optimize
56  * themselves by using the floating point registers. If the FPU support is
57  * disabled, the use of such APIs may result in memory corruption.
58  */
59 #ifndef configENABLE_FPU
60     #define configENABLE_FPU    1
61 #endif /* configENABLE_FPU */
62 
63 #define portENABLE_FPU configENABLE_FPU
64 
65 /* On the ArmV7-R Architecture the Operating mode of the Processor is set
66  * using the Current Program Status Register (CPSR) Mode bits, [4:0]. The only
67  * unprivileged mode is User Mode.
68  *
69  * Additional information about the Processor Modes can be found here:
70  * https://developer.arm.com/documentation/ddi0406/cb/System-Level-Architecture/The-System-Level-Programmers--Model/ARM-processor-modes-and-ARM-core-registers/ARM-processor-modes?lang=en
71  *
72  */
73 
74 /**
75  * @brief CPSR bits for various processor modes.
76  *
77  * @ingroup Port Privilege
78  */
79 #define USER_MODE   0x10U
80 #define FIQ_MODE    0x11U
81 #define IRQ_MODE    0x12U
82 #define SVC_MODE    0x13U
83 #define MON_MODE    0x16U
84 #define ABT_MODE    0x17U
85 #define HYP_MODE    0x1AU
86 #define UND_MODE    0x1BU
87 #define SYS_MODE    0x1FU
88 
89 /**
90  * @brief Flag used to mark that a FreeRTOS Task is privileged.
91  *
92  * @ingroup Port Privilege
93  */
94 #define portTASK_IS_PRIVILEGED_FLAG   ( 1UL << 1UL )
95 
96 /**
97  * @brief SVC numbers for various scheduler operations.
98  *
99  * @ingroup Scheduler
100  *
101  * @note These value must not be used in mpu_syscall_numbers.h.
102  */
103 #define portSVC_YIELD                 0x0100U
104 #define portSVC_SYSTEM_CALL_EXIT      0x0104U
105 
106 /**
107  * @brief Macros required to manipulate MPU.
108  *
109  * Further information about MPU can be found in Arm's documentation
110  * https://developer.arm.com/documentation/ddi0363/g/System-Control/Register-descriptions/c6--MPU-memory-region-programming-registers
111  *
112  */
113 
114 /* MPU sub-region disable settings. This information is encoded in the MPU
115  * Region Size and Enable Register. */
116 #define portMPU_SUBREGION_0_DISABLE   ( 0x1UL << 8UL )
117 #define portMPU_SUBREGION_1_DISABLE   ( 0x1UL << 9UL )
118 #define portMPU_SUBREGION_2_DISABLE   ( 0x1UL << 10UL )
119 #define portMPU_SUBREGION_3_DISABLE   ( 0x1UL << 11UL )
120 #define portMPU_SUBREGION_4_DISABLE   ( 0x1UL << 12UL )
121 #define portMPU_SUBREGION_5_DISABLE   ( 0x1UL << 13UL )
122 #define portMPU_SUBREGION_6_DISABLE   ( 0x1UL << 14UL )
123 #define portMPU_SUBREGION_7_DISABLE   ( 0x1UL << 15UL )
124 
125 /* Default MPU regions. */
126 #define portFIRST_CONFIGURABLE_REGION ( 0 )
127 #define portLAST_CONFIGURABLE_REGION  ( portMPU_TOTAL_REGIONS - 5UL )
128 #define portSTACK_REGION              ( portMPU_TOTAL_REGIONS - 4UL )
129 #define portUNPRIVILEGED_FLASH_REGION ( portMPU_TOTAL_REGIONS - 3UL )
130 #define portPRIVILEGED_FLASH_REGION   ( portMPU_TOTAL_REGIONS - 2UL )
131 #define portPRIVILEGED_RAM_REGION     ( portMPU_TOTAL_REGIONS - 1UL )
132 #define portNUM_CONFIGURABLE_REGIONS \
133     ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1UL )
134 /* Plus one to make space for the stack region. */
135 #define portTOTAL_NUM_REGIONS_IN_TCB        ( portNUM_CONFIGURABLE_REGIONS + 1UL )
136 
137 /* MPU region sizes. This information is encoded in the MPU Region Size and
138  * Enable Register. */
139 #define portMPU_REGION_SIZE_32B             ( 0x04UL << 1UL )
140 #define portMPU_REGION_SIZE_64B             ( 0x05UL << 1UL )
141 #define portMPU_REGION_SIZE_128B            ( 0x06UL << 1UL )
142 #define portMPU_REGION_SIZE_256B            ( 0x07UL << 1UL )
143 #define portMPU_REGION_SIZE_512B            ( 0x08UL << 1UL )
144 #define portMPU_REGION_SIZE_1KB             ( 0x09UL << 1UL )
145 #define portMPU_REGION_SIZE_2KB             ( 0x0AUL << 1UL )
146 #define portMPU_REGION_SIZE_4KB             ( 0x0BUL << 1UL )
147 #define portMPU_REGION_SIZE_8KB             ( 0x0CUL << 1UL )
148 #define portMPU_REGION_SIZE_16KB            ( 0x0DUL << 1UL )
149 #define portMPU_REGION_SIZE_32KB            ( 0x0EUL << 1UL )
150 #define portMPU_REGION_SIZE_64KB            ( 0x0FUL << 1UL )
151 #define portMPU_REGION_SIZE_128KB           ( 0x10UL << 1UL )
152 #define portMPU_REGION_SIZE_256KB           ( 0x11UL << 1UL )
153 #define portMPU_REGION_SIZE_512KB           ( 0x12UL << 1UL )
154 #define portMPU_REGION_SIZE_1MB             ( 0x13UL << 1UL )
155 #define portMPU_REGION_SIZE_2MB             ( 0x14UL << 1UL )
156 #define portMPU_REGION_SIZE_4MB             ( 0x15UL << 1UL )
157 #define portMPU_REGION_SIZE_8MB             ( 0x16UL << 1UL )
158 #define portMPU_REGION_SIZE_16MB            ( 0x17UL << 1UL )
159 #define portMPU_REGION_SIZE_32MB            ( 0x18UL << 1UL )
160 #define portMPU_REGION_SIZE_64MB            ( 0x19UL << 1UL )
161 #define portMPU_REGION_SIZE_128MB           ( 0x1AUL << 1UL )
162 #define portMPU_REGION_SIZE_256MB           ( 0x1BUL << 1UL )
163 #define portMPU_REGION_SIZE_512MB           ( 0x1CUL << 1UL )
164 #define portMPU_REGION_SIZE_1GB             ( 0x1DUL << 1UL )
165 #define portMPU_REGION_SIZE_2GB             ( 0x1EUL << 1UL )
166 #define portMPU_REGION_SIZE_4GB             ( 0x1FUL << 1UL )
167 
168 /* MPU memory types. This information is encoded in the TEX, S, C and B bits
169  * of the MPU Region Access Control Register. */
170 #define portMPU_REGION_STRONGLY_ORDERED_SHAREABLE  ( 0x00UL ) /* TEX=000, S=NA, C=0, B=0. */
171 #define portMPU_REGION_DEVICE_SHAREABLE            ( 0x01UL ) /* TEX=000, S=NA, C=0, B=1. */
172 #define portMPU_REGION_NORMAL_OIWTNOWA_NONSHARED   ( 0x02UL ) /* TEX=000, S=0, C=1, B=0. */
173 #define portMPU_REGION_NORMAL_OIWTNOWA_SHARED      ( 0x06UL ) /* TEX=000, S=1, C=1, B=0. */
174 #define portMPU_REGION_NORMAL_OIWBNOWA_NONSHARED   ( 0x03UL ) /* TEX=000, S=0, C=1, B=1. */
175 #define portMPU_REGION_NORMAL_OIWBNOWA_SHARED      ( 0x07UL ) /* TEX=000, S=1, C=1, B=1. */
176 #define portMPU_REGION_NORMAL_OINC_NONSHARED       ( 0x08UL ) /* TEX=001, S=0, C=0, B=0. */
177 #define portMPU_REGION_NORMAL_OINC_SHARED          ( 0x0CUL ) /* TEX=001, S=1, C=0, B=0. */
178 #define portMPU_REGION_NORMAL_OIWBWA_NONSHARED     ( 0x0BUL ) /* TEX=001, S=0, C=1, B=1. */
179 #define portMPU_REGION_NORMAL_OIWBWA_SHARED        ( 0x0FUL ) /* TEX=001, S=1, C=1, B=1. */
180 #define portMPU_REGION_DEVICE_NONSHAREABLE         ( 0x10UL ) /* TEX=010, S=NA, C=0, B=0. */
181 
182 /* MPU access permissions. This information is encoded in the XN and AP bits of
183  * the MPU Region Access Control Register. */
184 #define portMPU_REGION_AP_BITMASK                  ( 0x07UL << 8UL )
185 #define portMPU_REGION_XN_BITMASK                  ( 0x01UL << 12UL )
186 
187 #define portMPU_REGION_PRIV_NA_USER_NA             ( 0x00UL << 8UL )
188 #define portMPU_REGION_PRIV_NA_USER_NA_EXEC        ( portMPU_REGION_PRIV_NA_USER_NA ) /* Priv: X, Unpriv: X. */
189 #define portMPU_REGION_PRIV_NA_USER_NA_NOEXEC      ( portMPU_REGION_PRIV_NA_USER_NA | \
190                                                      portMPU_REGION_XN_BITMASK ) /* Priv: No Access, Unpriv: No Access. */
191 
192 #define portMPU_REGION_PRIV_RW_USER_NA             ( 0x01UL << 8UL )
193 #define portMPU_REGION_PRIV_RW_USER_NA_EXEC        ( portMPU_REGION_PRIV_RW_USER_NA ) /* Priv: RWX, Unpriv: X. */
194 #define portMPU_REGION_PRIV_RW_USER_NA_NOEXEC      ( portMPU_REGION_PRIV_RW_USER_NA | \
195                                                      portMPU_REGION_XN_BITMASK ) /* Priv: RW, Unpriv: No access. */
196 
197 #define portMPU_REGION_PRIV_RW_USER_RO             ( 0x02UL << 8UL )
198 #define portMPU_REGION_PRIV_RW_USER_RO_EXEC        ( portMPU_REGION_PRIV_RW_USER_RO ) /* Priv: RWX, Unpriv: RX. */
199 #define portMPU_REGION_PRIV_RW_USER_RO_NOEXEC      ( portMPU_REGION_PRIV_RW_USER_RO | \
200                                                      portMPU_REGION_XN_BITMASK ) /* Priv: RW, Unpriv: R. */
201 
202 #define portMPU_REGION_PRIV_RW_USER_RW             ( 0x03UL << 8UL )
203 #define portMPU_REGION_PRIV_RW_USER_RW_EXEC        ( portMPU_REGION_PRIV_RW_USER_RW ) /* Priv: RWX, Unpriv: RWX. */
204 #define portMPU_REGION_PRIV_RW_USER_RW_NOEXEC      ( portMPU_REGION_PRIV_RW_USER_RW | \
205                                                      portMPU_REGION_XN_BITMASK ) /* Priv: RW, Unpriv: RW. */
206 
207 #define portMPU_REGION_PRIV_RO_USER_NA             ( 0x05UL << 8UL )
208 #define portMPU_REGION_PRIV_RO_USER_NA_EXEC        ( portMPU_REGION_PRIV_RO_USER_NA ) /* Priv: RX, Unpriv: X. */
209 #define portMPU_REGION_PRIV_RO_USER_NA_NOEXEC      ( portMPU_REGION_PRIV_RO_USER_NA | \
210                                                      portMPU_REGION_XN_BITMASK ) /* Priv: R, Unpriv: No access. */
211 
212 #define portMPU_REGION_PRIV_RO_USER_RO             ( 0x06UL << 8UL )
213 #define portMPU_REGION_PRIV_RO_USER_RO_EXEC        ( portMPU_REGION_PRIV_RO_USER_RO ) /* Priv: RX, Unpriv: RX. */
214 #define portMPU_REGION_PRIV_RO_USER_RO_NOEXEC      ( portMPU_REGION_PRIV_RO_USER_RO | \
215                                                      portMPU_REGION_XN_BITMASK ) /* Priv: R, Unpriv: R. */
216 
217 /* MPU region management. */
218 #define portMPU_REGION_EXECUTE_NEVER               ( 0x01UL << 12UL )
219 #define portMPU_REGION_ENABLE                      ( 0x01UL )
220 
221 /**
222  * @brief The size (in words) of a task context.
223  *
224  * An array of this size is allocated in TCB where a task's context is saved
225  * when it is switched out.
226  *
227  * Information about Floating Point Unit (FPU):
228  * https://developer.arm.com/documentation/den0042/a/Floating-Point
229  *
230  * Additional information related to the Cortex R4-F's FPU Implementation:
231  * https://developer.arm.com/documentation/ddi0363/e/fpu-programmer-s-model
232  *
233  * Additional information related to the Cortex R5-F's FPU Implementation:
234  * https://developer.arm.com/documentation/ddi0460/d/FPU-Programmers-Model
235  *
236  * Additional information related to the ArmV7-R CPSR:
237  * https://developer.arm.com/documentation/ddi0406/cb/Application-Level-Architecture/Application-Level-Programmers--Model/The-Application-Program-Status-Register--APSR-?lang=en
238  *
239  * Additional information related to the GPRs:
240  * https://developer.arm.com/documentation/ddi0406/cb/System-Level-Architecture/The-System-Level-Programmers--Model/ARM-processor-modes-and-ARM-core-registers/ARM-core-registers?lang=en
241  *
242  */
243 
244 #if( portENABLE_FPU == 1 )
245     /*
246      * +-------------------+-------+----------+--------+----------+----------+----------+------+
247      * | ulCriticalNesting | FPSCR |  S0-S31  | R0-R12 | SP (R13) | LR (R14) | PC (R15) | CPSR |
248      * +-------------------+-------+----------+--------+----------+----------+----------+------+
249      *
250      * <------------------><------><---------><--------><---------><--------><----------><----->
251      *           1            1        32         13         1         1          1        1
252      */
253     #define CONTEXT_SIZE 51U
254 #else
255     /*
256      * +-------------------+--------+----------+----------+----------+------+
257      * | ulCriticalNesting | R0-R12 | SP (R13) | LR (R14) | PC (R15) | CPSR |
258      * +-------------------+--------+----------+----------+----------+------+
259      *
260      * <------------------><--------><---------><--------><----------><----->
261      *           1             13         1         1          1        1
262      */
263     #define CONTEXT_SIZE 18U
264 #endif /* CONTEXT_SIZE */
265 
266 /**
267  * @brief Offset of xSystemCallStackInfo from the start of a TCB.
268  */
269 #define portSYSTEM_CALL_INFO_OFFSET             \
270     ( ( 1U /* pxTopOfStack. */ +                \
271         ( portTOTAL_NUM_REGIONS_IN_TCB * 3U ) + \
272         1U /* ulTaskFlags. */                   \
273       ) * 4U )
274 
275 #ifdef __cplusplus
276 } /* extern C */
277 #endif
278 
279 #endif /* PORTMACRO_ASM_H */
280