Skip to content

Commit 19c9cc2

Browse files
committed
Merge remote-tracking branch 'origin/main'
2 parents 10a4456 + 53020f5 commit 19c9cc2

File tree

2 files changed

+57
-7
lines changed

2 files changed

+57
-7
lines changed

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

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "shared-bindings/busio/I2C.h"
3131
#include "shared-bindings/microcontroller/__init__.h"
3232
#include "shared-bindings/microcontroller/Pin.h"
33+
#include "supervisor/shared/tick.h"
3334
#include "py/mperrno.h"
3435
#include "py/runtime.h"
3536

@@ -39,18 +40,23 @@
3940

4041
// all TWI instances have the same max size
4142
// 16 bits for 840, 10 bits for 810, 8 bits for 832
42-
#define I2C_MAX_XFER_LEN ((1UL << TWIM0_EASYDMA_MAXCNT_SIZE) - 1)
43+
#define I2C_MAX_XFER_LEN MIN(((1UL << TWIM0_EASYDMA_MAXCNT_SIZE) - 1), 1024)
44+
#define I2C_TIMEOUT 1000 // 1 second timeout
4345

4446
STATIC twim_peripheral_t twim_peripherals[] = {
4547
#if NRFX_CHECK(NRFX_TWIM0_ENABLED)
4648
// SPIM0 and TWIM0 share an address.
4749
{ .twim = NRFX_TWIM_INSTANCE(0),
48-
.in_use = false},
50+
.in_use = false,
51+
.transferring = false,
52+
.last_event_type = NRFX_TWIM_EVT_DONE},
4953
#endif
5054
#if NRFX_CHECK(NRFX_TWIM1_ENABLED)
5155
// SPIM1 and TWIM1 share an address.
5256
{ .twim = NRFX_TWIM_INSTANCE(1),
53-
.in_use = false},
57+
.in_use = false,
58+
.transferring = false,
59+
.last_event_type = NRFX_TWIM_EVT_DONE},
5460
#endif
5561
};
5662

@@ -84,16 +90,26 @@ static uint8_t twi_error_to_mp(const nrfx_err_t err) {
8490
return MP_ENODEV;
8591
case NRFX_ERROR_BUSY:
8692
return MP_EBUSY;
87-
case NRFX_ERROR_DRV_TWI_ERR_DNACK:
8893
case NRFX_ERROR_INVALID_ADDR:
94+
case NRFX_ERROR_DRV_TWI_ERR_DNACK:
95+
case NRFX_ERROR_DRV_TWI_ERR_OVERRUN:
8996
return MP_EIO;
97+
case NRFX_ERROR_TIMEOUT:
98+
return MP_ETIMEDOUT;
9099
default:
91100
break;
92101
}
93102

94103
return 0;
95104
}
96105

