Skip to content

ChainBus on second UART port (pins 5/6) fails with ESP_FAIL — regression since ≥2.4.x (works on 2.3.9, still broken on 2.5.3) #109

Description

@andreassommer1973-dev

ChainBus on second UART port (pins 5/6) fails with ESP_FAIL — regression since ≥2.4.x (works on 2.3.9, still broken on 2.5.3)

Environment

   
Device M5STACK DualKey (ESP32-S3-PICO-1)
Tested on Multiple physical DualKey units — same result on all
Firmware (broken) UIFlow2 / MicroPython 2.5.3 (latest as of 2026-09-11)
Firmware (working) UIFlow2 / MicroPython 2.3.9 — Port 2 worked correctly
Chain units tested AngleChain, PIRChain — same failure with both, on Port 2 only

Summary

ChainBus initialization on the DualKey's second expansion port (Port 2 — UART TX=6, RX=5, per the official pinout) fails with OSError: ESP_FAIL on current firmware (2.5.3). The first port (Port 1 — UART TX=47, RX=48) works correctly on the exact same board, in the exact same script.

This was confirmed not an issue on firmware 2.3.9, where Port 2 initialized and worked correctly. The regression was introduced somewhere between 2.3.9 and 2.5.3.

Since the failure reproduces identically across multiple separate DualKey units and multiple different Chain units (AngleChain, PIRChain), this points to a firmware/driver regression rather than a hardware defect.

Steps to reproduce

Fresh boot, no other code running, pasted directly at the MicroPython REPL:

import os, sys, io
import M5
from M5 import *
from chain import ChainBus
from unit import AudioPlayerUnit
from chain import AngleChain
from chain import PIRChain

bus2 = None
audioplayer_0 = None
chain_angle_0 = None
chain_pir_0 = None

def setup():
global bus2, audioplayer_0, chain_angle_0, chain_pir_0
M5.begin()
bus2 = ChainBus(2, tx=6, rx=5) # Port 2 — fails
audioplayer_0 = AudioPlayerUnit(2, port=(47, 48)) # Port 1 — works fine
chain_angle_0 = AngleChain(bus2, 1)
chain_pir_0 = PIRChain(bus2, 2)

def loop():
global bus2, audioplayer_0, chain_angle_0, chain_pir_0
M5.update()
print('hello M5')

if name == 'main':
try:
setup()
while True:
loop()
except (Exception, KeyboardInterrupt) as e:
try:
import sys
sys.print_exception(e)
if bus2:
bus2.deinit()
except ImportError:
print("please update to latest firmware")

Actual result (firmware 2.5.3)

Traceback (most recent call last):
  File "<stdin>", line 25, in <module>
  File "<stdin>", line 15, in setup
  File "chain/chain.py", line 475, in __init__
OSError: [Errno 1] EPERM: ESP_FAIL

The failure occurs at the ChainBus(2, tx=6, rx=5) call itself — before any Chain unit is even addressed. Isolating just this one line (removing the AudioPlayerUnit/AngleChain/PIRChain calls) reproduces the same error.

Expected result

ChainBus(2, tx=6, rx=5) should initialize Port 2 successfully, exactly as it did on firmware 2.3.9, and exactly as Port 1 (tx=47, rx=48) still does on 2.5.3.

Additional notes

  • Verified the pin assignment against the official docs — Port 2 is documented as UART2 TX=6 / RX=5, which matches the code above.
  • Ruled out a "stale UART driver from a previous run" as the cause: the failure reproduces on a completely fresh power-on boot, before any user code has run.
  • Happy to test specific intermediate firmware builds (2.4.x, 2.5.0, 2.5.1, 2.5.2) via M5Burner to help narrow down exactly which release introduced the regression, if that's useful.
# ChainBus on second UART port (pins 5/6) fails with `ESP_FAIL` — regression since ≥2.4.x (works on 2.3.9, still broken on 2.5.3)

Environment

Device M5STACK DualKey (ESP32-S3-PICO-1)
Tested on Multiple physical DualKey units — same result on all
Firmware (broken) UIFlow2 / MicroPython 2.5.3 (latest as of 2026-09-11)
Firmware (working) UIFlow2 / MicroPython 2.3.9 — Port 2 worked correctly
Chain units tested AngleChain, PIRChain — same failure with both, on Port 2 only

Summary

ChainBus initialization on the DualKey's second expansion port (Port 2 — UART TX=6, RX=5, per [the official pinout](https://docs.m5stack.com/en/chain/Chain_DualKey)) fails with OSError: ESP_FAIL on current firmware (2.5.3). The first port (Port 1 — UART TX=47, RX=48) works correctly on the exact same board, in the exact same script.

This was confirmed not an issue on firmware 2.3.9, where Port 2 initialized and worked correctly. The regression was introduced somewhere between 2.3.9 and 2.5.3.

Since the failure reproduces identically across multiple separate DualKey units and multiple different Chain units (AngleChain, PIRChain), this points to a firmware/driver regression rather than a hardware defect.

Steps to reproduce

Fresh boot, no other code running, pasted directly at the MicroPython REPL:

import os, sys, io
import M5
from M5 import *
from chain import ChainBus
from unit import AudioPlayerUnit
from chain import AngleChain
from chain import PIRChain

bus2 = None
audioplayer_0 = None
chain_angle_0 = None
chain_pir_0 = None

def setup():
  global bus2, audioplayer_0, chain_angle_0, chain_pir_0
  M5.begin()
  bus2 = ChainBus(2, tx=6, rx=5)               # Port 2 — fails
  audioplayer_0 = AudioPlayerUnit(2, port=(47, 48))  # Port 1 — works fine
  chain_angle_0 = AngleChain(bus2, 1)
  chain_pir_0 = PIRChain(bus2, 2)

def loop():
  global bus2, audioplayer_0, chain_angle_0, chain_pir_0
  M5.update()
  print('hello M5')

if __name__ == '__main__':
  try:
    setup()
    while True:
      loop()
  except (Exception, KeyboardInterrupt) as e:
    try:
      import sys
      sys.print_exception(e)
      if bus2:
        bus2.deinit()
    except ImportError:
      print("please update to latest firmware")

Actual result (firmware 2.5.3)

Traceback (most recent call last):
  File "<stdin>", line 25, in <module>
  File "<stdin>", line 15, in setup
  File "chain/chain.py", line 475, in __init__
OSError: [Errno 1] EPERM: ESP_FAIL

The failure occurs at the ChainBus(2, tx=6, rx=5) call itself — before any Chain unit is even addressed. Isolating just this one line (removing the AudioPlayerUnit/AngleChain/PIRChain calls) reproduces the same error.

Expected result

ChainBus(2, tx=6, rx=5) should initialize Port 2 successfully, exactly as it did on firmware 2.3.9, and exactly as Port 1 (tx=47, rx=48) still does on 2.5.3.

Additional notes

  • Verified the pin assignment against the official docs — Port 2 is documented as UART2 TX=6 / RX=5, which matches the code above.
  • Ruled out a "stale UART driver from a previous run" as the cause: the failure reproduces on a completely fresh power-on boot, before any user code has run.
  • Happy to test specific intermediate firmware builds (2.4.x, 2.5.0, 2.5.1, 2.5.2) via M5Burner to help narrow down exactly which release introduced the regression, if that's useful.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions