有了浮点数运算的ICM42686驱动编译通过后,启动内核报错,如下:
[ 0.415753] --- icm42686_init ---
[ 0.415817] --- spi_match_device ---
[ 0.415880] --- spi_drv_probe ---
[ 0.416090] --- icm42686 probe ---
[ 0.439919] mmc_host mmc0: Bus speed (slot 0) = 198000000Hz (slot req 200000000Hz, actual 198000000HZ div = 0)
[ 0.439977] dwmmc_rockchip ffc50000.dwmmc: Successfully tuned phase to 90
[ 0.440666] mmc0: new HS200 MMC card at address 0001
[ 0.442242] mmcblk0: mmc0:0001 AJTD4R 14.6 GiB
[ 0.443150] mmcblk0boot0: mmc0:0001 AJTD4R partition 1 4.00 MiB
[ 0.444030] mmcblk0boot1: mmc0:0001 AJTD4R partition 2 4.00 MiB
[ 0.444728] mmcblk0rpmb: mmc0:0001 AJTD4R partition 3 4.00 MiB, chardev (242:0)
[ 0.452505] mmcblk0: p1 p2 p3 p4 p5 p6 p7 p8 p9
[ 0.518613] --- icm42686 ID = 0x44 ---
[ 0.522191] BUG: FP instruction issued in kernel mode with FP unit disabled
[ 0.522235] Internal error: Oops - undefined instruction: 0 [#1] PREEMPT SMP ARM
[ 0.523502] Modules linked in:
[ 0.523796] CPU: 2 PID: 1 Comm: swapper/0 Not tainted 4.19.111 #49
[ 0.524340] Hardware name: Generic DT based system
[ 0.524775] PC is at icm42686_get_data_front+0xc/0x21c
[ 0.525236] LR is at icm42686_probe+0x134/0x18c
【尝试解决】
1.修改arch/arm/Makefile,把 -msoft-float 改成 -mhard-float
# Need -Uarm for gcc < 3.x
KBUILD_CFLAGS +=$(CFLAGS_ABI) $(CFLAGS_ISA) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -mhard-float -Uarm
KBUILD_AFLAGS +=$(CFLAGS_ABI) $(AFLAGS_ISA) $(arch-y) $(tune-y) -include asm/unified.h -mhard-float
编译遇到报错:
/arch/arm/vdso/vdsomunge: Unexpected hard-float flag set in e_flags
2.使用 kernel_neon_begin() 和 kernel_neon_end()
运行还是panic。
3.浮数运算测试
理念上,不管硬还是软浮点,只是性能上的影响,不会报错,问题不是出现在运算上,而是浮点数作为参数的问题,写个简单的驱动试了试,如下代码:
a = icm42686_accel_data_gravity(12.34, 32.25) * ( 3.1415926 / 180 ); // 正常运行
h =12.34;
l =32.25;
a = icm42686_accel_data_gravity(h, l); // kernel panic
分析其原因,在内核运行这些代码,在进行函数栈调用切换时,没有保存和恢复浮点寄存器,从而导致内核崩了。