2009-11-24 09:44 AM
Polled I2C breaks with other interrupts
2011-05-17 04:31 AM
Hello,
Using the StdPeriph_Lib_V3.1.2 and STM32F105R8. Clocked at 4MHz throughout, no PLL. Cut down the example code to do continuous reads from a Microchip 24LC04B. When there are no interrupts, the code runs fine and reads indefinitely. The moment I enable an unrelated interrupt (for example SysTick that does nothing but return) it falls over at ''test on EV7''. Looking at the bus with a scope, there are no differences between any of the reads and writes - even when it hangs the bus returns to the idle state. I realise that the code is not optimal and should have timeouts/recovery but I would like to get this sorted before I add those. I have attached the code below, does anyone have any ideas? ----- #include ''stm32f10x.h'' void Eeprom_Config(I2C_TypeDef* I2Cx); void Eeprom_Byte_Read(I2C_TypeDef* I2Cx, uint8_t *Data, uint16_t ReadAddr); int main(void) { GPIO_InitTypeDef GPIO_InitStructure; uint8_t Index; uint8_t Data; /* System Clocks Configuration */ SystemInit(); RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); /* Configure the GPIO ports */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; GPIO_Init(GPIOB, &GPIO_InitStructure); SysTick_Config(SystemFrequency_AHBClk / 1000); Eeprom_Config(I2C2); while (1) { Eeprom_Byte_Read(I2C2, &Data, 0x0); for (Index = 0; Index < 50; Index ++) {}; } } void Eeprom_Config(I2C_TypeDef* I2Cx) { I2C_InitTypeDef I2C_InitStructure; /* I2C configuration */ I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; I2C_InitStructure.I2C_OwnAddress1 = 0xA0; I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_InitStructure.I2C_ClockSpeed = 400000; /* I2C Peripheral Enable */ I2C_Cmd(I2Cx, ENABLE); /* Apply I2C configuration after enabling it */ I2C_Init(I2Cx, &I2C_InitStructure); } void Eeprom_Byte_Read(I2C_TypeDef* I2Cx, uint8_t *Data, uint16_t ReadAddr) { /* While the bus is busy */ while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY)); /* Send START condition */ I2C_GenerateSTART(I2Cx, ENABLE); /* Test on EV5 and clear it */ while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)); /* Send EEPROM address for write */ I2C_Send7bitAddress(I2Cx, 0xA0, I2C_Direction_Transmitter); /* Test on EV6 and clear it */ while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); /* Send the EEPROM's internal address to read from: Only one byte address */ I2C_SendData(I2Cx, ReadAddr); /* Test on EV8 and clear it */ while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); /* Send START condition a second time */ I2C_GenerateSTART(I2Cx, ENABLE); /* Test on EV5 and clear it */ while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)); /* Send EEPROM address for read */ I2C_Send7bitAddress(I2Cx, 0xA0, I2C_Direction_Receiver); /* Test on EV6 and clear it */ while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); /* Disable Acknowledgement */ I2C_AcknowledgeConfig(I2Cx, DISABLE); /* Send STOP Condition */ I2C_GenerateSTOP(I2Cx, ENABLE); /* Test on EV7 and clear it */ while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)); /* Read a byte from the EEPROM */ *Data = I2C_ReceiveData(I2Cx); /* Enable Acknowledgement to be ready for another reception */ I2C_AcknowledgeConfig(I2Cx, ENABLE); } void SysTick_Handler(void) { }