espressif / esp-idf

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

A "LoadProhibited" error occurs when uploading data using ESP_Rainmaker. (IDFGH-11942) #13021

Closed EtrusUp closed 7 months ago

EtrusUp commented 7 months ago

Answers checklist.

IDF version.

v5.1.2

Espressif SoC revision.

ESP32-S3

Operating System used.

Windows

How did you build your project?

Command line with CMake

If you are using Windows, please specify command line type.

None

Development Kit.

ESP32-S3-SCH-V1.4

Power Supply used.

USB

What is the expected behavior?

Successfully created the rainmaker entity to collect my sensor data and upload it in real time!

What is the actual behavior?

It didn't work as expected, and whenever it ran to data upload, he had the following malfunction.

Steps to reproduce.

include

include

include "stdbool.h"

include "sdkconfig.h"

include "esp_log.h"

include "freertos/FreeRTOS.h"

include "freertos/timers.h"

include "freertos/task.h"

include "freertos/semphr.h"

include "driver/gpio.h"

include

include "onewire_bus.h"

include "ds18b20.h"

include "esp_adc/adc_cali.h"

include "esp_adc/adc_filter.h"

include "esp_adc/adc_continuous.h"

include "esp_adc/adc_cali_scheme.h"

include

include

include

include

include

define ADC_UNIT ADC_UNIT_1

define _ADC_UNIT_STR(unit) #unit

define ADC_UNIT_STR(unit) _ADC_UNIT_STR(unit)

define ADC_CONV_MODE ADC_CONV_SINGLE_UNIT_1

define ADC_ATTEN ADC_ATTEN_DB_6

define ADC_BIT_WIDTH SOC_ADC_DIGI_MAX_BITWIDTH

define ADC_DIGI_IIR_FILTER_COEFF ADC_DIGI_IIR_FILTER_COEFF_4

define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE2

define ADC_GET_CHANNEL(p_data) ((p_data)->type2.channel)

define ADC_GET_DATA(p_data) ((p_data)->type2.data)

/ This is the button that is used for toggling the power /

define BUTTON_GPIO 0

define BUTTON_ACTIVE_LEVEL 0

define WIFI_RESET_BUTTON_TIMEOUT 3

define FACTORY_RESET_BUTTON_TIMEOUT 10

define READ_LEN 256

define TOTAL_CHANNELS 1

define ONEWIRE_BUS_GPIO 5 // 指定温度传感器的 GPIO 口

define MAX_DS18B20_DEVICES 1

define voltage_fix 0.01

// DS18B20设备数量 static int num_ds18b20_devices = 0;

// 实时温度 TDS 浊度 水位 typedef struct { float temperature; float tds; float turbidity; float depth; } SensorData;

// Temperature compensation constants

define TEMP_COEFFICIENT 0.02 // Temperature compensation coefficient

define COMPENSATION_TEMPERATURE 25.0 // Standard compensation temperature

static adc_channel_t channel[TOTAL_CHANNELS] = {ADC_CHANNEL_3};

static const char *TAG = "WRM";

esp_rmaker_device_t *water_sensor_device;

// 1-Wire总线句柄 static onewire_bus_handle_t owb_bus = NULL;

adc_continuous_handle_t handle = NULL; adc_cali_handle_t cali_handle[TOTAL_CHANNELS]; adc_iir_filter_handle_t iir_filter_handle[TOTAL_CHANNELS];

// DS18B20设备句柄数组 static ds18b20_device_handle_t ds18b20_devices[MAX_DS18B20_DEVICES];

typedef struct { float temp; float tds; float deep; float turb; } water_data_t;

typedef enum { CHANNEL_TDS, CHANNEL_TURB, CHANNEL_DEEP } adc_channel_type_t;

SensorData raw_data_create() { SensorData raw_data = (SensorData *)calloc(1, sizeof(SensorData)); if (raw_data == NULL) { ESP_LOGE(TAG, "Allocate water data failed"); return NULL; } return raw_data; }

