Hi,
many thanks for your hint; I was successfully able to run an interrupt on BOD. The reason I wanted to achieve this is to save some data on poweroff (few bytes, nothing big). I tried using the internal flash with nvs, but it doesn't work.
Maybe the flash nvs is not reliable enough in a poweroff situation? Could someone take a look at my code and tell me if there is anything obviously flawed?
Code: Select all
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "nvs.h"
#include "soc/soc.h"
#include "soc/cpu.h"
#include "soc/rtc_cntl_reg.h"
#include "driver/rtc_cntl.h"
#ifdef CONFIG_BROWNOUT_DET_LVL
#define BROWNOUT_DET_LVL CONFIG_BROWNOUT_DET_LVL
#else
#define BROWNOUT_DET_LVL 5
#endif //CONFIG_BROWNOUT_DET_LVL
#define CONFIG_BROWNOUT_DET_LVL_SEL_5 1
void low_voltage_save() {
int32_t saved_counter = 0;
nvs_handle my_handle;
esp_err_t err = nvs_open("storage", NVS_READWRITE, &my_handle);
if (err != ESP_OK) {
ets_printf("Error (%s) opening NVS handle!\n", esp_err_to_name(err));
} else {
while(saved_counter < 100) {
saved_counter++;
err = nvs_set_i32(my_handle, "saved_counter", saved_counter);
err = nvs_commit(my_handle);
}
// Close
nvs_close(my_handle);
REG_WRITE(RTC_CNTL_INT_CLR_REG, RTC_CNTL_BROWN_OUT_INT_CLR);
esp_cpu_stall(!xPortGetCoreID());
ets_printf("\r\nBrownout detector was triggered\r\n\r\n");
//esp_restart_noos();
while(1) {
vTaskDelay(1 / portTICK_PERIOD_MS);
}
}
}
void brownout_init()
{
REG_WRITE(RTC_CNTL_BROWN_OUT_REG,
RTC_CNTL_BROWN_OUT_ENA /* Enable BOD */
| RTC_CNTL_BROWN_OUT_PD_RF_ENA /* Automatically power down RF */
/* Reset timeout must be set to >1 even if BOR feature is not used */
| (2 << RTC_CNTL_BROWN_OUT_RST_WAIT_S)
| (BROWNOUT_DET_LVL << RTC_CNTL_DBROWN_OUT_THRES_S));
ESP_ERROR_CHECK( rtc_isr_register(low_voltage_save, NULL, RTC_CNTL_BROWN_OUT_INT_ENA_M) );
printf("Initialized BOD\n");
REG_SET_BIT(RTC_CNTL_INT_ENA_REG, RTC_CNTL_BROWN_OUT_INT_ENA_M);
}
void app_main()
{
// Initialize NVS
brownout_init();
int32_t saved_counter = 0; // value will default to 0, if not set yet in NVS
esp_err_t err = nvs_flash_init();
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
// NVS partition was truncated and needs to be erased
// Retry nvs_flash_init
ESP_ERROR_CHECK(nvs_flash_erase());
err = nvs_flash_init();
}
ESP_ERROR_CHECK( err );
// Open
printf("\n");
printf("Opening Non-Volatile Storage (NVS) handle... ");
nvs_handle my_handle;
err = nvs_open("storage", NVS_READWRITE, &my_handle);
if (err != ESP_OK) {
printf("Error (%s) opening NVS handle!\n", esp_err_to_name(err));
} else {
printf("Done\n");
// Read
printf("Reading restart counter from NVS ... ");
err = nvs_get_i32(my_handle, "saved_counter", &saved_counter);
switch (err) {
case ESP_OK:
printf("Done\n");
printf("Restart counter = %d\n", saved_counter);
break;
case ESP_ERR_NVS_NOT_FOUND:
printf("The value is not initialized yet!\n");
break;
default :
printf("Error (%s) reading!\n", esp_err_to_name(err));
}
// Close
nvs_close(my_handle);
}
printf("\n");
while (1) {
printf("Restart counter = %d\n", saved_counter);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
And this is the output. I trigger the BOD by shutting down the power source, and the saved value appears uninitialized on the next reset. If I lower the voltage to 2.7V (without shutting it down completely) the BOD interrupt is triggered and the data is saved correctly.
Code: Select all
$ make monitor
MONITOR
--- idf_monitor on /dev/ttyUSB0 115200 ---
--- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
ets Jun 8 2016 00:22:57
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:4940
load:0x40078000,len:8920
load:0x40080400,len:5832
entry 0x400806f4
I (91) cpu_start: Pro cpu up.
I (91) cpu_start: Single core mode
I (92) heap_init: Initializing. RAM available for dynamic allocation:
I (95) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (101) heap_init: At 3FFB2808 len 0002D7F8 (181 KiB): DRAM
I (107) heap_init: At 3FFE0440 len 00003BC0 (14 KiB): D/IRAM
I (113) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (120) heap_init: At 40088268 len 00017D98 (95 KiB): IRAM
I (126) cpu_start: Pro cpu start user code
I (144) cpu_start: Starting scheduler on PRO CPU.
Initialized BOD
Opening Non-Volatile Storage (NVS) handle... Done
Reading restart counter from NVS ... The value is not initialized yet!
Restart counter = 0
Restart counter = 0
Restart counter = 0
Restart counter = 0
Restart counter = 0
Brownout detector was triggered
ets Jun 8 2016 00:22:57
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371
ets Jun 8 2016 00:22:57
rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:4940
load:0x40078000,len:8920
load:0x40080400,len:5832
entry 0x400806f4
I (92) cpu_start: Pro cpu up.
I (92) cpu_start: Single core mode
I (92) heap_init: Initializing. RAM available for dynamic allocation:
I (95) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (101) heap_init: At 3FFB2808 len 0002D7F8 (181 KiB): DRAM
I (108) heap_init: At 3FFE0440 len 00003BC0 (14 KiB): D/IRAM
I (114) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (120) heap_init: At 40088268 len 00017D98 (95 KiB): IRAM
I (127) cpu_start: Pro cpu start user code
I (144) cpu_start: Starting scheduler on PRO CPU.
Initialized BOD
Opening Non-Volatile Storage (NVS) handle... Done
Reading restart counter from NVS ... The value is not initialized yet!
Restart counter = 0
Restart counter = 0