Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Building for ESP32 #102

Open
madwizard-thomas opened this issue Apr 19, 2023 · 33 comments · May be fixed by #153
Open

Building for ESP32 #102

madwizard-thomas opened this issue Apr 19, 2023 · 33 comments · May be fixed by #153
Labels
bug Something isn't working

Comments

@madwizard-thomas
Copy link

madwizard-thomas commented Apr 19, 2023

Hi,

I'm trying to get lvgl-rs to run on ESP32 (m5stack core2 module to be precise) on a windows host and ran into some issues with cc and bindgen in lvlg-sys. The esp32 environment does not need cross but normally works out of the box with the correct target (xtensa-esp32-elf in my case). Most issues were fixable by specifying the right environment variables. For anyone playing along at home, besides the .\export-esp.ps1 script you will need:

CROSS_COMPILE, CC, AR for cc to pick the right compiler, and C_INCLUDE_PATH for bindgen to find the system headers. In powershell (for my specific version):

$ENV:CROSS_COMPILE="xtensa-esp32-elf"

$ENV:CC="xtensa-esp32-elf-cc"
$ENV:AR="xtensa-esp32-elf-ar"

$ENV:C_INCLUDE_PATH = (@(
 "lib\gcc\xtensa-esp32-elf\8.4.0\include", 
 "lib\gcc\xtensa-esp32-elf\8.4.0\include-fixed",
 "xtensa-esp32-elf\sys-include", 
 "xtensa-esp32-elf\include"
) | % { Join-Path "$HOME\.rustup\toolchains\esp\xtensa-esp32-elf\esp-2021r2-patch5-8_4_0\xtensa-esp32-elf\" $_ }) -join ";"

However bindgen cc still had an issue that env vars could not solve. Because the lvgl crate uses a magic trick to read the raw bindings.rs from the lvgl-sys crate, it has a build dependency on lvgl-sys. Because the build scripts executables themselves are built for the host platform rather than the target platform, this will build lvgl-sys twice, one for the host (windows in my case) to link to the build script of lvgl and one for the target platform to link in the final executable. Building lvgl-sys (for a windows target) fails on windows. cc actually uses the xtensa compiler (only because of the $CC env var) but the TARGET env is set to windows (the target is a windows executable) and it will pass the wrong flags to the compiler (like -m64) because it thinks it is msvc.

The bindgen step actually works because it uses clang and the active clang configuration set by the ESP environment targets ESP.

My workaround (and possible solution) is to put the compiling (cc) step in lvgl-sys behind a specific default feature while keeping the bindgen step, then disabling this feature in lvgl's lvgl-sys build-dependency (because it only needs the bindings and not the full lib). Although I wonder if on other platforms like linux the build and normal dependencies may generate bindings for different targets?

@nia-e
Copy link
Collaborator

nia-e commented Apr 19, 2023

Interesting, thanks for opening this :D Will admit that I didn't expect this to be an issue, hm.
Can you open a PR with your current patches? We can see what to do from there.

@nia-e nia-e added the bug Something isn't working label May 4, 2023
@cartoush
Copy link

cartoush commented Jul 3, 2023

Hello I confirm it creates the same problems on linux, @madwizard-thomas could you share your patches ? I've been trying to reproduce them but I did not manage to get it working

@madwizard-thomas
Copy link
Author

I tried replying to your e-mail but it bounces. Anyway, I can't access the source right now but I think I the main thing is to skip the cfg.compile("lvgl") in lvgl-sys/build.rs when it is a build dependency of lvgl. I added a feature flag for this compilation that is on by default, then explicitly disable this step for lvgl-sys in [build-dependencies] of lvgl/Cargo.toml. The build step does not need a compiled library to work and this fixes the problem.

I can look up the details later if you can't get it to work.

(sorry sent this reply via my work account first so I replaced it with this one)

@nia-e
Copy link
Collaborator

nia-e commented Jul 4, 2023

Does the resulting binary still work? I'd assume this means the user has to manually link it to a dylib LVGL

@madwizard-thomas
Copy link
Author

Yes, and no manual step needed. This only causes the build step of the lvgl crate to depend on a version of lvgl-sys without a library (only bindings), but the normal (non-build) step still depends on the normal version of lvgl-sys (lib + bindings). The issue here is that the build executable is a host targeted executable, while the normal executable is the embedded target.

Ideally, lvgl's build step would not depend on lvgl-sys at all, but it does because of the let widgets_impl = lvgl_sys::_bindgen_raw_src(); workaround that reads the generated source of another crate.

@nia-e
Copy link
Collaborator

nia-e commented Jul 4, 2023

Interesting find, thanks so much! You can open a PR for this if you'd like and I'll take a look today.

I don't think it's viable to decouple lvgl from lvgl-sys, though; most of the lvgl crate consists of wrappers around the unsafe C functions, and statically generating the bindings and bundling them here as a huge file of extern fns is not a viable solution (that used to be how it worked, and it was a mess).

I'll also look into this more, since building lvgl-sys twice will use up a lot of space and maybe there's some way to strictly build for the target, thus keeping the compile command in.

@cartoush
Copy link

cartoush commented Jul 6, 2023

I still havent managed to get it working, I did add a default feature in the sys crate and disabled default features in the lvgl crate but I'm still getting undefined references

@weixiongmei
Copy link

@madwizard-thomas Could you provide a buildable examples of the esp-rs+lv_binding_rust? I'm trying to use the lv_biding_rust on the ESP32S3, but failed on compiling, the .c headers can't be found..... Thanks

@madwizard-thomas
Copy link
Author

IIRC if the drivers feature is enabled it would force the SDL library so you need to remove it from lvgl-sys build as well if it is not available on your host. You also need the environment variables from my initial post (these are for windows, besides the export-esp.ps1 script). I used an empty lv_drv_conf.h
In lv_conf.h, you may need to reduce LV_MEM_SIZE, I also disabled LV_USE_LOG and LV_USE_DEMO_WIDGETS.
Any specific errors?

@weixiongmei
Copy link

weixiongmei commented Sep 19, 2023

@madwizard-thomas I had disabled SDL driver, set all the features in lv_drv_conf.h to 0.

[profile.release]
opt-level = "s"
lto = "off"

[profile.dev]
debug = true    # Symbols are nice and they don't increase the size on Flash
opt-level = "z"
lto = "off"

[features]

default = ["std", "hal", "esp-idf-sys/native"]

pio = ["esp-idf-sys/pio"]
all = ["std", "nightly", "experimental", "embassy"]
hal = ["esp-idf-hal", "embedded-svc", "esp-idf-svc"]
std = ["alloc", "esp-idf-sys/std", "esp-idf-sys/binstart", "embedded-svc?/std", "esp-idf-hal?/std", "esp-idf-svc?/std"]
alloc = ["embedded-svc?/alloc", "esp-idf-hal?/alloc", "esp-idf-svc?/alloc"]
nightly = ["embedded-svc?/nightly", "esp-idf-svc?/nightly"] # Future: "esp-idf-hal?/nightly"
experimental = ["embedded-svc?/experimental", "esp-idf-svc?/experimental"]
embassy = ["esp-idf-hal?/embassy-sync", "esp-idf-hal?/critical-section", "esp-idf-hal?/edge-executor", "esp-idf-svc?/embassy-time-driver", "esp-idf-svc?/embassy-time-isr-queue"]

[dependencies]
log = { version = "0.4.20", default-features = false }
esp-idf-sys = { version = "0.33.2", default-features = false }
esp-idf-hal = { version = "0.41.2", optional = true, default-features = false }
esp-idf-svc = { version = "0.46.2", optional = true, default-features = false }
embedded-svc = { version = "0.25.3", optional = true, default-features = false }
lvgl = "0.6.2"

[build-dependencies]
embuild = "0.31.3"
LVGL was added by the command
$ cargo add lvgl
Build command
$ DEP_LV_CONFIG_PATH=`pwd` cargo build

Compiling failed with ESP-IDF v5.1

  running: "cc" "-Os" "-ffunction-sections" "-fdata-sections" "-fPIC" "-g" "-fno-omit-frame-pointer" "-I" "/Users/root/.cargo/registry/src/index.crates.io-6f17d22bba15001f/lvgl-sys-0.6.2/vendor/lvgl/src" "-I" "/Users/root/.cargo/registry/src/index.crates.io-6f17d22bba15001f/lvgl-sys-0.6.2/vendor" "-I" "/Volumes/SSD1 1/Source Codes/Rust/std-training/intro/hello-world" "-I" "/Users/root/.cargo/registry/src/index.crates.io-6f17d22bba15001f/lvgl-sys-0.6.2/vendor/lv_drivers" "-I" "/usr/include" "-I" "/usr/local/include" "-DLV_CONF_INCLUDE_SIMPLE=1" "-o" "/Volumes/SSD1 1/Source Codes/Rust/std-training/intro/hello-world/target/xtensa-esp32s3-espidf/debug/build/lvgl-sys-6f91473d3a419559/out/7a316a986ee17f7b-psa_crypto_driver_wrappers.o" "-c" "/Volumes/SSD1 1/Source Codes/Rust/std-training/intro/hello-world/target/xtensa-esp32s3-espidf/release/build/esp-idf-sys-9b340c643fa42c58/out/build/esp-idf/mbedtls/mbedtls/library/psa_crypto_driver_wrappers.c"
  cargo:warning=/Volumes/SSD1 1/Source Codes/Rust/std-training/intro/hello-world/target/xtensa-esp32s3-espidf/release/build/esp-idf-sys-9b340c643fa42c58/out/build/esp-idf/mbedtls/mbedtls/library/psa_crypto_driver_wrappers.c:24:10: fatal error: 'common.h' file not found

  cargo:warning=#include "common.h"

  cargo:warning=         ^~~~~~~~~~

  cargo:warning=1 error generated.

  exit status: 1

  --- stderr


  error occurred: Command "cc" "-Os" "-ffunction-sections" "-fdata-sections" "-fPIC" "-g" "-fno-omit-frame-pointer" "-I" "/Users/root/.cargo/registry/src/index.crates.io-6f17d22bba15001f/lvgl-sys-0.6.2/vendor/lvgl/src" "-I" "/Users/root/.cargo/registry/src/index.crates.io-6f17d22bba15001f/lvgl-sys-0.6.2/vendor" "-I" "/Volumes/SSD1 1/Source Codes/Rust/std-training/intro/hello-world" "-I" "/Users/root/.cargo/registry/src/index.crates.io-6f17d22bba15001f/lvgl-sys-0.6.2/vendor/lv_drivers" "-I" "/usr/include" "-I" "/usr/local/include" "-DLV_CONF_INCLUDE_SIMPLE=1" "-o" "/Volumes/SSD1 1/Source Codes/Rust/std-training/intro/hello-world/target/xtensa-esp32s3-espidf/debug/build/lvgl-sys-6f91473d3a419559/out/7a316a986ee17f7b-psa_crypto_driver_wrappers.o" "-c" "/Volumes/SSD1 1/Source Codes/Rust/std-training/intro/hello-world/target/xtensa-esp32s3-espidf/release/build/esp-idf-sys-9b340c643fa42c58/out/build/esp-idf/mbedtls/mbedtls/library/psa_crypto_driver_wrappers.c" with args "cc" did not execute successfully (status code exit status: 1).


root@RootMBP hello-world % 

@madwizard-thomas
Copy link
Author

The error seems to be in the esp-idf mbedtls library, I'm not sure this is an lvgl issue. Does the project compile without lvgl?

@weixiongmei
Copy link

@madwizard-thomas Pretty sure the issue is causes by the LVGL-RS, if I comment the line of #lvgl = "0.6.2" , the project built & run successfully. Seems like it's because the include path of the C headers files are missing when compiling for the LVGL-RS, because I edited the file of psa_crypto_driver_wrappers.c, I changed the path of the "common.h" to a absolute path, other header files will be missing.... Just need a way to include all the header files of the ESP-IDF when compiling the LVGL-RS, do you know how to do it? Thank you!!

@madwizard-thomas
Copy link
Author

I haven't tried esp-idf in a while (it takes forever to compile with rust) but I tried a new no-std project with the latest espup (cargo generate), added lvgl configs and compiled it on windows (using the export-esp.ps1 environment) without source modifications with three fixes (the feature to disable the compilation part seems no longer needed but would save a useless compile step):

First error is error occurred: Failed to find tool. Is cc installed?.
This doesn't happen on linux I think but solution is to define CROSS_COMPILE:
$env:CROSS_COMPILE="xtensa-esp32s3-elf"

Then next error is: lv_conf_internal.h:11:10: fatal error: 'stdint.h' file not found
This seems to happen because bindgen doesn't have a (correct) sysroot. You can specify with a cc arg indirectly:
$env:BINDGEN_EXTRA_CLANG_ARGS='--sysroot "C:\Users\Thomas\.rustup\toolchains\esp\xtensa-esp32s3-elf\esp-12.2.0_20230208\xtensa-esp32s3-elf\xtensa-esp32s3-elf"'

Then it fails on lv_hal_tick.h:19:10: fatal error: 'stdbool.h' file not found
Solved by adding additional include paths:
$env:C_INCLUDE_PATH="C:\Users\Thomas\.rustup\toolchains\esp\xtensa-esp32s3-elf\esp-12.2.0_20230208\xtensa-esp32s3-elf\lib\gcc\xtensa-esp32s3-elf\12.2.0\include\"

After that it works, at least for no-std esp.

For linux (I tried it with the auto generated development container in vscode), replace these with export ENV=.. and the correct linux paths.

Pro tip: you can add the following to the env section in .cargo/config.toml so you don't have to specify DEP_LV_CONFIG_PATH manually all the time:

[env]
DEP_LV_CONFIG_PATH = { relative = true, value = "." }

Back on topic, even though it seems to compile on windows, it does generate bindings twice, both for the host target and the actual target, and lvgl/build.rs uses the host target bindings rather than the actual target's bindings (because the build script is build for the host and depends on the host version of the bindings). These bindings are not the same (types differ in many places) , at least on windows and likely on linux as well so this may cause issues.

@enelson1001
Copy link

Has anyone successfully been able to use this crate on ESP32.

I have exported the following env variables

export C_INCLUDE_PATH="/home/ed/.rustup/toolchains/esp/xtensa-esp-elf/esp-13.2.0_20230928/xtensa-esp-elf/xtensa-esp-elf/include"

export BINDGEN_EXTRA_CLANG_ARGS='--sysroot "C:/home/ed/.rustup/toolchains/esp/xtensa-esp32s3-elf/esp-13.2.0_20230928/xtensa-esp-elf/xtensa-esp-elf"'

But get the following error.

running: "cc" "-Os" "-ffunction-sections" "-fdata-sections" "-fPIC" "-g" "-fno-omit-frame-pointer" 
"-I" "/home/ed/.cargo/registry/src/index.crates.io-6f17d22bba15001f/lvgl-sys-0.6.2/vendor/lvgl/src" 
"-I" "/home/ed/.cargo/registry/src/index.crates.io-6f17d22bba15001f/lvgl-sys-0.6.2/vendor" 
"-I" "/home/ed/esp-rust-projects/esp32-s3/hello-tft/." 
"-I" "/home/ed/.cargo/registry/src/index.crates.io-6f17d22bba15001f/lvgl-sys-0.6.2/vendor/lv_drivers" "-I" "/usr/include" 
"-I" "/usr/local/include" 
"-DLV_CONF_INCLUDE_SIMPLE=1" 
"-o" "/home/ed/esp-rust-projects/esp32-s3/hello-tft/target/xtensa-esp32s3-espidf/debug/build/lvgl-sys-6bb1eb053b806f99/out/551e7f5eb83719ea-ssl_debug_helpers_generated.o" 
"-c" "/home/ed/esp-rust-projects/esp32-s3/hello-tft/./target/xtensa-esp32s3-espidf/debug/build/esp-idf-sys-1f81883f55744c57/out/build/esp-idf/mbedtls/mbedtls/library/ssl_debug_helpers_generated.c"

  cargo:warning=/home/ed/esp-rust-projects/esp32-s3/hello-tft/./target/xtensa-esp32s3-espidf/debug/build/esp-idf-sys-1f81883f55744c57/out/build/esp-idf/mbedtls/mbedtls/library/ssl_debug_helpers_generated.c:25:10: fatal error: common.h: No such file or directory

  cargo:warning=   25 | #include "common.h"

  cargo:warning=      |          ^~~~~~~~~~

  cargo:warning=compilation terminated.

  exit status: 1

Anyone have any suggestions?

@enelson1001
Copy link

I was able to get lvgl to build on my ESP32S3 device without errors.

I used the following command to build lvgl so I could look for errors

cargo build -j1 -vvv -p lvgl &>log3.txt

My first error was not finding 'bits/libc-header-start.h' file

--- stderr
  /usr/include/stdint.h:26:10: fatal error: 'bits/libc-header-start.h' file not found
  thread 'main' panicked at /home/ed/.cargo/registry/src/index.crates.io-6f17d22bba15001f/lvgl-sys-0.6.2/build.rs:236:10:
  Unable to generate bindings: ClangDiagnostic("/usr/include/stdint.h:26:10: fatal error: 'bits/libc-header-start.h' file not found\n")

This error was solved by doing the following:

$ sudo apt update
$ sudo apt upgrade
$ sudo apt-get install gcc-multilib

My second error was not finding string.h file

[lvgl-sys 0.6.2] exit status: 0
[lvgl-sys 0.6.2] running: "ar" "s" "/home/ed/esp-rust-projects/esp32-s3/hello-tft/target/debug/build/lvgl-sys-d72660327e743ef4/out/liblvgl.a"
[lvgl-sys 0.6.2] exit status: 0
[lvgl-sys 0.6.2] cargo:rustc-link-lib=static=lvgl
[lvgl-sys 0.6.2] cargo:rustc-link-search=native=/home/ed/esp-rust-projects/esp32-s3/hello-tft/target/debug/build/lvgl-sys-d72660327e743ef4/out
[lvgl-sys 0.6.2] /home/ed/lv-binding-rust/lv_binding_rust/lvgl-sys/vendor/lvgl/src/misc/lv_mem.h:20:10: fatal error: 'string.h' file not found
[lvgl-sys 0.6.2] thread 'main' panicked at /home/ed/lv-binding-rust/lv_binding_rust/lvgl-sys/build.rs:313:10:
[lvgl-sys 0.6.2] Unable to generate bindings: ClangDiagnostic("/home/ed/lv-binding-rust/lv_binding_rust/lvgl-sys/vendor/lvgl/src/misc/lv_mem.h:20:10: fatal error: 'string.h' file not found\n")

This was solved by editing the config.toml file to add additional items to rustflags. Since I was editing the file I added DEP_LV_CONFIG_PATH environmental variable setting

[build]
target = "xtensa-esp32s3-espidf"

[target.xtensa-esp32s3-espidf]
linker = "ldproxy"
# runner = "espflash --monitor" # Select this runner for espflash v1.x.x
runner = "espflash flash --monitor" # Select this runner for espflash v2.x.x

rustflags = [
    # Extending time_t for ESP IDF 5: https://github.com/esp-rs/rust/issues/110
    "--cfg",
    "espidf_time64",
    # Added the following 2 entries so lvgl will build without errors
    "--sysroot",
    "/home/ed/.rustup/toolchains/esp/xtensa-esp32s3-elf/esp-13.2.0_20230928/xtensa-esp-elf/xtensa-esp-elf/include",
] 

[unstable]
build-std = ["std", "panic_abort"]

[env]
MCU = "esp32s3"

# Note: this variable is not used by the pio builder (`cargo build --features pio`)
ESP_IDF_VERSION = "v5.1.1"

# The directory that has the lvgl config files - lv_conf.h, lv_drv_conf.h
DEP_LV_CONFIG_PATH = { relative = true, value = "lvgl-configs" }

The last error I got was a ctor error. I updated lvgl in Cargo.toml to look like the following.

lvgl = { version = "0.6.2", features = ["rust_timer", "unsafe_no_autoinit", ]}

@enelson1001
Copy link

I spoke to soon. When trying to build lvgl in my project I get the following error

 = note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-L" "/usr/local/rustup/toolchains/1.29.1-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.15kq92zzbmxot4k9.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.16u6js6g0l3k1ic6.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.181cuta0v63atwcm.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.1c4sbqhvukbgthag.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.1im38lueib99jsk0.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.1kduva7sc7em934m.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.1mvmz58owquyropc.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.1vut2eft6nlujjxr.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.1y16o1qfye96o7m0.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.1zwd8n7bcl3vhvvh.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.23tqyymcb18u96mb.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.2imnh2vhxcqrizhm.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.2jqywn86b2gsqohu.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.2lyh15q6cjwzy18c.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.2qhkzqx5zqexj20y.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.3ayaeypdcro9d6yk.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.3py0d821mvt07s4n.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.3rngp6bm2u2q5z0y.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.3wta9ctgdrpkmlpr.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.44bsbddupzfao2om.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.48721dc4k5qxei0u.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.49a7n47po4ttqjl7.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.49lx1q7cxvpykyv0.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.4b8ptp1vn215jmoe.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.4ezmh1vbs95c5ack.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.4oc10dk278mpk1vy.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.4vp4wqj2v29i7mgy.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.4xq48u46a1pwiqn7.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.4ybye971cqflgun6.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.4yh8x2b62dcih00t.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.4ypvbwho0bu5tnww.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.56dly8q07ws8ucdq.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.57qy3vyd9bhiuaon.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.5gf6du7k58s78kob.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.8xzrsc1ux72v29j.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.98g0d9x8aw3akpe.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.9elsx31vb4it187.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.c6lbtaiefvx3wya.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.oa3rad818d8sgn4.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.spyjbt69vcsrx9q.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.y08g5q2x813c4wx.rcgu.o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.z9ox7biyn1otfln.rcgu.o" "-o" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba" "/usr/src/myapp/target/debug/deps/create_snapshot-60efbce147cacbba.crate.allocator.rcgu.o" "-Wl,--gc-sections" "-pie" "-Wl,-zrelro" "-Wl,-znow" "-nodefaultlibs" "-L" "/usr/src/myapp/target/debug/deps" "-L" "/usr/src/myapp/target/debug/build/libfly-2ef616123afaf643/out" "-L" "/usr/src/myapp/libfly/third_party/v8/out.gn/x64.release/obj" "-L" "/usr/src/myapp/target/debug/build/libsqlite3-sys-7ac6aaa28420bed7/out" "-L" "/usr/src/myapp/target/debug/build/backtrace-sys-dc873d7131d9513f/out" "-L" "/usr/local/rustup/toolchains/1.29.1-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "/usr/src/myapp/target/debug/deps/liblibfly-973820a835f9f432.rlib" "/usr/src/myapp/target/debug/deps/liblibc-40d568469a8c2e87.rlib" "-Wl,--start-group" "/usr/local/rustup/toolchains/1.29.1-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-9318d1aa9575dbf9.rlib" "/usr/local/rustup/toolchains/1.29.1-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-e3cd3f44688b2d97.rlib" "/usr/local/rustup/toolchains/1.29.1-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc_jemalloc-2f4890fbea3bd5e0.rlib" "/usr/local/rustup/toolchains/1.29.1-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-a0ddde720c2c46c5.rlib" "/usr/local/rustup/toolchains/1.29.1-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc_system-9c41ffe739844496.rlib" "/usr/local/rustup/toolchains/1.29.1-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-af766b046896c123.rlib" "/usr/local/rustup/toolchains/1.29.1-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-00b776688b98de66.rlib" "/usr/local/rustup/toolchains/1.29.1-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-d05a4396ceff8bc8.rlib" "-Wl,--end-group" "/usr/local/rustup/toolchains/1.29.1-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-fe16a4dcdcd95bab.rlib" "-Wl,-Bdynamic" "-lstdc++" "-lutil" "-lutil" "-ldl" "-lrt" "-lpthread" "-lpthread" "-lgcc_s" "-lc" "-lm" "-lrt" "-lpthread" "-lutil" "-lutil"
  = note: /usr/src/myapp/target/debug/deps/liblibfly-973820a835f9f432.rlib: error adding symbols: File format not recognized
         collect2: error: ld returned 1 exit status

I solved this by using the following build command.

CROSS_COMPILE=xtensa-esp32-elf cargo build

But then the next error I get is the following.

= note: [ldproxy] Running ldproxy
          Error: Linker /home/ed/esp-rust-projects/esp32-s3/hello-tft/.embuild/espressif/tools/xtensa-esp32s3-elf/esp-12.2.0_20230208/xtensa-esp32s3-elf/bin/xtensa-esp32s3-elf-gcc failed: exit status: 1
          STDERR OUTPUT:
          /home/ed/esp-rust-projects/esp32-s3/hello-tft/.embuild/espressif/tools/xtensa-esp32s3-elf/esp-12.2.0_20230208/xtensa-esp32s3-elf/bin/../lib/gcc/xtensa-esp32s3-elf/12.2.0/../../../../xtensa-esp32s3-elf/bin/ld: cannot find -lSDL2: No such file or directory
          collect2: error: ld returned 1 exit status
          
          
          Stack backtrace:
             0: ldproxy::main
             1: std::sys_common::backtrace::__rust_begin_short_backtrace
             2: std::rt::lang_start::{{closure}}
             3: core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once
                       at /rustc/a8314ef7d0ec7b75c336af2c9857bfaf43002bfc/library/core/src/ops/function.rs:280:13
                std::panicking::try::do_call
                       at /rustc/a8314ef7d0ec7b75c336af2c9857bfaf43002bfc/library/std/src/panicking.rs:492:40
                std::panicking::try
                       at /rustc/a8314ef7d0ec7b75c336af2c9857bfaf43002bfc/library/std/src/panicking.rs:456:19
                std::panic::catch_unwind
                       at /rustc/a8314ef7d0ec7b75c336af2c9857bfaf43002bfc/library/std/src/panic.rs:137:14
                std::rt::lang_start_internal::{{closure}}
                       at /rustc/a8314ef7d0ec7b75c336af2c9857bfaf43002bfc/library/std/src/rt.rs:128:48
                std::panicking::try::do_call
                       at /rustc/a8314ef7d0ec7b75c336af2c9857bfaf43002bfc/library/std/src/panicking.rs:492:40
                std::panicking::try
                       at /rustc/a8314ef7d0ec7b75c336af2c9857bfaf43002bfc/library/std/src/panicking.rs:456:19
                std::panic::catch_unwind
                       at /rustc/a8314ef7d0ec7b75c336af2c9857bfaf43002bfc/library/std/src/panic.rs:137:14
                std::rt::lang_start_internal
                       at /rustc/a8314ef7d0ec7b75c336af2c9857bfaf43002bfc/library/std/src/rt.rs:128:20
             4: main
             5: __libc_start_main
                       at /build/glibc-BHL3KM/glibc-2.31/csu/../csu/libc-start.c:308:16
             6: _start

I did verify that SDL2 is present in /usr/lib/x86_64-linux-gnu.
To be able to find SDL2 library I modified config.toml rustflags as follows.

rustflags = [
    # Extending time_t for ESP IDF 5: https://github.com/esp-rs/rust/issues/110
    "--cfg",
    "espidf_time64",
    # Added the following 2 entries so lvgl will build without getting string.h file not found
    "--sysroot",
    "/home/ed/.rustup/toolchains/esp/xtensa-esp32s3-elf/esp-13.2.0_20230928/xtensa-esp-elf/xtensa-esp-elf/include",
    # Added the following so SDL2 library can be found
    "-L",
    "/usr/lib/x86_64-linux-gnu"
] 

But then I get the following error

= note: [ldproxy] Running ldproxy
          Error: Linker /home/ed/esp-rust-projects/esp32-s3/hello-tft/.embuild/espressif/tools/xtensa-esp32s3-elf/esp-12.2.0_20230208/xtensa-esp32s3-elf/bin/xtensa-esp32s3-elf-gcc failed: exit status: 1
          STDERR OUTPUT:
          /usr/lib/x86_64-linux-gnu/libSDL2.so: file not recognized: file format not recognized
          collect2: error: ld returned 1 exit status
          
          
          Stack backtrace:
             0: ldproxy::main
             1: std::sys_common::backtrace::__rust_begin_short_backtrace
             2: std::rt::lang_start::{{closure}}
             3: core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once
                       at /rustc/a8314ef7d0ec7b75c336af2c9857bfaf43002bfc/library/core/src/ops/function.rs:280:13
                std::panicking::try::do_call
                       at /rustc/a8314ef7d0ec7b75c336af2c9857bfaf43002bfc/library/std/src/panicking.rs:492:40
                std::panicking::try
                       at /rustc/a8314ef7d0ec7b75c336af2c9857bfaf43002bfc/library/std/src/panicking.rs:456:19
                std::panic::catch_unwind
                       at /rustc/a8314ef7d0ec7b75c336af2c9857bfaf43002bfc/library/std/src/panic.rs:137:14
                std::rt::lang_start_internal::{{closure}}
                       at /rustc/a8314ef7d0ec7b75c336af2c9857bfaf43002bfc/library/std/src/rt.rs:128:48
                std::panicking::try::do_call
                       at /rustc/a8314ef7d0ec7b75c336af2c9857bfaf43002bfc/library/std/src/panicking.rs:492:40
                std::panicking::try
                       at /rustc/a8314ef7d0ec7b75c336af2c9857bfaf43002bfc/library/std/src/panicking.rs:456:19
                std::panic::catch_unwind
                       at /rustc/a8314ef7d0ec7b75c336af2c9857bfaf43002bfc/library/std/src/panic.rs:137:14
                std::rt::lang_start_internal
                       at /rustc/a8314ef7d0ec7b75c336af2c9857bfaf43002bfc/library/std/src/rt.rs:128:20
             4: main
             5: __libc_start_main
                       at /build/glibc-BHL3KM/glibc-2.31/csu/../csu/libc-start.c:308:16
             6: _start

For now (since I don't know how to fix) I made changes the the build.rs file located in lvgl-sys directory so I could build without any errors.

COMMENTED OUT
/*
    #[cfg(feature = "drivers")]
    let link_extra = env::var("LVGL_LINK").unwrap_or("SDL2".to_string());
*/

COMMENTED OUT
/*
    #[cfg(feature = "drivers")]
    link_extra.split(',').for_each(|a| {
        println!("cargo:rustc-link-lib={a}");
        //println!("cargo:rustc-link-search=")
    });
*/

I will update if I have any more problems or solution to the SDL2 problem

@madwizard-thomas
Copy link
Author

It is because it is trying to link the SDL2 library compiled for the host to the xtensa binary, that will never work. You either need an SDL library compiled for your embedded device, which probably isn't supported or available, or disable SDL. Unfortunately the current lvgl-rs library automatically includes it when the drivers feature is enabled, so either disable the drivers feature or comment the lines out like you did.

Most of these problems are either the cc or bindgen crate compiling for the wrong platform. On linux it will sometimes even work but actually generate the bindings for the host. You can add this to lv_conf.h to check:

#ifndef __xtensa__
#error Not compiling for xtensa
#endif

(use __riscv instead for riscv)

If this error triggers it is compiling/generating bindings for the wrong platform. It will also then also likely generate a lvgl library for the host but because it is never referenced (lvgl's build step does not actually call lvgl-sys's C functions) it will never be linked in. If you would add for example lv_init() to _bindgen_raw_src it would actually quit with a linker error because it is mixing x86 and xtensa binaries.

I have some ideas to cleanup build.rs and fix some of the problems, I'll try to find some time to create a PR. CROSS_COMPILE and a sysroot for bindgen will still be necessary environment variables though, because in the end we are cross building.

@enelson1001
Copy link

I added your suggestion.

/**
 * @file lv_conf.h
 * Configuration file for v8.3.0-dev
 */

/*
 * Copy this file as `lv_conf.h`
 * 1. simply next to the `lvgl` folder
 * 2. or any other places and
 *    - define `LV_CONF_INCLUDE_SIMPLE`
 *    - add the path as include path
 */

/* clang-format off */
#if 1 /*Set it to "1" to enable content*/

#ifndef LV_CONF_H
#define LV_CONF_H

#include <stdint.h>

#ifndef __xtensa__
    #error Not compiling for xtensa
#endif

And the error triggered.

I have noticed that the build.rs program compiles for both the target = host and the target = xtensa-esp32-espidf. So I assumed everything would just work out correctly.

I have couple more questions related to implementation. All the examples given use the Simulator and I am struggling with how to run any of the examples with a real world display.

I would like to use a display that is written in Rust not C.
Question 1. How do I register this Rust display (my_rust_display).
Question 2. How do I have lv-binding-rs call this flush function (my_rust_display.draw_raw_iter(x1, y1, x2, y2, color)
Question 3. What do I put inside the "running" loop?

====== I tried this but that doesn't look right. =======
let buffer = DrawBuffer::<{ (HOR_RES * VER_RES) as usize }>::default();

    let display = Display::register(buffer, HOR_RES, VER_RES, |refresh| {
        my_rust_display.draw_raw_iter(refresh.area.x1, refresh.area.y1, refresh.area.x2, refresh.area.y2, refresh.colors).unwrap();
    })?;

I was looking at using register_raw but that doesn't seem to work either.

let display = Display::register_raw(buffer, 320, 240, Some(my_rust_display.draw_raw_iter), None, None, None, None, None, None, None, None, None).unwrap();

@enelson1001
Copy link

I can confirm that the build with the changes I made does not run the the esp device. The WDT is triggerd and the esp32 reboots when trying to execute the following instruction.

const HOR_RES: u32 = 320;
const VER_RES: u32 = 240;

let buffer = DrawBuffer::<{ (HOR_RES * VER_RES) as usize }>::default();

I will keep trying different settings.

I hope madwizard-thomas will submit a PR that will resolve the problem.

@madwizard-thomas madwizard-thomas linked a pull request Nov 14, 2023 that will close this issue
@madwizard-thomas
Copy link
Author

PR is submitted but it fixes the cross-compilations issues only, I think you are having unrelated issues. The drawbuffer is probably too large, I think it uses the stack the way you set it up so it probably runs out of stack. Try a drawbuffer of 10 lines for example, it doesn't have to be the same size as the display buffer.

@enelson1001
Copy link

@madwizard-thomas Thank you for your work and submitting the PR. Hopefully it will get approved

The drawbuffer size was the problem setting HORZ_RES = 320 and VER_RES = 10 fixed the wdt timeout.

Now I just need to figure out how to get the DisplayRefresh updates to work with my display. Everything compiles OK but my screen is not refreshed. I put a println inside the closure and know that lvgl is calling display_update that is registered.

@weixiongmei
Copy link

@enelson1001 are you using SPI display or RGB display with EPS32? I can't find any info about how to use 16-Bit RGB display with ESP32-Rust. If you're using RGB display, could you share a little info or example code for that? Thank you~~~

@enelson1001
Copy link

@weixiongmei If I something working on the RGB display I will let you know.

@enelson1001
Copy link

@madwizard-thomas
I have board with 8MB of PSRAM. I would like to use this memory for the DrawBuffer. I have added the feature alloc to lvgl in the Cargo.toml file.

lvgl = { version = "0.6.2", default-features = false, features = [
    "embedded_graphics",
    "unsafe_no_autoinit",
    "alloc"
] }

I have also added PSRAM settings to my sdconfig.defaults file.

CONFIG_SPIRAM=y
CONFIG_SPIRAM_MODE_OCT=y
CONFIG_SPIRAM_SPEED_80M=y

The program crashes with Could not allocate memory

Do you know how to make the DrawBuffer use the heap PSRAM

@cydergoth
Copy link
Contributor

cydergoth commented Nov 19, 2023 via email

@enelson1001
Copy link

I was trying to allocate about 150k bytes so that should not have been a problem correct?

@cydergoth
Copy link
Contributor

cydergoth commented Nov 19, 2023 via email

@enelson1001
Copy link

@weixiongmei See the examples below for using lv-binding-rust on the these devices

M5Stack
https://github.com/enelson1001/rust-m5stack-lvgl-demo

ESP32S3 - Not using touchscreen
https://github.com/enelson1001/rust-esp32s3-lvgl-demo

ESP32S3 - Using capacitive touchscreen
https://github.com/enelson1001/rust-esp32s3-lvgl-clickme

@weixiongmei
Copy link

@enelson1001 Very appreciated!

@weixiongmei
Copy link

@enelson1001 Have you figure out how to use the external RAM for display buffer yet? Thanks~~

@enelson1001
Copy link

@weixiongmei
Not yet

@weixiongmei
Copy link

@enelson1001 Can you share the external RAM example once you have figured out please? thank you!!!!

@enelson1001
Copy link

For those interested I have a more robust example using lv_binding_rust on a Aliexpress ESP32S3 development board with a 7 inch display and a capacitive touchscreen called weather-forecaster.
https://github.com/enelson1001/weather-forecaster/tree/master

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants
@cydergoth @madwizard-thomas @nia-e @weixiongmei @cartoush @enelson1001 and others