MC9S12DP512 EEprom

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

MC9S12DP512 EEprom

1,471 Views
tomst
Contributor I

I’m experiencing an EEprom fault using MC9S12DP512 where seemingly random addresses get erased after 2 or 3 years of use typically. I originally thought this was because the memory location was wearing out, but this is happening in locations where the EEprom is written to just once in the lab when first programmed. After we manually reset the data in the location, it will retain the data for about 6 weeks.

What external factors could affect the EEprom in this way? Ie. power supply, oscillator, decoupling?

 

Any help would be greatly appreciated.  

Labels (1)
0 Kudos
5 Replies

968 Views
lama
NXP TechSupport
NXP TechSupport

Hi,

Do you mean flash eeprom or eeprom?

What do you mean by erased? Erased status is 0xFF (charged cap.).

Main factors are temperature, correctly set flash machine frequency, correct bus clock.

In the case of flash eeprom it is necessary to clear flags in all blocks before E/W a word...

for(err=0;err<4;err++) { FCNFG_BKSEL = err; FSTAT=0x30; }    // PVIOL=ACERR=0

or

            ;erase error flags in all blocks
            MOVB FCNFG,temp       ; store FCNFG
            
            LDAA FCNFG            ; get FCNFG
            LDAB #FLASHblocks     ; loop constant
FES1:   
            DECB                  ; calculate block in loop
            ANDA  #$F0            ; mask block in FCNFG
            ABA                   ; write block to FCNFG
            STAA  FCNFG           ;
            MOVB  #$30,FSTAT      ; errase error flags in given block
            TSTB
            BNE   FES1

Best regards,

Ladislav

0 Kudos

968 Views
tomst
Contributor I

Thanks for your message Ladislav.

It’s Flash EEprom and the memory sectors are reset to 0xFFFF. Below is part of a memery dump where we have lost data at 0404 to 0407:

                               vvvv  vvvv (been reset)
0400: FFBF 163F FFFF FFFF 3032 3335 FFFF FFFF
                                                                    ^^ ^^    ^^ ^^ (unused)
0410: FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
0420: FFFF FFFF FFFF FFFF FFFF FFFF 8025 FFFF       
0430: 01AD 3EAB 541B E50A 0ED4 FFFF FFFF FFFF                              

Below is the function we use to write one word to the flash EEprom:

; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
EEWRITE: ; EEPROM[X]:=D; 1 WORD, X is preserved

; Note can only write aligned WORDs, i.e. EVEN addresses,
; and can only erase 4 bytes, i.e. address [1:0] ignored for erase
; Time to erase 4byte EEPROM sect {or 512k Flash sector} 22ms
; To prog 1 WORD 55us, to prog subsequent WORD 22us
; ** measured as 23ms proc !!!
; 16MHz OSCCLK{XTAL} /8 {b6} /(10d+1) = 182kHz NVMclk {Eclk of Fclk}
; MOVB #4AH,ECLKDIV ; EEPROM clock divider

; Method is to copy make stack of 2 WORDS, one of them being new, and one being
; copy of original. Then erase the 4 bytes, then write 2 WORDs back.

; Stack is to be:-

; <address>
; <lower WORD>
; <upper WORD>

; ----------------------------
; Example of usage ...
;
; LDX #TestEE1 ;^TestEE1
; LDD #12ABH ; WORD to write
; JSR EEWRITE ; EEPROM[X]:=D {TestEE1:=12ABH}
;
; LDD TestEE1 ; Check written
; JSR DISPHEX4

; ----------------------------

      PSHX                                       ; preserve
      PSHD                                       ; save data to write
      PSHD                                       ; twice {one will be wrong !}

; Make address even if not

      TFR X,D                                   ; D:=X
      ANDB #0FEH                           ; clr lsb
      PSHD                                       ; store real address
      ANDB #0FCH                           ; clear d1 to align to 4 byte sector 
      TFR D,X                                   ; X is ^ low end of the 4 byte sector to write

; ? which word are we requested to change ?
      CPX 0,SP                                 ; compare aligned address with stacked value
      BEQ EEw01                             ; lower WORD needs to change

; so, upper WORD to change
      LDD 0,X                                    ; get original lower WORD
      STD 2,SP                                 ; and save in stack
      BRA EEw02

EEw01:                                           ; lower word to change
      LDD 2,X                                    ; get original upper WORD
      STD 4,SP                                 ; change upper word in stack

EEw02:
      PULD                                        ; address clear off stack

