AnsweredAssumed Answered

STM32F207 I2C test failing

Question asked by sethi.alakh on Feb 3, 2014
Latest reply on Apr 20, 2014 by sethi.alakh
I am learning embedded development on the STM3220G-EVAL board with the STM32F207 microcontroller. I have tried to test the I2C interface by interfacing the two I2C2 and I2C3 modules on the same chip and sending/receiving a character. Here is the code I have currently written (using mdk-arm 5):
001.#include <stm32f2xx.h>
002. 
003.volatile uint8_t data = 'a', recv = 'x';
004. 
005.void i2c_init(void);
006. 
007.void I2C2_EV_IRQHandler(void)
008.{
009.    volatile uint16_t stat, dummy;
010.    stat = I2C2->SR1;
011.    switch(stat)
012.    {
013.        // SB set; read SR1 and write slave address in DR to clear
014.        case 0x01:
015.            dummy = I2C2->SR1;
016.            // Send address of slave
017.            I2C2->DR = (0x08 << 1);
018.            break;
019.        // ADDR set; read SR1 and SR2 to clear
020.        case 0x02:
021.            dummy = I2C2->SR1;
022.            dummy = I2C2->SR2;
023.            break;
024.        // BTF set; generate stop condition to clear
025.        case 0x04:
026.            // Generate stop
027.            I2C2->CR1 |= (1 << 9);
028.            break;
029.        // TxE set; write to DR to clear
030.        case 0x80:
031.            I2C2->DR = data;
032.            break;
033.    }
034.}
035. 
036.void I2C3_EV_IRQHandler(void)
037.{
038.    volatile uint16_t stat, dummy;
039.    stat = I2C3->SR1;
040.    switch(stat)
041.    {
042.        // ADDR set; read SR1 and SR2 to clear
043.        case 0x02:
044.            dummy = I2C3->SR1;
045.            dummy = I2C3->SR2;
046.            break;
047.        // STOPF set; read SR1 and write CR1 to clear
048.        case 0x10:
049.            dummy = I2C3->SR1;
050.            I2C3->CR1 &= ~(1 << 0);
051.            break;
052.        // RxNE set; read DR to clear
053.        case 0x40:
054.            recv = I2C3->DR;
055.            break;
056.    }
057.}
058. 
059.int main()
060.{
061.    i2c_init();
062.    while(1)
063.    {
064.        if(!(I2C2->OAR1 & (1 << 14)))
065.            I2C2->OAR1 |= (1 << 14);
066.        if(!(I2C3->OAR1 & (1 << 14)))
067.            I2C3->OAR1 |= (1 << 14);
068.        if(recv != 'x')
069.            break;
070.    }
071.    return 0;
072.}
073. 
074.void i2c_init(void)
075.{
076.    // Enable GPIOF, GPIOH, I2C2 and I2C3 peripherals
077.    RCC->AHB1ENR |= (1 << 5);
078.    RCC->AHB1ENR |= (1 << 7);
079.    RCC->APB1ENR |= (1 << 22);
080.    RCC->APB1ENR |= (1 << 23);
081.    // Set GPIO mode to AF
082.    GPIOF->MODER |= (1 << 1);
083.    GPIOF->MODER |= (1 << 3);
084.    GPIOH->MODER |= (1 << 15);
085.    GPIOH->MODER |= (1 << 17);
086.    // Set GPIO type to OD
087.    GPIOF->OTYPER |= (1 << 0);
088.    GPIOF->OTYPER |= (1 << 1);
089.    GPIOH->OTYPER |= (1 << 7);
090.    GPIOH->OTYPER |= (1 << 8);
091.    // Set GPIO speed to 50MHz
092.    GPIOF->OSPEEDR |= (1 << 1);
093.    GPIOF->OSPEEDR |= (1 << 3);
094.    GPIOH->OSPEEDR |= (1 << 15);
095.    GPIOH->OSPEEDR |= (1 << 17);
096.    // Internal pullups
097.    /*
098.    GPIOF->PUPDR |= (1 << 0);
099.    GPIOF->PUPDR |= (1 << 2);
100.    GPIOH->PUPDR |= (1 << 14);
101.    GPIOH->PUPDR |= (1 << 16);
102.    */
103.    // Link to AFs
104.    GPIOF->AFR[0] |= (1 << 2);
105.    GPIOF->AFR[0] |= (1 << 6);
106.    GPIOH->AFR[0] |= (1 << 30);
107.    GPIOH->AFR[1] |= (1 << 2);
108.    // Enable interrupts
109.    I2C2->CR2 |= (1 << 9);
110.    I2C2->CR2 |= (1 << 10);
111.    I2C3->CR2 |= (1 << 9);
112.    I2C3->CR2 |= (1 << 10);
113.    NVIC_EnableIRQ(I2C2_EV_IRQn);
114.    NVIC_EnableIRQ(I2C3_EV_IRQn);
115.    // Must set bit 14 in OAR1 to 1
116.    I2C2->OAR1 |= (1 << 14);
117.    I2C3->OAR1 |= (1 << 14);
118.    // Set addresses
119.    I2C2->OAR1 |= (0x04 << 1);
120.    I2C3->OAR1 |= (0x08 << 1);
121.    // Set peripheral clock frequency
122.    I2C2->CR2 |= 0x08;
123.    I2C3->CR2 |= 0x08;
124.    I2C2->CCR |= 0x28;
125.    I2C3->CCR |= 0x28;
126.    I2C2->TRISE |= 0x09;
127.    I2C3->TRISE |= 0x09;
128.    // Enable ACK
129.    I2C3->CR1 |= (1 << 10);
130.    // Enable I2C peripherals
131.    I2C2->CR1 |= (1 << 0);
132.    I2C3->CR1 |= (1 << 0);
133.    // Generate START condition
134.    I2C2->CR1 |= (1 << 8);
135.}

The problems I am facing are:
       
  1. The execution never goes into the interrupt handlers (verified by breakpoints)
  2.    
  3. The SB bit in SR1 of the master (I2C2) is never set even though i have set the START bit in CR1
  4.    
  5. The SDA line is HIGH but the SCL line is pulled LOW
I am using a pullup of 13K on SDA and 10K on SCL. Pin numbers used are PF0, PF1 (I2C2 SDA, SCL) and PH7, PH8 (I2C3 SCL, SDA). Using the internal or external pullups causes the SR2 register to display that the bus is busy.
Also I have not enabled I2C2 and I2C3 in RTE_Device.h. It just seems to provide convenience typedefs. (EDIT: Tried to enable it here, it didn't help)

Could anyone help me in solving this problem? I seem to have hit a dead end.

Outcomes