Skip to content

Commit f67e70b

Browse files
committed
Route Core default I2C to Ex_I2C to avoid bus collision in wiring helpers
1 parent a40dc9b commit f67e70b

1 file changed

Lines changed: 14 additions & 4 deletions

File tree

src/wiring/m5_unit_unified_wiring.hpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ struct HatPinPair {
137137
@param nesso NessoN1 only: PortB = direct GROVE (SoftwareI2C), PortA = QWIIC (Wire)
138138
@return I2CPins { sda, scl, backend }
139139
@note NessoN1 PortB -> SoftwareI2C on port_b. NessoN1 PortA -> Wire on port_a (= QWIIC).
140+
Core (board_M5Stack) -> ExI2C (In_I2C/Ex_I2C are one shared bus; borrow it to avoid a collision).
140141
NanoC6/NanoH2 -> ExI2C (sda/scl reflect port_a pins for diagnostic). Others -> Wire on port_a.
141142
*/
142143
inline I2CPins i2cPins(const NessoPort nesso = NessoPort::PortB)
@@ -154,6 +155,13 @@ inline I2CPins i2cPins(const NessoPort nesso = NessoPort::PortB)
154155
return {static_cast<int8_t>(M5.getPin(m5::pin_name_t::ex_i2c_sda)),
155156
static_cast<int8_t>(M5.getPin(m5::pin_name_t::ex_i2c_scl)), I2CPins::Backend::ExI2C};
156157
}
158+
if (board == m5::board_t::board_M5Stack) {
159+
// Core (Basic/Gray/Go/Fire): In_I2C and Ex_I2C are the same bus (I2C_NUM_0 / GPIO21,22).
160+
// M5.begin() already installs that bus via In_I2C, so opening a new Wire / native master bus
161+
// on the same port would collide. Borrow M5.Ex_I2C instead (ExI2C backend -> i2cClass).
162+
return {static_cast<int8_t>(M5.getPin(m5::pin_name_t::ex_i2c_sda)),
163+
static_cast<int8_t>(M5.getPin(m5::pin_name_t::ex_i2c_scl)), I2CPins::Backend::ExI2C};
164+
}
157165
return {static_cast<int8_t>(M5.getPin(m5::pin_name_t::port_a_sda)),
158166
static_cast<int8_t>(M5.getPin(m5::pin_name_t::port_a_scl)), I2CPins::Backend::Wire};
159167
}
@@ -812,9 +820,10 @@ inline spi_device_handle_t spiDeviceHandle(const spi_host_device_t host, const g
812820
//! @note Dispatch matrix (mirrors Arduino addI2C's intent on each backend / board):
813821
//! - SoftwareI2C (NessoN1 PortB) -> i2cSoftware() via M5HAL bit-bang
814822
//! - Wire on NessoN1 (PortA QWIIC) -> borrow M5.Ex_I2C (M5Unified holds I2C_NUM_0)
815-
//! - Wire on other boards (Core/Stick/S3 etc) -> install a new bus via i2c_new_master_bus
823+
//! - Wire on other boards (Stick/S3 etc) -> install a new bus via i2c_new_master_bus
816824
//! (M5Unified does NOT call Wire.begin() on these boards, so I2C_NUM_0 is free)
817-
//! - ExI2C (NanoC6/NanoH2) -> borrow M5.Ex_I2C
825+
//! - ExI2C (Core, NanoC6/NanoH2) -> borrow M5.Ex_I2C
826+
//! (Core: In_I2C/Ex_I2C share I2C_NUM_0, already installed by M5.begin(); borrow it)
818827
inline bool addI2C(UnitUnified& units, Component& unit, const uint32_t clock = 100000,
819828
const NessoPort nesso = NessoPort::PortB)
820829
{
@@ -836,7 +845,8 @@ inline bool addI2C(UnitUnified& units, Component& unit, const uint32_t clock = 1
836845
// M5Unified already holds I2C_NUM_0 here, so borrow instead of installing.
837846
return i2cClass(units, unit, M5.In_I2C);
838847
} else {
839-
// Core / Stick / S3 etc: M5Unified does not call Wire.begin(), so install ourselves
848+
// Stick / S3 etc: M5Unified does not call Wire.begin(), so install ourselves
849+
// (Core is routed to ExI2C by i2cPins() and never reaches this branch)
840850
#if __has_include(<driver/i2c_master.h>)
841851
auto bus = i2cBusHandle(I2C_NUM_0, (gpio_num_t)pins.sda, (gpio_num_t)pins.scl, clock);
842852
if (!bus) return false;
@@ -849,7 +859,7 @@ inline bool addI2C(UnitUnified& units, Component& unit, const uint32_t clock = 1
849859
#endif
850860
}
851861
case I2CPins::Backend::ExI2C:
852-
// NanoC6 / NanoH2: M5Unified manages Ex_I2C -> borrow
862+
// Core / NanoC6 / NanoH2: M5Unified manages Ex_I2C (Core shares it with In_I2C) -> borrow
853863
return i2cClass(units, unit, M5.Ex_I2C);
854864
}
855865
return false;

0 commit comments

Comments
 (0)