Skip to main content

probe_rs_target/
lib.rs

1//! Target description schema
2//!
3//! For debugging and flashing different chips, called *target* in probe-rs, some
4//! target specific configuration is required. This includes the architecture of
5//! the chip, e.g. RISC-V or ARM, and information about the memory map of the target,
6//! which can be used together with a flash algorithm to program the flash memory
7//! of a target.
8//!
9//! This crate contains the schema structs for the YAML target description files.
10//!
11#![warn(missing_docs)]
12
13mod chip;
14pub mod chip_detection;
15mod chip_family;
16mod flash_algorithm;
17mod flash_properties;
18mod memory;
19pub(crate) mod serialize;
20
21pub use chip::{
22    ApAddress, ArmCoreAccessOptions, Chip, Core, CoreAccessOptions, Jtag, RiscvCoreAccessOptions,
23    RiscvJtagTunnel, ScanChainElement, XtensaCoreAccessOptions,
24};
25pub use chip_family::{
26    Architecture, ChipFamily, CoreType, Endian, InstructionSet, TargetDescriptionSource,
27};
28pub use flash_algorithm::{RawFlashAlgorithm, TransferEncoding};
29pub use flash_properties::FlashProperties;
30pub use memory::{
31    GenericRegion, MemoryAccess, MemoryRange, MemoryRegion, NvmRegion, PageInfo, RamRegion,
32    RegionMergeIterator, SectorDescription, SectorInfo,
33};
34
35#[cfg(feature = "bincode")]
36mod builtin_targets {
37    use std::fs::{read_dir, read_to_string};
38    use std::io;
39    use std::path::{Path, PathBuf};
40
41    use crate::ChipFamily;
42
43    /// Process target yamls at the given source paths, and produce a bincode-encoded file at the destination path.
44    pub fn process_targets(source_paths: &[PathBuf], dest_path: &Path) {
45        let mut families = Vec::new();
46        let mut process_target_yaml = |file: &Path| {
47            let string = read_to_string(file).unwrap_or_else(|error| {
48                panic!(
49                    "Failed to read target file {} because:\n{error}",
50                    file.display()
51                )
52            });
53
54            match yaml_serde::from_str::<ChipFamily>(&string) {
55                Ok(family) => families.push(family),
56                Err(error) => panic!(
57                    "Failed to parse target file: {} because:\n{error}",
58                    file.display()
59                ),
60            }
61        };
62
63        for path in source_paths {
64            visit_dirs(path, &mut process_target_yaml).unwrap();
65        }
66
67        let config = bincode::config::standard();
68        let families_bin = bincode::serde::encode_to_vec(&families, config)
69            .expect("Failed to serialize families as bincode");
70
71        std::fs::write(dest_path, &families_bin).unwrap();
72
73        // Check if we can deserialize the bincode again, otherwise the binary will not be usable.
74        if let Err(deserialize_error) =
75            bincode::serde::decode_from_slice::<Vec<ChipFamily>, _>(&families_bin, config)
76        {
77            panic!(
78                "Failed to deserialize supported target definitions from bincode: {deserialize_error:?}"
79            );
80        }
81    }
82
83    /// Call `process` on all files in a directory and its subdirectories.
84    fn visit_dirs(dir: impl AsRef<Path>, process: &mut impl FnMut(&Path)) -> io::Result<()> {
85        // Inner function to avoid generating multiple implementations for the different path types.
86        fn visit_dirs_impl(dir: &Path, process: &mut impl FnMut(&Path)) -> io::Result<()> {
87            for entry in read_dir(dir)? {
88                let entry = entry?;
89                let path = entry.path();
90                if path.is_dir() {
91                    visit_dirs_impl(&path, process)?;
92                } else {
93                    process(&path);
94                }
95            }
96
97            Ok(())
98        }
99
100        let dir = dir.as_ref();
101        if !dir.is_dir() {
102            return Ok(());
103        }
104
105        visit_dirs_impl(dir, process)
106    }
107}
108
109#[cfg(feature = "bincode")]
110pub use builtin_targets::process_targets;