8000 allow preserving pin state during deep sleep · litui/circuitpython@60f43b1 · GitHub
[go: up one dir, main page]

Skip to content

Commit 60f43b1

Browse files
committed
allow preserving pin state during deep sleep
1 parent 5a053f9 commit 60f43b1

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

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,10 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj
247247
return wake_alarm;
248248
}
249249

250-
void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms) {
250+
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) {
251+
if (n_dios > 0) {
252+
mp_raise_NotImplementedError_varg(translate("%q"), MP_QSTR_preserve_dios);
253+
}
251254
_setup_sleep_alarms(true, n_alarms, alarms);
252255
}
253256

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,10 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj
194194
return wake_alarm;
195195
}
196196

197-
void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms) {
197+
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) {
198+
if (n_dios > 0) {
199+
mp_raise_NotImplementedError_varg(translate("%q"), MP_QSTR_preserve_dios);
200+
}
198201
_setup_sleep_alarms(true, n_alarms, alarms);
199202
}
200203

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

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

147-
void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms) {
147+
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) {
148+
if (n_dios > 0) {
149+
mp_raise_NotImplementedError_varg(translate("%q"), MP_QSTR_preserve_dios);
150+
}
148151
_setup_sleep_alarms(true, n_alarms, alarms);
149152
}
150153

ports/stm/supervisor/port.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ void SysTick_Handler(void) {
244244

245245
void reset_port(void) {
246246
reset_all_pins();
247+
247248
#if CIRCUITPY_RTC
248249
rtc_reset();
249250
#endif

0 commit comments

Comments
 (0)
0