Hi Yiping,
Thanks for your help. The I2C slave driver is hight priority for me. I attached part of my I2C slave driver code. Could you please take a look to check if my transmit/receive routine is correct?
my issue is after get IAAS interrupt, SCL (low)and SDA(low) can not be released by writing data into IBDR or dummy reading IBDR. So data transfer can not be initiated.
Thanks,
Jian
uint8_t ls1021a_wait_status (ls1021a_i2c_dev_t *dev)
{
uint64_t ntime = 500000000ULL;
int interr = EOK;
uint8_t sta;
while (1){
TimerTimeout(CLOCK_MONOTONIC, _NTO_TIMEOUT_INTR, NULL, &ntime, NULL);
interr = InterruptWait_r(0, NULL);
sta = in8(dev->base + I2C_IBSR);
if (sta & IBSR_IBIF){
// Clear IBIF bit
out8(dev->base + I2C_IBSR, in8(dev->base + I2C_IBSR) | IBSR_IBIF);
// Enable a hardware interrupt
InterruptUnmask(dev->intr, dev->iid);
return sta;
}else
return 0;
}
}
i2c_status_t i2cslave_rw_start(void *hdl, uint8_t *txbuf, uint8_t *rxbuf )
{
ls1021a_i2c_dev_t *dev = hdl;
i2c_status_t status;
uint8_t sta, ctrl, data;
sta = ls1021a_wait_status(dev);
ctrl = in8(dev->base + I2C_IBCR);
if(!sta)
return I2C_STATUS_ERROR;
if (sta & IBSR_IAAS) {
//Address Transfer
if (sta & IBSR_SRW) {
//slave send
//Set TX mode
out8(dev->base + I2C_IBCR, in8(dev->base + I2C_IBCR) | IBCR_TXRX);
//send data to IBDR
out8( dev->base + I2C_IBDR, 0xCC); //send test data 0xCC to master
} else {
//slave receive
// Set receive mode
out8(dev->base + I2C_IBCR, in8(dev->base + I2C_IBCR) &(~IBCR_TXRX));
//Dummy read from IBDR
in8(dev->base + I2C_IBDR);
}
} else {
// Data Transfer
if (ctrl & IBCR_TXRX) {
//Data send
if (!(sta & IBSR_RXAK)) {
//ACK received
//TX Next Byte */
out8( dev->base + I2C_IBDR, 0xCC); //send test data 0xCC to master
} else {
//NACK received
//Switch RX mode
out8(dev->base + I2C_IBCR, in8(dev->base + I2C_IBCR) &(~IBCR_TXRX));
//Dummy read from IBDR
in8(dev->base + I2C_IBDR);
}
} else {
// Data received
//Read data from IBDR
data = in8(dev->base + I2C_IBDR);
}
}
return I2C_STATUS_DONE;
}