|
1 | 1 | /*
|
2 | 2 | * Copyright (c) 2013-2014 Wind River Systems, Inc.
|
| 3 | + * Copyright (c) 2025 STMicroelectronics |
3 | 4 | *
|
4 | 5 | * SPDX-License-Identifier: Apache-2.0
|
5 | 6 | */
|
|
22 | 23 | #include <zephyr/linker/linker-defs.h>
|
23 | 24 | #include <zephyr/cache.h>
|
24 | 25 | #include <zephyr/arch/cache.h>
|
| 26 | +#include <zephyr/arch/arm/cortex_m/scb.h> |
| 27 | + |
| 28 | +/* For historical reasons, in Cortex-M family, CMSIS code calls System Handler Priority |
| 29 | + * register SHP or SHPR. This code defines the name of the register |
| 30 | + * according to the specific Cortex-M variant. |
| 31 | + */ |
| 32 | +#if defined(CONFIG_CPU_CORTEX_M0) || \ |
| 33 | + defined(CONFIG_CPU_CORTEX_M0PLUS) || \ |
| 34 | + defined(CONFIG_CPU_CORTEX_M1) || \ |
| 35 | + defined(CONFIG_CPU_CORTEX_M3) || \ |
| 36 | + defined(CONFIG_CPU_CORTEX_M4) |
| 37 | +#define SHPR_FIELD_NAME SHP |
| 38 | +#else |
| 39 | +#define SHPR_FIELD_NAME SHPR |
| 40 | +#endif |
25 | 41 |
|
26 | 42 | #if defined(CONFIG_CPU_HAS_NXP_SYSMPU)
|
27 | 43 | #include <fsl_sysmpu.h>
|
@@ -151,3 +167,80 @@ void z_arm_init_arch_hw_at_boot(void)
|
151 | 167 | barrier_isync_fence_full();
|
152 | 168 | }
|
153 | 169 | #endif /* CONFIG_INIT_ARCH_HW_AT_BOOT */
|
| 170 | + |
| 171 | +/** |
| 172 | + * @brief Save essential SCB registers into a provided context structure. |
| 173 | + * |
| 174 | + * This function reads the current values of critical System Control Block (SCB) |
| 175 | + * registers that are safe to backup, and stores them into the `context` structure. |
| 176 | + * Access to SCB registers requires atomicity and consistency, so calling code |
| 177 | + * should guarantee that interrupts are disabled. |
| 178 | + * |
| 179 | + * @param context Pointer to an `scb_context` structure where the register |
| 180 | + * values will be stored. Must not be NULL. |
| 181 | + */ |
| 182 | +void z_arm_save_scb_context(struct scb_context *context) |
| 183 | +{ |
| 184 | + __ASSERT_NO_MSG(context != NULL); |
| 185 | + |
| 186 | +#if defined(CONFIG_CPU_CORTEX_M_HAS_VTOR) |
| 187 | + context->vtor = SCB->VTOR; |
| 188 | +#endif |
| 189 | + context->aircr = SCB->AIRCR; |
| 190 | + context->scr = SCB->SCR; |
| 191 | + context->ccr = SCB->CCR; |
| 192 | + |
| 193 | + /* Backup System Handler Priority Registers */ |
| 194 | + __IOM uint32_t *shpr = (__IOM uint32_t *) SCB->SHPR_FIELD_NAME; |
| 195 | + |
| 196 | + for (int i = 0; i < SHPR_SIZE_W; i++) { |
| 197 | + context->shpr[i] = shpr[i]; |
| 198 | + } |
| 199 | + |
| 200 | + context->shcsr = SCB->SHCSR; |
| 201 | +} |
| 202 | + |
| 203 | +/** |
| 204 | + * @brief Restores essential SCB registers from a provided context structure. |
| 205 | + * |
| 206 | + * This function writes the values from the `context` structure back to the |
| 207 | + * respective System Control Block (SCB) registers. Access to SCB registers |
| 208 | + * requires atomicity and consistency, so calling code should guarantee that |
| 209 | + * interrupts are disabled. |
| 210 | + * |
| 211 | + * @warning The ICSR register is NOT restored directly due to its volatile nature |
| 212 | + * and presence of read-only status bits and write-only clear/set bits. |
| 213 | + * Direct restoration can lead to undefined behavior or corrupt interrupt state. |
| 214 | + * If specific ICSR bits need to be managed as part of a context, |
| 215 | + * a separate, highly controlled mechanism should be implemented. |
| 216 | + * |
| 217 | + * @param context Pointer to a `scb_context` structure containing the |
| 218 | + * register values to be restored. Must not be NULL. |
| 219 | + */ |
| 220 | +void z_arm_restore_scb_context(const struct scb_context *context) |
| 221 | +{ |
| 222 | + __ASSERT_NO_MSG(context != NULL); |
| 223 | + |
| 224 | +#if defined(CONFIG_CPU_CORTEX_M_HAS_VTOR) |
| 225 | + /* Restore Vector Table Offset Register first if it was modified. */ |
| 226 | + SCB->VTOR = context->vtor; |
| 227 | +#endif |
| 228 | + /* Restore AIRCR: Must write the VECTKEY (0x05FA) along with the desired bits. |
| 229 | + * Ensure only the relevant modifiable bits are restored. |
| 230 | + */ |
| 231 | + SCB->AIRCR = (context->aircr & ~SCB_AIRCR_VECTKEY_Msk) | |
| 232 | + (0x05FAUL << SCB_AIRCR_VECTKEY_Pos); |
| 233 | + |
| 234 | + SCB->SCR = context->scr; |
| 235 | + SCB->CCR = context->ccr; |
| 236 | + |
| 237 | + /* Restore System Handler Priority Registers */ |
| 238 | + __IOM uint32_t *shpr = (__IOM uint32_t *) SCB->SHPR_FIELD_NAME; |
| 239 | + |
| 240 | + for (int i = 0; i < SHPR_SIZE_W; i++) { |
| 241 | + shpr[i] = context->shpr[i]; |
| 242 | + } |
| 243 | + |
| 244 | + /* Restore SHCSR */ |
| 245 | + SCB->SHCSR = context->shcsr; |
| 246 | +} |
0 commit comments