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
  • 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.



Reply
  • 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.



Children
  • 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???