From bc93909d9b0484dc73921aa03c61fd4af21a594c Mon Sep 17 00:00:00 2001 From: Brad Barnett <127794626+bdbarnett@users.noreply.github.com> Date: Fri, 6 Nov 2026 03:06:54 -0600 Subject: [PATCH] MicroPython port: stm32 builds with single-precision floats link LVGL's gesture recogniser calls the double sqrt(), and an stm32 firmware built with MICROPY_FLOAT_IMPL=single links only MicroPython's single-precision libm, which has sqrtf() and no sqrt(). The link failed on the Arduino Giga R1. The port now adds a sqrt() that calls sqrtf() to those builds only; gesture distances are pixels, so single precision is enough. --- ports/micropython/micropython.mk | 8 ++++++++ ports/micropython/src/lv_sqrt_single.c | 20 +++++++++++++++++++ .../tests/test_micropython_port.py | 8 ++++++++ 3 files changed, 36 insertions(+) create mode 100644 ports/micropython/src/lv_sqrt_single.c diff --git a/ports/micropython/micropython.mk b/ports/micropython/micropython.mk index d8b8894..afca3d3 100644 --- a/ports/micropython/micropython.mk +++ b/ports/micropython/micropython.mk @@ -53,6 +53,14 @@ endif SOURCES += $(LVMP_DIR)/src/lv_mem_core_micropython.c +# An stm32 firmware with single-precision floats links MicroPython's +# single-precision libm, which has no double sqrt() for LVGL's gesture code. +ifneq ($(findstring /ports/stm32,$(LVMP_PORT_DIR)),) +ifeq ($(MICROPY_FLOAT_IMPL),single) +SOURCES += $(LVMP_DIR)/src/lv_sqrt_single.c +endif +endif + $(if $(wildcard $(LVMP_C)),,$(error $(LVMP_C) not found. Run $(BINDINGS_DIR)/regenerate_all.sh --target micropython)) # -Wno-unused-function here is not enough on ports that append -Werror after py.mk diff --git a/ports/micropython/src/lv_sqrt_single.c b/ports/micropython/src/lv_sqrt_single.c new file mode 100644 index 0000000..d706a66 --- /dev/null +++ b/ports/micropython/src/lv_sqrt_single.c @@ -0,0 +1,20 @@ +// SPDX-FileCopyrightText: 2026 Brad Barnett +// +// SPDX-License-Identifier: MIT + +// LVGL's gesture recogniser (src/indev/lv_indev_gesture.c) calls the double +// sqrt(). An stm32 firmware built with single-precision floats links only +// MicroPython's single-precision libm, which has sqrtf() and no sqrt(), so the +// link fails. Gesture distances are pixels: single precision is plenty. + +#include "py/mpconfig.h" + +#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT + +float sqrtf(float x); + +double sqrt(double x) { + return sqrtf((float)x); +} + +#endif diff --git a/ports/micropython/tests/test_micropython_port.py b/ports/micropython/tests/test_micropython_port.py index c259c2e..8d38c1a 100644 --- a/ports/micropython/tests/test_micropython_port.py +++ b/ports/micropython/tests/test_micropython_port.py @@ -32,3 +32,11 @@ def test_fs_driver_is_frozen_from_the_one_copy(): def test_no_consumer_smoke_wrapper_remains(): assert not (ROOT / "tools" / "test_lvgl_unix.py").exists() + + +def test_stm32_single_float_builds_get_a_double_sqrt(): + make = (ROOT / "micropython.mk").read_text() + assert "src/lv_sqrt_single.c" in make + assert "/ports/stm32" in make + shim = (ROOT / "src" / "lv_sqrt_single.c").read_text() + assert "MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT" in shim