Daniel White

EEPROM writes taking too much time

Discussion created by Daniel White on Mar 15, 2010
Latest reply on Mar 16, 2010 by Daniel White

MCU: S912XDT256

MASK: 1L15Y

16MHz xtal 40MHz bus clock

 

EEPROM writes are taking WAY too long.

 

According to the data sheet, the time required to erase one EEPROM sector and write the two words should be no more than 26.8mS but I am measuring over 40mS to complete this. I have placed port writes in the sector write function to confirm that the erase is actually only taking less than 1uS which I can not explain as it should be taking around 20mS. It is actually the first word program command that is taking over 40mS. Then the second word program command  takes about 50uS which is the only timing that agrees with the data sheet.

 

Looking at the test code, the port pin goes low the second time in B1 and stays low for over 40mS.

 

I actually have two boards to test on and the other one results in about a 30mS total time. I can't explain the difference in hardware, but am hoping that once the firmware is correct, both boards will behave properly.

 

I have confirmed that my ECLKDIV is set to 0xCA with no debugger connected (I have been burned by the write once problem before) by printing it with the putchar you can see commented out in my function.

 

Here is the function to write a sector. This is not how the code was originally written but I have tried many changes and experiments and simplified the code. None of the changes I have tried have influenced the timing. Please help as I am running out of ideas.

 

This code was originally based on an example credited to:

//  Copyright (c) Beissbarth GmbH 2003

 

void Clear_EEPROM_errors(void)
{
 // Wait for Finished or Error (all commands pending are executed)
  while(((ESTAT & ESTAT_CCIF_MASK) == 0) &&
        ((ESTAT & ESTAT_PVIOL_MASK) == 0) &&
        ((ESTAT & ESTAT_ACCERR_MASK) == 0)   ){};
  if(ESTAT & ESTAT_PVIOL_MASK)
  {
    ESTAT = ESTAT_PVIOL_MASK;
  }

  if(ESTAT & ESTAT_ACCERR_MASK)
  {

    ESTAT = ESTAT_ACCERR_MASK;
  } 

}

 

uByte Write_EEPROM_sector(uLong * value, uLong * address)

  uWord * ptr_ee_adr;
  uWord adr;
 
 SET_PIN_HIGH( DEBUG0_PORT, DEBUG0_PIN);
 
  adr = (uWord)address;
 
  // Check Adress
  if ((adr < EEPROM_START_ADDRESS) || (adr > EEPROM_END_ADDRESS) || (adr % 4))
  {
    SET_PIN_LOW( DEBUG0_PORT, DEBUG0_PIN);
 
    return(EEPROM_FAILED);
  }
  else
  {
    /* Sequence: A. Erase, B1. Write 2 Bytes, B2. Write 2 Bytes, C. Check */

    // Clear all Error Flags
    Clear_EEPROM_errors();
  
    // A. Erase -------------------------------------------
    // 1. Write Adress and data (dummy write)
    ptr_ee_adr = (uWord * near) adr;
    *ptr_ee_adr = 0;
 
    SET_PIN_LOW( DEBUG0_PORT, DEBUG0_PIN);

    // 2. Write CMD
    ECMD = ECMD_SECTOR_ERASE;
 
    // 3. Execute
    ESTAT = ESTAT_CBEIF_MASK;
 
    // 4. Wait for Command to complete
  while(((ESTAT & ESTAT_CBEIF_MASK) == 0) &&
        ((ESTAT & ESTAT_PVIOL_MASK) == 0) &&
        ((ESTAT & ESTAT_ACCERR_MASK) == 0)   ){};
 
    SET_PIN_HIGH( DEBUG0_PORT, DEBUG0_PIN);
   
    // B1. Write 2 Bytes -------------------------------------------
    // 1. Write Adress and data
    ptr_ee_adr = (uWord * near) adr;
    // First 2 Bytes of value
    *ptr_ee_adr = *((uWord *)(value));

    SET_PIN_LOW( DEBUG0_PORT, DEBUG0_PIN);
 
    // 2. Write CMD
    ECMD = ECMD_WORD_PROGRAM;
 
    // 3. Execute
    ESTAT = ESTAT_CBEIF_MASK;
 
    // 4. Wait for Command to complete
  while(((ESTAT & ESTAT_CBEIF_MASK) == 0) &&
        ((ESTAT & ESTAT_PVIOL_MASK) == 0) &&
        ((ESTAT & ESTAT_ACCERR_MASK) == 0)   ){};

    SET_PIN_HIGH( DEBUG0_PORT, DEBUG0_PIN);
 
    // B2. Write 2 Bytes -------------------------------------------
    // Second Write
  
    // 1. Write Adress and data
    ptr_ee_adr = (uWord * near) (adr+2);
    // Second 2 Bytes of value
    *ptr_ee_adr = *(((uWord *)(value))+1);
 
    // 2. Write CMD
    ECMD = ECMD_WORD_PROGRAM;
 
    // 3. Execute
    ESTAT = ESTAT_CBEIF_MASK;

    SET_PIN_LOW( DEBUG0_PORT, DEBUG0_PIN);
 
 // 4. Wait for Command to complete
  while(((ESTAT & ESTAT_CBEIF_MASK) == 0) &&
        ((ESTAT & ESTAT_PVIOL_MASK) == 0) &&
        ((ESTAT & ESTAT_ACCERR_MASK) == 0)   ){};

    SET_PIN_HIGH( DEBUG0_PORT, DEBUG0_PIN);
  
 // Now Wait for all commands to finish
  while(((ESTAT & ESTAT_CCIF_MASK) == 0) &&
        ((ESTAT & ESTAT_PVIOL_MASK) == 0) &&
        ((ESTAT & ESTAT_ACCERR_MASK) == 0)   ){};
  
    SET_PIN_LOW( DEBUG0_PORT, DEBUG0_PIN);
   
//to conifrm setting only    putchar(ECLKDIV);
   

    // Check if Error
    if(ESTAT_ACCERR || ESTAT_PVIOL)
    {
      return(EEPROM_FAILED);
    }
    else
    {
      // C. Check if data written correctly ------------------------
      if ((*value) == (*((uLong * near) adr)))
      {
        return(EEPROM_OK);
      }
      else
      {
        return(EEPROM_FAILED);
      }
    }
  } /* end of address check */
} /* end Write_EEPROM_sector */

Outcomes