news 2026/8/5 9:11:08

【转载】RISC-V IDE MRS2 代码编译 : 通过配置FPU提升浮点运算性能

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【转载】RISC-V IDE MRS2 代码编译 : 通过配置FPU提升浮点运算性能

本文介绍嵌入式中的浮点数与青稞系列芯片的FPU硬件浮点单元,并说明如何使用MRS2配置FPU提升浮点性能以及串口打印浮点数。

一、单精度浮点数与双精度浮点数

嵌入式处理器使用的浮点数遵循 IEEE 754 标准。这套标准规定了一种将实数编码为有限位二进制的方式,其核心思想是把一个数分解为三个独立的字段:符号位(Sign)、指数位(Exponent)和尾数位(Mantissa)。这三个字段在内存中是紧密排列的。

值 = (−1)^S × 2^(E − bias) × (1 + Mantissa)

浮点数一般根据其占用的位宽度分为单精度浮点数(float)与双精度浮点数(double)。其在内存中的布局如下所示。

单精度(float)的位布局

S(符号)Exponent(指数)Mantissa(尾数)
1 位8位 · bias=12723位

双精度(double)的位布局

S(符号)Exponent(指数)Mantissa(尾数)
1 位11位 · bias=102352位

单精度float占用 4 字节,能够提供约 7 位有效十进制数的精度,数值范围覆盖 ±3.4×10³⁸。双精度double则占用 8 字节,精度提升到约 15~16 位,范围扩展到 ±1.7×10³⁰⁸。从数学上看,double显然更精确,但在嵌入式领域,精度优势无法弥补它花费的巨大开销,优先使用float才是更好的选择。

二、浮点数常量

嵌入式开发中浮点数有一个非常容易被忽视的细节。

C 语言里所有不带后缀的浮点字面量,比如0.01、3.14,其类型默认是double而不是float 。

例如一个简单的浮点计算并赋值的代码:

float x = 3.14 * 2.0;

3.14和2.0都没有f后缀,所以编译器会把这两个常量都当作double来处理。由于赋值给float变量,因此在以double运算后编译器会进行一次截断,将64位运算结果截断为32位的float。

还有一种混合的情况:

float x = 3.14f * 2.0;

3.14添加了f后缀,显式定义为float常量,2.0未加f后缀,依然默认为double常量。C 语言规定,当 float 和 double 混合运算时,float 那一方会被隐式提升为 double,然后以 double 精度完成乘法,最后再截断回 float。也就是说,只要包含一个未加后缀的操作数,表达式就会以double进行运算。

建议给所有浮点数添加后缀f显式声明其为float常量。

float x = 3.14f * 2.0f;

此时由于全部操作数都为float,表达式会以float进行运算。在使用软件浮点库中的函数进行运算时似乎与使用double没有太大差别,但当芯片内置支持单精度运算的硬件浮点单元(FPU)时,float运算会有巨大的提升。

三、FPU 硬件浮点单元

FPU(Floating Point Unit,浮点运算单元)是处理器中专门用于执行浮点数运算的硬件模块。利用软件浮点库进行浮点运算时,调用相关的浮点运算函数进行模拟,一般需要十几到几十条指令才能完成。而在FPU的帮助下,加法、乘法等基础浮点运算可以在单个时钟周期内完成,极大提高浮点运算效率。

WCH部分芯片支持FPU,例如青稞V3F\V5F内核芯片(CH32H416、CH32H415、CH32H417)和青稞V4F内核芯片(CH32V303、CH32V305、CH32V307、CH32V317)。以上型号支持RISC-V F指令集,拥有F0-F31共32个浮点寄存器,用于存储单精度浮点指令所需数据。

使用MRS2开发时,通过几步配置即可使用芯片的FPU提高浮点运算性能。

1.勾选浮点扩展与ABI

打开工程配置Build Settings->Tool Settings->Target Processor页面:

Floating point选择Single precision extension(RVF)单精度浮点扩展;

Floating point ABI选择Single precision(f)单精度浮点。

2.勾选浮点优化选项

打开工程配置Build Settings->Tool Settings->Optimization页面

勾选Single precision constants(-fsingle-precision-constant)选项。

开启这个选项之后,会将源码里所有不带后缀的浮点常量强制当作float来处理,效果等同于在每一个浮点常量后手动加了f。可确保浮点运算为单精度,充分利用FPU硬件浮点单元提高浮点运算性能。

四、浮点数打印

嵌入式开发环境一般默认使用裁剪过的C库(如newlib-nano),出于代码体积考虑,printf的实现删去了浮点格式化的支持。如果直接调用printf("%.2f", val) ,串口浮点数输出为空。

若需通过串口打印浮点数,需要链接相应的浮点打印库。

MRS2中通过勾选链接选项,选择合适的浮点打印库,即可在串口打印浮点数。

打开工程配置Build Settings->Tool Settings->GNU RISC-V Cross Linker->Miscellaneous页面。

勾选Use float with nano printf(-u _printf_float)会使用标准库newlib-nano中的浮点打印函数,支持更全面的输出格式,相应的链接库体积会稍大;

勾选Use wchprintfloat(-lprintfloat)会使用MRS提供的精简浮点打印函数,仅保留常用的输出格式,能够有效减小代码体积。

同时,Use wchprintfloat(-lprintfloat)还可支持64位数据打印。

根据自身需求选择合适的选项即可。推荐使用Use wchprintfloat选项,基本可满足常见浮点打印格式需求,且代码体积优势较为明显。

————————————————
版权声明:本文为CSDN博主「MounRiver_Studio」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_36353650/article/details/163241703

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/5 9:09:53

G-Helper终极指南:如何免费解锁华硕笔记本完整性能控制功能

G-Helper终极指南:如何免费解锁华硕笔记本完整性能控制功能 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProArt, Vivobook, Zenboo…

作者头像 李华
网站建设 2026/8/5 9:09:42

基于RAG与Cherry Studio构建高精度私有AI知识库实战指南

在业务中尝试接入大模型时,你是否遇到过这样的困境:模型回答看似流畅,但一涉及公司内部文档、产品手册或私有代码库等具体知识,就常常“胡言乱语”,给出不准确甚至完全错误的答案?这正是传统大模型应用的核…

作者头像 李华
网站建设 2026/8/5 9:07:37

高压降压设计实战:从选型误区到Hi9214高效稳定电源方案

上周,一个做户外储能项目的朋友找到我,说他们新设计的板子,在给主控MCU供电的12V转5V这一路上,遇到了大麻烦。板子静态时一切正常,但只要一接上负载,尤其是负载电流变化时,输出电压就“跳舞”&a…

作者头像 李华
网站建设 2026/8/5 9:06:12

树莓派SPI1接口配置MCP2515 CAN总线控制器完整指南

1. 项目概述:当树莓派的SPI0口被占用时 玩树莓派的朋友,尤其是做物联网、机器人或者汽车电子相关项目的,肯定对MCP2515这颗CAN总线控制器芯片不陌生。它价格便宜,驱动成熟,是让树莓派接入CAN网络最经典、最稳定的方案。…

作者头像 李华
网站建设 2026/8/5 9:03:29

从黑盒到白盒:逆向分析赛尔号通信协议的技术实践

1. 从“黑盒”到“白盒”:为什么我们要对赛尔号通信下手? 如果你在2010年前后接触过网页游戏,那么“赛尔号”这个名字大概率不会陌生。这款基于Adobe Flash Player的页游,承载了一代人的童年回忆。但今天,我们不是来怀…

作者头像 李华