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.

LM4F232 on chip EEPROM byte write operations

Hi

LM4F232 on-chip EEPROM is not supporting byte read/write operations (supports only word read/write) I did modify EEPROMProgram() function to support byte write operations. i.e. read complete word and then append required bytes and then write back.

works fine when I debug step by step but it hangs in EEPROM busy check while loop on Run/Go command. i.e. EEPROM_EEDONE_WORKING flag stays at ‘1.  I am not sure why it happens and how can modify below code to avoid this. Flash write error appear on reprogramming chip so I have to erase memory using LM flash programmer to reprogram again.

 Using CodeRed IDE () and Red Probe + debugger.

Can you please help to find any missing steps.

 

typedef enum EEPROM_PROGRAM_TYPE
{
   WRITE_DATA_BYTES = 0,
   FILL_CONSTANT_DATA
}EEPROM_PROGRAM_TYPE; 

SysCtlPeripheralEnable(S

// init code

SysCtlPeripheralEnable(SYSCTL_PERIPH_EEPROM0);
EEPROMInit();

 

UINT32 EEPROMProgram(UINT8 *pucData, UINT32 ulAddress, UINT32 ulCount,
                     EEPROM_PROGRAM_TYPE type, UINT8 fillDataByte)
{
   UINT32 ulStatus = 0;
   UINT16 numberOfBytesWritten = 0; // initialize number of bytes written count to zero
   UINT16 startWordAlignOffset = (UINT16)(ulAddress % (UINT16)4); // get word align offset byte count
   UINT16 numberOfWordsToWrite = (UINT16)((ulCount + (startWordAlignOffset) + (UINT32)3) / (UINT16)4);
   UINT8  tempWord[4];
   UINT16 index;

   // Check parameters in a debug build.
   ASSERT(pucData);
   ASSERT(ulAddress < SIZE_FROM_EESIZE(HWREG(EEPROM_EESIZE)));
   ASSERT((ulAddress + ulCount) <= SIZE_FROM_EESIZE(HWREG(EEPROM_EESIZE)));
   // comment this because code is modified to support byte write operations
   //ASSERT((ulAddress & 3) == 0);
   //ASSERT((ulCount & 3) == 0);

   // word align incoming address
   ulAddress = (ulAddress & 0xFFFFFFFC);

   // Make sure the EEPROM is idle before we start.
   do
   {
      // Read the status.
      ulStatus = (HWREG(EEPROM_EEDONE) & (0x0000013D));
   }
   while(ulStatus & EEPROM_EEDONE_WORKING);

   // Set the block and offset appropriately to program the first word.
   HWREG(EEPROM_EEBLOCK) = EEPROMBlockFromAddr(ulAddress);
   HWREG(EEPROM_EEOFFSET) = OFFSET_FROM_ADDR(ulAddress);


   // Write each word in turn.
   while(numberOfWordsToWrite)
   {
      // This is a workaround for a silicon problem on Blizzard rev A.  We
      // need to do this before every word write to ensure that we don't
      // have problems in multi-word writes that span multiple flash sectors.
      if(CLASS_IS_BLIZZARD && REVISION_IS_A0)
      {
         EEPROMSetSectorMask(ulAddress);
         ulAddress += 4;
      }

      // read current data stored at this address without incrementing address
      *((UINT32*)(&tempWord[0])) = HWREG(EEPROM_EERDWR);


      // read offset bytes but make sure we not reading more than request numberOfBytesWritten
      for(index = startWordAlignOffset; (index < (UINT16)4) && (numberOfBytesWritten < ulCount); index++)
      {
         if(type == WRITE_DATA_BYTES)
         {
            // incoming data from offset address (in case its not word aligned
            // then we should not over write other bytes
            tempWord[index] = pucData[numberOfBytesWritten];
         }
         else
         {
            // fill constant data
            tempWord[index] = fillDataByte;
         }

         numberOfBytesWritten++;
      }

      // Write the next word through the autoincrementing register.
      HWREG(EEPROM_EERDWRINC) = *((UINT32*)(&tempWord[0]));

      // Wait for the write to complete.
      do
      {
         // Read the status.
         ulStatus = (HWREG(EEPROM_EEDONE) & (0x0000013D));
      }
      while(ulStatus & EEPROM_EEDONE_WORKING);

      // Make sure we completed the write without errors.  Note that we
      // must check this per-word because write permission can be set per
      // block resulting in only a section of the write not being performed.
      if(ulStatus & (EEPROM_EEDONE_NOPERM | EEPROM_EEDONE_INVPL))
      {
         // An error was reported that would prevent the values from
         // being written correctly.
         if(CLASS_IS_BLIZZARD && REVISION_IS_A0)
         {
            EEPROMClearSectorMask();
         }
         return(ulStatus);
      }

      // Move on to the next word.
      numberOfWordsToWrite--;
      startWordAlignOffset = 0;

      // Do we need to move to the next block?  This is the case if the
      // offset register has just wrapped back to 0.
      if(HWREG(EEPROM_EEOFFSET) == 0)
      {
         HWREG(EEPROM_EEBLOCK) += 1;
      }
   }

   // Clear the sector protection bits to prevent possible problems when
   // programming the main flash array later.
   if(CLASS_IS_BLIZZARD && REVISION_IS_A0)
   {
      EEPROMClearSectorMask();
   }

   // Return the current status to the caller.
   return(HWREG(EEPROM_EEDONE));
}

  • Hello,

    I suggest verifying that all status check variables/mechanisms are declared "volatile".  You should look at the actual assembly code being generated too.

    Good luck!

    Regards,

    Dave

  • Thanks, your suggestion helped me to come out of this problem.

    I agree that using volatile variable for status check will push compiler to always get latest values from status register but same code (same binary file) was working sometimes.  After correcting status check mechanism still it was behaving in the same way (works sometimes) then I commented version A0 related code. So now it works both bytes read and write operations.

    On top my controller chip it is written as version A1 but system register says it’s AO; I am not sure which one is correct. Anyway thanks for your suggestion