Skip to content

Commit 2d5b08c

Browse files
authored
Detect the bootloader and partition table from ESP-IDF when able (esp-rs#186)
* Create a build context struct which stores paths to various artifacts * Use the bootloader/partition table from ESP-IDF if detected
1 parent 2282087 commit 2d5b08c

File tree

2 files changed

+77
-15
lines changed

2 files changed

+77
-15
lines changed

cargo-espflash/src/main.rs

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,13 @@ fn main() -> Result<()> {
135135
}
136136
}
137137

138+
#[derive(Debug, Clone)]
139+
struct BuildContext {
140+
pub artifact_path: PathBuf,
141+
pub bootloader_path: Option<PathBuf>,
142+
pub partition_table_path: Option<PathBuf>,
143+
}
144+
138145
fn flash(
139146
opts: EspFlashOpts,
140147
config: Config,
@@ -143,7 +150,7 @@ fn flash(
143150
) -> Result<()> {
144151
let mut flasher = connect(&opts.connect_opts, &config)?;
145152

146-
let artifact_path = build(&opts.build_opts, &cargo_config, Some(flasher.chip()))
153+
let build_ctx = build(&opts.build_opts, &cargo_config, Some(flasher.chip()))
147154
.wrap_err("Failed to build project")?;
148155

149156
// Print the board information once the project has successfully built. We do
@@ -152,7 +159,7 @@ fn flash(
152159
flasher.board_info()?;
153160

154161
// Read the ELF data from the build path and load it to the target.
155-
let elf_data = fs::read(artifact_path).into_diagnostic()?;
162+
let elf_data = fs::read(build_ctx.artifact_path).into_diagnostic()?;
156163

157164
if opts.flash_opts.ram {
158165
flasher.load_elf_to_ram(&elf_data)?;
@@ -161,13 +168,15 @@ fn flash(
161168
.flash_opts
162169
.bootloader
163170
.as_deref()
164-
.or(metadata.bootloader.as_deref());
171+
.or(metadata.bootloader.as_deref())
172+
.or(build_ctx.bootloader_path.as_deref());
165173

166174
let partition_table = opts
167175
.flash_opts
168176
.partition_table
169177
.as_deref()
170-
.or(metadata.partition_table.as_deref());
178+
.or(metadata.partition_table.as_deref())
179+
.or(build_ctx.partition_table_path.as_deref());
171180

172181
let image_format = opts
173182
.build_opts
@@ -201,7 +210,7 @@ fn build(
201210
build_options: &BuildOpts,
202211
cargo_config: &CargoConfig,
203212
chip: Option<Chip>,
204-
) -> Result<PathBuf> {
213+
) -> Result<BuildContext> {
205214
let target = build_options
206215
.target
207216
.as_deref()
@@ -291,9 +300,31 @@ fn build(
291300

292301
// Find artifacts.
293302
let mut target_artifact = None;
303+
let mut bootloader_path = None;
304+
let mut partition_table_path = None;
294305

295306
for message in messages {
296307
match message.into_diagnostic()? {
308+
Message::BuildScriptExecuted(script)
309+
if script.package_id.repr.starts_with("esp-idf-sys") =>
310+
{
311+
// If the `esp-idf-sys` package is being used, attempt to use the bootloader and
312+
// partition table compiled by `embuild` instead.
313+
let build_path = PathBuf::from(script.out_dir).join("build");
314+
315+
let bl_path = build_path.join("bootloader").join("bootloader.bin");
316+
let pt_path = build_path
317+
.join("partition_table")
318+
.join("partition-table.bin");
319+
320+
if bl_path.exists() && bl_path.is_file() {
321+
bootloader_path = Some(bl_path);
322+
}
323+
324+
if pt_path.exists() && pt_path.is_file() {
325+
partition_table_path = Some(pt_path);
326+
}
327+
}
297328
Message::CompilerArtifact(artifact) => {
298329
if artifact.executable.is_some() {
299330
if target_artifact.is_some() {
@@ -324,7 +355,13 @@ fn build(
324355
let target_artifact = target_artifact.ok_or(Error::NoArtifact)?;
325356
let artifact_path = target_artifact.executable.unwrap().into();
326357

327-
Ok(artifact_path)
358+
let build_ctx = BuildContext {
359+
artifact_path,
360+
bootloader_path,
361+
partition_table_path,
362+
};
363+
364+
Ok(build_ctx)
328365
}
329366

330367
fn save_image(
@@ -342,8 +379,22 @@ fn save_image(
342379

343380
let chip = Chip::from_target(target).ok_or_else(|| Error::UnknownTarget(target.into()))?;
344381

345-
let path = build(&opts.build_opts, &cargo_config, Some(chip))?;
346-
let elf_data = fs::read(path).into_diagnostic()?;
382+
let build_ctx = build(&opts.build_opts, &cargo_config, Some(chip))?;
383+
let elf_data = fs::read(build_ctx.artifact_path).into_diagnostic()?;
384+
385+
let bootloader = opts
386+
.bootloader
387+
.as_deref()
388+
.or(metadata.bootloader.as_deref())
389+
.or(build_ctx.bootloader_path.as_deref())
390+
.map(|p| p.to_path_buf());
391+
392+
let partition_table = opts
393+
.partition_table
394+
.as_deref()
395+
.or(metadata.partition_table.as_deref())
396+
.or(build_ctx.partition_table_path.as_deref())
397+
.map(|p| p.to_path_buf());
347398

348399
let image_format = opts
349400
.build_opts
@@ -362,8 +413,8 @@ fn save_image(
362413
opts.build_opts.flash_config_opts.flash_size,
363414
opts.build_opts.flash_config_opts.flash_freq,
364415
opts.merge,
365-
opts.bootloader,
366-
opts.partition_table,
416+
bootloader,
417+
partition_table,
367418
)?;
368419

369420
Ok(())

espflash/src/cli/mod.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -244,12 +244,23 @@ pub fn flash_elf_image(
244244
// the CSV at the specified path.
245245
let partition_table = if let Some(path) = partition_table {
246246
let path = fs::canonicalize(path).into_diagnostic()?;
247-
let data = fs::read_to_string(path)
248-
.into_diagnostic()
249-
.wrap_err("Failed to open partition table")?;
250247

251-
let table =
252-
PartitionTable::try_from_str(data).wrap_err("Failed to parse partition table")?;
248+
// If a partition table was detected from ESP-IDF (eg. using `esp-idf-sys`) then
249+
// it will be passed in its _binary_ form. Otherwise, it will be provided as a
250+
// CSV.
251+
let table = if path.extension().map(|e| e.to_str().unwrap()) == Some("csv") {
252+
let data = fs::read_to_string(path)
253+
.into_diagnostic()
254+
.wrap_err("Failed to open partition table")?;
255+
256+
PartitionTable::try_from_str(data).wrap_err("Failed to parse partition table")?
257+
} else {
258+
let data = fs::read(path)
259+
.into_diagnostic()
260+
.wrap_err("Failed to open partition table")?;
261+
262+
PartitionTable::try_from_bytes(data).wrap_err("Failed to parse partition table")?
263+
};
253264

254265
Some(table)
255266
} else {

0 commit comments

Comments
 (0)