summaryrefslogtreecommitdiff
path: root/ports/stm32/pyb_i2c.c
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2019-05-21 13:45:17 +1000
committerDamien George <damien.p.george@gmail.com>2019-05-21 13:45:17 +1000
commitc769da1aaa28fb0eba9fabfba84c39cbc09e23da (patch)
treeb9e018a0842f148bb9c59e7dc8b8c07839d28aa5 /ports/stm32/pyb_i2c.c
parentddc657658af9ef74a7d891700a6e576c4fb5ff8e (diff)
stm32/i2c: Support setting the I2C TIMINGR value via keyword arg.
On MCUs that have an I2C TIMINGR register, this can now be explicitly set via the "timingr" keyword argument to the I2C constructor, for both machine.I2C and pyb.I2C. This allows to configure precise timing values when the defaults are inadequate.
Diffstat (limited to 'ports/stm32/pyb_i2c.c')
-rw-r--r--ports/stm32/pyb_i2c.c28
1 files changed, 26 insertions, 2 deletions
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;