Searching \ for '[PIC]: Page Switching Problem' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/power/priswitch.htm?key=switching
Search entire site for: 'Page Switching Problem'.

Exact match. Not showing close matches.
PICList Thread
'[PIC]: Page Switching Problem'
2001\04\17@213743 by Thomas N

picon face
Hi everyone,

I wrote this simple page switching macro and I put this file in page 0 (org
0x00).

PAGE0   MACRO
       BCF     PCLATH,3
       BCF     PCLATH,4
       ENDM

PAGE1   MACRO
       BSF     PCLATH,3
       BCF     PCLATH,4
       ENDM

PAGE2   MACRO
       BCF     PCLATH,3
       BSF     PCLATH,4
       ENDM

PAGE3   MACRO
       BSF     PCLATH,3
       BSF     PCLATH,4
       ENDM

I put a file on Page 3 and when I try to use the Page3 macro, I get
the following messages:

Warning[207] C:\HAIFIL~1\PROJECT\TEMP.ASM 2 : Found label after column 1.
PAGE3)
Error[116]   C:\HAIFIL~1\PROJECT\MACRO.ASM 36 : Address label duplicated or
different in second pass (PAGE3)

How come I cannot use the Page macro above for the file on different page?

Please help!
Thomas
_________________________________________________________________________
Get Your Private, Free E-mail from MSN Hotmail at http://www.hotmail.com.

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads


2001\04\17@214959 by Andrew Warren

flavicon
face
Thomas N <spam_OUTPICLISTTakeThisOuTspamMITVMA.MIT.EDU> wrote:

> I put a file on Page 3 and when I try to use the Page3 macro, I get
> the following messages:
>
> Warning[207] C:\HAIFIL~1\PROJECT\TEMP.ASM 2 : Found label after column
> 1. PAGE3) Error[116]   C:\HAIFIL~1\PROJECT\MACRO.ASM 36 : Address
> label duplicated or different in second pass (PAGE3)
>
> How come I cannot use the Page macro above for the file on different
> page?

Thomas:

This isn't a page-switching problem or even a macro problem; it
sounds as though you've tried to use the macro before defining it.

The "PAGE3 MACRO .... ENDM" definition has to be BEFORE (i.e., above)
the code which invokes the macro.

-Andy


=== Andrew Warren --- .....aiwKILLspamspam@spam@cypress.com
=== IPD Systems Engineering, CYSD
=== Cypress Semiconductor Corporation
===
=== Opinions expressed above do not
=== necessarily represent those of
=== Cypress Semiconductor Corporation

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads


2001\04\17@215632 by Tony Nixon

flavicon
picon face
Thomas N wrote:

> I put a file on Page 3 and when I try to use the Page3 macro, I get
> the following messages:
>
> Warning[207] C:\HAIFIL~1\PROJECT\TEMP.ASM 2 : Found label after column 1.
> PAGE3)
> Error[116]   C:\HAIFIL~1\PROJECT\MACRO.ASM 36 : Address label duplicated or
> different in second pass (PAGE3)

You may have a 'Page3' label somewhere else in your code.


--
Best regards

Tony

mICros
http://www.bubblesoftonline.com
salesspamKILLspampicnpoke.com

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads


2001\04\18@192217 by David Cary

flavicon
face
Hi Thomas N.

Did you know about the
 LCALL
 LGOTO
pseudo-ops ? They do everything your page macros do, and they're built into
MPASM.



--

David Cary

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics


2001\04\18@202741 by Andrew Warren

flavicon
face
David Cary <.....PICLISTKILLspamspam.....MITVMA.MIT.EDU> wrote:

> Did you know about the
>   LCALL
>   LGOTO
> pseudo-ops ? They do everything your page macros do, and they're
built
> into MPASM.

David:

MPASM's LCALL pseudo-op doesn't restore the page bits after the
subroutine return.

-Andy


=== Andrew Warren --- EraseMEaiwspam_OUTspamTakeThisOuTcypress.com
=== IPD Systems Engineering, CYSD
=== Cypress Semiconductor Corporation
===
=== Opinions expressed above do not
=== necessarily represent those of
=== Cypress Semiconductor Corporation

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics


2001\04\18@210558 by David P. Harris

picon face
Why particularly do we need to restore the page bits?
I thought these are only important when: doing a long call, long goto, or
otherwise manipulatiing the PCLATH register, say when doing a long table
look up?
David

Andrew Warren wrote:

{Quote hidden}

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics


2001\04\18@212452 by David Cary

flavicon
face
Dear Andrew Warren and David Harris,

"David P. Harris" <KILLspamdpharrisKILLspamspamTELUS.NET> on 2001-04-17 07:34:25 PM asked
> Why particularly do we need to restore the page bits?
> I thought these are only important when: doing a long call, long goto, or
> otherwise manipulatiing the PCLATH register, say when doing a long table
> look up?
> David

If you don't restore the page bits after a LCALL, this annoying problem happens:

    ; warning: untested code.
    incf fsr,f
    movlw 8
    movwf indf
next_iteration:
    lcall subroutine_on_another page
    ; ....... (normal, straight-line code)
    decfsz indf
    goto next_iteration
    decf fsr,f

Gotcha ! that final goto jumps some random location on that other page, rather
than back up to next_iteration.

Change that "lcall" to a "fcall" and then it works as expected (that
subroutine_on_another_page gets called 8 times).

Andrew Warren <RemoveMEaiwTakeThisOuTspamCYPRESS.COM> on 2001-04-18 07:20:35 PM noted:
> MPASM's LCALL pseudo-op doesn't restore the page bits after the
> subroutine return.

True, alas.

Currently I have lots of "fcall" scattered through my code

    ...
fcall     macro subroutine_name
    lcall subroutine_name
    ; just in case we do *local* calls or gotos before the next fcall.
    local   here
    pagesel here
here:
    endm

    ...
    fcall sb_left_shift
    fcall sb_add
    fcall sb_left_shift
    fcall lookupTOS
    movwf screen+1
    ...
    decfsz indf,f
    goto next_bit_iteration
    return
    ...

This macro lets me call subroutines in any page from any page,
and restores the page bits after return so that I can do "short" call and goto.
(LGOTO works fine as-is).

I see that lots of people have tried to make similar macros that automatically
assemble a short call when possible, but I've never seen anyone succeed.

Using MPASM 02.61.

-- David Cary

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics


2001\04\19@010048 by Andrew Warren

face
flavicon
face
David P. Harris <spamBeGonePICLISTspamBeGonespamMITVMA.MIT.EDU> wrote:

> Why particularly do we need to restore the page bits? I thought
> these are only important when: doing a long call, long goto, or
> otherwise manipulatiing the PCLATH register

David:

The PIC doesn't know that you're doing a "long" CALL or GOTO, so it
would be more accurate to say that the page bits are important "when
doing a CALL or GOTO".

If you think of it THAT way, it's clear that the page bits must be
set correctly before EVERY CALL or GOTO.  If the page bits weren't
always pointing to the current page -- that is, if you just left them
set to some other page after a long CALL -- then you'd have to
explicitly set them before each CALL or GOTO; in other words, EVERY
SINGLE GOTO OR CALL would have to be written as a long GOTO or long
CALL... Which would be monumentally wasteful, since most GOTOs and
CALLs are to addresses in the current page.  The waste is compounded
by the fact that "skip" instructions won't skip over long GOTOs and
CALLs properly... Which also means that even if you DO make all your
CALLs and GOTOs long, your code won't work.

