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.

How to write EEPROM?

Genius 5820 points

Hi,

there is an example hsi2cEeprom.c for BeagleBone Black that demonstrates how to read data from EEPROM. Just to push me into the right direction: what is needed to write some data to the EEPROM?

Thanks!

  • That file hsi2cEeprom.c is definitely not best example of EEPROM code. The function SetupI2CReception() should really be called I2CWrite2Read50() as it does a Start-Write2-Restart-Read50-Stop(). For writing with the same hard-coded restrictions, you want Start-Write52-Stop where 52 is 2 address bytes + 50 bytes of data. Something like the code below. I'd suggest a total rewrite.
    ...
    static void E2promWrite(const unsigned char *data);
    static void SetupI2CTransmission(unsigned int dcount);
    ...
    volatile unsigned char dataToSlave[50+2]; // 2 address + 50 data
    ...
     /*
     ** Reads data from a specific address of e2prom
     */
    static void E2promWrite(const unsigned char *data)
    {
        unsigned int i;

        dataToSlave[0] = E2PROM_ADDR_MSB;
        dataToSlave[1] = E2PROM_ADDR_LSB;
        for (i = 0; i < 50; i++ )
        {
             dataToSlave[2+i] = data[i];
        }

        tCount = 0;
        rCount = 0;
        SetupI2CTransmission(50);
    }
    ...
    /* Send dcount+2 bytes in global var dataToSlave. */
    static void SetupI2CTransmission(unsigned int dcount)
    {
        /* Data Count specifies the number of bytes to be transmitted */
        I2CSetDataCount(SOC_I2C_0_REGS, 0x02+dcount);

        numOfBytes = I2CDataCountGet(SOC_I2C_0_REGS); //Why not use dcount?

        /* Clear status of all interrupts */
        CleanUpInterrupts();

        /* Configure I2C controller in Master Transmitter mode */
        I2CMasterControl(SOC_I2C_0_REGS, I2C_CFG_MST_TX);

        /* Transmit interrupt is enabled */
        I2CMasterIntEnableEx(SOC_I2C_0_REGS, I2C_INT_TRANSMIT_READY);

        /* Generate Start Condition over I2C bus */
        I2CMasterStart(SOC_I2C_0_REGS);

        while(I2CMasterBusBusy(SOC_I2C_0_REGS) == 0);

        /* ISR will inc tCount until equal to numOfBytes */
        while(tCount != numOfBytes);

        /* Generate a STOP */
        I2CMasterStop(SOC_I2C_0_REGS);
    }

  • After playing around with this code for a while I afraid I have to come back with this: the example shown above seems to transmit data via I2C to EEMPROM but it does not write them into it. So...may be some kind of EEPROM-write-command or something like this is missing?

  • The Beagle Bone Black schematic shows a Microchip 24LC32A 32Kbit I2C EEPROM. The EEPROM has its Write Protect pulled high which means that the EEPROM is write protected. You need to pull down the WP pin via TP4/TESTPT1 to enable writing.

  • Pulling the WP intput to LOW (and even to HIGH) did not help, it is still not writing.

    So...may be there is a stop-condition missing between writing the address to EEPROM and writing data to be stored? Or not waiting long enough to acknowledge for page write operation? Or something like that?

  • I forgot about the page size limitation of 32 bytes. The EEPROM write should be one I2C write transaction of two bytes address + 32 bytes data. No addtional stop or restart. Try changing the hard-coded 50 to 32 every where. Wait 5ms between each page write.

  • Hm...currently I fail writing four bytes to address 0 or address 4...

  • I can't think of anything else at the moment, Please post your current test code and unverify my post. Maybe others can comment on your code.

  • OK, that's what I'm currently doing:

    void writeEEPROM(unsigned int addr,unsigned int length,const unsigned char *data)
    {
       I2CPinMuxSetup(0);
       SetupI2C();
       I2CAINTCConfigure();
       E2promWrite(addr,length,data);
    }
    
    static void SetupI2C(void)
    {
       I2C0ModuleClkConfig();
       I2CMasterDisable(SOC_I2C_0_REGS);
       I2CAutoIdleDisable(SOC_I2C_0_REGS);
       I2CMasterInitExpClk(SOC_I2C_0_REGS, 48000000, 12000000, 100000);
       I2CMasterSlaveAddrSet(SOC_I2C_0_REGS, I2C_SLAVE_ADDR);
       I2CMasterEnable(SOC_I2C_0_REGS);
    }
    
    static void E2promWrite(unsigned int addr,unsigned int length,const unsigned char *data)
    {
       dataToSlave[0]=(unsigned char)(addr >> 8);
       dataToSlave[1]=(unsigned char)(addr & 0xFF);
       memcpy((void*)&dataToSlave[2],data,length);
    
       tCount=0;
       rCount=0;
       SetupI2CTransmission(length);
    }
    
    static void SetupI2CTransmission(unsigned int dcount)
    {
       I2CSetDataCount(SOC_I2C_0_REGS,0x02+dcount);
       numOfBytes=I2CDataCountGet(SOC_I2C_0_REGS); //Why not use dcount?
       CleanUpInterrupts();
       I2CMasterControl(SOC_I2C_0_REGS,I2C_CFG_MST_TX);
       I2CMasterIntEnableEx(SOC_I2C_0_REGS,I2C_INT_TRANSMIT_READY);
       I2CMasterStart(SOC_I2C_0_REGS);
    
       while (I2CMasterBusBusy(SOC_I2C_0_REGS)==0);
       while (tCount!=numOfBytes);
       I2CMasterStop(SOC_I2C_0_REGS);
    }

    ISR is left untouched, it is the one that comes with the EEPROM examples for BBB.