My eventual goal is to be able to modify the serial passcode and censorship control words at will, but I'm having trouble getting there. I've tried following the AN3787 document's example code. This exact same type of approach worked on various normal flash blocks, but is crashing when I try to access the shadow blocks (I've tried both A and B).
/* enable shadow space */
FLASH.LML.R = LOW_ADDR_KEY;
FLASH.LML.R = LOW_ADDR_SR_UNLOCK;
FLASH.SLL.R = S_LOW_ADDR_KEY;
FLASH.SLL.R = LOW_ADDR_SR_UNLOCK;
/* step1. erase shadow row */
FLASH.MCR.B.ERS = 1;
W32(SHADOW_ADDRESS, 0x0); //interlock write
FLASH.MCR.B.EHV = 1;
FLASH.MCR.B.EHV = 0; //clear EHV
FLASH.MCR.B.ERS = 0; //clear ERS
Specifically, when I'm debugging, the program exits at the interlock write for erasing the shadow row, and ends up at a random RAM address executing no code. What could be causing this?
If you have correct addresses and keys then your sequence is right.
I would like to warn you censorship is very sensitive thing. It is needed to use it very carefully, because an inappropriate usage can lead in making the device useless. If you accidentally erase shadow flash following by reset there is no chance to recover it (unless it had been though about before).
If your device is accidentally censored there is no way how to unlock it and everything you can do is to order new sample, and re-solder it instead of the censored one.
I am attaching example code. There are two examples in the package, first censores the device with password 0xFEEDFACECAFEBEEF, second un-censores the device (its lauterbach script enables debug of a censored device how it is described in attached pdf document).
Regarding your issue - problems can be caused by enabled data cache or enabled interrupts (both needs to be disabled before flash erase sequence).
Thanks David, I'll have a look at your example code. I'm having some trouble figuring out how to disable the data cache though - I've tried a few inline assembly commands since the documentation only mentioned using mtspr and mfspr to access the register, but haven't had any luck with it. Could you show me an example of how to disable the cache and interrupts?
Edit - quick update; I had thought the assembly I wrote wasn't working, but according to my debugging view of the registers, the data cache has been successfully disabled. Here's what I tried:
// disable data cache
// put config register in R1
asm(" mfspr r1, 1010");
// get mask 0xFFFE into R2
asm(" addi r2, 0, 0xFFFE");
// apply mask, store result in R2
asm(" and r2, r1, r2");
// push R2 into SPR
asm(" mtspr 1010, r2");
// disable interrupts
FR.GIFER.R = 0x00u;
However, if this is the right way to go about disabling cache and interrupts, the program is still crashing during any kind of shadow block access.
I got it all sorted out. I'm connecting to the chip with a Greenhill debugger, and in my .mbs script I had to redefine the size of the flash memory. Basically the debugger thought I was going out of memory range with the write operation and killed the program.