Skip to content

Commit 9a82b67

Browse files
deshipudpgeorge
authored andcommitted
extmod/machine_i2c: Raise an error when clock stretching times out
1 parent 7029289 commit 9a82b67

1 file changed

Lines changed: 53 additions & 25 deletions

File tree

extmod/machine_i2c.c

Lines changed: 53 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,16 @@ STATIC void mp_hal_i2c_scl_low(machine_i2c_obj_t *self) {
5252
mp_hal_pin_od_low(self->scl);
5353
}
5454

55-
STATIC void mp_hal_i2c_scl_release(machine_i2c_obj_t *self) {
55+
STATIC int mp_hal_i2c_scl_release(machine_i2c_obj_t *self) {
56+
uint32_t count = self->us_timeout;
57+
5658
mp_hal_pin_od_high(self->scl);
5759
mp_hal_i2c_delay(self);
5860
// For clock stretching, wait for the SCL pin to be released, with timeout.
59-
for (uint32_t count = self->us_timeout; mp_hal_pin_read(self->scl) == 0 && count; --count) {
61+
for (; mp_hal_pin_read(self->scl) == 0 && count; --count) {
6062
mp_hal_delay_us_fast(1);
6163
}
64+
return count != 0;
6265
}
6366

6467
STATIC void mp_hal_i2c_sda_low(machine_i2c_obj_t *self) {
@@ -73,21 +76,23 @@ STATIC int mp_hal_i2c_sda_read(machine_i2c_obj_t *self) {
7376
return mp_hal_pin_read(self->sda);
7477
}
7578

76-
STATIC void mp_hal_i2c_start(machine_i2c_obj_t *self) {
79+
STATIC int mp_hal_i2c_start(machine_i2c_obj_t *self) {
7780
mp_hal_i2c_sda_release(self);
7881
mp_hal_i2c_delay(self);
79-
mp_hal_i2c_scl_release(self);
82+
int ret = mp_hal_i2c_scl_release(self);
8083
mp_hal_i2c_sda_low(self);
8184
mp_hal_i2c_delay(self);
85+
return ret;
8286
}
8387

84-
STATIC void mp_hal_i2c_stop(machine_i2c_obj_t *self) {
88+
STATIC int mp_hal_i2c_stop(machine_i2c_obj_t *self) {
8589
mp_hal_i2c_delay(self);
8690
mp_hal_i2c_sda_low(self);
8791
mp_hal_i2c_delay(self);
88-
mp_hal_i2c_scl_release(self);
92+
int ret = mp_hal_i2c_scl_release(self);
8993
mp_hal_i2c_sda_release(self);
9094
mp_hal_i2c_delay(self);
95+
return ret;
9196
}
9297

9398
STATIC void mp_hal_i2c_init(machine_i2c_obj_t *self, uint32_t freq) {
@@ -97,7 +102,7 @@ STATIC void mp_hal_i2c_init(machine_i2c_obj_t *self, uint32_t freq) {
97102
}
98103
mp_hal_pin_open_drain(self->scl);
99104
mp_hal_pin_open_drain(self->sda);
100-
mp_hal_i2c_stop(self);
105+
mp_hal_i2c_stop(self); // ignore error
101106
}
102107

103108
STATIC int mp_hal_i2c_write_byte(machine_i2c_obj_t *self, uint8_t val) {
@@ -111,13 +116,17 @@ STATIC int mp_hal_i2c_write_byte(machine_i2c_obj_t *self, uint8_t val) {
111116
mp_hal_i2c_sda_low(self);
112117
}
113118
mp_hal_i2c_delay(self);
114-
mp_hal_i2c_scl_release(self);
119+
if (!mp_hal_i2c_scl_release(self)) {
120+
return 0; // failure
121+
}
115122
mp_hal_i2c_scl_low(self);
116123
}
117124

118125
mp_hal_i2c_sda_release(self);
119126
mp_hal_i2c_delay(self);
120-
mp_hal_i2c_scl_release(self);
127+
if (!mp_hal_i2c_scl_release(self)) {
128+
return 0; // failure
129+
}
121130

122131
int ret = mp_hal_i2c_sda_read(self);
123132
mp_hal_i2c_delay(self);
@@ -133,7 +142,9 @@ STATIC int mp_hal_i2c_read_byte(machine_i2c_obj_t *self, uint8_t *val, int nack)
133142

134143
uint8_t data = 0;
135144
for (int i = 7; i >= 0; i--) {
136-
mp_hal_i2c_scl_release(self);
145+
if (!mp_hal_i2c_scl_release(self)) {
146+
return 0;
147+
}
137148
data = (data << 1) | mp_hal_i2c_sda_read(self);
138149
mp_hal_i2c_scl_low(self);
139150
mp_hal_i2c_delay(self);
@@ -145,7 +156,9 @@ STATIC int mp_hal_i2c_read_byte(machine_i2c_obj_t *self, uint8_t *val, int nack)
145156
mp_hal_i2c_sda_low(self);
146157
}
147158
mp_hal_i2c_delay(self);
148-
mp_hal_i2c_scl_release(self);
159+
if (!mp_hal_i2c_scl_release(self)) {
160+
return 0; // failure
161+
}
149162
mp_hal_i2c_scl_low(self);
150163
mp_hal_i2c_sda_release(self);
151164

@@ -169,7 +182,9 @@ STATIC int mp_hal_i2c_write_addresses(machine_i2c_obj_t *self, uint8_t addr,
169182
STATIC void mp_hal_i2c_write_mem(machine_i2c_obj_t *self, uint8_t addr,
170183
uint32_t memaddr, uint8_t addrsize, const uint8_t *src, size_t len) {
171184
// start the I2C transaction
172-
mp_hal_i2c_start(self);
185+
if (!mp_hal_i2c_start(self)) {
186+
goto er;
187+
}
173188

174189
// write the slave address and the memory address within the slave
175190
if (!mp_hal_i2c_write_addresses(self, addr, memaddr, addrsize)) {
@@ -184,18 +199,22 @@ STATIC void mp_hal_i2c_write_mem(machine_i2c_obj_t *self, uint8_t addr,
184199
}
185200

186201
// finish the I2C transaction
187-
mp_hal_i2c_stop(self);
202+
if (!mp_hal_i2c_stop(self)) {
203+
goto er;
204+
}
188205
return;
189206

190207
er:
191-
mp_hal_i2c_stop(self);
208+
mp_hal_i2c_stop(self); // ignore error
192209
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
193210
}
194211

195212
STATIC void mp_hal_i2c_read_mem(machine_i2c_obj_t *self, uint8_t addr,
196213
uint32_t memaddr, uint8_t addrsize, uint8_t *dest, size_t len) {
197214
// start the I2C transaction
198-
mp_hal_i2c_start(self);
215+
if (!mp_hal_i2c_start(self)) {
216+
goto er;
217+
}
199218

200219
if (addrsize) {
201220
// write the slave address and the memory address within the slave
@@ -204,7 +223,9 @@ STATIC void mp_hal_i2c_read_mem(machine_i2c_obj_t *self, uint8_t addr,
204223
}
205224

206225
// i2c_read will do a repeated start, and then read the I2C memory
207-
mp_hal_i2c_start(self);
226+
if (!mp_hal_i2c_start(self)) {
227+
goto er;
228+
}
208229
}
209230

210231
if (!mp_hal_i2c_write_byte(self, (addr << 1) | 1)) {
@@ -215,11 +236,13 @@ STATIC void mp_hal_i2c_read_mem(machine_i2c_obj_t *self, uint8_t addr,
215236
goto er;
216237
}
217238
}
218-
mp_hal_i2c_stop(self);
239+
if (!mp_hal_i2c_stop(self)) {
240+
goto er;
241+
}
219242
return;
220243

221244
er:
222-
mp_hal_i2c_stop(self);
245+
mp_hal_i2c_stop(self); // ignore error
223246
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
224247
}
225248

@@ -271,27 +294,32 @@ STATIC mp_obj_t machine_i2c_scan(mp_obj_t self_in) {
271294
mp_obj_t list = mp_obj_new_list(0, NULL);
272295
// 7-bit addresses 0b0000xxx and 0b1111xxx are reserved
273296
for (int addr = 0x08; addr < 0x78; ++addr) {
274-
mp_hal_i2c_start(self);
275-
int ack = mp_hal_i2c_write_byte(self, (addr << 1));
276-
if (ack) {
277-
mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr));
297+
if (mp_hal_i2c_start(self)) {
298+
int ack = mp_hal_i2c_write_byte(self, (addr << 1));
299+
if (ack) {
300+
mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr));
301+
}
302+
mp_hal_i2c_stop(self); // ignore error
278303
}
279-
mp_hal_i2c_stop(self);
280304
}
281305
return list;
282306
}
283307
MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_scan_obj, machine_i2c_scan);
284308

285309
STATIC mp_obj_t machine_i2c_start(mp_obj_t self_in) {
286310
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
287-
mp_hal_i2c_start(self);
311+
if (!mp_hal_i2c_start(self)) {
312+
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
313+
}
288314
return mp_const_none;
289315
}
290316
MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_start_obj, machine_i2c_start);
291317

292318
STATIC mp_obj_t machine_i2c_stop(mp_obj_t self_in) {
293319
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
294-
mp_hal_i2c_stop(self);
320+
if (!mp_hal_i2c_stop(self)) {
321+
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
322+
}
295323
return mp_const_none;
296324
}
297325
MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_stop_obj, machine_i2c_stop);

0 commit comments

Comments
 (0)