• AVR Freaks

Hot!PIC-AS interrupt example for K42 documentation issue?

Page: 12 > Showing page 1 of 2
Author
Jerry Messina
Super Member
  • Total Posts : 666
  • Reward points : 0
  • Joined: 2003/11/07 12:35:12
  • Status: offline
2021/01/28 05:58:53 (permalink)
5 (2)

PIC-AS interrupt example for K42 documentation issue?

I just was looking through the new version of 'XC8 PIC Assembler Users Guide for Embedded Engineers' which added chapter 8, with an example of using the multi-vector interrupt mode of the 18F47K42.
(ww1.microchip.com/downloads/en/DeviceDoc/50002994B.pdf),

In the example on page 38 is the following:

PSECT ivt,class=CODE,reloc=2,ovrld
ivtbase:
    ORG 31*2          ;timer 0 vector position
    DW tmr0Isr shr 2

PSECT code
tmr0Isr:
    bcf TMR0IF
    ;toggle the desired LED state
    movlw 1 shl (LEDState&7)
    xorwf LEDState/(0+8),c
    retfie f


If you read through the description below it you find two statements (emphasis added):

The ISR to handle the timer 0 in this example uses the label tmr0Isr and is located the code psect. This psect can be linked anywhere in the program memory, so no user-defined psect or special linker options are required.


and
The assembler's DW directive was used to place the address of the ISR, tmr0Isr, into the vector table. The device expects this address to be shifted right by 2 bits, so the assembler's shr operator was used to obtain this value.


It's my understanding the statement "tmr0Isr can be located anywhere in memory" is incorrect... it must be located at an address divisible by 4 so that the 'DW tmr0Isr shr 2' operation will load the correct address into the IVT.

Did I miss something in their explanation, or is their example wrong?


#1

