Nandflash startup and standard library issues
Put U-boot's start. S is ported to my program so that the program can be downloaded into memory with the Supervivi D feature, but not enough. Because the program is stored inside, if the power off program is gone, so we have to fix the program in Flash. Here we have to solidify in the Nandflash, which requires the program to be able to nandflash boot. Here I refer to mini2440 's Nandlfash read and write program NAND.C, which has a function copyprogramfromnand is to copy the Nandflash program into memory. Before this I have been using u-boot default download address 0x33f80000, this is to u-boot boot kernel convenience, because the kernel to download to the front of the memory, since my program does not have this function, then download to the 0x30000000 can be. Put the start. The text_base in S can be changed into 0x30000000. And there's the start. s, copy the program to determine whether the r0 is zero, if not then the program will enter the dead loop. The value returned by the AAPCS,C program is stored in the r0, which is to determine whether the program returned 0, in the Copyprogramfromnand default does not return the value, so to add the return value at the end. The next step is to eliminate compilation errors. Will NAND.C link to our program, pay attention to ensure that the program in the first 4k position range, because the Nandflash start, s3c2440 will nandflsh the contents of the former 4K copy into the chip inside the SRAM, if the Nandflash read and write program is not in this 4k code can not be completed into a copy of the program.
Compile the program in my download resources: http://download.csdn.net/detail/yaozhenguo2006/3752515 Nandflash start to go smoothly, after the revision to Nandflash, Then the development Board is cut to Nandflash, and the program runs normally. Here I noticed that the running lights didn't run as quickly as they were downloaded into memory, but waited a while, stating that the copy code took some time. Next is to transplant mini2440 from the library function, the corresponding file is 2440LIB.C, I originally thought that simple add to the makefile will be successful. But things are not as simple as they might seem, and there are a lot of bugs when compiling. These errors just seem strange, and not compile errors, are linked errors. When compiling the correct description is not a syntax error, link error description is the library out of the problem. The error message for the main prompt is as follows:
First Category:
2440lib.o:in function ' uart_init ':
2440lib.c: (. text+0x370): Undefined reference to ' __aeabi_i2d ' 2440LIB.C
: ( text+0x390): Undefined reference to ' __aeabi_ddiv '
2440lib.c: (. text+0x3a8): Undefined reference to ' __aeabi_i2d ' C3/>2440LIB.C: (. text+0x3c4): Undefined reference to ' __aeabi_ddiv '
In Uart_init this function, mainly uses some floating-point arithmetic and the division operation, we know that the armv4 instruction set is not the division and the floating-point operation instruction, therefore must the software simulation. When compiling the library to simulate division and floating-point operations, the linker was not found at the time of the link, so the problem arose. To verify my guess, I commented out the floating-point arithmetic and the division operation, and the error message was gone. Description is a library where floating-point operations and division operations are not found.
Second Category:
2440lib.o:in function ' uart_getintnum ':
2440lib.c: (. text+0x994): Undefined reference to ' strlen ' 2440LIB.C
: ( TEXT+0XA20): Undefined reference to ' atoi '
2440lib.c: (. text+0xa5c): Undefined reference to ' __ctype_b_loc
' 2440LIB.C: (. text+0xa90): Undefined reference to ' __ctype_b_loc ' 2440lib.o:in
function ' uart_printf ':
2440LIB.C: (. text+0xd90): Undefined reference to ' vsprintf '
In Uart_getintnum this function mainly called the standard C library in the strlen and Atio functions, can not find the symbol, the link did not find the standard C library. Uart_printf should also be the same mistake.
Both of these problems are library issues. Since the linker cannot find the associated library. Let's add a certain link option so he can find it. Before doing this, let's take a look at two ways to link programs in the GCC development environment. The first is the use of GCC with its own link functionality. In ARM-LINUX-GCC, this link-mode command has the following basic form
$ (cc) -static-wl,-tboot.lds,-map,system.map-nostartfiles-o boot.elf $ (OBJS)
CC This is ARM-LINUX-GCC
-Wl, -TBOOT.LDS,-MAP,SYSTEM.MAP-WL indicates that subsequent arguments are passed to the linker, and the arguments are separated by commas. -tboot.lds is the specified link script that plans the location of the program in place-map,system.map this is the symbolic table generated after the link
-nostartfile does not allow the linker to add the default boot code, if not added to this option, The linker will default to add a boot code, because we have to link our own startup code, of course, do not need it by default. -
o boot.elf the last generated elf-formatted file.
$ (OBJS) we compiled the. o File
Link the program in the above form, ARM-LINUX-GCC will call the COLLECT2 linker, this linker has certain default options, such as the default search for the library path, the default link library. By adding the-v option to ARM-LINUX-GCC, we can view his default behavior. Now take my development environment as an example, the link will have the following output:
/home/sun/study/crosstools/4.4.3/bin/..
/libexec/gcc/arm-none-linux-gnueabi/4.4.3/collect2 from this output, we can find that ARM-LINUX-GCC called Collect2. --sysroot=/home/sun/study/crosstools/4.4.3/bin/..
/arm-none-linux-gnueabi//sys-root-bstatic-dynamic-linker/lib/ld-linux.so.3-x-M Armelf_linux_eabi-o boot.elf Sysroot temporarily did not find what is done,-bstatic is obviously a static link-l/home/sun/study/crosstools/4.4.3/bin/. /lib/gcc/arm-none-linux-gnueabi/4.4.3-l/home/sun/study/crosstools/4.4.3/bin/.. /lib/gcc-l/home/sun/study/crosstools/4.4.3/bin/.. /lib/gcc/arm-none-linux-gnueabi/4.4.3/.. /.. /.. /.. /arm-none-linux-gnueabi/lib-l/home/sun/study/crosstools/4.4.3/bin/.. /arm-none-linux-gnueabi//sys-root/lib-l/home/sun/study/crosstools/4.4.3/bin/.. /arm-none-linux-gnueabi//sys-root/usr/lib above is collect2 default look for the library path-tboot.lds-map System.map passed over the linker parameter STA RT.O lowlevel_init.o nand.o interrupt.o main.o 2440lib.o you want to link the. o File print.o--start-group-lgcc-lgcc_eh-lc Group This option is important, the linker links the static library. -lc Represents the link standard C library, the-LGCC representative to link LIBGCC.A, this library should be the GCC extension library.
Here is another way to link, is to use the LD command to link, here is arm-linux-ld, this way is also my link error links. This link, there is no default parameters, find the path of the library and the link library to add their own. The reason the link went wrong is because I didn't specify the link's library and find the path to the library. That being the case, it would be right to link my program with the first link. I will makefile modified a bit more make, or wrong, it is gratifying that the error is reduced, only the following error is left:
/home/sun/study/crosstools/4.4.3/bin/.. /LIB/GCC/ARM-NONE-LINUX-GNUEABI/4.4.3/LIBGCC_EH.A (UNWIND-ARM.O): in function ' get_eit_entry ':
/opt/ friendlyarm/mini2440/build-toolschain/working/src/gcc-4.4.3/libgcc/.. /gcc/config/arm/unwind-arm.c:673:undefined reference to ' __exidx_end '
/opt/friendlyarm/mini2440/ build-toolschain/working/src/gcc-4.4.3/libgcc/.. /gcc/config/arm/unwind-arm.c:673:undefined reference to ' __exidx_start '
After analysis I think it is the uart_printf function called vsprintf, the uart_printf comment out, and then make. The link is passed, which explains the vsprintf problem. Let go of this problem, I'll try it. LD this way of linking, if you add a path to the library and the name of the library you want to link, you can make it successfully. Modify Makefile as follows:
CC = ARM-LINUX-GCC LD = arm-linux-ld objcopy = arm-linux-objcopy Objs: = START.O lowlevel_init.o MAIN.O NAND.O 2440LIB.O Boot.bin: $ (OBJS) $ (LD)-bstatic-tboot.lds-ttext 0x33f80000 $ (OBJS) \-l/home/sun/study /crosstools/4.4.3/lib/gcc/arm-none-linux-gnueabi/4.4.3 \-L/HOME/SUN/STUDY/CROSSTOOLS/4.4.3/ Arm-none-linux-gnueabi/sys-root/usr/lib \-map boot.map-o boot.elf--start-group-lgcc-lgcc_eh-lgcov-lc--end
-group $ (objcopy)-o binary boot.elf boot.bin%.o:%.c $ (CC)-wall-c-o $@ {1}lt; %.o:%.
S $ (CC)-wall-c-o $@ {1}lt; Clean:rm-f *.bin *elf *.o
With the above Makefile,make passed. The program downloads to the board the phenomenon is also correct. This means that the LD linker correctly links the program. Now both links can be correctly linked to the program. Then there is only one problem, the uart_printf function is vsprintf. This function is a format string conversion function, should be the standard C library functions, in the linker can find the C library, the two links are prompted the same error. I guess vsprintf also called other library functions, and I've been looking for a long time to find out what libraries were called. The print function is necessary for program debugging. Since vsprintf can not be used, then realize one on its own. Reference U-boot's printf implementation, I wrote a vsprintf, and then combined with uart_sendstring to achieve the serial printing function.
To simplify the method of implementing printf, first of all, to solve the problem of variable parameters of functions, printf (char *fmt,... is obviously a variable parameter function, the first argument is a string, followed by the formatted output parameter list. C language function parameters are pressed into the stack, the variable parameter function must have a parameter to indicate the number of parameters in order to let the compiler know how many parameters to press into the stack, and the function returned when the number of parameters, printf (char *fmt,... To implement this function is the FMT string, how many '% ' in it, representing the number of arguments behind it, so we have to extract the number of '% ' in the FMT string and handle the arguments for different characters after '% '. printf implementations are similar to the following:
void myprintf (char *fmt,...)
{
va_list ap;
Char string[256];
Va_start (AP,FMT);
myvsprintf (STRING,FMT,AP);
Uart_sendstring (string);
Va_end (AP);
}
Va_list is actually the *char type, and the va_list AP is beginning to define a pointer variable ap with a char type. Va_start is a macro that gets the FMT pointer address and skips the address assignment to the AP, so that the AP points to the address in memory except for the first variable parameter of the FMT pointer, and then through myvsprintf (STRING,FMT,AP) Transforms the FMT string into variable parameters, assigns the transformation result to string, and sends the string to the serial port through the uart_sendstring () function. The concrete implementation can look at my source code. In my resources, http://download.csdn.net/detail/yaozhenguo2006/3774535.
Standard C library problem even if temporarily solved, but still give me a wake up, ARM-LINUX-GCC on the development of bare-metal programs, if used to standard C library must pay attention to, not all functions can be used, such as vsnprintf can't use. What other functions can not be used or unknown, so try not to use the standard C library function is to ensure that the program security method. The typical example is u-boot, it does not use the standard C library, the related functions are implemented by themselves, so as to ensure u-boot very strong portability. Perhaps ARM-ELF-GCC will not have this problem, after all, the link is ULIBC library, specifically for the embedded, after the opportunity to be sure to verify.