cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 F3 I2C SCL Push-Pull Issue

GeoffF
Associate II

We're currently using STM32F373CC micros in several of our designs. Part of our standard design has an EEPROM connected via I2C. We have our own hardware layer that is tried and proven over the decades. However, it relies on the I2C port pins having pull-ups connected externally.

On some of our new designs we have designed out the pull-up on the SCL line and have set the port pin to Push-Pull mode. In theory, this should be no problem. However, what we've found is that the micro seems to be treating the port pin as open-drain regardless of the setting. For this particular design, we're using PF6 and PF7 as SCL and SDA respectively. With no pull-up connected, the SCL line is flat-lined. With internal pull-up enabled, the SCL line is pulsing, but the rise time is so long it's not working.

Nothing in the reference manual or the datasheet says anything about this issue. In the errata sheet we have (V4), there's quite a bit about the GPIO and I2C, but nothing that seems to relate to this.

For what it's worth, I'll copy and paste the relevant bit of the initialisation:

   switch( kasPinMap[eSCL].lwI2CNum )
 
   {
 
   case 1: RCC_APB1ENR.I2C1EN = TRUE; nI2CEEpsRegisters = (void*)&I2C1_CR1; break;
 
   case 2: RCC_APB1ENR.I2C2EN = TRUE; nI2CEEpsRegisters = (void*)&I2C2_CR1; break;
 
   }
 
 
   //configure the pins
 
   DIO_vConfigure( kasPinMap[eSCL].ePort,  kasPinMap[eSCL].lwBit,  DIOkeM_Alternate, DIOkeD_PushPull,  DIOkePU_None, DIOkeSP_Medium, kasPinMap[eSCL].lwAFN );
 
   DIO_vConfigure( kasPinMap[eSDA].ePort,  kasPinMap[eSDA].lwBit,  DIOkeM_Alternate, DIOkeD_OpenDrain, DIOkePU_None, DIOkeSP_Medium, kasPinMap[eSDA].lwAFN );
 
 
   //reset and enable the peripheral
 
   nI2CEE_vReset();

Although this is "non-standard" code, it definitely sets the registers correctly. In the debugger view of the registers, PF6 is definitely in push-pull mode and PF7 is open-drain, the GPIOF and I2C2 peripherals are enabled in the RCC register, and I2C works correctly if we solder an external pull-up resistor on.

Our Technical Director mentioned that to comply with the I2C standard and allow for multi-master mode, both SCL and SDA should both be open-drain. However, all we have here is the F3 and the EEPROM.

Any thoughts?

11 REPLIES 11
jiangfan
ST Employee

With internal pull-up enabled, the SCL line is pulsing, but the rise time is so long it's not working.

such behavior is reasonable, as STM32 internal pull-up has about 30k~50k resistance.

anyway, when the I2C IP is enabled, I2C SCL+SDA pins are set to be open drain, for some STM32 chips, and STM32F373 might be the case.

The issue is that, you can't change your hardware, to add external pull-up. you may workaround by slowing down I2C clock frequency, for example, 20kHz clock may work, if not - try 10kHz. slow clock like 10kHz should ​not be an issue for EEPROM.

Thanks Jiangfan,

We thought that might be the case. It's just not documented anywhere that I could find.

We have a batch of about 18 boards that will probably be re-worked to add the external resistor. There will probably need to be a board re-spin for future production.

maybe some presentation slides have some information, about peripheral overriding GPIO setting. You may check with your local FAE.

STM32 internal pull-up has about 30k~50k resistance - such information is in datasheet.

Minor issue for you, as you are OK for re-work to add the external resistor.

Andrew Neil
Evangelist III

"Our Technical Director mentioned that to comply with the I2C standard and allow for multi-master mode, both SCL and SDA should both be open-drain"

He is correct - the specification demands it:

0693W00000NqlLMQAZ.png 

While it violates the standard, in fact, as long as there's only one slave (EEPROM) which won'd drive SCL ever (i.e. it does not implement clock stretching, as is the case with probably all normal EEPROMs out there), push-pull SCL should work.

As the very first thing, you should read out and check/post the GPIO registers content. If I2C AF overrides the GPIO_OTYPER setting, then it's something surprising and undocumented. Not that there are no such things in STM32...

JW

PS. What is content of SYSCFG_CFGR1 register?

Thanks Andrew.

My one concern is that the ST documentation that I could find says nothing about it.

Jan Waclawek mentions clock stretching as a good reason to leave it open-drain. I have carefully examined the datasheet for our EEPROM (24LC02B) and the SCL input is only an input.

In our case where we have just one small EEPROM device attached I see no potential harm with using a push-pull output. Given that the majority of designs don't just allow random devices to be plugged into the I2C line, there should be some choice. If there's no choice, it should be documented. Otherwise, we just have the illusion of choice.

GPIO_OTYPER is definitely set to push-pull:

0693W00000Nqow1QAB.pngAnd SYSCFG_CFGR1 looks like this:

0693W00000NqowBQAR.pngWe haven't enabled Fast Mode or Fast Mode Plus. I wonder if that would make a difference?

... and thanks for the response Jan.

I was certainly surprised by this undocumented feature. So was our hardware designer.

I've just tried on an STM32F427 which I currently work on, SCL=PB6. I do have pullups (there are two 2k2 in parallel due to a certain modularity in this design), but the rise time changed unmistakenly when I switched OTYPER from 1 to 0, from 500ns to some 20ns.

So this is not something which goes across all STM32 families. I wouldn't be surprised if on the same 'F373 other SCL pins would work as expected and PF7 would be the exception. Unfortunately I don't have an 'F373 at my hand to try.

JW