···11+# will have compiled files and executables
22+debug/
33+target/
44+55+# Editor configuration
66+.vscode/
77+.zed/
88+.helix/
99+.nvim.lua
1010+1111+# These are backup files generated by rustfmt
1212+**/*.rs.bk
1313+1414+# MSVC Windows builds of rustc generate these, which store debugging information
1515+*.pdb
1616+1717+# RustRover
1818+# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
1919+# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
2020+# and can be added to the global gitignore or merged into this file. For a more nuclear
2121+# option (not recommended) you can uncomment the following to ignore the entire idea folder.
2222+#.idea/
2323+2424+2525+# Ignore .DS_Store file in mac
2626+**/.DS_Store
+50
Cargo.toml
···11+[package]
22+edition = "2024"
33+name = "pulp-os"
44+rust-version = "1.88"
55+version = "0.1.0"
66+77+[[bin]]
88+name = "pulp-os"
99+path = "./src/bin/main.rs"
1010+1111+[dependencies]
1212+esp-hal = { version = "~1.0", features = ["esp32c3", "log-04", "unstable"] }
1313+1414+esp-rtos = { version = "0.2.0", features = [
1515+ "embassy",
1616+ "esp-alloc",
1717+ "esp32c3",
1818+ "log-04",
1919+] }
2020+2121+esp-bootloader-esp-idf = { version = "0.4.0", features = ["esp32c3", "log-04"] }
2222+log = "0.4.27"
2323+2424+embassy-executor = { version = "0.9.1", features = ["log"] }
2525+embassy-time = { version = "0.5.0", features = ["log"] }
2626+esp-alloc = "0.9.0"
2727+esp-backtrace = { version = "0.18.1", features = [
2828+ "esp32c3",
2929+ "panic-handler",
3030+ "println",
3131+] }
3232+esp-println = { version = "0.16.1", features = ["esp32c3", "log-04"] }
3333+3434+critical-section = "1.2.0"
3535+static_cell = "2.1.1"
3636+3737+3838+[profile.dev]
3939+# Rust debug is too slow.
4040+# For debug builds always builds with some optimization
4141+opt-level = "s"
4242+4343+[profile.release]
4444+codegen-units = 1 # LLVM can perform better optimizations using a single thread
4545+debug = 2
4646+debug-assertions = false
4747+incremental = false
4848+lto = 'fat'
4949+opt-level = 's'
5050+overflow-checks = false
+70
build.rs
···11+fn main() {
22+ linker_be_nice();
33+ // make sure linkall.x is the last linker script (otherwise might cause problems with flip-link)
44+ println!("cargo:rustc-link-arg=-Tlinkall.x");
55+}
66+77+fn linker_be_nice() {
88+ let args: Vec<String> = std::env::args().collect();
99+ if args.len() > 1 {
1010+ let kind = &args[1];
1111+ let what = &args[2];
1212+1313+ match kind.as_str() {
1414+ "undefined-symbol" => match what.as_str() {
1515+ what if what.starts_with("_defmt_") => {
1616+ eprintln!();
1717+ eprintln!(
1818+ "💡 `defmt` not found - make sure `defmt.x` is added as a linker script and you have included `use defmt_rtt as _;`"
1919+ );
2020+ eprintln!();
2121+ }
2222+ "_stack_start" => {
2323+ eprintln!();
2424+ eprintln!("💡 Is the linker script `linkall.x` missing?");
2525+ eprintln!();
2626+ }
2727+ what if what.starts_with("esp_rtos_") => {
2828+ eprintln!();
2929+ eprintln!(
3030+ "💡 `esp-radio` has no scheduler enabled. Make sure you have initialized `esp-rtos` or provided an external scheduler."
3131+ );
3232+ eprintln!();
3333+ }
3434+ "embedded_test_linker_file_not_added_to_rustflags" => {
3535+ eprintln!();
3636+ eprintln!(
3737+ "💡 `embedded-test` not found - make sure `embedded-test.x` is added as a linker script for tests"
3838+ );
3939+ eprintln!();
4040+ }
4141+ "free"
4242+ | "malloc"
4343+ | "calloc"
4444+ | "get_free_internal_heap_size"
4545+ | "malloc_internal"
4646+ | "realloc_internal"
4747+ | "calloc_internal"
4848+ | "free_internal" => {
4949+ eprintln!();
5050+ eprintln!(
5151+ "💡 Did you forget the `esp-alloc` dependency or didn't enable the `compat` feature on it?"
5252+ );
5353+ eprintln!();
5454+ }
5555+ _ => (),
5656+ },
5757+ // we don't have anything helpful for "missing-lib" yet
5858+ _ => {
5959+ std::process::exit(1);
6060+ }
6161+ }
6262+6363+ std::process::exit(0);
6464+ }
6565+6666+ println!(
6767+ "cargo:rustc-link-arg=--error-handling-script={}",
6868+ std::env::current_exe().unwrap().display()
6969+ );
7070+}
···11+#![no_std]
22+#![no_main]
33+#![deny(
44+ clippy::mem_forget,
55+ reason = "mem::forget is generally not safe to do with esp_hal types, especially those \
66+ holding buffers for the duration of a data transfer."
77+)]
88+#![deny(clippy::large_stack_frames)]
99+1010+use embassy_executor::Spawner;
1111+use embassy_time::{Duration, Timer};
1212+use esp_backtrace as _;
1313+use esp_hal::clock::CpuClock;
1414+use esp_hal::timer::timg::TimerGroup;
1515+use log::info;
1616+1717+extern crate alloc;
1818+1919+// This creates a default app-descriptor required by the esp-idf bootloader.
2020+// For more information see: <https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/system/app_image_format.html#application-description>
2121+esp_bootloader_esp_idf::esp_app_desc!();
2222+2323+#[allow(
2424+ clippy::large_stack_frames,
2525+ reason = "it's not unusual to allocate larger buffers etc. in main"
2626+)]
2727+#[esp_rtos::main]
2828+async fn main(spawner: Spawner) -> ! {
2929+ // generator version: 1.2.0
3030+3131+ esp_println::logger::init_logger_from_env();
3232+3333+ let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
3434+ let peripherals = esp_hal::init(config);
3535+3636+ esp_alloc::heap_allocator!(#[esp_hal::ram(reclaimed)] size: 66320);
3737+3838+ let timg0 = TimerGroup::new(peripherals.TIMG0);
3939+ let sw_interrupt =
4040+ esp_hal::interrupt::software::SoftwareInterruptControl::new(peripherals.SW_INTERRUPT);
4141+ esp_rtos::start(timg0.timer0, sw_interrupt.software_interrupt0);
4242+4343+ info!("Embassy initialized!");
4444+4545+ // TODO: Spawn some tasks
4646+ let _ = spawner;
4747+4848+ loop {
4949+ info!("Hello world!");
5050+ Timer::after(Duration::from_secs(1)).await;
5151+ }
5252+5353+ // for inspiration have a look at the examples at https://github.com/esp-rs/esp-hal/tree/esp-hal-v1.0.0/examples
5454+}