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 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
use super::chip::Chip;
use super::flash_algorithm::RawFlashAlgorithm;
use jep106::JEP106Code;
use serde::{Deserialize, Serialize};
/// Source of a target description.
///
/// This is used for diagnostics, when
/// an error related to a target description occurs.
#[derive(Clone, Debug, PartialEq)]
pub enum TargetDescriptionSource {
/// The target description is a generic target description,
/// which just describes a core type (e.g. M4), without any
/// flash algorithm or memory description.
Generic,
/// The target description is a built-in target description,
/// which was included into probe-rs at compile time.
BuiltIn,
/// The target description was from an external source
/// during runtime.
External,
}
/// Type of a supported core.
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum CoreType {
/// ARMv6-M: Cortex M0, M0+, M1
Armv6m,
/// ARMv7-M: Cortex M3
Armv7m,
/// ARMv7e-M: Cortex M4, M7
Armv7em,
/// ARMv8-M: Cortex M23, M33
Armv8m,
/// RISC-V
Riscv,
}
/// The architecture family of a specific [`CoreType`].
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Architecture {
/// An ARM core of one of the specific types [`CoreType::Armv6m`], [`CoreType::Armv7m`], [`CoreType::Armv7em`] or [`CoreType::Armv8m`]
Arm,
/// A RISC-V core.
Riscv,
}
impl CoreType {
/// Returns the parent architecture family of this core type.
pub fn architecture(&self) -> Architecture {
match self {
CoreType::Riscv => Architecture::Riscv,
_ => Architecture::Arm,
}
}
}
/// This describes a chip family with all its variants.
///
/// This struct is usually read from a target description
/// file.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChipFamily {
/// This is the name of the chip family in base form.
/// E.g. `nRF52832`.
pub name: String,
/// The JEP106 code of the manufacturer.
#[cfg_attr(
not(feature = "bincode"),
serde(skip_serializing_if = "Option::is_none")
)]
pub manufacturer: Option<JEP106Code>,
/// This vector holds all the variants of the family.
pub variants: Vec<Chip>,
/// This vector holds all available algorithms.
pub flash_algorithms: Vec<RawFlashAlgorithm>,
#[serde(skip, default = "default_source")]
/// Source of the target description, used for diagnostics
pub source: TargetDescriptionSource,
}
fn default_source() -> TargetDescriptionSource {
TargetDescriptionSource::External
}
impl ChipFamily {
/// Validates the [`ChipFamily`] such that probe-rs can make assumptions about the correctness without validating thereafter.
///
/// This method should be called right after the [`ChipFamily`] is created!
pub fn validate(&self) -> Result<(), String> {
// We check each variant if it is valid.
// If one is not valid, we abort with an appropriate error message.
for variant in &self.variants {
// Make sure the algorithms used on the variant actually exist on the family (this is basically a check for typos).
for algorithm_name in variant.flash_algorithms.iter() {
if !self
.flash_algorithms
.iter()
.any(|algorithm| &algorithm.name == algorithm_name)
{
return Err(format!(
"unknown flash algorithm `{}` for variant `{}`",
algorithm_name, variant.name
));
}
}
// Check that there is at least one core.
if let Some(core) = variant.cores.get(0) {
// Make sure that the core types (architectures) are not mixed.
let architecture = core.core_type.architecture();
if variant
.cores
.iter()
.any(|core| core.core_type.architecture() != architecture)
{
return Err(format!(
"definition for variant `{}` contains mixed core architectures",
variant.name
));
}
} else {
return Err(format!(
"definition for variant `{}` does not contain any cores",
variant.name
));
}
}
Ok(())
}
}
impl ChipFamily {
/// Get the different [Chip]s which are part of this
/// family.
pub fn variants(&self) -> &[Chip] {
&self.variants
}
/// Get all flash algorithms for this family of chips.
pub fn algorithms(&self) -> &[RawFlashAlgorithm] {
&self.flash_algorithms
}
/// Try to find a [RawFlashAlgorithm] with a given name.
pub fn get_algorithm(&self, name: impl AsRef<str>) -> Option<&RawFlashAlgorithm> {
let name = name.as_ref();
self.flash_algorithms.iter().find(|elem| elem.name == name)
}
}