; ready to erase/prog 4 bytes

      MOVB #30H,ESTAT                 ; clr PVIOL & ACCERR
      PULD                                       ; retrieve lower data WORD
      STD 0,X                                   ; M[X]:=D setup to write

; commands are 20 - prog WORD; 40 erase 2 WORDs; 41 erase all EEPROM
; 60 - ERASE 2 WORDs then prog 1 WORD ..... in same operation

      MOVB #60H,ECMD                ; command 60 to erase then write
      MOVB #80H,ESTAT                ; clr CBEIF bit
      BRCLR ESTAT,80h,*              ; wait for CBEIF before next write !
      PULD                                      ; retrieve upper data WORD
      STD 2,X                                  ; M[X+2]:=D
      MOVB #20H,ECMD                ; command 20 to prog WORD
      MOVB #80H,ESTAT                ; clr CBEIF bit
      BRCLR ESTAT,80h,*              ; wait for buffer empty - this seems to be necessary
      BRCLR ESTAT,40h,*              ; wait for write complete before returning
      PULX                                      ; restore X
      RTS

; ***** End of EEWRITE SUBroutine *****

We also use a write 2 words to EEprom function but in essences it is the same just a larger stack.

Let me know if you need anymore details; I'm quite stuck on this one.

Thanks

Kind regards

Tom

0 Kudos

968 Views
lama
NXP TechSupport
NXP TechSupport

Hi,

The address 0400 is not flash EEPROM. It is EEPROM. Only to set terms.

Flash EPROM is the memory which usually stores code. It has larger sector size (512B or 1024B for S12 devices), less EW cycles,….

The EEPROM is memory usually used for data. It has smaller sector size (4B in S12 family devices), higher amount of E-W cycles,…

 

I do not know the setup of the INITRG, INITRM and INTEE registers. They are by default 0x00, 0x09,0x01 which places the memrie to following addresses.

Registers         0000~03FF                 size = 1kB
RAM               0800~3FFF                 size = 14kB
EEPROM        0000~0FFF                 size = 4kB (useable 0400~07FF, all other parts are overlapped by memories with higher priority)

Is suppose you use BUSCLK = 8MHz OSCCLK=16MHz => ECLKDIV = 0x4A which I can also see in your code.

!!! What I am missing is a safe period of time for writing to EEPROM to avoid an interrupt routine to read from EEPROM while it is written. It is forbidden to read while write if you do not want to have corrupted data.

The difference I use is for write finishing check.

You:   BRCLR ESTAT,80h,*              ; wait for CBEIF before next write !
Me:      CkStat3:
              ldab ESTAT
              BitB #mESTAT_CBEIF+mESTAT_CCIF  ;check command buffer empty status bit
              Beq  CkStat3

Moreover, if you check the data by IDE then you have to remove the window which reads the memory which is currently written. You have to avoid unexpected reading even by BDM.

However, I think it does not relate to an issue. The question is what were conditions for programming in lab. Lower programming frequencies can cause the memory cell is overloaded and data retention decreases. Higher programming frequencies, in opposite, cause either the EEPROM is not correctly erased or it is not correctly programmed or both together. Data retention is also decreased but the memory cell has correct quality.

Are you able to remember the conditions the EEPROM was originally programmed in lab?

Is it a problem of the only one device or you have observed it on more devices. (Could you send me entire text you can read on the top of the device)

Could I see schematic design of MCU environment to be sure it is OK before I suggest you to solve it as a quality incident. You can send it to me via technical support pages. Open a case, write correct part number and you can add “To Ladislav” to subject or description.

How to do it you can see in: https://community.nxp.com/docs/DOC-329745

 

The code I used for explanation with another customer for similar MCU many years ago. Only to show you if you want to compare.

;_______________________________________________________________________________

; - Example present erase sector and write word to the EEPROM

; - Before write it checks:

;                    * alignment (2B)

;                    * whwther sector is erased

; - Before sector erase it checks:

;                    * alignment (4B)

; - Variable err_code is used as a error return code

;_______________________________________________________________________________

 

; export symbols

            XDEF Entry            ; export 'Entry' symbol

            ABSENTRY Entry        ; for absolute assembly: mark this as application entry point

 

; include derivative specific macros

            INCLUDE 'mc9s12dg256.inc'

 

;_______________________________________________________________________________

; definitions

;_______________________________________________________________________________

ROMStart         EQU   $4000            ; absolute address to place my code/constant data

 

ERR_OK:          EQU   $0               ; OK

ERR_RANGE:       EQU   $1               ; Parameter out of range. (not alligned sector 4B; data 2B))

ERR_BUSY:        EQU   $2               ; Device is busy.

