Skip to main content
Stequila93
Associate II
August 23, 2021
Solved

stm32f103c6t6 I2C busy

  • August 23, 2021
  • 6 replies
  • 4115 views

Hello,

I know that has been asked a lot of times but i cannot get i2c work on my original stm32f103c6t6 mcu on a blue pill board.

I tried to read a lot on internet but anything let me come out.

I modified HAL_I2C_MspInit() as i read that i2c clk enable needed to be before the gpio clk enable, added also the reset.

void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
{
 GPIO_InitTypeDef GPIO_InitStruct = {0};
 if(hi2c->Instance==I2C1)
 {
 /* USER CODE BEGIN I2C1_MspInit 0 */
	__HAL_RCC_I2C1_CLK_ENABLE();		//ADDED BEFORE GPIO CLK
	__HAL_RCC_I2C1_FORCE_RESET();		//RESET
	__HAL_RCC_I2C1_RELEASE_RESET();		//RESET
 /* USER CODE END I2C1_MspInit 0 */
 
 __HAL_RCC_GPIOB_CLK_ENABLE();
 /**I2C1 GPIO Configuration
 PB6 ------> I2C1_SCL
 PB7 ------> I2C1_SDA
 */
 GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
 GPIO_InitStruct.Pull = GPIO_PULLUP;
 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 
 /* Peripheral clock enable */
 //__HAL_RCC_I2C1_CLK_ENABLE();	//REMOVED
 /* USER CODE BEGIN I2C1_MspInit 1 */
 
 /* USER CODE END I2C1_MspInit 1 */
 }
 
}

I tried as STM sais on errdata their workaroud about analog filter adding those functions that i hope are corrects.

void test(void){
	HAL_I2C_DeInit(&hi2c1);
	//1. Disable the I2C peripheral by clearing the PE bit in I2Cx_CR1 register.
	hi2c1.Instance->CR1 &= ~(1 << 0);
	//2. Configure the SCL and SDA I/Os as General Purpose Output Open-Drain, High level (Write 1 to GPIOx_ODR).
 
	GPIOB->CRL |= 3 << 24;
	GPIOB->CRL |= 3 << 28;
	GPIOB->CRL |= 1 << 26;
	GPIOB->CRL |= 1 << 30;
	GPIOB->BSRR |= 1 << 6;
	GPIOB->BSRR |= 1 << 7;
	//3. Check SCL and SDA High level in GPIOx_IDR.
	while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6) != GPIO_PIN_SET && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7) != GPIO_PIN_SET){
 
	}
	//4. Configure the SDA I/O as General Purpose Output Open-Drain, Low level (Write 0 to GPIOx_ODR).
	GPIOB->BSRR |= 1 << 23;
	//5. Check SDA Low level in GPIOx_IDR.
	while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7) == GPIO_PIN_SET){
 
	}
	//6. Configure the SCL I/O as General Purpose Output Open-Drain, Low level (Write 0 to GPIOx_ODR).
	GPIOB->BSRR |= 1 << 22;
	//7. Check SCL Low level in GPIOx_IDR.
	while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6) == GPIO_PIN_SET){
 
	}
	//8. Configure the SCL I/O as General Purpose Output Open-Drain, High level (Write 1 to GPIOx_ODR).
	GPIOB->BSRR |= 1 << 6;
	//9. Check SCL High level in GPIOx_IDR.
	while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6) != GPIO_PIN_SET){
 
	}
	//10. Configure the SDA I/O as General Purpose Output Open-Drain , High level (Write 1 to GPIOx_ODR).
	GPIOB->BSRR |= 1 << 7;
	//11. Check SDA High level in GPIOx_IDR.
	while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7) != GPIO_PIN_SET){
 
	}
	//12. Configure the SCL and SDA I/Os as Alternate function Open-Drain.
	GPIOB->CRL |= 3 << 26;
	GPIOB->CRL |= 3 << 30;
	//13. Set SWRST bit in I2Cx_CR1 register.
	hi2c1.Instance->CR1 |= 1 << 15;
	//14. Clear SWRST bit in I2Cx_CR1 register.
	hi2c1.Instance->CR1 &= ~(1 << 15);
	//15. Enable the I2C peripheral by setting the PE bit in I2Cx_CR1 register
	hi2c1.Instance->CR1 |= 1 << 0;
 
	HAL_I2C_Init(&hi2c1);
}

