Open ciniml opened 7 years ago
The question is that what happens to the ULP timer and the touch FSMS if the RTC_PERIPH is powered on.
Basically, depending on the time it takes to execute ULP program and some other factors, ULP coprocessor (and other things like touch and I2C) can start running from RTC_SLOW_CLK instead of RTC_FAST_CLK.
I think it should be possible to get this code to work without forcing RTC_PERIPH to be on, because when RTC_PERIPH is set to ESP_PD_OPTION_OFF, that basically means that the power domain is powered down automatically when it is not in use. Theoretically, when ULP is running some code (even in deep sleep), RTC_PERIPH should be powered on. It may be that there is some setting or register configuration missing in your code, will take a look at this issue.
Hmm... I thought both the RTC_I2C and the ULP wakeup timer belong to RTC_PERIPH
power domain. Is it correct?
I think the power domain option to power on it automatically is ESP_PD_OPTION_AUTO
not ESP_PD_OPTION_OFF
, according to the codes in get_power_down_flags
function.
The problem is that RTC_PERIPH
power domain is powered down automatically if either touch sensor wakeup trigger or ULP wakeup trigger is enabled.
Thus, I want to know why get_power_down_flags
function turns off RTC_PERIPH
power domain.
Hmm... I thought both the RTC_I2C and the ULP wakeup timer belong to RTC_PERIPH power domain. Is it correct?
No, this is not so. RTC_I2C does belong to RTC_PERIPH, but ULP timer is part of RTC_CNTL.
I think the power domain option to power on it automatically is ESP_PD_OPTION_AUTO not ESP_PD_OPTION_OFF, according to the codes in get_power_down_flags function.
Again, this is not so. In hardware, we can do three things with a power domain:
In software, there are three options: ON, OFF, AUTO:
AUTO
option means automatic selection of power down mode from software perspective, i.e. depending on the wakeup modes which are enabled by the application.We don't use the hardware "force power off" option at all, because "leave it to the FSMs" option disables power just as well and is more flexible.
Thus, I want to know why get_power_down_flags function turns off RTC_PERIPH power domain.
As mentioned in my previous reply, this is because of a clock switching issue. Normally, when RTC controller wakes up ULP or TOUCH FSMs, it first enables RTC_FAST_CLK. However, if RTC_PERIPH is powered on when this happens, then RTC_CNTL may (in some cases, not always) miss this step, and wake ULP or TOUCH up while RTC_FAST_CLK is not yet enabled. In this case, ULP or TOUCH will start running from RTC_SLOW_CLK. In case of ULP this only affects code execution time and (possibly) wakeup period. In case of TOUCH, this affects FSM timings, leading to incorrect readings. Because of this issue, we need to use ESP_PD_OPTION_OFF whenever ULP or TOUCH is enabled. In hardware, this translates into "let FSMs control power automatically". RTC_PERIPH should be powered up before ULP starts running, and gets powered down once it halts. The question is, why this is not happening in your example (if i understand you correctly, I2C does not work if you use ESP_PD_OPTION_OFF for RTC_PERIPH). As mentioned above, i need to do some debugging to figure this out.
Thanks you for your reply. I found that I did not understand about TOUCH FSMs correctly, which controls power up/down sequences automatically.
However, if RTC_PERIPH is powered on when this happens, then RTC_CNTL may (in some cases, not always) miss this step, and wake ULP or TOUCH up while RTC_FAST_CLK is not yet enabled. In this case, ULP or TOUCH will keep start running from RTC_SLOW_CLK. In case of ULP this only affects code execution time and (possibly) wakeup period.
I confirmed that if RTC_PERIPH
is powered on forcefully, frequency of I2C clock signal is sometimes slowed down compared to other times. (maybe it is because RTC_I2C is running with RTC_SLOW_CLK)
Actually, I2C_RD/WR instruction issues I2C transaction correctly even if the RTC_PERIPH
is not powered on forcefully.
(I checked that I2C SDA/SCL signal is input/output correctly with logic analyzer)
But without powering on RTC_PERIPH
forcefully, the SoC is not waken up by WAKE instruction.
I checked this with a simplified version of the ULP code to ensure WAKE instruction is always executed after I2C_RD instruction is executed.
.text
.global entry
entry:
i2c_rd 0x0b, 7, 0, 0
wake
halt
With this code the ULP also input/output I2C signals correctly. But the SoC does not wakeup.
Anyway, I'll recheck my code. Thank you for your help.
I have similar problem. In my case without:
esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
I2C signals are not visible on oscilloscope, but with this line (thanks for it !), I2C works perfectly fine.
In both cases after using any of i2c_rd/i2c_wr
instruction main cpu is unable to wake up using wake
instruction.
Moreover when i2c_rd
is my first instruction i can see on oscilloscope the moment of transition from the RTC_SLOW_CLK
to the RTC_FAST_CLK
, the i2c signal speeds up in the middle of i2c transmission. When I add wait 1000
before i2c_rd
everything works fine.
One note about usage of RTC_I2C in deep sleep: unlike other register blocks (such as RTC_IO), register contents of this block are not preserved when it is powered down. So you need to set all the configuration registers using ULP, not using the main CPU.
@igrr ok, thanks, that explains one thing, but still, i am unable to wake up main cpu after any usage of i2c_wr/i2c_rd
instructions. Neither ESP_PD_OPTION_ON
nor ESP_PD_OPTION_OFF
works. (Chip is ESP32D0WDQ6 (revision 0))
@Mucka @igrr just wondering if you were able to solve the wake up issue?
@xlfe No, I just written soft I2C on GPIOs without using i2c_wr/i2c_rd
instructions, so I can't say I solved issue, but it works now.
@Mucka is it possible share soft I2C GPIO code, I would appreciate that, cause so much trap under ULP I2C calling, that seems a brilliant way for this.
Yesterday, I use GPIO 0,2 under ULP I2C, I'm using register config in main CPU just like a friend here shared. but difference is i did a little adjustment as Mr. igrr suggested.
finally, i counld get both i2c_rd/i2c_wr work, and.... also it can calling wake instraction revoke main cpu. but, i still got a problem, I2C only read one byte from slave register which is two bytes, futher more that byte looks like lost a bit or shift something
i did a little adjustment as Mr. igrr suggested
@Pines what exactly is the adjustment? do you mean setting up RTC_I2C from ULP?
@Rojer, my friend, i've been through darkness on this little thing.
So, I would like tell you there is someone on earth build a Noah's Ark. it is https://github.com/tomtor/ulp-i2c (btw i'm think a i2c timeout is needed)
or maybe there is some other way, when you find out could you let me noticed.
@Pines ulp-i2c uses bit-banged i2c though, i am more interested in using the hardware unit as it should be more efficient (and i'm fine with 8-bit reads)
@igrr Can we close this issue?
@jack0c
If possible, keep it opened. I'm suffering issues about i2c hardware too.
As @Pines has said, using hardware unit seems to be more efficient. However, like our friends, I'm unable to wake up soc after I2C_RD / WR instructions.
In fact, it seems the ULP stops in I2C_RD/WR instructions. As I'm using a dev board (and so, I had to use TOUCH3 instead TOUCH1 for SCL), I made the following test: I tried to turn on the LED board just after I2C_WR instruction, when the LED remained off. If I tried just before the I2C_WR instruction, the LED turns on:
Here LED turns on:
WRITE_RTC_REG(RTC_GPIO_OUT_W1TS_REG, RTC_GPIO_OUT_DATA_W1TS_S+12, 1, 1)
I2C_WR 107, 0x80, 7, 0, 0
Here LED remains turned off:
I2C_WR 107, 0x80, 7, 0, 0
WRITE_RTC_REG(RTC_GPIO_OUT_W1TS_REG, RTC_GPIO_OUT_DATA_W1TS_S+12, 1, 1)
The same occurs to I2C_RD instructions.
Someone could use I2C_WR/RD instructions? And with TOUCH3 instead TOUCH1?
Thanks in advance, guys.
Hi everyone,
Sorry for the extended delay in responding.
It seems like the best solution for this would be if ESP-IDF could have a simple example using ULP hardware I2C and waking up the main CPU, which can then be used as a basis for other code.
I'm currently trying to use I2C_RD/WR instructions in the ULP to read some sensor outputs via I2C bus. And I found that the ULP processor does not wake up after executing I2C_RD/WR instructions.
Below is the program running on the ULP:
And in the main program, the RTC_I2C is configured before entering a sleep and the ULP wake up timer is configured to wake up every 10 seconds.
But I finally found that this code works correctly if the
RTC_PERIPH
power domain is configured to remain powered byesp-deep_sleep_pd_config
function.I checked the
get_power_down_flags
function incomponents/esp32/deep_sleep.c
and I found that theRTC_PERIPH
power domain is turned off forcefully if either touch sensor trigger or ULP trigger is enabled.In the
get_power_down_flags
function,s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH]
is set toESP_PD_OPTION_OFF
ifRTC_TOUCH_TRIG_EN
orRTC_ULP_TRIG_EN
is enabled, which results theRTC_PERIPH
power domain is turned off.And there are some comments about this operation in the code.
The question is that what happens to the ULP timer and the touch FSMS if the
RTC_PERIPH
is powered on. My program seems to work correctly and can read sensor value from I2C bus if theRTC_PERIPH
is powered by callingesp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON)
.