Skip to content

Commit a4e5501

Browse files
committed
arch: arm: cortex_m: Add API for scb save and restore
Add two API to save SCB context and restore it, typically used in suspend to RAM use case. The scb_context_t and the backup/restore functions are designed to only handle SCB registers that are: - Mutable: Their values can be changed by software. - Configurable: They control system behavior or features. - Stateful: Their values represent a specific configuration that an application might want to preserve and restore. Register excluded from backup/restore are: 1. CPUID (CPUID Base Register) Motivation for Exclusion: This is a read-only identification register. 2. ICSR (Interrupt Control and State Register) Motivation for Exclusion (from restoration): While its current value can be read, directly restoring a saved ICSR value is highly dangerous and generally unsafe in an RTOS context. Contains Read-Only Status Bits: A significant portion of ICSR consists of read-only bits (VECTACTIVE, VECTPENDING, ISRPREEMPT, TSRUNPEND). These bits reflect the current state of the exception system (e.g., which exception is active, which are pending) and are managed dynamically by the CPU and the RTOS. Forcing a previous state onto these bits would corrupt the live system's interrupt handling. Contains Write-Only Set/Clear Bits: Some bits are write-only to set or clear a pending interrupt (PENDSVSET, PENDSVCLR, SYSTICKSET, SYSTICKCLR). If these bits were set in the saved context, restoring them might immediately trigger an interrupt or change its pending state unexpectedly, outside the RTOS's control. RTOS Management: In Zephyr (and other RTOSes), the kernel tightly manages the interrupt and exception state. Direct manipulation of ICSR's volatile bits could conflict with the RTOS's internal state machine, leading to crashes or unpredictable behavior. 3. CFSR (Configurable Fault Status Register) Motivation for Exclusion: This is a read-only status register that reports the current state of Memory Management, Bus Fault, and Usage Faults. It's used by fault handlers to determine the cause of a fault. 4. HFSR (HardFault Status Register) Motivation for Exclusion: Similar to CFSR, this is a read-only status register that reports the current state of HardFaults. It's for reporting, not for configuration or restoration. 5. DFSR (Debug Fault Status Register) Motivation for Exclusion: This is a read-only status register that reports debug-related faults. It's primarily used by debuggers and is not part of the application's runtime context to be saved/restored. 6. MMFAR (MemManage Fault Address Register) Motivation for Exclusion: This is a read-only register that stores the address that caused a Memory Management fault. It's a diagnostic register, not a configurable parameter. 7. BFAR (BusFault Address Register) Motivation for Exclusion: Similar to MMFAR, this is a read-only register that stores the address that caused a BusFault. It's a diagnostic register. 8. AFSR (Auxiliary Fault Status Register) Motivation for Exclusion: This register is implementation-defined and read-only. Signed-off-by: Michele Sardo <[email protected]>
1 parent 322da1d commit a4e5501

File tree

1 file changed

+80
-0
lines changed
  • arch/arm/core/cortex_m

1 file changed

+80
-0
lines changed

arch/arm/core/cortex_m/scb.c

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <zephyr/linker/linker-defs.h>
2323
#include <zephyr/cache.h>
2424
#include <zephyr/arch/cache.h>
25+
#include <cortex_m/scb.h>
2526

2627
#if defined(CONFIG_CPU_HAS_NXP_SYSMPU)
2728
#include <fsl_sysmpu.h>
@@ -151,3 +152,82 @@ void z_arm_init_arch_hw_at_boot(void)
151152
barrier_isync_fence_full();
152153
}
153154
#endif /* CONFIG_INIT_ARCH_HW_AT_BOOT */
155+
156+
/**
157+
* @brief Save 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 z_arm_save_scb_context(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 z_arm_restore_scb_context(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+
*/
217+
SCB->AIRCR = (context->aircr & ~SCB_AIRCR_VECTKEY_Msk) |
218+
(0x05FAUL << SCB_AIRCR_VECTKEY_Pos);
219+
220+
SCB->SCR = context->scr;
221+
SCB->CCR = context->ccr;
222+
223+
/* Restore System Handler Priority Registers */
224+
for (int i = 0; i < 4; i++) {
225+
SCB->SHPR[i] = context->shpr[i];
226+
}
227+
228+
#if defined(CONFIG_CPU_CORTEX_M_HAS_SHCSR)
229+
/* Restore SHCSR */
230+
SCB->SHCSR = context->shcsr;
231+
#endif
232+
233+
}

0 commit comments

Comments
 (0)