@@ -79,20 +79,59 @@ void common_hal_busio_i2c_never_reset(busio_i2c_obj_t *self) {
7979 }
8080}
8181
82+ static bool _bus_is_sane (uint32_t scl_pin , uint32_t sda_pin ) {
83+ #if CIRCUITPY_REQUIRE_I2C_PULLUPS
84+ nrf_gpio_cfg_input (scl_pin , NRF_GPIO_PIN_PULLDOWN );
85+ nrf_gpio_cfg_input (sda_pin , NRF_GPIO_PIN_PULLDOWN );
86+
87+ common_hal_mcu_delay_us (10 );
88+
89+ nrf_gpio_cfg_input (scl_pin , NRF_GPIO_PIN_NOPULL );
90+ nrf_gpio_cfg_input (sda_pin , NRF_GPIO_PIN_NOPULL );
91+
92+ // We must pull up within 3us to achieve 400khz.
93+ common_hal_mcu_delay_us (3 );
94+ if (!nrf_gpio_pin_read (sda_pin ) || !nrf_gpio_pin_read (scl_pin )) {
95+ return false;
96+ } else {
97+ return true;
98+ }
99+ #else
100+ return true;
101+ #endif
102+ }
103+
104+ static nrfx_err_t _safe_twim_enable (busio_i2c_obj_t * self ) {
105+ // check to see if bus is in sensible state before enabling twim
106+ nrfx_err_t recover_result ;
107+
108+ if (!_bus_is_sane (self -> scl_pin_number , self -> sda_pin_number )) {
109+ // bus not in a sane state - try to recover
110+ recover_result = nrfx_twim_bus_recover (self -> scl_pin_number , self -> sda_pin_number );
111+ if (NRFX_SUCCESS != recover_result ) {
112+ // return error message if unable to recover the bus
113+ return recover_result ;
114+ }
115+ }
116+
117+ nrfx_twim_enable (& self -> twim_peripheral -> twim );
118+ return NRFX_SUCCESS ;
119+ }
120+
82121static uint8_t twi_error_to_mp (const nrfx_err_t err ) {
83122 switch (err ) {
84123 case NRFX_ERROR_DRV_TWI_ERR_ANACK :
85124 return MP_ENODEV ;
86125 case NRFX_ERROR_BUSY :
87126 return MP_EBUSY ;
127+ case NRFX_SUCCESS :
128+ return 0 ;
88129 case NRFX_ERROR_DRV_TWI_ERR_DNACK :
89130 case NRFX_ERROR_INVALID_ADDR :
90- return MP_EIO ;
131+ case NRFX_ERROR_INTERNAL :
91132 default :
92- break ;
133+ return MP_EIO ;
93134 }
94-
95- return 0 ;
96135}
97136
98137void common_hal_busio_i2c_construct (busio_i2c_obj_t * self , const mcu_pin_obj_t * scl , const mcu_pin_obj_t * sda , uint32_t frequency , uint32_t timeout ) {
@@ -114,25 +153,12 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t *
114153 mp_raise_ValueError (translate ("All I2C peripherals are in use" ));
115154 }
116155
117- #if CIRCUITPY_REQUIRE_I2C_PULLUPS
118- // Test that the pins are in a high state. (Hopefully indicating they are pulled up.)
119- nrf_gpio_cfg_input (scl -> number , NRF_GPIO_PIN_PULLDOWN );
120- nrf_gpio_cfg_input (sda -> number , NRF_GPIO_PIN_PULLDOWN );
121-
122- common_hal_mcu_delay_us (10 );
123-
124- nrf_gpio_cfg_input (scl -> number , NRF_GPIO_PIN_NOPULL );
125- nrf_gpio_cfg_input (sda -> number , NRF_GPIO_PIN_NOPULL );
126-
127- // We must pull up within 3us to achieve 400khz.
128- common_hal_mcu_delay_us (3 );
129-
130- if (!nrf_gpio_pin_read (sda -> number ) || !nrf_gpio_pin_read (scl -> number )) {
156+ // check bus is in a sane state
157+ if (!_bus_is_sane (scl -> number ,sda -> number )) {
131158 reset_pin_number (sda -> number );
132159 reset_pin_number (scl -> number );
133160 mp_raise_RuntimeError (translate ("No pull up found on SDA or SCL; check your wiring" ));
134161 }
135- #endif
136162
137163 nrfx_twim_config_t config = NRFX_TWIM_DEFAULT_CONFIG (scl -> number , sda -> number );
138164
@@ -188,7 +214,9 @@ bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) {
188214 NRF_TWIM_Type * reg = self -> twim_peripheral -> twim .p_twim ;
189215 bool found = true;
190216
191- nrfx_twim_enable (& self -> twim_peripheral -> twim );
217+ if (NRFX_SUCCESS != _safe_twim_enable (self )) {
218+ return false;
219+ }
192220
193221 nrf_twim_address_set (reg , addr );
194222 nrf_twim_tx_buffer_set (reg , NULL , 0 );
@@ -246,7 +274,10 @@ STATIC uint8_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr,
246274
247275 nrfx_err_t err = NRFX_SUCCESS ;
248276
249- nrfx_twim_enable (& self -> twim_peripheral -> twim );
277+ err = _safe_twim_enable (self );
278+ if (NRFX_SUCCESS != err ) {
279+ return twi_error_to_mp (err );
280+ }
250281
251282 // break into MAX_XFER_LEN transaction
252283 while (len ) {
@@ -278,7 +309,10 @@ uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t
278309
279310 nrfx_err_t err = NRFX_SUCCESS ;
280311
281- nrfx_twim_enable (& self -> twim_peripheral -> twim );
312+ err = _safe_twim_enable (self );
313+ if (NRFX_SUCCESS != err ) {
314+ return twi_error_to_mp (err );
315+ }
282316
283317 // break into MAX_XFER_LEN transaction
284318 while (len ) {
0 commit comments