Imagine, for example, that you wanted to do this:

        ORG    [somewhere on page 0]

        LCALL  PAGE3_SUB
        BTFSC  RETURNED_BIT
        GOTO   BIT_SET

        NOP

    BIT_SET:

        NOP

How would you make that "BTFSC/GOTO" combination work if you didn't
restore the page bits between the LCALL and the BTFSC?

If, on the other hand, you restore the page bits after a CALL or a
long table-lookup, then they always point to the current page and all
your same-page GOTOs and CALLs can be written normally.

-Andy


=== Andrew Warren - TakeThisOuTfastfwdEraseMEspamspam_OUTix.netcom.com
=== Fast Forward Engineering - San Diego, California
=== http://www.geocities.com/SiliconValley/2499

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


2001\04\19@032522 by dpharris

picon face
Umm, point well taken.  I guess it would been nice to have had a LCALL
and a CALL as separate instructions.  So, one is left being very careful
about where your code is, and how you call it.
D

Andrew Warren wrote:

{Quote hidden}

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


2001\04\19@040541 by o-8859-1?Q?K=FCbek_Tony?=

flavicon
face
Hi,

David Cary wrote:
<snip>
>I see that lots of people have tried to make similar macros that
automatically
>assemble a short call when possible, but I've never seen anyone succeed.

Well true in part as previously stated due to the two pass
nature of the compiler. However there are more 'effective'
ways to deal with page crossings. I belive Olin posted
his pagecrossing macros. 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


As it is impossible to actually change code size dynamically one
has to settle for second best, in this case using LONG_CALL *everythere*
in your program until routines has stabilized into their 'own' pages.
Then looking at the message output one can change every call that does not
require
both page bits to be changed, to either SHORT_CALL or even PCALL.
And BTW these *DO* preserv the WREG, using MPASM's PAGESEL does not
give the same warranty ( on some pic's that is ).


/Tony

Tony Kübek, Flintab AB            
²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²
E-mail: EraseMEtony.kubekspamflintab.com
²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²

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


2001\04\19@120619 by Olin Lathrop

face picon face
> Why particularly do we need to restore the page bits?
> I thought these are only important when: doing a long call, long goto, or
> otherwise manipulatiing the PCLATH register, say when doing a long table
> look up?

On the 16 family, there is only one GOTO and CALL, no long versus short.
Every GOTO and CALL contains the low 11 address bits in the instruction and
takes the remaining bits from PCLATH.  Therefore, local GOTOs and CALLs will
not work as expected when PCLATH is not pointing to the page the code is on.
Because of this, I use the convention that PCLATH is always set to the
current page.  That way I don't need to do anything special for local CALLs
and GOTOs.  On the flip side, this means I have to set then restore PCLATH
when doing external calls.


********************************************************************
Olin Lathrop, embedded systems consultant in Littleton Massachusetts
(978) 742-9014, RemoveMEolinEraseMEspamEraseMEembedinc.com, http://www.embedinc.com

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


2001\04\19@122055 by David Cary

flavicon
face
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 <RemoveMEtony.kubekspam_OUTspamKILLspamFLINTAB.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.


2001\04\19@122930 by Roman Black

flavicon
face
Olin Lathrop wrote:
>
> > Why particularly do we need to restore the page bits?
> > I thought these are only important when: doing a long call, long goto, or
> > otherwise manipulatiing the PCLATH register, say when doing a long table
> > look up?
>
> On the 16 family, there is only one GOTO and CALL, no long versus short.
> Every GOTO and CALL contains the low 11 address bits in the instruction and
> takes the remaining bits from PCLATH.  Therefore, local GOTOs and CALLs will
> not work as expected when PCLATH is not pointing to the page the code is on.
> Because of this, I use the convention that PCLATH is always set to the
> current page.  That way I don't need to do anything special for local CALLs
> and GOTOs.  On the flip side, this means I have to set then restore PCLATH
> when doing external calls.


Hi Olin, I have been playing with PICs long enough
that page switching is not really a problem for me,
but I would be interested to learn what an expert
prefers as a *general system* for coding around the
page problem.

I know this is wishy-washy and hard to define but
do you prefer:

1. code master routine on page 0 and jump to other
pages for special functions??

2. Divide code into basic types, and code (say)
LCD on page 1, sampling on page 0, data storage
on page 2, etc??

3. Code the whole lot as if page switching doesn't
matter and rely on well written page macros to
do all the dirty work??

4. Something better than suggested above??
:o)
-Roman

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


2001\04\19@124100 by Olin Lathrop

face picon face
> As it is impossible to actually change code size dynamically one
> has to settle for second best, in this case using LONG_CALL *everythere*
> in your program until routines has stabilized into their 'own' pages.
> Then looking at the message output one can change every call that does not
> require both page bits to be changed, to either SHORT_CALL or even PCALL.

I get around this without manual intervention.  The code for each module is
always wholly on one page.  That means calls and gotos within a module don't
require PCLATH diddling.  I use my GCALL macro for calls to globals outside
the module in the assumption that they could be on any page.  Yes, this
ignores potential savings when calling between modules that happen to get
loaded on the same page.  The important point is that it is reasonably
efficient and virtually error free.  (Reliability and maintainability is
more important than speed or code size for the vast majority of code.)  If
calling between two specific modules was really that critical, you could
force them both to the same page with the linker and then use local calls
between them.  I've done over 2 dozen PIC projects and this has so far not
been necessary.


********************************************************************
Olin Lathrop, embedded systems consultant in Littleton Massachusetts
(978) 742-9014, RemoveMEolinTakeThisOuTspamspamembedinc.com, http://www.embedinc.com

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


2001\04\19@160124 by Olin Lathrop

face picon face
> 1. code master routine on page 0 and jump to other
> pages for special functions??
>
> 2. Divide code into basic types, and code (say)
> LCD on page 1, sampling on page 0, data storage
> on page 2, etc??
>
> 3. Code the whole lot as if page switching doesn't
> matter and rely on well written page macros to
> do all the dirty work??

Closest to 2, but different.  I don't like manually allocating anything.

First, I use the linker.  I don't know why more people don't do this since
it's easy and has a number of advantages.  Most of the code I see here has
ORGs in it, indicating that the assembly is in absolute mode.  I have NEVER
yet used absolute mode.  The big advantage of using the linker is that code
can be in separate modules.  This makes things much more maintainable and
reusable.  Each module also gets its own namespace for local symbols, so you
don't have to worry about name collision with some unrelated part of the
code.  You can now group functional blocks into separate modules.  This also
provides a natural place to document the interfaces between the functional
blocks.

Since the code is now a collection of relatively small modules, you can
dictate that each module must be entirely on one page.  I do this by setting
up a separate linker section for each code page.  Except for the code at the
startup location and the interrupt routine, I just let the linker stick a
module wherever it wants to.  It does this quite nicely based on a best fit
algorithm.  I have never yet had a code module that was bigger than a page,
or even close to it.  I have had data modules bigger and handled that by
making separate one-off exceptions in the linker control file for that
project.  I've only had to do that once in over two dozen PIC projects, and
that happened to be a personal project.

