RT-Thread/rt-thread

[Bug] bsp/cvitek 大核无法支持 float 指令

unicornx opened this issue · 14 comments

RT-Thread Version

master

Hardware Type/Architectures

bsp/cvitek

Develop Toolchain

GCC

Describe the bug

bsp/cvitek/cv18xx_risc-v/applications/main.c 的 main 中加入如下代码:

flaot f = 100;

编译正常,但是运行会 crash,报 Unhandled Exception 2:Illegal Instruction

同样的代码加在 bsp/cvitek/c906_little/applications/main.c 中就正常

简单分析后发现大小核的编译选项有区别:
大核:-mabi=lp64

小核:-mabi=lp64d

统一成 -mabi=lp64d, 大核仍然 crash

后继续将大核的 gcc 换成 musl 的,即 https://download-redirect.rt-thread.org/download/rt-smart/toolchains/riscv64gc-linux-musleabi_for_x86_64-pc-linux-gnu_latest.tar.bz2

发现链接时报错:can't link soft-float modules with double-float modules

Other additional context

No response

走读代码时发现 libcpu/risc-v/t-head/c906/startup_gcc.S 存在如下逻辑:

    /* set to disable FPU */
    li t0, SSTATUS_FS
    csrc sstatus, t0
    li t0, SSTATUS_SUM
    csrs sstatus, t0

怀疑这会影响 float 指令的执行,但注释掉这四行语句后,运行依然报非法指令错误。

所以想问一下,@BernardXiong 当时为啥要 diable FPU?

@BernardXiong 搜索 libcpu/risc-v/t-head/c906/ 代码,还发现有不少 ifdef ENABLE_FPU 的逻辑,但是 Kconfig 中并没有 ENABLE_FPU 的配置开关。

请问当时移植 libcpu/risc-v/t-head/c906/ 的代码历史是什么?感觉需要再整理一下?

  • 保留 libcpu/risc-v/t-head/c906/startup_gcc.S 中 diable FPU 的操作 (即保持目前仓库中代码不变)。
  • 强制在 rtconfig.h 中手动定义 ENABLE_FPU
  • 修改 bsp/cvitek/cv18xx_risc-v/rtconfig.py, 将 -mabi=lp64 改成 -mabi=lp64d

编译ok,运行也正常,但是发现 rt_kprintf 无法打印 %f, 换成 printf 可以打印。

备注,没有使用 musl gcc,还是和小核一样用的 newlib 的 gcc

int main(void)
{
    int i= 100;
    float f = 100;

    float x = f / 2;
    i = x;

    rt_kprintf("rt_kprintf x = %f\n", x);
    rt_kprintf("Hello RTT test!, x = %d\n", i);
    printf("printf x = %f\n", x);

    return 0;
}

运行显示:

rt_kprintf x = %f
Hello RTT test!, x = 50
printf x = 50.000000

难道 rt_kprintf 自身不支持 float 打印?还不太清楚,网上搜到一篇文章:https://github.com/mysterywolf/rt_vsnprintf_full

但搜索 rtt 源码树,也看到有对 rt_kprintf 调用 %f 的例子,譬如 components/drivers/sensor/v2/sensor_cmd.c 中,所以目前猜测打印的问题可能和使用了 newlib gcc 有关系,尝试了在小核上也是一样的效果。

至于为啥 printf 可以,这个还没有深入研究。

rt_kprintf是不支持float打印的

目前这个 issue 实际上可以分成两个问题

  • 问题 1:基于 newlib gcc 的 FPU 没有 enable 导致 float 指令异常
  • 问题 2:将 -mabi=lp64 改成 -mabi=lp64d 后换成 musl gcc 链接报错。

从长远看,如果大核要上 smart,以及为了解决 #8943,则要用 musl gcc,但是由于 问题 2 ,可能要从 toolchain 角度再看看,这个应该要用另外一个 issue 跟踪。

如果单纯为了解决问题 1,不换 newlib gcc,那么我认为可以采用修改 Kconfig,增加 ENABLE_FPU 选项方式。但 @flyingcys 建议采用 ARCH_RISCV_FPU_D 更好。

image

目前这个 issue 实际上可以分成两个问题

  • 问题 1:基于 newlib gcc 的 FPU 没有 enable 导致 float 指令异常
  • 问题 2:将 -mabi=lp64 改成 -mabi=lp64d 后换成 musl gcc 链接报错。

从长远看,如果大核要上 smart,以及为了解决 #8943,则要用 musl gcc,但是由于 问题 2 ,可能要从 toolchain 角度再看看,这个应该要用另外一个 issue 跟踪。

针对问题 2 新提了一个 issue:#9094。本 issue 仅用于跟踪 问题 1。

走读代码时发现 libcpu/risc-v/t-head/c906/startup_gcc.S 存在如下逻辑:

    /* set to disable FPU */
    li t0, SSTATUS_FS
    csrc sstatus, t0
    li t0, SSTATUS_SUM
    csrs sstatus, t0

怀疑这会影响 float 指令的执行,但注释掉这四行语句后,运行依然报非法指令错误。

启动时关闭 FPU VPU 是因为它们是按需自动开启的 😂 否则会拖垮大部分常规任务的整体性能

目前这个 issue 实际上可以分成两个问题

  • 问题 1:基于 newlib gcc 的 FPU 没有 enable 导致 float 指令异常
  • 问题 2:将 -mabi=lp64 改成 -mabi=lp64d 后换成 musl gcc 链接报错。

从长远看,如果大核要上 smart,以及为了解决 #8943,则要用 musl gcc,但是由于 问题 2 ,可能要从 toolchain 角度再看看,这个应该要用另外一个 issue 跟踪。

针对问题 2 新提了一个 issue:#9094。本 issue 仅用于跟踪 问题 1。

问题 2 应该不是问题,保留 -mabi=lp64 即可。#9094 已经关闭。

参考 https://github.com/RT-Thread/rt-thread/blob/master/bsp/qemu-virt64-riscv/README_ch.md

  • 如果 -march 包含 v, 选择 Using RISC-V Vector Extension, 反之关闭
  • 如果 -march 包含 f/d, 选择 Enable FPU, 反之关闭

所以 rootcause 就是 bsp/cvitek 的 大核 配置没有 enable FPU,需要补上。

#9290 为 cvitek 大核使能了 float,如果这个 pr 能进主线,也就解决了本 issue。tracking......

#9290 这个要合并吗?

#9290 这个要合并吗?

先 review 吧 ~~~

solved: #9290

verified float can work now after #9290 is merged.
Verified commit id: d2160d3