【手写数字时钟源码下载】【活源码】【免费的源码】fpe源码

时间:2024-12-28 22:35:06 来源:rpccontext 源码 分类:休闲

1.AT89C51和AT89S51的区别?
2.交叉编译器 arm-linux-gnueabi 和 arm-linux-gnueabihf 的区别

fpe源码

AT89C51和AT89S51的区别?

       ATC是一种带4K字节闪烁可编程可擦除只读存储器(FPEROM—Falsh Programmable and Erasable Read Only Memory)的低电压,高性能CMOS8位微处理器,俗称单片机。ATC是一种带2K字节闪烁可编程可擦除只读存储器的单片机。单片机的可擦除只读存储器可以反复擦除次。该器件采用ATMEL高密度非易失存储器制造技术制造,手写数字时钟源码下载与工业标准的MCS-指令集和输出管脚相兼容。由于将多功能8位CPU和闪烁存储器组合在单个芯片中,ATMEL的ATC是一种高效微控制器,ATC是它的一种精简版本。ATC单片机为很多嵌入式控制系统提供了一种灵活性高且价廉的方案。外形及引脚排列如图所示

       [编辑本段]主要特性:

         ·与MCS- 兼容 

         ·4K字节可编程闪烁存储器 

         ·寿命:写/擦循环

         ·数据保留时间:年

         ·全静态工作:0Hz-MHz

         ·三级程序存储器锁定

         ·×8位内部RAM

         ·可编程I/O线

         ·两个位定时器/计数器

         ·5个中断源 

         ·可编程串行通道

         ·低功耗的闲置和掉电模式

         ·片内振荡器和时钟电路

       管脚说明:

         VCC:供电电压。

         GND:接地。

         P0口:P0口为一个8位漏级开路双向I/O口,每脚可吸收8TTL门电流。当P1口的管脚第一次写1时,被定义为高阻输入。P0能够用于外部程序数据存储器,它可以被定义为数据/地址的第八位。在FIASH编程时,P0 口作为原码输入口,当FIASH进行校验时,P0输出原码,此时P0外部必须被拉高。

         P1口:P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4TTL门电流。P1口管脚写入1后,被内部上拉为高,可用作输入,P1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。在FLASH编程和校验时,P1口作为第八位地址接收。 

         P2口:P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可接收,输出4个TTL门电流,当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入。并因此作为输入时,P2口的活源码管脚被外部拉低,将输出电流。这是由于内部上拉的缘故。P2口当用于外部程序存储器或位地址外部数据存储器进行存取时,P2口输出地址的高八位。在给出地址“1”时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器的内容。P2口在FLASH编程和校验时接收高八位地址信号和控制信号。

         P3口:P3口管脚是8个带内部上拉电阻的双向I/O口,可接收输出4个TTL门电流。当P3口写入“1”后,它们被内部上拉为高电平,并用作输入。作为输入,由于外部下拉为低电平,P3口将输出电流(ILL)这是由于上拉的缘故。

         P3口也可作为ATC的一些特殊功能口,如下表所示:

         口管脚 备选功能

         P3.0 RXD(串行输入口)

         P3.1 TXD(串行输出口)

         P3.2 /INT0(外部中断0)

         P3.3 /INT1(外部中断1)

         P3.4 T0(记时器0外部输入)

         P3.5 T1(记时器1外部输入)

         P3.6 /WR(外部数据存储器写选通)

         P3.7 /RD(外部数据存储器读选通)

         P3口同时为闪烁编程和编程校验接收一些控制信号。

         RST:复位输入。当振荡器复位器件时,要保持RST脚两个机器周期的高电平时间。

         ALE/PROG:当访问外部存储器时,地址锁存允许的输出电平用于锁存地址的地位字节。在FLASH编程期间,此引脚用于输入编程脉冲。在平时,ALE端以不变的频率周期输出正脉冲信号,此频率为振荡器频率的1/6。因此它可用作对外部输出的脉冲或用于定时目的。然而要注意的是:每当用作外部数据存储器时,将跳过一个ALE脉冲。如想禁止ALE的输出可在SFR8EH地址上置0。此时, ALE只有在执行MOVX,MOVC指令是ALE才起作用。另外,该引脚被略微拉高。如果微处理器在外部执行状态ALE禁止,置位无效。

         /PSEN:外部程序存储器的免费的源码选通信号。在由外部程序存储器取指期间,每个机器周期两次/PSEN有效。但在访问外部数据存储器时,这两次有效的/PSEN信号将不出现。

         /EA/VPP:当/EA保持低电平时,则在此期间外部程序存储器(H-FFFFH),不管是否有内部程序存储器。注意加密方式1时,/EA将内部锁定为RESET;当/EA端保持高电平时,此间内部程序存储器。在FLASH编程期间,此引脚也用于施加V编程电源(VPP)。

         XTAL1:反向振荡放大器的输入及内部时钟工作电路的输入。

         XTAL2:来自反向振荡器的输出。

         振荡器特性:

         XTAL1和XTAL2分别为反向放大器的输入和输出。该反向放大器可以配置为片内振荡器。石晶振荡和陶瓷振荡均可采用。如采用外部时钟源驱动器件,XTAL2应不接。有余输入至内部时钟信号要通过一个二分频触发器,因此对外部时钟信号的脉宽无任何要求,但必须保证脉冲的高低电平要求的宽度。

       芯片擦除:

         整个PEROM阵列和三个锁定位的电擦除可通过正确的控制信号组合,并保持ALE管脚处于低电平ms 来完成。在芯片擦操作中,代码阵列全被写“1”且在任何非空存储字节被重复编程以前,该操作必须被执行。

         此外,ATC设有稳态逻辑,可以在低到零频率的条件下静态逻辑,支持两种软件可选的掉电模式。在闲置模式下,CPU停止工作。但RAM,定时器,计数器,串口和中断系统仍在工作。在掉电模式下,保存RAM的内容并且冻结振荡器,禁止所用其他芯片功能,直到下一个硬件复位为止。积分商城源码 

         串口通讯

         单片机的结构和特殊寄存器,这是你编写软件的关键。至于串口通信需要用到那些特殊功能寄存器呢,它们是SCON,TCON,TMOD,SCON等,各代表什么含义呢?

         SBUF 数据缓冲寄存器这是一个可以直接寻址的串行口专用寄存器。有朋友这样问起过“为何在串行口收发中,都只是使用到同一个寄存器SBUF?而不是收发各用一个寄存器。”实际上SBUF 包含了两个独立的寄存器,一个是发送寄存,另一个是接收寄存器,但它们都共同使用同一个寻址地址-H。CPU 在读SBUF 时会指到接收寄存器,在写时会指到发送寄存器,而且接收寄存器是双缓冲寄存器,这样可以避免接收中断没有及时的被响应,数据没有被取走,下一帧数据已到来,而造成的数据重叠问题。发送器则不需要用到双缓冲,一般情况下我们在写发送程序时也不必用到发送中断去外理发送数据。操作SBUF寄存器的方法则很简单,只要把这个H 地址用关键字sfr定义为一个变量就可以对其进行读写操作了,如sfr SBUF = 0x;当然你也可以用其它的名称。通常在标准的reg.h 或atx.h 等头文件中已对其做了定义,只要用#include 引用就可以了。

         SCON 串行口控制寄存器通常在芯片或设备中为了监视或控制接口状态,都会引用到接口控制寄存器。SCON 就是 芯片的串行口控制寄存器。它的寻址地址是H,是一个可以位寻址的寄存器,作用就是监视和控制 芯片串行口的工作状态。 芯片的串口可以工作在几个不同的工作模式下,其工作模式的设置就是使用SCON 寄存器。它的各个位的具体定义如下:

         SM0 SM1 SM2 REN TB8 RB8 TI RI

         SM0、SM1 为串行口工作模式设置位,这样两位可以对应进行四种模式的设置。串行口工作模式设置。

         SM0 SM1 模式 功能 波特率

         0 0 0 同步移位寄存器 fosc/

         0 1 1 8位UART 可变

         1 0 2 9位UART fosc/ 或fosc/

         1 1 3 9位UART 可变

         在这里只说明最常用的网赚源码模式1,其它的模式也就一一略过,有兴趣的朋友可以找相关的硬件资料查看。表中的fosc 代表振荡器的频率,也就是晶振的频率。UART 为(Universal Asynchronous Receiver)的英文缩写。

         SM2 在模式2、模式3 中为多处理机通信使能位。在模式0 中要求该位为0。

         REM 为允许接收位,REM 置1 时串口允许接收,置0 时禁止接收。REM 是由软件置位或清零。如果在一个电路中接收和发送引脚P3.0,P3.1 都和上位机相连,在软件上有串口中断处理程序,当要求在处理某个子程序时不允许串口被上位机来的控制字符产生中断,那么可以在这个子程序的开始处加入REM=0 来禁止接收,在子程序结束处加入REM=1 再次打开串口接收。大家也可以用上面的实际源码加入REM=0 来进行实验。

         TB8 发送数据位8,在模式2 和3 是要发送的第9 位。该位可以用软件根据需要置位或清除,通常这位在通信协议中做奇偶位,在多处理机通信中这一位则用于表示是地址帧还是数据帧。

         RB8 接收数据位8,在模式2 和3 是已接收数据的第9 位。该位可能是奇偶位,地址/数据标识位。在模式0 中,RB8 为保留位没有被使用。在模式1 中,当SM2=0,RB8 是已接收数据的停止位。

         TI 发送中断标识位。在模式0,发送完第8 位数据时,由硬件置位。其它模式中则是在发送停止位之初,由硬件置位。TI 置位后,申请中断,CPU 响应中断后,发送下一帧数据。在任何模式下,TI 都必须由软件来清除,也就是说在数据写入到SBUF 后,硬件发送数据,中断响应(如中断打开),这时TI=1,表明发送已完成,TI 不会由硬件清除,所以这时必须用软件对其清零。

         RI 接收中断标识位。在模式0,接收第8 位结束时,由硬件置位。其它模式中则是在接收停止位的半中间,由硬件置位。RI=1,申请中断,要求CPU 取走数据。但在模式1 中,SM2=1时,当未收到有效的停止位,则不会对RI 置位。同样RI 也必须要靠软件清除。常用的串口模式1 是传输 个位的,1 位起始位为0,8 位数据位,低位在先,1 位停止位为1。它的波特率是可变的,其速率是取决于定时器1 或定时器2 的定时值(溢出速率)。ATC 和ATC 等 系列芯片只有两个定时器,定时器0 和定时器1,而定时器2是C 系列芯片才有的。

         波特率在使用串口做通讯时,一个很重要的参数就是波特率,只有上下位机的波特率一样时才可以进行正常通讯。波特率是指串行端口每秒内可以传输的波特位数。有一些初学的朋友认为波特率是指每秒传输的字节数,如标准 会被误认为每秒种可以传送个字节,而实际上它是指每秒可以传送 个二进位,而一个字节要8 个二进位,如用串口模式1 来传输那么加上起始位和停止位,每个数据字节就要占用 个二进位, 波特率用模式1 传输时,每秒传输的字节数是÷= 字节。 芯片的串口工作模式0的波特率是固定的,为fosc/,以一个M 的晶振来计算,那么它的波特率可以达到1M。模式2 的波特率是固定在fosc/ 或fosc/,具体用那一种就取决于PCON 寄存器中的SMOD位,如SMOD 为0,波特率为focs/,SMOD 为1,波特率为focs/。模式1 和模式3 的波特率是可变的,取决于定时器1 或2( 芯片)的溢出速率。那么我们怎么去计算这两个模

         式的波特率设置时相关的寄存器的值呢?可以用以下的公式去计算。

         波特率=(2SMOD÷)×定时器1 溢出速率

         上式中如设置了PCON 寄存器中的SMOD 位为1 时就可以把波特率提升2 倍。通常会使用定时器1 工作在定时器工作模式2 下,这时定时值中的TL1 做为计数,TH1 做为自动重装值 ,这个定时模式下,定时器溢出后,TH1 的值会自动装载到TL1,再次开始计数,这样可以不用软件去干预,使得定时更准确。在这个定时模式2 下定时器1 溢出速率的计算公式如下:

         溢出速率=(计数速率)/(-TH1)

         上式中的“计数速率”与所使用的晶体振荡器频率有关,在 芯片中定时器启动后会在每一个机器周期使定时寄存器TH 的值增加一,一个机器周期等于十二个振荡周期,所以可以得知 芯片的计数速率为晶体振荡器频率的1/,一个M 的晶振用在 芯片上,那么 的计数速率就为1M。通常用.M 晶体是为了得到标准的无误差的波特率,那么为何呢?计算一下就知道了。如我们要得到 的波特率,晶振为.M 和M,定时器1 为模式2,SMOD 设为1,分别看看那所要求的TH1 为何值。代入公式:

         .M

         =(2÷)×((.M/)/(-TH1))

         TH1=

         M

         =(2÷)×((M/)/(-TH1))

         TH1≈.

         上面的计算可以看出使用M 晶体的时候计算出来的TH1 不为整数,而TH1 的值只能取整数,这样它就会有一定的误差存在不能产生精确的 波特率。当然一定的误差是可以在使用中被接受的,就算使用.M 的晶体振荡器也会因晶体本身所存在的误差使波特率产生误差,但晶体本身的误差对波特率的影响是十分之小的,可以忽略不计。

       ATS是一个低功耗,高性能CMOS 8位单片机,片内含4k Bytes ISP(In-system programmable)的可反复擦写次的Flash只读程序存储器,器件采用ATMEL公司的高密度、非易失性存储技术制造,兼容标准MCS-指令系统及C引脚结构,芯片内集成了通用8位中央处理器和ISP Flash存储单元,功能强大的微型计算机的ATS可为许多嵌入式控制应用系统提供高性价比的解决方案。

         ATS具有如下特点:个引脚,4k Bytes Flash片内程序存储器, bytes的随机存取数据存储器(RAM),个外部双向输入/输出(I/O)口,5个中断优先级2层中断嵌套中断,2个位可编程定时计数器,2个全双工串行通信口,看门狗(WDT)电路,片内时钟振荡器。 

         此外,ATS设计和配置了振荡频率可为0Hz并可通过软件设置省电模式。空闲模式下,CPU暂停工作,而RAM定时计数器,串行口,外中断系统可继续工作,掉电模式冻结振荡器而保存RAM的数据,停止芯片其它功能直至外中断激活或硬件复位。同时该芯片还具有PDIP、TQFP和PLCC等三种封装形式,以适应不同产品的需求。

         1.主要特性:

         •  CPU与MCS- 兼容

         • 4K字节可编程FLASH存储器(寿命:写/擦循环)

         • 全静态工作:0Hz-KHz

         • 三级程序存储器保密锁定

         • *8位内部RAM

         • 条可编程I/O线

         • 两个位定时器/计数器

         • 6个中断源

         • 可编程串行通道

         • 低功耗的闲置和掉电模式

         • 片内振荡器和时钟电路

         2.管脚说明:

         VCC:供电电压。

         GND:接地。

         P0口:P0口为一个8位漏级开路双向I/O口,每脚可吸收8TTL门电流。当P1口的管脚第一次写1时,被定义为高阻输入。P0能够用于外部程序数据存储器,它可以被定义为数据/地址的第八位。在FIASH编程时,P0 口作为原码输入口,当FIASH进行校验时,P0输出原码,此时P0外部必须被拉高。

         P1口:P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4TTL门电流。P1口管脚写入1后,被内部上拉为高,可用作输入,P1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。在FLASH编程和校验时,P1口作为第八位地址接收。

         P2口:P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可接收,输出4个TTL门电流,当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入。并因此作为输入时,P2口的管脚被外部拉低,将输出电流。这是由于内部上拉的缘故。P2口当用于外部程序存储器或位地址外部数据存储器进行存取时,P2口输出地址的高八位。在给出地址“1”时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器的内容。P2口在FLASH编程和校验时接收高八位地址信号和控制信号。

         P3口:P3口管脚是8个带内部上拉电阻的双向I/O口,可接收输出4个TTL门电流。当P3口写入“1”后,它们被内部上拉为高电平,并用作输入。作为输入,由于外部下拉为低电平,P3口将输出电流(ILL)这是由于上拉的缘故。

         P3.0 RXD(串行输入口)

         P3.1 TXD(串行输出口)

         P3.2 /INT0(外部中断0)

         P3.3 /INT1(外部中断1)

         P3.4 T0(记时器0外部输入)

         P3.5 T1(记时器1外部输入)

         P3.6 /WR(外部数据存储器写选通)

         P3.7 /RD(外部数据存储器读选通)

         P3口同时为闪烁编程和编程校验接收一些控制信号。

         I/O口作为输入口时有两种工作方式即所谓的读端口与读引脚读端口时实际上并不从外部读入数据而是把端口锁存器的内容读入到内部总线经过某种运算或变换后再写回到端口锁存器只有读端口时才真正地把外部的数据读入到内部总线上面图中的两个三角形表示的就是输入缓冲器CPU将根据不同的指令分别发出读端口或读引脚信号以完成不同的操作这是由硬件自动完成的不需要我们操心1然后再实行读引脚操作否则就可能读入出错为什么看上面的图如果不对端口置1端口锁存器原来的状态有可能为0Q端为0Q^为1加到场效应管栅极的信号为1该场效应管就导通对地呈现低阻抗,此时即使引脚上输入的信号为1也会因端口的低阻抗而使信号变低使得外加的1信号读入后不一定是1若先执行置1操作则可以使场效应管截止引脚信号直接加到三态缓冲器中实现正确的读入由于在输入操作时还必须附加一个准备动作所以这类I/O口被称为准双向口C的P0/P1/P2/P3口作为输入时都是准双向口接下来让我们再看另一个问题从图中可以看出这四个端口还有一个差别除了P1口外P0P2P3口都还有其他的功能 

         RST:复位输入。当振荡器复位器件时,要保持RST脚两个机器周期的高电平时间。

         ALE/PROG:当访问外部存储器时,地址锁存允许的输出电平用于锁存地址的地位字节。在FLASH编程期间,此引脚用于输入编程脉冲。在平时,ALE端以不变的频率周期输出正脉冲信号,此频率为振荡器频率的1/6。因此它可用作对外部输出的脉冲或用于定时目的。然而要注意的是:每当用作外部数据存储器时,将跳过一个ALE脉冲。如想禁止ALE的输出可在SFR8EH地址上置0。此时, ALE只有在执行MOVX,MOVC指令是ALE才起作用。另外,该引脚被略微拉高。如果微处理器在外部执行状态ALE禁止,置位无效。

         /PSEN:外部程序存储器的选通信号。在由外部程序存储器取指期间,每个机器周期两次/PSEN有效。但在访问外部数据存储器时,这两次有效的/PSEN信号将不出现。

         /EA/VPP:当/EA保持低电平时,则在此期间外部程序存储器(H-FFFFH),不管是否有内部程序存储器。注意加密方式1时,/EA将内部锁定为RESET;当/EA端保持高电平时,此间内部程序存储器。在FLASH编程期间,此引脚也用于施加V编程电源(VPP)。

         XTAL1:反向振荡放大器的输入及内部时钟工作电路的输入。

         XTAL2:来自反向振荡器的输出。

