cancel
Showing results for 
Search instead for 
Did you mean: 

I2C2 busy - SDA being pulled low without any slave attached

Jacob L
Associate II
Posted on June 20, 2014 at 08:54

I'm trying to configure the I2C2 on an STM32F401 chip. The I2C1 is working fine, but the I2C2 is always returning HAL_BUSY. After initializing the GPIO port the SDA line is being pulled low, but no slave device is attached to the I2C bus. I have 2.2k pull ups.

In the code below, the SDA will be pulled low at line 32, but this is not correct I think. I have tried resetting the I2C2 in the RCC registers, but to no success. It should be noted, that the SDA is GPIOB 3, which is also JTDO. My understanding was that when changing the GPIO mode this would overwrite the JTAG functions. Any help is greatly appreciated


/*##-1- Configure the I2C peripheral ######################################*/

I2c2Handle.Instance = I2C2;

I2c2Handle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;

I2c2Handle.Init.ClockSpeed = 200000;

I2c2Handle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED; 

I2c2Handle.Init.DutyCycle = I2C_DUTYCYCLE_16_9; 
//I2C_DUTYCYCLE_2 / I2C_DUTYCYCLE_16_9

I2c2Handle.Init.GeneralCallMode = I2C_GENERALCALL_ENABLED; 
//I2C_GENERALCALL_ENABLED / 

I2c2Handle.Init.NoStretchMode = I2C_NOSTRETCH_ENABLED; 
//I2C_NOSTRETCH_ENABLED / I2C_NOSTRETCH_DISABLED

I2c2Handle.Init.OwnAddress1 = 0x34;

I2c2Handle.Init.OwnAddress2 = 0;


__GPIOB_CLK_ENABLE();

/* Enable I2C2 clock */

__I2C2_CLK_ENABLE(); 

//RCC->APB1RSTR |= 0x00400000; // Reset i2c peripheral

//RCC->APB1RSTR &= 0xFFBFFFFF;

__DMA1_CLK_ENABLE();


/*##-2- Configure peripheral GPIO ##########################################*/

/* I2C TX GPIO pin configuration */

GPIO_InitStruct.Pin = GPIO_PIN_10;

GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; 

GPIO_InitStruct.Pull = GPIO_NOPULL;

GPIO_InitStruct.Speed = GPIO_SPEED_FAST;

GPIO_InitStruct.Alternate = GPIO_AF4_I2C2;

HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);


/* I2C SDA GPIO pin configuration */

GPIO_InitStruct.Pin = GPIO_PIN_3;

GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; 
//GPIO_MODE_INPUT //GPIO_MODE_AF_OD

GPIO_InitStruct.Alternate = GPIO_AF4_I2C2;

HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); 
//this causes the SDA line to go Low.


/*##-3- Configure the DMA streams ##########################################*/

/* Configure the DMA handler for Transmission process */

hdma_tx.Instance = DMA1_Stream7;

hdma_tx.Init.Channel = DMA_CHANNEL_7;

hdma_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;

hdma_tx.Init.PeriphInc = DMA_PINC_DISABLE;

hdma_tx.Init.MemInc = DMA_MINC_ENABLE;

hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;

hdma_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;

hdma_tx.Init.Mode = DMA_NORMAL;

hdma_tx.Init.Priority = DMA_PRIORITY_LOW;

hdma_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; 

hdma_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;

hdma_tx.Init.MemBurst = DMA_MBURST_SINGLE; 

hdma_tx.Init.PeriphBurst = DMA_PBURST_SINGLE; 


HAL_DMA_Init(&hdma_tx); 


/* Associate the initialized DMA handle to the the I2C handle */

__HAL_LINKDMA(hi2c, hdmatx, hdma_tx);


/* Configure the DMA handler for Transmission process */

hdma_rx.Instance = DMA1_Stream3; 

hdma_rx.Init.Channel = DMA_CHANNEL_7;

hdma_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;

hdma_rx.Init.PeriphInc = DMA_PINC_DISABLE;

hdma_rx.Init.MemInc = DMA_MINC_ENABLE;

hdma_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;

hdma_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;

hdma_rx.Init.Mode = DMA_NORMAL;

hdma_rx.Init.Priority = DMA_PRIORITY_HIGH;

hdma_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; 

hdma_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;

hdma_rx.Init.MemBurst = DMA_MBURST_SINGLE;

hdma_rx.Init.PeriphBurst = DMA_PBURST_SINGLE; 


HAL_DMA_Init(&hdma_rx);


/* Associate the initialized DMA handle to the the I2C handle */

__HAL_LINKDMA(hi2c, hdmarx, hdma_rx);


/*##-4- Configure the NVIC for DMA #########################################*/

/* NVIC configuration for DMA transfer complete interrupt (I2C1_TX) */

HAL_NVIC_SetPriority(DMA1_Stream7_IRQn, 0, 1); 

HAL_NVIC_EnableIRQ(DMA1_Stream7_IRQn); 


/* NVIC configuration for DMA transfer complete interrupt (I2C1_RX) */

HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 0, 0); 

HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn); 

#i2c #stm32f401 #i2c2 #special-kind-of-stupid
3 REPLIES 3
stm322399
Senior
Posted on June 20, 2014 at 09:20

A closer look on the datasheet shows that I2C2 SDA is available on PB3 using AF09 (not AF04).

Jacob L
Associate II
Posted on June 20, 2014 at 13:06

That did the job, thank you SO MUCH! I spent 2 days trying to figure this one out by myself :D

Don't rely on the library being correct....

Posted on June 20, 2014 at 13:37

It's been covered here before, the libraries guys did address it, and it is in the Data Sheet

#define GPIO_AF9_I2C2          ((uint8_t)0x09)  /* I2C2 Alternate Function mapping (Only for STM32F401xx Devices) */

#define GPIO_AF9_I2C3          ((uint8_t)0x09)  /* I2C3 Alternate Function mapping (Only for STM32F401xx Devices) */

When pins don't do as I expect the first place to go is the Data Sheet, and to sanity check the pin choice and mux settings.

Who REALLY failed here were the IC design guys who implemented this screw-up, as it shows a clear lack of thought, and breaks the coherency of the design, for no good reason.

[DEAD LINK /public/STe2ecommunities/mcu/Lists/STM32Discovery/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/STM32Discovery/I2C3%20configuration&FolderCTID=0x01200200770978C69A1141439FE559EB459D75800084C20D8867EAD444A5987D47BE638E0F&currentviews=68]https://my.st.com/public/STe2ecommunities/mcu/Lists/STM32Discovery/Flat.aspx?RootFolder=%2Fpublic%2FSTe2ecommunities%2Fmcu%2FLists%2FSTM32Discovery%2FI2C3%20configuration&FolderCTID=0x01200200770978C69A1141439FE559EB459D75800084C20D8867EAD444A5987D47BE638E0F¤tviews=68

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..