Flash Update from in ISR

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Flash Update from in ISR

4,079 Views
rhb3
Contributor II
Hello,
 
I'd like to use flash to update variables that indicate abnormalities.  Consider the following:
 
----------8<-----------------------------
 
ISR(COP_internal_isr)
/*
 * Vector here for COP reset
 *
 *
 *
 *
 *
 *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 */
{
    signed char fl_retval;
    ++ram_COPcnt;
    // /* Update flash */
    /*lint -e{511} */
    fl_retval = Flash_Erase_Sector((unsigned int *far)0x3E8000);
    if (fl_retval == 1) {
        /*lint -e{511} */
        fl_retval = Flash_Write_Word((unsigned int *far)0x3E8000U, (unsigned int)ram_SWIcnt);
        /*lint -e{511} */
        fl_retval = Flash_Write_Word((unsigned int *far)0x3E8002U, (unsigned int)ram_COPcnt);
        /*lint -e{511} */
        fl_retval = Flash_Write_Word((unsigned int *far)0x3E8004U, (unsigned int)ram_UimpInstrcnt);
    }
}
ISR(SWI_isr)
/*
 * Vector here for the software interrupt.  NOTE: Unused flash is set to 0x3F
 * so if the program counter (PC) is corrupted you could come here.
 *
 *
 *
 *
 *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 */
{
    ++ram_SWIcnt;
    /* Force reset by writing other than 0x55 followed by 0xAA to ARMCOP */
    (*(volatile unsigned char*)_COP_RST_ADR) = 0x33;
    (*(volatile unsigned char*)_COP_RST_ADR) = 0x37;
}
 
----------8<-----------------------------
 
...this assumes the SWI "forced reset" will trigger the COP ISR which I don't acutally know that to be the case.  Other than that, should there be any issues with this?  These flash functions work in main(); however, when I have a random while(1) injected for test only to create a COP ISR, the flash is not updated.  Any thoughts?
 
Thanks!
Labels (1)
0 Kudos
6 Replies

668 Views
imajeff
Contributor III
Hard to verify your code because you apparently use an ISR() macro and I don't know what it expands to. I also don't know what compiler you use (I use GCC so am not a CW junkie).

You didn't mention whether you considered to make certain no Flash routines will be called during Flash writes. It can be tricky using Flash-based ISR because they can be called at unexpected times during a Flash write.

I don't know why COP ISR would not be called, but have you tried some way to see if the ISR is being called? That would narrow down the problem.

Maybe because COP resets everything, you're not fully re-configuring hardware to write to Flash?
0 Kudos

668 Views
rhb3
Contributor II

Hard to verify your code because you apparently use an ISR() macro and I don't know what it expands to. I also don't know what compiler you use (I use GCC so am not a CW junkie).

*** ISR = #define ISR(x) __interrupt void x(void)

*** I know what you mean...stripping out Processor Expert is difficult.  I am using a new version of chc12 and ahc12 from CW.


You didn't mention whether you considered to make certain no Flash routines will be called during Flash writes. It can be tricky using Flash-based ISR because they can be called at unexpected times during a Flash write.

*** I'm new to these parts (MC9S12E64 & 128).  I'm only catching the SWI, Unimplemented instruction and COP.  I want to increment a RAM value in each of these and save to flash and force a reset.  As these interrupts can not be masked I'm uncertain if they could potentially interfere with a flash write.  That said, I ONLY write to flash in the COP ISR now but it appears not to work.


I don't know why COP ISR would not be called, but have you tried some way to see if the ISR is being called? That would narrow down the problem.

*** It's definitley being called but the flash doesn't appear to be changed after the write.  I come from more of an 8051 background where ISR code is typically context sensitive based on the register bank so I'm curious regarding the rules about what can and can't be called from an ISR and how it relates to reentrant functions, etc.

Maybe because COP resets everything, you're not fully re-configuring hardware to write to Flash?

*** I only configure the hardware one time at startup.  Then I update the local copies of the RAM counter variables aforementioned from the flash.  If a SWI, Unimplemented Inst or a COP occur I'm trying to inc the RAM variable, write to flash and restart.  Thanks for the post!

 

