diff --git a/stmhal/boards/STM32F7DISC/mpconfigboard.h b/stmhal/boards/STM32F7DISC/mpconfigboard.h index dee42cb689..6a0d46bf4c 100644 --- a/stmhal/boards/STM32F7DISC/mpconfigboard.h +++ b/stmhal/boards/STM32F7DISC/mpconfigboard.h @@ -47,6 +47,19 @@ void STM32F7DISC_board_early_init(void); #define MICROPY_HW_I2C1_SCL (pin_B8) #define MICROPY_HW_I2C1_SDA (pin_B9) +#define MICROPY_HW_I2C3_SCL (pin_H7) +#define MICROPY_HW_I2C3_SDA (pin_H8) + +// The STM32F7 uses a TIMINGR register which is configured using an Excel +// Spreadsheet from AN4235: http://www.st.com/web/en/catalog/tools/PF258335 +// We use an array of baudrates and corresponding TIMINGR values. +// +// The value 0x40912732 was obtained from the DISCOVERY_I2Cx_TIMING constant +// defined in the STM32F7Cube file Drivers/BSP/STM32F746G-Discovery/stm32f7456g_discovery.h +#define MICROPY_HW_I2C_BAUDRATE_TIMING {{100000, 0x40912732}} +#define MICROPY_HW_I2C_BAUDRATE_DEFAULT 100000 +#define MICROPY_HW_I2C_BAUDRATE_MAX 100000 + // USRSW is pulled low. Pressing the button makes the input go high. #define MICROPY_HW_USRSW_PIN (pin_I11) #define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) diff --git a/stmhal/boards/STM32F7DISC/pins.csv b/stmhal/boards/STM32F7DISC/pins.csv index 37d0edaf3a..917214ae75 100644 --- a/stmhal/boards/STM32F7DISC/pins.csv +++ b/stmhal/boards/STM32F7DISC/pins.csv @@ -26,12 +26,16 @@ TP1,PH2 TP2,PI8 TP3,PH15 AUDIO_INT,PD6 +AUDIO_SDA,PH8 +AUDIO_SCL,PH7 EXT_SDA,PB9 EXT_SCL,PB8 EXT_RST,PG3 SD_SW,PC13 LCD_BL_CTRL,PK3 LCD_INT,PI13 +LCD_SDA,PH8 +LCD_SCL,PH7 OTG_FS_POWER,PD5 OTG_FS_OVER_CURRENT,PD4 OTG_HS_OVER_CURRENT,PE3 diff --git a/stmhal/i2c.c b/stmhal/i2c.c index 59f3a4fe4b..af37abf44c 100644 --- a/stmhal/i2c.c +++ b/stmhal/i2c.c @@ -37,9 +37,21 @@ #include "i2c.h" #include MICROPY_HAL_H -#if !defined(STM32F7) -// The STM32F7 has Timing, where the F4 has ClockSpeed and DutyCycle, so we -// need to figure that out before we can enable i2c +#if !defined(MICROPY_HW_I2C_BAUDRATE_DEFAULT) +#define MICROPY_HW_I2C_BAUDRATE_DEFAULT 400000 +#endif + +#if !defined(MICROPY_HW_I2C_BAUDRATE_MAX) +#define MICROPY_HW_I2C_BAUDRATE_MAX 400000 +#endif + +#if !defined(I2C_NOSTRETCH_DISABLE) +// Assumes that the F7 firmware is newer, so the F4 firmware will eventually +// catchup. I2C_NOSTRETCH_DISABLED was renamed to I2C_NOSTRETCH_DISABLE +// in the F7 so we use the F7 constant and provide a backwards compatabilty +// #define here. +#define I2C_NOSTRETCH_DISABLE I2C_NOSTRETCH_DISABLED +#endif /// \moduleref pyb /// \class I2C - a two-wire serial protocol @@ -138,6 +150,50 @@ STATIC const pyb_i2c_obj_t pyb_i2c_obj[] = { #endif }; +#if defined(MICROPY_HW_I2C_BAUDRATE_TIMING) +// The STM32F0, F3, and F7 use a TIMINGR register rather than ClockSpeed and +// DutyCycle. + +STATIC const struct { + uint32_t baudrate; + uint32_t timing; +} pyb_i2c_baudrate_timing[] = MICROPY_HW_I2C_BAUDRATE_TIMING; + +#define NUM_BAUDRATE_TIMINGS MP_ARRAY_SIZE(pyb_i2c_baudrate_timing) + +STATIC void i2c_set_baudrate(I2C_InitTypeDef *init, uint32_t baudrate) { + for (int i = 0; i < NUM_BAUDRATE_TIMINGS; i++) { + if (pyb_i2c_baudrate_timing[i].baudrate == baudrate) { + init->Timing = pyb_i2c_baudrate_timing[i].timing; + return; + } + } + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + "Unsupported I2C baudrate: %lu", baudrate)); +} + +STATIC uint32_t i2c_get_baudrate(I2C_InitTypeDef *init) { + for (int i = 0; i < NUM_BAUDRATE_TIMINGS; i++) { + if (pyb_i2c_baudrate_timing[i].timing == init->Timing) { + return pyb_i2c_baudrate_timing[i].baudrate; + } + } + return 0; +} + +#else + +STATIC void i2c_set_baudrate(I2C_InitTypeDef *init, uint32_t baudrate) { + init->ClockSpeed = baudrate; + init->DutyCycle = I2C_DUTYCYCLE_16_9; +} + +STATIC uint32_t i2c_get_baudrate(I2C_InitTypeDef *init) { + return init->ClockSpeed; +} + +#endif // MICROPY_HW_I2C_BAUDRATE_TIMING + void i2c_init0(void) { // reset the I2C1 handles #if defined(MICROPY_HW_I2C1_SCL) @@ -276,7 +332,7 @@ 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, self->i2c->Init.ClockSpeed); + mp_printf(print, "I2C(%u, I2C.MASTER, baudrate=%u)", i2c_num, i2c_get_baudrate(&self->i2c->Init)); } else { mp_printf(print, "I2C(%u, I2C.SLAVE, addr=0x%02x)", i2c_num, (self->i2c->Instance->OAR1 >> 1) & 0x7f); } @@ -295,7 +351,7 @@ STATIC mp_obj_t pyb_i2c_init_helper(const pyb_i2c_obj_t *self, mp_uint_t n_args, static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_addr, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0x12} }, - { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, + { 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} }, }; @@ -313,13 +369,13 @@ STATIC mp_obj_t pyb_i2c_init_helper(const pyb_i2c_obj_t *self, mp_uint_t n_args, init->OwnAddress1 = (args[1].u_int << 1) & 0xfe; } + i2c_set_baudrate(init, MIN(args[2].u_int, MICROPY_HW_I2C_BAUDRATE_MAX)); init->AddressingMode = I2C_ADDRESSINGMODE_7BIT; - init->ClockSpeed = MIN(args[2].u_int, 400000); init->DualAddressMode = I2C_DUALADDRESS_DISABLED; - init->DutyCycle = I2C_DUTYCYCLE_16_9; init->GeneralCallMode = args[3].u_bool ? I2C_GENERALCALL_ENABLED : I2C_GENERALCALL_DISABLED; init->NoStretchMode = I2C_NOSTRETCH_DISABLED; - init->OwnAddress2 = 0xfe; // unused + init->OwnAddress2 = 0; // unused + init->NoStretchMode = I2C_NOSTRETCH_DISABLE; // init the I2C bus i2c_init(self->i2c); @@ -753,5 +809,3 @@ const mp_obj_type_t pyb_i2c_type = { .make_new = pyb_i2c_make_new, .locals_dict = (mp_obj_t)&pyb_i2c_locals_dict, }; - -#endif // STM32F7 diff --git a/stmhal/main.c b/stmhal/main.c index ea385030bc..c1d85f978a 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -471,8 +471,8 @@ soft_reset: rng_init0(); #endif -#if !defined(STM32F7) // Temp hack i2c_init0(); +#if !defined(STM32F7) // Temp hack spi_init0(); #endif pyb_usb_init0(); diff --git a/stmhal/modpyb.c b/stmhal/modpyb.c index c32a8cfc31..dcc0f3da10 100644 --- a/stmhal/modpyb.c +++ b/stmhal/modpyb.c @@ -589,8 +589,8 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = { #if defined(MICROPY_HW_LED1) { MP_OBJ_NEW_QSTR(MP_QSTR_LED), (mp_obj_t)&pyb_led_type }, #endif -#if !defined(STM32F7) // Temp hack { MP_OBJ_NEW_QSTR(MP_QSTR_I2C), (mp_obj_t)&pyb_i2c_type }, +#if !defined(STM32F7) // Temp hack { MP_OBJ_NEW_QSTR(MP_QSTR_SPI), (mp_obj_t)&pyb_spi_type }, #endif { MP_OBJ_NEW_QSTR(MP_QSTR_UART), (mp_obj_t)&pyb_uart_type },