Skip to content

Commit 4a69dfa

Browse files
authored
Merge pull request micropython#6907 from dhalbert/preserve-pins-on-deep-sleep
allow preserving pin state during deep sleep
2 parents f994b11 + 60f43b1 commit 4a69dfa

File tree

18 files changed

+186
-65
lines changed

18 files changed

+186
-65
lines changed

locale/circuitpython.pot

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,16 @@ msgid ""
6666
"%d address pins, %d rgb pins and %d tiles indicate a height of %d, not %d"
6767
msgstr ""
6868

69+
#: ports/atmel-samd/common-hal/alarm/__init__.c
6970
#: ports/cxd56/common-hal/analogio/AnalogOut.c ports/cxd56/common-hal/rtc/RTC.c
7071
#: ports/espressif/common-hal/rtc/RTC.c
7172
#: ports/mimxrt10xx/common-hal/analogio/AnalogOut.c
72-
#: ports/mimxrt10xx/common-hal/rtc/RTC.c
73+
#: ports/mimxrt10xx/common-hal/rtc/RTC.c ports/nrf/common-hal/alarm/__init__.c
7374
#: ports/nrf/common-hal/analogio/AnalogOut.c ports/nrf/common-hal/rtc/RTC.c
75+
#: ports/raspberrypi/common-hal/alarm/__init__.c
7476
#: ports/raspberrypi/common-hal/analogio/AnalogOut.c
75-
#: ports/raspberrypi/common-hal/rtc/RTC.c ports/stm/common-hal/rtc/RTC.c
77+
#: ports/raspberrypi/common-hal/rtc/RTC.c ports/stm/common-hal/alarm/__init__.c
78+
#: ports/stm/common-hal/rtc/RTC.c
7679
msgid "%q"
7780
msgstr ""
7881

@@ -902,13 +905,14 @@ msgstr ""
902905

903906
#: ports/raspberrypi/bindings/rp2pio/StateMachine.c py/enum.c
904907
#: shared-bindings/_bleio/__init__.c shared-bindings/aesio/aes.c
905-
#: shared-bindings/busio/SPI.c shared-bindings/microcontroller/Pin.c
908+
#: shared-bindings/alarm/__init__.c shared-bindings/busio/SPI.c
909+
#: shared-bindings/microcontroller/Pin.c
906910
#: shared-bindings/neopixel_write/__init__.c
907911
msgid "Expected a %q"
908912
msgstr ""
909913

910914
#: shared-bindings/alarm/__init__.c
911-
msgid "Expected an alarm"
915+
msgid "Expected an %q"
912916
msgstr ""
913917

914918
#: ports/espressif/common-hal/_bleio/Adapter.c
@@ -3798,6 +3802,7 @@ msgstr ""
37983802
#: ports/espressif/boards/adafruit_qtpy_esp32c3/mpconfigboard.h
37993803
#: ports/espressif/boards/beetle-esp32-c3/mpconfigboard.h
38003804
#: ports/espressif/boards/lolin_c3_mini/mpconfigboard.h
3805+
#: ports/espressif/boards/microdev_micro_c3/mpconfigboard.h
38013806
#: supervisor/shared/safe_mode.c
38023807
msgid "pressing boot button at start up.\n"
38033808
msgstr ""

ports/atmel-samd/common-hal/alarm/__init__.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,10 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj
142142
return wake_alarm;
143143
}
144144

145-
void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms) {
145+
void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms, size_t n_dios, digitalio_digitalinout_obj_t **preserve_dios) {
146+
if (n_dios > 0) {
147+
mp_raise_NotImplementedError_varg(translate("%q"), MP_QSTR_preserve_dios);
148+
}
146149
_setup_sleep_alarms(true, n_alarms, alarms);
147150
}
148151

ports/espressif/boards/adafruit_feather_esp32_v2/board.c

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,14 @@
3131
#include "components/hal/include/hal/gpio_hal.h"
3232
#include "common-hal/microcontroller/Pin.h"
3333

34-
void board_init(void) {
35-
reset_board();
36-
}
37-
38-
void reset_board(void) {
39-
// Turn on NeoPixel and I2C power by default.
40-
gpio_set_direction(2, GPIO_MODE_DEF_OUTPUT);
41-
gpio_set_level(2, true);
42-
}
43-
4434
bool espressif_board_reset_pin_number(gpio_num_t pin_number) {
35+
if (pin_number == 2) {
36+
// Turn on NeoPixel and I2C power by default.
37+
gpio_set_direction(pin_number, GPIO_MODE_DEF_OUTPUT);
38+
gpio_set_level(pin_number, true);
39+
return true;
40+
}
41+
4542
return false;
4643
}
4744