Now that the code within a module is all guaranteed to be on the same page,
I use the convention that PCLATH is always pointing to that page.  It is the
responsibility of the caller (or GOTOer) to set PCLATH to the new page.  I
can forget about PCLATH when doing GOTOs and CALLs within a module.  To call
a global routine in some other module, I use the GCALL marco.  This sets
PCLATH before the call and restores it after.

The GCALL and other macros are in STD.INS.ASPIC which can be found at
http://www.embedinc.com/pic.  This page also describes a bunch of "standard"
modules I use with most PIC projects and provides template modules where you
can fill in the blanks to make your own PIC project.  These are the same
template files I use when creating a new project.  Click on the "HAL example
project" link to see the modules and source code for a real project.  You
can see that the executable part of this project was broken into 9 separate
modules.

I've described this a number of times before, although in less detail.  I
get the impression that I'm preaching to deaf ears, but I'm not sure why.
Do others think my method is silly, don't "see the light", have something
better, don't understand the description, don't think it solves the problem,
or what?  I don't think it's lack of interest because this issue of PCLATH
and code pages seems to come up every week or two.  Meanwhile I'm cranking
out reliable, maintainable PIC projects without wasting time on PCLATH bugs.


********************************************************************
Olin Lathrop, embedded systems consultant in Littleton Massachusetts
(978) 742-9014, EraseMEolinspamspamspamBeGoneembedinc.com, http://www.embedinc.com

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


2001\04\19@160212 by uter van ooijen & floortje hanneman

picon face
> Hi Olin, I have been playing with PICs long enough
> that page switching is not really a problem for me,
> but I would be interested to learn what an expert
> prefers as a *general system* for coding around the
> page problem.

I'm working on the page setting code for my compiler. The only really
general (functions are not restricted to one page) and reasonably effecient
way I could think of is

1- code generation inserts page settings before EACH jump or call (actually
not exactly before the intstruction, that would make conditional jumps
impossible)
2- optimization starts by marking all page settings 'unneeded'
3- control flow analysis identifies page settings that set a different page
than the current actual page setting, and marks those 'needed'
4- step 3 is repeated untill no new page instructions are marked 'needed'

I think it is very hard if not impossible to do this in assembly macro's.
Can anyone tell how other compilers do this? Any better idea's?

Wouter

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


2001\04\19@160428 by Andrew Warren

face
flavicon
face
Kübek Tony <RemoveMEPICLISTKILLspamspamMITVMA.MIT.EDU> wrote:

> > I see that lots of people have tried to make similar macros that
> > automatically assemble a short call when possible, but I've
> > never seen anyone succeed.
>
> Well true in part as previously stated due to the two pass
> nature of the compiler.
> ....
> As it is impossible to actually change code size dynamically one
> has to settle for second best, in this case using LONG_CALL
> *everythere* in your program until routines has stabilized into
> their 'own' pages. Then looking at the message output one can
> change every call that does not require both page bits to be
> changed

Tony and David:

Keep in mind that the assembler only chokes on FORWARD references
(i.e., on calls to labels that appear LATER in the source file).  If
you put all your subroutines at the START of your source file, and
order them so that every call is to a label that appears BEFORE the
call, there ARE no forward-referenced calls, so you can use a long-
call macro that sets and restores exactly the required number (zero,
one, or two) of page bits.

It's real easy to do, especially if you use macros like this to
locate your subroutines:

   P0SUB_START MACRO
               ORG LAST_P0_ADDRESS
               ENDM

   P0SUB_END   MACRO
   LAST_P0_ADDRESS SET $
               ENDM

   P1SUB_START MACRO
               ORG LAST_P1_ADDRESS
               ENDM

   P1SUB_END   MACRO
   LAST_P1_ADDRESS SET $
               ENDM

   etc...

Then you place the following above all your code:

   LAST_P0_ADDRESS SET 0     ;(or 5, or whatever)
   LAST_P1_ADDRESS SET 0800H
   etc...

Precede each page-0 subroutine with "P0SUB_START" and follow it with
"P0SUB_END", and bracket page-1, page-2, and page-3 subroutines the
same way.  That way, you can order them in your source file according
to their nested-call hierarchy rather than grouping all the
subroutines by the page they're on.

Your page-0 main code follows, prefaced by "ORG LAST_P0_ADDRESS",
page-1 main code is prefaced by "ORG LAST_P1_ADDRESS", etc.

-Andy


=== Andrew Warren - fastfwdSTOPspamspamspam_OUTix.netcom.com
=== Fast Forward Engineering - San Diego, California
=== http://www.geocities.com/SiliconValley/2499

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


2001\04\19@161703 by Andrew Warren

face
flavicon
face
Olin Lathrop <spamBeGonePICLISTSTOPspamspamEraseMEMITVMA.MIT.EDU> wrote:

> Now that the code within a module is all guaranteed to be on the
> same page, I use the convention that PCLATH is always pointing to
> that page. It is the responsibility of the caller (or GOTOer) to
> set PCLATH to the new page.  I can forget about PCLATH when doing
> GOTOs and CALLs within a module.  To call a global routine in some
> other module, I use the GCALL marco.  This sets PCLATH before the
> call and restores it after.
> ....
> I get the impression that I'm preaching to deaf ears, but I'm not
> sure why. Do others think my method is silly, don't "see the
> light", have something better, don't understand the description,
> don't think it solves the problem, or what?

Olin:

Many of us -- perhaps justifiably, perhaps not; I'm not going to go
off on that tangent -- don't use the linker, so we can't use your
method.  Even so, though, your method doesn't guarantee that all
CALLs and GOTOs will be optimized, since every one of your inter-
module branches uses the longest-possible code even when it's
unnecessary to do so.

That may be ok -- and the peace-of-mind, don't-ever-worry-about-
PCLATH benefits are certainly substantial -- but if the question is
"How do I guarantee that each GOTO or CALL will assemble to code
that's as short as possible," your solution isn't the answer.

-Andy


=== Andrew Warren - KILLspamfastfwdspamBeGonespamix.netcom.com
=== Fast Forward Engineering - San Diego, California
=== http://www.geocities.com/SiliconValley/2499

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


2001\04\19@205748 by jamesnewton

face picon face
Olin, re: your frustration with deaf ears, I can commiserate as I often
think that I do not communicate effectively what I see or have done. I think
what is needed is a step by step, click on this, type in that, here is why
you are doing it, example of how you would code a sample project. The
modules could be mostly nops or nonsense but the setup of the files and the
exact menus and options selected in MPLAB Maybe even screen shots with
Alt+PrintScreen, Start \ Programs \ Accessories \ Paint, Image \ Attributes,
Width: 1, Height: 1, Ok, Edit \ Paste, Yes (enlarge the bitmap), File \
SaveAs, ImageType: Gif or JPEG.

