probe_rs_target/
flash_algorithm.rs

1use super::flash_properties::FlashProperties;
2use crate::serialize::{hex_option, hex_u_int};
3use base64::{Engine as _, engine::general_purpose as base64_engine};
4use serde::{Deserialize, Serialize};
5
6/// Data encoding used by the flash algorithm.
7#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
8#[serde(rename_all = "snake_case")]
9pub enum TransferEncoding {
10    /// Raw binary encoding. Probe-rs will not apply any transformation to the flash data.
11    #[default]
12    Raw,
13
14    /// Zlib-compressed data, originally using the `miniz_oxide` crate.
15    ///
16    /// Compressed images are written in page sized chunks, each chunk written to the image's start
17    /// address. The length of the compressed image is stored in the first 4 bytes of the first
18    /// chunk of the image.
19    Miniz,
20}
21
22/// The raw flash algorithm is the description of a flash algorithm,
23/// and is usually read from a target description file.
24///
25/// Before it can be used for flashing, it has to be assembled for
26/// a specific chip, by determining the RAM addresses which are used when flashing.
27/// This process is done in the main `probe-rs` library.
28#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
29#[serde(deny_unknown_fields)]
30pub struct RawFlashAlgorithm {
31    /// The name of the flash algorithm.
32    pub name: String,
33    /// The description of the algorithm.
34    pub description: String,
35    /// Whether this flash algorithm is the default one or not.
36    #[serde(default)]
37    pub default: bool,
38    /// List of 32-bit words containing the code for the algo. If `load_address` is not specified, the code must be position independent (PIC).
39    #[serde(deserialize_with = "deserialize")]
40    #[serde(serialize_with = "serialize")]
41    pub instructions: Vec<u8>,
42    /// Address to load algo into RAM. Optional.
43    #[serde(serialize_with = "hex_option")]
44    pub load_address: Option<u64>,
45    /// Address to load data into RAM. Optional.
46    #[serde(serialize_with = "hex_option")]
47    pub data_load_address: Option<u64>,
48    /// Address of the `Init()` entry point. Optional.
49    #[serde(serialize_with = "hex_option")]
50    pub pc_init: Option<u64>,
51    /// Address of the `UnInit()` entry point. Optional.
52    #[serde(serialize_with = "hex_option")]
53    pub pc_uninit: Option<u64>,
54    /// Address of the `ProgramPage()` entry point.
55    #[serde(serialize_with = "hex_u_int")]
56    pub pc_program_page: u64,
57    /// Address of the `EraseSector()` entry point.
58    #[serde(serialize_with = "hex_u_int")]
59    pub pc_erase_sector: u64,
60    /// Address of the `EraseAll()` entry point. Optional.
61    #[serde(serialize_with = "hex_option")]
62    pub pc_erase_all: Option<u64>,
63    /// Address of the `Verify()` entry point. Optional.
64    #[serde(serialize_with = "hex_option")]
65    pub pc_verify: Option<u64>,
66    /// Address of the (non-standard) `ReadFlash()` entry point. Optional.
67    #[serde(serialize_with = "hex_option")]
68    pub pc_read: Option<u64>,
69    /// Address of the `BlankCheck()` entry point. Optional.
70    #[serde(serialize_with = "hex_option")]
71    pub pc_blank_check: Option<u64>,
72    /// The offset from the start of RAM to the data section.
73    #[serde(serialize_with = "hex_u_int")]
74    pub data_section_offset: u64,
75    /// Location of the RTT control block in RAM.
76    ///
77    /// If this is set, the flash algorithm supports RTT output
78    /// and debug messages will be read over RTT.
79    #[serde(serialize_with = "hex_option")]
80    pub rtt_location: Option<u64>,
81    /// The properties of the flash on the device.
82    pub flash_properties: FlashProperties,
83    /// List of cores that can use this algorithm
84    #[serde(default)]
85    pub cores: Vec<String>,
86    /// The flash algorithm's stack size, in bytes.
87    ///
88    /// If not set, probe-rs selects a default value.
89    /// Increase this value if you're concerned about stack
90    /// overruns during flashing.
91    pub stack_size: Option<u32>,
92
93    /// Whether to check for stack overflows during flashing.
94    #[serde(default)]
95    pub stack_overflow_check: Option<bool>,
96
97    /// The encoding format accepted by the flash algorithm.
98    #[serde(default)]
99    pub transfer_encoding: Option<TransferEncoding>,
100
101    /// `true` if the instructions are saved in Big Endian format
102    #[serde(default)]
103    pub big_endian: bool,
104}
105
106impl RawFlashAlgorithm {
107    /// Whether to check for stack overflows during flashing.
108    pub fn stack_overflow_check(&self) -> bool {
109        self.stack_overflow_check.unwrap_or(true)
110    }
111}
112
113pub fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
114where
115    S: serde::Serializer,
116{
117    // Use a separate, more compact representation for binary formats.
118    if serializer.is_human_readable() {
119        Base64::serialize(bytes, serializer)
120    } else {
121        Bytes::serialize(bytes, serializer)
122    }
123}
124
125pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
126where
127    D: serde::Deserializer<'de>,
128{
129    // Use a separate, more compact representation for binary formats.
130    if deserializer.is_human_readable() {
131        Base64::deserialize(deserializer)
132    } else {
133        Bytes::deserialize(deserializer)
134    }
135}
136
137struct Base64;
138impl Base64 {
139    fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
140    where
141        S: serde::Serializer,
142    {
143        serializer.serialize_str(base64_engine::STANDARD.encode(bytes).as_str())
144    }
145
146    fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
147    where
148        D: serde::Deserializer<'de>,
149    {
150        deserializer.deserialize_str(Base64)
151    }
152}
153impl serde::de::Visitor<'_> for Base64 {
154    type Value = Vec<u8>;
155
156    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
157        write!(formatter, "base64 ASCII text")
158    }
159
160    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
161    where
162        E: serde::de::Error,
163    {
164        base64_engine::STANDARD
165            .decode(v)
166            .map_err(serde::de::Error::custom)
167    }
168}
169
170struct Bytes;
171impl Bytes {
172    fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
173    where
174        S: serde::Serializer,
175    {
176        serializer.serialize_bytes(bytes)
177    }
178
179    fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
180    where
181        D: serde::Deserializer<'de>,
182    {
183        deserializer.deserialize_bytes(Bytes)
184    }
185}
186impl serde::de::Visitor<'_> for Bytes {
187    type Value = Vec<u8>;
188
189    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
190        write!(formatter, "binary data")
191    }
192
193    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
194    where
195        E: serde::de::Error,
196    {
197        Ok(v.to_vec())
198    }
199}