?? porting.texi
字號:
@chapter Porting newlib@menu* Crt0:: Crt0.S.* Linker Scripts:: Linker scripts for memory management.* What to do now:: Tricks for manipulating formats.* Libc:: Making libc work.@end menu@node Crt0, Linker Scripts, , Libraries@section Crt0, the main startup file To make a program that has been compiled with GCC to run, youneed to write some startup code. The initial piece of startup code iscalled a crt0. (C RunTime 0) This is usually written in assembler, andit's object gets linked in first, and bootstraps the rest of theapplication when executed. This file needs to do the following things.@enumerate@itemInitialize anything that needs it. This init section varies. If you aredeveloping an application that gets download to a ROM monitor, thenthere is usually no need for any special initialization. The ROM monitorhandles it for you.If you plan to burn your code in a ROM, then the crt0 typically has todo all the hardware initialization that is required to run anapplication. This can include things like initializing serial ports orrun a memory check. It all depends on the hardware. @itemZero the BSS section. This is for uninitialized data. All the addresses inthis section need to be initialized to zero so that programs that forgetto check new variables default value will get unpredictable results.@itemCall main()This is what basically starts things running. If your ROM monitorsupports it, then first setup argc and argv for command line argumentsand an environment pointer. Then branch to main(). For G++ the the mainroutine gets a branch to __main inserted by the code generator at thevery top. __main() is used by G++ to initialize it's internal tables.__main() then returns back to your original main() and your code getsexecuted.@itemCall exit()After main() has returned, you need to cleanup things and return controlof the hardware from the application. On some hardware, there is nothingto return to, especially if your program is in ROM. Sometimes the bestthing to do in this case is do a hardware reset, or branch back to thestart address all over again.When there is a ROM monitor present, usually a user trap can be calledand then the ROM takes over. Pick a safe vector with no sideeffects. Some ROMs have a builtin trap handler just for this case.@end enumerateportable between all the m68k based boards we have here.@ref{crt0.S,,Example Crt0.S}. @smallexample/* ANSI concatenation macros. */#define CONCAT1(a, b) CONCAT2(a, b)#define CONCAT2(a, b) a ## b@end smallexampleThese we'll use later.@smallexample/* These are predefined by new versions of GNU cpp. */#ifndef __USER_LABEL_PREFIX__#define __USER_LABEL_PREFIX__ _#endif/* Use the right prefix for global labels. */#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)@end smallexampleThese macros are to make this code portable between both @emph{COFF} and@emph{a.out}. @emph{COFF} always has an @var{_ (underline)} prepended onthe front of all global symbol names. @emph{a.out} has none.@smallexample#ifndef __REGISTER_PREFIX__#define __REGISTER_PREFIX__#endif/* Use the right prefix for registers. */#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)#define d0 REG (d0)#define d1 REG (d1)#define d2 REG (d2)#define d3 REG (d3)#define d4 REG (d4)#define d5 REG (d5)#define d6 REG (d6)#define d7 REG (d7)#define a0 REG (a0)#define a1 REG (a1)#define a2 REG (a2)#define a3 REG (a3)#define a4 REG (a4)#define a5 REG (a5)#define a6 REG (a6)#define fp REG (fp)#define sp REG (sp)@end smallexampleThis is for portability between assemblers. Some register names have a@var{%} or @var{$} prepended to the register name.@smallexample/* * Set up some room for a stack. We just grab a chunk of memory. */ .set stack_size, 0x2000 .comm SYM (stack), stack_size@end smallexampleSet up space for the stack. This can also be done in the linker script,but it typically gets done here.@smallexample/* * Define an empty environment. */ .data .align 2SYM (environ): .long 0@end smallexampleSet up an empty space for the environment. This is bogus on any most ROM monitor, but we setup a valid address for it, and pass it to main. Atleast that way if an application checks for it, it won't crash.@smallexample .align 2 .text .global SYM (stack) .global SYM (main) .global SYM (exit)/* * This really should be __bss_start, not SYM (__bss_start). */ .global __bss_start@end smallexampleSetup a few global symbols that get used elsewhere. @var{__bss_start}needs to be unchanged, as it's setup by the linker script.@smallexample/* * start -- set things up so the application will run. */SYM (start): link a6, #-8 moveal #SYM (stack) + stack_size, sp/* * zerobss -- zero out the bss section */ moveal #__bss_start, a0 moveal #SYM (end), a11: movel #0, (a0) leal 4(a0), a0 cmpal a0, a1 bne 1b@end smallexampleThe global symbol @code{start} is used by the linker as the defaultaddress to use for the @code{.text} section. then it zeros the@code{.bss} section so the uninitialized data will all be cleared. Someprograms have wild side effects from having the .bss section letuncleared. Particularly it causes problems with some implementations of@code{malloc}. @smallexample/* * Call the main routine from the application to get it going. * main (argc, argv, environ) * We pass argv as a pointer to NULL. */ pea 0 pea SYM (environ) pea sp@@(4) pea 0 jsr SYM (main) movel d0, sp@@-@end smallexampleSetup the environment pointer and jump to @code{main()}. When@code{main()} returns, it drops down to the @code{exit} routine below.@smallexample/* * _exit -- Exit from the application. Normally we cause a user trap * to return to the ROM monitor for another run. */SYM (exit): trap #0@end smallexampleImplementing @code{exit} here is easy. Both the @code{rom68k} and @code{bug}can handle a user caused exception of @code{zero} with no side effects.Although the @code{bug} monitor has a user caused trap that will returncontrol to the ROM monitor, this solution has been more portable.@node Linker Scripts, What to do now, Crt0, Libraries@section Linker scripts for memory managementThe linker script sets up the memory map of an application. It alsosets up default values for variables used elsewhere by sbrk() and thecrt0. These default variables are typically called @code{_bss_start} and@code{_end}.For G++, the constructor and destructor tables must also be setup here.The actual section names vary depending on the object file format. For@code{a.out} and @code{coff}, the three main sections are @code{.text},@code{.data}, and @code{.bss}.Now that you have an image, you can test to make sure it got thememory map right. You can do this by having the linker create a memorymap (by using the @code{-Map} option), or afterwards by using @code{nm} tocheck a few critical addresses like @code{start}, @code{bss_end}, and@code{_etext}.Here's a breakdown of a linker script for a m68k based target board.See the file @code{libgloss/m68k/idp.ld}, or go to the appendixes inthe end of the manual. @ref{idp.ld,,Example Linker Script}. @smallexampleSTARTUP(crt0.o)OUTPUT_ARCH(m68k)INPUT(idp.o)SEARCH_DIR(.)__DYNAMIC = 0;@end smallexampleThe @code{STARTUP} command loads the file specified so that it'sfirst. In this case it also doubles to load the file as well, becausethe m68k-coff configuration defaults to not linking in the crt0.o bydefault. It assumes that the developer probably has their own crt0.o.This behavior is controlled in the config file for each architecture.It's a macro called @code{STARTFILE_SPEC}, and if it's set to@code{null}, then when @code{gcc} formats it's command line, it doesn'tadd @code{crto.o}. Any file name can be specified here, but the defaultis always @code{crt0.o}.Course if you only use @code{ld} to link, then the control of whether ornot to link in @code{crt0.o} is done on the command line. If you havemultiple crto files, then you can leave this out all together, and linkin the @code{crt0.o} in the makefile, or by having different linkerscripts. Sometimes this is done for initializing floating pointoptionally, or to add device support.The @code{OUTPUT_ARCH} sets architecture the output file is for.@code{INPUT} loads in the file specified. In this case, it's a relocatedlibrary that contains the definitions for the low-level functions needby libc.a. This could have also been specified on the command line, butas it's always needed, it might as well be here as a default.@code{SEARCH_DIR} specifies the path to look for files, and@code{_DYNAMIC} means in this case there are no shared libraries. @c FIXME: Check the linker manual to make sure this is accurate.@smallexample/* * Setup the memory map of the MC68ec0x0 Board (IDP) * stack grows up towards high memory. This works for * both the rom68k and the mon68k monitors. */MEMORY@{ ram : ORIGIN = 0x10000, LENGTH = 2M@}@end smallexampleThis specifies a name for a section that can be referred to later in the script. In this case, it's only a pointer to the beginning of free RAMspace, with an upper limit at 2M. If the output file exceeds the upperlimit, it will produce an error message.@smallexample/* * stick everything in ram (of course) */SECTIONS@{ .text : @{ CREATE_OBJECT_SYMBOLS *(.text) etext = .; __CTOR_LIST__ = .; LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) *(.ctors) LONG(0) __CTOR_END__ = .; __DTOR_LIST__ = .; LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2) *(.dtors) LONG(0) __DTOR_END__ = .; *(.lit) *(.shdata) @} > ram .shbss SIZEOF(.text) + ADDR(.text) : @{ *(.shbss) @}@end smallexampleSet up the @code{.text} section. In a @code{COFF} file, .text is whereall the actual instructions are. This also sets up the @emph{CONTRUCTOR}and the @emph{DESTRUCTOR} tables for @code{G++}. Notice that the sectiondescription redirects itself to the @emph{ram} variable setup earlier.@smallexample .talias : @{ @} > ram .data : @{ *(.data) CONSTRUCTORS _edata = .; @} > ram@end smallexampleSetup the @code{.data} section. In a @code{coff} file, this is where allhe initialized data goes. @code{CONSTRUCTORS} is a special command usedby @code{ld}.@smallexample .bss SIZEOF(.data) + ADDR(.data) : @{ __bss_start = ALIGN(0x8); *(.bss) *(COMMON) end = ALIGN(0x8); _end = ALIGN(0x8); __end = ALIGN(0x8); @} .mstack : @{ @} > ram .rstack : @{ @} > ram .stab . (NOLOAD) : @{ [ .stab ] @} .stabstr . (NOLOAD) : @{ [ .stabstr ] @}@}@end smallexampleSetup the @code{.bss} section. In a @code{COFF} file, this is whereunitialized data goes. The symbols @code{_bss_start} and @code{_end}are setup here for use by the @code{crt0.o} when it zero's the@code{.bss} section. @node What to do now, Libc, Linker Scripts, Libraries@section What to do when you have a binary imageA few ROM monitors load binary images, typically @code{a.out}, but most allwill load an @code{srecord}. An srecord is an ASCII representation of a binary image. At it's simplest, an srecord is an address, followed by a bytecount, followed by the bytes, and a 2's compliment checksum. A wholesrecord file has an optional @emph{start} record, and a required @emph{end} record. To make an srecord from a binary image, the GNU @code{objcopy} programis used. This will read the image and make an srecord from it. To dothis, invoke objcopy like this: @code{objcopy -O srec infile outfile}. MostPROM burners also read srecords or a similar format. Use @code{objdump -i} toget a list of support object files types for your architecture. @node Libc, , What to do now, Libraries@section LibrariesThis describes @code{newlib}, a freely available libc replacement. Mostapplications use calls in the standard C library. When initially linkingin libc.a, several I/O functions are undefined. If you don't plan ondoing any I/O, then you're OK, otherwise they need to be created. Theseroutines are read, write, open, close. sbrk, and kill. Open & closedon't need to be fully supported unless you have a filesystems, sotypically they are stubbed out. Kill is also a stub, since you can't doprocess control on an embedded system. Sbrk() is only needed by applications that do dynamic memoryallocation. It's uses the symbol @code{_end} that is setup in the linkerscript. It also requires a compile time option to set the upper sizelimit on the heap space. This leaves us with read and write, which arerequired for serial I/O. Usually these two routines are written in C,and call a lower level function for the actual I/O operation. These twolowest level I/O primitives are inbyte() and outbyte(), and are alsoused by GDB back ends if you've written an exception handler. Somesystems also implement a havebyte() for input as well. Other commonly included functions are routines for manipulatingLED's on the target (if they exist) or low level debug help. Typically aputnum() for printing words and bytes as a hex number is helpful, aswell as a low-level print() to output simple strings. As libg++ uses the I/O routines in libc.a, if read and write work,then libg++ will also work with no additional changes. @menu* I/O Support:: Functions that make serial I/O work.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -