Skip to content

Commit 99e34e3

Browse files
authored
Merge pull request #829 from jerryneedell/jerryn_i2c
add keyword timeout to I2C -- only used for bitbangioi
2 parents 5429339 + 9a2cda7 commit 99e34e3

File tree

10 files changed

+30
-17
lines changed

10 files changed

+30
-17
lines changed

ports/atmel-samd/common-hal/busio/I2C.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
#define ATTEMPTS 2
4242

4343
void common_hal_busio_i2c_construct(busio_i2c_obj_t *self,
44-
const mcu_pin_obj_t* scl, const mcu_pin_obj_t* sda, uint32_t frequency) {
44+
const mcu_pin_obj_t* scl, const mcu_pin_obj_t* sda, uint32_t frequency, uint32_t timeout) {
4545
Sercom* sercom = NULL;
4646
uint8_t sercom_index;
4747
uint32_t sda_pinmux = 0;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
#include "pins.h"
3333
#include "nrf.h"
3434

35-
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) {
35+
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 ) {
3636
if (scl->pin == sda->pin) {
3737
mp_raise_ValueError("Invalid pins");
3838
}

py/objexcept.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -275,9 +275,7 @@ MP_DEFINE_EXCEPTION(Exception, BaseException)
275275
MP_DEFINE_EXCEPTION(UnboundLocalError, NameError)
276276
*/
277277
MP_DEFINE_EXCEPTION(OSError, Exception)
278-
#if MICROPY_PY_BUILTINS_TIMEOUTERROR
279-
MP_DEFINE_EXCEPTION(TimeoutError, OSError)
280-
#endif
278+
MP_DEFINE_EXCEPTION(TimeoutError, OSError)
281279
/*
282280
MP_DEFINE_EXCEPTION(BlockingIOError, OSError)
283281
MP_DEFINE_EXCEPTION(ChildProcessError, OSError)

shared-bindings/bitbangio/I2C.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "lib/utils/context_manager_helpers.h"
3636
#include "py/mperrno.h"
3737
#include "py/runtime.h"
38+
3839
//| .. currentmodule:: bitbangio
3940
//|
4041
//| :class:`I2C` --- Two wire serial protocol
@@ -49,6 +50,7 @@
4950
//| :param ~microcontroller.Pin scl: The clock pin
5051
//| :param ~microcontroller.Pin sda: The data pin
5152
//| :param int frequency: The clock frequency of the bus
53+
//| :param int timeout: The maximum clock stretching timeout in microseconds
5254
//|
5355
STATIC mp_obj_t bitbangio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) {
5456
mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true);
@@ -57,19 +59,20 @@ STATIC mp_obj_t bitbangio_i2c_make_new(const mp_obj_type_t *type, size_t n_args,
5759
self->base.type = &bitbangio_i2c_type;
5860
mp_map_t kw_args;
5961
mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args);
60-
enum { ARG_scl, ARG_sda, ARG_frequency };
62+
enum { ARG_scl, ARG_sda, ARG_frequency, ARG_timeout };
6163
static const mp_arg_t allowed_args[] = {
6264
{ MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ },
6365
{ MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_OBJ },
6466
{ MP_QSTR_frequency, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} },
67+
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 255} },
6568
};
6669
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
6770
mp_arg_parse_all(n_args, pos_args, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
6871
assert_pin(args[ARG_scl].u_obj, false);
6972
assert_pin(args[ARG_sda].u_obj, false);
7073
const mcu_pin_obj_t* scl = MP_OBJ_TO_PTR(args[ARG_scl].u_obj);
7174
const mcu_pin_obj_t* sda = MP_OBJ_TO_PTR(args[ARG_sda].u_obj);
72-
shared_module_bitbangio_i2c_construct(self, scl, sda, args[ARG_frequency].u_int);
75+
shared_module_bitbangio_i2c_construct(self, scl, sda, args[ARG_frequency].u_int, args[ARG_timeout].u_int);
7376
return (mp_obj_t)self;
7477
}
7578

shared-bindings/bitbangio/I2C.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ extern const mp_obj_type_t bitbangio_i2c_type;
3939
extern void shared_module_bitbangio_i2c_construct(bitbangio_i2c_obj_t *self,
4040
const mcu_pin_obj_t * scl,
4141
const mcu_pin_obj_t * sda,
42-
uint32_t frequency);
42+
uint32_t frequency,
43+
uint32_t us_timeout);
4344

4445
extern void shared_module_bitbangio_i2c_deinit(bitbangio_i2c_obj_t *self);
4546
extern bool shared_module_bitbangio_i2c_deinited(bitbangio_i2c_obj_t *self);

shared-bindings/busio/I2C.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,18 +56,20 @@
5656
//| :param ~microcontroller.Pin scl: The clock pin
5757
//| :param ~microcontroller.Pin sda: The data pin
5858
//| :param int frequency: The clock frequency in Hertz
59+
//| :param int timeout: The maximum clock stretching timeut - only for bitbang
5960
//|
6061
STATIC mp_obj_t busio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) {
6162
mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true);
6263
busio_i2c_obj_t *self = m_new_obj(busio_i2c_obj_t);
6364
self->base.type = &busio_i2c_type;
6465
mp_map_t kw_args;
6566
mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args);
66-
enum { ARG_scl, ARG_sda, ARG_frequency };
67+
enum { ARG_scl, ARG_sda, ARG_frequency, ARG_timeout };
6768
static const mp_arg_t allowed_args[] = {
6869
{ MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ },
6970
{ MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_OBJ },
7071
{ MP_QSTR_frequency, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} },
72+
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 255} },
7173
};
7274
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
7375
mp_arg_parse_all(n_args, pos_args, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
@@ -77,7 +79,7 @@ STATIC mp_obj_t busio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, siz
7779
assert_pin_free(scl);
7880
const mcu_pin_obj_t* sda = MP_OBJ_TO_PTR(args[ARG_sda].u_obj);
7981
assert_pin_free(sda);
80-
common_hal_busio_i2c_construct(self, scl, sda, args[ARG_frequency].u_int);
82+
common_hal_busio_i2c_construct(self, scl, sda, args[ARG_frequency].u_int, args[ARG_timeout].u_int);
8183
return (mp_obj_t)self;
8284
}
8385

shared-bindings/busio/I2C.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ extern const mp_obj_type_t busio_i2c_type;
4646
extern void common_hal_busio_i2c_construct(busio_i2c_obj_t *self,
4747
const mcu_pin_obj_t * scl,
4848
const mcu_pin_obj_t * sda,
49-
uint32_t frequency);
49+
uint32_t frequency,
50+
uint32_t timeout);
5051

5152
extern void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self);
5253
extern bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self);

shared-module/bitbangio/I2C.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,15 @@
2525
*/
2626

2727
#include "shared-bindings/bitbangio/I2C.h"
28-
2928
#include "py/mperrno.h"
3029
#include "py/obj.h"
30+
#include "py/runtime.h"
3131

3232
#include "common-hal/microcontroller/Pin.h"
3333
#include "shared-bindings/microcontroller/__init__.h"
3434
#include "shared-bindings/digitalio/DigitalInOut.h"
3535
#include "shared-module/bitbangio/types.h"
3636

37-
#define I2C_STRETCH_LIMIT 255
3837

3938
STATIC void delay(bitbangio_i2c_obj_t *self) {
4039
// We need to use an accurate delay to get acceptable I2C
@@ -48,11 +47,16 @@ STATIC void scl_low(bitbangio_i2c_obj_t *self) {
4847

4948
STATIC void scl_release(bitbangio_i2c_obj_t *self) {
5049
common_hal_digitalio_digitalinout_set_value(&self->scl, true);
50+
uint32_t count = self->us_timeout;
5151
delay(self);
5252
// For clock stretching, wait for the SCL pin to be released, with timeout.
53-
for (int count = I2C_STRETCH_LIMIT; !common_hal_digitalio_digitalinout_get_value(&self->scl) && count; --count) {
53+
for (; !common_hal_digitalio_digitalinout_get_value(&self->scl) && count; --count) {
5454
common_hal_mcu_delay_us(1);
5555
}
56+
// raise exception on timeout
57+
if (count == 0) {
58+
mp_raise_msg(&mp_type_TimeoutError, "Clock stretch too long");
59+
}
5660
}
5761

5862
STATIC void sda_low(bitbangio_i2c_obj_t *self) {
@@ -142,7 +146,10 @@ STATIC bool read_byte(bitbangio_i2c_obj_t *self, uint8_t *val, bool ack) {
142146
void shared_module_bitbangio_i2c_construct(bitbangio_i2c_obj_t *self,
143147
const mcu_pin_obj_t * scl,
144148
const mcu_pin_obj_t * sda,
145-
uint32_t frequency) {
149+
uint32_t frequency,
150+
uint32_t us_timeout) {
151+
152+
self->us_timeout = us_timeout;
146153
self->us_delay = 500000 / frequency;
147154
if (self->us_delay == 0) {
148155
self->us_delay = 1;

shared-module/bitbangio/types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ typedef struct {
3636
digitalio_digitalinout_obj_t scl;
3737
digitalio_digitalinout_obj_t sda;
3838
uint32_t us_delay;
39+
uint32_t us_timeout;
3940
volatile bool locked;
4041
} bitbangio_i2c_obj_t;
4142

shared-module/busio/I2C.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030
#include "py/nlr.h"
3131

3232
void common_hal_busio_i2c_construct(busio_i2c_obj_t *self,
33-
const mcu_pin_obj_t* scl, const mcu_pin_obj_t* sda, uint32_t freq) {
34-
shared_module_bitbangio_i2c_construct(&self->bitbang, scl, sda, freq);
33+
const mcu_pin_obj_t* scl, const mcu_pin_obj_t* sda, uint32_t freq, uint32_t timeout) {
34+
shared_module_bitbangio_i2c_construct(&self->bitbang, scl, sda, freq, timeout);
3535
}
3636

3737
bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self) {

0 commit comments

Comments
 (0)