Skip to content

Commit fae14cc

Browse files
committed
Fix for #8093
This adds a check to make sure that SDA and SCL are in a sane condition before starting any I2C operation. If they are not it tries to rectify it, and then returns an error code if unable to do so.
1 parent 1f20328 commit fae14cc

File tree

2 files changed

+50
-7
lines changed

2 files changed

+50
-7
lines changed

ports/nrf/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ SRC_NRFX = $(addprefix nrfx/,\
114114
drivers/src/nrfx_spim.c \
115115
drivers/src/nrfx_timer.c \
116116
drivers/src/nrfx_twim.c \
117+
drivers/src/nrfx_twi_twim.c \
117118
drivers/src/nrfx_uarte.c \
118119
drivers/src/nrfx_gpiote.c \
119120
drivers/src/nrfx_rtc.c \

ports/nrf/common-hal/busio/I2C.c

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,20 +79,54 @@ void common_hal_busio_i2c_never_reset(busio_i2c_obj_t *self) {
7979
}
8080
}
8181

82+
#define TWI_TWIM_PIN_CONFIGURE(_pin) nrf_gpio_cfg((_pin), \
83+
NRF_GPIO_PIN_DIR_OUTPUT, \
84+
NRF_GPIO_PIN_INPUT_CONNECT, \
85+
NRF_GPIO_PIN_PULLUP, \
86+
NRF_GPIO_PIN_S0D1, \
87+
NRF_GPIO_PIN_NOSENSE)
88+
89+
static nrfx_err_t _safe_twim_enable(busio_i2c_obj_t *self) {
90+
// check to see if bus is in sensible state before enabling twim
91+
nrfx_err_t recover_result;
92+
nrf_gpio_cfg_input(self->scl_pin_number, NRF_GPIO_PIN_PULLDOWN);
93+
nrf_gpio_cfg_input(self->sda_pin_number, NRF_GPIO_PIN_PULLDOWN);
94+
95+
common_hal_mcu_delay_us(10);
96+
97+
nrf_gpio_cfg_input(self->scl_pin_number, NRF_GPIO_PIN_NOPULL);
98+
nrf_gpio_cfg_input(self->sda_pin_number, NRF_GPIO_PIN_NOPULL);
99+
100+
// We must pull up within 3us to achieve 400khz.
101+
common_hal_mcu_delay_us(3);
102+
103+
if (!nrf_gpio_pin_read(self->sda_pin_number) || !nrf_gpio_pin_read(self->scl_pin_number)) {
104+
// bus not in a sane state - try to recover
105+
recover_result = nrfx_twim_bus_recover(self->scl_pin_number, self->sda_pin_number);
106+
if (NRFX_SUCCESS != recover_result) {
107+
// return error message if unable to recover the bus
108+
return recover_result;
109+
}
110+
}
111+
112+
nrfx_twim_enable(&self->twim_peripheral->twim);
113+
return NRFX_SUCCESS;
114+
}
115+
82116
static uint8_t twi_error_to_mp(const nrfx_err_t err) {
83117
switch (err) {
84118
case NRFX_ERROR_DRV_TWI_ERR_ANACK:
85119
return MP_ENODEV;
86120
case NRFX_ERROR_BUSY:
87121
return MP_EBUSY;
122+
case NRFX_SUCCESS:
123+
return 0;
88124
case NRFX_ERROR_DRV_TWI_ERR_DNACK:
89125
case NRFX_ERROR_INVALID_ADDR:
90-
return MP_EIO;
126+
case NRFX_ERROR_INTERNAL:
91127
default:
92-
break;
128+
return MP_EIO;
93129
}
94-
95-
return 0;
96130
}
97131

98132
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) {
@@ -188,7 +222,9 @@ bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) {
188222
NRF_TWIM_Type *reg = self->twim_peripheral->twim.p_twim;
189223
bool found = true;
190224

191-
nrfx_twim_enable(&self->twim_peripheral->twim);
225+
if (NRFX_SUCCESS != _safe_twim_enable(self)) {
226+
return false;
227+
}
192228

193229
nrf_twim_address_set(reg, addr);
194230
nrf_twim_tx_buffer_set(reg, NULL, 0);
@@ -246,7 +282,10 @@ STATIC uint8_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr,
246282

247283
nrfx_err_t err = NRFX_SUCCESS;
248284

249-
nrfx_twim_enable(&self->twim_peripheral->twim);
285+
err = _safe_twim_enable(self);
286+
if (NRFX_SUCCESS != err) {
287+
return twi_error_to_mp(err);
288+
}
250289

251290
// break into MAX_XFER_LEN transaction
252291
while (len) {
@@ -278,7 +317,10 @@ uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t
278317

279318
nrfx_err_t err = NRFX_SUCCESS;
280319

281-
nrfx_twim_enable(&self->twim_peripheral->twim);
320+
err = _safe_twim_enable(self);
321+
if (NRFX_SUCCESS != err) {
322+
return twi_error_to_mp(err);
323+
}
282324

283325
// break into MAX_XFER_LEN transaction
284326
while (len) {

0 commit comments

Comments
 (0)