Skip to content

Commit 778ca20

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

File tree

4 files changed

+106
-1
lines changed

4 files changed

+106
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ 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 GPIO wakeup from light sleep.
1314

1415
### Fixed
1516

libs/eavmlib/src/esp.erl

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@
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,
4144
mount/4,
4245
umount/1,
4346
nvs_fetch_binary/2,
@@ -272,6 +275,37 @@ sleep_enable_ulp_wakeup() ->
272275
deep_sleep() ->
273276
erlang:nif_error(undefined).
274277

278+
%%-----------------------------------------------------------------------------
279+
%% @doc Put the esp32 into light sleep.
280+
%% This function returns ok on success after the sleep.
281+
%% Program is NOT restarted and wake up reason can be inspected to determine how
282+
%% the esp32 was woken up.
283+
%% @end
284+
%%-----------------------------------------------------------------------------
285+
-spec light_sleep() -> ok | error.
286+
light_sleep() ->
287+
erlang:nif_error(undefined).
288+
289+
%%-----------------------------------------------------------------------------
290+
%% @doc Configure given GPIO as light sleep wakeup pin
291+
%% @param GPIONum the GPIO number
292+
%% @param logic level, either low or high that triggers the wakeup condition
293+
%% @returns `ok | error'
294+
%% @end
295+
%%-----------------------------------------------------------------------------
296+
-spec gpio_wakeup_enable(GPIONum :: non_neg_integer(), Level :: low | high) -> ok | error.
297+
gpio_wakeup_enable(_GPIONum, _Level) ->
298+
erlang:nif_error(undefined).
299+
300+
%%-----------------------------------------------------------------------------
301+
%% @doc Enable waking up from light sleep using a configured GPIO
302+
%% @returns `ok | error'
303+
%% @end
304+
%%-----------------------------------------------------------------------------
305+
-spec sleep_enable_gpio_wakeup() -> ok | error.
306+
sleep_enable_gpio_wakeup() ->
307+
erlang:nif_error(undefined).
308+
275309
%%-----------------------------------------------------------------------------
276310
%% @param SleepMS time to deep sleep in milliseconds
277311
%% @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: 70 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,34 @@ 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+
}
516559

517560
#if SOC_ULP_SUPPORTED
518561

@@ -842,6 +885,11 @@ static const struct Nif esp_deep_sleep_nif =
842885
.base.type = NIFFunctionType,
843886
.nif_ptr = nif_esp_deep_sleep
844887
};
888+
static const struct Nif esp_light_sleep_nif =
889+
{
890+
.base.type = NIFFunctionType,
891+
.nif_ptr = nif_esp_light_sleep
892+
};
845893
static const struct Nif esp_sleep_get_wakeup_cause_nif =
846894
{
847895
.base.type = NIFFunctionType,
@@ -880,6 +928,16 @@ static const struct Nif esp_deep_sleep_enable_gpio_wakeup_nif =
880928
.nif_ptr = nif_esp_deep_sleep_enable_gpio_wakeup
881929
};
882930
#endif
931+
static const struct Nif esp_gpio_wakeup_enable_nif =
932+
{
933+
.base.type = NIFFunctionType,
934+
.nif_ptr = nif_esp_gpio_wakeup_enable
935+
};
936+
static const struct Nif esp_sleep_enable_gpio_wakeup_nif =
937+
{
938+
.base.type = NIFFunctionType,
939+
.nif_ptr = nif_esp_sleep_enable_gpio_wakeup
940+
};
883941
#if SOC_ULP_SUPPORTED
884942
static const struct Nif esp_sleep_ulp_wakeup_nif =
885943
{
@@ -981,6 +1039,10 @@ const struct Nif *platform_nifs_get_nif(const char *nifname)
9811039
TRACE("Resolved platform nif %s ...\n", nifname);
9821040
return &esp_deep_sleep_nif;
9831041
}
1042+
if (strcmp("esp:light_sleep/0", nifname) == 0) {
1043+
TRACE("Resolved platform nif %s ...\n", nifname);
1044+
return &esp_light_sleep_nif;
1045+
}
9841046
if (strcmp("esp:sleep_get_wakeup_cause/0", nifname) == 0) {
9851047
TRACE("Resolved platform nif %s ...\n", nifname);
9861048
return &esp_sleep_get_wakeup_cause_nif;
@@ -1013,6 +1075,14 @@ const struct Nif *platform_nifs_get_nif(const char *nifname)
10131075
return &esp_deep_sleep_enable_gpio_wakeup_nif;
10141076
}
10151077
#endif
1078+
if (strcmp("esp:gpio_wakeup_enable/2", nifname) == 0) {
1079+
TRACE("Resolved platform nif %s ...\n", nifname);
1080+
return &esp_gpio_wakeup_enable_nif;
1081+
}
1082+
if (strcmp("esp:sleep_enable_gpio_wakeup/0", nifname) == 0) {
1083+
TRACE("Resolved platform nif %s ...\n", nifname);
1084+
return &esp_sleep_enable_gpio_wakeup_nif;
1085+
}
10161086
#if SOC_ULP_SUPPORTED
10171087
if (strcmp("esp:sleep_ulp_wakeup/0", nifname) == 0) {
10181088
TRACE("Resolved platform nif %s ...\n", nifname);

0 commit comments

Comments
 (0)