summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ports/stm32/machine_i2c.c18
-rw-r--r--ports/stm32/pyb_i2c.c28
2 files changed, 43 insertions, 3 deletions
diff --git a/ports/stm32/machine_i2c.c b/ports/stm32/machine_i2c.c
index 2aebb9426..b423ec1c8 100644
--- a/ports/stm32/machine_i2c.c
+++ b/ports/stm32/machine_i2c.c
@@ -187,15 +187,24 @@ STATIC void machine_hard_i2c_init(machine_hard_i2c_obj_t *self, uint32_t freq, u
/******************************************************************************/
/* MicroPython bindings for machine API */
+#if defined(STM32F0) || defined(STM32F7)
+#define MACHINE_I2C_TIMINGR (1)
+#else
+#define MACHINE_I2C_TIMINGR (0)
+#endif
+
mp_obj_t machine_hard_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
// parse args
- enum { ARG_id, ARG_scl, ARG_sda, ARG_freq, ARG_timeout };
+ enum { ARG_id, ARG_scl, ARG_sda, ARG_freq, ARG_timeout, ARG_timingr };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_scl, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_sda, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = I2C_POLL_DEFAULT_TIMEOUT_US} },
+ #if MACHINE_I2C_TIMINGR
+ { MP_QSTR_timingr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ #endif
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
@@ -241,6 +250,13 @@ mp_obj_t machine_hard_i2c_make_new(const mp_obj_type_t *type, size_t n_args, siz
// initialise the I2C peripheral
machine_hard_i2c_init(self, args[ARG_freq].u_int, args[ARG_timeout].u_int);
+ #if MACHINE_I2C_TIMINGR
+ // If given, explicitly set the TIMINGR value
+ if (args[ARG_timingr].u_obj != mp_const_none) {
+ self->i2c->TIMINGR = mp_obj_get_int_truncated(args[ARG_timingr].u_obj);
+ }
+ #endif
+
return MP_OBJ_FROM_PTR(self);
}
diff --git a/ports/stm32/pyb_i2c.c b/ports/stm32/pyb_i2c.c
index 233cbba51..8b816a25b 100644
--- a/ports/stm32/pyb_i2c.c
+++ b/ports/stm32/pyb_i2c.c
@@ -135,6 +135,8 @@ const pyb_i2c_obj_t pyb_i2c_obj[] = {
// The STM32F0, F3, F7, H7 and L4 use a TIMINGR register rather than ClockSpeed and
// DutyCycle.
+#define PYB_I2C_TIMINGR (1)
+
#if defined(STM32F746xx)
// The value 0x40912732 was obtained from the DISCOVERY_I2Cx_TIMING constant
@@ -213,6 +215,8 @@ uint32_t pyb_i2c_get_baudrate(I2C_HandleTypeDef *i2c) {
#else
+#define PYB_I2C_TIMINGR (0)
+
#define MICROPY_HW_I2C_BAUDRATE_DEFAULT (PYB_I2C_SPEED_FULL)
#define MICROPY_HW_I2C_BAUDRATE_MAX (PYB_I2C_SPEED_FULL)
@@ -564,7 +568,15 @@ STATIC void pyb_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ki
mp_printf(print, "I2C(%u)", i2c_num);
} else {
if (in_master_mode(self)) {
- mp_printf(print, "I2C(%u, I2C.MASTER, baudrate=%u)", i2c_num, pyb_i2c_get_baudrate(self->i2c));
+ mp_printf(print, "I2C(%u, I2C.MASTER, baudrate=%u"
+ #if PYB_I2C_TIMINGR
+ ", timingr=0x%08x"
+ #endif
+ ")", i2c_num, pyb_i2c_get_baudrate(self->i2c)
+ #if PYB_I2C_TIMINGR
+ , self->i2c->Init.Timing
+ #endif
+ );
} else {
mp_printf(print, "I2C(%u, I2C.SLAVE, addr=0x%02x)", i2c_num, (self->i2c->Instance->OAR1 >> 1) & 0x7f);
}
@@ -586,6 +598,9 @@ STATIC mp_obj_t pyb_i2c_init_helper(const pyb_i2c_obj_t *self, size_t n_args, co
{ MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = MICROPY_HW_I2C_BAUDRATE_DEFAULT} },
{ MP_QSTR_gencall, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
{ MP_QSTR_dma, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
+ #if PYB_I2C_TIMINGR
+ { MP_QSTR_timingr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ #endif
};
// parse args
@@ -602,7 +617,16 @@ STATIC mp_obj_t pyb_i2c_init_helper(const pyb_i2c_obj_t *self, size_t n_args, co
init->OwnAddress1 = (args[1].u_int << 1) & 0xfe;
}
- i2c_set_baudrate(init, MIN(args[2].u_int, MICROPY_HW_I2C_BAUDRATE_MAX));
+ // Set baudrate or timing value (if supported)
+ #if PYB_I2C_TIMINGR
+ if (args[5].u_obj != mp_const_none) {
+ init->Timing = mp_obj_get_int_truncated(args[5].u_obj);
+ } else
+ #endif
+ {
+ i2c_set_baudrate(init, MIN(args[2].u_int, MICROPY_HW_I2C_BAUDRATE_MAX));
+ }
+
init->AddressingMode = I2C_ADDRESSINGMODE_7BIT;
init->DualAddressMode = I2C_DUALADDRESS_DISABLED;
init->GeneralCallMode = args[3].u_bool ? I2C_GENERALCALL_ENABLED : I2C_GENERALCALL_DISABLED;