交叉编译器 arm-linux-gnueabi 和 arm-linux-gnueabihf 的区别

       è‡ªå·±ä¹‹å‰ä¸€ç›´æ²¡æžæ¸…楚这两个交叉编译器到底有什么问题,特意google一番,总结如下,希望能帮到道上和我有同样困惑的兄弟…..

       ä¸€. 什么是ABI和EABI

       1) ABI: 二进制应用程序接口(Application Binary Interface (ABI) for the ARM Architecture)

       åœ¨è®¡ç®—机中,应用二进制接口描述了应用程序(或者其他类型)和操作系统之间或其他应用程序的低级接口.

       ABI涵盖了各种细节,如:

       æ•°æ®ç±»åž‹çš„大小、布局和对齐;

       è°ƒç”¨çº¦å®šï¼ˆæŽ§åˆ¶ç€å‡½æ•°çš„参数如何传送以及如何接受返回值),例如,是所有的参数都通过栈传递,还是部分参数通过寄存器传递;哪个寄存器用于哪个函数参数;通过栈传递的第一个函数参数是最先push到栈上还是最后;

       ç³»ç»Ÿè°ƒç”¨çš„编码和一个应用如何向操作系统进行系统调用;

       ä»¥åŠåœ¨ä¸€ä¸ªå®Œæ•´çš„操作系统ABI中,目标文件的二进制格式、程序库等等。

       ä¸€ä¸ªå®Œæ•´çš„ABI,像Intel二进制兼容标准 (iBCS) ,允许支持它的操作系统上的程序不经修改在其他支持此ABI的操作体统上运行。

       ABI不同于应用程序接口(API),API定义了源代码和库之间的接口,因此同样的代码可以在支持这个API的任何系统中编译,ABI允许编译好的目标代码在使用兼容ABI的系统中无需改动就能运行。

       2) EABI: 嵌入式ABI

       åµŒå…¥å¼åº”用二进制接口指定了文件格式、数据类型、寄存器使用、堆积组织优化和在一个嵌入式软件中的参数的标准约定。

       å¼€å‘者使用自己的汇编语言也可以使用EABI作为与兼容的编译器生成的汇编语言的接口。

       æ”¯æŒEABI的编译器创建的目标文件可以和使用类似编译器产生的代码兼容,这样允许开发者链接一个由不同编译器产生的库。

       EABI与关于通用计算机的ABI的主要区别是应用程序代码中允许使用特权指令,不需要动态链接(有时是禁止的),和更紧凑的堆栈帧组织用来节省内存。广泛使用EABI的有Power PC和ARM.

       äºŒ. gnueabi相关的两个交叉编译器: gnueabi和gnueabihf

       åœ¨debian源里这两个交叉编译器的定义如下:

       gcc-arm-linux-gnueabi – The GNU C compiler for armel architecture

       gcc-arm-linux-gnueabihf – The GNU C compiler for armhf architecture

       å¯è§è¿™ä¸¤ä¸ªäº¤å‰ç¼–译器适用于armel和armhf两个不同的架构, armel和armhf这两种架构在对待浮点运算采取了不同的策略(有fpu的arm才能支持这两种浮点运算策略)

       å…¶å®žè¿™ä¸¤ä¸ªäº¤å‰ç¼–译器只不过是gcc的选项-mfloat-abi的默认值不同. gcc的选项-mfloat-abi有三种值soft,softfp,hard(其中后两者都要求arm里有fpu浮点运算单元,soft与后两者是兼容的,但softfp和hard两种模式互不兼容):

       soft : 不用fpu进行浮点计算,即使有fpu浮点运算单元也不用,而是使用软件模式。

       softfp : armel架构(对应的编译器为gcc-arm-linux-gnueabi)采用的默认值,用fpu计算,但是传参数用普通寄存器传,这样中断的时候,只需要保存普通寄存器,中断负荷小,但是参数需要转换成浮点的再计算。

       hard : armhf架构(对应的编译器gcc-arm-linux-gnueabihf)采用的默认值,用fpu计算,传参数也用fpu中的浮点寄存器传,省去了转换, 性能最好,但是中断负荷高。

       æŠŠä»¥ä¸‹æµ‹è¯•ä½¿ç”¨çš„c文件内容保存成mfloat.c:

       #include <stdio.h>

       int main(void)

       {

       double a,b,c;

       a = .;

       b = .;

       c = b/a;

       printf(“the /2 = %f\n”, c);

       printf(“hello world !\n”);

       return 0;

       }

       1)使用arm-linux-gnueabihf-gcc编译,使用“-v”选项以获取更详细的信息:

       # arm-linux-gnueabihf-gcc -v mfloat.c

       COLLECT_GCC_OPTIONS=’-v’ ‘-march=armv7-a’ ‘-mfloat-abi=hard’ ‘-mfpu=vfpv3-d′ ‘-mthumb’

       -mfloat-abi=hard,可看出使用hard硬件浮点模式。

       2)使用arm-linux-gnueabi-gcc编译:

       # arm-linux-gnueabi-gcc -v mfloat.c

       COLLECT_GCC_OPTIONS=’-v’ ‘-march=armv7-a’ ‘-mfloat-abi=softfp’ ‘-mfpu=vfpv3-d′ ‘-mthumb’

       -mfloat-abi=softfp,可看出使用softfp模式。

       ä¸‰. 拓展阅读

       ä¸‹æ–‡é˜è¿°äº†ARM代码编译时的软浮点(soft-float)和硬浮点(hard-float)的编译以及链接实现时的不同。从VFP浮点单元的引入到软浮点(soft-float)和硬浮点(hard-float)的概念

       VFP (vector floating-point)

       ä»ŽARMv5开始,就有可选的 Vector Floating Point (VFP) 模块,当然最新的如 Cortex-A8, Cortex-A9 和 Cortex-A5 可以配置成不带VFP的模式供芯片厂商选择。

       VFP经过若干年的发展,有VFPv2 (一些 ARM9 / ARM)、 VFPv3-D(只使用个浮点寄存器,默认为个)和VFPv3+NEON (如大多数的Cortex-A8芯片) 。对于包含NEON的ARM芯片,NEON一般和VFP公用寄存器。

       ç¡¬æµ®ç‚¹Hard-float

       ç¼–译器将代码直接编译成发射给硬件浮点协处理器(浮点运算单元FPU)去执行。FPU通常有一套额外的寄存器来完成浮点参数传递和运算。

       ä½¿ç”¨å®žé™…的硬件浮点运算单元FPU当然会带来性能的提升。因为往往一个浮点的函数调用需要几个或者几十个时钟周期。

       è½¯æµ®ç‚¹ Soft-float

       ç¼–译器把浮点运算转换成浮点运算的函数调用和库函数调用,没有FPU的指令调用,也没有浮点寄存器的参数传递。浮点参数的传递也是通过ARM寄存器或者堆栈完成。

       çŽ°åœ¨çš„Linux系统默认编译选择使用hard-float,即使系统没有任何浮点处理器单元,这就会产生非法指令和异常。因而一般的系统镜像都采用软浮点以兼容没有VFP的处理器。

       armel ABI和armhf ABI

       åœ¨armel中,关于浮点数计算的约定有三种。以gcc为例,对应的-mfloat-abi参数值有三个:soft,softfp,hard。

       soft是指所有浮点运算全部在软件层实现,效率当然不高,会存在不必要的浮点到整数、整数到浮点的转换,只适合于早期没有浮点计算单元的ARM处理器;

       softfp是目前armel的默认设置,它将浮点计算交给FPU处理,但函数参数的传递使用通用的整型寄存器而不是FPU寄存器;

       hard则使用FPU浮点寄存器将函数参数传递给FPU处理。

       éœ€è¦æ³¨æ„çš„是,在兼容性上,soft与后两者是兼容的,但softfp和hard两种模式不兼容。

       é»˜è®¤æƒ…况下,armel使用softfp,因此将hard模式的armel单独作为一个abi,称之为armhf。

       è€Œä½¿ç”¨hard模式,在每次浮点相关函数调用时,平均能节省个CPU周期。对ARM这样每个周期都很重要的体系结构来说,这样的提升无疑是巨大的。

       åœ¨å®Œå…¨ä¸æ”¹å˜æºç å’Œé…ç½®çš„情况下,在一些应用程序上,使用armhf能得到%——%的性能提升。对一些严重依赖于浮点运算的程序,更是可以达到%的性能提升。

       Soft-float和hard-float的编译选项

       åœ¨CodeSourcery gcc的编译参数上,使用-mfloat-abi=name来指定浮点运算处理方式。-mfpu=name来指定浮点协处理的类型。

       å¯é€‰ç±»åž‹å¦‚fpa,fpe2,fpe3,maverick,vfp,vfpv3,vfpv3-fp,vfpv3-d,vfpv3-d-fp,vfpv3xd,vfpv3xd-fp,neon,neon-fp,vfpv4,vfpv4-d,fpv4-sp-d,neon-vfpv4等。

       ä½¿ç”¨-mfloat-abi=hard (等价于-mhard-float) -mfpu=vfp来选择编译成硬浮点。使用-mfloat-abi=softfp就能兼容带VFP的硬件以及soft-float的软件实现,运行时的连接器ld.so会在执行浮点运算时对于运算单元的选择,

       æ˜¯ç›´æŽ¥çš„硬件调用还是库函数调用,是执行/lib还是/lib/vfp下的libm。-mfloat-abi=soft (等价于-msoft-float)直接调用软浮点实现库。

       åœ¨ARM RVCT工具链下,定义fpu模式:

       â€“fpu softvfp

       â€“fpu softvfp+vfpv2

       â€“fpu softvfp+vfpv3

       â€“fpu softvfp+vfpv_fp

       â€“fpu softvfp+vfpv_d

       â€“fpu softvfp+vfpv_d_fp.

       å®šä¹‰æµ®ç‚¹è¿ç®—类型

       â€“fpmode ieee_full : 所有单精度float和双精度double的精度都要和IEEE标准一致,具体的模式可以在运行时动态指定;

       â€“fpmode ieee_fixed : 舍入到最接近的实现的IEEE标准,不带不精确的异常;

       â€“fpmode ieee_no_fenv :舍入到最接近的实现的IEEE标准,不带异常;

       â€“fpmode std :非规格数flush到0、舍入到最接近的实现的IEEE标准,不带异常;

       â€“fpmode fast : 更积极的优化,可能会有一点精度损失。