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

LX51 RESERVE directive

I have a "classic" bank-switched project using LX51 that needs to reserve some address ranges to prevent code from being assigned to those areas. I have a linker directive thus:

RESERVE (0xf000-0xffff,0x1fff8-0x1ffff)

yet the linker will happily locate code in the reserved addresses:

00EFF5H 00EFFDH 000009H BYTE UNIT CODE/B1 ?L?COM00F0
00EFFEH 00F00CH 00000FH BYTE UNIT CODE/B1 ?L?COM038F
00F00DH 00F015H 000009H BYTE UNIT CODE/B1 ?L?COM0290
00F016H 00F022H 00000DH BYTE UNIT CODE/B1 ?L?COM0298
00F023H 00F02FH 00000DH BYTE UNIT CODE/B1 ?L?COM030C
00F030H 00F03FH 000010H BYTE UNIT CODE/B1 ?L?COM0374
00F040H 00F049H 00000AH BYTE UNIT CODE/B1 ?L?COM04B5
00F04AH 00F051H 000008H BYTE UNIT CODE/B1 ?L?COM0574

I noticed on review of the manual that the description of the RESERVE directive just says "address ranges of the physical memory", but doesn't make a distinction between code and data space. Perhaps the correct thing to do is use CLASSES to limit the address map, e.g.

CLASSES (CODE (0 - 0xf000, 0x10000 - 0x1fff8))

I have "Use Memory Layout from Target Dialog" checked, so the default CLASSES is

XDATA (X:0x0-X:0x7FFF), HDATA (X:0x0-X:0x7FFF), CODE (C:0x0-C:0x7FFF), ECODE (C:0x0-C:0x7FFF), HCONST (C:0x0-C:0x7FFF))

I've found in the past that if CODE is allowed to grow beyond 0x7fff, then code that should be limited to the common bank (0 - 0x7fff) can be located in the high end of the bank area (0x8000 - 0xffff) if such space happens to be unused by the code for that bank. That layout is bugged, since there's no guarantee that the upper bank with necessary code will happen to be switched in.

How do I keep the linker from placing code into certain address ranges?

  • You need to include the bank prefix with the addresses. For example,

    LX51 ... RESERVE(B0:0X808000-B0:0X808FFF,
                     B1:0X818000-B1:0X818FFF,
                     C:0X200-C:0X2FF)
    

    results in the following memory map (from the linker):

    * * * * * * * * * * *   C O D E   M E M O R Y   * * * * * * * * * * * * *
    
    ***   CODE BANK 0   ***
    808000H   808FFFH   001000H   ---    ---      *** RESERVED MEMORY ***
    009000H   00901BH   00001CH   BYTE   UNIT     CODE/B0        ?PR?FUNC0?C_BANK0
    
    ***   CODE BANK 1   ***
    818000H   818FFFH   001000H   ---    ---      *** RESERVED MEMORY ***
    009000H   00901BH   00001CH   BYTE   UNIT     CODE/B1        ?PR?FUNC1?C_BANK1
    
    ***   CODE BANK 2   ***
    008000H   008018H   000019H   BYTE   UNIT     CODE/B2        ?PR?FUNC2?C_BANK2
    
    ***   COMMON AREA   ***
    000000H   000002H   000003H   ---    OFFS..   CODE           ?CO??C_STARTUP?0
    000003H   000063H   000061H   BYTE   INBLOCK  CODE           ?BANK?SELECT
    000064H   0000F1H   00008EH   BYTE   UNIT     CODE           ?C?LIB_CODE
    0000F2H   00017DH   00008CH   BYTE   UNIT     CODE           ?C_C51STARTUP
    00017EH   0001E5H   000068H   BYTE   UNIT     CODE           ?CO?C_ROOT
    0001E6H   0001EDH   000008H   BYTE   UNIT     CODE           ?C_INITSEG
    0001EEH   0001FFH   000012H   ---    ---      **GAP**
    000200H   0002FFH   000100H   ---    ---      *** RESERVED MEMORY ***
    000300H   00065BH   00035CH   BYTE   UNIT     CODE           ?PR?PRINTF?PRINTF
    00065CH   0006A1H   000046H   BYTE   UNIT     CODE           ?CO?C_BANK1
    0006A2H   0006E7H   000046H   BYTE   UNIT     CODE           ?CO?C_BANK0
    


    I've found in the past that if CODE is allowed to grow beyond 0x7fff, then code that should be limited to the common bank (0 - 0x7fff) can be located in the high end of the bank area (0x8000 - 0xffff) if such space happens to be unused by the code for that bank. That layout is bugged, since there's no guarantee that the upper bank with necessary code will happen to be switched in.


    Yes. This is documented in the manual: http://www.keil.com/support/man/docs/lx51/lx51_bk_commonarea.htm.

    However, the common area that is copied to each code bank starts at the low end of each bank.

    Also, there is a ?B_RST_BANK option in the L51_BANK.A51 file that specifies which code bnak is switched in at reset.

    If your configuration has a way to select NO code bank, you may need to monitor the size of the common area very carefully. Otherwise, the normal banking system should work well.

    Jon

  • Thanks for the help on the syntax for RESERVE. Is the high order bit necessary? That is, RESERVE (B0:0x80f000-0x80ffff) rather than RESERVE (B0:0xf000-B0:0xffff)?


    If the ROM area that is dedicated as common area is not large enough to contain the entire common code, the linker duplicates the remaining part of the common code area into the beginning of each code bank.

    The behavior that I saw was the the high end of the bank area would contain common bank code. That is, common would range from 0 - 7fff, then there would be bank code from 8000 - e900 (say), and then there would be more common code from e900 up. This behavior was with the "Off-Chip Code Memory" in uVision set to 0 - 0xffff, which apparently translates to a CLASSES (CODE()) directive to the linker. Restricting the range to 0 - 0x7fff solves the problem. I assumed this was just misconfiguration on my part. (But maybe discrepancies between CODE and BANKAREA rate a warning?)

  • RESERVE (B0:0xf000-B0:0xffff) is just fine.

    Reinhard