Chip: MC9S12C128
I have a program that resides in both paged and unpaged memory. The program loads fine through the IDE. However, I am working on a CAN bootloader and being able to program the chip through a GUI using the P&E unit_12z libraries. Right now, I am having problems with erasing the second page of paged memory.
I do a mass erase command. That erases the unpaged memory and the first page of paged memory. That makes since as that is all that is in flash. I have tried to set the PPAGE register to 0x39 before a mass erase to erase the second page of paged memory but it doesn't have any effect. Is there something I am missing? How do you mass erase the paged memory?
The code snipet is:
// Mass erase flash | ||
write_data_byte(0x100, 0x49); | // set FCLKDIV clock divider | |
write_data_byte(0x103, 0); | // FCFNG select block 0 | |
write_data_byte(0x102, 0x10); | // set the WRALL bit in FTSTMOD to affect all blocks | |
write_data_byte(0x104, 0xFF); | // FPROT all protection disabled | |
write_data_byte(0x105, 0x30); | // clear PVIOL and ACCERR in FSTAT register | |
write_data_byte(0x106, 0x41); | // write MASS ERASE command in FCMD register | |
write_data_byte(0x105, 0x80); | // clear CBEIF in FSTAT register to execute the command | |
Sleep(2000); | // wait for command to complete |
// Reprogram Security byte to Unsecure state | ||
write_data_byte(0x100, 0x49); | // set FCLKDIV clock divider | |
write_data_byte(0x103, 0); | // FCFNG select block 0 | |
write_data_byte(0x104, 0xFF); | // FPROT all protection disabled | |
write_data_byte(0x105, 0x30); | // clear PVIOL and ACCERR in FSTAT register | |
write_data_word(0xFF0E, 0xFFFE); // write security byte to "Unsecured" state | ||
write_data_byte(0x106, 0x20); | // write MEMORY PROGRAM command in FCMD register | |
write_data_byte(0x105, 0x80); | // clear CBEIF in FSTAT register to execute the command | |
Sleep(2000); | // wait for command to complete |
// Mass erase flash | ||
write_data_byte(0x100, 0x49); | // set FCLKDIV clock divider | |
write_data_byte(0x103, 0); | // FCFNG select block 0 | |
write_data_byte(0x102, 0x10); | // set the WRALL bit in FTSTMOD to affect all blocks | |
write_data_byte(0x104, 0xFF); | // FPROT all protection disabled | |
write_data_byte(0x105, 0x30); | // clear PVIOL and ACCERR in FSTAT register | |
write_data_byte(0x30, 0x39); | // Set the PPAGE register to the next page | |
write_data_byte(0x106, 0x41); | // write MASS ERASE command in FCMD register | |
write_data_byte(0x105, 0x80); | // clear CBEIF in FSTAT register to execute the command | |
Sleep(2000); | // wait for command to complete |
bReturn = set_speed(); |
Solved! Go to Solution.
The code was actually fine. My error was in reading the values after the mass erase. Thanks to all!
The code was actually fine. My error was in reading the values after the mass erase. Thanks to all!
To speedup debugging and memory browsing, Hiwave debugger caches contents of flash memory. To see what really happens after you execute your erase and program routines, you need to go find Memory mapping dialog in Hiwave debugger and set some checkboxes to enable flash memory refreshing when you halt your MCU.
Mass erase, when it succeeds, erases all the flash on S12C. It can't erase just one flash page or some pages, but all the flash. Also, mass erase command won't erase anything in case any part of flash is write protected, and this makes it not useful for application in bootloader. Good bootloader should be never erased from flash memory, because bad things happen and MCU can be unpowered or reset while bootloader is erased, which will brick your product. Instead of mass erase you should erase your application code sector by sector.
You mass erase snipped has a bug. Even for erase command you need to write dummy data to flash array, like you do when programming security byte
write_data_word(0xFF0E, 0xFFFE); // write security byte to "Unsecured" state.
When using secor erase command, writing to particular flash memory sector specifies which sector of flash is going to be erased.
You can't unprotect flash when operating in normal mode, so you need to review this
write_data_byte(0x104, 0xFF); // FPROT all protection disabled
Don't forget that flash memory is not readable while any flash command is in progress, or when you are applying backdoor unsecure key. So you need to move part of your code to RAM and execute from there. Use forums search to find how to do that.
Thank you for the help! My problem is really two fold. 1) Programming everything (including bootloader) through the BDM using a GUI. 2) Writing the CAN bootloader.
This is mainly about #1. The code was originally this:
// Mass erase flash | ||
write_data_byte(0x100, 0x49); | // set FCLKDIV clock divider | |
write_data_byte(0x103, 0); | // FCFNG select block 0 | |
write_data_byte(0x102, 0x10); | // set the WRALL bit in FTSTMOD to affect all blocks | |
write_data_byte(0x104, 0xFF); | // FPROT all protection disabled | |
write_data_byte(0x105, 0x30); | // clear PVIOL and ACCERR in FSTAT register | |
write_data_byte(0x4000, 0xFF); | ||
write_data_byte(0x106, 0x41); | // write MASS ERASE command in FCMD register | |
write_data_byte(0x105, 0x80); | // clear CBEIF in FSTAT register to execute the command | |
Sleep(2000); | // wait for command to complete |
// Reprogram Security byte to Unsecure state | ||
write_data_byte(0x100, 0x49); | // set FCLKDIV clock divider | |
write_data_byte(0x103, 0); | // FCFNG select block 0 | |
write_data_byte(0x104, 0xFF); | // FPROT all protection disabled | |
write_data_byte(0x105, 0x30); | // clear PVIOL and ACCERR in FSTAT register | |
write_data_word(0xFF0E, 0xFFFE); // write security byte to "Unsecured" state | ||
write_data_byte(0x106, 0x20); | // write MEMORY PROGRAM command in FCMD register | |
write_data_byte(0x105, 0x80); | // clear CBEIF in FSTAT register to execute the command | |
Sleep(2000); |
The problem is that it is NOT erasing everything. I read the data bytes after this to verify. 0x400 to 0x7FFF is erased. 0xC000 to 0xFFFF is erased. 0x388000 to 0x38BFFF is erased. But 0x398000 to 0x39BFFF is NOT erased. It is erasing most but not all of the memory.
I have tried to do a sector erase too. That doesn't seem to work either. Could it be the chip? Or is there something special to erase the paged memory???
I'm still confused....
You are on the wrong track then. For secure application, bootloader should be programmed once and write protected.
^^ this last line is a new bug. You can't write to flash byte or misaligned word.
Instead of waiting here for fixed? amount of time here, you should wait for CCIF flag.
Did you check memory mapping in debugger? Isn't debugger fooling you showing you what was there in flash at initial flash programming over BDM? Again, mass erase on S12C128 either fails to erase anything, or erases everything.
It could be the same effect of debugger not refreshing memory views from device memory.
I really do appreciate the help. I am still having problems. I have changed what you suggested. It now reads:
/ Mass erase flash | ||
write_data_byte(0x100, 0x49); | // set FCLKDIV clock divider | |
write_data_byte(0x103, 0); | // FCFNG select block 0 | |
write_data_byte(0x102, 0x10); | // set the WRALL bit in FTSTMOD to affect all blocks | |
write_data_byte(0x104, 0xFF); | // FPROT all protection disabled | |
write_data_byte(0x105, 0x30); | // clear PVIOL and ACCERR in FSTAT register | |
write_data_word(0x4000, 0xFFFF); | ||
write_data_byte(0x106, 0x41); | // write MASS ERASE command in FCMD register | |
write_data_byte(0x105, 0x80); | // clear CBEIF in FSTAT register to execute the command | |
UINT8 cFSTAT = read_data_byte(0x105); while ((cFSTAT & 0xC0) == 0) { cFSTAT = read_data_byte(0x105); } |
// Reprogram Security byte to Unsecure state | ||
write_data_byte(0x100, 0x49); | // set FCLKDIV clock divider | |
write_data_byte(0x103, 0); | // FCFNG select block 0 | |
write_data_byte(0x104, 0xFF); | // FPROT all protection disabled | |
write_data_byte(0x105, 0x30); | // clear PVIOL and ACCERR in FSTAT register | |
write_data_word(0xFF0E, 0xFFFE); // write security byte to "Unsecured" state | ||
write_data_byte(0x106, 0x20); | // write MEMORY PROGRAM command in FCMD register | |
write_data_byte(0x105, 0x80); | // clear CBEIF in FSTAT register to execute the command | |
cFSTAT = read_data_byte(0x105); while ((cFSTAT & 0xC0) == 0) { cFSTAT = read_data_byte(0x105); } I am getting the same results. I am not going through the HIWAVE program. I am using the P&E multilink unit12z libraries. I have no idea what they do under the covers. After all this is over, I am reading the words out of flash and it is cleared for all memory addresses except for page 0x39. Any ideas?? |
There is procedure from datasheet:
Special single chip erase and unsecure sequence:
1. Reset into special single chip mode.
2. Write an appropriate value to the ECLKDIV register for correct timing.
3. Write 0xFF to the EPROT register to disable protection.
4. Write 0x30 to the ESTAT register to clear the PVIOL and ACCERR bits.
5. Write 0x0000 to the EDATA register (0x011A–0x011B).
6. Write 0x0000 to the EADDR register (0x0118–0x0119).
7. Write 0x41 (mass erase) to the ECMD register.
8. Write 0x80 to the ESTAT register to clear CBEIF.
9. Write an appropriate value to the FCLKDIV register for correct timing.
10. Write 0x00 to the FCNFG register to select Flash block 0.
11. Write 0x10 to the FTSTMOD register (0x0102) to set the WRALL bit, so the following writes
affect all Flash blocks.
12. Write 0xFF to the FPROT register to disable protection.
13. Write 0x30 to the FSTAT register to clear the PVIOL and ACCERR bits.
14. Write 0x0000 to the FDATA register (0x010A–0x010B).
15. Write 0x0000 to the FADDR register (0x0108–0x0109).
16. Write 0x41 (mass erase) to the FCMD register.
17. Write 0x80 to the FSTAT register to clear CBEIF.
18. Wait until all CCIF flags are set.
19. Reset back into special single chip mode.
20. Write an appropriate value to the FCLKDIV register for correct timing.
21. Write 0x00 to the FCNFG register to select Flash block 0.
22. Write 0xFF to the FPROT register to disable protection.
23. Write 0xFFBE to Flash address 0xFF0E.
24. Write 0x20 (program) to the FCMD register.
25. Write 0x80 to the FSTAT register to clear CBEIF.
26. Wait until the CCIF flag in FSTAT is are set.
27. Reset into any mode.
Anyway I would like to recommend “copy” mass erase procedure from PEmicro command file (in attachment).
I think that there could be some issue with FAIL flag in FSTAT register.