stmhal: Enable I2C support for F7 MCUs.
This commit is contained in:
parent
26664dd180
commit
34fe5a30c6
@ -47,6 +47,19 @@ void STM32F7DISC_board_early_init(void);
|
|||||||
#define MICROPY_HW_I2C1_SCL (pin_B8)
|
#define MICROPY_HW_I2C1_SCL (pin_B8)
|
||||||
#define MICROPY_HW_I2C1_SDA (pin_B9)
|
#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.
|
// USRSW is pulled low. Pressing the button makes the input go high.
|
||||||
#define MICROPY_HW_USRSW_PIN (pin_I11)
|
#define MICROPY_HW_USRSW_PIN (pin_I11)
|
||||||
#define MICROPY_HW_USRSW_PULL (GPIO_NOPULL)
|
#define MICROPY_HW_USRSW_PULL (GPIO_NOPULL)
|
||||||
|
@ -26,12 +26,16 @@ TP1,PH2
|
|||||||
TP2,PI8
|
TP2,PI8
|
||||||
TP3,PH15
|
TP3,PH15
|
||||||
AUDIO_INT,PD6
|
AUDIO_INT,PD6
|
||||||
|
AUDIO_SDA,PH8
|
||||||
|
AUDIO_SCL,PH7
|
||||||
EXT_SDA,PB9
|
EXT_SDA,PB9
|
||||||
EXT_SCL,PB8
|
EXT_SCL,PB8
|
||||||
EXT_RST,PG3
|
EXT_RST,PG3
|
||||||
SD_SW,PC13
|
SD_SW,PC13
|
||||||
LCD_BL_CTRL,PK3
|
LCD_BL_CTRL,PK3
|
||||||
LCD_INT,PI13
|
LCD_INT,PI13
|
||||||
|
LCD_SDA,PH8
|
||||||
|
LCD_SCL,PH7
|
||||||
OTG_FS_POWER,PD5
|
OTG_FS_POWER,PD5
|
||||||
OTG_FS_OVER_CURRENT,PD4
|
OTG_FS_OVER_CURRENT,PD4
|
||||||
OTG_HS_OVER_CURRENT,PE3
|
OTG_HS_OVER_CURRENT,PE3
|
||||||
|
|
74
stmhal/i2c.c
74
stmhal/i2c.c
@ -37,9 +37,21 @@
|
|||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
#include MICROPY_HAL_H
|
#include MICROPY_HAL_H
|
||||||
|
|
||||||
#if !defined(STM32F7)
|
#if !defined(MICROPY_HW_I2C_BAUDRATE_DEFAULT)
|
||||||
// The STM32F7 has Timing, where the F4 has ClockSpeed and DutyCycle, so we
|
#define MICROPY_HW_I2C_BAUDRATE_DEFAULT 400000
|
||||||
// need to figure that out before we can enable i2c
|
#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
|
/// \moduleref pyb
|
||||||
/// \class I2C - a two-wire serial protocol
|
/// \class I2C - a two-wire serial protocol
|
||||||
@ -138,6 +150,50 @@ STATIC const pyb_i2c_obj_t pyb_i2c_obj[] = {
|
|||||||
#endif
|
#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) {
|
void i2c_init0(void) {
|
||||||
// reset the I2C1 handles
|
// reset the I2C1 handles
|
||||||
#if defined(MICROPY_HW_I2C1_SCL)
|
#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);
|
mp_printf(print, "I2C(%u)", i2c_num);
|
||||||
} else {
|
} else {
|
||||||
if (in_master_mode(self)) {
|
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 {
|
} else {
|
||||||
mp_printf(print, "I2C(%u, I2C.SLAVE, addr=0x%02x)", i2c_num, (self->i2c->Instance->OAR1 >> 1) & 0x7f);
|
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[] = {
|
static const mp_arg_t allowed_args[] = {
|
||||||
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
|
{ 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_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} },
|
{ 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;
|
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->AddressingMode = I2C_ADDRESSINGMODE_7BIT;
|
||||||
init->ClockSpeed = MIN(args[2].u_int, 400000);
|
|
||||||
init->DualAddressMode = I2C_DUALADDRESS_DISABLED;
|
init->DualAddressMode = I2C_DUALADDRESS_DISABLED;
|
||||||
init->DutyCycle = I2C_DUTYCYCLE_16_9;
|
|
||||||
init->GeneralCallMode = args[3].u_bool ? I2C_GENERALCALL_ENABLED : I2C_GENERALCALL_DISABLED;
|
init->GeneralCallMode = args[3].u_bool ? I2C_GENERALCALL_ENABLED : I2C_GENERALCALL_DISABLED;
|
||||||
init->NoStretchMode = I2C_NOSTRETCH_DISABLED;
|
init->NoStretchMode = I2C_NOSTRETCH_DISABLED;
|
||||||
init->OwnAddress2 = 0xfe; // unused
|
init->OwnAddress2 = 0; // unused
|
||||||
|
init->NoStretchMode = I2C_NOSTRETCH_DISABLE;
|
||||||
|
|
||||||
// init the I2C bus
|
// init the I2C bus
|
||||||
i2c_init(self->i2c);
|
i2c_init(self->i2c);
|
||||||
@ -753,5 +809,3 @@ const mp_obj_type_t pyb_i2c_type = {
|
|||||||
.make_new = pyb_i2c_make_new,
|
.make_new = pyb_i2c_make_new,
|
||||||
.locals_dict = (mp_obj_t)&pyb_i2c_locals_dict,
|
.locals_dict = (mp_obj_t)&pyb_i2c_locals_dict,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // STM32F7
|
|
||||||
|
@ -471,8 +471,8 @@ soft_reset:
|
|||||||
rng_init0();
|
rng_init0();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(STM32F7) // Temp hack
|
|
||||||
i2c_init0();
|
i2c_init0();
|
||||||
|
#if !defined(STM32F7) // Temp hack
|
||||||
spi_init0();
|
spi_init0();
|
||||||
#endif
|
#endif
|
||||||
pyb_usb_init0();
|
pyb_usb_init0();
|
||||||
|
@ -589,8 +589,8 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = {
|
|||||||
#if defined(MICROPY_HW_LED1)
|
#if defined(MICROPY_HW_LED1)
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_LED), (mp_obj_t)&pyb_led_type },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_LED), (mp_obj_t)&pyb_led_type },
|
||||||
#endif
|
#endif
|
||||||
#if !defined(STM32F7) // Temp hack
|
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_I2C), (mp_obj_t)&pyb_i2c_type },
|
{ 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 },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_SPI), (mp_obj_t)&pyb_spi_type },
|
||||||
#endif
|
#endif
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_UART), (mp_obj_t)&pyb_uart_type },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_UART), (mp_obj_t)&pyb_uart_type },
|
||||||
|
Loading…
x
Reference in New Issue
Block a user