Andrew Heale
Andrew Heale

Reputation: 11

Saving Cortex-M4 processor state for power-down and resume

I'm working on a SoC that can power-off the ARM (Cortex-M4) while retaining the system RAM, and I'm interested in saving the processor state then restoring it when the ARM is restarted so that the software resumes from the point where it stopped. I'm looking for code or documentation about this process.

Prior to power-off the software would save all necessary register values to RAM, then during boot, rather than performing a regular application start-up, the software would reload the saved values. There is hardware that informs the software which is required.

The power-down will be initiated by the ARM: although I could use WFI to halt the clock, the goal is to remove power from the ARM entirely. RAM will be in a low-power state where it retains its contents. I know how to deal with peripherals outside the ARM, but I'm less familiar with ARM's internal hardware.

My goal is for the application to resume execution from the point where it stopped, with all its variables and stack retained. I know I would need to save and restore core registers, plus system control, NVIC, systick, and perhaps other things, though I'm not sure of the full list.

I'm looking for code or documentation about this process. It seems like a reasonably common task, but my searches on the arm infocenter and the wider internet found only a document related to the out-dated ARM11.

Is this already implemented on M4 - perhaps somewhere like in CMSIS, FreeRTOS, or a published example?

If not, is there documentation on how to do this on M4?

If not, would the "Cortex-M4 Technical Reference Manual" identify all the registers I need to save? Or are there more?

Upvotes: 1

Views: 831

Answers (1)

cooperised
cooperised

Reputation: 2599

There are several aspects to saving the state of a system to non-volatile storage ('hibernation' in desktop parlance). Only a few are directly related to the CPU itself.

  1. Some of the volatile context of the CPU will need saving and restoring. This is the only bit that's actually ARM specific. It's very similar to how a context switch works in an OS, so that would be a good place to start looking for examples. I've written a small OS for the M4 whose context switch is 8 lines of assembly language (12 with FPU support), so it's not actually a very complex process.

    Given that you're in control of the timing of the hibernation, you won't need to save everything; but any of the registers in the ARM calling convention that are callee-preserved (r0-r3, r12, lr and the PSR basically) will probably need saving, along with s15-s32 if the FPU is enabled. You might get away without saving lr and the PSR if your wake-from-hibernation routine doesn't need them. You'll also probably need to store the value of the stack pointer, possibly both stack pointers (MSP and PSP) if you're using an operating system of any type. This needs privilege, which usually implies handler mode. I'd do the whole thing in SVC handlers.

  2. The contents of RAM will need saving. Flash storage is slow, so copying the whole of the RAM in and out will be time consuming and increase wear on the flash. If you're not using all of the RAM I'd consider messing with the linker to restrict the address range of the RAM that the compiled code uses. But whatever the address range, this is a fairly simple process.

  3. The hard part is the peripherals. If you have any peripherals that are dynamically reconfigured, or that might be in a state that needs precise restoration (e.g. they have data in buffers) then you'll have to handle these on a case-by-case basis. On desktop, device drivers have to be written specifically to be hibernation-aware, and the same is effectively true for you here.

I'll be interested to see how you get on with this!

Upvotes: 1

Related Questions