2828#include "py/mphal.h"
2929#include "py/mperrno.h"
3030#include "extmod/modmachine.h"
31- #include "machine_i2c.h"
3231
33- #include "driver/i2c.h"
34- #include "hal/i2c_ll.h"
32+ #include "driver/i2c_master.h"
3533
3634#if MICROPY_PY_MACHINE_I2C || MICROPY_PY_MACHINE_SOFTI2C
3735
38- #if SOC_I2C_SUPPORT_XTAL
39- #if CONFIG_XTAL_FREQ > 0
40- #define I2C_SCLK_FREQ (CONFIG_XTAL_FREQ * 1000000)
36+ #ifndef MICROPY_HW_I2C0_SCL
37+ #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
38+ #define MICROPY_HW_I2C0_SCL (GPIO_NUM_9)
39+ #define MICROPY_HW_I2C0_SDA (GPIO_NUM_8)
40+ #else
41+ #define MICROPY_HW_I2C0_SCL (GPIO_NUM_18)
42+ #define MICROPY_HW_I2C0_SDA (GPIO_NUM_19)
43+ #endif
44+ #endif
45+
46+ #ifndef MICROPY_HW_I2C1_SCL
47+ #if CONFIG_IDF_TARGET_ESP32
48+ #define MICROPY_HW_I2C1_SCL (GPIO_NUM_25)
49+ #define MICROPY_HW_I2C1_SDA (GPIO_NUM_26)
4150#else
42- #error "I2C uses XTAL but no configured freq"
43- #endif // CONFIG_XTAL_FREQ
51+ #define MICROPY_HW_I2C1_SCL (GPIO_NUM_9)
52+ #define MICROPY_HW_I2C1_SDA (GPIO_NUM_8)
53+ #endif
54+ #endif
55+
56+ #if SOC_I2C_SUPPORT_XTAL
57+ #define I2C_SCLK_FREQ XTAL_CLK_FREQ
4458#elif SOC_I2C_SUPPORT_APB
4559#define I2C_SCLK_FREQ APB_CLK_FREQ
4660#else
4963
5064#define I2C_DEFAULT_TIMEOUT_US (50000) // 50ms
5165
66+ // ---------------- 内部数据结构 ----------------
5267typedef struct _machine_hw_i2c_obj_t {
5368 mp_obj_base_t base ;
54- i2c_port_t port : 8 ;
55- gpio_num_t scl : 8 ;
56- gpio_num_t sda : 8 ;
69+ i2c_master_bus_handle_t bus_handle ;
70+ i2c_master_dev_handle_t dev_handle ;
71+ uint8_t port ;
72+ gpio_num_t scl ;
73+ gpio_num_t sda ;
5774} machine_hw_i2c_obj_t ;
5875
5976static machine_hw_i2c_obj_t machine_hw_i2c_obj [I2C_NUM_MAX ];
6077
61- static void machine_hw_i2c_init (machine_hw_i2c_obj_t * self , uint32_t freq , uint32_t timeout_us , bool first_init ) {
62- if (!first_init ) {
63- i2c_driver_delete (self -> port );
78+ // ---------------- 初始化 ----------------
79+ static void machine_hw_i2c_init (machine_hw_i2c_obj_t * self ,
80+ uint32_t freq ,
81+ uint32_t timeout_us ,
82+ bool first_init ) {
83+
84+ // 1. 若已初始化,先卸载旧驱动
85+ if (!first_init && self -> bus_handle ) {
86+ i2c_master_bus_rm_device (self -> dev_handle );
87+ i2c_del_master_bus (self -> bus_handle );
88+ self -> bus_handle = NULL ;
89+ self -> dev_handle = NULL ;
6490 }
65- i2c_config_t conf = {
66- . mode = I2C_MODE_MASTER ,
67- . sda_io_num = self -> sda ,
68- .sda_pullup_en = GPIO_PULLUP_ENABLE ,
91+
92+ // 2. 配置总线
93+ i2c_master_bus_config_t bus_cfg = {
94+ .i2c_port = self -> port ,
6995 .scl_io_num = self -> scl ,
70- .scl_pullup_en = GPIO_PULLUP_ENABLE ,
71- .master .clk_speed = freq ,
96+ .sda_io_num = self -> sda ,
97+ .clk_source = I2C_CLK_SRC_DEFAULT ,
98+ .glitch_ignore_cnt = 7 ,
99+ .flags .enable_internal_pullup = true,
100+ };
101+ ESP_ERROR_CHECK (i2c_new_master_bus (& bus_cfg , & self -> bus_handle ));
102+
103+ // 3. 添加设备(占位地址,后面真正传输时再动态改)
104+ i2c_device_config_t dev_cfg = {
105+ .dev_addr_length = I2C_ADDR_BIT_LEN_7 ,
106+ .device_address = 0x00 , // 占位
107+ .scl_speed_hz = freq ,
72108 };
73- i2c_param_config (self -> port , & conf );
74- int timeout = I2C_SCLK_FREQ / 1000000 * timeout_us ;
75- i2c_set_timeout (self -> port , (timeout > I2C_LL_MAX_TIMEOUT ) ? I2C_LL_MAX_TIMEOUT : timeout );
76- i2c_driver_install (self -> port , I2C_MODE_MASTER , 0 , 0 , 0 );
109+ ESP_ERROR_CHECK (i2c_master_bus_add_device (self -> bus_handle , & dev_cfg , & self -> dev_handle ));
77110}
78111
79- int machine_hw_i2c_transfer (mp_obj_base_t * self_in , uint16_t addr , size_t n , mp_machine_i2c_buf_t * bufs , unsigned int flags ) {
112+ int machine_hw_i2c_transfer (mp_obj_base_t * self_in ,
113+ uint16_t addr ,
114+ size_t n ,
115+ mp_machine_i2c_buf_t * bufs ,
116+ unsigned int flags )
117+ {
80118 machine_hw_i2c_obj_t * self = MP_OBJ_TO_PTR (self_in );
81119
82- i2c_cmd_handle_t cmd = i2c_cmd_link_create ();
120+ /* 0. 先探测地址是否有设备回应 */
121+ esp_err_t err = i2c_master_probe (self -> bus_handle , addr , 1000 );
122+ if (err != ESP_OK ) {
123+ return - MP_ENODEV ; /* 地址无设备,直接返回 */
124+ }
125+ /* 1. 为本次事务创建临时 device 句柄 */
126+ i2c_device_config_t dev_cfg = {
127+ .dev_addr_length = I2C_ADDR_BIT_LEN_7 ,
128+ .device_address = addr ,
129+ .scl_speed_hz = 100000 , /* 沿用总线频率即可 */
130+ };
131+ i2c_master_dev_handle_t dev_handle ;
132+ err = i2c_master_bus_add_device (self -> bus_handle , & dev_cfg , & dev_handle );
133+ if (err != ESP_OK ) {
134+ return - MP_ENODEV ;
135+ }
136+
83137 int data_len = 0 ;
84138
139+ /* 2. 若有 WRITE1 段,先写一段 */
85140 if (flags & MP_MACHINE_I2C_FLAG_WRITE1 ) {
86- i2c_master_start (cmd );
87- i2c_master_write_byte (cmd , addr << 1 , true);
88- i2c_master_write (cmd , bufs -> buf , bufs -> len , true);
141+ if (bufs -> len ) {
142+ err = i2c_master_transmit (dev_handle ,
143+ bufs -> buf ,
144+ bufs -> len ,
145+ 1000 ); /* 阻塞超时 1 s */
146+ if (err != ESP_OK ) goto cleanup ;
147+ }
89148 data_len += bufs -> len ;
90149 -- n ;
91150 ++ bufs ;
92151 }
152+ if (flags & MP_MACHINE_I2C_FLAG_READ ) {
153+ /* 3. 主循环:剩余段 */
154+ for (; n -- ; ++ bufs ) {
155+ if (bufs -> len == 0 ) continue ;
156+ err = i2c_master_receive (dev_handle ,
157+ bufs -> buf ,
158+ //bufs->len,
159+ 1 ,
160+ 1000 );
161+ if (err != ESP_OK ) break ;
93162
94- i2c_master_start (cmd );
95- i2c_master_write_byte (cmd , addr << 1 | (flags & MP_MACHINE_I2C_FLAG_READ ), true);
163+ data_len += bufs -> len ;
164+ }
165+ } else {
166+ // 写操作逻辑
167+ size_t total_len = 0 ;
168+ mp_machine_i2c_buf_t * original_bufs = bufs ; // 保存原始指针
169+ size_t yuann = n ;
96170
97- for (; n -- ; ++ bufs ) {
98- if (flags & MP_MACHINE_I2C_FLAG_READ ) {
99- i2c_master_read (cmd , bufs -> buf , bufs -> len , n == 0 ? I2C_MASTER_LAST_NACK : I2C_MASTER_ACK );
100- } else {
101- if (bufs -> len != 0 ) {
102- i2c_master_write (cmd , bufs -> buf , bufs -> len , true);
103- }
171+ // 计算总长度
172+ for (; n -- ; ++ bufs ) {
173+ total_len += bufs -> len ;
104174 }
105- data_len += bufs -> len ;
106- }
107175
108- if (flags & MP_MACHINE_I2C_FLAG_STOP ) {
109- i2c_master_stop (cmd );
110- }
176+ // 重置指针
177+ bufs = original_bufs ;
178+ // 重置n
179+ n = yuann ;
180+ // 动态分配 write_buf
181+ uint8_t * write_buf = (uint8_t * )malloc (total_len );
182+ if (write_buf == NULL ) return - MP_ENOMEM ;
183+
184+ // 复制数据到 write_buf
185+ size_t index = 0 ;
186+ for (; n -- ; ++ bufs ) {
187+ memcpy (write_buf + index , bufs -> buf , bufs -> len );
188+ index += bufs -> len ;
189+ }
111190
112- // TODO proper timeout
113- esp_err_t err = i2c_master_cmd_begin ( self -> port , cmd , 100 * ( 1 + data_len ) / portTICK_PERIOD_MS );
114- i2c_cmd_link_delete ( cmd ) ;
191+ // 发送数据
192+ err = i2c_master_transmit ( dev_handle , write_buf , total_len , 1000 );
193+ if ( err != ESP_OK ) goto cleanup ;
115194
116- if (err == ESP_FAIL ) {
117- return - MP_ENODEV ;
118- } else if (err == ESP_ERR_TIMEOUT ) {
119- return - MP_ETIMEDOUT ;
120- } else if (err != ESP_OK ) {
121- return - abs (err );
195+ // 释放动态分配的内存
196+ free (write_buf );
122197 }
123198
199+ cleanup :
200+ /* 4. 立即销毁临时句柄 */
201+ i2c_master_bus_rm_device (dev_handle );
202+
203+ /* 5. 出错映射 */
204+ if (err == ESP_FAIL ) return - MP_ENODEV ;
205+ if (err == ESP_ERR_TIMEOUT ) return - MP_ETIMEDOUT ;
206+ if (err != ESP_OK ) return - abs (err );
207+
124208 return data_len ;
125209}
126210
127- /******************************************************************************/
128- // MicroPython bindings for machine API
129-
130- static void machine_hw_i2c_print ( const mp_print_t * print , mp_obj_t self_in , mp_print_kind_t kind ) {
211+ // ---------------- 打印 ----------------
212+ static void machine_hw_i2c_print ( const mp_print_t * print ,
213+ mp_obj_t self_in ,
214+ mp_print_kind_t kind ) {
131215 machine_hw_i2c_obj_t * self = MP_OBJ_TO_PTR (self_in );
132- int h , l ;
133- i2c_get_period (self -> port , & h , & l );
134- mp_printf (print , "I2C(%u, scl=%u, sda=%u, freq=%u)" ,
135- self -> port , self -> scl , self -> sda , I2C_SCLK_FREQ / (h + l ));
216+ mp_printf (print , "I2C(%u, scl=%u, sda=%u)" ,
217+ self -> port , self -> scl , self -> sda );
136218}
137219
138- mp_obj_t machine_hw_i2c_make_new (const mp_obj_type_t * type , size_t n_args , size_t n_kw , const mp_obj_t * all_args ) {
220+ // ---------------- 构造函数 ----------------
221+ mp_obj_t machine_hw_i2c_make_new (const mp_obj_type_t * type ,
222+ size_t n_args , size_t n_kw ,
223+ const mp_obj_t * all_args ) {
139224 // Create a SoftI2C instance if no id is specified (or is -1) but other arguments are given
140225 if (n_args != 0 ) {
141226 MP_MACHINE_I2C_CHECK_FOR_LEGACY_SOFTI2C_CONSTRUCTION (n_args , n_kw , all_args );
142227 }
143-
144- // Parse args
145228 enum { ARG_id , ARG_scl , ARG_sda , ARG_freq , ARG_timeout };
146229 static const mp_arg_t allowed_args [] = {
147230 { MP_QSTR_id , MP_ARG_INT , {.u_int = I2C_NUM_0 } },
@@ -151,48 +234,40 @@ mp_obj_t machine_hw_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_
151234 { MP_QSTR_timeout , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = I2C_DEFAULT_TIMEOUT_US } },
152235 };
153236 mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
154- mp_arg_parse_all_kw_array (n_args , n_kw , all_args , MP_ARRAY_SIZE (allowed_args ), allowed_args , args );
237+ mp_arg_parse_all_kw_array (n_args , n_kw , all_args ,
238+ MP_ARRAY_SIZE (allowed_args ), allowed_args , args );
155239
156- // Get I2C bus
157240 mp_int_t i2c_id = args [ARG_id ].u_int ;
158-
159- // Check if the I2C bus is valid
160241 if (!(I2C_NUM_0 <= i2c_id && i2c_id < I2C_NUM_MAX )) {
161- mp_raise_msg_varg (& mp_type_ValueError , MP_ERROR_TEXT ("I2C(%d) doesn't exist" ), i2c_id );
242+ mp_raise_msg_varg (& mp_type_ValueError ,
243+ MP_ERROR_TEXT ("I2C(%d) doesn't exist" ), i2c_id );
162244 }
163245
164- // Get static peripheral object
165- machine_hw_i2c_obj_t * self = (machine_hw_i2c_obj_t * )& machine_hw_i2c_obj [i2c_id ];
246+ machine_hw_i2c_obj_t * self = & machine_hw_i2c_obj [i2c_id ];
166247
167- bool first_init = false;
168- if (self -> base .type == NULL ) {
169- // Created for the first time, set default pins
248+ bool first_init = (self -> base .type == NULL );
249+ if (first_init ) {
170250 self -> base .type = & machine_i2c_type ;
171251 self -> port = i2c_id ;
172- if (self -> port == I2C_NUM_0 ) {
173- self -> scl = MICROPY_HW_I2C0_SCL ;
174- self -> sda = MICROPY_HW_I2C0_SDA ;
175- } else {
176- self -> scl = MICROPY_HW_I2C1_SCL ;
177- self -> sda = MICROPY_HW_I2C1_SDA ;
178- }
179- first_init = true;
252+ self -> scl = (i2c_id == I2C_NUM_0 ) ? MICROPY_HW_I2C0_SCL : MICROPY_HW_I2C1_SCL ;
253+ self -> sda = (i2c_id == I2C_NUM_0 ) ? MICROPY_HW_I2C0_SDA : MICROPY_HW_I2C1_SDA ;
180254 }
181255
182- // Set SCL/SDA pins if given
183256 if (args [ARG_scl ].u_obj != MP_OBJ_NULL ) {
184257 self -> scl = machine_pin_get_id (args [ARG_scl ].u_obj );
185258 }
186259 if (args [ARG_sda ].u_obj != MP_OBJ_NULL ) {
187260 self -> sda = machine_pin_get_id (args [ARG_sda ].u_obj );
188261 }
189262
190- // Initialise the I2C peripheral
191- machine_hw_i2c_init (self , args [ARG_freq ].u_int , args [ARG_timeout ].u_int , first_init );
192-
263+ machine_hw_i2c_init (self ,
264+ args [ARG_freq ].u_int ,
265+ args [ARG_timeout ].u_int ,
266+ first_init );
193267 return MP_OBJ_FROM_PTR (self );
194268}
195269
270+ // ---------------- 协议表 ----------------
196271static const mp_machine_i2c_p_t machine_hw_i2c_p = {
197272 .transfer_supports_write1 = true,
198273 .transfer = machine_hw_i2c_transfer ,
@@ -206,6 +281,6 @@ MP_DEFINE_CONST_OBJ_TYPE(
206281 print , machine_hw_i2c_print ,
207282 protocol , & machine_hw_i2c_p ,
208283 locals_dict , & mp_machine_i2c_locals_dict
209- );
284+ );
210285
211- #endif
286+ #endif // MICROPY_PY_MACHINE_I2C || MICROPY_PY_MACHINE_SOFTI2C
0 commit comments