Skip to content

Commit 0781cdb

Browse files
committed
Examples
1 parent 27644e0 commit 0781cdb

File tree

6 files changed

+200
-1
lines changed

6 files changed

+200
-1
lines changed

.cargo/config.toml

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
[build]
2+
target = "riscv32imc-esp-espidf"
3+
#target = "xtensa-esp32-espidf"
4+
5+
[target.xtensa-esp32-espidf]
6+
linker = "ldproxy"
7+
rustflags = ["--cfg", "espidf_time64"]
8+
9+
[target.xtensa-esp32s2-espidf]
10+
linker = "ldproxy"
11+
rustflags = ["--cfg", "espidf_time64"]
12+
13+
[target.xtensa-esp32s3-espidf]
14+
linker = "ldproxy"
15+
rustflags = ["--cfg", "espidf_time64"]
16+
17+
[target.riscv32imc-esp-espidf]
18+
linker = "ldproxy"
19+
rustflags = ["--cfg", "espidf_time64"]
20+
21+
[target.riscv32imac-esp-espidf]
22+
linker = "ldproxy"
23+
rustflags = ["--cfg", "espidf_time64"]
24+
25+
[env]
26+
ESP_IDF_SDKCONFIG_DEFAULTS = ".github/configs/sdkconfig.defaults"
27+
ESP_IDF_VERSION = "v5.1.2"
28+
29+
[unstable]
30+
build-std = ["std", "panic_abort"]

.github/configs/sdkconfig.defaults

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# The examples require a larger than the default stack size for the main thread and the posix threads.
2+
CONFIG_ESP_MAIN_TASK_STACK_SIZE=20000
3+
CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=8192

.github/workflows/ci.yml

+14
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,17 @@ jobs:
6868
RUSTFLAGS: "${{ '--cfg espidf_time64' }}"
6969
ESP_IDF_VERSION: release/v5.1
7070
run: cargo clean; cargo build --target ${{ matrix.target }} -Zbuild-std=std,panic_abort -Zbuild-std-features=panic_immediate_abort
71+
72+
- name: Setup | ldproxy
73+
if: matrix.target == 'riscv32imc-esp-espidf'
74+
run: |
75+
curl -L https://github.com/esp-rs/embuild/releases/latest/download/ldproxy-x86_64-unknown-linux-gnu.zip -o $HOME/.cargo/bin/ldproxy.zip
76+
unzip "$HOME/.cargo/bin/ldproxy.zip" -d "$HOME/.cargo/bin/"
77+
chmod a+x $HOME/.cargo/bin/ldproxy
78+
79+
- name: Build | Examples
80+
env:
81+
RUSTFLAGS: "${{ '--cfg espidf_time64' }}"
82+
ESP_IDF_SDKCONFIG_DEFAULTS: "${{ github.workspace }}/.github/configs/sdkconfig.defaults"
83+
ESP_IDF_VERSION: release/v5.1
84+
run: cargo build --examples --target ${{ matrix.target }} -Zbuild-std=std,panic_abort -Zbuild-std-features=panic_immediate_abort

README.md

