├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE │ └── pull_request_template.md ├── bors.toml ├── dependabot.yml └── workflows │ └── ci.yml ├── .gitignore ├── CHANGELOG.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── build.rs └── src ├── config ├── default.toml └── mod.rs ├── error.rs ├── main.rs └── rttui ├── app.rs ├── channel.rs ├── event.rs └── mod.rs /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [probe-rs] -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. ... 16 | 2. ... 17 | 3. ... 18 | 19 | **Expected behavior** 20 | A clear and concise description of what you expected to happen. 21 | 22 | **Stacktrace** 23 | If applicable, add a stacktrace to help explain your problem. 24 | 25 | **Desktop (please complete the following information):** 26 | - macOS Mojave 27 | - Windows 10 28 | - Linux (Ubuntu, Gentoo, Debian, Fedora, etc.) 29 | 30 | **Additional context** 31 | Add any other context about the problem here. 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: Yatekii 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Thank you! 2 | 3 | Thank you for your contribution. 4 | Please make sure that your submission includes the following: 5 | 6 | ### Must 7 | 8 | - [ ] The code compiles without `errors` or `warnings`. 9 | - [ ] All tests pass and in the best case you also added new tests. 10 | - [ ] `cargo fmt` was run. 11 | - [ ] Your changes were added to the `CHANGELOG.md` in the proper section. 12 | 13 | ### Nice to have 14 | 15 | - [ ] You add a description of your work to this PR. 16 | - [ ] You added proper docs (in code, rustdoc and README.md) for your newly added features and code. -------------------------------------------------------------------------------- /.github/bors.toml: -------------------------------------------------------------------------------- 1 | required_approvals = 1 2 | block_labels = ["wip"] 3 | delete_merged_branches = true 4 | status = [ 5 | "Check (ubuntu-latest)", 6 | "Check (windows-latest)", 7 | "Test Suite", 8 | "Rustfmt", 9 | ] 10 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | - package-ecosystem: cargo 8 | directory: "/" 9 | schedule: 10 | interval: daily 11 | ignore: 12 | # Ignore probe-rs dependencies to avoid unecessary updates 13 | # for all new commmits in the probe-rs repo. 14 | - dependency-name: "probe-rs" 15 | - dependency-name: "probe-rs-cli-util" 16 | - dependency-name: "gdb-server" 17 | - dependency-name: "probe-rs-rtt" 18 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | # Based on https://github.com/actions-rs/meta/blob/master/recipes/quickstart.md 2 | # 3 | # Currently only builds on Linux 4 | 5 | on: 6 | push: 7 | branches: [master, staging, trying] 8 | pull_request: 9 | 10 | name: CI 11 | 12 | jobs: 13 | check: 14 | name: Check 15 | strategy: 16 | matrix: 17 | os: 18 | - ubuntu-latest 19 | - windows-latest 20 | 21 | runs-on: ${{ matrix.os }} 22 | 23 | steps: 24 | - name: Checkout sources 25 | uses: actions/checkout@v3 26 | 27 | - name: Install libusb 28 | run: sudo apt update && sudo apt install -y libusb-1.0-0-dev libftdi1-dev libudev-dev 29 | # Only install on Ubuntu 30 | if: matrix.os == 'ubuntu-latest' 31 | 32 | - name: Install stable toolchain 33 | uses: actions-rs/toolchain@v1.0.7 34 | with: 35 | toolchain: stable 36 | override: true 37 | 38 | - name: Run cargo check 39 | uses: actions-rs/cargo@v1.0.3 40 | with: 41 | command: check 42 | 43 | test: 44 | name: Test Suite 45 | runs-on: ubuntu-latest 46 | steps: 47 | - name: Checkout sources 48 | uses: actions/checkout@v3 49 | 50 | - name: Install libusb 51 | run: sudo apt update && sudo apt install -y libusb-1.0-0-dev libftdi1-dev libudev-dev 52 | 53 | - name: Install stable toolchain 54 | uses: actions-rs/toolchain@v1.0.7 55 | with: 56 | toolchain: stable 57 | override: true 58 | 59 | - name: Run cargo test 60 | uses: actions-rs/cargo@v1.0.3 61 | with: 62 | command: test 63 | 64 | fmt: 65 | name: Rustfmt 66 | runs-on: ubuntu-latest 67 | steps: 68 | - name: Checkout sources 69 | uses: actions/checkout@v3 70 | 71 | - name: Install stable toolchain 72 | uses: actions-rs/toolchain@v1.0.7 73 | with: 74 | toolchain: stable 75 | override: true 76 | 77 | - name: Install rustfmt 78 | run: rustup component add rustfmt 79 | 80 | - name: Run cargo fmt 81 | uses: actions-rs/cargo@v1.0.3 82 | with: 83 | command: fmt 84 | args: --all -- --check 85 | 86 | clippy: 87 | name: Clippy 88 | runs-on: ubuntu-latest 89 | steps: 90 | - name: Checkout sources 91 | uses: actions/checkout@v3 92 | 93 | - name: Install libusb 94 | run: sudo apt update && sudo apt install -y libusb-1.0-0-dev libftdi1-dev libudev-dev 95 | 96 | - name: Install stable toolchain 97 | uses: actions-rs/toolchain@v1.0.7 98 | with: 99 | toolchain: stable 100 | override: true 101 | 102 | - name: Install clippy 103 | run: rustup component add clippy 104 | 105 | - name: Run cargo clippy 106 | uses: actions-rs/clippy-check@v1.0.7 107 | with: 108 | token: ${{ secrets.GITHUB_TOKEN }} 109 | args: --all-features 110 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) 4 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 5 | 6 | ## [Unreleased] 7 | 8 | ### Added 9 | 10 | ### Changed 11 | 12 | ### Fixed 13 | 14 | ## [0.13.0] 15 | 16 | ### Changed 17 | 18 | - Update to probe-rs 0.13.0. 19 | 20 | ## [0.12.0] 21 | 22 | ### Changed 23 | 24 | - Update to probe-rs 0.12.0. 25 | 26 | ## [0.11.0] 27 | 28 | ### Added 29 | 30 | - RTT channels can be configured to use one of three blocking modes 31 | - RTT and GDB server can now run concurrently (#159). 32 | 33 | ### Changed 34 | 35 | - Update to probe-rs 0.11.0. 36 | - Improved handling of config files. Unknown keys in the config file now cause an error, and trying to use unknown profiles as well (#205). 37 | 38 | ## [0.10.1] 39 | 40 | ### Changed 41 | 42 | - Disable sentry by default as an intermediate measure to fix the subpar user experience due to its introduction. 43 | 44 | ## [0.10.0] 45 | 46 | ### Added 47 | 48 | - Updated to probe-rs 0.10.0. Please consult its own changelog for new features and fixes. 49 | - Added logging to sentry.io. This is 100% OPT-IN! You will be asked only if an unhandled error or panic occurs, and only if you give consent, data is transmitted. If you do not trust us either way, you can disable the `sentry` feature when you install the crate. The completely anonymous data can be investigated on sentry.io by anyone who likes to see it. Unfortunately sentry.io does not feature public orgs yet, so please reach out to @Yatekii to be added. 50 | Sentry helps us track down tricky issues that only occur in very specific cases. It is very much appreciated if you log upcoming errors this way (#125)! 51 | - Added printing of the git hash cargo-embed was compiled with and the current package version (#116). 52 | 53 | ### Changed 54 | 55 | - FTDI support is now optional. To enable FTDI support, please use the `ftdi` feature (#131). 56 | 57 | ## [0.9.1] 58 | 59 | ### Added 60 | 61 | - Added a config flag to config what format to use on a channel. 62 | - Added support for Defmt over RTT 63 | 64 | ### Changed 65 | 66 | ### Fixed 67 | 68 | - Fixed a bug where all channels except 0 would be interpreted as binary. 69 | 70 | ## [0.9.0] 71 | 72 | ### Added 73 | 74 | - The config supports a new section called `reset`. It controls whether the target is reset. Default config: 75 | 76 | ```toml 77 | [default.reset] 78 | # Whether or not the target should be reset. 79 | # When flashing is enabled as well, the target will be reset after flashing. 80 | enabled = true 81 | # Whether or not the target should be halted after reset. 82 | halt_afterwards = false 83 | ``` 84 | 85 | This way, you can add a `cargo embed` target that allows resetting and 86 | optionally halting without flashing. Useful for debugging. 87 | 88 | - Improved logging on different levels. 89 | - Added the possibility to save logs (#28). 90 | - Added support for cargo workspaces with the replacement of `cargo-project` with `cargo-metadata`. 91 | - Added a flag to override the selected chip with `--chip`. 92 | - Added a flag to override the selected probe with `--probe`. 93 | 94 | ### Changed 95 | 96 | - The config option `flashing.halt_afterwards` has moved to `reset.halt_afterwards` 97 | 98 | ### Fixed 99 | 100 | - Fixed the enter key for text input in the RTT terminal. 101 | - Fixed loading of local config files. 102 | - Fixed the default.toml. 103 | - Fixed the error message when multiple probes are detected. 104 | 105 | ## [0.8.0] 106 | 107 | ### Added 108 | 109 | - Add Windows support with the help of crossterm instead of termion. 110 | - Introduced deriveable configs. With deriveable configs it is possible to create multible configs and derive parts of a config from another. 111 | An example is this config: 112 | 113 | ```toml 114 | [rtt.rtt] 115 | enabled = true 116 | 117 | [rtt.gdb] 118 | enabled = false 119 | 120 | [gdb.rtt] 121 | enabled = false 122 | 123 | [gdb.gdb] 124 | enabled = true 125 | ``` 126 | 127 | This creates a config which has three configs: 128 | - The default one with the prefix "default" as found in [default.toml](src/config/default.toml) 129 | - A config with the prefix "rtt" which inherits from "default" implicitely (use general.derives = "prefix" to derive from a specific config) which has RTT enabled but GDB disabled. 130 | - A config with the prefix "gdb" which inherits from "default" implicitely (use general.derives = "prefix" to derive from a specific config) which has GDB enabled but RTT disabled. 131 | To use a specific config, call `cargo-embed prefix`. 132 | NOTE: This is a congig breaking change! You must update your `Embed.toml` configs! 133 | 134 | ### Changed 135 | 136 | - The `probe.probe_selector` property is now split into three properties: 137 | - usb_vid 138 | - usb_pid 139 | - serial 140 | - The `RUST_LOG` environment variable can now override the log level set in the config. 141 | - Improved errors by a large margin by properly displaying the stacked errors with the help of anyhow. 142 | 143 | ### Fixed 144 | 145 | - Panics in app that could occur due to a bug will no longer mess up the user's terminal. 146 | - Fixed a bug where the progress bars from the flashing procedure would swallow all log messages. 147 | - Fixed a bug where the RTT UI would panic if no channels were configured. 148 | 149 | ### Known issues 150 | 151 | - Content that is longer than one line will not wrap when printed to the RTTUI unless it contains proper newlines itself. 152 | 153 | ## [0.7.0] 154 | 155 | ### Changed 156 | 157 | - Improve error handling a lot. We now print the complete stack of errors with anyhow/thiserror. 158 | - Update to the probe-rs 0.7.0 API. 159 | 160 | ### Fixed 161 | 162 | - Fixed a bug where cargo-embed would always flash the attached chip no matter if enabled or not. 163 | 164 | ### Known issues 165 | 166 | - Content that is longer than one line will not wrap when printed to the RTTUI unless it contains proper newlines itself. 167 | 168 | ## [0.6.1] 169 | 170 | ### Added 171 | 172 | - Added the possibility to use an `Embed.local.toml` to override the `Embed.toml` locally. 173 | - Added the possibility to use an `.embed.toml` and `.embed.local.toml`. See the [README](README.md) for more info. 174 | - Added host timestamps to the RTT printouts. 175 | 176 | ## [0.6.0] 177 | 178 | - Initial release 179 | 180 | [unreleased]: https://github.com/probe-rs/cargo-embed/compare/v0.13.0...master 181 | [0.13.0]: https://github.com/probe-rs/cargo-embed/releases/tag/v0.12.0..v0.13.0 182 | [0.12.0]: https://github.com/probe-rs/cargo-embed/releases/tag/v0.11.0..v0.12.0 183 | [0.11.0]: https://github.com/probe-rs/cargo-embed/releases/tag/v0.10.1..v0.11.0 184 | [0.10.1]: https://github.com/probe-rs/cargo-embed/releases/tag/v0.10.0..v0.10.1 185 | [0.10.0]: https://github.com/probe-rs/cargo-embed/releases/tag/v0.9.0..v0.10.0 186 | [0.9.1]: https://github.com/probe-rs/cargo-embed/releases/tag/v0.9.0..v0.9.1 187 | [0.9.0]: https://github.com/probe-rs/cargo-embed/releases/tag/v0.8.0..v0.9.0 188 | [0.8.0]: https://github.com/probe-rs/cargo-embed/releases/tag/v0.7.0..v0.8.0 189 | [0.7.0]: https://github.com/probe-rs/cargo-embed/releases/tag/v0.6.1..v0.7.0 190 | [0.6.1]: https://github.com/probe-rs/cargo-embed/releases/tag/v0.6.0..v0.6.1 191 | [0.6.0]: https://github.com/probe-rs/cargo-embed/releases/tag/v0.6.0 192 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.19.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" 10 | dependencies = [ 11 | "gimli 0.27.0", 12 | ] 13 | 14 | [[package]] 15 | name = "adler" 16 | version = "1.0.2" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 19 | 20 | [[package]] 21 | name = "ahash" 22 | version = "0.7.6" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" 25 | dependencies = [ 26 | "getrandom", 27 | "once_cell", 28 | "version_check", 29 | ] 30 | 31 | [[package]] 32 | name = "aho-corasick" 33 | version = "0.7.20" 34 | source = "registry+https://github.com/rust-lang/crates.io-index" 35 | checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" 36 | dependencies = [ 37 | "memchr", 38 | ] 39 | 40 | [[package]] 41 | name = "android_system_properties" 42 | version = "0.1.5" 43 | source = "registry+https://github.com/rust-lang/crates.io-index" 44 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 45 | dependencies = [ 46 | "libc", 47 | ] 48 | 49 | [[package]] 50 | name = "anyhow" 51 | version = "1.0.68" 52 | source = "registry+https://github.com/rust-lang/crates.io-index" 53 | checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" 54 | dependencies = [ 55 | "backtrace", 56 | ] 57 | 58 | [[package]] 59 | name = "atomic" 60 | version = "0.5.1" 61 | source = "registry+https://github.com/rust-lang/crates.io-index" 62 | checksum = "b88d82667eca772c4aa12f0f1348b3ae643424c8876448f3f7bd5787032e234c" 63 | dependencies = [ 64 | "autocfg", 65 | ] 66 | 67 | [[package]] 68 | name = "atty" 69 | version = "0.2.14" 70 | source = "registry+https://github.com/rust-lang/crates.io-index" 71 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 72 | dependencies = [ 73 | "hermit-abi 0.1.19", 74 | "libc", 75 | "winapi", 76 | ] 77 | 78 | [[package]] 79 | name = "autocfg" 80 | version = "1.1.0" 81 | source = "registry+https://github.com/rust-lang/crates.io-index" 82 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 83 | 84 | [[package]] 85 | name = "backtrace" 86 | version = "0.3.67" 87 | source = "registry+https://github.com/rust-lang/crates.io-index" 88 | checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" 89 | dependencies = [ 90 | "addr2line", 91 | "cc", 92 | "cfg-if", 93 | "libc", 94 | "miniz_oxide", 95 | "object 0.30.2", 96 | "rustc-demangle", 97 | ] 98 | 99 | [[package]] 100 | name = "base64" 101 | version = "0.13.1" 102 | source = "registry+https://github.com/rust-lang/crates.io-index" 103 | checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" 104 | 105 | [[package]] 106 | name = "base64" 107 | version = "0.21.0" 108 | source = "registry+https://github.com/rust-lang/crates.io-index" 109 | checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" 110 | 111 | [[package]] 112 | name = "bincode" 113 | version = "1.3.3" 114 | source = "registry+https://github.com/rust-lang/crates.io-index" 115 | checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" 116 | dependencies = [ 117 | "serde", 118 | ] 119 | 120 | [[package]] 121 | name = "bitfield" 122 | version = "0.14.0" 123 | source = "registry+https://github.com/rust-lang/crates.io-index" 124 | checksum = "2d7e60934ceec538daadb9d8432424ed043a904d8e0243f3c6446bce549a46ac" 125 | 126 | [[package]] 127 | name = "bitflags" 128 | version = "1.3.2" 129 | source = "registry+https://github.com/rust-lang/crates.io-index" 130 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 131 | 132 | [[package]] 133 | name = "bitvec" 134 | version = "1.0.1" 135 | source = "registry+https://github.com/rust-lang/crates.io-index" 136 | checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" 137 | dependencies = [ 138 | "funty", 139 | "radium", 140 | "tap", 141 | "wyz", 142 | ] 143 | 144 | [[package]] 145 | name = "bumpalo" 146 | version = "3.11.1" 147 | source = "registry+https://github.com/rust-lang/crates.io-index" 148 | checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" 149 | 150 | [[package]] 151 | name = "byte-unit" 152 | version = "4.0.18" 153 | source = "registry+https://github.com/rust-lang/crates.io-index" 154 | checksum = "3348673602e04848647fffaa8e9a861e7b5d5cae6570727b41bde0f722514484" 155 | dependencies = [ 156 | "serde", 157 | "utf8-width", 158 | ] 159 | 160 | [[package]] 161 | name = "byteorder" 162 | version = "1.4.3" 163 | source = "registry+https://github.com/rust-lang/crates.io-index" 164 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 165 | 166 | [[package]] 167 | name = "bytes" 168 | version = "1.3.0" 169 | source = "registry+https://github.com/rust-lang/crates.io-index" 170 | checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" 171 | 172 | [[package]] 173 | name = "camino" 174 | version = "1.1.2" 175 | source = "registry+https://github.com/rust-lang/crates.io-index" 176 | checksum = "c77df041dc383319cc661b428b6961a005db4d6808d5e12536931b1ca9556055" 177 | dependencies = [ 178 | "serde", 179 | ] 180 | 181 | [[package]] 182 | name = "cargo-embed" 183 | version = "0.13.0" 184 | dependencies = [ 185 | "anyhow", 186 | "chrono", 187 | "colored", 188 | "crossterm", 189 | "defmt-decoder", 190 | "env_logger", 191 | "figment", 192 | "gdb-server", 193 | "git-version", 194 | "goblin", 195 | "lazy_static", 196 | "log", 197 | "probe-rs", 198 | "probe-rs-cli-util", 199 | "probe-rs-rtt", 200 | "sanitize-filename", 201 | "serde", 202 | "serde_json", 203 | "textwrap", 204 | "tui", 205 | ] 206 | 207 | [[package]] 208 | name = "cargo-platform" 209 | version = "0.1.2" 210 | source = "registry+https://github.com/rust-lang/crates.io-index" 211 | checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" 212 | dependencies = [ 213 | "serde", 214 | ] 215 | 216 | [[package]] 217 | name = "cargo_metadata" 218 | version = "0.15.2" 219 | source = "registry+https://github.com/rust-lang/crates.io-index" 220 | checksum = "982a0cf6a99c350d7246035613882e376d58cebe571785abc5da4f648d53ac0a" 221 | dependencies = [ 222 | "camino", 223 | "cargo-platform", 224 | "semver", 225 | "serde", 226 | "serde_json", 227 | "thiserror", 228 | ] 229 | 230 | [[package]] 231 | name = "cargo_toml" 232 | version = "0.14.0" 233 | source = "registry+https://github.com/rust-lang/crates.io-index" 234 | checksum = "0f1204fe51a1e56042b8ec31d6407547ecd18f596b66f470dadb9abd9be9c843" 235 | dependencies = [ 236 | "serde", 237 | "toml", 238 | ] 239 | 240 | [[package]] 241 | name = "cassowary" 242 | version = "0.3.0" 243 | source = "registry+https://github.com/rust-lang/crates.io-index" 244 | checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" 245 | 246 | [[package]] 247 | name = "cc" 248 | version = "1.0.78" 249 | source = "registry+https://github.com/rust-lang/crates.io-index" 250 | checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" 251 | 252 | [[package]] 253 | name = "cfg-if" 254 | version = "1.0.0" 255 | source = "registry+https://github.com/rust-lang/crates.io-index" 256 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 257 | 258 | [[package]] 259 | name = "chrono" 260 | version = "0.4.23" 261 | source = "registry+https://github.com/rust-lang/crates.io-index" 262 | checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" 263 | dependencies = [ 264 | "iana-time-zone", 265 | "js-sys", 266 | "num-integer", 267 | "num-traits", 268 | "serde", 269 | "time 0.1.45", 270 | "wasm-bindgen", 271 | "winapi", 272 | ] 273 | 274 | [[package]] 275 | name = "clap" 276 | version = "4.1.0" 277 | source = "registry+https://github.com/rust-lang/crates.io-index" 278 | checksum = "aa91278560fc226a5d9d736cc21e485ff9aad47d26b8ffe1f54cba868b684b9f" 279 | dependencies = [ 280 | "bitflags", 281 | "clap_derive", 282 | "clap_lex", 283 | "is-terminal", 284 | "once_cell", 285 | "strsim", 286 | "termcolor", 287 | ] 288 | 289 | [[package]] 290 | name = "clap_derive" 291 | version = "4.1.0" 292 | source = "registry+https://github.com/rust-lang/crates.io-index" 293 | checksum = "684a277d672e91966334af371f1a7b5833f9aa00b07c84e92fbce95e00208ce8" 294 | dependencies = [ 295 | "heck", 296 | "proc-macro-error", 297 | "proc-macro2", 298 | "quote", 299 | "syn", 300 | ] 301 | 302 | [[package]] 303 | name = "clap_lex" 304 | version = "0.3.1" 305 | source = "registry+https://github.com/rust-lang/crates.io-index" 306 | checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade" 307 | dependencies = [ 308 | "os_str_bytes", 309 | ] 310 | 311 | [[package]] 312 | name = "codespan-reporting" 313 | version = "0.11.1" 314 | source = "registry+https://github.com/rust-lang/crates.io-index" 315 | checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" 316 | dependencies = [ 317 | "termcolor", 318 | "unicode-width", 319 | ] 320 | 321 | [[package]] 322 | name = "colored" 323 | version = "2.0.0" 324 | source = "registry+https://github.com/rust-lang/crates.io-index" 325 | checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" 326 | dependencies = [ 327 | "atty", 328 | "lazy_static", 329 | "winapi", 330 | ] 331 | 332 | [[package]] 333 | name = "console" 334 | version = "0.15.4" 335 | source = "registry+https://github.com/rust-lang/crates.io-index" 336 | checksum = "c9b6515d269224923b26b5febea2ed42b2d5f2ce37284a4dd670fedd6cb8347a" 337 | dependencies = [ 338 | "encode_unicode", 339 | "lazy_static", 340 | "libc", 341 | "unicode-width", 342 | "windows-sys", 343 | ] 344 | 345 | [[package]] 346 | name = "core-foundation" 347 | version = "0.9.3" 348 | source = "registry+https://github.com/rust-lang/crates.io-index" 349 | checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" 350 | dependencies = [ 351 | "core-foundation-sys", 352 | "libc", 353 | ] 354 | 355 | [[package]] 356 | name = "core-foundation-sys" 357 | version = "0.8.3" 358 | source = "registry+https://github.com/rust-lang/crates.io-index" 359 | checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" 360 | 361 | [[package]] 362 | name = "crossterm" 363 | version = "0.25.0" 364 | source = "registry+https://github.com/rust-lang/crates.io-index" 365 | checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67" 366 | dependencies = [ 367 | "bitflags", 368 | "crossterm_winapi", 369 | "libc", 370 | "mio", 371 | "parking_lot", 372 | "signal-hook", 373 | "signal-hook-mio", 374 | "winapi", 375 | ] 376 | 377 | [[package]] 378 | name = "crossterm_winapi" 379 | version = "0.9.0" 380 | source = "registry+https://github.com/rust-lang/crates.io-index" 381 | checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c" 382 | dependencies = [ 383 | "winapi", 384 | ] 385 | 386 | [[package]] 387 | name = "cxx" 388 | version = "1.0.86" 389 | source = "registry+https://github.com/rust-lang/crates.io-index" 390 | checksum = "51d1075c37807dcf850c379432f0df05ba52cc30f279c5cfc43cc221ce7f8579" 391 | dependencies = [ 392 | "cc", 393 | "cxxbridge-flags", 394 | "cxxbridge-macro", 395 | "link-cplusplus", 396 | ] 397 | 398 | [[package]] 399 | name = "cxx-build" 400 | version = "1.0.86" 401 | source = "registry+https://github.com/rust-lang/crates.io-index" 402 | checksum = "5044281f61b27bc598f2f6647d480aed48d2bf52d6eb0b627d84c0361b17aa70" 403 | dependencies = [ 404 | "cc", 405 | "codespan-reporting", 406 | "once_cell", 407 | "proc-macro2", 408 | "quote", 409 | "scratch", 410 | "syn", 411 | ] 412 | 413 | [[package]] 414 | name = "cxxbridge-flags" 415 | version = "1.0.86" 416 | source = "registry+https://github.com/rust-lang/crates.io-index" 417 | checksum = "61b50bc93ba22c27b0d31128d2d130a0a6b3d267ae27ef7e4fae2167dfe8781c" 418 | 419 | [[package]] 420 | name = "cxxbridge-macro" 421 | version = "1.0.86" 422 | source = "registry+https://github.com/rust-lang/crates.io-index" 423 | checksum = "39e61fda7e62115119469c7b3591fd913ecca96fb766cfd3f2e2502ab7bc87a5" 424 | dependencies = [ 425 | "proc-macro2", 426 | "quote", 427 | "syn", 428 | ] 429 | 430 | [[package]] 431 | name = "debugid" 432 | version = "0.8.0" 433 | source = "registry+https://github.com/rust-lang/crates.io-index" 434 | checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" 435 | dependencies = [ 436 | "serde", 437 | "uuid", 438 | ] 439 | 440 | [[package]] 441 | name = "defmt-decoder" 442 | version = "0.3.3" 443 | source = "registry+https://github.com/rust-lang/crates.io-index" 444 | checksum = "3d1405280032c1be7fcad411f7ba7b24de9dcea89fd77ae043dae1b2b9dd1254" 445 | dependencies = [ 446 | "anyhow", 447 | "byteorder", 448 | "chrono", 449 | "colored", 450 | "defmt-json-schema", 451 | "defmt-parser", 452 | "difference", 453 | "gimli 0.26.2", 454 | "log", 455 | "object 0.29.0", 456 | "ryu", 457 | "serde", 458 | "serde_json", 459 | ] 460 | 461 | [[package]] 462 | name = "defmt-json-schema" 463 | version = "0.1.0" 464 | source = "registry+https://github.com/rust-lang/crates.io-index" 465 | checksum = "96b04d228e57a61cf385d86bc8980bb41b47c6fc0eace90592668df97b2dad6a" 466 | dependencies = [ 467 | "log", 468 | "serde", 469 | ] 470 | 471 | [[package]] 472 | name = "defmt-parser" 473 | version = "0.3.1" 474 | source = "registry+https://github.com/rust-lang/crates.io-index" 475 | checksum = "0db23d29972d99baa3de2ee2ae3f104c10564a6d05a346eb3f4c4f2c0525a06e" 476 | 477 | [[package]] 478 | name = "difference" 479 | version = "2.0.0" 480 | source = "registry+https://github.com/rust-lang/crates.io-index" 481 | checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" 482 | 483 | [[package]] 484 | name = "dunce" 485 | version = "1.0.3" 486 | source = "registry+https://github.com/rust-lang/crates.io-index" 487 | checksum = "0bd4b30a6560bbd9b4620f4de34c3f14f60848e58a9b7216801afcb4c7b31c3c" 488 | 489 | [[package]] 490 | name = "either" 491 | version = "1.8.0" 492 | source = "registry+https://github.com/rust-lang/crates.io-index" 493 | checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" 494 | 495 | [[package]] 496 | name = "encode_unicode" 497 | version = "0.3.6" 498 | source = "registry+https://github.com/rust-lang/crates.io-index" 499 | checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" 500 | 501 | [[package]] 502 | name = "encoding_rs" 503 | version = "0.8.31" 504 | source = "registry+https://github.com/rust-lang/crates.io-index" 505 | checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" 506 | dependencies = [ 507 | "cfg-if", 508 | ] 509 | 510 | [[package]] 511 | name = "enum-primitive-derive" 512 | version = "0.2.2" 513 | source = "registry+https://github.com/rust-lang/crates.io-index" 514 | checksum = "c375b9c5eadb68d0a6efee2999fef292f45854c3444c86f09d8ab086ba942b0e" 515 | dependencies = [ 516 | "num-traits", 517 | "quote", 518 | "syn", 519 | ] 520 | 521 | [[package]] 522 | name = "env_logger" 523 | version = "0.10.0" 524 | source = "registry+https://github.com/rust-lang/crates.io-index" 525 | checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" 526 | dependencies = [ 527 | "humantime", 528 | "is-terminal", 529 | "log", 530 | "regex", 531 | "termcolor", 532 | ] 533 | 534 | [[package]] 535 | name = "errno" 536 | version = "0.2.8" 537 | source = "registry+https://github.com/rust-lang/crates.io-index" 538 | checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" 539 | dependencies = [ 540 | "errno-dragonfly", 541 | "libc", 542 | "winapi", 543 | ] 544 | 545 | [[package]] 546 | name = "errno-dragonfly" 547 | version = "0.1.2" 548 | source = "registry+https://github.com/rust-lang/crates.io-index" 549 | checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" 550 | dependencies = [ 551 | "cc", 552 | "libc", 553 | ] 554 | 555 | [[package]] 556 | name = "fallible-iterator" 557 | version = "0.2.0" 558 | source = "registry+https://github.com/rust-lang/crates.io-index" 559 | checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" 560 | 561 | [[package]] 562 | name = "fastrand" 563 | version = "1.8.0" 564 | source = "registry+https://github.com/rust-lang/crates.io-index" 565 | checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" 566 | dependencies = [ 567 | "instant", 568 | ] 569 | 570 | [[package]] 571 | name = "figment" 572 | version = "0.10.8" 573 | source = "registry+https://github.com/rust-lang/crates.io-index" 574 | checksum = "4e56602b469b2201400dec66a66aec5a9b8761ee97cd1b8c96ab2483fcc16cc9" 575 | dependencies = [ 576 | "atomic", 577 | "pear", 578 | "serde", 579 | "serde_json", 580 | "serde_yaml", 581 | "toml", 582 | "uncased", 583 | "version_check", 584 | ] 585 | 586 | [[package]] 587 | name = "fnv" 588 | version = "1.0.7" 589 | source = "registry+https://github.com/rust-lang/crates.io-index" 590 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 591 | 592 | [[package]] 593 | name = "foreign-types" 594 | version = "0.3.2" 595 | source = "registry+https://github.com/rust-lang/crates.io-index" 596 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 597 | dependencies = [ 598 | "foreign-types-shared", 599 | ] 600 | 601 | [[package]] 602 | name = "foreign-types-shared" 603 | version = "0.1.1" 604 | source = "registry+https://github.com/rust-lang/crates.io-index" 605 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 606 | 607 | [[package]] 608 | name = "form_urlencoded" 609 | version = "1.1.0" 610 | source = "registry+https://github.com/rust-lang/crates.io-index" 611 | checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" 612 | dependencies = [ 613 | "percent-encoding", 614 | ] 615 | 616 | [[package]] 617 | name = "funty" 618 | version = "2.0.0" 619 | source = "registry+https://github.com/rust-lang/crates.io-index" 620 | checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" 621 | 622 | [[package]] 623 | name = "futures-channel" 624 | version = "0.3.25" 625 | source = "registry+https://github.com/rust-lang/crates.io-index" 626 | checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" 627 | dependencies = [ 628 | "futures-core", 629 | ] 630 | 631 | [[package]] 632 | name = "futures-core" 633 | version = "0.3.25" 634 | source = "registry+https://github.com/rust-lang/crates.io-index" 635 | checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" 636 | 637 | [[package]] 638 | name = "futures-io" 639 | version = "0.3.25" 640 | source = "registry+https://github.com/rust-lang/crates.io-index" 641 | checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" 642 | 643 | [[package]] 644 | name = "futures-sink" 645 | version = "0.3.25" 646 | source = "registry+https://github.com/rust-lang/crates.io-index" 647 | checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" 648 | 649 | [[package]] 650 | name = "futures-task" 651 | version = "0.3.25" 652 | source = "registry+https://github.com/rust-lang/crates.io-index" 653 | checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" 654 | 655 | [[package]] 656 | name = "futures-util" 657 | version = "0.3.25" 658 | source = "registry+https://github.com/rust-lang/crates.io-index" 659 | checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" 660 | dependencies = [ 661 | "futures-core", 662 | "futures-io", 663 | "futures-task", 664 | "memchr", 665 | "pin-project-lite", 666 | "pin-utils", 667 | "slab", 668 | ] 669 | 670 | [[package]] 671 | name = "gdb-server" 672 | version = "0.13.0" 673 | source = "git+https://github.com/probe-rs/probe-rs#e71043a288d25d1a23b050d6a7b9b44688c00535" 674 | dependencies = [ 675 | "anyhow", 676 | "gdbstub", 677 | "itertools", 678 | "log", 679 | "probe-rs", 680 | ] 681 | 682 | [[package]] 683 | name = "gdbstub" 684 | version = "0.6.3" 685 | source = "registry+https://github.com/rust-lang/crates.io-index" 686 | checksum = "32c95766e0414f8bfc1d07055574c621b67739466d6ba516c4fef8e99d30d2e6" 687 | dependencies = [ 688 | "bitflags", 689 | "cfg-if", 690 | "log", 691 | "managed", 692 | "num-traits", 693 | "paste", 694 | ] 695 | 696 | [[package]] 697 | name = "getrandom" 698 | version = "0.2.8" 699 | source = "registry+https://github.com/rust-lang/crates.io-index" 700 | checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" 701 | dependencies = [ 702 | "cfg-if", 703 | "libc", 704 | "wasi 0.11.0+wasi-snapshot-preview1", 705 | ] 706 | 707 | [[package]] 708 | name = "gimli" 709 | version = "0.26.2" 710 | source = "registry+https://github.com/rust-lang/crates.io-index" 711 | checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" 712 | dependencies = [ 713 | "fallible-iterator", 714 | "stable_deref_trait", 715 | ] 716 | 717 | [[package]] 718 | name = "gimli" 719 | version = "0.27.0" 720 | source = "registry+https://github.com/rust-lang/crates.io-index" 721 | checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793" 722 | dependencies = [ 723 | "fallible-iterator", 724 | "stable_deref_trait", 725 | ] 726 | 727 | [[package]] 728 | name = "git-version" 729 | version = "0.3.5" 730 | source = "registry+https://github.com/rust-lang/crates.io-index" 731 | checksum = "f6b0decc02f4636b9ccad390dcbe77b722a77efedfa393caf8379a51d5c61899" 732 | dependencies = [ 733 | "git-version-macro", 734 | "proc-macro-hack", 735 | ] 736 | 737 | [[package]] 738 | name = "git-version-macro" 739 | version = "0.3.5" 740 | source = "registry+https://github.com/rust-lang/crates.io-index" 741 | checksum = "fe69f1cbdb6e28af2bac214e943b99ce8a0a06b447d15d3e61161b0423139f3f" 742 | dependencies = [ 743 | "proc-macro-hack", 744 | "proc-macro2", 745 | "quote", 746 | "syn", 747 | ] 748 | 749 | [[package]] 750 | name = "goblin" 751 | version = "0.6.0" 752 | source = "registry+https://github.com/rust-lang/crates.io-index" 753 | checksum = "572564d6cba7d09775202c8e7eebc4d534d5ae36578ab402fb21e182a0ac9505" 754 | dependencies = [ 755 | "log", 756 | "plain", 757 | "scroll 0.11.0", 758 | ] 759 | 760 | [[package]] 761 | name = "h2" 762 | version = "0.3.15" 763 | source = "registry+https://github.com/rust-lang/crates.io-index" 764 | checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" 765 | dependencies = [ 766 | "bytes", 767 | "fnv", 768 | "futures-core", 769 | "futures-sink", 770 | "futures-util", 771 | "http", 772 | "indexmap", 773 | "slab", 774 | "tokio", 775 | "tokio-util", 776 | "tracing", 777 | ] 778 | 779 | [[package]] 780 | name = "hashbrown" 781 | version = "0.12.3" 782 | source = "registry+https://github.com/rust-lang/crates.io-index" 783 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 784 | dependencies = [ 785 | "ahash", 786 | ] 787 | 788 | [[package]] 789 | name = "heck" 790 | version = "0.4.0" 791 | source = "registry+https://github.com/rust-lang/crates.io-index" 792 | checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" 793 | 794 | [[package]] 795 | name = "hermit-abi" 796 | version = "0.1.19" 797 | source = "registry+https://github.com/rust-lang/crates.io-index" 798 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 799 | dependencies = [ 800 | "libc", 801 | ] 802 | 803 | [[package]] 804 | name = "hermit-abi" 805 | version = "0.2.6" 806 | source = "registry+https://github.com/rust-lang/crates.io-index" 807 | checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" 808 | dependencies = [ 809 | "libc", 810 | ] 811 | 812 | [[package]] 813 | name = "hex" 814 | version = "0.4.3" 815 | source = "registry+https://github.com/rust-lang/crates.io-index" 816 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 817 | 818 | [[package]] 819 | name = "hidapi" 820 | version = "2.1.1" 821 | source = "registry+https://github.com/rust-lang/crates.io-index" 822 | checksum = "41cd9e1a4d30b483574da670f07701c87469a4919062b4236f0147a7df805cab" 823 | dependencies = [ 824 | "cc", 825 | "libc", 826 | "pkg-config", 827 | "winapi", 828 | ] 829 | 830 | [[package]] 831 | name = "hostname" 832 | version = "0.3.1" 833 | source = "registry+https://github.com/rust-lang/crates.io-index" 834 | checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" 835 | dependencies = [ 836 | "libc", 837 | "match_cfg", 838 | "winapi", 839 | ] 840 | 841 | [[package]] 842 | name = "http" 843 | version = "0.2.8" 844 | source = "registry+https://github.com/rust-lang/crates.io-index" 845 | checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" 846 | dependencies = [ 847 | "bytes", 848 | "fnv", 849 | "itoa", 850 | ] 851 | 852 | [[package]] 853 | name = "http-body" 854 | version = "0.4.5" 855 | source = "registry+https://github.com/rust-lang/crates.io-index" 856 | checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" 857 | dependencies = [ 858 | "bytes", 859 | "http", 860 | "pin-project-lite", 861 | ] 862 | 863 | [[package]] 864 | name = "httparse" 865 | version = "1.8.0" 866 | source = "registry+https://github.com/rust-lang/crates.io-index" 867 | checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" 868 | 869 | [[package]] 870 | name = "httpdate" 871 | version = "1.0.2" 872 | source = "registry+https://github.com/rust-lang/crates.io-index" 873 | checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" 874 | 875 | [[package]] 876 | name = "humantime" 877 | version = "2.1.0" 878 | source = "registry+https://github.com/rust-lang/crates.io-index" 879 | checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" 880 | 881 | [[package]] 882 | name = "hyper" 883 | version = "0.14.23" 884 | source = "registry+https://github.com/rust-lang/crates.io-index" 885 | checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c" 886 | dependencies = [ 887 | "bytes", 888 | "futures-channel", 889 | "futures-core", 890 | "futures-util", 891 | "h2", 892 | "http", 893 | "http-body", 894 | "httparse", 895 | "httpdate", 896 | "itoa", 897 | "pin-project-lite", 898 | "socket2", 899 | "tokio", 900 | "tower-service", 901 | "tracing", 902 | "want", 903 | ] 904 | 905 | [[package]] 906 | name = "hyper-tls" 907 | version = "0.5.0" 908 | source = "registry+https://github.com/rust-lang/crates.io-index" 909 | checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" 910 | dependencies = [ 911 | "bytes", 912 | "hyper", 913 | "native-tls", 914 | "tokio", 915 | "tokio-native-tls", 916 | ] 917 | 918 | [[package]] 919 | name = "iana-time-zone" 920 | version = "0.1.53" 921 | source = "registry+https://github.com/rust-lang/crates.io-index" 922 | checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" 923 | dependencies = [ 924 | "android_system_properties", 925 | "core-foundation-sys", 926 | "iana-time-zone-haiku", 927 | "js-sys", 928 | "wasm-bindgen", 929 | "winapi", 930 | ] 931 | 932 | [[package]] 933 | name = "iana-time-zone-haiku" 934 | version = "0.1.1" 935 | source = "registry+https://github.com/rust-lang/crates.io-index" 936 | checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" 937 | dependencies = [ 938 | "cxx", 939 | "cxx-build", 940 | ] 941 | 942 | [[package]] 943 | name = "idna" 944 | version = "0.3.0" 945 | source = "registry+https://github.com/rust-lang/crates.io-index" 946 | checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" 947 | dependencies = [ 948 | "unicode-bidi", 949 | "unicode-normalization", 950 | ] 951 | 952 | [[package]] 953 | name = "ihex" 954 | version = "3.0.0" 955 | source = "registry+https://github.com/rust-lang/crates.io-index" 956 | checksum = "365a784774bb381e8c19edb91190a90d7f2625e057b55de2bc0f6b57bc779ff2" 957 | 958 | [[package]] 959 | name = "indexmap" 960 | version = "1.9.2" 961 | source = "registry+https://github.com/rust-lang/crates.io-index" 962 | checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" 963 | dependencies = [ 964 | "autocfg", 965 | "hashbrown", 966 | ] 967 | 968 | [[package]] 969 | name = "indicatif" 970 | version = "0.17.2" 971 | source = "registry+https://github.com/rust-lang/crates.io-index" 972 | checksum = "4295cbb7573c16d310e99e713cf9e75101eb190ab31fccd35f2d2691b4352b19" 973 | dependencies = [ 974 | "console", 975 | "number_prefix", 976 | "portable-atomic", 977 | "unicode-width", 978 | ] 979 | 980 | [[package]] 981 | name = "inlinable_string" 982 | version = "0.1.15" 983 | source = "registry+https://github.com/rust-lang/crates.io-index" 984 | checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" 985 | 986 | [[package]] 987 | name = "instant" 988 | version = "0.1.12" 989 | source = "registry+https://github.com/rust-lang/crates.io-index" 990 | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" 991 | dependencies = [ 992 | "cfg-if", 993 | ] 994 | 995 | [[package]] 996 | name = "io-lifetimes" 997 | version = "1.0.4" 998 | source = "registry+https://github.com/rust-lang/crates.io-index" 999 | checksum = "e7d6c6f8c91b4b9ed43484ad1a938e393caf35960fce7f82a040497207bd8e9e" 1000 | dependencies = [ 1001 | "libc", 1002 | "windows-sys", 1003 | ] 1004 | 1005 | [[package]] 1006 | name = "ipnet" 1007 | version = "2.7.1" 1008 | source = "registry+https://github.com/rust-lang/crates.io-index" 1009 | checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146" 1010 | 1011 | [[package]] 1012 | name = "is-terminal" 1013 | version = "0.4.2" 1014 | source = "registry+https://github.com/rust-lang/crates.io-index" 1015 | checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189" 1016 | dependencies = [ 1017 | "hermit-abi 0.2.6", 1018 | "io-lifetimes", 1019 | "rustix", 1020 | "windows-sys", 1021 | ] 1022 | 1023 | [[package]] 1024 | name = "itertools" 1025 | version = "0.10.5" 1026 | source = "registry+https://github.com/rust-lang/crates.io-index" 1027 | checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" 1028 | dependencies = [ 1029 | "either", 1030 | ] 1031 | 1032 | [[package]] 1033 | name = "itoa" 1034 | version = "1.0.5" 1035 | source = "registry+https://github.com/rust-lang/crates.io-index" 1036 | checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" 1037 | 1038 | [[package]] 1039 | name = "jaylink" 1040 | version = "0.3.0" 1041 | source = "registry+https://github.com/rust-lang/crates.io-index" 1042 | checksum = "2d891935e08397d85684c1d3c88b6a0a6941c6e15e9f04a1ae9e30079f0b0df0" 1043 | dependencies = [ 1044 | "bitflags", 1045 | "byteorder", 1046 | "log", 1047 | "rusb", 1048 | ] 1049 | 1050 | [[package]] 1051 | name = "jep106" 1052 | version = "0.2.8" 1053 | source = "registry+https://github.com/rust-lang/crates.io-index" 1054 | checksum = "ff93b33ae176e47fe588708ff6a4cccae22bd369b81c2d26d2179a8d41c0a0b0" 1055 | dependencies = [ 1056 | "serde", 1057 | ] 1058 | 1059 | [[package]] 1060 | name = "js-sys" 1061 | version = "0.3.60" 1062 | source = "registry+https://github.com/rust-lang/crates.io-index" 1063 | checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" 1064 | dependencies = [ 1065 | "wasm-bindgen", 1066 | ] 1067 | 1068 | [[package]] 1069 | name = "lazy_static" 1070 | version = "1.4.0" 1071 | source = "registry+https://github.com/rust-lang/crates.io-index" 1072 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 1073 | 1074 | [[package]] 1075 | name = "libc" 1076 | version = "0.2.139" 1077 | source = "registry+https://github.com/rust-lang/crates.io-index" 1078 | checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" 1079 | 1080 | [[package]] 1081 | name = "libftdi1-sys" 1082 | version = "1.1.2" 1083 | source = "registry+https://github.com/rust-lang/crates.io-index" 1084 | checksum = "3ff6928872c7d13bec3c8a60c4c92f41f6252f3369b7552a5b4f9c90c8ba2338" 1085 | dependencies = [ 1086 | "cfg-if", 1087 | "libc", 1088 | "pkg-config", 1089 | "vcpkg", 1090 | ] 1091 | 1092 | [[package]] 1093 | name = "libusb1-sys" 1094 | version = "0.6.4" 1095 | source = "registry+https://github.com/rust-lang/crates.io-index" 1096 | checksum = "f9d0e2afce4245f2c9a418511e5af8718bcaf2fa408aefb259504d1a9cb25f27" 1097 | dependencies = [ 1098 | "cc", 1099 | "libc", 1100 | "pkg-config", 1101 | "vcpkg", 1102 | ] 1103 | 1104 | [[package]] 1105 | name = "link-cplusplus" 1106 | version = "1.0.8" 1107 | source = "registry+https://github.com/rust-lang/crates.io-index" 1108 | checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" 1109 | dependencies = [ 1110 | "cc", 1111 | ] 1112 | 1113 | [[package]] 1114 | name = "linux-raw-sys" 1115 | version = "0.1.4" 1116 | source = "registry+https://github.com/rust-lang/crates.io-index" 1117 | checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" 1118 | 1119 | [[package]] 1120 | name = "lock_api" 1121 | version = "0.4.9" 1122 | source = "registry+https://github.com/rust-lang/crates.io-index" 1123 | checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" 1124 | dependencies = [ 1125 | "autocfg", 1126 | "scopeguard", 1127 | ] 1128 | 1129 | [[package]] 1130 | name = "log" 1131 | version = "0.4.17" 1132 | source = "registry+https://github.com/rust-lang/crates.io-index" 1133 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" 1134 | dependencies = [ 1135 | "cfg-if", 1136 | "serde", 1137 | ] 1138 | 1139 | [[package]] 1140 | name = "managed" 1141 | version = "0.8.0" 1142 | source = "registry+https://github.com/rust-lang/crates.io-index" 1143 | checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d" 1144 | 1145 | [[package]] 1146 | name = "match_cfg" 1147 | version = "0.1.0" 1148 | source = "registry+https://github.com/rust-lang/crates.io-index" 1149 | checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" 1150 | 1151 | [[package]] 1152 | name = "memchr" 1153 | version = "2.5.0" 1154 | source = "registry+https://github.com/rust-lang/crates.io-index" 1155 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 1156 | 1157 | [[package]] 1158 | name = "mime" 1159 | version = "0.3.16" 1160 | source = "registry+https://github.com/rust-lang/crates.io-index" 1161 | checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" 1162 | 1163 | [[package]] 1164 | name = "miniz_oxide" 1165 | version = "0.6.2" 1166 | source = "registry+https://github.com/rust-lang/crates.io-index" 1167 | checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" 1168 | dependencies = [ 1169 | "adler", 1170 | ] 1171 | 1172 | [[package]] 1173 | name = "mio" 1174 | version = "0.8.5" 1175 | source = "registry+https://github.com/rust-lang/crates.io-index" 1176 | checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" 1177 | dependencies = [ 1178 | "libc", 1179 | "log", 1180 | "wasi 0.11.0+wasi-snapshot-preview1", 1181 | "windows-sys", 1182 | ] 1183 | 1184 | [[package]] 1185 | name = "native-tls" 1186 | version = "0.2.11" 1187 | source = "registry+https://github.com/rust-lang/crates.io-index" 1188 | checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" 1189 | dependencies = [ 1190 | "lazy_static", 1191 | "libc", 1192 | "log", 1193 | "openssl", 1194 | "openssl-probe", 1195 | "openssl-sys", 1196 | "schannel", 1197 | "security-framework", 1198 | "security-framework-sys", 1199 | "tempfile", 1200 | ] 1201 | 1202 | [[package]] 1203 | name = "num-integer" 1204 | version = "0.1.45" 1205 | source = "registry+https://github.com/rust-lang/crates.io-index" 1206 | checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" 1207 | dependencies = [ 1208 | "autocfg", 1209 | "num-traits", 1210 | ] 1211 | 1212 | [[package]] 1213 | name = "num-traits" 1214 | version = "0.2.15" 1215 | source = "registry+https://github.com/rust-lang/crates.io-index" 1216 | checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" 1217 | dependencies = [ 1218 | "autocfg", 1219 | ] 1220 | 1221 | [[package]] 1222 | name = "num_cpus" 1223 | version = "1.15.0" 1224 | source = "registry+https://github.com/rust-lang/crates.io-index" 1225 | checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" 1226 | dependencies = [ 1227 | "hermit-abi 0.2.6", 1228 | "libc", 1229 | ] 1230 | 1231 | [[package]] 1232 | name = "num_threads" 1233 | version = "0.1.6" 1234 | source = "registry+https://github.com/rust-lang/crates.io-index" 1235 | checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" 1236 | dependencies = [ 1237 | "libc", 1238 | ] 1239 | 1240 | [[package]] 1241 | name = "number_prefix" 1242 | version = "0.4.0" 1243 | source = "registry+https://github.com/rust-lang/crates.io-index" 1244 | checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" 1245 | 1246 | [[package]] 1247 | name = "object" 1248 | version = "0.29.0" 1249 | source = "registry+https://github.com/rust-lang/crates.io-index" 1250 | checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" 1251 | dependencies = [ 1252 | "memchr", 1253 | ] 1254 | 1255 | [[package]] 1256 | name = "object" 1257 | version = "0.30.2" 1258 | source = "registry+https://github.com/rust-lang/crates.io-index" 1259 | checksum = "2b8c786513eb403643f2a88c244c2aaa270ef2153f55094587d0c48a3cf22a83" 1260 | dependencies = [ 1261 | "memchr", 1262 | ] 1263 | 1264 | [[package]] 1265 | name = "once_cell" 1266 | version = "1.17.0" 1267 | source = "registry+https://github.com/rust-lang/crates.io-index" 1268 | checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" 1269 | 1270 | [[package]] 1271 | name = "openssl" 1272 | version = "0.10.45" 1273 | source = "registry+https://github.com/rust-lang/crates.io-index" 1274 | checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1" 1275 | dependencies = [ 1276 | "bitflags", 1277 | "cfg-if", 1278 | "foreign-types", 1279 | "libc", 1280 | "once_cell", 1281 | "openssl-macros", 1282 | "openssl-sys", 1283 | ] 1284 | 1285 | [[package]] 1286 | name = "openssl-macros" 1287 | version = "0.1.0" 1288 | source = "registry+https://github.com/rust-lang/crates.io-index" 1289 | checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" 1290 | dependencies = [ 1291 | "proc-macro2", 1292 | "quote", 1293 | "syn", 1294 | ] 1295 | 1296 | [[package]] 1297 | name = "openssl-probe" 1298 | version = "0.1.5" 1299 | source = "registry+https://github.com/rust-lang/crates.io-index" 1300 | checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" 1301 | 1302 | [[package]] 1303 | name = "openssl-sys" 1304 | version = "0.9.80" 1305 | source = "registry+https://github.com/rust-lang/crates.io-index" 1306 | checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7" 1307 | dependencies = [ 1308 | "autocfg", 1309 | "cc", 1310 | "libc", 1311 | "pkg-config", 1312 | "vcpkg", 1313 | ] 1314 | 1315 | [[package]] 1316 | name = "os_info" 1317 | version = "3.5.1" 1318 | source = "registry+https://github.com/rust-lang/crates.io-index" 1319 | checksum = "c4750134fb6a5d49afc80777394ad5d95b04bc12068c6abb92fae8f43817270f" 1320 | dependencies = [ 1321 | "log", 1322 | "serde", 1323 | "winapi", 1324 | ] 1325 | 1326 | [[package]] 1327 | name = "os_str_bytes" 1328 | version = "6.4.1" 1329 | source = "registry+https://github.com/rust-lang/crates.io-index" 1330 | checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" 1331 | 1332 | [[package]] 1333 | name = "parking_lot" 1334 | version = "0.12.1" 1335 | source = "registry+https://github.com/rust-lang/crates.io-index" 1336 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 1337 | dependencies = [ 1338 | "lock_api", 1339 | "parking_lot_core", 1340 | ] 1341 | 1342 | [[package]] 1343 | name = "parking_lot_core" 1344 | version = "0.9.6" 1345 | source = "registry+https://github.com/rust-lang/crates.io-index" 1346 | checksum = "ba1ef8814b5c993410bb3adfad7a5ed269563e4a2f90c41f5d85be7fb47133bf" 1347 | dependencies = [ 1348 | "cfg-if", 1349 | "libc", 1350 | "redox_syscall", 1351 | "smallvec", 1352 | "windows-sys", 1353 | ] 1354 | 1355 | [[package]] 1356 | name = "paste" 1357 | version = "1.0.11" 1358 | source = "registry+https://github.com/rust-lang/crates.io-index" 1359 | checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" 1360 | 1361 | [[package]] 1362 | name = "pear" 1363 | version = "0.2.3" 1364 | source = "registry+https://github.com/rust-lang/crates.io-index" 1365 | checksum = "15e44241c5e4c868e3eaa78b7c1848cadd6344ed4f54d029832d32b415a58702" 1366 | dependencies = [ 1367 | "inlinable_string", 1368 | "pear_codegen", 1369 | "yansi", 1370 | ] 1371 | 1372 | [[package]] 1373 | name = "pear_codegen" 1374 | version = "0.2.3" 1375 | source = "registry+https://github.com/rust-lang/crates.io-index" 1376 | checksum = "82a5ca643c2303ecb740d506539deba189e16f2754040a42901cd8105d0282d0" 1377 | dependencies = [ 1378 | "proc-macro2", 1379 | "proc-macro2-diagnostics", 1380 | "quote", 1381 | "syn", 1382 | ] 1383 | 1384 | [[package]] 1385 | name = "percent-encoding" 1386 | version = "2.2.0" 1387 | source = "registry+https://github.com/rust-lang/crates.io-index" 1388 | checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" 1389 | 1390 | [[package]] 1391 | name = "pin-project-lite" 1392 | version = "0.2.9" 1393 | source = "registry+https://github.com/rust-lang/crates.io-index" 1394 | checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" 1395 | 1396 | [[package]] 1397 | name = "pin-utils" 1398 | version = "0.1.0" 1399 | source = "registry+https://github.com/rust-lang/crates.io-index" 1400 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1401 | 1402 | [[package]] 1403 | name = "pkg-config" 1404 | version = "0.3.26" 1405 | source = "registry+https://github.com/rust-lang/crates.io-index" 1406 | checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" 1407 | 1408 | [[package]] 1409 | name = "plain" 1410 | version = "0.2.3" 1411 | source = "registry+https://github.com/rust-lang/crates.io-index" 1412 | checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" 1413 | 1414 | [[package]] 1415 | name = "portable-atomic" 1416 | version = "0.3.19" 1417 | source = "registry+https://github.com/rust-lang/crates.io-index" 1418 | checksum = "26f6a7b87c2e435a3241addceeeff740ff8b7e76b74c13bf9acb17fa454ea00b" 1419 | 1420 | [[package]] 1421 | name = "ppv-lite86" 1422 | version = "0.2.17" 1423 | source = "registry+https://github.com/rust-lang/crates.io-index" 1424 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" 1425 | 1426 | [[package]] 1427 | name = "probe-rs" 1428 | version = "0.13.0" 1429 | source = "git+https://github.com/probe-rs/probe-rs#e71043a288d25d1a23b050d6a7b9b44688c00535" 1430 | dependencies = [ 1431 | "anyhow", 1432 | "base64 0.21.0", 1433 | "bincode", 1434 | "bitfield", 1435 | "bitvec", 1436 | "enum-primitive-derive", 1437 | "gimli 0.27.0", 1438 | "hidapi", 1439 | "ihex", 1440 | "jaylink", 1441 | "jep106", 1442 | "libftdi1-sys", 1443 | "num-traits", 1444 | "object 0.30.2", 1445 | "once_cell", 1446 | "probe-rs-target", 1447 | "rusb", 1448 | "scroll 0.11.0", 1449 | "serde", 1450 | "serde_yaml", 1451 | "static_assertions", 1452 | "svg", 1453 | "thiserror", 1454 | "tracing", 1455 | ] 1456 | 1457 | [[package]] 1458 | name = "probe-rs-cli-util" 1459 | version = "0.13.0" 1460 | source = "git+https://github.com/probe-rs/probe-rs#e71043a288d25d1a23b050d6a7b9b44688c00535" 1461 | dependencies = [ 1462 | "anyhow", 1463 | "byte-unit", 1464 | "cargo_metadata", 1465 | "cargo_toml", 1466 | "chrono", 1467 | "clap", 1468 | "colored", 1469 | "defmt-decoder", 1470 | "dunce", 1471 | "env_logger", 1472 | "git-version", 1473 | "goblin", 1474 | "indicatif", 1475 | "log", 1476 | "num-traits", 1477 | "once_cell", 1478 | "probe-rs", 1479 | "probe-rs-rtt", 1480 | "sentry", 1481 | "serde", 1482 | "simplelog", 1483 | "terminal_size", 1484 | "thiserror", 1485 | ] 1486 | 1487 | [[package]] 1488 | name = "probe-rs-rtt" 1489 | version = "0.13.0" 1490 | source = "git+https://github.com/probe-rs/probe-rs#e71043a288d25d1a23b050d6a7b9b44688c00535" 1491 | dependencies = [ 1492 | "probe-rs", 1493 | "scroll 0.10.2", 1494 | "serde", 1495 | "thiserror", 1496 | "tracing", 1497 | ] 1498 | 1499 | [[package]] 1500 | name = "probe-rs-target" 1501 | version = "0.13.0" 1502 | source = "git+https://github.com/probe-rs/probe-rs#e71043a288d25d1a23b050d6a7b9b44688c00535" 1503 | dependencies = [ 1504 | "base64 0.21.0", 1505 | "jep106", 1506 | "serde", 1507 | ] 1508 | 1509 | [[package]] 1510 | name = "proc-macro-error" 1511 | version = "1.0.4" 1512 | source = "registry+https://github.com/rust-lang/crates.io-index" 1513 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 1514 | dependencies = [ 1515 | "proc-macro-error-attr", 1516 | "proc-macro2", 1517 | "quote", 1518 | "syn", 1519 | "version_check", 1520 | ] 1521 | 1522 | [[package]] 1523 | name = "proc-macro-error-attr" 1524 | version = "1.0.4" 1525 | source = "registry+https://github.com/rust-lang/crates.io-index" 1526 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 1527 | dependencies = [ 1528 | "proc-macro2", 1529 | "quote", 1530 | "version_check", 1531 | ] 1532 | 1533 | [[package]] 1534 | name = "proc-macro-hack" 1535 | version = "0.5.20+deprecated" 1536 | source = "registry+https://github.com/rust-lang/crates.io-index" 1537 | checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" 1538 | 1539 | [[package]] 1540 | name = "proc-macro2" 1541 | version = "1.0.49" 1542 | source = "registry+https://github.com/rust-lang/crates.io-index" 1543 | checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" 1544 | dependencies = [ 1545 | "unicode-ident", 1546 | ] 1547 | 1548 | [[package]] 1549 | name = "proc-macro2-diagnostics" 1550 | version = "0.9.1" 1551 | source = "registry+https://github.com/rust-lang/crates.io-index" 1552 | checksum = "4bf29726d67464d49fa6224a1d07936a8c08bb3fba727c7493f6cf1616fdaada" 1553 | dependencies = [ 1554 | "proc-macro2", 1555 | "quote", 1556 | "syn", 1557 | "version_check", 1558 | "yansi", 1559 | ] 1560 | 1561 | [[package]] 1562 | name = "quote" 1563 | version = "1.0.23" 1564 | source = "registry+https://github.com/rust-lang/crates.io-index" 1565 | checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" 1566 | dependencies = [ 1567 | "proc-macro2", 1568 | ] 1569 | 1570 | [[package]] 1571 | name = "radium" 1572 | version = "0.7.0" 1573 | source = "registry+https://github.com/rust-lang/crates.io-index" 1574 | checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" 1575 | 1576 | [[package]] 1577 | name = "rand" 1578 | version = "0.8.5" 1579 | source = "registry+https://github.com/rust-lang/crates.io-index" 1580 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 1581 | dependencies = [ 1582 | "libc", 1583 | "rand_chacha", 1584 | "rand_core", 1585 | ] 1586 | 1587 | [[package]] 1588 | name = "rand_chacha" 1589 | version = "0.3.1" 1590 | source = "registry+https://github.com/rust-lang/crates.io-index" 1591 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 1592 | dependencies = [ 1593 | "ppv-lite86", 1594 | "rand_core", 1595 | ] 1596 | 1597 | [[package]] 1598 | name = "rand_core" 1599 | version = "0.6.4" 1600 | source = "registry+https://github.com/rust-lang/crates.io-index" 1601 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 1602 | dependencies = [ 1603 | "getrandom", 1604 | ] 1605 | 1606 | [[package]] 1607 | name = "redox_syscall" 1608 | version = "0.2.16" 1609 | source = "registry+https://github.com/rust-lang/crates.io-index" 1610 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 1611 | dependencies = [ 1612 | "bitflags", 1613 | ] 1614 | 1615 | [[package]] 1616 | name = "regex" 1617 | version = "1.7.1" 1618 | source = "registry+https://github.com/rust-lang/crates.io-index" 1619 | checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" 1620 | dependencies = [ 1621 | "aho-corasick", 1622 | "memchr", 1623 | "regex-syntax", 1624 | ] 1625 | 1626 | [[package]] 1627 | name = "regex-syntax" 1628 | version = "0.6.28" 1629 | source = "registry+https://github.com/rust-lang/crates.io-index" 1630 | checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" 1631 | 1632 | [[package]] 1633 | name = "remove_dir_all" 1634 | version = "0.5.3" 1635 | source = "registry+https://github.com/rust-lang/crates.io-index" 1636 | checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" 1637 | dependencies = [ 1638 | "winapi", 1639 | ] 1640 | 1641 | [[package]] 1642 | name = "reqwest" 1643 | version = "0.11.13" 1644 | source = "registry+https://github.com/rust-lang/crates.io-index" 1645 | checksum = "68cc60575865c7831548863cc02356512e3f1dc2f3f82cb837d7fc4cc8f3c97c" 1646 | dependencies = [ 1647 | "base64 0.13.1", 1648 | "bytes", 1649 | "encoding_rs", 1650 | "futures-core", 1651 | "futures-util", 1652 | "h2", 1653 | "http", 1654 | "http-body", 1655 | "hyper", 1656 | "hyper-tls", 1657 | "ipnet", 1658 | "js-sys", 1659 | "log", 1660 | "mime", 1661 | "native-tls", 1662 | "once_cell", 1663 | "percent-encoding", 1664 | "pin-project-lite", 1665 | "serde", 1666 | "serde_json", 1667 | "serde_urlencoded", 1668 | "tokio", 1669 | "tokio-native-tls", 1670 | "tower-service", 1671 | "url", 1672 | "wasm-bindgen", 1673 | "wasm-bindgen-futures", 1674 | "web-sys", 1675 | "winreg", 1676 | ] 1677 | 1678 | [[package]] 1679 | name = "rusb" 1680 | version = "0.9.1" 1681 | source = "registry+https://github.com/rust-lang/crates.io-index" 1682 | checksum = "703aa035c21c589b34fb5136b12e68fc8dcf7ea46486861381361dd8ebf5cee0" 1683 | dependencies = [ 1684 | "libc", 1685 | "libusb1-sys", 1686 | ] 1687 | 1688 | [[package]] 1689 | name = "rustc-demangle" 1690 | version = "0.1.21" 1691 | source = "registry+https://github.com/rust-lang/crates.io-index" 1692 | checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" 1693 | 1694 | [[package]] 1695 | name = "rustc_version" 1696 | version = "0.4.0" 1697 | source = "registry+https://github.com/rust-lang/crates.io-index" 1698 | checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" 1699 | dependencies = [ 1700 | "semver", 1701 | ] 1702 | 1703 | [[package]] 1704 | name = "rustix" 1705 | version = "0.36.6" 1706 | source = "registry+https://github.com/rust-lang/crates.io-index" 1707 | checksum = "4feacf7db682c6c329c4ede12649cd36ecab0f3be5b7d74e6a20304725db4549" 1708 | dependencies = [ 1709 | "bitflags", 1710 | "errno", 1711 | "io-lifetimes", 1712 | "libc", 1713 | "linux-raw-sys", 1714 | "windows-sys", 1715 | ] 1716 | 1717 | [[package]] 1718 | name = "ryu" 1719 | version = "1.0.12" 1720 | source = "registry+https://github.com/rust-lang/crates.io-index" 1721 | checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" 1722 | 1723 | [[package]] 1724 | name = "sanitize-filename" 1725 | version = "0.4.0" 1726 | source = "registry+https://github.com/rust-lang/crates.io-index" 1727 | checksum = "08c502bdb638f1396509467cb0580ef3b29aa2a45c5d43e5d84928241280296c" 1728 | dependencies = [ 1729 | "lazy_static", 1730 | "regex", 1731 | ] 1732 | 1733 | [[package]] 1734 | name = "schannel" 1735 | version = "0.1.21" 1736 | source = "registry+https://github.com/rust-lang/crates.io-index" 1737 | checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" 1738 | dependencies = [ 1739 | "windows-sys", 1740 | ] 1741 | 1742 | [[package]] 1743 | name = "scopeguard" 1744 | version = "1.1.0" 1745 | source = "registry+https://github.com/rust-lang/crates.io-index" 1746 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 1747 | 1748 | [[package]] 1749 | name = "scratch" 1750 | version = "1.0.3" 1751 | source = "registry+https://github.com/rust-lang/crates.io-index" 1752 | checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" 1753 | 1754 | [[package]] 1755 | name = "scroll" 1756 | version = "0.10.2" 1757 | source = "registry+https://github.com/rust-lang/crates.io-index" 1758 | checksum = "fda28d4b4830b807a8b43f7b0e6b5df875311b3e7621d84577188c175b6ec1ec" 1759 | 1760 | [[package]] 1761 | name = "scroll" 1762 | version = "0.11.0" 1763 | source = "registry+https://github.com/rust-lang/crates.io-index" 1764 | checksum = "04c565b551bafbef4157586fa379538366e4385d42082f255bfd96e4fe8519da" 1765 | dependencies = [ 1766 | "scroll_derive", 1767 | ] 1768 | 1769 | [[package]] 1770 | name = "scroll_derive" 1771 | version = "0.11.0" 1772 | source = "registry+https://github.com/rust-lang/crates.io-index" 1773 | checksum = "bdbda6ac5cd1321e724fa9cee216f3a61885889b896f073b8f82322789c5250e" 1774 | dependencies = [ 1775 | "proc-macro2", 1776 | "quote", 1777 | "syn", 1778 | ] 1779 | 1780 | [[package]] 1781 | name = "security-framework" 1782 | version = "2.7.0" 1783 | source = "registry+https://github.com/rust-lang/crates.io-index" 1784 | checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c" 1785 | dependencies = [ 1786 | "bitflags", 1787 | "core-foundation", 1788 | "core-foundation-sys", 1789 | "libc", 1790 | "security-framework-sys", 1791 | ] 1792 | 1793 | [[package]] 1794 | name = "security-framework-sys" 1795 | version = "2.6.1" 1796 | source = "registry+https://github.com/rust-lang/crates.io-index" 1797 | checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" 1798 | dependencies = [ 1799 | "core-foundation-sys", 1800 | "libc", 1801 | ] 1802 | 1803 | [[package]] 1804 | name = "semver" 1805 | version = "1.0.16" 1806 | source = "registry+https://github.com/rust-lang/crates.io-index" 1807 | checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" 1808 | dependencies = [ 1809 | "serde", 1810 | ] 1811 | 1812 | [[package]] 1813 | name = "sentry" 1814 | version = "0.29.1" 1815 | source = "registry+https://github.com/rust-lang/crates.io-index" 1816 | checksum = "17ad137b9df78294b98cab1a650bef237cc6c950e82e5ce164655e674d07c5cc" 1817 | dependencies = [ 1818 | "httpdate", 1819 | "native-tls", 1820 | "reqwest", 1821 | "sentry-anyhow", 1822 | "sentry-backtrace", 1823 | "sentry-contexts", 1824 | "sentry-core", 1825 | "sentry-panic", 1826 | "tokio", 1827 | "ureq", 1828 | ] 1829 | 1830 | [[package]] 1831 | name = "sentry-anyhow" 1832 | version = "0.29.1" 1833 | source = "registry+https://github.com/rust-lang/crates.io-index" 1834 | checksum = "f55adcceaad4189af35d82c3c51613c0c372f15c25f42f70bf23c9c3ede223e1" 1835 | dependencies = [ 1836 | "anyhow", 1837 | "sentry-backtrace", 1838 | "sentry-core", 1839 | ] 1840 | 1841 | [[package]] 1842 | name = "sentry-backtrace" 1843 | version = "0.29.1" 1844 | source = "registry+https://github.com/rust-lang/crates.io-index" 1845 | checksum = "afe4800806552aab314129761d5d3b3d422284eca3de2ab59e9fd133636cbd3d" 1846 | dependencies = [ 1847 | "backtrace", 1848 | "once_cell", 1849 | "regex", 1850 | "sentry-core", 1851 | ] 1852 | 1853 | [[package]] 1854 | name = "sentry-contexts" 1855 | version = "0.29.1" 1856 | source = "registry+https://github.com/rust-lang/crates.io-index" 1857 | checksum = "a42938426670f6e7974989cd1417837a96dd8bbb01567094f567d6acb360bf88" 1858 | dependencies = [ 1859 | "hostname", 1860 | "libc", 1861 | "os_info", 1862 | "rustc_version", 1863 | "sentry-core", 1864 | "uname", 1865 | ] 1866 | 1867 | [[package]] 1868 | name = "sentry-core" 1869 | version = "0.29.1" 1870 | source = "registry+https://github.com/rust-lang/crates.io-index" 1871 | checksum = "4df9b9d8de2658a1ecd4e45f7b06c80c5dd97b891bfbc7c501186189b7e9bbdf" 1872 | dependencies = [ 1873 | "once_cell", 1874 | "rand", 1875 | "sentry-types", 1876 | "serde", 1877 | "serde_json", 1878 | ] 1879 | 1880 | [[package]] 1881 | name = "sentry-panic" 1882 | version = "0.29.1" 1883 | source = "registry+https://github.com/rust-lang/crates.io-index" 1884 | checksum = "0af37b8500f273e511ebd6eb0d342ff7937d64ce3f134764b2b4653112d48cb4" 1885 | dependencies = [ 1886 | "sentry-backtrace", 1887 | "sentry-core", 1888 | ] 1889 | 1890 | [[package]] 1891 | name = "sentry-types" 1892 | version = "0.29.1" 1893 | source = "registry+https://github.com/rust-lang/crates.io-index" 1894 | checksum = "ccc95faa4078768a6bf8df45e2b894bbf372b3dbbfb364e9429c1c58ab7545c6" 1895 | dependencies = [ 1896 | "debugid", 1897 | "getrandom", 1898 | "hex", 1899 | "serde", 1900 | "serde_json", 1901 | "thiserror", 1902 | "time 0.3.17", 1903 | "url", 1904 | "uuid", 1905 | ] 1906 | 1907 | [[package]] 1908 | name = "serde" 1909 | version = "1.0.152" 1910 | source = "registry+https://github.com/rust-lang/crates.io-index" 1911 | checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" 1912 | dependencies = [ 1913 | "serde_derive", 1914 | ] 1915 | 1916 | [[package]] 1917 | name = "serde_derive" 1918 | version = "1.0.152" 1919 | source = "registry+https://github.com/rust-lang/crates.io-index" 1920 | checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" 1921 | dependencies = [ 1922 | "proc-macro2", 1923 | "quote", 1924 | "syn", 1925 | ] 1926 | 1927 | [[package]] 1928 | name = "serde_json" 1929 | version = "1.0.91" 1930 | source = "registry+https://github.com/rust-lang/crates.io-index" 1931 | checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" 1932 | dependencies = [ 1933 | "itoa", 1934 | "ryu", 1935 | "serde", 1936 | ] 1937 | 1938 | [[package]] 1939 | name = "serde_urlencoded" 1940 | version = "0.7.1" 1941 | source = "registry+https://github.com/rust-lang/crates.io-index" 1942 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 1943 | dependencies = [ 1944 | "form_urlencoded", 1945 | "itoa", 1946 | "ryu", 1947 | "serde", 1948 | ] 1949 | 1950 | [[package]] 1951 | name = "serde_yaml" 1952 | version = "0.9.16" 1953 | source = "registry+https://github.com/rust-lang/crates.io-index" 1954 | checksum = "92b5b431e8907b50339b51223b97d102db8d987ced36f6e4d03621db9316c834" 1955 | dependencies = [ 1956 | "indexmap", 1957 | "itoa", 1958 | "ryu", 1959 | "serde", 1960 | "unsafe-libyaml", 1961 | ] 1962 | 1963 | [[package]] 1964 | name = "signal-hook" 1965 | version = "0.3.14" 1966 | source = "registry+https://github.com/rust-lang/crates.io-index" 1967 | checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d" 1968 | dependencies = [ 1969 | "libc", 1970 | "signal-hook-registry", 1971 | ] 1972 | 1973 | [[package]] 1974 | name = "signal-hook-mio" 1975 | version = "0.2.3" 1976 | source = "registry+https://github.com/rust-lang/crates.io-index" 1977 | checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" 1978 | dependencies = [ 1979 | "libc", 1980 | "mio", 1981 | "signal-hook", 1982 | ] 1983 | 1984 | [[package]] 1985 | name = "signal-hook-registry" 1986 | version = "1.4.0" 1987 | source = "registry+https://github.com/rust-lang/crates.io-index" 1988 | checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" 1989 | dependencies = [ 1990 | "libc", 1991 | ] 1992 | 1993 | [[package]] 1994 | name = "simplelog" 1995 | version = "0.12.0" 1996 | source = "registry+https://github.com/rust-lang/crates.io-index" 1997 | checksum = "48dfff04aade74dd495b007c831cd6f4e0cee19c344dd9dc0884c0289b70a786" 1998 | dependencies = [ 1999 | "log", 2000 | "termcolor", 2001 | "time 0.3.17", 2002 | ] 2003 | 2004 | [[package]] 2005 | name = "slab" 2006 | version = "0.4.7" 2007 | source = "registry+https://github.com/rust-lang/crates.io-index" 2008 | checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" 2009 | dependencies = [ 2010 | "autocfg", 2011 | ] 2012 | 2013 | [[package]] 2014 | name = "smallvec" 2015 | version = "1.10.0" 2016 | source = "registry+https://github.com/rust-lang/crates.io-index" 2017 | checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" 2018 | 2019 | [[package]] 2020 | name = "smawk" 2021 | version = "0.3.1" 2022 | source = "registry+https://github.com/rust-lang/crates.io-index" 2023 | checksum = "f67ad224767faa3c7d8b6d91985b78e70a1324408abcb1cfcc2be4c06bc06043" 2024 | 2025 | [[package]] 2026 | name = "socket2" 2027 | version = "0.4.7" 2028 | source = "registry+https://github.com/rust-lang/crates.io-index" 2029 | checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" 2030 | dependencies = [ 2031 | "libc", 2032 | "winapi", 2033 | ] 2034 | 2035 | [[package]] 2036 | name = "stable_deref_trait" 2037 | version = "1.2.0" 2038 | source = "registry+https://github.com/rust-lang/crates.io-index" 2039 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 2040 | 2041 | [[package]] 2042 | name = "static_assertions" 2043 | version = "1.1.0" 2044 | source = "registry+https://github.com/rust-lang/crates.io-index" 2045 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" 2046 | 2047 | [[package]] 2048 | name = "strsim" 2049 | version = "0.10.0" 2050 | source = "registry+https://github.com/rust-lang/crates.io-index" 2051 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 2052 | 2053 | [[package]] 2054 | name = "svg" 2055 | version = "0.13.0" 2056 | source = "registry+https://github.com/rust-lang/crates.io-index" 2057 | checksum = "e715e0c3fc987f4c435dc7189641fd9caa6919a74675ace605c38e201d278001" 2058 | 2059 | [[package]] 2060 | name = "syn" 2061 | version = "1.0.107" 2062 | source = "registry+https://github.com/rust-lang/crates.io-index" 2063 | checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" 2064 | dependencies = [ 2065 | "proc-macro2", 2066 | "quote", 2067 | "unicode-ident", 2068 | ] 2069 | 2070 | [[package]] 2071 | name = "tap" 2072 | version = "1.0.1" 2073 | source = "registry+https://github.com/rust-lang/crates.io-index" 2074 | checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" 2075 | 2076 | [[package]] 2077 | name = "tempfile" 2078 | version = "3.3.0" 2079 | source = "registry+https://github.com/rust-lang/crates.io-index" 2080 | checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" 2081 | dependencies = [ 2082 | "cfg-if", 2083 | "fastrand", 2084 | "libc", 2085 | "redox_syscall", 2086 | "remove_dir_all", 2087 | "winapi", 2088 | ] 2089 | 2090 | [[package]] 2091 | name = "termcolor" 2092 | version = "1.1.3" 2093 | source = "registry+https://github.com/rust-lang/crates.io-index" 2094 | checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" 2095 | dependencies = [ 2096 | "winapi-util", 2097 | ] 2098 | 2099 | [[package]] 2100 | name = "terminal_size" 2101 | version = "0.2.3" 2102 | source = "registry+https://github.com/rust-lang/crates.io-index" 2103 | checksum = "cb20089a8ba2b69debd491f8d2d023761cbf196e999218c591fa1e7e15a21907" 2104 | dependencies = [ 2105 | "rustix", 2106 | "windows-sys", 2107 | ] 2108 | 2109 | [[package]] 2110 | name = "textwrap" 2111 | version = "0.16.0" 2112 | source = "registry+https://github.com/rust-lang/crates.io-index" 2113 | checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" 2114 | dependencies = [ 2115 | "smawk", 2116 | "unicode-linebreak", 2117 | "unicode-width", 2118 | ] 2119 | 2120 | [[package]] 2121 | name = "thiserror" 2122 | version = "1.0.38" 2123 | source = "registry+https://github.com/rust-lang/crates.io-index" 2124 | checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" 2125 | dependencies = [ 2126 | "thiserror-impl", 2127 | ] 2128 | 2129 | [[package]] 2130 | name = "thiserror-impl" 2131 | version = "1.0.38" 2132 | source = "registry+https://github.com/rust-lang/crates.io-index" 2133 | checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" 2134 | dependencies = [ 2135 | "proc-macro2", 2136 | "quote", 2137 | "syn", 2138 | ] 2139 | 2140 | [[package]] 2141 | name = "time" 2142 | version = "0.1.45" 2143 | source = "registry+https://github.com/rust-lang/crates.io-index" 2144 | checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" 2145 | dependencies = [ 2146 | "libc", 2147 | "wasi 0.10.0+wasi-snapshot-preview1", 2148 | "winapi", 2149 | ] 2150 | 2151 | [[package]] 2152 | name = "time" 2153 | version = "0.3.17" 2154 | source = "registry+https://github.com/rust-lang/crates.io-index" 2155 | checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" 2156 | dependencies = [ 2157 | "itoa", 2158 | "libc", 2159 | "num_threads", 2160 | "serde", 2161 | "time-core", 2162 | "time-macros", 2163 | ] 2164 | 2165 | [[package]] 2166 | name = "time-core" 2167 | version = "0.1.0" 2168 | source = "registry+https://github.com/rust-lang/crates.io-index" 2169 | checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" 2170 | 2171 | [[package]] 2172 | name = "time-macros" 2173 | version = "0.2.6" 2174 | source = "registry+https://github.com/rust-lang/crates.io-index" 2175 | checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" 2176 | dependencies = [ 2177 | "time-core", 2178 | ] 2179 | 2180 | [[package]] 2181 | name = "tinyvec" 2182 | version = "1.6.0" 2183 | source = "registry+https://github.com/rust-lang/crates.io-index" 2184 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" 2185 | dependencies = [ 2186 | "tinyvec_macros", 2187 | ] 2188 | 2189 | [[package]] 2190 | name = "tinyvec_macros" 2191 | version = "0.1.0" 2192 | source = "registry+https://github.com/rust-lang/crates.io-index" 2193 | checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" 2194 | 2195 | [[package]] 2196 | name = "tokio" 2197 | version = "1.24.1" 2198 | source = "registry+https://github.com/rust-lang/crates.io-index" 2199 | checksum = "1d9f76183f91ecfb55e1d7d5602bd1d979e38a3a522fe900241cf195624d67ae" 2200 | dependencies = [ 2201 | "autocfg", 2202 | "bytes", 2203 | "libc", 2204 | "memchr", 2205 | "mio", 2206 | "num_cpus", 2207 | "pin-project-lite", 2208 | "socket2", 2209 | "windows-sys", 2210 | ] 2211 | 2212 | [[package]] 2213 | name = "tokio-native-tls" 2214 | version = "0.3.0" 2215 | source = "registry+https://github.com/rust-lang/crates.io-index" 2216 | checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" 2217 | dependencies = [ 2218 | "native-tls", 2219 | "tokio", 2220 | ] 2221 | 2222 | [[package]] 2223 | name = "tokio-util" 2224 | version = "0.7.4" 2225 | source = "registry+https://github.com/rust-lang/crates.io-index" 2226 | checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" 2227 | dependencies = [ 2228 | "bytes", 2229 | "futures-core", 2230 | "futures-sink", 2231 | "pin-project-lite", 2232 | "tokio", 2233 | "tracing", 2234 | ] 2235 | 2236 | [[package]] 2237 | name = "toml" 2238 | version = "0.5.10" 2239 | source = "registry+https://github.com/rust-lang/crates.io-index" 2240 | checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f" 2241 | dependencies = [ 2242 | "serde", 2243 | ] 2244 | 2245 | [[package]] 2246 | name = "tower-service" 2247 | version = "0.3.2" 2248 | source = "registry+https://github.com/rust-lang/crates.io-index" 2249 | checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" 2250 | 2251 | [[package]] 2252 | name = "tracing" 2253 | version = "0.1.37" 2254 | source = "registry+https://github.com/rust-lang/crates.io-index" 2255 | checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" 2256 | dependencies = [ 2257 | "cfg-if", 2258 | "log", 2259 | "pin-project-lite", 2260 | "tracing-attributes", 2261 | "tracing-core", 2262 | ] 2263 | 2264 | [[package]] 2265 | name = "tracing-attributes" 2266 | version = "0.1.23" 2267 | source = "registry+https://github.com/rust-lang/crates.io-index" 2268 | checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" 2269 | dependencies = [ 2270 | "proc-macro2", 2271 | "quote", 2272 | "syn", 2273 | ] 2274 | 2275 | [[package]] 2276 | name = "tracing-core" 2277 | version = "0.1.30" 2278 | source = "registry+https://github.com/rust-lang/crates.io-index" 2279 | checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" 2280 | dependencies = [ 2281 | "once_cell", 2282 | ] 2283 | 2284 | [[package]] 2285 | name = "try-lock" 2286 | version = "0.2.4" 2287 | source = "registry+https://github.com/rust-lang/crates.io-index" 2288 | checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" 2289 | 2290 | [[package]] 2291 | name = "tui" 2292 | version = "0.19.0" 2293 | source = "registry+https://github.com/rust-lang/crates.io-index" 2294 | checksum = "ccdd26cbd674007e649a272da4475fb666d3aa0ad0531da7136db6fab0e5bad1" 2295 | dependencies = [ 2296 | "bitflags", 2297 | "cassowary", 2298 | "crossterm", 2299 | "unicode-segmentation", 2300 | "unicode-width", 2301 | ] 2302 | 2303 | [[package]] 2304 | name = "uname" 2305 | version = "0.1.1" 2306 | source = "registry+https://github.com/rust-lang/crates.io-index" 2307 | checksum = "b72f89f0ca32e4db1c04e2a72f5345d59796d4866a1ee0609084569f73683dc8" 2308 | dependencies = [ 2309 | "libc", 2310 | ] 2311 | 2312 | [[package]] 2313 | name = "uncased" 2314 | version = "0.9.7" 2315 | source = "registry+https://github.com/rust-lang/crates.io-index" 2316 | checksum = "09b01702b0fd0b3fadcf98e098780badda8742d4f4a7676615cad90e8ac73622" 2317 | dependencies = [ 2318 | "version_check", 2319 | ] 2320 | 2321 | [[package]] 2322 | name = "unicode-bidi" 2323 | version = "0.3.8" 2324 | source = "registry+https://github.com/rust-lang/crates.io-index" 2325 | checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" 2326 | 2327 | [[package]] 2328 | name = "unicode-ident" 2329 | version = "1.0.6" 2330 | source = "registry+https://github.com/rust-lang/crates.io-index" 2331 | checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" 2332 | 2333 | [[package]] 2334 | name = "unicode-linebreak" 2335 | version = "0.1.4" 2336 | source = "registry+https://github.com/rust-lang/crates.io-index" 2337 | checksum = "c5faade31a542b8b35855fff6e8def199853b2da8da256da52f52f1316ee3137" 2338 | dependencies = [ 2339 | "hashbrown", 2340 | "regex", 2341 | ] 2342 | 2343 | [[package]] 2344 | name = "unicode-normalization" 2345 | version = "0.1.22" 2346 | source = "registry+https://github.com/rust-lang/crates.io-index" 2347 | checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" 2348 | dependencies = [ 2349 | "tinyvec", 2350 | ] 2351 | 2352 | [[package]] 2353 | name = "unicode-segmentation" 2354 | version = "1.10.0" 2355 | source = "registry+https://github.com/rust-lang/crates.io-index" 2356 | checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" 2357 | 2358 | [[package]] 2359 | name = "unicode-width" 2360 | version = "0.1.10" 2361 | source = "registry+https://github.com/rust-lang/crates.io-index" 2362 | checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" 2363 | 2364 | [[package]] 2365 | name = "unsafe-libyaml" 2366 | version = "0.2.5" 2367 | source = "registry+https://github.com/rust-lang/crates.io-index" 2368 | checksum = "bc7ed8ba44ca06be78ea1ad2c3682a43349126c8818054231ee6f4748012aed2" 2369 | 2370 | [[package]] 2371 | name = "ureq" 2372 | version = "2.6.1" 2373 | source = "registry+https://github.com/rust-lang/crates.io-index" 2374 | checksum = "733b5ad78377302af52c0dbcb2623d78fe50e4b3bf215948ff29e9ee031d8566" 2375 | dependencies = [ 2376 | "base64 0.13.1", 2377 | "log", 2378 | "native-tls", 2379 | "once_cell", 2380 | "url", 2381 | ] 2382 | 2383 | [[package]] 2384 | name = "url" 2385 | version = "2.3.1" 2386 | source = "registry+https://github.com/rust-lang/crates.io-index" 2387 | checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" 2388 | dependencies = [ 2389 | "form_urlencoded", 2390 | "idna", 2391 | "percent-encoding", 2392 | "serde", 2393 | ] 2394 | 2395 | [[package]] 2396 | name = "utf8-width" 2397 | version = "0.1.6" 2398 | source = "registry+https://github.com/rust-lang/crates.io-index" 2399 | checksum = "5190c9442dcdaf0ddd50f37420417d219ae5261bbf5db120d0f9bab996c9cba1" 2400 | 2401 | [[package]] 2402 | name = "uuid" 2403 | version = "1.2.2" 2404 | source = "registry+https://github.com/rust-lang/crates.io-index" 2405 | checksum = "422ee0de9031b5b948b97a8fc04e3aa35230001a722ddd27943e0be31564ce4c" 2406 | dependencies = [ 2407 | "getrandom", 2408 | "serde", 2409 | ] 2410 | 2411 | [[package]] 2412 | name = "vcpkg" 2413 | version = "0.2.15" 2414 | source = "registry+https://github.com/rust-lang/crates.io-index" 2415 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 2416 | 2417 | [[package]] 2418 | name = "version_check" 2419 | version = "0.9.4" 2420 | source = "registry+https://github.com/rust-lang/crates.io-index" 2421 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 2422 | 2423 | [[package]] 2424 | name = "want" 2425 | version = "0.3.0" 2426 | source = "registry+https://github.com/rust-lang/crates.io-index" 2427 | checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" 2428 | dependencies = [ 2429 | "log", 2430 | "try-lock", 2431 | ] 2432 | 2433 | [[package]] 2434 | name = "wasi" 2435 | version = "0.10.0+wasi-snapshot-preview1" 2436 | source = "registry+https://github.com/rust-lang/crates.io-index" 2437 | checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" 2438 | 2439 | [[package]] 2440 | name = "wasi" 2441 | version = "0.11.0+wasi-snapshot-preview1" 2442 | source = "registry+https://github.com/rust-lang/crates.io-index" 2443 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 2444 | 2445 | [[package]] 2446 | name = "wasm-bindgen" 2447 | version = "0.2.83" 2448 | source = "registry+https://github.com/rust-lang/crates.io-index" 2449 | checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" 2450 | dependencies = [ 2451 | "cfg-if", 2452 | "wasm-bindgen-macro", 2453 | ] 2454 | 2455 | [[package]] 2456 | name = "wasm-bindgen-backend" 2457 | version = "0.2.83" 2458 | source = "registry+https://github.com/rust-lang/crates.io-index" 2459 | checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" 2460 | dependencies = [ 2461 | "bumpalo", 2462 | "log", 2463 | "once_cell", 2464 | "proc-macro2", 2465 | "quote", 2466 | "syn", 2467 | "wasm-bindgen-shared", 2468 | ] 2469 | 2470 | [[package]] 2471 | name = "wasm-bindgen-futures" 2472 | version = "0.4.33" 2473 | source = "registry+https://github.com/rust-lang/crates.io-index" 2474 | checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" 2475 | dependencies = [ 2476 | "cfg-if", 2477 | "js-sys", 2478 | "wasm-bindgen", 2479 | "web-sys", 2480 | ] 2481 | 2482 | [[package]] 2483 | name = "wasm-bindgen-macro" 2484 | version = "0.2.83" 2485 | source = "registry+https://github.com/rust-lang/crates.io-index" 2486 | checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" 2487 | dependencies = [ 2488 | "quote", 2489 | "wasm-bindgen-macro-support", 2490 | ] 2491 | 2492 | [[package]] 2493 | name = "wasm-bindgen-macro-support" 2494 | version = "0.2.83" 2495 | source = "registry+https://github.com/rust-lang/crates.io-index" 2496 | checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" 2497 | dependencies = [ 2498 | "proc-macro2", 2499 | "quote", 2500 | "syn", 2501 | "wasm-bindgen-backend", 2502 | "wasm-bindgen-shared", 2503 | ] 2504 | 2505 | [[package]] 2506 | name = "wasm-bindgen-shared" 2507 | version = "0.2.83" 2508 | source = "registry+https://github.com/rust-lang/crates.io-index" 2509 | checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" 2510 | 2511 | [[package]] 2512 | name = "web-sys" 2513 | version = "0.3.60" 2514 | source = "registry+https://github.com/rust-lang/crates.io-index" 2515 | checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" 2516 | dependencies = [ 2517 | "js-sys", 2518 | "wasm-bindgen", 2519 | ] 2520 | 2521 | [[package]] 2522 | name = "winapi" 2523 | version = "0.3.9" 2524 | source = "registry+https://github.com/rust-lang/crates.io-index" 2525 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 2526 | dependencies = [ 2527 | "winapi-i686-pc-windows-gnu", 2528 | "winapi-x86_64-pc-windows-gnu", 2529 | ] 2530 | 2531 | [[package]] 2532 | name = "winapi-i686-pc-windows-gnu" 2533 | version = "0.4.0" 2534 | source = "registry+https://github.com/rust-lang/crates.io-index" 2535 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 2536 | 2537 | [[package]] 2538 | name = "winapi-util" 2539 | version = "0.1.5" 2540 | source = "registry+https://github.com/rust-lang/crates.io-index" 2541 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" 2542 | dependencies = [ 2543 | "winapi", 2544 | ] 2545 | 2546 | [[package]] 2547 | name = "winapi-x86_64-pc-windows-gnu" 2548 | version = "0.4.0" 2549 | source = "registry+https://github.com/rust-lang/crates.io-index" 2550 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 2551 | 2552 | [[package]] 2553 | name = "windows-sys" 2554 | version = "0.42.0" 2555 | source = "registry+https://github.com/rust-lang/crates.io-index" 2556 | checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" 2557 | dependencies = [ 2558 | "windows_aarch64_gnullvm", 2559 | "windows_aarch64_msvc", 2560 | "windows_i686_gnu", 2561 | "windows_i686_msvc", 2562 | "windows_x86_64_gnu", 2563 | "windows_x86_64_gnullvm", 2564 | "windows_x86_64_msvc", 2565 | ] 2566 | 2567 | [[package]] 2568 | name = "windows_aarch64_gnullvm" 2569 | version = "0.42.1" 2570 | source = "registry+https://github.com/rust-lang/crates.io-index" 2571 | checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" 2572 | 2573 | [[package]] 2574 | name = "windows_aarch64_msvc" 2575 | version = "0.42.1" 2576 | source = "registry+https://github.com/rust-lang/crates.io-index" 2577 | checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" 2578 | 2579 | [[package]] 2580 | name = "windows_i686_gnu" 2581 | version = "0.42.1" 2582 | source = "registry+https://github.com/rust-lang/crates.io-index" 2583 | checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" 2584 | 2585 | [[package]] 2586 | name = "windows_i686_msvc" 2587 | version = "0.42.1" 2588 | source = "registry+https://github.com/rust-lang/crates.io-index" 2589 | checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" 2590 | 2591 | [[package]] 2592 | name = "windows_x86_64_gnu" 2593 | version = "0.42.1" 2594 | source = "registry+https://github.com/rust-lang/crates.io-index" 2595 | checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" 2596 | 2597 | [[package]] 2598 | name = "windows_x86_64_gnullvm" 2599 | version = "0.42.1" 2600 | source = "registry+https://github.com/rust-lang/crates.io-index" 2601 | checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" 2602 | 2603 | [[package]] 2604 | name = "windows_x86_64_msvc" 2605 | version = "0.42.1" 2606 | source = "registry+https://github.com/rust-lang/crates.io-index" 2607 | checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" 2608 | 2609 | [[package]] 2610 | name = "winreg" 2611 | version = "0.10.1" 2612 | source = "registry+https://github.com/rust-lang/crates.io-index" 2613 | checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" 2614 | dependencies = [ 2615 | "winapi", 2616 | ] 2617 | 2618 | [[package]] 2619 | name = "wyz" 2620 | version = "0.5.1" 2621 | source = "registry+https://github.com/rust-lang/crates.io-index" 2622 | checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" 2623 | dependencies = [ 2624 | "tap", 2625 | ] 2626 | 2627 | [[package]] 2628 | name = "yansi" 2629 | version = "0.5.1" 2630 | source = "registry+https://github.com/rust-lang/crates.io-index" 2631 | checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" 2632 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cargo-embed" 3 | version = "0.13.0" 4 | authors = ["Noah Hüsser "] 5 | edition = "2018" 6 | description = "A utility to develop software for embedded ARM and RISC-V cores." 7 | documentation = "https://docs.rs/cargo-embed/" 8 | homepage = "https://github.com/probe-rs/cargo-embed" 9 | repository = "https://github.com/probe-rs/cargo-embed" 10 | readme = "README.md" 11 | categories = ["embedded", "hardware-support", "development-tools::debugging"] 12 | keywords = ["embedded"] 13 | license = "MIT OR Apache-2.0" 14 | 15 | [features] 16 | default = [] 17 | ftdi = ["probe-rs/ftdi"] 18 | sentry = ["probe-rs-cli-util/sentry"] 19 | 20 | [dependencies] 21 | probe-rs = { version = "0.13.0", git = "https://github.com/probe-rs/probe-rs" } 22 | gdb-server = { version = "0.13.0", git = "https://github.com/probe-rs/probe-rs" } 23 | probe-rs-cli-util = { version = "0.13.0", git = "https://github.com/probe-rs/probe-rs", default-features = false, features = [ 24 | "anyhow", 25 | ] } 26 | probe-rs-rtt = { version = "0.13.0", git = "https://github.com/probe-rs/probe-rs" } 27 | 28 | git-version = "0.3.5" 29 | env_logger = "0.10.0" 30 | log = { version = "0.4.17", features = ["serde"] } 31 | lazy_static = "1.4.0" 32 | colored = "2.0.0" 33 | serde = { version = "1.0", features = ["derive"] } 34 | serde_json = { version = "1.0.91" } 35 | figment = { version = "0.10", features = ["toml", "json", "yaml", "env"] } 36 | chrono = "0.4" 37 | crossterm = "<= 0.25.1" 38 | goblin = "0.6.0" 39 | tui = { version = "0.19.0", default-features = false, features = ["crossterm"] } 40 | anyhow = "1.0.68" 41 | textwrap = "0.16.0" 42 | defmt-decoder = { version = "0.3.3", features = ["unstable"] } 43 | sanitize-filename = "0.4" 44 | 45 | [build-dependencies] 46 | probe-rs-cli-util = { version = "0.13.0", git = "https://github.com/probe-rs/probe-rs", default-features = false, features = [ 47 | "anyhow", 48 | ] } 49 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 probe-rs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cargo-embed has moved repository 2 | 3 | cargo-embed is now part of the main probe-rs repository at https://github.com/probe-rs/probe-rs. 4 | 5 | This repository is not used anymore. 6 | 7 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | probe_rs_cli_util::meta::generate_meta(); 3 | println!("cargo:rerun-if-changed=build.rs"); 4 | } 5 | -------------------------------------------------------------------------------- /src/config/default.toml: -------------------------------------------------------------------------------- 1 | [default.probe] 2 | # USB vendor ID 3 | # usb_vid = "1337" 4 | # USB product ID 5 | # usb_pid = "1337" 6 | # Serial number 7 | # serial = "12345678" 8 | # The protocol to be used for communicating with the target. 9 | protocol = "Swd" 10 | # The speed in kHz of the data link to the target. 11 | # speed = 1337 12 | 13 | [default.flashing] 14 | # Whether or not the target should be flashed. 15 | enabled = true 16 | # Whether or not the target should be halted after reset. 17 | # DEPRECATED, moved to reset section 18 | halt_afterwards = false 19 | # Whether or not bytes erased but not rewritten with data from the ELF 20 | # should be restored with their contents before erasing. 21 | restore_unwritten_bytes = false 22 | # The path where an SVG of the assembled flash layout should be written to. 23 | # flash_layout_output_path = "out.svg" 24 | # Triggers a full chip erase instead of a page by page erase. 25 | do_chip_erase = false 26 | 27 | [default.reset] 28 | # Whether or not the target should be reset. 29 | # When flashing is enabled as well, the target will be reset after flashing. 30 | enabled = true 31 | # Whether or not the target should be halted after reset. 32 | halt_afterwards = false 33 | 34 | [default.general] 35 | # The chip name of the chip to be debugged. 36 | # chip = "name" 37 | # A list of chip descriptions to be loaded during runtime. 38 | chip_descriptions = [] 39 | # The default log level to be used. Possible values are one of: 40 | # "OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" 41 | log_level = "WARN" 42 | # Use this flag to assert the nreset & ntrst pins during attaching the probe to the chip. 43 | connect_under_reset = false 44 | 45 | [default.rtt] 46 | # Whether or not an RTTUI should be opened after flashing. 47 | enabled = false 48 | # How the target handles RTT outputs that won't fit in the buffer. This can be 49 | # overridden per-channel. If left unset, the firmware will determine the default 50 | # for each RTT up channel. 51 | # NoBlockSkip - Skip writing the data completely if it doesn't fit in its 52 | # entirety. 53 | # NoBlockTrim - Write as much as possible of the data and ignore the rest. 54 | # BlockIfFull - Spin until the host reads data. Can result in app freezing. 55 | # 56 | # up_mode = "BlockIfFull" 57 | 58 | # A list of channel associations to be displayed. If left empty, all channels are displayed. 59 | # up, down (Optional) - RTT channel numbers 60 | # name (Optional) - String to be displayed in the RTTUI tab 61 | # up_mode (Optional) - RTT channel specific as described above 62 | # format (Required) - How to interpret data from target firmware. One of: 63 | # String - Directly show output from the target 64 | # Defmt - Format output on the host, see https://defmt.ferrous-systems.com/ 65 | # BinaryLE - Display as raw hex 66 | channels = [ 67 | # { up = 0, down = 0, name = "name", up_mode = "BlockIfFull", format = "Defmt" }, 68 | ] 69 | # The duration in ms for which the logger should retry to attach to RTT. 70 | timeout = 3000 71 | # Whether timestamps in the RTTUI are enabled 72 | show_timestamps = true 73 | # Whether to save rtt history buffer on exit. 74 | log_enabled = false 75 | # Where to save rtt history buffer relative to manifest path. 76 | log_path = "./logs" 77 | 78 | [default.gdb] 79 | # Whether or not a GDB server should be opened after flashing. 80 | enabled = false 81 | # The connection string in host:port format wher the GDB server will open a socket. 82 | gdb_connection_string = "127.0.0.1:1337" 83 | -------------------------------------------------------------------------------- /src/config/mod.rs: -------------------------------------------------------------------------------- 1 | use crate::rttui::channel::ChannelConfig; 2 | use anyhow::bail; 3 | use figment::{ 4 | providers::{Format, Json, Toml, Yaml}, 5 | Figment, 6 | }; 7 | use probe_rs::WireProtocol; 8 | use probe_rs_rtt::ChannelMode; 9 | use serde::{Deserialize, Serialize}; 10 | use std::path::PathBuf; 11 | 12 | /// A struct which holds all configs. 13 | #[derive(Debug, Clone)] 14 | pub struct Configs { 15 | figment: Figment, 16 | } 17 | 18 | /// The main struct holding all the possible config options. 19 | #[derive(Debug, Deserialize, Serialize)] 20 | #[serde(deny_unknown_fields)] 21 | pub struct Config { 22 | pub general: General, 23 | pub flashing: Flashing, 24 | pub reset: Reset, 25 | pub probe: Probe, 26 | pub rtt: Rtt, 27 | pub gdb: Gdb, 28 | } 29 | 30 | /// The probe config struct holding all the possible probe options. 31 | #[derive(Debug, Deserialize, Serialize)] 32 | #[serde(deny_unknown_fields)] 33 | pub struct Probe { 34 | pub usb_vid: Option, 35 | pub usb_pid: Option, 36 | pub serial: Option, 37 | pub protocol: WireProtocol, 38 | pub speed: Option, 39 | } 40 | 41 | /// The flashing config struct holding all the possible flashing options. 42 | #[derive(Debug, Deserialize, Serialize)] 43 | #[serde(deny_unknown_fields)] 44 | pub struct Flashing { 45 | pub enabled: bool, 46 | #[deprecated( 47 | since = "0.9.0", 48 | note = "The 'halt_afterwards' key has moved to the 'reset' section" 49 | )] 50 | pub halt_afterwards: bool, 51 | pub restore_unwritten_bytes: bool, 52 | pub flash_layout_output_path: Option, 53 | pub do_chip_erase: bool, 54 | } 55 | 56 | /// The reset config struct holding all the possible reset options. 57 | #[derive(Debug, Deserialize, Serialize)] 58 | #[serde(deny_unknown_fields)] 59 | pub struct Reset { 60 | pub enabled: bool, 61 | pub halt_afterwards: bool, 62 | } 63 | 64 | /// The general config struct holding all the possible general options. 65 | #[derive(Debug, Deserialize, Serialize)] 66 | #[serde(deny_unknown_fields)] 67 | pub struct General { 68 | pub chip: Option, 69 | pub chip_descriptions: Vec, 70 | pub log_level: log::Level, 71 | pub derives: Option, 72 | /// Use this flag to assert the nreset & ntrst pins during attaching the probe to the chip. 73 | pub connect_under_reset: bool, 74 | } 75 | 76 | /// The rtt config struct holding all the possible rtt options. 77 | #[derive(Debug, Deserialize, Serialize)] 78 | #[serde(deny_unknown_fields)] 79 | pub struct Rtt { 80 | pub enabled: bool, 81 | /// Up mode, when not specified per-channel. Target picks if neither is set 82 | pub up_mode: Option, 83 | /// Channels to be displayed, and options for them 84 | pub channels: Vec, 85 | /// Connection timeout in ms. 86 | pub timeout: usize, 87 | /// Whether to show timestamps in RTTUI 88 | pub show_timestamps: bool, 89 | /// Whether to save rtt history buffer on exit to file named history.txt 90 | pub log_enabled: bool, 91 | /// Where to save rtt history buffer relative to manifest path. 92 | pub log_path: PathBuf, 93 | } 94 | 95 | /// The gdb config struct holding all the possible gdb options. 96 | #[derive(Debug, Deserialize, Serialize)] 97 | #[serde(deny_unknown_fields)] 98 | pub struct Gdb { 99 | pub enabled: bool, 100 | pub gdb_connection_string: Option, 101 | } 102 | 103 | impl Configs { 104 | pub fn new(conf_dir: PathBuf) -> Configs { 105 | // Start off by merging in the default configuration file. 106 | let mut figments = 107 | Figment::new().merge(Toml::string(include_str!("default.toml")).nested()); 108 | 109 | // Ordered list of config files, which are handled in the order specified here. 110 | let config_files = [ 111 | // The following files are intended to be project-specific and would normally be 112 | // included in a project's source repository. 113 | ".embed", 114 | "Embed", 115 | // The following files are intended to hold personal or exceptional settings, which 116 | // are not useful for other users, and would NOT normally be included in a project's 117 | // source repository. 118 | ".embed.local", 119 | "Embed.local", 120 | ]; 121 | 122 | for file in &config_files { 123 | let mut toml_path: std::path::PathBuf = conf_dir.clone(); 124 | toml_path.push(format!("{}.toml", file)); 125 | 126 | let mut json_path = conf_dir.clone(); 127 | json_path.push(format!("{}.json", file)); 128 | 129 | let mut yaml_path = conf_dir.clone(); 130 | yaml_path.push(format!("{}.yaml", file)); 131 | 132 | let mut yml_path = conf_dir.clone(); 133 | yml_path.push(format!("{}.yml", file)); 134 | 135 | figments = Figment::from(figments) 136 | .merge(Toml::file(toml_path).nested()) 137 | .merge(Json::file(json_path).nested()) 138 | .merge(Yaml::file(yaml_path).nested()) 139 | .merge(Yaml::file(yml_path).nested()); 140 | } 141 | Configs { figment: figments } 142 | } 143 | 144 | pub fn prof_names(&self) -> Vec { 145 | self.figment 146 | .profiles() 147 | .map(|p| String::from(p.as_str().as_str())) 148 | .collect() 149 | } 150 | 151 | /// Extract the requested config, but only if the profile has been explicity defined in the 152 | /// configuration files etc. (selecting an arbitrary undefined profile with Figment will coerce 153 | /// it into existance - inheriting from the default config). 154 | pub fn select_defined(self: Configs, name: &str) -> anyhow::Result { 155 | let defined_profiles = self.prof_names(); 156 | let requested_profile_defined: bool = defined_profiles 157 | .iter() 158 | .any(|p| p.to_lowercase() == name.to_lowercase()); 159 | 160 | let figext: figment::error::Result = self.figment.select(name).extract(); 161 | match figext { 162 | Err(figerr) => { 163 | // Join all the figment errors into a multiline string. 164 | bail!( 165 | "Failed to parse supplied configuration:\n{}", 166 | figerr 167 | .into_iter() 168 | .map(|e| e.to_string()) 169 | .collect::>() 170 | .join("\n") 171 | ); 172 | } 173 | Ok(config) => { 174 | // Gross errors (e.g. config file syntax problems) have already been caught by the 175 | // other match arm. Guard against Figment coercing previously undefined profiles 176 | // into existance. 177 | if !requested_profile_defined { 178 | bail!( 179 | "the requested configuration profile \"{}\" hasn't been defined (defined profiles: {})", 180 | name, 181 | defined_profiles.join(", ") 182 | ); 183 | } 184 | Ok(config) 185 | } 186 | } 187 | } 188 | #[cfg(test)] 189 | pub fn new_with_test_data(conf_dir: PathBuf) -> Configs { 190 | let mut cfs = Configs::new(conf_dir); 191 | cfs.figment = cfs.figment.merge( 192 | Toml::string( 193 | r#" 194 | [default] 195 | bogusInvalidItem = "oops" 196 | "#, 197 | ) 198 | .nested(), 199 | ); 200 | cfs 201 | } 202 | } 203 | 204 | #[cfg(test)] 205 | mod test { 206 | use super::Configs; 207 | 208 | #[test] 209 | fn default_profile() { 210 | // Ensure the default config can be parsed. 211 | let configs = Configs::new(std::env::current_dir().unwrap()); 212 | let _config = configs.select_defined("default").unwrap(); 213 | } 214 | #[test] 215 | fn non_existant_profile_is_error() { 216 | // Selecting a non-existant profile. 217 | let configs = Configs::new(std::env::current_dir().unwrap()); 218 | let _noprofile = configs.select_defined("nonexxistantprofle").unwrap_err(); 219 | } 220 | #[test] 221 | fn unknown_config_items_in_config_fail() { 222 | // Selecting a profile with an invalid item. 223 | let configs = Configs::new_with_test_data(std::env::current_dir().unwrap()); 224 | let _superfluous: anyhow::Error = configs.select_defined("default").unwrap_err(); 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /src/error.rs: -------------------------------------------------------------------------------- 1 | use probe_rs::{architecture::arm::ap::AccessPortError, DebugProbeError}; 2 | use std::error::Error; 3 | use std::fmt; 4 | 5 | #[derive(Debug)] 6 | pub enum DownloadError { 7 | DebugProbe(DebugProbeError), 8 | AccessPort(AccessPortError), 9 | StdIO(std::io::Error), 10 | } 11 | 12 | impl Error for DownloadError { 13 | fn source(&self) -> Option<&(dyn Error + 'static)> { 14 | use DownloadError::*; 15 | 16 | match self { 17 | DebugProbe(ref e) => Some(e), 18 | AccessPort(ref e) => Some(e), 19 | StdIO(ref e) => Some(e), 20 | } 21 | } 22 | } 23 | 24 | impl fmt::Display for DownloadError { 25 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 26 | use DownloadError::*; 27 | 28 | match self { 29 | DebugProbe(ref e) => e.fmt(f), 30 | AccessPort(ref e) => e.fmt(f), 31 | StdIO(ref e) => e.fmt(f), 32 | } 33 | } 34 | } 35 | 36 | impl From for DownloadError { 37 | fn from(error: AccessPortError) -> Self { 38 | DownloadError::AccessPort(error) 39 | } 40 | } 41 | 42 | impl From for DownloadError { 43 | fn from(error: DebugProbeError) -> Self { 44 | DownloadError::DebugProbe(error) 45 | } 46 | } 47 | 48 | impl From for DownloadError { 49 | fn from(error: std::io::Error) -> Self { 50 | DownloadError::StdIO(error) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | mod config; 2 | mod error; 3 | mod rttui; 4 | 5 | include!(concat!(env!("OUT_DIR"), "/meta.rs")); 6 | 7 | use anyhow::{anyhow, Context, Result}; 8 | use chrono::Local; 9 | use colored::*; 10 | use std::{ 11 | env, fs, 12 | fs::File, 13 | io::Write, 14 | panic, 15 | path::Path, 16 | process, 17 | sync::{Arc, Mutex}, 18 | time::{Duration, Instant}, 19 | }; 20 | 21 | use probe_rs::{ 22 | config::TargetSelector, 23 | flashing::{download_file_with_options, DownloadOptions, FlashProgress, Format, ProgressEvent}, 24 | DebugProbeSelector, Permissions, Probe, 25 | }; 26 | #[cfg(feature = "sentry")] 27 | use probe_rs_cli_util::logging::{ask_to_log_crash, capture_anyhow, capture_panic}; 28 | 29 | use probe_rs_cli_util::{ 30 | build_artifact, 31 | clap::{self, Parser}, 32 | common_options::CargoOptions, 33 | indicatif::{MultiProgress, ProgressBar, ProgressStyle}, 34 | logging::{self, Metadata}, 35 | }; 36 | 37 | use probe_rs_rtt::{Rtt, ScanRegion}; 38 | 39 | use probe_rs_gdb_server::GdbInstanceConfiguration; 40 | 41 | use crate::rttui::channel::DataFormat; 42 | 43 | lazy_static::lazy_static! { 44 | static ref METADATA: Arc> = Arc::new(Mutex::new(Metadata { 45 | release: meta::CARGO_VERSION.to_string(), 46 | chip: None, 47 | probe: None, 48 | speed: None, 49 | commit: meta::GIT_VERSION.to_string() 50 | })); 51 | } 52 | 53 | #[derive(Debug, clap::Parser)] 54 | #[clap( 55 | name = "cargo embed", 56 | author = "Noah Hüsser / Dominik Böhi ", 57 | version = meta::CARGO_VERSION, 58 | long_version = meta::LONG_VERSION 59 | )] 60 | struct Opt { 61 | #[clap(name = "config")] 62 | config: Option, 63 | #[clap(name = "chip", long = "chip")] 64 | chip: Option, 65 | #[clap( 66 | long = "probe", 67 | help = "Use this flag to select a specific probe in the list.\n\ 68 | Use '--probe VID:PID' or '--probe VID:PID:Serial' if you have more than one probe with the same VID:PID." 69 | )] 70 | probe_selector: Option, 71 | #[clap(name = "list-chips", long = "list-chips")] 72 | list_chips: bool, 73 | #[clap(name = "disable-progressbars", long = "disable-progressbars")] 74 | disable_progressbars: bool, 75 | #[clap(flatten)] 76 | cargo_options: CargoOptions, 77 | } 78 | 79 | fn main() { 80 | let next = panic::take_hook(); 81 | panic::set_hook(Box::new(move |info| { 82 | #[cfg(feature = "sentry")] 83 | if ask_to_log_crash() { 84 | capture_panic(&METADATA.lock().unwrap(), info) 85 | } 86 | #[cfg(not(feature = "sentry"))] 87 | log::info!("{:#?}", &METADATA.lock().unwrap()); 88 | next(info); 89 | })); 90 | 91 | match main_try() { 92 | Ok(_) => (), 93 | Err(e) => { 94 | // Ensure stderr is flushed before calling proces::exit, 95 | // otherwise the process might panic, because it tries 96 | // to access stderr during shutdown. 97 | // 98 | // We ignore the errors, not much we can do anyway. 99 | 100 | let mut stderr = std::io::stderr(); 101 | 102 | let first_line_prefix = "Error".red().bold(); 103 | let other_line_prefix: String = " ".repeat(first_line_prefix.chars().count()); 104 | 105 | let error = format!("{:?}", e); 106 | 107 | for (i, line) in error.lines().enumerate() { 108 | let _ = write!(stderr, " "); 109 | 110 | if i == 0 { 111 | let _ = write!(stderr, "{}", first_line_prefix); 112 | } else { 113 | let _ = write!(stderr, "{}", other_line_prefix); 114 | }; 115 | 116 | let _ = writeln!(stderr, " {}", line); 117 | } 118 | 119 | let _ = stderr.flush(); 120 | 121 | #[cfg(feature = "sentry")] 122 | if ask_to_log_crash() { 123 | capture_anyhow(&METADATA.lock().unwrap(), &e) 124 | } 125 | #[cfg(not(feature = "sentry"))] 126 | log::info!("{:#?}", &METADATA.lock().unwrap()); 127 | 128 | process::exit(1); 129 | } 130 | } 131 | } 132 | 133 | fn main_try() -> Result<()> { 134 | let mut args = std::env::args(); 135 | 136 | // When called by Cargo, the first argument after the binary name will be `embed`. If that's the 137 | // case, remove one argument (`Opt::from_iter` will remove the binary name by itself). 138 | if env::args().nth(1) == Some("embed".to_string()) { 139 | args.next(); 140 | } 141 | 142 | let mut args: Vec<_> = args.collect(); 143 | 144 | // Get commandline options. 145 | let opt = Opt::parse_from(&args); 146 | 147 | let work_dir = std::env::current_dir()?; 148 | 149 | // Get the config. 150 | let config_name = opt.config.as_deref().unwrap_or("default"); 151 | let configs = config::Configs::new(work_dir.clone()); 152 | let config = configs.select_defined(config_name)?; 153 | 154 | logging::init(Some(config.general.log_level)); 155 | 156 | // Make sure we load the config given in the cli parameters. 157 | for cdp in &config.general.chip_descriptions { 158 | probe_rs::config::add_target_from_yaml(Path::new(cdp)) 159 | .with_context(|| format!("failed to load the chip description from {}", cdp))?; 160 | } 161 | 162 | let chip = if opt.list_chips { 163 | print_families()?; 164 | std::process::exit(0); 165 | } else { 166 | opt.chip 167 | .or_else(|| config.general.chip.clone()) 168 | .map(|chip| chip.into()) 169 | .unwrap_or(TargetSelector::Auto) 170 | }; 171 | 172 | METADATA.lock().unwrap().chip = Some(format!("{:?}", chip)); 173 | 174 | // Remove executable name from the arguments list. 175 | args.remove(0); 176 | 177 | if let Some(index) = args.iter().position(|x| x == config_name) { 178 | // We remove the argument we found. 179 | args.remove(index); 180 | } 181 | 182 | let cargo_options = opt.cargo_options.to_cargo_options(); 183 | 184 | let artifact = build_artifact(&work_dir, &cargo_options)?; 185 | 186 | let path = artifact.path(); 187 | 188 | // Get the binary name (without extension) from the build artifact path 189 | let name = path.file_stem().and_then(|f| f.to_str()).ok_or_else(|| { 190 | anyhow!( 191 | "Unable to determine binary file name from path {}", 192 | path.display() 193 | ) 194 | })?; 195 | 196 | logging::println(format!(" {} {}", "Config".green().bold(), config_name)); 197 | logging::println(format!( 198 | " {} {}", 199 | "Target".green().bold(), 200 | path.display() 201 | )); 202 | 203 | // If we got a probe selector in the config, open the probe matching the selector if possible. 204 | let mut probe = if let Some(selector) = opt.probe_selector { 205 | Probe::open(selector)? 206 | } else { 207 | match (config.probe.usb_vid.as_ref(), config.probe.usb_pid.as_ref()) { 208 | (Some(vid), Some(pid)) => { 209 | let selector = DebugProbeSelector { 210 | vendor_id: u16::from_str_radix(vid, 16)?, 211 | product_id: u16::from_str_radix(pid, 16)?, 212 | serial_number: config.probe.serial.clone(), 213 | }; 214 | // if two probes with the same VID:PID pair exist we just choose one 215 | Probe::open(selector)? 216 | } 217 | _ => { 218 | if config.probe.usb_vid.is_some() { 219 | log::warn!("USB VID ignored, because PID is not specified."); 220 | } 221 | if config.probe.usb_pid.is_some() { 222 | log::warn!("USB PID ignored, because VID is not specified."); 223 | } 224 | 225 | // Only automatically select a probe if there is only 226 | // a single probe detected. 227 | let list = Probe::list_all(); 228 | if list.len() > 1 { 229 | return Err(anyhow!("The following devices were found:\n \ 230 | {} \ 231 | \ 232 | Use '--probe VID:PID'\n \ 233 | \ 234 | You can also set the [default.probe] config attribute \ 235 | (in your Embed.toml) to select which probe to use. \ 236 | For usage examples see https://github.com/probe-rs/cargo-embed/blob/master/src/config/default.toml .", 237 | list.iter().enumerate().map(|(num, link)| format!("[{}]: {:?}\n", num, link)).collect::())); 238 | } 239 | Probe::open( 240 | list.first() 241 | .map(|info| { 242 | METADATA.lock().unwrap().probe = Some(format!("{:?}", info.probe_type)); 243 | info 244 | }) 245 | .ok_or_else(|| anyhow!("No supported probe was found"))?, 246 | )? 247 | } 248 | } 249 | }; 250 | 251 | probe 252 | .select_protocol(config.probe.protocol) 253 | .context("failed to select protocol")?; 254 | 255 | let protocol_speed = if let Some(speed) = config.probe.speed { 256 | let actual_speed = probe.set_speed(speed).context("failed to set speed")?; 257 | 258 | if actual_speed < speed { 259 | log::warn!( 260 | "Unable to use specified speed of {} kHz, actual speed used is {} kHz", 261 | speed, 262 | actual_speed 263 | ); 264 | } 265 | 266 | actual_speed 267 | } else { 268 | probe.speed_khz() 269 | }; 270 | 271 | METADATA.lock().unwrap().speed = Some(format!("{:?}", protocol_speed)); 272 | 273 | log::info!("Protocol speed {} kHz", protocol_speed); 274 | 275 | let permissions = if config.flashing.enabled || config.gdb.enabled { 276 | Permissions::new().allow_erase_all() 277 | } else { 278 | Permissions::new() 279 | }; 280 | 281 | let mut session = if config.general.connect_under_reset { 282 | probe 283 | .attach_under_reset(chip, permissions) 284 | .context("failed attaching to target")? 285 | } else { 286 | let potential_session = probe.attach(chip, permissions); 287 | match potential_session { 288 | Ok(session) => session, 289 | Err(err) => { 290 | log::info!("The target seems to be unable to be attached to."); 291 | log::info!( 292 | "A hard reset during attaching might help. This will reset the entire chip." 293 | ); 294 | log::info!("Set `general.connect_under_reset` in your cargo-embed configuration file to enable this feature."); 295 | return Err(err).context("failed attaching to target"); 296 | } 297 | } 298 | }; 299 | 300 | if config.flashing.enabled { 301 | // Start timer. 302 | let instant = Instant::now(); 303 | 304 | if !opt.disable_progressbars { 305 | // Create progress bars. 306 | let multi_progress = MultiProgress::new(); 307 | let style = ProgressStyle::default_bar() 308 | .tick_chars("⠁⠁⠉⠙⠚⠒⠂⠂⠒⠲⠴⠤⠄⠄⠤⠠⠠⠤⠦⠖⠒⠐⠐⠒⠓⠋⠉⠈⠈✔") 309 | .progress_chars("##-") 310 | .template("{msg:.green.bold} {spinner} [{elapsed_precise}] [{wide_bar}] {bytes:>8}/{total_bytes:>8} @ {bytes_per_sec:>10} (eta {eta:3})")?; 311 | 312 | // Create a new progress bar for the fill progress if filling is enabled. 313 | let fill_progress = if config.flashing.restore_unwritten_bytes { 314 | let fill_progress = Arc::new(multi_progress.add(ProgressBar::new(0))); 315 | fill_progress.set_style(style.clone()); 316 | fill_progress.set_message(" Reading flash "); 317 | Some(fill_progress) 318 | } else { 319 | None 320 | }; 321 | 322 | // Create a new progress bar for the erase progress. 323 | let erase_progress = Arc::new(multi_progress.add(ProgressBar::new(0))); 324 | { 325 | logging::set_progress_bar(erase_progress.clone()); 326 | } 327 | erase_progress.set_style(style.clone()); 328 | erase_progress.set_message(" Erasing sectors"); 329 | 330 | // Create a new progress bar for the program progress. 331 | let program_progress = multi_progress.add(ProgressBar::new(0)); 332 | program_progress.set_style(style); 333 | program_progress.set_message(" Programming pages "); 334 | 335 | let flash_layout_output_path = config.flashing.flash_layout_output_path.clone(); 336 | // Register callback to update the progress. 337 | let progress = FlashProgress::new(move |event| { 338 | use ProgressEvent::*; 339 | match event { 340 | Initialized { flash_layout } => { 341 | let total_page_size: u32 = 342 | flash_layout.pages().iter().map(|s| s.size()).sum(); 343 | let total_sector_size: u64 = 344 | flash_layout.sectors().iter().map(|s| s.size()).sum(); 345 | let total_fill_size: u64 = 346 | flash_layout.fills().iter().map(|s| s.size()).sum(); 347 | if let Some(fp) = fill_progress.as_ref() { 348 | fp.set_length(total_fill_size) 349 | } 350 | erase_progress.set_length(total_sector_size); 351 | program_progress.set_length(total_page_size as u64); 352 | let visualizer = flash_layout.visualize(); 353 | flash_layout_output_path 354 | .as_ref() 355 | .map(|path| visualizer.write_svg(path)); 356 | } 357 | StartedProgramming => { 358 | program_progress.enable_steady_tick(Duration::from_millis(100)); 359 | program_progress.reset_elapsed(); 360 | } 361 | StartedErasing => { 362 | erase_progress.enable_steady_tick(Duration::from_millis(100)); 363 | erase_progress.reset_elapsed(); 364 | } 365 | StartedFilling => { 366 | if let Some(fp) = fill_progress.as_ref() { 367 | fp.enable_steady_tick(Duration::from_millis(100)) 368 | }; 369 | if let Some(fp) = fill_progress.as_ref() { 370 | fp.reset_elapsed() 371 | }; 372 | } 373 | PageProgrammed { size, .. } => { 374 | program_progress.inc(size as u64); 375 | } 376 | SectorErased { size, .. } => { 377 | erase_progress.inc(size); 378 | } 379 | PageFilled { size, .. } => { 380 | if let Some(fp) = fill_progress.as_ref() { 381 | fp.inc(size) 382 | }; 383 | } 384 | FailedErasing => { 385 | erase_progress.abandon(); 386 | program_progress.abandon(); 387 | } 388 | FinishedErasing => { 389 | erase_progress.finish(); 390 | } 391 | FailedProgramming => { 392 | program_progress.abandon(); 393 | } 394 | FinishedProgramming => { 395 | program_progress.finish(); 396 | } 397 | FailedFilling => { 398 | if let Some(fp) = fill_progress.as_ref() { 399 | fp.abandon() 400 | }; 401 | } 402 | FinishedFilling => { 403 | if let Some(fp) = fill_progress.as_ref() { 404 | fp.finish() 405 | }; 406 | } 407 | } 408 | }); 409 | 410 | let mut options = DownloadOptions::new(); 411 | 412 | options.progress = Some(&progress); 413 | options.keep_unwritten_bytes = config.flashing.restore_unwritten_bytes; 414 | options.do_chip_erase = config.flashing.do_chip_erase; 415 | 416 | download_file_with_options(&mut session, path, Format::Elf, options) 417 | .with_context(|| format!("failed to flash {}", path.display()))?; 418 | 419 | // If we don't do this, the inactive progress bars will swallow log 420 | // messages, so they'll never be printed anywhere. 421 | logging::clear_progress_bar(); 422 | } else { 423 | let mut options = DownloadOptions::new(); 424 | options.keep_unwritten_bytes = config.flashing.restore_unwritten_bytes; 425 | options.do_chip_erase = config.flashing.do_chip_erase; 426 | 427 | download_file_with_options(&mut session, path, Format::Elf, options) 428 | .with_context(|| format!("failed to flash {}", path.display()))?; 429 | } 430 | 431 | // Stop timer. 432 | let elapsed = instant.elapsed(); 433 | logging::println(format!( 434 | " {} flashing in {}s", 435 | "Finished".green().bold(), 436 | elapsed.as_millis() as f32 / 1000.0, 437 | )); 438 | } 439 | 440 | if config.reset.enabled { 441 | let mut core = session.core(0)?; 442 | let halt_timeout = Duration::from_millis(500); 443 | #[allow(deprecated)] // Remove in 0.10 444 | if config.flashing.halt_afterwards { 445 | logging::eprintln(format!( 446 | " {} The 'flashing.halt_afterwards' option in the config has moved to the 'reset' section", 447 | "Warning".yellow().bold() 448 | )); 449 | core.reset_and_halt(halt_timeout)?; 450 | } else if config.reset.halt_afterwards { 451 | core.reset_and_halt(halt_timeout)?; 452 | } else { 453 | core.reset()?; 454 | } 455 | } 456 | 457 | let session = Arc::new(Mutex::new(session)); 458 | 459 | let mut gdb_thread_handle = None; 460 | if config.gdb.enabled { 461 | let gdb_connection_string = config.gdb.gdb_connection_string.clone(); 462 | let session = session.clone(); 463 | gdb_thread_handle = Some(std::thread::spawn(move || { 464 | let gdb_connection_string = gdb_connection_string.as_deref().or(Some("127.0.0.1:1337")); 465 | // This next unwrap will always resolve as the connection string is always Some(T). 466 | logging::println(format!( 467 | " {} listening at {}", 468 | "GDB stub".green().bold(), 469 | gdb_connection_string.as_ref().unwrap(), 470 | )); 471 | let instances = { 472 | let session = session.lock().unwrap(); 473 | GdbInstanceConfiguration::from_session(&session, gdb_connection_string) 474 | }; 475 | if let Err(e) = probe_rs_gdb_server::run(&session, instances.iter()) { 476 | logging::eprintln("During the execution of GDB an error was encountered:"); 477 | logging::eprintln(format!("{:?}", e)); 478 | } 479 | })); 480 | } 481 | if config.rtt.enabled { 482 | let defmt_enable = config 483 | .rtt 484 | .channels 485 | .iter() 486 | .any(|elem| elem.format == DataFormat::Defmt); 487 | let defmt_state = if defmt_enable { 488 | let elf = fs::read(path).unwrap(); 489 | if let Some(table) = defmt_decoder::Table::parse(&elf)? { 490 | let locs = { 491 | let locs = table.get_locations(&elf)?; 492 | 493 | if !table.is_empty() && locs.is_empty() { 494 | log::warn!("Insufficient DWARF info; compile your program with `debug = 2` to enable location info."); 495 | None 496 | } else if table.indices().all(|idx| locs.contains_key(&(idx as u64))) { 497 | Some(locs) 498 | } else { 499 | log::warn!( 500 | "Location info is incomplete; it will be omitted from the output." 501 | ); 502 | None 503 | } 504 | }; 505 | Some((table, locs)) 506 | } else { 507 | log::error!("Defmt enabled in rtt channel config, but defmt table couldn't be loaded from binary."); 508 | None 509 | } 510 | } else { 511 | None 512 | }; 513 | 514 | let t = std::time::Instant::now(); 515 | let mut error = None; 516 | 517 | let mut i = 1; 518 | 519 | while (t.elapsed().as_millis() as usize) < config.rtt.timeout { 520 | log::info!("Initializing RTT (attempt {})...", i); 521 | i += 1; 522 | 523 | let rtt_header_address = if let Ok(mut file) = File::open(path) { 524 | if let Some(address) = rttui::app::App::get_rtt_symbol(&mut file) { 525 | ScanRegion::Exact(address as u32) 526 | } else { 527 | ScanRegion::Ram 528 | } 529 | } else { 530 | ScanRegion::Ram 531 | }; 532 | 533 | let mut session_handle = session.lock().unwrap(); 534 | let memory_map = session_handle.target().memory_map.clone(); 535 | let mut core = session_handle.core(0)?; 536 | 537 | match Rtt::attach_region(&mut core, &memory_map, &rtt_header_address) { 538 | Ok(mut rtt) => { 539 | // RTT supports three different "modes" for channels, which 540 | // describe how the firmware should handle writes that won't 541 | // fit in the available buffer. The config file can 542 | // optionally specify a mode to use for all up channels, 543 | // and/or a mode for specific channels. 544 | let default_up_mode = config.rtt.up_mode; 545 | 546 | for up_channel in rtt.up_channels().iter() { 547 | let mut specific_mode = None; 548 | for channel_config in config 549 | .rtt 550 | .channels 551 | .iter() 552 | .filter(|ch_conf| ch_conf.up == Some(up_channel.number())) 553 | { 554 | if let Some(mode) = channel_config.up_mode { 555 | if specific_mode.is_some() 556 | && specific_mode != channel_config.up_mode 557 | { 558 | // Can't safely resolve this generally... 559 | return Err(anyhow!("Conflicting modes specified for RTT up channel {}: {:?} and {:?}", 560 | up_channel.number(), specific_mode.unwrap(), mode)); 561 | } 562 | 563 | specific_mode = Some(mode); 564 | } 565 | } 566 | 567 | if let Some(mode) = specific_mode.or(default_up_mode) { 568 | // Only set the mode when the config file says to, 569 | // when not set explicitly, the firmware picks. 570 | log::debug!( 571 | "Setting RTT channel {} to {:?}", 572 | up_channel.number(), 573 | &mode 574 | ); 575 | up_channel.set_mode(&mut core, mode)?; 576 | } 577 | } 578 | 579 | drop(core); 580 | drop(session_handle); 581 | log::info!("RTT initialized."); 582 | 583 | // `App` puts the terminal into a special state, as required 584 | // by the text-based UI. If a panic happens while the 585 | // terminal is in that state, this will completely mess up 586 | // the user's terminal (misformatted panic message, newlines 587 | // being ignored, input characters not being echoed, ...). 588 | // 589 | // The following panic hook cleans up the terminal, while 590 | // otherwise preserving the behavior of the default panic 591 | // hook (or whichever custom hook might have been registered 592 | // before). 593 | let previous_panic_hook = panic::take_hook(); 594 | panic::set_hook(Box::new(move |panic_info| { 595 | rttui::app::clean_up_terminal(); 596 | previous_panic_hook(panic_info); 597 | })); 598 | 599 | let chip_name = config.general.chip.as_deref().unwrap_or_default(); 600 | let logname = 601 | format!("{}_{}_{}", name, chip_name, Local::now().timestamp_millis()); 602 | let mut app = rttui::app::App::new(rtt, &config, logname)?; 603 | loop { 604 | let mut session_handle = session.lock().unwrap(); 605 | let mut core = session_handle.core(0)?; 606 | app.poll_rtt(&mut core); 607 | app.render(&defmt_state); 608 | if app.handle_event(&mut core) { 609 | logging::println("Shutting down."); 610 | return Ok(()); 611 | }; 612 | std::thread::sleep(Duration::from_millis(10)); 613 | } 614 | } 615 | Err(err) => { 616 | error = Some(anyhow!("Error attaching to RTT: {}", err)); 617 | } 618 | }; 619 | 620 | log::debug!("Failed to initialize RTT. Retrying until timeout."); 621 | } 622 | if let Some(error) = error { 623 | return Err(error); 624 | } 625 | } 626 | 627 | if let Some(gdb_thread_handle) = gdb_thread_handle { 628 | let _ = gdb_thread_handle.join(); 629 | } 630 | 631 | logging::println(format!( 632 | " {} processing config {}", 633 | "Done".green().bold(), 634 | config_name 635 | )); 636 | 637 | Ok(()) 638 | } 639 | 640 | fn print_families() -> Result<()> { 641 | logging::println("Available chips:"); 642 | for family in 643 | probe_rs::config::families().map_err(|e| anyhow!("Families could not be read: {:?}", e))? 644 | { 645 | logging::println(&family.name); 646 | logging::println(" Variants:"); 647 | for variant in family.variants() { 648 | logging::println(format!(" {}", variant.name)); 649 | } 650 | } 651 | Ok(()) 652 | } 653 | -------------------------------------------------------------------------------- /src/rttui/app.rs: -------------------------------------------------------------------------------- 1 | use anyhow::{anyhow, Context, Result}; 2 | use crossterm::{ 3 | event::{self, KeyCode}, 4 | execute, 5 | terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, 6 | }; 7 | use probe_rs::Core; 8 | use probe_rs_rtt::RttChannel; 9 | use std::{fmt::write, path::PathBuf, sync::mpsc::RecvTimeoutError}; 10 | use std::{ 11 | io::{Read, Seek, Write}, 12 | time::Duration, 13 | }; 14 | use tui::{ 15 | backend::CrosstermBackend, 16 | layout::{Constraint, Direction, Layout}, 17 | style::{Color, Modifier, Style}, 18 | text::{Span, Spans}, 19 | widgets::{Block, Borders, List, ListItem, Paragraph, Tabs}, 20 | Terminal, 21 | }; 22 | 23 | use super::{ 24 | channel::{ChannelState, DataFormat}, 25 | event::Events, 26 | }; 27 | 28 | use event::KeyModifiers; 29 | 30 | /// App holds the state of the application 31 | pub struct App { 32 | tabs: Vec, 33 | current_tab: usize, 34 | 35 | terminal: Terminal>, 36 | events: Events, 37 | history_path: Option, 38 | logname: String, 39 | } 40 | 41 | fn pull_channel(channels: &mut Vec, n: usize) -> Option { 42 | let c = channels 43 | .iter() 44 | .enumerate() 45 | .find_map(|(i, c)| if c.number() == n { Some(i) } else { None }); 46 | 47 | c.map(|c| channels.remove(c)) 48 | } 49 | 50 | impl App { 51 | pub fn new( 52 | mut rtt: probe_rs_rtt::Rtt, 53 | config: &crate::config::Config, 54 | logname: String, 55 | ) -> Result { 56 | let mut tabs = Vec::new(); 57 | if !config.rtt.channels.is_empty() { 58 | let mut up_channels = rtt.up_channels().drain().collect::>(); 59 | let mut down_channels = rtt.down_channels().drain().collect::>(); 60 | for channel in &config.rtt.channels { 61 | tabs.push(ChannelState::new( 62 | channel.up.and_then(|up| pull_channel(&mut up_channels, up)), 63 | channel 64 | .down 65 | .and_then(|down| pull_channel(&mut down_channels, down)), 66 | channel.name.clone(), 67 | config.rtt.show_timestamps, 68 | channel.format, 69 | )) 70 | } 71 | } else { 72 | let up_channels = rtt.up_channels().drain(); 73 | let mut down_channels = rtt.down_channels().drain().collect::>(); 74 | for channel in up_channels { 75 | let number = channel.number(); 76 | tabs.push(ChannelState::new( 77 | Some(channel), 78 | pull_channel(&mut down_channels, number), 79 | None, 80 | config.rtt.show_timestamps, 81 | DataFormat::String, 82 | )); 83 | } 84 | 85 | for channel in down_channels { 86 | tabs.push(ChannelState::new( 87 | None, 88 | Some(channel), 89 | None, 90 | config.rtt.show_timestamps, 91 | DataFormat::String, 92 | )); 93 | } 94 | } 95 | 96 | // Code farther down relies on tabs being configured and might panic 97 | // otherwise. 98 | if tabs.is_empty() { 99 | return Err(anyhow!( 100 | "Failed to initialize RTT UI: No RTT channels configured" 101 | )); 102 | } 103 | 104 | let events = Events::new(); 105 | 106 | enable_raw_mode().context("Failed to enable 'raw' mode for terminal")?; 107 | let mut stdout = std::io::stdout(); 108 | execute!(stdout, EnterAlternateScreen).unwrap(); 109 | let backend = CrosstermBackend::new(stdout); 110 | let mut terminal = Terminal::new(backend).unwrap(); 111 | let _ = terminal.hide_cursor(); 112 | 113 | let history_path = { 114 | if !config.rtt.log_enabled { 115 | None 116 | } else { 117 | //when is the right time if ever to fail if the directory or file cant be created? 118 | //should we create the path on startup or when we write 119 | match std::fs::create_dir_all(&config.rtt.log_path) { 120 | Ok(_) => Some(config.rtt.log_path.clone()), 121 | Err(_) => { 122 | log::warn!("Could not create log directory"); 123 | None 124 | } 125 | } 126 | } 127 | }; 128 | 129 | Ok(Self { 130 | tabs, 131 | current_tab: 0, 132 | terminal, 133 | events, 134 | history_path, 135 | logname, 136 | }) 137 | } 138 | 139 | pub fn get_rtt_symbol(file: &mut T) -> Option { 140 | let mut buffer = Vec::new(); 141 | if file.read_to_end(&mut buffer).is_ok() { 142 | if let Ok(binary) = goblin::elf::Elf::parse(buffer.as_slice()) { 143 | for sym in &binary.syms { 144 | if let Some(name) = binary.strtab.get_at(sym.st_name) { 145 | if name == "_SEGGER_RTT" { 146 | return Some(sym.st_value); 147 | } 148 | } 149 | } 150 | } 151 | } 152 | 153 | log::warn!("No RTT header info was present in the ELF file. Does your firmware run RTT?"); 154 | None 155 | } 156 | 157 | pub fn render( 158 | &mut self, 159 | defmt_state: &Option<(defmt_decoder::Table, Option)>, 160 | ) { 161 | let input = self.current_tab().input().to_owned(); 162 | let has_down_channel = self.current_tab().has_down_channel(); 163 | let scroll_offset = self.current_tab().scroll_offset(); 164 | let messages = self.current_tab().messages().clone(); 165 | let data = self.current_tab().data().clone(); 166 | 167 | log::debug!("Data length: {}", data.len()); 168 | 169 | let tabs = &self.tabs; 170 | let current_tab = self.current_tab; 171 | let mut height = 0; 172 | let mut messages_wrapped: Vec = Vec::new(); 173 | 174 | match tabs[current_tab].format() { 175 | DataFormat::String => { 176 | self.terminal 177 | .draw(|f| { 178 | let constraints = if has_down_channel { 179 | &[ 180 | Constraint::Length(1), 181 | Constraint::Min(1), 182 | Constraint::Length(1), 183 | ][..] 184 | } else { 185 | &[Constraint::Length(1), Constraint::Min(1)][..] 186 | }; 187 | let chunks = Layout::default() 188 | .direction(Direction::Vertical) 189 | .margin(0) 190 | .constraints(constraints) 191 | .split(f.size()); 192 | 193 | let tab_names = tabs 194 | .iter() 195 | .map(|t| Spans::from(t.name())) 196 | .collect::>(); 197 | let tabs = Tabs::new(tab_names) 198 | .select(current_tab) 199 | .style(Style::default().fg(Color::Black).bg(Color::Yellow)) 200 | .highlight_style( 201 | Style::default() 202 | .fg(Color::Green) 203 | .bg(Color::Yellow) 204 | .add_modifier(Modifier::BOLD), 205 | ); 206 | f.render_widget(tabs, chunks[0]); 207 | 208 | height = chunks[1].height as usize; 209 | 210 | // We need to collect to generate message_num :( 211 | messages_wrapped = messages 212 | .iter() 213 | .flat_map(|m| textwrap::wrap(m, chunks[1].width as usize)) 214 | .map(|s| s.into_owned()) 215 | .collect(); 216 | 217 | let message_num = messages_wrapped.len(); 218 | 219 | let messages: Vec = messages_wrapped 220 | .iter() 221 | .skip(message_num - (height + scroll_offset).min(message_num)) 222 | .take(height) 223 | .map(|s| ListItem::new(vec![Spans::from(Span::raw(s))])) 224 | .collect(); 225 | 226 | let messages = List::new(messages.as_slice()) 227 | .block(Block::default().borders(Borders::NONE)); 228 | f.render_widget(messages, chunks[1]); 229 | 230 | if has_down_channel { 231 | let input = Paragraph::new(Spans::from(vec![Span::raw(input.clone())])) 232 | .style(Style::default().fg(Color::Yellow).bg(Color::Blue)); 233 | f.render_widget(input, chunks[2]); 234 | } 235 | }) 236 | .unwrap(); 237 | 238 | let message_num = messages_wrapped.len(); 239 | let scroll_offset = self.tabs[self.current_tab].scroll_offset(); 240 | if message_num < height + scroll_offset { 241 | self.current_tab_mut() 242 | .set_scroll_offset(message_num - height.min(message_num)); 243 | } 244 | } 245 | binle_or_defmt => { 246 | self.terminal 247 | .draw(|f| { 248 | let constraints = if has_down_channel { 249 | &[ 250 | Constraint::Length(1), 251 | Constraint::Min(1), 252 | Constraint::Length(1), 253 | ][..] 254 | } else { 255 | &[Constraint::Length(1), Constraint::Min(1)][..] 256 | }; 257 | let chunks = Layout::default() 258 | .direction(Direction::Vertical) 259 | .margin(0) 260 | .constraints(constraints) 261 | .split(f.size()); 262 | 263 | let tab_names = tabs 264 | .iter() 265 | .map(|t| Spans::from(t.name())) 266 | .collect::>(); 267 | let tabs = Tabs::new(tab_names) 268 | .select(current_tab) 269 | .style(Style::default().fg(Color::Black).bg(Color::Yellow)) 270 | .highlight_style( 271 | Style::default() 272 | .fg(Color::Green) 273 | .bg(Color::Yellow) 274 | .add_modifier(Modifier::BOLD), 275 | ); 276 | f.render_widget(tabs, chunks[0]); 277 | 278 | height = chunks[1].height as usize; 279 | 280 | // probably pretty bad 281 | match binle_or_defmt { 282 | DataFormat::BinaryLE => { 283 | messages_wrapped.push(data.iter().fold( 284 | String::new(), 285 | |mut output, byte| { 286 | let _ = write(&mut output, format_args!("{:#04x}, ", byte)); 287 | output 288 | }, 289 | )); 290 | } 291 | DataFormat::Defmt => { 292 | let (table, locs) = defmt_state.as_ref().expect( 293 | "Running rtt in defmt mode but table or locations could not be loaded.", 294 | ); 295 | let mut stream_decoder = table.new_stream_decoder(); 296 | stream_decoder.received(&data); 297 | while let Ok(frame) = stream_decoder.decode() 298 | { 299 | // NOTE(`[]` indexing) all indices in `table` have already been 300 | // verified to exist in the `locs` map. 301 | let loc = locs.as_ref().map(|locs| &locs[&frame.index()]); 302 | 303 | messages_wrapped.push(format!("{}", frame.display(false))); 304 | if let Some(loc) = loc { 305 | let relpath = if let Ok(relpath) = 306 | loc.file.strip_prefix(&std::env::current_dir().unwrap()) 307 | { 308 | relpath 309 | } else { 310 | // not relative; use full path 311 | &loc.file 312 | }; 313 | 314 | messages_wrapped.push(format!( 315 | "└─ {}:{}", 316 | relpath.display(), 317 | loc.line 318 | )); 319 | } 320 | } 321 | } 322 | DataFormat::String => unreachable!("You encountered a bug. Please open an issue on Github."), 323 | } 324 | 325 | let message_num = messages_wrapped.len(); 326 | 327 | let messages: Vec = messages_wrapped 328 | .iter() 329 | .skip(message_num - (height + scroll_offset).min(message_num)) 330 | .take(height) 331 | .map(|s| ListItem::new(vec![Spans::from(Span::raw(s))])) 332 | .collect(); 333 | 334 | let messages = List::new(messages.as_slice()) 335 | .block(Block::default().borders(Borders::NONE)); 336 | f.render_widget(messages, chunks[1]); 337 | 338 | if has_down_channel { 339 | let input = Paragraph::new(Spans::from(vec![Span::raw(input.clone())])) 340 | .style(Style::default().fg(Color::Yellow).bg(Color::Blue)); 341 | f.render_widget(input, chunks[2]); 342 | } 343 | }) 344 | .unwrap(); 345 | 346 | let message_num = messages_wrapped.len(); 347 | let scroll_offset = self.tabs[self.current_tab].scroll_offset(); 348 | if message_num < height + scroll_offset { 349 | self.current_tab_mut() 350 | .set_scroll_offset(message_num - height.min(message_num)); 351 | } 352 | } 353 | } 354 | } 355 | 356 | /// Returns true if the application should exit. 357 | pub fn handle_event(&mut self, core: &mut Core) -> bool { 358 | match self.events.next(Duration::from_millis(10)) { 359 | Ok(event) => match event.code { 360 | KeyCode::Char('c') if event.modifiers.contains(KeyModifiers::CONTROL) => { 361 | clean_up_terminal(); 362 | let _ = self.terminal.show_cursor(); 363 | 364 | if let Some(path) = &self.history_path { 365 | for (i, tab) in self.tabs.iter().enumerate() { 366 | if tab.format() == DataFormat::Defmt { 367 | eprintln!("Not saving tab {} as saving defmt logs is currently unsupported.", i + 1); 368 | continue; 369 | } 370 | 371 | let extension = match tab.format() { 372 | DataFormat::String => "txt", 373 | DataFormat::BinaryLE => "dat", 374 | DataFormat::Defmt => unreachable!(), 375 | }; 376 | 377 | let name = format!("{}_channel{}.{}", self.logname, i, extension); 378 | let sanitize_options = sanitize_filename::Options { 379 | replacement: "_", 380 | ..Default::default() 381 | }; 382 | let sanitized_name = 383 | sanitize_filename::sanitize_with_options(name, sanitize_options); 384 | let final_path = path.join(sanitized_name); 385 | 386 | match std::fs::File::create(&final_path) { 387 | Ok(mut file) => { 388 | match tab.format() { 389 | DataFormat::String => { 390 | for line in tab.messages() { 391 | match writeln!(file, "{}", line) { 392 | Ok(_) => {} 393 | Err(e) => { 394 | eprintln!( 395 | "\nError writing log channel {}: {}", 396 | i, e 397 | ); 398 | continue; 399 | } 400 | } 401 | } 402 | } 403 | DataFormat::BinaryLE => match file.write(tab.data()) { 404 | Ok(_) => {} 405 | Err(e) => { 406 | eprintln!( 407 | "\nError writing log channel {}: {}", 408 | i, e 409 | ); 410 | continue; 411 | } 412 | }, 413 | DataFormat::Defmt => unreachable!(), 414 | }; 415 | 416 | // Flush file 417 | if let Err(e) = file.flush() { 418 | eprintln!("Error writing log channel {}: {}", i, e) 419 | } 420 | } 421 | Err(e) => { 422 | eprintln!( 423 | "\nCould not create log file {}: {}", 424 | final_path.display(), 425 | e 426 | ); 427 | } 428 | } 429 | } 430 | } 431 | true 432 | } 433 | KeyCode::Char('l') if event.modifiers.contains(KeyModifiers::CONTROL) => { 434 | self.current_tab_mut().clear(); 435 | false 436 | } 437 | KeyCode::F(n) => { 438 | let n = n as usize - 1; 439 | if n < self.tabs.len() { 440 | self.current_tab = n; 441 | } 442 | false 443 | } 444 | KeyCode::Enter => { 445 | self.push_rtt(core); 446 | false 447 | } 448 | KeyCode::Char(c) => { 449 | self.current_tab_mut().input_mut().push(c); 450 | false 451 | } 452 | KeyCode::Backspace => { 453 | self.current_tab_mut().input_mut().pop(); 454 | false 455 | } 456 | KeyCode::PageUp => { 457 | self.current_tab_mut().scroll_up(); 458 | false 459 | } 460 | KeyCode::PageDown => { 461 | self.current_tab_mut().scroll_down(); 462 | false 463 | } 464 | _ => false, 465 | }, 466 | Err(RecvTimeoutError::Disconnected) => { 467 | log::warn!("Unable to receive anymore input events from terminal, shutting down."); 468 | true 469 | } 470 | // Timeout just means no input received. 471 | Err(RecvTimeoutError::Timeout) => false, 472 | } 473 | } 474 | 475 | pub fn current_tab(&self) -> &ChannelState { 476 | &self.tabs[self.current_tab] 477 | } 478 | 479 | pub fn current_tab_mut(&mut self) -> &mut ChannelState { 480 | &mut self.tabs[self.current_tab] 481 | } 482 | 483 | /// Polls the RTT target for new data on all channels. 484 | pub fn poll_rtt(&mut self, core: &mut Core) { 485 | for channel in self.tabs.iter_mut() { 486 | channel.poll_rtt(core); 487 | } 488 | } 489 | 490 | pub fn push_rtt(&mut self, core: &mut Core) { 491 | self.tabs[self.current_tab].push_rtt(core); 492 | } 493 | } 494 | 495 | pub fn clean_up_terminal() { 496 | let _ = disable_raw_mode(); 497 | let _ = execute!(std::io::stdout(), LeaveAlternateScreen); 498 | } 499 | -------------------------------------------------------------------------------- /src/rttui/channel.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | 3 | use chrono::Local; 4 | use probe_rs::Core; 5 | use probe_rs_rtt::{ChannelMode, DownChannel, UpChannel}; 6 | 7 | #[derive(Debug, Copy, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] 8 | pub enum DataFormat { 9 | String, 10 | BinaryLE, 11 | Defmt, 12 | } 13 | 14 | #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] 15 | pub struct ChannelConfig { 16 | pub up: Option, 17 | pub down: Option, 18 | pub name: Option, 19 | pub up_mode: Option, 20 | pub format: DataFormat, 21 | } 22 | 23 | #[derive(Debug)] 24 | pub struct ChannelState { 25 | up_channel: Option, 26 | down_channel: Option, 27 | name: String, 28 | format: DataFormat, 29 | /// Contains the strings when [ChannelState::format] is [DataFormat::String]. 30 | messages: Vec, 31 | /// When [ChannelState::format] is not [DataFormat::String] this 32 | /// contains RTT binary data or binary data in defmt format. 33 | data: Vec, 34 | last_line_done: bool, 35 | input: String, 36 | scroll_offset: usize, 37 | rtt_buffer: RttBuffer, 38 | show_timestamps: bool, 39 | } 40 | 41 | impl ChannelState { 42 | pub fn new( 43 | up_channel: Option, 44 | down_channel: Option, 45 | name: Option, 46 | show_timestamps: bool, 47 | format: DataFormat, 48 | ) -> Self { 49 | let name = name 50 | .or_else(|| up_channel.as_ref().and_then(|up| up.name().map(Into::into))) 51 | .or_else(|| { 52 | down_channel 53 | .as_ref() 54 | .and_then(|down| down.name().map(Into::into)) 55 | }) 56 | .unwrap_or_else(|| "Unnamed channel".to_owned()); 57 | 58 | Self { 59 | up_channel, 60 | down_channel, 61 | name, 62 | format, 63 | messages: Vec::new(), 64 | last_line_done: true, 65 | input: String::new(), 66 | scroll_offset: 0, 67 | rtt_buffer: RttBuffer([0u8; 1024]), 68 | show_timestamps, 69 | data: Vec::new(), 70 | } 71 | } 72 | 73 | pub fn has_down_channel(&self) -> bool { 74 | self.down_channel.is_some() 75 | } 76 | 77 | pub fn messages(&self) -> &Vec { 78 | &self.messages 79 | } 80 | 81 | pub fn input(&self) -> &str { 82 | &self.input 83 | } 84 | 85 | pub fn input_mut(&mut self) -> &mut String { 86 | &mut self.input 87 | } 88 | 89 | pub fn scroll_offset(&self) -> usize { 90 | self.scroll_offset 91 | } 92 | 93 | pub fn scroll_up(&mut self) { 94 | self.scroll_offset += 1; 95 | } 96 | 97 | pub fn scroll_down(&mut self) { 98 | if self.scroll_offset > 0 { 99 | self.scroll_offset -= 1; 100 | } 101 | } 102 | 103 | pub fn name(&self) -> &str { 104 | &self.name 105 | } 106 | 107 | pub fn format(&self) -> DataFormat { 108 | self.format 109 | } 110 | 111 | pub fn set_scroll_offset(&mut self, value: usize) { 112 | self.scroll_offset = value; 113 | } 114 | 115 | pub fn clear(&mut self) { 116 | self.scroll_offset = 0; 117 | self.data = Vec::new(); 118 | self.messages = Vec::new(); 119 | } 120 | 121 | pub fn data(&self) -> &Vec { 122 | &self.data 123 | } 124 | 125 | /// Polls the RTT target for new data on the specified channel. 126 | /// 127 | /// Processes all the new data and adds it to the linebuffer of the respective channel. 128 | pub fn poll_rtt(&mut self, core: &mut Core) { 129 | // TODO: Proper error handling. 130 | let count = if let Some(channel) = self.up_channel.as_mut() { 131 | match channel.read(core, self.rtt_buffer.0.as_mut()) { 132 | Ok(count) => count, 133 | Err(err) => { 134 | log::error!("\nError reading from RTT: {}", err); 135 | return; 136 | } 137 | } 138 | } else { 139 | 0 140 | }; 141 | 142 | if count == 0 { 143 | return; 144 | } 145 | 146 | match self.format { 147 | DataFormat::String => { 148 | let now = Local::now(); 149 | 150 | // First, convert the incoming bytes to UTF8. 151 | let mut incoming = String::from_utf8_lossy(&self.rtt_buffer.0[..count]).to_string(); 152 | 153 | // Then pop the last stored line from our line buffer if possible and append our new line. 154 | let last_line_done = self.last_line_done; 155 | if !last_line_done { 156 | if let Some(last_line) = self.messages.pop() { 157 | incoming = last_line + &incoming; 158 | } 159 | } 160 | self.last_line_done = incoming.ends_with('\n'); 161 | 162 | // Then split the incoming buffer discarding newlines and if necessary 163 | // add a timestamp at start of each. 164 | // Note: this means if you print a newline in the middle of your debug 165 | // you get a timestamp there too.. 166 | // Note: we timestamp at receipt of newline, not first char received if that 167 | // matters. 168 | for (i, line) in incoming.split_terminator('\n').enumerate() { 169 | if self.show_timestamps && (last_line_done || i > 0) { 170 | let ts = now.format("%H:%M:%S%.3f"); 171 | self.messages.push(format!("{} {}", ts, line)); 172 | } else { 173 | self.messages.push(line.to_string()); 174 | } 175 | if self.scroll_offset != 0 { 176 | self.scroll_offset += 1; 177 | } 178 | } 179 | } 180 | // defmt output is later formatted into strings in [App::render]. 181 | DataFormat::BinaryLE | DataFormat::Defmt => { 182 | self.data.extend_from_slice(&self.rtt_buffer.0[..count]); 183 | } 184 | }; 185 | } 186 | 187 | pub fn push_rtt(&mut self, core: &mut Core) { 188 | if let Some(down_channel) = self.down_channel.as_mut() { 189 | self.input += "\n"; 190 | down_channel.write(core, self.input.as_bytes()).unwrap(); 191 | self.input.clear(); 192 | } 193 | } 194 | } 195 | 196 | struct RttBuffer([u8; 1024]); 197 | 198 | impl fmt::Debug for RttBuffer { 199 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 200 | self.0.fmt(f) 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /src/rttui/event.rs: -------------------------------------------------------------------------------- 1 | use std::sync::mpsc; 2 | use std::sync::{atomic::AtomicBool, Arc}; 3 | use std::thread; 4 | use std::time::Duration; 5 | 6 | use crossterm::event::{self, Event as CEvent, KeyEvent}; 7 | 8 | /// A small event handler that wrap termion input and tick events. Each event 9 | /// type is handled in its own thread and returned to a common `Receiver` 10 | pub struct Events { 11 | rx: mpsc::Receiver, 12 | _input_handle: thread::JoinHandle<()>, 13 | _ignore_exit_key: Arc, 14 | } 15 | 16 | #[derive(Debug, Clone, Copy)] 17 | pub struct Config { 18 | pub poll_rate: Duration, 19 | } 20 | 21 | impl Default for Config { 22 | fn default() -> Config { 23 | Config { 24 | poll_rate: Duration::from_millis(10), 25 | } 26 | } 27 | } 28 | 29 | impl Events { 30 | pub fn new() -> Events { 31 | Self::with_config(Config::default()) 32 | } 33 | 34 | pub fn with_config(config: Config) -> Events { 35 | let (tx, rx) = mpsc::channel(); 36 | let ignore_exit_key = Arc::new(AtomicBool::new(false)); 37 | let input_handle = { 38 | thread::Builder::new() 39 | .name("probe-rs-terminal-event-handler".to_owned()) 40 | .spawn(move || { 41 | loop { 42 | // poll for tick rate duration, if no events, sent tick event. 43 | if event::poll(config.poll_rate).unwrap() { 44 | if let CEvent::Key(key) = event::read().unwrap() { 45 | if tx.send(key).is_err() { 46 | return; 47 | } 48 | } 49 | } 50 | } 51 | }) 52 | .unwrap() 53 | }; 54 | 55 | Events { 56 | rx, 57 | _ignore_exit_key: ignore_exit_key, 58 | _input_handle: input_handle, 59 | } 60 | } 61 | 62 | pub fn next(&self, timeout: Duration) -> Result { 63 | self.rx.recv_timeout(timeout) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/rttui/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod app; 2 | pub mod channel; 3 | pub mod event; 4 | --------------------------------------------------------------------------------