mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-09-27 04:10:28 +00:00
Create the esp-metadata
package, update esp-hal
build script to use it (#1256)
This commit is contained in:
parent
c283563542
commit
1f129744fd
@ -6,6 +6,7 @@ exclude = [
|
||||
"esp-hal-procmacros",
|
||||
"esp-hal-smartled",
|
||||
"esp-lp-hal",
|
||||
"esp-metadata",
|
||||
"esp-riscv-rt",
|
||||
"examples",
|
||||
]
|
||||
|
@ -68,9 +68,10 @@ esp-riscv-rt = { version = "0.7.0", optional = true, path = "../esp-riscv-rt" }
|
||||
xtensa-lx-rt = { version = "0.16.0", optional = true }
|
||||
|
||||
[build-dependencies]
|
||||
basic-toml = "0.1.8"
|
||||
cfg-if = "1.0.0"
|
||||
serde = { version = "1.0.197", features = ["derive"] }
|
||||
basic-toml = "0.1.8"
|
||||
cfg-if = "1.0.0"
|
||||
esp-metadata = { version = "0.1.0", path = "../esp-metadata" }
|
||||
serde = { version = "1.0.197", features = ["derive"] }
|
||||
|
||||
[features]
|
||||
default = ["rt", "vectored"]
|
||||
|
108
esp-hal/build.rs
108
esp-hal/build.rs
@ -4,9 +4,10 @@ use std::{
|
||||
fs::{self, File},
|
||||
io::{BufRead, Write},
|
||||
path::{Path, PathBuf},
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
use serde::Deserialize;
|
||||
use esp_metadata::{Arch, Chip, Config};
|
||||
|
||||
// Macros taken from:
|
||||
// https://github.com/TheDan64/inkwell/blob/36c3b10/src/lib.rs#L81-L110
|
||||
@ -45,61 +46,6 @@ macro_rules! assert_unique_used_features {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq)]
|
||||
enum Arch {
|
||||
#[serde(rename = "riscv")]
|
||||
RiscV,
|
||||
#[serde(rename = "xtensa")]
|
||||
Xtensa,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Arch {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match self {
|
||||
Arch::RiscV => "riscv",
|
||||
Arch::Xtensa => "xtensa",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
enum CoreCount {
|
||||
#[serde(rename = "single_core")]
|
||||
Single,
|
||||
#[serde(rename = "multi_core")]
|
||||
Multi,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for CoreCount {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match self {
|
||||
CoreCount::Single => "single_core",
|
||||
CoreCount::Multi => "multi_core",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Device {
|
||||
pub arch: Arch,
|
||||
pub cores: CoreCount,
|
||||
pub peripherals: Vec<String>,
|
||||
pub symbols: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Config {
|
||||
pub device: Device,
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
// NOTE: update when adding new device support!
|
||||
// Ensure that exactly one chip has been specified:
|
||||
@ -157,18 +103,11 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
}
|
||||
|
||||
// Load the configuration file for the configured device:
|
||||
let chip_toml_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("devices")
|
||||
.join(device_name)
|
||||
.join("device.toml")
|
||||
.canonicalize()?;
|
||||
|
||||
let config = fs::read_to_string(chip_toml_path)?;
|
||||
let config: Config = basic_toml::from_str(&config)?;
|
||||
let device = &config.device;
|
||||
let chip = Chip::from_str(device_name)?;
|
||||
let config = Config::for_chip(&chip);
|
||||
|
||||
// Check PSRAM features are only given if the target supports PSRAM:
|
||||
if !&device.symbols.contains(&String::from("psram"))
|
||||
if !config.contains(&String::from("psram"))
|
||||
&& (cfg!(feature = "psram-2m") || cfg!(feature = "psram-4m") || cfg!(feature = "psram-8m"))
|
||||
{
|
||||
panic!("The target does not support PSRAM");
|
||||
@ -176,40 +115,17 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
|
||||
// Don't support "interrupt-preemption" and "direct-vectoring" on Xtensa and
|
||||
// RISC-V with CLIC:
|
||||
if (device.symbols.contains(&String::from("clic")) || device.arch == Arch::Xtensa)
|
||||
if (config.contains(&String::from("clic")) || config.arch() == Arch::Xtensa)
|
||||
&& (cfg!(feature = "direct-vectoring") || cfg!(feature = "interrupt-preemption"))
|
||||
{
|
||||
panic!("The target does not support interrupt-preemption and direct-vectoring");
|
||||
}
|
||||
|
||||
// Define all necessary configuration symbols for the configured device:
|
||||
println!("cargo:rustc-cfg={}", device_name);
|
||||
println!("cargo:rustc-cfg={}", device.arch);
|
||||
println!("cargo:rustc-cfg={}", device.cores);
|
||||
|
||||
for peripheral in &device.peripherals {
|
||||
println!("cargo:rustc-cfg={peripheral}");
|
||||
}
|
||||
|
||||
for symbol in &device.symbols {
|
||||
println!("cargo:rustc-cfg={symbol}");
|
||||
}
|
||||
|
||||
let mut config_symbols = Vec::new();
|
||||
let arch = device.arch.to_string();
|
||||
let cores = device.cores.to_string();
|
||||
config_symbols.push(device_name);
|
||||
config_symbols.push(&arch);
|
||||
config_symbols.push(&cores);
|
||||
|
||||
for peripheral in &device.peripherals {
|
||||
config_symbols.push(peripheral);
|
||||
}
|
||||
|
||||
for symbol in &device.symbols {
|
||||
config_symbols.push(symbol);
|
||||
}
|
||||
config.define_symbols();
|
||||
|
||||
#[allow(unused_mut)]
|
||||
let mut config_symbols = config.all();
|
||||
#[cfg(feature = "flip-link")]
|
||||
config_symbols.push("flip-link");
|
||||
|
||||
@ -260,7 +176,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
}
|
||||
|
||||
fn copy_dir_all(
|
||||
config_symbols: &Vec<&str>,
|
||||
config_symbols: &Vec<String>,
|
||||
src: impl AsRef<Path>,
|
||||
dst: impl AsRef<Path>,
|
||||
) -> std::io::Result<()> {
|
||||
@ -287,7 +203,7 @@ fn copy_dir_all(
|
||||
|
||||
/// A naive pre-processor for linker scripts
|
||||
fn preprocess_file(
|
||||
config: &[&str],
|
||||
config: &[String],
|
||||
src: impl AsRef<Path>,
|
||||
dst: impl AsRef<Path>,
|
||||
) -> std::io::Result<()> {
|
||||
@ -302,7 +218,7 @@ fn preprocess_file(
|
||||
let trimmed = line.trim();
|
||||
|
||||
if let Some(stripped) = trimmed.strip_prefix("#IF ") {
|
||||
let condition = stripped;
|
||||
let condition = stripped.to_string();
|
||||
let should_take = take.iter().all(|v| *v);
|
||||
let should_take = should_take && config.contains(&condition);
|
||||
take.push(should_take);
|
||||
|
14
esp-metadata/Cargo.toml
Normal file
14
esp-metadata/Cargo.toml
Normal file
@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "esp-metadata"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.60.0"
|
||||
description = "Metadata for Espressif devices"
|
||||
repository = "https://github.com/esp-rs/esp-hal"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
||||
[dependencies]
|
||||
basic-toml = "0.1.8"
|
||||
lazy_static = "1.4.0"
|
||||
serde = { version = "1.0.197", features = ["derive"] }
|
||||
strum = { version = "0.26.1", features = ["derive"] }
|
30
esp-metadata/README.md
Normal file
30
esp-metadata/README.md
Normal file
@ -0,0 +1,30 @@
|
||||
# esp-metadata
|
||||
|
||||
[](https://crates.io/crates/esp-metadata)
|
||||
[](https://docs.rs/esp-metadata)
|
||||

|
||||

|
||||
|
||||
Metadata for Espressif devices, primarily intended for use in build scripts.
|
||||
|
||||
## [Documentation](https://docs.rs/crate/esp-metadata)
|
||||
|
||||
## Minimum Supported Rust Version (MSRV)
|
||||
|
||||
This crate is guaranteed to compile on stable Rust 1.60 and up. It _might_
|
||||
compile with older versions but that may change in any new patch release.
|
||||
|
||||
## License
|
||||
|
||||
Licensed under either of:
|
||||
|
||||
- Apache License, Version 2.0 ([LICENSE-APACHE](../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
|
||||
- MIT license ([LICENSE-MIT](../LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
||||
|
||||
at your option.
|
||||
|
||||
### Contribution
|
||||
|
||||
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in
|
||||
the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without
|
||||
any additional terms or conditions.
|
@ -1,4 +1,5 @@
|
||||
[device]
|
||||
name = "esp32"
|
||||
arch = "xtensa"
|
||||
cores = "multi_core"
|
||||
|
@ -1,5 +1,6 @@
|
||||
[device]
|
||||
arch = "riscv"
|
||||
name = "esp32c2"
|
||||
arch = "riscv"
|
||||
cores = "single_core"
|
||||
|
||||
peripherals = [
|
@ -1,5 +1,6 @@
|
||||
[device]
|
||||
arch = "riscv"
|
||||
name = "esp32c3"
|
||||
arch = "riscv"
|
||||
cores = "single_core"
|
||||
|
||||
peripherals = [
|
@ -1,5 +1,6 @@
|
||||
[device]
|
||||
arch = "riscv"
|
||||
name = "esp32c6"
|
||||
arch = "riscv"
|
||||
cores = "single_core"
|
||||
|
||||
peripherals = [
|
@ -1,5 +1,6 @@
|
||||
[device]
|
||||
arch = "riscv"
|
||||
name = "esp32h2"
|
||||
arch = "riscv"
|
||||
cores = "single_core"
|
||||
|
||||
peripherals = [
|
@ -1,5 +1,6 @@
|
||||
[device]
|
||||
arch = "riscv"
|
||||
name = "esp32p4"
|
||||
arch = "riscv"
|
||||
cores = "multi_core"
|
||||
|
||||
peripherals = [
|
@ -1,4 +1,5 @@
|
||||
[device]
|
||||
name = "esp32s2"
|
||||
arch = "xtensa"
|
||||
cores = "single_core"
|
||||
|
@ -1,5 +1,6 @@
|
||||
[device]
|
||||
arch = "xtensa"
|
||||
name = "esp32s3"
|
||||
arch = "xtensa"
|
||||
cores = "multi_core"
|
||||
|
||||
peripherals = [
|
198
esp-metadata/src/lib.rs
Normal file
198
esp-metadata/src/lib.rs
Normal file
@ -0,0 +1,198 @@
|
||||
//! Metadata for Espressif devices, primarily intended for use in build scripts.
|
||||
|
||||
const ESP32_TOML: &'static str = include_str!("../devices/esp32.toml");
|
||||
const ESP32C2_TOML: &'static str = include_str!("../devices/esp32c2.toml");
|
||||
const ESP32C3_TOML: &'static str = include_str!("../devices/esp32c3.toml");
|
||||
const ESP32C6_TOML: &'static str = include_str!("../devices/esp32c6.toml");
|
||||
const ESP32H2_TOML: &'static str = include_str!("../devices/esp32h2.toml");
|
||||
const ESP32P4_TOML: &'static str = include_str!("../devices/esp32p4.toml");
|
||||
const ESP32S2_TOML: &'static str = include_str!("../devices/esp32s2.toml");
|
||||
const ESP32S3_TOML: &'static str = include_str!("../devices/esp32s3.toml");
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref ESP32_CFG: Config = basic_toml::from_str(ESP32_TOML).unwrap();
|
||||
static ref ESP32C2_CFG: Config = basic_toml::from_str(ESP32C2_TOML).unwrap();
|
||||
static ref ESP32C3_CFG: Config = basic_toml::from_str(ESP32C3_TOML).unwrap();
|
||||
static ref ESP32C6_CFG: Config = basic_toml::from_str(ESP32C6_TOML).unwrap();
|
||||
static ref ESP32H2_CFG: Config = basic_toml::from_str(ESP32H2_TOML).unwrap();
|
||||
static ref ESP32P4_CFG: Config = basic_toml::from_str(ESP32P4_TOML).unwrap();
|
||||
static ref ESP32S2_CFG: Config = basic_toml::from_str(ESP32S2_TOML).unwrap();
|
||||
static ref ESP32S3_CFG: Config = basic_toml::from_str(ESP32S3_TOML).unwrap();
|
||||
}
|
||||
|
||||
/// Supported device architectures.
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
Copy,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
serde::Deserialize,
|
||||
serde::Serialize,
|
||||
strum::Display,
|
||||
strum::EnumIter,
|
||||
strum::EnumString,
|
||||
)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
#[strum(serialize_all = "lowercase")]
|
||||
pub enum Arch {
|
||||
/// RISC-V architecture
|
||||
RiscV,
|
||||
/// Xtensa architecture
|
||||
Xtensa,
|
||||
}
|
||||
|
||||
/// Device core count.
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
Copy,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
serde::Deserialize,
|
||||
serde::Serialize,
|
||||
strum::Display,
|
||||
strum::EnumIter,
|
||||
strum::EnumString,
|
||||
)]
|
||||
pub enum Cores {
|
||||
/// Single CPU core
|
||||
#[serde(rename = "single_core")]
|
||||
#[strum(serialize = "single_core")]
|
||||
Single,
|
||||
/// Two or more CPU cores
|
||||
#[serde(rename = "multi_core")]
|
||||
#[strum(serialize = "multi_core")]
|
||||
Multi,
|
||||
}
|
||||
|
||||
/// Supported devices.
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
Copy,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
serde::Deserialize,
|
||||
serde::Serialize,
|
||||
strum::Display,
|
||||
strum::EnumIter,
|
||||
strum::EnumString,
|
||||
)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
#[strum(serialize_all = "lowercase")]
|
||||
pub enum Chip {
|
||||
/// ESP32
|
||||
Esp32,
|
||||
/// ESP32-C2, ESP8684
|
||||
Esp32c2,
|
||||
/// ESP32-C3, ESP8685
|
||||
Esp32c3,
|
||||
/// ESP32-C6
|
||||
Esp32c6,
|
||||
/// ESP32-H2
|
||||
Esp32h2,
|
||||
/// ESP32-P4
|
||||
Esp32p4,
|
||||
/// ESP32-S2
|
||||
Esp32s2,
|
||||
/// ESP32-S3
|
||||
Esp32s3,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
|
||||
struct Device {
|
||||
pub name: String,
|
||||
pub arch: Arch,
|
||||
pub cores: Cores,
|
||||
pub peripherals: Vec<String>,
|
||||
pub symbols: Vec<String>,
|
||||
}
|
||||
|
||||
/// Device configuration file format.
|
||||
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
|
||||
pub struct Config {
|
||||
device: Device,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
/// The configuration for the specified chip.
|
||||
pub fn for_chip(chip: &Chip) -> Self {
|
||||
match chip {
|
||||
Chip::Esp32 => ESP32_CFG.clone(),
|
||||
Chip::Esp32c2 => ESP32C2_CFG.clone(),
|
||||
Chip::Esp32c3 => ESP32C3_CFG.clone(),
|
||||
Chip::Esp32c6 => ESP32C6_CFG.clone(),
|
||||
Chip::Esp32h2 => ESP32H2_CFG.clone(),
|
||||
Chip::Esp32p4 => ESP32P4_CFG.clone(),
|
||||
Chip::Esp32s2 => ESP32S2_CFG.clone(),
|
||||
Chip::Esp32s3 => ESP32S3_CFG.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
/// The name of the device.
|
||||
pub fn name(&self) -> String {
|
||||
self.device.name.clone()
|
||||
}
|
||||
|
||||
/// The CPU architecture of the device.
|
||||
pub fn arch(&self) -> Arch {
|
||||
self.device.arch
|
||||
}
|
||||
|
||||
/// The core count of the device.
|
||||
pub fn cores(&self) -> Cores {
|
||||
self.device.cores
|
||||
}
|
||||
|
||||
/// The peripherals of the device.
|
||||
pub fn peripherals(&self) -> &[String] {
|
||||
&self.device.peripherals
|
||||
}
|
||||
|
||||
/// User-defined symbols for the device.
|
||||
pub fn symbols(&self) -> &[String] {
|
||||
&self.device.symbols
|
||||
}
|
||||
|
||||
/// All configuration values for the device.
|
||||
pub fn all(&self) -> Vec<String> {
|
||||
[
|
||||
vec![
|
||||
self.device.name.clone(),
|
||||
self.device.arch.to_string(),
|
||||
self.device.cores.to_string(),
|
||||
],
|
||||
self.device.peripherals.clone(),
|
||||
self.device.symbols.clone(),
|
||||
]
|
||||
.concat()
|
||||
}
|
||||
|
||||
/// Does the configuration contain `item`?
|
||||
pub fn contains(&self, item: &String) -> bool {
|
||||
self.all().contains(item)
|
||||
}
|
||||
|
||||
/// Define all symbols for a given configuration.
|
||||
pub fn define_symbols(&self) {
|
||||
// Define all necessary configuration symbols for the configured device:
|
||||
println!("cargo:rustc-cfg={}", self.name());
|
||||
println!("cargo:rustc-cfg={}", self.arch());
|
||||
println!("cargo:rustc-cfg={}", self.cores());
|
||||
|
||||
for peripheral in self.peripherals() {
|
||||
println!("cargo:rustc-cfg={peripheral}");
|
||||
}
|
||||
|
||||
for symbol in self.symbols() {
|
||||
println!("cargo:rustc-cfg={symbol}");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user