Skip to content

Commit

Permalink
First draft of the config structure for cmsis pack based flashing con…
Browse files Browse the repository at this point in the history
…figuration (#86)

* First draft of the config structure for cmsis pack based flashing configuration

* Remove repositories module as we don't need it for now

* Add range extension function testing

* Updated some types

* Add config parsing

* Fix target selection

* Change everything to the new config structure.

* Add fixed algorithm. It is slow as hell now (example blinky takes 68s)

* Add extracted LPC845

* Clean up flash builder module

* Clean up download.rs & add hex flashing

* Removal of old types that were moved to the config module

* Add LPC55 series

* Add STM32F103 targets

* Combine all chip configs into one family config.

* Clean up code, comment, remove pyocd artifacts

* Improve logging

* Add some docs

* Clean up some real ugly code

* Update cargo-flash/README.md

* Add the m33 to the get_core() method
  • Loading branch information
Yatekii committed Dec 6, 2019
1 parent 8d6f12f commit f1ee66f
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 92 deletions.
1 change: 0 additions & 1 deletion cargo-flash/Cargo.toml
Expand Up @@ -19,4 +19,3 @@ cargo-project = "0.2.2"
failure = "0.1.5"
colored = "1.8.0"
probe-rs = { path = "../probe-rs", version = "0.2.0" }
probe-rs-targets = { path = "../probe-rs-targets", version = "0.2.0" }
15 changes: 9 additions & 6 deletions cargo-flash/README.md
Expand Up @@ -32,20 +32,23 @@ which will then build your binary and download the contents onto the connected t

#### Use a custom chip definition from a non-builtin file

`cargo flash --release --chip-description-path ../../.config/probe-rs/targets/nRF52840.yaml --target thumbv6m-none-eabi --example gpio_hal_blinky`
`cargo flash --release --chip-description-path nRF51822.yaml --target thumbv6m-none-eabi --example gpio_hal_blinky`

### Manually selecting a chip

To manually select a chip, you can use the `--chip <chip name>` argument. The chip name is an identifier such as `nRF51822` or `STM32F042`. Capitalization does not matter; Special characters do matter.

### Specifying the chip via chip configuration file
### Specifying a chip family description file

You can directly set the chip description by using the `--chip-description-path <chip description file path>` or `-c` argument. You need to pass it the path to a valid yaml chip description.
You can add a temporary chip family description by using the `--chip-description-path <chip description file path>` or `-c` argument. You need to pass it the path to a valid yaml family description.
All the targets of the family will then be added to the registry temporarily and will override existing variants with the same name.
You can use this feature to tinker with a chip family description until it works and then submit it to upstream for inclusion.

### Locally installing & overriding chip descripions
### Extracting a chip family description file from a CMSIS-Pack

You can install valid chip description files locally under `$HOME/.config/probe-rs/targets` and flash algorithm files under `$HOME/.config/probe-rs/algorithms`. Any chip descriptions for identifiers that match the compiled in identifiers will replace the compiled in descriptions. You can override all the descriptions like this. Invalid files will be ignored gracefully.
You can extract the family description file by running [target-gen](https://github.com/probe-rs/target-gen) on a `.pack` file with `cargo run -- file.pack out_dir`. You can obtain the pack from ARM for example. Their online [registry](https://developer.arm.com/tools-and-software/embedded/cmsis/cmsis-search) is a good start :)
You can also reference to an already unziped `pack` directory instead of the `file.pack` archive file.

## Add more chip definitions

If you have a chip you want to flash, feel free to contribute to [probe-rs](https://github.com/probe-rs/probe-rs).
If you have a chip you want to flash, feel free to contribute to [probe-rs](https://github.com/probe-rs/probe-rs).
119 changes: 34 additions & 85 deletions cargo-flash/src/main.rs
Expand Up @@ -6,31 +6,26 @@ use std::{
env,
error::Error,
fmt,
fs::read_to_string,
path::PathBuf,
path::{Path, PathBuf},
process::{self, Command, Stdio},
time::Instant,
};
use structopt::StructOpt;

use probe_rs::{
config::registry::{Registry, SelectionStrategy},
coresight::access_ports::AccessPortError,
probe::{
daplink,
debug_probe::{DebugProbe, DebugProbeError, DebugProbeType, MasterProbe},
flash::{
download::{FileDownloader, Format},
flasher::AlgorithmSelectionError,
},
flash::download::{download_file, Format},
protocol::WireProtocol,
stlink,
},
session::Session,
target::{info::ChipInfo, Target},
target::info::ChipInfo,
};

use probe_rs_targets::{select_algorithm, select_target, SelectionStrategy};

#[derive(Debug, StructOpt)]
struct Opt {
#[structopt(name = "chip", long = "chip")]
Expand All @@ -43,6 +38,8 @@ struct Opt {
chip_description_path: Option<String>,
#[structopt(name = "nrf-recover", long = "nrf-recover")]
nrf_recover: bool,
#[structopt(name = "list-chips", long = "list-chips")]
list_chips: bool,

// `cargo build` arguments
#[structopt(name = "binary", long = "bin")]
Expand Down Expand Up @@ -89,6 +86,12 @@ fn main_try() -> Result<(), failure::Error> {

// Get commandline options.
let opt = Opt::from_iter(&args);

if opt.list_chips {
print_families();
std::process::exit(0);
}

args.remove(0); // Remove executable name

// Remove possible `--chip <chip>` arguments as cargo build does not understand it.
Expand Down Expand Up @@ -210,47 +213,26 @@ fn main_try() -> Result<(), failure::Error> {
}
};

let target_override = opt
.chip_description_path
.as_ref()
.map(|cd| -> Result<_, failure::Error> {
let string = read_to_string(&cd).map_err(|e| {
format_err!("failed to read chip description file from {}: {}", cd, e)
})?;
let target = Target::new(&string)
.map_err(|e| format_err!("failed to parse chip description file {}: {}", cd, e))?;

Ok(target)
})
.transpose()?;

let strategy = if let Some(name) = opt.chip {
if name == "nRF52832" || name == "nRF52840" {
let _ = ChipInfo::read_from_rom_table(&mut probe)?;
}
SelectionStrategy::Name(name)
let strategy = if let Some(identifier) = opt.chip {
SelectionStrategy::TargetIdentifier(identifier.into())
} else {
SelectionStrategy::ChipInfo(ChipInfo::read_from_rom_table(&mut probe)?)
};
let target = if let Some(target) = target_override {
target
} else {
select_target(&strategy)?
};

let flash_algorithm = match target.flash_algorithm.clone() {
Some(name) => select_algorithm(name)?,
None => return Err(AlgorithmSelectionError::NoAlgorithmSuggested.into()),
};
let mut registry = Registry::from_builtin_families();
if let Some(cdp) = opt.chip_description_path {
registry.add_target_from_yaml(&Path::new(&cdp))?;
}

let target = registry.get_target(strategy)?;

let mut session = Session::new(target, probe, Some(flash_algorithm));
let mut session = Session::new(target, probe);

// Start timer.
let instant = Instant::now();

let mm = session.target.memory_map.clone();
let fd = FileDownloader::new();
fd.download_file(
download_file(
&mut session,
std::path::Path::new(&path_str.to_string().as_str()),
Format::Elf,
Expand All @@ -271,45 +253,21 @@ fn main_try() -> Result<(), failure::Error> {
Ok(())
}

/// Takes a closure that is handed an `DAPLink` instance and then executed.
/// After the closure is done, the USB device is always closed,
/// even in an error case inside the closure!
pub fn with_device<F>(n: usize, target: Target, f: F) -> Result<(), DownloadError>
where
for<'a> F: FnOnce(Session) -> Result<(), DownloadError>,
{
let device = {
let mut list = daplink::tools::list_daplink_devices();
list.extend(stlink::tools::list_stlink_devices());

list.remove(n)
};

let probe = match device.probe_type {
DebugProbeType::DAPLink => {
let mut link = daplink::DAPLink::new_from_probe_info(&device)?;

link.attach(Some(WireProtocol::Swd))?;

MasterProbe::from_specific_probe(link)
fn print_families() {
println!("Available chips:");
let registry = Registry::from_builtin_families();
for family in registry.families() {
println!("{}", family.name);
println!(" Variants:");
for variant in family.variants() {
println!(" {}", variant.name);
}
DebugProbeType::STLink => {
let mut link = stlink::STLink::new_from_probe_info(&device)?;

link.attach(Some(WireProtocol::Swd))?;

MasterProbe::from_specific_probe(link)
println!(" Algorithms:");
for algorithms in family.algorithms() {
println!(" {} ({})", algorithms.name, algorithms.description);
}
};

let flash_algorithm = match target.flash_algorithm.clone() {
Some(name) => select_algorithm(name)?,
None => return Err(AlgorithmSelectionError::NoAlgorithmSuggested.into()),
};

let session = Session::new(target, probe, Some(flash_algorithm));

f(session)
}
}

#[cfg(unix)]
Expand All @@ -331,7 +289,6 @@ pub enum DownloadError {
AccessPort(AccessPortError),
StdIO(std::io::Error),
Quit,
FlashAlgorithm(AlgorithmSelectionError),
}

impl Error for DownloadError {
Expand All @@ -343,7 +300,6 @@ impl Error for DownloadError {
AccessPort(ref e) => Some(e),
StdIO(ref e) => Some(e),
Quit => None,
FlashAlgorithm(ref e) => Some(e),
}
}
}
Expand All @@ -357,7 +313,6 @@ impl fmt::Display for DownloadError {
AccessPort(ref e) => e.fmt(f),
StdIO(ref e) => e.fmt(f),
Quit => write!(f, "Quit error..."),
FlashAlgorithm(ref e) => e.fmt(f),
}
}
}
Expand All @@ -379,9 +334,3 @@ impl From<std::io::Error> for DownloadError {
DownloadError::StdIO(error)
}
}

impl From<AlgorithmSelectionError> for DownloadError {
fn from(error: AlgorithmSelectionError) -> Self {
DownloadError::FlashAlgorithm(error)
}
}

0 comments on commit f1ee66f

Please sign in to comment.