Question about LS1021a I2C

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Question about LS1021a I2C

2,048 Views
jianwu
Contributor II

Hello,

I am working on the LS1021A I2C Host and I2C device driver. Following the I2C programming guideline in LS1021A Reference Manual Rev C.1.pdf  04/2014. I use Freescale LS1021A TWR board Rev C1 board to debug.

-- I2C host driver: I based our existed mx-i2c driver and modify I2C registers size and MDIS, IBAL and IBIF clearing bit.

Host mode issue :

Start bit and slave address+R/W bit can be sent to I2C slave device and also can get ACK from I2C slave device when tracking on i2C bus line with scope.

But in master transmit mode(I2C1_IBCR = 0x70, I2C1_IBSR= 0xA0), when data is written to the IBDR, a data transfer isn't initiated correctly.  I can't see date transmit on I2C bus line. After write I2C_IBDR, I2C_IBSR=0xA5,  I got Transmit interrupt (TCF) and slave transmit interrupt(SRW)-- Note: this SRW interrupt suppose not to be happened in master mode. 

In master receive mode (I2C1_IBCR = 0x60, I2C1_IBSR= 0x24),  when read I2C_IBDR register, Next byte receiving isn't initiated.  I can't see date transfer on I2C bus line. After read I2C_IBDR, I2C_IBSR=0xA4.  I got Transmit interrupt (TCF) and slave transmit interrupt(SRW). 

-- I2C slave driver 

I use Aardvark I2C device as I2C host. Slave mode issue is similar to Host mode issue.

I can get IAAS interrupt (for slave address matching interrupt )every time when Aardvark host write and read,  but I only can get seldom non-IAAS interrupt (data transfer interrupt ). So some time I2C slave can't transmit/receive any data,  Some time I2C slave can only transmit/receive 1 byte data.  I think the issue looks I2C data register IBDR can't initiated correctly as its doc mentioned. In slave transmit mode, when data is written to the IBDR, a data transfer isn't initiated;  In slave receive mode, reading this register doesn't  initiates next byte data receiving. 


I tested Uboot I2C host driver, it works fine. So I think there is something wrong in my drivers' transmit/receive sequence. I followed Figure26-41.Recommanded i2C interrupt service routine flowchart and 26.6.3.2 Transmit/Receive sequence part in LS1021A Reference Manual Rev C.1.pdf  04/2014.


Could you please give me some suggestion about my issue? SRW interrupt suppose not to be happened in master mode, why I got SRW interrupt in I2C host mode? Why I2C_IBDR can't initiate correctly?

Thanks, Jian

5 Replies

1,547 Views
yipingwang
NXP TechSupport
NXP TechSupport

Hello Jian Wu,


Please refer to i2c_imx_xfer funtion in the attached file from drivers/i2c/busses/i2c-imx.c of SDK 1.7 release.


Have a great day,
Yiping

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

1,547 Views
jianwu
Contributor II

Thanks Yiping for your quick reply.


I tried your attached code on LS1021A TWR board use I2C1 device: 0x69. In i2c_imx_write(), "write slave address"  part is ok. but "write data" part, i2c_imx_acked() always failed since it never receive ACK.

See I2C Bus Monitor log:     (2015-01-26 16:43:01) [S] <69:w> 10* cc* 


But I test with Uboot  with "i2c mw 0x69 0x10 0xcc 1",  i2c controller works fine.

See I2C Bus Monitor log:    (2015-01-26 16:53:52) [S] <69:w> 10 cc [P]

 

Do you have any idea why I  can not get ACK?


Thanks,

Jian



0 Kudos

1,547 Views
yipingwang
NXP TechSupport
NXP TechSupport

Hello Jian Wu,


Did you follow i2c_imx_start sequence to enable and configure I2C controller?


In addition, would you please enable CONFIG_I2C_DEBUG_BUS micro to get I2SR register status in the attached driver?


Thanks,

Yiping


0 Kudos

1,547 Views
jianwu
Contributor II

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;

}

0 Kudos

1,547 Views
jianwu
Contributor II

Hi Yiping,

I got I2C slave and master driver work. I just realized LS1021a I2C1/2/3 interrupt ID is changed in LS102A REV D docs :-(.


Thanks for your help,

Jian