espressif / esp-idf

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

Temperature sensor crashes RISC-V (IDFGH-8723) #10164

Open NoNullptr opened 1 year ago

NoNullptr commented 1 year ago

Answers checklist.

IDF version.

v5.1-dev-1626-g4b6d9c8ad3

Operating System used.

macOS

How did you build your project?

VS Code IDE

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

No response

Development Kit.

ESP32-S3-MINI-1U

Power Supply used.

USB

What is the expected behavior?

The Technical Reference Manual, chapter 39.4, states how to configure and read out the temperature sensor, namely:

Started by software, i.e. by CPU or ULP-RISC-V configuring related registers: – Set SENS_TSENS_POWER_UP_FORCE and SENS_TSENS_POWER_UP to enable the temperature sensor. – Wait for a while, then configure SENS_TSENS_DUMP_OUT. The output value gradually approaches the actual temperature linearly as the measurement time increases. – Wait for SENS_TSENS_READY, and read the conversion result from SENS_TSENS_OUT.

This translate roughly to this:

REG_SET_BIT(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_POWER_UP_FORCE);
REG_SET_BIT(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_POWER_UP);
ulp_riscv_delay_cycles(8000);
REG_SET_BIT(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_DUMP_OUT);
while (REG_GET_BIT(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_READY) == 0) {}
uint32_t raw_temperature = REG_GET_FIELD(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_OUT);

This code, however, is an infinite loop at while which effectively crashes the coprocessor. From the ESP-IDF driver one can see that also SENS_TSENS_CLK_EN and SENS_TSENS_XPD_FORCE need to be enabled, that is,

REG_SET_BIT(SENS_SAR_PERI_CLK_GATE_CONF_REG, SENS_TSENS_CLK_EN);
REG_SET_BIT(SENS_SAR_TSENS_CTRL2_REG, SENS_TSENS_XPD_FORCE);

need to be set, too. The documentation also misses that SENS_TSENS_DUMP_OUT should be reset after making a readout.

While this fixes the infinite loop, the read out values are wrong in deep sleep, always returning the value 1 or 127. I tried various register settings and compared various register values when running during deep sleep and during normal operation, but cannot find what needs to be set to read out the correct temperature during deep sleep; the technical reference manual is too lacking to be of much help.

What is the actual behavior?

An infinite loop when following the documentation. Wrong values after making the required fixes to not have an infinite loop.

Steps to reproduce.

Here's a minimal code that reads the temperature and pauses for about 1s in total ten times and then wakes up the main cpu:

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <soc/rtc_cntl_reg.h>
#include <ulp_riscv.h>
#include <ulp_riscv_utils.h>
#include <ulp_riscv_gpio.h>

#define N 10

static int i = 0;
static int j = 0;

int which;
uint32_t data0[N];
uint32_t data1[N];

int main()
{
    uint32_t temperature;

    REG_SET_BIT(SENS_SAR_PERI_CLK_GATE_CONF_REG, SENS_TSENS_CLK_EN);
    REG_SET_BIT(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_POWER_UP_FORCE);
    REG_SET_BIT(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_POWER_UP);
    REG_SET_BIT(SENS_SAR_TSENS_CTRL2_REG, SENS_TSENS_XPD_FORCE);

    ulp_riscv_delay_cycles(8000);

    REG_SET_BIT(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_DUMP_OUT);
    while (REG_GET_BIT(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_READY) == 0) {}
    REG_CLR_BIT(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_DUMP_OUT);
    temperature = REG_GET_FIELD(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_OUT);

    REG_CLR_BIT(SENS_SAR_TSENS_CTRL2_REG, SENS_TSENS_XPD_FORCE);
    REG_CLR_BIT(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_POWER_UP_FORCE);
    REG_CLR_BIT(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_POWER_UP);

    if (j == 0) {
        data0[i] = temperature;
    } else {
        data1[i] = temperature;
    }

    if (++i < N) {
        REG_SET_FIELD(RTC_CNTL_ULP_CP_TIMER_1_REG, RTC_CNTL_ULP_CP_TIMER_SLP_CYCLE, 150000);
        REG_SET_BIT(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN);
    } else {
        which = j;
        j = j == 0 ? 1 : 0;
        i = 0;
        ulp_riscv_wakeup_main_processor();
    }
    return 0;
}

Debug Logs.

No response

More Information.

No response

ESP-Marius commented 1 year ago

Hi @NoNullptr,

Your basic steps seem correct to me. I have an internal test branch for adding support that does the same, but unfortunately we discovered that the results seems to be incorrect after entering deep sleep. The current theory is that we might need to adjust some sleep parameters to be able to correctly use the temp sensor during sleep, so right now the support for ulp temp sensor is blocked on that.

The team responsible for the RTC part of the SW is looking at it, so as soon as this is resolved on their end we will be able to add support for it in IDF.

NoNullptr commented 1 year ago

Thank you for your response and looking into it, I am looking forward to having it resolved.

mickeyl commented 6 months ago

This has been stale for quite some time now – is there any progress on this issue?

AxelLin commented 1 month ago

Hi @NoNullptr,

Your basic steps seem correct to me. I have an internal test branch for adding support that does the same, but unfortunately we discovered that the results seems to be incorrect after entering deep sleep. The current theory is that we might need to adjust some sleep parameters to be able to correctly use the temp sensor during sleep, so right now the support for ulp temp sensor is blocked on that.

The team responsible for the RTC part of the SW is looking at it, so as soon as this is resolved on their end we will be able to add support for it in IDF.

@ESP-Marius So how is the status now? Any update?