EEPROM writes taking too much time

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

EEPROM writes taking too much time

2,411 Views
dwhite
Contributor I

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 */

Labels (1)
0 Kudos
6 Replies

671 Views
kef
Specialist I

I don't know why it takes 40ms, but for me it is clear why erase seems to take <1us:

 

 // 4. Wait for Command to complete
  while(((ESTAT & ESTAT_CBEIF_MASK) == 0) &&
        ((ESTAT & ESTAT_PVIOL_MASK) == 0) &&
        ((ESTAT & ESTAT_ACCERR_MASK) == 0)   ){};
 
You are waiting ^^ here for command buffer empty, not for command complete. Since command FIFO has two stages, first while loop should take almost no time. Second while after buffering first word-write should take about 20ms (erase time).

0 Kudos

671 Views
dwhite
Contributor I

Thanks, Kef.

I noticed that the last two wait periods were both 55uS which is about right for the sector word write time (calculated 50.348uS based on my 181kHz clock).

 

So, it is actually the erase that is taking 42-44mS. At least now that makes some sense.

 

But, I still need to know why it is taking twice as long as it should.

 

I feel that I should have pointed out that this code has been working for years and we have never noticed any data failures even on these "bad" modules.

We never had any timing failures before either but we never measured the EE erase time to this level of detail until we had a new system component that fails due to the slow response time. We do have some modules that work because the failure threshold is right at 40mS.

 

So, I really need to understand the root cause of the time delay and variances between modules.

 

 

 

 

0 Kudos

671 Views
kef
Specialist I

That's interesting. Also 16MHz clock, also ECLKDIV set to 0x4A, bus clock derived from oscilator, no PLL, Vcc=3.3V. Measured EEPROM erase time:

 

0L15Y maskset, part date code 0626 - 70ms

0L15Y maskset, part date code 0704 - 34ms

0L15Y maskset, part date code 0651 - 22ms

 

I'm surprised.

0 Kudos

671 Views
dwhite
Contributor I

Kef,

Thank you very much for running the verification test for me. I was hoping someone would do this and prove that I'm not insane.

 

I think everyone on this forum needs to beware of this issue.

 

Do you know how to contact the factory to report this or for more information about this?

How do we determine if the erase time is truly correllated to the date code or just random?

 

FYI: The date codes on my parts are 0622 (43mS) and 0651 (30mS)

 

If I add an EEPROM erase time test to our production tester, are we going to be scrapping entire batches of chips and what threshold should I put on the test?

 

I know you can't answer these questions but I'm going to contact our distributor about this.

 

Thanks again,

Dan

 

 

0 Kudos

671 Views
kef
Specialist I

Dan,

 

thank you for making us aware.

 

Did you file service request for this? If not then then I think you should do it here https://www.freescale.com/webapp/servicerequest.create_SR.framework 

Of course you may prefer phone call, I don't know. You may check support page for available options.

 

I don't know if date code correlates with erase time. I just took 3 identical boards, all 3 using same maskset MCUs, runnig same EEPROM erase code. The only difference was the batch. 70ms sector erase is totally out of specifications, as is in 30ms case.

 

 

I wonder how erase time could be different. Is erase clock derived from some RC oscilator? Maybe erase procedure is switching read margins and continues until all bits at all margins read as erased? Is there some configuration EPROM that configures additional clock dividers? Would be nice to get it explained.

0 Kudos

671 Views
dwhite
Contributor I

Thanks, again.

 

I have submitted a service request and contacted my Freescale sales representative.

 

I will report back here with any findings that may help other users.

0 Kudos