10
10
11
11
#include "components/driver/i2c/include/driver/i2c.h"
12
12
13
+ #include "bindings/espidf/__init__.h"
13
14
#include "shared-bindings/microcontroller/__init__.h"
14
15
#include "shared-bindings/microcontroller/Pin.h"
15
16
16
17
void common_hal_busio_i2c_construct (busio_i2c_obj_t * self ,
17
- const mcu_pin_obj_t * scl , const mcu_pin_obj_t * sda , uint32_t frequency , uint32_t timeout ) {
18
+ const mcu_pin_obj_t * scl , const mcu_pin_obj_t * sda , uint32_t frequency , uint32_t timeout_us ) {
18
19
// Pins 45 and 46 are "strapping" pins that impact start up behavior. They usually need to
19
20
// be pulled-down so pulling them up for I2C is a bad idea. To make this hard, we don't
20
21
// support I2C on these pins.
@@ -60,44 +61,42 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self,
60
61
}
61
62
#endif
62
63
64
+
65
+ i2c_master_bus_config_t config = {
66
+ .i2c_port = -1 , // auto
67
+ .sda_io_num = sda -> number ,
68
+ .scl_io_num = scl -> number ,
69
+ .clk_source = I2C_CLK_SRC_DEFAULT ,
70
+ .glitch_ignore_cnt = 7 ,
71
+ .flags = {
72
+ #if CIRCUITPY_I2C_ALLOW_INTERNAL_PULL_UP
73
+ .enable_internal_pullup = true, /*!< Internal GPIO pull mode for I2C sda signal*/
74
+ #else
75
+ .enable_internal_pullup = false, /*!< Internal GPIO pull mode for I2C sda signal*/
76
+ #endif
77
+ }
78
+ };
79
+ esp_err_t result = i2c_new_master_bus (& config , & self -> handle );
80
+
81
+ if (result == ESP_ERR_NOT_FOUND ) {
82
+ mp_raise_ValueError (MP_ERROR_TEXT ("All I2C peripherals are in use" ));
83
+ }
84
+ CHECK_ESP_RESULT (result );
85
+
63
86
self -> xSemaphore = xSemaphoreCreateMutex ();
64
87
if (self -> xSemaphore == NULL ) {
88
+ i2c_del_master_bus (self -> handle );
89
+ self -> handle = NULL ;
65
90
mp_raise_RuntimeError (MP_ERROR_TEXT ("Unable to create lock" ));
66
91
}
67
92
self -> sda_pin = sda ;
68
93
self -> scl_pin = scl ;
69
- self -> i2c_num = peripherals_i2c_get_free_num ();
70
- self -> has_lock = 0 ;
71
-
72
- if (self -> i2c_num == I2C_NUM_MAX ) {
73
- mp_raise_ValueError (MP_ERROR_TEXT ("All I2C peripherals are in use" ));
74
- }
75
-
76
- const i2c_config_t i2c_conf = {
77
- .mode = I2C_MODE_MASTER ,
78
- .sda_io_num = self -> sda_pin -> number ,
79
- .scl_io_num = self -> scl_pin -> number ,
80
- #if CIRCUITPY_I2C_ALLOW_INTERNAL_PULL_UP
81
- .sda_pullup_en = GPIO_PULLUP_ENABLE , /*!< Internal GPIO pull mode for I2C sda signal*/
82
- .scl_pullup_en = GPIO_PULLUP_ENABLE , /*!< Internal GPIO pull mode for I2C scl signal*/
83
- #else
84
- .sda_pullup_en = GPIO_PULLUP_DISABLE , /*!< Internal GPIO pull mode for I2C sda signal*/
85
- .scl_pullup_en = GPIO_PULLUP_DISABLE , /*!< Internal GPIO pull mode for I2C scl signal*/
86
- #endif
87
-
88
- .master = {
89
- .clk_speed = frequency ,
90
- }
91
- };
92
-
93
- // Initialize I2C.
94
- esp_err_t err = peripherals_i2c_init (self -> i2c_num , & i2c_conf );
95
- if (err != ESP_OK ) {
96
- if (err == ESP_FAIL ) {
97
- mp_raise_OSError (MP_EIO );
98
- } else {
99
- mp_raise_RuntimeError (MP_ERROR_TEXT ("init I2C" ));
100
- }
94
+ self -> has_lock = false;
95
+ self -> frequency = frequency ;
96
+ self -> timeout_ms = timeout_us / 1000 ;
97
+ // Round up timeout to nearest ms.
98
+ if (timeout_us % 1000 != 0 ) {
99
+ self -> timeout_ms += 1 ;
101
100
}
102
101
103
102
claim_pin (sda );
@@ -108,32 +107,27 @@ bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self) {
108
107
return self -> sda_pin == NULL ;
109
108
}
110
109
110
+ void common_hal_busio_i2c_mark_deinit (busio_i2c_obj_t * self ) {
111
+ self -> sda_pin = NULL ;
112
+ }
113
+
111
114
void common_hal_busio_i2c_deinit (busio_i2c_obj_t * self ) {
112
115
if (common_hal_busio_i2c_deinited (self )) {
113
116
return ;
114
117
}
115
118
116
- peripherals_i2c_deinit (self -> i2c_num );
119
+ i2c_del_master_bus (self -> handle );
120
+ self -> handle = NULL ;
117
121
118
122
common_hal_reset_pin (self -> sda_pin );
119
123
common_hal_reset_pin (self -> scl_pin );
120
124
self -> sda_pin = NULL ;
121
125
self -> scl_pin = NULL ;
122
- }
123
-
124
- static esp_err_t i2c_zero_length_write (busio_i2c_obj_t * self , uint8_t addr , TickType_t timeout ) {
125
- // i2c_master_write_to_device() won't do zero-length writes, so we do it by hand.
126
- i2c_cmd_handle_t cmd = i2c_cmd_link_create ();
127
- i2c_master_start (cmd );
128
- i2c_master_write_byte (cmd , addr << 1 , true);
129
- i2c_master_stop (cmd );
130
- esp_err_t result = i2c_master_cmd_begin (self -> i2c_num , cmd , timeout );
131
- i2c_cmd_link_delete (cmd );
132
- return result ;
126
+ common_hal_busio_i2c_mark_deinit (self );
133
127
}
134
128
135
129
bool common_hal_busio_i2c_probe (busio_i2c_obj_t * self , uint8_t addr ) {
136
- esp_err_t result = i2c_zero_length_write (self , addr , pdMS_TO_TICKS ( 10 ) );
130
+ esp_err_t result = i2c_master_probe (self -> handle , addr , 1 );
137
131
return result == ESP_OK ;
138
132
}
139
133
@@ -170,28 +164,54 @@ static uint8_t convert_esp_err(esp_err_t result) {
170
164
}
171
165
}
172
166
167
+ static size_t _transaction_duration (size_t frequency , size_t len ) {
168
+ size_t khz = frequency / 1000 ;
169
+ size_t bytes_per_ms = khz / 8 ;
170
+ // + 1 for the address byte
171
+ return (len + 1 ) / bytes_per_ms ;
172
+ }
173
+
173
174
uint8_t common_hal_busio_i2c_write (busio_i2c_obj_t * self , uint16_t addr , const uint8_t * data , size_t len ) {
174
- return convert_esp_err (len == 0
175
- ? i2c_zero_length_write (self , addr , pdMS_TO_TICKS (1000 ))
176
- : i2c_master_write_to_device (self -> i2c_num , (uint8_t )addr , data , len , pdMS_TO_TICKS (1000 ))
177
- );
175
+ i2c_device_config_t dev_config = {
176
+ .dev_addr_length = I2C_ADDR_BIT_LEN_7 ,
177
+ .device_address = addr ,
178
+ .scl_speed_hz = self -> frequency
179
+ };
180
+ i2c_master_dev_handle_t dev_handle ;
181
+ CHECK_ESP_RESULT (i2c_master_bus_add_device (self -> handle , & dev_config , & dev_handle ));
182
+ esp_err_t result = i2c_master_transmit (dev_handle , data , len , _transaction_duration (self -> frequency , len ) + self -> timeout_ms );
183
+ CHECK_ESP_RESULT (i2c_master_bus_rm_device (dev_handle ));
184
+ return convert_esp_err (result );
178
185
}
179
186
180
187
uint8_t common_hal_busio_i2c_read (busio_i2c_obj_t * self , uint16_t addr , uint8_t * data , size_t len ) {
181
- return convert_esp_err (
182
- i2c_master_read_from_device (self -> i2c_num , (uint8_t )addr , data , len , pdMS_TO_TICKS (1000 )));
188
+ i2c_device_config_t dev_config = {
189
+ .dev_addr_length = I2C_ADDR_BIT_LEN_7 ,
190
+ .device_address = addr ,
191
+ .scl_speed_hz = self -> frequency
192
+ };
193
+ i2c_master_dev_handle_t dev_handle ;
194
+ CHECK_ESP_RESULT (i2c_master_bus_add_device (self -> handle , & dev_config , & dev_handle ));
195
+ esp_err_t result = i2c_master_receive (dev_handle , data , len , _transaction_duration (self -> frequency , len ) + self -> timeout_ms );
196
+ CHECK_ESP_RESULT (i2c_master_bus_rm_device (dev_handle ));
197
+ return convert_esp_err (result );
183
198
}
184
199
185
200
uint8_t common_hal_busio_i2c_write_read (busio_i2c_obj_t * self , uint16_t addr ,
186
201
uint8_t * out_data , size_t out_len , uint8_t * in_data , size_t in_len ) {
187
- return convert_esp_err (
188
- i2c_master_write_read_device (self -> i2c_num , (uint8_t )addr ,
189
- out_data , out_len , in_data , in_len , pdMS_TO_TICKS (1000 )));
202
+ i2c_device_config_t dev_config = {
203
+ .dev_addr_length = I2C_ADDR_BIT_LEN_7 ,
204
+ .device_address = addr ,
205
+ .scl_speed_hz = self -> frequency
206
+ };
207
+ i2c_master_dev_handle_t dev_handle ;
208
+ CHECK_ESP_RESULT (i2c_master_bus_add_device (self -> handle , & dev_config , & dev_handle ));
209
+ esp_err_t result = i2c_master_transmit_receive (dev_handle , out_data , out_len , in_data , in_len , _transaction_duration (self -> frequency , out_len ) + _transaction_duration (self -> frequency , in_len ) + self -> timeout_ms );
210
+ CHECK_ESP_RESULT (i2c_master_bus_rm_device (dev_handle ));
211
+ return convert_esp_err (result );
190
212
}
191
213
192
214
void common_hal_busio_i2c_never_reset (busio_i2c_obj_t * self ) {
193
- never_reset_i2c (self -> i2c_num );
194
-
195
215
common_hal_never_reset_pin (self -> scl_pin );
196
216
common_hal_never_reset_pin (self -> sda_pin );
197
217
}
0 commit comments