Also tried in an other way as i saw.

void test_1(void){
	GPIO_InitTypeDef strutturaGPIO = {0};
 
 
	//1. Disable the I2C peripheral by clearing the PE bit in I2Cx_CR1 register.
	hi2c1.Instance->CR1 &= ~(1 << 0);
	//2. Configure the SCL and SDA I/Os as General Purpose Output Open-Drain, High level (Write 1 to GPIOx_ODR).
	HAL_I2C_DeInit(&hi2c1);
 
	strutturaGPIO.Pin = GPIO_PIN_6|GPIO_PIN_7;
	strutturaGPIO.Mode = GPIO_MODE_OUTPUT_OD;
	strutturaGPIO.Pull = GPIO_PULLUP;
	strutturaGPIO.Speed = GPIO_SPEED_HIGH;
 HAL_GPIO_Init(GPIOB, &strutturaGPIO);
 
 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);
 
	//3. Check SCL and SDA High level in GPIOx_IDR.
	while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6) != GPIO_PIN_SET && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7) != GPIO_PIN_SET){
 
	}
	//4. Configure the SDA I/O as General Purpose Output Open-Drain, Low level (Write 0 to GPIOx_ODR).
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);
	//5. Check SDA Low level in GPIOx_IDR.
	while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7) == GPIO_PIN_SET){
 
	}
	//6. Configure the SCL I/O as General Purpose Output Open-Drain, Low level (Write 0 to GPIOx_ODR).
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
	//7. Check SCL Low level in GPIOx_IDR.
	while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6) == GPIO_PIN_SET){
 
	}
	//8. Configure the SCL I/O as General Purpose Output Open-Drain, High level (Write 1 to GPIOx_ODR).
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
	//9. Check SCL High level in GPIOx_IDR.
	while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6) != GPIO_PIN_SET){
 
	}
	//10. Configure the SDA I/O as General Purpose Output Open-Drain , High level (Write 1 to GPIOx_ODR).
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);
	//11. Check SDA High level in GPIOx_IDR.
	while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7) != GPIO_PIN_SET){
 
	}
	//12. Configure the SCL and SDA I/Os as Alternate function Open-Drain.
	strutturaGPIO.Pin = GPIO_PIN_6|GPIO_PIN_7;
	strutturaGPIO.Mode = GPIO_MODE_AF_OD;
	strutturaGPIO.Pull = GPIO_PULLUP;
	strutturaGPIO.Speed = GPIO_SPEED_HIGH;
 HAL_GPIO_Init(GPIOB, &strutturaGPIO);
	//13. Set SWRST bit in I2Cx_CR1 register.
	hi2c1.Instance->CR1 |= 1 << 15;
	//14. Clear SWRST bit in I2Cx_CR1 register.
	hi2c1.Instance->CR1 &= ~(1 << 15);
	//15. Enable the I2C peripheral by setting the PE bit in I2Cx_CR1 register
	hi2c1.Instance->CR1 |= 1 << 0;
 
	HAL_I2C_Init(&hi2c1);
}

I have my 4.7k pull up resistors on 3.3 V , i cannot get it work on both original STM MCU.

By the way i was working with i2c on a fake MCU CSK and it was working fine.

I use cubemx so i let it generate everything.

Debugging it seem that HAL_GPIO_Init(GPIOB, &GPIO_InitStruct) in HAL_I2C_MspInit() put Bus busy high.

I tried with nothing on the line or also with a ads1115.

Thanks a lot

This topic has been closed for replies.
Best answer by Stequila93

Well thanks,

I found out that it was not setting up the speed of the gpio in the structure sent to the gpio init, so it was set up as input and not as output OD.

 0693W00000DqCKsQAN.jpgBy the way it's generated by stmcube so is it missing while generating or i missed something in cube?

Thanks again

6 replies

Tesla DeLorean
Guru
August 23, 2021

Yeah, got bad memories about the F1 / I2C

Seem to remember I needed to ENABLE the I2C via CR, before initializing, at least in SPL days

Would double check the AFIO, GPIO and I2C clocks.

Make sure I2C is properly mapped, and perhaps conflicting peripherals are remapped off those pins.

Check Errata

Make sure structure is properly cleared/initialized.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Stequila93
Associate II
August 23, 2021

Hello Thanks,

I tried to enable in the CR1 register but i keep getting error before initializing.

