We're using systemoff=1 to turn our system off, but the command doesn't work after programming, i.e. device immediately turns back on with 16 MHz RC osc running, and current consumption is approx. 4.0 mA. If we cycle power after programming, the command does work effectively.
Here's our setup:
nRF51422 QFAAE0/F0
Segger programmer attached or detached from IC
Keil or nRFgo Studio
S210 v4.0.1 soft device
Here's the code context:
// ----------------------------------------------------------------------------------
void
SetSystemOff( // Put the beacon into system off mode (suspend)
void)
{
uint32_t ulReturnValue = 0;
uint32_t ulPowerdownTimeCount = 0;
// Ensure system timer is stopped
TimerStop(SYSTEM_TIMER_INDEX);
ulPowerdownTimeCount = 0;
// Disable all events from input GPIO
GPIOTEDisableInputPin(GPIO_PIN_VOLTAGE_SUPERVISOR);
GPIOTEDisableInputPin(GPIO_PIN_BUTTON_INPUT);
// Set the button to wake system on high signal
ulReturnValue = GPIOTEConfigureInputPin(GPIO_PIN_BUTTON_INPUT, GENERATE_EVENT_HIGH);
ErrorCheck(ulReturnValue);
// Wait for 500 milliseconds to ensure we don't suspend too soon after power on, and to debounce button signal
while(ulPowerdownTimeCount < BEACON_POWERDOWN_DELAY_100MS*5)
{
//Delay 50 ms
DelayUS(50*1000);
WatchDogReload();
ProcessGPIOEvents();
DebounceProcessing();
ulPowerdownTimeCount += 50;
}
// Stop timer
TimerStop(SYSTEM_TIMER_INDEX);
DisableSoftDevice();
// Set the power off flag if it's not set already
if(!gulPowerOffFlag)
{
ulReturnValue = NvmcPageErase(BEACON_POWERSTATE_FLASH_ADDRESS);
ErrorCheck(ulReturnValue);
WatchDogReload();
ulReturnValue = NvmcWriteWord(BEACON_POWERSTATE_FLASH_ADDRESS,1);
ErrorCheck(ulReturnValue);
}
// Set the general purpose register to indicate manual power down, we need this as a workaround to PAN #14
NRF_POWER->GPREGRET = ((BEACON_OFF_INDICATOR & POWER_GPREGRET_GPREGRET_Msk) << POWER_GPREGRET_GPREGRET_Pos);
// Go to system off
NRF_POWER->SYSTEMOFF = 1;
// Wait for suspend to occurr
while(1)
{}
}
// ----------------------------------------------------------------------------------
void
DisableSoftDevice() //If enabled disable the softdevice
{
uint8_t ucSoftDeviceEnabled = 0;
uint32_t ulReturnValue = 0;
ulReturnValue = sd_softdevice_is_enabled(&ucSoftDeviceEnabled);
ErrorCheck(ulReturnValue);
// If soft device is enabled, shut it down
if(ucSoftDeviceEnabled)
{
WatchDogReload();
// Stop all broadcast channels
ChannelStop(BROADCAST_BEACON_CHANNEL1);
ChannelStop(BROADCAST_BEACON_CHANNEL2);
ChannelStop(BROADCAST_BEACON_CHANNEL3);
WatchDogReload();
// Disable softdevice
ulReturnValue = sd_softdevice_disable();
ErrorCheck(ulReturnValue);
}
}