Inline assembler ISR for all standard midrange devices

This forum handles questions and discussions concerning Microchip’s 8-bit compilers, assemblers, linkers and related tools.

Inline assembler ISR for all standard midrange devices

Postby Ian.M » Fri Jul 25, 2014 2:07 am

The original was developed for HiTech C for PIC10/12/16 v9.83 and ported to an early XC8 version. I've tidied it up a bit for xc8 v1.32 by removing the reference to the depreciated caspic.h and the need to use absolute addressing. Instead it now uses address qualifiers for the bank selection that *MUST* be enabled in the project's compiler options.

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
Ian.M
Verified identity
 
Posts: 94
Joined: Wed May 28, 2014 12:47 am
PIC experience: Professional 1+ years with MCHP products

Re: Inline assembler ISR for all standard midrange devices

Postby Ian.M » Wed May 25, 2016 8:41 am

The FNCALL directive has been depreciated in recent XC8 compiler versions and the line using it should be removed from the above code. All that is needed to prevent the optimiser removing the ISR is the GLOBAL line. See http://www.microchip.com/forums/m899466.aspx for an explanation by Mad_c (Jeff from the XC8 ex-HiTech compiler team).
Ian.M
Verified identity
 
Posts: 94
Joined: Wed May 28, 2014 12:47 am
PIC experience: Professional 1+ years with MCHP products


Return to MPLAB XC8

Who is online

Users browsing this forum: No registered users and 1 guest

cron