ports/espressif/common-hal/alarm/SleepMemory.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,14 @@
3131
#include "common-hal/alarm/SleepMemory.h"
3232
#include "shared-bindings/alarm/SleepMemory.h"
3333

34-
#include "esp_log.h"
3534
#include "esp_sleep.h"
3635

3736
// Data storage for singleton instance of SleepMemory.
3837
// Might be RTC_SLOW_MEM or RTC_FAST_MEM, depending on setting of CONFIG_ESP32S2_RTCDATA_IN_FAST_MEM.
3938
static RTC_DATA_ATTR uint8_t _sleep_mem[SLEEP_MEMORY_LENGTH];
4039

4140
void alarm_sleep_memory_reset(void) {
42-
// ESP-IDF build system takes care of doing esp_sleep_pd_config() or the equivalentwith
41+
// ESP-IDF build system takes care of doing esp_sleep_pd_config() or the equivalent with
4342
// the correct settings, depending on which RTC mem we are using.
4443
// https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-reference/system/sleep_modes.html#power-down-of-rtc-peripherals-and-memories
4544
}

ports/espressif/common-hal/alarm/__init__.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,15 @@
3939
#include "shared-bindings/wifi/__init__.h"
4040
#include "shared-bindings/microcontroller/__init__.h"
4141

42+
#include "common-hal/digitalio/DigitalInOut.h"
43+
4244
#include "supervisor/port.h"
4345
#include "supervisor/shared/workflow.h"
4446

4547
#include "esp_sleep.h"
4648

4749
#include "soc/rtc_cntl_reg.h"
50+
#include "components/driver/include/driver/gpio.h"
4851
#include "components/driver/include/driver/uart.h"
4952

5053
// Singleton instance of SleepMemory.
@@ -158,14 +161,21 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj
158161
return wake_alarm;
159162
}
160163

161-
void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms) {
164+
void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms, size_t n_dios, digitalio_digitalinout_obj_t *preserve_dios[]) {
165+
digitalio_digitalinout_preserve_for_deep_sleep(n_dios, preserve_dios);
162166
_setup_sleep_alarms(true, n_alarms, alarms);
163167
}
164168

