@@ -79,20 +79,59 @@ void common_hal_busio_i2c_never_reset(busio_i2c_obj_t *self) {
79
79
}
80
80
}
81
81
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
+
82
121
static uint8_t twi_error_to_mp (const nrfx_err_t err ) {
83
122
switch (err ) {
84
123
case NRFX_ERROR_DRV_TWI_ERR_ANACK :
85
124
return MP_ENODEV ;
86
125
case NRFX_ERROR_BUSY :
87
126
return MP_EBUSY ;
127
+ case NRFX_SUCCESS :
128
+ return 0 ;
88
129
case NRFX_ERROR_DRV_TWI_ERR_DNACK :
89
130
case NRFX_ERROR_INVALID_ADDR :
90
- return MP_EIO ;
131
+ case NRFX_ERROR_INTERNAL :
91
132
default :
92
- break ;
133
+ return MP_EIO ;
93
134
}
94
-
95
- return 0 ;
96
135
}
97
136
98
137
void 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 *
114
153
mp_raise_ValueError (translate ("All I2C peripherals are in use" ));
115
154
}
116
155
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 )) {
131
158
reset_pin_number (sda -> number );
132
159
reset_pin_number (scl -> number );
133
160
mp_raise_RuntimeError (translate ("No pull up found on SDA or SCL; check your wiring" ));
134
161
}
135
- #endif
136
162
137
163
nrfx_twim_config_t config = NRFX_TWIM_DEFAULT_CONFIG (scl -> number , sda -> number );
138
164
@@ -188,7 +214,9 @@ bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) {
188
214
NRF_TWIM_Type * reg = self -> twim_peripheral -> twim .p_twim ;
189
215
bool found = true;
190
216
191
- nrfx_twim_enable (& self -> twim_peripheral -> twim );
217
+ if (NRFX_SUCCESS != _safe_twim_enable (self )) {
218
+ return false;
219
+ }
192
220
193
221
nrf_twim_address_set (reg , addr );
194
222
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,
246
274
247
275
nrfx_err_t err = NRFX_SUCCESS ;
248
276
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
+ }
250
281
251
282
// break into MAX_XFER_LEN transaction
252
283
while (len ) {
@@ -278,7 +309,10 @@ uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t
278
309
279
310
nrfx_err_t err = NRFX_SUCCESS ;
280
311
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
+ }
282
316
283
317
// break into MAX_XFER_LEN transaction
284
318
while (len ) {
0 commit comments