Skip to main content

probe_rs_target/
flash_algorithm.rs

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