ral_gen/lib.rs
1//! Code generator for [ral](https://docs.rs/ral) crate
2//!
3//! # How to install
4//!
5//! ```bash
6//! $ cargo install ral-gen
7//! ```
8//!
9//! # How to use
10//!
11//! ```bash
12//! $ cargo ral-gen --svd <SVD file> --overrides <YML file> --out <Target dir>
13//! ```
14//! or short form
15//! ```bash
16//! $ cargo ral-gen -i <SVD file> -e <YML file> -o <Target dir>
17//! ```
18//!
19//! # Overrides
20//!
21//! Overrides can be specified in separate `yaml` file of the following structure
22//! ```yaml
23//! name: <alternate device name> // Must be identifier
24//! description: <alternate device description>
25//! peripherals:
26//! <peripheral name>: // as can be found in .svd file
27//! name: <alternate peripheral name> // Must be identifier
28//! description: <alternate peripheral description>
29//! features: // List of features for conditional compilation, e.g. packaging names
30//! - <feature1> // to exclude peripheral if it's not available
31//! - <feature2>
32//! clusters:
33//! <cluster name>: // as can be found in .svd file
34//! name: <alternate cluster name> // Must be identifier
35//! description: <alternate cluster description>
36//! features: // List of features for conditional compilation, e.g. packaging names
37//! - <feature1> // to exclude cluster if it's not available
38//! - <feature2>
39//! registers:
40//! <register name>: // as can be found in .svd file
41//! name: <alternate register name> // Must be identifier
42//! description: <alternate register description>
43//! features: // List of features for conditional compilation, e.g. packaging names
44//! - <feature1> // to exclude register if it's not available
45//! - <feature2>
46//! uses: // use expressions required for field type overrides
47//! - crate_name::types::CustomType
48//! fields:
49//! <field name>: // as can be found in .svd file
50//! name: <alternate field name> // Must be identifier
51//! description: <alternate field description>
52//! type: CustomType // Required use expression must be specified in register's uses section
53//! ```
54//! All fields are optional
55//!
56//! # What will be generated
57//!
58//! Module structure described in [ral](https://docs.rs/ral) crate documentation will be generated
59//!
60//! Also `Cargo.toml` will be generated with content
61//! ```toml
62//! [package]
63//! name = "<device name in lowercase>"
64//! description = "<device description if present>"
65//! version = "<ral-gen version>"
66//! edition = "2018"
67//!
68//! [dependencies]
69//! ral = "<ral-gen version with patch section zeroed>"
70//!
71//! [features]
72//! feature1 = []
73//! feature2 = []
74//! ```
75use std::fs::File;
76use std::io::Read;
77use std::path::Path;
78
79use anyhow::Result;
80use svd_parser as svd;
81use svd_parser::Device;
82
83use crate::overrides::DeviceOverrides;
84use crate::package::_Package;
85
86#[macro_use]
87mod utils;
88mod cluster;
89mod device;
90mod field;
91mod generate;
92mod overrides;
93mod package;
94mod peripheral;
95mod register;
96
97/// Generates module structure
98pub fn generate(svd_file: &Path, overrides_file: Option<&Path>, project_dir: &Path) -> Result<()> {
99 let device = load_device(svd_file)?;
100 let overrides = load_overrides(overrides_file)?;
101 generate::generate_package(project_dir, _Package::build(&device, overrides.as_ref()))?;
102 Ok(())
103}
104
105fn load_device(svd_file: &Path) -> Result<Device> {
106 let file = &mut String::new();
107 File::open(svd_file)?.read_to_string(file)?;
108 svd::parse(file)
109}
110
111fn load_overrides(overrides_file: Option<&Path>) -> Result<Option<DeviceOverrides>> {
112 if overrides_file.is_none() {
113 return Ok(None);
114 }
115 let file = &mut String::new();
116 File::open(overrides_file.unwrap())?.read_to_string(file)?;
117
118 let overrides: DeviceOverrides = serde_yaml::from_str(file)?;
119 Ok(Some(overrides))
120}