About AFIO i don't see anything of strange i would check it better tomorrow.

I checked in the register if was mapped at 0 for pin 6 7 and its fine, i have nothing over i2c1 its an empty project with just swd debug.

Errata was saying what i did (maybe i did it wrong).

Is fine that in GPIO_INIT set pin 6 and 7 as INPUT?

0693W00000Dq9JXQAZ.jpgI'm getting MODE 00 and CNF 11 on the table configuration is "reserved".

It doesnt match with what i set up on stmcube that was output open drain with no pullup.

I'll check more tomorrow.

Thanks a lot.

Stequila93
Stequila93AuthorAnswer
Associate II
August 24, 2021

Well thanks,

I found out that it was not setting up the speed of the gpio in the structure sent to the gpio init, so it was set up as input and not as output OD.

 0693W00000DqCKsQAN.jpgBy the way it's generated by stmcube so is it missing while generating or i missed something in cube?

Thanks again

Powablocks
Associate
November 14, 2022

Thank you a lot I was desperatly trying to understand why the I2C didn't work and your solution worked for me. In 2022 MxCube is still generating the I2C the wrong way.

RShiv.1
Associate III
November 17, 2022

Hi,

I am also facing similar issue with I2C not working when used from STMcubeMx and STM32cubeID...we should just change the GPIO_Initstruct.Speed ??

can we still use HAL_I2C_Transmit and Rx??

should we use the same code of bitbang and then change the code..

Kindly suggest as we are working with STM32TC6T6 here...

Thanks

regards

Ravi

RShiv.1
Associate III
November 17, 2022

Hi,

attached is the code you had shared as above...but still facing issues with I2C..

I have chosen I2C as PB6 and PB7 ...do we need to change this to GPIO output..If so why in the above code HAL_I2C_INIT() is also present??....any change in the code let me know.

Thanks

Ravi

RShiv.1
Associate III
November 17, 2022

Hi,

any update kindly let me know so that I can try the I2C changes and see whether this works..

You have defined GPIO as well as I2C ..wanted to know how you compiled and how this was run..

regards

Ravi

zzxcv.1
Visitor II
November 22, 2022

HI,@RShiv.1​ 

I have also a stm32c6t6, the i2c code generated by the stm32cubeMX didn't works.

The solution is in the answer of this post.

The i2c initialization tree is:

  1. main.c: main()
  2. main.c: MX_I2C1_Init()
  3. ./Driver/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c: HAL_I2C_Init()
  4. Core/Src/stm32f1xx_hal_msp.c: HAL_I2C_MspInit() //<-- probleme here

You have to do:

  • open ./Core/Src/stm32f1xx_hal_msp.c
  • find HAL_I2C_MspInit(), about line 102

   GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;

   GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;

   GPIO_InitStruct.Pull = GPIO_PULLUP;

   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;

  • add the missing Speed member of GPIO, you can set it LOW MEDIUM OR HIGH, all works, but you have to set something :grinning_face_with_sweat:

RShiv.1
Associate III
November 22, 2022

Hi,

Thanks for your suggestion...currently we are using cubeMx to generate the code..instead of C6 our code worked on C8.

but as you suggested Core/Src/stm32f1xx_hal_msp.c this file itself is not generated now..

Inside HAL_I2C_Init function itself we have HAL_I2C_MspInit(hi2c);...if I flow through this we get one more function like this...

 */

__weak void HAL_MspInit(void)

{

 /* NOTE : This function should not be modified, when the callback is needed,

      the HAL_MspInit could be implemented in the user file

  */

}

can we modify the GPIO.speed here..for C6 ???...kindly let me know..so that we need not change to C8

thanks

Ravi

zzxcv.1
Visitor II
November 22, 2022

I just tried to generate the stm32f103C8T6 code from stm32cubeMX.

In the ./Core/Src, the file stm32f1xx_hal_msp.c is generated with:

```c

GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;

GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

/* Peripheral clock enable */

__HAL_RCC_I2C1_CLK_ENABLE();

```

which have SPEED set. This is the missing line/param in the generated c6t6 code by stm32cubeMX.

ps: HAL_I2C_MspInit in the Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c have __weak attribute, which means, if there are two function with the same name, the __weak one will not be chosen. (e.g replaced by the same function in the ./Core/Src/stmf1xx_hal_msp.c: line 85, HAL_I2C_MspInit() )