Michael Aeberhard

Problems Erase Flash Sectors

Discussion created by Michael Aeberhard on Mar 8, 2006
Latest reply on Aug 14, 2006 by James Williams
I am trying to erase all (well, most actually) of the Flash in the HCS12XDP512, but am having problems getting it to work right.  I am using the code from AN2720 to do the Flash operations (the relevant code is pasted at the bottom of this message).  What I want to do is erase page $FF (local address 0xC000-0xFFFF), and then the paged flash, $E0 through $FC, and then also page $FE.  For some reason, when I run the following code, it gets hung up (I try to halt the debugger to see where it hangs up, but it will not let me halt it, rather it goes straight back to running - have never had this happen).  But now if I comment out the line that erases the sector in $E0, the code works fine and it seems to erase correctly.  Does anyone see anything wrong with what I'm doing?  Just to test, I'm only erasing one sector in $E0, but eventually it'll be a loop that erases all sectors in all the pages.
//Erase local page FF
flash_start = (long) 0xFFC000;
flash_end = (long) 0xFFF000;
result = Flash_Erase_Block((unsigned int *far) flash_start, (unsigned int *far) flash_end);
if(result < 0) return result;
//Erase vector table
flash_start = (long) 0xFFFF10;
flash_end = (long) 0xFFFFFF;
result = Flash_Erase_Block((unsigned int *far) flash_start, (unsigned int *far) flash_end);
if(result < 0) return result;
//erase paged flash
flash_current = (long) 0xE08000;
result = Flash_Erase_Sector((unsigned int *far) flash_current);
if(result < 0) return result;
flash_current = flash_current + Flash_Sector_Size;
signed char Flash_Erase_Sector(unsigned int *far far_address)
 unsigned int* address;
 address = (unsigned int*)far_address; // strip page off
 if((unsigned int)address & 0x0001) {return Flash_Odd_Access;} // Aligned word?
 //if((unsigned int)address % Flash_Sector_Size !=0) {return Not_StartofSector_Error;}
 Flash.fstat.byte = Flash.fstat.byte & (ACCERR | PVIOL); // clear errors*/
 (*address) = 0xFFFF;/* Dummy store to page to be erased */
 if (Flash.fstat.bit.accerr) {return Access_Error;}
 if (Flash.fstat.bit.pviol) {return Protection_Error;}
 return 1;

signed char Flash_Erase_Block(unsigned int *far start_address, unsigned int *far end_address)
 unsigned int i;
 unsigned int count;
 unsigned long address;
 signed char ret_val;
 count = ((((unsigned int)end_address)-((unsigned int)start_address))/Flash_Sector_Size)+1;
 address = (unsigned long)start_address;
 for (i = 0;i < count;i++)
   ret_val = Flash_Erase_Sector((unsigned int *far)address);
   if (ret_val == Access_Error) {return Access_Error;}
   if (ret_val == Protection_Error) {return Protection_Error;}
   address = address+Flash_Sector_Size;
 return 1;
DoOnStack ASM:

; Local defines
                       ORG   $5000           
           CBEIF:      EQU   $80
           FSTAT:      EQU   $105
           FCMD:       EQU   $106
           CCIF:       EQU   $40
           PAGE_ADDR:  EQU   $30
                       xdef  DoOnStack
;* DoOnStack - copy SpSub onto stack and call it (see also SpSub)
;* De-allocates the stack space used by SpSub after returning from it.
;* Allows final steps in a flash prog/erase command to execute out
;* of RAM (on stack) while flash is out of the memory map
;* This routine can be used for flash word-program or erase commands
           pshb                          ;save B - PPAGE
           ldx     #SpSubEnd-2           ;point at last word to move to stack
SpmoveLoop: ldd     2,x-                  ;read from flash
           pshd                          ;move onto stack
           cpx     #SpSub-2              ;past end?
           bne     SpmoveLoop            ;loop till whole sub on stack
           tfr     sp,x                  ;point to sub on stack
           ldaa    #CBEIF                ;preload mask to register command
           call    0,x,00                ;execute the sub on the stack
           leas    SpSubEnd-SpSub,sp     ;de-allocate space used by sub
           pulb                          ;restore B
           rtc                           ;to flash where DoOnStack was called
;* SpSub - register flash command and wait for Flash CCIF
;* this subroutine is copied onto the stack before executing
;* because you can't execute out of flash while a flash command is
;* in progress (see DoOnStack to see how this is used)
          EVEN                          ;Make code start word aliened
           ldab    SpSubEnd-SpSub+2,sp   ;get PPAGE back
           stab    PAGE_ADDR             ;Store the PPAGE address
           tfr     ccr,b                 ;get copy of ccr
           orcc    #$10                  ;disable interrupts
           staa    FSTAT                 ;[PwO] register command
           nop                           ;[O] wait min 4~ from w cycle to r
           nop                           ;[O]
           nop                           ;[O]
           brclr   FSTAT,CCIF,*          ;[rfPPP] wait for queued commands to finish
           tfr     b,ccr                 ;restore ccr and int condition
           rtc                           ;back into DoOnStack in flash
Sorry for the long code listing, but I hope it saves time from not having to go look up the Application Note.

Message Edited by MichaelA on 03-08-200611:31 AM