diff --git a/zephyr-build/src/devicetree.rs b/zephyr-build/src/devicetree.rs index 2ec6b64b..6c7d0d08 100644 --- a/zephyr-build/src/devicetree.rs +++ b/zephyr-build/src/devicetree.rs @@ -24,12 +24,11 @@ use ordmap::OrdMap; use std::{cell::RefCell, collections::BTreeMap, path::Path, rc::Rc}; mod augment; -pub mod config; mod ordmap; mod output; mod parse; -pub use augment::Augment; +pub use augment::{Augment, load_augments}; pub struct DeviceTree { /// The root of the tree. diff --git a/zephyr-build/src/devicetree/augment.rs b/zephyr-build/src/devicetree/augment.rs index b39a7196..6b82d87f 100644 --- a/zephyr-build/src/devicetree/augment.rs +++ b/zephyr-build/src/devicetree/augment.rs @@ -1,11 +1,25 @@ //! Support for augmenting the device tree. - -use proc_macro2::TokenStream; +//! +//! There are various aspects of the device tree in Zephyr whose semantics are only indirectly +//! defined by the behavior of C code. Rather than trying to decipher this at build time, we will +//! use one or more yaml files that describe aspects of the device tree. +//! +//! This module is responsible for the format of this config file and the parsed contents will be +//! used to generate the [`Augment`] objects that will do the actual augmentation of the generated +//! device tree. +//! +//! Each augment is described by a top-level yaml element in an array. + +use std::{fs::File, path::Path}; + +use anyhow::Result; +use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote}; +use serde::{Deserialize, Serialize}; -use crate::devicetree::output::dt_to_lower_id; +use crate::devicetree::{output::dt_to_lower_id, Word}; -use super::{DeviceTree, Node, Word}; +use super::{DeviceTree, Node}; /// This action is given to each node in the device tree, and it is given a chance to return /// additional code to be included in the module associated with that entry. These are all @@ -29,228 +43,256 @@ pub trait Augment { fn generate(&self, node: &Node, tree: &DeviceTree) -> TokenStream; } -/// Return all of the Augments we wish to apply. -pub fn get_augments() -> Vec> { - vec![ - Box::new(GpioAugment), - Box::new(GpioLedsAugment), - Box::new(FlashControllerAugment), - Box::new(FlashPartitionAugment), - Box::new(SinglePartitionAugment), - Box::new(LabelAugment), - ] +/// A top level augmentation. +/// +/// This top level augmentation describes how to match a given node within the device tree, and then +/// what kind of action to describe upon that. +#[derive(Debug, Serialize, Deserialize)] +pub struct Augmentation { + /// A name for this augmentation. Used for diagnostic purposes. + name: String, + /// What to match. This is an array, and all must match for a given node to be considered. + /// This does mean that if this is an empty array, it will match on every node. + rules: Vec, + /// What to do when a given node matches. + actions: Vec, } -/// Augment gpio nodes. Gpio nodes are indicated by the 'gpio-controller' property, and not a -/// particular compatible. -struct GpioAugment; - -impl Augment for GpioAugment { +impl Augment for Augmentation { fn is_compatible(&self, node: &Node) -> bool { - node.has_prop("gpio-controller") + self.rules.iter().all(|n| n.is_compatible(node)) } - fn generate(&self, node: &Node, _tree: &DeviceTree) -> TokenStream { - let ord = node.ord; - let device = format_ident!("__device_dts_ord_{}", ord); + fn generate(&self, node: &Node, tree: &DeviceTree) -> TokenStream { + let name = format_ident!("{}", dt_to_lower_id(&self.name)); + let actions = self.actions.iter().map(|a| a.generate(&name, node, tree)); + quote! { - pub unsafe fn get_instance_raw() -> *const crate::raw::device { - &crate::raw::#device - } - pub fn get_instance() -> crate::sys::gpio::Gpio { - let device = unsafe { get_instance_raw() }; - crate::sys::gpio::Gpio { - device, - } - } + #(#actions)* } } } -/// Augment the individual led nodes. This provides a safe wrapper that can be used to directly use -/// these nodes. -struct GpioLedsAugment; +/// A matching rule. +#[derive(Debug, Serialize, Deserialize)] +#[serde(tag = "type", rename_all = "snake_case", content = "value")] +pub enum Rule { + /// A set of "or" matches. + Or(Vec), + /// A set of "and" matches. Not needed at the top level, as the top level vec is an implicit + /// and. + And(Vec), + /// Matches if the node has the given property. + HasProp(String), + /// Matches if this node has one of the listed compatible strings. The the 'level' property + /// indicates how many levels up in the tree. Zero means match the current node, 1 means the + /// parent node, and so on. + Compatible { + names: Vec, + level: usize, + }, + /// Matches at the root of tree. + Root, +} -impl Augment for GpioLedsAugment { - // GPIO Leds are nodes whose parent is compatible with "gpio-leds". +impl Rule { fn is_compatible(&self, node: &Node) -> bool { - if let Some(parent) = node.parent.borrow().as_ref() { - parent.is_compatible("gpio-leds") - } else { - false + match self { + Rule::Or(rules) => rules.iter().any(|n| n.is_compatible(node)), + Rule::And(rules) => rules.iter().all(|n| n.is_compatible(node)), + Rule::HasProp(name) => node.has_prop(name), + Rule::Compatible { names, level } => parent_compatible(node, names, *level), + Rule::Root => node.parent.borrow().is_none(), } } +} - fn generate(&self, node: &Node, _tree: &DeviceTree) -> TokenStream { - // TODO: Generalize this. - let words = node.get_words("gpios").unwrap(); - let target = if let Word::Phandle(gpio) = &words[0] { - gpio.node_ref() +/// Determine if a node is compatible, looking `levels` levels up in the tree, where 0 means this +/// node. +fn parent_compatible(node: &Node, names: &[String], level: usize) -> bool { + // Writing this recursively simplifies the borrowing a lot. Otherwise, we'd have to clone the + // RCs. Our choice is the extra clone, or keeping the borrowed values on the stack. This code + // runs on the host, so the stack is easier. + if level == 0 { + names.iter().any(|n| node.is_compatible(n)) + } else { + if let Some(parent) = node.parent.borrow().as_ref() { + parent_compatible(parent, names, level - 1) } else { - panic!("gpios property in node is empty"); - }; - - // At this point, we support gpio-cells of 2. - if target.get_number("#gpio-cells") != Some(2) { - panic!("gpios only support with #gpio-cells of 2"); - } - - if words.len() != 3 { - panic!("gpio-leds, gpios property expected to have only one entry"); + false } + } +} - let pin = words[1].get_number().unwrap(); - let flags = words[2].get_number().unwrap(); +/// An action to perform +#[derive(Debug, Serialize, Deserialize)] +#[serde(tag = "type", rename_all = "snake_case", content = "value")] +pub enum Action { + /// Generate an "instance" with a specific device name. + Instance { + /// Where to get the raw device information. + raw: RawInfo, + /// The name of the full path (within the zephyr-sys crate) for the wrapper node for this + /// device. + device: String, + }, + /// Generate all of the labels as its own node. + Labels, +} - let gpio_route = target.route_to_rust(); - quote! { - pub fn get_instance() -> crate::sys::gpio::GpioPin { - unsafe { - let port = #gpio_route :: get_instance_raw(); - crate::sys::gpio::GpioPin { - pin: crate::raw::gpio_dt_spec { - port, - pin: #pin as crate::raw::gpio_pin_t, - dt_flags: #flags as crate::raw::gpio_dt_flags_t, +impl Action { + fn generate(&self, _name: &Ident, node: &Node, tree: &DeviceTree) -> TokenStream { + match self { + Action::Instance { raw, device } => { + raw.generate(node, device) + } + Action::Labels => { + let nodes = tree.labels.iter().map(|(k, v)| { + let name = dt_to_lower_id(k); + let path = v.route_to_rust(); + quote! { + pub mod #name { + pub use #path::*; } } + }); + + quote! { + // This does assume the devicetree doesn't have a "labels" node at the root. + pub mod labels { + /// All of the labeles in the device tree. The device tree compiler + /// enforces that these are unique, allowing references such as + /// `zephyr::devicetree::labels::labelname::get_instance()`. + #(#nodes)* + } } } } } } -/// Augment flash controllers. -/// -/// Flash controllers are a little weird, because there is no unified compatible that says they -/// implement the flash interface. In fact, they seem to generally not be accessed through the -/// device tree at all. -struct FlashControllerAugment; +#[derive(Debug, Serialize, Deserialize)] +#[serde(tag = "type", rename_all = "snake_case", content = "value")] +pub enum RawInfo { + /// Get the raw device directly from this node. + Myself, + /// Get the reference from a parent of this node, at a given level. + Parent { + /// How many levels to look up. 0 would refer to this node (but would also be an error). + level: usize, + args: Vec, + }, + /// Get the raw device from a phandle property. Additional parameters in the phandle will be + /// passed as additional arguments to the `new` constructor on the wrapper type. + Phandle(String), +} -impl Augment for FlashControllerAugment { - // For now, just look for specific ones we know. - fn is_compatible(&self, node: &Node) -> bool { - node.is_compatible("nordic,nrf52-flash-controller") || - node.is_compatible("raspberrypi,pico-flash-controller") - } +impl RawInfo { + fn generate(&self, node: &Node, device: &str) -> TokenStream { + let device_id = str_to_path(device); + match self { + RawInfo::Myself => { + let ord = node.ord; + let rawdev = format_ident!("__device_dts_ord_{}", ord); + quote! { + /// Get the raw `const struct device *` of the device tree generated node. + pub unsafe fn get_instance_raw() -> *const crate::raw::device { + &crate::raw::#rawdev + } - fn generate(&self, node: &Node, _tree: &DeviceTree) -> TokenStream { - // For now, just return the device node. - let ord = node.ord; - let device = format_ident!("__device_dts_ord_{}", ord); - quote! { - pub unsafe fn get_instance_raw() -> *const crate::raw::device { - &crate::raw::#device + static UNIQUE: crate::device::Unique = crate::device::Unique::new(); + pub fn get_instance() -> Option<#device_id> { + unsafe { + let device = get_instance_raw(); + #device_id::new(&UNIQUE, device) + } + } + } } - - pub fn get_instance() -> crate::sys::flash::FlashController { - let device = unsafe { get_instance_raw() }; - crate::sys::flash::FlashController { - device, + RawInfo::Phandle(pname) => { + let words = node.get_words(pname).unwrap(); + // We assume that elt 0 is the phandle, and that the rest are numbers. + let target = if let Word::Phandle(handle) = &words[0] { + handle.node_ref() + } else { + panic!("phandle property {:?} in node is empty", pname); + }; + + // TODO: We would try to correlate with parent node's notion of number of cells, and + // try to handle cases where there is more than one reference. It is unclear when + // this will be needed. + let args: Vec = words[1..].iter().map(|n| n.get_number().unwrap()).collect(); + + let target_route = target.route_to_rust(); + + quote! { + static UNIQUE: crate::device::Unique = crate::device::Unique::new(); + pub fn get_instance() -> Option<#device_id> { + unsafe { + let device = #target_route :: get_instance_raw(); + #device_id::new(&UNIQUE, device, #(#args),*) + } + } } } - } - } -} + RawInfo::Parent { level, args } => { + let get_args = args.iter().map(|arg| arg.args(node)); -/// Augment flash partitions. -/// -/// This provides access to the individual partitions via named modules under the flash device. -struct FlashPartitionAugment; - -impl Augment for FlashPartitionAugment { - fn is_compatible(&self, node: &Node) -> bool { - node.compatible_path(&[Some("fixed-partitions"), Some("soc-nv-flash")]) - } - - fn generate(&self, node: &Node, _tree: &DeviceTree) -> TokenStream { - let children = node.children.iter().map(|child| { - let label = child.get_single_string("label").unwrap(); - let label = dt_to_lower_id(label); - let reg = child.get_numbers("reg").unwrap(); - if reg.len() != 2 { - panic!("flash partition entry must have 2 reg values"); - } - let offset = reg[0]; - let size = reg[1]; + assert!(*level > 0); + let mut path = quote! {super}; + for _ in 1..*level { + path = quote! { #path :: super }; + } - quote! { - pub mod #label { - pub fn get_instance() -> crate::sys::flash::FlashPartition { - let controller = super::super::super::get_instance(); - crate::sys::flash::FlashPartition { - controller, - offset: #offset, - size: #size, + quote! { + static UNIQUE: crate::device::Unique = crate::device::Unique::new(); + pub fn get_instance() -> Option<#device_id> { + unsafe { + let device = #path :: get_instance_raw(); + #device_id::new(&UNIQUE, device, #(#get_args),*) } } } } - }); - quote! { - #(#children)* } } } -/// Augment the partitions themselves rather than the whole partition table. -struct SinglePartitionAugment; - -impl Augment for SinglePartitionAugment { - fn is_compatible(&self, node: &Node) -> bool { - node.compatible_path(&[None, Some("fixed-partitions"), Some("soc-nv-flash")]) - } - - fn generate(&self, node: &Node, _tree: &DeviceTree) -> TokenStream { - let reg = node.get_numbers("reg").unwrap(); - if reg.len() != 2 { - panic!("flash partition entry must have 2 reg values"); - } - let offset = reg[0]; - let size = reg[1]; +/// Information about where to get constructor properties for arguments. +/// +/// At this point, we assume these all come from the current node. +#[derive(Debug, Serialize, Deserialize)] +#[serde(tag = "type", rename_all = "snake_case", content = "value")] +pub enum ArgInfo { + /// The arguments come from a 'reg' property. + Reg, +} - quote! { - pub fn get_instance() -> crate::sys::flash::FlashPartition { - let controller = super::super::super::get_instance(); - crate::sys::flash::FlashPartition { - controller, - offset: #offset, - size: #size, +impl ArgInfo { + /// Extra properties for the argument, assembling the arguents that should be passed in. + fn args(&self, node: &Node) -> TokenStream { + match self { + ArgInfo::Reg => { + let reg = node.get_numbers("reg").unwrap(); + quote! { + #(#reg),* } } } } } -/// Add in all of the labels. -struct LabelAugment; - -impl Augment for LabelAugment { - fn is_compatible(&self, node: &Node) -> bool { - // Insert the labels at the root node. - println!("Augment check: {}", node.path); - if let Some(parent) = node.parent.borrow().as_ref() { - println!(" parent: {}", parent.path); - } - node.parent.borrow().is_none() +/// Split a path given by a user into a token stream. +fn str_to_path(path: &str) -> TokenStream { + let names = path.split("::").map(|n| format_ident!("{}", n)); + quote! { + #(#names)::* } +} - fn generate(&self, _node: &Node, tree: &DeviceTree) -> TokenStream { - let nodes = tree.labels.iter().map(|(k, v)| { - let name = dt_to_lower_id(k); - let path = v.route_to_rust(); - quote! { - pub mod #name { - pub use #path::*; - } - } - }); - - quote! { - // This does assume the devicetree doesn't have a "labels" node at the root. - pub mod labels { - #(#nodes)* - } - } - } +/// Load a file of the given name. +pub fn load_augments>(name: P) -> Result> { + let fd = File::open(name)?; + let augs: Vec = serde_yaml_ng::from_reader(fd)?; + Ok(augs) } diff --git a/zephyr-build/src/devicetree/config.rs b/zephyr-build/src/devicetree/config.rs deleted file mode 100644 index 09488bef..00000000 --- a/zephyr-build/src/devicetree/config.rs +++ /dev/null @@ -1,313 +0,0 @@ -//! Config handling. -//! -//! There are various aspects of the device tree in Zephyr whose semantics are only indirectly -//! defined by the behavior of C code. Rather than trying to decipher this at build time, we will -//! use one or more yaml files that describe aspects of the device tree. -//! -//! This module is responsible for the format of this config file and the parsed contents will be -//! used to generate the [`Augment`] objects that will do the actual augmentation of the generated -//! device tree. -//! -//! Each augment is described by a top-level yaml element in an array. - -use std::{fs::File, path::Path}; - -use anyhow::Result; -use proc_macro2::{Ident, TokenStream}; -use quote::{format_ident, quote}; -use serde::{Deserialize, Serialize}; - -use crate::devicetree::{output::dt_to_lower_id, Word}; - -use super::{augment::Augment, DeviceTree, Node}; - -/// A top level augmentation. -/// -/// This top level augmentation describes how to match a given node within the device tree, and then -/// what kind of action to describe upon that. -#[derive(Debug, Serialize, Deserialize)] -pub struct Augmentation { - /// A name for this augmentation. Used for diagnostic purposes. - name: String, - /// What to match. This is an array, and all must match for a given node to be considered. - /// This does mean that if this is an empty array, it will match on every node. - rules: Vec, - /// What to do when a given node matches. - actions: Vec, -} - -impl Augment for Augmentation { - fn is_compatible(&self, node: &Node) -> bool { - self.rules.iter().all(|n| n.is_compatible(node)) - } - - fn generate(&self, node: &Node, tree: &DeviceTree) -> TokenStream { - let name = format_ident!("{}", dt_to_lower_id(&self.name)); - let actions = self.actions.iter().map(|a| a.generate(&name, node, tree)); - - quote! { - #(#actions)* - } - } -} - -/// A matching rule. -#[derive(Debug, Serialize, Deserialize)] -#[serde(tag = "type", rename_all = "snake_case", content = "value")] -pub enum Rule { - /// A set of "or" matches. - Or(Vec), - /// A set of "and" matches. Not needed at the top level, as the top level vec is an implicit - /// and. - And(Vec), - /// Matches if the node has the given property. - HasProp(String), - /// Matches if this node has one of the listed compatible strings. The the 'level' property - /// indicates how many levels up in the tree. Zero means match the current node, 1 means the - /// parent node, and so on. - Compatible { - names: Vec, - level: usize, - }, - /// Matches at the root of tree. - Root, -} - -impl Rule { - fn is_compatible(&self, node: &Node) -> bool { - match self { - Rule::Or(rules) => rules.iter().any(|n| n.is_compatible(node)), - Rule::And(rules) => rules.iter().all(|n| n.is_compatible(node)), - Rule::HasProp(name) => node.has_prop(name), - Rule::Compatible { names, level } => parent_compatible(node, names, *level), - Rule::Root => node.parent.borrow().is_none(), - } - } -} - -/// Determine if a node is compatible, looking `levels` levels up in the tree, where 0 means this -/// node. -fn parent_compatible(node: &Node, names: &[String], level: usize) -> bool { - // Writing this recursively simplifies the borrowing a lot. Otherwise, we'd have to clone the - // RCs. Our choice is the extra clone, or keeping the borrowed values on the stack. This code - // runs on the host, so the stack is easier. - if level == 0 { - names.iter().any(|n| node.is_compatible(n)) - } else { - if let Some(parent) = node.parent.borrow().as_ref() { - parent_compatible(parent, names, level - 1) - } else { - false - } - } -} - -/// An action to perform -#[derive(Debug, Serialize, Deserialize)] -#[serde(tag = "type", rename_all = "snake_case", content = "value")] -pub enum Action { - /// Generate an "instance" with a specific device name. - Instance { - /// Where to get the raw device information. - raw: RawInfo, - /// The name of the full path (within the zephyr-sys crate) for the wrapper node for this - /// device. - device: String, - }, - /// Generate all of the labels as its own node. - Labels, -} - -impl Action { - fn generate(&self, _name: &Ident, node: &Node, tree: &DeviceTree) -> TokenStream { - match self { - Action::Instance { raw, device } => { - raw.generate(node, device) - } - Action::Labels => { - let nodes = tree.labels.iter().map(|(k, v)| { - let name = dt_to_lower_id(k); - let path = v.route_to_rust(); - quote! { - pub mod #name { - pub use #path::*; - } - } - }); - - quote! { - // This does assume the devicetree doesn't have a "labels" node at the root. - pub mod labels { - /// All of the labeles in the device tree. The device tree compiler - /// enforces that these are unique, allowing references such as - /// `zephyr::devicetree::labels::labelname::get_instance()`. - #(#nodes)* - } - } - } - } - } -} - -#[derive(Debug, Serialize, Deserialize)] -#[serde(tag = "type", rename_all = "snake_case", content = "value")] -pub enum RawInfo { - /// Get the raw device directly from this node. - Myself, - /// Get the reference from a parent of this node, at a given level. - Parent { - /// How many levels to look up. 0 would refer to this node (but would also be an error). - level: usize, - args: Vec, - }, - /// Get the raw device from a phandle property. Additional parameters in the phandle will be - /// passed as additional arguments to the `new` constructor on the wrapper type. - Phandle(String), -} - -impl RawInfo { - fn generate(&self, node: &Node, device: &str) -> TokenStream { - let device_id = str_to_path(device); - match self { - RawInfo::Myself => { - let ord = node.ord; - let rawdev = format_ident!("__device_dts_ord_{}", ord); - quote! { - /// Get the raw `const struct device *` of the device tree generated node. - pub unsafe fn get_instance_raw() -> *const crate::raw::device { - &crate::raw::#rawdev - } - - static UNIQUE: crate::device::Unique = crate::device::Unique::new(); - pub fn get_instance() -> Option<#device_id> { - unsafe { - let device = get_instance_raw(); - #device_id::new(&UNIQUE, device) - } - } - } - } - RawInfo::Phandle(pname) => { - let words = node.get_words(pname).unwrap(); - // We assume that elt 0 is the phandle, and that the rest are numbers. - let target = if let Word::Phandle(handle) = &words[0] { - handle.node_ref() - } else { - panic!("phandle property {:?} in node is empty", pname); - }; - - // TODO: We would try to correlate with parent node's notion of number of cells, and - // try to handle cases where there is more than one reference. It is unclear when - // this will be needed. - let args: Vec = words[1..].iter().map(|n| n.get_number().unwrap()).collect(); - - let target_route = target.route_to_rust(); - - quote! { - static UNIQUE: crate::device::Unique = crate::device::Unique::new(); - pub fn get_instance() -> Option<#device_id> { - unsafe { - let device = #target_route :: get_instance_raw(); - #device_id::new(&UNIQUE, device, #(#args),*) - } - } - } - } - RawInfo::Parent { level, args } => { - let get_args = args.iter().map(|arg| arg.args(node)); - - assert!(*level > 0); - let mut path = quote! {super}; - for _ in 1..*level { - path = quote! { #path :: super }; - } - - quote! { - static UNIQUE: crate::device::Unique = crate::device::Unique::new(); - pub fn get_instance() -> Option<#device_id> { - unsafe { - let device = #path :: get_instance_raw(); - #device_id::new(&UNIQUE, device, #(#get_args),*) - } - } - } - } - } - } -} - -/// Information about where to get constructor properties for arguments. -/// -/// At this point, we assume these all come from the current node. -#[derive(Debug, Serialize, Deserialize)] -#[serde(tag = "type", rename_all = "snake_case", content = "value")] -pub enum ArgInfo { - /// The arguments come from a 'reg' property. - Reg, -} - -impl ArgInfo { - /// Extra properties for the argument, assembling the arguents that should be passed in. - fn args(&self, node: &Node) -> TokenStream { - match self { - ArgInfo::Reg => { - let reg = node.get_numbers("reg").unwrap(); - quote! { - #(#reg),* - } - } - } - } -} - -/// Split a path given by a user into a token stream. -fn str_to_path(path: &str) -> TokenStream { - let names = path.split("::").map(|n| format_ident!("{}", n)); - quote! { - #(#names)::* - } -} - -/// Load a file of the given name. -pub fn load>(name: P) -> Result> { - let fd = File::open(name)?; - let augs: Vec = serde_yaml_ng::from_reader(fd)?; - Ok(augs) -} - -/// Output a sample yaml file, so we can understand the format. -pub fn sample() { - use std::fs::File; - - let data = vec![ - Augmentation { - name: "gpio-controller".to_string(), - rules: vec![ - Rule::HasProp("gpio-controller".to_string()), - ], - actions: vec![ - Action::Instance { - raw: RawInfo::Myself, - device: "crate::sys::gpio::Gpio".to_string(), - }, - ], - }, - Augmentation { - name: "gpio-leds".to_string(), - rules: vec![ - Rule::Compatible { - names: vec!["gpio-leds".to_string()], - level: 1, - }, - ], - actions: vec![ - Action::Instance { - raw: RawInfo::Phandle("gpios".to_string()), - device: "crate::sys::gpio::GpioPin".to_string(), - } - ], - }, - ]; - let fd = File::create("dt-sample.yaml").unwrap(); - serde_yaml_ng::to_writer(fd, &data).unwrap(); -} diff --git a/zephyr-build/src/lib.rs b/zephyr-build/src/lib.rs index e9be1320..7763449d 100644 --- a/zephyr-build/src/lib.rs +++ b/zephyr-build/src/lib.rs @@ -24,9 +24,6 @@ use devicetree::{Augment, DeviceTree}; mod devicetree; -/// For debugging. -pub use devicetree::config::sample; - /// Export boolean Kconfig entries. This must happen in any crate that wishes to access the /// configuration settings. pub fn export_bool_kconfig() { @@ -102,7 +99,7 @@ pub fn build_dts() { let mut augs = Vec::new(); for aug in &augments { // println!("Load augment: {:?}", aug); - let mut aug = devicetree::config::load(aug).expect("Loading augment file"); + let mut aug = devicetree::load_augments(aug).expect("Loading augment file"); augs.append(&mut aug); } // For now, just print it out.