We are using the i2c peripheral in slave mode. After detection of the slave address (which causes the ADSL flag to be set) and the subsequent detection of BTF, one data byte is written into the DR. The master would not acknowledge the reception of that data byte, thus indicating, that no more data is requested. The corresponding parts in our sources (pls. have a glance at them) detect react to the AF as recommended in the STR710 data sheet. So the sda line is released and a stop condition is generated (although we cannot decide, wether this comes from the master or the slave...). The bus is free again.
Now the master issues our slave address again. Although we have done nothing to disable the slave's i2c peripheral and have not changed the slave address, the slave would not acknowledge the reception of the address (and in deed, it is not clocked in, no ADSL,no BTF, no other i2c interrupt). Where are we wrong? Why does the interface seem to be switched off? Please, pay attention to the fact, that we have mapped both i2c interrupts (iterr and rx_tx_int) to one single handler function. We've had them separate, but it wouldn't be any better. Attached you find the parts of our code dealing with the i2c. ---------------------------------------------------------------- void i2c0_init(u32 Baudrate) { //configure the Interrupt to be used GPIO_Config (GPIO1,1< GPIO_Config (GPIO1,1< EIC_IRQChannelPriorityConfig(I2C0_IRQChannel, 0x05); EIC_IRQChannelConfig(I2C0_IRQChannel, ENABLE); EIC_IRQChannelPriorityConfig(I2C0ITERR_IRQChannel, 0x05); EIC_IRQChannelConfig(I2C0ITERR_IRQChannel, ENABLE); //Configure the I2C0 module I2C_Init (I2C0); I2C_FCLKConfig (I2C0); //Enable the I2C0 I2C_OnOffConfig (I2C0, ENABLE); //Configure the I2C0 speed I2C_SpeedConfig (I2C0, Baudrate); //Configure the I2C0 address (to be used specially when this cell has to be adressed) I2C_AddressConfig (I2C0,0x30, I2C_Mode7); //Enable the Acknowledge I2C_AcknowledgeConfig (I2C0, ENABLE); // Enable the interrupt generation I2C_ITConfig (I2C0, ENABLE); } ---------------------------------------------------------------- void I2C0ITERR_IRQHandler(void) { I2C_Interrupt_Process(I2C0); } void I2C0_IRQHandler(void) { I2C_Interrupt_Process(I2C0); } ---------------------------------------------------------------- #define I2C_ADSL 0x04 #define I2C_BTF 0x08 #define I2C_BERR 0x02 #define I2C_AF 0x10 #define I2C_STOPF 0x08 void ResetI2C(I2C_TypeDef *I2Cx) { u8 temp; //Reset I2C interface I2Cx->CR=0x00; // reset the control register temp=I2Cx->CR; // remove pending interrupts I2Cx->CR=0x05; // reset I2C I2Cx->CR=0x25; // set initial value } void I2C_Interrupt_Process(I2C_TypeDef *I2Cx) { static u8 AddressByte=0; static u8 TransmitByte=0; u8 Sr1; u8 Sr2; Sr1 = I2Cx->SR1; Sr2 = I2Cx->SR2; //----------------------------------we have a BUS error----------------------------------------------------------------- if (Sr2 & I2C_BERR) { ResetI2C(I2Cx); //Reset the I2C interface return ; } //---------------------------------we have a acknowlege failure--------------------------------------------------------- if (Sr2 & I2C_AF) { I2Cx->DR=0xFF; // Dummy write to see STOP condition /*Sr1 = I2Cx->SR1; I2Cx->CR=I2Cx->CR|0x02; //generates a stop condition I2Cx->CR=I2Cx->CR&0xFD; //generates the SDA/SCL lines */ return ; } //--------------------------------test of own address ADSL-------------------------------------------------------------- if (Sr1 & I2C_ADSL) { AddressByte=1; return ; } //--------------------------------End of byte transfer BTF-------------------------------------------------------------- if (Sr1 & I2C_BTF) { if (AddressByte) { u8 Data=I2Cx->DR; if (Data&0x01) TransmitByte=1; else TransmitByte=0; AddressByte=0; } else { // transmitter mode if (TransmitByte) { u8 Data; if (!ReadI2CSlaveTransmit(&Data)) { //buffer is empty - we have to stop the transmission /*I2Cx->DR=0xFF; // Dummy write to see STOP condition */ Sr1 = I2Cx->SR1; I2Cx->CR=I2Cx->CR|0x02; //generates a stop condition I2Cx->CR=I2Cx->CR&0xFD; //generates the SDA/SCL lines } else { I2Cx->DR=Data; } } // receiver mode else { u8 temp=I2Cx->DR; if (!WriteI2CSlaveReceive(temp)) { //buffer is full - we have to block the transmission I2Cx->CR=I2Cx->CR|0x02; //generates a stop condition I2Cx->CR=I2Cx->CR&0xFD; //generates the SDA/SCL lines } } } } // else { if (Sr2 & I2C_STOPF) { return ; //stop condition detected } else { ResetI2C(I2Cx); //Reset the I2C interface return ; } } }
Is it possible to get some sample code for an I2C Slave transmission interrupt handler, particulary showing the howto for the last transmitted byte, which would not be ack'd by the master.