@@ -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*/
142143inline 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)
818827inline 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