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

Proper deepsleep as proposed upstream #4

Merged
merged 22 commits into from
Jun 7, 2017
Merged

Proper deepsleep as proposed upstream #4

merged 22 commits into from
Jun 7, 2017

Conversation

annejan
Copy link
Member

@annejan annejan commented Jun 7, 2017

Want to be ahead of the curve micropython#85

Very rough support, just enough to get machine.deepsleep() to
work properly
esp32/modmachine.c Added RTC object
esp32/modmachine.h Added RTC object

Just enough code for this to work on ESP32:

    import machine
    rtc = machine.RTC() # Need to implement this first!
    rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP) # syntactic sugar to match, probably a NOP
    rtc.alarm(rtc.ALARM0, 10000) # calls esp_deep_sleep_enable_timer_wakeup() in IDF
    machine.deepsleep() # calls esp_deep_sleep_start() in IDF
esp32/machine_pin.h: Exposes machine_pin_get_pin_object_ptr

New function so that the RTC wake mode configurations can
return the current Pin(s) that they're configured for.
These didn't seem to add much value, expecially since
returning Pin objects is nearly useless.
exp32/machine_rtc.h
exp32/modmachine.c

Removed the legacy compatibility 8266 code.
esp32/modmachine.c: format fixes
Conflicts:
	esp32/modmachine.c
	esp32/modmachine.h
@annejan annejan merged commit 865d5a7 into SHA2017-badge:esp32 Jun 7, 2017
@MrSurly
Copy link

MrSurly commented Jun 11, 2017

Would appreciate any feedback or bug reports.

@annejan
Copy link
Member Author

annejan commented Jun 11, 2017

Sure thing!
It seems to work well from my experience sofar 😀

@pacmac
Copy link

pacmac commented Jun 13, 2017

Sorry to be so dumb, but how can I merge this pull request into my local version so that I can test it ?

@annejan
Copy link
Member Author

annejan commented Jun 13, 2017

I used the pretty invasive method of pulling from @MrSurly's repo-branch with the command
git pull git@github.com:MrSurly/micropython-esp32.git dev-deepsleep
You can do this in a separate branch if you want . .

@pacmac
Copy link

pacmac commented Jun 13, 2017

@annejan - Thanks that worked, I know the basics, but struggle to understand github sometimes.

Just doing a quick test, this is the output, when the timer expires, I presume I need to check the reset reason, but why the "flash read err, 1000" ??

>>> import machine as m
>>> m.deepsleep(sleep_ms = 3000)
ets Jun  8 2016 00:22:57

rst:0x5 (DEEPSLEEP_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
Falling back to built-in command interpreter.
OK

@annejan
Copy link
Member Author

annejan commented Jun 13, 2017

I have not had that happening myself.
Could be you need to make erase and make deploy since it 'sounds' like a storage issue.

In our branch I've added a helper for reading the reset reason . .

STATIC mp_obj_t esp_rtc_get_reset_reason_(mp_obj_t cpu) {
  uint8_t cpu_id = mp_obj_get_int(cpu);
  if (cpu_id > 1) {
    return mp_obj_new_int(0);
  }
  uint8_t val = rtc_get_reset_reason(cpu_id);
  return mp_obj_new_int(val);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_rtc_get_reset_reason_obj,
                                 esp_rtc_get_reset_reason_);

And exporting the symbols like . .

{MP_ROM_QSTR(MP_QSTR_rtc_get_reset_reason), MP_ROM_PTR(&esp_rtc_get_reset_reason_obj)},

I use it like this . .

if esp.rtc_get_reset_reason(0) == 16:
    print('full reset')
else:
    print('wake from sleep')

http://esp32.info/docs/esp_idf/html/db/dc1/group__rtc__apis.html#ga826b88529aef76135636c06d408513aa

@pacmac
Copy link

pacmac commented Jun 13, 2017

Thanks, yes I did erase before I flashed it, also calling machine.reset() results in lots of this:

Guru Meditation Error of type IllegalInstruction occurred on core  0. Exception was unhandled.
... Lots & lots more of this..
Guru Meditation Error of type IllegalInstruction occurred on core  0. Exception was unhandled.
Guru Meditation Error of type IllegalInstruction occurred on core  0. Exception was unhandled.
Guru Meditation Error of type IllegalInstruction occurred on core  0. Exception was unhandled.
Guru Meditation Error of type IllegalInstruction occurred on core  0. Exception was unhandled.
Guru Meditation Error of type IllegalI�ets Jun  8 2016 00:22:57

rst:0x10 (RTCWDT_RTC_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0x00
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0008,len:8
load:0x3fff0010,len:3424
load:0x40078000,len:9460
ho 0 tail 12 room 4
load:0x40080000,len:252
entry 0x40080034

@MrSurly
Copy link

MrSurly commented Jun 13, 2017

In our branch I've added a helper for reading the reset reason . .

@annejan: That's a good idea (and I'm going to steal it), but I'm going to roll it into machine.reset_cause() so it matches mainline MP.

@annejan
Copy link
Member Author

annejan commented Jun 13, 2017

Sounds like I should move it there as well!

Thanks :)

@pacmac
Copy link

pacmac commented Jun 13, 2017

On the 8266 it's done like this:

if machine.reset_cause() == machine.DEEPSLEEP_RESET:
    print('woke from a deep sleep')
else:
    print('power on or hard reset')

@MrSurly
Copy link

MrSurly commented Jun 13, 2017 via email

@MrSurly
Copy link

MrSurly commented Jun 13, 2017

I'm working on a full PR for ESP32 upstream. I'll be done today, if you
can wait.

Ok, this is working, but I'm seeing the same issue as @pacmac, with the multiple illegal instruction errors. This results in an eventual WDT reset, so any call to machine.reset() will look like a WDT reset instead of ... something else.

Here: https://github.com/MrSurly/micropython-esp32/tree/dev-reset-cause

@pacmac
Copy link

pacmac commented Jun 18, 2017

OK, seems this is a known issue, ( espressif/esp-idf#113) seems to be caused by a slow wakeup of the flash device on the esp32-wroom, there is a work-around built into the IDF: CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY.

>>> import machine as m
>>> m.deepsleep(sleep_ms = 3000)
ets Jun  8 2016 00:22:57

rst:0x5 (DEEPSLEEP_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
Falling back to built-in command interpreter.
OK

Although this config setting appears in sdconfig.h, there does not appear to be any code that is looking for this config setting.

As I know next to nothing about the C language, how can I add this check to the code as per the example given in the IDF examples:

#if CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY > 0
    // ROM code has not started yet, so we need to set delay factor
    // used by ets_delay_us first.
    ets_update_cpu_frequency_rom(ets_get_detected_xtal_freq() / 1000000);
    // This delay is configured in menuconfig, it can be used to give
    // the flash chip some time to become ready.
    ets_delay_us(CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY);
#endif

@MrSurly
Copy link

MrSurly commented Jun 18, 2017

Although this config setting appears in sdconfig.h, there does not appear to be any code that is looking for this config setting.

It's used in components/esp32/deep_sleep.c, in the IDF itself.

Simply setting the value should do it.

@pacmac
Copy link

pacmac commented Jun 18, 2017

Do I set the value directly in sdkconfig.h ?

@MrSurly
Copy link

MrSurly commented Jun 19, 2017

Do I set the value directly in sdkconfig.h ?

Here's what I would do: Use make menuconfig in an empty IDF project, change only the option that might set this flag, then take whatever flags are actually changed, and apply to sdkconfig.h, noting that the format is slightly different from the actual sdkconfig file from the project.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants