This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

User Stack Placement

I am considering placing the user stack into internal ram. It defaults into near which is assigned to the first 16k external ram. I am a bit confused about the asm in the startup file. The section Ex.1, see below, obviously places the user stack into near (NDATA) so i assume changing this to either IDATA or SDATA will do the trick. But after this, the section Ex.2, see below, refers the user stack to NDATA. So should this change too? If i change it, i get an error A77: Missing DPP info. Can anyone help tell me what is going on and if it is a good idea to move the user stack to internal ram in the first place.

Section Ex.1
?C_USERSTACK    SECTION DATA PUBLIC 'NDATA'
?C_USRSTKBOT:
                DS      USTSZ           ; Size of User Stack
?C_USERSTKTOP:
?C_USERSTACK    ENDS

Section Ex.2
$IF NOT TINY
IF (UST1SZ > 0) AND (UST2SZ > 0)        ; Define User Stack 1 area
NDATA           DGROUP  ?C_USERSTACK, ?C_USERSTACK1, ?C_USERSTACK2
ENDIF

  • For example, all three stacks to SDATA should work like this:

    ?C_USERSTACK    SECTION DATA PUBLIC 'SDATA'
    ?C_USRSTKBOT:
                    DS      USTSZ           ; Size of User Stack
    ?C_USERSTKTOP:
    ?C_USERSTACK    ENDS
    
    
    IF UST1SZ > 0                           ; Define User Stack 1 area
    ?C_USERSTACK1   SECTION DATA PUBLIC 'SDATA'
    ?C_USRSTKBOT1:
                    DS      UST1SZ          ; Size of User Stack 1
    ?C_USERSTKTOP1:
    ?C_USERSTACK1   ENDS
    ENDIF
    
    IF UST2SZ > 0                           ; Define User Stack 2 area
    ?C_USERSTACK2   SECTION DATA PUBLIC 'SDATA'
    ?C_USRSTKBOT2:
                    DS      UST2SZ          ; Size of User Stack 2
    ?C_USERSTKTOP2:
    ?C_USERSTACK2   ENDS
    ENDIF
    
    ;$IF NOT TINY
    ;IF (UST1SZ > 0) AND (UST2SZ > 0)        ; Define User Stack 1 area
    ;NDATA           DGROUP  ?C_USERSTACK, ?C_USERSTACK1, ?C_USERSTACK2
    ;ENDIF
    ;IF (UST1SZ > 0) AND (UST2SZ = 0)
    ;NDATA           DGROUP  ?C_USERSTACK, ?C_USERSTACK1
    ;ENDIF
    ;IF (UST1SZ = 0) AND (UST2SZ > 0)
    ;NDATA           DGROUP  ?C_USERSTACK, ?C_USERSTACK2
    ;ENDIF
    ;IF (UST1SZ = 0) AND (UST2SZ = 0)
    ;NDATA           DGROUP  ?C_USERSTACK
    ;ENDIF
    ;$ENDIF
    
    ?C_MAINREGISTERS        REGDEF  R0 - R15
    
    ?C_SYSSTACK     SECTION DATA PUBLIC 'IDATA'
    $IF NOT TINY
    IF (UST1SZ > 0) AND (UST2SZ > 0)
    SDATA           DGROUP  ?C_USERSTACK, ?C_USERSTACK1, ?C_USERSTACK2, ?C_SYSSTACK, SYSTEM
    ENDIF
    IF (UST1SZ > 0) AND (UST2SZ = 0)
    SDATA           DGROUP  ?C_USERSTACK, ?C_USERSTACK1, ?C_SYSSTACK, SYSTEM
    ENDIF
    IF (UST1SZ = 0) AND (UST2SZ > 0)
    SDATA           DGROUP  ?C_USERSTACK, ?C_USERSTACK2, ?C_SYSSTACK, SYSTEM
    ENDIF
    IF (UST1SZ = 0) AND (UST2SZ = 0)
    SDATA           DGROUP  ?C_USERSTACK, ?C_SYSSTACK, SYSTEM
    ENDIF
    $ENDIF
    

    Putting the stacks to SDATA is a good idea if you gain something by doing so.

    Sauli

  • Thanks, that makes obvious sense now you pointed it out! The reason i want to do this is 'speed', the NDATA section points to external ram which is obviously slow compared to internal ram. Therefore any autos not allocated to registers will be in external ram. To force an auto into internal ram would mean it would have to be made static, the compiler changes the storage class for you, which is not always good.

    If you have a better suggestion or feel the reason i am doing this is not worth it, please advise further. Thanks.

  • Hi, I found this in a help file, which appears to apply to me but i cannot find the line described at the end which contains DPP2 or 3. All i can see is :-

    IF UST1SZ > 0
    BFLDH PSW,#03H,#02H
    MOV R0,#?C_USERSTKTOP1
    ENDIF

    Can anyone help?

    -------------------------------------------------

    The USERSTACKDPP3 directive allows you to locate the user stack in the IDATA or SDATA memory classes which are accessed using DPP3. When relocating the user stack, some changes must be made to the definition of the ?C_USERSTACK section in the startup code (STARTUP.A66 or START167.A66) as follows.

    ?C_USERSTACK SECTION DATA PUBLIC 'IDATA'
    or

    ?C_USERSTACK SECTION DATA PUBLIC 'SDATA'
    In addition, you must change the following line:

    MOV R0,#DPP2:?C_USERSTKTOP
    to:

    MOV R0,#DPP3:?C_USERSTKTOP

  • The documentation may be a bit outdated regarding this. I believe the line you cannot find refers to this line a few lines down of what you were looking at:

           MOV     R0,#?C_USERSTKTOP
    


    Change it to:

           MOV     R0,#DPP3:?C_USERSTKTOP
    


    I was a bit surprised that this actually works because ?C_USERSTKTOP is still listed belonging to the NDATA group. When experimenting, I would advise you to check the link map to see where each section actually is placed and to check R0 and the DPP values to see that they do have the values you expect.

    BTW, have you looked at the HOLD compiler directive? Gives you yet another way to put more data in the internal RAM.

    Sauli

  • I was a bit surprised that this actually works because ?C_USERSTKTOP is still listed belonging to the NDATA group.

    Hi, where are you refering to when you say it still belongs to NDATA? I thought if we changed the references of NDATA to SDATA (or IDATA) this placed the stack in internal ram?

    ?C_USERSTACK    SECTION DATA PUBLIC 'NDATA'
    
    IF (UST1SZ > 0) AND (UST2SZ > 0)        ; Define User Stack area
    NDATA           DGROUP  ?C_USERSTACK, ?C_USERSTACK1, ?C_USERSTACK2
    ENDIF
    

    I have used the HOLD directive in modules to do as you suggested. Thanks.

    I am a bit confused about the DPP's now, i understand what they do but am struggling to see their useage in my application, are they only relevent in memory models that use near & far pointers? I am using 'HLarge' and i cannot see any difference is speed accessing near data than huge data. I created a simple loop which accessed data via a pointer, first in near then in huge but there was no difference in speed. As i understand the point of DPP's was to create fast access to near data. DPP2 does hold the value for the base of near data but i cannot see how its being used. DPP2=0x0020, Ext Ram=0x80000.

    Do i need to specify the DPPUSE directive or something? Or am i just being stupid! How do i check they are being used and why is access to near data no faster than huge? If there is any easy advise you can give. Thanks.

  • Hi, where are you refering to when you say it still belongs to NDATA?

    I was referring to the original startup file modified as suggested by Keil to place the stack to internal RAM. Then these lines remain saying that user stack is in NDATA:

    $IF NOT TINY
    IF (UST1SZ > 0) AND (UST2SZ > 0)        ; Define User Stack 1 area
    NDATA           DGROUP  ?C_USERSTACK, ?C_USERSTACK1, ?C_USERSTACK2
    .
    .
    IF (UST1SZ = 0) AND (UST2SZ = 0)
    NDATA           DGROUP  ?C_USERSTACK
    ENDIF
    $ENDIF
    

    The usage of the DPP registers is described in the compiler documentation. The default usage is:
    DPP0 Not used for C167.
    DPP1 Used for accessing near constants (NCONST)
    DPP2 Used for accessing near data (NDATA)
    DPP3 Used for accessing SYSTEM area, 0xC000-0xFFFF.

    You can change the usage with the DPPUSE directive.

    DPP addressing is explained in the XC167 User's Manual. The DPP registers are used in indirect and direct long (16 bit) modes. The two most significant bits of the 16 bit address (GPR or memory address) select the DPP register (and thus the page), and bits 13..0 are the offset into the page.

    For example:
    DPP2 = 0x0020
    R0 = 0x8040

    The two most significant bits of R0 are 10, which selects DPP2. The 24 bit address referenced then is:
    (DPP2 << 14) + (R0 & 0x3FF) = 0x80040

    The reason you don't see any difference in the speed of accessing near/huge data is that you access it with a pointer, which in hlarge model is a 24 bit pointer, and the DPP adressing mechanism is not used. If you know that a pointer always points to near data, you may want to explicitly tell the compiler so (e.g. char * near p;, if memory serves me correct).

    Sauli

  • Many thanks for all your help Sauli, i think i have it about sorted now. I probably shouldnt post thankyou's, but there you go.

    P.s. I thought it was as you described but this seems to be the case:-

    char * near ptr_in_near; // puts the pointer in near whereas,
    char near *near_ptr; // make it a near pointer

    Cheers.