Skip to content

Commit 786bacf

Browse files
committed
1. Optimize the description of i2c_bus-related usage
1 parent 5e5ed6e commit 786bacf

2 files changed

Lines changed: 35 additions & 35 deletions

File tree

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ If used alongside `M5Unified`, include it **before** `M5IOE1`:
3636
>
3737
> Alternatively, enable `CONFIG_I2C_BUS_BACKWARD_CONFIG` in menuconfig to remove the restriction.
3838
39+
### i2c_bus mode is not supported when M5GFX / M5Unified is present
40+
41+
Use `begin(&M5.In_I2C, addr, freq)` instead — M5GFX already owns the I2C bus and the two drivers cannot share it.
42+
3943
## License
4044

4145
- [M5IOE1 - MIT](LICENSE)

src/M5IOE1_i2c_compat.h

Lines changed: 31 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -152,36 +152,17 @@ static inline void M5IOE1_I2C_ARDUINO_SEND_WAKE(TwoWire *wire, uint8_t addr)
152152
// Detect if i2c_bus is available
153153
//
154154
// ESP-IDF < 5.3.0
155-
// 未启用 BACKWARD_CONFIG
156-
// → 不支持 i2c_bus,使用传统 driver/i2c.h Legacy API
157-
// 启用 BACKWARD_CONFIG
158-
// → i2c_bus.h 内部回退到 driver/i2c.h,可安全使用
155+
// Without BACKWARD_CONFIG: i2c_bus not supported; use legacy driver/i2c.h API.
156+
// With BACKWARD_CONFIG: i2c_bus.h falls back to driver/i2c.h internally, safe to use.
159157
//
160158
// ESP-IDF >= 5.3.0
161-
// 启用 BACKWARD_CONFIG
162-
// → i2c_bus.h 内部使用 driver/i2c.h,无冲突风险
163-
// 未启用 BACKWARD_CONFIG
164-
// driver/i2c.h 已被其他组件提前包含(_DRIVER_I2C_H_ 已定义)
165-
// → i2c_bus.h 会自定义 i2c_config_t,与已定义的版本冲突 → 禁用
166-
// driver/i2c.h 尚未被包含(_DRIVER_I2C_H_ 未定义)
167-
// → 无冲突风险,按默认配置启用 i2c_bus
168-
//
169-
// Detection logic:
170-
// ESP-IDF < 5.3.0:
171-
// Without BACKWARD_CONFIG: i2c_bus not supported; use legacy driver/i2c.h API.
172-
// With BACKWARD_CONFIG: i2c_bus.h falls back to driver/i2c.h internally, safe to use.
173-
// ESP-IDF >= 5.3.0:
174-
// With BACKWARD_CONFIG: i2c_bus.h uses driver/i2c.h internally, always conflict-free.
175-
// Without BACKWARD_CONFIG:
176-
// _DRIVER_I2C_H_ defined (driver/i2c.h already included by another component)
177-
// → i2c_bus.h would define its own i2c_config_t, conflicting with the existing one → disabled.
178-
// _DRIVER_I2C_H_ not defined (driver/i2c.h not yet included)
179-
// → no conflict risk, enable i2c_bus with default config.
180-
//
181-
// Note: _DRIVER_I2C_H_ is the include guard of driver/i2c.h (ESP-IDF legacy I2C header).
182-
// Checking it at preprocessor time reflects whether driver/i2c.h was included
183-
// BEFORE this header. Inclusion after this header cannot be detected here;
184-
// in that case the user is responsible for ensuring no conflict (or enabling BACKWARD_CONFIG).
159+
// [Highest priority] M5GFX or M5Unified is present:
160+
// -> i2c_bus mode is NEVER safe (runtime conflict), disabled with #error if detected.
161+
// Fix: use ioe1.begin(&M5.In_I2C, addr, freq) instead.
162+
// With BACKWARD_CONFIG (no M5GFX/M5Unified): i2c_bus.h uses driver/i2c.h internally, safe.
163+
// Without BACKWARD_CONFIG (no M5GFX/M5Unified):
164+
// _DRIVER_I2C_H_ defined: i2c_config_t typedef conflict risk, disabled.
165+
// _DRIVER_I2C_H_ not defined: no conflict risk, enable i2c_bus.
185166
#if __has_include(<i2c_bus.h>)
186167
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 3, 0)
187168
#if defined(CONFIG_I2C_BUS_BACKWARD_CONFIG)
@@ -191,14 +172,29 @@ static inline void M5IOE1_I2C_ARDUINO_SEND_WAKE(TwoWire *wire, uint8_t addr)
191172
#endif
192173
#else
193174
// IDF >= 5.3.0
194-
#if defined(CONFIG_I2C_BUS_BACKWARD_CONFIG)
195-
#define M5IOE1_HAS_I2C_BUS 1 // BACKWARD_CONFIG:i2c_bus.h 使用 driver/i2c.h,无冲突 / no conflict
196-
#elif defined(_DRIVER_I2C_H_) || (defined(__cplusplus) && __has_include(<utility/I2C_Class.hpp>))
197-
#define M5IOE1_HAS_I2C_BUS \
198-
0 // driver/i2c.h 已包含或 M5Unified 可用(将包含 driver/i2c.h)→ i2c_config_t 冲突风险,禁用
199-
// driver/i2c.h already included or M5Unified available (will include driver/i2c.h) → conflict risk, disabled
175+
//
176+
// Runtime conflict (highest priority):
177+
// M5GFX calls i2c_new_master_bus() (driver_ng) during global construction.
178+
// espressif__i2c_bus conflicts with it on both code paths:
179+
// BACKWARD_CONFIG=y -> i2c_bus.c calls i2c_driver_install() (legacy) -> runtime abort()
180+
// BACKWARD_CONFIG=n -> i2c_bus_v2.c calls i2c_new_master_bus() on the same port -> undefined behaviour
181+
// Therefore, i2c_bus mode MUST be disabled whenever M5GFX or M5Unified is in the project.
182+
#if __has_include(<M5GFX.h>) || __has_include(<M5Unified.h>)
183+
#if defined(_I2C_BUS_H_)
184+
#error \
185+
"[M5IOE1] i2c_bus cannot be used together with M5GFX/M5Unified. " \
186+
"M5GFX registers driver_ng via i2c_new_master_bus() during global construction. " \
187+
"BACKWARD_CONFIG=y: i2c_bus.c calls i2c_driver_install() (legacy driver) -> runtime abort() in check_i2c_driver_conflict(). " \
188+
"BACKWARD_CONFIG=n: i2c_bus_v2.c calls i2c_new_master_bus() on the same port -> undefined behaviour. " \
189+
"Fix: use ioe1.begin(&M5.In_I2C, addr, freq) and set I2C_USE_MODE=0."
190+
#endif
191+
#define M5IOE1_HAS_I2C_BUS 0
192+
#elif defined(CONFIG_I2C_BUS_BACKWARD_CONFIG)
193+
#define M5IOE1_HAS_I2C_BUS 1 // BACKWARD_CONFIG, no M5GFX/M5Unified: compatible
194+
#elif defined(_DRIVER_I2C_H_)
195+
#define M5IOE1_HAS_I2C_BUS 0 // driver/i2c.h already included -> i2c_config_t typedef conflict risk, disabled
200196
#else
201-
#define M5IOE1_HAS_I2C_BUS 1 // driver/i2c.h 尚未包含,无冲突风险 / driver/i2c.h not yet included, no conflict
197+
#define M5IOE1_HAS_I2C_BUS 1 // no conflict risk
202198
#endif
203199
#endif
204200
#else

0 commit comments

Comments
 (0)