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 `BlankCheck()` entry point. Optional.
67    #[serde(serialize_with = "hex_option")]
68    pub pc_blank_check: Option<u64>,
69    /// Address of the (non-standard) `ReadFlash(adr: u32, sz: u32, buf: *mut u8)` entry point. Optional.
70    #[serde(serialize_with = "hex_option")]
71    pub pc_read: Option<u64>,
72    /// Address of the (non-standard) `FlashSize()` entry point. Optional.
73    #[serde(serialize_with = "hex_option")]
74    pub pc_flash_size: Option<u64>,
75    /// The offset from the start of RAM to the data section.
76    #[serde(serialize_with = "hex_u_int")]
77    pub data_section_offset: u64,
78    /// Location of the RTT control block in RAM.
79    ///
80    /// If this is set, the flash algorithm supports RTT output
81    /// and debug messages will be read over RTT.
82    #[serde(serialize_with = "hex_option")]
83    pub rtt_location: Option<u64>,
84    /// Milliseconds between RTT polls.
85    ///
86    /// Defaults to 20ms.
87    #[serde(default = "default_rtt_poll_interval")]
88    pub rtt_poll_interval: u64,
89    /// The properties of the flash on the device.
90    pub flash_properties: FlashProperties,
91    /// List of cores that can use this algorithm
92    #[serde(default)]
93    pub cores: Vec<String>,
94    /// The flash algorithm's stack size, in bytes.
95    ///
96    /// If not set, probe-rs selects a default value.
97    /// Increase this value if you're concerned about stack
98    /// overruns during flashing.
99    pub stack_size: Option<u32>,
100
101    /// Whether to check for stack overflows during flashing.
102    #[serde(default)]
103    pub stack_overflow_check: Option<bool>,
104
105    /// The encoding format accepted by the flash algorithm.
106    #[serde(default)]
107    pub transfer_encoding: Option<TransferEncoding>,
108
109    /// `true` if the instructions are saved in Big Endian format
110    #[serde(default)]
111    pub big_endian: bool,
112}
113
114impl RawFlashAlgorithm {
115    /// Whether to check for stack overflows during flashing.
116    pub fn stack_overflow_check(&self) -> bool {
117        self.stack_overflow_check.unwrap_or(true)
118    }
119}
120
121pub fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
122where
123    S: serde::Serializer,
124{
125    // Use a separate, more compact representation for binary formats.
126    if serializer.is_human_readable() {
127        Base64::serialize(bytes, serializer)
128    } else {
129        Bytes::serialize(bytes, serializer)
130    }
131}
132
133pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
134where
135    D: serde::Deserializer<'de>,
136{
137    // Use a separate, more compact representation for binary formats.
138    if deserializer.is_human_readable() {
139        Base64::deserialize(deserializer)
140    } else {
141        Bytes::deserialize(deserializer)
142    }
143}
144
145struct Base64;
146impl Base64 {
147    fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
148    where
149        S: serde::Serializer,
150    {
151        serializer.serialize_str(base64_engine::STANDARD.encode(bytes).as_str())
152    }
153
154    fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
155    where
156        D: serde::Deserializer<'de>,
157    {
158        deserializer.deserialize_str(Base64)
159    }
160}
161impl serde::de::Visitor<'_> for Base64 {
162    type Value = Vec<u8>;
163
164    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
165        write!(formatter, "base64 ASCII text")
166    }
167
168    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
169    where
170        E: serde::de::Error,
171    {
172        base64_engine::STANDARD
173            .decode(v)
174            .map_err(serde::de::Error::custom)
175    }
176}
177
178struct Bytes;
179impl Bytes {
180    fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
181    where
182        S: serde::Serializer,
183    {
184        serializer.serialize_bytes(bytes)
185    }
186
187    fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
188    where
189        D: serde::Deserializer<'de>,
190    {
191        deserializer.deserialize_bytes(Bytes)
192    }
193}
194impl serde::de::Visitor<'_> for Bytes {
195    type Value = Vec<u8>;
196
197    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
198        write!(formatter, "binary data")
199    }
200
201    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
202    where
203        E: serde::de::Error,
204    {
205        Ok(v.to_vec())
206    }
207}
208
209fn default_rtt_poll_interval() -> u64 {
210    20
211}