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

use anyhow::Result;
use svd_parser as svd;
use svd_parser::Device;

use crate::overrides::DeviceOverrides;
use crate::package::_Package;

#[macro_use]
mod utils;
mod cluster;
mod device;
mod field;
mod generate;
mod overrides;
mod package;
mod peripheral;
mod register;

/// Generates module structure
pub fn generate(svd_file: &Path, overrides_file: Option<&Path>, project_dir: &Path) -> Result<()> {
    let device = load_device(svd_file)?;
    let overrides = load_overrides(overrides_file)?;
    generate::generate_package(project_dir, _Package::build(&device, overrides.as_ref()))?;
    Ok(())
}

fn load_device(svd_file: &Path) -> Result<Device> {
    let file = &mut String::new();
    File::open(svd_file)?.read_to_string(file)?;
    svd::parse(file)
}

fn load_overrides(overrides_file: Option<&Path>) -> Result<Option<DeviceOverrides>> {
    if overrides_file.is_none() {
        return Ok(None);
    }
    let file = &mut String::new();
    File::open(overrides_file.unwrap())?.read_to_string(file)?;

    let overrides: DeviceOverrides = serde_yaml::from_str(file)?;
    Ok(Some(overrides))
}