nrfcxx
0.1.0
C++-17 Framework for Nordic nRF5 Devices
|
A class supporting watchdog configuration and cross-reset retention of state. More...
#include <nrfcxx/core.hpp>
Data Structures | |
class | scoped_sleeper |
RAII instance that configures the operational mode to enter OM_SLEEP when constructed, and to leave OM_SLEEP when destructed. More... | |
struct | state_type |
The raw data supporting cross-reset state transfer. More... | |
Public Types | |
enum | om_enum : om_type { OM_SLEEP = 0x01, OM_HFCLK = 0x02, OM_RADIO = 0x04, NUM_OPERATIONAL_MODES = (OM_RADIO << 1) } |
Bits used to build up an operational mode. More... | |
using | app_handler_type = void(*)(const state_type &ss, bool is_reset, bool was_retained) |
Type of a function allowing application state maintenance. More... | |
Public Member Functions | |
systemState (state_type &state, uint32_t magic, app_handler_type app_handler=nullptr) | |
Set up a wrapper around a cross-reset state object. More... | |
const state_type & | state () const |
Access a read-only instance of the state referenced by this object. | |
int | watchdogInit (unsigned int delay_32KiHz, unsigned int channel_mask=1, bool run_in_sleep=true, bool run_in_debug=false) const |
Configure the watchdog infrastructure. More... | |
bool | watchdogActive () const |
Check whether the watchdog infrastructure is active. More... | |
void | watchdogFeed (unsigned int channel) const |
Reload a specific channel in the watchdog. More... | |
void | watchdogFeedMulti (unsigned int channel_mask) const |
As with watchdogFeed() but feeds multiple channels. More... | |
bool | watchdogCheckExtended () |
Check that the extended watchdog channels are current. More... | |
void | reset (unsigned int code, bool bypass_watchdog=false) |
Record some information and reset the system. More... | |
unsigned int | stack_reserved () const |
Return the size of the reserved stack region. | |
unsigned int | stack_used () const |
Return the size of stack region that has been used since startup. More... | |
unsigned int | heap_reserved () const |
Return the size of the reserved heap region. | |
unsigned int | heap_used () const |
Return the current total heap allocation. More... | |
uint64_t | operationalModeBreakdown (uint64_t &sleep_utt, uint64_t &radio_utt) const |
Provide information on the total time spent in various operations states since reset. More... | |
Static Public Member Functions | |
static unsigned int | updateOperationalMode (unsigned int om_clear=0, unsigned int om_set=0) |
Update the operational mode. More... | |
static scoped_sleeper | make_scoped_sleeper () noexcept |
Construct an RAII object to track sleep periods. More... | |
static void | WFE () |
Issue a __WFE instruction that records time spent sleeping. More... | |
static void | sd_fault_handler (uint32_t id, uint32_t pc, uint32_t info) |
A function suitable for use as the fault_handler argument to sd_softdevice_enable() . More... | |
static uint32_t | current_pc () |
Return the address of the instruction after the call. More... | |
static uint64_t | total_now () |
Return the aggregate time since the retained state was reset. More... | |
static unsigned int | wfe_count () |
Return the number of times WFE() has returned. More... | |
static void | systemOff (unsigned int preserve, int button_psel=-1) |
Enter system off mode. More... | |
Static Public Attributes | |
static const char *const | operationalModeText [NUM_OPERATIONAL_MODES] |
Text representations of each operational mode. | |
static constexpr unsigned int | WATCHDOG_Hz = 32768U |
Frequency at which the watchdog clock runs. | |
static constexpr auto | WATCHDOG_MASK_EXTENDED = (1U << 8) |
Pseudo-channel used to support extended watchdog channels. More... | |
Static Protected Attributes | |
static state_type * | statep_ |
Pointer to the #state_ field of the first systemState instance to be constructed. More... | |
static app_handler_type | app_handler_ |
Pointer to the application state handler for the first systemState instance to be constructed. | |
A class supporting watchdog configuration and cross-reset retention of state.
Applications may encounter situations where they can no longer function and need to restart. These situations may be detectable by program code and initiated intentionally; result from a watchdog reset detecting failure to execute some critical operation in a timely manner; or when an unrecoverable system failure causes a failsafe restart.
Information about the reset is available from the POWER
module, but for completeness must be accompanied by information persisted from the session that reset. This class supports that state transfer.
Example:
static __attribute__((__section__(".noinit.systemState"))) nrfcxx::systemState::state_type state; nrfcxx::systemState cs{state}; // constructor invoked before main() int main () { if (nrfcxx::systemState::state_type::RESET_REAS_FAILSAFE & cs.state().reset_reas) { // bring system up in fail-safe mode }
using nrfcxx::systemState::app_handler_type = void (*) (const state_type& ss, bool is_reset, bool was_retained) |
Type of a function allowing application state maintenance.
This function is invoked twice:
Implementations should reference internally-held or global retained application state.
A template for filling in state is:
if (is_reset) { // Shutting down. Save anything that has to be saved // that isn't maintained in the structure supported by this // function. If anything is done here, the condition on // retained should include the test for RESET_REAS_CONTROLLED. } else if (retained && (systemState::state_type::RESET_REAS_CONTROLLED & ss.reset_reas)) { // Starting up and previous shutdown was controlled. Update // from retained state. } else { // Starting up, everything was lost. }
sp | pointer to the initialized system state |
is_reset | false on the invocation from the constructor, true on the invocation during a controlled reset. |
was_retained | valid only when is_reset is false , this indicates whether the constructor found a valid state object. |
enum nrfcxx::systemState::om_enum : om_type |
Bits used to build up an operational mode.
Enumerator | |
---|---|
OM_SLEEP | Operational mode flag indicating that CPU is turned off. In operationalModeText this flag is represented in the first character, which is |
OM_HFCLK | Operational mode flag indicating that high-frequency clock is running. In operationalModeText this flag is represented in the second character, which is
|
OM_RADIO | Operational mode flag indicating that 2.4 GHz radio is running. In operationalModeText this flag is represented in the third character, which is |
NUM_OPERATIONAL_MODES | The number of distinct operational modes supported.
|
nrfcxx::systemState::systemState | ( | state_type & | state, |
uint32_t | magic, | ||
app_handler_type | app_handler = nullptr |
||
) |
Set up a wrapper around a cross-reset state object.
This verifies that the retained state is compatible with magic
; if not it is cleared. Information available from the reset is copied into the state object.
NRF_POWER->RESETREAS
. The pre-clear content can be reconstructed from state().reset_reas.state | reference to a state_type instance. |
magic | the application constant used to derive state_type::magic, which indicates that the state has been properly initialized. A non-random reasonable value would be the timestamp expressed as decimal YYYYMMDDHH, e.g. 2018101310. |
app_handler | optional application handler used to retain application state. |
|
static |
Return the address of the instruction after the call.
This is used to provide the location of the reset operation when reset() is invoked. It may be useful in other situations.
unsigned int nrfcxx::systemState::heap_used | ( | ) | const |
Return the current total heap allocation.
This delegates to _nrfcxx_heap_used(). As the block allocator underlying that capability does not release memory it is an accurate reflection of maximum use since startup.
|
inlinestaticnoexcept |
Construct an RAII object to track sleep periods.
Example:
{ auto sleeper = systemState::make_scoped_sleeper; sd_app_evt_wait(); }
uint64_t nrfcxx::systemState::operationalModeBreakdown | ( | uint64_t & | sleep_utt, |
uint64_t & | radio_utt | ||
) | const |
|
inline |
Record some information and reset the system.
If watchdogInit() has not been invoked—or if bypass_watchdog
is true—this delegates to NVIC_SystemReset()
, which should produce an immediate reset. However, if the watchdog had been enabled it remains enabled at the start of the next session, which means unless feedings resume in a timely fashion the device may reset unexpectedly.
If watchdogInit() has been invoked and bypass_watchdog
is false this disables interrupts and goes to sleep in a loop, allowing the reset to occur due to the watchdog timeout so when the system starts up the watchdog is disabled and can be reprogrammed. In this situation the time before the reset takes effect is determined by the watchdog delay.
code | a value to be stored in state_type::code after the reset completes. |
bypass_watchdog | if true the reset will take effect immediately even if doing so will leave a running watchdog. |
|
static |
A function suitable for use as the fault_handler
argument to sd_softdevice_enable()
.
When invoked this causes a system reset where the next session will include state_type::RESET_REAS_SDFAULT in state_type::reset_reas, the id
parameter will be in state_type::sdfault_id, the pc
parameter will be in state_type::last_pc, and the info
parameter will be in state_type::code.
id | the SD-specific fault identifier. After reset this value is available from state_type::sdfault_id. |
pc | the program counter of the instruction that triggered the fault. After reset this will be in state_type::last_pc. |
info | additional fault-specific information. After reset this will be in state_type::code. |
unsigned int nrfcxx::systemState::stack_used | ( | ) | const |
Return the size of stack region that has been used since startup.
This delegates to stack_infer_highwater(). If the value exceeds stack_reserved() there is a greater chance of stack and heap colliding.
|
static |
Enter system off mode.
preserve | bits from state_type::reset_reas for which the failures from the previous session should be preserved as though they occurred in this session. In decreasing priority this supports state_type::RESET_REAS_FAILSAFE, state_type::RESET_REAS_SDFAULT, state_type::RESET_REAS_PROGRAMMATIC. |
button_psel | optional PSEL for a button that will be programmed to issue a DETECT signal that will wake the system from off mode. Pass a negative value to disable wakeups. |
|
static |
Return the aggregate time since the retained state was reset.
This fetches clock::uptime::now() and adds total_uptime to it if a system_state is registered.
|
static |
Update the operational mode.
om_clear | bits in the operational mode that are to be turned off. Pass zero to leave all currently set bits set. |
om_set | bits in the operational mode that are to be turned on. Pass zero to leave all currently cleared bits clear. |
bool nrfcxx::systemState::watchdogActive | ( | ) | const |
Check whether the watchdog infrastructure is active.
NRF_WDT->RUNSTATUS
bool nrfcxx::systemState::watchdogCheckExtended | ( | ) |
Check that the extended watchdog channels are current.
Applications should invoke this within the watchdog peripheral delay to confirm that all extended watchdogs are current. If so, the underlying hardware channel common to those channels is fed.
true
iff all channels are fed. If this returns false
, the system will watchdog reset within the current delay. void nrfcxx::systemState::watchdogFeed | ( | unsigned int | channel | ) | const |
Reload a specific channel in the watchdog.
channel | the channel to be reloaded. Allowed values range from 0 through 7. To be useful the corresponding bit should have been set in channels when watchdogInit() was invoked. |
If you want to avoid the overhead of a function call in code that includes <nrfcxx/impl.hpp> this is functionally equivalent to a bounds-checked execution of:
NRF_WDT->RR[channel] = WDT_RR_RR_Reload;
void nrfcxx::systemState::watchdogFeedMulti | ( | unsigned int | channel_mask | ) | const |
As with watchdogFeed() but feeds multiple channels.
channel_mask | a bit mask where a set bit indicates a channel index to clear. |
int nrfcxx::systemState::watchdogInit | ( | unsigned int | delay_32KiHz, |
unsigned int | channel_mask = 1 , |
||
bool | run_in_sleep = true , |
||
bool | run_in_debug = false |
||
) | const |
Configure the watchdog infrastructure.
Set up the nRF5 watchdog peripheral and add hooks so that if it fires state will be persisted across the reset.
If the watchdog is already running when this function is invoked and the requested configuration matches the existing configuration then the active channels will be fed and the existing session continued to be used. If the configuration is different from the running configuration state_type::reset_reas will be preserved and the system will wait out the previous watchdog.
After configuration watchdogFeed() must be invoked for all channels enabled in channel_mask
with less than delay_32KiHz
intervals or the system will reset.
If WATCHDOG_MASK_EXTENDED is present in channel_mask
then the watchdog_extended_channel infrastructure is enabled, and watchdogCheckExtended() must also be invoked within delay_32KiHz
.
delay_32KiHz | the value to write to NRF_WDT->CRV |
channel_mask | a bit mask identifying which watchdog channels are required to complete a reload. The low 8 bits correspond to the eight available physical watchdog channels. If WATCHDOG_MASK_EXTENDED is included then channel 7 is not available and attempting to enable it will produce FailsafeCode::API_VIOLATION. |
run_in_sleep | if true the watchdog will continue to run while the CPU is inactive. |
run_in_debug | if true the watchdog will continue to run while the CPU is halted through a debug interface. |
|
static |
Issue a __WFE
instruction that records time spent sleeping.
This invokes updateOperationalMode() before and after the __WFE
passing OM_SLEEP appropriately to track the sleep time.
|
inlinestatic |
Return the number of times WFE() has returned.
In common use the application uses event_set operations to return to active mode. This is accomplished by using WFE() in a loop, and executing the application event loop only if application events are set. Wakeups from ARM events may occur much more frequently, and although OM_SLEEP is adjusted on each ARM event wakeup the presence of rapidly firing ARM events may be hidden.
Tracking the rate at which this counter increments can reveal these wakeups.
|
staticprotected |
Pointer to the #state_ field of the first systemState instance to be constructed.
This is used by static member functions.
|
staticconstexpr |
Pseudo-channel used to support extended watchdog channels.
Use this in the channel_mask
parameter to watchdogInit() to enable the feature.