From 8f45032f34743932b946749fa7343f3d0ea32761 Mon Sep 17 00:00:00 2001 From: Ivan Li Date: Mon, 15 Jan 2024 00:14:47 +0800 Subject: [PATCH] first commit. --- .cargo/config.toml | 17 ++++++++ .devcontainer/Dockerfile | 66 ++++++++++++++++++++++++++++ .devcontainer/devcontainer.json | 44 +++++++++++++++++++ .dockerignore | 1 + .github/workflows/rust_ci.yml | 39 +++++++++++++++++ .gitignore | 4 ++ Cargo.toml | 31 +++++++++++++ build.rs | 3 ++ diagram.json | 34 +++++++++++++++ docs/README.md | 77 +++++++++++++++++++++++++++++++++ rust-toolchain.toml | 3 ++ scripts/build.sh | 18 ++++++++ scripts/flash.sh | 21 +++++++++ sdkconfig.defaults | 10 +++++ src/main.rs | 19 ++++++++ wokwi.toml | 5 +++ 16 files changed, 392 insertions(+) create mode 100644 .cargo/config.toml create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/devcontainer.json create mode 100644 .dockerignore create mode 100644 .github/workflows/rust_ci.yml create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 build.rs create mode 100644 diagram.json create mode 100644 docs/README.md create mode 100644 rust-toolchain.toml create mode 100755 scripts/build.sh create mode 100755 scripts/flash.sh create mode 100644 sdkconfig.defaults create mode 100644 src/main.rs create mode 100644 wokwi.toml diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..3a9f1c0 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,17 @@ +[build] +target = "riscv32imc-esp-espidf" + +[target.riscv32imc-esp-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 = ["--cfg", "espidf_time64", "-C", "default-linker-libraries"] + +[unstable] +build-std = ["std", "panic_abort"] + +[env] +MCU="esp32c3" +# Note: this variable is not used by the pio builder (`cargo build --features pio`) +ESP_IDF_VERSION = "v5.1.1" + diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..0366f8c --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,66 @@ +ARG VARIANT=bookworm-slim +FROM debian:${VARIANT} +ENV DEBIAN_FRONTEND=noninteractive +ENV LC_ALL=C.UTF-8 +ENV LANG=C.UTF-8 + +# Arguments +ARG CONTAINER_USER=esp +ARG CONTAINER_GROUP=esp +ARG ESP_BOARD=all +ARG GITHUB_TOKEN + +# Install dependencies +RUN apt-get update \ + && apt-get install -y pkg-config curl gcc clang libudev-dev unzip xz-utils \ + git wget flex bison gperf python3 python3-pip python3-venv cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0 \ + && apt-get clean -y && rm -rf /var/lib/apt/lists/* /tmp/library-scripts + +# Set users +RUN adduser --disabled-password --gecos "" ${CONTAINER_USER} +USER ${CONTAINER_USER} +WORKDIR /home/${CONTAINER_USER} + +# Install rustup +RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- \ + --default-toolchain none -y --profile minimal + +# Update envs +ENV PATH=${PATH}:/home/${CONTAINER_USER}/.cargo/bin + +# Install extra crates +RUN ARCH=$($HOME/.cargo/bin/rustup show | grep "Default host" | sed -e 's/.* //') && \ + curl -L "https://github.com/esp-rs/espup/releases/latest/download/espup-${ARCH}" -o "${HOME}/.cargo/bin/espup" && \ + chmod u+x "${HOME}/.cargo/bin/espup" && \ + curl -L "https://github.com/esp-rs/espflash/releases/latest/download/cargo-espflash-${ARCH}.zip" -o "${HOME}/.cargo/bin/cargo-espflash.zip" && \ + unzip "${HOME}/.cargo/bin/cargo-espflash.zip" -d "${HOME}/.cargo/bin/" && \ + rm "${HOME}/.cargo/bin/cargo-espflash.zip" && \ + chmod u+x "${HOME}/.cargo/bin/cargo-espflash" && \ + curl -L "https://github.com/esp-rs/espflash/releases/latest/download/espflash-${ARCH}.zip" -o "${HOME}/.cargo/bin/espflash.zip" && \ + unzip "${HOME}/.cargo/bin/espflash.zip" -d "${HOME}/.cargo/bin/" && \ + rm "${HOME}/.cargo/bin/espflash.zip" && \ + chmod u+x "${HOME}/.cargo/bin/espflash" && \ + curl -L "https://github.com/esp-rs/embuild/releases/latest/download/ldproxy-${ARCH}.zip" -o "${HOME}/.cargo/bin/ldproxy.zip" && \ + unzip "${HOME}/.cargo/bin/ldproxy.zip" -d "${HOME}/.cargo/bin/" && \ + rm "${HOME}/.cargo/bin/ldproxy.zip" && \ + chmod u+x "${HOME}/.cargo/bin/ldproxy" && \ + curl -L "https://github.com/esp-rs/esp-web-flash-server/releases/latest/download/web-flash-${ARCH}.zip" -o "${HOME}/.cargo/bin/web-flash.zip" && \ + unzip "${HOME}/.cargo/bin/web-flash.zip" -d "${HOME}/.cargo/bin/" && \ + rm "${HOME}/.cargo/bin/web-flash.zip" && \ + chmod u+x "${HOME}/.cargo/bin/web-flash" + +# Install Xtensa Rust +RUN if [ -n "${GITHUB_TOKEN}" ]; then export GITHUB_TOKEN=${GITHUB_TOKEN}; fi \ + && ${HOME}/.cargo/bin/espup install\ + --targets "${ESP_BOARD}" \ + --log-level debug \ + --export-file /home/${CONTAINER_USER}/export-esp.sh + +# Set default toolchain +RUN rustup default nightly + + +# Activate ESP environment +RUN echo "source /home/${CONTAINER_USER}/export-esp.sh" >> ~/.bashrc + +CMD [ "/bin/bash" ] diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..79dfc50 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,44 @@ +{ + "name": "network_monitor_esp_rs", + // Select between image and build propieties to pull or build the image. + // "image": "docker.io/espressif/idf-rust:esp32c3_latest", + "build": { + "dockerfile": "Dockerfile", + "args": { + "CONTAINER_USER": "esp", + "CONTAINER_GROUP": "esp", + "ESP_BOARD": "esp32c3" + } + }, + "settings": { + "editor.formatOnPaste": true, + "editor.formatOnSave": true, + "editor.formatOnSaveMode": "file", + "editor.formatOnType": true, + "lldb.executable": "/usr/bin/lldb", + "files.watcherExclude": { + "**/target/**": true + }, + "rust-analyzer.checkOnSave.command": "clippy", + "rust-analyzer.checkOnSave.allTargets": false, + "[rust]": { + "editor.defaultFormatter": "rust-lang.rust-analyzer" + } + }, + "extensions": [ + "rust-lang.rust-analyzer", + "tamasfe.even-better-toml", + "serayuzgur.crates", + "mutantdino.resourcemonitor", + "yzhang.markdown-all-in-one", + "ms-vscode.cpptools", + "actboy168.tasks", + "Wokwi.wokwi-vscode" + ], + "forwardPorts": [ + 3333, + 8000 + ], + "workspaceMount": "source=${localWorkspaceFolder},target=/home/esp/network_monitor_esp_rs,type=bind,consistency=cached", + "workspaceFolder": "/home/esp/network_monitor_esp_rs" +} diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..eb5a316 --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +target diff --git a/.github/workflows/rust_ci.yml b/.github/workflows/rust_ci.yml new file mode 100644 index 0000000..ca87285 --- /dev/null +++ b/.github/workflows/rust_ci.yml @@ -0,0 +1,39 @@ +name: Continuous Integration + +on: + push: + paths-ignore: + - "**/README.md" + pull_request: + workflow_dispatch: + +env: + CARGO_TERM_COLOR: always + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +jobs: + rust-checks: + name: Rust Checks + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + action: + - command: build + args: --release + - command: fmt + args: --all -- --check --color always + - command: clippy + args: --all-targets --all-features --workspace -- -D warnings + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Enable caching + uses: Swatinem/rust-cache@v2 + - name: Setup Rust + uses: dtolnay/rust-toolchain@v1 + with: + toolchain: nightly + components: rust-src + - name: Run command + run: cargo ${{ matrix.action.command }} ${{ matrix.action.args }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..73a638b --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/.vscode +/.embuild +/target +/Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..d7ea0b3 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "network-monitor-esp-rs" +version = "0.1.0" +authors = ["Ivan Li "] +edition = "2021" +resolver = "2" +rust-version = "1.71" + +[profile.release] +opt-level = "s" + +[profile.dev] +debug = true # Symbols are nice and they don't increase the size on Flash +opt-level = "z" + +[features] +default = ["std", "embassy", "esp-idf-svc/native"] + +pio = ["esp-idf-svc/pio"] +std = ["alloc", "esp-idf-svc/binstart", "esp-idf-svc/std"] +alloc = ["esp-idf-svc/alloc"] +nightly = ["esp-idf-svc/nightly"] +experimental = ["esp-idf-svc/experimental"] +embassy = ["esp-idf-svc/embassy-sync", "esp-idf-svc/critical-section", "esp-idf-svc/embassy-time-driver"] + +[dependencies] +log = { version = "0.4", default-features = false } +esp-idf-svc = { version = "0.47.3", default-features = false } + +[build-dependencies] +embuild = "0.31.3" diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..112ec3f --- /dev/null +++ b/build.rs @@ -0,0 +1,3 @@ +fn main() { + embuild::espidf::sysenv::output(); +} diff --git a/diagram.json b/diagram.json new file mode 100644 index 0000000..6c11e37 --- /dev/null +++ b/diagram.json @@ -0,0 +1,34 @@ +{ + "version": 1, + "editor": "wokwi", + "author": "Ivan Li ", + "parts": [ + { + "type": "board-esp32-c3-devkitm-1", + "id": "esp", + "top": 0.59, + "left": 0.67, + "attrs": { + "flashSize": "16" + } + } + ], + "connections": [ + [ + "esp:TX", + "$serialMonitor:RX", + "", + [] + ], + [ + "esp:RX", + "$serialMonitor:TX", + "", + [] + ] + ], + "serialMonitor": { + "display": "terminal", + "convertEol": true + } +} diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..5e99df5 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,77 @@ +# network_monitor_esp_rs + +## Dev Containers +This repository offers Dev Containers supports for: +- [VS Code Dev Containers](https://code.visualstudio.com/docs/remote/containers#_quick-start-open-an-existing-folder-in-a-container) +- [GitHub Codespaces](https://docs.github.com/en/codespaces/developing-in-codespaces/creating-a-codespace) +> **Note** +> +> In [order to use GitHub Codespaces](https://github.com/features/codespaces#faq) +> the project needs to be published in a GitHub repository and the user needs +> to be part of the Codespaces beta or have the project under an organization. + +If using VS Code or GitHub Codespaces, you can pull the image instead of building it +from the Dockerfile by selecting the `image` property instead of `build` in +`.devcontainer/devcontainer.json`. Further customization of the Dev Container can +be achived, see [.devcontainer.json reference](https://code.visualstudio.com/docs/remote/devcontainerjson-reference). + +When using Dev Containers, some tooling to facilitate building, flashing and +simulating in Wokwi is also added. +### Build +- Terminal approach: + + ``` + scripts/build.sh [debug | release] + ``` + > If no argument is passed, `release` will be used as default + + +- UI approach: + + The default build task is already set to build the project, and it can be used + in VS Code and GitHub Codespaces: + - From the [Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette) (`Ctrl-Shift-P` or `Cmd-Shift-P`) run the `Tasks: Run Build Task` command. + - `Terminal`-> `Run Build Task` in the menu. + - With `Ctrl-Shift-B` or `Cmd-Shift-B`. + - From the [Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette) (`Ctrl-Shift-P` or `Cmd-Shift-P`) run the `Tasks: Run Task` command and + select `Build`. + - From UI: Press `Build` on the left side of the Status Bar. + +### Flash + +> **Note** +> +> When using GitHub Codespaces, we need to make the ports +> public, [see instructions](https://docs.github.com/en/codespaces/developing-in-codespaces/forwarding-ports-in-your-codespace#sharing-a-port). + +- Terminal approach: + - Using `flash.sh` script: + + ``` + scripts/flash.sh [debug | release] + ``` + > If no argument is passed, `release` will be used as default + +- UI approach: + - From the [Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette) (`Ctrl-Shift-P` or `Cmd-Shift-P`) run the `Tasks: Run Task` command and + select `Build & Flash`. + - From UI: Press `Build & Flash` on the left side of the Status Bar. +- Any alternative flashing method from host machine. + + +### Wokwi Simulation + +#### VS Code Dev Containers and GitHub Codespaces + +The Dev Container includes the Wokwi Vs Code installed, hence you can simulate your built projects doing the following: +1. Press `F1` +2. Run `Wokwi: Start Simulator` + +> **Note** +> +> We assume that the project is built in `debug` mode, if you want to simulate projects in release, please update the `elf` and `firmware` proprieties in `wokwi.toml`. + +For more information and details on how to use the Wokwi extension, see [Getting Started] and [Debugging your code] Chapter of the Wokwi documentation. + +[Getting Started]: https://docs.wokwi.com/vscode/getting-started +[Debugging your code]: https://docs.wokwi.com/vscode/debugging diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..f70d225 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,3 @@ +[toolchain] +channel = "nightly" +components = ["rust-src"] diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100755 index 0000000..ba22089 --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +which idf.py >/dev/null || { + source ~/export-esp.sh >/dev/null 2>&1 +} + +case "$1" in +"" | "release") + cargo build --release + ;; +"debug") + cargo build + ;; +*) + echo "Wrong argument. Only \"debug\"/\"release\" arguments are supported" + exit 1 + ;; +esac diff --git a/scripts/flash.sh b/scripts/flash.sh new file mode 100755 index 0000000..1fda498 --- /dev/null +++ b/scripts/flash.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +set -e + +BUILD_MODE="" +case "$1" in +"" | "release") + bash scripts/build.sh + BUILD_MODE="release" + ;; +"debug") + bash scripts/build.sh debug + BUILD_MODE="debug" + ;; +*) + echo "Wrong argument. Only \"debug\"/\"release\" arguments are supported" + exit 1 + ;; +esac + +web-flash --chip esp32c3 target/riscv32imc-esp-espidf/${BUILD_MODE}/network-monitor-esp-rs diff --git a/sdkconfig.defaults b/sdkconfig.defaults new file mode 100644 index 0000000..9ea5d73 --- /dev/null +++ b/sdkconfig.defaults @@ -0,0 +1,10 @@ +# Rust often needs a bit of an extra main task stack size compared to C (the default is 3K) +CONFIG_ESP_MAIN_TASK_STACK_SIZE=8000 + +# Use this to set FreeRTOS kernel tick frequency to 1000 Hz (100 Hz by default). +# This allows to use 1 ms granuality for thread sleeps (10 ms by default). +#CONFIG_FREERTOS_HZ=1000 + +# Workaround for https://github.com/espressif/esp-idf/issues/7631 +#CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=n +#CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=n diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..dbcc105 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,19 @@ +#![feature(thread_sleep_until)] + +use std::{thread::sleep_until, time::Instant}; + +fn main() { + // It is necessary to call this function once. Otherwise some patches to the runtime + // implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71 + esp_idf_svc::sys::link_patches(); + + // Bind the log crate to the ESP Logging facilities + esp_idf_svc::log::EspLogger::initialize_default(); + + loop { + log::info!("Hello, world!"); + + // 睡眠一秒 + sleep_until(Instant::now() + std::time::Duration::from_secs(1)); + } +} diff --git a/wokwi.toml b/wokwi.toml new file mode 100644 index 0000000..60e3bd6 --- /dev/null +++ b/wokwi.toml @@ -0,0 +1,5 @@ +[wokwi] +version = 1 +gdbServerPort = 3333 +elf = "target/riscv32imc-esp-espidf/debug/network-monitor-esp-rs" +firmware = "target/riscv32imc-esp-espidf/debug/network-monitor-esp-rs"