piclist 2001\04\19\122055a >
Thread: Page Switching Problem
www.piclist.com/techref/power/priswitch.htm?key=switching
flavicon
face BY : David Cary email (remove spam text)

part 1 16 bytes content-type:text/plain; charset=us-ascii



Dear Tony K

part 2 9439 bytes content-type:text/plain; charset=iso-8859-1
(decoded quoted-printable)


übek,

The "fcall" macro I'm using now works for me. I just have one tiny little
nit-picking question ...

> Kübek Tony <.....tony.kubekEraseMEspamspamFLINTAB.COM> on 2001-04-19 02:58:47 AM wrote:
> And on the page below you will find
> some other musings regarding page crossings.
> In particular look at LONG_CALL, SHORT_CALL and PCALL ( pagecall ).
>
> http://www.piclist.com/techref/microchip/pages.htm

Thanks for putting useful information on that web page.

Those macros *look* useful. Unfortunately, those macros don't seem to work for
me.
Did I make a typo ? a thinko ?
When I use them in my program (appended below), I get this error:

---- output from MPASM 02.61
Building EXCEL.HEX...

Compiling MAIN.ASM:
Command line: "C:\PROGRA~1\MPLAB\MPASMWIN.EXE /e+ /l+ /x- /c+ /p16F877 /o+ /q
C:\DAVID\GRAPHI~1\TEST_L~1\MAIN.ASM"
Error[151]   C:\DAVID\GRAPHI~1\TEST_L~1\MAIN.ASM 56 : Operand contains
unresolvable labels or is too complex
Error[151]   C:\DAVID\GRAPHI~1\TEST_L~1\MAIN.ASM 57 : Operand contains
unresolvable labels or is too complex
Message[301] C:\DAVID\GRAPHI~1\TEST_L~1\MAIN.ASM 60 : MESSAGE: ("Call on same
page, replace LONG_CALL with PCALL " times1.5)
Error[151]   C:\DAVID\GRAPHI~1\TEST_L~1\MAIN.ASM 56 : Operand contains
unresolvable labels or is too complex
Error[151]   C:\DAVID\GRAPHI~1\TEST_L~1\MAIN.ASM 57 : Operand contains
unresolvable labels or is too complex
Message[301] C:\DAVID\GRAPHI~1\TEST_L~1\MAIN.ASM 60 : MESSAGE: ("Call on same
page, replace LONG_CALL with PCALL " sub1)
Error[151]   C:\DAVID\GRAPHI~1\TEST_L~1\MAIN.ASM 56 : Operand contains
unresolvable labels or is too complex
Error[151]   C:\DAVID\GRAPHI~1\TEST_L~1\MAIN.ASM 57 : Operand contains
unresolvable labels or is too complex
Message[301] C:\DAVID\GRAPHI~1\TEST_L~1\MAIN.ASM 60 : MESSAGE: ("Call on same
page, replace LONG_CALL with PCALL " sub2)

MPLAB is unable to find output file "MAIN.O".

Build failed.
---- end output

; (next lines would typically be in a ".inc" include file)
; from www.piclist.com/techref/microchip/pages.htm
;Tony Kübek [tony.kubek at flintab.com] of Flintab AB says
;Trying to be clever I came up with the following:
;LONG_CALL ROUTINE ; any page -> any page ( 4 BCF/BSF totally )
;SHORT_CALL ROUTINE ; page0<->1 or page2<->3 ( 2 BSF/BCF totally )
;PCALL ROUTINE ; same page call, however gives REAL warnings when crossing page
( not like mplink :-) )
;Ideally one would use LONG_CALL XX all over until program has stabilized ( code
not moving around ) then look at the messages and change accordingly.
;+++++
;    SET_PCLATH 'help' macro for LONG_CALL
;    Set's/clears PCLATH bits 3:4 according to
;    'variable' PCLATH_34
;
SET_PCLATH     MACRO   PCLATH_34
    IF(PCLATH_34&0x10)
    BSF  PCLATH,4
    ELSE
    BCF  PCLATH,4
    ENDIF
    IF(PCLATH_34&0x08)
    BSF  PCLATH,3
    ELSE
    BCF  PCLATH,3
    ENDIF
    ENDM
;+++++
;    SET_PCLATH4 'help' macro for LONG/SHORT_CALL
;    Set's/clears PCLATH bit 4 according to
;    'variable' PCLATH_4
SET_PCLATH4    MACRO   PCLATH_4
    IF(PCLATH_4&0x10)
    BSF  PCLATH,4
    ELSE
    BCF  PCLATH,4
    ENDIF
    ENDM
;+++++
;    SET_PCLATH3 'help' macro for LONG/SHORT_CALL
;    Set's/clears PCLATH bit 3 according to
;    'variable' PCLATH_3
;
SET_PCLATH3    MACRO   PCLATH_3
    IF(PCLATH_3&0x08)
    BSF  PCLATH,3
    ELSE
    BCF  PCLATH,3
    ENDIF
    ENDM
;+++++
;    LONG_CALL long call, sets the page bits 4:5 of PCLATH
;    so call can cross ANY page boundary, reset's PCLATH after call.
;    w-reg is left untouched.
LONG_CALL MACRO     LABEL
    LOCAL     DEST_HIGH, SOURCE_HIGH, DIFF_HIGH
DEST_HIGH      SET  (HIGH(LABEL)&0x18)        ; save bit's 4:5 of dest adress
SOURCE_HIGH    SET  (HIGH($)&0x18)       ; --- || ---  source adress
DIFF_HIGH SET     DEST_HIGH ^ SOURCE_HIGH ; get difference ( XOR )
    IF   (DIFF_HIGH == 0) ; same page, SHOULD generate no extra code, delta 0
pages
    MESSG     "Call on same page, replace LONG_CALL with PCALL " LABEL
    NOP  ; redundant NOP's
    NOP
    CALL LABEL
    NOP
    NOP
    ELSE
         ; test if both bits must be set ? i.e. page0<->page3 or page2<->page3
         IF   (DIFF_HIGH == 0x18) ; difference in BOTH bit's, delta 2 pages
         MESSG  "Setting page bit's for long page crossing call"
         SET_PCLATH     DEST_HIGH   ; set both bits in PCLATH
         CALL LABEL
         SET_PCLATH     SOURCE_HIGH ; reset both bits in pclath
         ELSE
              ; if we end up here then one BSF/BCF is enough, i.e. delta 1 page
              ; i.e. page0<->1 or page2<->3
              MESSG "Call only one page, replace LONG_CALL with SHORT_CALL "
LABEL
              IF   (DIFF_HIGH == 0x10) ; diff in high bit
              NOP  ; redundant NOP
              SET_PCLATH4    DEST_HIGH ; set high(4) bit of PCLATH
              CALL LABEL
              SET_PCLATH4    SOURCE_HIGH
              NOP  ; redundant NOP
              ELSE
              ; lowest bit only
              NOP  ; redundant NOP
              SET_PCLATH3    DEST_HIGH ; set low(3) bit of PCLATH
              CALL LABEL
              SET_PCLATH3    SOURCE_HIGH
              NOP
              ENDIF
         ENDIF
    ENDIF
    ENDM
;+++++
;    SHORT_CALL short call, code for calling between page0<->1 or page2<->3
;    Reset's PCLATH after call.
;    w-reg is left untouched.
SHORT_CALL     MACRO     LABEL
    LOCAL     DEST_HIGH, SOURCE_HIGH, DIFF_HIGH
DEST_HIGH      SET  (HIGH(LABEL)&0x18)        ; save bit's 4:5 of dest adress
SOURCE_HIGH    SET  (HIGH($)&0x18)       ; --- || ---  source adress
DIFF_HIGH SET     DEST_HIGH ^ SOURCE_HIGH ; get difference ( XOR )
    IF   (DIFF_HIGH == 0) ; same page, SHOULD generate no extra code, delta 0
pages
    MESSG     "Call on same page, replace SHORT_CALL with PCALL "
LABEL
    NOP  ; redundant NOP's
    CALL LABEL
    NOP
    ELSE
         ; for safety check so we do not require LONG_CALL
         IF   ((DIFF_HIGH&0x18)==0x18)
         MESSG  " WARNING ! Replace SHORT_CALL with LONG_CALL "
LABEL
         ENDIF
         MESSG  "Setting page bit's for short page crossing call"
         IF   (DIFF_HIGH == 0x10) ; diff in high bit
         SET_PCLATH4    DEST_HIGH ; set high(4) bit of PCLATH
         CALL LABEL
         SET_PCLATH4    SOURCE_HIGH
         ELSE
         ; lowest bit only
         SET_PCLATH3    DEST_HIGH ; set low(3) bit of PCLATH
         CALL LABEL
         SET_PCLATH3    SOURCE_HIGH
         ENDIF
    ENDIF
    ENDM
;+++++
;    PCALL page call, code for calling on same page
;    outputs messages if LONG/SHORT call could/must be used
;
PCALL     MACRO     LABEL
    LOCAL     DEST_HIGH, SOURCE_HIGH, DIFF_HIGH
DEST_HIGH      SET  (HIGH(LABEL)&0x18)        ; save bit's 4:5 of dest adress
SOURCE_HIGH    SET  (HIGH($)&0x18)       ; --- || ---  source adress
DIFF_HIGH SET     DEST_HIGH ^ SOURCE_HIGH ; get difference ( XOR )
    IF   (DIFF_HIGH == 0) ; same page, call ok
    CALL LABEL
    ELSE
         ; for safety check so we do not require LONG_CALL
         IF   ((DIFF_HIGH&0x18)==0x18)
         MESSG  " WARNING ! Replace PCALL with LONG_CALL " LABEL
         CALL LABEL     ; INCORRECT Call !!!
         ELSE
         MESSG  " WARNING ! Replace PCALL with SHORT_CALL " LABEL
         CALL LABEL
         ENDIF
    ENDIF
    ENDM
;My question is: Is there any way to remove these two extra NOP's ??
;(end include file)
; ------------------------------------------------------


; main.asm
; 2001-04-09:DAV: David Cary
    LIST      P=PIC16F877
    INCLUDE        P16F877.INC    ;INCLUDE REGISTER DEFINITION FILE
;    INCLUDE        test.inc
; ================
; Reset vector
STARTUP   CODE 0x0000
RESET:
    NOP                 ;REQUIRED BY ICD
    PAGESEL   beginning
    GOTO beginning           ;INITIALIZE PROCESSOR AFTER RESET

shared_stuff   UDATA_shr ; Let linker allocate space for these.
ISR_W          res 1     ; must be in a ``global'' register or in every page at
the same offset.
idle_count     res 4

    ; 16 bit return value from read_timer1().
TMPH      res 1
TMPL      res 1

; ================
;beginning     CODE
;hardwire location for the L_CALL test
beginning CODE 0x0200

beginning:
    BCF  INTCON,7       ;GLOBALLY DISABLE INTERRUPTS
    BTFSC     INTCON,7       ;BRANCH IF INTERRUPTS ARE DISABLED
    GOTO RESET               ;ELSE, TRY TO DISABLE AGAIN

MAINLP:

; [FIXME: do something useful here.]
    movlw 0x03
    movwf idle_count+3
    ;movlw 0x10
    ;movwf ACC1
    ; LONG_CALL
    LONG_CALL times1.5
    LONG_CALL sub1
    LONG_CALL sub2

    GOTO MAINLP


sub2:
    nop
    return

;hardwire location for the L_CALL test
; more_subroutines  CODE
more_subroutines    CODE 0x0800

sub1:
    nop
    return

shared_math_stuff   UDATA_shr
ACC0 res 1
ACC1 res 1
TEMP0     res 1
TEMP1     res 1

;hardwire location for the L_CALL test
; test_subs    CODE
test_subs CODE 0x1000

times1.5:
    GLOBAL sub1
    GLOBAL times1.5
    ;[do something useful here]
    ;
    rlf ACC1,f
    rlf ACC0,f
    retlw 0xAA


    END
; end file main.asm




part 3 131 bytes
--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.


<86256A33.00599702.00@Brunswickoutdoor.com>

See also: www.piclist.com/techref/power/priswitch.htm?key=switching
Reply You must be a member of the piclist mailing list (not only a www.piclist.com member) to post to the piclist. This form requires JavaScript and a browser/email client that can handle form mailto: posts.
Subject (change) Page Switching Problem

month overview.

new search...