water_data_t water_data_create() { water_data_t water_data = (water_data_t *)calloc(1, sizeof(water_data_t));

if (water_data == NULL)
{
    ESP_LOGE(TAG, "Allocate water data failed");
    return NULL;
}

// 初始化操作(如果需要)
water_data->temp = 0.0f;
water_data->tds = 0.0f;
water_data->deep = 0.0f;
water_data->turb = 0.0f;

return water_data;

}

/ Report weather data to RainMaker cloud / esp_err_t rmaker_report_data(water_data_t *water_data) { if (water_data == NULL) { return ESP_FAIL; }

ESP_ERROR_CHECK(esp_rmaker_param_update_and_report(
    esp_rmaker_device_get_param_by_type(water_sensor_device, "温度"),
    esp_rmaker_float(water_data->temp)));

ESP_ERROR_CHECK(esp_rmaker_param_update_and_report(
    esp_rmaker_device_get_param_by_type(water_sensor_device, "TDS值"),
    esp_rmaker_float(water_data->tds)));

ESP_ERROR_CHECK(esp_rmaker_param_update_and_report(
    esp_rmaker_device_get_param_by_type(water_sensor_device, "浊度"),
    esp_rmaker_float(water_data->turb)));

ESP_ERROR_CHECK(esp_rmaker_param_update_and_report(
    esp_rmaker_device_get_param_by_type(water_sensor_device, "水位"),
    esp_rmaker_float(water_data->deep)));

/* Check the current weather text */
if ((water_data->temp) >= 40)
{
    ESP_ERROR_CHECK(esp_rmaker_raise_alert("水温超过40℃"));
}

if ((water_data->tds) >= 100)
{
    ESP_ERROR_CHECK(esp_rmaker_raise_alert("蓄水池TDS值异常"));
}

if ((water_data->turb) >= 1)
{
    ESP_ERROR_CHECK(esp_rmaker_raise_alert("蓄水池浊度超过1NTU"));
}

return ESP_OK;

}

