本帖最后由 hello、C 于 2021-2-27 15:26 编辑
#申请原创# #技术资源#
在传统的C51单片机及基于ARM Cortex M0、Cortex M0+及ARM Cortex M3内核的微控制器上,
加上其时钟频率不会太高,因此在浮点运算的应用场合,会显得较为吃力,CPU使用效率低下。
当计算一次含有一个单精度的浮点运算数和一个正整数的乘法时,单指令周期,时钟频率为
25MHz的单片机时,其大概将占用几十微秒至上百微秒不等。在性能要求较高,延迟要求较低,
精度要求较高,需要大量浮点运算的应用场合时,不含FPU单元的单片机将显得捉襟见肘,力
不从芯。
今天测评下雅特力官方提供的关于FPU效率的例程,在板级支持包里面,Keil工程路径为:
BSP\AT32F4xx_StdPeriph_Lib_V1.2.9\Project\AT_START_F407\Examples\CortexM4\FPU. 在
该路径下,包含有FPU使用的帮助文档,在很多文档里面都有提及,附上官方应用笔记:
AN0037_How_to_use_FPU_ZH_V1.0.0.pdf
(376.18 KB)
打开FPU的Keil工程,编译链接,下载程序,观察结果。复位两次产生同样的结果。如图
所示:
测试花费了219ms,分析一下程序文件,在main.c文件中,执行了一个函数:
Generate**_fpu(SCREEN_X_SIZE,
SCREEN_Y_SIZE,
SCREEN_X_SIZE / 2,
SCREEN_Y_SIZE / 2,
animation_zoom[animation_pointer],
buffer);
Func code:
/**
******************************************************************************
* File : CortexM4/FPU/at32f4xx_**_fpu.c
* Version: V1.2.9
* Date : 2021-01-15
* Brief : at32f4xx **_fpu source file
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "at32f4xx_**.h"
/** @addtogroup AT32F407_StdPeriph_Examples
* @{
*/
/** @addtogroup CortexM4_FPU
* @{
*/
/**
* [url=home.php?mod=space&uid=247401]@brief[/url] ** Calculation with FPU option disable
* @param size_x: screen width in pixel
* @param size_y: screen height in pixel
* @param offset_x: x offset for starting point
* @param offset_y: y offset for starting point
* @param zoom: Iteration zoom ratio
* @param buffer: pointer to output buffer where values are stored
* @retval None
*/
void Generate**_fpu(uint16_t size_x, uint16_t size_y, uint16_t offset_x, uint16_t offset_y, uint16_t zoom, uint8_t * buffer)
{
float tmp1, tmp2;
float num_real, num_img;
float rayon;
uint8_t i;
uint16_t x, y;
for (y = 0; y < size_y; y++)
{
for (x = 0; x < size_x; x++)
{
num_real = y - offset_y;
num_real = num_real / zoom;
num_img = x - offset_x;
num_img = num_img / zoom;
i = 0;
rayon = 0;
while ((i < ITERATION - 1) && (rayon < 4))
{
tmp1 = num_real * num_real;
tmp2 = num_img * num_img;
num_img = 2 * num_real * num_img + IMG_CONSTANT;
num_real = tmp1 - tmp2 + REAL_CONSTANT;
rayon = tmp1 + tmp2;
i++;
}
/* Store the value in the buffer */
buffer[x+y*size_x] = i;
}
}
}
/**
* @}
*/
/**
* @}
*/
搜索了一下 ** FPU 这个东西,有如下描述:
①FPU **是利用朱利亚碎形几何运算,来评估CPU的单精度(32bit)浮点运算能力。
②This benchmark measures the single precision (also known as 32-bit) floating-point performance through the computation of several frames of the popular “**” fractal. The code behind this benchmark method is written in Assembly, and it is extremely optimized for every popular AMD, Intel and VIA processor core variants by utilizing the appropriate x87, 3DNow!, 3DNow!+, SSE, AVX or FMA4 instruction set extension.FPU ** test consumes 4 MB system memory per calculation thread, and it is HyperThreading, multi-processor (SMP) and multi-core (CMP) aware.
大致存在以下这么几个概念:
** 集合的生成算法: 对于复平面的每个点,我们计算一个定义序列的发散速度。该序列的** 集计算公式为:
【Zn+1 = Zn2 + c】
针对复平面的每个 【x + i.y】 点,我们用 【c = cx + i.cy】 计算该序列:
【Xn+1 + i.Yn+1 = Xn2 - Yn2 + 2.i.Xn.Yn + cx + i.cy】
【Xn+1 = Xn2 - Yn2 + cx】 且 【Yn+1 = 2.Xn.Yn + cy】
一旦计算出的复值超出给定圆的范围(数值大小大于圆半径),序列便会发散,达到此限值时
完成的迭代次数与该点相关。随后将该值转换为颜色,以图形方式显示复平面上各个点的分散
速度。经过给定的迭代次数后,若产生的复值保持在圆范围内,则计算过程停止,并且序列也
不发散。
特点:
这种算法非常有效地展示了 FPU 的优势:无需修改代码,只需在编译阶段激活或禁止FPU(在
MDK Code Generation 里面设置:Use FPU/Not Used),即可测试使用硬件 FPU 和不使用硬件
FPU 的差距。
那么我们根据提示,设置工程配置里面的Floating Point Hardware为Not use.
如图所示:
编译链接,下载程序,然后输出测试结果,复位两次后产生同样的结果。
如图所示:
算一下使用了硬件FPU浮点运算单元后其浮点运算性能较不使用提升了:
2715ms / 219ms = 12.3972603倍的运算性能,可以看到提升还是很大的,相当于几十微秒的运算,
时间,使用硬件FPU后可能只有几微秒的运算延迟。心情一下就舒畅了,哈哈。。。
最后总结一句话,雅特力 AT32F407 CortexM4 FPU 可以的!!!
|