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.

Sitara eeprom.c is buggy

Good morning all,

Being in need of EEPROM support for a project, I came across eeprom.c in AM335X_StarterWare_02_00_00_07\platform\evmAM335x.  It lookde like what I wanted - programmed I/O, a clean API, and not board specific.  So I included it in a test project for testing.  I found several bugs.

1)      After sending the address, need to wait for idle to set up receive.  If not, we lose the first two bytes of data.

2)      Need to set a receive count.  If not, hangs waiting for data

3)      Need to increment the index in the rx data loop.  Otherwise, all the bytes read end up at the same address.

4)      Need to clear the status flag after reading the data.  The flag stays set until manually cleared.

The revised routine I ended up with is:


/**
 * \Function EEPROMI2CRead
 * \brief   This function reads data from EEPROM.
 *          
 * \param   data    pointer to address where data is to be read to.
 * \param   length  Length of data to be read
 * \param   offset  Address of the starting EEPROM data byte
 *
 * \return  None.
 *
 * \note    This depends on the instance and slave address being preconfigured.
 *          EEPROMI2CSetUp Shall be called Before this API is used
 */
void EEPROMI2CRead (unsigned char *data, unsigned int length,
                   unsigned short offset)
{
    unsigned int idx = 0;

    /* First send the register offset - TX operation */
    I2CSetDataCount(EEPROM_I2C_BASE, 2);

    I2CMasterControl(EEPROM_I2C_BASE, I2C_CFG_MST_TX);

    I2CMasterStart(EEPROM_I2C_BASE);

    /* Wait for the START to actually occur on the bus */
    while (0 == I2CMasterBusBusy(EEPROM_I2C_BASE));

    /* Wait for the Tx register to be empty */
    while (0 == I2CMasterIntRawStatusEx(EEPROM_I2C_BASE,
                                        I2C_INT_TRANSMIT_READY));

    /* Write the offset MSB */
    I2CMasterDataPut(EEPROM_I2C_BASE, (unsigned char)((offset >> 8) & 0xFF));

    /* Wait for the Tx register to be empty */
    while (0 == I2CMasterIntRawStatusEx(EEPROM_I2C_BASE,
                                        I2C_INT_TRANSMIT_READY));

    /* Write the offset LSB */
    I2CMasterDataPut(EEPROM_I2C_BASE, (unsigned char)(offset & 0xFF));

    /* Wait until I2C registers are ready to access */
    while (0 == I2CMasterIntRawStatusEx(EEPROM_I2C_BASE,
                                I2C_INT_ADRR_READY_ACESS));

    /* Now that we have sent the register offset, start a RX operation*/
    I2CMasterControl(EEPROM_I2C_BASE, I2C_CFG_MST_RX);

    /* Set the Rx data count */
    I2CSetDataCount(EEPROM_I2C_BASE, length);

    /* Repeated start condition */
    I2CMasterStart(EEPROM_I2C_BASE);

    while (length--)
    {
        while (0 == I2CMasterIntRawStatusEx(EEPROM_I2C_BASE,
                                            I2C_INT_RECV_READY));

        data[idx++] = (unsigned char)I2CMasterDataGet(EEPROM_I2C_BASE);

        /* Clear receive ready interrupt status */
        I2CMasterIntClearEx(EEPROM_I2C_BASE,  I2C_INT_RECV_READY);
    }

    I2CMasterStop(EEPROM_I2C_BASE);
}

I hope this makes it into the next revision of StarterWare.

It looks like creating an EEPROM write version of this would be pretty straightforward.

This code was tested on a BeagleBone, as it is not platform specific.  I did not provide the whole file, as I changed the setup to accommodate both I2C0 and I2C2 to support capes, and used my own eeprom.h header to replace the evm header.

Gerry Belanger