From 14eac99bd7f8ca76c23005662c405dbca3ebb1a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matheus=20Catarino=20Fran=C3=A7a?= Date: Wed, 27 Mar 2024 13:54:10 -0300 Subject: [PATCH] ziglang support --- .../build-zig-esp-idf-hello-world.yaml | 201 ++++++++++++++++++ .gitignore | 1 + docs/README.md | 98 ++++----- .../get-started/hello_world/CMakeLists.txt | 7 + .../get-started/hello_world/build.zig | 49 +++++ .../get-started/hello_world/build.zig.zon | 11 + .../hello_world/main/CMakeLists.txt | 93 ++++++++ .../get-started/hello_world/main/hello.zig | 59 +++++ .../hello_world/main/placeholder.c | 1 + support/wokwi/diagram-esp32c6.json | 2 +- support/wokwi/diagram-esp32h2.json | 2 +- support/wokwi/diagram-esp32s2.json | 3 +- support/wokwi/diagram-esp32s3.json | 2 +- 13 files changed, 475 insertions(+), 54 deletions(-) create mode 100644 .github/workflows/build-zig-esp-idf-hello-world.yaml create mode 100644 examples/zig/esp-idf-v5/get-started/hello_world/CMakeLists.txt create mode 100644 examples/zig/esp-idf-v5/get-started/hello_world/build.zig create mode 100644 examples/zig/esp-idf-v5/get-started/hello_world/build.zig.zon create mode 100644 examples/zig/esp-idf-v5/get-started/hello_world/main/CMakeLists.txt create mode 100644 examples/zig/esp-idf-v5/get-started/hello_world/main/hello.zig create mode 100644 examples/zig/esp-idf-v5/get-started/hello_world/main/placeholder.c diff --git a/.github/workflows/build-zig-esp-idf-hello-world.yaml b/.github/workflows/build-zig-esp-idf-hello-world.yaml new file mode 100644 index 0000000..54b43a1 --- /dev/null +++ b/.github/workflows/build-zig-esp-idf-hello-world.yaml @@ -0,0 +1,201 @@ +name: Build ESP32 (ZIG) ESP-IDF binaries and upload to GitHub Release + +on: + workflow_dispatch: + inputs: + release_tag: + description: "Upload to specific release" + required: true + default: 'v0.1.0' + skip_projects: + description: "Skip projects during build (e.g. esp32-c3-devkit-rust)" + required: false + default: '' + +jobs: + get_release: + name: Get release + runs-on: ubuntu-latest + outputs: + upload_url: ${{ steps.get_upload_url.outputs.url }} + steps: + - uses: octokit/request-action@v2.x + id: get_release + with: + route: GET /repos/{owner}/{repo}/releases/tags/${{ github.event.inputs.release_tag }} + owner: georgik + repo: esp32-lang-lab + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: get upload url + id: get_upload_url + run: | + url=$(echo "$response" | jq -r '.upload_url' | sed 's/{?name,label}//') + echo "url=$url" >> $GITHUB_OUTPUT + env: + response: ${{ steps.get_release.outputs.data }} + + build: + runs-on: ubuntu-22.04 + container: + image: espressif/idf:release-v5.1 + needs: get_release + steps: + - name: Clone repository with specific branch + shell: bash + run: | + export HOME=/home/esp + mkdir -p /home/esp + cd /home/esp + + pwd + git clone --depth 1 --branch ${{ github.ref_name }} https://github.com/georgik/esp32-lang-lab.git esp32-lang-lab + + set +e # Workaround for Exit code 2 exit code installation + curl -L https://wokwi.com/ci/install.sh | sh + exit_code=$? + if [ $exit_code -eq 2 ]; then + echo "Received exit code 2 from install script, overriding to 0" + exit_code=0 + else + exit $exit_code + fi + set -e + + - name: Build and upload binaries + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + WOKWI_CLI_TOKEN: ${{ secrets.WOKWI_CLI_TOKEN }} + shell: bash + run: | + source /opt/esp/idf/export.sh + + # Workaround GitHub issue with setting HOME in container https://github.com/actions/runner/issues/863 + export HOME=/home/esp + export SUPPORT_DIR="${HOME}/esp32-lang-lab/support" + export PROJECT="${HOME}/esp32-lang-lab/examples/zig/esp-idf-v5/get-started/hello_world/" + cd /home/esp + source /opt/esp/idf/export.sh + + # Install jq - workaround when running in the image without jq + apt-get update && apt-get install -y jq + + echo "Project path: ${PROJECT}" + cd ${PROJECT} + + # Prepare report + echo '[]' > results.json + + for TARGET in esp32 esp32s2 esp32s3 esp32c3 esp32c6 esp32h2; do + + echo "Building $TARGET" + OUTPUT_PREFIX="zig-esp-idf-v5-hello-world-${TARGET}-${{ github.event.inputs.release_tag }}" + OUTPUT_BIN="build/hello_world_zig.bin" + OUTPUT_TXT="${OUTPUT_PREFIX}.txt" + + # If TARGET is a substring in SKIP_PROJECTS, skip it + #if echo "${{ github.event.inputs.skip_projects }}" | grep -q "${TARGET}"; then + # echo "Skipping $TARGET" + # continue + #fi + + idf.py set-target "${TARGET}" + idf.py build + + # Prepare Wokwi test + cp ${SUPPORT_DIR}/wokwi/diagram-${TARGET}.json diagram.json + + echo '[wokwi]' > wokwi.toml + echo 'version = 1' >> wokwi.toml + echo 'elf = "build/hello_world_zig.elf"' >> wokwi.toml + echo 'firmware = "build/hello_world_zig.bin"' >> wokwi.toml + + # Run Wokwi test + /home/esp/bin/wokwi-cli --timeout 5000 \ + --timeout-exit-code 0 \ + --serial-log-file ${PROJECT}/${OUTPUT_TXT} \ + --elf ${OUTPUT_BIN} \ + "." + + # Upload binary + asset_path="${PROJECT}/${OUTPUT_BIN}" + asset_name="${OUTPUT_PREFIX}.bin" + curl \ + --request POST \ + --header "authorization: Bearer $GITHUB_TOKEN" \ + --header "Content-Type: application/octet-stream" \ + --data-binary "@$asset_path" \ + --url "${{ needs.get_release.outputs.upload_url }}?name=${asset_name}" + + # Upload log + asset_path="${PROJECT}/${OUTPUT_TXT}" + asset_name="${OUTPUT_TXT}" + curl \ + --request POST \ + --header "authorization: Bearer $GITHUB_TOKEN" \ + --header "Content-Type: application/octet-stream" \ + --data-binary "@$asset_path" \ + --url "${{ needs.get_release.outputs.upload_url }}?name=${asset_name}" + + # Extract heap size (you might need to adjust the parsing command) + HEAP_SIZE=$(grep 'Minimum free heap size' ${OUTPUT_TXT} | sed -e 's/Minimum free heap size: //' -e 's/ bytes//') + + # Add a new record to the JSON database + jq --arg target "$TARGET" \ + --arg language "ZIG" \ + --arg flavor "ESP-IDF" \ + --arg example "hello-world" \ + --arg property "heap" \ + --arg value "$HEAP_SIZE" \ + --arg unit "bytes" \ + --arg note "" \ + --arg version "4.4.6" \ + --arg timestamp "$(date -Iseconds)" \ + '. += [{ + target: $target, + language: $language, + flavor: $flavor, + example: $example, + property: $property, + value: $value, + unit: $unit, + note: $note, + version: $version, + timestamp: $timestamp + }]' results.json > temp.json && mv temp.json results.json + + # If skip-wokwi-test.toml exists, skip Wokwi test + #if [ ! -f "skip-wokwi-test.toml" ]; then + # asset_path="/home/esp/project/${TARGET}/screenshot.png" + # asset_name="spooky-maze-${TARGET}-${{ github.event.inputs.release_tag }}.png" + # curl \ + # --request POST \ + # --header "authorization: Bearer $GITHUB_TOKEN" \ + # --header "Content-Type: application/octet-stream" \ + # --data-binary "@$asset_path" \ + # --url "${{ needs.get_release.outputs.upload_url }}?name=${asset_name}" + #fi + done + + # Generate report + echo "| Target | Language | Flavor | Example | Property | Value | Unit | Note | Version | Timestamp |" > report.md + echo "|--------|----------|--------|---------|----------|-------|------|------|---------|-----------|" >> report.md + jq -r '.[] | "| \(.target) | \(.language) | \(.flavor) | \(.example) | \(.property) | \(.value) | \(.unit) | \(.note) | \(.version) | \(.timestamp) |"' results.json >> report.md + + asset_path="report.md" + asset_name="zig-esp-idf-hello-world-report.md" + curl \ + --request POST \ + --header "authorization: Bearer $GITHUB_TOKEN" \ + --header "Content-Type: application/octet-stream" \ + --data-binary "@$asset_path" \ + --url "${{ needs.get_release.outputs.upload_url }}?name=${asset_name}" + + asset_path="results.json" + asset_name="zig-esp-idf-hello-world-results.json" + curl \ + --request POST \ + --header "authorization: Bearer $GITHUB_TOKEN" \ + --header "Content-Type: application/octet-stream" \ + --data-binary "@$asset_path" \ + --url "${{ needs.get_release.outputs.upload_url }}?name=${asset_name}" diff --git a/.gitignore b/.gitignore index 50a646b..d21ff53 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ build/ managed_components/ target/ +zig-*/ \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index 9530128..72c1f3a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -9,74 +9,74 @@ Then the application waits for 10 seconds before rebooting. ### Results for ESP32: -| | ESP-IDF C | Arduino | CircuitPython | MicroPython | Rust no_std | Rust std | Toit | -|-------------|------------|------------|---------------|-------------|-------------|----------|------| -| Chip Target | ESP32 | n/a | n/a | n/a | n/a | | n/a | -| CPU Cores | 2 | 2 | n/a | n/a | n/a | | n/a | -| Features | WiFi/BTBLE | WiFi/BTBLE | n/a | n/a | n/a | | n/a | -| Flash size | 2MB [^1] | 4MB | 8192 (?)[^4] | 4 MB | n/a | | n/a | -| Free heap | 300892 | 237568 | 113424 | 164064 | 179200 [^2] | 296028 | n/a | +| | ESP-IDF C | Arduino | CircuitPython | MicroPython | Rust no_std | Rust std | Toit |ESP-IDF ZIG | +|-------------|------------|------------|---------------|-------------|-------------|----------|------|------------| +| Chip Target | ESP32 | n/a | n/a | n/a | n/a | | n/a | | +| CPU Cores | 2 | 2 | n/a | n/a | n/a | | n/a | | +| Features | WiFi/BTBLE | WiFi/BTBLE | n/a | n/a | n/a | | n/a | | +| Flash size | 2MB [^1] | 4MB | 8192 (?)[^4] | 4 MB | n/a | | n/a | | +| Free heap | 300892 | 237568 | 113424 | 164064 | 179200 [^2] | 296028 | n/a | | ### Results for ESP32-S2: -| | ESP-IDF C | Arduino | CircuitPython | MicroPython | Rust no_std | Rust std | Toit | -|-------------|------------|------------|---------------|-------------|-------------|----------|------| -| Chip Target | esp32s2 | n/a | | | | | | -| CPU Cores | 1 | 1 | | | | | | -| Features | WiFi | WiFi | | | | | | -| Flash size | 2MB [^1] | 4MB | | | | | | -| Free heap | 246696 | 229688 | 70848 | 2059520 | 178176 [^3] | 246844 | | +| | ESP-IDF C | Arduino | CircuitPython | MicroPython | Rust no_std | Rust std | Toit |ESP-IDF ZIG | +|-------------|------------|------------|---------------|-------------|-------------|----------|------|------------| +| Chip Target | esp32s2 | n/a | | | | | | | +| CPU Cores | 1 | 1 | | | | | | | +| Features | WiFi | WiFi | | | | | | | +| Flash size | 2MB [^1] | 4MB | | | | | | | +| Free heap | 246696 | 229688 | 70848 | 2059520 | 178176 [^3] | 246844 | | | ### Results for ESP32-S3: -| | ESP-IDF C | Arduino | CircuitPython | MicroPython | Rust no_std | Rust std | Toit | -|-------------|------------|------------|---------------|-------------|-------------|----------|------| -| Chip Target | esp32s3 | n/a | | | | | | -| CPU Cores | 2 | 2 | | | | | | -| Features | WiFi/BLE | WiFi/BLE | | | | | | -| Flash size | 2MB [^1] | 8MB external | | | | | | -| Free heap | 386744 | 36992 | 150432 | | 332800 | 388016 | | +| | ESP-IDF C | Arduino | CircuitPython | MicroPython | Rust no_std | Rust std | Toit |ESP-IDF ZIG | +|-------------|------------|------------|---------------|-------------|-------------|----------|------|------------| +| Chip Target | esp32s3 | n/a | | | | | | | +| CPU Cores | 2 | 2 | | | | | | | +| Features | WiFi/BLE | WiFi/BLE | | | | | | | +| Flash size | 2MB [^1] | 8MB external | | | | | | | +| Free heap | 386744 | 36992 | 150432 | | 332800 | 388016 | | | ### Results for ESP32-C3: -| | ESP-IDF C | Arduino | CircuitPython | MicroPython | Rust no_std | Rust std | Toit | -|-------------|------------|------------|---------------|-------------|-------------|----------|------| -| Chip Target | esp32c3 | | | | | | | -| CPU Cores | 1 | | | | | | | -| Features | WiFi/BLE | | | | | | | -| Flash size | 2MB [^1] | | | | | | | -| Free heap | 327840 | | 129808 | | 322556 | 327124 | | +| | ESP-IDF C | Arduino | CircuitPython | MicroPython | Rust no_std | Rust std | Toit |ESP-IDF ZIG | +|-------------|------------|------------|---------------|-------------|-------------|----------|------|------------| +| Chip Target | esp32c3 | | | | | | | | +| CPU Cores | 1 | | | | | | | | +| Features | WiFi/BLE | | | | | | | | +| Flash size | 2MB [^1] | | | | | | | | +| Free heap | 327840 | | 129808 | | 322556 | 327124 | | | ### Results for ESP32-C6: -| | ESP-IDF C | Arduino | CircuitPython | MicroPython | Rust no_std | Rust std | Toit | -|-------------|------------|------------|---------------|-------------|-------------|----------|------| -| Chip Target | esp32c6 | Not supported | | | | | | -| CPU Cores | 1 | | | | | | | -| Features | WiFi/BLE 802.15.4 (Zigbee/Thread) | | | | | | | -| Flash size | 2MB (1.) | | | | | | | -| Free heap | 468852 | | | | 440316 | 471068 | | +| | ESP-IDF C | Arduino | CircuitPython | MicroPython | Rust no_std | Rust std | Toit |ESP-IDF ZIG | +|-------------|------------|------------|---------------|-------------|-------------|----------|------|------------| +| Chip Target | esp32c6 | Not supported | | | | | | | +| CPU Cores | 1 | | | | | | | | +| Features | WiFi/BLE 802.15.4 (Zigbee/Thread) | | | | | | | | +| Flash size | 2MB (1.) | | | | | | | | +| Free heap | 468852 | | | | 440316 | 471068 | | | ### Results for ESP32-H2: -| | ESP-IDF C | Arduino | CircuitPython | MicroPython | Rust no_std | Rust std | Toit | -|-------------|------------|------------|---------------|-------------|-------------|----------|------| -| Chip Target | esp32h2 | Not supported | | | | | | -| CPU Cores | 1 | | | | | | | -| Features | BLE, 802.15.4 (Zigbee/Thread) | | | | | | | -| Flash size | 2MB [^1] | | | | | | | -| Free heap | 262644 | | | | 252924 | 265060 | | +| | ESP-IDF C | Arduino | CircuitPython | MicroPython | Rust no_std | Rust std | Toit |ESP-IDF ZIG | +|-------------|------------|------------|---------------|-------------|-------------|----------|------|------------| +| Chip Target | esp32h2 | Not supported | | | | | | | +| CPU Cores | 1 | | | | | | | | +| Features | BLE, 802.15.4 (Zigbee/Thread) | | | | | | | | +| Flash size | 2MB [^1] | | | | | | | | +| Free heap | 262644 | | | | 252924 | 265060 | | | ### Results for ESP32-P4: -| | ESP-IDF C | Arduino | CircuitPython | MicroPython | Rust no_std | Rust std | Toit | -|-------------|------------|------------|---------------|-------------|-------------|----------|------| -| Chip Target | esp32p4 | Not supported | | | | | | -| CPU Cores | 2 | | | | | | | -| Features | none | | | | | | | -| Flash size | 2MB [^1] | | | | | | | -| Free heap | 618680 | | | | | | | +| | ESP-IDF C | Arduino | CircuitPython | MicroPython | Rust no_std | Rust std | Toit |ESP-IDF ZIG | +|-------------|------------|------------|---------------|-------------|-------------|----------|------|------------| +| Chip Target | esp32p4 | Not supported | | | | | | | +| CPU Cores | 2 | | | | | | | | +| Features | none | | | | | | | | +| Flash size | 2MB [^1] | | | | | | | | +| Free heap | 618680 | | | | | | | | ## Notes diff --git a/examples/zig/esp-idf-v5/get-started/hello_world/CMakeLists.txt b/examples/zig/esp-idf-v5/get-started/hello_world/CMakeLists.txt new file mode 100644 index 0000000..d21333c --- /dev/null +++ b/examples/zig/esp-idf-v5/get-started/hello_world/CMakeLists.txt @@ -0,0 +1,7 @@ +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +set(BUILD_PATH ${CMAKE_CURRENT_SOURCE_DIR}) +project(hello_world_zig) diff --git a/examples/zig/esp-idf-v5/get-started/hello_world/build.zig b/examples/zig/esp-idf-v5/get-started/hello_world/build.zig new file mode 100644 index 0000000..5182c4c --- /dev/null +++ b/examples/zig/esp-idf-v5/get-started/hello_world/build.zig @@ -0,0 +1,49 @@ +const std = @import("std"); +const idf = @import("idf"); + +pub fn build(b: *std.Build) !void { + const target = b.standardTargetOptions(.{ + .whitelist = idf.espressif_targets, + .default_target = idf.espressif_targets[0], + }); + const optimize = b.standardOptimizeOption(.{}); + + const lib = b.addStaticLibrary(.{ + .name = "hello", + .root_source_file = .{ .path = "main/hello.zig" }, + .target = target, + .optimize = optimize, + }); + lib.root_module.addImport("esp_idf", idf.idf_wrapped_modules(b)); + + const idf_path = std.process.getEnvVarOwned(b.allocator, "IDF_PATH") catch ""; + if (!std.mem.eql(u8, idf_path, "")) { + try idf.searched_idf_include(b, lib, idf_path); + try searched_idf_libs(b, lib); + } + lib.linkLibC(); + b.installArtifact(lib); +} + +fn searched_idf_libs(b: *std.Build, lib: *std.Build.Step.Compile) !void { + var dir = try std.fs.cwd().openDir("../build", .{ + .iterate = true, + }); + defer dir.close(); + var walker = try dir.walk(b.allocator); + defer walker.deinit(); + + while (try walker.next()) |entry| { + const ext = std.fs.path.extension(entry.basename); + const lib_ext = inline for (&.{".obj"}) |e| { + if (std.mem.eql(u8, ext, e)) + break true; + } else false; + if (lib_ext) { + const src_path = std.fs.path.dirname(@src().file).?; + const cwd_path = b.pathJoin(&.{ src_path, "build", b.dupe(entry.path) }); + const lib_file: std.Build.LazyPath = .{ .path = cwd_path }; + lib.addObjectFile(lib_file); + } + } +} diff --git a/examples/zig/esp-idf-v5/get-started/hello_world/build.zig.zon b/examples/zig/esp-idf-v5/get-started/hello_world/build.zig.zon new file mode 100644 index 0000000..7f3d973 --- /dev/null +++ b/examples/zig/esp-idf-v5/get-started/hello_world/build.zig.zon @@ -0,0 +1,11 @@ +.{ + .name = "hello World!", + .version = "0.1.0", + .dependencies = .{ + .idf = .{ + .url = "git+https://github.com/kassane/zig-esp-idf-sample#71c342b77863f56ded6748f49a10ecab5f67bbc0", + .hash = "1220e30e27fd2c1e09684c7eb9584584ed43bd4df1b5127ba149fea3fd9a17ea5045", + }, + }, + .paths = .{""}, +} diff --git a/examples/zig/esp-idf-v5/get-started/hello_world/main/CMakeLists.txt b/examples/zig/esp-idf-v5/get-started/hello_world/main/CMakeLists.txt new file mode 100644 index 0000000..1efdc94 --- /dev/null +++ b/examples/zig/esp-idf-v5/get-started/hello_world/main/CMakeLists.txt @@ -0,0 +1,93 @@ +idf_component_register(SRCS "placeholder.c" + INCLUDE_DIRS "." +) +set(include_dirs $ ${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES}) + +# Detect target architecture and platform +if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "x86_64") + set(TARGET_ARCH "x86_64") +elseif(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "aarch64") + set(TARGET_ARCH "aarch64") +else() + message(FATAL_ERROR "Unsupported architecture") +endif() + +set(EXT "tar.xz") +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") + set(TARGET_PLATFORM "linux-musl") +elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + set(TARGET_PLATFORM "windows-gnu") + set(EXT "zip") +elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") + set(TARGET_PLATFORM "macos-none") +else() + message(FATAL_ERROR "Unsupported platform") +endif() + +if(NOT EXISTS "${CMAKE_BINARY_DIR}/zig-${TARGET_ARCH}-relsafe-espressif-${TARGET_PLATFORM}-baseline") + file(DOWNLOAD "https://github.com/kassane/zig-espressif-bootstrap/releases/download/0.12.0-dev/zig-${TARGET_ARCH}-relsafe-espressif-${TARGET_PLATFORM}-baseline.${EXT}" + "${CMAKE_BINARY_DIR}/zig.${EXT}") + + if(CMAKE_SYSTEM_NAME STREQUAL "Windows") + execute_process( + COMMAND powershell -Command "Expand-Archive -Path ${CMAKE_BINARY_DIR}/zig.${EXT} -DestinationPath ${CMAKE_BINARY_DIR}" + ) + else() + execute_process( + COMMAND ${CMAKE_COMMAND} -E tar xf ${CMAKE_BINARY_DIR}/zig.${EXT} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + ) + endif() +else() + message(STATUS "Zig already downloaded. Skipping zig install.") +endif() +set(ZIG_INSTALL ${CMAKE_BINARY_DIR}/zig-${TARGET_ARCH}-relsafe-espressif-${TARGET_PLATFORM}-baseline) + +if(CONFIG_IDF_TARGET_ARCH_RISCV) + set(ZIG_TARGET "riscv32-freestanding-none") + if(CONFIG_IDF_TARGET_ESP32C6 OR CONFIG_IDF_TARGET_ESP32C5 OR CONFIG_IDF_TARGET_ESP32H2) + set(TARGET_CPU_MODEL "generic_rv32+m+a+c") + elseif(CONFIG_IDF_TARGET_ESP32P4) + string(REGEX REPLACE "-none" "-eabihf" ZIG_TARGET ${ZIG_TARGET}) + set(TARGET_CPU_MODEL "generic_rv32+m+a+c+f") + else() + set(TARGET_CPU_MODEL "generic_rv32+m+c") + endif() +elseif(CONFIG_IDF_TARGET_ARCH_XTENSA) + set(ZIG_TARGET "xtensa-freestanding-none") + if(CONFIG_IDF_TARGET_ESP32) + set(TARGET_CPU_MODEL "esp32") + elseif(CONFIG_IDF_TARGET_ESP32S2) + set(TARGET_CPU_MODEL "esp32s2") + else(CONFIG_IDF_TARGET_ESP32S3) + set(TARGET_CPU_MODEL "esp32s3") + endif() +else() + message(FATAL_ERROR "Unsupported target ${CONFIG_IDF_TARGET}") +endif() + +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(ZIG_BUILD_TYPE "Debug") +else() + set(ZIG_BUILD_TYPE "ReleaseSafe") +endif() + +add_custom_target(zig_build + COMMAND ${CMAKE_COMMAND} -E env + "INCLUDE_DIRS=${include_dirs}" + ${ZIG_INSTALL}/zig build + --build-file ${BUILD_PATH}/build.zig + -Doptimize=${ZIG_BUILD_TYPE} + -Dtarget=${ZIG_TARGET} + -Dcpu=${TARGET_CPU_MODEL} + -freference-trace + --prominent-compile-errors + --cache-dir ${CMAKE_BINARY_DIR}/zig-cache + --prefix ${CMAKE_BINARY_DIR} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + BYPRODUCTS ${CMAKE_BINARY_DIR}/lib/libhello.a + VERBATIM) + +add_prebuilt_library(zig ${CMAKE_BINARY_DIR}/lib/libhello.a) +add_dependencies(zig zig_build) +target_link_libraries(${COMPONENT_LIB} PRIVATE ${CMAKE_BINARY_DIR}/lib/libhello.a) diff --git a/examples/zig/esp-idf-v5/get-started/hello_world/main/hello.zig b/examples/zig/esp-idf-v5/get-started/hello_world/main/hello.zig new file mode 100644 index 0000000..d6ecd92 --- /dev/null +++ b/examples/zig/esp-idf-v5/get-started/hello_world/main/hello.zig @@ -0,0 +1,59 @@ +const std = @import("std"); +const builtin = @import("builtin"); +const idf = @import("esp_idf"); + +export fn app_main() callconv(.C) void { + var heap = idf.heap.HeapCapsAllocator.init(.MALLOC_CAP_DEFAULT); + var arena = std.heap.ArenaAllocator.init(heap.allocator()); + defer arena.deinit(); + const allocator = arena.allocator(); + + log.info("Hello, world from Zig!", .{}); + + log.info( + \\[Zig Info] + \\* Version: {s} + \\* Compiler Backend: {s} + \\ + , .{ builtin.zig_version_string, @tagName(builtin.zig_backend) }); + + idf.ESP_LOG(allocator, tag, + \\[ESP-IDF Info] + \\* Version: {s} + \\ + , .{idf.Version.get().toString(allocator)}); + + idf.ESP_LOG(allocator, tag, + \\[Memory Info] + \\* Total: {d} + \\* Free: {d} + \\* Minimum: {d} + \\ + , .{ + heap.totalSize(), + heap.freeSize(), + heap.minimumFreeSize(), + }); + + idf.ESP_LOG(allocator, tag, "Let's have a look at your shiny {s} - {s} system! :)\n\n", .{ + @tagName(builtin.cpu.arch), + builtin.cpu.model.name, + }); + + if (builtin.mode == .Debug) + heap.dump(); +} + +// override the std panic function with idf.panic +pub const panic = idf.panic; +const log = std.log.scoped(.@"esp-idf"); +pub const std_options = .{ + .log_level = switch (builtin.mode) { + .Debug => .debug, + else => .info, + }, + // Define logFn to override the std implementation + .logFn = idf.espLogFn, +}; + +const tag = "zig-hello"; diff --git a/examples/zig/esp-idf-v5/get-started/hello_world/main/placeholder.c b/examples/zig/esp-idf-v5/get-started/hello_world/main/placeholder.c new file mode 100644 index 0000000..887d03c --- /dev/null +++ b/examples/zig/esp-idf-v5/get-started/hello_world/main/placeholder.c @@ -0,0 +1 @@ +// empty (app) file \ No newline at end of file diff --git a/support/wokwi/diagram-esp32c6.json b/support/wokwi/diagram-esp32c6.json index d25eaa3..7df7fb8 100644 --- a/support/wokwi/diagram-esp32c6.json +++ b/support/wokwi/diagram-esp32c6.json @@ -11,6 +11,6 @@ "attrs": { } } ], - "connections": [ ], + "connections": [ [ "esp:TX", "$serialMonitor:RX", "", [] ], [ "esp:RX", "$serialMonitor:TX", "", [] ] ], "dependencies": {} } \ No newline at end of file diff --git a/support/wokwi/diagram-esp32h2.json b/support/wokwi/diagram-esp32h2.json index d0052cd..adfb803 100644 --- a/support/wokwi/diagram-esp32h2.json +++ b/support/wokwi/diagram-esp32h2.json @@ -11,6 +11,6 @@ "attrs": { "builder": "esp-idf" } } ], - "connections": [ ], + "connections": [ [ "esp:TX", "$serialMonitor:RX", "", [] ], [ "esp:RX", "$serialMonitor:TX", "", [] ] ], "dependencies": {} } \ No newline at end of file diff --git a/support/wokwi/diagram-esp32s2.json b/support/wokwi/diagram-esp32s2.json index bcc6887..d62d002 100644 --- a/support/wokwi/diagram-esp32s2.json +++ b/support/wokwi/diagram-esp32s2.json @@ -3,7 +3,6 @@ "author": "Juraj Michálek", "editor": "wokwi", "parts": [ { "type": "board-esp32-s2-devkitm-1", "id": "esp", "top": 0, "left": 0, "attrs": {} } ], - "connections": [ -], + "connections": [ [ "esp:TX", "$serialMonitor:RX", "", [] ], [ "esp:RX", "$serialMonitor:TX", "", [] ] ], "dependencies": {} } diff --git a/support/wokwi/diagram-esp32s3.json b/support/wokwi/diagram-esp32s3.json index 501843f..8dd7f12 100644 --- a/support/wokwi/diagram-esp32s3.json +++ b/support/wokwi/diagram-esp32s3.json @@ -3,6 +3,6 @@ "author": "Juraj Michálek", "editor": "wokwi", "parts": [ { "type": "board-esp32-s3-devkitc-1", "id": "esp", "top": 0, "left": 0, "attrs": { "flashSize":"8"} } ], - "connections": [], + "connections": [ [ "esp:TX", "$serialMonitor:RX", "", [] ], [ "esp:RX", "$serialMonitor:TX", "", [] ] ], "dependencies": {} } \ No newline at end of file