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

C166: Call-segmented to a ram-address does not work

Hello,

I use a ST10F269 (SMALL-modell) with Keil C166 v6.
I try to call a RAM-routine (in XRAM2) from ROM (in Segment 2 => all code is located within 64kB in Segment 2) via assembler routine:

BCLR IEN
CALLS #0,#SOF fls_ram
BSET IEN

fls_ram is a variable at address 0xDBBE

What I expect is, that the call is to address 0xDBBE but it is to address 0x9BBE (14bit address).

When I use:
MOV R4, #SOF fls_ram
it works fine, I have the 16bit-address in register R4 but not with CALLS, JMPS, ..

Are there restrictions for the use of #SOF?
How can I jump to the RAM-area (in a different segment)?

Thanks for the help!

Best Regards,
Josef Aspelmayr

  • Maybe this is not what you are asking but did you try this.

      CALLS #SEG fls_ram, #SOF fls_ram
    

    Regards,
    Chris

  • Yes,

    I tried:

    CALLS #SEG fls_ram, #SOF fls_ram
    

    The result is the same, segment is 0x0 and address is 0x9BBE and not 0xDBBE..

    What is really strange for me is the fact, that when I use..

    MOV R4, #SOF fls_ram
    


    ..I have the correct value in R4 but not when I use CALLS/JMPS.

    Thanks and best regards
    Josef Aspelmayr

  • fls_ram is a variable at address 0xDBBE

    I think you mean routine or symbol?

    Did you double check the map/.m66 file? And the linker file?

    According to http://www.keil.com/support/docs/688.htm :
    This function combines the segment (DPP register) and offset to get a real 16-bit address.

    Could it be that the fls_ram routine is in DPP space and the DPP contains 0? Naah, that doesn't make sense either...

    It -is- weird...

    Good luck!
    Joost Leeuwesteijn

  • fls_ram is a variable (array) in XRAM. I copy the code to XRAM, then I want to start the code. Thats the reason why I call/jump to a RAM-address.

    And the address (0xDBBE) is from map-file..

    Best Regards,
    Josef Aspelmayr

  • I am not sure how you have everything defined in your project. But if I try a sample program everything is working as I would expect.

    unsigned int fls_ram[50];
    
    extern void MyFunc (void);
    
    void main(void) {
    
      fls_ram[0] = 0x00DB;  /* RETS instruction */
      MyFunc();
    
      for(;;);
    }
    

    I defined a RAM section from 0x40000--0x4FFFF
    040140H fls_ram VAR --- NDATA0 ?ND0?MAIN

    Here is the assembly file:

    $NOMACRO
    $SEGMENTED CASE
    $MODINF (43)
      NAME MYASM
    
      NCODE  CGROUP  ?PR?MYASM
    
      ASSUME  DPP3 : SYSTEM
    
      REGDEF   R0 - R15
      EXTERN fls_ram:WORD
    
      ?PR?MYASM  SECTION  CODE WORD 'NCODE'
    
      MyFunc  PROC  NEAR
      PUBLIC  MyFunc
    
      CALLS   #SEG fls_ram, #SOF fls_ram
      RET
    
      MyFunc  ENDP
    
      ?PR?MYASM  ENDS
      END
    

    If you run this code it jumps to the RAM location (0x40140) and then does a RETS, just as expected.

         5: void main(void) {
         6:
         7:   fls_ram[0] = 0x00DB;  /* RETS instruction */
    00020000 E6F4DB00  MOV      R4,#0x00DB
    00020004 F6F44081  MOV      DPP2:0x0140,R4
         8:   MyFunc();
         9:
    00020008 CA000E00  CALLA    CC_UC,MyFunc(0x2000E)
        10:   for(;;);
    0002000C 0DFF      JMPR     CC_UC,0x02000C
        18:   CALLS   #SEG fls_ram, #SOF fls_ram
    0002000E DA044001  CALLS    0x040140
        19:         RET
    

    Sorry not sure how to help you. Perhaps you can reduce your problem to a small working code snippet then others could look to find the problem?

    Best regards,
    Chris

  • Hello Chris,

    thanks for the help!

    I have tried your code-snippet, but with variable located in XRAM-area:

    00C200H     fls_ram  VAR   ---  NDATA0  ?ND0?TEST
    

    And it works!

    But I have tried to do the same with #pragma ASM and I get the same failure:

    unsigned int fls_ram[50];
    
    void MyFunc(void);
    
    void main(void) {
    
      fls_ram[0] = 0x00DB;  /* RETS instruction */
      MyFunc();
    
      for(;;);
    }
    
    void MyFunc(void)
    {
    
    #pragma ASM
      CALLS   #0, #SOF fls_ram
    #pragma ENDASM
    }
    

    In that case I have a:

    CALLS 0x8200
    


    .. so this is wrong!

    Best Regards,
    Josef

  • I left off the reference to the DPP in the extern reference in the separate assembly file.

    It appears the environment always assumes a data access (which it should) and this is why the DPP is causing you an issue (you don't want this).

    If you want to jump to a variable then I would create a function pointer assigned to the data variable address and then call it (keeping everything in C). Here is an example.

    unsigned int fls_ram[50];
    
    void (far *MyFunc)(void) = (void far *)(&fls_ram[0]);
    
    void main (void) {
    
      fls_ram[0] = 0x00DB;  /* RETS instruction */
    
      (*MyFunc)();          /* call MyFunc in XRAM */
    
      for(;;);
    }
    

    Best regards,
    Chris

  • Despite the DPP-addressing, the SOF-Operator shall use the 16bit-address (and this should be done with any opcode-variant).

    I was in contact with Keil and according to Support-Team this is a compiler-issue and will be solved.

    Thanks for all the help!

    Best Regards,
    Josef

  • I was in contact with Keil and according to Support-Team this is a compiler-issue and will be solved.

    Seems like you've found a bug! Nice work (reporting it)!

    I was thinking it might help to explicitly declare the fls_ram variable as huge/xhuge in the C file? To make sure it doesn't use near/DPP. But this would generate the same #SOF instruction I guess, not sure.

    Regards,
    Joost Leeuwesteijn