165169
void NORETURN common_hal_alarm_enter_deep_sleep(void) {
166170
alarm_pin_pinalarm_prepare_for_deep_sleep();
167171
alarm_touch_touchalarm_prepare_for_deep_sleep();
168172

173+
// We no longer need to remember the pin preservations, since any pin resets are all done.
174+
clear_pin_preservations();
175+
176+
// Allow pin holds to work during deep sleep.
177+
gpio_deep_sleep_hold_en();
178+
169179
// The ESP-IDF caches the deep sleep settings and applies them before sleep.
170180
// We don't need to worry about resetting them in the interim.
171181
esp_deep_sleep_start();

ports/espressif/common-hal/digitalio/DigitalInOut.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,20 @@
3232

3333
#include "components/hal/include/hal/gpio_hal.h"
3434

35+
STATIC bool _pin_is_input(uint8_t pin_number) {
36+
const uint32_t iomux = READ_PERI_REG(GPIO_PIN_MUX_REG[pin_number]);
37+
return (iomux & FUN_IE) != 0;
38+
}
39+
40+
void digitalio_digitalinout_preserve_for_deep_sleep(size_t n_dios, digitalio_digitalinout_obj_t *preserve_dios[]) {
41+
// Mark the pin states of the given DigitalInOuts for preservation during deep sleep
42+
for (size_t i = 0; i < n_dios; i++) {
43+
if (!common_hal_digitalio_digitalinout_deinited(preserve_dios[i])) {
44+
preserve_pin_number(preserve_dios[i]->pin->number);
45+
}
46+
}
47+
}
48+
3549
void common_hal_digitalio_digitalinout_never_reset(
3650
digitalio_digitalinout_obj_t *self) {
3751
never_reset_pin_number(self->pin->number);
@@ -83,8 +97,7 @@ digitalinout_result_t common_hal_digitalio_digitalinout_switch_to_output(
8397

8498
digitalio_direction_t common_hal_digitalio_digitalinout_get_direction(
8599
digitalio_digitalinout_obj_t *self) {
86-
uint32_t iomux = READ_PERI_REG(GPIO_PIN_MUX_REG[self->pin->number]);
87-
if ((iomux & FUN_IE) != 0) {
100+
if (_pin_is_input(self->pin->number)) {
88101
return DIRECTION_INPUT;
89102
}
90103
return DIRECTION_OUTPUT;

ports/espressif/common-hal/digitalio/DigitalInOut.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,6 @@ typedef struct {
3636
bool output_value;
3737
} digitalio_digitalinout_obj_t;
3838

39+
extern void digitalio_digitalinout_preserve_for_deep_sleep(size_t n_dios, digitalio_digitalinout_obj_t *preserve_dios[]);
40+
3941
#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_DIGITALIO_DIGITALINOUT_H

ports/espressif/common-hal/esp32_camera/Camera.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,6 @@ framesize_t common_hal_esp32_camera_camera_get_frame_size(esp32_camera_camera_ob
191191
return self->camera_config.frame_size;
192192
}
193193

194-
#include "esp_log.h"
195-
196194
void common_hal_esp32_camera_camera_reconfigure(esp32_camera_camera_obj_t *self, framesize_t frame_size, pixformat_t pixel_format, camera_grab_mode_t grab_mode, mp_int_t framebuffer_count) {
197195
sensor_t *sensor = esp_camera_sensor_get();
198196
camera_sensor_info_t *sensor_info = esp_camera_sensor_get_info(&sensor->id);

ports/espressif/common-hal/microcontroller/Pin.c

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,13 @@
3333
#include "components/driver/include/driver/gpio.h"
3434
#include "components/hal/include/hal/gpio_hal.h"
3535

36-
STATIC uint64_t never_reset_pins;
37-
STATIC uint64_t in_use;
36+
STATIC uint64_t _never_reset_pin_mask;
37+
STATIC uint64_t _preserved_pin_mask;
38+
STATIC uint64_t _in_use_pin_mask;
3839

39-
// 64-bit pin mask for a single bit
40-
#define PIN_BIT(pin_number) (((uint64_t)1) << pin_number)
41-
42-
// Bit mask of all pins that should never ever be reset.
40+
// Bit mask of all pins that should never EVER be reset.
4341
// Typically these are SPI flash and PSRAM control pins, and communication pins.
42+
// "Reset forbidden" is stronger than "never reset" below, which may only be temporary.
4443
static const uint64_t pin_mask_reset_forbidden =
4544
#if defined(CONFIG_IDF_TARGET_ESP32)
4645
// Never ever reset serial pins for bootloader and possibly USB-serial converter.
@@ -105,7 +104,7 @@ void never_reset_pin_number(gpio_num_t pin_number) {
105104
if (pin_number == NO_PIN || pin_number == (uint8_t)NO_PIN) {
106105
return;
107106
}
108-
never_reset_pins |= PIN_BIT(pin_number);
107+
_never_reset_pin_mask |= PIN_BIT(pin_number);
109108
}
110109

111110
void common_hal_never_reset_pin(const mcu_pin_obj_t *pin) {
@@ -119,12 +118,29 @@ MP_WEAK bool espressif_board_reset_pin_number(gpio_num_t pin_number) {
119118
return false;
120119
}
121120

121+
STATIC bool _reset_forbidden(gpio_num_t pin_number) {
122+
return pin_mask_reset_forbidden & PIN_BIT(pin_number);
123+
}
124+
125+
STATIC bool _never_reset(gpio_num_t pin_number) {
126+
return _never_reset_pin_mask & PIN_BIT(pin_number);
127+
}
128+
129+
STATIC bool _preserved_pin(gpio_num_t pin_number) {
130+
return _preserved_pin_mask & PIN_BIT(pin_number);
131+
}
132+
122133
STATIC void _reset_pin(gpio_num_t pin_number) {
123134
// Never ever reset pins used for flash, RAM, and basic communication.
124-
if (pin_mask_reset_forbidden & PIN_BIT(pin_number)) {
135+
if (_reset_forbidden(pin_number)) {
125136
return;
126137
}
127138

139+
// Disable any existing hold on this pin,
140+
if (GPIO_IS_VALID_OUTPUT_GPIO(pin_number)) {
141+
gpio_hold_dis(pin_number);
142+
}
143+
128144
// Give the board a chance to reset the pin in a particular way.
129145
if (espressif_board_reset_pin_number(pin_number)) {
130146
return;
@@ -152,15 +168,27 @@ STATIC void _reset_pin(gpio_num_t pin_number) {
152168
}
153169
}
154170

171+
void preserve_pin_number(gpio_num_t pin_number) {
172+
if (GPIO_IS_VALID_OUTPUT_GPIO(pin_number)) {
173+
gpio_hold_en(pin_number);
174+
_preserved_pin_mask |= PIN_BIT(pin_number);
175+
}
176+
}
177+
178+
void clear_pin_preservations(void) {
179+
_preserved_pin_mask = 0;
180+
}
181+
182+
155183
// Mark pin as free and return it to a quiescent state.
156184
void reset_pin_number(gpio_num_t pin_number) {
157185
// Some CircuitPython APIs deal in uint8_t pin numbers, but NO_PIN is -1.
158186
// Also allow pin 255 to be treated as NO_PIN to avoid crashes
159187
if (pin_number == NO_PIN || pin_number == (uint8_t)NO_PIN) {
160188
return;
161189
}
162-
never_reset_pins &= ~PIN_BIT(pin_number);
163-
in_use &= ~PIN_BIT(pin_number);
190+
_never_reset_pin_mask &= ~PIN_BIT(pin_number);
191+
_in_use_pin_mask &= ~PIN_BIT(pin_number);
164192

165193
_reset_pin(pin_number);
166194
}
@@ -177,15 +205,20 @@ void common_hal_reset_pin(const mcu_pin_obj_t *pin) {
177205
}
178206

179207
void reset_all_pins(void) {
208+
// Undo deep sleep holds in case we woke up from deep sleep.
209+
// We still need to unhold individual pins, which is done by _reset_pin.
210+
gpio_deep_sleep_hold_dis();
211+
180212
for (uint8_t i = 0; i < GPIO_PIN_COUNT; i++) {
181213
uint32_t iomux_address = GPIO_PIN_MUX_REG[i];
182214
if (iomux_address == 0 ||
183-
(never_reset_pins & PIN_BIT(i))) {
215+
_never_reset(i) ||
216+
_preserved_pin(i)) {
184217
continue;
185218
}
186219
_reset_pin(i);
187220
}
188-
in_use = never_reset_pins;
221+
_in_use_pin_mask = _never_reset_pin_mask;
189222
}
190223

191224
void claim_pin_number(gpio_num_t pin_number) {
@@ -194,7 +227,7 @@ void claim_pin_number(gpio_num_t pin_number) {
194227
if (pin_number == NO_PIN || pin_number == (uint8_t)NO_PIN) {
195228
return;
196229
}
197-
in_use |= PIN_BIT(pin_number);
230+
_in_use_pin_mask |= PIN_BIT(pin_number);
198231
}
199232

200233
void claim_pin(const mcu_pin_obj_t *pin) {
@@ -206,7 +239,7 @@ void common_hal_mcu_pin_claim(const mcu_pin_obj_t *pin) {
206239
}
207240

208241
bool pin_number_is_free(gpio_num_t pin_number) {
209-
return !(in_use & PIN_BIT(pin_number));
242+
return !(_in_use_pin_mask & PIN_BIT(pin_number));
210243
}
211244

212245
bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t *pin) {

ports/espressif/common-hal/microcontroller/Pin.h

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,21 +31,28 @@
3131

3232
#include "peripherals/pins.h"
3333

34-
void reset_all_pins(void);
34+
// 64-bit pin mask for a single bit
35+
#define PIN_BIT(pin_number) (((uint64_t)1) << pin_number)
36+
37+
extern void common_hal_reset_pin(const mcu_pin_obj_t *pin);
38+
extern void common_hal_never_reset_pin(const mcu_pin_obj_t *pin);
39+
40+
extern void reset_all_pins(void);
3541
// reset_pin_number takes the pin number instead of the pointer so that objects don't
3642
// need to store a full pointer.
37-
void reset_pin_number(gpio_num_t pin_number);
38-
void common_hal_reset_pin(const mcu_pin_obj_t *pin);
39-
void common_hal_never_reset_pin(const mcu_pin_obj_t *pin);
40-
void claim_pin(const mcu_pin_obj_t *pin);
41-
void claim_pin_number(gpio_num_t pin_number);
42-
bool pin_number_is_free(gpio_num_t pin_number);
43-
void never_reset_pin_number(gpio_num_t pin_number);
43+
extern void reset_pin_number(gpio_num_t pin_number);
44+
extern void claim_pin(const mcu_pin_obj_t *pin);
45+
extern void claim_pin_number(gpio_num_t pin_number);
46+
extern bool pin_number_is_free(gpio_num_t pin_number);
47+
extern void never_reset_pin_number(gpio_num_t pin_number);
48+
49+
extern void preserve_pin_number(gpio_num_t pin_number);
50+
extern void clear_pin_preservations(void);
4451

4552
// Allow the board to reset a pin in a board-specific way. This can be used
4653
// for LEDs or enable pins to put them in a state beside the default pull-up.
4754
// Return true to indicate that the pin was reset. Returning false will lead to
4855
// the port-default reset behavior.
49-
bool espressif_board_reset_pin_number(gpio_num_t pin_number);
56+
extern bool espressif_board_reset_pin_number(gpio_num_t pin_number);
5057

5158
#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_MICROCONTROLLER_PIN_H

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy