- The S12ZVC flash or eeprom erase and progarm will cause CPU core Machine Exception when interruption of power supply.
Loss of power itself doesn't cause machine exception. Machine exception happens later when you power up again and try to read partially programmed locations which are not correctable by ECC.
- I want to use LVI ISR to stop flash or eeprom erase and progarm before lost power.
But I cannot find the way to stop flash or eeprom erase and program.
If power is lost it is already to late to stop flash/EEPROM command. LVI monitors VDDA and triggers when it is below ~4V. Though seems not explicitly stated, I think normal flash/EEPROM operation requires 5V. I would use BATS low voltage interrupt instead of LVI. Would be nice if you could provide that voltage regulator input voltage would drop from BATS low event to LVI event slower than it takes to erase flash/EEPROM sector, which would help providing that started NVM command completes and new one doesn't start.
You should also try handling machine exception, which happens reading partially programmed locations. Machine exception is unfriendly since return address is not easy to calculate. MMCPC points to instruction which could cause exception. If it was read data from bad ECC location, return to the same instruction could cause boot loop. It is also not known which EEPROM location had bad ECC. So I found it necessary to be ready for ME each time I read any piece of data from EEPROM. I handle EEPROM exception like this:
void ReadEepromByte(void *src, char *dst)
{
*dst = *(char*)(src); // read may lead to jump to ME handler
asm {
NOP // NOP is single byte instruction
NOP // amount of NOPs to replicate longest S12Z instruction
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
}
// ME handler may set EeepromECCUncorrectable byte variable
// If it's set, fixecc() will erase location with uncorrectable ECC and
// reset EeepromECCUncorrectable to 0.
fixecc(src, sizeof(char));
}
ME handler:
#pragma NO_ENTRY
#pragma NO_EXIT
static void MachineException(void)
{
asm{
LEA S, (-3,S) // reserve space for return address
PSH ALL // save all registers
LSL.B D0, MMCECH, #4 // inspect MMCECH.TGT register
CMP D0, #3 << 4 // MMCRCH.TGT == 3/*EEPROM*/?, is it read from EEPROM exception?
BNE L1
// yes, read from EEPROM exception
ST D0, EeepromECCUncorrectable // signal to fixecc() last read location
// had bad ECC
LD X, MMCPC // read PC of instruction which caused ME
LEA X, (11,X) // skip to one of NOPs in Readxxx() function
// longest instruction is 11 bytes. please fill location
// after EEPROM read access with NOPs
ST X, (26, S) // store return address
RTI // return to read EEPROM
L1:
}
// for everything else loop forever
for(;;)
{
int a;
a++;
if(!a)
DEBUGPIN25_PORT ^= DEBUGPIN25_PIN;
}
}