Jerry Messina
Super Member
- Total Posts : 666
- Reward points : 0
- Joined: 2003/11/07 12:35:12
- Status: offline
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?
|
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)
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.
|
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)
@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.
|
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)
...
post edited by 1and0 - 2021/01/30 20:10:32
|
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)
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. ;)
|
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)
... 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.
|
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)
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.
|
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)
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.
|
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)
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:
|
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)
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.
|
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)
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
|
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)
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.
|
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)
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
|
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)
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.
|
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)
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)
|
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)
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.
|
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)
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.
|
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)
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?
|
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)
The application I'm using this with uses MPASM in absolute mode.
|
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)
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
|