espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
13.34k stars 7.21k forks source link

Randomly getting stuck after waking up from Deep Sleep (IDFGH-3846) #5752

Closed sagar448 closed 4 years ago

sagar448 commented 4 years ago

Problem Description

Sorry for the long explanation.

We were using Arduino and our code involves interfacing with the two sensors, BME680 and TCS. We wake up every 5 minutes from deep sleep take readings, send them via esp now and go back to deep sleep. Issue was that after a random amount of wakeups the esp32 would just get stuck after waking up and not produce any error and be halted. Here is the Arduino issue, still not been resolved. https://github.com/espressif/arduino-esp32/issues/796

Seeing as how we never had this issue with ESP-IDF we decided to switch to ESP-IDf. Now it feels like the issue persists. It would get stuck and not wake up. The worst of it is that when we turn on verbose logging to get further information we have further complications. We had to change the partition offset from 0x8000 to 0x10000. When we did so, a line in our code esp_light_sleep_start() started giving us abort issues in regards to the lock.c file. Trying to do verbose with 0x8000 offset, causes issues. So we are unable to see the logs for when it gets stuck in deep sleep reset.

Expected Behavior

It should not get stuck after deep sleep reset.

Actual Behavior

After a random number of cycles it gets stuck in deep sleep reset.

Code to reproduce this issue

This is the main.c file

#include "nvs_flash.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

extern void sensorBeginRun();

void sensorBegin(void *pvParameter)
{
    sensorBeginRun();
    vTaskDelete( NULL );
}

void app_main()
{
    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 );

    xTaskCreatePinnedToCore(sensorBegin, "sensorBegin",  5*1024, NULL, 5, NULL, 0);
}

This is the sensor begin file

#include <time.h>
#include <string.h>
#include <esp_log.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include <fastmath.h>
#include <driver/i2c.h>
#include <bsec_integration.h>
#include <bsec_serialized_configurations_iaq.h>
#include "tcs.h"
#include "driver/rtc_io.h"
#include "esp_event_loop.h"
#include "nvs_flash.h"
#include "nvs.h"

const char* TAG = "Spacr";
static const char* sensor_binary = "sensor_blob";
uint16_t r, g, b, c, colorTemp, lux;
xTaskHandle xHandle = NULL;
int timeToSleep = 300*1000000;

void gotoSleep() {
    rtc_gpio_isolate(GPIO_NUM_0);
    rtc_gpio_isolate(GPIO_NUM_2);
    rtc_gpio_isolate(GPIO_NUM_5);
    rtc_gpio_isolate(GPIO_NUM_12);
    rtc_gpio_isolate(GPIO_NUM_15);
    esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF);
    rtc_gpio_isolate(GPIO_NUM_16);
    rtc_gpio_isolate(GPIO_NUM_13);
    ESP_LOGI(TAG, "Entering Deep Sleep...");
    esp_sleep_enable_timer_wakeup(timeToSleep);
    esp_deep_sleep_start();
}

int8_t bus_write(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data_ptr, uint16_t data_len)
{
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    assert(data_len > 0 && reg_data_ptr != NULL); // Safeguarding the assumptions
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (dev_addr << 1) | I2C_MASTER_WRITE, true);
    i2c_master_write_byte(cmd, reg_addr, true);
    i2c_master_write(cmd, reg_data_ptr, data_len, true);
    i2c_master_stop(cmd);
    esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, pdMS_TO_TICKS(1000));
    i2c_cmd_link_delete(cmd);
    // ESP_OK matches with the function success code (0)
    return (int8_t)ret;
}

int8_t bus_read(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data_ptr, uint16_t data_len)
{
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();

    assert(data_len > 0 && reg_data_ptr != NULL); // Safeguarding the assumptions
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (dev_addr << 1) | I2C_MASTER_WRITE, true);
    i2c_master_write_byte(cmd, reg_addr, true);
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (dev_addr << 1) | I2C_MASTER_READ, true);
    if (data_len > 1) {
        i2c_master_read(cmd, reg_data_ptr, data_len - 1, I2C_MASTER_ACK);
    }
    i2c_master_read_byte(cmd, reg_data_ptr + data_len - 1, I2C_MASTER_NACK);
    i2c_master_stop(cmd);
    esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, pdMS_TO_TICKS(1000));
    i2c_cmd_link_delete(cmd);
    return (int8_t)ret;
}

