Initial commit
Signed-off-by: Thomas Klaehn <thomas.klaehn@perinet.io>
This commit is contained in:
commit
18e9f86c36
28
.cargo/config.toml
Normal file
28
.cargo/config.toml
Normal file
@ -0,0 +1,28 @@
|
||||
[build]
|
||||
target = "riscv32imc-esp-espidf"
|
||||
|
||||
[target.riscv32imc-esp-espidf]
|
||||
linker = "ldproxy"
|
||||
runner = "espflash flash --monitor"
|
||||
# Future - necessary for the experimental "native build" of esp-idf-sys with ESP32C3
|
||||
# See also https://github.com/ivmarkov/embuild/issues/16
|
||||
rustflags = ["--cfg", "espidf_time64"]
|
||||
|
||||
[unstable]
|
||||
build-std = ["std", "panic_abort"]
|
||||
|
||||
[env]
|
||||
# Enables the esp-idf-sys "native" build feature (`cargo build --features native`) to build against ESP-IDF (v5.3.2)
|
||||
ESP_IDF_VERSION = { value = "tag:v5.3.2" }
|
||||
|
||||
# These configurations will pick up your custom "sdkconfig.release", "sdkconfig.debug" or "sdkconfig.defaults[.*]" files
|
||||
# that you might put in the root of the project
|
||||
# The easiest way to generate a full "sdkconfig[.release|debug]" configuration (as opposed to manually enabling only the necessary flags via "sdkconfig.defaults[.*]"
|
||||
# is by running "cargo pio espidf menuconfig" (that is, if using the pio builder)
|
||||
#ESP_IDF_SDKCONFIG = { value = "./sdkconfig.release", relative = true }
|
||||
#ESP_IDF_SDKCONFIG = { value = "./sdkconfig.debug", relative = true }
|
||||
ESP_IDF_SDKCONFIG_DEFAULTS = { value = "./sdkconfig.defaults", relative = true }
|
||||
# ESP-IDF will be installed in ~/.espressif so it can be reused across the different examples.
|
||||
# See also https://github.com/esp-rs/esp-idf-sys/blob/master/BUILD-OPTIONS.md#esp_idf_tools_install_dir-esp_idf_tools_install_dir
|
||||
ESP_IDF_TOOLS_INSTALL_DIR = { value = "global" }
|
||||
|
79
.devcontainer/Dockerfile
Normal file
79
.devcontainer/Dockerfile
Normal file
@ -0,0 +1,79 @@
|
||||
# Base image
|
||||
FROM debian:bookworm-slim
|
||||
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 NIGHTLY_VERSION=nightly-2024-06-30
|
||||
ARG ESP_IDF_VERSION=v5.2.2
|
||||
ARG ESP_BOARD=esp32c3
|
||||
|
||||
# Install dependencies
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y git wget flex bison gperf python3 python3-pip python3-venv \
|
||||
cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0 \
|
||||
llvm-dev libclang-dev clang pkg-config unzip libusb-1.0-0 \
|
||||
libpython3-all-dev python3-virtualenv curl \
|
||||
&& apt-get clean -y \
|
||||
&& rm -rf /var/lib/apt/lists/* /tmp/library-scripts
|
||||
|
||||
# Set users
|
||||
RUN adduser --disabled-password --gecos "" ${CONTAINER_USER}
|
||||
RUN adduser ${CONTAINER_USER} root
|
||||
USER ${CONTAINER_USER}
|
||||
WORKDIR /home/${CONTAINER_USER}
|
||||
|
||||
# Install rustup
|
||||
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- \
|
||||
--default-toolchain ${NIGHTLY_VERSION} -y --profile minimal \
|
||||
--component rust-src,clippy,rustfmt
|
||||
|
||||
# Update envs
|
||||
ENV PATH=${PATH}:$HOME/.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/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/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" && \
|
||||
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" && \
|
||||
GENERATE_VERSION=$(git ls-remote --refs --sort="version:refname" --tags "https://github.com/cargo-generate/cargo-generate" | cut -d/ -f3- | tail -n1) && \
|
||||
GENERATE_URL="https://github.com/cargo-generate/cargo-generate/releases/latest/download/cargo-generate-${GENERATE_VERSION}-${ARCH}.tar.gz" && \
|
||||
curl -L "${GENERATE_URL}" -o "${HOME}/.cargo/bin/cargo-generate.tar.gz" && \
|
||||
tar xf "${HOME}/.cargo/bin/cargo-generate.tar.gz" -C "${HOME}/.cargo/bin/" && \
|
||||
rm "${HOME}/.cargo/bin/cargo-generate.tar.gz" && \
|
||||
chmod u+x "${HOME}/.cargo/bin/cargo-generate"
|
||||
|
||||
# Install esp-idf
|
||||
RUN mkdir -p ${HOME}/.espressif/frameworks/ \
|
||||
&& git clone --branch ${ESP_IDF_VERSION} -q --depth 1 --shallow-submodules \
|
||||
--recursive https://github.com/espressif/esp-idf.git \
|
||||
${HOME}/.espressif/frameworks/esp-idf \
|
||||
&& python3 ${HOME}/.espressif/frameworks/esp-idf/tools/idf_tools.py install cmake \
|
||||
&& ${HOME}/.espressif/frameworks/esp-idf/install.sh ${ESP_BOARD} \
|
||||
&& rm -rf .espressif/dist \
|
||||
&& rm -rf .espressif/frameworks/esp-idf/docs \
|
||||
&& rm -rf .espressif/frameworks/esp-idf/examples \
|
||||
&& rm -rf .espressif/frameworks/esp-idf/tools/esp_app_trace \
|
||||
&& rm -rf .espressif/frameworks/esp-idf/tools/test_idf_size
|
||||
|
||||
# Activate ESP environment
|
||||
ENV IDF_TOOLS_PATH=${HOME}/.espressif
|
||||
RUN echo "source ${HOME}/.espressif/frameworks/esp-idf/export.sh > /dev/null 2>&1" >> ~/.bashrc
|
||||
|
||||
CMD "/bin/bash"
|
51
.devcontainer/devcontainer.json
Executable file
51
.devcontainer/devcontainer.json
Executable file
@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": "espressif-training",
|
||||
// Comment the image and use the build property to build the image from the
|
||||
// Dockerfile instead of downloading it from https://hub.docker.com/r/espressif/rust-std-training
|
||||
// "image": "docker.io/espressif/rust-std-training",
|
||||
"build": {
|
||||
"dockerfile": "Dockerfile",
|
||||
"args": {
|
||||
"NIGHTLY_VERSION": "nightly-2025-01-01"
|
||||
}
|
||||
},
|
||||
// Privileged container in order to access /dev
|
||||
"privileged": true,
|
||||
// Mount USB devices (debug probes, UART interfaces, ...)
|
||||
"mounts": [
|
||||
"source=/dev/bus/usb/,target=/dev/bus/usb/,type=bind"
|
||||
],
|
||||
"runArgs": [
|
||||
"--device=/dev/ttyACM0"
|
||||
],
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"settings": {
|
||||
"editor.formatOnPaste": true,
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnSaveMode": "modifications",
|
||||
"editor.formatOnType": true,
|
||||
"lldb.executable": "/usr/bin/lldb",
|
||||
"files.watcherExclude": {
|
||||
"**/target/**": true
|
||||
},
|
||||
"rust-analyzer.checkOnSave.command": "clippy",
|
||||
"[rust]": {
|
||||
"editor.defaultFormatter": "rust-lang.rust-analyzer"
|
||||
}
|
||||
},
|
||||
"extensions": [
|
||||
"rust-lang.rust-analyzer",
|
||||
"tamasfe.even-better-toml",
|
||||
"vadimcn.vscode-lldb",
|
||||
"serayuzgur.crates",
|
||||
"mutantdino.resourcemonitor",
|
||||
"yzhang.markdown-all-in-one",
|
||||
"Wokwi.wokwi-vscode"
|
||||
]
|
||||
}
|
||||
},
|
||||
"remoteUser": "esp",
|
||||
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached",
|
||||
"workspaceFolder": "/workspace"
|
||||
}
|
50
.devcontainer/test.sh
Normal file
50
.devcontainer/test.sh
Normal file
@ -0,0 +1,50 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -ef
|
||||
|
||||
echo "Compiling $1"
|
||||
|
||||
cd /home/esp/workspace/$1
|
||||
|
||||
if [ -f cfg.toml.example ]; then
|
||||
# Rename file to cfg.toml
|
||||
cp cfg.toml.example cfg.toml
|
||||
# Replace defaults
|
||||
sed -i 's/wifi_ssid = "FBI Surveillance Van"/wifi_ssid = "Wokwi-GUEST"/g' cfg.toml
|
||||
sed -i 's/wifi_psk = "hunter2"/wifi_psk = ""/g' cfg.toml
|
||||
sed -i 's/mqtt_user = "horse"/mqtt_user = "user"/g' cfg.toml
|
||||
sed -i 's/mqtt_pass = "CorrectHorseBatteryStaple"/mqtt_pass = "pass"/g' cfg.toml
|
||||
sed -i 's/mqtt_host = "yourpc.local"/mqtt_host = "host"/g' cfg.toml
|
||||
fi
|
||||
|
||||
$HOME/.cargo/bin/cargo clean
|
||||
$HOME/.cargo/bin/cargo build
|
||||
|
||||
# Check examples
|
||||
if [[ "$1" == advanced/button-interrupt ]]; then
|
||||
$HOME/.cargo/bin/cargo build --example solution
|
||||
$HOME/.cargo/bin/cargo build --example solution_led
|
||||
# Simulate with Wokwi
|
||||
sed -i 's/^[[:space:]]*firmware[[:space:]]*=[[:space:]]*["'"'"']\([^"'"'"']*\)["'"'"']\([[:space:]]*\)$/\nfirmware = "target\/riscv32imc-esp-espidf\/debug\/examples\/solution"/' wokwi.toml
|
||||
fi
|
||||
|
||||
if [[ "$1" == advanced/i2c-sensor-reading ]]; then
|
||||
$HOME/.cargo/bin/cargo build --example part_1
|
||||
$HOME/.cargo/bin/cargo build --example part_2
|
||||
fi
|
||||
|
||||
if [[ "$1" == intro/http-client ]]; then
|
||||
$HOME/.cargo/bin/cargo build --example http_client
|
||||
$HOME/.cargo/bin/cargo build --example https_client
|
||||
# Simulate with Wokwi
|
||||
sed -i 's/^[[:space:]]*firmware[[:space:]]*=[[:space:]]*["'"'"']\([^"'"'"']*\)["'"'"']\([[:space:]]*\)$/\nfirmware = "target\/riscv32imc-esp-espidf\/debug\/examples\/http_client"/' wokwi.toml
|
||||
fi
|
||||
|
||||
if [[ "$1" == intro/http-server ]]; then
|
||||
$HOME/.cargo/bin/cargo build --example http_server
|
||||
fi
|
||||
|
||||
if [[ "$1" == intro/mqtt/exercise ]]; then
|
||||
$HOME/.cargo/bin/cargo build --example solution_publ_rcv
|
||||
$HOME/.cargo/bin/cargo build --example solution_publ
|
||||
fi
|
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
.vscode
|
||||
.idea
|
||||
target
|
||||
Cargo.lock
|
||||
cfg.toml
|
||||
__pycache__
|
||||
.DS_Store
|
||||
.embuild/
|
||||
.vale
|
||||
.vale.ini
|
||||
components_esp32c3.lock
|
32
Cargo.toml
Normal file
32
Cargo.toml
Normal file
@ -0,0 +1,32 @@
|
||||
[package]
|
||||
name = "hardware-check"
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"Anatol Ulrich <anatol.ulrich@ferrous-systems.com>",
|
||||
"Sergio Gasquez <sergio.gasquez@gmail.com>",
|
||||
]
|
||||
edition = "2021"
|
||||
resolver = "2"
|
||||
|
||||
[[bin]]
|
||||
name = "hardware-check"
|
||||
harness = false # We can't use the default rust libtest harness for a crosscompile target
|
||||
|
||||
[profile.release]
|
||||
opt-level = "s"
|
||||
|
||||
[profile.dev]
|
||||
debug = true # Symbols are nice and they don't increase the size on Flash
|
||||
opt-level = "z"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "=1.0.95"
|
||||
esp-idf-svc = "=0.50.1"
|
||||
log = "=0.4.22"
|
||||
rgb-led = { path = "lib/rgb-led" }
|
||||
toml-cfg = "=0.1.3"
|
||||
wifi = { path = "lib/wifi" }
|
||||
|
||||
[build-dependencies]
|
||||
embuild = "=0.33.0"
|
||||
toml-cfg = "=0.1.3"
|
22
build.rs
Normal file
22
build.rs
Normal file
@ -0,0 +1,22 @@
|
||||
#[toml_cfg::toml_config]
|
||||
pub struct Config {
|
||||
#[default("")]
|
||||
wifi_ssid: &'static str,
|
||||
#[default("")]
|
||||
wifi_psk: &'static str,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Check if the `cfg.toml` file exists and has been filled out.
|
||||
if !std::path::Path::new("cfg.toml").exists() {
|
||||
panic!("You need to create a `cfg.toml` file with your Wi-Fi credentials! Use `cfg.toml.example` as a template.");
|
||||
}
|
||||
|
||||
// The constant `CONFIG` is auto-generated by `toml_config`.
|
||||
let app_config = CONFIG;
|
||||
if app_config.wifi_ssid == "FBI Surveillance Van" || app_config.wifi_psk == "hunter2" {
|
||||
panic!("You need to set the Wi-Fi credentials in `cfg.toml`!");
|
||||
}
|
||||
|
||||
embuild::espidf::sysenv::output();
|
||||
}
|
28
lib/rgb-led/.cargo/config.toml
Normal file
28
lib/rgb-led/.cargo/config.toml
Normal file
@ -0,0 +1,28 @@
|
||||
[build]
|
||||
target = "riscv32imc-esp-espidf"
|
||||
|
||||
[target.riscv32imc-esp-espidf]
|
||||
linker = "ldproxy"
|
||||
runner = "espflash flash --monitor"
|
||||
# Future - necessary for the experimental "native build" of esp-idf-sys with ESP32C3
|
||||
# See also https://github.com/ivmarkov/embuild/issues/16
|
||||
rustflags = ["--cfg", "espidf_time64"]
|
||||
|
||||
[unstable]
|
||||
build-std = ["panic_abort", "std"]
|
||||
|
||||
[env]
|
||||
# Enables the esp-idf-sys "native" build feature (`cargo build --features native`) to build against ESP-IDF (v5.3.2)
|
||||
ESP_IDF_VERSION = { value = "tag:v5.3.2" }
|
||||
|
||||
# These configurations will pick up your custom "sdkconfig.release", "sdkconfig.debug" or "sdkconfig.defaults[.*]" files
|
||||
# that you might put in the root of the project
|
||||
# The easiest way to generate a full "sdkconfig[.release|debug]" configuration (as opposed to manually enabling only the necessary flags via "sdkconfig.defaults[.*]"
|
||||
# is by running "cargo pio espidf menuconfig" (that is, if using the pio builder)
|
||||
#ESP_IDF_SDKCONFIG = { value = "./sdkconfig.release", relative = true }
|
||||
#ESP_IDF_SDKCONFIG = { value = "./sdkconfig.debug", relative = true }
|
||||
ESP_IDF_SDKCONFIG_DEFAULTS = { value = "./sdkconfig.defaults", relative = true }
|
||||
# ESP-IDF will be installed in ~/.espressif so it can be reused across the different examples.
|
||||
# See also https://github.com/esp-rs/esp-idf-sys/blob/master/BUILD-OPTIONS.md#esp_idf_tools_install_dir-esp_idf_tools_install_dir
|
||||
ESP_IDF_TOOLS_INSTALL_DIR = { value = "global" }
|
||||
|
2
lib/rgb-led/.gitignore
vendored
Normal file
2
lib/rgb-led/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/target
|
||||
Cargo.lock
|
15
lib/rgb-led/Cargo.toml
Normal file
15
lib/rgb-led/Cargo.toml
Normal file
@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "rgb-led"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
authors = ["Sergio Gasquez <sergio.gasquez@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
anyhow = "=1.0.95"
|
||||
esp-idf-svc = "=0.50.1"
|
||||
esp-idf-hal ={ version = "=0.45.0", features = ["rmt-legacy"] }
|
||||
log = "=0.4.22"
|
||||
rgb = "0.8.29"
|
||||
|
||||
[build-dependencies]
|
||||
embuild = "=0.33.0"
|
3
lib/rgb-led/build.rs
Normal file
3
lib/rgb-led/build.rs
Normal file
@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
embuild::espidf::sysenv::output();
|
||||
}
|
27
lib/rgb-led/examples/ws2812.rs
Normal file
27
lib/rgb-led/examples/ws2812.rs
Normal file
@ -0,0 +1,27 @@
|
||||
use anyhow::Result;
|
||||
use esp_idf_svc::hal::{delay::FreeRtos, peripherals::Peripherals};
|
||||
use log::info;
|
||||
use rgb_led::WS2812RMT;
|
||||
|
||||
fn main() -> Result<()> {
|
||||
esp_idf_svc::sys::link_patches();
|
||||
esp_idf_svc::log::EspLogger::initialize_default();
|
||||
|
||||
let peripherals = Peripherals::take().unwrap();
|
||||
// Onboard RGB LED pin
|
||||
// Rust ESP Board gpio2, ESP32-C3-DevKitC-02 gpio8
|
||||
let led = peripherals.pins.gpio2;
|
||||
let channel = peripherals.rmt.channel0;
|
||||
let mut ws2812 = WS2812RMT::new(led, channel)?;
|
||||
loop {
|
||||
info!("Red!");
|
||||
ws2812.set_pixel(rgb::RGB8::new(255, 0, 0))?;
|
||||
FreeRtos::delay_ms(1000);
|
||||
info!("Green!");
|
||||
ws2812.set_pixel(rgb::RGB8::new(0, 255, 0))?;
|
||||
FreeRtos::delay_ms(1000);
|
||||
info!("Blue!");
|
||||
ws2812.set_pixel(rgb::RGB8::new(0, 0, 255))?;
|
||||
FreeRtos::delay_ms(1000);
|
||||
}
|
||||
}
|
3
lib/rgb-led/rust-toolchain.toml
Normal file
3
lib/rgb-led/rust-toolchain.toml
Normal file
@ -0,0 +1,3 @@
|
||||
[toolchain]
|
||||
channel = "nightly-2025-01-01"
|
||||
components = ["rust-src"]
|
48
lib/rgb-led/src/lib.rs
Normal file
48
lib/rgb-led/src/lib.rs
Normal file
@ -0,0 +1,48 @@
|
||||
use anyhow::Result;
|
||||
use core::time::Duration;
|
||||
use esp_idf_hal::{
|
||||
gpio::OutputPin,
|
||||
peripheral::Peripheral,
|
||||
rmt::{config::TransmitConfig, FixedLengthSignal, PinState, Pulse, RmtChannel, TxRmtDriver},
|
||||
};
|
||||
|
||||
pub use rgb::RGB8;
|
||||
|
||||
pub struct WS2812RMT<'a> {
|
||||
tx_rtm_driver: TxRmtDriver<'a>,
|
||||
}
|
||||
|
||||
impl<'d> WS2812RMT<'d> {
|
||||
// Rust ESP Board gpio2, ESP32-C3-DevKitC-02 gpio8
|
||||
pub fn new(
|
||||
led: impl Peripheral<P = impl OutputPin> + 'd,
|
||||
channel: impl Peripheral<P = impl RmtChannel> + 'd,
|
||||
) -> Result<Self> {
|
||||
let config = TransmitConfig::new().clock_divider(2);
|
||||
let tx = TxRmtDriver::new(channel, led, &config)?;
|
||||
Ok(Self { tx_rtm_driver: tx })
|
||||
}
|
||||
|
||||
pub fn set_pixel(&mut self, rgb: RGB8) -> Result<()> {
|
||||
let color: u32 = ((rgb.g as u32) << 16) | ((rgb.r as u32) << 8) | rgb.b as u32;
|
||||
let ticks_hz = self.tx_rtm_driver.counter_clock()?;
|
||||
let t0h = Pulse::new_with_duration(ticks_hz, PinState::High, &ns(350))?;
|
||||
let t0l = Pulse::new_with_duration(ticks_hz, PinState::Low, &ns(800))?;
|
||||
let t1h = Pulse::new_with_duration(ticks_hz, PinState::High, &ns(700))?;
|
||||
let t1l = Pulse::new_with_duration(ticks_hz, PinState::Low, &ns(600))?;
|
||||
let mut signal = FixedLengthSignal::<24>::new();
|
||||
for i in (0..24).rev() {
|
||||
let p = 2_u32.pow(i);
|
||||
let bit = p & color != 0;
|
||||
let (high_pulse, low_pulse) = if bit { (t1h, t1l) } else { (t0h, t0l) };
|
||||
signal.set(23 - i as usize, &(high_pulse, low_pulse))?;
|
||||
}
|
||||
self.tx_rtm_driver.start_blocking(&signal)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn ns(nanos: u64) -> Duration {
|
||||
Duration::from_nanos(nanos)
|
||||
}
|
28
lib/wifi/.cargo/config.toml
Normal file
28
lib/wifi/.cargo/config.toml
Normal file
@ -0,0 +1,28 @@
|
||||
[build]
|
||||
target = "riscv32imc-esp-espidf"
|
||||
|
||||
[target.riscv32imc-esp-espidf]
|
||||
linker = "ldproxy"
|
||||
runner = "espflash flash --monitor"
|
||||
# Future - necessary for the experimental "native build" of esp-idf-sys with ESP32C3
|
||||
# See also https://github.com/ivmarkov/embuild/issues/16
|
||||
rustflags = ["--cfg", "espidf_time64"]
|
||||
|
||||
[unstable]
|
||||
build-std = ["panic_abort", "std"]
|
||||
|
||||
[env]
|
||||
# Enables the esp-idf-sys "native" build feature (`cargo build --features native`) to build against ESP-IDF (v5.3.2)
|
||||
ESP_IDF_VERSION = { value = "tag:v5.3.2" }
|
||||
|
||||
# These configurations will pick up your custom "sdkconfig.release", "sdkconfig.debug" or "sdkconfig.defaults[.*]" files
|
||||
# that you might put in the root of the project
|
||||
# The easiest way to generate a full "sdkconfig[.release|debug]" configuration (as opposed to manually enabling only the necessary flags via "sdkconfig.defaults[.*]"
|
||||
# is by running "cargo pio espidf menuconfig" (that is, if using the pio builder)
|
||||
#ESP_IDF_SDKCONFIG = { value = "./sdkconfig.release", relative = true }
|
||||
#ESP_IDF_SDKCONFIG = { value = "./sdkconfig.debug", relative = true }
|
||||
ESP_IDF_SDKCONFIG_DEFAULTS = { value = "./sdkconfig.defaults", relative = true }
|
||||
# ESP-IDF will be installed in ~/.espressif so it can be reused across the different examples.
|
||||
# See also https://github.com/esp-rs/esp-idf-sys/blob/master/BUILD-OPTIONS.md#esp_idf_tools_install_dir-esp_idf_tools_install_dir
|
||||
ESP_IDF_TOOLS_INSTALL_DIR = { value = "global" }
|
||||
|
2
lib/wifi/.gitignore
vendored
Normal file
2
lib/wifi/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/target
|
||||
Cargo.lock
|
16
lib/wifi/Cargo.toml
Normal file
16
lib/wifi/Cargo.toml
Normal file
@ -0,0 +1,16 @@
|
||||
[package]
|
||||
name = "wifi"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
authors = ["Sergio Gasquez <sergio.gasquez@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
anyhow = "=1.0.95"
|
||||
esp-idf-svc = "=0.50.1"
|
||||
log = "=0.4.22"
|
||||
|
||||
[build-dependencies]
|
||||
embuild = "=0.33.0"
|
||||
|
||||
[dev-dependencies]
|
||||
toml-cfg = "=0.1.3"
|
3
lib/wifi/build.rs
Normal file
3
lib/wifi/build.rs
Normal file
@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
embuild::espidf::sysenv::output();
|
||||
}
|
3
lib/wifi/cfg.toml.example
Normal file
3
lib/wifi/cfg.toml.example
Normal file
@ -0,0 +1,3 @@
|
||||
[wifi]
|
||||
wifi_ssid = "FBI Surveillance Van"
|
||||
wifi_psk = "hunter2"
|
40
lib/wifi/examples/wifi.rs
Normal file
40
lib/wifi/examples/wifi.rs
Normal file
@ -0,0 +1,40 @@
|
||||
use anyhow::{bail, Result};
|
||||
use esp_idf_svc::{eventloop::EspSystemEventLoop, hal::prelude::Peripherals};
|
||||
use wifi::wifi;
|
||||
|
||||
/// This configuration is picked up at compile time by `build.rs` from the
|
||||
/// file `cfg.toml`.
|
||||
#[toml_cfg::toml_config]
|
||||
pub struct Config {
|
||||
#[default("")]
|
||||
wifi_ssid: &'static str,
|
||||
#[default("")]
|
||||
wifi_psk: &'static str,
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
esp_idf_svc::sys::link_patches();
|
||||
esp_idf_svc::log::EspLogger::initialize_default();
|
||||
|
||||
let peripherals = Peripherals::take().unwrap();
|
||||
let sysloop = EspSystemEventLoop::take()?;
|
||||
|
||||
let app_config = CONFIG;
|
||||
// Connect to the Wi-Fi network
|
||||
let _wifi = match wifi(
|
||||
app_config.wifi_ssid,
|
||||
app_config.wifi_psk,
|
||||
peripherals.modem,
|
||||
sysloop,
|
||||
) {
|
||||
Ok(inner) => {
|
||||
println!("Connected to Wi-Fi network!");
|
||||
inner
|
||||
}
|
||||
Err(err) => {
|
||||
// Red!
|
||||
bail!("Could not connect to Wi-Fi network: {:?}", err)
|
||||
}
|
||||
};
|
||||
Ok(())
|
||||
}
|
3
lib/wifi/rust-toolchain.toml
Normal file
3
lib/wifi/rust-toolchain.toml
Normal file
@ -0,0 +1,3 @@
|
||||
[toolchain]
|
||||
channel = "nightly-2025-01-01"
|
||||
components = ["rust-src"]
|
2
lib/wifi/sdkconfig.defaults
Normal file
2
lib/wifi/sdkconfig.defaults
Normal file
@ -0,0 +1,2 @@
|
||||
CONFIG_ESP_MAIN_TASK_STACK_SIZE=20000
|
||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=4096
|
78
lib/wifi/src/lib.rs
Normal file
78
lib/wifi/src/lib.rs
Normal file
@ -0,0 +1,78 @@
|
||||
use anyhow::{bail, Result};
|
||||
use esp_idf_svc::{
|
||||
eventloop::EspSystemEventLoop,
|
||||
hal::peripheral,
|
||||
wifi::{AuthMethod, BlockingWifi, ClientConfiguration, Configuration, EspWifi},
|
||||
};
|
||||
use log::info;
|
||||
|
||||
pub fn wifi(
|
||||
ssid: &str,
|
||||
pass: &str,
|
||||
modem: impl peripheral::Peripheral<P = esp_idf_svc::hal::modem::Modem> + 'static,
|
||||
sysloop: EspSystemEventLoop,
|
||||
) -> Result<Box<EspWifi<'static>>> {
|
||||
let mut auth_method = AuthMethod::WPA2Personal;
|
||||
if ssid.is_empty() {
|
||||
bail!("Missing WiFi name")
|
||||
}
|
||||
if pass.is_empty() {
|
||||
auth_method = AuthMethod::None;
|
||||
info!("Wifi password is empty");
|
||||
}
|
||||
let mut esp_wifi = EspWifi::new(modem, sysloop.clone(), None)?;
|
||||
|
||||
let mut wifi = BlockingWifi::wrap(&mut esp_wifi, sysloop)?;
|
||||
|
||||
wifi.set_configuration(&Configuration::Client(ClientConfiguration::default()))?;
|
||||
|
||||
info!("Starting wifi...");
|
||||
|
||||
wifi.start()?;
|
||||
|
||||
info!("Scanning...");
|
||||
|
||||
let ap_infos = wifi.scan()?;
|
||||
|
||||
let ours = ap_infos.into_iter().find(|a| a.ssid == ssid);
|
||||
|
||||
let channel = if let Some(ours) = ours {
|
||||
info!(
|
||||
"Found configured access point {} on channel {}",
|
||||
ssid, ours.channel
|
||||
);
|
||||
Some(ours.channel)
|
||||
} else {
|
||||
info!(
|
||||
"Configured access point {} not found during scanning, will go with unknown channel",
|
||||
ssid
|
||||
);
|
||||
None
|
||||
};
|
||||
|
||||
wifi.set_configuration(&Configuration::Client(ClientConfiguration {
|
||||
ssid: ssid
|
||||
.try_into()
|
||||
.expect("Could not parse the given SSID into WiFi config"),
|
||||
password: pass
|
||||
.try_into()
|
||||
.expect("Could not parse the given password into WiFi config"),
|
||||
channel,
|
||||
auth_method,
|
||||
..Default::default()
|
||||
}))?;
|
||||
|
||||
info!("Connecting wifi...");
|
||||
|
||||
wifi.connect()?;
|
||||
|
||||
info!("Waiting for DHCP lease...");
|
||||
|
||||
wifi.wait_netif_up()?;
|
||||
|
||||
let ip_info = wifi.wifi().sta_netif().get_ip_info()?;
|
||||
|
||||
info!("Wifi DHCP info: {:?}", ip_info);
|
||||
|
||||
Ok(Box::new(esp_wifi))
|
||||
}
|
3
rust-toolchain.toml
Normal file
3
rust-toolchain.toml
Normal file
@ -0,0 +1,3 @@
|
||||
[toolchain]
|
||||
channel = "nightly-2025-01-01"
|
||||
components = ["rust-src"]
|
10
scripts/jtag-host.sh
Executable file
10
scripts/jtag-host.sh
Executable file
@ -0,0 +1,10 @@
|
||||
#! /bin/sh
|
||||
|
||||
git clone https://github.com/espressif/openocd-esp32.git
|
||||
|
||||
install -m 0644 openocd-esp32/contrib/60-openocd.rules /etc/udev/rules.d
|
||||
|
||||
rm -rf openocd-esp32/
|
||||
|
||||
udevadm control -R
|
||||
udevadm trigger
|
2
sdkconfig.defaults
Normal file
2
sdkconfig.defaults
Normal file
@ -0,0 +1,2 @@
|
||||
CONFIG_ESP_MAIN_TASK_STACK_SIZE=20000
|
||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=4096
|
68
src/main.rs
Normal file
68
src/main.rs
Normal file
@ -0,0 +1,68 @@
|
||||
use anyhow::{bail, Result};
|
||||
use esp_idf_svc::eventloop::EspSystemEventLoop;
|
||||
use esp_idf_svc::hal::prelude::Peripherals;
|
||||
use log::info;
|
||||
use rgb_led::{RGB8, WS2812RMT};
|
||||
use wifi::wifi;
|
||||
|
||||
/// This configuration is picked up at compile time by `build.rs` from the
|
||||
/// file `cfg.toml`.
|
||||
#[toml_cfg::toml_config]
|
||||
pub struct Config {
|
||||
#[default("Wokwi-GUEST")]
|
||||
wifi_ssid: &'static str,
|
||||
#[default("")]
|
||||
wifi_psk: &'static str,
|
||||
}
|
||||
|
||||
/// Entry point to our application.
|
||||
///
|
||||
/// It sets up a Wi-Fi connection to the Access Point given in the
|
||||
/// configuration, then blinks the RGB LED green/blue.
|
||||
///
|
||||
/// If the LED goes solid red, then it was unable to connect to your Wi-Fi
|
||||
/// network.
|
||||
fn main() -> Result<()> {
|
||||
esp_idf_svc::sys::link_patches();
|
||||
esp_idf_svc::log::EspLogger::initialize_default();
|
||||
|
||||
let peripherals = Peripherals::take().unwrap();
|
||||
let sysloop = EspSystemEventLoop::take()?;
|
||||
|
||||
info!("Hello, world!");
|
||||
|
||||
// Start the LED off yellow
|
||||
let mut led = WS2812RMT::new(peripherals.pins.gpio2, peripherals.rmt.channel0)?;
|
||||
led.set_pixel(RGB8::new(50, 50, 0))?;
|
||||
|
||||
// The constant `CONFIG` is auto-generated by `toml_config`.
|
||||
let app_config = CONFIG;
|
||||
|
||||
// Connect to the Wi-Fi network
|
||||
let _wifi = match wifi(
|
||||
app_config.wifi_ssid,
|
||||
app_config.wifi_psk,
|
||||
peripherals.modem,
|
||||
sysloop,
|
||||
) {
|
||||
Ok(inner) => inner,
|
||||
Err(err) => {
|
||||
// Red!
|
||||
led.set_pixel(RGB8::new(50, 0, 0))?;
|
||||
bail!("Could not connect to Wi-Fi network: {:?}", err)
|
||||
}
|
||||
};
|
||||
|
||||
loop {
|
||||
// Blue!
|
||||
led.set_pixel(RGB8::new(0, 0, 50))?;
|
||||
// Wait...
|
||||
std::thread::sleep(std::time::Duration::from_secs(1));
|
||||
info!("Hello, world!");
|
||||
|
||||
// Green!
|
||||
led.set_pixel(RGB8::new(0, 50, 0))?;
|
||||
// Wait...
|
||||
std::thread::sleep(std::time::Duration::from_secs(1));
|
||||
}
|
||||
}
|
12
workspace.code-workspace
Normal file
12
workspace.code-workspace
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": ".",
|
||||
"name": "ESP32"
|
||||
},
|
||||
// { "path": "/usr/src/libperiCORE", "name":"libperiCORE" },
|
||||
// { "path": "/usr/src/seve", "name":"sève" },
|
||||
// { "path": "/usr/src/periCORE-buildsystem", "name":"periCORE-buildsystem" },
|
||||
// { "path": "/usr/src/", "name": "/usr/src" }
|
||||
]
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user