106+
static void twim_event_handler(nrfx_twim_evt_t const *p_event, void *p_context) {
107+
// this is the callback handler - sets transferring to false and records the most recent event.
108+
twim_peripheral_t *peripheral = (twim_peripheral_t *)p_context;
109+
peripheral->last_event_type = p_event->type;
110+
peripheral->transferring = false;
111+
}
112+
97113
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) {
98114
if (scl->number == sda->number) {
99115
raise_ValueError_invalid_pins();
@@ -155,7 +171,7 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t *
155171

156172
// About to init. If we fail after this point, common_hal_busio_i2c_deinit() will set in_use to false.
157173
self->twim_peripheral->in_use = true;
158-
nrfx_err_t err = nrfx_twim_init(&self->twim_peripheral->twim, &config, NULL, NULL);
174+
nrfx_err_t err = nrfx_twim_init(&self->twim_peripheral->twim, &config, twim_event_handler, self->twim_peripheral);
159175
if (err != NRFX_SUCCESS) {
160176
common_hal_busio_i2c_deinit(self);
161177
mp_raise_OSError(MP_EIO);
@@ -238,6 +254,37 @@ void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self) {
238254
self->has_lock = false;
239255
}
240256

257+
STATIC nrfx_err_t _twim_xfer_with_timeout(busio_i2c_obj_t *self, nrfx_twim_xfer_desc_t const *p_xfer_desc, uint32_t flags) {
258+
// does non-blocking transfer and raises and exception if it takes longer than I2C_TIMEOUT ms to complete
259+
uint64_t deadline = supervisor_ticks_ms64() + I2C_TIMEOUT;
260+
nrfx_err_t err = NRFX_SUCCESS;
261+
self->twim_peripheral->transferring = true;
262+
err = nrfx_twim_xfer(&self->twim_peripheral->twim, p_xfer_desc, flags);
263+
if (err != NRFX_SUCCESS) {
264+
self->twim_peripheral->transferring = false;
265+
return err;
266+
}
267+
while (self->twim_peripheral->transferring) {
268+
if (supervisor_ticks_ms64() > deadline) {
269+
self->twim_peripheral->transferring = false;
270+
return NRFX_ERROR_TIMEOUT;
271+
}
272+
}
273+
switch (self->twim_peripheral->last_event_type) {
274+
case NRFX_TWIM_EVT_DONE: ///< Transfer completed event.
275+
return NRFX_SUCCESS;
276+
case NRFX_TWIM_EVT_ADDRESS_NACK: ///< Error event: NACK received after sending the address.
277+
return NRFX_ERROR_DRV_TWI_ERR_ANACK;
278+
case NRFX_TWIM_EVT_BUS_ERROR: ///< Error event: An unexpected transition occurred on the bus.
279+
case NRFX_TWIM_EVT_DATA_NACK: ///< Error event: NACK received after sending a data byte.
280+
return NRFX_ERROR_DRV_TWI_ERR_DNACK;
281+
case NRFX_TWIM_EVT_OVERRUN: ///< Error event: The unread data is replaced by new data.
282+
return NRFX_ERROR_DRV_TWI_ERR_OVERRUN;
283+
default: /// unknown error...
284+
return NRFX_ERROR_INTERNAL;
285+
}
286+
}
287+
241288
STATIC uint8_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, const uint8_t *data, size_t len, bool stopBit) {
242289
if (len == 0) {
243290
return common_hal_busio_i2c_probe(self, addr) ? 0 : MP_ENODEV;
@@ -253,7 +300,7 @@ STATIC uint8_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr,
253300
nrfx_twim_xfer_desc_t xfer_desc = NRFX_TWIM_XFER_DESC_TX(addr, (uint8_t *)data, xact_len);
254301
uint32_t const flags = (stopBit ? 0 : NRFX_TWIM_FLAG_TX_NO_STOP);
255302

256-
if (NRFX_SUCCESS != (err = nrfx_twim_xfer(&self->twim_peripheral->twim, &xfer_desc, flags))) {
303+
if (NRFX_SUCCESS != (err = _twim_xfer_with_timeout(self, &xfer_desc, flags))) {
257304
break;
258305
}
259306

@@ -284,7 +331,7 @@ uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t
284331
const size_t xact_len = MIN(len, I2C_MAX_XFER_LEN);
285332
nrfx_twim_xfer_desc_t xfer_desc = NRFX_TWIM_XFER_DESC_RX(addr, data, xact_len);
286333

287-
if (NRFX_SUCCESS != (err = nrfx_twim_xfer(&self->twim_peripheral->twim, &xfer_desc, 0))) {
334+
if (NRFX_SUCCESS != (err = _twim_xfer_with_timeout(self, &xfer_desc, 0))) {
288335
break;
289336
}
290337

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
typedef struct {
3535
nrfx_twim_t twim;
3636
bool in_use;
37+
volatile bool transferring;
38+
nrfx_twim_evt_type_t last_event_type;
39+
uint32_t timeout;
3740
} twim_peripheral_t;
3841

3942
typedef struct {

0 commit comments

Comments
 (0)