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.

I2C master continues without ACK on address or data

I'm working with the DM6435 (DM6437) with the I2C set up with the DSP as the master.  I note that when the DSP sends the address to a particular device that it will continue to send the data even if the address was not ACK'd.  Everthing sort of goes downhill after that.  I looked a bit at trying to capture the NAK interrupt but, 1) I'm not sure it even happens, and 2) if it does happen, I don't know how to kill the I2C sequence since spru991 says that issuing a reset while a transaction is in process can lockup the I2C in the DSP. 

So, the basic question is:

How do I make the I2C terminate immediately when a NAK occurs?

  • Hi,

    You would want to check for NAK (polling or interrupt is ok) right after you send the slave address out. You would not want to send any data if you get a NAK. If you get a NAK then you can reset the I2C and try to figure out why you don't get an ACK (wrong address perhaps) and then start over by resetting the I2C. And doing this should not lock up the I2C. 

    Thanks.

    -Tai Nguyen  

  • We agree on the intent but I don't think the hardware works that way. 

    Attached is a code snippet based upon the app note and what I pulled from your driver:

     

        I2C_ICMDR=0;

       I2C_ICMDR = ICMDR_STT               // Set for Master Write
                  | ICMDR_TRX   
                  | ICMDR_STP
    #ifdef I2C_FREE
                  | ICMDR_FREE
    #endif
                  | ICMDR_MST;

        I2C_ICCNT = *len;                    // Set length
        I2C_ICSAR = i2c_addr;               // Set I2C slave address


       I2C_ICMDR = ICMDR_STT               // Set for Master Write
                  | ICMDR_TRX   
                  | ICMDR_IRS                // release reset
                  | ICMDR_STP
    #ifdef I2C_FREE
                  | ICMDR_FREE
    #endif
                  | ICMDR_MST;


        for ( i = 0 ; i < *len ; i++ )
        {
            I2C_ICDXR = data[i];            // Write

       { error checks here....

         if I find an error wait until I2C is not busy and then reset and abort with error

          }while ( ( I2C_ICSTR & ICSTR_ICXRDY ) == 0 );// Wait for Tx Ready

    You are suggesting that I can somehow break in between the address and the data.  If I don't supply the data I will get an underflow condition since it expects more bytes.  If I specify zero length, I get the address and then a stop condition terminating the transmission and I don't know of any way to continue the transfer without another address being sent.    In either case, issuing a reset during a transfer is specifically listed as a problem in Section 2.10.1 of SPRU991.  It appears the hardware will continue inspite of a NAK on address or data until I2C_ICCNT decrements to zero?

  • Yes,

    You should be able to break in between the address and the data. Here is the example code that I use to test with the I2C EPROM using the CSL.

        /*Wait till the Bus is free for transfer */
        do
        {
         CSL_i2cGetHwStatus(hI2c[I2C_NUM],CSL_I2C_QUERY_BUS_BUSY,&response);
       
        }while((response & CSL_I2C_BUS_BUSY)!=0x0);
      
        
      
        /*Setup the Slave Adrress (E2PROM) address from where data is to be written */      
        CSL_i2cHwControl(hI2c[I2C_NUM],CSL_I2C_CMD_SET_SLAVE_ADDR,&slvaddr);
        
         /*Start Sending the address to EEPROM I2C*/
        CSL_i2cHwControl(hI2c[I2C_NUM],CSL_I2C_CMD_START,NULL);
       
          /*Check for NACK */      
        for(k=0;k<10;k++);
       
        if(CSL_FEXT(hI2c[I2C_NUM]->regs->ICSTR,I2C_ICSTR_NACK))
        {
           while(1);  //hang here if NO ACK --reset the I2C if required
        }

        for(k=0;k<1000; k++)
        {
         asm(" nop");
        }
       /*First two bytes are taken as address pointers from where the data is written into i2c eeprom */
       
       /*Transmit 2 bytes of address from where data in I2C eeprom needs to be written*/
        for(i=0;i<2;i++)
        {
          /*Check if Transmit Data Register is Ready */
           CSL_i2cGetHwStatus(hI2c[I2C_NUM],CSL_I2C_QUERY_TX_RDY,&response);
         do
         {
        
         }while((response & CSL_I2C_TX_READY)==0);
          CSL_i2cWrite(hI2c[I2C_NUM], &i2c_eeprom_add[i]);
           for(k=0;k<1000; k++)
           {
              asm(" nop");
           }
        }
       /*Check for NACK from EEPROM */
        for(k=0;k<1000;k++);
        if(CSL_FEXT(hI2c[I2C_NUM]->regs->ICSTR,I2C_ICSTR_NACK))
        {
          while(1); //hang here if NO ACK --reset the I2C if required

       }

    Hope this helps.

    Thanks.

    -Tai Nguyen

     

  • This is different from what I have seen/am using. 

    Just for background, we are not using the bios or CSL.  I don't mind using them for reference and understanding but they will not work with our requirements.

    For CSL commands, the only reference I have is SPRU401j.  It doesn't list a number of your function calls.  What is the proper documentation for this?

     

  • I should make it more clear that the code that I have here is just for your reference. You should be able to change your code to mimic the steps in my example. Some of the CSL function calls are used internally for silicon validation and verification purposes.   

    Thanks.

    -Tai Nguyen

  • Looking at the code sample and  the way it works makes me think that perhaps the FDF bit is set in the ICMDR register?  Can you confirm?

    It would be a bit of a rewrite but possible. It would also mean that we would never be able to feed the I2C from the DMA.

    Are there any known issues or errata about the I2C?

  • No, the FDF (Free Data Format) bit should not be set here.

    You should be able to use the EDMA to feed the data but not the slave address.

    I am not aware of any known issue about the I2C on the DM6437.

    Thanks.

    -Tai Nguyen