| /* |
| * Copyright (c) 2022, Carlo Caione <ccaione@baylibre.com> |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| /** |
| * @file |
| * @brief ARM Cortex-M suspend-to-RAM code (S2RAM) |
| */ |
| |
| #include <zephyr/toolchain.h> |
| #include <offsets_short.h> |
| #include <zephyr/arch/cpu.h> |
| #include <zephyr/arch/common/pm_s2ram.h> |
| |
| #define MAGIC (0xDABBAD00) |
| |
| _ASM_FILE_PROLOGUE |
| |
| GDATA(_cpu_context) |
| GDATA(marker) |
| |
| SECTION_FUNC(TEXT, arch_pm_s2ram_suspend) |
| /* |
| * Save the CPU context |
| * |
| * r0: address of the system_off function |
| */ |
| push {r4-r12, lr} |
| ldr r1, =_cpu_context |
| |
| mrs r2, msp |
| str r2, [r1, #___cpu_context_t_msp_OFFSET] |
| |
| mrs r2, msplim |
| str r2, [r1, #___cpu_context_t_msplim_OFFSET] |
| |
| mrs r2, psp |
| str r2, [r1, #___cpu_context_t_psp_OFFSET] |
| |
| mrs r2, psplim |
| str r2, [r1, #___cpu_context_t_psplim_OFFSET] |
| |
| mrs r2, apsr |
| str r2, [r1, #___cpu_context_t_apsr_OFFSET] |
| |
| mrs r2, ipsr |
| str r2, [r1, #___cpu_context_t_ipsr_OFFSET] |
| |
| mrs r2, epsr |
| str r2, [r1, #___cpu_context_t_epsr_OFFSET] |
| |
| mrs r2, primask |
| str r2, [r1, #___cpu_context_t_primask_OFFSET] |
| |
| mrs r2, faultmask |
| str r2, [r1, #___cpu_context_t_faultmask_OFFSET] |
| |
| mrs r2, basepri |
| str r2, [r1, #___cpu_context_t_basepri_OFFSET] |
| |
| mrs r2, control |
| str r2, [r1, #___cpu_context_t_control_OFFSET] |
| |
| /* |
| * Set the marker to MAGIC value |
| */ |
| ldr r1, =marker |
| ldr r2, =MAGIC |
| str r2, [r1] |
| |
| /* |
| * Call the system_off function passed as parameter. This should never |
| * return. |
| */ |
| blx r0 |
| |
| /* |
| * The system_off function returns here only when the powering off was |
| * not successful (in r0 the return value). |
| */ |
| |
| /* |
| * Reset the marker |
| */ |
| ldr r1, =marker |
| mov r2, #0x0 |
| str r2, [r1] |
| |
| pop {r4-r12, lr} |
| bx lr |
| |
| GTEXT(arch_pm_s2ram_resume) |
| SECTION_FUNC(TEXT, arch_pm_s2ram_resume) |
| /* |
| * Check if the marker is set |
| */ |
| ldr r0, =marker |
| ldr r0, [r0] |
| ldr r1, =MAGIC |
| cmp r0, r1 |
| beq resume |
| bx lr |
| |
| resume: |
| /* |
| * Reset the marker |
| */ |
| ldr r0, =marker |
| mov r1, #0x0 |
| str r1, [r0] |
| |
| /* |
| * Restore the CPU context |
| */ |
| ldr r0, =_cpu_context |
| |
| ldr r1, [r0, #___cpu_context_t_msp_OFFSET] |
| msr msp, r1 |
| |
| ldr r1, [r0, #___cpu_context_t_msplim_OFFSET] |
| msr msplim, r1 |
| |
| ldr r1, [r0, #___cpu_context_t_psp_OFFSET] |
| msr psp, r1 |
| |
| ldr r1, [r0, #___cpu_context_t_psplim_OFFSET] |
| msr psplim, r1 |
| |
| ldr r1, [r0, #___cpu_context_t_apsr_OFFSET] |
| msr apsr_nzcvq, r1 |
| |
| ldr r1, [r0, #___cpu_context_t_ipsr_OFFSET] |
| msr ipsr, r1 |
| |
| ldr r1, [r0, #___cpu_context_t_epsr_OFFSET] |
| msr epsr, r1 |
| |
| ldr r1, [r0, #___cpu_context_t_primask_OFFSET] |
| msr primask, r1 |
| |
| ldr r1, [r0, #___cpu_context_t_faultmask_OFFSET] |
| msr faultmask, r1 |
| |
| ldr r1, [r0, #___cpu_context_t_basepri_OFFSET] |
| msr basepri, r1 |
| |
| ldr r1, [r0, #___cpu_context_t_control_OFFSET] |
| msr control, r1 |
| isb |
| |
| pop {r4-r12, lr} |
| |
| /* |
| * Set the return value and return |
| */ |
| mov r0, #0 |
| bx lr |