|
22 | 22 | #include <zephyr/linker/linker-defs.h>
|
23 | 23 | #include <zephyr/cache.h>
|
24 | 24 | #include <zephyr/arch/cache.h>
|
| 25 | +#include <arm/cortex_m/scb.h> |
25 | 26 |
|
26 | 27 | #if defined(CONFIG_CPU_HAS_NXP_SYSMPU)
|
27 | 28 | #include <fsl_sysmpu.h>
|
@@ -151,3 +152,81 @@ void z_arm_init_arch_hw_at_boot(void)
|
151 | 152 | barrier_isync_fence_full();
|
152 | 153 | }
|
153 | 154 | #endif /* CONFIG_INIT_ARCH_HW_AT_BOOT */
|
| 155 | + |
| 156 | +/** |
| 157 | + * @brief Backs up essential SCB registers into a provided context structure. |
| 158 | + * |
| 159 | + * This function reads the current values of critical System Control Block (SCB) |
| 160 | + * registers that are safe to backup, and stores them into the `context` structure. |
| 161 | + * Access to SCB registers requires atomicity and consistency, so calling code |
| 162 | + * should guaranteed that interrupts are disabled. |
| 163 | + * |
| 164 | + * @param context Pointer to an `scb_context_t` structure where the register |
| 165 | + * values will be stored. Must not be NULL. |
| 166 | + */ |
| 167 | +void scb_backup_registers(scb_context_t *context) |
| 168 | +{ |
| 169 | + __ASSERT_NO_MSG(context != NULL); |
| 170 | + |
| 171 | +#if defined(CONFIG_CPU_CORTEX_M_HAS_VTOR) |
| 172 | + context->vtor = SCB->VTOR; |
| 173 | +#endif |
| 174 | + context->aircr = SCB->AIRCR; |
| 175 | + context->scr = SCB->SCR; |
| 176 | + context->ccr = SCB->CCR; |
| 177 | + |
| 178 | + /* Backup System Handler Priority Registers */ |
| 179 | + for (int i = 0; i < 4; i++) { |
| 180 | + context->shpr[i] = SCB->SHPR[i]; |
| 181 | + } |
| 182 | + |
| 183 | +#if defined(CONFIG_CPU_CORTEX_M_HAS_SHCSR) |
| 184 | + context->shcsr = SCB->SHCSR; |
| 185 | +#endif |
| 186 | + |
| 187 | +} |
| 188 | + |
| 189 | +/** |
| 190 | + * @brief Restores essential SCB registers from a provided context structure. |
| 191 | + * |
| 192 | + * This function writes the values from the `context` structure back to the |
| 193 | + * respective System Control Block (SCB) registers. Access to SCB registers |
| 194 | + * requires atomicity and consistency, so calling code should guaranteed that |
| 195 | + * interrupts are disabled. |
| 196 | + * |
| 197 | + * @warning The ICSR register is NOT restored directly due to its volatile nature |
| 198 | + * and presence of read-only status bits and write-only clear/set bits. |
| 199 | + * Direct restoration can lead to undefined behavior or corrupt interrupt state. |
| 200 | + * If specific ICSR bits need to be managed as part of a context, |
| 201 | + * a separate, highly controlled mechanism should be implemented. |
| 202 | + * |
| 203 | + * @param context Pointer to a `scb_context_t` structure containing the |
| 204 | + * register values to be restored. Must not be NULL. |
| 205 | + */ |
| 206 | +void scb_restore_registers(const scb_context_t *context) |
| 207 | +{ |
| 208 | + __ASSERT_NO_MSG(context != NULL); |
| 209 | + |
| 210 | +#if defined(CONFIG_CPU_CORTEX_M_HAS_VTOR) |
| 211 | + /* Restore Vector Table Offset Register first if it was modified. */ |
| 212 | + SCB->VTOR = context->vtor; |
| 213 | +#endif |
| 214 | + /* Restore AIRCR: Must write the VECTKEY (0x05FA) along with the desired bits. |
| 215 | + Ensure only the relevant modifiable bits are restored. */ |
| 216 | + SCB->AIRCR = (context->aircr & ~SCB_AIRCR_VECTKEY_Msk) | |
| 217 | + (0x05FAUL << SCB_AIRCR_VECTKEY_Pos); |
| 218 | + |
| 219 | + SCB->SCR = context->scr; |
| 220 | + SCB->CCR = context->ccr; |
| 221 | + |
| 222 | + /* Restore System Handler Priority Registers */ |
| 223 | + for (int i = 0; i < 4; i++) { |
| 224 | + SCB->SHPR[i] = context->shpr[i]; |
| 225 | + } |
| 226 | + |
| 227 | +#if defined(CONFIG_CPU_CORTEX_M_HAS_SHCSR) |
| 228 | + /* Restore SHCSR */ |
| 229 | + SCB->SHCSR = context->shcsr; |
| 230 | +#endif |
| 231 | + |
| 232 | +} |
0 commit comments