+19
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,25 @@ Follow the [Prerequisites](https://github.com/esp-rs/esp-idf-template#prerequisi
3131

3232
Read the [documentation here](BUILD-OPTIONS.md).
3333

34+
## Examples
35+
36+
The examples could be built and flashed conveniently with [`cargo-espflash`](https://github.com/esp-rs/espflash/). To run e.g. `std_basics` on an e.g. ESP32-C3:
37+
(Swap the Rust target and example name with the target corresponding for your ESP32 MCU and with the example you would like to build)
38+
39+
with `cargo-espflash` V2+:
40+
```sh
41+
$ cargo espflash flash --target riscv32imc-esp-espidf --example std_basics --monitor
42+
```
43+
44+
with older `cargo-espflash`:
45+
```sh
46+
$ cargo espflash --target riscv32imc-esp-espidf --example std_basics --monitor /dev/ttyUSB0
47+
```
48+
49+
## Setting up a "Hello, world!" binary crate with ESP IDF
50+
51+
Use the [esp-idf-template](https://github.com/esp-rs/esp-idf-template) project. Everything would be arranged and built for you automatically - no need to manually clone the ESP IDF repository.
52+
3453
## More information
3554

3655
For more information, check out:

build/build.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -202,14 +202,17 @@ fn main() -> anyhow::Result<()> {
202202
cargo::set_metadata(embuild::build::ENV_PATH_VAR, env_path);
203203
}
204204

205-
// In case other crates need to the ESP-IDF SDK
205+
// In case other crates need access to the ESP-IDF SDK
206206
cargo::set_metadata(
207207
embuild::build::ESP_IDF_PATH_VAR,
208208
build_output.esp_idf.try_to_str()?,
209209
);
210210

211211
if let Some(link_args) = build_output.link_args {
212212
link_args.propagate();
213+
214+
// Only necessary for building the examples
215+
link_args.output();
213216
}
214217

215218
Ok(())

examples/std_basics.rs

+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
use core::cell::RefCell;
2+
use core::ptr;
3+
use core::sync::atomic::{AtomicUsize, Ordering};
4+
use core::time::Duration;
5+
6+
use std::env;
7+
use std::io;
8+
use std::thread;
9+
10+
thread_local! {
11+
static TLS: RefCell<u32> = RefCell::new(13);
12+
}
13+
14+
fn main() -> Result<(), io::Error> {
15+
esp_idf_sys::link_patches();
16+
17+
// Get backtraces from anyhow; only works for Xtensa arch currently
18+
#[cfg(target_arch = "xtensa")]
19+
env::set_var("RUST_BACKTRACE", "1");
20+
21+
test_print();
22+
23+
test_atomics();
24+
25+
test_threads()?;
26+
27+
#[cfg(not(esp_idf_version = "4.3"))]
28+
test_fs()?;
29+
30+
loop {
31+
println!("Sleeping for 2 seconds...");
32+
thread::sleep(Duration::from_secs(2));
33+
}
34+
}
35+
36+
#[allow(clippy::vec_init_then_push)]
37+
fn test_print() {
38+
// Start simple
39+
println!("Hello from Rust!");
40+
41+
// Check collections
42+
let mut children = vec![];
43+
44+
children.push("foo");
45+
children.push("bar");
46+
println!("More complex print {children:?}");
47+
}
48+
49+
#[allow(deprecated)]
50+
fn test_atomics() {
51+
let a = AtomicUsize::new(0);
52+
let v1 = a.compare_and_swap(0, 1, Ordering::SeqCst);
53+
let v2 = a.swap(2, Ordering::SeqCst);
54+
55+
let (r1, r2) = unsafe {
56+
// don't optimize our atomics out
57+
let r1 = ptr::read_volatile(&v1);
58+
let r2 = ptr::read_volatile(&v2);
59+
60+
(r1, r2)
61+
};
62+
63+
println!("Result: {r1}, {r2}");
64+
}
65+
66+
fn test_threads() -> Result<(), io::Error> {
67+
let mut children = vec![];
68+
69+
println!("Rust main thread: {:?}", thread::current());
70+
71+
TLS.with(|tls| {
72+
println!("Main TLS before change: {}", *tls.borrow());
73+
});
74+
75+
TLS.with(|tls| *tls.borrow_mut() = 42);
76+
77+
TLS.with(|tls| {
78+
println!("Main TLS after change: {}", *tls.borrow());
79+
});
80+
81+
for i in 0..5 {
82+
// Spin up another thread
83+
children.push(thread::spawn(move || {
84+
println!("This is thread number {}, {:?}", i, thread::current());
85+
86+
TLS.with(|tls| *tls.borrow_mut() = i);
87+
88+
TLS.with(|tls| {
89+
println!("Inner TLS: {}", *tls.borrow());
90+
});
91+
}));
92+
}
93+
94+
println!("About to join the threads.");
95+
96+
for child in children {
97+
// Wait for the thread to finish. Returns a result.
98+
let _ = child.join();
99+
}
100+
101+
TLS.with(|tls| {
102+
println!("Main TLS after threads: {}", *tls.borrow());
103+
});
104+
105+
thread::sleep(Duration::from_secs(2));
106+
107+
println!("Joins were successful.");
108+
109+
Ok(())
110+
}
111+
112+
#[cfg(not(esp_idf_version = "4.3"))]
113+
fn test_fs() -> Result<(), io::Error> {
114+
use std::{fs, path::PathBuf};
115+
116+
assert_eq!(fs::canonicalize(PathBuf::from("."))?, PathBuf::from("/"));
117+
assert_eq!(
118+
fs::canonicalize(
119+
PathBuf::from("/")
120+
.join("foo")
121+
.join("bar")
122+
.join(".")
123+
.join("..")
124+
.join("baz")
125+
)?,
126+
PathBuf::from("/foo/baz")
127+
);
128+
129+
Ok(())
130+
}

0 commit comments

Comments
 (0)