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