ESP32-S3: digitalio open-drain output doesn't work on GPIO45, so bitbangio.I2C fails there
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 48/100
- Tipo di issue
- Bug
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Attiva
- Ambito
- embedded-iot
Direzione di ricerca
Start with the GPIO handling in ports/espressif/common-hal/digitalio/DigitalInOut.c and the open-drain release and read sequence in shared-module/bitbangio/I2C.c. Reproduce the reported difference on GPIO45 with the supplied digitalio script, then trace the lower-level ESP32-S3 GPIO behavior. Done means open-drain transactions on GPIO45 work as they do on GPIO0, without breaking the reported working cases.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
CircuitPython 10.3.1 on an ESP32-S3 (M5Stack AtomS3R: espressif_esp32s3_devkitc_1_n8r8, and a local m5stack_atoms3r build). The board's internal I2C bus is SCL GPIO0 / SDA GPIO45 with external pull-ups, a BMI270 at 0x68 and an LP5562 at 0x30.
Symptom: bitbangio.I2C(GPIO0, GPIO45) finds both devices with scan() (at 100 kHz and 10 kHz), but writeto and writeto_then_readfrom raise [Errno 5], and readfrom_into returns 0xFF. busio.I2C on the same pins works (with CIRCUITPY_I2C_ALLOW_STRAPPING_PINS), so the wiring and pull-ups are fine.
Narrowed: the same transaction bit-banged with digitalio, changing only how a line is released. "-od" = the way shared-module/bitbangio/I2C.c does it: an open-drain output set to 1, switched to input and back to read (sda_read, and scl_release's clock-stretch check).
| SCL (GPIO0) released by | SDA (GPIO45) released by | Result |
|---|---|---|
| switching to input | switching to input | works: chip ID 0x24 |
| open-drain output (with the input round trip) | switching to input | works |
| switching to input | open-drain output (with the input round trip) | address ACKed, register byte NACKed, read 0xFF |
| open-drain output | open-drain output | the same failure (bitbangio's way) |
The identical open-drain sequence works on GPIO0 and fails on GPIO45 (a strapping pin), on both builds, repeatably.
Two more observations:
DigitalInOut.drive_modereportsDriveMode.OPEN_DRAINon GPIO45 afterswitch_to_output(drive_mode=OPEN_DRAIN), before and after the input round trip (same as GPIO0, 5 and 6), so the requested mode does read back.- The address byte is ACKed in every variant; the failure begins after the first input → open-drain round trip on SDA (reading the ACK, then going back to an open-drain output set to 1).
ports/espressif/common-hal/digitalio/DigitalInOut.c is pin-agnostic (gpio_set_direction(GPIO_MODE_OUTPUT | GPIO_MODE_OUTPUT_OD)), so the cause looks to be below it; I haven't found it. Seen on one board (one AtomS3R), so I can't say whether every ESP32-S3's GPIO45 does this.
Repro (save as code.py; output above):
# Repro: digitalio open-drain output fails on ESP32-S3 GPIO45 (so bitbangio.I2C fails there). Save as code.py on an
# M5Stack AtomS3R (internal I2C: SCL GPIO0, SDA GPIO45, external pull-ups; BMI270 at 0x68, chip ID register 0x00 = 0x24)
# and read the serial console. Each run bit-bangs "read the BMI270's chip ID" with digitalio; a line in an "-od" mode is
# released the way shared-module/bitbangio/I2C.c does it (open-drain output set to 1, switched to input and back to
# read). Seen on CircuitPython 10.3.1 (espressif_esp32s3_devkitc_1_n8r8, and an m5stack_atoms3r build):
# input / scl-od-roundtrip: acks (True, True, True), chip id 24
# sda-od-roundtrip / both-od-roundtrip: acks (True, False, True), chip id ff
import digitalio, microcontroller as mc
OD = digitalio.DriveMode.OPEN_DRAIN
def run(mode):
scl = digitalio.DigitalInOut(mc.pin.GPIO0); sda = digitalio.DigitalInOut(mc.pin.GPIO45)
od = {"scl-od-roundtrip": (scl,), "sda-od-roundtrip": (sda,), "both-od-roundtrip": (scl, sda), "input": ()}[mode]
for p in od:
p.switch_to_output(value=True, drive_mode=OD)
def rel(p):
if p in od:
p.value = True
p.switch_to_input(); p.value; p.switch_to_output(value=True, drive_mode=OD) # bitbangio's round trip
else:
p.switch_to_input()
def low(p):
if p in od: p.value = False
else: p.switch_to_output(value=False)
def rd(p):
p.switch_to_input(); v = p.value
if p in od: p.switch_to_output(value=True, drive_mode=OD)
return v
def wbyte(v):
for i in range(8):
(rel if v & (0x80 >> i) else low)(sda); rel(scl); low(scl)
rel(sda); rel(scl); ack = not rd(sda); low(scl); return ack
def rbyte():
rel(sda); v = 0
for _ in range(8):
rel(scl); v = (v << 1) | rd(sda); low(scl)
rel(sda); rel(scl); low(scl); return v
rel(scl); rel(sda); low(sda); low(scl)
acks = (wbyte(0x68 << 1), wbyte(0x00))
rel(sda); rel(scl); low(sda); low(scl)
acks += (wbyte((0x68 << 1) | 1),)
v = rbyte()
low(sda); rel(scl); rel(sda)
scl.deinit(); sda.deinit()
print("%-18s acks %s chip id %02x" % (mode, acks, v))
for m in ("input", "scl-od-roundtrip", "sda-od-roundtrip", "both-od-roundtrip", "input"):
run(m)
- Lingua principale
- C
- Stelle
- 4.6k
- Fork
- 1.4k
- Merge medio
- 1g 8h
- PR unite (30g)
- 158
Preparare l'ambiente
Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di adafruit/circuitpython
-
bug
Difficoltà 4/5 1-2 giorni Idoneità per principianti 35/100
adafruit/circuitpython#11641 ·
I maintainer di solito rispondono entro 1 giorno
-
Web Workflow Locks UpApertabug esp32 web workflow
Difficoltà 5/5 Più di una settimana Idoneità per principianti 12/100
adafruit/circuitpython#11616 · 9 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
nordic
Difficoltà 4/5 3-5 giorni Idoneità per principianti 30/100
adafruit/circuitpython#11611 ·
I maintainer di solito rispondono entro 1 giorno
-
zephyr: REPL on console?Aperta
Difficoltà 5/5 Più di una settimana Idoneità per principianti 15/100
adafruit/circuitpython#11606 ·
I maintainer di solito rispondono entro 1 giorno
-
busio zephyr
Difficoltà 5/5 Più di una settimana Idoneità per principianti 18/100
adafruit/circuitpython#11605 ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di adafruit/circuitpython
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
HexaCluster/credcheck#86 ·
-
Wheels for Python 3.15Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 66/100
mongodb/winkerberos#175 ·
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
AOMediaCodec/SVT-AV1#3320 ·
-
Add `CPC_TAKE_TILL_CHARS`Apertadifficulty: easy
Difficoltà 2/5 1-3 ore Idoneità per principianti 64/100