0 Kudos

668 Views
Steve
NXP Employee
NXP Employee
Hi,
 I think there is some confusion here and imajeff has identified the core problem. Let me try to clarify my (or your) confusion:
 The SWI ISR is an interrupt for the core and should violate the COP watchdog (assuming it's active) which will cause the MCU to reset. Assuming your hardware is set up correctly the MCU will fetch the COP reset vector and execute code there. Note that the COP is a hardware reset not an ISR so you need to consider what happens after it tries to program the flash. At the moment it looks like the ISR terminates which creates an RTI (return from interrupt) opcode but since you are not in an interrupt there is nowhere to return to. At this point I would expect the MCU to crash. Typically, users will perform some sort of COP recovery and then call the startup code to commence normal operation.

rhb3 wrote:

I don't know why COP ISR would not be called, but have you tried some way to see if the ISR is being called? That would narrow down the problem.

*** It's definitley being called but the flash doesn't appear to be changed after the write.  I come from more of an 8051 background where ISR code is typically context sensitive based on the register bank so I'm curious regarding the rules about what can and can't be called from an ISR and how it relates to reentrant functions, etc.


The CAN reset vector will be called assuming the reset pin recovers from the reset pulse correctly. If you have a load on the reset pin then the MCU may not be able to distinguish the COP reset (see the reset section in the manual).

rhb3 wrote:

Maybe because COP resets everything, you're not fully re-configuring hardware to write to Flash?

*** I only configure the hardware one time at startup.  Then I update the local copies of the RAM counter variables aforementioned from the flash.  If a SWI, Unimplemented Inst or a COP occur I'm trying to inc the RAM variable, write to flash and restart.  Thanks for the post!


This is likely the flash problem. As imajeff says you need to reconfigure the hardware after a reset and the COP causes a reset here.

You should be sure that the reset you force doesn't cause any problems - for example if you are changing flash or EEPROM when the reset occurs then you will lose data and possibly incorrectly program the NVM.

Is there a reason why you don't program the flash in the SWI ISR and then force a reset?


0 Kudos

668 Views
rhb3
Contributor II

Thanks for the help.  I think it is definitely my confusion!  Ok, so a COP is a reset that you can "hook" to run code.  So below is a snippet from my vectors.c file...

Code:

        RTI_isr,                       /* 56: RTI isr */        Unimplemented_ISR,                 /* 57 Default (unused) interrupt, address 0xFFF2 */        Unimplemented_ISR,                 /* 58 Default (unused) interrupt, address 0xFFF4 */        SWI_isr,                       /* 59: Software Interrup (0x3F flash default isr) */        Unimp_instr_isr,               /* 60 Default (unused) interrupt, address 0xFFF8 */        COP_internal_isr,              /* 61: internal COP */        Unimplemented_ISR,                 /* 62 Default (unused) interrupt, address 0xFFFC */        _EntryPoint                    /* Reset vector, address 0xFFFE */   };


So when exactly does COP_internal_isr execute?  I surmise it is before the reset actually occurs.  If so, it seems FCLK should stil be initialized and I could technically write a variable to flash in that "isr."  I plan to change my strategy a bit so that the SWI_isr and Unimp_instr_isr both become Unimplemented_ISR so that any unplanned vectoring basically forces a COP reset and I have a single variable in flash indicating how often that happens.  So Unimplemented__ISR will look something like:

Code:

    /* Force reset by writing other than 0x55 followed by 0xAA to ARMCOP */    (*(volatile unsigned char*)_COP_RST_ADR) = 0x33;    (*(volatile unsigned char*)_COP_RST_ADR) = 0x37;

 

I think this will force a COP reset immediately and COP_internal_isr will execute followed by a reset.  Does that sound correct?

As for the SWI, I'm still confused.  Suppose I fill unused flash with 0x3F and my PC is corrupted.  Would this then cause a vector to the handler SWI_isr (soon to be Unimplemented_ISR)?  If so, it would vector there and I could force a COP reset withing SWI_isr, correct?