ERR_NOTAVAIL:    EQU   $3               ; Requested value or method not available.

ERR_NOTERASED:   EQU   $4               ; Requested address is not erased

;_______________________________________________________________________________

; variable/data section

;_______________________________________________________________________________

            ORG RAMStart

;_______________________________________________________________________________

 

EE_data          DS.W  1                ; data to be written

err_code         DS.B  1                                                      ; return value from flash erase/write functions

 

 

CCRbackup        DS.B  1                                                      ; CCR backup value

 

p_EE_address:

EE_address       DS.W  1                ; address for sector erase or data write

 

p_EE_lngdata:

EE_lngdataH      DS.W  1                ; long data to write

EE_lngdataL      DS.W  1                ; long data to write

;_______________________________________________________________________________

; code section

;_______________________________________________________________________________

            ORG   ROMStart

;_______________________________________________________________________________

; main loop

;_______________________________________________________________________________

Entry:

       ;--- memory mapping ------------------

  ;MOVB #$0,INITRM                       ; INITRM = 0x00; Set the RAM map position     0x0000~0x2FFF

  ;MOVB #$31,INITEE                      ; INITEE = 0x31; Set the EEPROM map position  0x3000~0x3FFF, EEON=1

  ;MOVB #$0,$INITRG                      ; INITRG = 0x00; Set the Reg map position     0x0000~0x03FF

  ;NOP;                                  ; recommended

  ;LDS   #$3000                          ; initialize stack on the top of RAM

      

       ;--- reset default memory mapping ----

  ;INITRG = 0x00; Set the Reg map position     0x0000~0x03FF

  ;INITEE = 0x01; Set the EEPROM map position  0x0000~0x0FFF, EEON=1 => visible 0x0400~0x0FFF

  ;INITRM = 0x09; Set the RAM map position     0x1000~0x3FFF

  LDS   #$4000                               ; initialize stack on the top of RAM

  ;--- EEPROM clock---------------------

       MOVB  #$4A,ECLKDIV                    ; ECLKDIV = 0x4A, eeprom clock prescaler; OSCCLK = 16MHz BUSCLK=8MHz

 

  ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

loopCTM:

  ; no EEPROM range checking

  ; no 4B allignment checking

  ; no EEPROM busy checking

  ; no protection checking

  ; no error checking      

  ; default memory map (no remapping)  - part of visible EEPROM is at 0400~0FFF

  ; Y *data

  ; X *addr

 

  ;-------------------------------------

  ;your approach X stores destination address Y stores pointer to data

  MOVW #$0400,EE_address                                                 ; prepare address for sector modify function

  MOVW #$7654,EE_lngdataH                                                ; prepare data for sector modify function

  MOVW #$3210,EE_lngdataL                                                ; prepare data for sector modify function

 

  LDX #p_EE_address

  LDY #p_EE_lngdata

 

  JSR WriteLong                          ; corrected your approach

  ;-------------------------------------

; my approach parameters are EE_address, EE_lngdataH, EE_lngdataL

 

  MOVW #$0404,EE_address                                                 ; prepare address for sector modify function

  MOVW #$DEAD,EE_lngdataH                                                ; prepare data for sector modify function

  MOVW #$D0D0,EE_lngdataL                                               ; prepare data for sector modify function

 

  JSR WriteLong1                        

   

  JMP loopCTM

  ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

loop:

       ;--- Erase sector --------------------

  MOVW #$0400,EE_address                                                 ; prepare address for write function

       JSR  EraseSector                      ; erase sector at address $0400

       ;--- Write word to eeprom ------------

  MOVW #$0400,EE_address                                                 ; prepare address for write function

  MOVW #$1234,EE_data                   ; prepre data for write function

       JSR  WriteWord                        ; write word to the eeprom without checking address and EEPROM erased

       ;--- check error code and written data

       ;...

       ;...

       ;...

       ;--- Write word to eeprom ------------

  MOVW #$0402,EE_address                                               ; prepare address for write function

  MOVW #$5678,EE_data                   ; prepre data for write function

       JSR  WriteWord                        ; write word to the eeprom without checking address and EEPROM erased

       ;--- check error code and written data

       ;...

       ;...

       ;...

       ;--- loop forever---------------------

  JMP loop                              ; endless loop

 

;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

WriteLong:

Wrt1stWord:

  ; get CCR disable interrupts to avoid EEPROM reading while EEPROM under E/W

  TPA  

  STAA  CCRbackup

  SEI  

  ;....................................

  ; erase sector and write first word

  ;....................................

  MovB #$30,ESTAT                      ; Clear error flags

  LdD  0,Y                             ; prepare higher word for wrriting

  LDX  0,X

  StD  0,X

  MovB #$60,ECMD                       ;sector modify command

  MovB #$80,ESTAT                      ;start command

