1
votes

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?

1
not sure what arm would have to do with it only a tiny percentage of what you would have to save is related to the ARM IP within the chip. You need to preserve everything, including the contents of ram, All the peripheral states if even possible, etc. - old_timer
is this a controlled power down where the device is turning itself off or the user has pulled the plug and you need to save in a hurry? you need to design your pcb to have enough power storage to handle that case plus a way to sense when power has been pulled. - old_timer
it is all part of your system design as such how would one know how to make an example for you? realistically you want to do your system design such that you dont have to do a complete backup of the entire memory space, but instead define what needs to be preserved and what can be initialized fresh. would one need to preserve the packets in flight to/from wifi for example. in general no, that doesnt make sense, init that fresh. repeat for every other peripheral and data structure in your design. - old_timer
Say I have a simple A/C thermostat. On/Off button, fan auto/on switch/button, and a setpoint via a knob or up/down buttons. And I want off to mean the mcu that I used to build it turns off. Would there be any reason why I would need to save the processor registers or the nvic state (why would you ever need to save the nvic state). Or would I simply need to save the fan on/auto bit and the setpoint value byte, bring everything up clean and use the saved settings for fan on/auto and the setpoint? - old_timer
Thanks @old_timer. ARM will initiate the shutdown; RAM will be retained. I've edited my question. - Andrew Heale

1 Answers

1
votes

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!