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

LOCATING SUBROUTINES IN MEMORY

I am trying to put a subroutine at a fixed address (I want it to remain fixed after the code is rebuilt and other modules are changed).

First I linked my code and obtained its absolute linked address (assigned by the linker). Then I used the _at_ (0x07A) command in the C source file.
I got a FIXUP error when I linked.
When I did the same thing using the linker SE command, I didn't get any errors. I really wanted to cast the addresses in the source
C code file using the _at_ command but I am having problems.... Any thoughts...



Thanks, Jim

Parents
  • I don't believe I am trying to put the subroutine too far away from the callers
    because I am putting it exactly where the linker puts it when I don't explicitly
    locate it using the _at_ declaration. (part of my C code)

    The reason I want to explicitly specify the addresses is because I don't want
    the linker change them if code is modified or added to the build.
    (I have set up two separate memory areas (one on the processor for bootloading and flash memory writing)
    and the other in the external flash memory for the functional code. (this
    code will be modified during integration -- the onboard code will not)

Reply
  • I don't believe I am trying to put the subroutine too far away from the callers
    because I am putting it exactly where the linker puts it when I don't explicitly
    locate it using the _at_ declaration. (part of my C code)

    The reason I want to explicitly specify the addresses is because I don't want
    the linker change them if code is modified or added to the build.
    (I have set up two separate memory areas (one on the processor for bootloading and flash memory writing)
    and the other in the external flash memory for the functional code. (this
    code will be modified during integration -- the onboard code will not)

Children
  • Can you post the code snippets, and the warning? This might give someone here enough info to help...

  • This is part of my link file *************************************
    // Internal Code is from FF:0000 - FF:F7FFF
    // I don't want any entry point addresses to change when external code
    // is modified


    SE(?PR?TIMER0_ISR?TMR0_ISR (0FF0080H),
    ?PR?SERIALINTR?SER_ISR,
    ?PR?INIT_SERIAL_COMM?INIT_SER,


    ?PR?RETURN_CSCI_BLK_ACK?BMSGHDLR,
    ?PR?unsolicited_send_b_status?BMSGHDLR,

    ?PR?INIT_TIMER?INIT_TMR,

    ?PR?MAIN?BOOT_EXE,

    ?PR?INIT_FLASH_BUFFER?FLASH,
    ?PR?buffer_write_to_flash?FLASH,
    ?PR?process_ihex_to_buffer?FLASH,

    ?C_INITEDATA,
    ?C_C51STARTUP,



    // ****************This is EXTERNAL FLASH CODE


    ?PR?mux_main?MUX_MAIN (0FF8000H),
    ?PR?transfer_flash_blks_to_RAM?MUX_MAIN,

    ?PR?msg_hdlr?MSG_HDLR,
    ?PR?store_upload_data?MSG_HDLR,


    // ****** OUTPUT FROM LINKER
    ACTIVE MEMORY CLASSES OF MODULE: D:\MUX_JU~2\MUX_CSCI (BMSGHDLR)

    BASE START END MEMORY CLASS
    ==========================================
    000000H 000000H 00041FH EDATA
    FF0000H FF0000H FFFFFFH CODE
    010000H 010000H 01FFFFH XDATA
    000000H 000000H FFFFFFH HDATA
    000000H FF0000H FFFFFFH HCONST
    000000H 008000H 00FFFFH NCONST
    000000H 000000H 0000FFH IDATA
    000000H 000000H 00007FH DATA


    MEMORY MAP OF MODULE: D:\MUX_JU~2\MUX_CSCI (BMSGHDLR)


    START STOP LENGTH ALIGN RELOC MEMORY CLASS SEGMENT NAME
    =========================================================================
    000000H 000007H 000008H --- AT.. DATA "REG BANK 0"
    000008H 00000BH 000004H BYTE UNIT IDATA _IDATA_GROUP_
    000018H 00001FH 000008H --- AT.. DATA "REG BANK 3"
    000020H 000256H 000237H BYTE UNIT EDATA ?ED?BOOT_EXE
    000257H 000356H 000100H BYTE UNIT EDATA ?STACK
    008000H 008000H 000001H BYTE UNIT NCONST ?NC?BOOT_EXE
    010000H 0196B6H 0096B7H BYTE INSEG XDATA ?XD?BOOT_EXE
    0196B7H 0196BBH 000005H BYTE UNIT XDATA ?XD?INIT_FLASH_BUFFER?FLASH
    0196BCH 0196BDH 000002H BYTE INSEG XDATA ?XD?MUX_MAIN
    0196BEH 0196BEH 000001H BYTE INSEG XDATA ?XD?SER_ISR
    0196BFH 01987CH 0001BEH BYTE UNIT XDATA _XDATA_GROUP_

    FF0000H FF0002H 000003H --- OFFS.. CODE ?CO?START251?4
    FF0003H FF0003H 000001H BYTE UNIT CODE ?CO?MAIN?BOOT_EXE
    FF000BH FF000DH 000003H --- OFFS.. CODE ?PR?IV?1
    FF000EH FF0017H 00000AH BYTE INSEG CODE ?PR?TIMER2_ISR?BOOT_EXE
    FF0018H FF0020H 000009H BYTE INSEG CODE ?PR?TIMER2_ISR_HANDLER?BOOT_EXE
    FF0023H FF0025H 000003H --- OFFS.. CODE ?PR?IV?4
    FF002BH FF002DH 000003H --- OFFS.. CODE ?PR?IV?5
    FF002EH FF0036H 000009H BYTE UNIT HCONST ?C_INITHDATA
    FF0080H FF00C0H 000041H BYTE INSEG CODE ?PR?TIMER0_ISR?TMR0_ISR
    FF00C1H FF0202H 000142H BYTE INSEG CODE ?PR?SERIALINTR?SER_ISR
    FF0203H FF0225H 000023H BYTE INSEG CODE ?PR?INIT_SERIAL_COMM?INIT_SER
    FF0226H FF0281H 00005CH BYTE INSEG CODE ?PR?RETURN_CSCI_BLK_ACK?BMSGHDLR
    FF0282H FF02B1H 000030H BYTE INSEG CODE ?PR?STORE_CSCI_UPLOAD_DATA?BMSGHDLR

    FF05CFH FF0635H 000067H BYTE INSEG CODE ?PR?UNSOLICITED_SEND_B_STATUS?BMSGHDLR
    FF0636H FF0658H 000023H BYTE INSEG CODE ?PR?INIT_TIMER?INIT_TMR
    LINKER/LOCATER L251 V1.30 08/08/01 10:09:05 PAGE 3


    FF0659H FF0719H 0000C1H BYTE INSEG CODE ?PR?MAIN?BOOT_EXE
    FF071AH FF0773H 00005AH BYTE OFFS.. CODE ?PR?INIT_FLASH_BUFFER?FLASH
    FF0774H FF079AH 000027H BYTE INSEG CODE ?PR?AHEX2INT?FLASH
    FF079BH FF07B8H 00001EH BYTE INSEG CODE ?PR?COMPUTE_CHECKSUM?FLASH
    FF07B9H FF0AFDH 000345H BYTE INSEG CODE ?PR?BUFFER_WRITE_TO_FLASH?FLASH
    FF0AFEH FF0B79H 00007CH BYTE INSEG CODE ?PR?WRITE_DATA_TO_FLASH?FLASH
    FF0B7AH FF1026H 0004ADH BYTE INSEG CODE ?PR?PROCESS_IHEX_TO_BUFFER?FLASH
    FF1027H FF1028H 000002H BYTE UNIT HCONST ?C_INITEDATA
    FF1029H FF103BH 000013H BYTE UNIT CODE ?C_C51STARTUP
    FF103CH FF109DH 000062H BYTE UNIT CODE ?C_C51STARTUP?2
    FF109EH FF10A0H 000003H BYTE UNIT CODE ?C_C51STARTUP?3
    FF10A1H FF1137H 000097H BYTE INSEG CODE ?PR?AHEXFIELD2INT?FLASH
    FF1138H FF11EDH 0000B6H BYTE UNIT CODE ?C?LIB_CODE
    FF11EEH FF1495H 0002A8H BYTE UNIT HCONST ?HC?BOOT_EXE

    FF8000H FF8642H 000643H BYTE INSEG CODE ?PR?MUX_MAIN?MUX_MAIN
    FF8643H FF87CBH 000189H BYTE INSEG CODE ?PR?TRANSFER_FLASH_BLKS_TO_RAM?MUX_MAIN
    FF87CCH FF8AF9H 00032EH BYTE INSEG CODE ?PR?MSG_HDLR?MSG_HDLR
    FF8AFAH FF8B47H 00004EH BYTE INSEG CODE ?PR?MESSAGE_SIZE_CHECK?MSG_HDLR

    ******************************************************************************
    NOTE: I WANT TO KEEP THE INTERNAL CODE ADDRESSES FROM POSSIBLY BEING CHANGED WHEN EXTERNAL CODE
    IS UPDATED AND EVERYTHING IS REBUILT.

    IF I USE the following FLASH_GLOBAL FunctionStatus init_flash_buffer (unsigned char *src_ptr,
    unsigned char *msg_buffer_ptr,
    unsigned long buffer_size,
    unsigned char fill_value) _at_ (0xFF071A);

    (I am coding it to the same address that the linker had previously given it but I want it to be fixed in the code itself ---
    This way the entry point will never be changed inadvertantly )

    I get the following linker error
    *** Error L121 Improper Fixup
    Module: D:\MUX_JU~\BMSGHDLR.OBJ(BMSGHDLR)
    SEGMENT:?PRBOOT_MSGHDLR?BMSGHDLR
    OFFSET: 00006FH

    Maybe there is some other way that I can "lock up" the
    design so that any changes to the external code will
    not cause different code to be generated for the
    internal code. This is to be burnt once in the processor.



  • Jim

    Okay, to find the problem, first when you compile the file that has the ?PRBOOT_MSGHDLR?BMSGHDLR in it, use the CD option. This appends an assembler listing to the list file. From the listing file, find the 00006F offset address from the :?PRBOOT_MSGHDLR?BMSGHDLR segment. That instruction will contain the address that the linker cannot handle. In my example below, I could get a FIXUP message at address 000005, if the function I was calling could not be reached by that particular instruction. This can also happen with data accesses.



    ; FUNCTION Context_SaveProgId? (BEGIN)
    ; SOURCE LINE # 48
    000000 CA3B PUSH DR12
    000002 7F30 MOV DR12,DR0
    ;---- Variable 'sptr' assigned to Register 'DR12' ----
    ; SOURCE LINE # 51
    * error could appear here
    000004 9A000000 E ECALL I2CStop?
    ; SOURCE LINE # 52
    000008 9A000000 E ECALL I2CStart?
    ; SOURCE LINE # 54
    00000C 9A000000 E ECALL HwdIOWait?
    ; SOURCE LINE # 55
    000010 74D0 MOV A,#0D0H ; A=R11
    000012 9A000000 E ECALL I2CSend?
    000016 7006 JNZ ?C0001

    I think that you have a bigger problem though. I see that the C library code is also stored in the 'fixed' portion of memory. Unless this remains at the same locations, you are going to have more problems in the future, especially if the libraries change. I believe that your system has a kernel in fixed memory, and the application is loadable to flash. What you need to do is separate the fixed program from the application. In other words, the kernel should compile and link with only the code that will be fixed in memory. The application should compile and link only the code that is in external memory. Functions that are called between the application and kernel are defined in the linker with fixed addresses. When the application is linked, calls or jumps are made to those addresses. Any library functions will be present in the flash memory for the application, and any library functions will be present in the fixed memory for the kernel. In this way, if the tools are changed, you can compile and link the application knowing that the libraries are correct for that version of the compiler.

    The application needs a fixed startup address that the kernel can jump to after reset. This can also be done by using the linker to fix the address of the main() function.

    Our product has this architecture, and that is how we handled this. The application compiles and links as one object, and the kernel does likewise. There are only a few addresses that are fixed by the linker between the two, so that function calls can be made.



  • Tom

    Thanks for the help and your design comments.

    I believe that I can locate variables and subroutines where I want them in
    internal or external memory. I am concerned about the library routines
    as you pointed out. Is it possible to get the library source and then locate subroutines
    and data to external memory when the application code may require
    these utilities? I could let the linker relocate them if this is possible. Note: This
    system design should not see many changes in the functional side, however
    the fixed side (251 onboard) will not be allowed to change once burnt into the 251.

    The functional code changes will be done so as not to intentionally
    change the onboard code image.

    Any thoughts on this???