Put that up on your site (I'll mirror it if you like) and I'll point the
"Beginners checklist for PICs" page and the "Paging" page to it as an
example of how to get MPLAB to just do it for you.

---
James Newton (PICList Admin #3)
EraseMEjamesnewtonspamEraseMEpiclist.com 1-619-652-0593
PIC/PICList FAQ: http://www.piclist.com or .org

{Original Message removed}

2001\04\19@210206 by jamesnewton

face picon face
I never could (didn't take the time to) get the linker to work. That is the
sticking point in Olin's method for many people I think.

Again, a tutorial on using the linker would make me willing to try it again,
next time I work with a PIC anyway <GRIN>.

---
James Newton (PICList Admin #3)
@spam@jamesnewton@spam@spamspam_OUTpiclist.com 1-619-652-0593
PIC/PICList FAQ: http://www.piclist.com or .org

{Original Message removed}

2001\04\19@210613 by Olin Lathrop

face picon face
> That may be ok -- and the peace-of-mind, don't-ever-worry-about-
> PCLATH benefits are certainly substantial -- but if the question is
> "How do I guarantee that each GOTO or CALL will assemble to code
> that's as short as possible," your solution isn't the answer.

I don't believe it is possible to optimize every call and goto with the
existing assembler/linker.  Therefore I was trying to answer the question
"what's the best workable method that gets the customer what he wants most
reliably, maintainably, and cheaply"?


********************************************************************
Olin Lathrop, embedded systems consultant in Littleton Massachusetts
(978) 742-9014, spamBeGoneolinspamKILLspamembedinc.com, http://www.embedinc.com

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


2001\04\19@233120 by Bill Westfield

face picon face
> [Olin's paging macros]
> I've described this a number of times before, although in less detail.  I
> get the impression that I'm preaching to deaf ears, but I'm not sure why.

I think the problem is that a lot of people are used to code examples that
run entirely in a single page, so they don't need to worry about pclath at
all.  There's a congnitive jump involved going from not worrying about
pclath at all, to using it everywhere - a sort of "I only added one function
in page1 and now I have to use the lcall macros everywhere?  I don't get it!"

It's a bit like programming in C with the old 8086/80286 compilers.  All
sorts of effort went into "small" and "medium" compile models that conserved
(some) memory and execution speed by not paying attention to the segment
registers.  People got themselves into all sorts of trouble because some
functions would eventually end up beyond one of those 64k limits, and they'd
mix their models together.  Things would have been a lot easier to just use
entirely "huge" model semantics that always paid attention to the segments.

The "problem" is particularly visible on small microcontrollers - people
hate to "waste" memory if they can possible avoid it.  In fact, of course,
if you just crossed that page boundry, then you have a LOT of program memory
available - double what you're using so far.  And in a microcontroller
environment, your code either fits or it doesn't - there's none of this
"runs out of memory if quickkeys is installed", or "requires a system with
the 256k memory upgrade to run at all."

Olin - do you have a methodology for "squeezing" out the extra page handling
code if you're really tight on bytes?

BillW

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


2001\04\19@234013 by Thomas N

picon face
Hopefully, in the future, Microchip makes a single page of memory so we can
forget all about the PCLATH problem!
Thomas


{Quote hidden}

_________________________________________________________________________
Get Your Private, Free E-mail from MSN Hotmail at http://www.hotmail.com.

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


2001\04\20@013939 by Andrew Warren

face
flavicon
face
Olin Lathrop <.....PICLISTspamRemoveMEMITVMA.MIT.EDU> wrote:

> I don't believe it is possible to optimize every call and goto with
> the existing assembler/linker.

   As I showed in my earlier message, it IS possible, and it only
   requires a little bit of discipline.

> Therefore I was trying to answer the question "what's the best
> workable method that gets the customer what he wants most reliably,
> maintainably, and cheaply"?

   Your method is certainly reliable, maintainable, and cheap.  I'd
   stop short of calling it the "best" or "most", but that's just
   me; perhaps what I want is different from what your customer
   wants.

   -Andy


=== Andrew Warren - RemoveMEfastfwdspamspamBeGoneix.netcom.com
=== Fast Forward Engineering - San Diego, California
=== http://www.geocities.com/SiliconValley/2499

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email spamBeGonelistserv@spam@spamspam_OUTmitvma.mit.edu with SET PICList DIGEST in the body


2001\04\20@042521 by Alan B. Pearce

face picon face
>you put all your subroutines at the START of your source file, and
>order them so that every call is to a label that appears BEFORE the
>call, there ARE no forward-referenced calls, so you can use a long-
>call macro that sets and restores exactly the required number (zero,
>one, or two) of page bits.

Sounds like we should get some training in Pascal and then write in
assembler.

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email TakeThisOuTlistservspamspammitvma.mit.edu with SET PICList DIGEST in the body


2001\04\20@042620 by Alan B. Pearce

face picon face
> I get the impression that I'm preaching to deaf ears, but I'm not
> sure why. Do others think my method is silly, don't "see the
> light", have something better, don't understand the description,
> don't think it solves the problem, or what?

Perhaps they have all converted to C and let the compiler worry about it?

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email listservEraseMEspammitvma.mit.edu with SET PICList DIGEST in the body


2001\04\20@063559 by Bob Ammerman

picon face
----- Original Message -----
From: "Thomas N" <RemoveMEthomasn101EraseMEspamspam_OUTHOTMAIL.COM>
To: <@spam@PICLISTRemoveMEspamEraseMEMITVMA.MIT.EDU>
Sent: Thursday, April 19, 2001 11:39 PM
Subject: Re: [PIC]: Page Switching Problem


> Hopefully, in the future, Microchip makes a single page of memory so we
can
> forget all about the PCLATH problem!
> Thomas

The future is upon us : see the 18C architecture.

Bob Ammerman
RAm Systems
(contract development of high performance, high function, low-level
software)

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email EraseMElistservspam@spam@mitvma.mit.edu with SET PICList DIGEST in the body


2001\04\20@072518 by Roman Black

flavicon
face
Olin Lathrop wrote:

{Quote hidden}

Thanks for taking the time to explain all that Olin,
it's appreciated. Very different from the way I do
things. (BTW I crank out reliable code with no PCLATH
bugs too!)

Being an old C programmer for PC I use the linker
there as standard procedure, most of my favorite
personal code is in modules.

But when I started with PICs, especially the 1k
16F84 it seemed easier to ignore the linker and just
cut and paste text pieces of my favorite code.
Obviously now because I am doing more work with
larger PICs this means a re-structuring of the way I
do things, and as we all know good programming is not
about understanding opcodes and saving a few cycles,
it's about designing good *systems*.

I try and keep the main code and all it's small
fast routines on page 0, then any real large code
items (big dedicated procedures) I put on their
own page. These procedures are generally done from
start to finish.

If that system is not possible I try to divide
code into "groups" that are more modular, ie, are
very unlikely to access bits of each other. Then
the modules are on different pages and it means
that although calls across pages are not eliminated
they are reduced in a sensible manner.

Thanks again for describing your system. I am also
interested in learning more about the linker too
if anyone has advice or online info.
:o)
-Roman

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email @spam@listservspam_OUTspam.....mitvma.mit.edu with SET PICList DIGEST in the body


2001\04\20@072930 by Roman Black

flavicon
face
Andrew Warren wrote:

> Olin:
> That may be ok -- and the peace-of-mind, don't-ever-worry-about-
> PCLATH benefits are certainly substantial -- but if the question is
> "How do I guarantee that each GOTO or CALL will assemble to code
> that's as short as possible," your solution isn't the answer.


Hi Andy, So do you have a preferred system of handling
pages? I'm not talking PCLATH problems, more about system
design and structure stuff.
:o)
-Roman

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email spamBeGonelistservEraseMEspammitvma.mit.edu with SET PICList DIGEST in the body


2001\04\20@090746 by Olin Lathrop

face picon face
> Olin, re: your frustration with deaf ears, I can commiserate as I often
> think that I do not communicate effectively what I see or have done. I
think
> what is needed is a step by step, click on this, type in that, here is why
> you are doing it, example of how you would code a sample project. The
> modules could be mostly nops or nonsense but the setup of the files and
the
> exact menus and options selected in MPLAB Maybe even screen shots with
> Alt+PrintScreen, Start \ Programs \ Accessories \ Paint, Image \
Attributes,
> Width: 1, Height: 1, Ok, Edit \ Paste, Yes (enlarge the bitmap), File \
> SaveAs, ImageType: Gif or JPEG.

I don't use MPLAB that way.  I have a source code control and build system
for everything, not just creating PIC executables.  When building PIC code,
this system runs MPASM, MPLIB, and MPLINK in batch mode.  I only use MPLAB
for debugging.  In fact, I've had to create wrappers around the three
executables because they don't even return proper status codes on failure,
etc.  My MPASM wrapper makes MPASM produce an error file, then inspects the
error file.  If errors are found, they are emitted to standard output and
the wrapper exits with status indicating error.  It also does some pathname
handling.

Since I have this extra program between my source and MPASM, I've added some
pre-processor capabilities.  Instead of repeating the explanation, here is a
snippet from the documentation file that explains the pre-processor
directives:

 /INBIT name port bit

      Declares a particular I/O bit and indicates that the I/O bit
      will be used as an input.  PORT is the address of the port
      register containing the bit, and BIT is the bit number within
      the register.  The following assembler constants will be
      declared:

        <name>_reg   -  Address of port register containing I/O bit.

        <name>_tris  -  Address of TRIS register controlling in/out
             direction.

        <name>_bit   -  number of bit within port and tris regs for
             this I/O bit.

      In addition the VAL_TRISp (where P is the port name, like "A")
      assembler variable will be updated to indicate this bit is an
      input bit.

      For example,

        /inbit xyz porta 3

      Declares bit 3 of porta (RA3 pin) to be an input, and the
      following assembler declarations will be written:

        xyz_reg  equ  porta
        xyz_tris equ  trisa
        xyz_bit  equ  3

      In addition, bit 3 of the assembler variable VAL_TRISA will be
      set.

 /OUTBIT name port bit [val]

      Just like /INBIT except that it declares the I/O bit to be an
      output instead of an input.  This means the VAL_TRISp assembler
      variable will be updated to indicate this bit is an output.

      The optional VAL parameter is the value this bit should be set
      to on system initialization.  VAL must be either 0 or 1.  The
      VAL_PORTp assembler variable will be updated with its
      appropriate bit set to VAL.


********************************************************************
Olin Lathrop, embedded systems consultant in Littleton Massachusetts
(978) 742-9014, olinspamBeGonespamembedinc.com, http://www.embedinc.com

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email RemoveMElistserv@spam@spamspamBeGonemitvma.mit.edu with SET PICList DIGEST in the body


2001\04\20@090752 by Olin Lathrop

face picon face
> I never could (didn't take the time to) get the linker to work. That is
the
> sticking point in Olin's method for many people I think.

Hmm.  Sounds like people are afraid of the linker.  I don't see why because
it seems to be rather straight forward and solid.  The linker chapter is a
lot shorter than the MPASM chapter, so it takes relatively little time to
learn.  It worked for me first time, every time, based solely on the
information in that chapter.  Maybe I should provide a template linker
control file on my web site.


********************************************************************
Olin Lathrop, embedded systems consultant in Littleton Massachusetts
(978) 742-9014, .....olin@spam@spamEraseMEembedinc.com, http://www.embedinc.com

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email .....listservRemoveMEspammitvma.mit.edu with SET PICList DIGEST in the body


2001\04\20@090757 by Olin Lathrop

face picon face
> Olin - do you have a methodology for "squeezing" out the extra page
handling
> code if you're really tight on bytes?

No, but in over two dozen PIC projects this has yet to be an issue.
Remember that PCLATH code is only added for calls between modules, not
within a module.

If it ever became an issue, I would force the two modules in question to be
loaded onto the same code page.  This is easy to do in the source code
because I already have each code page set up as a separate linker section.
After adding explanation comments in both modules, I would add a private
macro to the calling module that just calls the MCALL (local module call)
macro, then replace the GCALLs in question with the private version of
MCALL.  By not using MCALL directly, it documents the special nature of that
particular call and allows a path to get back in case things change.


********************************************************************
Olin Lathrop, embedded systems consultant in Littleton Massachusetts
(978) 742-9014, .....olinSTOPspamspam@spam@embedinc.com, http://www.embedinc.com

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email listservEraseMEspam@spam@mitvma.mit.edu with SET PICList DIGEST in the body


2001\04\20@090803 by Olin Lathrop

face picon face
> > I don't believe it is possible to optimize every call and goto with
> > the existing assembler/linker.
>
>     As I showed in my earlier message, it IS possible, and it only
>     requires a little bit of discipline.

I don't remember seeing any method that does this.  I still don't think it
is possible.  Perhaps we are working from two different problem statements?
I absolutely don't want any "manual" method.  Those are tedius, and more
important, error prone.  Would you care to remind me of your solution?


********************************************************************
Olin Lathrop, embedded systems consultant in Littleton Massachusetts
(978) 742-9014, RemoveMEolinspamspamBeGoneembedinc.com, http://www.embedinc.com

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email spamBeGonelistservKILLspamspam@spam@mitvma.mit.edu with SET PICList DIGEST in the body


2001\04\20@093018 by Thomas C. Sefranek

face picon face
Olin Lathrop wrote:

> > I never could (didn't take the time to) get the linker to work. That is
> the
> > sticking point in Olin's method for many people I think.
>
> Hmm.  Sounds like people are afraid of the linker.  I don't see why because
> it seems to be rather straight forward and solid.  The linker chapter is a
> lot shorter than the MPASM chapter, so it takes relatively little time to
> learn.  It worked for me first time, every time, based solely on the
> information in that chapter.  Maybe I should provide a template linker
> control file on my web site.

I must admit, I have to get re-aquainted with a linker,
so YES, do a template.

>
>
> ********************************************************************
> Olin Lathrop, embedded systems consultant in Littleton Massachusetts
> (978) 742-9014, olinspam_OUTspam@spam@embedinc.com, http://www.embedinc.com
>
> --
> http://www.piclist.com#nomail Going offline? Don't AutoReply us!
> email spamBeGonelistserv@spam@spammitvma.mit.edu with SET PICList DIGEST in the body

--
 *
 |  __O    Thomas C. Sefranek  RemoveMEtcsEraseMEspamKILLspamcmcorp.com
 |_-\<,_   Amateur Radio Operator: WA1RHP
 (*)/ (*)  Bicycle mobile on 145.41, 448.625 MHz

ARRL Instructor, Technical Specialist, VE Contact.
hamradio.cmcorp.com/inventory/Inventory.html
http://www.harvardrepeater.org

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email spamBeGonelistservspam_OUTspamRemoveMEmitvma.mit.edu with SET PICList DIGEST in the body


2001\04\20@095311 by Olin Lathrop

face picon face
> ... and as we all know good programming is not
> about understanding opcodes and saving a few cycles,
> it's about designing good *systems*.

Right on!  The only part I disagree with is "we all know".  It seems you can
say this to someone 100 times, but the revelation ultimately has to come
from within.  I haven't found a good way to get the great unwashed
masses to see the light.

> I am also
> interested in learning more about the linker too
> if anyone has advice or online info.

I guess I should put build scripts and such on my web site.  Some day
<sigh>.  For now maybe this will help.  This is my default linker control
file for the 16F876 (my favorite "universal" PIC):

//   Linker control file for the PIC 16F876 processor.
//
CODEPAGE NAME=config START=0x2007  END=0x2007 //special processor config word

CODEPAGE NAME=code0      START=0  END=0x7FF //code page 0
CODEPAGE NAME=code1  START=0x800  END=0xFFF //code page 1
CODEPAGE NAME=code2 START=0x1000 END=0x17FF //code page 2
CODEPAGE NAME=code3 START=0x1800 END=0x1FFF //code page 3

DATABANK NAME=bank0  START=0x20  END=0x6F //register bank 0
DATABANK NAME=bank1  START=0xA0  END=0xEF //register bank 1
DATABANK NAME=bank2 START=0x110 END=0x16F //register bank 2
DATABANK NAME=bank3 START=0x190 END=0x1EF //register bank 3

SHAREBANK NAME=globalram  START=0x70  END=0x7F PROTECTED //global regs, bank 0
SHAREBANK NAME=globalram  START=0xF0  END=0xFF PROTECTED //global regs, bank 1
SHAREBANK NAME=globalram START=0x170 END=0x17F PROTECTED //global regs, bank 2
SHAREBANK NAME=globalram START=0x1F0 END=0x1FF PROTECTED //global regs, bank 3

SECTION NAME=.udata_shr RAM=globalram //global memory mapped to all register banks
SECTION NAME=.BANK0 RAM=bank0 //for registers explicitly in bank 0
SECTION NAME=.BANK1 RAM=bank1 //for registers explicitly in bank 1
SECTION NAME=.BANK2 RAM=bank2 //for registers explicitly in bank 2
SECTION NAME=.BANK3 RAM=bank3 //for registers explicitly in bank 3


********************************************************************
Olin Lathrop, embedded systems consultant in Littleton Massachusetts
(978) 742-9014, .....olinspamRemoveMEembedinc.com, http://www.embedinc.com

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email listservspam@spam@mitvma.mit.edu with SET PICList DIGEST in the body


2001\04\20@111517 by Roman Black
flavicon
face
Thanks!:o)
-Roman


Olin Lathrop wrote:

{Quote hidden}

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email spamBeGonelistservspam@spam@mitvma.mit.edu with SET PICList DIGEST in the body


2001\04\20@120621 by Olin Lathrop

face picon face
> CODEPAGE NAME=code0      START=0  END=0x7FF file://code page 0
> CODEPAGE NAME=code1  START=0x800  END=0xFFF file://code page 1
> CODEPAGE NAME=code2 START=0x1000 END=0x17FF file://code page 2
> CODEPAGE NAME=code3 START=0x1800 END=0x1FFF file://code page 3
> ...

I noticed that my mailer (MS Outlook Express) displayed these and other
lines incorrectly because it thought the double slash was a reference to a
file, and therefore inserted "file:" in front of it.  Please note that the
"file:" is NOT part of a valid linker control file.  If you save the email
message into a text file it will get written correctly.

Sorry to bother those whos mailers did display this correctly.


********************************************************************
Olin Lathrop, embedded systems consultant in Littleton Massachusetts
(978) 742-9014, RemoveMEolinspam_OUTspamembedinc.com, http://www.embedinc.com

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email listservspamspammitvma.mit.edu with SET PICList DIGEST in the body


2001\04\20@123554 by Andrew Warren

face
flavicon
face
Olin Lathrop <spam_OUTPICLISTspam_OUTspamspam_OUTMITVMA.MIT.EDU> wrote:

> > > I don't believe it is possible to optimize every call and goto
> > > with the existing assembler/linker.
> >
> > As I showed in my earlier message, it IS possible, and it only
> > requires a little bit of discipline.
>
> I don't remember seeing any method that does this.  I still don't
> think it is possible.  Perhaps we are working from two different
> problem statements? I absolutely don't want any "manual" method.
> Those are tedius, and more important, error prone.  Would you care
> to remind me of your solution?

Olin:

Before I do... I've been reading over this thread, and it occurs to
me that my comments might have seemed a bit antagonistic.  Please
understand that I didn't mean to give that impression.

Ok...

My method involved placing subroutines FIRST in the source file, and
ordering them according to their call hierarchy.  Once that's done,
there are no forward references to them, so a long-call macro which
dynamically decides whether to generate 1, 3, or 5 bytes of code will
work.

It's not tedious, and if an error is made in the ordering, the
assembler points it out immediately.

-Andy


=== Andrew Warren - fastfwdspam_OUTspamix.netcom.com
=== Fast Forward Engineering - San Diego, California
=== http://www.geocities.com/SiliconValley/2499

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email RemoveMElistservKILLspamspam@spam@mitvma.mit.edu with SET PICList DIGEST in the body


2001\04\20@125004 by David Cary

flavicon
face
[Executive summary: When I looked at absolute mode vs. the linker, Olin
Lathrop's system made the most sense to me for handling ROM paging, so I'm using
it. Also, I liked James Cameron's stack-based math package]

Dear Olin Lathrop,

Olin Lathrop <olin_piclistspamBeGonespam.....EMBEDINC.COM> on 2001-04-19 12:45:56 PM wrote:
> I don't like manually allocating anything.
> First, I use the linker.  I don't know why more people don't do this
...
> I have NEVER yet used absolute mode.

Same for me -- so far all my programs have used the linker.

I hate manually specifying stuff like addresses when I don't even care what the
address is. When I assign a specific address, you can be sure there is a reason.

> You can now group functional blocks into separate modules.  This also
> provides a natural place to document the interfaces between the functional
> blocks.

Yes, the ".inc" files in assembler now act just like the ".h" header files I'm
used to from the C language.

> I have never yet had a code module that was bigger than a page,
> or even close to it.  I have had data modules bigger
...
> once in over two dozen PIC projects

Same for me. Each code module (in its own file) is far less than 1 ROM page.
I got to play with the
 piclist.com/techref/datafile/charset/extractor/charset_extractor.htm
 by Nikolai Golovchenko
which is very cool and saved me a *lot* of time.
But at 96 chars * 3 or more words per char, it immediately overflows a single
page (fortunately, I could just cut-and-paste code from
 www.piclist.com/techref/microchip/tables.htm
to handle it).

...
> It is the
> responsibility of the caller (or GOTOer) to set PCLATH to the new page.

It's impossible to get around setting PCLATH here, anyway.

>  I
> can forget about PCLATH when doing GOTOs and CALLs within a module.  To call
> a global routine in some other module, I use the GCALL marco.
...
> I
> get the impression that I'm preaching to deaf ears, but I'm not sure why.
> Do others think my method is silly, don't "see the light", have something
> better, don't understand the description, don't think it solves the problem,
> or what?  I don't think it's lack of interest because this issue of PCLATH
> and code pages seems to come up every week or two.  Meanwhile I'm cranking
> out reliable, maintainable PIC projects without wasting time on PCLATH bugs.

I think your GCALL is great. Thanks for putting your file online.

I'm just using MPLAB directly right now, your development system sounded a
little complex ... but eventually I'll want to build my projects by typing
"make" or clicking a button (including re-generating fonts from modified font
".png" files), so I'll probably end up with something like your system. Why does
everyone have to re-invent the wheel ?

nit-pick:

--- file std.ins.aspic at http://www.embedinc.com/pic
...
setpage  macro   adr
...
        pagesel adr
 if fam_16 && (ncodepages == 2) ;need NOP bug workaround ?
        nop
   endif
...
    endm
...
mypage   macro
...
        local   here
        setpage here
here
        endm
...
--- end file

Um, I've deleted that ``nop'' in my copy of that file. This works for me in code
I have currently running on a 16F877 chip:

--- file std.ins.inc on david's development machine:
...
mypage   macro
        local   here
        pagesel here
here
        endm

fcall     macro subroutine_name
    lcall subroutine_name
    mypage    ; just in case we do *local* calls or gotos before the next
fcall.
    endm
...
----

> this issue of PCLATH
> and code pages seems to come up every week or two.  Meanwhile I'm cranking
> out reliable, maintainable PIC projects without wasting time on PCLATH bugs.
...
> Olin Lathrop

I'm guessing that people who use your macros or something similar never have a
problem, so they don't even think about it any more. It's newbies who are trying
to write code from scratch and are trying to deal with "pages" and "banks"
manually with BCF and BSF, spending lots of time manually adjusting them, who
get more and more confused and post lots of questions. (Fortunately, my MPASM
quick reference guide lists the PAGESEL, BANKSEL, and BANKISEL pseudo-ops right
up front, so I was saved from most of this confusion).

I'm just using the MPLAB environment directly now, typing code in its editor
(wish I had a editor with proper syntax coloring).

My application (at the moment) is RAM limited and ROM limited, rather than speed
limited. I like
 James Cameron's stack-based math package.
 http://quozl.us.netrek.org/stack-math.asm
His subroutines are a little longer and slower than some of the super-optimized
macros I've seen here, but I only need 1 copy of this "increment a 32 bit
counter", rather than a separate routine for each counter I have. Since I use a
HP calculator, I'm familiar with stack operations.

I'm pretty sure that recycling common subroutines ("factoring", in FORTH-speak)
saves more bytes than the few I "waste" on extra PCLATH manipulation. Currently
I don't worry about the data stack (it's 8 deep in the 16F87x series I use); if
I ever do overflow it -- well, I'll worry about that then.

-- David Cary

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email KILLspamlistservspam.....mitvma.mit.edu with SET PICList DIGEST in the body


2001\04\20@162511 by Olin Lathrop

face picon face
> [Executive summary: When I looked at absolute mode vs. the linker, Olin
> Lathrop's system made the most sense to me for handling ROM paging, so I'm
using
> it. Also, I liked James Cameron's stack-based math package]

Thanks for letting me know.  I guess putting all that stuff on the web site
wasn't a waste of time after all.

{Quote hidden}

in code
> I have currently running on a 16F877 chip:

This wouldn't make any difference on a 16F877 anyway because it has 4 code
pages, not 2.  Note that the NOP is only inserted when the processor has
exactly 2 code pages.  This was to work around an MPLINK bug a few versions
ago.  It's probably been fixed by now, but I haven't gone back and verified
it yet so I've left the NOP in there.

The problem was that Microchip messed up the transition from the old way of
implementing PAGESEL to the new way.  The old method did a MOVLW, MOVWF
PCLATH.  This always took 2 instructions and always trashed W.  About a year
ago (?) they updated PAGESEL to to BSF/BCF on PCLATH.  On machines with 4 or
less pages (all the current relevant machines) this never exceeds 2
instructions and never trashes W, so it's definitely superior.  The problem
was that they forgot to tell the linker that PAGESEL sometimes only became
one instruction instead of two.  Note that this only mattered on machines
with exactly 2 code pages.  On these machines, the linker would trash the
following instruction by making it a NOP if I remember correctly.  I ran
into this problem on a 16C923, which has exactly 2 code pages.  I guessed
what was going on by looking at the code in memory and Microchip confirmed
my suspicions.  Adding a NOP after each PAGESEL worked around the problem.

Again, I haven't verified the bug is fixed, which is why I left in the NOP
workaround for now.  I'll probably do that next time I use a machine with
two code pages.  I recommend you leave the workaround in unless you KNOW
this has been fixed.


********************************************************************
Olin Lathrop, embedded systems consultant in Littleton Massachusetts
(978) 742-9014, spam_OUTolinspamKILLspamembedinc.com, http://www.embedinc.com

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email RemoveMElistservRemoveMEspamEraseMEmitvma.mit.edu with SET PICList DIGEST in the body


2001\04\20@162520 by Olin Lathrop

face picon face
> My method involved placing subroutines FIRST in the source file, and
> ordering them according to their call hierarchy.  Once that's done,
> there are no forward references to them, so a long-call macro which
> dynamically decides whether to generate 1, 3, or 5 bytes of code will
> work.
>
> It's not tedious, and if an error is made in the ordering, the
> assembler points it out immediately.

That solves part of the problem but still leaves some unresolved issues.  I
wouldn't personally use this method because:

1  -  It forces all code into a single file.  This causes maintenance
headaches and makes it impossible to enforce clean interfaces between
functional blocks.  You could use include files sortof like modules, but you
wouldn't get the separate name spaces for local symbols.  This makes it
nearly impossible to take independently written modules from different
projects and incorporate them into a new project.

2  -  Code for a functional block may be scattered around with routines from
other functional blocks in between depending on the call hierarchy.  This
makes it very difficult to properly document the functional blocks.  If the
call hierarchy changes you have to change positions of routines in the
source file.  At least the assembler tells you when it is necessary, but
it's still a pain.

3  -  It only takes care of CALLs, not GOTOs.  You can't order jump points
to be only at the beginning.  A page transition will happen somewhere in the
code.  What if

loop  blah
     blah
     btfsc ...
     goto  loop

and the page transition happens to come between LOOP and the GOTO LOOP?  As
I understand your method, there is nothing to handle and fix this.


********************************************************************
Olin Lathrop, embedded systems consultant in Littleton Massachusetts
(978) 742-9014, KILLspamolinspamspamBeGoneembedinc.com, http://www.embedinc.com

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email listservspamspammitvma.mit.edu with SET PICList DIGEST in the body


2001\04\22@151446 by Andrew Warren

face
flavicon
face
Olin Lathrop <RemoveMEPICLISTspamBeGonespamRemoveMEMITVMA.MIT.EDU> wrote:

> > My method involved placing subroutines FIRST in the source file, and
> > ordering them according to their call hierarchy.  Once that's done,
> > there are no forward references to them, so a long-call macro which
> > dynamically decides whether to generate 1, 3, or 5 bytes of code
> > will work.
>
> That solves part of the problem but still leaves some unresolved
> issues.  I wouldn't personally use this method because:
>
> 1  -  It forces all code into a single file.

   No, it doesn't.

> This causes maintenance headaches

   No, it doesn't.

> and makes it impossible to enforce clean interfaces between
> functional blocks.

   No, it doesn't.

> You could use include files sortof like modules, but you wouldn't
> get the separate name spaces for local symbols.  This makes it
> nearly impossible to take independently written modules from
> different projects and incorporate them into a new project.

   Ok, that's true, but you're going off on a tangent here.  The
   local-name-space issue is an argument for using the linker in
   general; it's not a direct argument against the method I
   suggested for optimizing CALLs.

   Besides, local name-spaces are a pain in the ass when you're
   debugging.  If I have twenty variables called "COUNTER", I don't
   want to have to figure out which one I'm looking at in my
   emulator at any given time.

> 2  -  Code for a functional block may be scattered around with
> routines from other functional blocks in between depending on the
> call hierarchy.  This makes it very difficult to properly document
> the functional blocks.

   This presupposes that your code MUST be thought of as a
   collection of "functional blocks", each of which may have
   multiple subroutines.  You said earlier that you've never
   written PIC code any other way, so I understand that you're
   locked into this mode of thinking, but that doesn't necessarily
   mean that the rest of us are.

   Even if we agree that the modularized, black-box
   functional-block model is the best one to use when writing PIC
   code, there's never a problem with a functional block being
   broken up due to call hierarchy, since -- IF THE BLOCKS ARE
   WRITTEN PROPERLY -- each functional block is its own branch on
   the hierarchy tree.  Show me a "functional block" whose internal
   subroutines can be called from within other functional blocks,
   and I'll show you:

       a) A block that should have been split into two separate
       blocks, or

       b) A "library" file each of whose subroutines should be
       individually documented ANYWAY.

> If the call hierarchy changes you have to change positions of
> routines in the source file.  At least the assembler tells you when
> it is necessary, but it's still a pain.

   Agreed, but it doesn't happen much, even at the start of a
   project.

> 3  -  It only takes care of CALLs, not GOTOs.

   GOTOs take care of themselves, since each page starts (or SHOULD
   start, anyway) with an ORG directive.

{Quote hidden}

   My method assumes that the guy using it is neither a complete
   idiot nor a novice PIC programmer.

   Anyone who writes code that just spills over from one page into
   the next deserves to be bitten by this.

   -Andy


=== Andrew Warren - KILLspamfastfwdspamBeGonespamix.netcom.com
=== Fast Forward Engineering - San Diego, California
=== http://www.geocities.com/SiliconValley/2499

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads


2001\04\23@104455 by Roman Black

flavicon
face
Olin Lathrop wrote:

{Quote hidden}

Hi Olin, again thanks for taking the time to disect
your system for us. I have spent the last couple of
days reading chapter 4 of MPASM guide, How to use
relocatable objects, and checking my own projects
I realised i've been doing a similar thing by cut
and pasting my code modules in text format, and
many of my common routines are in separate .asm
files that I include when I need them in the main
.asm file.

I think that it's time to start refining some
of my routines to relocatable modules but i'm a
bit confused as to some of the problems;

Do you use your GCALL macro for every call from
the main routine to the modules?? I understand your
modules use local calls within themselves.
It would be nice if the linker were optimising,
and only inserted the minimum code for any call.

As many modules use the same shared (global) data
to manipulate it, do your modules use banksel on
every access of these variables?? Isn't that slow?

Sorry to fire questions at you, I downloaded the
files from your embedinc.com page and the hal
project also but haven't had the chance to go
right through them yet. :o)
-Roman

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics


2001\04\23@180728 by Olin Lathrop

face picon face
> Do you use your GCALL macro for every call from
> the main routine to the modules??

I use GCALL for every call between modules, whether its from the main
routine or not.  However, I sometimes don't call event routines that handle
events when they are detected by the main loop.  I usually use the
convention that code for handling a specific event jumps back to LOOP_MAIN,
which is the start of the event check loop.  This gives events a priority
with the first checked the highest priority.  Since the main event loop
doesn't need the general register preserved and since event handling
routines don't need to return, I GOTO them instead of CALL them.  If they
are external to the MAIN module, then use GJUMP (global jump, sets PCLATH
before the GOTO).

> I understand your
> modules use local calls within themselves.
> It would be nice if the linker were optimising,
> and only inserted the minimum code for any call.

Yes, but unfortunately it isn't.  This method does do unnecessary PCLATH
diddling when calling between modules that happened to end up on the same
page, but this is probably rather trivial from the overall system point of
view.  If it were to ever be an issue, I would force the modules in question
onto the same page with the CODE directive, then use a local call.  I would
make a new locally defined macro for this, just to document the particular
calls and to allow a way to get back to GCALL if things changed.

> As many modules use the same shared (global) data
> to manipulate it, do your modules use banksel on
> every access of these variables?? Isn't that slow?

No, yes.  I always define a global assembly constant called GBANK which is
the register bank the ordinary global state is in.  You can see this
declaration in the template QQQ.INS.ASPIC or in the example HAL.INS.ASPIC.
The constant GBANKADR is automatically derived from GBANK, and is an address
within the GBANK bank.  GBANKADR can be used with DBANKIF to set the bank
for access to the global state.

By convention, each module declares the local assembler constant LBANK and
LBANKADR which is the bank and address within bank for local persistant
state used privately by that module.  I don't like allocating state to
particular banks at assembly time, but the advantage is that you know which
bank it is in at assembly time and can therefore do clever things with that
information, like the DBANKIF and related macros.  If the convention is
followed, then it is easy to move local state of a module from one bank to
another just by changing the LBANK value for the module.

Note also that you're not stuck having just GBANK for global state.  You can
make up your own names for other groups of state.  I've done this for I/O
buffers and the like sometimes.  For example, BUFBANK and BUFBANKADR might
be for the UART I/O FIFOs.


********************************************************************
Olin Lathrop, embedded systems consultant in Littleton Massachusetts
(978) 742-9014, @spam@olinSTOPspamspam@spam@embedinc.com, http://www.embedinc.com

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics


2001\04\24@035129 by Roman Black

flavicon
face
Thanks Olin, will take a me a couple of days to
digest. Would it be possible to write a gcall
macro that knows the calling page and only uses
the minimum code needed? If the macro can keep a
record of the page of the last call and only gcall
macro is used it will always know current (calling)
page and can insert correct code...
-Roman



Olin Lathrop wrote:
{Quote hidden}

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


2001\04\24@090552 by Olin Lathrop

face picon face
> Thanks Olin, will take a me a couple of days to
> digest. Would it be possible to write a gcall
> macro that knows the calling page and only uses
> the minimum code needed? If the macro can keep a
> record of the page of the last call and only gcall
> macro is used it will always know current (calling)
> page and can insert correct code...

Unfortunately the code page is not known at assembly time.  The linker would
need to be a lot smarter, and the assembler would need to leave special
instructions for the linker to conditionally insert page swapping code.  I
have been tempted to write such an assembler/linker myself, but there always
seem to be more pressing issues to take care of first.


********************************************************************
Olin Lathrop, embedded systems consultant in Littleton Massachusetts
(978) 742-9014, spamBeGoneolinspamembedinc.com, http://www.embedinc.com

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


More... (looser matching)
- Last day of these posts
- In 2001 , 2002 only
- Today
- New search...