├── example.elf ├── rust-toolchain.toml ├── .vscode └── settings.json ├── .gitignore ├── src ├── chip │ ├── mod.rs │ ├── esp32c2.rs │ ├── esp32c3.rs │ ├── esp32s3.rs │ ├── esp32c6.rs │ ├── esp32h2.rs │ ├── esp32.rs │ └── esp32s2.rs ├── image.rs └── main.rs ├── README.md ├── Cargo.toml ├── .cargo └── config.toml ├── ld ├── link_esp32c2.x ├── link_esp32c6.x ├── link_esp32h2.x ├── link_esp32c3.x ├── link_esp32s2.x ├── link_esp32.x └── link_esp32s3.x └── Cargo.lock /example.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjoernQ/esp32c3-bootloader-experiment/main/example.elf -------------------------------------------------------------------------------- /rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | # use nightly to compile core etc. with more optimizations 3 | channel = "nightly" 4 | components = ["rust-src"] 5 | targets = ["riscv32imc-unknown-none-elf"] 6 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "rust-analyzer.cargo.target": "riscv32imc-unknown-none-elf", 3 | "rust-analyzer.cargo.features": [ 4 | "esp32c3" 5 | ], 6 | "rust-analyzer.cargo.buildScripts.useRustcWrapper": true, 7 | "rust-analyzer.cargo.allTargets": false, 8 | "rust-analyzer.check.allTargets": false, 9 | "rust-analyzer.showUnlinkedFileNotification": false, 10 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | debug/ 4 | target/ 5 | 6 | # These are backup files generated by rustfmt 7 | **/*.rs.bk 8 | 9 | # MSVC Windows builds of rustc generate these, which store debugging information 10 | *.pdb 11 | 12 | # RustRover 13 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 14 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 15 | # and can be added to the global gitignore or merged into this file. For a more nuclear 16 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 17 | #.idea/ 18 | 19 | justboot.bin* 20 | -------------------------------------------------------------------------------- /src/chip/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "esp32c2")] 2 | pub mod esp32c2; 3 | 4 | #[cfg(feature = "esp32c2")] 5 | pub use esp32c2::*; 6 | 7 | #[cfg(feature = "esp32c3")] 8 | pub mod esp32c3; 9 | 10 | #[cfg(feature = "esp32c3")] 11 | pub use esp32c3::*; 12 | 13 | #[cfg(feature = "esp32c6")] 14 | pub mod esp32c6; 15 | 16 | #[cfg(feature = "esp32c6")] 17 | pub use esp32c6::*; 18 | 19 | #[cfg(feature = "esp32h2")] 20 | pub mod esp32h2; 21 | 22 | #[cfg(feature = "esp32h2")] 23 | pub use esp32h2::*; 24 | 25 | #[cfg(feature = "esp32")] 26 | pub mod esp32; 27 | 28 | #[cfg(feature = "esp32")] 29 | pub use esp32::*; 30 | 31 | #[cfg(feature = "esp32s2")] 32 | pub mod esp32s2; 33 | 34 | #[cfg(feature = "esp32s2")] 35 | pub use esp32s2::*; 36 | 37 | #[cfg(feature = "esp32s3")] 38 | pub mod esp32s3; 39 | 40 | #[cfg(feature = "esp32s3")] 41 | pub use esp32s3::*; 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ESP32-C3 Bootloader Experiment 2 | 3 | Just a bare-minimum bootloader. Things are mostly hardcoded. 4 | 5 | ## Build 6 | 7 | cargo xbuild-esp32XXX --release 8 | esptool --chip=esp32XXX elf2image target\riscv32imc-unknown-none-elf\release\justboot --output justboot.bin --flash_mode dio 9 | 10 | ## Status 11 | 12 | Just for booting esp-hal baremetal. esp-idf images won't work (for now). 13 | 14 | - ESP32-C3 15 | - works fine so far 16 | 17 | - added ESP32-C2 18 | - works so far for, wifi etc. only on chips with a 40MHz xtal 19 | 20 | - added ESP32-C6 21 | - works fine so far 22 | 23 | - added ESP32-H2 24 | - works fine so far 25 | 26 | - ESP32-S3 27 | - works fine so far 28 | 29 | - ESP32-S2 30 | - something simple works, clocks are off after trying to change CPU clock, clocks (e.g. timers) slower than assumed 31 | 32 | - ESP32 33 | - like ESP32-S2 34 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | edition = "2021" 3 | name = "justboot" 4 | version = "0.1.0" 5 | 6 | [dependencies] 7 | esp-hal = { version = "0.23.1", features = ["unstable"] } 8 | esp-println = { version = "0.13.0" } 9 | 10 | [features] 11 | esp32c2 = [ "esp-hal/esp32c2", "esp-println/esp32c2" ] 12 | esp32c3 = [ "esp-hal/esp32c3", "esp-println/esp32c3" ] 13 | esp32c6 = [ "esp-hal/esp32c6", "esp-println/esp32c6" ] 14 | esp32h2 = [ "esp-hal/esp32h2", "esp-println/esp32h2" ] 15 | esp32 = [ "esp-hal/esp32", "esp-println/esp32" ] 16 | esp32s2 = [ "esp-hal/esp32s2", "esp-println/esp32s2" ] 17 | esp32s3 = [ "esp-hal/esp32s3", "esp-println/esp32s3" ] 18 | 19 | [profile.dev] 20 | # Rust debug is too slow. 21 | # For debug builds always builds with some optimization 22 | opt-level = "s" 23 | 24 | [profile.release] 25 | codegen-units = 1 # LLVM can perform better optimizations using a single thread 26 | debug = 2 27 | debug-assertions = false 28 | incremental = false 29 | lto = 'fat' 30 | opt-level = 's' 31 | overflow-checks = false 32 | panic = "abort" 33 | -------------------------------------------------------------------------------- /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [alias] 2 | xbuild-esp32c2 = "build --features=esp32c2 --target=riscv32imc-unknown-none-elf" 3 | xbuild-esp32c3 = "build --features=esp32c3 --target=riscv32imc-unknown-none-elf" 4 | xbuild-esp32c6 = "build --features=esp32c6 --target=riscv32imac-unknown-none-elf" 5 | xbuild-esp32h2 = "build --features=esp32h2 --target=riscv32imac-unknown-none-elf" 6 | xbuild-esp32s3 = "build --features=esp32s3 --target=xtensa-esp32s3-none-elf" 7 | xbuild-esp32s2 = "build --features=esp32s2 --target=xtensa-esp32s2-none-elf" 8 | xbuild-esp32 = "build --features=esp32 --target=xtensa-esp32-none-elf" 9 | 10 | [env] 11 | ESP_LOG="INFO" 12 | 13 | [target.riscv32imc-unknown-none-elf] 14 | runner = "espflash flash --monitor" 15 | 16 | rustflags = [ 17 | ] 18 | 19 | [target.riscv32imac-unknown-none-elf] 20 | rustflags = [ 21 | ] 22 | 23 | [target.xtensa-esp32s3-none-elf] 24 | rustflags = [ 25 | "-C", "link-arg=-nostartfiles", 26 | # "-C", "link-arg=-Wl,-Map=output.map", 27 | ] 28 | 29 | [target.xtensa-esp32s2-none-elf] 30 | rustflags = [ 31 | "-C", "link-arg=-nostartfiles", 32 | # "-C", "link-arg=-Wl,-Map=output.map", 33 | ] 34 | [target.xtensa-esp32-none-elf] 35 | rustflags = [ 36 | "-C", "link-arg=-nostartfiles", 37 | # "-C", "link-arg=-Wl,-Map=output.map", 38 | ] 39 | 40 | [unstable] 41 | build-std = ["core", "compiler_builtins", "panic_abort"] -------------------------------------------------------------------------------- /src/image.rs: -------------------------------------------------------------------------------- 1 | /// Main header of binary image 2 | #[repr(C, packed)] 3 | pub struct EspImageHeader { 4 | pub magic: u8, // Magic word ESP_IMAGE_HEADER_MAGIC 5 | pub segment_count: u8, // Count of memory segments 6 | pub spi_mode: u8, // flash read mode (esp_image_spi_mode_t as u8) 7 | pub spi_speed_and_size: u8, // flash frequency (esp_image_spi_freq_t as u8) and flash chip size (esp_image_flash_size_t as u8) 8 | pub entry_addr: u32, // Entry address 9 | pub wp_pin: u8, // WP pin when SPI pins set via efuse (read by ROM bootloader, 10 | // the IDF bootloader uses software to configure the WP 11 | // pin and sets this field to 0xEE=disabled) 12 | pub spi_pin_drv: [u8; 3], // Drive settings for the SPI flash pins (read by ROM bootloader) 13 | pub chip_id: EspChipId, // Chip identification number 14 | pub min_chip_rev: u8, // Minimal chip revision supported by image 15 | // After the Major and Minor revision eFuses were introduced into the chips, this field is no longer used. 16 | // But for compatibility reasons, we keep this field and the data in it. 17 | // Use min_chip_rev_full instead. 18 | // The software interprets this as a Major version for most of the chips and as a Minor version for the ESP32-C3. 19 | pub min_chip_rev_full: u16, // Minimal chip revision supported by image, in format: major * 100 + minor 20 | pub max_chip_rev_full: u16, // Maximal chip revision supported by image, in format: major * 100 + minor 21 | pub reserved: [u8; 4], // Reserved bytes in additional header space, currently unused 22 | pub hash_appended: u8, // If 1, a SHA256 digest "simple hash" (of the entire image) is appended after the checksum. 23 | // Included in image length. This digest 24 | // is separate to secure boot and only used for detecting corruption. 25 | // For secure boot signed images, the signature 26 | // is appended after this (and the simple hash is included in the signed data). 27 | } 28 | 29 | /// Header of binary image segment 30 | #[repr(C, packed)] 31 | pub struct EspImageSegmentHeader { 32 | pub load_addr: u32, // Address of segment 33 | pub data_len: u32, // Length of data 34 | } 35 | 36 | /// ESP chip ID 37 | #[repr(u16)] 38 | #[allow(unused)] 39 | pub enum EspChipId { 40 | Esp32 = 0x0000, // chip ID: ESP32 41 | Esp32S2 = 0x0002, // chip ID: ESP32-S2 42 | Esp32C3 = 0x0005, // chip ID: ESP32-C3 43 | Esp32S3 = 0x0009, // chip ID: ESP32-S3 44 | Esp32C2 = 0x000C, // chip ID: ESP32-C2 45 | Esp32C6 = 0x000D, // chip ID: ESP32-C6 46 | Esp32H2 = 0x0010, // chip ID: ESP32-H2 47 | Esp32P4 = 0x0012, // chip ID: ESP32-P4 48 | Esp32C5Beta3 = 0x0011, // chip ID: ESP32-C5 beta3 (MPW) 49 | Esp32C5Mp = 0x0017, // chip ID: ESP32-C5 MP 50 | Invalid = 0xFFFF, // Invalid chip ID (we defined it to make sure the esp_chip_id_t is 2 bytes size) 51 | } 52 | -------------------------------------------------------------------------------- /src/chip/esp32c2.rs: -------------------------------------------------------------------------------- 1 | use esp_println::println; 2 | 3 | pub const MMU_ACCESS_FLASH: u32 = 0; 4 | 5 | pub fn init_flash() { 6 | let spiconfig = 0; 7 | 8 | pub const FLASH_SIZE: u32 = 0x1000000; 9 | pub const FLASH_STATUS_MASK: u32 = 0xFFFF; 10 | pub const FLASH_SECTOR_SIZE: u32 = 4096; 11 | pub const PAGE_SIZE: u32 = 0x4000; 12 | pub const FLASH_BLOCK_SIZE: u32 = 65536; 13 | 14 | // init flash 15 | let config_result = unsafe { 16 | esp_rom_spiflash_config_param( 17 | 0, 18 | FLASH_SIZE, // total_size 19 | FLASH_BLOCK_SIZE, // block_size 20 | FLASH_SECTOR_SIZE, // sector_size 21 | PAGE_SIZE, // page_size 22 | FLASH_STATUS_MASK, // status_mask 23 | ) 24 | }; 25 | 26 | if config_result == 0 { 27 | unsafe { esp_rom_spiflash_attach(spiconfig, false) }; 28 | } else { 29 | println!("Nope 💀"); 30 | } 31 | } 32 | 33 | pub fn init_mmu() -> u32 { 34 | // init mmu 35 | unsafe { 36 | Cache_MMU_Init(); 37 | Cache_Enable_ICache(1); 38 | 39 | let autoload = Cache_Suspend_ICache(); 40 | Cache_Invalidate_ICache_All(); 41 | 42 | autoload 43 | } 44 | } 45 | 46 | pub fn resume_mmu(autoload: u32) { 47 | unsafe { 48 | Cache_Resume_ICache(autoload); 49 | } 50 | } 51 | 52 | pub fn is_drom(addr: u32) -> bool { 53 | addr >= 0x3C00_0000 && addr <= 0x3C3F_FFFF 54 | } 55 | 56 | pub fn is_ram(addr: usize) -> bool { 57 | !(addr >= 0x3C00_0000 && addr <= 0x3C3F_FFFF || addr >= 0x4200_0000 && addr <= 0x423F_FFFF) 58 | } 59 | 60 | pub fn read_flash(flash_addr: u32, len: usize, data: &mut [u8]) { 61 | // read from flash 62 | if unsafe { esp_rom_spiflash_read(flash_addr, data.as_mut_ptr(), len as u32) } != 0 { 63 | println!("F"); 64 | } 65 | } 66 | 67 | pub fn dbus_mmu_set(vaddr: u32, paddr: u32, psize: u32, num: u32, fixed: u32) -> i32 { 68 | unsafe { Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, vaddr, paddr, psize, num, fixed) } 69 | } 70 | 71 | pub fn ibus_mmu_set(vaddr: u32, paddr: u32, psize: u32, num: u32, fixed: u32) -> i32 { 72 | unsafe { Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, vaddr, paddr, psize, num, fixed) } 73 | } 74 | 75 | extern "C" { 76 | // flash functions 77 | pub fn esp_rom_spiflash_attach(config: u32, legacy: bool); 78 | 79 | pub fn esp_rom_spiflash_config_param( 80 | device_id: u32, 81 | chip_size: u32, 82 | block_size: u32, 83 | sector_size: u32, 84 | page_size: u32, 85 | status_mask: u32, 86 | ) -> u32; 87 | 88 | pub fn esp_rom_spiflash_read(src_addr: u32, data: *mut u8, len: u32) -> i32; 89 | 90 | // mmu functions 91 | pub fn Cache_Suspend_ICache() -> u32; 92 | pub fn Cache_Resume_ICache(val: u32); 93 | pub fn Cache_Invalidate_ICache_All(); 94 | pub fn Cache_Ibus_MMU_Set( 95 | ext_ram: u32, 96 | vaddr: u32, 97 | paddr: u32, 98 | psize: u32, 99 | num: u32, 100 | fixed: u32, 101 | ) -> i32; 102 | 103 | pub fn Cache_Dbus_MMU_Set( 104 | ext_ram: u32, 105 | vaddr: u32, 106 | paddr: u32, 107 | psize: u32, 108 | num: u32, 109 | fixed: u32, 110 | ) -> i32; 111 | 112 | pub fn Cache_MMU_Init(); 113 | 114 | pub fn Cache_Enable_ICache(autoload: u32); 115 | } 116 | -------------------------------------------------------------------------------- /src/chip/esp32c3.rs: -------------------------------------------------------------------------------- 1 | use esp_println::println; 2 | 3 | pub const MMU_ACCESS_FLASH: u32 = 0; 4 | 5 | pub fn init_flash() { 6 | let spiconfig = unsafe { ets_efuse_get_spiconfig() }; 7 | 8 | pub const FLASH_SIZE: u32 = 0x1000000; 9 | pub const FLASH_STATUS_MASK: u32 = 0xFFFF; 10 | pub const FLASH_SECTOR_SIZE: u32 = 4096; 11 | pub const PAGE_SIZE: u32 = 0x4000; 12 | pub const FLASH_BLOCK_SIZE: u32 = 65536; 13 | 14 | // init flash 15 | let config_result = unsafe { 16 | esp_rom_spiflash_config_param( 17 | 0, 18 | FLASH_SIZE, // total_size 19 | FLASH_BLOCK_SIZE, // block_size 20 | FLASH_SECTOR_SIZE, // sector_size 21 | PAGE_SIZE, // page_size 22 | FLASH_STATUS_MASK, // status_mask 23 | ) 24 | }; 25 | 26 | if config_result == 0 { 27 | unsafe { esp_rom_spiflash_attach(spiconfig, false) }; 28 | } else { 29 | println!("Nope 💀"); 30 | } 31 | } 32 | 33 | pub fn init_mmu() -> u32 { 34 | // init mmu 35 | unsafe { 36 | Cache_MMU_Init(); 37 | Cache_Enable_ICache(1); 38 | 39 | let autoload = Cache_Suspend_ICache(); 40 | Cache_Invalidate_ICache_All(); 41 | 42 | autoload 43 | } 44 | } 45 | 46 | pub fn resume_mmu(autoload: u32) { 47 | unsafe { 48 | Cache_Resume_ICache(autoload); 49 | } 50 | } 51 | 52 | pub fn is_drom(addr: u32) -> bool { 53 | addr >= 0x3C00_0000 && addr <= 0x3C7F_FFFF 54 | } 55 | 56 | pub fn is_ram(addr: usize) -> bool { 57 | !(addr >= 0x3C00_0000 && addr <= 0x3C7F_FFFF || addr >= 0x4200_0000 && addr <= 0x427F_FFFF) 58 | } 59 | 60 | pub fn read_flash(flash_addr: u32, len: usize, data: &mut [u8]) { 61 | // read from flash 62 | if unsafe { esp_rom_spiflash_read(flash_addr, data.as_mut_ptr(), len as u32) } != 0 { 63 | println!("F"); 64 | } 65 | } 66 | 67 | pub fn dbus_mmu_set(vaddr: u32, paddr: u32, psize: u32, num: u32, fixed: u32) -> i32 { 68 | unsafe { Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, vaddr, paddr, psize, num, fixed) } 69 | } 70 | 71 | pub fn ibus_mmu_set(vaddr: u32, paddr: u32, psize: u32, num: u32, fixed: u32) -> i32 { 72 | unsafe { Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, vaddr, paddr, psize, num, fixed) } 73 | } 74 | 75 | extern "C" { 76 | // flash functions 77 | pub fn esp_rom_spiflash_attach(config: u32, legacy: bool); 78 | 79 | pub fn esp_rom_spiflash_config_param( 80 | device_id: u32, 81 | chip_size: u32, 82 | block_size: u32, 83 | sector_size: u32, 84 | page_size: u32, 85 | status_mask: u32, 86 | ) -> u32; 87 | 88 | pub fn ets_efuse_get_spiconfig() -> u32; 89 | 90 | pub fn esp_rom_spiflash_read(src_addr: u32, data: *mut u8, len: u32) -> i32; 91 | 92 | // mmu functions 93 | pub fn Cache_Suspend_ICache() -> u32; 94 | pub fn Cache_Resume_ICache(val: u32); 95 | pub fn Cache_Invalidate_ICache_All(); 96 | pub fn Cache_Ibus_MMU_Set( 97 | ext_ram: u32, 98 | vaddr: u32, 99 | paddr: u32, 100 | psize: u32, 101 | num: u32, 102 | fixed: u32, 103 | ) -> i32; 104 | 105 | pub fn Cache_Dbus_MMU_Set( 106 | ext_ram: u32, 107 | vaddr: u32, 108 | paddr: u32, 109 | psize: u32, 110 | num: u32, 111 | fixed: u32, 112 | ) -> i32; 113 | 114 | pub fn Cache_MMU_Init(); 115 | 116 | pub fn Cache_Enable_ICache(autoload: u32); 117 | } 118 | -------------------------------------------------------------------------------- /src/chip/esp32s3.rs: -------------------------------------------------------------------------------- 1 | use esp_println::println; 2 | 3 | pub const MMU_ACCESS_FLASH: u32 = 0; 4 | 5 | pub fn init_flash() { 6 | let spiconfig = unsafe { ets_efuse_get_spiconfig() }; 7 | 8 | pub const FLASH_SIZE: u32 = 0x1000000; 9 | pub const FLASH_STATUS_MASK: u32 = 0xFFFF; 10 | pub const FLASH_SECTOR_SIZE: u32 = 4096; 11 | pub const PAGE_SIZE: u32 = 0x4000; 12 | pub const FLASH_BLOCK_SIZE: u32 = 65536; 13 | 14 | // init flash 15 | let config_result = unsafe { 16 | esp_rom_spiflash_config_param( 17 | 0, 18 | FLASH_SIZE, // total_size 19 | FLASH_BLOCK_SIZE, // block_size 20 | FLASH_SECTOR_SIZE, // sector_size 21 | PAGE_SIZE, // page_size 22 | FLASH_STATUS_MASK, // status_mask 23 | ) 24 | }; 25 | 26 | if config_result == 0 { 27 | unsafe { esp_rom_spiflash_attach(spiconfig, false) }; 28 | } else { 29 | println!("Nope 💀"); 30 | } 31 | } 32 | 33 | pub fn init_mmu() -> u32 { 34 | // init mmu 35 | unsafe { 36 | Cache_MMU_Init(); 37 | Cache_Enable_ICache(1); 38 | 39 | let autoload = rom_Cache_Suspend_ICache(); 40 | Cache_Invalidate_ICache_All(); 41 | 42 | autoload 43 | } 44 | } 45 | 46 | pub fn resume_mmu(autoload: u32) { 47 | unsafe { 48 | Cache_Resume_ICache(autoload); 49 | } 50 | } 51 | 52 | pub fn is_drom(addr: u32) -> bool { 53 | addr >= 0x3C00_0000 && addr <= 0x3C7F_FFFF 54 | } 55 | 56 | pub fn is_ram(addr: usize) -> bool { 57 | !(addr >= 0x3C00_0000 && addr <= 0x3C7F_FFFF || addr >= 0x4200_0000 && addr <= 0x427F_FFFF) 58 | } 59 | 60 | pub fn read_flash(flash_addr: u32, len: usize, data: &mut [u8]) { 61 | // read from flash 62 | if unsafe { esp_rom_spiflash_read(flash_addr, data.as_mut_ptr(), len as u32) } != 0 { 63 | println!("F"); 64 | } 65 | } 66 | 67 | pub fn dbus_mmu_set(vaddr: u32, paddr: u32, psize: u32, num: u32, fixed: u32) -> i32 { 68 | unsafe { Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, vaddr, paddr, psize, num, fixed) } 69 | } 70 | 71 | pub fn ibus_mmu_set(vaddr: u32, paddr: u32, psize: u32, num: u32, fixed: u32) -> i32 { 72 | unsafe { Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, vaddr, paddr, psize, num, fixed) } 73 | } 74 | 75 | extern "C" { 76 | // flash functions 77 | pub fn esp_rom_spiflash_attach(config: u32, legacy: bool); 78 | 79 | pub fn esp_rom_spiflash_config_param( 80 | device_id: u32, 81 | chip_size: u32, 82 | block_size: u32, 83 | sector_size: u32, 84 | page_size: u32, 85 | status_mask: u32, 86 | ) -> u32; 87 | 88 | pub fn ets_efuse_get_spiconfig() -> u32; 89 | 90 | pub fn esp_rom_spiflash_read(src_addr: u32, data: *mut u8, len: u32) -> i32; 91 | 92 | // mmu functions 93 | pub fn rom_Cache_Suspend_ICache() -> u32; 94 | pub fn Cache_Resume_ICache(val: u32); 95 | pub fn Cache_Invalidate_ICache_All(); 96 | pub fn Cache_Ibus_MMU_Set( 97 | ext_ram: u32, 98 | vaddr: u32, 99 | paddr: u32, 100 | psize: u32, 101 | num: u32, 102 | fixed: u32, 103 | ) -> i32; 104 | 105 | pub fn Cache_Dbus_MMU_Set( 106 | ext_ram: u32, 107 | vaddr: u32, 108 | paddr: u32, 109 | psize: u32, 110 | num: u32, 111 | fixed: u32, 112 | ) -> i32; 113 | 114 | pub fn Cache_MMU_Init(); 115 | 116 | pub fn Cache_Enable_ICache(autoload: u32); 117 | } 118 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | mod chip; 5 | mod image; 6 | 7 | pub(crate) use chip::*; 8 | use esp_hal::main; 9 | use esp_println::println; 10 | pub(crate) use image::*; 11 | 12 | #[panic_handler] 13 | fn panic<'a, 'b>(_pi: &'a core::panic::PanicInfo<'b>) -> ! { 14 | println!("💀{:?}", _pi); 15 | loop {} 16 | } 17 | 18 | #[main] 19 | fn main() -> ! { 20 | esp_hal::init(esp_hal::Config::default()); 21 | println!("I'm just a humble bootloader 🦀\n"); 22 | 23 | init_flash(); 24 | 25 | let autoload = init_mmu(); 26 | 27 | let image_offset = 0x10_000; 28 | 29 | let mut buffer = [0u8; 128]; 30 | 31 | read_flash(image_offset, 128, &mut buffer); 32 | 33 | let header = unsafe { &*(buffer.as_ptr() as *const EspImageHeader) }; 34 | 35 | let segments = header.segment_count as usize; 36 | let entry_addr = header.entry_addr as usize; 37 | 38 | println!("Segments: {}", segments); 39 | println!("entry_addr: {:x}", entry_addr); 40 | 41 | let mut flash_addr = image_offset + core::mem::size_of::() as u32; 42 | for segment in 0..segments { 43 | read_flash(flash_addr, 128, &mut buffer); 44 | 45 | let segment_header = unsafe { &*(buffer.as_ptr() as *const EspImageSegmentHeader) }; 46 | 47 | let load_addr = segment_header.load_addr as usize; 48 | let data_len = segment_header.data_len as usize; 49 | 50 | println!( 51 | "Segment {}: {:x} - {:x} (len = {:x})", 52 | segment, 53 | load_addr, 54 | load_addr + data_len, 55 | data_len, 56 | ); 57 | 58 | if load_addr == 0 { 59 | println!("skip"); 60 | } else { 61 | if is_ram(load_addr) { 62 | println!( 63 | "Copying to RAM from {:x}", 64 | flash_addr + core::mem::size_of::() as u32 65 | ); 66 | let dst = load_addr as *mut u8; 67 | read_flash( 68 | flash_addr + core::mem::size_of::() as u32, 69 | data_len, 70 | unsafe { core::slice::from_raw_parts_mut(dst, data_len) }, 71 | ); 72 | } else { 73 | println!("Mapping flash"); 74 | let paddr = flash_addr + core::mem::size_of::() as u32; 75 | let vaddr = load_addr as u32; 76 | let blocks = (data_len as u32 + vaddr % 0x10_000).div_ceil(64 * 1024); 77 | 78 | let vaddr = vaddr - vaddr % 0x10_000; 79 | let paddr = paddr - paddr % 0x10_000; 80 | 81 | println!("vaddr: {:x}, paddr: {:x}, blocks: {}", vaddr, paddr, blocks); 82 | 83 | let res = if is_drom(vaddr) { 84 | dbus_mmu_set(vaddr, paddr, 64, blocks, 0) 85 | } else { 86 | ibus_mmu_set(vaddr, paddr, 64, blocks, 0) 87 | }; 88 | 89 | if res != 0 { 90 | println!("💀 mmuset {}", res); 91 | } 92 | } 93 | } 94 | flash_addr += core::mem::size_of::() as u32 + data_len as u32; 95 | } 96 | 97 | resume_mmu(autoload); 98 | 99 | // jump to entry 100 | let entry: extern "C" fn() -> ! = unsafe { core::mem::transmute(entry_addr) }; 101 | 102 | println!("\nJump! 🏃‍♂️‍➡️\n"); 103 | entry(); 104 | } 105 | -------------------------------------------------------------------------------- /src/chip/esp32c6.rs: -------------------------------------------------------------------------------- 1 | use esp_println::println; 2 | 3 | pub const MMU_ACCESS_FLASH: u32 = 0; 4 | 5 | pub fn init_flash() { 6 | let spiconfig = 0; 7 | 8 | pub const FLASH_SIZE: u32 = 0x1000000; 9 | pub const FLASH_STATUS_MASK: u32 = 0xFFFF; 10 | pub const FLASH_SECTOR_SIZE: u32 = 4096; 11 | pub const PAGE_SIZE: u32 = 0x4000; 12 | pub const FLASH_BLOCK_SIZE: u32 = 65536; 13 | 14 | // init flash 15 | let config_result = unsafe { 16 | esp_rom_spiflash_config_param( 17 | 0, 18 | FLASH_SIZE, // total_size 19 | FLASH_BLOCK_SIZE, // block_size 20 | FLASH_SECTOR_SIZE, // sector_size 21 | PAGE_SIZE, // page_size 22 | FLASH_STATUS_MASK, // status_mask 23 | ) 24 | }; 25 | 26 | if config_result == 0 { 27 | unsafe { esp_rom_spiflash_attach(spiconfig, false) }; 28 | } else { 29 | println!("Nope 💀"); 30 | } 31 | } 32 | 33 | pub fn init_mmu() -> u32 { 34 | // init mmu 35 | unsafe { 36 | Cache_MMU_Init(); 37 | Cache_Enable_ICache(1); 38 | 39 | let autoload = Cache_Suspend_ICache(); 40 | Cache_Invalidate_ICache_All(); 41 | 42 | autoload 43 | } 44 | } 45 | 46 | pub fn resume_mmu(autoload: u32) { 47 | unsafe { 48 | Cache_Resume_ICache(autoload); 49 | } 50 | } 51 | 52 | pub fn is_drom(addr: u32) -> bool { 53 | true 54 | } 55 | 56 | pub fn is_ram(addr: usize) -> bool { 57 | !(addr >= 0x4200_0000 && addr <= 0x42FF_FFFF) 58 | } 59 | 60 | pub fn read_flash(flash_addr: u32, len: usize, data: &mut [u8]) { 61 | // read from flash 62 | if unsafe { esp_rom_spiflash_read(flash_addr, data.as_mut_ptr(), len as u32) } != 0 { 63 | println!("F"); 64 | } 65 | } 66 | 67 | pub fn dbus_mmu_set(vaddr: u32, paddr: u32, psize: u32, num: u32, fixed: u32) -> i32 { 68 | unsafe { Cache_MSPI_MMU_Set(0, MMU_ACCESS_FLASH, vaddr, paddr, psize, num, fixed) } 69 | } 70 | 71 | pub fn ibus_mmu_set(vaddr: u32, paddr: u32, psize: u32, num: u32, fixed: u32) -> i32 { 72 | unsafe { Cache_MSPI_MMU_Set(0, MMU_ACCESS_FLASH, vaddr, paddr, psize, num, fixed) } 73 | } 74 | 75 | extern "C" { 76 | // flash functions 77 | pub fn esp_rom_spiflash_attach(config: u32, legacy: bool); 78 | 79 | pub fn esp_rom_spiflash_config_param( 80 | device_id: u32, 81 | chip_size: u32, 82 | block_size: u32, 83 | sector_size: u32, 84 | page_size: u32, 85 | status_mask: u32, 86 | ) -> u32; 87 | 88 | pub fn esp_rom_spiflash_read(src_addr: u32, data: *mut u8, len: u32) -> i32; 89 | 90 | // mmu functions 91 | pub fn Cache_Suspend_ICache() -> u32; 92 | pub fn Cache_Resume_ICache(val: u32); 93 | pub fn Cache_Invalidate_ICache_All(); 94 | 95 | /** 96 | * @brief Set ICache mmu mapping. 97 | * Please do not call this function in your SDK application. 98 | * 99 | * @param uint32_t senitive : Config this page should apply flash encryption or not 100 | * 101 | * @param uint32_t ext_ram : DPORT_MMU_ACCESS_FLASH for flash, DPORT_MMU_INVALID for invalid. In 102 | * esp32c6, external memory is always flash 103 | * 104 | * @param uint32_t vaddr : virtual address in CPU address space. 105 | * Can be Iram0,Iram1,Irom0,Drom0 and AHB buses address. 106 | * Should be aligned by psize. 107 | * 108 | * @param uint32_t paddr : physical address in external memory. 109 | * Should be aligned by psize. 110 | * 111 | * @param uint32_t psize : page size of ICache, in kilobytes. Should be 64 here. 112 | * 113 | * @param uint32_t num : pages to be set. 114 | * 115 | * @param uint32_t fixed : 0 for physical pages grow with virtual pages, other for virtual pages map to same physical page. 116 | * 117 | * @return uint32_t: error status 118 | * 0 : mmu set success 119 | * 2 : vaddr or paddr is not aligned 120 | * 3 : psize error 121 | * 4 : vaddr is out of range 122 | */ 123 | pub fn Cache_MSPI_MMU_Set( 124 | sensitive: u32, 125 | ext_ram: u32, 126 | vaddr: u32, 127 | paddr: u32, 128 | psize: u32, 129 | num: u32, 130 | fixed: u32, 131 | ) -> i32; 132 | 133 | pub fn Cache_MMU_Init(); 134 | 135 | pub fn Cache_Enable_ICache(autoload: u32); 136 | } 137 | -------------------------------------------------------------------------------- /src/chip/esp32h2.rs: -------------------------------------------------------------------------------- 1 | use esp_println::println; 2 | 3 | pub const MMU_ACCESS_FLASH: u32 = 0; 4 | 5 | pub fn init_flash() { 6 | let spiconfig = 0; 7 | 8 | pub const FLASH_SIZE: u32 = 0x1000000; 9 | pub const FLASH_STATUS_MASK: u32 = 0xFFFF; 10 | pub const FLASH_SECTOR_SIZE: u32 = 4096; 11 | pub const PAGE_SIZE: u32 = 0x4000; 12 | pub const FLASH_BLOCK_SIZE: u32 = 65536; 13 | 14 | // init flash 15 | let config_result = unsafe { 16 | esp_rom_spiflash_config_param( 17 | 0, 18 | FLASH_SIZE, // total_size 19 | FLASH_BLOCK_SIZE, // block_size 20 | FLASH_SECTOR_SIZE, // sector_size 21 | PAGE_SIZE, // page_size 22 | FLASH_STATUS_MASK, // status_mask 23 | ) 24 | }; 25 | 26 | if config_result == 0 { 27 | unsafe { esp_rom_spiflash_attach(spiconfig, false) }; 28 | } else { 29 | println!("Nope 💀"); 30 | } 31 | } 32 | 33 | pub fn init_mmu() -> u32 { 34 | // init mmu 35 | unsafe { 36 | Cache_MMU_Init(); 37 | Cache_Enable_ICache(1); 38 | 39 | let autoload = Cache_Suspend_ICache(); 40 | Cache_Invalidate_ICache_All(); 41 | 42 | autoload 43 | } 44 | } 45 | 46 | pub fn resume_mmu(autoload: u32) { 47 | unsafe { 48 | Cache_Resume_ICache(autoload); 49 | } 50 | } 51 | 52 | pub fn is_drom(addr: u32) -> bool { 53 | true 54 | } 55 | 56 | pub fn is_ram(addr: usize) -> bool { 57 | !(addr >= 0x4200_0000 && addr <= 0x42FF_FFFF) 58 | } 59 | 60 | pub fn read_flash(flash_addr: u32, len: usize, data: &mut [u8]) { 61 | // read from flash 62 | if unsafe { esp_rom_spiflash_read(flash_addr, data.as_mut_ptr(), len as u32) } != 0 { 63 | println!("F"); 64 | } 65 | } 66 | 67 | pub fn dbus_mmu_set(vaddr: u32, paddr: u32, psize: u32, num: u32, fixed: u32) -> i32 { 68 | unsafe { Cache_MSPI_MMU_Set(0, MMU_ACCESS_FLASH, vaddr, paddr, psize, num, fixed) } 69 | } 70 | 71 | pub fn ibus_mmu_set(vaddr: u32, paddr: u32, psize: u32, num: u32, fixed: u32) -> i32 { 72 | unsafe { Cache_MSPI_MMU_Set(0, MMU_ACCESS_FLASH, vaddr, paddr, psize, num, fixed) } 73 | } 74 | 75 | extern "C" { 76 | // flash functions 77 | pub fn esp_rom_spiflash_attach(config: u32, legacy: bool); 78 | 79 | pub fn esp_rom_spiflash_config_param( 80 | device_id: u32, 81 | chip_size: u32, 82 | block_size: u32, 83 | sector_size: u32, 84 | page_size: u32, 85 | status_mask: u32, 86 | ) -> u32; 87 | 88 | pub fn esp_rom_spiflash_read(src_addr: u32, data: *mut u8, len: u32) -> i32; 89 | 90 | // mmu functions 91 | pub fn Cache_Suspend_ICache() -> u32; 92 | pub fn Cache_Resume_ICache(val: u32); 93 | pub fn Cache_Invalidate_ICache_All(); 94 | 95 | /** 96 | * @brief Set ICache mmu mapping. 97 | * Please do not call this function in your SDK application. 98 | * 99 | * @param uint32_t senitive : Config this page should apply flash encryption or not 100 | * 101 | * @param uint32_t ext_ram : DPORT_MMU_ACCESS_FLASH for flash, DPORT_MMU_INVALID for invalid. In 102 | * esp32c6, external memory is always flash 103 | * 104 | * @param uint32_t vaddr : virtual address in CPU address space. 105 | * Can be Iram0,Iram1,Irom0,Drom0 and AHB buses address. 106 | * Should be aligned by psize. 107 | * 108 | * @param uint32_t paddr : physical address in external memory. 109 | * Should be aligned by psize. 110 | * 111 | * @param uint32_t psize : page size of ICache, in kilobytes. Should be 64 here. 112 | * 113 | * @param uint32_t num : pages to be set. 114 | * 115 | * @param uint32_t fixed : 0 for physical pages grow with virtual pages, other for virtual pages map to same physical page. 116 | * 117 | * @return uint32_t: error status 118 | * 0 : mmu set success 119 | * 2 : vaddr or paddr is not aligned 120 | * 3 : psize error 121 | * 4 : vaddr is out of range 122 | */ 123 | pub fn Cache_MSPI_MMU_Set( 124 | sensitive: u32, 125 | ext_ram: u32, 126 | vaddr: u32, 127 | paddr: u32, 128 | psize: u32, 129 | num: u32, 130 | fixed: u32, 131 | ) -> i32; 132 | 133 | pub fn Cache_MMU_Init(); 134 | 135 | pub fn Cache_Enable_ICache(autoload: u32); 136 | } 137 | -------------------------------------------------------------------------------- /ld/link_esp32c2.x: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | /** Simplified memory map for the bootloader. 7 | * Make sure the bootloader can load into main memory without overwriting itself. 8 | * 9 | * ESP32-C2 ROM static data usage is as follows: 10 | * - 0x3fccb264 - 0x3fcdcb70: Shared buffers, used in UART/USB/SPI download mode only 11 | * - 0x3fcdcb70 - 0x3fcdeb70: PRO CPU stack, can be reclaimed as heap after RTOS startup 12 | * - 0x3fcdeb70 - 0x3fce0000: ROM .bss and .data (not easily reclaimable) 13 | * 14 | * The 2nd stage bootloader can take space up to the end of ROM shared 15 | * buffers area (0x3fcdcb70). 16 | */ 17 | 18 | /* The offset between Dbus and Ibus. Used to convert between 0x403xxxxx and 0x3fcxxxxx addresses. */ 19 | iram_dram_offset = 0x6e0000; 20 | 21 | /* We consider 0x3fcdcb70 to be the last usable address for 2nd stage bootloader stack overhead, dram_seg, 22 | * and work out iram_seg and iram_loader_seg addresses from there, backwards. 23 | */ 24 | 25 | /* These lengths can be adjusted, if necessary: */ 26 | bootloader_usable_dram_end = 0x3fcdcb70; 27 | bootloader_stack_overhead = 0x2000; /* For safety margin between bootloader data section and startup stacks */ 28 | bootloader_dram_seg_len = 0x5000; 29 | bootloader_iram_loader_seg_len = 0x7000; 30 | bootloader_iram_seg_len = 0x2800; 31 | 32 | /* Start of the lower region is determined by region size and the end of the higher region */ 33 | bootloader_dram_seg_end = bootloader_usable_dram_end - bootloader_stack_overhead; 34 | bootloader_dram_seg_start = bootloader_dram_seg_end - bootloader_dram_seg_len; 35 | bootloader_iram_loader_seg_start = bootloader_dram_seg_start - bootloader_iram_loader_seg_len + iram_dram_offset; 36 | bootloader_iram_seg_start = bootloader_iram_loader_seg_start - bootloader_iram_seg_len; 37 | 38 | MEMORY 39 | { 40 | iram_seg (RWX) : org = bootloader_iram_seg_start, len = bootloader_iram_seg_len 41 | iram_loader_seg (RWX) : org = bootloader_iram_loader_seg_start, len = bootloader_iram_loader_seg_len 42 | dram_seg (RW) : org = bootloader_dram_seg_start, len = bootloader_dram_seg_len 43 | } 44 | 45 | REGION_ALIAS("iram", iram_loader_seg); 46 | REGION_ALIAS("dram", dram_seg); 47 | 48 | INCLUDE "hal-defaults.x" 49 | INCLUDE "rom-functions.x" 50 | 51 | 52 | SECTIONS { 53 | .text : ALIGN(4) 54 | { 55 | KEEP(*(.trap)); 56 | *(.trap.*); 57 | 58 | KEEP(*(.init)); 59 | KEEP(*(.init.rust)); 60 | KEEP(*(.text.abort)); 61 | *(.literal .text .literal.* .text.*) 62 | *(.rwtext.literal .rwtext .rwtext.literal.* .rwtext.*) 63 | } > iram 64 | 65 | .data : ALIGN(4) 66 | { 67 | _data_start = ABSOLUTE(.); 68 | . = ALIGN (4); 69 | 70 | *(.sdata .sdata.* .sdata2 .sdata2.*); 71 | *(.data .data.*); 72 | *(.data1) 73 | 74 | *(.rodata .rodata.*) 75 | *(.srodata .srodata.*) 76 | 77 | . = ALIGN(4); 78 | } > dram 79 | 80 | .bss (NOLOAD) : ALIGN(4) 81 | { 82 | _bss_start = ABSOLUTE(.); 83 | . = ALIGN (4); 84 | *(.dynsbss) 85 | *(.sbss) 86 | *(.sbss.*) 87 | *(.gnu.linkonce.sb.*) 88 | *(.scommon) 89 | *(.sbss2) 90 | *(.sbss2.*) 91 | *(.gnu.linkonce.sb2.*) 92 | *(.dynbss) 93 | *(.sbss .sbss.* .bss .bss.*); 94 | *(.share.mem) 95 | *(.gnu.linkonce.b.*) 96 | *(COMMON) 97 | _bss_end = ABSOLUTE(.); 98 | . = ALIGN(4); 99 | } > dram 100 | 101 | /* must be last segment using RWDATA */ 102 | .stack (NOLOAD) : ALIGN(4) 103 | { 104 | . = ALIGN (4); 105 | _stack_end = ABSOLUTE(.); 106 | _stack_end_cpu0 = ABSOLUTE(.); 107 | } > dram 108 | 109 | .unused (NOLOAD) : 110 | { 111 | *(.eh_frame) 112 | } > rtc_fast 113 | } 114 | 115 | 116 | PROVIDE(_stack_start = ORIGIN(iram) + LENGTH(iram)); 117 | PROVIDE(_stack_start_cpu0 = ORIGIN(iram) + LENGTH(iram)); 118 | PROVIDE(__stack_chk_guard = _stack_end + 4096); 119 | 120 | PROVIDE(UserSoft = DefaultHandler); 121 | PROVIDE(SupervisorSoft = DefaultHandler); 122 | PROVIDE(MachineSoft = DefaultHandler); 123 | PROVIDE(UserTimer = DefaultHandler); 124 | PROVIDE(SupervisorTimer = DefaultHandler); 125 | PROVIDE(MachineTimer = DefaultHandler); 126 | PROVIDE(UserExternal = DefaultHandler); 127 | PROVIDE(SupervisorExternal = DefaultHandler); 128 | PROVIDE(MachineExternal = DefaultHandler); 129 | 130 | PROVIDE(ExceptionHandler = DefaultExceptionHandler); 131 | 132 | PROVIDE(__post_init = default_post_init); 133 | 134 | PROVIDE(_max_hart_id = 0); 135 | -------------------------------------------------------------------------------- /ld/link_esp32c6.x: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | /** Simplified memory map for the bootloader. 7 | * Make sure the bootloader can load into main memory without overwriting itself. 8 | * 9 | * ESP32-C6 ROM static data usage is as follows: 10 | * - 0x4086ad08 - 0x4087c610: Shared buffers, used in UART/USB/SPI download mode only 11 | * - 0x4087c610 - 0x4087e610: PRO CPU stack, can be reclaimed as heap after RTOS startup 12 | * - 0x4087e610 - 0x40880000: ROM .bss and .data (not easily reclaimable) 13 | * 14 | * The 2nd stage bootloader can take space up to the end of ROM shared 15 | * buffers area (0x4087c610). 16 | */ 17 | 18 | /* We consider 0x4087c610 to be the last usable address for 2nd stage bootloader stack overhead, dram_seg, 19 | * and work out iram_seg and iram_loader_seg addresses from there, backwards. 20 | */ 21 | 22 | /* These lengths can be adjusted, if necessary: */ 23 | bootloader_usable_dram_end = 0x4087c610; 24 | bootloader_stack_overhead = 0x2000; /* For safety margin between bootloader data section and startup stacks */ 25 | bootloader_dram_seg_len = 0x5000; 26 | bootloader_iram_loader_seg_len = 0x7000; 27 | bootloader_iram_seg_len = 0x2D00; 28 | 29 | /* Start of the lower region is determined by region size and the end of the higher region */ 30 | bootloader_dram_seg_end = bootloader_usable_dram_end - bootloader_stack_overhead; 31 | bootloader_dram_seg_start = bootloader_dram_seg_end - bootloader_dram_seg_len; 32 | bootloader_iram_loader_seg_start = bootloader_dram_seg_start - bootloader_iram_loader_seg_len; 33 | bootloader_iram_seg_start = bootloader_iram_loader_seg_start - bootloader_iram_seg_len; 34 | 35 | MEMORY 36 | { 37 | iram_seg (RWX) : org = bootloader_iram_seg_start, len = bootloader_iram_seg_len 38 | iram_loader_seg (RWX) : org = bootloader_iram_loader_seg_start, len = bootloader_iram_loader_seg_len 39 | dram_seg (RW) : org = bootloader_dram_seg_start, len = bootloader_dram_seg_len 40 | 41 | RTC_FAST : ORIGIN = 0x50000000, LENGTH = 0x2000 42 | } 43 | 44 | 45 | REGION_ALIAS("iram", iram_loader_seg); 46 | REGION_ALIAS("dram", dram_seg); 47 | REGION_ALIAS("rtc_fast", RTC_FAST); 48 | 49 | INCLUDE "hal-defaults.x" 50 | INCLUDE "rom-functions.x" 51 | 52 | 53 | SECTIONS { 54 | .text : ALIGN(4) 55 | { 56 | KEEP(*(.trap)); 57 | *(.trap.*); 58 | 59 | KEEP(*(.init)); 60 | KEEP(*(.init.rust)); 61 | KEEP(*(.text.abort)); 62 | *(.literal .text .literal.* .text.*) 63 | *(.rwtext.literal .rwtext .rwtext.literal.* .rwtext.*) 64 | } > iram 65 | 66 | .data : ALIGN(4) 67 | { 68 | _data_start = ABSOLUTE(.); 69 | . = ALIGN (4); 70 | 71 | *(.sdata .sdata.* .sdata2 .sdata2.*); 72 | *(.data .data.*); 73 | *(.data1) 74 | 75 | *(.rodata .rodata.*) 76 | *(.srodata .srodata.*) 77 | 78 | . = ALIGN(4); 79 | } > dram 80 | 81 | .bss (NOLOAD) : ALIGN(4) 82 | { 83 | _bss_start = ABSOLUTE(.); 84 | . = ALIGN (4); 85 | *(.dynsbss) 86 | *(.sbss) 87 | *(.sbss.*) 88 | *(.gnu.linkonce.sb.*) 89 | *(.scommon) 90 | *(.sbss2) 91 | *(.sbss2.*) 92 | *(.gnu.linkonce.sb2.*) 93 | *(.dynbss) 94 | *(.sbss .sbss.* .bss .bss.*); 95 | *(.share.mem) 96 | *(.gnu.linkonce.b.*) 97 | *(COMMON) 98 | _bss_end = ABSOLUTE(.); 99 | . = ALIGN(4); 100 | } > dram 101 | 102 | /* must be last segment using RWDATA */ 103 | .stack (NOLOAD) : ALIGN(4) 104 | { 105 | . = ALIGN (4); 106 | _stack_end = ABSOLUTE(.); 107 | _stack_end_cpu0 = ABSOLUTE(.); 108 | } > dram 109 | 110 | .rtc_fast.bss (NOLOAD) : 111 | { 112 | . = ALIGN(4); 113 | _rtc_fast_bss_start = ABSOLUTE(.); 114 | *(.rtc_fast.bss .rtc_fast.bss.*) 115 | _rtc_fast_bss_end = ABSOLUTE(.); 116 | . = ALIGN(4); 117 | } > rtc_fast 118 | 119 | .rtc_fast.persistent (NOLOAD) : 120 | { 121 | . = ALIGN(4); 122 | _rtc_fast_persistent_start = ABSOLUTE(.); 123 | *(.rtc_fast.persistent .rtc_fast.persistent.*) 124 | _rtc_fast_persistent_end = ABSOLUTE(.); 125 | . = ALIGN(4); 126 | } > rtc_fast 127 | 128 | .unused (NOLOAD) : 129 | { 130 | *(.eh_frame) 131 | } > rtc_fast 132 | } 133 | 134 | 135 | PROVIDE(_stack_start = ORIGIN(iram) + LENGTH(iram)); 136 | PROVIDE(_stack_start_cpu0 = ORIGIN(iram) + LENGTH(iram)); 137 | PROVIDE(__stack_chk_guard = _stack_end + 4096); 138 | 139 | PROVIDE(UserSoft = DefaultHandler); 140 | PROVIDE(SupervisorSoft = DefaultHandler); 141 | PROVIDE(MachineSoft = DefaultHandler); 142 | PROVIDE(UserTimer = DefaultHandler); 143 | PROVIDE(SupervisorTimer = DefaultHandler); 144 | PROVIDE(MachineTimer = DefaultHandler); 145 | PROVIDE(UserExternal = DefaultHandler); 146 | PROVIDE(SupervisorExternal = DefaultHandler); 147 | PROVIDE(MachineExternal = DefaultHandler); 148 | 149 | PROVIDE(ExceptionHandler = DefaultExceptionHandler); 150 | 151 | PROVIDE(__post_init = default_post_init); 152 | 153 | PROVIDE(_max_hart_id = 0); 154 | -------------------------------------------------------------------------------- /ld/link_esp32h2.x: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | /** Simplified memory map for the bootloader. 7 | * Make sure the bootloader can load into main memory without overwriting itself. 8 | * 9 | * ESP32-H2 ROM static data usage is as follows: 10 | * - 0x4083ba78 - 0x4084d380: Shared buffers, used in UART/USB/SPI download mode only 11 | * - 0x4084d380 - 0x4084f380: PRO CPU stack, can be reclaimed as heap after RTOS startup 12 | * - 0x4084f380 - 0x4084fee0: ROM .bss and .data used in startup code or nonos/early boot (can be freed when IDF runs) 13 | * - 0x4084fee0 - 0x40850000: ROM .bss and .data used in startup code and when IDF runs (cannot be freed) 14 | * 15 | * The 2nd stage bootloader can take space up to the end of ROM shared 16 | * buffers area (0x4084d380). 17 | */ 18 | 19 | /* We consider 0x3fcdc710 to be the last usable address for 2nd stage bootloader stack overhead, dram_seg, 20 | * and work out iram_seg and iram_loader_seg addresses from there, backwards. 21 | */ 22 | 23 | /* These lengths can be adjusted, if necessary: */ 24 | bootloader_usable_dram_end = 0x4084cfd0; 25 | bootloader_stack_overhead = 0x2000; /* For safety margin between bootloader data section and startup stacks */ 26 | bootloader_dram_seg_len = 0x5000; 27 | bootloader_iram_loader_seg_len = 0x7000; 28 | bootloader_iram_seg_len = 0x2D00; 29 | 30 | /* Start of the lower region is determined by region size and the end of the higher region */ 31 | bootloader_dram_seg_end = bootloader_usable_dram_end - bootloader_stack_overhead; 32 | bootloader_dram_seg_start = bootloader_dram_seg_end - bootloader_dram_seg_len; 33 | bootloader_iram_loader_seg_start = bootloader_dram_seg_start - bootloader_iram_loader_seg_len; 34 | bootloader_iram_seg_start = bootloader_iram_loader_seg_start - bootloader_iram_seg_len; 35 | 36 | MEMORY 37 | { 38 | iram_seg (RWX) : org = bootloader_iram_seg_start, len = bootloader_iram_seg_len 39 | iram_loader_seg (RWX) : org = bootloader_iram_loader_seg_start, len = bootloader_iram_loader_seg_len 40 | dram_seg (RW) : org = bootloader_dram_seg_start, len = bootloader_dram_seg_len 41 | 42 | RTC_FAST : ORIGIN = 0x50000000, LENGTH = 0x2000 43 | } 44 | 45 | 46 | REGION_ALIAS("iram", iram_loader_seg); 47 | REGION_ALIAS("dram", dram_seg); 48 | REGION_ALIAS("rtc_fast", RTC_FAST); 49 | 50 | INCLUDE "hal-defaults.x" 51 | INCLUDE "rom-functions.x" 52 | 53 | 54 | SECTIONS { 55 | .text : ALIGN(4) 56 | { 57 | KEEP(*(.trap)); 58 | *(.trap.*); 59 | 60 | KEEP(*(.init)); 61 | KEEP(*(.init.rust)); 62 | KEEP(*(.text.abort)); 63 | *(.literal .text .literal.* .text.*) 64 | *(.rwtext.literal .rwtext .rwtext.literal.* .rwtext.*) 65 | } > iram 66 | 67 | .data : ALIGN(4) 68 | { 69 | _data_start = ABSOLUTE(.); 70 | . = ALIGN (4); 71 | 72 | *(.sdata .sdata.* .sdata2 .sdata2.*); 73 | *(.data .data.*); 74 | *(.data1) 75 | 76 | *(.rodata .rodata.*) 77 | *(.srodata .srodata.*) 78 | 79 | . = ALIGN(4); 80 | } > dram 81 | 82 | .bss (NOLOAD) : ALIGN(4) 83 | { 84 | _bss_start = ABSOLUTE(.); 85 | . = ALIGN (4); 86 | *(.dynsbss) 87 | *(.sbss) 88 | *(.sbss.*) 89 | *(.gnu.linkonce.sb.*) 90 | *(.scommon) 91 | *(.sbss2) 92 | *(.sbss2.*) 93 | *(.gnu.linkonce.sb2.*) 94 | *(.dynbss) 95 | *(.sbss .sbss.* .bss .bss.*); 96 | *(.share.mem) 97 | *(.gnu.linkonce.b.*) 98 | *(COMMON) 99 | _bss_end = ABSOLUTE(.); 100 | . = ALIGN(4); 101 | } > dram 102 | 103 | /* must be last segment using RWDATA */ 104 | .stack (NOLOAD) : ALIGN(4) 105 | { 106 | . = ALIGN (4); 107 | _stack_end = ABSOLUTE(.); 108 | _stack_end_cpu0 = ABSOLUTE(.); 109 | } > dram 110 | 111 | .rtc_fast.bss (NOLOAD) : 112 | { 113 | . = ALIGN(4); 114 | _rtc_fast_bss_start = ABSOLUTE(.); 115 | *(.rtc_fast.bss .rtc_fast.bss.*) 116 | _rtc_fast_bss_end = ABSOLUTE(.); 117 | . = ALIGN(4); 118 | } > rtc_fast 119 | 120 | .rtc_fast.persistent (NOLOAD) : 121 | { 122 | . = ALIGN(4); 123 | _rtc_fast_persistent_start = ABSOLUTE(.); 124 | *(.rtc_fast.persistent .rtc_fast.persistent.*) 125 | _rtc_fast_persistent_end = ABSOLUTE(.); 126 | . = ALIGN(4); 127 | } > rtc_fast 128 | 129 | .unused (NOLOAD) : 130 | { 131 | *(.eh_frame) 132 | } > rtc_fast 133 | } 134 | 135 | 136 | PROVIDE(_stack_start = ORIGIN(iram) + LENGTH(iram)); 137 | PROVIDE(_stack_start_cpu0 = ORIGIN(iram) + LENGTH(iram)); 138 | PROVIDE(__stack_chk_guard = _stack_end + 4096); 139 | 140 | PROVIDE(UserSoft = DefaultHandler); 141 | PROVIDE(SupervisorSoft = DefaultHandler); 142 | PROVIDE(MachineSoft = DefaultHandler); 143 | PROVIDE(UserTimer = DefaultHandler); 144 | PROVIDE(SupervisorTimer = DefaultHandler); 145 | PROVIDE(MachineTimer = DefaultHandler); 146 | PROVIDE(UserExternal = DefaultHandler); 147 | PROVIDE(SupervisorExternal = DefaultHandler); 148 | PROVIDE(MachineExternal = DefaultHandler); 149 | 150 | PROVIDE(ExceptionHandler = DefaultExceptionHandler); 151 | 152 | PROVIDE(__post_init = default_post_init); 153 | 154 | PROVIDE(_max_hart_id = 0); 155 | -------------------------------------------------------------------------------- /ld/link_esp32c3.x: -------------------------------------------------------------------------------- 1 | ENTRY(_start) 2 | 3 | /* 4 | * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD 5 | * 6 | * SPDX-License-Identifier: Apache-2.0 7 | */ 8 | /** Simplified memory map for the bootloader. 9 | * Make sure the bootloader can load into main memory without overwriting itself. 10 | * 11 | * ESP32-C3 ROM static data usage is as follows: 12 | * - 0x3fccae00 - 0x3fcdc710: Shared buffers, used in UART/USB/SPI download mode only 13 | * - 0x3fcdc710 - 0x3fcde710: PRO CPU stack, can be reclaimed as heap after RTOS startup 14 | * - 0x3fcde710 - 0x3fce0000: ROM .bss and .data (not easily reclaimable) 15 | * 16 | * The 2nd stage bootloader can take space up to the end of ROM shared 17 | * buffers area (0x3fcdc710). 18 | */ 19 | 20 | /* The offset between Dbus and Ibus. Used to convert between 0x403xxxxx and 0x3fcxxxxx addresses. */ 21 | iram_dram_offset = 0x700000; 22 | 23 | /* We consider 0x3fcdc710 to be the last usable address for 2nd stage bootloader stack overhead, dram_seg, 24 | * and work out iram_seg and iram_loader_seg addresses from there, backwards. 25 | */ 26 | 27 | /* These lengths can be adjusted, if necessary: */ 28 | bootloader_usable_dram_end = 0x3fcdc710; 29 | bootloader_stack_overhead = 0x2000; /* For safety margin between bootloader data section and startup stacks */ 30 | bootloader_dram_seg_len = 0x5000; 31 | bootloader_iram_loader_seg_len = 0x7000; 32 | bootloader_iram_seg_len = 0x2000; 33 | 34 | /* Start of the lower region is determined by region size and the end of the higher region */ 35 | bootloader_dram_seg_end = bootloader_usable_dram_end - bootloader_stack_overhead; 36 | bootloader_dram_seg_start = bootloader_dram_seg_end - bootloader_dram_seg_len; 37 | bootloader_iram_loader_seg_start = bootloader_dram_seg_start - bootloader_iram_loader_seg_len + iram_dram_offset; 38 | bootloader_iram_seg_start = bootloader_iram_loader_seg_start - bootloader_iram_seg_len; 39 | 40 | MEMORY 41 | { 42 | iram_seg (RWX) : org = bootloader_iram_seg_start, len = bootloader_iram_seg_len 43 | iram_loader_seg (RWX) : org = bootloader_iram_loader_seg_start, len = bootloader_iram_loader_seg_len 44 | dram_seg (RW) : org = bootloader_dram_seg_start, len = bootloader_dram_seg_len 45 | 46 | RTC_FAST : ORIGIN = 0x50000000, LENGTH = 0x2000 47 | } 48 | 49 | REGION_ALIAS("iram", iram_loader_seg); 50 | REGION_ALIAS("dram", dram_seg); 51 | REGION_ALIAS("rtc_fast", RTC_FAST); 52 | 53 | INCLUDE "hal-defaults.x" 54 | INCLUDE "rom-functions.x" 55 | 56 | 57 | SECTIONS { 58 | .text : ALIGN(4) 59 | { 60 | KEEP(*(.trap)); 61 | *(.trap.*); 62 | 63 | KEEP(*(.init)); 64 | KEEP(*(.init.rust)); 65 | KEEP(*(.text.abort)); 66 | *(.literal .text .literal.* .text.*) 67 | *(.rwtext.literal .rwtext .rwtext.literal.* .rwtext.*) 68 | } > iram 69 | 70 | .data : ALIGN(4) 71 | { 72 | _data_start = ABSOLUTE(.); 73 | . = ALIGN (4); 74 | 75 | *(.sdata .sdata.* .sdata2 .sdata2.*); 76 | *(.data .data.*); 77 | *(.data1) 78 | 79 | *(.rodata .rodata.*) 80 | *(.srodata .srodata.*) 81 | 82 | . = ALIGN(4); 83 | } > dram 84 | 85 | .bss (NOLOAD) : ALIGN(4) 86 | { 87 | _bss_start = ABSOLUTE(.); 88 | . = ALIGN (4); 89 | *(.dynsbss) 90 | *(.sbss) 91 | *(.sbss.*) 92 | *(.gnu.linkonce.sb.*) 93 | *(.scommon) 94 | *(.sbss2) 95 | *(.sbss2.*) 96 | *(.gnu.linkonce.sb2.*) 97 | *(.dynbss) 98 | *(.sbss .sbss.* .bss .bss.*); 99 | *(.share.mem) 100 | *(.gnu.linkonce.b.*) 101 | *(COMMON) 102 | _bss_end = ABSOLUTE(.); 103 | . = ALIGN(4); 104 | } > dram 105 | 106 | /* must be last segment using RWDATA */ 107 | .stack (NOLOAD) : ALIGN(4) 108 | { 109 | . = ALIGN (4); 110 | _stack_end = ABSOLUTE(.); 111 | _stack_end_cpu0 = ABSOLUTE(.); 112 | } > dram 113 | 114 | .rtc_fast.bss (NOLOAD) : 115 | { 116 | . = ALIGN(4); 117 | _rtc_fast_bss_start = ABSOLUTE(.); 118 | *(.rtc_fast.bss .rtc_fast.bss.*) 119 | _rtc_fast_bss_end = ABSOLUTE(.); 120 | . = ALIGN(4); 121 | } > rtc_fast 122 | 123 | .rtc_fast.persistent (NOLOAD) : 124 | { 125 | . = ALIGN(4); 126 | _rtc_fast_persistent_start = ABSOLUTE(.); 127 | *(.rtc_fast.persistent .rtc_fast.persistent.*) 128 | _rtc_fast_persistent_end = ABSOLUTE(.); 129 | . = ALIGN(4); 130 | } > rtc_fast 131 | 132 | .unused (NOLOAD) : 133 | { 134 | *(.eh_frame) 135 | } > rtc_fast 136 | } 137 | 138 | 139 | PROVIDE(_stack_start = ORIGIN(iram) + LENGTH(iram)); 140 | PROVIDE(_stack_start_cpu0 = ORIGIN(iram) + LENGTH(iram)); 141 | PROVIDE(__stack_chk_guard = _stack_end + 4096); 142 | 143 | PROVIDE(UserSoft = DefaultHandler); 144 | PROVIDE(SupervisorSoft = DefaultHandler); 145 | PROVIDE(MachineSoft = DefaultHandler); 146 | PROVIDE(UserTimer = DefaultHandler); 147 | PROVIDE(SupervisorTimer = DefaultHandler); 148 | PROVIDE(MachineTimer = DefaultHandler); 149 | PROVIDE(UserExternal = DefaultHandler); 150 | PROVIDE(SupervisorExternal = DefaultHandler); 151 | PROVIDE(MachineExternal = DefaultHandler); 152 | 153 | PROVIDE(ExceptionHandler = DefaultExceptionHandler); 154 | 155 | PROVIDE(__post_init = default_post_init); 156 | 157 | PROVIDE(_max_hart_id = 0); 158 | -------------------------------------------------------------------------------- /src/chip/esp32.rs: -------------------------------------------------------------------------------- 1 | use esp_println::println; 2 | 3 | pub const MMU_ACCESS_FLASH: u32 = 1 << 15; 4 | 5 | pub fn init_flash() { 6 | let spiconfig = unsafe { ets_efuse_get_spiconfig() }; 7 | 8 | pub const FLASH_SIZE: u32 = 0x1000000; 9 | pub const FLASH_STATUS_MASK: u32 = 0xFFFF; 10 | pub const FLASH_SECTOR_SIZE: u32 = 4096; 11 | pub const PAGE_SIZE: u32 = 0x4000; 12 | pub const FLASH_BLOCK_SIZE: u32 = 65536; 13 | 14 | // init flash 15 | let config_result = unsafe { 16 | esp_rom_spiflash_config_param( 17 | 0, 18 | FLASH_SIZE, // total_size 19 | FLASH_BLOCK_SIZE, // block_size 20 | FLASH_SECTOR_SIZE, // sector_size 21 | PAGE_SIZE, // page_size 22 | FLASH_STATUS_MASK, // status_mask 23 | ) 24 | }; 25 | 26 | if config_result == 0 { 27 | unsafe { esp_rom_spiflash_attach(spiconfig, false) }; 28 | } else { 29 | println!("Nope 💀"); 30 | } 31 | } 32 | 33 | pub fn init_mmu() -> u32 { 34 | // init mmu 35 | unsafe { 36 | mmu_init(0); 37 | mmu_init(1); 38 | 39 | // Cache_MMU_Init(); 40 | // Cache_Enable_ICache(1); 41 | 42 | // let autoload = Cache_Suspend_ICache(); 43 | // Cache_Invalidate_ICache_All(); 44 | 45 | // autoload 46 | 1 47 | } 48 | } 49 | 50 | pub fn resume_mmu(autoload: u32) { 51 | unsafe { 52 | const DR_REG_DPORT_BASE: usize = 0x3ff00000; 53 | const DPORT_PRO_CACHE_CTRL1_REG: usize = (DR_REG_DPORT_BASE + 0x044); 54 | // TODO DPORT_APP_CACHE_CTRL1_REG 55 | 56 | (DPORT_PRO_CACHE_CTRL1_REG as *mut u32) 57 | .write_volatile((DPORT_PRO_CACHE_CTRL1_REG as *mut u32).read_volatile() & !0b1001); 58 | 59 | Cache_Read_Enable_rom(0); 60 | } 61 | } 62 | 63 | pub fn is_drom(addr: u32) -> bool { 64 | addr >= 0x3F40_0000 && addr <= 0x3FBF_FFFF 65 | } 66 | 67 | pub fn is_ram(addr: usize) -> bool { 68 | !(addr >= 0x3F40_0000 && addr <= 0x3FBF_FFFF || addr >= 0x400C_2000 && addr <= 0x40BF_FFFF) 69 | } 70 | 71 | pub fn read_flash(flash_addr: u32, len: usize, data: &mut [u8]) { 72 | // read from flash 73 | if unsafe { esp_rom_spiflash_read(flash_addr, data.as_mut_ptr(), len as u32) } != 0 { 74 | println!("F"); 75 | } 76 | } 77 | 78 | pub fn dbus_mmu_set(vaddr: u32, paddr: u32, psize: u32, num: u32, fixed: u32) -> i32 { 79 | unsafe { 80 | cache_flash_mmu_set_rom(0, 0, vaddr, paddr, psize, num) 81 | | cache_flash_mmu_set_rom(1, 0, vaddr, paddr, psize, num) 82 | } 83 | } 84 | 85 | pub fn ibus_mmu_set(vaddr: u32, paddr: u32, psize: u32, num: u32, fixed: u32) -> i32 { 86 | unsafe { 87 | cache_flash_mmu_set_rom(0, 0, vaddr, paddr, psize, num) 88 | | cache_flash_mmu_set_rom(1, 0, vaddr, paddr, psize, num) 89 | } 90 | } 91 | 92 | extern "C" { 93 | // flash functions 94 | pub fn esp_rom_spiflash_attach(config: u32, legacy: bool); 95 | 96 | pub fn esp_rom_spiflash_config_param( 97 | device_id: u32, 98 | chip_size: u32, 99 | block_size: u32, 100 | sector_size: u32, 101 | page_size: u32, 102 | status_mask: u32, 103 | ) -> u32; 104 | 105 | pub fn ets_efuse_get_spiconfig() -> u32; 106 | 107 | pub fn esp_rom_spiflash_read(src_addr: u32, data: *mut u8, len: u32) -> i32; 108 | 109 | // mmu functions 110 | 111 | /** 112 | * @brief Set Flash-Cache mmu mapping. 113 | * Please do not call this function in your SDK application. 114 | * 115 | * @param int cpu_no : CPU number, 0 for PRO cpu, 1 for APP cpu. 116 | * 117 | * @param int pod : process identifier. Range 0~7. 118 | * 119 | * @param unsigned int vaddr : virtual address in CPU address space. 120 | * Can be IRam0, IRam1, IRom0 and DRom0 memory address. 121 | * Should be aligned by psize. 122 | * 123 | * @param unsigned int paddr : physical address in Flash. 124 | * Should be aligned by psize. 125 | * 126 | * @param int psize : page size of flash, in kilobytes. Should be 64 here. 127 | * 128 | * @param int num : pages to be set. 129 | * 130 | * @return unsigned int: error status 131 | * 0 : mmu set success 132 | * 1 : vaddr or paddr is not aligned 133 | * 2 : pid error 134 | * 3 : psize error 135 | * 4 : mmu table to be written is out of range 136 | * 5 : vaddr is out of range 137 | */ 138 | pub fn cache_flash_mmu_set_rom( 139 | cpu_no: u32, 140 | pid: u32, 141 | vaddr: u32, 142 | paddr: u32, 143 | psize: u32, 144 | num: u32, 145 | ) -> i32; 146 | 147 | pub fn mmu_init(cpu: u32); 148 | 149 | /** 150 | * @brief Enable Cache access for the cpu. 151 | * Please do not call this function in your SDK application. 152 | * 153 | * @param int cpu_no : 0 for PRO cpu, 1 for APP cpu. 154 | * 155 | * @return None 156 | */ 157 | pub fn Cache_Read_Enable_rom(cpu_no: u32); 158 | } 159 | -------------------------------------------------------------------------------- /src/chip/esp32s2.rs: -------------------------------------------------------------------------------- 1 | use esp_println::println; 2 | 3 | pub const MMU_ACCESS_FLASH: u32 = 1 << 15; 4 | 5 | pub fn init_flash() { 6 | // super-wdt-autofeed ... doesn't belong here - have a dedicated init function 7 | const DR_REG_RTCCNTL_BASE: usize = 0x3f408000; 8 | const RTC_CNTL_SWD_CONF_REG: usize = (DR_REG_RTCCNTL_BASE + 0x00B0); 9 | const RTC_CNTL_SWD_AUTO_FEED_EN: u32 = 1 << 31; 10 | 11 | unsafe { 12 | let ptr = RTC_CNTL_SWD_CONF_REG as *mut u32; 13 | ptr.write_volatile(ptr.read_volatile() | RTC_CNTL_SWD_AUTO_FEED_EN); 14 | } 15 | 16 | // actually init flash 17 | let spiconfig = unsafe { ets_efuse_get_spiconfig() }; 18 | 19 | pub const FLASH_SIZE: u32 = 0x1000000; 20 | pub const FLASH_STATUS_MASK: u32 = 0xFFFF; 21 | pub const FLASH_SECTOR_SIZE: u32 = 4096; 22 | pub const PAGE_SIZE: u32 = 0x4000; 23 | pub const FLASH_BLOCK_SIZE: u32 = 65536; 24 | 25 | // init flash 26 | let config_result = unsafe { 27 | esp_rom_spiflash_config_param( 28 | 0, 29 | FLASH_SIZE, // total_size 30 | FLASH_BLOCK_SIZE, // block_size 31 | FLASH_SECTOR_SIZE, // sector_size 32 | PAGE_SIZE, // page_size 33 | FLASH_STATUS_MASK, // status_mask 34 | ) 35 | }; 36 | 37 | if config_result == 0 { 38 | unsafe { esp_rom_spiflash_attach(spiconfig, false) }; 39 | } else { 40 | println!("Nope 💀"); 41 | } 42 | } 43 | 44 | pub fn init_mmu() -> u32 { 45 | // init mmu 46 | unsafe { 47 | Cache_MMU_Init(); 48 | // Cache_Enable_ICache(1); 49 | 50 | // let autoload = Cache_Suspend_ICache(); 51 | // Cache_Invalidate_ICache_All(); 52 | 53 | Cache_Disable_ICache(); 54 | Cache_Disable_DCache(); 55 | 56 | 1 57 | } 58 | } 59 | 60 | pub fn resume_mmu(autoload: u32) { 61 | unsafe { 62 | // enable bus 63 | const DR_REG_EXTMEM_BASE: u32 = 0x61800000; 64 | const EXTMEM_PRO_DCACHE_CTRL1_REG: u32 = DR_REG_EXTMEM_BASE + 0x004; 65 | const EXTMEM_PRO_ICACHE_CTRL1_REG: u32 = DR_REG_EXTMEM_BASE + 0x044; 66 | 67 | (EXTMEM_PRO_DCACHE_CTRL1_REG as *mut u32).write_volatile( 68 | 0b010, /*((EXTMEM_PRO_DCACHE_CTRL1_REG as *mut u32).read_volatile() & !0b101)*/ 69 | ); 70 | (EXTMEM_PRO_ICACHE_CTRL1_REG as *mut u32).write_volatile( 71 | 0b010, /*((EXTMEM_PRO_ICACHE_CTRL1_REG as *mut u32).read_volatile() & !0b101)*/ 72 | ); 73 | // also need for APP cpu 74 | 75 | Cache_Resume_ICache(1); 76 | Cache_Resume_DCache(1); 77 | 78 | Cache_Invalidate_ICache_All(); 79 | Cache_Invalidate_DCache_All(); 80 | 81 | Cache_Enable_DCache(1); 82 | Cache_Enable_ICache(1); 83 | } 84 | } 85 | 86 | pub fn is_drom(addr: u32) -> bool { 87 | addr >= 0x3F00_0000 && addr <= 0x3FF7_FFFF 88 | } 89 | 90 | pub fn is_ram(addr: usize) -> bool { 91 | !(addr >= 0x3F00_0000 && addr <= 0x3FF7_FFFF || addr >= 0x4008_0000 && addr <= 0x407F_FFFF) 92 | } 93 | 94 | pub fn read_flash(flash_addr: u32, len: usize, data: &mut [u8]) { 95 | // read from flash 96 | if unsafe { esp_rom_spiflash_read(flash_addr, data.as_mut_ptr(), len as u32) } != 0 { 97 | println!("F"); 98 | } 99 | } 100 | 101 | pub fn dbus_mmu_set(vaddr: u32, paddr: u32, psize: u32, num: u32, fixed: u32) -> i32 { 102 | // dbus doesn't seem to work for the used addr ranges????? 103 | unsafe { Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, vaddr, paddr, psize, num, fixed) } 104 | } 105 | 106 | pub fn ibus_mmu_set(vaddr: u32, paddr: u32, psize: u32, num: u32, fixed: u32) -> i32 { 107 | unsafe { Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, vaddr, paddr, psize, num, fixed) } 108 | } 109 | 110 | extern "C" { 111 | // flash functions 112 | pub fn esp_rom_spiflash_attach(config: u32, legacy: bool); 113 | 114 | pub fn esp_rom_spiflash_config_param( 115 | device_id: u32, 116 | chip_size: u32, 117 | block_size: u32, 118 | sector_size: u32, 119 | page_size: u32, 120 | status_mask: u32, 121 | ) -> u32; 122 | 123 | pub fn ets_efuse_get_spiconfig() -> u32; 124 | 125 | pub fn esp_rom_spiflash_read(src_addr: u32, data: *mut u8, len: u32) -> i32; 126 | 127 | // mmu functions 128 | pub fn Cache_Suspend_ICache() -> u32; 129 | pub fn Cache_Suspend_DCache() -> u32; 130 | 131 | pub fn Cache_Resume_ICache(val: u32); 132 | pub fn Cache_Resume_DCache(val: u32); 133 | 134 | pub fn Cache_Invalidate_ICache_All(); 135 | pub fn Cache_Invalidate_DCache_All(); 136 | 137 | pub fn Cache_Ibus_MMU_Set( 138 | ext_ram: u32, 139 | vaddr: u32, 140 | paddr: u32, 141 | psize: u32, 142 | num: u32, 143 | fixed: u32, 144 | ) -> i32; 145 | 146 | pub fn Cache_Dbus_MMU_Set( 147 | ext_ram: u32, 148 | vaddr: u32, 149 | paddr: u32, 150 | psize: u32, 151 | num: u32, 152 | fixed: u32, 153 | ) -> i32; 154 | 155 | pub fn Cache_MMU_Init(); 156 | 157 | pub fn Cache_Enable_ICache(autoload: u32); 158 | 159 | pub fn Cache_Enable_DCache(autoload: u32); 160 | 161 | pub fn Cache_Disable_ICache(); 162 | 163 | pub fn Cache_Disable_DCache(); 164 | } 165 | -------------------------------------------------------------------------------- /ld/link_esp32s2.x: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | /* Simplified memory map for the bootloader. 7 | * Make sure the bootloader can load into main memory without overwriting itself. 8 | */ 9 | 10 | 11 | MEMORY 12 | { 13 | iram_seg (RWX) : org = 0x4004A000, len = 0x4000 /* SRAM part of block 12 and 13 */ 14 | iram_loader_seg (RWX) : org = 0x4004E000, len = 0x7000 /* SRAM part of block 13, Block 14 & part of 15 */ 15 | dram_seg (RW) : org = 0x3FFE5000, len = 0x5B00 /* Part SRAM Blocks 15 & 16, ROM static buffer starts at end of this region (reclaimed after app runs) */ 16 | 17 | /* RTC fast memory (executable). Persists over deep sleep. Only for core 0 (PRO_CPU) */ 18 | rtc_fast_seg(RWX) : ORIGIN = 0x40070000, len = 8k 19 | 20 | /* RTC fast memory (same block as above), viewed from data bus. Only for core 0 (PRO_CPU) */ 21 | rtc_fast_dram_seg(RW) : ORIGIN = 0x3ff9e000, len = 8k 22 | 23 | /* RTC slow memory (data accessible). Persists over deep sleep. */ 24 | rtc_slow_seg(RW) : ORIGIN = 0x50000000, len = 8k 25 | } 26 | 27 | 28 | 29 | REGION_ALIAS("iram", iram_loader_seg); 30 | REGION_ALIAS("dram", dram_seg); 31 | REGION_ALIAS("rtc_fast", rtc_fast_seg); 32 | REGION_ALIAS("rtc_slow", rtc_slow_seg); 33 | 34 | ENTRY(ESP32Reset) 35 | 36 | PROVIDE(__pre_init = DefaultPreInit); 37 | PROVIDE(__zero_bss = default_mem_hook); 38 | PROVIDE(__init_data = default_mem_hook); 39 | PROVIDE(__post_init = default_post_init); 40 | 41 | PROVIDE(__level_1_interrupt = handle_interrupts); 42 | PROVIDE(__level_2_interrupt = handle_interrupts); 43 | PROVIDE(__level_3_interrupt = handle_interrupts); 44 | 45 | INCLUDE device.x 46 | 47 | INCLUDE "hal-defaults.x" 48 | INCLUDE "rom-functions.x" 49 | 50 | /* high level exception/interrupt routines, which can be override with Rust functions */ 51 | PROVIDE(__exception = __default_exception); 52 | PROVIDE(__user_exception = __default_user_exception); 53 | PROVIDE(__double_exception = __default_double_exception); 54 | PROVIDE(__level_1_interrupt = __default_interrupt); 55 | PROVIDE(__level_2_interrupt = __default_interrupt); 56 | PROVIDE(__level_3_interrupt = __default_interrupt); 57 | PROVIDE(__level_4_interrupt = __default_interrupt); 58 | PROVIDE(__level_5_interrupt = __default_interrupt); 59 | PROVIDE(__level_6_interrupt = __default_interrupt); 60 | PROVIDE(__level_7_interrupt = __default_interrupt); 61 | 62 | /* high level CPU interrupts */ 63 | PROVIDE(Timer0 = __default_user_exception); 64 | PROVIDE(Timer1 = __default_user_exception); 65 | PROVIDE(Timer2 = __default_user_exception); 66 | PROVIDE(Timer3 = __default_user_exception); 67 | PROVIDE(Profiling = __default_user_exception); 68 | PROVIDE(NMI = __default_user_exception); 69 | PROVIDE(Software0 = __default_user_exception); 70 | PROVIDE(Software1 = __default_user_exception); 71 | 72 | /* low level exception/interrupt, which must be overridden using naked functions */ 73 | PROVIDE(__naked_user_exception = __default_naked_exception); 74 | PROVIDE(__naked_kernel_exception = __default_naked_exception); 75 | PROVIDE(__naked_double_exception = __default_naked_double_exception); 76 | PROVIDE(__naked_level_2_interrupt = __default_naked_level_2_interrupt); 77 | PROVIDE(__naked_level_3_interrupt = __default_naked_level_3_interrupt); 78 | PROVIDE(__naked_level_4_interrupt = __default_naked_level_4_interrupt); 79 | PROVIDE(__naked_level_5_interrupt = __default_naked_level_5_interrupt); 80 | PROVIDE(__naked_level_6_interrupt = __default_naked_level_6_interrupt); 81 | PROVIDE(__naked_level_7_interrupt = __default_naked_level_7_interrupt); 82 | 83 | 84 | /* needed to force inclusion of the vectors */ 85 | EXTERN(__default_exception); 86 | EXTERN(__default_double_exception); 87 | EXTERN(__default_interrupt); 88 | 89 | EXTERN(__default_naked_exception); 90 | EXTERN(__default_naked_double_exception); 91 | EXTERN(__default_naked_level_2_interrupt); 92 | EXTERN(__default_naked_level_3_interrupt); 93 | EXTERN(__default_naked_level_4_interrupt); 94 | EXTERN(__default_naked_level_5_interrupt); 95 | EXTERN(__default_naked_level_6_interrupt); 96 | EXTERN(__default_naked_level_7_interrupt); 97 | 98 | SECTIONS { 99 | .vectors : 100 | { 101 | . = ALIGN(0x400); 102 | /* 103 | Each vector has 64 bytes that it must fit inside. For each vector we calculate the size of the previous one, 104 | and subtract that from 64 and start the new vector there. 105 | */ 106 | _init_start = ABSOLUTE(.); 107 | . = ALIGN(64); 108 | KEEP(*(.WindowOverflow4.text)); 109 | . = ALIGN(64); 110 | KEEP(*(.WindowUnderflow4.text)); 111 | . = ALIGN(64); 112 | KEEP(*(.WindowOverflow8.text)); 113 | . = ALIGN(64); 114 | KEEP(*(.WindowUnderflow8.text)); 115 | . = ALIGN(64); 116 | KEEP(*(.WindowOverflow12.text)); 117 | . = ALIGN(64); 118 | KEEP(*(.WindowUnderflow12.text)); 119 | . = ALIGN(64); 120 | KEEP(*(.Level2InterruptVector.text)); 121 | . = ALIGN(64); 122 | KEEP(*(.Level3InterruptVector.text)); 123 | . = ALIGN(64); 124 | KEEP(*(.Level4InterruptVector.text)); 125 | . = ALIGN(64); 126 | KEEP(*(.Level5InterruptVector.text)); 127 | . = ALIGN(64); 128 | KEEP(*(.DebugExceptionVector.text)); 129 | . = ALIGN(64); 130 | KEEP(*(.NMIExceptionVector.text)); 131 | . = ALIGN(64); 132 | KEEP(*(.KernelExceptionVector.text)); 133 | . = ALIGN(64); 134 | KEEP(*(.UserExceptionVector.text)); 135 | . = ALIGN(128); 136 | KEEP(*(.DoubleExceptionVector.text)); 137 | . = ALIGN(64); 138 | . = ALIGN(0x400); 139 | _init_end = ABSOLUTE(.); 140 | } > iram 141 | 142 | .text : ALIGN(4) 143 | { 144 | KEEP(*(.trap)); 145 | *(.trap.*); 146 | 147 | KEEP(*(.init)); 148 | KEEP(*(.init.rust)); 149 | KEEP(*(.text.abort)); 150 | *(.literal .text .literal.* .text.*) 151 | *(.rwtext.literal .rwtext .rwtext.literal.* .rwtext.*) 152 | } > iram 153 | 154 | .data : ALIGN(4) 155 | { 156 | _data_start = ABSOLUTE(.); 157 | . = ALIGN (4); 158 | 159 | *(.sdata .sdata.* .sdata2 .sdata2.*); 160 | *(.data .data.*); 161 | *(.data1) 162 | 163 | *(.rodata .rodata.*) 164 | *(.srodata .srodata.*) 165 | 166 | . = ALIGN(4); 167 | } > dram 168 | 169 | .bss (NOLOAD) : ALIGN(4) 170 | { 171 | _bss_start = ABSOLUTE(.); 172 | . = ALIGN (4); 173 | *(.dynsbss) 174 | *(.sbss) 175 | *(.sbss.*) 176 | *(.gnu.linkonce.sb.*) 177 | *(.scommon) 178 | *(.sbss2) 179 | *(.sbss2.*) 180 | *(.gnu.linkonce.sb2.*) 181 | *(.dynbss) 182 | *(.sbss .sbss.* .bss .bss.*); 183 | *(.share.mem) 184 | *(.gnu.linkonce.b.*) 185 | *(COMMON) 186 | _bss_end = ABSOLUTE(.); 187 | . = ALIGN(4); 188 | } > dram 189 | 190 | /* must be last segment using RWDATA */ 191 | .stack (NOLOAD) : ALIGN(4) 192 | { 193 | . = ALIGN (4); 194 | _stack_end = ABSOLUTE(.); 195 | _stack_end_cpu0 = ABSOLUTE(.); 196 | } > dram 197 | 198 | .rtc_slow.text : { 199 | . = ALIGN(4); 200 | *(.rtc_slow.literal .rtc_slow.text .rtc_slow.literal.* .rtc_slow.text.*) 201 | . = ALIGN(4); 202 | } > rtc_slow_seg 203 | 204 | .rtc_slow.data : 205 | { 206 | . = ALIGN(4); 207 | _rtc_slow_data_start = ABSOLUTE(.); 208 | *(.rtc_slow.data .rtc_slow.data.*) 209 | _rtc_slow_data_end = ABSOLUTE(.); 210 | . = ALIGN(4); 211 | } > rtc_slow_seg 212 | 213 | .rtc_slow.bss (NOLOAD) : 214 | { 215 | . = ALIGN(4); 216 | _rtc_slow_bss_start = ABSOLUTE(.); 217 | *(.rtc_slow.bss .rtc_slow.bss.*) 218 | _rtc_slow_bss_end = ABSOLUTE(.); 219 | . = ALIGN(4); 220 | } > rtc_slow_seg 221 | 222 | .rtc_slow.persistent (NOLOAD) : 223 | { 224 | . = ALIGN(4); 225 | _rtc_slow_persistent_start = ABSOLUTE(.); 226 | *(.rtc_slow.persistent .rtc_slow.persistent.*) 227 | _rtc_slow_persistent_end = ABSOLUTE(.); 228 | . = ALIGN(4); 229 | } > rtc_slow_seg 230 | 231 | .rtc_fast.text : { 232 | . = ALIGN(4); 233 | *(.rtc_fast.literal .rtc_fast.text .rtc_fast.literal.* .rtc_fast.text.*) 234 | . = ALIGN(4); 235 | } > rtc_fast_seg 236 | 237 | .rtc_fast.data : 238 | { 239 | . = ALIGN(4); 240 | _rtc_fast_data_start = ABSOLUTE(.); 241 | *(.rtc_fast.data .rtc_fast.data.*) 242 | _rtc_fast_data_end = ABSOLUTE(.); 243 | . = ALIGN(4); 244 | } > rtc_fast_seg 245 | 246 | .rtc_fast.bss (NOLOAD) : 247 | { 248 | . = ALIGN(4); 249 | _rtc_fast_bss_start = ABSOLUTE(.); 250 | *(.rtc_fast.bss .rtc_fast.bss.*) 251 | _rtc_fast_bss_end = ABSOLUTE(.); 252 | . = ALIGN(4); 253 | } > rtc_fast_seg 254 | 255 | .rtc_fast.persistent (NOLOAD) : 256 | { 257 | . = ALIGN(4); 258 | _rtc_fast_persistent_start = ABSOLUTE(.); 259 | *(.rtc_fast.persistent .rtc_fast.persistent.*) 260 | _rtc_fast_persistent_end = ABSOLUTE(.); 261 | . = ALIGN(4); 262 | } > rtc_fast_seg 263 | 264 | .unused (NOLOAD) : 265 | { 266 | *(.eh_frame) 267 | } > rtc_fast 268 | } 269 | 270 | 271 | PROVIDE(_stack_start = ORIGIN(dram) + LENGTH(iram)); 272 | PROVIDE(_stack_start_cpu0 = ORIGIN(dram) + LENGTH(iram)); 273 | PROVIDE(__stack_chk_guard = _stack_end + 4096); 274 | -------------------------------------------------------------------------------- /ld/link_esp32.x: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | /* 7 | Linker file used to link the bootloader. 8 | */ 9 | 10 | 11 | /* Simplified memory map for the bootloader 12 | 13 | The main purpose is to make sure the bootloader can load into main memory 14 | without overwriting itself. 15 | */ 16 | 17 | MEMORY 18 | { 19 | /* IRAM POOL1, used for APP CPU cache. Bootloader runs from here during the final stage of loading the app because APP CPU is still held in reset, the main app enables APP CPU cache */ 20 | iram_loader_seg (RWX) : org = 0x40078000, len = 0x8000 /* 32KB, APP CPU cache */ 21 | /* 63kB, IRAM. We skip the first 1k to prevent the entry point being 22 | placed into the same range as exception vectors in the app. 23 | This leads to idf_monitor decoding ROM bootloader "entry 0x40080xxx" 24 | message as one of the exception vectors, which looks scary to users. 25 | */ 26 | iram_seg (RWX) : org = 0x40080400, len = 0xfc00 27 | /* 64k at the end of DRAM, after ROM bootloader stack */ 28 | dram_seg (RW) : org = 0x3FFF0000, len = 0x6000 29 | 30 | /* RTC fast memory (executable). Persists over deep sleep. Only for core 0 (PRO_CPU) */ 31 | rtc_fast_seg(RWX) : ORIGIN = 0x400C0000, len = 8k 32 | 33 | /* RTC fast memory (same block as above), viewed from data bus. Only for core 0 (PRO_CPU) */ 34 | rtc_fast_dram_seg(RW) : ORIGIN = 0x3FF80000, len = 8k 35 | 36 | /* RTC slow memory (data accessible). Persists over deep sleep. */ 37 | rtc_slow_seg(RW) : ORIGIN = 0x50000000, len = 8k 38 | } 39 | 40 | 41 | 42 | REGION_ALIAS("iram", iram_loader_seg); 43 | REGION_ALIAS("dram", dram_seg); 44 | REGION_ALIAS("rtc_fast", rtc_fast_seg); 45 | REGION_ALIAS("rtc_slow", rtc_slow_seg); 46 | 47 | ENTRY(ESP32Reset) 48 | 49 | PROVIDE(__pre_init = DefaultPreInit); 50 | PROVIDE(__zero_bss = default_mem_hook); 51 | PROVIDE(__init_data = default_mem_hook); 52 | PROVIDE(__post_init = default_post_init); 53 | 54 | PROVIDE(__level_1_interrupt = handle_interrupts); 55 | PROVIDE(__level_2_interrupt = handle_interrupts); 56 | PROVIDE(__level_3_interrupt = handle_interrupts); 57 | 58 | INCLUDE device.x 59 | 60 | INCLUDE "hal-defaults.x" 61 | INCLUDE "rom-functions.x" 62 | 63 | /* high level exception/interrupt routines, which can be override with Rust functions */ 64 | PROVIDE(__exception = __default_exception); 65 | PROVIDE(__user_exception = __default_user_exception); 66 | PROVIDE(__double_exception = __default_double_exception); 67 | PROVIDE(__level_1_interrupt = __default_interrupt); 68 | PROVIDE(__level_2_interrupt = __default_interrupt); 69 | PROVIDE(__level_3_interrupt = __default_interrupt); 70 | PROVIDE(__level_4_interrupt = __default_interrupt); 71 | PROVIDE(__level_5_interrupt = __default_interrupt); 72 | PROVIDE(__level_6_interrupt = __default_interrupt); 73 | PROVIDE(__level_7_interrupt = __default_interrupt); 74 | 75 | /* high level CPU interrupts */ 76 | PROVIDE(Timer0 = __default_user_exception); 77 | PROVIDE(Timer1 = __default_user_exception); 78 | PROVIDE(Timer2 = __default_user_exception); 79 | PROVIDE(Timer3 = __default_user_exception); 80 | PROVIDE(Profiling = __default_user_exception); 81 | PROVIDE(NMI = __default_user_exception); 82 | PROVIDE(Software0 = __default_user_exception); 83 | PROVIDE(Software1 = __default_user_exception); 84 | 85 | /* low level exception/interrupt, which must be overridden using naked functions */ 86 | PROVIDE(__naked_user_exception = __default_naked_exception); 87 | PROVIDE(__naked_kernel_exception = __default_naked_exception); 88 | PROVIDE(__naked_double_exception = __default_naked_double_exception); 89 | PROVIDE(__naked_level_2_interrupt = __default_naked_level_2_interrupt); 90 | PROVIDE(__naked_level_3_interrupt = __default_naked_level_3_interrupt); 91 | PROVIDE(__naked_level_4_interrupt = __default_naked_level_4_interrupt); 92 | PROVIDE(__naked_level_5_interrupt = __default_naked_level_5_interrupt); 93 | PROVIDE(__naked_level_6_interrupt = __default_naked_level_6_interrupt); 94 | PROVIDE(__naked_level_7_interrupt = __default_naked_level_7_interrupt); 95 | 96 | 97 | /* needed to force inclusion of the vectors */ 98 | EXTERN(__default_exception); 99 | EXTERN(__default_double_exception); 100 | EXTERN(__default_interrupt); 101 | 102 | EXTERN(__default_naked_exception); 103 | EXTERN(__default_naked_double_exception); 104 | EXTERN(__default_naked_level_2_interrupt); 105 | EXTERN(__default_naked_level_3_interrupt); 106 | EXTERN(__default_naked_level_4_interrupt); 107 | EXTERN(__default_naked_level_5_interrupt); 108 | EXTERN(__default_naked_level_6_interrupt); 109 | EXTERN(__default_naked_level_7_interrupt); 110 | 111 | SECTIONS { 112 | .vectors : 113 | { 114 | . = ALIGN(0x400); 115 | /* 116 | Each vector has 64 bytes that it must fit inside. For each vector we calculate the size of the previous one, 117 | and subtract that from 64 and start the new vector there. 118 | */ 119 | _init_start = ABSOLUTE(.); 120 | . = ALIGN(64); 121 | KEEP(*(.WindowOverflow4.text)); 122 | . = ALIGN(64); 123 | KEEP(*(.WindowUnderflow4.text)); 124 | . = ALIGN(64); 125 | KEEP(*(.WindowOverflow8.text)); 126 | . = ALIGN(64); 127 | KEEP(*(.WindowUnderflow8.text)); 128 | . = ALIGN(64); 129 | KEEP(*(.WindowOverflow12.text)); 130 | . = ALIGN(64); 131 | KEEP(*(.WindowUnderflow12.text)); 132 | . = ALIGN(64); 133 | KEEP(*(.Level2InterruptVector.text)); 134 | . = ALIGN(64); 135 | KEEP(*(.Level3InterruptVector.text)); 136 | . = ALIGN(64); 137 | KEEP(*(.Level4InterruptVector.text)); 138 | . = ALIGN(64); 139 | KEEP(*(.Level5InterruptVector.text)); 140 | . = ALIGN(64); 141 | KEEP(*(.DebugExceptionVector.text)); 142 | . = ALIGN(64); 143 | KEEP(*(.NMIExceptionVector.text)); 144 | . = ALIGN(64); 145 | KEEP(*(.KernelExceptionVector.text)); 146 | . = ALIGN(64); 147 | KEEP(*(.UserExceptionVector.text)); 148 | . = ALIGN(128); 149 | KEEP(*(.DoubleExceptionVector.text)); 150 | . = ALIGN(64); 151 | . = ALIGN(0x400); 152 | _init_end = ABSOLUTE(.); 153 | } > iram 154 | 155 | .text : ALIGN(4) 156 | { 157 | KEEP(*(.trap)); 158 | *(.trap.*); 159 | 160 | KEEP(*(.init)); 161 | KEEP(*(.init.rust)); 162 | KEEP(*(.text.abort)); 163 | *(.literal .text .literal.* .text.*) 164 | *(.rwtext.literal .rwtext .rwtext.literal.* .rwtext.*) 165 | } > iram 166 | 167 | .data : ALIGN(4) 168 | { 169 | _data_start = ABSOLUTE(.); 170 | . = ALIGN (4); 171 | 172 | *(.sdata .sdata.* .sdata2 .sdata2.*); 173 | *(.data .data.*); 174 | *(.data1) 175 | 176 | *(.rodata .rodata.*) 177 | *(.srodata .srodata.*) 178 | 179 | . = ALIGN(4); 180 | } > dram 181 | 182 | .bss (NOLOAD) : ALIGN(4) 183 | { 184 | _bss_start = ABSOLUTE(.); 185 | . = ALIGN (4); 186 | *(.dynsbss) 187 | *(.sbss) 188 | *(.sbss.*) 189 | *(.gnu.linkonce.sb.*) 190 | *(.scommon) 191 | *(.sbss2) 192 | *(.sbss2.*) 193 | *(.gnu.linkonce.sb2.*) 194 | *(.dynbss) 195 | *(.sbss .sbss.* .bss .bss.*); 196 | *(.share.mem) 197 | *(.gnu.linkonce.b.*) 198 | *(COMMON) 199 | _bss_end = ABSOLUTE(.); 200 | . = ALIGN(4); 201 | } > dram 202 | 203 | /* must be last segment using RWDATA */ 204 | .stack (NOLOAD) : ALIGN(4) 205 | { 206 | . = ALIGN (4); 207 | _stack_end = ABSOLUTE(.); 208 | _stack_end_cpu0 = ABSOLUTE(.); 209 | } > dram 210 | 211 | .rtc_slow.text : { 212 | . = ALIGN(4); 213 | *(.rtc_slow.literal .rtc_slow.text .rtc_slow.literal.* .rtc_slow.text.*) 214 | . = ALIGN(4); 215 | } > rtc_slow_seg 216 | 217 | .rtc_slow.data : 218 | { 219 | . = ALIGN(4); 220 | _rtc_slow_data_start = ABSOLUTE(.); 221 | *(.rtc_slow.data .rtc_slow.data.*) 222 | _rtc_slow_data_end = ABSOLUTE(.); 223 | . = ALIGN(4); 224 | } > rtc_slow_seg 225 | 226 | .rtc_slow.bss (NOLOAD) : 227 | { 228 | . = ALIGN(4); 229 | _rtc_slow_bss_start = ABSOLUTE(.); 230 | *(.rtc_slow.bss .rtc_slow.bss.*) 231 | _rtc_slow_bss_end = ABSOLUTE(.); 232 | . = ALIGN(4); 233 | } > rtc_slow_seg 234 | 235 | .rtc_slow.persistent (NOLOAD) : 236 | { 237 | . = ALIGN(4); 238 | _rtc_slow_persistent_start = ABSOLUTE(.); 239 | *(.rtc_slow.persistent .rtc_slow.persistent.*) 240 | _rtc_slow_persistent_end = ABSOLUTE(.); 241 | . = ALIGN(4); 242 | } > rtc_slow_seg 243 | 244 | .rtc_fast.text : { 245 | . = ALIGN(4); 246 | *(.rtc_fast.literal .rtc_fast.text .rtc_fast.literal.* .rtc_fast.text.*) 247 | . = ALIGN(4); 248 | } > rtc_fast_seg 249 | 250 | .rtc_fast.data : 251 | { 252 | . = ALIGN(4); 253 | _rtc_fast_data_start = ABSOLUTE(.); 254 | *(.rtc_fast.data .rtc_fast.data.*) 255 | _rtc_fast_data_end = ABSOLUTE(.); 256 | . = ALIGN(4); 257 | } > rtc_fast_seg 258 | 259 | .rtc_fast.bss (NOLOAD) : 260 | { 261 | . = ALIGN(4); 262 | _rtc_fast_bss_start = ABSOLUTE(.); 263 | *(.rtc_fast.bss .rtc_fast.bss.*) 264 | _rtc_fast_bss_end = ABSOLUTE(.); 265 | . = ALIGN(4); 266 | } > rtc_fast_seg 267 | 268 | .rtc_fast.persistent (NOLOAD) : 269 | { 270 | . = ALIGN(4); 271 | _rtc_fast_persistent_start = ABSOLUTE(.); 272 | *(.rtc_fast.persistent .rtc_fast.persistent.*) 273 | _rtc_fast_persistent_end = ABSOLUTE(.); 274 | . = ALIGN(4); 275 | } > rtc_fast_seg 276 | 277 | .unused (NOLOAD) : 278 | { 279 | *(.eh_frame) 280 | } > rtc_fast 281 | } 282 | 283 | 284 | PROVIDE(_stack_start = ORIGIN(dram) + LENGTH(iram)); 285 | PROVIDE(_stack_start_cpu0 = ORIGIN(dram) + LENGTH(iram)); 286 | PROVIDE(__stack_chk_guard = _stack_end + 4096); 287 | 288 | -------------------------------------------------------------------------------- /ld/link_esp32s3.x: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | /** Simplified memory map for the bootloader. 7 | * Make sure the bootloader can load into main memory without overwriting itself. 8 | * 9 | * ESP32-S3 ROM static data usage is as follows: 10 | * - 0x3fcd7e00 - 0x3fce9704: Shared buffers, used in UART/USB/SPI download mode only 11 | * - 0x3fce9710 - 0x3fceb710: PRO CPU stack, can be reclaimed as heap after RTOS startup 12 | * - 0x3fceb710 - 0x3fced710: APP CPU stack, can be reclaimed as heap after RTOS startup 13 | * - 0x3fced710 - 0x3fcf0000: ROM .bss and .data (not easily reclaimable) 14 | * 15 | * The 2nd stage bootloader can take space up to the end of ROM shared 16 | * buffers area (0x3fce9704). For alignment purpose we shall use value (0x3fce9700). 17 | */ 18 | 19 | /* The offset between Dbus and Ibus. Used to convert between 0x403xxxxx and 0x3fcxxxxx addresses. */ 20 | iram_dram_offset = 0x6f0000; 21 | 22 | /* We consider 0x3fce9700 to be the last usable address for 2nd stage bootloader stack overhead, dram_seg, 23 | * and work out iram_seg and iram_loader_seg addresses from there, backwards. 24 | */ 25 | 26 | /* These lengths can be adjusted, if necessary: */ 27 | bootloader_usable_dram_end = 0x3fce9700; 28 | bootloader_stack_overhead = 0x2000; /* For safety margin between bootloader data section and startup stacks */ 29 | bootloader_dram_seg_len = 0x5000; 30 | bootloader_iram_loader_seg_len = 0x7000; 31 | bootloader_iram_seg_len = 0x3000; 32 | 33 | /* Start of the lower region is determined by region size and the end of the higher region */ 34 | bootloader_dram_seg_end = bootloader_usable_dram_end - bootloader_stack_overhead; 35 | bootloader_dram_seg_start = bootloader_dram_seg_end - bootloader_dram_seg_len; 36 | bootloader_iram_loader_seg_start = bootloader_dram_seg_start - bootloader_iram_loader_seg_len + iram_dram_offset; 37 | bootloader_iram_seg_start = bootloader_iram_loader_seg_start - bootloader_iram_seg_len; 38 | 39 | MEMORY 40 | { 41 | iram_seg (RWX) : org = bootloader_iram_seg_start, len = bootloader_iram_seg_len 42 | iram_loader_seg (RWX) : org = bootloader_iram_loader_seg_start, len = bootloader_iram_loader_seg_len 43 | dram_seg (RW) : org = bootloader_dram_seg_start, len = bootloader_dram_seg_len 44 | 45 | RTC_FAST : ORIGIN = 0x50000000, LENGTH = 0x2000 46 | 47 | /* RTC fast memory (executable). Persists over deep sleep. Only for core 0 (PRO_CPU) */ 48 | rtc_fast_seg(RWX) : ORIGIN = 0x600fe000, len = 8k 49 | 50 | /* RTC slow memory (data accessible). Persists over deep sleep. */ 51 | rtc_slow_seg(RW) : ORIGIN = 0x50000000, len = 8k 52 | } 53 | 54 | 55 | REGION_ALIAS("iram", iram_loader_seg); 56 | REGION_ALIAS("dram", dram_seg); 57 | REGION_ALIAS("rtc_fast", rtc_fast_seg); 58 | REGION_ALIAS("rtc_slow", rtc_slow_seg); 59 | 60 | ENTRY(ESP32Reset) 61 | 62 | PROVIDE(__pre_init = DefaultPreInit); 63 | PROVIDE(__zero_bss = default_mem_hook); 64 | PROVIDE(__init_data = default_mem_hook); 65 | PROVIDE(__post_init = default_post_init); 66 | 67 | PROVIDE(__level_1_interrupt = handle_interrupts); 68 | PROVIDE(__level_2_interrupt = handle_interrupts); 69 | PROVIDE(__level_3_interrupt = handle_interrupts); 70 | 71 | INCLUDE device.x 72 | 73 | INCLUDE "hal-defaults.x" 74 | INCLUDE "rom-functions.x" 75 | 76 | /* high level exception/interrupt routines, which can be override with Rust functions */ 77 | PROVIDE(__exception = __default_exception); 78 | PROVIDE(__user_exception = __default_user_exception); 79 | PROVIDE(__double_exception = __default_double_exception); 80 | PROVIDE(__level_1_interrupt = __default_interrupt); 81 | PROVIDE(__level_2_interrupt = __default_interrupt); 82 | PROVIDE(__level_3_interrupt = __default_interrupt); 83 | PROVIDE(__level_4_interrupt = __default_interrupt); 84 | PROVIDE(__level_5_interrupt = __default_interrupt); 85 | PROVIDE(__level_6_interrupt = __default_interrupt); 86 | PROVIDE(__level_7_interrupt = __default_interrupt); 87 | 88 | /* high level CPU interrupts */ 89 | PROVIDE(Timer0 = __default_user_exception); 90 | PROVIDE(Timer1 = __default_user_exception); 91 | PROVIDE(Timer2 = __default_user_exception); 92 | PROVIDE(Timer3 = __default_user_exception); 93 | PROVIDE(Profiling = __default_user_exception); 94 | PROVIDE(NMI = __default_user_exception); 95 | PROVIDE(Software0 = __default_user_exception); 96 | PROVIDE(Software1 = __default_user_exception); 97 | 98 | /* low level exception/interrupt, which must be overridden using naked functions */ 99 | PROVIDE(__naked_user_exception = __default_naked_exception); 100 | PROVIDE(__naked_kernel_exception = __default_naked_exception); 101 | PROVIDE(__naked_double_exception = __default_naked_double_exception); 102 | PROVIDE(__naked_level_2_interrupt = __default_naked_level_2_interrupt); 103 | PROVIDE(__naked_level_3_interrupt = __default_naked_level_3_interrupt); 104 | PROVIDE(__naked_level_4_interrupt = __default_naked_level_4_interrupt); 105 | PROVIDE(__naked_level_5_interrupt = __default_naked_level_5_interrupt); 106 | PROVIDE(__naked_level_6_interrupt = __default_naked_level_6_interrupt); 107 | PROVIDE(__naked_level_7_interrupt = __default_naked_level_7_interrupt); 108 | 109 | 110 | /* needed to force inclusion of the vectors */ 111 | EXTERN(__default_exception); 112 | EXTERN(__default_double_exception); 113 | EXTERN(__default_interrupt); 114 | 115 | EXTERN(__default_naked_exception); 116 | EXTERN(__default_naked_double_exception); 117 | EXTERN(__default_naked_level_2_interrupt); 118 | EXTERN(__default_naked_level_3_interrupt); 119 | EXTERN(__default_naked_level_4_interrupt); 120 | EXTERN(__default_naked_level_5_interrupt); 121 | EXTERN(__default_naked_level_6_interrupt); 122 | EXTERN(__default_naked_level_7_interrupt); 123 | 124 | SECTIONS { 125 | .vectors : 126 | { 127 | . = ALIGN(0x400); 128 | /* 129 | Each vector has 64 bytes that it must fit inside. For each vector we calculate the size of the previous one, 130 | and subtract that from 64 and start the new vector there. 131 | */ 132 | _init_start = ABSOLUTE(.); 133 | . = ALIGN(64); 134 | KEEP(*(.WindowOverflow4.text)); 135 | . = ALIGN(64); 136 | KEEP(*(.WindowUnderflow4.text)); 137 | . = ALIGN(64); 138 | KEEP(*(.WindowOverflow8.text)); 139 | . = ALIGN(64); 140 | KEEP(*(.WindowUnderflow8.text)); 141 | . = ALIGN(64); 142 | KEEP(*(.WindowOverflow12.text)); 143 | . = ALIGN(64); 144 | KEEP(*(.WindowUnderflow12.text)); 145 | . = ALIGN(64); 146 | KEEP(*(.Level2InterruptVector.text)); 147 | . = ALIGN(64); 148 | KEEP(*(.Level3InterruptVector.text)); 149 | . = ALIGN(64); 150 | KEEP(*(.Level4InterruptVector.text)); 151 | . = ALIGN(64); 152 | KEEP(*(.Level5InterruptVector.text)); 153 | . = ALIGN(64); 154 | KEEP(*(.DebugExceptionVector.text)); 155 | . = ALIGN(64); 156 | KEEP(*(.NMIExceptionVector.text)); 157 | . = ALIGN(64); 158 | KEEP(*(.KernelExceptionVector.text)); 159 | . = ALIGN(64); 160 | KEEP(*(.UserExceptionVector.text)); 161 | . = ALIGN(128); 162 | KEEP(*(.DoubleExceptionVector.text)); 163 | . = ALIGN(64); 164 | . = ALIGN(0x400); 165 | _init_end = ABSOLUTE(.); 166 | } > iram 167 | 168 | .text : ALIGN(4) 169 | { 170 | KEEP(*(.trap)); 171 | *(.trap.*); 172 | 173 | KEEP(*(.init)); 174 | KEEP(*(.init.rust)); 175 | KEEP(*(.text.abort)); 176 | *(.literal .text .literal.* .text.*) 177 | *(.rwtext.literal .rwtext .rwtext.literal.* .rwtext.*) 178 | } > iram 179 | 180 | .data : ALIGN(4) 181 | { 182 | _data_start = ABSOLUTE(.); 183 | . = ALIGN (4); 184 | 185 | *(.sdata .sdata.* .sdata2 .sdata2.*); 186 | *(.data .data.*); 187 | *(.data1) 188 | 189 | *(.rodata .rodata.*) 190 | *(.srodata .srodata.*) 191 | 192 | . = ALIGN(4); 193 | } > dram 194 | 195 | .bss (NOLOAD) : ALIGN(4) 196 | { 197 | _bss_start = ABSOLUTE(.); 198 | . = ALIGN (4); 199 | *(.dynsbss) 200 | *(.sbss) 201 | *(.sbss.*) 202 | *(.gnu.linkonce.sb.*) 203 | *(.scommon) 204 | *(.sbss2) 205 | *(.sbss2.*) 206 | *(.gnu.linkonce.sb2.*) 207 | *(.dynbss) 208 | *(.sbss .sbss.* .bss .bss.*); 209 | *(.share.mem) 210 | *(.gnu.linkonce.b.*) 211 | *(COMMON) 212 | _bss_end = ABSOLUTE(.); 213 | . = ALIGN(4); 214 | } > dram 215 | 216 | /* must be last segment using RWDATA */ 217 | .stack (NOLOAD) : ALIGN(4) 218 | { 219 | . = ALIGN (4); 220 | _stack_end = ABSOLUTE(.); 221 | _stack_end_cpu0 = ABSOLUTE(.); 222 | } > dram 223 | 224 | .rtc_slow.text : { 225 | . = ALIGN(4); 226 | *(.rtc_slow.literal .rtc_slow.text .rtc_slow.literal.* .rtc_slow.text.*) 227 | . = ALIGN(4); 228 | } > rtc_slow_seg 229 | 230 | .rtc_slow.data : 231 | { 232 | . = ALIGN(4); 233 | _rtc_slow_data_start = ABSOLUTE(.); 234 | *(.rtc_slow.data .rtc_slow.data.*) 235 | _rtc_slow_data_end = ABSOLUTE(.); 236 | . = ALIGN(4); 237 | } > rtc_slow_seg 238 | 239 | .rtc_slow.bss (NOLOAD) : 240 | { 241 | . = ALIGN(4); 242 | _rtc_slow_bss_start = ABSOLUTE(.); 243 | *(.rtc_slow.bss .rtc_slow.bss.*) 244 | _rtc_slow_bss_end = ABSOLUTE(.); 245 | . = ALIGN(4); 246 | } > rtc_slow_seg 247 | 248 | .rtc_slow.persistent (NOLOAD) : 249 | { 250 | . = ALIGN(4); 251 | _rtc_slow_persistent_start = ABSOLUTE(.); 252 | *(.rtc_slow.persistent .rtc_slow.persistent.*) 253 | _rtc_slow_persistent_end = ABSOLUTE(.); 254 | . = ALIGN(4); 255 | } > rtc_slow_seg 256 | 257 | .rtc_fast.text : { 258 | . = ALIGN(4); 259 | *(.rtc_fast.literal .rtc_fast.text .rtc_fast.literal.* .rtc_fast.text.*) 260 | . = ALIGN(4); 261 | } > rtc_fast_seg 262 | 263 | .rtc_fast.data : 264 | { 265 | . = ALIGN(4); 266 | _rtc_fast_data_start = ABSOLUTE(.); 267 | *(.rtc_fast.data .rtc_fast.data.*) 268 | _rtc_fast_data_end = ABSOLUTE(.); 269 | . = ALIGN(4); 270 | } > rtc_fast_seg 271 | 272 | .rtc_fast.bss (NOLOAD) : 273 | { 274 | . = ALIGN(4); 275 | _rtc_fast_bss_start = ABSOLUTE(.); 276 | *(.rtc_fast.bss .rtc_fast.bss.*) 277 | _rtc_fast_bss_end = ABSOLUTE(.); 278 | . = ALIGN(4); 279 | } > rtc_fast_seg 280 | 281 | .rtc_fast.persistent (NOLOAD) : 282 | { 283 | . = ALIGN(4); 284 | _rtc_fast_persistent_start = ABSOLUTE(.); 285 | *(.rtc_fast.persistent .rtc_fast.persistent.*) 286 | _rtc_fast_persistent_end = ABSOLUTE(.); 287 | . = ALIGN(4); 288 | } > rtc_fast_seg 289 | 290 | .unused (NOLOAD) : 291 | { 292 | *(.eh_frame) 293 | } > rtc_fast 294 | } 295 | 296 | 297 | PROVIDE(_stack_start = ORIGIN(dram) + LENGTH(iram)); 298 | PROVIDE(_stack_start_cpu0 = ORIGIN(dram) + LENGTH(iram)); 299 | PROVIDE(__stack_chk_guard = _stack_end + 4096); 300 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "anyhow" 7 | version = "1.0.95" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" 10 | 11 | [[package]] 12 | name = "autocfg" 13 | version = "1.4.0" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" 16 | 17 | [[package]] 18 | name = "basic-toml" 19 | version = "0.1.9" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | checksum = "823388e228f614e9558c6804262db37960ec8821856535f5c3f59913140558f8" 22 | dependencies = [ 23 | "serde", 24 | ] 25 | 26 | [[package]] 27 | name = "bitfield" 28 | version = "0.17.0" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "f798d2d157e547aa99aab0967df39edd0b70307312b6f8bd2848e6abe40896e0" 31 | 32 | [[package]] 33 | name = "bitflags" 34 | version = "2.8.0" 35 | source = "registry+https://github.com/rust-lang/crates.io-index" 36 | checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" 37 | 38 | [[package]] 39 | name = "bytemuck" 40 | version = "1.21.0" 41 | source = "registry+https://github.com/rust-lang/crates.io-index" 42 | checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" 43 | 44 | [[package]] 45 | name = "byteorder" 46 | version = "1.5.0" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 49 | 50 | [[package]] 51 | name = "cfg-if" 52 | version = "1.0.0" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 55 | 56 | [[package]] 57 | name = "chrono" 58 | version = "0.4.39" 59 | source = "registry+https://github.com/rust-lang/crates.io-index" 60 | checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" 61 | dependencies = [ 62 | "num-traits", 63 | ] 64 | 65 | [[package]] 66 | name = "critical-section" 67 | version = "1.2.0" 68 | source = "registry+https://github.com/rust-lang/crates.io-index" 69 | checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" 70 | 71 | [[package]] 72 | name = "darling" 73 | version = "0.20.10" 74 | source = "registry+https://github.com/rust-lang/crates.io-index" 75 | checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" 76 | dependencies = [ 77 | "darling_core", 78 | "darling_macro", 79 | ] 80 | 81 | [[package]] 82 | name = "darling_core" 83 | version = "0.20.10" 84 | source = "registry+https://github.com/rust-lang/crates.io-index" 85 | checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" 86 | dependencies = [ 87 | "fnv", 88 | "ident_case", 89 | "proc-macro2", 90 | "quote", 91 | "strsim", 92 | "syn", 93 | ] 94 | 95 | [[package]] 96 | name = "darling_macro" 97 | version = "0.20.10" 98 | source = "registry+https://github.com/rust-lang/crates.io-index" 99 | checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" 100 | dependencies = [ 101 | "darling_core", 102 | "quote", 103 | "syn", 104 | ] 105 | 106 | [[package]] 107 | name = "delegate" 108 | version = "0.13.2" 109 | source = "registry+https://github.com/rust-lang/crates.io-index" 110 | checksum = "297806318ef30ad066b15792a8372858020ae3ca2e414ee6c2133b1eb9e9e945" 111 | dependencies = [ 112 | "proc-macro2", 113 | "quote", 114 | "syn", 115 | ] 116 | 117 | [[package]] 118 | name = "document-features" 119 | version = "0.2.10" 120 | source = "registry+https://github.com/rust-lang/crates.io-index" 121 | checksum = "cb6969eaabd2421f8a2775cfd2471a2b634372b4a25d41e3bd647b79912850a0" 122 | dependencies = [ 123 | "litrs", 124 | ] 125 | 126 | [[package]] 127 | name = "embassy-embedded-hal" 128 | version = "0.3.0" 129 | source = "registry+https://github.com/rust-lang/crates.io-index" 130 | checksum = "41fea5ef5bed4d3468dfd44f5c9fa4cda8f54c86d4fb4ae683eacf9d39e2ea12" 131 | dependencies = [ 132 | "embassy-futures", 133 | "embassy-sync", 134 | "embassy-time", 135 | "embedded-hal 0.2.7", 136 | "embedded-hal 1.0.0", 137 | "embedded-hal-async", 138 | "embedded-storage", 139 | "embedded-storage-async", 140 | "nb 1.1.0", 141 | ] 142 | 143 | [[package]] 144 | name = "embassy-futures" 145 | version = "0.1.1" 146 | source = "registry+https://github.com/rust-lang/crates.io-index" 147 | checksum = "1f878075b9794c1e4ac788c95b728f26aa6366d32eeb10c7051389f898f7d067" 148 | 149 | [[package]] 150 | name = "embassy-sync" 151 | version = "0.6.2" 152 | source = "registry+https://github.com/rust-lang/crates.io-index" 153 | checksum = "8d2c8cdff05a7a51ba0087489ea44b0b1d97a296ca6b1d6d1a33ea7423d34049" 154 | dependencies = [ 155 | "cfg-if", 156 | "critical-section", 157 | "embedded-io-async", 158 | "futures-sink", 159 | "futures-util", 160 | "heapless", 161 | ] 162 | 163 | [[package]] 164 | name = "embassy-time" 165 | version = "0.4.0" 166 | source = "registry+https://github.com/rust-lang/crates.io-index" 167 | checksum = "f820157f198ada183ad62e0a66f554c610cdcd1a9f27d4b316358103ced7a1f8" 168 | dependencies = [ 169 | "cfg-if", 170 | "critical-section", 171 | "document-features", 172 | "embassy-time-driver", 173 | "embedded-hal 0.2.7", 174 | "embedded-hal 1.0.0", 175 | "embedded-hal-async", 176 | "futures-util", 177 | ] 178 | 179 | [[package]] 180 | name = "embassy-time-driver" 181 | version = "0.2.0" 182 | source = "registry+https://github.com/rust-lang/crates.io-index" 183 | checksum = "8d45f5d833b6d98bd2aab0c2de70b18bfaa10faf661a1578fd8e5dfb15eb7eba" 184 | dependencies = [ 185 | "document-features", 186 | ] 187 | 188 | [[package]] 189 | name = "embassy-usb-driver" 190 | version = "0.1.0" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | checksum = "4fc247028eae04174b6635104a35b1ed336aabef4654f5e87a8f32327d231970" 193 | 194 | [[package]] 195 | name = "embassy-usb-synopsys-otg" 196 | version = "0.2.0" 197 | source = "registry+https://github.com/rust-lang/crates.io-index" 198 | checksum = "08e753b23799329780c7ac434264026d0422044d6649ed70a73441b14a6436d7" 199 | dependencies = [ 200 | "critical-section", 201 | "embassy-sync", 202 | "embassy-usb-driver", 203 | ] 204 | 205 | [[package]] 206 | name = "embedded-can" 207 | version = "0.4.1" 208 | source = "registry+https://github.com/rust-lang/crates.io-index" 209 | checksum = "e9d2e857f87ac832df68fa498d18ddc679175cf3d2e4aa893988e5601baf9438" 210 | dependencies = [ 211 | "nb 1.1.0", 212 | ] 213 | 214 | [[package]] 215 | name = "embedded-hal" 216 | version = "0.2.7" 217 | source = "registry+https://github.com/rust-lang/crates.io-index" 218 | checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" 219 | dependencies = [ 220 | "nb 0.1.3", 221 | "void", 222 | ] 223 | 224 | [[package]] 225 | name = "embedded-hal" 226 | version = "1.0.0" 227 | source = "registry+https://github.com/rust-lang/crates.io-index" 228 | checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" 229 | 230 | [[package]] 231 | name = "embedded-hal-async" 232 | version = "1.0.0" 233 | source = "registry+https://github.com/rust-lang/crates.io-index" 234 | checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884" 235 | dependencies = [ 236 | "embedded-hal 1.0.0", 237 | ] 238 | 239 | [[package]] 240 | name = "embedded-hal-nb" 241 | version = "1.0.0" 242 | source = "registry+https://github.com/rust-lang/crates.io-index" 243 | checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605" 244 | dependencies = [ 245 | "embedded-hal 1.0.0", 246 | "nb 1.1.0", 247 | ] 248 | 249 | [[package]] 250 | name = "embedded-io" 251 | version = "0.6.1" 252 | source = "registry+https://github.com/rust-lang/crates.io-index" 253 | checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" 254 | 255 | [[package]] 256 | name = "embedded-io-async" 257 | version = "0.6.1" 258 | source = "registry+https://github.com/rust-lang/crates.io-index" 259 | checksum = "3ff09972d4073aa8c299395be75161d582e7629cd663171d62af73c8d50dba3f" 260 | dependencies = [ 261 | "embedded-io", 262 | ] 263 | 264 | [[package]] 265 | name = "embedded-storage" 266 | version = "0.3.1" 267 | source = "registry+https://github.com/rust-lang/crates.io-index" 268 | checksum = "a21dea9854beb860f3062d10228ce9b976da520a73474aed3171ec276bc0c032" 269 | 270 | [[package]] 271 | name = "embedded-storage-async" 272 | version = "0.4.1" 273 | source = "registry+https://github.com/rust-lang/crates.io-index" 274 | checksum = "1763775e2323b7d5f0aa6090657f5e21cfa02ede71f5dc40eead06d64dcd15cc" 275 | dependencies = [ 276 | "embedded-storage", 277 | ] 278 | 279 | [[package]] 280 | name = "enum-as-inner" 281 | version = "0.6.1" 282 | source = "registry+https://github.com/rust-lang/crates.io-index" 283 | checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" 284 | dependencies = [ 285 | "heck", 286 | "proc-macro2", 287 | "quote", 288 | "syn", 289 | ] 290 | 291 | [[package]] 292 | name = "enumset" 293 | version = "1.1.5" 294 | source = "registry+https://github.com/rust-lang/crates.io-index" 295 | checksum = "d07a4b049558765cef5f0c1a273c3fc57084d768b44d2f98127aef4cceb17293" 296 | dependencies = [ 297 | "enumset_derive", 298 | ] 299 | 300 | [[package]] 301 | name = "enumset_derive" 302 | version = "0.10.0" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | checksum = "59c3b24c345d8c314966bdc1832f6c2635bfcce8e7cf363bd115987bba2ee242" 305 | dependencies = [ 306 | "darling", 307 | "proc-macro2", 308 | "quote", 309 | "syn", 310 | ] 311 | 312 | [[package]] 313 | name = "equivalent" 314 | version = "1.0.1" 315 | source = "registry+https://github.com/rust-lang/crates.io-index" 316 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 317 | 318 | [[package]] 319 | name = "esp-build" 320 | version = "0.2.0" 321 | source = "registry+https://github.com/rust-lang/crates.io-index" 322 | checksum = "8aa1c8f9954c9506699cf1ca10a2adcc226ff10b6ae3cb9e875cf2c6a0b9a372" 323 | dependencies = [ 324 | "quote", 325 | "syn", 326 | "termcolor", 327 | ] 328 | 329 | [[package]] 330 | name = "esp-config" 331 | version = "0.3.0" 332 | source = "registry+https://github.com/rust-lang/crates.io-index" 333 | checksum = "bd428a3b4b2975772f24eabea123d45cf6a5e28020396ed5dcb331ee3a904046" 334 | dependencies = [ 335 | "document-features", 336 | ] 337 | 338 | [[package]] 339 | name = "esp-hal" 340 | version = "0.23.1" 341 | source = "registry+https://github.com/rust-lang/crates.io-index" 342 | checksum = "a573175c540fd1d21a9cf07b0dee286b5a8f4cfde4b35da0f4f4657de7942c45" 343 | dependencies = [ 344 | "basic-toml", 345 | "bitfield", 346 | "bitflags", 347 | "bytemuck", 348 | "cfg-if", 349 | "chrono", 350 | "critical-section", 351 | "delegate", 352 | "document-features", 353 | "embassy-embedded-hal", 354 | "embassy-futures", 355 | "embassy-sync", 356 | "embassy-usb-driver", 357 | "embassy-usb-synopsys-otg", 358 | "embedded-can", 359 | "embedded-hal 1.0.0", 360 | "embedded-hal-async", 361 | "embedded-hal-nb", 362 | "embedded-io", 363 | "embedded-io-async", 364 | "enumset", 365 | "esp-build", 366 | "esp-config", 367 | "esp-hal-procmacros", 368 | "esp-metadata", 369 | "esp-riscv-rt", 370 | "esp-synopsys-usb-otg", 371 | "esp32", 372 | "esp32c2", 373 | "esp32c3", 374 | "esp32c6", 375 | "esp32h2", 376 | "esp32s2", 377 | "esp32s3", 378 | "fugit", 379 | "instability", 380 | "nb 1.1.0", 381 | "paste", 382 | "portable-atomic", 383 | "rand_core", 384 | "riscv", 385 | "serde", 386 | "strum", 387 | "ufmt-write", 388 | "usb-device", 389 | "void", 390 | "xtensa-lx", 391 | "xtensa-lx-rt", 392 | ] 393 | 394 | [[package]] 395 | name = "esp-hal-procmacros" 396 | version = "0.16.0" 397 | source = "registry+https://github.com/rust-lang/crates.io-index" 398 | checksum = "e4a3297005c2b31cd00e2ba50037edc9bddf99da3afe1c97a2d1b0165a312eab" 399 | dependencies = [ 400 | "darling", 401 | "document-features", 402 | "litrs", 403 | "object", 404 | "proc-macro-crate", 405 | "proc-macro-error2", 406 | "proc-macro2", 407 | "quote", 408 | "syn", 409 | ] 410 | 411 | [[package]] 412 | name = "esp-metadata" 413 | version = "0.5.0" 414 | source = "registry+https://github.com/rust-lang/crates.io-index" 415 | checksum = "fb15c17e50f4cccb0d88305c19eae2d5533d750f0a05b6a05f1c99864974758e" 416 | dependencies = [ 417 | "anyhow", 418 | "basic-toml", 419 | "serde", 420 | "strum", 421 | ] 422 | 423 | [[package]] 424 | name = "esp-println" 425 | version = "0.13.0" 426 | source = "registry+https://github.com/rust-lang/crates.io-index" 427 | checksum = "645e54eb592ca0a3d60213b1695e2a5fc0b51ca6d693c08d6983857224a629ed" 428 | dependencies = [ 429 | "critical-section", 430 | "esp-build", 431 | "log", 432 | "portable-atomic", 433 | ] 434 | 435 | [[package]] 436 | name = "esp-riscv-rt" 437 | version = "0.9.1" 438 | source = "registry+https://github.com/rust-lang/crates.io-index" 439 | checksum = "94aca65db6157aa5f42d9df6595b21462f28207ca4230b799aa3620352ef6a72" 440 | dependencies = [ 441 | "document-features", 442 | "riscv", 443 | "riscv-rt-macros", 444 | ] 445 | 446 | [[package]] 447 | name = "esp-synopsys-usb-otg" 448 | version = "0.4.2" 449 | source = "registry+https://github.com/rust-lang/crates.io-index" 450 | checksum = "8938451cb19032f13365328ea66ab38c8d16deecdf322067442297110eb74468" 451 | dependencies = [ 452 | "critical-section", 453 | "embedded-hal 0.2.7", 454 | "ral-registers", 455 | "usb-device", 456 | "vcell", 457 | ] 458 | 459 | [[package]] 460 | name = "esp32" 461 | version = "0.35.0" 462 | source = "registry+https://github.com/rust-lang/crates.io-index" 463 | checksum = "19d3bff1d268a4b8d34b494c0e88466cd59a827bb330189773db299ff525ea13" 464 | dependencies = [ 465 | "critical-section", 466 | "vcell", 467 | ] 468 | 469 | [[package]] 470 | name = "esp32c2" 471 | version = "0.24.0" 472 | source = "registry+https://github.com/rust-lang/crates.io-index" 473 | checksum = "0285be5b9dc4018d7f31fefe4c3d17f56461ef3ab46300ea1bf9d760968957f0" 474 | dependencies = [ 475 | "critical-section", 476 | "vcell", 477 | ] 478 | 479 | [[package]] 480 | name = "esp32c3" 481 | version = "0.27.0" 482 | source = "registry+https://github.com/rust-lang/crates.io-index" 483 | checksum = "61655d48e45039dfac5ae769581fb50ea7f61dea3227b4b744a1a900d03fbbd4" 484 | dependencies = [ 485 | "critical-section", 486 | "vcell", 487 | ] 488 | 489 | [[package]] 490 | name = "esp32c6" 491 | version = "0.18.0" 492 | source = "registry+https://github.com/rust-lang/crates.io-index" 493 | checksum = "fd38a7771b65cb640cc4a79324a6301ba4ac3bf2987caca5d3aa34492238fdb9" 494 | dependencies = [ 495 | "critical-section", 496 | "vcell", 497 | ] 498 | 499 | [[package]] 500 | name = "esp32h2" 501 | version = "0.14.0" 502 | source = "registry+https://github.com/rust-lang/crates.io-index" 503 | checksum = "a05aafc25d8c68ce504d8025750fc37915a2fc7d2605be3d3b51f8886a43411a" 504 | dependencies = [ 505 | "critical-section", 506 | "vcell", 507 | ] 508 | 509 | [[package]] 510 | name = "esp32s2" 511 | version = "0.26.0" 512 | source = "registry+https://github.com/rust-lang/crates.io-index" 513 | checksum = "0eb30ae371e72436629a70affedd1e3570829f16a3b718d6ec96508791d9da5e" 514 | dependencies = [ 515 | "critical-section", 516 | "vcell", 517 | ] 518 | 519 | [[package]] 520 | name = "esp32s3" 521 | version = "0.30.0" 522 | source = "registry+https://github.com/rust-lang/crates.io-index" 523 | checksum = "9f0ab39d5ae3b61b3a83f5616a03220a7dc9c4d6e4ed16d2da73d50bf8d798d7" 524 | dependencies = [ 525 | "critical-section", 526 | "vcell", 527 | ] 528 | 529 | [[package]] 530 | name = "fnv" 531 | version = "1.0.7" 532 | source = "registry+https://github.com/rust-lang/crates.io-index" 533 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 534 | 535 | [[package]] 536 | name = "fugit" 537 | version = "0.3.7" 538 | source = "registry+https://github.com/rust-lang/crates.io-index" 539 | checksum = "17186ad64927d5ac8f02c1e77ccefa08ccd9eaa314d5a4772278aa204a22f7e7" 540 | dependencies = [ 541 | "gcd", 542 | ] 543 | 544 | [[package]] 545 | name = "futures-core" 546 | version = "0.3.31" 547 | source = "registry+https://github.com/rust-lang/crates.io-index" 548 | checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" 549 | 550 | [[package]] 551 | name = "futures-sink" 552 | version = "0.3.31" 553 | source = "registry+https://github.com/rust-lang/crates.io-index" 554 | checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" 555 | 556 | [[package]] 557 | name = "futures-task" 558 | version = "0.3.31" 559 | source = "registry+https://github.com/rust-lang/crates.io-index" 560 | checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" 561 | 562 | [[package]] 563 | name = "futures-util" 564 | version = "0.3.31" 565 | source = "registry+https://github.com/rust-lang/crates.io-index" 566 | checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" 567 | dependencies = [ 568 | "futures-core", 569 | "futures-task", 570 | "pin-project-lite", 571 | "pin-utils", 572 | ] 573 | 574 | [[package]] 575 | name = "gcd" 576 | version = "2.3.0" 577 | source = "registry+https://github.com/rust-lang/crates.io-index" 578 | checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" 579 | 580 | [[package]] 581 | name = "hash32" 582 | version = "0.3.1" 583 | source = "registry+https://github.com/rust-lang/crates.io-index" 584 | checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" 585 | dependencies = [ 586 | "byteorder", 587 | ] 588 | 589 | [[package]] 590 | name = "hashbrown" 591 | version = "0.15.2" 592 | source = "registry+https://github.com/rust-lang/crates.io-index" 593 | checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" 594 | 595 | [[package]] 596 | name = "heapless" 597 | version = "0.8.0" 598 | source = "registry+https://github.com/rust-lang/crates.io-index" 599 | checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" 600 | dependencies = [ 601 | "hash32", 602 | "stable_deref_trait", 603 | ] 604 | 605 | [[package]] 606 | name = "heck" 607 | version = "0.5.0" 608 | source = "registry+https://github.com/rust-lang/crates.io-index" 609 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 610 | 611 | [[package]] 612 | name = "ident_case" 613 | version = "1.0.1" 614 | source = "registry+https://github.com/rust-lang/crates.io-index" 615 | checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" 616 | 617 | [[package]] 618 | name = "indexmap" 619 | version = "2.7.1" 620 | source = "registry+https://github.com/rust-lang/crates.io-index" 621 | checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" 622 | dependencies = [ 623 | "equivalent", 624 | "hashbrown", 625 | ] 626 | 627 | [[package]] 628 | name = "indoc" 629 | version = "2.0.5" 630 | source = "registry+https://github.com/rust-lang/crates.io-index" 631 | checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" 632 | 633 | [[package]] 634 | name = "instability" 635 | version = "0.3.7" 636 | source = "registry+https://github.com/rust-lang/crates.io-index" 637 | checksum = "0bf9fed6d91cfb734e7476a06bde8300a1b94e217e1b523b6f0cd1a01998c71d" 638 | dependencies = [ 639 | "darling", 640 | "indoc", 641 | "proc-macro2", 642 | "quote", 643 | "syn", 644 | ] 645 | 646 | [[package]] 647 | name = "justboot" 648 | version = "0.1.0" 649 | dependencies = [ 650 | "esp-hal", 651 | "esp-println", 652 | ] 653 | 654 | [[package]] 655 | name = "litrs" 656 | version = "0.4.1" 657 | source = "registry+https://github.com/rust-lang/crates.io-index" 658 | checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" 659 | dependencies = [ 660 | "proc-macro2", 661 | ] 662 | 663 | [[package]] 664 | name = "log" 665 | version = "0.4.25" 666 | source = "registry+https://github.com/rust-lang/crates.io-index" 667 | checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" 668 | 669 | [[package]] 670 | name = "memchr" 671 | version = "2.7.4" 672 | source = "registry+https://github.com/rust-lang/crates.io-index" 673 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 674 | 675 | [[package]] 676 | name = "minijinja" 677 | version = "2.7.0" 678 | source = "registry+https://github.com/rust-lang/crates.io-index" 679 | checksum = "cff7b8df5e85e30b87c2b0b3f58ba3a87b68e133738bf512a7713769326dbca9" 680 | dependencies = [ 681 | "serde", 682 | ] 683 | 684 | [[package]] 685 | name = "nb" 686 | version = "0.1.3" 687 | source = "registry+https://github.com/rust-lang/crates.io-index" 688 | checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" 689 | dependencies = [ 690 | "nb 1.1.0", 691 | ] 692 | 693 | [[package]] 694 | name = "nb" 695 | version = "1.1.0" 696 | source = "registry+https://github.com/rust-lang/crates.io-index" 697 | checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" 698 | 699 | [[package]] 700 | name = "num-traits" 701 | version = "0.2.19" 702 | source = "registry+https://github.com/rust-lang/crates.io-index" 703 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 704 | dependencies = [ 705 | "autocfg", 706 | ] 707 | 708 | [[package]] 709 | name = "object" 710 | version = "0.36.7" 711 | source = "registry+https://github.com/rust-lang/crates.io-index" 712 | checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" 713 | dependencies = [ 714 | "memchr", 715 | ] 716 | 717 | [[package]] 718 | name = "paste" 719 | version = "1.0.15" 720 | source = "registry+https://github.com/rust-lang/crates.io-index" 721 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 722 | 723 | [[package]] 724 | name = "pin-project-lite" 725 | version = "0.2.16" 726 | source = "registry+https://github.com/rust-lang/crates.io-index" 727 | checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" 728 | 729 | [[package]] 730 | name = "pin-utils" 731 | version = "0.1.0" 732 | source = "registry+https://github.com/rust-lang/crates.io-index" 733 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 734 | 735 | [[package]] 736 | name = "portable-atomic" 737 | version = "1.10.0" 738 | source = "registry+https://github.com/rust-lang/crates.io-index" 739 | checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" 740 | dependencies = [ 741 | "critical-section", 742 | ] 743 | 744 | [[package]] 745 | name = "proc-macro-crate" 746 | version = "3.2.0" 747 | source = "registry+https://github.com/rust-lang/crates.io-index" 748 | checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" 749 | dependencies = [ 750 | "toml_edit", 751 | ] 752 | 753 | [[package]] 754 | name = "proc-macro-error-attr2" 755 | version = "2.0.0" 756 | source = "registry+https://github.com/rust-lang/crates.io-index" 757 | checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" 758 | dependencies = [ 759 | "proc-macro2", 760 | "quote", 761 | ] 762 | 763 | [[package]] 764 | name = "proc-macro-error2" 765 | version = "2.0.1" 766 | source = "registry+https://github.com/rust-lang/crates.io-index" 767 | checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" 768 | dependencies = [ 769 | "proc-macro-error-attr2", 770 | "proc-macro2", 771 | "quote", 772 | "syn", 773 | ] 774 | 775 | [[package]] 776 | name = "proc-macro2" 777 | version = "1.0.93" 778 | source = "registry+https://github.com/rust-lang/crates.io-index" 779 | checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" 780 | dependencies = [ 781 | "unicode-ident", 782 | ] 783 | 784 | [[package]] 785 | name = "quote" 786 | version = "1.0.38" 787 | source = "registry+https://github.com/rust-lang/crates.io-index" 788 | checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" 789 | dependencies = [ 790 | "proc-macro2", 791 | ] 792 | 793 | [[package]] 794 | name = "r0" 795 | version = "1.0.0" 796 | source = "registry+https://github.com/rust-lang/crates.io-index" 797 | checksum = "bd7a31eed1591dcbc95d92ad7161908e72f4677f8fabf2a32ca49b4237cbf211" 798 | 799 | [[package]] 800 | name = "ral-registers" 801 | version = "0.1.3" 802 | source = "registry+https://github.com/rust-lang/crates.io-index" 803 | checksum = "46b71a9d9206e8b46714c74255adcaea8b11e0350c1d8456165073c3f75fc81a" 804 | 805 | [[package]] 806 | name = "rand_core" 807 | version = "0.6.4" 808 | source = "registry+https://github.com/rust-lang/crates.io-index" 809 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 810 | 811 | [[package]] 812 | name = "riscv" 813 | version = "0.12.1" 814 | source = "registry+https://github.com/rust-lang/crates.io-index" 815 | checksum = "5ea8ff73d3720bdd0a97925f0bf79ad2744b6da8ff36be3840c48ac81191d7a7" 816 | dependencies = [ 817 | "critical-section", 818 | "embedded-hal 1.0.0", 819 | "paste", 820 | "riscv-macros", 821 | "riscv-pac", 822 | ] 823 | 824 | [[package]] 825 | name = "riscv-macros" 826 | version = "0.1.0" 827 | source = "registry+https://github.com/rust-lang/crates.io-index" 828 | checksum = "f265be5d634272320a7de94cea15c22a3bfdd4eb42eb43edc528415f066a1f25" 829 | dependencies = [ 830 | "proc-macro2", 831 | "quote", 832 | "syn", 833 | ] 834 | 835 | [[package]] 836 | name = "riscv-pac" 837 | version = "0.2.0" 838 | source = "registry+https://github.com/rust-lang/crates.io-index" 839 | checksum = "8188909339ccc0c68cfb5a04648313f09621e8b87dc03095454f1a11f6c5d436" 840 | 841 | [[package]] 842 | name = "riscv-rt-macros" 843 | version = "0.2.2" 844 | source = "registry+https://github.com/rust-lang/crates.io-index" 845 | checksum = "30f19a85fe107b65031e0ba8ec60c34c2494069fe910d6c297f5e7cb5a6f76d0" 846 | dependencies = [ 847 | "proc-macro2", 848 | "quote", 849 | "syn", 850 | ] 851 | 852 | [[package]] 853 | name = "rustversion" 854 | version = "1.0.19" 855 | source = "registry+https://github.com/rust-lang/crates.io-index" 856 | checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" 857 | 858 | [[package]] 859 | name = "serde" 860 | version = "1.0.217" 861 | source = "registry+https://github.com/rust-lang/crates.io-index" 862 | checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" 863 | dependencies = [ 864 | "serde_derive", 865 | ] 866 | 867 | [[package]] 868 | name = "serde_derive" 869 | version = "1.0.217" 870 | source = "registry+https://github.com/rust-lang/crates.io-index" 871 | checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" 872 | dependencies = [ 873 | "proc-macro2", 874 | "quote", 875 | "syn", 876 | ] 877 | 878 | [[package]] 879 | name = "serde_spanned" 880 | version = "0.6.8" 881 | source = "registry+https://github.com/rust-lang/crates.io-index" 882 | checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" 883 | dependencies = [ 884 | "serde", 885 | ] 886 | 887 | [[package]] 888 | name = "stable_deref_trait" 889 | version = "1.2.0" 890 | source = "registry+https://github.com/rust-lang/crates.io-index" 891 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 892 | 893 | [[package]] 894 | name = "strsim" 895 | version = "0.11.1" 896 | source = "registry+https://github.com/rust-lang/crates.io-index" 897 | checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" 898 | 899 | [[package]] 900 | name = "strum" 901 | version = "0.26.3" 902 | source = "registry+https://github.com/rust-lang/crates.io-index" 903 | checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" 904 | dependencies = [ 905 | "strum_macros", 906 | ] 907 | 908 | [[package]] 909 | name = "strum_macros" 910 | version = "0.26.4" 911 | source = "registry+https://github.com/rust-lang/crates.io-index" 912 | checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" 913 | dependencies = [ 914 | "heck", 915 | "proc-macro2", 916 | "quote", 917 | "rustversion", 918 | "syn", 919 | ] 920 | 921 | [[package]] 922 | name = "syn" 923 | version = "2.0.98" 924 | source = "registry+https://github.com/rust-lang/crates.io-index" 925 | checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" 926 | dependencies = [ 927 | "proc-macro2", 928 | "quote", 929 | "unicode-ident", 930 | ] 931 | 932 | [[package]] 933 | name = "termcolor" 934 | version = "1.4.1" 935 | source = "registry+https://github.com/rust-lang/crates.io-index" 936 | checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" 937 | dependencies = [ 938 | "winapi-util", 939 | ] 940 | 941 | [[package]] 942 | name = "toml" 943 | version = "0.8.19" 944 | source = "registry+https://github.com/rust-lang/crates.io-index" 945 | checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" 946 | dependencies = [ 947 | "serde", 948 | "serde_spanned", 949 | "toml_datetime", 950 | "toml_edit", 951 | ] 952 | 953 | [[package]] 954 | name = "toml_datetime" 955 | version = "0.6.8" 956 | source = "registry+https://github.com/rust-lang/crates.io-index" 957 | checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" 958 | dependencies = [ 959 | "serde", 960 | ] 961 | 962 | [[package]] 963 | name = "toml_edit" 964 | version = "0.22.23" 965 | source = "registry+https://github.com/rust-lang/crates.io-index" 966 | checksum = "02a8b472d1a3d7c18e2d61a489aee3453fd9031c33e4f55bd533f4a7adca1bee" 967 | dependencies = [ 968 | "indexmap", 969 | "serde", 970 | "serde_spanned", 971 | "toml_datetime", 972 | "winnow", 973 | ] 974 | 975 | [[package]] 976 | name = "ufmt-write" 977 | version = "0.1.0" 978 | source = "registry+https://github.com/rust-lang/crates.io-index" 979 | checksum = "e87a2ed6b42ec5e28cc3b94c09982969e9227600b2e3dcbc1db927a84c06bd69" 980 | 981 | [[package]] 982 | name = "unicode-ident" 983 | version = "1.0.16" 984 | source = "registry+https://github.com/rust-lang/crates.io-index" 985 | checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" 986 | 987 | [[package]] 988 | name = "usb-device" 989 | version = "0.3.2" 990 | source = "registry+https://github.com/rust-lang/crates.io-index" 991 | checksum = "98816b1accafbb09085168b90f27e93d790b4bfa19d883466b5e53315b5f06a6" 992 | dependencies = [ 993 | "heapless", 994 | "portable-atomic", 995 | ] 996 | 997 | [[package]] 998 | name = "vcell" 999 | version = "0.1.3" 1000 | source = "registry+https://github.com/rust-lang/crates.io-index" 1001 | checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" 1002 | 1003 | [[package]] 1004 | name = "void" 1005 | version = "1.0.2" 1006 | source = "registry+https://github.com/rust-lang/crates.io-index" 1007 | checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" 1008 | 1009 | [[package]] 1010 | name = "winapi-util" 1011 | version = "0.1.9" 1012 | source = "registry+https://github.com/rust-lang/crates.io-index" 1013 | checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" 1014 | dependencies = [ 1015 | "windows-sys", 1016 | ] 1017 | 1018 | [[package]] 1019 | name = "windows-sys" 1020 | version = "0.59.0" 1021 | source = "registry+https://github.com/rust-lang/crates.io-index" 1022 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 1023 | dependencies = [ 1024 | "windows-targets", 1025 | ] 1026 | 1027 | [[package]] 1028 | name = "windows-targets" 1029 | version = "0.52.6" 1030 | source = "registry+https://github.com/rust-lang/crates.io-index" 1031 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 1032 | dependencies = [ 1033 | "windows_aarch64_gnullvm", 1034 | "windows_aarch64_msvc", 1035 | "windows_i686_gnu", 1036 | "windows_i686_gnullvm", 1037 | "windows_i686_msvc", 1038 | "windows_x86_64_gnu", 1039 | "windows_x86_64_gnullvm", 1040 | "windows_x86_64_msvc", 1041 | ] 1042 | 1043 | [[package]] 1044 | name = "windows_aarch64_gnullvm" 1045 | version = "0.52.6" 1046 | source = "registry+https://github.com/rust-lang/crates.io-index" 1047 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 1048 | 1049 | [[package]] 1050 | name = "windows_aarch64_msvc" 1051 | version = "0.52.6" 1052 | source = "registry+https://github.com/rust-lang/crates.io-index" 1053 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 1054 | 1055 | [[package]] 1056 | name = "windows_i686_gnu" 1057 | version = "0.52.6" 1058 | source = "registry+https://github.com/rust-lang/crates.io-index" 1059 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 1060 | 1061 | [[package]] 1062 | name = "windows_i686_gnullvm" 1063 | version = "0.52.6" 1064 | source = "registry+https://github.com/rust-lang/crates.io-index" 1065 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 1066 | 1067 | [[package]] 1068 | name = "windows_i686_msvc" 1069 | version = "0.52.6" 1070 | source = "registry+https://github.com/rust-lang/crates.io-index" 1071 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 1072 | 1073 | [[package]] 1074 | name = "windows_x86_64_gnu" 1075 | version = "0.52.6" 1076 | source = "registry+https://github.com/rust-lang/crates.io-index" 1077 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 1078 | 1079 | [[package]] 1080 | name = "windows_x86_64_gnullvm" 1081 | version = "0.52.6" 1082 | source = "registry+https://github.com/rust-lang/crates.io-index" 1083 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 1084 | 1085 | [[package]] 1086 | name = "windows_x86_64_msvc" 1087 | version = "0.52.6" 1088 | source = "registry+https://github.com/rust-lang/crates.io-index" 1089 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 1090 | 1091 | [[package]] 1092 | name = "winnow" 1093 | version = "0.7.1" 1094 | source = "registry+https://github.com/rust-lang/crates.io-index" 1095 | checksum = "86e376c75f4f43f44db463cf729e0d3acbf954d13e22c51e26e4c264b4ab545f" 1096 | dependencies = [ 1097 | "memchr", 1098 | ] 1099 | 1100 | [[package]] 1101 | name = "xtensa-lx" 1102 | version = "0.10.0" 1103 | source = "registry+https://github.com/rust-lang/crates.io-index" 1104 | checksum = "51cbb46c78cfd284c9378070ab90bae9d14d38b3766cb853a97c0a137f736d5b" 1105 | dependencies = [ 1106 | "critical-section", 1107 | "document-features", 1108 | ] 1109 | 1110 | [[package]] 1111 | name = "xtensa-lx-rt" 1112 | version = "0.18.0" 1113 | source = "registry+https://github.com/rust-lang/crates.io-index" 1114 | checksum = "689c2ef159d9cd4fc9503603e9999968a84a30db9bde0f0f880d0cceea0190a9" 1115 | dependencies = [ 1116 | "anyhow", 1117 | "document-features", 1118 | "enum-as-inner", 1119 | "minijinja", 1120 | "r0", 1121 | "serde", 1122 | "strum", 1123 | "toml", 1124 | "xtensa-lx", 1125 | "xtensa-lx-rt-proc-macros", 1126 | ] 1127 | 1128 | [[package]] 1129 | name = "xtensa-lx-rt-proc-macros" 1130 | version = "0.2.2" 1131 | source = "registry+https://github.com/rust-lang/crates.io-index" 1132 | checksum = "11277b1e4cbb7ffe44678c668518b249c843c81df249b8f096701757bc50d7ee" 1133 | dependencies = [ 1134 | "darling", 1135 | "proc-macro2", 1136 | "quote", 1137 | "syn", 1138 | ] 1139 | --------------------------------------------------------------------------------