Skip to content

Commit 0cb4308

Browse files
committed
ESP32: add support to light sleep
Allow putting ESP32 to light sleep, and wake it up using a GPIO or a timer. Signed-off-by: Davide Bettio <[email protected]>
1 parent 38d2fca commit 0cb4308

File tree

4 files changed

+140
-1
lines changed

4 files changed

+140
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010

1111
- Added `lists:keysort/2`
1212
- Added `lists:merge/2,3`
13+
- [ESP32] Added support to light sleep (`esp:light_sleep/0`) and to GPIO and timer wakeup from
14+
light sleep.
1315

1416
### Fixed
1517

libs/eavmlib/src/esp.erl

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@
3838
sleep_enable_ulp_wakeup/0,
3939
deep_sleep/0,
4040
deep_sleep/1,
41+
light_sleep/0,
42+
gpio_wakeup_enable/2,
43+
sleep_enable_gpio_wakeup/0,
44+
sleep_enable_timer_wakeup_us/1,
4145
mount/4,
4246
umount/1,
4347
nvs_fetch_binary/2,
@@ -272,6 +276,47 @@ sleep_enable_ulp_wakeup() ->
272276
deep_sleep() ->
273277
erlang:nif_error(undefined).
274278

279+
%%-----------------------------------------------------------------------------
280+
%% @doc Put the esp32 into light sleep.
281+
%% This function returns ok on success after the sleep.
282+
%% Program is NOT restarted and wake up reason can be inspected to determine how
283+
%% the esp32 was woken up.
284+
%% @end
285+
%%-----------------------------------------------------------------------------
286+
-spec light_sleep() -> ok | error.
287+
light_sleep() ->
288+
erlang:nif_error(undefined).
289+
290+
%%-----------------------------------------------------------------------------
291+
%% @doc Configure given GPIO as light sleep wakeup pin
292+
%% @param GPIONum the GPIO number
293+
%% @param logic level, either low or high that triggers the wakeup condition
294+
%% @returns `ok | error'
295+
%% @end
296+
%%-----------------------------------------------------------------------------
297+
-spec gpio_wakeup_enable(GPIONum :: non_neg_integer(), Level :: low | high) -> ok | error.
298+
gpio_wakeup_enable(_GPIONum, _Level) ->
299+
erlang:nif_error(undefined).
300+
301+
%%-----------------------------------------------------------------------------
302+
%% @doc Enable waking up from light sleep using a configured GPIO
303+
%% @returns `ok | error'
304+
%% @end
305+
%%-----------------------------------------------------------------------------
306+
-spec sleep_enable_gpio_wakeup() -> ok | error.
307+
sleep_enable_gpio_wakeup() ->
308+
erlang:nif_error(undefined).
309+
310+
%%-----------------------------------------------------------------------------
311+
%% @doc Enable waking up from light sleep using a timer
312+
%% @param time before wakeup in microseconds
313+
%% @returns `ok | error'
314+
%% @end
315+
%%-----------------------------------------------------------------------------
316+
-spec sleep_enable_timer_wakeup_us(SleepUS :: non_neg_integer()) -> ok | error.
317+
sleep_enable_timer_wakeup_us(_SleepUS) ->
318+
erlang:nif_error(undefined).
319+
275320
%%-----------------------------------------------------------------------------
276321
%% @param SleepMS time to deep sleep in milliseconds
277322
%% @doc Put the esp32 into deep sleep.

src/platforms/esp32/components/avm_sys/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ idf_component_register(
4545
SRCS ${AVM_SYS_COMPONENT_SRCS}
4646
INCLUDE_DIRS "include"
4747
REQUIRES "spi_flash" "soc" "newlib" "pthread" "vfs" "mbedtls" ${ADDITIONAL_COMPONENTS}
48-
PRIV_REQUIRES "libatomvm" "esp_timer" ${ADDITIONAL_PRIV_REQUIRES}
48+
PRIV_REQUIRES "libatomvm" "driver" "esp_timer" ${ADDITIONAL_PRIV_REQUIRES}
4949
)
5050

5151
target_compile_features(${COMPONENT_LIB} INTERFACE c_std_11)

src/platforms/esp32/components/avm_sys/platform_nifs.c

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,16 @@
3838
#include <esp_sleep.h>
3939
#include <esp_system.h>
4040
#include <esp_task_wdt.h>
41+
42+
// driver/gpio.h is required for wakeup from light sleep
43+
#include <driver/gpio.h>
4144
#include <mbedtls/cipher.h>
4245
#include <mbedtls/md5.h>
4346
#include <mbedtls/sha1.h>
4447
#include <mbedtls/sha256.h>
4548
#include <mbedtls/sha512.h>
4649
#include <soc/soc.h>
50+
4751
#include <stdlib.h>
4852

4953
// introduced starting with 4.4
@@ -340,6 +344,17 @@ static term nif_esp_deep_sleep(Context *ctx, int argc, term argv[])
340344
return OK_ATOM;
341345
}
342346

347+
static term nif_esp_light_sleep(Context *ctx, int argc, term argv[])
348+
{
349+
UNUSED(ctx);
350+
UNUSED(argc);
351+
UNUSED(argv);
352+
353+
esp_err_t ret = esp_light_sleep_start();
354+
355+
return (ret == ESP_OK) ? OK_ATOM : ERROR_ATOM;
356+
}
357+
343358
#if SOC_PM_SUPPORT_EXT_WAKEUP || SOC_PM_SUPPORT_EXT0_WAKEUP
344359
static const char *const sleep_wakeup_ext0_atom = "\x11" "sleep_wakeup_ext0";
345360
#endif
@@ -513,6 +528,47 @@ static term nif_esp_deep_sleep_enable_gpio_wakeup(Context *ctx, int argc, term a
513528
}
514529
#endif
515530

531+
static term nif_esp_gpio_wakeup_enable(Context *ctx, int argc, term argv[])
532+
{
533+
UNUSED(ctx);
534+
UNUSED(argc);
535+
536+
VALIDATE_VALUE(argv[0], term_is_integer);
537+
if ((argv[1] != LOW_ATOM) && (argv[1] != HIGH_ATOM)) {
538+
RAISE_ERROR(BADARG_ATOM);
539+
}
540+
541+
avm_int_t gpio = term_to_int(argv[0]);
542+
gpio_int_type_t int_type = (argv[1] == LOW_ATOM) ? GPIO_INTR_LOW_LEVEL : GPIO_INTR_HIGH_LEVEL;
543+
544+
esp_err_t ret = gpio_wakeup_enable(gpio, int_type);
545+
546+
return (ret == ESP_OK) ? OK_ATOM : ERROR_ATOM;
547+
}
548+
549+
static term nif_esp_sleep_enable_gpio_wakeup(Context *ctx, int argc, term argv[])
550+
{
551+
UNUSED(ctx);
552+
UNUSED(argc);
553+
UNUSED(argv);
554+
555+
esp_err_t ret = esp_sleep_enable_gpio_wakeup();
556+
557+
return (ret == ESP_OK) ? OK_ATOM : ERROR_ATOM;
558+
}
559+
560+
static term nif_esp_sleep_enable_timer_wakeup_us(Context *ctx, int argc, term argv[])
561+
{
562+
UNUSED(ctx);
563+
UNUSED(argc);
564+
565+
VALIDATE_VALUE(argv[0], term_is_any_integer);
566+
avm_int64_t us = term_maybe_unbox_int64(argv[0]);
567+
568+
esp_err_t ret = esp_sleep_enable_timer_wakeup(us);
569+
570+
return (ret == ESP_OK) ? OK_ATOM : ERROR_ATOM;
571+
}
516572

517573
#if SOC_ULP_SUPPORTED
518574

@@ -842,6 +898,11 @@ static const struct Nif esp_deep_sleep_nif =
842898
.base.type = NIFFunctionType,
843899
.nif_ptr = nif_esp_deep_sleep
844900
};
901+
static const struct Nif esp_light_sleep_nif =
902+
{
903+
.base.type = NIFFunctionType,
904+
.nif_ptr = nif_esp_light_sleep
905+
};
845906
static const struct Nif esp_sleep_get_wakeup_cause_nif =
846907
{
847908
.base.type = NIFFunctionType,
@@ -880,6 +941,21 @@ static const struct Nif esp_deep_sleep_enable_gpio_wakeup_nif =
880941
.nif_ptr = nif_esp_deep_sleep_enable_gpio_wakeup
881942
};
882943
#endif
944+
static const struct Nif esp_gpio_wakeup_enable_nif =
945+
{
946+
.base.type = NIFFunctionType,
947+
.nif_ptr = nif_esp_gpio_wakeup_enable
948+
};
949+
static const struct Nif esp_sleep_enable_gpio_wakeup_nif =
950+
{
951+
.base.type = NIFFunctionType,
952+
.nif_ptr = nif_esp_sleep_enable_gpio_wakeup
953+
};
954+
static const struct Nif esp_sleep_enable_timer_wakeup_us_nif =
955+
{
956+
.base.type = NIFFunctionType,
957+
.nif_ptr = nif_esp_sleep_enable_timer_wakeup_us
958+
};
883959
#if SOC_ULP_SUPPORTED
884960
static const struct Nif esp_sleep_ulp_wakeup_nif =
885961
{
@@ -981,6 +1057,10 @@ const struct Nif *platform_nifs_get_nif(const char *nifname)
9811057
TRACE("Resolved platform nif %s ...\n", nifname);
9821058
return &esp_deep_sleep_nif;
9831059
}
1060+
if (strcmp("esp:light_sleep/0", nifname) == 0) {
1061+
TRACE("Resolved platform nif %s ...\n", nifname);
1062+
return &esp_light_sleep_nif;
1063+
}
9841064
if (strcmp("esp:sleep_get_wakeup_cause/0", nifname) == 0) {
9851065
TRACE("Resolved platform nif %s ...\n", nifname);
9861066
return &esp_sleep_get_wakeup_cause_nif;
@@ -1013,6 +1093,18 @@ const struct Nif *platform_nifs_get_nif(const char *nifname)
10131093
return &esp_deep_sleep_enable_gpio_wakeup_nif;
10141094
}
10151095
#endif
1096+
if (strcmp("esp:gpio_wakeup_enable/2", nifname) == 0) {
1097+
TRACE("Resolved platform nif %s ...\n", nifname);
1098+
return &esp_gpio_wakeup_enable_nif;
1099+
}
1100+
if (strcmp("esp:sleep_enable_gpio_wakeup/0", nifname) == 0) {
1101+
TRACE("Resolved platform nif %s ...\n", nifname);
1102+
return &esp_sleep_enable_gpio_wakeup_nif;
1103+
}
1104+
if (strcmp("esp:sleep_enable_timer_wakeup_us/1", nifname) == 0) {
1105+
TRACE("Resolved platform nif %s ...\n", nifname);
1106+
return &esp_sleep_enable_timer_wakeup_us_nif;
1107+
}
10161108
#if SOC_ULP_SUPPORTED
10171109
if (strcmp("esp:sleep_ulp_wakeup/0", nifname) == 0) {
10181110
TRACE("Resolved platform nif %s ...\n", nifname);

0 commit comments

Comments
 (0)