CkStat:

  LdaB ESTAT

  BitB #mESTAT_CBEIF+mESTAT_CCIF       ;check command buffer empty status bit

  Beq  CkStat

  ;....................................

  ; write second word

  ;....................................

Wrt2ndWord:

  LdD  2,Y                             ; get lower word for writing

  INX

  INX

  StD  X                               ; store it to next address

  MovB #$20,ECMD                       ; write a word command

  MovB #$80,ESTAT                      ;start command

CkStat1:

  LdaB ESTAT

  BitB #mESTAT_CBEIF+mESTAT_CCIF       ; check for all commands complete

  Beq  CkStat1

  ;....................................

  ; RESTORE_CCR;

  LDAA  CCRbackup

  TAP  

  ;....................................

  RTS

 

 

 

;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

WriteLong1:

  PSHD                                ; store what modified

  PSHX 

  ; get CCR disable interrupts to avoid EEPROM reading while EEPROM under E/W

  TPA  

  STAA  CCRbackup

  SEI  

  ;....................................

  ; erase sector and write first word

  ;....................................

  MovB #$30,ESTAT                      ; Clear error flags

  LDX   EE_address               

  LDD   EE_lngdataH

  STD   0,X

  MovB #$60,ECMD                       ;sector modify command

  MovB #$80,ESTAT                      ;start command

CkStat3:

  LdaB ESTAT

  BitB #mESTAT_CBEIF+mESTAT_CCIF       ;check command buffer empty status bit

  Beq  CkStat3

  ;....................................

  ; write second word

  ;....................................

  LDD   EE_lngdataL                    ; get lower word for writing

  INX

  INX

  StD  X                               ; store it to next address

  MovB #$20,ECMD                       ; write a word command

  MovB #$80,ESTAT                      ;start command

CkStat4:

  LdaB ESTAT

  BitB #mESTAT_CBEIF+mESTAT_CCIF       ; check for all commands complete

  Beq  CkStat4

  ;....................................

  ; RESTORE_CCR;

  LDAA  CCRbackup

  TAP  

  ;....................................

  PULX                                 ;restore

  PULD 

  RTS

 

 

 

;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

 

;_______________________________________________________________________________

; WriteWord

; inputs: EE_address

;                             EE_data  

;      output: err_code    

;_______________________________________________________________________________

WriteWord:

    PSHD 

    PSHX 

 

    LDD   EE_address                ; check alignment (4B)

    LDX   #$2

    IDIV

    CPD   #$0                       ; if != $0 => error

    BEQ   WriteWord_LBL6

    MOVB  #ERR_RANGE,err_code       ;return ERR_RANGE;

    BRA   WriteWord_LBL2

 

WriteWord_LBL6:                     ; check whether word is errased

    LDX   EE_address                ;*(volatile word *) AddrRow = Data16; // Array address and program data  

    LDD   0,X

    CPD   #$FFFF                    ; if != $FFFF => error

    BEQ   WriteWord_LBL5

    MOVB  #ERR_NOTERASED,err_code   ;return ERR_BUSY;      // If yes then error

    BRA   WriteWord_LBL2

 

WriteWord_LBL5:

    BRSET ESTAT,#128,WriteWord_LBL1 ;if (ESTAT_CBEIF == 0) // Is command buffer full ?

    MOVB  #ERR_BUSY,err_code        ;return ERR_BUSY;      // If yes then error

    BRA   WriteWord_LBL2

   

WriteWord_LBL1:

    MOVB  #$30,ESTAT                ;ESTAT = 0x30;         // Clear error flags

    LDX   EE_address                ;*(volatile word *) AddrRow = Data16; // Array address and program data  

    LDD   EE_data

    STD   0,X

 

    MOVB  #$20,ECMD                 ;ECMD = 0x20;          // Word program command

    BSET  ESTAT,#$80                ;ESTAT_CBEIF = 1;      // Clear flag command buffer empty

 

    BRSET ESTAT,#$20,WriteWord_LBL3 ;if ((ESTAT_PVIOL == 1)||(ESTAT_ACCERR == 1)) // Is protection violation or acces error detected ?

    BRCLR ESTAT,#$10,WriteWord_LBL4

 

WriteWord_LBL3:

    MOVB  #ERR_NOTAVAIL,err_code    ;return ERR_NOTAVAIL;  // If yes then error

    BRA   WriteWord_LBL2

 

