- Code: Select all
#include <xc.h>
/*
* Assembly Interrupt framework for PIC16
*/
//Needs compiler option "--ADDRQUAL=require" on PIC16 with banked RAM and common RAM
static near unsigned char W_TEMP; // Save W register for ISR in shared bank
static bank0 unsigned char STATUS_TEMP; // Dont *really* care where others get saved
static bank0 unsigned char PCLATH_TEMP; // but they need to be in Bank 0
// Add ASMISR() to main()'s call graph so it doesn't get deleted by the optimiser
#asm
GLOBAL _ASMISR
FNCALL _main,_ASMISR
#endasm
void ASMISR(void) @ 0x0004
{
#asm
; Context saving for ISR
MOVWF _W_TEMP ; save off current W register contents
MOVF STATUS,W ; move status register into W register
CLRF STATUS ; force Bank 0 for ISR data - not needed if only one RAM bank
MOVWF _STATUS_TEMP ; save off contents of STATUS register
MOVF PCLATH,W ; move pclath register into W register
MOVWF _PCLATH_TEMP ; save off contents of PCLATH register
;------------------------------------------------------------------------------
; USER INTERRUPT SERVICE ROUTINE GOES HERE
;------------------------------------------------------------------------------
; Restore context before returning from interrupt
MOVF _PCLATH_TEMP,W ; retrieve copy of PCLATH register
MOVWF PCLATH ; restore pre-isr PCLATH register contents
MOVF _STATUS_TEMP,W ; retrieve copy of STATUS register
MOVWF STATUS ; restore pre-isr STATUS register contents
; no longer using Bank 0
SWAPF _W_TEMP,F
SWAPF _W_TEMP,W ; restore pre-isr W register contents
RETFIE ; return from interrupt
#endasm
}
void
main(void)
{
/* setup stuff */
OPTION_REG = 0b00000111;
T0IE = 1; // Enable interrupt on TMR0 overflow
GIE = 1; // Global interrupt enable
for(;;){
CLRWDT(); // Idly kick the dog
}
}
On a chip with only a single RAM bank that appears in all banks, simply remove the qualifiers near and bank0. On a chip with multiple RAM banks but no common RAM like the PIC16F874, you must allocate W_TEMP using absolute addressing + allocate 'shadows' for it at the same offset in each actual RAM bank. e.g.:
- Code: Select all
// Save W register for ISR in same location in all banks
static unsigned char W_TEMP @ 0x20; // Locate it at the bottom of bank 0
static unsigned char W_TEMP1 @ 0xA0; // reserve same location in bank 1