Skip to content

Commit 2e68492

Browse files
committed
rp2/machine_i2c_target: Support clock stretching for RX.
Signed-off-by: Damien George <[email protected]>
1 parent 25196ba commit 2e68492

File tree

1 file changed

+19
-3
lines changed

1 file changed

+19
-3
lines changed

ports/rp2/machine_i2c_target.c

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ typedef struct _machine_i2c_target_obj_t {
7676
mp_hal_pin_obj_t scl;
7777
mp_hal_pin_obj_t sda;
7878
uint8_t state;
79+
bool stop_pending;
7980
} machine_i2c_target_obj_t;
8081

8182
static machine_i2c_target_data_t i2c_target_data[4];
@@ -130,8 +131,12 @@ static void i2c_target_handler(i2c_inst_t *i2c) {
130131
if (self->state == STATE_IDLE) {
131132
machine_i2c_target_data_addr_match(data, false);
132133
}
133-
machine_i2c_target_data_restart_or_stop(data);
134-
self->state = STATE_IDLE;
134+
if (i2c->hw->status & I2C_IC_STATUS_RFNE_BITS) {
135+
self->stop_pending = true;
136+
} else {
137+
machine_i2c_target_data_restart_or_stop(data);
138+
self->state = STATE_IDLE;
139+
}
135140
}
136141
}
137142

@@ -146,7 +151,9 @@ static void i2c_slave_init(i2c_inst_t *i2c, uint16_t addr, bool addr_10bit) {
146151

147152
// Note: The I2C slave does clock stretching implicitly after a RD_REQ, while the Tx FIFO is empty.
148153
// Clock stretching while the Rx FIFO is full is also enabled by default.
149-
i2c->hw->con = I2C_IC_CON_STOP_DET_IFADDRESSED_BITS;
154+
i2c->hw->con =
155+
I2C_IC_CON_RX_FIFO_FULL_HLD_CTRL_BITS
156+
| I2C_IC_CON_STOP_DET_IFADDRESSED_BITS;
150157
if (addr_10bit) {
151158
i2c->hw->con |= I2C_IC_CON_IC_10BITADDR_SLAVE_BITS;
152159
}
@@ -204,6 +211,14 @@ static mp_int_t mp_machine_i2c_target_read_bytes(machine_i2c_target_obj_t *self,
204211
// Re-enable RX_FULL interrupt.
205212
i2c_hw->intr_mask |= I2C_IC_INTR_MASK_M_RX_FULL_BITS;
206213

214+
if (self->stop_pending && !(i2c_hw->status & I2C_IC_STATUS_RFNE_BITS)) {
215+
unsigned int i2c_id = self->i2c_inst == i2c0 ? 0 : 1;
216+
machine_i2c_target_data_t *data = &i2c_target_data[i2c_id];
217+
self->stop_pending = false;
218+
self->state = STATE_IDLE;
219+
machine_i2c_target_data_restart_or_stop(data);
220+
}
221+
207222
return i;
208223
}
209224

@@ -255,6 +270,7 @@ static mp_obj_t mp_machine_i2c_target_make_new(const mp_obj_type_t *type, size_t
255270

256271
// Initialise data.
257272
self->state = STATE_IDLE;
273+
self->stop_pending = false;
258274
MP_STATE_PORT(i2c_target_mem_obj)[i2c_id] = args[ARG_mem].u_obj;
259275
machine_i2c_target_data_t *data = &i2c_target_data[i2c_id];
260276
machine_i2c_target_data_init(data, args[ARG_mem].u_obj, args[ARG_mem_addrsize].u_int);

0 commit comments

Comments
 (0)