Forum Discussion
Altera_Forum
Honored Contributor
22 years agoHpw do I change the startup adr of an app
Hi
I tried writing about this before. Hope someone can help me. I have a simple program. I want to change the startup adr of my program from 0x1000000(SDRAM base adr) to for an exsample 0x1100000. I have tried to define my own custom linker script in the system library. Here below I have copied in the changes I made to the default linker script ----------------------------------------------------------------------------------------------------- MEMORY { reset : ORIGIN = 0x00000000, LENGTH = 32 ext_flash : ORIGIN = 0x00000020, LENGTH = 8388576 ext_ram : ORIGIN = 0x00800000, LENGTH = 1048576 epcs_controller : ORIGIN = 0x00900000, LENGTH = 2048 sdram_UNUSED : ORIGIN = 0x01100000, LENGTH = 32 sdram : ORIGIN = 0x01100020, LENGTH = 15728640 } /* Define symbols for each memory base-address */ __alt_mem_ext_flash = 0x00000000 ; __alt_mem_ext_ram = 0x00800000 ; __alt_mem_epcs_controller = 0x00900000 ; __alt_mem_sdram = 0x01100000 ; ----------------------------------------------------------------------------------------------------- But when I use this script nothing really happens when I starte up the program. What am I missing??? Can this be done with this script or must it be done with the ELF tools???? If yes how with the ELF tools???? Hope someone can help me since the documentation for this is none existing Best regards GreateWhite.DK13 Replies
- Altera_Forum
Honored Contributor
Somebody who knows if the boot_loader.S is used in a C++ standard project??? I can see that one can define an other CODE_BASE value. But if it is not used when I compile it dos not really matter.
Regards GreateWhite.DK - Altera_Forum
Honored Contributor
You can set the starting address of the .text segment with the -Ttext
linker command line option. For example: ld -Ttext 0x01100000 ... Alternatively, you can use objcopy with any number of various command line options (e.g. --adjust-vma). The actual __entry__ point can be set in the linker command file. In many implementations: ENTRY(_start) For example, the u-boot monitor uses the following linker command file contents, with the command line option -Ttext 0x018e0000. Regards, --ScottOUTPUT_FORMAT("elf32-littlenios2") OUTPUT_ARCH(nios2) ENTRY(_start) SECTIONS { .text : { cpu/nios2/start.o (.text) *(.text) *(.text.*) *(.gnu.linkonce.t*) *(.rodata) *(.rodata.*) *(.gnu.linkonce.r*) } . = ALIGN (4); _etext = .; PROVIDE (etext = .); /* CMD TABLE - sandwich this in between text and data so * the initialization code relocates the command table as * well -- admittedly, this is just pure laziness;-) */ __u_boot_cmd_start = .; .u_boot_cmd : { *(.u_boot_cmd) } . = ALIGN(4); __u_boot_cmd_end = .; /* INIT DATA sections - "Small" data (see the gcc -G option) * is always gp-relative. Here we make all init data sections * adjacent to simplify the startup code -- and provide * the global pointer for gp-relative access. */ _data = .; .data : { *(.data) *(.data.*) *(.gnu.linkonce.d*) } . = ALIGN(16); _gp = .; /* Global pointer addr */ PROVIDE (gp = .); .sdata : { *(.sdata) *(.sdata.*) *(.gnu.linkonce.s.*) } . = ALIGN(4); _edata = .; PROVIDE (edata = .); /* UNINIT DATA - Small uninitialized data is first so it's * adjacent to sdata and can be referenced via gp. The normal * bss follows. We keep it adjacent to simplify init code. */ __bss_start = .; .sbss : { *(.sbss) *(.sbss.*) *(.gnu.linkonce.sb.*) *(.scommon) } . = ALIGN(4); .bss : { *(.bss) *(.bss.*) *(.dynbss) *(COMMON) *(.scommon) } . = ALIGN(4); _end = .; PROVIDE (end = .); /* DEBUG -- symbol table, string table, etc. etc. */ .stab 0 : { *(.stab) } .stabstr 0 : { *(.stabstr) } .stab.excl 0 : { *(.stab.excl) } .stab.exclstr 0 : { *(.stab.exclstr) } .stab.index 0 : { *(.stab.index) } .stab.indexstr 0 : { *(.stab.indexstr) } .comment 0 : { *(.comment) } .debug 0 : { *(.debug) } .line 0 : { *(.line) } .debug_srcinfo 0 : { *(.debug_srcinfo) } .debug_sfnames 0 : { *(.debug_sfnames) } .debug_aranges 0 : { *(.debug_aranges) } .debug_pubnames 0 : { *(.debug_pubnames) } .debug_info 0 : { *(.debug_info) } .debug_abbrev 0 : { *(.debug_abbrev) } .debug_line 0 : { *(.debug_line) } .debug_frame 0 : { *(.debug_frame) } .debug_str 0 : { *(.debug_str) } .debug_loc 0 : { *(.debug_loc) } .debug_macinfo 0 : { *(.debug_macinfo) } .debug_weaknames 0 : { *(.debug_weaknames) } .debug_funcnames 0 : { *(.debug_funcnames) } .debug_typenames 0 : { *(.debug_typenames) } .debug_varnames 0 : { *(.debug_varnames) } } - Altera_Forum
Honored Contributor
Thx very much for your answer smcnutt
I am trying to look trough your post. A lot of command I don't understand. But now I have somewhere to start. Tried using the Ttext 0x1100000 command. That worked just fine and now my app can start up. But I have not had any succes with starting up my kernel yet. It just freezes when I try to call my function pointer with the adr 0x1000000(start of the kernel in SDRAM). Regards GreateWhite.DK - Altera_Forum
Honored Contributor
I'm not sure what your startup code does, but there are a few
things you might want to double-check: 1. If your startup code copies the kernel into SDRAM, make sure you flush the data cache, invalidate the instruction cache, sync, then flush the pipeline. There's a little routine that does such below. 2. Make sure interrupts are disabled. 3. Make sure you have your stack setup. 4. Check the kernel startup code to make sure its relocation implementation isn't broken. I haven't looked closely at it yet, but some (new) implementations don't do this too well ... especially if there is an overlap of source and destination locations ;-) Regards, --ScottC Interface: extern void flush_cache (void *p, unsigned len); p -pointer to base of copied code. len -length (bytes) of copied code. -------------------------------------------------------------------- .global flush_cache flush_cache: add r5, r5, r4 mov r9, r4 mov r10, r5 /* Flush data cache */ movhi r8, %hi(DCACHELINE_SIZE) ori r8, r8, %lo(DCACHELINE_SIZE) 0: flushd 0(r4) add r4, r4, r8 bltu r4, r5, 0b /* Invalidateinstruction cache */ mov r4, r9 mov r5, r10 movhi r8, %hi(ICACHELINE_SIZE) ori r8, r8, %lo(ICACHELINE_SIZE) 1: flushi r4 add r4, r4, r8 bltu r4, r5, 1b /* sync and flush the pipeline */ sync flushp ret - Altera_Forum
Honored Contributor
<div class='quotetop'>QUOTE </div>
--- Quote Start --- 1. If your startup code copies the kernel into SDRAM, make sure you flush the data cache, invalidate the instruction cache, sync, then flush the pipeline. There's a little routine that does such below.[/b] --- Quote End --- Tried using that bit of ASM code. I am very green when it comes to ASM so I don't understand much of what you are doing there. The DCACHELINE_SIZE (aka NIOS2_DCACHE_LINE_SIZE) is set to 0 in the projects system.h file. When the code is executed the NIOS dies. Interrupts are disabled. <div class='quotetop'>QUOTE </div> --- Quote Start --- 2. Make sure interrupts are disabled.[/b] --- Quote End --- Check <div class='quotetop'>QUOTE </div> --- Quote Start --- 3. Make sure you have your stack setup.[/b] --- Quote End --- Huh http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/blink.gif <div class='quotetop'>QUOTE </div> --- Quote Start --- Check the kernel startup code to make sure its relocation implementation isn't broken. I haven't looked closely at it yet, but some (new) implementations don't do this too well ... especially if there is an overlap of source and destination locations ;-)[/b] --- Quote End --- http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/unsure.gif I dunno what that is. Relocation implementation... wheres that??? Sorry that I am such a newbie at this. You clearly are not. Regards an upset GreateWhite.DK - Altera_Forum
Honored Contributor
Ok ... finally had some time to check a few things...
> When the code is executed the NIOS dies ... Hmmm ... the code was tested so I believe it to be correct. You can call it _after_ copying the kernel code. The p parameter should point to the address where you copied the kernel to, the len parameter is the length of the kernel (in bytes). >> 3. Make sure you have your stack setup. > Huh? Disregard ... the kernel code has no dependency on a bootloader stack. >> Check the kernel startup code to make sure its >> relocation implementation isn't broken. > I dunno what that is. Relocation implementation... > wheres that??? It's in arch/nios2nommu/kernel/head.S ... this is where it all begins ;-) The kernel startup code copies itself from an arbitrary address to its run-time (linked) address (vma, etc) as necessary. I didn't see any obvious problems unless ... you are copying the kernel to a location just below it's actual run-time addr such that it will overlap. The startup code does not account for such a situation ... it will over-write itself while it's relocating. Safest bet is to do one of the following: 1. Copy the kernel to its run-time address (vma). In which case your boot code must know the correct address. Or, 2. Copy the kernel up high in RAM, then let it relocate itself to a lower address. Regards, --Scott - Altera_Forum
Honored Contributor
Hi Scott
Thx for your patience with me Scott!!! <div class='quotetop'>QUOTE </div> --- Quote Start --- 1. Copy the kernel to its run-time address (vma). In which case your boot code must know the correct address.[/b] --- Quote End --- I am copying the kernel code to the VMA. I have pasted in what objdump say about my vmlinux file [SOPC Builder]$ nios2-elf-objdump -h vmlinux vmlinux: file format elf32-littlenios2 Sections: Idx Name Size VMA LMA File off Algn 0 .text 00158108 01000000 01000000 00000074 2**3 CONTENTS, ALLOC, LOAD, READONLY, CODE 1 .data 0002fef0 01158110 01158110 0015817c 2**4 CONTENTS, ALLOC, LOAD, DATA 2 .init 0000c390 01188000 01188000 0018806c 2**3 CONTENTS, ALLOC, LOAD, CODE 3 .bss 0000f08c 01194390 01194390 001943fc 2**4 . . . When I use 0x1000000(which is the SDRAM base adr) the loader simply dies. I tried using 0x1100000 as the VMA. Here it starts up the kernel, but when it died a horrible dead when it tries to start up a kernel thread. I copy the binary vmlinux.bin file simply from startadr until there is no more data to copy. <div class='quotetop'>QUOTE </div> --- Quote Start --- 2. Copy the kernel up high in RAM, then let it relocate itself to a lower address.[/b] --- Quote End --- I tried this. THAT WORKED!!! But I cannot do this in my final target board. I copied the data to 0x1200000 and then executed the code. Then the kernel started up(VMA=0x1000000). What am I doing wrong in the other case??? Regards from a bit more optimistic GreateWhite.DK http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/smile.gif - Altera_Forum
Honored Contributor
> When I use 0x1000000(which is the SDRAM base adr) the loader simply dies.
... snip ... > What am I doing wrong .... It looks like you may be corrupting your loader code during the kernel copy process. Based on the kernel sections: Section Size Start End -------------------------------------------- .text 00158108 01000000 01188108 .data 0002FEF0 01158110 01188000 .init 0000C390 01188000 01194390 The kernel binary is copied to the range [0x01000000 .. 0x01194390]. If you loader starts at 0x1100000 (as indicated in an earlier post), the kernel .text section alone extends half a Meg into your loader ... which is probably enough to blow the entire loader away. When you copy the kernel to high memory, your loader can successfully complete the copy (without corrupting itself) and call the kernel. Since the kernel copies itself to the proper location, you can store it at an arbitrary address. You may want to just stuff the kernel binary in flash and have your loader jump into flash without any copying at all. Regards, --Scott - Altera_Forum
Honored Contributor
Hi Scott.
<div class='quotetop'>QUOTE </div> --- Quote Start --- Since the kernel copies itself to the proper location, you can store it at an arbitrary address. You may want to just stuff the kernel binary in flash and have your loader jump into flash without any copying at all.[/b] --- Quote End --- A really good idea. But in my case that's a no go. I have a 2MB flash and here I have to have space for my safe img and user img. I still need to fit the code that should run on the linux into the flash also. I have tried looking at the u-boot that you ported to NIOS. From what I see it supports decompression from a zipped file and really all I need. But as I am new to this and since the "do_bootm_linux" function has not been completed I have a hard time seeing how I can use u-boot. I will try continuing with my little project. All your responces has always given me a little kick futher so thank you very much. Just keep kicking me http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/wink.gif if you have some more pointers for me. Regards GreateWhite.DK - Altera_Forum
Honored Contributor
> I have tried looking at the u-boot ....
... snip ... > since the "do_bootm_linux" function has not been completed > I have a hard time seeing how I can use u-boot. I'll try to get that implemented soon. Whether or not it is appropriate for your application is (of course) your call. However, if you would like to use it, but there are 'show stoppers' (like no bootm) please let me know :-) BTW: A few features that may be useful to you: --RS-232 cli (w/kermit & SREC download support) --JTAG uart support --Flash programming (via cli) --Scripting --Linux loader - once bootm is implemented 8-/ --JFFS2, FAT, cramfs support Again, I'll try to get bootm finished & provide instructions for reducing it's size to fit in a single 64KB flash sector. (currently, with the 'extended help' option and full network support it's around 71K). Regards, --Scott