This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[C6727] I2C Issue

Hello, folks.

I'm encountered this phenomena with I2C accessing without CSL. (with CSL, it seem to be fine)

In CSL, It natularry waiting while running some redundant code, I think.

Accesssing I2Cx_CNT and  I2Cx_MDR is need some wait between them.

This is may not documented. (I  couldnot find it ; )

Best regards

 

  • What processor are you using?  Also, there are a lot of good tips on I2C here.  Can you please share a code snippet where you need to put a delay between these accesses?  What you've described so far does not bring any problems to mind.

    Brad

  • Hi, Brad. I'm using C6727 @ 300MHz

    here is code fragment works well. not wait, not works well.

    void init_i2c( void )
    {
     I2C1_MDR = 0; // IRS=0  make reset state
     I2C1_PSC = 17;
     I2C1_CLKL = 34;
     I2C1_CLKH = 34;

     I2C1_IER = 0;

     I2C1_EMDR = 1;
     
     I2C1_MDR = ( (1<<10) | (1<<9) ); // MST,TRX=1  master, transmit
     I2C1_OAR = 5;  // owner address

     I2C1_PFUNC = 0;   // GPMODE=0   not GPIO
     I2C1_MDR |= (1<<5);  // IRS=1

     while( (I2C1_MDR & (1<<5) )== 0 ){ // until IRS=1 (I2C is enabled) [timeout needed?]
      asm(" nop");
      asm(" nop");
      asm(" nop");
      asm(" nop");
     }

     I2C1_SAR = 0x1a; // AIC23 adrs

    }

    void send_i2c( u8 reg, u8 dat )
    {

     I2C1_CNT = 2;  // 2byte send

     while( (I2C1_STR & (1<<12) ) ){  // wait while bus busy  [timeout needed???]
      asm(" nop");  // for BP  while debug
      asm(" nop");
      asm(" nop");
      asm(" nop");
     }

     t_wait();  // this wait is needed for right working

     I2C1_MDR |= (1<<10);  // MST make master
     I2C1_MDR |= (1<<13);  // STT make start condition
    // I2C1_MDR = 0x2e20;

     while( (I2C1_STR & (1<<4) )==0 ){  // wait until ICXRDY==1 [timeout needed???]
      asm(" nop");  // for BP while debug
      asm(" nop");
      asm(" nop");
      asm(" nop");
     }
     I2C1_DXR = reg & 0xff;
     while( (I2C1_STR & (1<<4) )==0 ){  // wait until ICXRDY==1 [timeout needed???]
      asm(" nop");
      asm(" nop");
      asm(" nop");
      asm(" nop");
     }
     I2C1_DXR = dat & 0xff;
     while( (I2C1_STR & (1<<4) )==0 ){  // wait until ICXRDY==1 [timeout needed???]
      asm(" nop");
      asm(" nop");
      asm(" nop");
      asm(" nop");
     }

     I2C1_MDR |= (1<<11);  // STP make stop condition


    }

  • Hiro,

    No, the delays are not necessary.  I believe the pertinent info in your case is under the "back to back transfers" heading in the I2C tips wiki page I referenced previously.  Specifically, at the end of a transfer you should poll for MST==0 before beginning another one.

    I recommend making the following changes to your code to implement this efficiently:

    1. In your init function, do NOT set the MST bit.  Allow this to be completed in the "send" function.
    2. At the start of your send function, poll for MST==0.
    3. You should now be able to remove the unnecessary waits...

    Also, I highly recommend that you add a check for NACKs in your code as mentioned in the wiki page.  If for some reason you ever received a NACK (board issue) then your software would permanently stick in the loop polling for XRDY.  If however you check for NACK it could actually printout a diagnostic, retry, etc.

    Brad