Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
3 tasks done
NoNullptr opened this issue Nov 11, 2022 · 11 comments
Closed
3 tasks done

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

NoNullptr opened this issue Nov 11, 2022 · 11 comments
Labels
Resolution: Won't Do This will not be worked on Status: Done Issue is done internally Type: Bug bugs in IDF

Comments

@NoNullptr
Copy link

NoNullptr commented Nov 11, 2022

Answers checklist.

  • I have read the documentation ESP-IDF Programming Guide and the issue is not addressed there.
  • I have updated my IDF branch (master or release) to the latest version and checked that the issue is present there.
  • I have searched the issue tracker for a similar issue and not found a similar issue.

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

@NoNullptr NoNullptr added the Type: Bug bugs in IDF label Nov 11, 2022
@espressif-bot espressif-bot added the Status: Opened Issue is new label Nov 11, 2022
@github-actions github-actions bot changed the title Temperature sensor crashes RISC-V Temperature sensor crashes RISC-V (IDFGH-8723) Nov 11, 2022
@ESP-Marius
Copy link
Collaborator

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
Copy link
Author

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

@mickeyl
Copy link
Contributor

mickeyl commented Jan 4, 2024

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

@AxelLin
Copy link
Contributor

AxelLin commented May 20, 2024

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?

@clinnemann
Copy link

Hi, I am also very much interested in the topic. I also wasn't able to get it running.

Is there any update?

Best regards,
Christian

@mythbuster5
Copy link
Collaborator

Seems you not set REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_TSENS_DAC, tsens_dac);. Please check how esp-idf temperature sensor driver did.

@mythbuster5
Copy link
Collaborator

Some confidential information is not ready to be shown in trm.. Please refer to espressif driver. As for this issue we will close it because it's not an esp-idf issue. Feel free to comment it or reopen it if you got any update. Thanks!

@espressif-bot espressif-bot added Status: In Progress Work is in progress Status: Done Issue is done internally Resolution: Won't Do This will not be worked on and removed Status: Opened Issue is new Status: In Progress Work is in progress labels Dec 18, 2024
@clinnemann
Copy link

Hi @mythbuster5,

thanks very much for your answer. I already tried including "REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_TSENS_DAC, 15)";

Problem is that I get a linker error that REGI2C_WRITE_MASK is not found (undefined reference to `regi2c_ctrl_write_reg_mask')

Do you know how to solve that?

Best,
Christian

@mythbuster5
Copy link
Collaborator

Yes, because that is confidential. Not all information is allowed to expose to user according to espressif confidential policy

@mythbuster5
Copy link
Collaborator

The way to solve that is refer to idf driver *_ll.h function tells you how to use esp chip register.

@clinnemann
Copy link

clinnemann commented Jan 7, 2025

Hi mythbuster5,

thanks a lot for your help and support.

The relevant function seems to be uint32_t m_esp_rom_regi2c_write_mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb, uint8_t data). The problem is I only find the source code of this function in esp32-S2 documentation and while everything compiles fine it does not give me any valid temperature readings on my esp32-S3. I assume the problem is that a lot of definitions like for example I2C_RTC_SLAVE_ID_V are wrong (as they are taken from esp32-S2). For esp32-S3 I cannot find those variables.

Attached are the two functions that I use. They do compile fine but unfortunetaly they don't give me any valid temperature measurements UNLESS the main core runs. Do you have any guideance for me?

Best regards,
Christian

uint32_t m_esp_rom_regi2c_write_mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb, uint8_t data)
{
//assert(msb - lsb < 8); // Sicherstellen, dass die Breite der zu schreibenden Bits gültig ist

// Aktivieren des I2C-Blocks
i2c_rtc_enable_block(block);

// Register auslesen
uint32_t temp = ((block & I2C_RTC_SLAVE_ID_V) << I2C_RTC_SLAVE_ID_S)
                | (reg_add & I2C_RTC_ADDR_V) << I2C_RTC_ADDR_S;
REG_WRITE(I2C_RTC_CONFIG2, temp);

while (REG_GET_BIT(I2C_RTC_CONFIG2, I2C_RTC_BUSY));

temp = REG_GET_FIELD(I2C_RTC_CONFIG2, I2C_RTC_DATA);
uint32_t old = temp;

// Bits innerhalb des Registers setzen
temp &= ((~(0xFFFFFFFF << lsb)) | (0xFFFFFFFF << (msb + 1)));
temp = (((uint32_t)data & (~(0xFFFFFFFF << (msb - lsb + 1)))) << lsb) | temp;

// Modifiziertes Register zurückschreiben
temp = ((block & I2C_RTC_SLAVE_ID_V) << I2C_RTC_SLAVE_ID_S)
       | ((reg_add & I2C_RTC_ADDR_V) << I2C_RTC_ADDR_S)
       | ((0x1 & I2C_RTC_WR_CNTL_V) << I2C_RTC_WR_CNTL_S)
       | ((temp & I2C_RTC_DATA_V) << I2C_RTC_DATA_S);

REG_WRITE(I2C_RTC_CONFIG2, (uint32_t)temp);
while (REG_GET_BIT(I2C_RTC_CONFIG2, I2C_RTC_BUSY));

return old;
}

int read_temperature()
{
uint32_t ready;
int temperature;

SET_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_POWER_UP_FORCE);
SET_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_POWER_UP);

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);

REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_TSENS_DAC, 15);

ulp_riscv_delay_cycles(8000);

SET_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_DUMP_OUT);

ready = 0;
while (!ready) {
ready = REG_GET_FIELD(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_READY);
}

temperature = REG_GET_FIELD(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_OUT);
CLEAR_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_DUMP_OUT);

REG_WRITE(I2C_RTC_CONFIG2, temp);


REG_CLR_BIT(SENS_SAR_PERI_CLK_GATE_CONF_REG, SENS_TSENS_CLK_EN);
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);

return temperature;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Resolution: Won't Do This will not be worked on Status: Done Issue is done internally Type: Bug bugs in IDF
Projects
None yet
Development

No branches or pull requests

7 participants