This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Erasing a sector from the internal memory block

Hello,

I have a problem when erasing the internal memory block on an XC167CS-32F microcontroller.

I can erase sectors 0, 1, 2, and 3 OK. Sector 4 fails to erase, but then sectors 5, 6, and 7 erase OK.

I can write to all of the sectors (with the exception of sector 3).

The Keil uVision 'Flash->Erase' instruction DOES manage to do the erase correctly, so I know that my device is OK - it is just down to something that I am doing wrong.

Is it possible that one of the sectors (sector 4) has become 'protected', and if so, how do I go about reseting things so that the sector is no longer protected !

Thanks for you help,

Simon May

  • If you think the sector is protected have you examined the value in the PROCON ro confirm this?

    In addition you can check the Flash Status Register (FSR) as you try to program or erase to help you understand if any errors are occurring.

  • Chris,

    Firstly, thanks for getting back to me, and thanks for the steer. This forum is definitely the most effective way of getting problems resolved.

    As for the actual issues, as a result of your post, I have run the code again - through the debugger - and have looked at the PROCON register (at address 0xFF'F004). The data at that address is 0x00 - and remains that for each loop through the execution.

    As for the FSR. The code that I have written carries out the erase instructions and then calls a function 'FSR_test' before returning to the calling function. The function FSR_test is as follows :

    static  __inline        bool    FSR_test                                ( void )
    {
            union   fsreg           fsr ;
    
            do {
                    fsr.v = FSR_read() ;            /* read the flash status register */
    
            } while ( fsr.b.busy ) ;                                /* wait whilst Flash is Busy */
    
            if ( fsr.b.oper || fsr.b.sqer || fsr.b.proer )
            {
                    /* we've read the status register, and it tells us that there's been an error */
    
                            /* reset the flash ROM module to read mode */
                    XC167Flash_reset_to_read() ;
    
                            /* ... failure */
                    return ( FALSE ) ;
    
            }
    
            if ( fsr.b.prog || fsr.b.erase )
            {
                    FSR_clear() ;                   /* clear the flash status register */
            }
    
            return ( TRUE ) ;
    
    }       /* FSR_test */
    

    Thanks again, Chris. Any further thoughts, much appreciated.

    Simon May

  • Hi Simon,

    Do you still have a problem to erase?

    If I were to write it, assuming this is an in-system reprogramming. I would do the following:

    1) Load the erase/write routines into PSRAM (from my boot code)
    2) Perform a Reset-To-Read command sequence
    3) Perform a Clear-Status command sequence
    4) Call the erase function in the PSRAM
    5) Perform an Erase command sequence (passing the SLOC which is the first (lowest) location within the target sector, e.g. C0'6000H for sector 3)
    6) Check for any errors and make sure both FSR.ERASE and FSR.BUSY are true
    7) Use a hardware timer to set a timeout that exceeds the maximum erase time
    8) Enter a loop waiting for both FSR.ERASE and FSR.BUSY to clear or if a timeout occurs
    9) Return from the erase routine with the status
    10) Repeat as needed or take error actions

    Just one other comment, I don't think there is anything wrong with using "C" for the flash routines as this is a user preference but I usually choose to write them in assembly and provide a "C" wrapper.

    -Chris

  • Chris,

    Just wanted to say thanks - you've given me some things to think about and try out.

    I will post back if I have any more insight into the problem.

    Simon

  • Since my last post, I have been working on this problem and now have some more information.

    The problem only occurs when erasing sectors which contain more than a trivial amount of data (approximately more than 1 KByte) - the problem can occur in any sector.

    This points to what I think Chris was hinting at - not waiting long enough for the erase to complete.

    The Infineon documentation for this controller does state that the FSR (0xFFF000) erase bit - FSR.ERASE - remains set to 1 for the duration of the erase. I think that this is probably incorrect.

    As far as I can tell, immediately on completion of the instruction to erase, the FSR is set to indicate both BUSY and ERASE, but almost immediately after that, the FSR is cleared again, by the hardware.

    The question then becomes how long to wait before checking what's going on. Chris suggests setting a hardware timer to wait for the maximum erase time. However, the Infineon in-application programming example has the interrupts explicitly disabled - and it is this code on which I have based my code.

    I am not sure which way to progress right now - I will try introducing a 'nop' loop to delay things to see if that has any effect.

    As ever - any ideas, please post !

    Thanks,

    Simon May

  • Have tried introducing a 'nop' loop which waits for more than 10 seconds - no joy !

  • I am not sure what is going on your setup. I made some code to erase and I don't see the same issue. The sector erase only takes about 220 msec to complete. I also preprogrammed the complete sector with a pattern of 0x55AA.

    You can use a hardware timer without interrupts. You just need to poll the ready flag.

      src = (U16 huge *)0xC08000;
      ResetToRead();
      ClearStatus();
      FlashErase(src);
      flashStatus = *(U16 huge *)(0xFFF000);
    

    With the FlashErase routine:

      T2CON     DEFR  0FF40H
      T2        DEFR  0FE40H
      T2IC      DEFR  0FF60H
      T2R       BIT   T2CON.6
      T2IC_IR   BIT   T2IC.7
    
    TIMEOUT_1SEC EQU 19531
    
    ;*****************************************************************************
    ;
    ; Function    :  void far FlashErase(unsigned int huge * src)
    ;
    ;             :  sector base address passed in registers 'R8/R9'
    ;******************************************************************************
      FlashErase  PROC  FAR
      PUBLIC  FlashErase
    
      MOV   T2,#TIMEOUT_1SEC
      BCLR  T2IC_IR
    
    ; *(unsigned int huge *) (0xC000AA) = 0x0080;
      MOV   R4,#080H
      EXTS  R9,#1
      MOV   000AAH,R4
    
    ; *(unsigned int huge *) (0xC00054) = 0x00AA;
      MOV   R4,#0AAH
      EXTS  R9,#1
      MOV   00054H,R4
    
    ; *src = 0x0033;
      MOV   R4,#033H
      EXTS  R9,#1
      MOV   [R8],R4
    
    FlashEraseActive:
      NOP
      NOP
      NOP
      NOP   ; delays to make sure Flash state machine starts
      EXTS  #0FFH,#1
      MOV   R4,0F000H
      JNB   R4.2,FlashEraseExit
    
      BSET  T2R ; start timer
    
    ;  wait for flash operation to finish or timeout
    FlashEraseDone:
      JB    T2IC_IR,FlashEraseExit ; jump on timeout
      EXTS  #0FFH,#1
      MOV   R4,0F000H
      AND   R4,#5
      JMP   cc_NZ,FlashEraseDone  ; wait for command to finsih
    
    FlashEraseExit:
      BCLR  T2R     ; stop timer
      RETS
    
      FlashErase  ENDP
    

  • I forgot to mention that the FlashErase routine is loaded from Flash to PSRAM and executed out of PSRAM.

  • Chris,

    Once again many thanks for your time and effort in answering my questions.

    I will not be able to get around to trying out the code that you suggest until Monday, now, but I did want to say thank you.

    All the best,

    Simon

  • Tues 29th Jan, 2008 - an update

    I have built a project with the code that Chris has shown, above.

    The project is built to work with the XC161CS-32F microcontroller with 256KBytes of internal flash ROM.

    The project works great when the flash ROM sector has been filled with data which is written to it by the application.

    In the case where we have a source code module which contains a constant definition which we load into the flash ROM sector, the erase continues to fail to work.

    From a simple point of view it would seem that the erase routine should not care whether the data in the sector to be erased has been put there by the application writing to it or by the initial programming of the flash ROM module by the Keil IDE via the JTAG ULINK box.

    Is it, however, the case that there IS a difference ?

    Any thoughts ?!?!

    Thanks,

    Simon May

  • Weds 30th January, 2008 - an update

    To recap :

    Code written which is loaded onto the internal flash ROM module of an XC161CS-32F microcontroller.

    Erase routines have been written which are stored in ROM but copied from ROM to RAM and executed from RAM.

    The erase routines work on sectors which have small amounts of data in.

    In the MAIN module, include a const declaration :

    const  char  A_str [ 100 ] = "this is a string" ;
    

    With the memory model, 'small', selected, this const gets located to address 0xC04000.

    When the erase routines are executed, they work fine.

    If the const declaration is changed to :

    const  char  A_str [ 200 ] = "this is a string" ;
    

    ie: if the size is changed from 100 to 200, the erase routines execute, cause no FSR error, but do not actually erase the sector.

    I am somewhat perplexed !

    Any thoughts are much appreciated,

    Thanks,

    Simon May

  • This issue has now been resolved.

    It turns out that the code that I have been using from the start HAS been working.

    The reason that I thought that it was NOT working was that the UVision debugger memory window was showing me that the flash ROM module contained data.

    I eventually used the Infineon memtool to download the contents of the internal flash ROM module and when I looked at the resultant data files, I could see that the internal flash ROM module HAD in fact been erased.

    Simon May