35 Replies Related Threads

    mad_c
    Super Member
    • Total Posts : 1289
    • Reward points : 0
    • Joined: 2010/12/12 17:48:27
    • Location: Brisbane, Australia
    • Status: online
    Re: PIC-AS interrupt example for K42 documentation issue? 2021/01/28 13:27:21 (permalink)
    +2 (2)
    Jerry Messina
    It's my understanding the statement "tmr0Isr can be located anywhere in memory" is incorrect... it must be located at an address divisible by 4 so that the 'DW tmr0Isr shr 2' operation will load the correct address into the IVT.

    Did I miss something in their explanation, or is their example wrong?


    Well spotted.
     
    There should be a reloc=4 used with the psect that holds the ISR. The example uses the code psect, which is predefined by the assembler and has a reloc of 2. Since there is no predefined psect that is suitable, you would need to define your own, for example:

    PSECT textISR,class=CODE,reloc=4
    tmr0Isr:
    ...

    Such code then does not need any special linker options. When stating 'located anywhere in memory' it was assumed that the linker would still be abiding by any requirements of the psect (it's just that those requirements have to be correctly stated!).
     
    Thanks for pointing this out.
     
    Jeff.
    #2
    dan1138
    Super Member
    • Total Posts : 4242
    • Reward points : 0
    • Joined: 2007/02/21 23:04:16
    • Location: 0
    • Status: offline
    Re: PIC-AS interrupt example for K42 documentation issue? 2021/01/30 17:59:24 (permalink)
    0
    @mad_c(Jeff),
     
    I have read the data sheet abd I can see the parts that describe the IVT but cannot find any text that describes explicitly how an IVT entry is constructed.
     
    The data sheet DS40001919F-page 133, EXAMPLE 9-3: SETTING UP VECTORED INTERRUPTS USING MPASM shows a few vectors being setup. This example uses magic numbers and literal constants to locate code at specific addresses using the obsolete MPASM assembler.
     
    Can you point me to the documentation that describes the contents of 16-bit entry in the PIC18F47K42 Interrupt Vector Table(IVT) ?
     
    What this 16-bit value appears to be is bits 17:2 of the address of a function that must be located in the code space within the address range of 0x000000 to 0x03FFFC, and must be on a 4 byte boundary.
     
    If a statement like the above exists in the Microchip documentation for the PIC18F47K42 I cannot find it.
    #3
    1and0
    Access is Denied
    • Total Posts : 12086
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: PIC-AS interrupt example for K42 documentation issue? 2021/01/30 19:56:05 (permalink)
    0
    ...
     
    post edited by 1and0 - 2021/01/30 20:10:32
    #4
    1and0
    Access is Denied
    • Total Posts : 12086
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: PIC-AS interrupt example for K42 documentation issue? 2021/01/30 20:23:34 (permalink)
    0
    dan1138
    I have read the data sheet abd I can see the parts that describe the IVT but cannot find any text that describes explicitly how an IVT entry is constructed.
     
    The data sheet DS40001919F-page 133, EXAMPLE 9-3: SETTING UP VECTORED INTERRUPTS USING MPASM shows a few vectors being setup. This example uses magic numbers and literal constants to locate code at specific addresses using the obsolete MPASM assembler.
     
    Can you point me to the documentation that describes the contents of 16-bit entry in the PIC18F47K42 Interrupt Vector Table(IVT) ?
     
    What this 16-bit value appears to be is bits 17:2 of the address of a function that must be located in the code space within the address range of 0x000000 to 0x03FFFC, and must be on a 4 byte boundary.
     
    If a statement like the above exists in the Microchip documentation for the PIC18F47K42 I cannot find it.

    From Section 9.2.2 on page 116 of the said datasheet
     
        ISR Location = Interrupt Vector Table entry << 2
     
    This scheme creates a problem with relocatable mode. If the address of the ISR is to be relocatable, then the assembler cannot resolve the address until the linker assigns the address. Hence, the example in the datasheet must use magic numbers and literal constants (absolute addresses) because relocatable mode cannot compute >>2 or /4 on a relocatable symbol. This defeats the purpose of relocatable mode. In absolute mode, this issue is non-existent. ;)


    #5
    1and0
    Access is Denied
    • Total Posts : 12086
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: PIC-AS interrupt example for K42 documentation issue? 2021/01/30 21:14:22 (permalink)
    0
    ... and there is this comment from Example 9-3 on page 133:
    ; Each ISR routine must have a predetermined origin otherwise there will be
    ; an assembly error because the address is not determined until link time
    ; which is too late to do the divide by 4 math on the address.
    ; Predetermined addresses must be evenly divisible by 4.

    #6
    dan1138
    Super Member
    • Total Posts : 4242
    • Reward points : 0
    • Joined: 2007/02/21 23:04:16
    • Location: 0
    • Status: offline
    Re: PIC-AS interrupt example for K42 documentation issue? 2021/01/31 00:13:48 (permalink)
    0
    The linker used with MPASM is not able to do the same kind of manipulation of relocatable objects that the pic-as linker can perform.
     
    The PIC18F silicon implementation of an Interrupt Vector Table is lame for allowing only a 16-bit handle to select an address in a 20-bit address space by forcing the target to be on a 4 byte boundry.
     
    This choice also limits the location of the ISR handlers to be in the first 256K bytes of the code address space. At present the maximum code space for a PIC18F47Kxx device is 128K bytes. So this cannot be a problem yet.
     
    I cooked up this example using MPASM and MPLABX v5.35:
    ;
    ;   Filename:     main.asm
    ;   Date:         2021-January-30
    ;   Author:       dan1138
    ;   Target:       PIC18F47K42
    ;   Assembler:    MPASMWIN v5.87
    ;   IDE:          MPLABX v5.35
    ;
    ;   Files required from IDE:
    ;
    ;   P18f47k42.INC  Special Function Register definitions
    ;   18f47k42_G.LKR Generic linker script
    ;
    ;   Description:
    ;
    ;       Blink the LED on a PIC18F47K42 Curiosity Nano Board
    ;       using the timer and interrupts to control the flash period.
    ;
        list        p=18F47k42
        list        c=162,n=0
        list        r=dec
    ;
    ; PIC18F47K42 Configuration Bit Settings

    ; Assembly source line config statements

    #include "p18f47k42.inc"

    ; CONFIG1L
      CONFIG  FEXTOSC = RESERVED    ; External Oscillator Selection (Reserved (DO NOT USE))
      CONFIG  RSTOSC = HFINTOSC_1MHZ; Reset Oscillator Selection (HFINTOSC with HFFRQ = 4 MHz and CDIV = 4:1)

    ; CONFIG1H
      CONFIG  CLKOUTEN = OFF        ; Clock out Enable bit (CLKOUT function is disabled)
      CONFIG  PR1WAY = ON           ; PRLOCKED One-Way Set Enable bit (PRLOCK bit can be cleared and set only once)
      CONFIG  CSWEN = ON            ; Clock Switch Enable bit (Writing to NOSC and NDIV is allowed)
      CONFIG  FCMEN = ON            ; Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor enabled)

    ; CONFIG2L
      CONFIG  MCLRE = EXTMCLR       ; MCLR Enable bit (If LVP = 0, MCLR pin is MCLR; If LVP = 1, RE3 pin function is MCLR )
      CONFIG  PWRTS = PWRT_OFF      ; Power-up timer selection bits (PWRT is disabled)
      CONFIG  MVECEN = ON           ; Multi-vector enable bit (Multi-vector enabled, Vector table used for interrupts)
      CONFIG  IVT1WAY = ON              ; IVTLOCK bit One-way set enable bit (IVTLOCK bit can be cleared and set only once)
      CONFIG  LPBOREN = OFF         ; Low Power BOR Enable bit (ULPBOR disabled)
      CONFIG  BOREN = SBORDIS       ; Brown-out Reset Enable bits (Brown-out Reset enabled , SBOREN bit is ignored)

    ; CONFIG2H
      CONFIG  BORV = VBOR_2P45      ; Brown-out Reset Voltage Selection bits (Brown-out Reset Voltage (VBOR) set to 2.45V)
      CONFIG  ZCD = OFF             ; ZCD Disable bit (ZCD disabled. ZCD can be enabled by setting the ZCDSEN bit of ZCDCON)
      CONFIG  PPS1WAY = ON          ; PPSLOCK bit One-Way Set Enable bit (PPSLOCK bit can be cleared and set only once; PPS registers remain locked after one clear/set cycle)
      CONFIG  STVREN = ON           ; Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
      CONFIG  DEBUG = OFF           ; Debugger Enable bit (Background debugger disabled)
      CONFIG  XINST = OFF           ; Extended Instruction Set Enable bit (Extended Instruction Set and Indexed Addressing Mode disabled)

    ; CONFIG3L
      CONFIG  WDTCPS = WDTCPS_31    ; WDT Period selection bits (Divider ratio 1:65536; software control of WDTPS)
      CONFIG  WDTE = OFF            ; WDT operating mode (WDT Disabled; SWDTEN is ignored)

    ; CONFIG3H
      CONFIG  WDTCWS = WDTCWS_7     ; WDT Window Select bits (window always open (100%); software control; keyed access not required)
      CONFIG  WDTCCS = SC           ; WDT input clock selector (Software Control)

    ; CONFIG4L
      CONFIG  BBSIZE = BBSIZE_512   ; Boot Block Size selection bits (Boot Block size is 512 words)
      CONFIG  BBEN = OFF            ; Boot Block enable bit (Boot block disabled)
      CONFIG  SAFEN = OFF           ; Storage Area Flash enable bit (SAF disabled)
      CONFIG  WRTAPP = OFF          ; Application Block write protection bit (Application Block not write protected)

    ; CONFIG4H
      CONFIG  WRTB = OFF            ; Configuration Register Write Protection bit (Configuration registers (300000-30000Bh) not write-protected)
      CONFIG  WRTC = OFF            ; Boot Block Write Protection bit (Boot Block (000000-0007FFh) not write-protected)
      CONFIG  WRTD = OFF            ; Data EEPROM Write Protection bit (Data EEPROM not write-protected)
      CONFIG  WRTSAF = OFF          ; SAF Write protection bit (SAF not Write Protected)
      CONFIG  LVP = ON              ; Low Voltage Programming Enable bit (Low voltage programming enabled. MCLR/VPP pin function is MCLR. MCLRE configuration bit is ignored)

    ; CONFIG5L
      CONFIG  CP = OFF              ; PFM and Data EEPROM Code Protection bit (PFM and Data EEPROM code protection disabled)

    ; CONFIG5H
    ;
    ; Data in common bank
    ;
    ISR_DATA UDATA_ACS
    LEDState: res   1
    ;
    ;
    RES_VECT  CODE  0x0000          ; processor reset vector
            GOTO    START           ; go to beginning of program
    ;
    #define IVT_START 0x0008
    #define IVT_SIZE 82
    #define IVT_BRANCH_LOC (((IVT_SIZE*2)+IVT_START+3)>>2)
    ;
    IVT_TABLE CODE    IVT_START     ;
    ivt:
        DW  IVT_BRANCH_LOC+0        ; IVT 0  - Software Interrupt
        DW  IVT_BRANCH_LOC+1        ; IVT 1  - HLVD
        DW  IVT_BRANCH_LOC+2        ; IVT 2  - OSF
        DW  IVT_BRANCH_LOC+3        ; IVT 3  - CSW
        DW  IVT_BRANCH_LOC+4        ; IVT 4  - NVM
        DW  IVT_BRANCH_LOC+5        ; IVT 5  - SCAN
        DW  IVT_BRANCH_LOC+6        ; IVT 6  - CRC
        DW  IVT_BRANCH_LOC+7        ; IVT 7  - IOC
        DW  IVT_BRANCH_LOC+8        ; IVT 8  - INT0
        DW  IVT_BRANCH_LOC+9        ; IVT 9  - ZCD
        DW  IVT_BRANCH_LOC+10       ; IVT 10 - AD
        DW  IVT_BRANCH_LOC+11       ; IVT 11 - ADT
        DW  IVT_BRANCH_LOC+12       ; IVT 12 - C1
        DW  IVT_BRANCH_LOC+13       ; IVT 13 - SMT1
        DW  IVT_BRANCH_LOC+14       ; IVT 14 - SMT1PRA
        DW  IVT_BRANCH_LOC+15       ; IVT 15 - SMT1PWA
        DW  IVT_BRANCH_LOC+16       ; IVT 16 - DMA1SCNT
        DW  IVT_BRANCH_LOC+17       ; IVT 17 - DMA1DCNT
        DW  IVT_BRANCH_LOC+18       ; IVT 18 - DMA1OR
        DW  IVT_BRANCH_LOC+19       ; IVT 19 - DMA1A
        DW  IVT_BRANCH_LOC+20       ; IVT 20 - SPI1RX
        DW  IVT_BRANCH_LOC+21       ; IVT 21 - SPI1TX
        DW  IVT_BRANCH_LOC+22       ; IVT 22 - SPI1
        DW  IVT_BRANCH_LOC+23       ; IVT 23 - I2C1RX
        DW  IVT_BRANCH_LOC+24       ; IVT 24 - I2C1TX
        DW  IVT_BRANCH_LOC+25       ; IVT 25 - I2C1
        DW  IVT_BRANCH_LOC+26       ; IVT 26 - I2C1E
        DW  IVT_BRANCH_LOC+27       ; IVT 27 - U1RX
        DW  IVT_BRANCH_LOC+28       ; IVT 28 - U1TX
        DW  IVT_BRANCH_LOC+29       ; IVT 29 - U1E
        DW  IVT_BRANCH_LOC+30       ; IVT 30 - U1
        DW  IVT_BRANCH_LOC+31       ; IVT 31 - TMR0
        DW  IVT_BRANCH_LOC+32       ; IVT 32 - TMR1
        DW  IVT_BRANCH_LOC+33       ; IVT 33 - TMR1G
        DW  IVT_BRANCH_LOC+34       ; IVT 34 - TMR2
        DW  IVT_BRANCH_LOC+35       ; IVT 35 - CCP1
        DW  IVT_BRANCH_LOC+36       ; IVT 36 - reserved
        DW  IVT_BRANCH_LOC+37       ; IVT 37 - NCO
        DW  IVT_BRANCH_LOC+38       ; IVT 38 - CWG1
        DW  IVT_BRANCH_LOC+39       ; IVT 39 - CLC1
        DW  IVT_BRANCH_LOC+40       ; IVT 40 - INT1
        DW  IVT_BRANCH_LOC+41       ; IVT 41 - C2
        DW  IVT_BRANCH_LOC+42       ; IVT 42 - DMA2SCNT
        DW  IVT_BRANCH_LOC+43       ; IVT 43 - DMA2DCNT
        DW  IVT_BRANCH_LOC+44       ; IVT 44 - DMA2OR
        DW  IVT_BRANCH_LOC+45       ; IVT 45 - DMA2A
        DW  IVT_BRANCH_LOC+46       ; IVT 46 - I2C2RX
        DW  IVT_BRANCH_LOC+47       ; IVT 47 - I2C2TX
        DW  IVT_BRANCH_LOC+48       ; IVT 48 - I2C2
        DW  IVT_BRANCH_LOC+49       ; IVT 49 - I2C2E
        DW  IVT_BRANCH_LOC+50       ; IVT 50 - U2RX
        DW  IVT_BRANCH_LOC+51       ; IVT 51 - U2TX
        DW  IVT_BRANCH_LOC+52       ; IVT 52 - U2E
        DW  IVT_BRANCH_LOC+53       ; IVT 53 - U2
        DW  IVT_BRANCH_LOC+54       ; IVT 54 - TMR3
        DW  IVT_BRANCH_LOC+55       ; IVT 55 - TMR3G
        DW  IVT_BRANCH_LOC+56       ; IVT 56 - TMR4
        DW  IVT_BRANCH_LOC+57       ; IVT 57 - CCP2
        DW  IVT_BRANCH_LOC+58       ; IVT 58 - reserved
        DW  IVT_BRANCH_LOC+59       ; IVT 59 - CWG2
        DW  IVT_BRANCH_LOC+60       ; IVT 60 - CLC2
        DW  IVT_BRANCH_LOC+61       ; IVT 61 - INT2
        DW  IVT_BRANCH_LOC+62       ; IVT 62 - reserved
        DW  IVT_BRANCH_LOC+63       ; IVT 63 - reserved
        DW  IVT_BRANCH_LOC+64       ; IVT 64 - reserved
        DW  IVT_BRANCH_LOC+65       ; IVT 65 - reserved
        DW  IVT_BRANCH_LOC+66       ; IVT 66 - reserved
        DW  IVT_BRANCH_LOC+67       ; IVT 67 - reserved
        DW  IVT_BRANCH_LOC+68       ; IVT 68 - reserved
        DW  IVT_BRANCH_LOC+69       ; IVT 69 - reserved
        DW  IVT_BRANCH_LOC+70       ; IVT 70 - TMR5
        DW  IVT_BRANCH_LOC+71       ; IVT 71 - TMR5G
        DW  IVT_BRANCH_LOC+72       ; IVT 72 - TMR6
        DW  IVT_BRANCH_LOC+73       ; IVT 73 - CCP3
        DW  IVT_BRANCH_LOC+74       ; IVT 74 - CWG3
        DW  IVT_BRANCH_LOC+75       ; IVT 75 - CLC3
        DW  IVT_BRANCH_LOC+76       ; IVT 76 - reserved
        DW  IVT_BRANCH_LOC+77       ; IVT 77 - reserved
        DW  IVT_BRANCH_LOC+78       ; IVT 78 - reserved
        DW  IVT_BRANCH_LOC+79       ; IVT 79 - reserved
        DW  IVT_BRANCH_LOC+80       ; IVT 80 - CCP4
        DW  IVT_BRANCH_LOC+81       ; IVT 81 - CLC4
    ;
    IVT_BRANCH CODE    IVT_BRANCH_LOC<<2
        GOTO Default_vector         ; Software Interrupt
        GOTO Default_vector         ; HLVD
        GOTO Default_vector         ; OSF
        GOTO Default_vector         ; CSW
        GOTO Default_vector         ; NVM
        GOTO Default_vector         ; SCAN
        GOTO Default_vector         ; CRC
        GOTO Default_vector         ; IOC
        GOTO Default_vector         ; INT0
        GOTO Default_vector         ; ZCD
        GOTO Default_vector         ; AD
        GOTO Default_vector         ; ADT
        GOTO Default_vector         ; C1
        GOTO Default_vector         ; SMT1
        GOTO Default_vector         ; SMT1PRA
        GOTO Default_vector         ; SMT1PWA
        GOTO Default_vector         ; DMA1SCNT
        GOTO Default_vector         ; DMA1DCNT
        GOTO Default_vector         ; DMA1OR
        GOTO Default_vector         ; DMA1A
        GOTO Default_vector         ; SPI1RX
        GOTO Default_vector         ; SPI1TX
        GOTO Default_vector         ; SPI1
        GOTO Default_vector         ; I2C1RX
        GOTO Default_vector         ; I2C1TX
        GOTO Default_vector         ; I2C1
        GOTO Default_vector         ; I2C1E
        GOTO Default_vector         ; U1RX
        GOTO Default_vector         ; U1TX
        GOTO Default_vector         ; U1E
        GOTO Default_vector         ; U1
        GOTO tmr0Isr                ; TMR0
        GOTO Default_vector         ; TMR1
        GOTO Default_vector         ; TMR1G
        GOTO Default_vector         ; TMR2
        GOTO Default_vector         ; CCP1
        GOTO Default_vector         ; reserved
        GOTO Default_vector         ; NCO
        GOTO Default_vector         ; CWG1
        GOTO Default_vector         ; CLC1
        GOTO Default_vector         ; INT1
        GOTO Default_vector         ; C2
        GOTO Default_vector         ; DMA2SCNT
        GOTO Default_vector         ; DMA2DCNT
        GOTO Default_vector         ; DMA2OR
        GOTO Default_vector         ; DMA2A
        GOTO Default_vector         ; I2C2RX
        GOTO Default_vector         ; I2C2TX
        GOTO Default_vector         ; I2C2
        GOTO Default_vector         ; I2C2E
        GOTO Default_vector         ; U2RX
        GOTO Default_vector         ; U2TX
        GOTO Default_vector         ; U2E
        GOTO Default_vector         ; U2
        GOTO Default_vector         ; TMR3
        GOTO Default_vector         ; TMR3G
        GOTO Default_vector         ; TMR4
        GOTO Default_vector         ; CCP2
        GOTO Default_vector         ; reserved
        GOTO Default_vector         ; CWG2
        GOTO Default_vector         ; CLC2
        GOTO Default_vector         ; INT2
        GOTO Default_vector         ; reserved
        GOTO Default_vector         ; reserved
        GOTO Default_vector         ; reserved
        GOTO Default_vector         ; reserved
        GOTO Default_vector         ; reserved
        GOTO Default_vector         ; reserved
        GOTO Default_vector         ; reserved
        GOTO Default_vector         ; reserved
        GOTO Default_vector         ; TMR5
        GOTO Default_vector         ; TMR5G
        GOTO Default_vector         ; TMR6
        GOTO Default_vector         ; CCP3
        GOTO Default_vector         ; CWG3
        GOTO Default_vector         ; CLC3
        GOTO Default_vector         ; reserved
        GOTO Default_vector         ; reserved
        GOTO Default_vector         ; reserved
        GOTO Default_vector         ; reserved
        GOTO Default_vector         ; CCP4
        GOTO Default_vector         ; CLC4
    ;
    Default_vector:
        reset
    ;
    ; TIMER0 interrupt handler
    ;
    TMR0_CODE CODE
    tmr0Isr:
        bcf     PIR3,TMR0IF
        ;toggle the desired LED state
        btg     LEDState,7

        retfie  FAST
    ;
    ; Main application
    ;
    MAIN_PROG CODE                      ; let linker place main program

    START:
        bsf     INTCON0,IPEN_INTCON0    ; set IPEN bit
        ; use the unlock sequence to set the vector table position
        ; based on where the ivt psect is linked
        bcf     INTCON0,GIE
        movlw   0x55
        movwf   IVTLOCK
        movlw   0xAA
        movwf   IVTLOCK
        bcf     IVTLOCK,IVTLOCKED
        movlw   UPPER(ivt)
        movwf   IVTBASEU
        movlw   HIGH(ivt)
        movwf   IVTBASEH
        movlw   LOW(ivt)
        movwf   IVTBASEL
        movlw   0x55
        movwf   IVTLOCK
        movlw   0xAA
        movwf   IVTLOCK
        bsf     IVTLOCK,IVTLOCKED
        ; set up the state of the oscillator and peripherals with RE0 as a digital output driving
        ; the LED, assuming that other registers have not changed from their reset state
        BANKSEL ANSELE
        bcf     ANSELE,ANSELE0,BANKED
        bcf     TRISE,TRISE0
        movlw   0x62
        BANKSEL OSCCON1
        movwf   OSCCON1,BANKED
        clrf    OSCCON3,BANKED
        clrf    OSCEN,BANKED
        movlw   2                           ; Select 4MHz as HFINTOSC frequency
        movwf   OSCFRQ,BANKED
        clrf    OSCTUNE,BANKED
        ;configure and start timer interrupts
        BANKSEL IPR3
        bsf     IPR3,TMR0IP,BANKED
        movlw   0x4B                        ; TIMER0 clock source as FOSC/4 (only one that works in simulation), prescaler 1:2048
        movwf   T0CON1                      ; FOSC/4 is 1MHz
        movlw   0xF3                        ; TIMER0 interrupt period (1/1000)*2048*244 = 499.712 milliseconds
        movwf   TMR0H           
        clrf    TMR0L
        BANKSEL PIR3
        bcf     PIR3,TMR0IF,BANKED
        bsf     PIE3,TMR0IE,BANKED
        movlw   0x80
        movwf   T0CON0
        bsf     INTCON0,GIEH
        clrf    LEDState
    ;
    ; Application loop
    ;
    loop:
        ;set LED state to be that requested by the interrupt code
        btfss   LEDState,7
        goto    lightLED
        bsf     LATE,LATE0                  ; turn LED off
        goto    loop
    lightLED:
        bcf     LATE,LATE0                  ; turn LED on
        goto    loop
    ;
        END

    This code selects where the IVT is located at build time and populates the table with handles to a GOTO branch table to reach the ISR handler. This is likely the way the silicon designers expected the code to be implemented.
     
    It woule be better if Microchip could actually explain this in a clearly written document.
    #7
    1and0
    Access is Denied
    • Total Posts : 12086
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: PIC-AS interrupt example for K42 documentation issue? 2021/01/31 03:20:36 (permalink)
    0
    dan1138
    The linker used with MPASM is not able to do the same kind of manipulation of relocatable objects that the pic-as linker can perform.

    I learned that the PIC-AS linker can perform >>2 on relocatable objects by playing with the code example mentioned in Post #1, which comes from the "MPLAB XC8 PIC Assembler User's Guide for Embedded Engineers" where all the SFRs are terribly wrapped with the BANKMASK() macro.
     
    dan1138
    The PIC18F silicon implementation of an Interrupt Vector Table is lame for allowing only a 16-bit handle to select an address in a 20-bit address space by forcing the target to be on a 4 byte boundry.
     
    This choice also limits the location of the ISR handlers to be in the first 256K bytes of the code address space. At present the maximum code space for a PIC18F47Kxx device is 128K bytes. So this cannot be a problem yet.

    Agreed.
     
    dan1138
    I cooked up this example using MPASM and MPLABX v5.35:

    I see you've modified the PIC18 code example from the "MPLAB XC8 PIC Assembler User's Guide for Embedded Engineers" for MPASM. Don't you agree the MPASM version is a much cleaner and simpler code to write?! Take the followings for examples,

    ISR_DATA UDATA_ACS

    vs
    PSECT bitbssCOMMON,bit,class=COMRAM,space=1


    RES_VECT  CODE  0x0000

    vs
    PSECT resetVec,class=CODE,reloc=2


    IVT_TABLE CODE  IVT_START

    vs
    PSECT ivt,class=CODE,reloc=2,ovrld


    TMR0_CODE CODE

    vs
    PSECT textISR,class=CODE,reloc=4


        END

    vs
        END     resetVec


    ... not to mention the psect addresses for "resetVec" and "ivt" need to be manually and correctly stated in the PIC-AS linker options.
     
    dan1138
    This code selects where the IVT is located at build time and populates the table with handles to a GOTO branch table to reach the ISR handler. This is likely the way the silicon designers expected the code to be implemented.
     
    It woule be better if Microchip could actually explain this in a clearly written document.

    The addition of a GOTO table to branch to the ISR handlers allows interrupt service routines to be relocatable, but it also increases interrupt latency and uses more code space. So I doubt that is the designers' intention.

    I suspect and predict Microchip will implement double-word entries for the Interrupt Vector Table on PIC18 devices with more than 256K bytes of program memory space. That is, the IVT may be a jump table of GOTO instructions able to branch anywhere within the entire 2 Mbyte memory range.
     
    #8
    1and0
    Access is Denied
    • Total Posts : 12086
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: PIC-AS interrupt example for K42 documentation issue? 2021/01/31 03:29:43 (permalink)
    0
    Getting back to the PIC-AS PIC18 code example on pages 36-37 of the "MPLAB XC8 PIC Assembler User's Guide for Embedded Engineers". The abundant usage of BANKMASK() is not only verbose but also forces the RAM access bit to be explicitly specified, which means one will have to consistently looking in the datasheet to determine whether the SFR is located in the Access Bank or not. IMO, whoever wrote that PIC-AS code example clearly does not understand how the assembler works. Remove all the BANKMASK() on SFRs and RAM access bits, and let the assembler automatically inserts the RAM access bit which will make for a more readable and less error-prone code.

    I've already commented on symbolic bits in another thread:
    bsf     BANKMASK(INTCON0),INTCON0_IPEN_POSN,c ;set IPEN bit

    Don't even get me started commenting on this
    btfss   LEDState/8,LEDState&7,c

    LoL: LoL
     
    #9
    Jerry Messina
    Super Member
    • Total Posts : 666
    • Reward points : 0
    • Joined: 2003/11/07 12:35:12
    • Status: offline
    Re: PIC-AS interrupt example for K42 documentation issue? 2021/01/31 09:37:15 (permalink)
    +1 (1)
    dan1138
    I cooked up this example using MPASM and MPLABX v5.35:[code];

    That's exactly the approach I've used. It's lamer than lame and I doubt that's what was intended, but at least it works.
     
    It would have been nice if they had this work across the whole address space to start with, but it's likely they'll never have an 18F part with >256K so maybe they thought it's a moot point.
    #10
    1and0
    Access is Denied
    • Total Posts : 12086
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: PIC-AS interrupt example for K42 documentation issue? 2021/01/31 11:03:13 (permalink)
    +1 (1)
    Jerry Messina
    It's my understanding the statement "tmr0Isr can be located anywhere in memory" is incorrect... it must be located at an address divisible by 4 so that the 'DW tmr0Isr shr 2' operation will load the correct address into the IVT.

    Just curious, what happen if the address of the interrupt service routine is located at an address NOT evenly divisible by 4?
     
    I'm thinking something likes this will work-around the 4-byte boundary:

            nop
    tmr0Isr:
            ; isr code here

     
    post edited by 1and0 - 2021/01/31 11:23:38
    #11
    Jerry Messina
    Super Member
    • Total Posts : 666
    • Reward points : 0
    • Joined: 2003/11/07 12:35:12
    • Status: offline
    Re: PIC-AS interrupt example for K42 documentation issue? 2021/01/31 11:23:26 (permalink)
    +2 (2)
    The K42 will take whatever 16-bit value is in the IVT, shift it left twice, and branch to that address.
    If it eventually hits your isr, congratulations. Otherwise, you're SOL.
     
     
    #12
    1and0
    Access is Denied
    • Total Posts : 12086
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: PIC-AS interrupt example for K42 documentation issue? 2021/01/31 11:24:14 (permalink)
    0
    Jerry Messina
    The K42 will take whatever 16-bit value is in the IVT, shift it left twice, and branch to that address.
    If it eventually hits your isr, congratulations. Otherwise, you're SOL.

    I'm thinking something likes this will work-around the 4-byte boundary:
            nop
    tmr0Isr:
            ; isr code here

    #13
    dan1138
    Super Member
    • Total Posts : 4242
    • Reward points : 0
    • Joined: 2007/02/21 23:04:16
    • Location: 0
    • Status: offline
    Re: PIC-AS interrupt example for K42 documentation issue? 2021/01/31 12:10:36 (permalink)
    0
    1and0
    Just curious, what happen if the address of the interrupt service routine is located at an address NOT evenly divisible by 4?

    Your suggestion works for an assembler like pic-as that knows the final addresses of relocatable objects but fails with MPASM because the linker this assembler uses does not support logical operations like shifts on the final addresses of relocatable objects.
    #14
    1and0
    Access is Denied
    • Total Posts : 12086
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: PIC-AS interrupt example for K42 documentation issue? 2021/01/31 12:28:04 (permalink)
    +1 (1)
    dan1138
    Your suggestion works for an assembler like pic-as that knows the final addresses of relocatable objects but fails with MPASM because the linker this assembler uses does not support logical operations like shifts on the final addresses of relocatable objects.

    Agreed. I always wonder why the MPLINK linker is so limited and crippled. ;)  It can handle relocatable objects in only this form: 
     
    [upper | high | low] (relocatable_symbol + constant_offset)
     
    #15
    Jerry Messina
    Super Member
    • Total Posts : 666
    • Reward points : 0
    • Joined: 2003/11/07 12:35:12
    • Status: offline
    Re: PIC-AS interrupt example for K42 documentation issue? 2021/02/01 05:36:05 (permalink)
    0
    1and0
    I'm thinking something likes this will work-around the 4-byte boundary:
            nop
    tmr0Isr:
            ; isr code here


    Since the code space is already word-aligned, that should work. Worst-case, you get an extra NOP... that's better than having to deal with an additional jump table.
    #16
    1and0
    Access is Denied
    • Total Posts : 12086
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: PIC-AS interrupt example for K42 documentation issue? 2021/02/01 10:51:45 (permalink)
    0
    Jerry Messina
    Since the code space is already word-aligned, that should work. Worst-case, you get an extra NOP... that's better than having to deal with an additional jump table.

    Yeah, a jump table requires not only more code space but also more latency.
     
    #17
    dan1138
    Super Member
    • Total Posts : 4242
    • Reward points : 0
    • Joined: 2007/02/21 23:04:16
    • Location: 0
    • Status: offline
    Re: PIC-AS interrupt example for K42 documentation issue? 2021/02/01 12:07:09 (permalink)
    +1 (1)
    Jerry Messina
    1and0
    I'm thinking something likes this will work-around the 4-byte boundary:
            nop
    tmr0Isr:
            ; isr code here


    Since the code space is already word-aligned, that should work. Worst-case, you get an extra NOP... that's better than having to deal with an additional jump table.

    You guys are trying to solve the wrong problem in the wrong way.
     
    The problem you do not seem to be seeing is that MPASM cannot do logical operations on a relocatable object.
     
    PERIOD. FULL STOP!
     
    Placing the unshifted low 16-bit of the address of the Interrupt Service Routine in the IVT does not work as the address that will be vectored to will be 4 time the 16-bit value in the IVT vector. As the MPASM linker CANNOT DO LOGICAL OPERATIONS ON RELOCATABLE OBJECTS the values in the IVT and the addresses they are associated with must be know at build time.
     
    To use Interrupt Service Routines that can be located anywhere the linker wants with MPASM is my goal.
     
    The only way I have been able to build the PIC18F47K42 Interrupt Vector Table with MPASM in relocatable mode is to define CODE sections at fixed locations for the IVT and a GOTO branch table and take a 2 instruction cycle hit to the interrupt latency.
     
    A fully utilized IVT takes 162 bytes, the GOTO branch table takes 324 bytes and must be in a 4 byte boundary,
     
    By using the pic-as assembler with a correctly declared PSECT works and there is no hit to interrupt latency.
     
    So the question you need to ask yourselves: Is a 2 instruction cycle hit to the interrupt latency and allocating 366 instruction words for IVT handling worth it to still use the MPASM assembler?
    #18
    Jerry Messina
    Super Member
    • Total Posts : 666
    • Reward points : 0
    • Joined: 2003/11/07 12:35:12
    • Status: offline
    Re: PIC-AS interrupt example for K42 documentation issue? 2021/02/01 12:22:36 (permalink)
    0
    The application I'm using this with uses MPASM in absolute mode.
     
    #19
    1and0
    Access is Denied
    • Total Posts : 12086
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: PIC-AS interrupt example for K42 documentation issue? 2021/02/01 12:30:32 (permalink)
    +1 (1)
    dan1138
    You guys are trying to solve the wrong problem in the wrong way.
     
    The problem you do not seem to be seeing is that MPASM cannot do logical operations on a relocatable object.

    I use MPASM in absolute mode. ;)

    So, I was solving the 4-byte boundary problem without having to assign fixed addresses that are divisible by 4 for all the interrupt service routines in absolute mode, where the addresses of objects are known at build time.
        dw      tmr0Isr >> 2

     
    #20
    Page: 12 > Showing page 1 of 2
    Jump to:
    © 2021 APG vNext Commercial Version 4.5