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!
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.
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?
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!
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.