Skip to content

Commit 49090d1

Browse files
committed
Fully implement digitalio and pin-in-use tracking.
Fixes #2901
1 parent acf4b1b commit 49090d1

File tree

17 files changed

+264
-57
lines changed

17 files changed

+264
-57
lines changed

ports/esp32s2/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ SRC_C += \
149149
mphalport.c \
150150
boards/$(BOARD)/board.c \
151151
boards/$(BOARD)/pins.c \
152+
modules/$(CIRCUITPY_MODULE).c \
152153
lib/libc/string0.c \
153154
lib/mp-readline/readline.c \
154155
lib/oofatfs/ff.c \

ports/esp32s2/boards/espressif_saola_1_wroom/board.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,16 @@
2626

2727
#include "boards/board.h"
2828
#include "mpconfigboard.h"
29+
#include "shared-bindings/microcontroller/Pin.h"
2930

3031
void board_init(void) {
32+
// USB
33+
never_reset_pin(&pin_GPIO19);
34+
never_reset_pin(&pin_GPIO20);
35+
36+
// Debug UART
37+
never_reset_pin(&pin_GPIO43);
38+
never_reset_pin(&pin_GPIO44);
3139
}
3240

3341
bool board_requests_safe_mode(void) {

ports/esp32s2/boards/espressif_saola_1_wroom/mpconfigboard.mk

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,5 @@ CIRCUITPY_MICROCONTROLLER = 0
1818
CIRCUITPY_ESP_FLASH_MODE=dio
1919
CIRCUITPY_ESP_FLASH_FREQ=40m
2020
CIRCUITPY_ESP_FLASH_SIZE=4MB
21+
22+
CIRCUITPY_MODULE=wroom

ports/esp32s2/boards/espressif_saola_1_wrover/board.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@
2828
#include "mpconfigboard.h"
2929

3030
void board_init(void) {
31+
// USB
32+
never_reset_pin(&pin_GPIO19);
33+
never_reset_pin(&pin_GPIO20);
34+
35+
// Debug UART
36+
never_reset_pin(&pin_GPIO43);
37+
never_reset_pin(&pin_GPIO44);
3138
}
3239

3340
bool board_requests_safe_mode(void) {

ports/esp32s2/boards/espressif_saola_1_wrover/mpconfigboard.mk

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,5 @@ CIRCUITPY_MICROCONTROLLER = 0
1818
CIRCUITPY_ESP_FLASH_MODE=dio
1919
CIRCUITPY_ESP_FLASH_FREQ=40m
2020
CIRCUITPY_ESP_FLASH_SIZE=4MB
21+
22+
CIRCUITPY_MODULE=wrover

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

Lines changed: 44 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -30,24 +30,18 @@
3030

3131
#include "driver/gpio.h"
3232

33-
34-
#include "esp_log.h"
35-
36-
static const char* TAG = "CircuitPython digitalio";
33+
#include "esp-idf/components/soc/include/hal/gpio_hal.h"
3734

3835
void common_hal_digitalio_digitalinout_never_reset(
3936
digitalio_digitalinout_obj_t *self) {
40-
(void)self;
37+
never_reset_pin_number(self->pin->number);
4138
}
4239

4340
digitalinout_result_t common_hal_digitalio_digitalinout_construct(
4441
digitalio_digitalinout_obj_t *self, const mcu_pin_obj_t *pin) {
45-
46-
// claim_pin(pin);
42+
claim_pin(pin);
4743
self->pin = pin;
4844

49-
ESP_EARLY_LOGW(TAG, "construct %d", pin->number);
50-
5145
return DIGITALINOUT_OK;
5246
}
5347

@@ -60,78 +54,86 @@ void common_hal_digitalio_digitalinout_deinit(digitalio_digitalinout_obj_t *self
6054
return;
6155
}
6256

63-
// reset_pin_number(0, self->pin->number);
57+
reset_pin_number(self->pin->number);
6458
self->pin = mp_const_none;
6559
}
6660

6761
void common_hal_digitalio_digitalinout_switch_to_input(
6862
digitalio_digitalinout_obj_t *self, digitalio_pull_t pull) {
69-
gpio_config_t config = {
70-
.pin_bit_mask = 1 << self->pin->number,
71-
.mode = GPIO_MODE_INPUT
72-
};
73-
if (pull == PULL_UP) {
74-
config.pull_up_en = GPIO_PULLUP_ENABLE;
75-
} else if (pull == PULL_DOWN) {
76-
config.pull_down_en = GPIO_PULLDOWN_ENABLE;
77-
}
78-
79-
gpio_config(&config);
63+
common_hal_digitalio_digitalinout_set_pull(self, pull);
64+
gpio_set_direction(self->pin->number, GPIO_MODE_DEF_INPUT);
8065
}
8166

82-
void common_hal_digitalio_digitalinout_switch_to_output(
67+
digitalinout_result_t common_hal_digitalio_digitalinout_switch_to_output(
8368
digitalio_digitalinout_obj_t *self, bool value,
8469
digitalio_drive_mode_t drive_mode) {
85-
gpio_config_t config = {
86-
.pin_bit_mask = 1ULL << self->pin->number,
87-
.mode = GPIO_MODE_OUTPUT
88-
};
89-
if (drive_mode == DRIVE_MODE_OPEN_DRAIN) {
90-
config.mode = GPIO_MODE_OUTPUT_OD;
91-
}
9270
gpio_set_level(self->pin->number, value);
93-
gpio_config(&config);
71+
return common_hal_digitalio_digitalinout_set_drive_mode(self, drive_mode);
9472
}
9573

9674
digitalio_direction_t common_hal_digitalio_digitalinout_get_direction(
9775
digitalio_digitalinout_obj_t *self) {
98-
76+
uint32_t iomux = READ_PERI_REG(GPIO_PIN_MUX_REG[self->pin->number]);
77+
if ((iomux & FUN_IE) != 0) {
78+
return DIRECTION_INPUT;
79+
}
9980
return DIRECTION_OUTPUT;
10081
}
10182

10283
void common_hal_digitalio_digitalinout_set_value(
10384
digitalio_digitalinout_obj_t *self, bool value) {
104-
ESP_EARLY_LOGW(TAG, "set %d %d", self->pin->number, value);
10585
gpio_set_level(self->pin->number, value);
10686
}
10787

10888
bool common_hal_digitalio_digitalinout_get_value(
10989
digitalio_digitalinout_obj_t *self) {
110-
return true;
90+
return gpio_get_level(self->pin->number) == 1;
11191
}
11292

113-
void common_hal_digitalio_digitalinout_set_drive_mode(
93+
digitalinout_result_t common_hal_digitalio_digitalinout_set_drive_mode(
11494
digitalio_digitalinout_obj_t *self,
11595
digitalio_drive_mode_t drive_mode) {
116-
(void)self;
117-
(void)drive_mode;
96+
gpio_num_t number = self->pin->number;
97+
gpio_mode_t mode;
98+
if (drive_mode == DRIVE_MODE_OPEN_DRAIN) {
99+
mode = GPIO_MODE_DEF_OD;
100+
} else {
101+
mode = GPIO_MODE_DEF_OUTPUT;
102+
}
103+
esp_err_t result = gpio_set_direction(number, mode);
104+
if (result != ESP_OK) {
105+
return DIGITALINOUT_INPUT_ONLY;
106+
}
107+
return DIGITALINOUT_OK;
118108
}
119109

120110
digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(
121111
digitalio_digitalinout_obj_t *self) {
122-
// if (common_hal_digitalio_digitalinout_get_direction(self) == DIRECTION_OUTPUT)
123-
// return DRIVE_MODE_PUSH_PULL;
124-
// else
125-
return DRIVE_MODE_OPEN_DRAIN;
112+
if (GPIO_HAL_GET_HW(GPIO_PORT_0)->pin[self->pin->number].pad_driver == 1) {
113+
return DRIVE_MODE_OPEN_DRAIN;
114+
}
115+
return DRIVE_MODE_PUSH_PULL;
126116
}
127117

128118
void common_hal_digitalio_digitalinout_set_pull(
129119
digitalio_digitalinout_obj_t *self, digitalio_pull_t pull) {
130-
(void)self;
131-
(void)pull;
120+
gpio_num_t number = self->pin->number;
121+
gpio_pullup_dis(number);
122+
gpio_pulldown_dis(number);
123+
if (pull == PULL_UP) {
124+
gpio_pullup_en(number);
125+
} else if (pull == PULL_DOWN) {
126+
gpio_pulldown_en(number);
127+
}
132128
}
133129

134130
digitalio_pull_t common_hal_digitalio_digitalinout_get_pull(
135131
digitalio_digitalinout_obj_t *self) {
132+
gpio_num_t gpio_num = self->pin->number;
133+
if (REG_GET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PU) == 1) {
134+
return PULL_UP;
135+
} else if (REG_GET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PD) == 1) {
136+
return PULL_DOWN;
137+
}
136138
return PULL_NONE;
137139
}

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

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,51 @@
2929

3030
#include "py/mphal.h"
3131

32+
#include "esp-idf/components/driver/include/driver/gpio.h"
33+
#include "esp-idf/components/soc/include/hal/gpio_hal.h"
34+
35+
STATIC uint32_t never_reset_pins[2];
36+
STATIC uint32_t in_use[2];
37+
38+
void never_reset_pin_number(gpio_num_t pin_number) {
39+
never_reset_pins[pin_number / 32] |= 1 << pin_number % 32;
40+
}
41+
42+
void never_reset_pin(const mcu_pin_obj_t* pin) {
43+
never_reset_pin_number(pin->number);
44+
}
45+
3246
// Mark pin as free and return it to a quiescent state.
33-
void reset_pin_number(uint8_t pin_port, uint8_t pin_number) {
47+
void reset_pin_number(gpio_num_t pin_number) {
48+
never_reset_pins[pin_number / 32] &= ~(1 << pin_number % 32);
49+
in_use[pin_number / 32] &= ~(1 << pin_number % 32);
3450
}
3551

52+
void reset_all_pins(void) {
53+
for (uint8_t i = 0; i < GPIO_PIN_COUNT; i++) {
54+
uint32_t iomux_address = GPIO_PIN_MUX_REG[i];
55+
if (iomux_address == 0 ||
56+
(never_reset_pins[i / 32] & (1 << i % 32)) != 0) {
57+
continue;
58+
}
59+
gpio_set_direction(i, GPIO_MODE_DEF_INPUT);
60+
gpio_pullup_dis(i);
61+
gpio_pulldown_dis(i);
62+
}
63+
in_use[0] = 0;
64+
in_use[1] = 0;
65+
}
3666

3767
void claim_pin(const mcu_pin_obj_t* pin) {
68+
in_use[pin->number / 32] |= (1 << pin->number % 32);
3869
}
3970

40-
bool pin_number_is_free(uint8_t pin_port, uint8_t pin_number) {
41-
return true;
71+
bool pin_number_is_free(gpio_num_t pin_number) {
72+
uint8_t offset = pin_number / 32;
73+
uint8_t mask = 1 << pin_number % 32;
74+
return (never_reset_pins[offset] & mask) == 0 && (in_use[offset] & mask) == 0;
4275
}
4376

4477
bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t *pin) {
45-
return pin_number_is_free(0, pin->number);
78+
return pin_number_is_free(pin->number);
4679
}

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,10 @@
3434
void reset_all_pins(void);
3535
// reset_pin_number takes the pin number instead of the pointer so that objects don't
3636
// need to store a full pointer.
37-
void reset_pin_number(uint8_t pin_port, uint8_t pin_number);
37+
void reset_pin_number(gpio_num_t pin_number);
3838
void claim_pin(const mcu_pin_obj_t* pin);
39-
bool pin_number_is_free(uint8_t pin_port, uint8_t pin_number);
40-
void never_reset_pin_number(uint8_t pin_port, uint8_t pin_number);
41-
// GPIO_TypeDef * pin_port(uint8_t pin_port);
42-
uint16_t pin_mask(uint8_t pin_number);
39+
bool pin_number_is_free(gpio_num_t pin_number);
40+
void never_reset_pin_number(gpio_num_t pin_number);
41+
void never_reset_pin(const mcu_pin_obj_t* pin);
4342

4443
#endif // MICROPY_INCLUDED_ESP32S2_COMMON_HAL_MICROCONTROLLER_PIN_H

ports/esp32s2/modules/module.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* This file is part of the Micro Python project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
28+
#ifndef MICROPY_INCLUDED_ESP32S2_MODULES_MODULE_H
29+
#define MICROPY_INCLUDED_ESP32S2_MODULES_MODULE_H
30+
31+
#include "shared-bindings/microcontroller/Pin.h"
32+
33+
void never_reset_module_internal_pins(void);
34+
35+
#endif // MICROPY_INCLUDED_ESP32S2_MODULES_MODULE_H

ports/esp32s2/modules/none.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* This file is part of the Micro Python project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
void never_reset_module_internal_pins(void) {
28+
}

0 commit comments

Comments
 (0)