W806 是一款安全 IoT MCU 芯片。芯片集成 32 位 CPU 处理器,内置 UART、GPIO、SPI、SDIO、 I2C、I2S、PSRAM、7816、ADC、LCD、TouchSensor 等数字接口;支持 TEE 安全引擎,支持多种硬件加解密算法,内置 DSP、浮点运算单元与安全引擎,支持代码安全权限设置,内置 1MB Flash 存储器,支持固件加密存储、固件签名、安全调试、安全升级等多项安全措施,保证产品安全特性。适用用于小家电、智能家居、智能玩具、工业控制、医疗监护等广泛的物联网领域。
文章目录
FPU简介
以下内容摘抄自《玄铁E804用户手册_v04》。
浮点单元作为 E804 的可配置硬件单元,旨在提升 E804 面向浮点应用的处理能力。E804 浮点单元提供了一种低成本、高性能的硬件浮点实现。
浮点单元支持 IEEE-754 浮点标准中的单精度浮点运算,实现了 16 个单精度浮点寄存器。在系统软件支持下,E804可实现对双精度浮点运算的支持。
浮点单元的体系结构与编程模型的主要特点如下:
- 完全兼容 ANSI/IEEE Std 754 浮点标准(系统软件支持下);
- 仅支持单精度浮点运算;
- 支持向零舍入、向正无穷舍入、向负无穷舍入和就近舍入四种舍入方式;
- 支持浮点异常的陷入与非陷入两种处理模式;
- 支持浮点异常的精确处理;
- 支持浮点硬件除法与开方。
浮点单元的微体系结构的主要特点如下:
- 16 个独立的单精度浮点寄存器;
- 单发射结构,每个周期处理一条浮点算术指令;
- 支持浮点算术指令的按序发射、按序执行、按序回写;
- 包含三条独立的执行流水线,分别是浮点 ALU、浮点乘法与浮点除法开方;
- 优化的执行延时技术,除浮点除法开方指令外,均可在 1-2 个时钟周期执行完毕;
- 基于运算部件复用的成本优化技术;
- 基于门控时钟与数据通路隔离的功耗优化技术。
测试项目
基本算法
- 浮点与浮点的加减乘除
- 三角函数和反三角函数
- 开平方
- e为底的X次幂
- X的Y次幂
复合算法
- 100点一阶低通滤波
- 100点正弦曲线值
- 32*32像素RGB转灰度
测试方法
分别记录关闭FPU和开启FPU时,10ms定时周期内的算法执行次数,值越高越好。
所有测试统一使用单精度浮点,代码-O3优化,为了尽量减少循环带来的额外开销,手动展开了最里层的循环。
测试结果
基本算法
浮点与浮点的加减乘除
__IO uint32_t cnt = 0;
__IO float a = 1.1f;
__IO float b = 0.123456f;
__IO float c;
while(1)
{
c = a + b;
c = a + b;
c = a + b;
c = a + b;
cnt += 4;
}
结果如下,减法、乘法、除法的测试方法和加法是一样的,所以测试代码就不放出来了。
算法 | 关闭FPU(次/10ms) | 打开FPU(次/10ms) | 次数比 |
---|---|---|---|
c = a + b | 12708 | 319268 | 25.12 |
c = a - b | 11116 | 319268 | 28.72 |
c = a * b | 18640 | 319268 | 17.13 |
c = a / b | 5592 | 69412 | 12.41 |
三角函数和反三角函数
算法 | 关闭FPU(次/10ms) | 打开FPU(次/10ms) | 次数比 |
---|---|---|---|
c = sinf(a) | 440 | 14068 | 31.97 |
c = cosf(a) | 480 | 15628 | 32.56 |
c = tanf(a) | 236 | 9268 | 39.27 |
c = asinf(a) | 6612 | 41112 | 6.22 |
c = acosf(a) | 6668 | 37860 | 5.68 |
c = atanf(a) | 336 | 3816 | 11.36 |
开平方
while(1)
{
c = sqrtf(a);
c = sqrtf(a);
c = sqrtf(a);
c = sqrtf(a);
cnt += 4;
}
算法 | 关闭FPU(次/10ms) | 打开FPU(次/10ms) | 次数比 |
---|---|---|---|
sqrtf() | 7364 | 57704 | 7.84 |
e为底的X次幂
while(1)
{
c = expf(a);
c = expf(a);
c = expf(a);
c = expf(a);
cnt += 4;
}
算法 | 关闭FPU(次/10ms) | 打开FPU(次/10ms) | 次数比 |
---|---|---|---|
expf() | 444 | 14404 | 32.44 |
X的Y次幂
while(1)
{
c = powf(a, b);
c = powf(a, b);
c = powf(a, b);
c = powf(a, b);
cnt += 4;
}
算法 | 关闭FPU(次/10ms) | 打开FPU(次/10ms) | 次数比 |
---|---|---|---|
powf() | 124 | 5308 | 42.8 |
复合算法
100点一阶低通滤波
__IO float t1[100];
__IO float t2;
static inline float first_oder_filter(float new_data)
{
static float old_data;
float a = 0.05f;
old_data = a * new_data + (1.0f - a) * old_data;
return old_data;
}
int main(void)
{
SystemClock_Config(CPU_CLK_240M);
for (uint32_t i = 0; i < 100; i++)
{
t1[i] = rand() / (float)(RAND_MAX / 0xffff);
}
while (1)
{
for (uint32_t i = 0; i < 100; i += 4)
{
t2 = first_oder_filter(t1[i]);
t2 = first_oder_filter(t1[i + 1]);
t2 = first_oder_filter(t1[i + 2]);
t2 = first_oder_filter(t1[i + 3]);
}
cnt++;
}
return 0;
}
关闭FPU(次/10ms) | 打开FPU(次/10ms) | 次数比 |
---|---|---|
37 | 1940 | 52.43 |
100点正弦曲线
int main(void)
{
SystemClock_Config(CPU_CLK_240M);
/* 正弦曲线公式:y=Asin(ωx+ψ)+k */
__IO float W = 3.1415926f / 50.f;
__IO float A = 100.0f;
__IO float k = 50.0f;
__IO float offset = 6.0f;
__IO float wave;
__IO float x[100] = { 0.0f };
float temp = 0.0f;
for (uint32_t i = 0; i < 100; i++)
{
x[i] = temp + 0.05f;
}
while (1)
{
for (uint32_t i = 0; i < 100; i += 4)
{
wave = A * sinf(W * x[i] + offset) + k;
wave = A * sinf(W * x[i + 1] + offset) + k;
wave = A * sinf(W * x[i + 2] + offset) + k;
wave = A * sinf(W * x[i + 3] + offset) + k;
}
cnt++;
}
return 0;
}
关闭FPU(次/10ms) | 打开FPU(次/10ms) | 次数比 |
---|---|---|
4 | 116 | 29.0 |
32*32像素RGB转灰度
int main(void)
{
SystemClock_Config(CPU_CLK_240M);
__IO uint32_t cnt = 0;
__IO uint8_t color_r[32][32];
__IO uint8_t color_g[32][32];
__IO uint8_t color_b[32][32];
__IO uint8_t color_gray[32][32];
for (uint32_t i = 0; i < 32; i++)
{
for (uint32_t j = 0; j < 32; j++)
{
color_r[i][j] = rand() % 0xff;
color_g[i][j] = rand() % 0xff;
color_b[i][j] = rand() % 0xff;
}
}
while (1)
{
for (uint32_t i = 0; i < 32; i++)
{
for (uint32_t j = 0; j < 32; j += 4)
{
color_gray[i][j] = color_r[i][j] * 0.299f + color_g[i][j] * 0.587f + color_b[i][j] * 0.114f;
color_gray[i][j + 1] = color_r[i][j + 1] * 0.299f + color_g[i][j + 1] * 0.587f + color_b[i][j + 1] * 0.114f;
color_gray[i][j + 2] = color_r[i][j + 2] * 0.299f + color_g[i][j + 2] * 0.587f + color_b[i][j + 2] * 0.114f;
color_gray[i][j + 3] = color_r[i][j + 3] * 0.299f + color_g[i][j + 3] * 0.587f + color_b[i][j + 3] * 0.114f;
}
}
cnt++;
}
return 0;
}
关闭FPU(次/10ms) | 打开FPU(次/10ms) | 次数比 |
---|---|---|
2 | 61 | 30.5 |
总结
通过以上测试结果可以发现,W806的XT804内核在没有FPU时的浮点数计算能力是非常弱的,而FPU的加入可以大幅提高内核对于单精度浮点的计算能力,不管是基础算法还是复合算法,几乎都是几十倍的提升。W806的工程是默认开启FPU的,直接用就好。
参考资料
- 《W806 MCU 芯片规格书V2.0》
- 《玄铁E804用户手册_v04》