diff --git a/.cargo/config.toml b/.cargo/config.toml index 292a084..d3444d9 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -3,8 +3,8 @@ runner = "espflash flash --monitor" [build] rustflags = [ - "-C", "link-arg=-Tlinkall.x", "-C", "link-arg=-nostartfiles", + "-C", "link-arg=-Wl,-Tlinkall.x", ] target = "xtensa-esp32s3-none-elf" diff --git a/Cargo.lock b/Cargo.lock index 4c427e1..f5934c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,24 @@ version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" +[[package]] +name = "atomic-polyfill" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ff7eb3f316534d83a8a2c3d1674ace8a5a71198eba31e2e2b597833f699b28" +dependencies = [ + "critical-section", +] + +[[package]] +name = "atomic-polyfill" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c314e70d181aa6053b26e3f7fbf86d1dfff84f816a6175b967666b3506ef7289" +dependencies = [ + "critical-section", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -38,6 +56,18 @@ dependencies = [ "serde", ] +[[package]] +name = "bitflags" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24a6904aef64d73cf10ab17ebace7befb918b82164785cb89907993be7f83813" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + [[package]] name = "cfg-if" version = "1.0.0" @@ -63,14 +93,38 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6548a0ad5d2549e111e1f6a11a6c2e2d00ce6a3dafe22948d67c2b443f775e52" +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +dependencies = [ + "darling_core 0.13.4", + "darling_macro 0.13.4", +] + [[package]] name = "darling" version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.14.4", + "darling_macro 0.14.4", +] + +[[package]] +name = "darling_core" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 1.0.109", ] [[package]] @@ -87,17 +141,69 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "darling_macro" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +dependencies = [ + "darling_core 0.13.4", + "quote", + "syn 1.0.109", +] + [[package]] name = "darling_macro" version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" dependencies = [ - "darling_core", + "darling_core 0.14.4", "quote", "syn 1.0.109", ] +[[package]] +name = "embassy-executor" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acebf176f4622fd87c7200b568ee32d5b435e3a4d58e39355ce0837b45139eca" +dependencies = [ + "atomic-polyfill 1.0.2", + "critical-section", + "embassy-macros", + "embassy-time", + "futures-util", + "static_cell", +] + +[[package]] +name = "embassy-macros" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acf2e5e33cc670fcdf208c0fdf8ee93493681658562fb1c50ba8ceb09591e0ff" +dependencies = [ + "darling 0.13.4", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "embassy-time" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd403e218939bba4a1fe4b58c6f81bf0818852bdd824147f95e6dc4ff4166ac4" +dependencies = [ + "atomic-polyfill 1.0.2", + "cfg-if", + "critical-section", + "embedded-hal 0.2.7", + "embedded-hal-async", + "futures-util", + "heapless", +] + [[package]] name = "embedded-dma" version = "0.2.0" @@ -117,6 +223,21 @@ dependencies = [ "void", ] +[[package]] +name = "embedded-hal" +version = "1.0.0-alpha.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f65c4d073f5d91c66e629b216818a4c9747eeda0debedf2deda9a0a947e4e93b" + +[[package]] +name = "embedded-hal-async" +version = "0.2.0-alpha.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8042370aa7af48de36d5312cda14c18ed8ca6b7ce64f5a07832fedc9dc83063f" +dependencies = [ + "embedded-hal 1.0.0-alpha.10", +] + [[package]] name = "enum-as-inner" version = "0.4.0" @@ -140,15 +261,17 @@ dependencies = [ [[package]] name = "esp-hal-common" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c37621a91b6465e4d13eb5596530e67304a0ef04d186d832012b2b9d7a3cd394" +checksum = "d077ffedaa2632004cf73e713438a18706d6d04d2fb0632ffe5a5f02bb9c17e0" dependencies = [ "basic-toml", + "bitflags", "cfg-if", "critical-section", + "embassy-time", "embedded-dma", - "embedded-hal", + "embedded-hal 0.2.7", "esp-hal-procmacros", "esp-synopsys-usb-otg", "esp32s3", @@ -170,7 +293,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14e4123798117de04121fcbd7991f0e2c3cfccf9a31017c94f611013be401080" dependencies = [ - "darling", + "darling 0.14.4", "proc-macro-crate", "proc-macro-error", "proc-macro2", @@ -194,16 +317,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0879f2f008c0213b1a5959345e54afcbf1490c1591f5145a5e65bdff371b65af" dependencies = [ "critical-section", - "embedded-hal", + "embedded-hal 0.2.7", "usb-device", "vcell", ] [[package]] name = "esp32s3" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c9ae8f9e711427c0c1e980e6d6a96ce553fcf057ab92a441e09b42cc08057f" +checksum = "1db7600b41665765aebe759042802f52a595fe96017ee49a8007f667887b4f7a" dependencies = [ "critical-section", "vcell", @@ -212,12 +335,13 @@ dependencies = [ [[package]] name = "esp32s3-hal" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3481c4d24517fd5d41093946ff1e7d0ae7dc1f6d46275d30d90d2a3a34adfcb8" +checksum = "552c3669d592a96479b2a526268e7b29421888defd08029c7bdc3c0c77cdee7c" dependencies = [ "bare-metal", - "embedded-hal", + "embassy-time", + "embedded-hal 0.2.7", "esp-hal-common", ] @@ -225,9 +349,12 @@ dependencies = [ name = "esp_miner" version = "0.1.0" dependencies = [ + "embassy-executor", + "embassy-time", "esp-backtrace", "esp-println", "esp32s3-hal", + "static_cell", ] [[package]] @@ -245,18 +372,64 @@ dependencies = [ "gcd", ] +[[package]] +name = "futures-core" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" + +[[package]] +name = "futures-task" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" + +[[package]] +name = "futures-util" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + [[package]] name = "gcd" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + [[package]] name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "heapless" +version = "0.7.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743" +dependencies = [ + "atomic-polyfill 0.1.11", + "hash32", + "rustc_version", + "spin", + "stable_deref_trait", +] + [[package]] name = "heck" version = "0.4.1" @@ -337,6 +510,18 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + [[package]] name = "proc-macro-crate" version = "1.3.1" @@ -412,6 +597,15 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + [[package]] name = "rustversion" version = "1.0.12" @@ -424,6 +618,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "semver" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" + [[package]] name = "serde" version = "1.0.160" @@ -459,6 +659,15 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "static_cell" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4c37c250d21f53fa7165e76e5401d7e6539c211a8d2cf449e3962956a5cc2ce" +dependencies = [ + "atomic-polyfill 1.0.2", +] + [[package]] name = "strsim" version = "0.10.0" diff --git a/Cargo.toml b/Cargo.toml index 708a68f..19899cf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,9 +3,34 @@ name = "esp_miner" version = "0.1.0" authors = ["Georges PALAUQUI "] edition = "2021" +rust-version = "1.65.0" +description = "Rust based firmware for BitaxeMax" +repository = "https://github.com/skot/ESP-Miner" license = "MIT OR Apache-2.0" +keywords = ["embedded", "embedded-hal", "esp", "esp32s3", "no-std"] +categories = ["embedded", "no-std"] + [dependencies] -hal = { package = "esp32s3-hal", version = "0.8.0" } -esp-backtrace = { version = "0.7.0", features = ["esp32s3", "panic-handler", "exception-handler", "print-uart"] } -esp-println = { version = "0.5.0", features = ["esp32s3"] } +embassy-time = { version = "0.1.1", package = "embassy-time", features = [ + "nightly", + "tick-hz-16_000_000", +] } +esp32s3-hal = { version = "0.9.0", package = "esp32s3-hal", features = [ + "embassy", + "embassy-time-systick", +] } +embassy-executor = { version = "0.2.0", features = [ + "nightly", + "integrated-timers", + "arch-xtensa", + "executor-thread", +] } +esp-backtrace = { version = "0.7.0", features = [ + "esp32s3", + "panic-handler", + "exception-handler", + "print-uart", +] } +esp-println = { version = "0.5.0", features = ["esp32s3"] } +static_cell = "1.0.0" diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..d5a42ec --- /dev/null +++ b/build.rs @@ -0,0 +1,68 @@ +use std::{env, fs::File, io::Write, path::PathBuf}; + +#[cfg(not(feature = "direct-boot"))] +fn main() { + // Put the linker script somewhere the linker can find it + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + File::create(out.join("memory.x")) + .unwrap() + .write_all(include_bytes!("ld/memory.x")) + .unwrap(); + + File::create(out.join("link-esp32s3.x")) + .unwrap() + .write_all(include_bytes!("ld/link-esp32s3.x")) + .unwrap(); + + File::create(out.join("linkall.x")) + .unwrap() + .write_all(include_bytes!("ld/linkall.x")) + .unwrap(); + + println!("cargo:rustc-link-search={}", out.display()); + + // Only re-run the build script when memory.x is changed, + // instead of when any part of the source code changes. + println!("cargo:rerun-if-changed=ld/memory.x"); + + add_defaults(); +} + +#[cfg(feature = "direct-boot")] +fn main() { + // Put the linker script somewhere the linker can find it + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + File::create(out.join("memory.x")) + .unwrap() + .write_all(include_bytes!("ld/db-memory.x")) + .unwrap(); + + File::create(out.join("link-esp32s3.x")) + .unwrap() + .write_all(include_bytes!("ld/db-esp32s3.x")) + .unwrap(); + + File::create(out.join("linkall.x")) + .unwrap() + .write_all(include_bytes!("ld/linkall.x")) + .unwrap(); + + println!("cargo:rustc-link-search={}", out.display()); + + // Only re-run the build script when memory.x is changed, + // instead of when any part of the source code changes. + println!("cargo:rerun-if-changed=ld/memory.x"); + + add_defaults(); +} + +fn add_defaults() { + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + + File::create(out.join("rom-functions.x")) + .unwrap() + .write_all(include_bytes!("ld/rom-functions.x")) + .unwrap(); + + println!("cargo:rustc-link-search={}", out.display()); +} diff --git a/ld/db-esp32s3.x b/ld/db-esp32s3.x new file mode 100644 index 0000000..38feb46 --- /dev/null +++ b/ld/db-esp32s3.x @@ -0,0 +1,311 @@ +/* before memory.x to allow override */ +ENTRY(Reset) + +INCLUDE memory.x + +/* map generic regions to output sections */ +INCLUDE "alias.x" + +_external_ram_start = ABSOLUTE(ORIGIN(psram_seg)); +_external_ram_end = ABSOLUTE(ORIGIN(psram_seg)+LENGTH(psram_seg)); + +_heap_end = ABSOLUTE(ORIGIN(dram_seg))+LENGTH(dram_seg)+LENGTH(reserved_for_boot_seg) - 2*STACK_SIZE; +_text_heap_end = ABSOLUTE(ORIGIN(iram_seg)+LENGTH(iram_seg)); +_external_heap_end = ABSOLUTE(ORIGIN(psram_seg)+LENGTH(psram_seg)); + +_stack_start_cpu1 = _heap_end; +_stack_end_cpu1 = _stack_start_cpu1 + STACK_SIZE; +_stack_start_cpu0 = _stack_end_cpu1; +_stack_end_cpu0 = _stack_start_cpu0 + STACK_SIZE; + +EXTERN(DefaultHandler); + +INCLUDE "device.x" + +/* after memory.x to allow override */ +PROVIDE(__pre_init = DefaultPreInit); +PROVIDE(__zero_bss = default_mem_hook); +PROVIDE(__init_data = default_mem_hook); + +/*INCLUDE exception.x*/ +/* exception vector for the ESP32, requiring high priority interrupts and register window support */ + +/* high level exception/interrupt routines, which can be override with Rust functions */ +PROVIDE(__exception = __default_exception); +PROVIDE(__user_exception = __default_user_exception); +PROVIDE(__double_exception = __default_double_exception); +PROVIDE(__level_1_interrupt = __default_interrupt); +PROVIDE(__level_2_interrupt = __default_interrupt); +PROVIDE(__level_3_interrupt = __default_interrupt); +PROVIDE(__level_4_interrupt = __default_interrupt); +PROVIDE(__level_5_interrupt = __default_interrupt); +PROVIDE(__level_6_interrupt = __default_interrupt); +PROVIDE(__level_7_interrupt = __default_interrupt); + +/* low level exception/interrupt, which must be overridden using naked functions */ +PROVIDE(__naked_user_exception = __default_naked_exception); +PROVIDE(__naked_kernel_exception = __default_naked_exception); +PROVIDE(__naked_double_exception = __default_naked_double_exception); +PROVIDE(__naked_level_2_interrupt = __default_naked_level_2_interrupt); +PROVIDE(__naked_level_3_interrupt = __default_naked_level_3_interrupt); +PROVIDE(__naked_level_4_interrupt = __default_naked_level_4_interrupt); +PROVIDE(__naked_level_5_interrupt = __default_naked_level_5_interrupt); +PROVIDE(__naked_level_6_interrupt = __default_naked_level_6_interrupt); +PROVIDE(__naked_level_7_interrupt = __default_naked_level_7_interrupt); + +/* needed to force inclusion of the vectors */ +EXTERN(__default_exception); +EXTERN(__default_double_exception); +EXTERN(__default_interrupt); + +/* high level CPU interrupts */ +PROVIDE(Timer0 = __default_user_exception); +PROVIDE(Timer1 = __default_user_exception); +PROVIDE(Timer2 = __default_user_exception); +PROVIDE(Timer3 = __default_user_exception); +PROVIDE(Profiling = __default_user_exception); +PROVIDE(NMI = __default_user_exception); +PROVIDE(Software0 = __default_user_exception); +PROVIDE(Software1 = __default_user_exception); + +/* low level exception/interrupt, which must be overridden using naked functions */ +EXTERN(__default_naked_exception); +EXTERN(__default_naked_double_exception); +EXTERN(__default_naked_level_2_interrupt); +EXTERN(__default_naked_level_3_interrupt); +EXTERN(__default_naked_level_4_interrupt); +EXTERN(__default_naked_level_5_interrupt); +EXTERN(__default_naked_level_6_interrupt); +EXTERN(__default_naked_level_7_interrupt); + +SECTIONS { + .pre_header (NOLOAD) : AT(0) + { + . = . + 0x400; + } + + .header ORIGIN(ROTEXT) : AT(0x400) + { + LONG(0xaedb041d) + LONG(0xaedb041d) + } + + .text ORIGIN(ROTEXT) + 0x408 : AT(0x408) + { + _stext = .; + . = ALIGN (4); + _text_start = ABSOLUTE(.); + . = ALIGN (4); + KEEP(*(.init)); + *(.literal .text .literal.* .text.*) + . = ALIGN (4); + _text_end = ABSOLUTE(.); + _etext = .; + } + _text_size = _etext - _stext; + + .rodata ORIGIN(RODATA) + 0x408 + _text_size : AT(_text_size + SIZEOF(.header) + SIZEOF(.pre_header)) + { + _rodata_start = ABSOLUTE(.); + . = ALIGN (4); + *(.rodata .rodata.*) + . = ALIGN (4); + _rodata_end = ABSOLUTE(.); + } + + .rwtext ORIGIN(RWTEXT) + 0x408 + _text_size + SIZEOF(.rodata) : + AT(_text_size + SIZEOF(.header) + SIZEOF(.pre_header) + SIZEOF(.rodata)) + { + _irwtext = ORIGIN(RODATA) + 0x408 + _text_size + SIZEOF(.rodata); + _srwtext = .; + + . = ALIGN (4); + + . = ALIGN(0x1000); + _init_start = ABSOLUTE(.); + KEEP(*(.WindowOverflow4.text)); + . = ALIGN(64); + KEEP(*(.WindowUnderflow4.text)); + . = ALIGN(64); + KEEP(*(.WindowOverflow8.text)); + . = ALIGN(64); + KEEP(*(.WindowUnderflow8.text)); + . = ALIGN(64); + KEEP(*(.WindowOverflow12.text)); + . = ALIGN(64); + KEEP(*(.WindowUnderflow12.text)); + . = ALIGN(64); + KEEP(*(.Level2InterruptVector.text)); + . = ALIGN(64); + KEEP(*(.Level3InterruptVector.text)); + . = ALIGN(64); + KEEP(*(.Level4InterruptVector.text)); + . = ALIGN(64); + KEEP(*(.Level5InterruptVector.text)); + . = ALIGN(64); + KEEP(*(.DebugExceptionVector.text)); + . = ALIGN(64); + KEEP(*(.NMIExceptionVector.text)); + . = ALIGN(64); + KEEP(*(.KernelExceptionVector.text)); + . = ALIGN(64); + KEEP(*(.UserExceptionVector.text)); + . = ALIGN(128); + KEEP(*(.DoubleExceptionVector.text)); + . = ALIGN(0x400); + + _init_end = ABSOLUTE(.); + + *(.rwtext.literal .rwtext .rwtext.literal.* .rwtext.*) + + . = ALIGN (4); + _erwtext = .; + } + + .data ORIGIN(RWDATA) : + AT(_text_size + SIZEOF(.header) + SIZEOF(.pre_header) + SIZEOF(.rodata) + SIZEOF(.rwtext)) + { + _data_start = ABSOLUTE(.); + . = ALIGN (4); + *(.data .data.*) + . = ALIGN (4); + _data_end = ABSOLUTE(.); + } + + + /* LMA of .data */ + _sidata = ORIGIN(RODATA) + _text_size + SIZEOF(.header) + SIZEOF(.pre_header) + SIZEOF(.rodata) + SIZEOF(.rwtext); + + .bss (NOLOAD) : ALIGN(4) + { + _bss_start = ABSOLUTE(.); + . = ALIGN (4); + *(.bss .bss.* COMMON) + . = ALIGN (4); + _bss_end = ABSOLUTE(.); + } > RWDATA + + .noinit (NOLOAD) : ALIGN(4) + { + . = ALIGN(4); + *(.noinit .noinit.*) + . = ALIGN (4); + } > RWDATA + + .rtc_fast.text ORIGIN(rtc_fast_iram_seg) : + AT(_text_size + SIZEOF(.header) + SIZEOF(.pre_header) + SIZEOF(.rodata) + SIZEOF(.rwtext) ) + { + . = ALIGN(4); + _rtc_fast_text_start = ABSOLUTE(.); + *(.rtc_fast.literal .rtc_fast.text .rtc_fast.literal.* .rtc_fast.text.*) + . = ALIGN(4); + _rtc_fast_text_end = ABSOLUTE(.); + } + _irtc_fast_text = ORIGIN(RODATA) + _text_size + SIZEOF(.header) + SIZEOF(.pre_header) + SIZEOF(.rodata) + SIZEOF(.rwtext); + + .rtc_fast.data ORIGIN(rtc_fast_dram_seg) + SIZEOF(.rtc_fast.text) : + AT(_text_size + SIZEOF(.header) + SIZEOF(.pre_header) + SIZEOF(.rodata) + SIZEOF(.rwtext) + SIZEOF(.rtc_fast.text) ) + { + . = ALIGN(4); + _rtc_fast_data_start = ABSOLUTE(.); + *(.rtc_fast.data .rtc_fast.data.*) + . = ALIGN(4); + _rtc_fast_data_end = ABSOLUTE(.); + } + _irtc_fast_data = ORIGIN(RODATA) + _text_size + SIZEOF(.header) + SIZEOF(.pre_header) + SIZEOF(.rodata) + SIZEOF(.rwtext) + SIZEOF(.rtc_fast.text); + + .rtc_fast.bss ORIGIN(rtc_fast_dram_seg) + SIZEOF(.rtc_fast.text) + SIZEOF(.rtc_fast.data) (NOLOAD) : + AT(_text_size + SIZEOF(.header) + SIZEOF(.pre_header) + SIZEOF(.rodata) + + SIZEOF(.rwtext) + SIZEOF(.rtc_fast.text) + SIZEOF(.rtc_fast.data)) + { + . = ALIGN(4); + _rtc_fast_bss_start = ABSOLUTE(.); + *(.rtc_fast.bss .rtc_fast.bss.*) + . = ALIGN (4); + _rtc_fast_bss_end = ABSOLUTE(.); + } + + .rtc_fast.noinit ORIGIN(rtc_fast_dram_seg) + SIZEOF(.rtc_fast.text) + SIZEOF(.rtc_fast.data) + SIZEOF(.rtc_fast.bss) (NOLOAD) : + { + . = ALIGN(4); + *(.rtc_fast.noinit .rtc_fast.noinit.*) + . = ALIGN (4); + } + + .rtc_slow.text ORIGIN(rtc_slow_seg) : + AT(_text_size + SIZEOF(.header) + SIZEOF(.pre_header) + SIZEOF(.rodata) + SIZEOF(.rwtext) + + SIZEOF(.rtc_fast.text) + SIZEOF(.rtc_fast.data) + SIZEOF(.rtc_fast.bss)) + { + . = ALIGN(4); + _rtc_slow_text_start = ABSOLUTE(.); + *(.rtc_slow.literal .rtc_slow.text .rtc_slow.literal.* .rtc_slow.text.*) + . = ALIGN(4); + _rtc_slow_text_end = ABSOLUTE(.); + } + _irtc_slow_text = ORIGIN(RODATA) + _text_size + SIZEOF(.header) + SIZEOF(.pre_header) + SIZEOF(.rodata) + SIZEOF(.rwtext) + + SIZEOF(.rtc_fast.text) + SIZEOF(.rtc_fast.data) + SIZEOF(.rtc_fast.bss); + + .rtc_slow.data ORIGIN(rtc_slow_seg) + SIZEOF(.rtc_slow.text) : + AT(_text_size + SIZEOF(.header) + SIZEOF(.pre_header) + SIZEOF(.rodata) + SIZEOF(.rwtext) + + SIZEOF(.rtc_fast.text) + SIZEOF(.rtc_fast.data) + SIZEOF(.rtc_fast.bss) + SIZEOF(.rtc_slow.text)) + { + . = ALIGN(4); + _rtc_slow_data_start = ABSOLUTE(.); + *(.rtc_slow.data .rtc_slow.data.*) + . = ALIGN(4); + _rtc_slow_data_end = ABSOLUTE(.); + } + _irtc_slow_data = ORIGIN(RODATA) + _text_size + SIZEOF(.header) + SIZEOF(.pre_header) + SIZEOF(.rodata) + SIZEOF(.rwtext) + + SIZEOF(.rtc_fast.text) + SIZEOF(.rtc_fast.data) + SIZEOF(.rtc_fast.bss) + SIZEOF(.rtc_slow.text); + + .rtc_slow.bss ORIGIN(rtc_slow_seg) + SIZEOF(.rtc_slow.text) + SIZEOF(.rtc_slow.data) (NOLOAD) : + AT(_text_size + SIZEOF(.header) + SIZEOF(.pre_header) + SIZEOF(.rodata) + SIZEOF(.rwtext) + + SIZEOF(.rtc_fast.text) + SIZEOF(.rtc_fast.data) + SIZEOF(.rtc_fast.bss) + SIZEOF(.rtc_slow.text) + SIZEOF(.rtc_slow.data)) + { + . = ALIGN(4); + _rtc_slow_bss_start = ABSOLUTE(.); + *(.rtc_slow.bss .rtc_slow.bss.*) + . = ALIGN (4); + _rtc_slow_bss_end = ABSOLUTE(.); + } + + .rtc_slow.noinit ORIGIN(rtc_slow_seg) + SIZEOF(.rtc_slow.text) + SIZEOF(.rtc_slow.data) + SIZEOF(.rtc_slow.bss) (NOLOAD) : + { + . = ALIGN(4); + *(.rtc_slow.noinit .rtc_slow.noinit.*) + . = ALIGN (4); + } + + .external.data : + { + _external_data_start = ABSOLUTE(.); + . = ALIGN(4); + *(.external.data .external.data.*) + . = ALIGN (4); + _external_data_end = ABSOLUTE(.); + } > psram_seg AT > RODATA + + .external.bss (NOLOAD) : + { + _external_bss_start = ABSOLUTE(.); + . = ALIGN(4); + *(.external.bss .external.bss.*) + . = ALIGN (4); + _external_bss_end = ABSOLUTE(.); + } > psram_seg + + .external.noinit (NOLOAD) : + { + . = ALIGN(4); + *(.external.noinit .external.noinit.*) + . = ALIGN (4); + } > psram_seg + + /* must be last segment using psram_seg */ + .external_heap_start (NOLOAD) : + { + . = ALIGN (4); + _external_heap_start = ABSOLUTE(.); + . = ALIGN (4); + } > psram_seg +} diff --git a/ld/db-memory.x b/ld/db-memory.x new file mode 100644 index 0000000..9d0099e --- /dev/null +++ b/ld/db-memory.x @@ -0,0 +1,44 @@ +/* override entry point */ +ENTRY(ESP32Reset) + +/* reserved at the start of DRAM */ +RESERVE_DRAM = 0x8000; + +/* reserved at the start of the RTC memories for use by the ULP processor */ +RESERVE_RTC_FAST = 0; +RESERVE_RTC_SLOW = 0; + +/* define stack size for both cores */ +STACK_SIZE = 8k; + +/* Specify main memory areas */ +MEMORY +{ + iram_seg ( RX ) : ORIGIN = 0x40370400 + RESERVE_DRAM, len = 328k - 0x400 + + dram_seg ( RW ) : ORIGIN = 0x3FC80000 + RESERVE_DRAM, len = 328k - RESERVE_DRAM + reserved_for_boot_seg : ORIGIN = 0x3FFDC200, len = 144k /* ???? SRAM1; reserved for static ROM usage; can be used for heap */ + + /* external flash + The 0x20 offset is a convenience for the app binary image generation. + Flash cache has 64KB pages. The .bin file which is flashed to the chip + has a 0x18 byte file header, and each segment has a 0x08 byte segment + header. Setting this offset makes it simple to meet the flash cache MMU's + constraint that (paddr % 64KB == vaddr % 64KB).) + */ + irom_seg ( RX ) : ORIGIN = 0x42000000, len = 4M + drom_seg ( R ) : ORIGIN = 0x3C000000, len = 4M + + + /* RTC fast memory (executable). Persists over deep sleep. Only for core 0 (PRO_CPU) */ + rtc_fast_iram_seg(RWX) : ORIGIN = 0x600fe000, len = 8k + + /* RTC fast memory (same block as above), viewed from data bus. Only for core 0 (PRO_CPU) */ + rtc_fast_dram_seg(RW) : ORIGIN = 0x600fe000 + RESERVE_RTC_FAST, len = 8k - RESERVE_RTC_FAST + + /* RTC slow memory (data accessible). Persists over deep sleep. */ + rtc_slow_seg(RW) : ORIGIN = 0x50000000 + RESERVE_RTC_SLOW, len = 8k - RESERVE_RTC_SLOW + + /* external memory, including data and text */ + psram_seg(RWX) : ORIGIN = 0x3F500000, len = 0xA80000 /* ??? */ +} diff --git a/ld/link-esp32s3.x b/ld/link-esp32s3.x new file mode 100644 index 0000000..6dc4419 --- /dev/null +++ b/ld/link-esp32s3.x @@ -0,0 +1,63 @@ +/* before memory.x to allow override */ +ENTRY(ESP32Reset) + +INCLUDE memory.x + +/* after memory.x to allow override */ +PROVIDE(__pre_init = DefaultPreInit); +PROVIDE(__zero_bss = default_mem_hook); +PROVIDE(__init_data = default_mem_hook); + +INCLUDE exception.x + +/* map generic regions to output sections */ +INCLUDE "alias.x" + +/* ESP32S3 fixups */ +SECTIONS { + .rwdata_dummy (NOLOAD) : + { + /* This dummy section represents the .rwtext section but in RWDATA. + * Thus, it must have its alignment and (at least) its size. + */ + + /* Start at the same alignment constraint than .flash.text */ + + . = ALIGN(ALIGNOF(.rwtext)); + + /* Create an empty gap as big as .rwtext section - 32k (SRAM0) + * because SRAM1 is available on the data bus and instruction bus + */ + . = MAX(SIZEOF(.rwtext) + SIZEOF(.rwtext.wifi) + RESERVE_ICACHE + VECTORS_SIZE, 32k) - 32k; + + /* Prepare the alignment of the section above. */ + . = ALIGN(4); + _rwdata_reserved_start = .; + } > RWDATA +} +INSERT BEFORE .data; + +INCLUDE "fixups/rodata_dummy.x" +INCLUDE "fixups/rtc_fast_rwdata_dummy.x" +/* End of ESP32S3 fixups */ + +/* Shared sections - ordering matters */ +INCLUDE "text.x" +INCLUDE "rodata.x" +INCLUDE "rwtext.x" +INCLUDE "rwdata.x" +INCLUDE "rtc_fast.x" +INCLUDE "rtc_slow.x" +INCLUDE "external.x" +/* End of Shared sections */ + +_heap_end = ABSOLUTE(ORIGIN(dram_seg))+LENGTH(dram_seg) - 2*STACK_SIZE; + +_stack_start_cpu1 = _heap_end; +_stack_end_cpu1 = _stack_start_cpu1 + STACK_SIZE; +_stack_start_cpu0 = _stack_end_cpu1; +_stack_end_cpu0 = _stack_start_cpu0 + STACK_SIZE; + +EXTERN(DefaultHandler); + +INCLUDE "device.x" diff --git a/ld/linkall.x b/ld/linkall.x new file mode 100644 index 0000000..48a6ef2 --- /dev/null +++ b/ld/linkall.x @@ -0,0 +1,3 @@ +INCLUDE "link-esp32s3.x" +INCLUDE "hal-defaults.x" +INCLUDE "rom-functions.x" diff --git a/ld/memory.x b/ld/memory.x new file mode 100644 index 0000000..c60a165 --- /dev/null +++ b/ld/memory.x @@ -0,0 +1,56 @@ +/* override entry point */ +ENTRY(ESP32Reset) + +/* reserved for ICACHE */ +RESERVE_ICACHE = 0x8000; + +/* reserved at the start of the RTC memories for use by the ULP processor */ +RESERVE_RTC_FAST = 0; +RESERVE_RTC_SLOW = 0; + +/* define stack size for both cores */ +STACK_SIZE = 8k; + +VECTORS_SIZE = 0x400; + +/* Specify main memory areas + + 40370000 <- IRAM/Icache -> 40378000 <- D/IRAM (I) -> 403E0000 + 3FC88000 <- D/IRAM (D) -> 3FCF0000 <- DRAM/DCache -> 3FD00000 + + Startup code uses the IRAM from 0x403B9000 to 0x403E0000, which is not available for static + memory, but can only be used after app starts. + + D cache use the memory from high address, so when it's configured to 16K/32K, the region + 0x3FCF0000 ~ (3FD00000 - DATA_CACHE_SIZE) should be available. This region is not used as + static memory, leaving to the heap. +*/ +MEMORY +{ + vectors_seg ( RX ) : ORIGIN = 0x40370000 + RESERVE_ICACHE, len = VECTORS_SIZE + iram_seg ( RX ) : ORIGIN = 0x40370000 + RESERVE_ICACHE + VECTORS_SIZE, len = 328k - VECTORS_SIZE - RESERVE_ICACHE + dram_seg ( RW ) : ORIGIN = 0x3FC88000 , len = 345856 + + /* external flash + The 0x20 offset is a convenience for the app binary image generation. + Flash cache has 64KB pages. The .bin file which is flashed to the chip + has a 0x18 byte file header, and each segment has a 0x08 byte segment + header. Setting this offset makes it simple to meet the flash cache MMU's + constraint that (paddr % 64KB == vaddr % 64KB).) + */ + irom_seg ( RX ) : ORIGIN = 0x42000020, len = 4M - 0x20 + drom_seg ( R ) : ORIGIN = 0x3C000020, len = 4M - 0x20 + + + /* RTC fast memory (executable). Persists over deep sleep. Only for core 0 (PRO_CPU) */ + rtc_fast_iram_seg(RWX) : ORIGIN = 0x600fe000, len = 8k + + /* RTC fast memory (same block as above), viewed from data bus. Only for core 0 (PRO_CPU) */ + rtc_fast_dram_seg(RW) : ORIGIN = 0x600fe000 + RESERVE_RTC_FAST, len = 8k - RESERVE_RTC_FAST + + /* RTC slow memory (data accessible). Persists over deep sleep. */ + rtc_slow_seg(RW) : ORIGIN = 0x50000000 + RESERVE_RTC_SLOW, len = 8k - RESERVE_RTC_SLOW + + /* external memory, including data and text */ + psram_seg(RWX) : ORIGIN = 0x3F500000, len = 0xA80000 /* ??? */ +} diff --git a/ld/rom-functions.x b/ld/rom-functions.x new file mode 100644 index 0000000..c4d9d6a --- /dev/null +++ b/ld/rom-functions.x @@ -0,0 +1,8 @@ +PROVIDE(ets_delay_us = 0x40000600); +PROVIDE(ets_update_cpu_frequency_rom = 0x40043164); +PROVIDE(rom_i2c_writeReg = 0x40005d60); +PROVIDE(rom_i2c_writeReg_Mask = 0x40005d6c); +PROVIDE(rtc_get_reset_reason = 0x4000057c); +PROVIDE(rom_config_instruction_cache_mode = 0x40001a1c); +PROVIDE(software_reset = 0x400006d8); +PROVIDE(software_reset_cpu = 0x400006e4); diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 90aabae..de5cd80 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] channel = "esp" components = ["rustfmt", "rustc-dev"] -targets = ["xtensa-esp32-none-elf"] +targets = ["xtensa-esp32s3-none-elf"] diff --git a/src/main.rs b/src/main.rs index dc785f4..ae03210 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,25 +1,74 @@ #![no_std] #![no_main] +#![feature(type_alias_impl_trait)] +use embassy_executor::Executor; +use embassy_time::{Duration, Timer}; +use esp32s3_hal::{ + clock::ClockControl, embassy, peripherals::Peripherals, prelude::*, timer::TimerGroup, Rtc, +}; use esp_backtrace as _; use esp_println::println; -use hal::{clock::ClockControl, peripherals::Peripherals, prelude::*, timer::TimerGroup, Rtc}; +use static_cell::StaticCell; + +#[embassy_executor::task] +async fn run1() { + loop { + esp_println::println!("Hello world from embassy using esp-hal-async!"); + Timer::after(Duration::from_millis(1_000)).await; + } +} + +#[embassy_executor::task] +async fn run2() { + loop { + esp_println::println!("Bing!"); + Timer::after(Duration::from_millis(5_000)).await; + } +} + +static EXECUTOR: StaticCell = StaticCell::new(); + #[entry] fn main() -> ! { + println!("Init!"); let peripherals = Peripherals::take(); - let system = peripherals.SYSTEM.split(); + let mut system = peripherals.SYSTEM.split(); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); // Disable the RTC and TIMG watchdog timers let mut rtc = Rtc::new(peripherals.RTC_CNTL); - let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let timer_group0 = TimerGroup::new( + peripherals.TIMG0, + &clocks, + &mut system.peripheral_clock_control, + ); let mut wdt0 = timer_group0.wdt; - let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let timer_group1 = TimerGroup::new( + peripherals.TIMG1, + &clocks, + &mut system.peripheral_clock_control, + ); let mut wdt1 = timer_group1.wdt; + + // Disable watchdog timers + rtc.swd.disable(); rtc.rwdt.disable(); wdt0.disable(); wdt1.disable(); - println!("Hello world!"); - loop {} + // #[cfg(feature = "embassy-time-systick")] + embassy::init( + &clocks, + esp32s3_hal::systimer::SystemTimer::new(peripherals.SYSTIMER), + ); + + #[cfg(feature = "embassy-time-timg0")] + embassy::init(&clocks, timer_group0.timer0); + + let executor = EXECUTOR.init(Executor::new()); + executor.run(|spawner| { + spawner.spawn(run1()).ok(); + spawner.spawn(run2()).ok(); + }); }