78 Commits

Author SHA1 Message Date
bors[bot]
8a8466a560 Merge #46
46: bump dependencies r=adamgreig a=japaric

r? @rust-embedded/cortex-m (anyone)

Co-authored-by: Jorge Aparicio <jorge@japaric.io>
2018-09-03 15:04:28 +00:00
Jorge Aparicio
666bf52748 bump dependencies 2018-09-03 16:57:03 +02:00
bors[bot]
7e36bbe1df Merge #44
44: dedup contents of .cargo/config; don't depend on auto-load-safe-path being set r=ithinuel a=japaric

see individual commit messages for details

unfortunately this didn't come up as nice as I expected because there seems to
be a bug around `target.cfg.runner` (rust-lang/cargo#5946). Still, I think this
is an improvement.

r? @rust-embedded/cortex-m

Co-authored-by: Jorge Aparicio <jorge@japaric.io>
2018-08-29 22:26:27 +00:00
Jorge Aparicio
4265e01ef7 add a comment indicating which core each target maps to 2018-08-29 16:55:50 +02:00
Jorge Aparicio
98137712a5 workaround rust-lang/cargo#5946 2018-08-29 15:15:40 +02:00
Jorge Aparicio
065efc83fb be explicit about the GDB script to use
with this change the user doesn't need to set an [auto-load-safe-path]

[auto-load-safe-path]: https://sourceware.org/gdb/onlinedocs/gdb/Auto_002dloading-safe-path.html
2018-08-29 14:26:24 +02:00
Jorge Aparicio
b43bd7d20d deduplicate the contents .cargo/config
using `cfg`s. Also add all the possible compilation targets to .cargo/config.
2018-08-29 14:23:25 +02:00
bors[bot]
3da03fc6b8 Merge #43
43: add CHANGELOG for v0.3.4 r=adamgreig a=japaric

r? @rust-embedded/cortex-m (anyone)

Co-authored-by: Jorge Aparicio <jorge@japaric.io>
2018-08-28 19:51:15 +00:00
Jorge Aparicio
1fdaec36bd add CHANGELOG for v0.3.4 2018-08-28 21:41:37 +02:00
bors[bot]
217ebb3a79 Merge #42
42: v0.3.4 r=therealprof a=japaric

a few more updates before the next release

r? @rust-embedded/cortex-m

Co-authored-by: Jorge Aparicio <jorge@japaric.io>
2018-08-28 14:07:43 +00:00
Jorge Aparicio
5063e90960 v0.3.4 2018-08-28 15:56:49 +02:00
bors[bot]
73ced50a21 Merge #41
41: use LLD as the default linker r=therealprof a=japaric

closes #39

I added instructions on how to switch to a different linker to .cargo/config but
I don't think that's too visible. Beginners are unlikely to look into that file
if they run into problems with the default linker. Any suggestions to improve
the visibility of that information?

Also, don't merge this until the default linker changes for the Cortex-M targets
on nightly as this relies on that change.

r? @rust-embedded/cortex-m

Co-authored-by: Jorge Aparicio <jorge@japaric.io>
2018-08-28 13:15:12 +00:00
Jorge Aparicio
b89c76e3fc use size instead of arm-none-eabi-size 2018-08-28 14:55:02 +02:00
Jorge Aparicio
7bb74b2123 fix some warnings 2018-08-28 14:54:40 +02:00
Jorge Aparicio
0eaa0de3c6 update the minimal example 2018-08-27 22:52:02 +02:00
Jorge Aparicio
3e39a0b927 publish docs on GH pages 2018-08-27 17:44:55 +02:00
Jorge Aparicio
a79ea9bee7 bump dependencies to not depend on arm-none-eabi-gcc 2018-08-27 17:39:07 +02:00
Jorge Aparicio
34d34975c3 update symptom for the 'overwrite .cargo/config' problem 2018-08-27 15:19:48 +02:00
Jorge Aparicio
72e914069c use LLD as the default linker
closes #39
2018-08-25 19:32:28 +02:00
Jorge Aparicio
014dab642a tweak bors.toml 2018-08-11 19:37:39 -05:00
bors[bot]
cb68ff7248 Merge #40
40: v0.3.3 r=adamgreig a=japaric

changes required to publish a new version

r? @adamgreig (chosen at random)

Co-authored-by: Jorge Aparicio <jorge@japaric.io>
2018-08-07 22:33:55 +00:00
Jorge Aparicio
55f44f21be v0.3.3 2018-08-07 17:25:15 -05:00
bors[bot]
f38979def1 Merge #27
27: Clarify purpose of rerun-if-changed in build.rs r=japaric a=adamgreig

The current `build.rs` contains
```rust
    println!("cargo:rerun-if-changed=build.rs");
    println!("cargo:rerun-if-changed=memory.x");
```

This causes the build script to be re-run if (and *only if*) `build.rs` or `memory.x` change. The line for `build.rs` is redundant: the Cargo guide [says](https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script) the build script is always rerun when `build.rs` changes, so we can drop that line.

The remaining line caused me a bit of confusion when adding other functionality to my project's build script, before I realised it tells Cargo to *only* rerun the build script when `memory.x` changes, as opposed to the default behaviour which is to rerun it on every build. The comment helps clarify the point of this line, so if users add other functionality to their build scripts it is hopefully easier to notice.

Co-authored-by: Adam Greig <adam@adamgreig.com>
2018-08-07 21:14:34 +00:00
Adam Greig
ba27df0b57 Update comment on rerun-if-changed to better reflect what it does 2018-08-07 20:58:00 +01:00
Adam Greig
f39fa8ebef Add comment to build script about rerun-if-changed, and remove redundant line for build.rs 2018-08-07 20:57:02 +01:00
Jorge Aparicio
5832d097c6 README: mention the CoC and who maintains this repo 2018-08-07 00:25:15 -05:00
Jorge Aparicio
2a2879a3b0 add CODEOWNERS, CoC; tweak bors and Travis 2018-08-06 21:41:02 -05:00
bors[bot]
daea420f17 Merge #38
38: stop recommending LLD r=japaric a=japaric

until https://bugs.llvm.org/show_bug.cgi?id=38435 is fixed

Co-authored-by: Jorge Aparicio <jorge@japaric.io>
2018-08-03 02:39:19 +00:00
Jorge Aparicio
b7884948b2 fix the allocator example 2018-08-02 21:38:42 -05:00
Jorge Aparicio
01e9a597c1 stop recommending LLD
until https://bugs.llvm.org/show_bug.cgi?id=38435 is fixed
2018-08-02 21:12:11 -05:00
Jorge Aparicio
ae503ee8fb v0.3.2 2018-06-19 19:53:30 -05:00
bors[bot]
4a398df058 Merge #33
33: Update panic-semihosting dependency to 0.3.0 r=japaric a=plaes

This is due to #[lang = "panic_fmt"] -> #[panic_implementation] breakage

Co-authored-by: Priit Laes <plaes@plaes.org>
2018-06-20 00:46:27 +00:00
Priit Laes
efb84ccf53 Update panic-semihosting dependency to 0.3.0
This is due to #[lang = "panic_fmt"] -> #[panic_implementation] breakage
2018-06-17 09:23:23 +03:00
Jorge Aparicio
a462ab027d Merge pull request #30 from MrBuddyCasino/master
minor doc fix: git => cargo
2018-05-16 12:50:57 +02:00
Michael Böckling
6da25bced8 Update lib.rs
fixed doc: clone command should be cargo, not git
2018-05-16 11:00:33 +02:00
Jorge Aparicio
7cb137968b v0.3.1 2018-05-13 13:41:59 +02:00
Jorge Aparicio
7ae7245956 document the no #![no_main] issue 2018-05-13 12:02:37 +02:00
Jorge Aparicio
91a894e369 v0.3.0 2018-05-12 21:06:19 +02:00
bors[bot]
f7cf8de167 Merge #29
29: use less unstable dependencies r=japaric a=japaric

This PR and the ones at the bottom reduce the number of unstable features needed for Cortex-M development to a single one: `lang = "panic_fmt"`, which already has a path towards stabilization and which we hope to get on stable by 1.28.

[Check out the temporary documentation](https://japaric.github.io/cortex-m-quickstart/cortex_m_quickstart/index.html) (we still need more docs) to try out this preview. 

We would love your input on [these unresolved questions](https://github.com/japaric/cortex-m-rt/pull/69#issuecomment-384488537)

This PR depends on:

- japaric/cortex-m-rt#69
- japaric/cortex-m#88
- japaric/panic-semihosting#2
- japaric/svd2rust#203
- japaric/stm32f103xx#24

Co-authored-by: Jorge Aparicio <jorge@japaric.io>
2018-05-12 18:58:57 +00:00
Jorge Aparicio
66c0c588b0 fix tests 2018-05-12 20:51:52 +02:00
Jorge Aparicio
0f139c386b use published versions, doc up, update CHANGELOG 2018-05-12 20:41:42 +02:00
Jorge Aparicio
3a4a5be709 TODO: drop opt-level=s 2018-04-26 07:57:34 +02:00
Jorge Aparicio
a35486b2f4 update examples and docs 2018-04-26 07:37:15 +02:00
Jorge Aparicio
8e79d05cc4 drop linker-flavor, port more examples 2018-04-26 05:27:03 +02:00
Jorge Aparicio
0e2ec97ce6 make the hello example work 2018-04-25 07:54:05 +02:00
Jorge Aparicio
f6988f1ced use less unstable dependencies 2018-04-24 20:56:52 +02:00
bors[bot]
43acbc4e12 Merge #28
28: bump the cortex-m-rt to v0.4.0 r=japaric a=japaric



Co-authored-by: Jorge Aparicio <jorge@japaric.io>
2018-04-24 00:49:55 +00:00
Jorge Aparicio
a18a2fe64b don't call ci/after_success.sh 2018-04-24 02:49:32 +02:00
Jorge Aparicio
3b2e5699f3 remove panic-itm dependency 2018-04-24 02:13:15 +02:00
Jorge Aparicio
72b23f0e85 ci: don't install cargo-edit 2018-04-24 01:42:13 +02:00
Jorge Aparicio
2cd4ea31e5 bump the cortex-m-rt to v0.4.0 2018-04-24 01:24:06 +02:00
Jorge Aparicio
6f62705eaf v0.2.6 2018-04-09 00:11:59 +02:00
Jorge Aparicio
1d3d6e708c Merge pull request #26 from japaric/bye-xargo
remove all mentions of Xargo
2018-04-09 00:09:33 +02:00
Jorge Aparicio
fb3f403be5 remove all mentions of Xargo
as you can use plain Cargo to do ARM Cortex-M development
2018-04-09 00:06:24 +02:00
Jorge Aparicio
578dfc7f86 v0.2.5 2018-02-26 22:31:17 +01:00
Jorge Aparicio
23ae289bf4 fix the allocator example 2018-02-26 22:27:52 +01:00
Jorge Aparicio
5206ef79d2 examples/panic: add column information 2018-02-26 21:55:25 +01:00
Jorge Aparicio
46c97c6cee remove unused #[allow] 2018-02-26 21:49:45 +01:00
Jorge Aparicio
ba8994a2ed use stable release of alloc-cortex-m 2018-02-26 21:49:25 +01:00
Jorge Aparicio
7ebac078c0 Merge pull request #23 from kitling/update-examples
Update examples
2018-02-26 21:48:47 +01:00
Kitlith
d002e0f239 Add comments to Cargo.toml/Xargo.toml.
This should make it easier to comment/uncomment stuff for the various
examples.
2018-02-24 18:28:53 -08:00
Kitlith
9f573d73b2 Update examples to newer svd2rust api.
Similarly, the cortex-m crate API was also updated.
2018-02-24 18:26:31 -08:00
Jorge Aparicio
bf91f60d40 v0.2.4 2018-01-26 11:39:18 +01:00
Jorge Aparicio
682fe4e77c v0.2.3 2018-01-20 11:27:24 +01:00
Jorge Aparicio
d60563ff45 update the CHANGELOG 2018-01-17 14:46:18 +01:00
Jorge Aparicio
48ce24b303 document workaround for "Ignoring packet error" 2018-01-17 14:42:13 +01:00
Jorge Aparicio
3dc0cf09db disable incremental compilation and parallel codegen in dev mode 2018-01-17 14:27:57 +01:00
Jorge Aparicio
59b8b866c7 bump the cortex-m-rt dependency 2018-01-17 14:26:42 +01:00
Jorge Aparicio
1bb99c92f1 Merge pull request #20 from japaric/demangle
gdbinit: print demangled symbols by default
2017-11-25 01:12:55 +01:00
Jorge Aparicio
d41dd6a4c7 gdbinit: print demangled symbols by default
this change turns this:

``` console
(gdb) x/4 0x200003f0
0x200003f0 <_ZN3app2XS17h4b49405669958fd2E+1008>:       0x20000400      0x080004f5      0x00000000      0x00000001
```

into this:

``` console
(gdb) x/4 0x200003f0
0x200003f0 <app::XS+1008>:      0x20000400      0x080004f5      0x00000000      0x00000001
```
2017-11-25 01:12:17 +01:00
Jorge Aparicio
a8a02d9162 v0.2.1 2017-07-14 21:53:54 -05:00
Jorge Aparicio
affd24f2bb document another common error
overwriting the `.cargo/config` file instead of appending text to it
2017-07-14 21:48:05 -05:00
Jorge Aparicio
67003f069c enable the "mem" feature of the compiler-builtins crate
turns out it *is* required if your application ends up requiring a `memcmp`
operation.
2017-07-14 21:36:34 -05:00
Jorge Aparicio
51f4b4e7ed Merge pull request #16 from japaric/device
expand the device example
2017-07-14 21:26:25 -05:00
Jorge Aparicio
8890c461d6 expand the device example 2017-07-11 19:01:40 -05:00
Jorge Aparicio
3f66a585a8 Merge pull request #14 from protomors/upstream-builtins
Build compiler-builtins from rust source instead of github repository.
2017-07-10 19:03:43 -05:00
protomors
ba1263e7a1 Build compiler-builtins from rust source instead of github repository. 2017-07-09 12:05:26 +03:00
Jorge Aparicio
4b1a2f3811 fix CHANGELOG 2017-07-07 20:11:05 -05:00
43 changed files with 1479 additions and 800 deletions

View File

@@ -1,31 +1,38 @@
[target.thumbv6m-none-eabi]
runner = 'arm-none-eabi-gdb'
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
# runner = 'arm-none-eabi-gdb -x debug.gdb'
rustflags = [
# LLD (shipped with the Rust toolchain) is used as the default linker
"-C", "link-arg=-Tlink.x",
"-C", "linker=arm-none-eabi-ld",
"-Z", "linker-flavor=ld",
# if you run into problems with LLD switch to the GNU linker by commenting out
# this line
# "-C", "linker=arm-none-eabi-ld",
# if you need to link to pre-compiled C libraries provided by a C toolchain
# use GCC as the linker by commenting out both lines above and then
# uncommenting the three lines below
# "-C", "linker=arm-none-eabi-gcc",
# "-C", "link-arg=-Wl,-Tlink.x",
# "-C", "link-arg=-nostartfiles",
]
# work around rust-lang/cargo#5946
[target.thumbv6m-none-eabi]
runner = 'arm-none-eabi-gdb -x debug.gdb'
[target.thumbv7m-none-eabi]
runner = 'arm-none-eabi-gdb'
rustflags = [
"-C", "link-arg=-Tlink.x",
"-C", "linker=arm-none-eabi-ld",
"-Z", "linker-flavor=ld",
]
runner = 'arm-none-eabi-gdb -x debug.gdb'
[target.thumbv7em-none-eabi]
runner = 'arm-none-eabi-gdb'
rustflags = [
"-C", "link-arg=-Tlink.x",
"-C", "linker=arm-none-eabi-ld",
"-Z", "linker-flavor=ld",
]
runner = 'arm-none-eabi-gdb -x debug.gdb'
[target.thumbv7em-none-eabihf]
runner = 'arm-none-eabi-gdb'
rustflags = [
"-C", "link-arg=-Tlink.x",
"-C", "linker=arm-none-eabi-ld",
"-Z", "linker-flavor=ld",
]
runner = 'arm-none-eabi-gdb -x debug.gdb'
# end of workaround
[build]
# Pick one of these compilation targets
# target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+
# target = "thumbv7m-none-eabi" # Cortex-M3
# target = "thumbv7em-none-eabi" # Cortex-M4 and Cortex-M7 (no FPU)
# target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU)

1
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1 @@
* @rust-embedded/cortex-m

4
.github/bors.toml vendored Normal file
View File

@@ -0,0 +1,4 @@
block_labels = ["needs-decision"]
delete_merged_branches = true
required_approvals = 1
status = ["continuous-integration/travis-ci/push"]

1
.gitignore vendored
View File

@@ -1,4 +1,5 @@
**/*.rs.bk
.#*
.gdb_history
Cargo.lock
target/

52
.travis.yml Normal file
View File

@@ -0,0 +1,52 @@
language: rust
matrix:
include:
- env: TARGET=x86_64-unknown-linux-gnu
rust: nightly
if: branch = master AND type != pull_request
- env: TARGET=thumbv6m-none-eabi
rust: nightly
if: (branch = staging OR branch = trying) OR (type = pull_request AND branch = master)
- env: TARGET=thumbv7m-none-eabi
rust: nightly
if: (branch = staging OR branch = trying) OR (type = pull_request AND branch = master)
- env: TARGET=thumbv7em-none-eabi
rust: nightly
if: (branch = staging OR branch = trying) OR (type = pull_request AND branch = master)
- env: TARGET=thumbv7em-none-eabihf
rust: nightly
if: (branch = staging OR branch = trying) OR (type = pull_request AND branch = master)
before_install: set -e
install:
- bash ci/install.sh
script:
- bash ci/script.sh
after_success:
- bash ci/after-success.sh
after_script: set +e
cache: cargo
before_cache:
# Travis can't cache files that are not readable by "others"
- chmod -R a+r $HOME/.cargo
branches:
only:
- master
- staging
- trying
notifications:
email:
on_success: never

View File

@@ -5,6 +5,122 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]
## [v0.3.4] - 2018-08-27
### Changed
- LLD is now used as the default linker.
- Updated the troubleshooting guide to reflect the change in the default linker.
- Simplified the minimal example.
- The examples in this template no longer require `arm-none-eabi-gcc` to build.
## [v0.3.3] - 2018-08-07
### Changed
- Stopped recommending LLD as it requires an unstable feature.
### Fixed
- The allocator example. It now uses the `#[alloc_error_handler]` attribute
instead of the unstable `oom` lang item.
## [v0.3.2] - 2018-06-19
### Fixed
- Bumped the panic-semihosting dependency to fix some examples when compiling with latest nightly.
## [v0.3.1] - 2018-05-13
- Document the standard `main` interface issue in the troubleshooting guide.
## [v0.3.0] - 2018-05-12
### Changed
- [breaking-change] `arm-none-eabi-gcc` is now a mandatory dependency as it's required by the
`cortex-m-rt` dependency and also the default linker.
- Bumped the `cortex-m` and `cortex-m-rt` dependencies to v0.5.0. Updated all the examples to match
the new `cortex-m-rt` API.
- Updated the `allocator` example to compile on a recent nightly.
- Set the number of codegen-units to 1 when compiling in release mode. This produces smaller and
faster binaries.
### Removed
- Removed `opt-level = "s"` from `profile.release`. This flag is still unstable.
## [v0.2.7] - 2018-04-24
### Changed
- Bumped the dependency of `cortex-m-rt` to v0.4.0.
## [v0.2.6] - 2018-04-09
### Changed
- The documentation to instruct the user to use Cargo instead of Xargo
## [v0.2.5] - 2018-02-26
### Added
- Comments to Cargo.toml and Xargo.toml to make it easier to try the examples.
### Fixed
- The `allocator` example to use the `#[global_allocator]` feature.
## [v0.2.4] - 2018-01-26
### Changed
- Disable ThinLTO which causes extreme binary size bloat. See rust-lang/rust#47770 for details.
## [v0.2.3] - 2018-01-20
### Changed
- Tweaked docs. Instruction steps are now numbered.
### Removed
- The `CARGO_INCREMENTAL=1` workaround has been removed since it's now controlled via Cargo.toml and
we have the setting disabled in the template.
## [v0.2.2] - 2018-01-17
### Added
- Troubleshooting documentation: how to workaround the "Ignoring packet error, continuing..." GDB
error.
### Changed
- Disabled incremental compilation and parallel codegen on the dev profile to reduce the changes of
running into rust-lang/rust#47074.
- Bumped the version of the `cortex-m-rt` dependency to v0.3.12.
## [v0.2.1] - 2017-07-14
### Added
- Troubleshooting documentation: how to fix the error of overwriting the
`.cargo/config` file when you meant to append text to it.
### Changed
- Xargo.toml: Changed the source of the `compiler-builtins` crate from git to
the `rust-src` component.
- Expanded the `device` example to do some I/O.
## [v0.2.0] - 2017-07-07
### Changed
@@ -82,12 +198,25 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Initial release
[Unreleased]: https://github.com/japaric/cortex-m-quickstart/compare/v0.1.8...HEAD
[v0.1.8]: https://github.com/japaric/cortex-m-quickstart/compare/v0.1.7...v0.1.8
[v0.1.7]: https://github.com/japaric/cortex-m-quickstart/compare/v0.1.6...v0.1.7
[v0.1.6]: https://github.com/japaric/cortex-m-quickstart/compare/v0.1.5...v0.1.6
[v0.1.5]: https://github.com/japaric/cortex-m-quickstart/compare/v0.1.4...v0.1.5
[v0.1.4]: https://github.com/japaric/cortex-m-quickstart/compare/v0.1.3...v0.1.4
[v0.1.3]: https://github.com/japaric/cortex-m-quickstart/compare/v0.1.2...v0.1.3
[v0.1.2]: https://github.com/japaric/cortex-m-quickstart/compare/v0.1.1...v0.1.2
[v0.1.1]: https://github.com/japaric/cortex-m-quickstart/compare/v0.1.0...v0.1.1
[Unreleased]: https://github.com/rust-embedded/cortex-m-quickstart/compare/v0.3.4...HEAD
[v0.3.4]: https://github.com/rust-embedded/cortex-m-quickstart/compare/v0.3.3...v0.3.4
[v0.3.3]: https://github.com/rust-embedded/cortex-m-quickstart/compare/v0.3.2...v0.3.3
[v0.3.2]: https://github.com/rust-embedded/cortex-m-quickstart/compare/v0.3.1...v0.3.2
[v0.3.1]: https://github.com/rust-embedded/cortex-m-quickstart/compare/v0.3.0...v0.3.1
[v0.3.0]: https://github.com/rust-embedded/cortex-m-quickstart/compare/v0.2.7...v0.3.0
[v0.2.7]: https://github.com/rust-embedded/cortex-m-quickstart/compare/v0.2.6...v0.2.7
[v0.2.6]: https://github.com/rust-embedded/cortex-m-quickstart/compare/v0.2.5...v0.2.6
[v0.2.5]: https://github.com/rust-embedded/cortex-m-quickstart/compare/v0.2.4...v0.2.5
[v0.2.4]: https://github.com/rust-embedded/cortex-m-quickstart/compare/v0.2.3...v0.2.4
[v0.2.3]: https://github.com/rust-embedded/cortex-m-quickstart/compare/v0.2.2...v0.2.3
[v0.2.2]: https://github.com/rust-embedded/cortex-m-quickstart/compare/v0.2.1...v0.2.2
[v0.2.1]: https://github.com/rust-embedded/cortex-m-quickstart/compare/v0.2.0...v0.2.1
[v0.2.0]: https://github.com/rust-embedded/cortex-m-quickstart/compare/v0.1.8...v0.2.0
[v0.1.8]: https://github.com/rust-embedded/cortex-m-quickstart/compare/v0.1.7...v0.1.8
[v0.1.7]: https://github.com/rust-embedded/cortex-m-quickstart/compare/v0.1.6...v0.1.7
[v0.1.6]: https://github.com/rust-embedded/cortex-m-quickstart/compare/v0.1.5...v0.1.6
[v0.1.5]: https://github.com/rust-embedded/cortex-m-quickstart/compare/v0.1.4...v0.1.5
[v0.1.4]: https://github.com/rust-embedded/cortex-m-quickstart/compare/v0.1.3...v0.1.4
[v0.1.3]: https://github.com/rust-embedded/cortex-m-quickstart/compare/v0.1.2...v0.1.3
[v0.1.2]: https://github.com/rust-embedded/cortex-m-quickstart/compare/v0.1.1...v0.1.2
[v0.1.1]: https://github.com/rust-embedded/cortex-m-quickstart/compare/v0.1.0...v0.1.1

37
CODE_OF_CONDUCT.md Normal file
View File

@@ -0,0 +1,37 @@
# The Rust Code of Conduct
## Conduct
**Contact**: [Cortex-M team](https://github.com/rust-embedded/wg#the-cortex-m-team)
* We are committed to providing a friendly, safe and welcoming environment for all, regardless of level of experience, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, nationality, or other similar characteristic.
* On IRC, please avoid using overtly sexual nicknames or other nicknames that might detract from a friendly, safe and welcoming environment for all.
* Please be kind and courteous. There's no need to be mean or rude.
* Respect that people have differences of opinion and that every design or implementation choice carries a trade-off and numerous costs. There is seldom a right answer.
* Please keep unstructured critique to a minimum. If you have solid ideas you want to experiment with, make a fork and see how it works.
* We will exclude you from interaction if you insult, demean or harass anyone. That is not welcome behavior. We interpret the term "harassment" as including the definition in the [Citizen Code of Conduct](http://citizencodeofconduct.org/); if you have any lack of clarity about what might be included in that concept, please read their definition. In particular, we don't tolerate behavior that excludes people in socially marginalized groups.
* Private harassment is also unacceptable. No matter who you are, if you feel you have been or are being harassed or made uncomfortable by a community member, please contact one of the channel ops or any of the [Cortex-M team][team] immediately. Whether you're a regular contributor or a newcomer, we care about making this community a safe place for you and we've got your back.
* Likewise any spamming, trolling, flaming, baiting or other attention-stealing behavior is not welcome.
## Moderation
These are the policies for upholding our community's standards of conduct.
1. Remarks that violate the Rust standards of conduct, including hateful, hurtful, oppressive, or exclusionary remarks, are not allowed. (Cursing is allowed, but never targeting another user, and never in a hateful manner.)
2. Remarks that moderators find inappropriate, whether listed in the code of conduct or not, are also not allowed.
3. Moderators will first respond to such remarks with a warning.
4. If the warning is unheeded, the user will be "kicked," i.e., kicked out of the communication channel to cool off.
5. If the user comes back and continues to make trouble, they will be banned, i.e., indefinitely excluded.
6. Moderators may choose at their discretion to un-ban the user if it was a first offense and they offer the offended party a genuine apology.
7. If a moderator bans someone and you think it was unjustified, please take it up with that moderator, or with a different moderator, **in private**. Complaints about bans in-channel are not allowed.
8. Moderators are held to a higher standard than other community members. If a moderator creates an inappropriate situation, they should expect less leeway than others.
In the Rust community we strive to go the extra step to look out for each other. Don't just aim to be technically unimpeachable, try to be your best self. In particular, avoid flirting with offensive or sensitive issues, particularly if they're off-topic; this all too often leads to unnecessary fights, hurt feelings, and damaged trust; worse, it can drive people away from the community entirely.
And if someone takes issue with something you said or did, resist the urge to be defensive. Just stop doing what it was they complained about and apologize. Even if you feel you were misinterpreted or unfairly accused, chances are good there was something you could've communicated better — remember that it's your responsibility to make your fellow Rustaceans comfortable. Everyone wants to get along and we are all here first and foremost because we want to talk about cool technology. You will find that people will be eager to assume good intent and forgive as long as you earn their trust.
The enforcement policies listed above apply to all official embedded WG venues; including official IRC channels (#rust-embedded); GitHub repositories under rust-embedded; and all forums under rust-embedded.org (forum.rust-embedded.org).
*Adapted from the [Node.js Policy on Trolling](http://blog.izs.me/post/30036893703/policy-on-trolling) as well as the [Contributor Covenant v1.3.0](https://www.contributor-covenant.org/version/1/3/0/).*
[team]: https://github.com/rust-embedded/wg#the-cortex-m-team

View File

@@ -2,20 +2,31 @@
authors = ["Jorge Aparicio <jorge@japaric.io>"]
categories = ["embedded", "no-std"]
description = "A template for building applications for ARM Cortex-M microcontrollers"
documentation = "https://rust-embedded.github.io/cortex-m-quickstart/cortex_m_quickstart"
keywords = ["arm", "cortex-m", "template"]
license = "MIT OR Apache-2.0"
name = "cortex-m-quickstart"
repository = "https://github.com/japaric/cortex-m-quickstart"
version = "0.2.0"
version = "0.3.4"
[dependencies]
cortex-m = "0.3.0"
cortex-m-semihosting = "0.2.0"
cortex-m = "0.5.6"
cortex-m-rt = "0.5.3"
cortex-m-semihosting = "0.3.1"
panic-semihosting = "0.4.0"
[dependencies.cortex-m-rt]
features = ["abort-on-panic"]
version = "0.3.2"
# Uncomment for the panic example.
# panic-itm = "0.3.0"
# Uncomment for the allocator example.
# alloc-cortex-m = "0.3.5"
# Uncomment for the device example.
# [dependencies.stm32f103xx]
# features = ["rt"]
# version = "0.10.0"
[profile.release]
codegen-units = 1 # better optimizations
debug = true
lto = true
lto = true # better optimizations

View File

@@ -1,4 +1,4 @@
Copyright (c) 2017 {{toml-escape author}}
Copyright (c) 2018
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated

View File

@@ -2,7 +2,9 @@
> A template for building applications for ARM Cortex-M microcontrollers
# [Documentation](https://docs.rs/cortex-m-quickstart)
This project is developed and maintained by the [Cortex-M team][team].
# [Documentation](https://rust-embedded.github.io/cortex-m-quickstart/cortex_m_quickstart)
# License
@@ -20,3 +22,12 @@ at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.
## Code of Conduct
Contribution to this crate is organized under the terms of the [Rust Code of
Conduct][CoC], the maintainer of this crate, the [Cortex-M team][team], promises
to intervene to uphold that code of conduct.
[CoC]: CODE_OF_CONDUCT.md
[team]: https://github.com/rust-embedded/wg#the-cortex-m-team

View File

@@ -1,6 +0,0 @@
[dependencies.core]
stage = 0
[dependencies.compiler_builtins]
git = "https://github.com/rust-lang-nursery/compiler-builtins"
stage = 1

View File

@@ -12,6 +12,7 @@ fn main() {
.unwrap();
println!("cargo:rustc-link-search={}", out.display());
println!("cargo:rerun-if-changed=build.rs");
// Only re-run the build script when memory.x is changed,
// instead of when any part of the source code changes.
println!("cargo:rerun-if-changed=memory.x");
}

20
ci/after-success.sh Normal file
View File

@@ -0,0 +1,20 @@
set -euxo pipefail
main() {
cargo doc
mkdir ghp-import
curl -Ls https://github.com/davisp/ghp-import/archive/master.tar.gz |
tar --strip-components 1 -C ghp-import -xz
./ghp-import/ghp_import.py target/doc
set +x
git push -fq https://$GH_TOKEN@github.com/$TRAVIS_REPO_SLUG.git gh-pages && echo OK
}
# only publish on successful merges to master
if [ $TRAVIS_BRANCH = master ] && [ $TRAVIS_PULL_REQUEST = false ] && [ $TARGET = x86_64-unknown-linux-gnu ]; then
main
fi

9
ci/install.sh Normal file
View File

@@ -0,0 +1,9 @@
set -euxo pipefail
main() {
if [ $TARGET != x86_64-unknown-linux-gnu ]; then
rustup target add $TARGET
fi
}
main

72
ci/script.sh Normal file
View File

@@ -0,0 +1,72 @@
set -euxo pipefail
main() {
local td=$(mktemp -d)
git clone . $td
pushd $td
cat >memory.x <<'EOF'
MEMORY
{
FLASH : ORIGIN = 0x08000000, LENGTH = 256K
RAM : ORIGIN = 0x20000000, LENGTH = 40K
}
EOF
local examples=(
crash
exception
hello
minimal
panic
)
for ex in "${examples[@]}"; do
cargo build --target $TARGET --example $ex
cargo build --target $TARGET --example $ex --release
done
# ITM is not available on Cortex-M0
if [ $TARGET != thumbv6m-none-eabi ]; then
local ex=itm
cargo build --target $TARGET --example $ex
cargo build --target $TARGET --example $ex --release
examples+=( $ex )
fi
# Allocator example needs an extra dependency
cat >>Cargo.toml <<'EOF'
[dependencies.alloc-cortex-m]
version = "0.3.4"
EOF
local ex=allocator
cargo build --target $TARGET --example $ex --release
examples+=( $ex )
# Device example needs an extra dependency
if [ $TARGET = thumbv7m-none-eabi ]; then
cat >>Cargo.toml <<'EOF'
[dependencies.stm32f103xx]
features = ["rt"]
version = "0.10.0"
EOF
local ex=device
cargo build --target $TARGET --example $ex
cargo build --target $TARGET --example $ex --release
examples+=( $ex )
fi
IFS=,;eval size target/$TARGET/release/examples/"{${examples[*]}}"
popd
rm -rf $td
}
if [ $TARGET != x86_64-unknown-linux-gnu ]; then
main
fi

View File

@@ -1,5 +1,8 @@
target remote :3333
# print demangled symbols by default
set print asm-demangle on
monitor arm semihosting enable
# # send captured ITM to the file itm.fifo

View File

@@ -1,23 +1,6 @@
//! How to use the heap and a dynamic memory allocator
//!
//! To compile this example you'll need to build the collections crate as part
//! of the Xargo sysroot. To do that change the Xargo.toml file to look like
//! this:
//!
//! ``` text
//! [dependencies.core]
//! stage = 0
//!
//! [dependencies.collections] # NEW
//! stage = 0
//!
//! [dependencies.compiler_builtins]
//! git = "https://github.com/rust-lang-nursery/compiler-builtins"
//! stage = 1
//! ```
//!
//! This example depends on the alloc-cortex-m crate so you'll have to add it
//! to your Cargo.toml:
//! This example depends on the alloc-cortex-m crate so you'll have to add it to your Cargo.toml:
//!
//! ``` text
//! # or edit the Cargo.toml file manually
@@ -26,55 +9,68 @@
//!
//! ---
#[allow(deprecated)]
#![feature(collections)]
#![feature(used)]
#![feature(alloc)]
#![feature(alloc_error_handler)]
#![feature(lang_items)]
#![no_main]
#![no_std]
// This is the allocator crate; you can use a different one
extern crate alloc_cortex_m;
#[macro_use]
extern crate collections;
extern crate alloc;
extern crate cortex_m;
extern crate cortex_m_rt;
extern crate cortex_m_semihosting;
#[macro_use]
extern crate cortex_m_rt as rt;
extern crate cortex_m_semihosting as sh;
extern crate panic_semihosting;
use core::alloc::Layout;
use core::fmt::Write;
use alloc_cortex_m::CortexMHeap;
use cortex_m::asm;
use cortex_m_semihosting::hio;
use rt::ExceptionFrame;
use sh::hio;
fn main() {
// Initialize the allocator
unsafe {
extern "C" {
// Start of the heap
static mut _sheap: usize;
}
// this is the allocator the application will use
#[global_allocator]
static ALLOCATOR: CortexMHeap = CortexMHeap::empty();
// Size of the heap in words (1 word = 4 bytes)
// NOTE The bigger the heap the greater the chance to run into a stack
// overflow (collision between the stack and the heap)
const SIZE: isize = 256;
const HEAP_SIZE: usize = 1024; // in bytes
// End of the heap
let _eheap = (&mut _sheap as *mut _).offset(SIZE);
entry!(main);
alloc_cortex_m::init(&mut _sheap, _eheap);
}
fn main() -> ! {
// Initialize the allocator BEFORE you use it
unsafe { ALLOCATOR.init(rt::heap_start() as usize, HEAP_SIZE) }
// Growable array allocated on the heap
let xs = vec![0, 1, 2];
let mut stdout = hio::hstdout().unwrap();
writeln!(stdout, "{:?}", xs).unwrap();
loop {}
}
// As we are not using interrupts, we just register a dummy catch all handler
#[link_section = ".vector_table.interrupts"]
#[used]
static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240];
extern "C" fn default_handler() {
// define what happens in an Out Of Memory (OOM) condition
#[alloc_error_handler]
#[no_mangle]
pub fn alloc_error(_layout: Layout) -> ! {
asm::bkpt();
loop {}
}
exception!(HardFault, hard_fault);
fn hard_fault(ef: &ExceptionFrame) -> ! {
panic!("HardFault at {:#?}", ef);
}
exception!(*, default_handler);
fn default_handler(irqn: i16) {
panic!("Unhandled exception (IRQn = {})", irqn);
}

View File

@@ -1,85 +1,114 @@
//! Debugging a crash (exception)
//!
//! The `cortex-m-rt` crate provides functionality for this through a default
//! exception handler. When an exception is hit, the default handler will
//! trigger a breakpoint and in this debugging context the stacked registers
//! are accessible.
//! Most crash conditions trigger a hard fault exception, whose handler is defined via
//! `exception!(HardFault, ..)`. The `HardFault` handler has access to the exception frame, a
//! snapshot of the CPU registers at the moment of the exception.
//!
//! In you run the example below, you'll be able to inspect the state of your
//! program under the debugger using these commands:
//! This program crashes and the `HardFault` handler prints to the console the contents of the
//! `ExceptionFrame` and then triggers a breakpoint. From that breakpoint one can see the backtrace
//! that led to the exception.
//!
//! ``` text
//! (gdb) # Exception frame = program state during the crash
//! (gdb) print/x *ef
//! $1 = cortex_m::exception::ExceptionFrame {
//! r0 = 0x2fffffff,
//! r1 = 0x2fffffff,
//! r2 = 0x0,
//! r3 = 0x0,
//! r12 = 0x0,
//! lr = 0x8000481,
//! pc = 0x8000460,
//! xpsr = 0x61000000,
//! }
//! (gdb) continue
//! Program received signal SIGTRAP, Trace/breakpoint trap.
//! __bkpt () at asm/bkpt.s:3
//! 3 bkpt
//!
//! (gdb) # Where did we come from?
//! (gdb) backtrace
//! #0 cortex_m_rt::default_handler (ef=0x20004f54) at (..)
//! #1 <signal handler called>
//! #2 0x08000460 in core::ptr::read_volatile<u32> (src=0x2fffffff) at (..)
//! #3 0x08000480 in crash::main () at examples/crash.rs:68
//! #0 __bkpt () at asm/bkpt.s:3
//! #1 0x080030b4 in cortex_m::asm::bkpt () at $$/cortex-m-0.5.0/src/asm.rs:19
//! #2 rust_begin_unwind (args=..., file=..., line=99, col=5) at $$/panic-semihosting-0.2.0/src/lib.rs:87
//! #3 0x08001d06 in core::panicking::panic_fmt () at libcore/panicking.rs:71
//! #4 0x080004a6 in crash::hard_fault (ef=0x20004fa0) at examples/crash.rs:99
//! #5 0x08000548 in UserHardFault (ef=0x20004fa0) at <exception macros>:10
//! #6 0x0800093a in HardFault () at asm.s:5
//! Backtrace stopped: previous frame identical to this frame (corrupt stack?)
//! ```
//!
//! (gdb) # Nail down the location of the crash
//! (gdb) disassemble/m ef.pc
//! Dump of assembler code for function core::ptr::read_volatile<u32>:
//! 408 pub unsafe fn read_volatile<T>(src: *const T) -> T {
//! 0x08000454 <+0>: sub sp, #20
//! 0x08000456 <+2>: mov r1, r0
//! 0x08000458 <+4>: str r0, [sp, #8]
//! 0x0800045a <+6>: ldr r0, [sp, #8]
//! 0x0800045c <+8>: str r0, [sp, #12]
//! In the console output one will find the state of the Program Counter (PC) register at the time
//! of the exception.
//!
//! 409 intrinsics::volatile_load(src)
//! 0x0800045e <+10>: ldr r0, [sp, #12]
//! 0x08000460 <+12>: ldr r0, [r0, #0]
//! 0x08000462 <+14>: str r0, [sp, #16]
//! 0x08000464 <+16>: ldr r0, [sp, #16]
//! 0x08000466 <+18>: str r1, [sp, #4]
//! 0x08000468 <+20>: str r0, [sp, #0]
//! 0x0800046a <+22>: b.n 0x800046c <core::ptr::read_volatile<u32>+24>
//! ``` text
//! panicked at 'HardFault at ExceptionFrame {
//! r0: 0x2fffffff,
//! r1: 0x2fffffff,
//! r2: 0x080051d4,
//! r3: 0x080051d4,
//! r12: 0x20000000,
//! lr: 0x08000435,
//! pc: 0x08000ab6,
//! xpsr: 0x61000000
//! }', examples/crash.rs:106:5
//! ```
//!
//! 410 }
//! 0x0800046c <+24>: ldr r0, [sp, #0]
//! 0x0800046e <+26>: add sp, #20
//! 0x08000470 <+28>: bx lr
//! This register contains the address of the instruction that caused the exception. In GDB one can
//! disassemble the program around this address to observe the instruction that caused the
//! exception.
//!
//! ``` text
//! (gdb) disassemble/m 0x08000ab6
//! Dump of assembler code for function core::ptr::read_volatile:
//! 451 pub unsafe fn read_volatile<T>(src: *const T) -> T {
//! 0x08000aae <+0>: sub sp, #16
//! 0x08000ab0 <+2>: mov r1, r0
//! 0x08000ab2 <+4>: str r0, [sp, #8]
//!
//! 452 intrinsics::volatile_load(src)
//! 0x08000ab4 <+6>: ldr r0, [sp, #8]
//! -> 0x08000ab6 <+8>: ldr r0, [r0, #0]
//! 0x08000ab8 <+10>: str r0, [sp, #12]
//! 0x08000aba <+12>: ldr r0, [sp, #12]
//! 0x08000abc <+14>: str r1, [sp, #4]
//! 0x08000abe <+16>: str r0, [sp, #0]
//! 0x08000ac0 <+18>: b.n 0x8000ac2 <core::ptr::read_volatile+20>
//!
//! 453 }
//! 0x08000ac2 <+20>: ldr r0, [sp, #0]
//! 0x08000ac4 <+22>: add sp, #16
//! 0x08000ac6 <+24>: bx lr
//!
//! End of assembler dump.
//! ```
//!
//! `ldr r0, [r0, #0]` caused the exception. This instruction tried to load (read) a 32-bit word
//! from the address stored in the register `r0`. Looking again at the contents of `ExceptionFrame`
//! we see that the `r0` contained the address `0x2FFF_FFFF` when this instruction was executed.
//!
//! ---
#![feature(used)]
#![no_main]
#![no_std]
extern crate cortex_m;
extern crate cortex_m_rt;
#[macro_use]
extern crate cortex_m_rt as rt;
extern crate panic_semihosting;
use core::ptr;
use cortex_m::asm;
use rt::ExceptionFrame;
fn main() {
// Read an invalid memory address
entry!(main);
fn main() -> ! {
unsafe {
// read an address outside of the RAM region; causes a HardFault exception
ptr::read_volatile(0x2FFF_FFFF as *const u32);
}
loop {}
}
// As we are not using interrupts, we just register a dummy catch all handler
#[link_section = ".vector_table.interrupts"]
#[used]
static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240];
// define the hard fault handler
exception!(HardFault, hard_fault);
extern "C" fn default_handler() {
asm::bkpt();
fn hard_fault(ef: &ExceptionFrame) -> ! {
panic!("HardFault at {:#?}", ef);
}
// define the default exception handler
exception!(*, default_handler);
fn default_handler(irqn: i16) {
panic!("Unhandled exception (IRQn = {})", irqn);
}

View File

@@ -1,58 +1,89 @@
//! Using a device crate
//!
//! Crates generated using [`svd2rust`] are referred to as device crates. These
//! crates provides an API to access the peripherals of a device. When you
//! depend on one of these crates and the "rt" feature is enabled you don't need
//! link to the cortex-m-rt crate.
//! Crates generated using [`svd2rust`] are referred to as device crates. These crates provide an
//! API to access the peripherals of a device.
//!
//! [`svd2rust`]: https://crates.io/crates/svd2rust
//!
//! Device crates also provide an `interrupt!` macro to register interrupt
//! Device crates also provide an `interrupt!` macro (behind the "rt" feature) to register interrupt
//! handlers.
//!
//! This example depends on the [`stm32f103xx`] crate so you'll have to add it
//! to your Cargo.toml.
//! This example depends on the [`stm32f103xx`] crate so you'll have to add it to your Cargo.toml.
//!
//! [`stm32f103xx`]: https://crates.io/crates/stm32f103xx
//!
//! ```
//! $ edit Cargo.toml && cat $_
//! $ edit Cargo.toml && tail $_
//! [dependencies.stm32f103xx]
//! features = ["rt"]
//! version = "0.7.0"
//! version = "0.10.0"
//! ```
//!
//! ---
#![no_main]
#![no_std]
extern crate cortex_m;
#[macro_use(exception, interrupt)]
#[macro_use]
extern crate cortex_m_rt as rt;
extern crate cortex_m_semihosting as sh;
#[macro_use]
extern crate stm32f103xx;
extern crate panic_semihosting;
use cortex_m::interrupt;
use core::fmt::Write;
fn main() {
interrupt::free(|cs| {
let _gpioa = stm32f103xx::GPIOA.borrow(cs);
// do something with GPIOA
});
use cortex_m::peripheral::syst::SystClkSource;
use rt::ExceptionFrame;
use sh::hio::{self, HStdout};
use stm32f103xx::Interrupt;
entry!(main);
fn main() -> ! {
let p = cortex_m::Peripherals::take().unwrap();
let mut syst = p.SYST;
let mut nvic = p.NVIC;
nvic.enable(Interrupt::EXTI0);
// configure the system timer to wrap around every second
syst.set_clock_source(SystClkSource::Core);
syst.set_reload(8_000_000); // 1s
syst.enable_counter();
loop {
// busy wait until the timer wraps around
while !syst.has_wrapped() {}
// trigger the `EXTI0` interrupt
nvic.set_pending(Interrupt::EXTI0);
}
}
exception!(SYS_TICK, tick, locals: {
ticks: u32 = 0;
});
// try commenting out this line: you'll end in `default_handler` instead of in `exti0`
interrupt!(EXTI0, exti0, state: Option<HStdout> = None);
fn tick(l: &mut SYS_TICK::Locals) {
l.ticks += 1;
// ..
fn exti0(state: &mut Option<HStdout>) {
if state.is_none() {
*state = Some(hio::hstdout().unwrap());
}
if let Some(hstdout) = state.as_mut() {
hstdout.write_str(".").unwrap();
}
}
interrupt!(TIM2, tock, locals: {
tocks: u32 = 0;
});
exception!(HardFault, hard_fault);
fn tock(l: &mut TIM2::Locals) {
l.tocks += 1;
// ..
fn hard_fault(ef: &ExceptionFrame) -> ! {
panic!("HardFault at {:#?}", ef);
}
exception!(*, default_handler);
fn default_handler(irqn: i16) {
panic!("Unhandled exception (IRQn = {})", irqn);
}

64
examples/exception.rs Normal file
View File

@@ -0,0 +1,64 @@
//! Overriding an exception handler
//!
//! You can override an exception handler using the [`exception!`][1] macro.
//!
//! [1]: https://docs.rs/cortex-m-rt/0.5.0/cortex_m_rt/macro.exception.html
//!
//! ---
#![deny(unsafe_code)]
#![no_main]
#![no_std]
extern crate cortex_m;
#[macro_use]
extern crate cortex_m_rt as rt;
extern crate cortex_m_semihosting as sh;
extern crate panic_semihosting;
use core::fmt::Write;
use cortex_m::peripheral::syst::SystClkSource;
use cortex_m::Peripherals;
use rt::ExceptionFrame;
use sh::hio::{self, HStdout};
entry!(main);
fn main() -> ! {
let p = Peripherals::take().unwrap();
let mut syst = p.SYST;
// configures the system timer to trigger a SysTick exception every second
syst.set_clock_source(SystClkSource::Core);
syst.set_reload(8_000_000); // period = 1s
syst.enable_counter();
syst.enable_interrupt();
loop {}
}
// try commenting out this line: you'll end in `default_handler` instead of in `sys_tick`
exception!(SysTick, sys_tick, state: Option<HStdout> = None);
fn sys_tick(state: &mut Option<HStdout>) {
if state.is_none() {
*state = Some(hio::hstdout().unwrap());
}
if let Some(hstdout) = state.as_mut() {
hstdout.write_str(".").unwrap();
}
}
exception!(HardFault, hard_fault);
fn hard_fault(ef: &ExceptionFrame) -> ! {
panic!("HardFault at {:#?}", ef);
}
exception!(*, default_handler);
fn default_handler(irqn: i16) {
panic!("Unhandled exception (IRQn = {})", irqn);
}

View File

@@ -2,28 +2,36 @@
//!
//! ---
#![feature(used)]
#![no_main]
#![no_std]
extern crate cortex_m;
extern crate cortex_m_rt;
extern crate cortex_m_semihosting;
#[macro_use]
extern crate cortex_m_rt as rt;
extern crate cortex_m_semihosting as sh;
extern crate panic_semihosting;
use core::fmt::Write;
use cortex_m::asm;
use cortex_m_semihosting::hio;
use rt::ExceptionFrame;
use sh::hio;
fn main() {
entry!(main);
fn main() -> ! {
let mut stdout = hio::hstdout().unwrap();
writeln!(stdout, "Hello, world!").unwrap();
loop {}
}
// As we are not using interrupts, we just register a dummy catch all handler
#[link_section = ".vector_table.interrupts"]
#[used]
static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240];
exception!(HardFault, hard_fault);
extern "C" fn default_handler() {
asm::bkpt();
fn hard_fault(ef: &ExceptionFrame) -> ! {
panic!("HardFault at {:#?}", ef);
}
exception!(*, default_handler);
fn default_handler(irqn: i16) {
panic!("Unhandled exception (IRQn = {})", irqn);
}

View File

@@ -1,40 +1,54 @@
//! Sends "Hello, world!" through the ITM port 0
//!
//! **IMPORTANT** Not all Cortex-M chips support ITM. You'll have to connect the
//! microcontroller's SWO pin to the SWD interface. Note that some development
//! boards don't provide this option.
//!
//! ITM is much faster than semihosting. Like 4 orders of magnitude or so.
//!
//! You'll need [`itmdump`] to receive the message on the host plus you'll need
//! to uncomment the `monitor` commands in the `.gdbinit` file.
//! **NOTE** Cortex-M0 chips don't support ITM.
//!
//! [`itmdump`]: https://docs.rs/itm/0.1.1/itm/
//! You'll have to connect the microcontroller's SWO pin to the SWD interface. Note that some
//! development boards don't provide this option.
//!
//! You'll need [`itmdump`] to receive the message on the host plus you'll need to uncomment two
//! `monitor` commands in the `.gdbinit` file.
//!
//! [`itmdump`]: https://docs.rs/itm/0.2.1/itm/
//!
//! ---
#![feature(used)]
#![no_main]
#![no_std]
#[macro_use]
extern crate cortex_m;
extern crate cortex_m_rt;
#[macro_use]
extern crate cortex_m_rt as rt;
extern crate panic_semihosting;
use cortex_m::{asm, interrupt, peripheral};
use cortex_m::{asm, Peripherals};
use rt::ExceptionFrame;
fn main() {
interrupt::free(|cs| {
let itm = peripheral::ITM.borrow(&cs);
entry!(main);
iprintln!(&itm.stim[0], "Hello, world!");
});
fn main() -> ! {
let mut p = Peripherals::take().unwrap();
let stim = &mut p.ITM.stim[0];
iprintln!(stim, "Hello, world!");
loop {
asm::bkpt();
}
}
// As we are not using interrupts, we just register a dummy catch all handler
#[link_section = ".vector_table.interrupts"]
#[used]
static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240];
// define the hard fault handler
exception!(HardFault, hard_fault);
extern "C" fn default_handler() {
asm::bkpt();
fn hard_fault(ef: &ExceptionFrame) -> ! {
panic!("HardFault at {:#?}", ef);
}
// define the default exception handler
exception!(*, default_handler);
fn default_handler(irqn: i16) {
panic!("Unhandled exception (IRQn = {})", irqn);
}

40
examples/minimal.rs Normal file
View File

@@ -0,0 +1,40 @@
//! Minimal Cortex-M program
//!
//! When executed this program will hit the breakpoint set in `main`.
//!
//! All Cortex-M programs need to:
//!
//! - Contain the `#![no_main]` and `#![no_std]` attributes. Embedded programs don't use the
//! standard Rust `main` interface or the Rust standard (`std`) library.
//!
//! - Define their entry point using [`entry!`] macro.
//!
//! [`entry!`]: https://docs.rs/cortex-m-rt/~0.5/cortex_m_rt/macro.entry.html
//!
//! - Define their panicking behavior, i.e. what happens when `panic!` is called. The easiest way to
//! define a panicking behavior is to link to a [panic handler crate][0]
//!
//! [0]: https://crates.io/keywords/panic-impl
#![no_main] // <- IMPORTANT!
#![no_std]
extern crate cortex_m;
#[macro_use(entry)]
extern crate cortex_m_rt as rt;
// makes `panic!` print messages to the host stderr using semihosting
extern crate panic_semihosting;
use cortex_m::asm;
// the program entry point is ...
entry!(main);
// ... this never ending function
fn main() -> ! {
loop {
asm::bkpt();
}
}

View File

@@ -1,47 +0,0 @@
//! Overriding an exception handler
//!
//! You can override an exception handler using the [`exception!`][1] macro.
//!
//! [1]: https://docs.rs/cortex-m-rt/0.3.2/cortex_m_rt/macro.exception.html
//!
//! The default exception handler can be overridden using the
//! [`default_handler!`][2] macro
//!
//! [2]: https://docs.rs/cortex-m-rt/0.3.2/cortex_m_rt/macro.default_handler.html
//!
//! ---
#![feature(used)]
#![no_std]
extern crate cortex_m;
#[macro_use(exception)]
extern crate cortex_m_rt;
use core::ptr;
use cortex_m::asm;
fn main() {
unsafe {
// Invalid memory access
ptr::read_volatile(0x2FFF_FFFF as *const u32);
}
}
exception!(HARD_FAULT, handler);
fn handler() {
// You'll hit this breakpoint rather than the one in cortex-m-rt
asm::bkpt()
}
// As we are not using interrupts, we just register a dummy catch all handler
#[allow(dead_code)]
#[used]
#[link_section = ".vector_table.interrupts"]
static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240];
extern "C" fn default_handler() {
asm::bkpt();
}

View File

@@ -1,58 +1,44 @@
//! Defining the panic handler
//! Changing the panic handler
//!
//! The panic handler can be defined through the `panic_fmt` [language item][1].
//! Make sure that the "abort-on-panic" feature of the cortex-m-rt crate is
//! disabled to avoid redefining the language item.
//! The easiest way to change the panic handler is to use a different [panic handler crate][0].
//!
//! [1]: https://doc.rust-lang.org/unstable-book/language-features/lang-items.html
//! [0]: https://crates.io/keywords/panic-impl
//!
//! ---
#![feature(core_intrinsics)]
#![feature(lang_items)]
#![feature(used)]
#![no_main]
#![no_std]
extern crate cortex_m;
extern crate cortex_m_rt;
extern crate cortex_m_semihosting;
#[macro_use]
extern crate cortex_m_rt as rt;
use core::fmt::Write;
use core::intrinsics;
// Pick one of these two panic handlers:
use cortex_m::asm;
use cortex_m_semihosting::hio;
// Reports panic messages to the host stderr using semihosting
extern crate panic_semihosting;
fn main() {
panic!("Oops");
// Logs panic messages using the ITM (Instrumentation Trace Macrocell)
// NOTE to use this you need to uncomment the `panic-itm` dependency in Cargo.toml
// extern crate panic_itm;
use rt::ExceptionFrame;
entry!(main);
fn main() -> ! {
panic!("Oops")
}
#[lang = "panic_fmt"]
#[no_mangle]
unsafe extern "C" fn rust_begin_unwind(
args: core::fmt::Arguments,
file: &'static str,
line: u32,
col: u32,
) -> ! {
if let Ok(mut stdout) = hio::hstdout() {
write!(stdout, "panicked at '")
.and_then(|_| {
stdout
.write_fmt(args)
.and_then(|_| writeln!(stdout, "', {}:{}", file, line))
})
.ok();
}
// define the hard fault handler
exception!(HardFault, hard_fault);
intrinsics::abort()
fn hard_fault(ef: &ExceptionFrame) -> ! {
panic!("HardFault at {:#?}", ef);
}
// As we are not using interrupts, we just register a dummy catch all handler
#[link_section = ".vector_table.interrupts"]
#[used]
static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240];
// define the default exception handler
exception!(*, default_handler);
extern "C" fn default_handler() {
asm::bkpt();
fn default_handler(irqn: i16) {
panic!("Unhandled exception (IRQn = {})", irqn);
}

View File

@@ -5,13 +5,14 @@ set -ex
main() {
local examples=(
minimal
hello
itm
panic
crash
override-exception-handler
device
exception
allocator
device
)
rm -rf src/examples
@@ -19,7 +20,7 @@ main() {
mkdir src/examples
cat >src/examples/mod.rs <<'EOF'
//! Examples
//! Examples sorted in increasing degree of complexity
// Auto-generated. Do not modify.
EOF

View File

@@ -2,8 +2,8 @@ MEMORY
{
/* NOTE K = KiBi = 1024 bytes */
/* TODO Adjust these memory regions to match your device memory layout */
FLASH : ORIGIN = 0xBAAAAAAD, LENGTH = 0K
RAM : ORIGIN = 0xBAAAAAAD, LENGTH = 0K
FLASH : ORIGIN = 0x000BAAD0, LENGTH = 0K
RAM : ORIGIN = 0xBAAD0000, LENGTH = 0K
}
/* This is where the call stack will be allocated. */
@@ -18,3 +18,6 @@ MEMORY
/* This is required only on microcontrollers that store some configuration right
after the vector table */
/* _stext = ORIGIN(FLASH) + 0x400; */
/* Size of the heap (in bytes) */
/* _heap_size = 1024; */

View File

@@ -1,33 +0,0 @@
//! Prints "Hello, world!" on the OpenOCD console using semihosting
//!
//! ---
//!
//! ```
//!
//! #![feature(used)]
//! #![no_std]
//!
//! extern crate cortex_m;
//! extern crate cortex_m_rt;
//! extern crate cortex_m_semihosting;
//!
//! use core::fmt::Write;
//!
//! use cortex_m::asm;
//! use cortex_m_semihosting::hio;
//!
//! fn main() {
//! let mut stdout = hio::hstdout().unwrap();
//! writeln!(stdout, "Hello, world!").unwrap();
//! }
//!
//! // As we are not using interrupts, we just register a dummy catch all handler
//! #[link_section = ".vector_table.interrupts"]
//! #[used]
//! static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240];
//!
//! extern "C" fn default_handler() {
//! asm::bkpt();
//! }
//! ```
// Auto-generated. Do not modify.

View File

@@ -0,0 +1,67 @@
//! Minimal Cortex-M program
//!
//! When executed this program will hit the breakpoint set in `main`.
//!
//! All Cortex-M programs need to:
//!
//! - Contain the `#![no_main]` and `#![no_std]` attributes. Embedded programs don't use the
//! standard Rust `main` interface or the Rust standard (`std`) library.
//!
//! - Define their entry point using [`entry!`] macro.
//!
//! [`entry!`]: https://docs.rs/cortex-m-rt/~0.5/cortex_m_rt/macro.entry.html
//!
//! - Define their panicking behavior, i.e. what happens when `panic!` is called. The easiest way to
//! define a panicking behavior is to link to a [panic handler crate][0]
//!
//! [0]: https://crates.io/keywords/panic-impl
//!
//! - Define the `HardFault` handler using the [`exception!`] macro. This handler (function) is
//! called when a hard fault exception is raised by the hardware.
//!
//! [`exception!`]: https://docs.rs/cortex-m-rt/~0.5/cortex_m_rt/macro..html
//!
//! - Define a default handler using the [`exception!`] macro. This function will be used to handle
//! all interrupts and exceptions which have not been assigned a specific handler.
//!
//! ```
//!
//! #![no_main] // <- IMPORTANT!
//! #![no_std]
//!
//! extern crate cortex_m;
//!
//! #[macro_use(entry, exception)]
//! extern crate cortex_m_rt as rt;
//!
//! // makes `panic!` print messages to the host stderr using semihosting
//! extern crate panic_semihosting;
//!
//! use cortex_m::asm;
//! use rt::ExceptionFrame;
//!
//! // the program entry point is ...
//! entry!(main);
//!
//! // ... this never ending function
//! fn main() -> ! {
//! loop {
//! asm::bkpt();
//! }
//! }
//!
//! // define the hard fault handler
//! exception!(HardFault, hard_fault);
//!
//! fn hard_fault(ef: &ExceptionFrame) -> ! {
//! panic!("HardFault at {:#?}", ef);
//! }
//!
//! // define the default exception handler
//! exception!(*, default_handler);
//!
//! fn default_handler(irqn: i16) {
//! panic!("Unhandled exception (IRQn = {})", irqn);
//! }
//! ```
// Auto-generated. Do not modify.

41
src/examples/_1_hello.rs Normal file
View File

@@ -0,0 +1,41 @@
//! Prints "Hello, world!" on the OpenOCD console using semihosting
//!
//! ---
//!
//! ```
//!
//! #![no_main]
//! #![no_std]
//!
//! #[macro_use]
//! extern crate cortex_m_rt as rt;
//! extern crate cortex_m_semihosting as sh;
//! extern crate panic_semihosting;
//!
//! use core::fmt::Write;
//!
//! use rt::ExceptionFrame;
//! use sh::hio;
//!
//! entry!(main);
//!
//! fn main() -> ! {
//! let mut stdout = hio::hstdout().unwrap();
//! writeln!(stdout, "Hello, world!").unwrap();
//!
//! loop {}
//! }
//!
//! exception!(HardFault, hard_fault);
//!
//! fn hard_fault(ef: &ExceptionFrame) -> ! {
//! panic!("HardFault at {:#?}", ef);
//! }
//!
//! exception!(*, default_handler);
//!
//! fn default_handler(irqn: i16) {
//! panic!("Unhandled exception (IRQn = {})", irqn);
//! }
//! ```
// Auto-generated. Do not modify.

View File

@@ -1,44 +0,0 @@
//! Sends "Hello, world!" through the ITM port 0
//!
//! **IMPORTANT** Not all Cortex-M chips support ITM. You'll have to connect the
//! microcontroller's SWO pin to the SWD interface. Note that some development
//! boards don't provide this option.
//!
//! ITM is much faster than semihosting. Like 4 orders of magnitude or so.
//!
//! You'll need [`itmdump`] to receive the message on the host plus you'll need
//! to uncomment the `monitor` commands in the `.gdbinit` file.
//!
//! [`itmdump`]: https://docs.rs/itm/0.1.1/itm/
//!
//! ---
//!
//! ```
//!
//! #![feature(used)]
//! #![no_std]
//!
//! #[macro_use]
//! extern crate cortex_m;
//! extern crate cortex_m_rt;
//!
//! use cortex_m::{asm, interrupt, peripheral};
//!
//! fn main() {
//! interrupt::free(|cs| {
//! let itm = peripheral::ITM.borrow(&cs);
//!
//! iprintln!(&itm.stim[0], "Hello, world!");
//! });
//! }
//!
//! // As we are not using interrupts, we just register a dummy catch all handler
//! #[link_section = ".vector_table.interrupts"]
//! #[used]
//! static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240];
//!
//! extern "C" fn default_handler() {
//! asm::bkpt();
//! }
//! ```
// Auto-generated. Do not modify.

58
src/examples/_2_itm.rs Normal file
View File

@@ -0,0 +1,58 @@
//! Sends "Hello, world!" through the ITM port 0
//!
//! ITM is much faster than semihosting. Like 4 orders of magnitude or so.
//!
//! **NOTE** Cortex-M0 chips don't support ITM.
//!
//! You'll have to connect the microcontroller's SWO pin to the SWD interface. Note that some
//! development boards don't provide this option.
//!
//! You'll need [`itmdump`] to receive the message on the host plus you'll need to uncomment two
//! `monitor` commands in the `.gdbinit` file.
//!
//! [`itmdump`]: https://docs.rs/itm/0.2.1/itm/
//!
//! ---
//!
//! ```
//!
//! #![no_main]
//! #![no_std]
//!
//! #[macro_use]
//! extern crate cortex_m;
//! #[macro_use]
//! extern crate cortex_m_rt as rt;
//! extern crate panic_semihosting;
//!
//! use cortex_m::{asm, Peripherals};
//! use rt::ExceptionFrame;
//!
//! entry!(main);
//!
//! fn main() -> ! {
//! let mut p = Peripherals::take().unwrap();
//! let stim = &mut p.ITM.stim[0];
//!
//! iprintln!(stim, "Hello, world!");
//!
//! loop {
//! asm::bkpt();
//! }
//! }
//!
//! // define the hard fault handler
//! exception!(HardFault, hard_fault);
//!
//! fn hard_fault(ef: &ExceptionFrame) -> ! {
//! panic!("HardFault at {:#?}", ef);
//! }
//!
//! // define the default exception handler
//! exception!(*, default_handler);
//!
//! fn default_handler(irqn: i16) {
//! panic!("Unhandled exception (IRQn = {})", irqn);
//! }
//! ```
// Auto-generated. Do not modify.

View File

@@ -1,62 +0,0 @@
//! Defining the panic handler
//!
//! The panic handler can be defined through the `panic_fmt` [language item][1].
//! Make sure that the "abort-on-panic" feature of the cortex-m-rt crate is
//! disabled to avoid redefining the language item.
//!
//! [1]: https://doc.rust-lang.org/unstable-book/language-features/lang-items.html
//!
//! ---
//!
//! ```
//!
//! #![feature(core_intrinsics)]
//! #![feature(lang_items)]
//! #![feature(used)]
//! #![no_std]
//!
//! extern crate cortex_m;
//! extern crate cortex_m_rt;
//! extern crate cortex_m_semihosting;
//!
//! use core::fmt::Write;
//! use core::intrinsics;
//!
//! use cortex_m::asm;
//! use cortex_m_semihosting::hio;
//!
//! fn main() {
//! panic!("Oops");
//! }
//!
//! #[lang = "panic_fmt"]
//! #[no_mangle]
//! unsafe extern "C" fn rust_begin_unwind(
//! args: core::fmt::Arguments,
//! file: &'static str,
//! line: u32,
//! col: u32,
//! ) -> ! {
//! if let Ok(mut stdout) = hio::hstdout() {
//! write!(stdout, "panicked at '")
//! .and_then(|_| {
//! stdout
//! .write_fmt(args)
//! .and_then(|_| writeln!(stdout, "', {}:{}", file, line))
//! })
//! .ok();
//! }
//!
//! intrinsics::abort()
//! }
//!
//! // As we are not using interrupts, we just register a dummy catch all handler
//! #[link_section = ".vector_table.interrupts"]
//! #[used]
//! static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240];
//!
//! extern "C" fn default_handler() {
//! asm::bkpt();
//! }
//! ```
// Auto-generated. Do not modify.

View File

@@ -1,89 +0,0 @@
//! Debugging a crash (exception)
//!
//! The `cortex-m-rt` crate provides functionality for this through a default
//! exception handler. When an exception is hit, the default handler will
//! trigger a breakpoint and in this debugging context the stacked registers
//! are accessible.
//!
//! In you run the example below, you'll be able to inspect the state of your
//! program under the debugger using these commands:
//!
//! ``` text
//! (gdb) # Exception frame = program state during the crash
//! (gdb) print/x *ef
//! $1 = cortex_m::exception::ExceptionFrame {
//! r0 = 0x2fffffff,
//! r1 = 0x2fffffff,
//! r2 = 0x0,
//! r3 = 0x0,
//! r12 = 0x0,
//! lr = 0x8000481,
//! pc = 0x8000460,
//! xpsr = 0x61000000,
//! }
//!
//! (gdb) # Where did we come from?
//! (gdb) backtrace
//! #0 cortex_m_rt::default_handler (ef=0x20004f54) at (..)
//! #1 <signal handler called>
//! #2 0x08000460 in core::ptr::read_volatile<u32> (src=0x2fffffff) at (..)
//! #3 0x08000480 in crash::main () at examples/crash.rs:68
//!
//! (gdb) # Nail down the location of the crash
//! (gdb) disassemble/m ef.pc
//! Dump of assembler code for function core::ptr::read_volatile<u32>:
//! 408 pub unsafe fn read_volatile<T>(src: *const T) -> T {
//! 0x08000454 <+0>: sub sp, #20
//! 0x08000456 <+2>: mov r1, r0
//! 0x08000458 <+4>: str r0, [sp, #8]
//! 0x0800045a <+6>: ldr r0, [sp, #8]
//! 0x0800045c <+8>: str r0, [sp, #12]
//!
//! 409 intrinsics::volatile_load(src)
//! 0x0800045e <+10>: ldr r0, [sp, #12]
//! 0x08000460 <+12>: ldr r0, [r0, #0]
//! 0x08000462 <+14>: str r0, [sp, #16]
//! 0x08000464 <+16>: ldr r0, [sp, #16]
//! 0x08000466 <+18>: str r1, [sp, #4]
//! 0x08000468 <+20>: str r0, [sp, #0]
//! 0x0800046a <+22>: b.n 0x800046c <core::ptr::read_volatile<u32>+24>
//!
//! 410 }
//! 0x0800046c <+24>: ldr r0, [sp, #0]
//! 0x0800046e <+26>: add sp, #20
//! 0x08000470 <+28>: bx lr
//!
//! End of assembler dump.
//! ```
//!
//! ---
//!
//! ```
//!
//! #![feature(used)]
//! #![no_std]
//!
//! extern crate cortex_m;
//! extern crate cortex_m_rt;
//!
//! use core::ptr;
//!
//! use cortex_m::asm;
//!
//! fn main() {
//! // Read an invalid memory address
//! unsafe {
//! ptr::read_volatile(0x2FFF_FFFF as *const u32);
//! }
//! }
//!
//! // As we are not using interrupts, we just register a dummy catch all handler
//! #[link_section = ".vector_table.interrupts"]
//! #[used]
//! static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240];
//!
//! extern "C" fn default_handler() {
//! asm::bkpt();
//! }
//! ```
// Auto-generated. Do not modify.

47
src/examples/_3_panic.rs Normal file
View File

@@ -0,0 +1,47 @@
//! Changing the panic handler
//!
//! The easiest way to change the panic handler is to use a different [panic handler crate][0].
//!
//! [0]: https://crates.io/keywords/panic-impl
//!
//! ---
//!
//! ```
//!
//! #![no_main]
//! #![no_std]
//!
//! #[macro_use]
//! extern crate cortex_m_rt as rt;
//!
//! // Pick one of these two panic handlers:
//!
//! // Reports panic messages to the host stderr using semihosting
//! extern crate panic_semihosting;
//!
//! // Logs panic messages using the ITM (Instrumentation Trace Macrocell)
//! // extern crate panic_itm;
//!
//! use rt::ExceptionFrame;
//!
//! entry!(main);
//!
//! fn main() -> ! {
//! panic!("Oops")
//! }
//!
//! // define the hard fault handler
//! exception!(HardFault, hard_fault);
//!
//! fn hard_fault(ef: &ExceptionFrame) -> ! {
//! panic!("HardFault at {:#?}", ef);
//! }
//!
//! // define the default exception handler
//! exception!(*, default_handler);
//!
//! fn default_handler(irqn: i16) {
//! panic!("Unhandled exception (IRQn = {})", irqn);
//! }
//! ```
// Auto-generated. Do not modify.

118
src/examples/_4_crash.rs Normal file
View File

@@ -0,0 +1,118 @@
//! Debugging a crash (exception)
//!
//! Most crash conditions trigger a hard fault exception, whose handler is defined via
//! `exception!(HardFault, ..)`. The `HardFault` handler has access to the exception frame, a
//! snapshot of the CPU registers at the moment of the exception.
//!
//! This program crashes and the `HardFault` handler prints to the console the contents of the
//! `ExceptionFrame` and then triggers a breakpoint. From that breakpoint one can see the backtrace
//! that led to the exception.
//!
//! ``` text
//! (gdb) continue
//! Program received signal SIGTRAP, Trace/breakpoint trap.
//! __bkpt () at asm/bkpt.s:3
//! 3 bkpt
//!
//! (gdb) backtrace
//! #0 __bkpt () at asm/bkpt.s:3
//! #1 0x080030b4 in cortex_m::asm::bkpt () at $$/cortex-m-0.5.0/src/asm.rs:19
//! #2 rust_begin_unwind (args=..., file=..., line=99, col=5) at $$/panic-semihosting-0.2.0/src/lib.rs:87
//! #3 0x08001d06 in core::panicking::panic_fmt () at libcore/panicking.rs:71
//! #4 0x080004a6 in crash::hard_fault (ef=0x20004fa0) at examples/crash.rs:99
//! #5 0x08000548 in UserHardFault (ef=0x20004fa0) at <exception macros>:10
//! #6 0x0800093a in HardFault () at asm.s:5
//! Backtrace stopped: previous frame identical to this frame (corrupt stack?)
//! ```
//!
//! In the console output one will find the state of the Program Counter (PC) register at the time
//! of the exception.
//!
//! ``` text
//! panicked at 'HardFault at ExceptionFrame {
//! r0: 0x2fffffff,
//! r1: 0x2fffffff,
//! r2: 0x080051d4,
//! r3: 0x080051d4,
//! r12: 0x20000000,
//! lr: 0x08000435,
//! pc: 0x08000ab6,
//! xpsr: 0x61000000
//! }', examples/crash.rs:106:5
//! ```
//!
//! This register contains the address of the instruction that caused the exception. In GDB one can
//! disassemble the program around this address to observe the instruction that caused the
//! exception.
//!
//! ``` text
//! (gdb) disassemble/m 0x08000ab6
//! Dump of assembler code for function core::ptr::read_volatile:
//! 451 pub unsafe fn read_volatile<T>(src: *const T) -> T {
//! 0x08000aae <+0>: sub sp, #16
//! 0x08000ab0 <+2>: mov r1, r0
//! 0x08000ab2 <+4>: str r0, [sp, #8]
//!
//! 452 intrinsics::volatile_load(src)
//! 0x08000ab4 <+6>: ldr r0, [sp, #8]
//! -> 0x08000ab6 <+8>: ldr r0, [r0, #0]
//! 0x08000ab8 <+10>: str r0, [sp, #12]
//! 0x08000aba <+12>: ldr r0, [sp, #12]
//! 0x08000abc <+14>: str r1, [sp, #4]
//! 0x08000abe <+16>: str r0, [sp, #0]
//! 0x08000ac0 <+18>: b.n 0x8000ac2 <core::ptr::read_volatile+20>
//!
//! 453 }
//! 0x08000ac2 <+20>: ldr r0, [sp, #0]
//! 0x08000ac4 <+22>: add sp, #16
//! 0x08000ac6 <+24>: bx lr
//!
//! End of assembler dump.
//! ```
//!
//! `ldr r0, [r0, #0]` caused the exception. This instruction tried to load (read) a 32-bit word
//! from the address stored in the register `r0`. Looking again at the contents of `ExceptionFrame`
//! we see that the `r0` contained the address `0x2FFF_FFFF` when this instruction was executed.
//!
//! ---
//!
//! ```
//!
//! #![no_main]
//! #![no_std]
//!
//! extern crate cortex_m;
//! #[macro_use]
//! extern crate cortex_m_rt as rt;
//! extern crate panic_semihosting;
//!
//! use core::ptr;
//!
//! use rt::ExceptionFrame;
//!
//! entry!(main);
//!
//! fn main() -> ! {
//! unsafe {
//! // read an address outside of the RAM region; causes a HardFault exception
//! ptr::read_volatile(0x2FFF_FFFF as *const u32);
//! }
//!
//! loop {}
//! }
//!
//! // define the hard fault handler
//! exception!(HardFault, hard_fault);
//!
//! fn hard_fault(ef: &ExceptionFrame) -> ! {
//! panic!("HardFault at {:#?}", ef);
//! }
//!
//! // define the default exception handler
//! exception!(*, default_handler);
//!
//! fn default_handler(irqn: i16) {
//! panic!("Unhandled exception (IRQn = {})", irqn);
//! }
//! ```
// Auto-generated. Do not modify.

View File

@@ -1,51 +0,0 @@
//! Overriding an exception handler
//!
//! You can override an exception handler using the [`exception!`][1] macro.
//!
//! [1]: https://docs.rs/cortex-m-rt/0.3.2/cortex_m_rt/macro.exception.html
//!
//! The default exception handler can be overridden using the
//! [`default_handler!`][2] macro
//!
//! [2]: https://docs.rs/cortex-m-rt/0.3.2/cortex_m_rt/macro.default_handler.html
//!
//! ---
//!
//! ```
//!
//! #![feature(used)]
//! #![no_std]
//!
//! extern crate cortex_m;
//! #[macro_use(exception)]
//! extern crate cortex_m_rt;
//!
//! use core::ptr;
//!
//! use cortex_m::asm;
//!
//! fn main() {
//! unsafe {
//! // Invalid memory access
//! ptr::read_volatile(0x2FFF_FFFF as *const u32);
//! }
//! }
//!
//! exception!(HARD_FAULT, handler);
//!
//! fn handler() {
//! // You'll hit this breakpoint rather than the one in cortex-m-rt
//! asm::bkpt()
//! }
//!
//! // As we are not using interrupts, we just register a dummy catch all handler
//! #[allow(dead_code)]
//! #[used]
//! #[link_section = ".vector_table.interrupts"]
//! static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240];
//!
//! extern "C" fn default_handler() {
//! asm::bkpt();
//! }
//! ```
// Auto-generated. Do not modify.

View File

@@ -1,62 +0,0 @@
//! Using a device crate
//!
//! Crates generated using [`svd2rust`] are referred to as device crates. These
//! crates provides an API to access the peripherals of a device. When you
//! depend on one of these crates and the "rt" feature is enabled you don't need
//! link to the cortex-m-rt crate.
//!
//! [`svd2rust`]: https://crates.io/crates/svd2rust
//!
//! Device crates also provide an `interrupt!` macro to register interrupt
//! handlers.
//!
//! This example depends on the [`stm32f103xx`] crate so you'll have to add it
//! to your Cargo.toml.
//!
//! [`stm32f103xx`]: https://crates.io/crates/stm32f103xx
//!
//! ```
//! $ edit Cargo.toml && cat $_
//! [dependencies.stm32f103xx]
//! features = ["rt"]
//! version = "0.7.0"
//! ```
//!
//! ---
//!
//! ```
//!
//! #![no_std]
//!
//! extern crate cortex_m;
//! #[macro_use(exception, interrupt)]
//! extern crate stm32f103xx;
//!
//! use cortex_m::interrupt;
//!
//! fn main() {
//! interrupt::free(|cs| {
//! let _gpioa = stm32f103xx::GPIOA.borrow(cs);
//! // do something with GPIOA
//! });
//! }
//!
//! exception!(SYS_TICK, tick, locals: {
//! ticks: u32 = 0;
//! });
//!
//! fn tick(l: &mut SYS_TICK::Locals) {
//! l.ticks += 1;
//! // ..
//! }
//!
//! interrupt!(TIM2, tock, locals: {
//! tocks: u32 = 0;
//! });
//!
//! fn tock(l: &mut TIM2::Locals) {
//! l.tocks += 1;
//! // ..
//! }
//! ```
// Auto-generated. Do not modify.

View File

@@ -0,0 +1,68 @@
//! Overriding an exception handler
//!
//! You can override an exception handler using the [`exception!`][1] macro.
//!
//! [1]: https://docs.rs/cortex-m-rt/0.5.0/cortex_m_rt/macro.exception.html
//!
//! ---
//!
//! ```
//!
//! #![deny(unsafe_code)]
//! #![no_main]
//! #![no_std]
//!
//! extern crate cortex_m;
//! #[macro_use]
//! extern crate cortex_m_rt as rt;
//! extern crate cortex_m_semihosting as sh;
//! extern crate panic_semihosting;
//!
//! use core::fmt::Write;
//!
//! use cortex_m::peripheral::syst::SystClkSource;
//! use cortex_m::Peripherals;
//! use rt::ExceptionFrame;
//! use sh::hio::{self, HStdout};
//!
//! entry!(main);
//!
//! fn main() -> ! {
//! let p = Peripherals::take().unwrap();
//! let mut syst = p.SYST;
//!
//! // configures the system timer to trigger a SysTick exception every second
//! syst.set_clock_source(SystClkSource::Core);
//! syst.set_reload(8_000_000); // period = 1s
//! syst.enable_counter();
//! syst.enable_interrupt();
//!
//! loop {}
//! }
//!
//! // try commenting out this line: you'll end in `default_handler` instead of in `sys_tick`
//! exception!(SysTick, sys_tick, state: Option<HStdout> = None);
//!
//! fn sys_tick(state: &mut Option<HStdout>) {
//! if state.is_none() {
//! *state = Some(hio::hstdout().unwrap());
//! }
//!
//! if let Some(hstdout) = state.as_mut() {
//! hstdout.write_str(".").unwrap();
//! }
//! }
//!
//! exception!(HardFault, hard_fault);
//!
//! fn hard_fault(ef: &ExceptionFrame) -> ! {
//! panic!("HardFault at {:#?}", ef);
//! }
//!
//! exception!(*, default_handler);
//!
//! fn default_handler(irqn: i16) {
//! panic!("Unhandled exception (IRQn = {})", irqn);
//! }
//! ```
// Auto-generated. Do not modify.

View File

@@ -1,23 +1,6 @@
//! How to use the heap and a dynamic memory allocator
//!
//! To compile this example you'll need to build the collections crate as part
//! of the Xargo sysroot. To do that change the Xargo.toml file to look like
//! this:
//!
//! ``` text
//! [dependencies.core]
//! stage = 0
//!
//! [dependencies.collections] # NEW
//! stage = 0
//!
//! [dependencies.compiler_builtins]
//! git = "https://github.com/rust-lang-nursery/compiler-builtins"
//! stage = 1
//! ```
//!
//! This example depends on the alloc-cortex-m crate so you'll have to add it
//! to your Cargo.toml:
//! This example depends on the alloc-cortex-m crate so you'll have to add it to your Cargo.toml:
//!
//! ``` text
//! # or edit the Cargo.toml file manually
@@ -27,58 +10,70 @@
//! ---
//!
//! ```
//!
//! #[allow(deprecated)]
//! #![feature(collections)]
//! #![feature(used)]
//!
//! #![feature(alloc)]
//! #![feature(global_allocator)]
//! #![feature(lang_items)]
//! #![no_main]
//! #![no_std]
//!
//!
//! // This is the allocator crate; you can use a different one
//! extern crate alloc_cortex_m;
//! #[macro_use]
//! extern crate collections;
//! extern crate alloc;
//! extern crate cortex_m;
//! extern crate cortex_m_rt;
//! extern crate cortex_m_semihosting;
//!
//! #[macro_use]
//! extern crate cortex_m_rt as rt;
//! extern crate cortex_m_semihosting as sh;
//! extern crate panic_semihosting;
//!
//! use core::fmt::Write;
//!
//!
//! use alloc_cortex_m::CortexMHeap;
//! use cortex_m::asm;
//! use cortex_m_semihosting::hio;
//!
//! fn main() {
//! // Initialize the allocator
//! unsafe {
//! extern "C" {
//! // Start of the heap
//! static mut _sheap: usize;
//! }
//!
//! // Size of the heap in words (1 word = 4 bytes)
//! // NOTE The bigger the heap the greater the chance to run into a stack
//! // overflow (collision between the stack and the heap)
//! const SIZE: isize = 256;
//!
//! // End of the heap
//! let _eheap = (&mut _sheap as *mut _).offset(SIZE);
//!
//! alloc_cortex_m::init(&mut _sheap, _eheap);
//! }
//!
//! use rt::ExceptionFrame;
//! use sh::hio;
//!
//! // this is the allocator the application will use
//! #[global_allocator]
//! static ALLOCATOR: CortexMHeap = CortexMHeap::empty();
//!
//! const HEAP_SIZE: usize = 1024; // in bytes
//!
//! entry!(main);
//!
//! fn main() -> ! {
//! // Initialize the allocator BEFORE you use it
//! unsafe { ALLOCATOR.init(rt::heap_start() as usize, HEAP_SIZE) }
//!
//! // Growable array allocated on the heap
//! let xs = vec![0, 1, 2];
//!
//!
//! let mut stdout = hio::hstdout().unwrap();
//! writeln!(stdout, "{:?}", xs).unwrap();
//!
//! loop {}
//! }
//!
//! // As we are not using interrupts, we just register a dummy catch all handler
//! #[link_section = ".vector_table.interrupts"]
//! #[used]
//! static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240];
//!
//! extern "C" fn default_handler() {
//!
//! // define what happens in an Out Of Memory (OOM) condition
//! #[lang = "oom"]
//! #[no_mangle]
//! pub fn rust_oom() -> ! {
//! asm::bkpt();
//!
//! loop {}
//! }
//!
//! exception!(HardFault, hard_fault);
//!
//! fn hard_fault(ef: &ExceptionFrame) -> ! {
//! panic!("HardFault at {:#?}", ef);
//! }
//!
//! exception!(*, default_handler);
//!
//! fn default_handler(irqn: i16) {
//! panic!("Unhandled exception (IRQn = {})", irqn);
//! }
//! ```
// Auto-generated. Do not modify.

93
src/examples/_7_device.rs Normal file
View File

@@ -0,0 +1,93 @@
//! Using a device crate
//!
//! Crates generated using [`svd2rust`] are referred to as device crates. These crates provide an
//! API to access the peripherals of a device.
//!
//! [`svd2rust`]: https://crates.io/crates/svd2rust
//!
//! Device crates also provide an `interrupt!` macro (behind the "rt" feature) to register interrupt
//! handlers.
//!
//! This example depends on the [`stm32f103xx`] crate so you'll have to add it to your Cargo.toml.
//!
//! [`stm32f103xx`]: https://crates.io/crates/stm32f103xx
//!
//! ```
//! $ edit Cargo.toml && tail $_
//! [dependencies.stm32f103xx]
//! features = ["rt"]
//! version = "0.10.0"
//! ```
//!
//! ---
//!
//! ```
//!
//! #![no_main]
//! #![no_std]
//!
//! extern crate cortex_m;
//! #[macro_use]
//! extern crate cortex_m_rt as rt;
//! extern crate cortex_m_semihosting as sh;
//! #[macro_use]
//! extern crate stm32f103xx;
//! extern crate panic_semihosting;
//!
//! use core::fmt::Write;
//!
//! use cortex_m::peripheral::syst::SystClkSource;
//! use rt::ExceptionFrame;
//! use sh::hio::{self, HStdout};
//! use stm32f103xx::Interrupt;
//!
//! entry!(main);
//!
//! fn main() -> ! {
//! let p = cortex_m::Peripherals::take().unwrap();
//!
//! let mut syst = p.SYST;
//! let mut nvic = p.NVIC;
//!
//! nvic.enable(Interrupt::EXTI0);
//!
//! // configure the system timer to wrap around every second
//! syst.set_clock_source(SystClkSource::Core);
//! syst.set_reload(8_000_000); // 1s
//! syst.enable_counter();
//!
//! loop {
//! // busy wait until the timer wraps around
//! while !syst.has_wrapped() {}
//!
//! // trigger the `EXTI0` interrupt
//! nvic.set_pending(Interrupt::EXTI0);
//! }
//! }
//!
//! // try commenting out this line: you'll end in `default_handler` instead of in `exti0`
//! interrupt!(EXTI0, exti0, state: Option<HStdout> = None);
//!
//! fn exti0(state: &mut Option<HStdout>) {
//! if state.is_none() {
//! *state = Some(hio::hstdout().unwrap());
//! }
//!
//! if let Some(hstdout) = state.as_mut() {
//! hstdout.write_str(".").unwrap();
//! }
//! }
//!
//! exception!(HardFault, hard_fault);
//!
//! fn hard_fault(ef: &ExceptionFrame) -> ! {
//! panic!("HardFault at {:#?}", ef);
//! }
//!
//! exception!(*, default_handler);
//!
//! fn default_handler(irqn: i16) {
//! panic!("Unhandled exception (IRQn = {})", irqn);
//! }
//! ```
// Auto-generated. Do not modify.

View File

@@ -1,9 +1,10 @@
//! Examples
//! Examples sorted in increasing degree of complexity
// Auto-generated. Do not modify.
pub mod _0_hello;
pub mod _1_itm;
pub mod _2_panic;
pub mod _3_crash;
pub mod _4_override_exception_handler;
pub mod _5_device;
pub mod _0_minimal;
pub mod _1_hello;
pub mod _2_itm;
pub mod _3_panic;
pub mod _4_crash;
pub mod _5_exception;
pub mod _6_allocator;
pub mod _7_device;

View File

@@ -2,23 +2,34 @@
//!
//! # Dependencies
//!
//! - Nightly Rust toolchain: `rustup default nightly`
//! - ARM linker: `sudo apt-get install binutils-arm-none-eabi`
//! - Nightly Rust toolchain from 2018-08-28 or newer: `rustup default nightly`
//! - Cargo `clone` subcommand: `cargo install cargo-clone`
//! - GDB: `sudo apt-get install gdb-arm-none-eabi`
//! - OpenOCD: `sudo apt-get install OpenOCD`
//! - Xargo: `cargo install xargo`
//! - GDB: `sudo apt-get install gdb-arm-none-eabi` (on Ubuntu)
//! - OpenOCD: `sudo apt-get install OpenOCD` (on Ubuntu)
//! - [Optional] Cargo `add` subcommand: `cargo install cargo-edit`
//!
//! # Usage
//!
//! - Clone this crate
//! 0) Figure out the cross compilation *target* to use.
//!
//! ``` text
//! $ cargo clone cortex-m-quickstart && cd $_
//! - Use `thumbv6m-none-eabi` for ARM Cortex-M0 and Cortex-M0+
//! - Use `thumbv7m-none-eabi` for ARM Cortex-M3
//! - Use `thumbv7em-none-eabi` for ARM Cortex-M4 and Cortex-M7 (*no* FPU support)
//! - Use `thumbv7em-none-eabihf` for ARM Cortex-M4**F** and Cortex-M7**F** (*with* FPU support)
//!
//! 1) Install the `rust-std` component for your target, if you haven't done so already
//!
//! ``` console
//! $ rustup target add thumbv7em-none-eabihf
//! ```
//!
//! - Change the crate name, author and version
//! 2) Clone this crate
//!
//! ``` text
//! $ cargo clone cortex-m-quickstart --vers 0.3.4
//! ```
//!
//! 3) Change the crate name, author and version
//!
//! ``` text
//! $ edit Cargo.toml && head $_
@@ -28,23 +39,25 @@
//! version = "0.1.0"
//! ```
//!
//! - Specify the memory layout of the target device
//! 4) Specify the memory layout of the target device
//!
//! (Note that some board support crates may provide this file for you (check
//! the crate documentation). If you are using one that does that then remove
//! *both* the `memory.x` and `build.rs` files.)
//! **NOTE** board support crates sometimes provide this file for you (check the crate
//! documentation). If you are using one that does then remove *both* `memory.x` and `build.rs` from
//! the root of this crate.
//!
//! ``` text
//! $ edit memory.x && cat $_
//! $ cat >memory.x <<'EOF'
//! MEMORY
//! {
//! /* NOTE K = KiBi = 1024 bytes */
//! FLASH : ORIGIN = 0x08000000, LENGTH = 256K
//! RAM : ORIGIN = 0x20000000, LENGTH = 40K
//! }
//! EOF
//! ```
//!
//! - Optionally, set a default build target
//! 5) Optionally, set a default build target. This way you don't have to pass `--target` to each
//! Cargo invocation.
//!
//! ``` text
//! $ cat >>.cargo/config <<'EOF'
@@ -53,35 +66,31 @@
//! EOF
//! ```
//!
//! - Very likely, depend on a device or a BSP (Board Support Package) crate.
//! 6) Optionally, depend on a device, HAL implementation or a board support crate.
//!
//! ``` text
//! # add a device crate, or
//! $ cargo add stm32f103xx
//! $ # add a device crate, OR
//! $ cargo add stm32f30x
//!
//! # add a board support crate
//! $ cargo add blue-pill --git https://github.com/japaric/blue-pill
//! $ # add a HAL implementation crate, OR
//! $ cargo add stm32f30x-hal
//!
//! $ # add a board support crate
//! $ cargo add f3
//! ```
//!
//! - Write the application or start from one of the examples
//! 7) Write the application or start from one of the examples
//!
//! ``` text
//! $ rm -r src/* && cp examples/hello.rs src/main.rs
//! ```
//!
//! - Disable incremental compilation. It doesn't work for embedded development.
//! You'll hit nonsensical linker errors if you use it.
//! 8) Build the application
//!
//! ``` text
//! $ unset CARGO_INCREMENTAL
//! ```
//!
//! - Build the application
//!
//! ``` text
//! # NOTE this command requires `arm-none-eabi-ld` to be in $PATH
//! $ xargo build --release
//! $ cargo build --release
//!
//! $ # sanity check
//! $ arm-none-eabi-readelf -A target/thumbv7em-none-eabihf/release/demo
//! Attribute Section: aeabi
//! File Attributes
@@ -104,22 +113,19 @@
//! Tag_ABI_FP_16bit_format: IEEE 754
//! ```
//!
//! - Flash the program
//! 9) Flash and debug the program
//!
//! ``` text
//! # Launch OpenOCD on a terminal
//! $ # Launch OpenOCD on a terminal
//! $ openocd -f (..)
//! ```
//!
//! ``` text
//! # Start a debug session in another terminal
//! $ arm-none-eabi-gdb target/..
//! $ # Start a debug session in another terminal
//! $ arm-none-eabi-gdb target/thumbv7em-none-eabihf/release/demo
//! ```
//!
//! **NOTE** As of nightly-2017-05-14 or so and cortex-m-quickstart v0.1.6 you
//! can simply run `cargo run` or `cargo run --example $example` to build the
//! program, and immediately start a debug session. IOW, it lets you omit the
//! `arm-none-eabi-gdb` command.
//! Alternatively, you can use `cargo run` to build, flash and debug the program in a single step.
//!
//! ``` text
//! $ cargo run --example hello
@@ -128,13 +134,28 @@
//!
//! # Examples
//!
//! Check the [examples module](./examples/index.html)
//! Check the [examples module][examples]
//!
//! [examples]: ./examples/index.html
//!
//! # Troubleshooting
//!
//! This section contains fixes for common errors encountered when the
//! `cortex-m-quickstart` template is misused.
//!
//! ## Used the standard `main` interface
//!
//! Error message:
//!
//! ``` text
//! $ cargo build
//! Compiling demo v0.1.0 (file:///home/japaric/tmp/demo)
//!
//! error: requires `start` lang_item
//! ```
//!
//! Solution: Use `#![no_main]` and `entry!` as shown in the [examples].
//!
//! ## Forgot to launch an OpenOCD instance
//!
//! Error message:
@@ -155,38 +176,53 @@
//! Error message:
//!
//! ``` text
//! $ xargo build
//! $ cargo build
//! Compiling demo v0.1.0 (file:///home/japaric/tmp/demo)
//! error: linking with `arm-none-eabi-ld` failed: exit code: 1
//! error: linking with `rust-lld` failed: exit code: 1
//! |
//! = note: "arm-none-eabi-ld" "-L" (..)
//! = note: arm-none-eabi-ld: address 0xbaaab838 of hello section `.text' is ..
//! arm-none-eabi-ld: address 0xbaaab838 of hello section `.text' is ..
//! arm-none-eabi-ld:
//! Invalid '.rodata.exceptions' section.
//! Make sure to place a static with type `cortex_m::exception::Handlers`
//! in that section (cf. #[link_section]) ONLY ONCE.
//! = note: "rust-lld" "-flavor" "gnu" "-L" (..)
//! (..)
//! = note: rust-lld: error: section '.vector_table' will not fit in region 'FLASH': overflowed by X bytes
//! rust-lld: error: section '.vector_table' will not fit in region 'FLASH': overflowed by Y bytes
//! (..)
//! ```
//!
//! Solution: Specify your device memory layout in the `memory.x` linker script.
//! See [Usage] section.
//! Solution: Specify your device memory layout in the `memory.x` linker script. See [Usage]
//! section.
//!
//! ## Forgot to set a default build target
//! ## Didn't set a default build target and forgot to pass `--target` to Cargo
//!
//! Error message:
//!
//! ``` text
//! $ xargo build
//! $ cargo build
//! (..)
//! Compiling cortex-m-semihosting v0.1.3
//! error[E0463]: can't find crate for `std`
//! error: language item required, but not found: `eh_personality`
//!
//! error: aborting due to previous error
//! ```
//!
//! Solution: Set a default build target in the `.cargo/config` file
//! (see [Usage] section), or call Xargo with `--target` flag:
//! `xargo build --target thumbv7em-none-eabi`.
//! Solution: Set a default build target in the `.cargo/config` file (see [Usage] section), or call
//! Cargo with `--target` flag: `cargo build --target thumbv7em-none-eabi`.
//!
//! ## Overwrote the original `.cargo/config` file
//!
//! You won't get an error message but the output binary will be empty
//!
//! ``` text
//! $ cargo build && echo OK
//! OK
//!
//! $ size target/thumbv7m-none-eabi/debug/app
//! text data bss dec hex filename
//! 0 0 0 0 0 target/thumbv7m-none-eabi/debug/app
//! ```
//!
//! Solution: You probably overwrote the original `.cargo/config` instead of appending the default
//! build target (e.g. `cat >` instead of `cat >>`). The less error prone way to fix this is to
//! remove the `.cargo` directory, clone a new copy of the template and then copy the `.cargo`
//! directory from that fresh template into your current project. Don't forget to *append* the
//! default build target to `.cargo/config`.
//!
//! ## Called OpenOCD with wrong arguments
//!
@@ -200,11 +236,23 @@
//! in procedure 'ocd_bouncer'
//! ```
//!
//! Solution: Correct the OpenOCD arguments. Check the
//! `/usr/share/openocd/scripts` directory (exact location varies per
//! distribution / OS) for a list of scripts that can be used.
//! Solution: Correct the OpenOCD arguments. Check the `/usr/share/openocd/scripts` directory (exact
//! location varies per distribution / OS) for a list of scripts that can be used.
//!
//! ## Used Cargo instead of Xargo
//! ## Forgot to install the `rust-std` component
//!
//! Error message:
//!
//! ``` text
//! $ cargo build
//! error[E0463]: can't find crate for `core`
//! |
//! = note: the `thumbv7m-none-eabi` target may not be installed
//! ```
//!
//! Solution: call `rustup target add thumbv7m-none-eabi` but with the name of your target
//!
//! ## Used an old nightly
//!
//! Error message:
//!
@@ -218,44 +266,20 @@
//! error: aborting due to previous error
//! ```
//!
//! Solution: Use `xargo build`.
//! Solution: Use a more recent nightly
//!
//! ## Used the stable toolchain
//!
//! Error message:
//!
//! ``` text
//! $ xargo build
//! error: failed to run `rustc` to learn about target-specific information
//!
//! To learn more, run the command again with --verbose.
//! $ cargo build
//! error[E0463]: can't find crate for `core`
//! |
//! = note: the `thumbv7em-none-eabihf` target may not be installed
//! ```
//!
//! Solution: Switch to the nightly toolchain with `rustup default nightly`.
//!
//! ## Used `CARGO_INCREMENTAL=1`
//!
//! Error message:
//!
//! ``` text
//! $ xargo build
//! error: linking with `arm-none-eabi-ld` failed: exit code: 1
//! |
//! = note: "arm-none-eabi-ld" (..)
//! = note: arm-none-eabi-ld:
//! You must specify the exception handlers.
//! Create a non `pub` static variable with type
//! `cortex_m::exception::Handlers` and place it in the
//! '.rodata.exceptions' section. (cf. #[link_section]). Apply the
//! `#[used]` attribute to the variable to make it reach the linker.
//! arm-none-eabi-ld:
//! Invalid '.rodata.exceptions' section.
//! Make sure to place a static with type `cortex_m::exception::Handlers`
//! in that section (cf. #[link_section]) ONLY ONCE.
//! ```
//!
//! Solution: `$ unset CARGO_INCREMENAL`. And to be on the safe side, call
//! `cargo clean` and thrash the Xargo sysroot: `$ rm -rf ~/.xargo`
//! Solution: We are not there yet! Switch to the nightly toolchain with `rustup default nightly`.
//!
//! ## Used `gdb` instead of `arm-none-eabi-gdb`
//!
@@ -281,6 +305,37 @@
//! ```
//!
//! Solution: Use `arm-none-eabi-gdb target/..`
//!
//! # Used a named piped for `itm.fifo`
//!
//! Error message:
//!
//! ``` text
//! $ cargo run [--example ..]
//!
//! Reading symbols from target/thumbv7em-none-eabihf/debug/cortex-m-quickstart...done.
//! cortex_m_rt::reset_handler ()
//! at $REGISTRY/cortex-m-rt-0.3.12/src/lib.rs:330
//! 330 unsafe extern "C" fn reset_handler() -> ! {
//! semihosting is enabled
//! Ignoring packet error, continuing...
//! Ignoring packet error, continuing...
//! ```
//!
//! Note that when you reach this point OpenOCD will become unresponsive and you'll have to kill it
//! and start a new OpenOCD process before you can invoke `cargo run` / start GDB.
//!
//! Cause: You uncommented the `monitor tpiu ..` line in `.gdbinit` and are using a named pipe to
//! receive the ITM data (i.e. you ran `mkfifo itm.fifo`). This error occurs when `itmdump -f
//! itm.fifo` (or equivalent, e.g. `cat itm.fifo`) is not running.
//!
//! Solution: Run `itmdump -f itm.fifo` (or equivalently `cat itm.fifo`) *before* invoking `cargo
//! run` / starting GDB. Note that sometimes `itmdump` will exit when the GDB session ends. In that
//! case you'll have to run `itmdump` before you start the next GDB session.
//!
//! Alternative solution: Use a plain text file instead of a named pipe. In this scenario you omit
//! the `mkfifo itm.dump` command. You can use `itmdump`'s *follow* mode (-F) to get named pipe like
//! output.
#![no_std]