static void bme680_sleep(uint32_t t_ms)
{
    printf("Delay time %d\n", t_ms);
    if(t_ms > 1000 && count <3){
        printf("Count here\n");
        esp_sleep_enable_timer_wakeup(t_ms*1000);
        esp_light_sleep_start();

    }else if (t_ms > 1000 && count == 3){
        printf("Initialising tcs\n");
        esp_sleep_enable_timer_wakeup((t_ms-350)*1000);
        esp_light_sleep_start();

        begin();
        getRawData(&r, &g, &b, &c);
        colorTemp = calculateColorTemperature_dn40(r, g, b, c);
        lux = calculateLux(r, g, b, c);
        disable();
        printf("TCS Done\n");
        printf("LUX/4: %f\n", lux/4.0);

    }else{
        vTaskDelay(pdMS_TO_TICKS(t_ms));
    }
}

void output_ready(int64_t timestamp, float iaq, uint8_t iaq_accuracy, float temperature, float humidity,
     float pressure, float raw_temperature, float raw_humidity, float gas, bsec_library_return_t bsec_status,
     float static_iaq, float co2_equivalent, float breath_voc_equivalent)
{
    //prepare the data

}

uint32_t state_load(uint8_t *state_buffer, uint32_t n_buffer)
{

    nvs_handle my_handle;
    esp_err_t err = nvs_open("state", NVS_READWRITE, &my_handle);
    ESP_ERROR_CHECK( err );
    err = nvs_get_blob(my_handle, sensor_binary, state_buffer, &n_buffer);
    nvs_close(my_handle);
    if (err == ESP_OK){
        return n_buffer;
    }
    ESP_LOGW(TAG, "loading sensor binary blob failed with code %d", err);
    return 0;
}

void state_save(const uint8_t *state_buffer, uint32_t length)
{

    nvs_handle my_handle;
    esp_err_t err = nvs_open("state", NVS_READWRITE, &my_handle);
    ESP_ERROR_CHECK( err );

    err = nvs_set_blob(my_handle, sensor_binary, state_buffer, length);
    ESP_ERROR_CHECK( err );
    err = nvs_commit(my_handle);
    ESP_ERROR_CHECK(err);
    nvs_close(my_handle);
}

uint32_t config_load(uint8_t *config_buffer, uint32_t n_buffer)
{
    ESP_LOGI(TAG, "Loading configuration: buffer-size %d  config size %d", n_buffer, sizeof(bsec_config_iaq));
    assert(n_buffer >= sizeof(bsec_config_iaq));
    memcpy(config_buffer, bsec_config_iaq, sizeof(bsec_config_iaq));

    return sizeof(bsec_config_iaq);
}

int64_t GetTimestamp() {
  struct timeval tv;
  gettimeofday(&tv, NULL);
  int64_t tm = ((tv.tv_sec * 1000000LL) + tv.tv_usec);
  printf("The timestamp is %llu\n", tm);
  return tm;
}

void bsec_iot_loop(sleep_fct sleep, get_timestamp_us_fct get_timestamp_us, output_ready_fct output_ready,
                    state_save_fct state_save, uint32_t save_intvl)
{
//do some stuff
gotoSleep();
}

void sensorBeginRun() {
    rtc_gpio_hold_dis(GPIO_NUM_16);
    rtc_gpio_hold_dis(GPIO_NUM_13);
    i2c_init(I2C_NUM_0, GPIO_NUM_16, GPIO_NUM_13, 400000);
    printf("Initialised I2c\n");
    return_values_init ret;
    ret = bsec_iot_init(BSEC_SAMPLE_RATE_ULP, 0.0f, bus_write, bus_read, bme680_sleep, state_load, config_load);
    if (ret.bme680_status || ret.bsec_status)
    {
        printf("Could not initialise BME\n");
        esp_restart();
    }
    bsec_iot_loop(bme680_sleep, GetTimestamp, output_ready, state_save, 0);
}

Any help will be greatly appreciated.

It is also very hard to reproduce because it gets stuck sporadically and not after the same number of cycles.

Alvin1Zhang commented 4 years ago

Thanks for reporting.

Alvin1Zhang commented 4 years ago

@sagar448 Thanks for reporting, would you please help provide simple working example to reproduce this issue? Thanks.

zonehun commented 4 years ago

@Alvin1Zhang I think we had the same issue but not exactly in the ESP-IDF. We are using Arduino with the leatest versions (for the board and for the Arduino env itself).

We investigated that this issue is only happened when we are on battery power (3.3V). I do not want to falme this thread, so here is the link where I wrote the symptomps: https://github.com/espressif/arduino-esp32/issues/796#issuecomment-678757960

If I can try or check anything for you to help solving the problem please let me know. Thanks.

sagar448 commented 4 years ago

@zonehun stop hijacking my post please. Post your issue in the arduino section.

@Alvin1Zhang I cannot provide an example because its very random. But I think we have solved this issue. For anyone experiencing the same, we essentially stripped down the esp32 from the menuconfig. Disabling features we did not need.