pub(crate) mod aes;
pub(crate) mod ecc;
pub(crate) mod gpio;
pub(crate) mod i2c_master;
pub(crate) mod interrupt;
pub(crate) mod rmt;
pub(crate) mod rsa;
pub(crate) mod sha;
pub(crate) mod soc;
pub(crate) mod spi_master;
pub(crate) mod spi_slave;
pub(crate) mod timergroup;
pub(crate) mod uart;
pub(crate) use aes::*;
pub(crate) use ecc::*;
pub(crate) use gpio::*;
pub(crate) use i2c_master::*;
pub(crate) use interrupt::*;
pub(crate) use rmt::*;
pub(crate) use sha::*;
pub(crate) use soc::*;
pub(crate) use spi_master::*;
pub(crate) use spi_slave::*;
pub(crate) use timergroup::*;
pub(crate) use uart::*;
use crate::support_status::{SupportStatus, SupportStatusLevel};
pub(crate) trait GenericProperty {
fn cfgs(&self) -> Option<Vec<String>> {
None
}
fn macros(&self) -> Option<proc_macro2::TokenStream> {
None
}
fn property_macro_branches(&self) -> proc_macro2::TokenStream {
quote::quote! {}
}
}
impl<T: GenericProperty> GenericProperty for Option<T> {
fn cfgs(&self) -> Option<Vec<String>> {
self.as_ref().and_then(|v| v.cfgs())
}
fn macros(&self) -> Option<proc_macro2::TokenStream> {
self.as_ref().and_then(|v| v.macros())
}
fn property_macro_branches(&self) -> proc_macro2::TokenStream {
self.as_ref()
.map(|v| v.property_macro_branches())
.unwrap_or_default()
}
}
pub(crate) enum Value {
Unset,
Number(u32),
Boolean(bool),
String(String),
NumberList(Vec<u32>),
StringList(Vec<String>),
Generic(Box<dyn GenericProperty>),
}
impl From<Option<u32>> for Value {
fn from(value: Option<u32>) -> Self {
match value {
Some(v) => Value::Number(v),
None => Value::Unset,
}
}
}
#[derive(Debug, Default, Clone, serde::Deserialize, serde::Serialize)]
pub(crate) struct EmptyInstanceConfig {}
#[derive(Debug, Default, Clone, serde::Deserialize, serde::Serialize)]
pub(crate) struct PeriInstance<I = EmptyInstanceConfig> {
pub name: String,
#[serde(flatten)]
pub instance_config: I,
}
#[derive(Default)]
pub(crate) struct SupportItem {
pub name: &'static str,
pub config_group: &'static str,
pub hide_from_peri_table: bool,
}
macro_rules! driver_configs {
(@ignore $t:tt) => {};
(@property (u32) $self:ident, $config:ident) => { Value::Number($self.$config) };
(@property (bool) $self:ident, $config:ident) => { Value::Boolean($self.$config) };
(@property (String) $self:ident, $config:ident) => { Value::String($self.$config.clone()) };
(@property (Vec<u32>) $self:ident, $config:ident) => { Value::NumberList($self.$config.clone()) };
(@property (Vec<String>) $self:ident, $config:ident) => { Value::StringList($self.$config.clone()) };
(@property (Option<u32>) $self:ident, $config:ident) => { Value::from($self.$config) };
(@property ($($other:ty)*) $self:ident, $config:ident) => { Value::Generic(Box::new($self.$config.clone())) };
(@is_optional Option<$t:ty>) => { true };
(@is_optional $t:ty) => { false };
(@default $default:literal) => { $default };
(@default $default:literal $opt:literal) => { $opt };
(@one
$struct:ident $(<$instance_config:ident>)? ($group:ident) {
$(
$(#[$meta:meta])* $config:ident: $ty:tt $(<$generic:tt>)?,
)*
}
) => {
#[derive(Debug, Clone, serde::Deserialize)]
pub(crate) struct $struct {
#[serde(default)]
#[serde(deserialize_with = "crate::support_status::string_or_struct")]
pub support_status: SupportStatus,
#[serde(default)]
pub instances: Vec<PeriInstance $(<$instance_config>)?>,
$(
$(#[$meta])*
pub $config: $ty $(<$generic>)?
),*
}
impl $struct {
fn properties(&self) -> impl Iterator<Item = (&str, bool, Value)> {
[$( (
concat!(stringify!($group), ".", stringify!($config)),
driver_configs!(@is_optional $ty $(<$generic>)?),
driver_configs!(@property ($ty $(<$generic>)?) self, $config),
),
)*].into_iter()
}
}
};
($(
$struct:ident $(<$instance_config:ident>)? {
driver: $driver:ident,
name: $name:literal,
$(hide_from_peri_table: $hide:literal,)?
$(has_computed_properties: $computed:literal,)?
properties: $tokens:tt
},
)+) => {
$(
driver_configs!(@one $struct $(<$instance_config>)? ($driver) $tokens);
)+
#[derive(Default, Debug, Clone, serde::Deserialize)]
pub(crate) struct PeriConfig {
$(
#[serde(default)]
pub(crate) $driver: Option<$struct>,
)+
}
impl PeriConfig {
pub fn drivers() -> &'static [SupportItem] {
&[
$(
SupportItem {
name: $name,
config_group: stringify!($driver),
hide_from_peri_table: driver_configs!(@default false $($hide)?),
},
)+
]
}
pub fn driver_names(&self) -> impl Iterator<Item = &str> {
[$(
self.$driver.as_ref().and_then(|d| {
match d.support_status.status {
SupportStatusLevel::NotAvailable | SupportStatusLevel::NotSupported => None,
_ => Some(stringify!($driver)),
}
}),
)*].into_iter().flatten()
}
pub fn driver_instances(&self) -> impl Iterator<Item = String> {
let mut instances = vec![];
$(
if let Some(driver) = &self.$driver {
instances.extend(driver.instances.iter().map(|i| {
format!("{}.{}", stringify!($driver), i.name)
}));
}
)*
instances.into_iter()
}
pub fn properties(&self) -> impl Iterator<Item = (&str, bool, Value)> {
let mut properties = vec![];
$(
if let Some(driver) = &self.$driver {
properties.extend(driver.properties());
$(
driver_configs!(@ignore $computed);
properties.extend(driver.computed_properties());
)?
}
)*
properties.into_iter()
}
pub fn support_status(&self, driver: &str) -> SupportStatus {
let maybe_status = match driver {
$(stringify!($driver) => self.$driver.as_ref().map(|p| p.support_status),)*
_ => None,
};
maybe_status.unwrap_or(SupportStatus { status: SupportStatusLevel::NotAvailable, issue: None })
}
}
};
}
driver_configs![
AdcProperties {
driver: adc,
name: "ADC",
properties: {}
},
AesProperties {
driver: aes,
name: "AES",
properties: {
key_length: AesKeyLength,
#[serde(default)]
dma: bool,
#[serde(default)]
dma_mode: Vec<String>,
has_split_text_registers: bool,
endianness_configurable: bool,
}
},
AssistDebugProperties {
driver: assist_debug,
name: "ASSIST_DEBUG",
properties: {
#[serde(default)]
has_sp_monitor: bool,
#[serde(default)]
has_region_monitor: bool,
}
},
AvcProperties {
driver: avc,
name: "Analog Voltage Comparator",
properties: {}
},
BitScramblerProperties {
driver: bit_scrambler,
name: "Bit Scrambler",
properties: {}
},
BluetoothProperties {
driver: bt,
name: "Bluetooth",
properties: {
controller: String,
}
},
CameraProperties {
driver: camera,
name: "Camera interface", properties: {}
},
DacProperties {
driver: dac,
name: "DAC",
properties: {}
},
DedicatedGpioProperties {
driver: dedicated_gpio,
name: "Dedicated GPIO",
properties: {
#[serde(default)]
needs_initialization: bool,
#[serde(flatten)]
channel_properties: DedicatedGpioChannels,
}
},
DmaProperties {
driver: dma,
name: "DMA",
properties: {
kind: String,
#[serde(default)]
supports_mem2mem: bool,
#[serde(default)]
can_access_psram: bool,
#[serde(default)]
ext_mem_configurable_block_size: bool,
#[serde(default)]
separate_in_out_interrupts: bool,
#[serde(default)]
max_priority: Option<u32>,
#[serde(default)]
gdma_version: Option<u32>,
}
},
DsProperties {
driver: ds,
name: "DS",
properties: {}
},
EccProperties {
driver: ecc,
name: "ECC",
properties: {
#[serde(default)]
zero_extend_writes: bool,
#[serde(default)]
separate_jacobian_point_memory: bool, #[serde(default)]
has_memory_clock_gate: bool, #[serde(default)]
supports_enhanced_security: bool, #[serde(flatten)]
extras: EccDriverProperties,
}
},
EthernetProperties {
driver: ethernet,
name: "Ethernet",
properties: {}
},
EtmProperties {
driver: etm,
name: "ETM",
properties: {}
},
GpioProperties {
driver: gpio,
name: "GPIO",
has_computed_properties: true,
properties: {
#[serde(default)]
has_bank_1: bool,
gpio_function: u32,
constant_0_input: u32,
constant_1_input: u32,
#[serde(default)]
remap_iomux_pin_registers: bool,
#[serde(default)] func_in_sel_offset: u32,
#[serde(flatten)]
pins_and_signals: GpioPinsAndSignals,
}
},
HmacProperties {
driver: hmac,
name: "HMAC",
properties: {}
},
I2cMasterProperties<I2cMasterInstanceConfig> {
driver: i2c_master,
name: "I2C master",
properties: {
#[serde(default)]
has_fsm_timeouts: bool,
#[serde(default)]
has_hw_bus_clear: bool,
#[serde(default)]
has_bus_timeout_enable: bool,
#[serde(default)]
separate_filter_config_registers: bool,
#[serde(default)]
can_estimate_nack_reason: bool,
#[serde(default)]
has_conf_update: bool,
#[serde(default)]
has_reliable_fsm_reset: bool,
#[serde(default)]
has_arbitration_en: bool,
#[serde(default)]
has_tx_fifo_watermark: bool,
#[serde(default)]
bus_timeout_is_exponential: bool,
#[serde(default)]
i2c0_data_register_ahb_address: Option<u32>,
max_bus_timeout: u32,
ll_intr_mask: u32,
fifo_size: u32,
}
},
I2cSlaveProperties {
driver: i2c_slave,
name: "I2C slave",
properties: {}
},
I2sProperties {
driver: i2s,
name: "I2S",
properties: {}
},
IeeeProperties {
driver: ieee802154,
name: "IEEE 802.15.4",
properties: {}
},
InterruptProperties {
driver: interrupts,
name: "Interrupts",
properties: {
status_registers: u32,
controller: InterruptControllerProperties,
#[serde(flatten)]
software_interrupt_properties: SoftwareInterruptProperties,
}
},
IoMuxProperties {
driver: io_mux,
name: "IOMUX",
properties: {}
},
KeyManagerProperties {
driver: key_manager,
name: "Key Manager",
properties: {}
},
LedcProperties {
driver: ledc,
name: "LEDC",
properties: {}
},
LpI2cMasterProperties {
driver: lp_i2c_master,
name: "LP I2C master",
properties: {
fifo_size: u32,
}
},
LpUartProperties {
driver: lp_uart,
name: "LP UART",
properties: {
ram_size: u32,
}
},
McpwmProperties {
driver: mcpwm,
name: "MCPWM",
properties: {}
},
ParlIoProperties {
driver: parl_io,
name: "PARL_IO",
properties: {
version: u32,
}
},
PcntProperties {
driver: pcnt,
name: "PCNT",
properties: {}
},
PhyProperties {
driver: phy,
name: "PHY",
properties: {
#[serde(default)]
combo_module: bool,
#[serde(default)]
backed_up_digital_register_count: Option<u32>,
}
},
PsramProperties {
driver: psram,
name: "PSRAM",
properties: {
#[serde(default)]
octal_spi: bool,
extmem_origin: u32,
}
},
RgbProperties {
driver: rgb_display,
name: "RGB display", properties: {}
},
RmtProperties {
driver: rmt,
name: "RMT",
properties: {
ram_start: u32,
channel_ram_size: u32,
channels: RmtChannelConfig,
#[serde(default)]
has_tx_immediate_stop: bool,
#[serde(default)]
has_tx_loop_count: bool,
#[serde(default)]
has_tx_loop_auto_stop: bool,
#[serde(default)]
has_tx_carrier_data_only: bool,
#[serde(default)]
has_tx_sync: bool,
#[serde(default)]
has_rx_wrap: bool,
#[serde(default)]
has_rx_demodulation: bool,
#[serde(default)]
has_dma: bool,
#[serde(default)]
has_per_channel_clock: bool,
clock_sources: RmtClockSourcesConfig,
}
},
RngProperties {
driver: rng,
name: "RNG",
properties: {
apb_cycle_wait_num: u32,
#[serde(default)]
trng_supported: bool,
}
},
RsaProperties {
driver: rsa,
name: "RSA",
has_computed_properties: true,
properties: {
size_increment: u32,
memory_size_bytes: u32,
}
},
LpTimer {
driver: lp_timer,
name: "RTC Timekeeping",
properties: {}
},
SdHostProperties {
driver: sd_host,
name: "SDIO host",
properties: {}
},
SdSlaveProperties {
driver: sd_slave,
name: "SDIO slave",
properties: {}
},
ShaProperties {
driver: sha,
name: "SHA",
properties: {
#[serde(default)]
dma: bool,
#[serde(default)]
algo: ShaAlgoMap,
}
},
SleepProperties {
driver: sleep,
name: "Light/deep sleep",
properties: {
#[serde(default)]
light_sleep: bool,
#[serde(default)]
deep_sleep: bool,
}
},
SocProperties {
driver: soc,
name: "SOC",
hide_from_peri_table: true,
properties: {
#[serde(default)]
cpu_has_branch_predictor: bool,
#[serde(default)]
cpu_has_csr_pc: bool,
#[serde(default)]
multi_core_enabled: bool,
#[serde(default)]
cpu_csr_prv_mode: Option<u32>,
#[serde(default)]
rc_fast_clk_default: Option<u32>,
#[serde(flatten)]
config: SocConfig,
}
},
SpiMasterProperties<SpiMasterInstanceConfig> {
driver: spi_master,
name: "SPI master",
properties: {
#[serde(default)]
supports_dma: bool,
#[serde(default)]
has_octal: bool,
#[serde(default)]
has_app_interrupts: bool,
#[serde(default)]
has_dma_segmented_transfer: bool,
#[serde(default)]
has_clk_pre_div: bool,
}
},
SpiSlaveProperties<SpiSlaveInstanceConfig> {
driver: spi_slave,
name: "SPI slave",
properties: {
#[serde(default)]
supports_dma: bool,
}
},
SysTimerProperties {
driver: systimer,
name: "SYSTIMER",
properties: {}
},
TempProperties {
driver: temp_sensor,
name: "Temperature sensor",
properties: {}
},
TimersProperties {
driver: timergroup,
name: "Timers",
properties: {
#[serde(default)]
timg_has_timer1: bool,
#[serde(default)]
timg_has_divcnt_rst: bool,
#[serde(default)]
rc_fast_calibration: Option<RcFastCalibrationProperties>,
}
},
TouchProperties {
driver: touch,
name: "Touch",
properties: {}
},
TwaiProperties {
driver: twai,
name: "TWAI / CAN / CANFD",
properties: {}
},
UartProperties<UartInstanceConfig> {
driver: uart,
name: "UART",
properties: {
ram_size: u32,
#[serde(default)]
peripheral_controls_mem_clk: bool,
#[serde(default)]
has_sclk_divider: bool,
}
},
UhciProperties {
driver: uhci,
name: "UHCI",
properties: {
#[serde(default)]
combined_uart_selector_field: bool,
}
},
UlpFsmProperties {
driver: ulp_fsm,
name: "ULP (FSM)",
properties: {}
},
UlpRiscvProperties {
driver: ulp_riscv,
name: "ULP (RISC-V)",
properties: {}
},
UsbOtgProperties {
driver: usb_otg,
name: "USB OTG FS",
properties: {}
},
UsbSerialJtagProperties {
driver: usb_serial_jtag,
name: "USB Serial/JTAG",
properties: {}
},
WifiProperties {
driver: wifi,
name: "WIFI",
properties: {
#[serde(default)]
has_wifi6: bool,
mac_version: u32,
#[serde(default)]
has_5g: bool,
#[serde(default)]
csi_supported: bool,
}
},
];