I've reviewed the MCU firmware code. Writing 4003h bytes as continous block seems to have been right.
STOP conditions
Sending STOP conditions anywhere inside of the 4000h byte block would abort flash writing, a STOP condition on LAST byte would "abort", too, but that might still work okay since it was the last byte anyways (I am not 100% sure if it would abort before or after the last byte, so it may be safer to send all bytes (including last byte) without stop condition).
Sending a STOP condition after the leading 3 bytes shouldn't be needed, and it would probably rather screw up things (or at least would make it much more difficult to safely send the following 4000h bytes). So, best don't use any STOP conditions at all.
Delays
A delay after the leading 3 bytes doesn't seem to be required. The 4000h-byte transfer function is "enqueued as callback" (but the normal I2C interrupt is disabled immediately upon receiving the 3-byte flash ID, so the databytes should safely arrive in the callback function, even if the callback got started a bit later than having sent the first data byte). Delays before/during flashing are probably automatically handled via SCL-hold on the I2C bus. So additional manual delays shouldn't be needed (and any LONG delays could be fatal because they would cause the MCU's watchdog to reboot during flashing).
So far, everything looks fine...
Uhm, but I've made a stupid mistake in my uploader when updating the new "HH:MM:SS",00h timestamps:
Code: Select all
mov r0,'q' ;new last byte for the "HH:MM:SS",00h timestamps
ldr r2,=mcu_image+0ff6h+8 ;\
mov r1,3000h ; store
strb r0,[r2,r1] ;[4FF6h+N-1000h] ; (3x)
strb r1,[r2,0Ah] ;[2000h+N-1000h] ;
strb r0,[r2] ;[0FF6h+N] ;/
That should have stored thrice "r0" (not "r1"). The "r1" was there because I had copied the check/compare code, and merely changed "ldrb" to "strb", without changing the "r1" register number... so well, it's been just lazyness.
The related bug on Nintendo's side is that their flash function does check ONLY the ID's at [4FF6h+N] and [1FF6h+N] (the latter one later getting swapped to [0FF6h+N]). But coincidentally, their flash function doesn't check [2000h+N], so the flash function continues with swapping the 4K at 01000h and 00000h (with proper error-detection, they would have instead wanted to restore the 12K backup from 5000h to 2000h).
What is happening now is that my uploaded code is neatly installed at 0000h (first 4K) and at 2000h (other 12K), but hangs because the boot procedure checks all three IDs, including the bugged one at [2000h+N].
At that point it should also restore the backup (and maybe it did actually do so). I think the problem there is that it does merely copy 12K from 5000h to 2000h (but forgets to swap the 4K at 00000h and 01000h, so the current firmware becomes a mixup of old+new version (and the backup also becomes a similar mixup of new+old version)).
Conclusion: The "strb r1" was lazy, and it was bad luck that I had written it to [2000h+N]. Writing wrong data to [4FF6h+N] or [0FF6h+N] instead of [2000h+N] would have probably triggered the intended error handling.
When avoiding that specific mistake...
I think that MCU flashing should be perfectly safe.
Or if it goes wrong... having more bricked consoles could be pretty valuable for drawing schematics. Especially the Old3DS mainboards with text layer would be pretty nice to have for that purpose. Just don't brick New3DS-XL's, because I have already done that myself ; )