Thanks!

0 Kudos

668 Views
imajeff
Contributor III
Steve is explaining this too, but...

Quite simply, COP is a "reset vector" just like the "start vector". When you turn the power on the first time, the MCU comes out of reset and starts at the start vector address. COP works in the same way, except when it comes out of reset because of COP, it starts at the COP vector. Therefore COP_internal_isr() executes after the reset.

The best approach to your problem is probably
  1. The COP "ISR" should first call function(s) which initialize the hardware as is done on normal startup before calling main(). Mine is __premain() but CodeWarrior is something like start().
  2. The COP "ISR" calls the function to write to Flash.
  3. The COP "ISR" continues normal execution by calling main(). This is because the COP routine is not an ISR, should not need defined as an ISR, and does not return.
0 Kudos

668 Views
Steve
NXP Employee
NXP Employee


rhb3 wrote:

Thanks for the help.  I think it is definitely my confusion!  Ok, so a COP is a reset that you can "hook" to run code.  So below is a snippet from my vectors.c file...

Code:

        RTI_isr,                       /* 56: RTI isr */        Unimplemented_ISR,                 /* 57 Default (unused) interrupt, address 0xFFF2 */        Unimplemented_ISR,                 /* 58 Default (unused) interrupt, address 0xFFF4 */        SWI_isr,                       /* 59: Software Interrup (0x3F flash default isr) */        Unimp_instr_isr,               /* 60 Default (unused) interrupt, address 0xFFF8 */        COP_internal_isr,              /* 61: internal COP */        Unimplemented_ISR,                 /* 62 Default (unused) interrupt, address 0xFFFC */        _EntryPoint                    /* Reset vector, address 0xFFFE */   };


So when exactly does COP_internal_isr execute?  I surmise it is before the reset actually occurs.  If so, it seems FCLK should stil be initialized and I could technically write a variable to flash in that "isr." 


Well the COP reset is the same as any other reset except that it is caused uniquely by the COP. This may be different to other processors that you have used but on S12 we have different reset vectors depending on what caused the reset. So the bottom three entries in your table are not interrupt vectors but reset vectors and they all mean that the MCU has already been completely reset. Any code that follows these three vectors must configure the MCU again. Think of the COP vector as the same as the _EntryPoint vector except that it was caused by the COP error. The normal use of the COP is to detect a software error but it can be used to force a reset if the user believes that some kind of system reset is needed.


I plan to change my strategy a bit so that the SWI_isr and Unimp_instr_isr both become Unimplemented_ISR so that any unplanned vectoring basically forces a COP reset and I have a single variable in flash indicating how often that happens.  So Unimplemented__ISR will look something like:

Code:

    /* Force reset by writing other than 0x55 followed by 0xAA to ARMCOP */    (*(volatile unsigned char*)_COP_RST_ADR) = 0x33;    (*(volatile unsigned char*)_COP_RST_ADR) = 0x37;

 

I think this will force a COP reset immediately and COP_internal_isr will execute followed by a reset.  Does that sound correct?


Per your table SWI_isr and Unimp_instr_isr are both interrupts so they could call this code which would cause a COP reset. However, you have multiple vectors set to Unimplemented_ISR and one of them is actually a reset vector for clock failure. I suggest if you want these interrupts to cause a system reset that you call it something like SystemReset_ISR and point the SWI and unimplemented instruction vectors to it.


As for the SWI, I'm still confused.  Suppose I fill unused flash with 0x3F and my PC is corrupted.  Would this then cause a vector to the handler SWI_isr (soon to be Unimplemented_ISR)?  If so, it would vector there and I could force a COP reset withing SWI_isr, correct?


SWI is a just a software way of causing interrupts. It's used for various reasons including debugging and for OS calls. If your program counter reaches a 0x3F opcode (SWI) it will jump to the code at SWI_isr and then cause a COP reset. Be sure to handle the COP reset as a starting point for your application.

0 Kudos