1010
1111#include "components/driver/i2c/include/driver/i2c.h"
1212
13+ #include "bindings/espidf/__init__.h"
1314#include "shared-bindings/microcontroller/__init__.h"
1415#include "shared-bindings/microcontroller/Pin.h"
1516
1617void 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 ) {
1819 // Pins 45 and 46 are "strapping" pins that impact start up behavior. They usually need to
1920 // be pulled-down so pulling them up for I2C is a bad idea. To make this hard, we don't
2021 // support I2C on these pins.
@@ -60,44 +61,42 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self,
6061 }
6162 #endif
6263
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+
6386 self -> xSemaphore = xSemaphoreCreateMutex ();
6487 if (self -> xSemaphore == NULL ) {
88+ i2c_del_master_bus (self -> handle );
89+ self -> handle = NULL ;
6590 mp_raise_RuntimeError (MP_ERROR_TEXT ("Unable to create lock" ));
6691 }
6792 self -> sda_pin = sda ;
6893 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 ;
101100 }
102101
103102 claim_pin (sda );
@@ -108,32 +107,27 @@ bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self) {
108107 return self -> sda_pin == NULL ;
109108}
110109
110+ void common_hal_busio_i2c_mark_deinit (busio_i2c_obj_t * self ) {
111+ self -> sda_pin = NULL ;
112+ }
113+
111114void common_hal_busio_i2c_deinit (busio_i2c_obj_t * self ) {
112115 if (common_hal_busio_i2c_deinited (self )) {
113116 return ;
114117 }
115118
116- peripherals_i2c_deinit (self -> i2c_num );
119+ i2c_del_master_bus (self -> handle );
120+ self -> handle = NULL ;
117121
118122 common_hal_reset_pin (self -> sda_pin );
119123 common_hal_reset_pin (self -> scl_pin );
120124 self -> sda_pin = NULL ;
121125 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 );
133127}
134128
135129bool 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 );
137131 return result == ESP_OK ;
138132}
139133
@@ -170,28 +164,54 @@ static uint8_t convert_esp_err(esp_err_t result) {
170164 }
171165}
172166
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+
173174uint8_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 );
178185}
179186
180187uint8_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 );
183198}
184199
185200uint8_t common_hal_busio_i2c_write_read (busio_i2c_obj_t * self , uint16_t addr ,
186201 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 );
190212}
191213
192214void common_hal_busio_i2c_never_reset (busio_i2c_obj_t * self ) {
193- never_reset_i2c (self -> i2c_num );
194-
195215 common_hal_never_reset_pin (self -> scl_pin );
196216 common_hal_never_reset_pin (self -> sda_pin );
197217}
0 commit comments