• AVR Freaks

Hot!Call Above 2K limit

Page: 123 > Showing page 1 of 3
Author
Designer
Super Member
  • Total Posts : 432
  • Reward points : 0
  • Joined: 2007/11/20 20:28:41
  • Location: 0
  • Status: offline
2019/08/12 04:13:39 (permalink)
0

Call Above 2K limit

I use PIC16F1508 PIC & my program is really long & subroutines are placed bottom of my code above 2K limit.
 
Do I still need to write to PCLATH when I call subroutines above 2K limit with this modern PICs as well?
#1

54 Replies Related Threads

    ric
    Super Member
    • Total Posts : 23581
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: Call Above 2K limit 2019/08/12 04:19:08 (permalink)
    +1 (1)
    Yes, the mechanism for calling across pages is still the same.
    You don't mention it, but I assume you are working in assembler. If you were using C then the compiler would manage it all.
    Some careful planning, placing all your lookup tables in a separate page, and grouping related code together can reduce how often you need to call from one page to another.

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #2
    kl27x
    Super Member
    • Total Posts : 253
    • Reward points : 0
    • Joined: 2006/09/20 13:51:48
    • Location: 0
    • Status: offline
    Re: Call Above 2K limit 2019/08/18 03:51:11 (permalink)
    0
    lcall subroutine.label      ;this is all you need to do in your assembly code when calling to a different page
                                        ;this expands to two instructions in enhanced midrange PIC.
    pagesel $                      ;this will set PCLATH back to the current page after the return. 
                                        ;this pagesel directive takes a single instruction with the enhanced midrange PIC.
     
    or
     
    pagesel subroutine.label   
    call subroutine.label
    pagesel $
     
     
    If you are calling multiple interpage subroutines that are located (and also return from) the same page you don't necessarily need to do that for each one. Example:
     
    org 0x100
    lcall subroutine.on.page.1              ;located on page 1 between 0x800 and 0xFFF and returns from this page
     
    ...
    addwf registerA
    incf  registerB
    ...
     
    call another.subroutine.on.page.1  ;also located between 0x800 and 0xFFF
    ;you can do more stuff, as long as it is not a branch
    pagesel $
    decfsz registerA,f
     
    You have to make sure you set PCLATH back to the current page before any instruction that results in a branch. Skip if's and goto's and BRW/addwfpcl. Or a local call. if PCLATH is set to a page other than the current one, you can also just lcall a local subroutine, and after it returns (again, provided it returns from the same page), PCLATH would already be set to the current page, so no need to pagesel $, after.)
     
    I wish someone explained this stuff to me 10 years ago. Took me a long time to actually understand paging. 
     
     
     
     
     
     
    post edited by kl27x - 2019/08/18 04:02:34
    #3
    1and0
    Access is Denied
    • Total Posts : 9623
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Call Above 2K limit 2019/08/18 04:00:14 (permalink)
    0
    kl27x
    Skip if's and goto's and BRW/addwfpcl. 

    Please clarify this.
    #4
    kl27x
    Super Member
    • Total Posts : 253
    • Reward points : 0
    • Joined: 2006/09/20 13:51:48
    • Location: 0
    • Status: offline
    Re: Call Above 2K limit 2019/08/18 04:05:41 (permalink)
    0
    ^These instruction result in a local branch/jump. Thus, PCLATH must be returned back to the current page before this is executed, else the branch will jump to the page where you left PCLATH. 
     
    You do not necessarily need to return PCLATH to the current page immediately after the stack pops. Like if you have a lot of subroutines on page1, but your main code loop is on page0, you can leave PCLATH set to page1 until your code must perform one of these instructions (and/or must make a local call).
     
    Note that after the stack pops, PCLATH will be set to wherever it was when the stack popped. So a subroutine might start on page1, but it might return from page2. After calling that subroutine from page1, PCLATH will be set to page2 upon the return.
    post edited by kl27x - 2019/08/18 04:14:28
    #5
    ric
    Super Member
    • Total Posts : 23581
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: Call Above 2K limit 2019/08/18 04:09:00 (permalink)
    0
    I  think it is the first part "skip ifs ..." that 1and0 is querying.
    There is no "if" instruction, so I assume you mean the BTFSS and BTFSC instructions (and maybe DECFS/INCFSZ), which do NOT depend upon PCLATH.
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #6
    kl27x
    Super Member
    • Total Posts : 253
    • Reward points : 0
    • Joined: 2006/09/20 13:51:48
    • Location: 0
    • Status: offline
    Re: Call Above 2K limit 2019/08/18 04:16:20 (permalink)
    0
    Yes, that's what I meant... all of those 4 instructions. Well, damn, I'm glad I made that mistake. I shall have to try this and learn something new. 
     
    And what of relative goto's? Goto $+3   ?
    post edited by kl27x - 2019/08/18 04:22:39
    #7
    1and0
    Access is Denied
    • Total Posts : 9623
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Call Above 2K limit 2019/08/18 04:25:09 (permalink)
    +1 (1)
    kl27x
    And what of relative goto's? Goto $+3   ?

    GOTO depends on PCLATH.
    #8
    1and0
    Access is Denied
    • Total Posts : 9623
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Call Above 2K limit 2019/08/18 04:25:36 (permalink)
    +1 (1)
    kl27x
    Note that after the stack pops, PCLATH will be set to wherever it was when the stack popped. So a subroutine might start on page1, but it might return from page2. After calling that subroutine from page1, PCLATH will be set to page2 upon the return.

    You might want to think about that some more. :)
     
    #9
    kl27x
    Super Member
    • Total Posts : 253
    • Reward points : 0
    • Joined: 2006/09/20 13:51:48
    • Location: 0
    • Status: offline
    Re: Call Above 2K limit 2019/08/18 04:29:24 (permalink)
    0
    ^Please enlighten me. :)
     
    To my erudite brain, it seems like PCLATH should always be on the current page after it returns. Else how would it know where to return to?
     
    But yet, PCLATH is always set to the page where it returned from, in my decades of practice. I'm always eager to learn what I'm doing wrong. 
     
    For example:
    0rg 0x0000
    lcall subroutine.page1
    call another.subroutine.page1
    ;this works
     
    When first writing a subroutine that crossed page boundaries, I was stumped over how to deal with it for probably weeks. I came here for help, and no one could explain it (in a way I could understand.) Trial and error to figure this out. Documentation just not clear.  
     
    So for instance, 
    org 0x000
    call 0x700 ;local call. but subroutine continues to page1 before returning
    pagesel 0h ; I find it is necessary to set PCLATH back to page0, after this "local" call.
     
    ; and if call can return from multiple pages, then PCLATH is undetermined and must be set before a branch. 
     
     
    post edited by kl27x - 2019/08/18 04:42:48
    #10
    1and0
    Access is Denied
    • Total Posts : 9623
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Call Above 2K limit 2019/08/18 04:45:27 (permalink)
    +1 (1)
    kl27x
    ^Please enlighten me. :)

    Let's say your subroutine cross to another page:
            org     0x0FFF
    MySub   nop     ; page 1 here
            nop     ; page 2 here
            return

    To call MySub, PCLATH must first be set to Page1. After returning from MySub, PCLATH is still set to Page1, not Page2.
     
     
    To my erudite brain, it seems like PCLATH should always be on the current page after it returns. Else how would it know where to return to?

    The return is done by popping the hardware stack, which contains the full address for the return.
     

    But yet, PCLATH is always set to the page where it returned from, in my decades of practice. I'm always eager to learn what I'm doing wrong. 

    Wrong, PCLATH does not change based on what page the code is current executing from.
     

    When first writing a subroutine that crossed page boundaries, I was stumped over how to deal with it for probably over a week. Trial and error to figure this out. Documentation just not clear.  
     
    So for instance, 
    org 0x000
    call 0x700 ;local call. but subroutine continues to page1 before returning
    pagesel 0h ; I find it is necessary to set PCLATH back to page0, after a this local call.

    pagesel 0h is not necessary here as long as the subroutine does not change PCLATH.
     

    ; and if call can return from multiple pages, then PCLATH is undetermined and must be set before a branch. 

    No, PCLATH is always known.  <edit> Unless you meant the subroutine changed PCLATH, then you will have to reset PCLATH to whereever you will branch to after that. </edit>
     
    post edited by 1and0 - 2019/08/18 04:51:53
    #11
    ric
    Super Member
    • Total Posts : 23581
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: Call Above 2K limit 2019/08/18 04:58:52 (permalink)
    +1 (1)
    As Harry said ^^^^^^
    Bottom line, NOTHING changes PCLATH except manual writes to it.
    PCLATH is NOT the high byte of the current PC, it is simply a latch which is written to that high byte whenever GOTO/CALL is executed, or something writes to PCL.
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #12
    ric
    Super Member
    • Total Posts : 23581
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: Call Above 2K limit 2019/08/18 05:10:52 (permalink)
    +1 (1)
    kl27x
    .
    And what of relative goto's? Goto $+3   ?

    and just to be clear, there ARE NO relative GOTOs.
    The assembler evaluates the "$+3" expression, and puts the absolute address in there.
    The actual instruction is identical to "GOTO label" assuming you had "label:" three instructions later.
     
    Enhanced PIC16F parts do have a relative branch instruction (BRA and BRW).
    Neither of those instructions uses PCLATH.
     
     
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #13
    1and0
    Access is Denied
    • Total Posts : 9623
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Call Above 2K limit 2019/08/18 05:14:29 (permalink)
    0
    Also, in case you have not caught on, the pseduo-instructions
            lcall   sub

    is actually
            pagesel sub
            call    sub

    and
            lgoto    sub

    is actually
            pagesel sub
            goto    sub

    #14
    kl27x
    Super Member
    • Total Posts : 253
    • Reward points : 0
    • Joined: 2006/09/20 13:51:48
    • Location: 0
    • Status: offline
    Re: Call Above 2K limit 2019/08/18 05:17:13 (permalink)
    0
    Ok, wow. So I'm trying to wrap my brain around my apparent misunderstanding and trying to figure out how I fluked into getting working code. I think I got it. 
     
    so example
    0rg 0x7FE   ;page0
    pagesel 0h
    nop
    ;.............page1 ;0x0800
    goto $+1
     
     
    So this "goto $+1" would send the PC to 0x001, rather than 0x801?
     
    Admittedly, since "fixing" this code, I have never again crossed a page boundary without throwing in a pagesel + goto, for maintainability reasons. So to me, if a subroutine crosses pages, it would always have PCLATH set to the page from where it returns... and I must have overgeneralized, then, right?
     
     
     
     
     
     
     
    #15
    1and0
    Access is Denied
    • Total Posts : 9623
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Call Above 2K limit 2019/08/18 05:19:10 (permalink)
    0
    ric
    Bottom line, NOTHING changes PCLATH except manual writes to it.

    I've never had the need to to this, but I seem to recall reading PCL will update PCLATH.
    #16
    ric
    Super Member
    • Total Posts : 23581
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: Call Above 2K limit 2019/08/18 05:24:07 (permalink)
    0
    1and0
    ric
    Bottom line, NOTHING changes PCLATH except manual writes to it.

    I've never had the need to to this, but I seem to recall reading PCL will update PCLATH.

    I had a similar thought at the back of my mind, but I cannot find any mention of it in the datasheets.

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #17
    1and0
    Access is Denied
    • Total Posts : 9623
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Call Above 2K limit 2019/08/18 05:29:28 (permalink)
    0
    kl27x
    So this "goto $+1" would send the PC to 0x001, rather than 0x801?

    Correct.
     

    Admittedly, since "fixing" this code, I have never again crossed a page boundary without throwing in a pagesel + goto, for maintainability reasons. So to me, if a subroutine crosses pages, it would always have PCLATH set to the page from where it returns... and I must have overgeneralized, then, right?

    Like we said, PCLATH does not change based on what page your code is executing from. You the programmer has control over what value PCLATH has.
    #18
    1and0
    Access is Denied
    • Total Posts : 9623
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Call Above 2K limit 2019/08/18 05:41:18 (permalink)
    0
    ric
    1and0
    ric
    Bottom line, NOTHING changes PCLATH except manual writes to it.

    I've never had the need to to this, but I seem to recall reading PCL will update PCLATH.

    I had a similar thought at the back of my mind, but I cannot find any mention of it in the datasheets.

    I found this in the PIC18F2520 datasheet:
     
    The contents of PCLATH and PCLATU are transferred
    to the program counter by any operation that writes
    PCL. Similarly, the upper two bytes of the program
    counter are transferred to PCLATH and PCLATU by an
    operation that reads PCL.
     
    I'd assume the same will occur in the PIC16 devices. ;)
     
    #19
    kl27x
    Super Member
    • Total Posts : 253
    • Reward points : 0
    • Joined: 2006/09/20 13:51:48
    • Location: 0
    • Status: offline
    Re: Call Above 2K limit 2019/08/18 05:43:17 (permalink)
    0
    ... But IF PCL updates PCLATH.... then this is one of two ways to cross a page boundary. 
     
    The other being a branch... which can only get to the other page if you set PCLATH.
     
    So IF in my example, that goto $+1 actually goes to 0x801, then what I said is fundamentally correct? If the subroutine crosses pages, it has to be one of those two ways, no?
     
    And if that "goto $+1" takes the PC to 0x001, then what I said is maybe sorta practically correct? Because crossing a page boundary in your code without delineating it with an org statement and actually setting PCLATH would be.... kinda stupid? Any editing of your code would change where the code crossed that boundary. I suppose when out of space and trying to cram the last bit in there, it might be an exception. 
     
    So do I understand correctly, or did I reveal additional ignorance? I'm very grateful for your guys' corrections. 
     
     
    post edited by kl27x - 2019/08/18 05:47:29
    #20
    Page: 123 > Showing page 1 of 3
    Jump to:
    © 2019 APG vNext Commercial Version 4.5