/ Deallocates memory used by a weather data structure / esp_err_t water_data_delete(water_data_t *water_data) { if (water_data != NULL) { free(water_data); // 释放整个结构体所占用的内存 return ESP_OK; } else { ESP_LOGE(TAG, "water data is NULL"); return ESP_FAIL; } }

static int readAverageValue(int *dataArray, int arrayLength) { int sum = 0;

// Calculate the sum of all values in the array
for (int i = 0; i < arrayLength; i++)
{
    sum += dataArray[i];
}

// Calculate the average value
int averageValue = sum / arrayLength;

// Return the average value
return averageValue;

}

static void initialize_ds18b20() { // 初始化1-Wire总线 onewire_bus_config_t bus_config = { .bus_gpio_num = ONEWIRE_BUS_GPIO, }; onewire_bus_rmt_config_t rmt_config = { .max_rx_bytes = 10, // 1byte ROM command + 8byte ROM number + 1byte device command }; ESP_ERROR_CHECK(onewire_new_bus_rmt(&bus_config, &rmt_config, &owb_bus));

// 枚举DS18B20设备
onewire_device_iter_handle_t iter = NULL;
onewire_device_t next_device;
esp_err_t search_result = ESP_OK;

// 创建1-Wire设备迭代器,用于搜索设备
ESP_ERROR_CHECK(onewire_new_device_iter(owb_bus, &iter));

do
{
    search_result = onewire_device_iter_get_next(iter, &next_device);

    if (search_result == ESP_OK)
    { // 找到新设备,检查是否为DS18B20
        ds18b20_config_t ds18b20_cfg = {};

        // 检查设备是否为DS18B20,如果是,返回DS18B20句柄
        if (ds18b20_new_device(&next_device, &ds18b20_cfg, &ds18b20_devices[num_ds18b20_devices]) == ESP_OK)
        {
            num_ds18b20_devices++;
            ESP_LOGI(TAG, "Found an DS18B20 device, address: %016llX\n", next_device.address);
        }
        else
        {
            ESP_LOGW(TAG, "Found an unknown device, address: %016llX\n", next_device.address);
        }
    }
} while (search_result != ESP_ERR_NOT_FOUND);

ESP_ERROR_CHECK(onewire_del_device_iter(iter));

}

static void continuous_adc_init(adc_channel_t channel, uint8_t channel_num, adc_continuous_handle_t out_handle) { adc_continuous_handle_t handle = NULL;

adc_continuous_handle_cfg_t adc_config = {
    .max_store_buf_size = 1024,
    .conv_frame_size = READ_LEN,
};
ESP_ERROR_CHECK(adc_continuous_new_handle(&adc_config, &handle));

adc_continuous_config_t dig_cfg = {
    .sample_freq_hz = 1 * 1000,
    .conv_mode = ADC_CONV_MODE,
    .format = ADC_OUTPUT_TYPE,
};

adc_digi_pattern_config_t adc_pattern[SOC_ADC_PATT_LEN_MAX] = {0};
dig_cfg.pattern_num = channel_num;
for (int i = 0; i < channel_num; i++)
{
    adc_pattern[i].atten = ADC_ATTEN;
    adc_pattern[i].channel = channel[i] & 0x7;
    adc_pattern[i].unit = ADC_UNIT;
    adc_pattern[i].bit_width = ADC_BIT_WIDTH;
}
dig_cfg.adc_pattern = adc_pattern;
ESP_ERROR_CHECK(adc_continuous_config(handle, &dig_cfg));

*out_handle = handle;

}

void hardware_init() { // 初始化1-Wire总线和DS18B20设备 initialize_ds18b20();

// 初始化ADC
continuous_adc_init(channel, TOTAL_CHANNELS, &handle);

// 为每个通道单独创建校准和滤波器实例
for (int i = 0; i < TOTAL_CHANNELS; i++)
{
    // 校准初始化
    adc_cali_curve_fitting_config_t cali_config = {
        .unit_id = ADC_UNIT,
        .chan = channel[i],
        .atten = ADC_ATTEN,
        .bitwidth = ADC_BIT_WIDTH};
    ESP_ERROR_CHECK(adc_cali_create_scheme_curve_fitting(&cali_config, &cali_handle[i]));

    // 滤波器初始化
    adc_continuous_iir_filter_config_t iir_filter_config = {
        .unit = ADC_UNIT,
        .channel = channel[i],
        .coeff = ADC_DIGI_IIR_FILTER_COEFF};
    ESP_ERROR_CHECK(adc_new_continuous_iir_filter(handle, &iir_filter_config, &iir_filter_handle[i]));
    ESP_ERROR_CHECK(adc_continuous_iir_filter_enable(iir_filter_handle[i]));
}

// 开始ADC连续读取
ESP_ERROR_CHECK(adc_continuous_start(handle));

/*用于确保在初始化失败后,系统处于已知且稳定的状态,从而可以安全地尝试重新初始化或采取其他恢复措施
ESP_ERROR_CHECK(adc_continuous_stop(handle));
    ESP_ERROR_CHECK(adc_continuous_deinit(handle));
    */

app_reset_button_register(app_reset_button_create(BUTTON_GPIO, BUTTON_ACTIVE_LEVEL),
                          WIFI_RESET_BUTTON_TIMEOUT, FACTORY_RESET_BUTTON_TIMEOUT);

}

float get_realtime_temp(SensorData *raw_data) { // 触发温度转换并读取数据 for (int i = 0; i < num_ds18b20_devices; i++) { ESP_ERROR_CHECK(ds18b20_trigger_temperature_conversion(ds18b20_devices[i])); ESP_ERROR_CHECK(ds18b20_get_temperature(ds18b20_devices[i], &raw_data->temperature)); }

return raw_data->temperature;

}

int get_adc_Value(adc_channel_type_t channel_type) { esp_err_t ret; uint32_t ret_num = 0; int prv = 0;

uint8_t result[READ_LEN] = {0};
memset(result, 0xcc, READ_LEN);

char unit[] = ADC_UNIT_STR(ADC_UNIT);
int tds_data_realtime[READ_LEN / SOC_ADC_DIGI_RESULT_BYTES] = {0};
int turb_data_realtime[READ_LEN / SOC_ADC_DIGI_RESULT_BYTES] = {0};
int deep_data_realtime[READ_LEN / SOC_ADC_DIGI_RESULT_BYTES] = {0};

ret = adc_continuous_read(handle, result, READ_LEN, &ret_num, 0);
if (ret == ESP_OK)
{
    for (int i = 0; i < ret_num; i += SOC_ADC_DIGI_RESULT_BYTES)
    {
        adc_digi_output_data_t *p = (void *)&result[i];
        uint32_t chan_num = ADC_GET_CHANNEL(p);
        uint32_t data = ADC_GET_DATA(p);

        if (chan_num < SOC_ADC_CHANNEL_NUM(ADC_UNIT))
        {
            switch (chan_num)
            {
            case 3:
                tds_data_realtime[i / SOC_ADC_DIGI_RESULT_BYTES] = data;
                break;
            case 4:
                turb_data_realtime[i / SOC_ADC_DIGI_RESULT_BYTES] = data;
                break;
            case 5:
                deep_data_realtime[i / SOC_ADC_DIGI_RESULT_BYTES] = data;
                break;
            default:
                ESP_LOGW(TAG, "通道未配置!请重新配置通道");
                break;
            }
        }
        else
        {
            ESP_LOGW(TAG, "Invalid data [%s_%" PRIu32 "_%" PRIx32 "]", unit, chan_num, data);
        }
    }
}
else if (ret == ESP_ERR_TIMEOUT)
{
    ESP_LOGW(TAG, "ADC值获取超时");
    return -1; // 或其他适当的错误代码
}

// 根据传入的通道类型返回相应的平均值
switch (channel_type)
{
case CHANNEL_TDS:
    return prv = readAverageValue(tds_data_realtime, READ_LEN / SOC_ADC_DIGI_RESULT_BYTES);
case CHANNEL_TURB:
    return prv = readAverageValue(turb_data_realtime, READ_LEN / SOC_ADC_DIGI_RESULT_BYTES);
case CHANNEL_DEEP:
    return prv = readAverageValue(deep_data_realtime, READ_LEN / SOC_ADC_DIGI_RESULT_BYTES);
default:
    return -1; // 或其他适当的错误代码
}

}

float get_tds_Value(SensorData *raw_data) { int calibrated_voltage = 0; float voltageV = 0;

int AverageValue = get_adc_Value(CHANNEL_TDS);

/* Convert the raw data to calibrated voltage */
ESP_ERROR_CHECK(adc_cali_raw_to_voltage(cali_handle[0], AverageValue, &calibrated_voltage));

// Convert voltage from mV to V for the TDS calculation
if (calibrated_voltage == 0)
{
    voltageV = calibrated_voltage / 1000.0;
}
else
{
    voltageV = calibrated_voltage / 1000.0 + voltage_fix;
}

// Calculate the TDS value based on the voltage using the calibration formula
// provided by DFRobot for their Gravity TDS sensor.
float compensationCoefficient = 1.0 + TEMP_COEFFICIENT * (raw_data->temperature - COMPENSATION_TEMPERATURE);
float compensationVolatge = voltageV / compensationCoefficient;

// Temperature compensation
raw_data->tds = (133.42 * compensationVolatge * compensationVolatge * compensationVolatge - 255.86 * compensationVolatge * compensationVolatge + 857.39 * compensationVolatge) * 0.5;

return raw_data->tds;

}

float get_turb_Value(SensorData *raw_data) { int AverageValue = get_adc_Value(CHANNEL_TURB); raw_data->turbidity = 0;

return raw_data->turbidity;

}

float get_deep_Value(SensorData *raw_data) { int AverageValue = get_adc_Value(CHANNEL_DEEP); raw_data->depth = 0;

return raw_data->depth;

}

esp_err_t get_raw_Value(water_data_t *water_data) { if (water_data == NULL) { ESP_LOGE(TAG, "water_data 指针为空"); return ESP_ERR_INVALID_ARG; }

SensorData *raw_data = raw_data_create();

// 从传感器获取数据
water_data->temp = get_realtime_temp(raw_data);
vTaskDelay(pdMS_TO_TICKS(100)); // 延时 100 毫秒
water_data->tds = get_tds_Value(raw_data);
vTaskDelay(pdMS_TO_TICKS(100)); // 延时 100 毫秒
water_data->deep = get_deep_Value(raw_data);
vTaskDelay(pdMS_TO_TICKS(100)); // 延时 100 毫秒
water_data->turb = get_turb_Value(raw_data);

if (water_data->temp < -256 || water_data->temp > 100)
{
    ESP_LOGW(TAG, "温度值不在合理范围内");
    return ESP_FAIL;
}
if (water_data->tds < 0)
{
    ESP_LOGW(TAG, "TDS值不在合理范围内");
    return ESP_FAIL;
}
if (water_data->turb < 0)
{
    ESP_LOGW(TAG, "浊度值不在合理范围内");
    return ESP_FAIL;
}
if (water_data->deep < 0)
{
    ESP_LOGW(TAG, "水位值不在合理范围内");
    return ESP_FAIL;
}

return ESP_OK;

}

void get_date_task(void pvParameters) { while (1) { water_data_t water_data = water_data_create();

    ESP_ERROR_CHECK(get_raw_Value(water_data));
    ESP_LOGI(TAG, "水温:%.2f TDS值: %.2f 浊度: %.2f 水位: %.2f", water_data->temp, water_data->tds, water_data->turb, water_data->deep);
    ESP_ERROR_CHECK(rmaker_report_data(water_data));
    ESP_LOGI(TAG, "水温:%.2f TDS值: %.2f 浊度: %.2f 水位: %.2f", water_data->temp, water_data->tds, water_data->turb, water_data->deep);
    ESP_ERROR_CHECK(water_data_delete(water_data));

    vTaskDelay(pdMS_TO_TICKS(10000));
}
vTaskDelete(NULL);

}

void app_main(void) {

hardware_init();

// Initialize NVS.
esp_err_t err = nvs_flash_init();
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND)
{
    ESP_ERROR_CHECK(nvs_flash_erase());
    err = nvs_flash_init();
}
ESP_ERROR_CHECK(err);

/* Initialize Wi-Fi. Note that, this should be called before esp_rmaker_node_init()
 */
app_wifi_init();

esp_rmaker_config_t rainmaker_cfg = {
    .enable_time_sync = true,
};
esp_rmaker_node_t *node = esp_rmaker_node_init(&rainmaker_cfg, "ESP RainMaker Device", "Temperature Sensor");

/* Create a device and add the relevant parameters to it */
water_sensor_device = esp_rmaker_temp_sensor_device_create("蓄水池水况", NULL, 0);

esp_rmaker_param_t *temp_param = esp_rmaker_param_create("温度", NULL, esp_rmaker_float(0), PROP_FLAG_READ);
esp_rmaker_param_t *tds_param = esp_rmaker_param_create("TDS值", NULL, esp_rmaker_float(0), PROP_FLAG_READ);
esp_rmaker_param_t *turb_param = esp_rmaker_param_create("浊度", NULL, esp_rmaker_float(0), PROP_FLAG_READ);
esp_rmaker_param_t *deep_param = esp_rmaker_param_create("水位", NULL, esp_rmaker_float(0), PROP_FLAG_READ);

esp_rmaker_device_add_param(water_sensor_device, temp_param);
esp_rmaker_device_add_param(water_sensor_device, tds_param);
esp_rmaker_device_add_param(water_sensor_device, turb_param);
esp_rmaker_device_add_param(water_sensor_device, deep_param);

esp_rmaker_device_assign_primary_param(water_sensor_device, deep_param);

esp_rmaker_node_add_device(node, water_sensor_device);

/* Start 

tds.zip the ESP RainMaker Agent */ esp_rmaker_start();

app_wifi_start(POP_TYPE_RANDOM);

vTaskDelay(pdMS_TO_TICKS(60000));

xTaskCreate(&get_date_task, "get_date_task", 48 * 1024, NULL, 5, NULL);

} As you can see I was able to increase the stack depth when creating the task, but unfortunately it still triggers the issue. You can see my log reaction before and after uploading the data in the task "get_date_task", my program completes this part

ESP_ERROR_CHECK(get_raw_Value(water_data)); ESP_LOGI(TAG, "水温:%.2f TDS值: %.2f 浊度: %.2f 水位: %.2f", water_data->temp, water_data->tds, water_data->turb, water_data->deep); without any problem, but at this part

ESP_ERROR_CHECK(rmaker_report_data(water_data)); ESP_LOGI(TAG, "水温:%.2f TDS值: %.2f 浊度: %.2f 水位: %.2f", water_data->temp, water_data->tds, water_data->turb, water_data->deep); the program sends a fault with the following error code.

Guru Meditation Error: Core 0 panic'ed (LoadProhibited). Exception was unhandled.

Core 0 register dump: PC : 0x4005544b PS : 0x00060e30 A0 : 0x8200e705 A1 : 0x3fcd6530 0x4005544b: strcmp in ROM

A2 : 0x00000000 A3 : 0x3c0f6d28 A4 : 0x3fcd6560 A5 : 0x0000000c A6 : 0x3fcd6130 A7 : 0xb33fffff A8 : 0x00000065 A9 : 0x000000e6 A10 : 0x00000003 A11 : 0xffffffff A12 : 0x00000050 A13 : 0x3fcd63e0 A14 : 0x3fcd61e0 A15 : 0x00000006 SAR : 0x00000020 EXCCAUSE: 0x0000001c EXCVADDR: 0x00000000 LBEG : 0x420d1d9d LEND : 0x420d1db8 LCOUNT : 0x00000000
0x420d1d9d: __lshift at /builds/idf/crosstool-NG/.build/HOST-x86_64-w64-mingw32/xtensa-esp32s3-elf/src/newlib/newlib/libc/stdlib/mprec.c:486 (discriminator 1)

0x420d1db8: __lshift at /builds/idf/crosstool-NG/.build/HOST-x86_64-w64-mingw32/xtensa-esp32s3-elf/src/newlib/newlib/libc/stdlib/mprec.c:486

Backtrace: 0x40055448:0x3fcd6530 |<-CORRUPTED 0x40055448: strcmp in ROM

ELF file SHA256: 42027b2a48f5e6de

Debug Logs.

I'm sorry I don't know how to find this log, this error code is all I can see.
/*
Guru Meditation Error: Core  0 panic'ed (LoadProhibited). Exception was unhandled.

Core  0 register dump:
PC      : 0x4005544b  PS      : 0x00060e30  A0      : 0x8200e705  A1      : 0x3fcd6530
0x4005544b: strcmp in ROM

A2      : 0x00000000  A3      : 0x3c0f6d28  A4      : 0x3fcd6560  A5      : 0x0000000c
A6      : 0x3fcd6130  A7      : 0xb33fffff  A8      : 0x00000065  A9      : 0x000000e6
A10     : 0x00000003  A11     : 0xffffffff  A12     : 0x00000050  A13     : 0x3fcd63e0
A14     : 0x3fcd61e0  A15     : 0x00000006  SAR     : 0x00000020  EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000000  LBEG    : 0x420d1d9d  LEND    : 0x420d1db8  LCOUNT  : 0x00000000  
0x420d1d9d: __lshift at /builds/idf/crosstool-NG/.build/HOST-x86_64-w64-mingw32/xtensa-esp32s3-elf/src/newlib/newlib/libc/stdlib/mprec.c:486 (discriminator 1)

0x420d1db8: __lshift at /builds/idf/crosstool-NG/.build/HOST-x86_64-w64-mingw32/xtensa-esp32s3-elf/src/newlib/newlib/libc/stdlib/mprec.c:486

Backtrace: 0x40055448:0x3fcd6530 |<-CORRUPTED
0x40055448: strcmp in ROM

ELF file SHA256: 42027b2a48f5e6de
*/
I've provided my source file and hopefully it will help assist me in solving the problem. Appreciate it!

More Information.

No response

Alvin1Zhang commented 7 months ago

Seems a duplicate of https://github.com/espressif/esp-rainmaker/issues/298, will close this one, and let us track in https://github.com/espressif/esp-rainmaker/issues/298. Thanks.