软件版本:练习程序
例程路径:F:\code\004
硬件平台:JZ2440(S3C2440)
/************************************************************************************************************************************/
知识普及:
(1)硬浮点(hard-float)
编译器将代码直接编译成硬件浮点协处理器(浮点运算单元FPU)能识别的指令,这些指令在执行的时候ARM核直接把它转给协处理器执行。FPU 通常有一套额外的寄存器来完成浮点参数传递和运算。使用实际的硬件浮点运算单元(FPU)会带来性能的提升。
(2)软浮点(soft-float)
编译器把浮点运算转成浮点运算的函数调用和库函数调用,没有FPU的指令调用,也没有浮点寄存器的参数传递。浮点参数的传递也是通过ARM寄存器或者堆栈完成。现在的Linux系统默认编译选择使用hard-float,如果系统没有任何浮点处理器单元,这就会产生非法指令和异常。因而一般的系统镜像都采用软浮点以兼容没有VFP的处理器。
用一句话总结,软浮点是通过浮点库去实现浮点运算的,效率低;硬浮点是通过浮点运算单元(FPU)来完成的,效率高。
/************************************************************************************************************************************/
编写JZ2440(S3C2440)UART驱动程序,初始化函数参考TI的DSP驱动写法,配置波特率寄存器使用了浮点运算
uReg->ULCON=(0<<6)|(uartlink->parity<<3)|(uartlink->stopbit<<2)|(uartlink->databit<<0);
uReg->UCON=(0<<10)|(1<<2)|(1<<0);//PCLK;TX/RX interrupt type:Interrupt request or polling mode
uReg->UFCON=(0<<0);//disable fifo
uReg->UMCON=(0<<4);
uReg->UBRDIV=(unsigned int)(clock_MHz*1000000.f/(uartlink->baudrate*16)-1);
上述代码最后一行使用了浮点运算自行根据外设时钟PCLK计算波特率设置寄存器参数,编译时出现错误如下:
arm-linux-ld -Tlink.lds init.o uart.o start.o -o test.elf
uart.o(.text+0x1d8): In function `$a':
: undefined reference to `__mulsf3'
uart.o(.text+0x200): In function `$a':
: undefined reference to `__floatsisf'
uart.o(.text+0x224): In function `$a':
: undefined reference to `__floatsisf'
uart.o(.text+0x234): In function `$a':
: undefined reference to `__addsf3'
uart.o(.text+0x248): In function `$a':
: undefined reference to `__divsf3'
uart.o(.text+0x258): In function `$a':
: undefined reference to `__subsf3'
uart.o(.text+0x264): In function `$a':
: undefined reference to `__fixunssfsi'
Makefile:26: recipe for target 'test' failed
make: *** [test] Error 1
将uReg->UBRDIV=(unsigned int)(clock_MHz*1000000.f/(uartlink->baudrate*16)-1);改为
uReg->UBRDIV=26;则编译通过没有问题,查找资料发现是S3C2440没有浮点运算单元,只能使用软浮点,即由编译器的库文件支持,我使用的编译器没有浮点库,需要自己添加浮点库,并在编译器选项上添加库路径。
CFLAGS := -static -Werror -Iinclude -msoft -float -L/usr/local/arm/../libgcc.a
目前问题没有解决,留待以后完善
、、、、、、、、、、、、
根据韦东山裸机LCD视频,去库函数中查找 (一般来说编译器自带有很多库),进入工具链的目录: grep "__floatsisf" * -nr找到.a文件。
echo $PATH查看环境变量,得到编译器路径/usr/local/arm/gcc-3.4.5-glibc-2.3.6/bin,回到上层目录/usr/local/arm/gcc-3.4.5-glibc-2.3.6,使用 grep "__floatsisf" * -nr查找目录下含有__floatsisf标示的文件,得到:
Binary file arm-linux/lib/libm.a matches
Binary file arm-linux/lib/libm-2.3.6.so matches
Binary file arm-linux/lib/libc.a matches
Binary file arm-linux/lib/libgcc_s.so.1 matches
Binary file arm-linux/lib/libc-2.3.6.so matches
Binary file include/c++/3.4.5/arm-linux/bits/stdc++.h.gch/O0g matches
Binary file include/c++/3.4.5/arm-linux/bits/stdc++.h.gch/O2g matches
info/gccint.info:555: -- Runtime Function: float __floatsisf (int I)
Binary file info/gccint.info matches
Binary file lib/gcc/arm-linux/3.4.5/libgcc.a matches
将静态库拷贝到代码目录下,修改链接器命令:$(LD) -Tlink.lds $^ libgcc.a -o $@.elf,测试发现libgcc.a库包含浮点库函数,可以正常编译。
$(LD) -Tlink.lds $^ -L$(LIBPATH) -llibgcc -o $@.elf这个命令却不能找到库,只能拷贝到代码目录下链接