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.
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
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,
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.
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,
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 ?!?!
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,
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.