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.

EEPROM Ack polling with I2C controller

I am implementing an I2C EEPROM module for a non-os application.  I am trying to implement ACK polling to be used following a write so I do not have to use a fixed delay.  The recommended method from at least 2 memory vendors is to send a write command to the slave address of the EEPROM with no data.  If the slave address byte is ACKed, we are done.  If not ACKed, try again.

Unfortunately it appears that TI designed the Sitara I2C controller to preclude this (refer to the TRM description of the DCOUNT register).

The Sttara Starterware EEPROM examples provide no guidance, as they are read only.

Does TI have any recommendations on how to use the Sitara I2C core to do ACK polling?

Gerry Belanger

  • Gerard, unfortunately as you have found, the module does not support zero data byte transfers.  Is there any other way to poll the EEPROM?  What if you try to a continuous read, will it return a NACK until it is finished with its internal programming?  Or will it hold off further writes with a NACK until it is ready?

    Regards,

    James

  • James,

    There are ways to work around this, but each has disadvantages the method recommended by the eeprom manufacturers avoids.

    1) simply wait the tWR, in this case 5ms, after each write.

    2) Do a 1 byte write. The data byte would be the MS address byte.  I'm not sure if that would change the eeprom data pointer.  It is an undefined eeprom operation.

    3) Do a read as you suggested.  That WILL change the eeprom internal data pointer when it succeeds.

    4) Redo my read and write routines to look for a NAK and keep retrying until success.  This is probably the route I will have to take.

    So how does TI do it when you program the eeprom in the eval boards?  They are shipped with data in the eeproms, so they have to be programmed somehow.

    Gerry Belanger

  • James,

    Given the core design, there is probably no hope of inducing it to send an I2C EEPROM software reset sequence:

    Start, 9 '1' bits, Start, Stop.

    Looks like I will have to bit bang that one.

    Gerry Belanger

  • Gerard, looks like we have some timed delays for the I2C programming.  We don't program much, so there was not too much effort to optimize it. I've attached the file that performs the i2c write, maybe this will help you out. 

    /******************************************************************************
    **+-------------------------------------------------------------------------+**
    **| 								****									|**
    **| 								**** 									|**
    **| 							******o*** 									|**
    **| 						********_///_**** 								|**
    **| 						***** /_//_/ **** 								|**
    **|							 ** ** (__/ **** 								|**
    **| 							********* 									|**
    **| 								**** 									|**
    **| 								*** 									|**
    **| 																		|**
    **| 		Copyright (c) 2008-2009 Texas Instruments Incorporated 			|**
    **|							 ALL RIGHTS RESERVED 							|**
    **|																			|**
    **| Permission is hereby granted to licensees of Texas Instruments 			|**
    **| Incorporated (TI) products to use this computer program for the sole 	|**
    **| purpose of implementing a licensee product based on TI products. 		|**
    **| No other rights to reproduce, use, or disseminate this computer 		|**
    **| program, whether in part or in whole, are granted.						|**
    **|																			|**
    **| TI makes no representation or warranties with respect to the 			|**
    **| performance of this computer program, and specifically disclaims 		|**
    **| any responsibility for any damages, special or consequential, 			|**
    **| connected with the use of this program. 								|**
    **| 																		|**
    **+-------------------------------------------------------------------------+**
    ******************************************************************************/
    
    /*
     * hsI2c.c
     *
     * This file contains the routines for configuring and
     * accessing the I2C controller and slave devices.
     *
     *  @Component:   I2C
     *
     *  @Filename:    hsI2c.h
     *
     */
    
    /*
     *====================
     * Function implementations
     *====================
     */
    #include "hw_types.h"
    #include "soc_errors.h"
    #include "delay.h"
    #include "hsI2c.h"
    #include "hw_i2c.h"
    #include "hw_cm_per.h"
    
    
    
    /*
     *====================
     * Function implementations
     *====================
     */
    
    
    /** **************************************************************************
     * clockInit
     *
     * brief
     *
     * This routine initializes the clock part for I2C on the Bases of BUS number
     *
     * Parameter busNum		[IN]	Bus Instance number
     *
     * Return
     *   NA
     *
     */
    
    void clockInit
    (
        UINT8    busNum
    )
    {
    #ifdef centarus
        HWREG(PINCNTL263) = I2C0_PIN_EN;
        HWREG(PINCNTL264) = I2C0_PIN_EN;
    
        /*Ensure the module is enabled and the clock to it is also enabled*/
        HWREG(PRCM + CM_PER_I2C0_CLKCTRL) =
                    CM_PER_I2C0_CLKCTRL_MODULEMODE_ENABLE;
    
    	DELAYMilliSeconds(I2C_TIMEOUT);
    
    	/* Check the state is changed */
        while (HWREG(CM_ALWON_I2C_0_CLKCTRL) & CM_PER_I2C2_CLKCTRL_IDLEST);
    
        DELAYMilliSeconds(DELAY_MILLI_SEC);
    
        *(UINT32*)(PRCM + CM_PER_I2C1_CLKCTR) =
                    CM_PER_I2C0_CLKCTRL_MODULEMODE_ENABLE;
    
    	DELAYMilliSeconds(I2C_TIMEOUT);
    
    	/* Check the state is changed */
    	while ((*(UINT32*) CM_ALWON_I2C_1_CLKCTRL) & CM_PER_I2C2_CLKCTRL_IDLEST);
    
        DELAYMilliSeconds(DELAY_MILLI_SEC);
    
    
    #else
    
        switch (busNum)
        {
            case I2C0_BUS:
                /*Ensure the module is enabled and the clock to it is also enabled*/
                HWREG(PRCM + CM_PER_I2C1_CLKCTRL) =
                    CM_PER_I2C1_CLKCTRL_MODULEMODE_ENABLE;
                break;
    
            case I2C1_BUS:
                /*Ensure the module is enabled and the clock to it is also enabled*/
                HWREG(PRCM + CM_PER_I2C2_CLKCTRL) =
                    CM_PER_I2C2_CLKCTRL_MODULEMODE_ENABLE;
                break;
        }
    #endif
    }
    
    
    INT16 pinmuxSetting
    (
        UINT8	busNum
    )
    {
        switch (busNum)
        {
            case I2C0_BUS:
                /* FOR I2C0  I2C_SCL*/
                HWREG(CTRL_MODULE_BASE_ADD + CONTROL_CONF_I2C0_SDA) = 0
                    | (CONTROL_CONF_I2C0_SDA_CONF_I2C0_SDA_MMODE &
                        (PINMUXMODE_1 <<
                             CONTROL_CONF_I2C0_SDA_CONF_I2C0_SDA_MMODE_SHIFT))
                    | CONTROL_CONF_I2C0_SDA_CONF_I2C0_SDA_RXACTIVE
    
                    | CONTROL_CONF_I2C0_SDA_CONF_I2C0_SDA_PUDEN;
    
                /* FOR I2C0  I2C_SDA*/
                HWREG(CTRL_MODULE_BASE_ADD + CONTROL_CONF_I2C0_SCL) = 0
                    | (CONTROL_CONF_I2C0_SCL_CONF_I2C0_SCL_MMODE &
                        (PINMUXMODE_1 <<
                            CONTROL_CONF_I2C0_SCL_CONF_I2C0_SCL_MMODE_SHIFT))
    
                    | CONTROL_CONF_I2C0_SCL_CONF_I2C0_SCL_PUDEN
    
                    | CONTROL_CONF_I2C0_SCL_CONF_I2C0_SCL_RXACTIVE ;
    
                DELAYMilliSeconds(I2C_TIMEOUT);
                break;
    
            case I2C1_BUS:
                /* FOR I2C1  I2C_SCL*/
                HWREG(CTRL_MODULE_BASE_ADD + CONTROL_CONF_MII1_CRS) = 0
                    | (CONTROL_CONF_MII1_CRS_CONF_MII1_CRS_MMODE &
                        (PINMUXMODE_4 <<
                            CONTROL_CONF_MII1_CRS_CONF_MII1_CRS_MMODE_SHIFT))
                    | CONTROL_CONF_MII1_CRS_CONF_MII1_CRS_PUDEN
    
                    | CONTROL_CONF_MII1_CRS_CONF_MII1_CRS_RXACTIVE;
    
                /* FOR I2C1  I2C_SDA*/
                HWREG(CTRL_MODULE_BASE_ADD + CONTROL_CONF_MII1_RXERR) = 0
                    | (CONTROL_CONF_MII1_RXERR_CONF_MII1_RXERR_MMODE &
                        (PINMUXMODE_4 <<
                            CONTROL_CONF_MII1_RXERR_CONF_MII1_RXERR_MMODE_SHIFT))
    
                    | CONTROL_CONF_MII1_RXERR_CONF_MII1_RXERR_PUDEN
    
                    | CONTROL_CONF_MII1_RXERR_CONF_MII1_RXERR_RXACTIVE
    
                    ;
                DELAYMilliSeconds(I2C_TIMEOUT);
                break;
    
        }
        return SUCCESS;
    }
    
    
    
    /** **************************************************************************
     * INT16 i2cInit()
     * brief Routine to initialize the I2C
     *
     * This routine initializes the I2C instance as per given bus number.No use of
     * interrupts here as the code is intended to carry out all I/O operations
     * in polled mode.
     *
     * Parameter busNum		[IN]	Bus Instance number
     *
     * Return
     *       return SUCCESS for success  - Description
     *       return FAIL for error   - Description
     */
    INT16 I2CInit
    (
        UINT8	busNum
    )
    {
        INT16   retVal = SUCCESS;
        UINT16  sclValues = 0;
        UINT32  baseI2c = 0;
        UINT8   flag=0;
        UINT16  delayCnt = 1000;
    
        switch (busNum)
        {
            case I2C0_BUS:
                baseI2c = HSI2C0_BASE;
                break;
            case I2C1_BUS:
                baseI2c = HSI2C1_BASE;
                break;
            default:
                retVal = ERR_INVALID_PARAM;
                return retVal;
        }
    
        if (SUCCESS == retVal)
        {
    #ifdef centarus
        	;
    #else
            /* Setting PINMUX Required for I2C*/
            pinmuxSetting(busNum);
    #endif
            /*Setting Clock as Required for I2C to Work*/
            clockInit(busNum);
    
            /* Reset all the registers */
            HWREG(baseI2c + I2C_CON) = 0;
            HWREG(baseI2c + I2C_PSC) = 0;
            HWREG(baseI2c + I2C_SCLL) = 0;
            HWREG(baseI2c + I2C_SCLH) = 0;
            HWREG(baseI2c + I2C_BUF) = 0;
            HWREG(baseI2c + I2C_SYSC) = 0;
            HWREG(baseI2c + I2C_WE) = 0;
            HWREG(baseI2c + I2C_STAT) = 0;
    
            DELAYMilliSeconds(DELAY_MILLI_SEC/2);
            /* soft-reset the I2c Controller */
            HWREG(baseI2c + I2C_SYSC) = I2C_SYSC_SRST;
    
            /*  I2C requires to be enabled for reset to complete */
            HWREG(baseI2c + I2C_CON) = I2C_CON_I2C_EN;
    
            /* wait for  reset  */
            while (I2C_SYSC_SRST_RESET != flag)
            {
                flag = ( HWREG(baseI2c + I2C_SYSC)  & I2C_SYSC_SRST_RESET) ;
                delayCnt--;
                DELAYMilliSeconds(DELAY_MILLI_SEC);
                if (delayCnt <= 0)
                    break;
            }
            if (delayCnt == 0)
            {
                retVal = FAIL;
        	    return(retVal);
        	}
            DELAYMilliSeconds(I2C_TIMEOUT);
    
    
            /* Wake Up*/
            HWREG(baseI2c + I2C_SYSC) =  0
                |I2C_SYSC_AUTOIDLE
    
                | I2C_SYSC_ENAWAKEUP
    
            /*NO IDLE MODE*/
                | (I2C_SYSC_IDLEMODE_SMARTIDLE << I2C_SYSC_IDLEMODE_SHIFT)
    
            /*CLOCK ACTIVITY IN FUNCTIONAL MODE*/
                | (I2C_SYSC_CLKACTIVITY_FUNC << I2C_SYSC_CLKACTIVITY_SHIFT);
    
    
            /* Disable the controller */
            HWREG(baseI2c + I2C_CON) = 0;
    
            /* compute the PSC value */
            if (HSI2C_BUS_CLOCK > I2C_TIMEOUT)
            {
                /* I2C PRESCALE settings. */
                HWREG(baseI2c + I2C_PSC) = HSI2C_PRESCALE_DIV1;
                sclValues = HSI2C_INTERNAL_CLOCK1 / HSI2C_BUS_CLOCK;
            }
            else
            {
                /* I2C PRESCALE settings. */
                HWREG(baseI2c + I2C_PSC) = HSI2C_PRESCALE_DIV2;
                sclValues = HSI2C_INTERNAL_CLOCK2 / HSI2C_BUS_CLOCK;
            }
    
            /* Disable  & clear all the Interrupts */
            HWREG(baseI2c + I2C_IRQENABLE_CLR) = HSI2C_IRQDISABLE_ALL;
    
            /* set the SCL Low and High time */
            HWREG(baseI2c + I2C_SCLL) = sclValues - HI2C_SCLL_VAL;
            HWREG(baseI2c + I2C_SCLH) = sclValues - HI2C_SCLH_VAL;
    
            /* Set the self address */
            HWREG(baseI2c + I2C_OA) = I2C_OA_OA & OWN_ADD;
    
            /* Enable the I2C controller */
            HWREG(baseI2c + I2C_CON) = I2C_CON_I2C_EN;
    
            /* set the slave address */
            HWREG(baseI2c + I2C_SA) = (INT16) NULL;;
    
            /* Set data count */
            HWREG(baseI2c + I2C_CNT) = (INT16) NULL;
        }
        return (retVal);
    }
    
    
    
    /** **************************************************************************
     * \n \brief Routine to read data from slave device the I2C - 0
     *
     * This routine initializes the I2C controller for reading from the slave
     * peripheral connected to the bus. This function takes the slave address
     * as a parameter along with the read buffer pointer and the length of buffer.
     * This function returns the number of bytes read into the output length pointer.
     *
     * busNum 		[IN]		I2C Bus number
     * slaveAddr 	[IN]		I2C Slave address to read from
     * buffer		[OUT]		Buffer pointer to copy data into
     * bufLen 		[IN]		Length of the input buffer pointer
     * pDataRead	[OUT]		Place holder to return read number of bytes
     *
     * \return
     * \n      return SUCCESS for success  - Description
     * \n      return FAIL for error   - Description
     */
    INT16 I2CRead
    (
        UINT8	busNum,
        UINT16	slaveAddr,
        UINT8	*buffer,
        UINT8	bufLen,
        UINT8	*pDataRead
    )
    {
        INT16 retVal = SUCCESS;
        UINT16 status = 0;
        UINT8 bytesRead = 0;
        UINT8* pDataPtr = NULL; /*Pointer to save received data*/
        UINT32	timeOut = I2C_TIMEOUT;
        UINT32  baseI2c = 0;
    
        /* input parameter validation */
        if ((NULL != buffer) && (0 != bufLen) && (NULL != pDataRead))
        {
            pDataPtr = buffer;
        }
        else
        {
            retVal = ERR_INVALID_PARAM;
            return retVal;
        }
        
        switch (busNum)
        {
            case I2C0_BUS:
                baseI2c = HSI2C0_BASE;
                break;
            case I2C1_BUS:
                baseI2c = HSI2C1_BASE;
                break;
            default:
                retVal = ERR_INVALID_PARAM;
                return retVal;
        }
    
        /*  set the slave address */
        HWREG(baseI2c + I2C_SA) = slaveAddr & I2C_SA_SA;
    
        /* set the count */
        HWREG(baseI2c + I2C_CNT) = bufLen;
    
        /* Poll for the bus to become free/idle */
        for (timeOut = 0; timeOut < I2C_TIMEOUT; timeOut++)
        {
            if (I2C_IRQSTATUS_RAW_BB_FREE == (HWREG(baseI2c + I2C_STAT) &
                I2C_IRQSTATUS_RAW_BB))
            break;
        }
    
        if (timeOut == I2C_TIMEOUT)
            retVal = FAIL;
    
        if (SUCCESS == retVal)
        {
            /* configure the I2C bus as master for receiving mode */
            HWREG(baseI2c + I2C_CON) = 0
                | (I2C_CON_I2C_EN)     // I2C Enable
                | (I2C_CON_MST)        // Master Mode
                | (I2C_CON_TRX_RCV)        // Receive Mode
                | (I2C_CON_STP)        // Stop
                | (I2C_CON_STT);       // Start
        }
        /* in THIS loop till we have TO read all the data or we have timed-out,
         * read the data from I2C data register and return
         */
    
        for (timeOut = 0; timeOut < I2C_TIMEOUT; timeOut++)
        {
            status = HWREG(baseI2c + I2C_STAT);
    
            /* Check for NACK*/
            if (0 == (status & I2C_IRQSTATUS_RAW_NACK))
            {
                /*  ACK received. Now check for data ready */
                if (0 == (status & I2C_IRQSTATUS_RAW_ARDY))
                {
                    /* check for RRDY for data availability */
                    if (I2C_IRQSTATUS_RAW_RRDY == (status & I2C_IRQSTATUS_RAW_RRDY ))
                    {
                        /* check if we have buffer space available */
                        if (bytesRead < bufLen)
                        {
                            /* data is available. Read it now and ACK */
                            *pDataPtr++ = (HWREG(baseI2c + I2C_DATA)) &
                                I2C_DATA_DATA;
                            bytesRead++;
                        }
    
                        /* clear the RRDY bits */
                        HWREG(baseI2c + I2C_STAT) = I2C_IRQSTATUS_RAW_RRDY;
                    }
                }
                status = HWREG(baseI2c + I2C_STAT);
                /* if we have lost the arbitration */
                if (I2C_IRQSTATUS_RAW_AL_LOST ==
                    (status & I2C_IRQSTATUS_RAW_AL))
                {
                    retVal = FAIL;
                    /* clear the AL bits */
                    HWREG(baseI2c + I2C_STAT) = 0 |
                        I2C_IRQSTATUS_RAW_AL_CLEAR;
                    break;
                }
    
                if (I2C_IRQSTATUS_RAW_ARDY == (status & I2C_IRQSTATUS_RAW_ARDY))
                {
                    /* all the reads are completed */
                    /* Clear the ARDY BIT */
                    HWREG(baseI2c + I2C_STAT) = 0 |
                        (I2C_IRQSTATUS_RAW_ARDY_CLEAR
                        << I2C_IRQSTATUS_RAW_ARDY_SHIFT);
                    break;
                }
    
                if (I2C_IRQSTATUS_RAW_NACK == (status & I2C_IRQSTATUS_RAW_NACK))
                {
                    retVal = FAIL;
                    /* Clear that Bit */
                    HWREG(baseI2c + I2C_STAT) = 0 |
                        (I2C_IRQSTATUS_RAW_NACK_CLEAR
                        << I2C_IRQSTATUS_RAW_NACK_SHIFT);
                    break;
                }
    
                DELAYSeconds( 1 );
            }
            else
            {
                retVal = FAIL;
                /* clear the NACK bits */
                HWREG(baseI2c + I2C_STAT) = 0 |
                    (I2C_IRQSTATUS_RAW_NACK_CLEAR
                    << I2C_IRQSTATUS_RAW_NACK_SHIFT);
                break;
            }
        }
        /* before returning, update the return counts too */
        if (NULL != pDataRead)
            *pDataRead = bytesRead;
        return (retVal);
    }
    
    /** **************************************************************************
     * \n \brief Routine to write data from slave device the I2C - 0
     *
     * This routine initializes the I2C controller for writing to the slave
     * peripheral connected to the bus. This function takes the slave address
     * as a parameter along with the write buffer pointer and the length of buffer.
     * This function returns the number of bytes written into the output length pointer.
     *
     * busNum 		[IN]		I2C Bus number
     * slaveAddr 	[IN]		I2C Slave address to read from
     * buffer		[OUT]		Buffer pointer to copy data into
     * bufLen 		[IN]		Length of the input buffer pointer
     * pDataRead	[OUT]		Place holder to return read number of bytes
     *
     * Return
     *       return SUCCESS for success  - Description
     *       return FAIL for error   - Description
     */
    INT16 I2CWrite
    (
        UINT8 	busNum,
        UINT16 	slaveAddr,
        UINT8	*buffer,
        UINT8	bufLen,
        UINT8   *dataWritten
    )
    {
        INT16 retVal = SUCCESS;
        UINT16  status = 0;
        UINT8	bytesWritten = 0;
        UINT32	timeOut = I2C_TIMEOUT;
        UINT32  baseI2c = 0;
    
    
        if ((NULL == buffer) ||  (0 == bufLen) || (NULL == dataWritten ))
            {
                retVal = 0;
                return (retVal);
            }
    
        /* Assign the I2C register base */
    	switch (busNum)
    	{
            case 0:
                baseI2c = HSI2C0_BASE;
                break;
            case 1:
                baseI2c = HSI2C1_BASE;
                break;
            case 2:
                baseI2c = HSI2C2_BASE;
                break;
            default:
                return FAIL;
        }
    
        /* just to ensure the previous transactions flags are cleared */
        HWREG(baseI2c + I2C_STAT ) = I2C_CNT_DCOUNT;
    
        /*  set the slave address */
        HWREG(baseI2c + I2C_SA) = slaveAddr & I2C_SA_SA;
    
        /* set the count */
        HWREG(baseI2c + I2C_CNT) = bufLen;
    
        /* Poll for the bus to become free/idle */
        for (timeOut = 0; timeOut < I2C_TIMEOUT; timeOut++)
        {
            if (I2C_IRQSTATUS_RAW_BB_FREE == (HWREG(baseI2c + I2C_STAT) &
                I2C_IRQSTATUS_RAW_BB))
            break;
        }
    
        /*********/
    
        if (timeOut == I2C_TIMEOUT)
            retVal = FAIL;
    
        if (SUCCESS == retVal)
        {
            /* configure the I2C bus as master for receiving mode */
            HWREG(baseI2c + I2C_CON) = 0
                | (I2C_CON_I2C_EN & (I2C_CON_I2C_EN_ENABLE
                    << I2C_CON_I2C_EN_SHIFT))     // I2C Enable
                | (I2C_CON_MST & (I2C_CON_MST_MST
                    << I2C_CON_MST_SHIFT))        // Master Mode
                | (I2C_CON_TRX & (I2C_CON_TRX_TRX
                    << I2C_CON_TRX_SHIFT))        // TRansmit Mode
                | (I2C_CON_STP & (I2C_CON_STP_STP
                    << I2C_CON_STP_SHIFT))        // Stop
                | (I2C_CON_STT & (I2C_CON_STT_STT
                    << I2C_CON_STT_SHIFT));       // Start
        }
    
        /* Loop till we have written all the data or we have timed-out */
        for (timeOut = 0; timeOut < I2C_TIMEOUT; timeOut++)
        {
    
            /* clear the AL bits */
            HWREG(baseI2c + I2C_STAT) = 0 |
                I2C_IRQSTATUS_RAW_AL_CLEAR;
    
            status = HWREG(baseI2c + I2C_STAT);
    
            /* Check for NACK*/
            if (0 == (status & I2C_IRQSTATUS_RAW_NACK))
            {
                /*  ACK received. Now check for data ready */
                if (0 == (status & I2C_IRQSTATUS_RAW_ARDY))
                {
                    /* check for XRDY for data availability */
                    if (I2C_IRQSTATUS_RAW_XRDY ==(status & I2C_IRQSTATUS_RAW_XRDY))
                    {
                        /* check if we have buffer space available */
    
                        if (bytesWritten < bufLen)
                        {
                            /* Write the data and ACK */
                            HWREG(baseI2c + I2C_DATA) =
                                (*buffer++ & I2C_DATA_DATA);
                            bytesWritten++;
                        }
                        /* check if we have buffer space available */
    
                        /* clear the XRDY bits */
                        HWREG(baseI2c + I2C_STAT) = 0 |
                            (I2C_IRQSTATUS_RAW_XRDY_CLEAR
                            << I2C_IRQSTATUS_RAW_XRDY_SHIFT);
                    }
                    else
                    {
                        /* loop through to make another attempt */
                    }
    
                }
                if (bytesWritten == bufLen)
                    DELAYSeconds(I2C_TIMEOUT);
                status =  HWREG(baseI2c + I2C_STAT);
    
                /* if we have lost the arbitration */
                if (I2C_IRQSTATUS_RAW_AL_LOST ==
                    (HWREG(baseI2c + I2C_STAT) & I2C_IRQSTATUS_RAW_AL))
                {
                    retVal = FAIL;
                    /* clear the AL bits */
                    HWREG(baseI2c + I2C_STAT) = 0 |
                        I2C_IRQSTATUS_RAW_AL_CLEAR;
                    break;
                }
    
                if (I2C_IRQSTATUS_RAW_ARDY ==(HWREG(baseI2c + I2C_STAT) &
                		I2C_IRQSTATUS_RAW_ARDY))
                {
                    /* Clear the ARDY BIT */
                    HWREG(baseI2c + I2C_STAT) = 0 |
                        (I2C_IRQSTATUS_RAW_ARDY_CLEAR
                        << I2C_IRQSTATUS_RAW_ARDY_SHIFT);
                    break;
                }
    
                if (I2C_IRQSTATUS_RAW_NACK == (HWREG(baseI2c + I2C_STAT)
                		& I2C_IRQSTATUS_RAW_NACK))
                {
                    retVal = FAIL;
                    /* Clear that Bit */
                    HWREG(baseI2c + I2C_STAT) = 0 |
                        (I2C_IRQSTATUS_RAW_NACK_CLEAR
                        << I2C_IRQSTATUS_RAW_NACK_SHIFT);
                    break;
                }
    
                    DELAYSeconds( 10 );
            }
            else
            {
                retVal = FAIL;
                /* clear the NACK bits */
                HWREG(baseI2c + I2C_STAT) = 0 |
                    (I2C_IRQSTATUS_RAW_NACK_CLEAR
                    << I2C_IRQSTATUS_RAW_NACK_SHIFT);
                break;
            }
        }
            /* before returning, update the return counts too */
            if (NULL != dataWritten)
                *dataWritten = bytesWritten;
    
                return (retVal);
    }
    

    Regards,

    James

  • James,

    That code implements a NACK check and restart on NACK, my option 4.  So I will do it that way, using the facility the core has to offer.

    Thanks!

    Gerry Belanger

    .