WriteWord_LBL4:

    LDAB  ESTAT                     ;while (EEPROM_BUSY);  // Wait for command completition

    ANDB  #192

    CMPB  #192

    BNE   WriteWord_LBL4

 

    MOVB  ERR_OK,err_code           ;return ERR_OK; 

 

WriteWord_LBL2:

    PULX 

    PULD 

    RTS  

;_______________________________________________________________________________

; EraseSector

; inputs: EE_address

;      output: err_code    

;_______________________________________________________________________________

EraseSector:

    PSHD 

    PSHX 

 

    LDD   EE_address                ; check alignment (4B)

    LDX   #$4

    IDIV

    CPD   #$0                       ; if != $0 => error

    BEQ   EraseSector_LBL5

    MOVB  #ERR_RANGE,err_code       ;return ERR_RANGE;

    BRA   EraseSector_LBL2

 

EraseSector_LBL5:

    BRSET ESTAT,#128,EraseSector_LBL1;if (ESTAT_CBEIF == 0) // Is command buffer full ?

    MOVB  #ERR_BUSY,err_code        ;return ERR_BUSY;      // If yes then error

    BRA   EraseSector_LBL2

   

EraseSector_LBL1:

    MOVB  #$30,ESTAT                ;ESTAT = 0x30;         // Clear error flags

    LDX   EE_address                ;*(volatile word *) AddrRow = Data16; // Array address and program data  

    LDD   #$FFFF                    ; dummy data

    STD   0,X

 

    MOVB  #$40,ECMD                 ;ECMD = 0x20;          // Word program command

    BSET  ESTAT,#$80                ;ESTAT_CBEIF = 1;      // Clear flag command buffer empty

 

    BRSET ESTAT,#$20,EraseSector_LBL3 ;if ((ESTAT_PVIOL == 1)||(ESTAT_ACCERR == 1)) // Is protection violation or acces error detected ?

    BRCLR ESTAT,#$10,EraseSector_LBL4

 

EraseSector_LBL3:

    MOVB  #ERR_NOTAVAIL,err_code    ;return ERR_NOTAVAIL;  // If yes then error

    BRA   EraseSector_LBL2

 

EraseSector_LBL4:

    LDAB  ESTAT                     ;while (EEPROM_BUSY);  // Wait for command completition

    ANDB  #192

    CMPB  #192

    BNE   EraseSector_LBL4

 

    MOVB  ERR_OK,err_code           ;return ERR_OK; 

 

EraseSector_LBL2:

    PULX 

    PULD 

    RTS  

;_______________________________________________________________________________

 

 

;**************************************************************

;*                 Interrupt Vectors                          *

;**************************************************************

            ORG   $FFFE

            DC.W  Entry           ; Reset Vector

Best regards,

Ladislav

0 Kudos

968 Views
tomst
Contributor I

Thanks Ladislav that is really useful and gave me a lot to think about.

The program can interrupt while there is an EEprom write in process, but it doesn't do any EEprom read or writes in the interrupt. We use the interrupt mainly for timing and CAN RX signals. Could the interrupt be affecting the EEprom?     

We program the MCU with a bootloader that has some basic functions first using PE micro mulitlink and noICE. Using some of the functions in the bootloader we can set things like serial number in EEprom (@0404 to 040B) and this is only done once in the lab via a RS232 interface and uses the EEwrite function I mentioned above. We can then load the main program in afterwards.

The eeprom fault has happened on about 14 devices out of about 400 that regularly use the eeprom. We tried replacing the processor on a bad board that was failing frequently but it made no difference (keeping the program the same). It had worked correctly for about 3 years, then got worse as time when on until it would fail overnight.

An device example is: MC9S12DP512MPVE 4L00M QQQG1317

I will send you the circuit diagrams in a ticket.

Thanks for your help.

Kind regards

Tom

0 Kudos

968 Views
RadekS
NXP Employee
NXP Employee

Hi Tom,

I am sorry, but Ladislav is now sick.

I just shortly check your conversation and received schematic and layout.

I didn’t found any obvious or potential issue at schematic and layout until now.

 

Interesting is your last statement about bootloader and programming serial number in EEprom (@0404 to 040B).

How did you manage enter bootloader mode and what steps are necessary prior bootloader jumps into programming routine (erase sector from 0x0404 and … )?

Is it possible that MCU unintentionally jumps into bootloader mode, automatically erase EEPROM sector with serial number and wait for data from SCI (since there is no valid communication, the serial number is not programmed)?

Have a great day,
Radek

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos