I have system on sleep mode implemented which is still drawing 8mA of current i would like to take it down to 1mA or less what i need to do to get it that low?
I have two wake up sources which will wake it up from sleep mode one is RTC and other is a GPIO which comes from an accel.
#include "common.h"
#include "FreeRTOS.h"
#include "task.h"
#include "event_groups.h"
#include "powermanager.h"
//#include "silego.h"
#include "nrf_drv_rtc.h"
#include "nrf.h"
#include "nrf_gpio.h"
#include "nrf_drv_clock.h"
#include "boards.h"
#include "app_error.h"
#include <nrfx_rtc.h>
#include "zoe_ubx.h"
#include "zoe_ubx_gen.h"
#include "nrf_drv_gpiote.h"
#include "rtc_handler.h"
#include "accel.h"
#include "leds.h"
#include "cellular.h"
#include "silego.h"
#include "fuelgauge.h"
#include "nrf.h"
#include "leds.h"
#include "i2c.h"
#define POWER_MANAGER_ON_CHARGER_SIGNAL (0x01)
#define POWER_MANAGER_OFF_CHARGER_SIGNAL (0x02)
#define POWER_MANAGER_TIMER_SIGNAL (0x04)
#define POWER_MANAGER_SHUTDOWN_SIGNAL (0x10)
#define POWER_MANAGER_REQUEST_SLEEP (0x08)
#define NRF52 1
#define POWER_MANAGER_SHUTDOWN_PERCENTAGE (15)
#define POWER_MANAGER_SHUTDOWN_MILLIVOLTS (3000)
//#define SHUTDOWN_VIA_PERCENTAGE
#define SHUTDOWN_VIA_VOLTAGE
static TaskHandle_t PowerManagerThreadHandle = NULL;
static EventGroupHandle_t PowerManagerEventGroup = NULL;
static TimerHandle_t PowerManagerTimer = NULL;
static void PowerManagerThreadEntry(void * argument);
static void PowerManagerCallbackFunction(TimerHandle_t xTimer);
#define NRF52_ONRAM1_OFFRAM1 POWER_RAM_POWER_S0POWER_On << POWER_RAM_POWER_S0POWER_Pos \
| POWER_RAM_POWER_S1POWER_On << POWER_RAM_POWER_S1POWER_Pos \
| POWER_RAM_POWER_S0RETENTION_On << POWER_RAM_POWER_S0RETENTION_Pos \
| POWER_RAM_POWER_S1RETENTION_On << POWER_RAM_POWER_S1RETENTION_Pos;
#define NRF52_ONRAM1_OFFRAM0 POWER_RAM_POWER_S0POWER_On << POWER_RAM_POWER_S0POWER_Pos \
| POWER_RAM_POWER_S1POWER_On << POWER_RAM_POWER_S1POWER_Pos \
| POWER_RAM_POWER_S0RETENTION_Off << POWER_RAM_POWER_S0RETENTION_Pos \
| POWER_RAM_POWER_S1RETENTION_Off << POWER_RAM_POWER_S1RETENTION_Pos;
#define NRF52_ONRAM0_OFFRAM0 POWER_RAM_POWER_S0POWER_Off << POWER_RAM_POWER_S0POWER_Pos \
| POWER_RAM_POWER_S1POWER_Off << POWER_RAM_POWER_S1POWER_Pos;
#define FPU_EXCEPTION_MASK 0x0000009F
volatile bool sleep = true;
volatile bool rtc_flag = false;
volatile bool rtc_config_flag = true;
void power_manager_sleep_exit(void)
{
sleep = false;
}
bool rtc_event_flag(void)
{
return rtc_flag = true;
}
void configure_ram_retention(void)
{
#ifdef NRF52
// Configure nRF52 RAM retention parameters. Set for System On 64kB RAM retention
NRF_POWER->RAM[0].POWER = NRF52_ONRAM1_OFFRAM0;
NRF_POWER->RAM[1].POWER = NRF52_ONRAM1_OFFRAM0;
NRF_POWER->RAM[2].POWER = NRF52_ONRAM1_OFFRAM0;
NRF_POWER->RAM[3].POWER = NRF52_ONRAM1_OFFRAM0;
NRF_POWER->RAM[4].POWER = NRF52_ONRAM1_OFFRAM0;
NRF_POWER->RAM[5].POWER = NRF52_ONRAM1_OFFRAM0;
NRF_POWER->RAM[6].POWER = NRF52_ONRAM1_OFFRAM0;
NRF_POWER->RAM[7].POWER = NRF52_ONRAM1_OFFRAM0;
#endif //NRF52
}
int PowerManager_Init(void)
{
BaseType_t ret;
// ret_code_t err_code;
ret = xTaskCreate(PowerManagerThreadEntry, "PMThread", 1*1024, NULL, POWER_MANAGER_THREAD_PRIORITY, &PowerManagerThreadHandle); //TODO: revisit priority
if (PowerManagerThreadHandle == NULL)
{
SEGGER_RTT_printf(0,"ERR: PowerManagerThreadHandle is null: %d\n\r",ret);
return -1;
}
PowerManagerEventGroup = xEventGroupCreate();
if(PowerManagerEventGroup == NULL)
{
SEGGER_RTT_printf(0,"ERR: PowerManagerEventGroup is null\n\r");
return -1;
}
PowerManagerTimer = xTimerCreate("PowerManagerTimer", pdMS_TO_TICKS(60000), pdTRUE, NULL, PowerManagerCallbackFunction);
if(PowerManagerTimer == NULL)
{
SEGGER_RTT_printf(0,"ERR: PowerManagerTimer is null\n\r");
return -1;
}
configure_ram_retention();
SEGGER_RTT_printf(0,"PowerManager Init OK\n\r");
return 0;
}
void PowerManager_ShutdownRequest(void)
{
if(PowerManagerEventGroup == NULL)
{
SEGGER_RTT_printf(0,"PowerManager not ready to shutdown\n\r");
return;
}
/* TODO: add any pre-shutdown code here */
BaseType_t higherPriorityTaskWoken;
xEventGroupSetBitsFromISR(PowerManagerEventGroup,POWER_MANAGER_SHUTDOWN_SIGNAL,&higherPriorityTaskWoken);
}
void PowerManager_OnCharger(void)
{
if(PowerManagerEventGroup == NULL)
{
return;
}
BaseType_t higherPriorityTaskWoken;
xEventGroupSetBitsFromISR(PowerManagerEventGroup,POWER_MANAGER_ON_CHARGER_SIGNAL,&higherPriorityTaskWoken);
}
void PowerManager_request_sleep(void)
{
if(PowerManagerEventGroup == NULL)
{
return;
}
xEventGroupSetBits(PowerManagerEventGroup,POWER_MANAGER_REQUEST_SLEEP);
}
void PowerManager_OffCharger(void)
{
if(PowerManagerEventGroup == NULL)
{
return;
}
BaseType_t higherPriorityTaskWoken;
xEventGroupSetBitsFromISR(PowerManagerEventGroup,POWER_MANAGER_OFF_CHARGER_SIGNAL,&higherPriorityTaskWoken);
}
/************************************ Local Functions ****************************/
static void PowerManagerThreadEntry(void * argument)
{
EventBits_t event = 0;
xTimerStart(PowerManagerTimer,0);
while(1)
{
SEGGER_RTT_printf(0," In PM thread \n\r");
event = xEventGroupWaitBits(PowerManagerEventGroup,POWER_MANAGER_REQUEST_SLEEP|POWER_MANAGER_ON_CHARGER_SIGNAL | POWER_MANAGER_OFF_CHARGER_SIGNAL | POWER_MANAGER_TIMER_SIGNAL | POWER_MANAGER_SHUTDOWN_SIGNAL, true, false, portMAX_DELAY);
if(event & POWER_MANAGER_SHUTDOWN_SIGNAL)
{
SEGGER_RTT_printf(0,"PM Thread: System Shutdown request\n\r");
LEDs_IndicateShutdown();
Cellular_Disable();
vTaskDelay(pdMS_TO_TICKS(250));
Silego_SystemShutdown();
vTaskDelay(pdMS_TO_TICKS(1000));
PowerManager_ShutdownRequest(); /* needed here in case last shutdown request did not work */
}
if(event & POWER_MANAGER_REQUEST_SLEEP)
{
if(rtc_config_flag)
{
rtc_config_flag = false;
rtc_config();
}
lfclk_config();
Accel_EnableWUM();
sleep = true;
led_turn_off();
SEGGER_RTT_printf(0,"PM Thread: Handling Sleep for both events\n\r");
vTaskSuspendAll();
while(sleep)
{
__SEV;
__WFE;
__WFE;
}
xTaskResumeAll();
if(rtc_flag)
{
Cellular_PublishHello();
}
SEGGER_RTT_printf(0,"Sleep Mode EXIT Event Triggered \n\r");
}
if(event & POWER_MANAGER_ON_CHARGER_SIGNAL)
{
SEGGER_RTT_printf(0,"PM Thread: Handling On Charger event\n\r");
//TODO: HandleOnChargerEvent();
}
if(event & POWER_MANAGER_OFF_CHARGER_SIGNAL)
{
SEGGER_RTT_printf(0,"PM Thread: Handling Off Charger event\n\r");
//TODO:HandleOffChargerEvent();
}
if(event & POWER_MANAGER_TIMER_SIGNAL)
{
//SEGGER_RTT_printf(0,"PM Thread: Handling Timer event\n\r");
uint16_t batt_percentage, batt_voltage;
batt_percentage = FuelGauge_GetPercentage();
batt_voltage = FuelGauge_GetVoltage();
SEGGER_RTT_printf(0,"Batt%% = %u, V=%u\n\r",(unsigned int)batt_percentage,(unsigned int)batt_voltage);
#ifdef SHUTDOWN_VIA_PERCENTAGE
if(batt_percentage < POWER_MANAGER_SHUTDOWN_PERCENTAGE)
{
SEGGER_RTT_printf(0,"Low battery percentage, requesting shutdown\n\r");
PowerManager_ShutdownRequest();
}
#elif defined(SHUTDOWN_VIA_VOLTAGE)
if(batt_voltage < POWER_MANAGER_SHUTDOWN_MILLIVOLTS)
{
SEGGER_RTT_printf(0,"Low battery voltage, requesting shutdown\n\r");
PowerManager_ShutdownRequest();
}
#endif
}
}
}
static void PowerManagerCallbackFunction(TimerHandle_t xTimer)
{
if(xTimer == PowerManagerTimer)
{
BaseType_t higherPriorityTaskWoken;
xEventGroupSetBitsFromISR(PowerManagerEventGroup, POWER_MANAGER_TIMER_SIGNAL, &higherPriorityTaskWoken);
}
}