Page 2 of 3
Re: Why can MicroPython not use the ULP WAKE instruction
Posted: Thu Dec 03, 2020 9:49 pm
by ellisjr
@mattyt
Oh dear, I've looked at the code you referred to and it's fairly much mumbo-jumbo to me
I guess we need to add another bool called
wake to the typedef for machine_rtc_config and also another static object similar to
esp32_wake_on_touch called
esp32_wake but I don't see where these connect to the "real world" which for the ulp timer wakeup API is
here and for our new ULP wakeup for the WAKE instruction would be
this.
I so want this to work but I fear that I am going to need so much help that my input will be negligible. However, I can see that the code required is small and so maybe I
can stumble through it with some help
After all, I did used to write machine code for Z80 before assemblers were available to joe public, but that was (sigh) a long time ago
and had the benefit of being essentially simple even if a lot of care was required
Anyway, still waiting to find non-V0/V1 chip dev boards, so there's no rush I guess...
Re: Why can MicroPython not use the ULP WAKE instruction
Posted: Sat Dec 12, 2020 11:10 pm
by mattyt
Re-reading the ESP-IDF, I've definitely over-stated this:
The IDF says this:
ESP-IDF wrote:
In revisions 0 and 1 of the ESP32, ULP wakeup source cannot be used when RTC_PERIPH power domain is forced to be powered on (ESP_PD_OPTION_ON) or when ext0 wakeup source is used.
Those are fairly specific conditions so I think v0 and v1 chips should work ok.
Re: Why can MicroPython not use the ULP WAKE instruction
Posted: Sun Dec 13, 2020 12:04 am
by mattyt
ellisjr wrote: ↑Thu Dec 03, 2020 9:49 pm
Oh dear, I've looked at the code you referred to and it's fairly much mumbo-jumbo to me
Some of that code was a bit...hairy.
Having briefly read a little more I think all we need to do is enable the ULP to wake up the CPU and then put the CPU into a deep sleep (after running code on the ULP that will trigger a WAKE).
I think this means that the only missing link is to enable the ULP to wake the CPU. That's just an IDF call that can be exposed like this:
Code: Select all
diff --git a/ports/esp32/modesp32.c b/ports/esp32/modesp32.c
index 28d1762d2..8d304d4a3 100644
--- a/ports/esp32/modesp32.c
+++ b/ports/esp32/modesp32.c
@@ -45,6 +45,13 @@
#include "modmachine.h"
#include "machine_rtc.h"
#include "modesp32.h"
+#include "esp_sleep.h"
+
+STATIC mp_obj_t esp32_enable_ulp_wakeup(void) {
+ return mp_obj_new_int(esp_sleep_enable_ulp_wakeup())
+}
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp32_raw_temperature_obj, esp32_raw_temperature);
STATIC mp_obj_t esp32_wake_on_touch(const mp_obj_t wake) {
@@ -173,6 +180,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_idf_heap_info_obj, esp32_idf_heap_info);
STATIC const mp_rom_map_elem_t esp32_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_esp32) },
+ { MP_ROM_QSTR(MP_QSTR_enable_ulp_wakeup), MP_ROM_PTR(&esp32_enable_ulp_wakeup_obj) },
{ MP_ROM_QSTR(MP_QSTR_wake_on_touch), MP_ROM_PTR(&esp32_wake_on_touch_obj) },
{ MP_ROM_QSTR(MP_QSTR_wake_on_ext0), MP_ROM_PTR(&esp32_wake_on_ext0_obj) },
{ MP_ROM_QSTR(MP_QSTR_wake_on_ext1), MP_ROM_PTR(&esp32_wake_on_ext1_obj) },
That would enable you to do something like:
Code: Select all
import machine
import esp32
# Allow ESP32 to be woken by ULP WAKE opcode
esp32.enable_ulp_wakeup()
# Load and run pre-compiled ULP binary
ulp = esp32.ULP()
f = open('ulp_main.bin')
binary = f.read()
load_addr, entry_addr = 0, 4
ulp.load_binary(load_addr, binary)
ulp.run(entry_addr)
# Put ESP32 to sleep, relying on the ULP to wake
machine.deepsleep()
# Note that machine.wake_reason() == machine.ULP_WAKE
Now, a big disclaimer; I haven't tested
any of that. I'm going to have to leave that to you!
Re: Why can MicroPython not use the ULP WAKE instruction
Posted: Tue Dec 15, 2020 2:26 pm
by ellisjr
Those are fairly specific conditions so I think v0 and v1 chips should work ok.
Yes, I think I just got there yesterday, empirically, when I bit the bullet and installed the whole ESP-IDF thing and worked through an example to use the WAKE instruction (with the ADC as it happens) and it all works just fine, so the revision 1 chips clearly work. I now have enough dev boards, all revision 1 from different suppliers, to wallpaper my office
So, now knowing I have h/w that will allow me to test, I will look at your (no doubt excellent) code and see what I can do with it!
Thank you!
Just an interesting titbit: When I run that ULP ADC program and I power the ESP32 from an Anker USB battery pack, after 1 minute, the battery pack switches off the juice. I assume that the current is
so low that it thinks nothing is connected!? Cases with battery holders have been ordered for the next phase of testing
The light at the end of the tunnel has reappeared...
Re: Why can MicroPython not use the ULP WAKE instruction
Posted: Tue Dec 15, 2020 4:12 pm
by kevinkk525
ellisjr wrote: ↑Tue Dec 15, 2020 2:26 pm
Just an interesting titbit: When I run that ULP ADC program and I power the ESP32 from an Anker USB battery pack, after 1 minute, the battery pack switches off the juice. I assume that the current is
so low that it thinks nothing is connected!? Cases with battery holders have been ordered for the next phase of testing
yeah that happens with most battery packs sadly. Had that problem with my esp8266 too
Apparently you can force them to stay on if you make consumption peaks in a certain interval. But didn't quite work with my battery pack.. Ultimately I gave up on that
Re: Why can MicroPython not use the ULP WAKE instruction
Posted: Tue Dec 15, 2020 5:31 pm
by pythoncoder
Yup, me too. Fixed (or rather bodged) with a resistor between the 5V supply and gnd. ISTR 47Ω 0.5W did the trick with mine.
Re: Why can MicroPython not use the ULP WAKE instruction
Posted: Sun Dec 20, 2020 2:53 pm
by clone
mattyt wrote: ↑Sun Dec 13, 2020 12:04 am
Now, a big disclaimer; I haven't tested
any of that. I'm going to have to leave that to you!
Thanks, there is one mistake in the patch, it should be:
Code: Select all
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp32_enable_ulp_wakeup_obj, esp32_enable_ulp_wakeup);
I can confirm that the ULP wake-up works on patched firmware after calling esp32.enable_ulp_wakeup()
To test if the system is ready for wake up and avoid unnecessary interrupts the
Code: Select all
READ_RTC_FIELD(RTC_CNTL_LOW_POWER_ST_REG, RTC_CNTL_RDY_FOR_WAKEUP)
can be written as
So the ULP code can be compiled using py-esp32-ulp that lacks of macro support.
Where 0x3ff480c0 =
DR_REG_RTCCNTL_BASE +
0xc0:
Code: Select all
> hex(0x3ff48000 + 0xc0)
'0x3ff480c0'
It would be nice if this change could be added to the official micropython source code among adc1_ulp_enable() (and other ULP related calls if there is any)
Re: Why can MicroPython not use the ULP WAKE instruction
Posted: Mon Dec 21, 2020 4:42 pm
by ellisjr
@clone
Welcome to the party! Or should I say, thank goodness, the cavalry have arrived! I have spent three days getting to the point where I can build Micropython, so that I could test Mattyt's code, but I have finally
just done it. Many traps for the unwary/uninitiated...
So, I will also test the change and add to the calls for it to be added to the official release.
Also, I am impressed that you could work out the raw reg_rd instruction instead of the macros; I tried it with no success, but somehow that doesn't surprise me
That IS very useful though so that we can use py-esp32-ulp with ease.
Re: Why can MicroPython not use the ULP WAKE instruction
Posted: Wed Dec 23, 2020 4:27 pm
by ellisjr
@mattyt
So, I built MP with the changes as debugged by @clone and of course, it works perfectly. Thank you both!
I'm guessing that this is a silly question, but why can't esp32.enable_ulp_wakeup() take a Boolean to enable and
disable the use of the ULP WAKE instruction? It would seem good to be able to turn it off as well as on, but I guess maybe when I start building real applications I might see why one would not need to turn it off (though on that basis, why is it not always on?
)
Anyway, if we ignore my NOOB question this all seems good and I would welcome it in the standard build asap.
Re: Why can MicroPython not use the ULP WAKE instruction
Posted: Tue Dec 29, 2020 6:01 pm
by clone
ellisjr wrote: ↑Wed Dec 23, 2020 4:27 pm
I'm guessing that this is a silly question, but why can't esp32.enable_ulp_wakeup() take a Boolean to enable and
disable the use of the ULP WAKE instruction? It would seem good to be able to turn it off as well as on, but I guess maybe when I start building real applications I might see why one would not need to turn it off (though on that basis, why is it not always on?
)
There is no disable_ulp_wakeup in official API, because you have to call
enable_ulp_wakeup() every time before you go to deep sleep if you want to enable ULP wake.
Probably
esp32.wake_from_ulp(wake: bool) would be the closest to current micropython function names: there is already a
esp32.wake_on_touch(wake: bool) function to call
esp_sleep_enable_touchpad_wakeup(void).
Probably it will require more modification based on current
esp32.wake_on_touch that stores the enable/disable status in rtc memory to preserve it between restarts.