|
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> |
25 | 27 |
|
26 | 28 | #if defined(CONFIG_CPU_HAS_NXP_SYSMPU)
|
27 | 29 | #include <fsl_sysmpu.h>
|
@@ -151,3 +153,99 @@ void z_arm_init_arch_hw_at_boot(void)
|
151 | 153 | barrier_isync_fence_full();
|
152 | 154 | }
|
153 | 155 | #endif /* CONFIG_INIT_ARCH_HW_AT_BOOT */
|
| 156 | + |
| 157 | +/** |
| 158 | + * @brief Save essential SCB registers into a provided context structure. |
| 159 | + * |
| 160 | + * This function reads the current values of critical System Control Block (SCB) |
| 161 | + * registers that are safe to backup, and stores them into the `context` structure. |
| 162 | + * Access to SCB registers requires atomicity and consistency, so calling code |
| 163 | + * should guarantee that interrupts are disabled. |
| 164 | + * |
| 165 | + * @param context Pointer to an `scb_context` structure where the register |
| 166 | + * values will be stored. Must not be NULL. |
| 167 | + */ |
| 168 | +void z_arm_save_scb_context(struct scb_context *context) |
| 169 | +{ |
| 170 | + __ASSERT_NO_MSG(context != NULL); |
| 171 | + |
| 172 | +#if defined(CONFIG_CPU_CORTEX_M_HAS_VTOR) |
| 173 | + context->vtor = SCB->VTOR; |
| 174 | +#endif |
| 175 | + context->aircr = SCB->AIRCR; |
| 176 | + context->scr = SCB->SCR; |
| 177 | + context->ccr = SCB->CCR; |
| 178 | + |
| 179 | + /* |
| 180 | + * Backup the System Handler Priority Registers. |
| 181 | + * SCB->SHPR is defined as u8[] or u32[] depending |
| 182 | + * on the target Cortex-M core, but it can always |
| 183 | + * be accessed using word-sized reads and writes. |
| 184 | + * Make u32 pointer using explicit cast to allow |
| 185 | + * access on all cores without compiler warnings. |
| 186 | + */ |
| 187 | + volatile uint32_t *shpr = (volatile uint32_t *)SCB->SHPR; |
| 188 | + |
| 189 | + for (int i = 0; i < SHPR_SIZE_W; i++) { |
| 190 | + context->shpr[i] = shpr[i]; |
| 191 | + } |
| 192 | + |
| 193 | + context->shcsr = SCB->SHCSR; |
| 194 | +#if defined(CPACR_PRESENT) |
| 195 | + context->cpacr = SCB->CPACR; |
| 196 | +#endif /* CPACR_PRESENT */ |
| 197 | +} |
| 198 | + |
| 199 | +/** |
| 200 | + * @brief Restores essential SCB registers from a provided context structure. |
| 201 | + * |
| 202 | + * This function writes the values from the `context` structure back to the |
| 203 | + * respective System Control Block (SCB) registers. Access to SCB registers |
| 204 | + * requires atomicity and consistency, so calling code should guarantee that |
| 205 | + * interrupts are disabled. |
| 206 | + * |
| 207 | + * @param context Pointer to a `scb_context` structure containing the |
| 208 | + * register values to be restored. Must not be NULL. |
| 209 | + */ |
| 210 | +void z_arm_restore_scb_context(const struct scb_context *context) |
| 211 | +{ |
| 212 | + __ASSERT_NO_MSG(context != NULL); |
| 213 | + |
| 214 | +#if defined(CONFIG_CPU_CORTEX_M_HAS_VTOR) |
| 215 | + /* Restore VTOR if present on this CPU */ |
| 216 | + SCB->VTOR = context->vtor; |
| 217 | +#endif |
| 218 | + /* Restoring AIRCR requires writing VECTKEY along with desired bits. |
| 219 | + * Mask backed up data to ensure only modifiable bits are restored. |
| 220 | + */ |
| 221 | + SCB->AIRCR = (context->aircr & ~SCB_AIRCR_VECTKEY_Msk) | |
| 222 | + (AIRCR_VECT_KEY_PERMIT_WRITE << SCB_AIRCR_VECTKEY_Pos); |
| 223 | + |
| 224 | + SCB->SCR = context->scr; |
| 225 | + SCB->CCR = context->ccr; |
| 226 | + |
| 227 | + /* Restore System Handler Priority Registers */ |
| 228 | + volatile uint32_t *shpr = (volatile uint32_t *)SCB->SHPR; |
| 229 | + |
| 230 | + for (int i = 0; i < SHPR_SIZE_W; i++) { |
| 231 | + shpr[i] = context->shpr[i]; |
| 232 | + } |
| 233 | + |
| 234 | + /* Restore SHCSR */ |
| 235 | + SCB->SHCSR = context->shcsr; |
| 236 | + |
| 237 | +#if defined(CPACR_PRESENT) |
| 238 | + /* Restore CPACR */ |
| 239 | + SCB->CPACR = context->cpacr; |
| 240 | +#endif /* CPACR_PRESENT */ |
| 241 | + |
| 242 | + /** |
| 243 | + * Ensure that updates to the SCB are visible by executing a DSB followed by ISB. |
| 244 | + * This sequence is recommended in the M-profile Architecture Reference Manuals: |
| 245 | + * - ARMv6: DDI0419 Issue E - §B2.5 "Barrier support for system correctness" |
| 246 | + * - ARMv7: DDI0403 Issue E.e - §A3.7.3 "Memory barriers" (at end of section) |
| 247 | + * - ARMv8: DDI0553 Version B.Y - §B7.2.16 "Synchronization requirements [...]" |
| 248 | + */ |
| 249 | + __DSB(); |
| 250 | + __ISB(); |
| 251 | +} |
0 commit comments