We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
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
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)
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???