- (future) Provide a method to newt by which certain tasks memory can be linked earlier in RAM, so that for systems where RAM suspension is desired, a core set of system services can be located there, while other services can be re-initialized in a second phase. - This may cause some modification to the task structure to provide these “re-init” functions.
I was specifically wondering if folks had any thoughts on this scenario. This is the case on certain processors where you can go into ever low power states, as you retain only certain blocks of RAM (I believe Nordic allows you to retain down to 4K of RAM on the NRF52.)
In terms of use-cases, I think the most common one here will be on a system where you have the processor need to wake-up from some external operation (e.g. button press), and you want to have system asleep until that happens. When implementing these cases, you’ll probably also want to have some code that comes up very quickly, and performs certain operations, prior to fully booting the system (e.g. debouncing an I/O pin.)
My initial thought on this was that we could locate the operating system in that 4K of RAM, and designate a single task, which retains context to do this. This could currently be the idle task, and the idle task can have a restore from deep sleep hook, which was user provided. Given that the user provided hook would likely be in a separate context from the OS, we would dedicate a linker section to user provided retained memory so that any data associated with the user hook could also be saved.
Then, when the processor wants to transition to sleep mode: either through an ISR, or some task’s context. It tells the system to transition into that state, which triggers a saving of critical system context. When the IDLE task comes up, it immediately calls the deep sleep hook, to determine if the full system should reboot. If it determines the system should reboot, the entire system then jumps to C startup and re-initializes.
I should note that on some processors (e.g. Nordic), in these deep sleep RAM retained states, the code begins running from the reset vector (0 in internal flash.) Currently we locate our boot loader there, so we’ll need some other code in the boot loader to skip image verification (if enabled), and look into RAM for a specific pattern — if that pattern is present, restore system operation, otherwise continue booting.
The other option, is to skip multi-purposing the idle task, and instead add a linker section for “retained RAM” that goes ahead of all other sections. And then, add a hook in the C startup code that goes prior to any initialization. In this case, that hook can run, look at the retained RAM, and perform operations prior to system boot. This would avoid all interactions with the RTOS itself, yet provide a standard way of having people hook into this state.
I’m not sure which of these I like more. The OS approach seems more complicated, but somehow feels more right. Nonetheless, I can’t really see why running out of the idle task is that desirable, if you end up losing all of your other task contexts. You’re really going to have to re-run system initialization anyway (e.g. reboot) in order to get full system functionality.
Are there any other approaches folks have seen in the past/liked? What have people done when they’ve needed to manage these states?
Thanks, Sterling
