From 076b096efe3a7ef363719e1c1f1cdcd63b514c9d Mon Sep 17 00:00:00 2001 From: Laurent MEUNIER Date: Thu, 14 Sep 2017 17:15:11 +0200 Subject: [PATCH] STM: I2C: Confifure pins in OpenDrainNoPull by default (no pullup) As reported by MBED user Fran6Jack: I2C bus are usually 5V tolerant on all STM32 processor. If an external device on the I2C bus requires 5V operation, we usually acheive it by using 5V external pull-ups on the bus. Since signaling uses open-drain output on I2C for both signal SCL and SDA any 5V tolerant MCU will work on a 5V I2C bus. Having pull-up activated on a 5V externally pull bus, cause the pin to clamp on the STM32 die diode and could damage the IC (There is a note in STM32 datasheet specifying this issue). It is understood by all the community that I2C bus should always be externally pulled by physical resistor. I2C initialization should then be ALWAYS OpenDrainNoPull by default. Up to now, this I2C driver was setting pull up by default as it helps basic testing, like 1 master and 1 slave, conencted with 2 wires without any external pull ups. This will not work anymore after this commit and applications tests or examples needs to be modified to explicitely configure pull ups ... But it is safer to follow reference manual guidelines. --- targets/TARGET_STM/i2c_api.c | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/targets/TARGET_STM/i2c_api.c b/targets/TARGET_STM/i2c_api.c index dd95931a46..ef3d7a353d 100644 --- a/targets/TARGET_STM/i2c_api.c +++ b/targets/TARGET_STM/i2c_api.c @@ -274,10 +274,6 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) { obj_s->index = 0; __HAL_RCC_I2C1_CLK_ENABLE(); // Configure I2C pins - pinmap_pinout(sda, PinMap_I2C_SDA); - pinmap_pinout(scl, PinMap_I2C_SCL); - pin_mode(sda, OpenDrainPullUp); - pin_mode(scl, OpenDrainPullUp); obj_s->event_i2cIRQ = I2C1_EV_IRQn; obj_s->error_i2cIRQ = I2C1_ER_IRQn; } @@ -287,11 +283,6 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) { if (obj_s->i2c == I2C_2) { obj_s->index = 1; __HAL_RCC_I2C2_CLK_ENABLE(); - // Configure I2C pins - pinmap_pinout(sda, PinMap_I2C_SDA); - pinmap_pinout(scl, PinMap_I2C_SCL); - pin_mode(sda, OpenDrainPullUp); - pin_mode(scl, OpenDrainPullUp); obj_s->event_i2cIRQ = I2C2_EV_IRQn; obj_s->error_i2cIRQ = I2C2_ER_IRQn; } @@ -301,11 +292,6 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) { if (obj_s->i2c == I2C_3) { obj_s->index = 2; __HAL_RCC_I2C3_CLK_ENABLE(); - // Configure I2C pins - pinmap_pinout(sda, PinMap_I2C_SDA); - pinmap_pinout(scl, PinMap_I2C_SCL); - pin_mode(sda, OpenDrainPullUp); - pin_mode(scl, OpenDrainPullUp); obj_s->event_i2cIRQ = I2C3_EV_IRQn; obj_s->error_i2cIRQ = I2C3_ER_IRQn; } @@ -315,11 +301,6 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) { if (obj_s->i2c == I2C_4) { obj_s->index = 3; __HAL_RCC_I2C4_CLK_ENABLE(); - // Configure I2C pins - pinmap_pinout(sda, PinMap_I2C_SDA); - pinmap_pinout(scl, PinMap_I2C_SCL); - pin_mode(sda, OpenDrainPullUp); - pin_mode(scl, OpenDrainPullUp); obj_s->event_i2cIRQ = I2C4_EV_IRQn; obj_s->error_i2cIRQ = I2C4_ER_IRQn; } @@ -329,16 +310,17 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) { if (obj_s->i2c == FMPI2C_1) { obj_s->index = 4; __HAL_RCC_FMPI2C1_CLK_ENABLE(); - // Configure I2C pins - pinmap_pinout(sda, PinMap_I2C_SDA); - pinmap_pinout(scl, PinMap_I2C_SCL); - pin_mode(sda, OpenDrainPullUp); - pin_mode(scl, OpenDrainPullUp); obj_s->event_i2cIRQ = FMPI2C1_EV_IRQn; obj_s->error_i2cIRQ = FMPI2C1_ER_IRQn; } #endif + // Configure I2C pins + pinmap_pinout(sda, PinMap_I2C_SDA); + pinmap_pinout(scl, PinMap_I2C_SCL); + pin_mode(sda, OpenDrainNoPull); + pin_mode(scl, OpenDrainNoPull); + // I2C configuration // Default hz value used for timeout computation if(!obj_s->hz)