Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions docs/bootload.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,15 +111,22 @@ in the release or ZIP file. Since the bin files do not contain where
they should be flashed you can either set the target on the commandline
or leave it blank to select.

The following command will promt you to select what target to flash the firmware
The following command will prompt you to select what target to flash the firmware
bin to:

```text
cfcli bootload flash --bin firmware.bin
```

If you want to flash one binary to one target without an interactive prompt,
select that target with `--targets`:

```text
cfcli bootload flash --bin lighthouse.bin --targets bcLighthouse4-fw
```

It's also possible to set the target directly and also to flash multiple bins. The command
below will promt you for where you want to flash ```color-led-firmware.bin``` and will
below will prompt you for where you want to flash ```color-led-firmware.bin``` and will
then flash it to the selected target as well as flashing the ```nrf51-firmware.bin```
to the nRF51.

Expand Down
115 changes: 107 additions & 8 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,88 @@ use modules::settings;

include!("cli.rs");

fn single_explicit_target_for_bare_bin(
bin: &Option<HashMap<String, Option<String>>>,
targets: &Option<Option<String>>,
) -> Option<String> {
let bin_map = bin.as_ref()?;
if bin_map.len() != 1 {
return None;
}

let (_bin_path, selected_target) = bin_map.iter().next()?;
if selected_target.is_some() {
return None;
}

let target_arg = match targets {
Some(Some(target_arg)) => target_arg,
_ => return None,
};

let mut target_names = target_arg
.split(',')
.map(str::trim)
.filter(|target| !target.is_empty());
let target = target_names.next()?;
if target_names.next().is_some() {
return None;
}

Some(target.to_string())
}

fn unsupported_flash_targets(selected: &[String]) -> Vec<String> {
let supported = bootloader::get_hardcoded_list_of_targets();

selected
.iter()
.filter(|target| !supported.contains(&target.as_str()))
.cloned()
.collect()
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn single_bare_bin_uses_single_explicit_target() {
let mut bin = HashMap::new();
bin.insert("lighthouse.bin".to_string(), None);
let targets = Some(Some("bcLighthouse4-fw".to_string()));

assert_eq!(
single_explicit_target_for_bare_bin(&Some(bin), &targets),
Some("bcLighthouse4-fw".to_string())
);
}

#[test]
fn single_bare_bin_does_not_use_multiple_explicit_targets() {
let mut bin = HashMap::new();
bin.insert("lighthouse.bin".to_string(), None);
let targets = Some(Some("bcLighthouse4-fw,stm32-fw".to_string()));

assert_eq!(single_explicit_target_for_bare_bin(&Some(bin), &targets), None);
}

#[test]
fn keyed_bin_does_not_get_rewritten_from_targets() {
let mut bin = HashMap::new();
bin.insert("bcLighthouse4-fw".to_string(), Some("lighthouse.bin".to_string()));
let targets = Some(Some("bcLighthouse4-fw".to_string()));

assert_eq!(single_explicit_target_for_bare_bin(&Some(bin), &targets), None);
}

#[test]
fn unsupported_flash_targets_reports_unknown_targets() {
let selected = vec!["stm32ohnooo-fw".to_string(), "stm32-fw".to_string()];

assert_eq!(unsupported_flash_targets(&selected), vec!["stm32ohnooo-fw".to_string()]);
}
}

impl MemoryTypeArg {
/// Convert to the `crazyflie_lib` memory type. Defined here (not on the
Expand Down Expand Up @@ -1367,19 +1449,25 @@ async fn run() -> Result<()> {
// until we reach the deck flashing stage.
let bin_with_selections = {
let mut result = HashMap::new();
let target_from_single_bare_bin =
single_explicit_target_for_bare_bin(&params.bin, &params.targets);
if let Some(bin_map) = &params.bin {
for (key, value_opt) in bin_map.iter() {
let (k,v) = match (key, value_opt) {
(k, Some(v)) => (k.clone(), v.clone()),
(k, None) => {
require_arg(non_interactive, "--bin target=file")?;
let selected_target = Select::new(
&format!("Select target for [{}]:", k),
bootloader::get_hardcoded_list_of_targets()
)
.prompt()
.map_err(|_| anyhow::anyhow!("No binary selected"))?;
(selected_target.to_string(), k.to_string())
if let Some(selected_target) = &target_from_single_bare_bin {
(selected_target.clone(), k.to_string())
Comment thread
ataffanel marked this conversation as resolved.
} else {
require_arg(non_interactive, "--bin target=file (or: --targets <TARGET> for a single bare --bin)")?;
let selected_target = Select::new(
&format!("Select target for [{}]:", k),
bootloader::get_hardcoded_list_of_targets()
)
.prompt()
.map_err(|_| anyhow::anyhow!("No binary selected"))?;
(selected_target.to_string(), k.to_string())
}
}
};
result.insert(k, v);
Expand Down Expand Up @@ -1444,6 +1532,17 @@ async fn run() -> Result<()> {
None => upgrade.get_target_and_types(),
};

if matches!(&params.targets, Some(Some(_))) {
let unsupported_targets = unsupported_flash_targets(&selected_target_and_types);
if !unsupported_targets.is_empty() {
bail!(CliError::InvalidValue(format!(
"unknown flash target(s): {}. Valid targets: {}",
unsupported_targets.join(", "),
bootloader::get_hardcoded_list_of_targets().join(", ")
)));
}
}

upgrade.filter_targets(&selected_target_and_types);

if upgrade.get_target_and_types().is_empty() {
Expand Down
Loading