nrfcxx  0.1.0
C++-17 Framework for Nordic nRF5 Devices
Data Structures | Public Types | Public Member Functions | Static Public Member Functions | Static Public Attributes | Static Protected Attributes
nrfcxx::systemState Class Reference

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_typestate () 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_typestatep_
 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.
 

Detailed Description

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
  }

Member Typedef Documentation

◆ app_handler_type

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:

  • As the last step of the constructor, to allow application-specific retained state to be updated based on history from the previous invocation;
  • As the last step before initiating or waiting out a controlled reset.

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.
}
Parameters
sppointer to the initialized system state
is_resetfalse on the invocation from the constructor, true on the invocation during a controlled reset.
was_retainedvalid only when is_reset is false, this indicates whether the constructor found a valid state object.

Member Enumeration Documentation

◆ om_enum

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 A for active (cleared) and S for sleeping (set). Use WFE() to automatically update this part of the mode.

OM_HFCLK 

Operational mode flag indicating that high-frequency clock is running.

In operationalModeText this flag is represented in the second character, which is - for disabled (cleared) and H for enabled (set). Control of this flag is managed by nrfcxx::clock.

Note
Although nrfcxx::clock will set and clear this flag, when soft devices are used they are responsible for managing HFCLK and this flag will generally remain off even when the clock is enabled.
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 - for disabled (cleared) and R for enabled (set). Control of this flag is the responsibility of the application's use of RADIO_IRQHandler.

NUM_OPERATIONAL_MODES 

The number of distinct operational modes supported.

Note
Code depends on this being a power of two.

Constructor & Destructor Documentation

◆ systemState()

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.

Warning
Invoking this will clear NRF_POWER->RESETREAS. The pre-clear content can be reconstructed from state().reset_reas.
Parameters
statereference to a state_type instance.
magicthe 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_handleroptional application handler used to retain application state.

Member Function Documentation

◆ current_pc()

static uint32_t nrfcxx::systemState::current_pc ( )
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.

◆ heap_used()

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.

◆ make_scoped_sleeper()

static scoped_sleeper nrfcxx::systemState::make_scoped_sleeper ( )
inlinestaticnoexcept

Construct an RAII object to track sleep periods.

Example:

{
  auto sleeper = systemState::make_scoped_sleeper;
  sd_app_evt_wait();
}

◆ operationalModeBreakdown()

uint64_t nrfcxx::systemState::operationalModeBreakdown ( uint64_t &  sleep_utt,
uint64_t &  radio_utt 
) const

Provide information on the total time spent in various operations states since reset.

Parameters
[out]sleep_uttthe sum of the durations of modes where OM_SLEEP was set.
[out]radio_uttthe sum of the durations of modes where OM_RADIO was set.
Returns
total_utt the sum of the durations of all modes.

◆ reset()

void nrfcxx::systemState::reset ( unsigned int  code,
bool  bypass_watchdog = false 
)
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.

Parameters
codea value to be stored in state_type::code after the reset completes.
bypass_watchdogif true the reset will take effect immediately even if doing so will leave a running watchdog.

◆ sd_fault_handler()

static void nrfcxx::systemState::sd_fault_handler ( uint32_t  id,
uint32_t  pc,
uint32_t  info 
)
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.

Parameters
idthe SD-specific fault identifier. After reset this value is available from state_type::sdfault_id.
pcthe program counter of the instruction that triggered the fault. After reset this will be in state_type::last_pc.
infoadditional fault-specific information. After reset this will be in state_type::code.

◆ stack_used()

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.

◆ systemOff()

static void nrfcxx::systemState::systemOff ( unsigned int  preserve,
int  button_psel = -1 
)
static

Enter system off mode.

Parameters
preservebits 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_pseloptional 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.

◆ total_now()

static uint64_t nrfcxx::systemState::total_now ( )
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.

◆ updateOperationalMode()

static unsigned int nrfcxx::systemState::updateOperationalMode ( unsigned int  om_clear = 0,
unsigned int  om_set = 0 
)
static

Update the operational mode.

Parameters
om_clearbits in the operational mode that are to be turned off. Pass zero to leave all currently set bits set.
om_setbits in the operational mode that are to be turned on. Pass zero to leave all currently cleared bits clear.
Returns
the number of uptime clock ticks since the last change to the operational mode.
Note
Because of the resolution of the time tracking variables this function must be invoked at least once every 512 s to ensure that tick counter wraps are measured properly.
See also
OM_SLEEP
OM_HFCLK
OM_RADIO

◆ watchdogActive()

bool nrfcxx::systemState::watchdogActive ( ) const

Check whether the watchdog infrastructure is active.

Note
If you want to avoid the overhead of a function call in code that includes <nrfcxx/impl.hpp> this is functionally equivalent to reading NRF_WDT->RUNSTATUS

◆ watchdogCheckExtended()

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.

Returns
true iff all channels are fed. If this returns false, the system will watchdog reset within the current delay.

◆ watchdogFeed()

void nrfcxx::systemState::watchdogFeed ( unsigned int  channel) const

Reload a specific channel in the watchdog.

Parameters
channelthe 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.
Note

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;

◆ watchdogFeedMulti()

void nrfcxx::systemState::watchdogFeedMulti ( unsigned int  channel_mask) const

As with watchdogFeed() but feeds multiple channels.

Parameters
channel_maska bit mask where a set bit indicates a channel index to clear.

◆ watchdogInit()

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.

Parameters
delay_32KiHzthe value to write to NRF_WDT->CRV
channel_maska 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_sleepif true the watchdog will continue to run while the CPU is inactive.
run_in_debugif true the watchdog will continue to run while the CPU is halted through a debug interface.
Returns
Zero if the watchdog is successfully started, or a negative code if the watchdog is not running and could not be started.

◆ WFE()

static void nrfcxx::systemState::WFE ( )
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.

◆ wfe_count()

static unsigned int nrfcxx::systemState::wfe_count ( )
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.

Note
This is a 32-bit counter, and is expected to wrap.

Field Documentation

◆ statep_

state_type* nrfcxx::systemState::statep_
staticprotected

Pointer to the #state_ field of the first systemState instance to be constructed.

This is used by static member functions.

◆ WATCHDOG_MASK_EXTENDED

constexpr auto nrfcxx::systemState::WATCHDOG_MASK_EXTENDED = (1U << 8)
staticconstexpr

Pseudo-channel used to support extended watchdog channels.

Use this in the channel_mask parameter to watchdogInit() to enable the feature.


The documentation for this class was generated from the following file: