I am learning embedded development on the STM3220G-EVAL board with the STM32F207 microcontroller. I am testing 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:
#include <stm32f2xx.h>
volatile uint8_t data = 'a', recv = 'x';
void i2c_init(void);
// Master handler
void I2C2_EV_IRQHandler(void)
{
volatile uint16_t stat, dummy;
stat = I2C2->SR1;
switch(stat)
{
// SB set; read SR1 and write slave address in DR to clear
case 0x01:
dummy = I2C2->SR1;
// Send address of slave
I2C2->DR = 0x40;
break;
// ADDR set; read SR1 and SR2 to clear
case 0x02:
dummy = I2C2->SR1;
dummy = I2C2->SR2;
break;
// TxE set; write to DR to clear
case 0x80:
I2C2->DR = data;
break;
// TxE and BTF set; generate stop condition to clear
case 0x84:
// Generate stop
I2C2->CR1 |= (1 << 9);
break;
}
}
// Slave handler
void I2C3_EV_IRQHandler(void)
{
volatile uint16_t stat, dummy;
stat = I2C3->SR1;
switch(stat)
{
// ADDR set; read SR1 and SR2 to clear
case 0x02:
dummy = I2C3->SR1;
dummy = I2C3->SR2;
break;
// STOPF set; read SR1 and write CR1 to clear
case 0x10:
dummy = I2C3->SR1;
I2C3->CR1 &= ~(1 << 0);
break;
// RxNE set; read DR to clear
case 0x40:
recv = I2C3->DR;
break;
}
}
int main()
{
i2c_init();
// Generate START condition
I2C2->CR1 |= (1 << 8);
while(1)
{
if(!(I2C2->OAR1 & (1 << 14)))
I2C2->OAR1 |= (1 << 14);
if(!(I2C3->OAR1 & (1 << 14)))
I2C3->OAR1 |= (1 << 14);
if(recv != 'x')
break;
}
return 0;
}
void i2c_init(void)
{
// Enable GPIOA, GPIOC, GPIOF, I2C2 and I2C3 peripherals
RCC->AHB1ENR |= (1 << 0);
RCC->AHB1ENR |= (1 << 2);
RCC->AHB1ENR |= (1 << 5);
RCC->APB1ENR |= (1 << 22);
RCC->APB1ENR |= (1 << 23);
// Set GPIO mode to AF
GPIOA->MODER |= (1 << 17);
GPIOC->MODER |= (1 << 19);
GPIOF->MODER |= (1 << 1);
GPIOF->MODER |= (1 << 3);
// Set GPIO type to OD
GPIOA->OTYPER |= (1 << 8);
GPIOC->OTYPER |= (1 << 9);
GPIOF->OTYPER |= (1 << 0);
GPIOF->OTYPER |= (1 << 1);
// Set GPIO speed to 50MHz
GPIOA->OSPEEDR |= (1 << 17);
GPIOC->OSPEEDR |= (1 << 19);
GPIOF->OSPEEDR |= (1 << 1);
GPIOF->OSPEEDR |= (1 << 3);
// Link to I2C AF
GPIOA->AFR[1] |= (1 << 2);
GPIOC->AFR[1] |= (1 << 6);
GPIOF->AFR[0] |= (1 << 2);
GPIOF->AFR[0] |= (1 << 6);
// Enable interrupts
I2C2->CR2 |= (1 << 9);
I2C2->CR2 |= (1 << 10);
I2C3->CR2 |= (1 << 9);
I2C3->CR2 |= (1 << 10);
NVIC_EnableIRQ(I2C2_EV_IRQn);
NVIC_EnableIRQ(I2C3_EV_IRQn);
// Must set bit 14 in OAR1 to 1
I2C2->OAR1 |= (1 << 14);
I2C3->OAR1 |= (1 << 14);
// Set addresses
I2C2->OAR1 = 0x40;
I2C3->OAR1 = 0x40;
// Set peripheral clock frequency
I2C2->CR2 |= 0x08;
I2C3->CR2 |= 0x08;
I2C2->CCR |= 0x28;
I2C3->CCR |= 0x28;
I2C2->TRISE = 0x09;
I2C3->TRISE = 0x09;
// Enable ACK
I2C2->CR1 |= (1 << 10);
I2C3->CR1 |= (1 << 10);
// Enable I2C peripherals
I2C2->CR1 |= (1 << 0);
I2C3->CR1 |= (1 << 0);
}
I am using a pullup of 13K on SDA and 10K on SCL. Pin numbers used are PF0, PF1 (I2C2 SDA, SCL) and PA8, PC9 (I2C3 SCL, SDA). I have not enabled I2C2 and I2C3 in RTE_Device.h. It just seems to provide convenience typedefs. (EDIT : Tried to enable these, it does not help)
The master event handler is successfully being called. But still some problems persist. The acknowledge failure bit is being set, and the slave handler is not called. Bus lines have been verified to be HIGH when idle.
Could anyone help me in solving this problem? I seem to have hit a dead end.