Initial commit

Much of the content here is a direct port from https://github.com/japaric/discovery
This commit is contained in:
Michael Droogleever
2018-07-02 23:01:03 +02:00
commit 8e05dfd010
32 changed files with 2513 additions and 0 deletions

11
.gitignore vendored Normal file
View File

@@ -0,0 +1,11 @@
# Rust ignores
/target/
Cargo.lock
**/*.rs.bk
# mdBook ignores
*.org
.#*
.gdb_history
/template
book/

32
.travis.yml Normal file
View File

@@ -0,0 +1,32 @@
language: rust
rust: nightly
addons:
apt:
packages:
- gcc-arm-none-eabi
install:
- bash ci/install.sh
script:
- bash ci/script.sh
after_success:
- bash ci/after-success.sh
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

12
Cargo.toml Normal file
View File

@@ -0,0 +1,12 @@
[workspace]
members = [
"src/getting-started",
]
[profile.dev]
codegen-units = 1
incremental = false
[profile.release]
debug = true
lto = true

218
LICENSE-APACHE Normal file
View File

@@ -0,0 +1,218 @@
Copyright 2018 Michael Droogleever
Copyright 2016 Jorge Aparicio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

395
LICENSE-CC-BY Normal file
View File

@@ -0,0 +1,395 @@
Attribution 4.0 International
=======================================================================
Creative Commons Corporation ("Creative Commons") is not a law firm and
does not provide legal services or legal advice. Distribution of
Creative Commons public licenses does not create a lawyer-client or
other relationship. Creative Commons makes its licenses and related
information available on an "as-is" basis. Creative Commons gives no
warranties regarding its licenses, any material licensed under their
terms and conditions, or any related information. Creative Commons
disclaims all liability for damages resulting from their use to the
fullest extent possible.
Using Creative Commons Public Licenses
Creative Commons public licenses provide a standard set of terms and
conditions that creators and other rights holders may use to share
original works of authorship and other material subject to copyright
and certain other rights specified in the public license below. The
following considerations are for informational purposes only, are not
exhaustive, and do not form part of our licenses.
Considerations for licensors: Our public licenses are
intended for use by those authorized to give the public
permission to use material in ways otherwise restricted by
copyright and certain other rights. Our licenses are
irrevocable. Licensors should read and understand the terms
and conditions of the license they choose before applying it.
Licensors should also secure all rights necessary before
applying our licenses so that the public can reuse the
material as expected. Licensors should clearly mark any
material not subject to the license. This includes other CC-
licensed material, or material used under an exception or
limitation to copyright. More considerations for licensors:
wiki.creativecommons.org/Considerations_for_licensors
Considerations for the public: By using one of our public
licenses, a licensor grants the public permission to use the
licensed material under specified terms and conditions. If
the licensor's permission is not necessary for any reason--for
example, because of any applicable exception or limitation to
copyright--then that use is not regulated by the license. Our
licenses grant only permissions under copyright and certain
other rights that a licensor has authority to grant. Use of
the licensed material may still be restricted for other
reasons, including because others have copyright or other
rights in the material. A licensor may make special requests,
such as asking that all changes be marked or described.
Although not required by our licenses, you are encouraged to
respect those requests where reasonable. More_considerations
for the public:
wiki.creativecommons.org/Considerations_for_licensees
=======================================================================
Creative Commons Attribution 4.0 International Public License
By exercising the Licensed Rights (defined below), You accept and agree
to be bound by the terms and conditions of this Creative Commons
Attribution 4.0 International Public License ("Public License"). To the
extent this Public License may be interpreted as a contract, You are
granted the Licensed Rights in consideration of Your acceptance of
these terms and conditions, and the Licensor grants You such rights in
consideration of benefits the Licensor receives from making the
Licensed Material available under these terms and conditions.
Section 1 -- Definitions.
a. Adapted Material means material subject to Copyright and Similar
Rights that is derived from or based upon the Licensed Material
and in which the Licensed Material is translated, altered,
arranged, transformed, or otherwise modified in a manner requiring
permission under the Copyright and Similar Rights held by the
Licensor. For purposes of this Public License, where the Licensed
Material is a musical work, performance, or sound recording,
Adapted Material is always produced where the Licensed Material is
synched in timed relation with a moving image.
b. Adapter's License means the license You apply to Your Copyright
and Similar Rights in Your contributions to Adapted Material in
accordance with the terms and conditions of this Public License.
c. Copyright and Similar Rights means copyright and/or similar rights
closely related to copyright including, without limitation,
performance, broadcast, sound recording, and Sui Generis Database
Rights, without regard to how the rights are labeled or
categorized. For purposes of this Public License, the rights
specified in Section 2(b)(1)-(2) are not Copyright and Similar
Rights.
d. Effective Technological Measures means those measures that, in the
absence of proper authority, may not be circumvented under laws
fulfilling obligations under Article 11 of the WIPO Copyright
Treaty adopted on December 20, 1996, and/or similar international
agreements.
e. Exceptions and Limitations means fair use, fair dealing, and/or
any other exception or limitation to Copyright and Similar Rights
that applies to Your use of the Licensed Material.
f. Licensed Material means the artistic or literary work, database,
or other material to which the Licensor applied this Public
License.
g. Licensed Rights means the rights granted to You subject to the
terms and conditions of this Public License, which are limited to
all Copyright and Similar Rights that apply to Your use of the
Licensed Material and that the Licensor has authority to license.
h. Licensor means the individual(s) or entity(ies) granting rights
under this Public License.
i. Share means to provide material to the public by any means or
process that requires permission under the Licensed Rights, such
as reproduction, public display, public performance, distribution,
dissemination, communication, or importation, and to make material
available to the public including in ways that members of the
public may access the material from a place and at a time
individually chosen by them.
j. Sui Generis Database Rights means rights other than copyright
resulting from Directive 96/9/EC of the European Parliament and of
the Council of 11 March 1996 on the legal protection of databases,
as amended and/or succeeded, as well as other essentially
equivalent rights anywhere in the world.
k. You means the individual or entity exercising the Licensed Rights
under this Public License. Your has a corresponding meaning.
Section 2 -- Scope.
a. License grant.
1. Subject to the terms and conditions of this Public License,
the Licensor hereby grants You a worldwide, royalty-free,
non-sublicensable, non-exclusive, irrevocable license to
exercise the Licensed Rights in the Licensed Material to:
a. reproduce and Share the Licensed Material, in whole or
in part; and
b. produce, reproduce, and Share Adapted Material.
2. Exceptions and Limitations. For the avoidance of doubt, where
Exceptions and Limitations apply to Your use, this Public
License does not apply, and You do not need to comply with
its terms and conditions.
3. Term. The term of this Public License is specified in Section
6(a).
4. Media and formats; technical modifications allowed. The
Licensor authorizes You to exercise the Licensed Rights in
all media and formats whether now known or hereafter created,
and to make technical modifications necessary to do so. The
Licensor waives and/or agrees not to assert any right or
authority to forbid You from making technical modifications
necessary to exercise the Licensed Rights, including
technical modifications necessary to circumvent Effective
Technological Measures. For purposes of this Public License,
simply making modifications authorized by this Section 2(a)
(4) never produces Adapted Material.
5. Downstream recipients.
a. Offer from the Licensor -- Licensed Material. Every
recipient of the Licensed Material automatically
receives an offer from the Licensor to exercise the
Licensed Rights under the terms and conditions of this
Public License.
b. No downstream restrictions. You may not offer or impose
any additional or different terms or conditions on, or
apply any Effective Technological Measures to, the
Licensed Material if doing so restricts exercise of the
Licensed Rights by any recipient of the Licensed
Material.
6. No endorsement. Nothing in this Public License constitutes or
may be construed as permission to assert or imply that You
are, or that Your use of the Licensed Material is, connected
with, or sponsored, endorsed, or granted official status by,
the Licensor or others designated to receive attribution as
provided in Section 3(a)(1)(A)(i).
b. Other rights.
1. Moral rights, such as the right of integrity, are not
licensed under this Public License, nor are publicity,
privacy, and/or other similar personality rights; however, to
the extent possible, the Licensor waives and/or agrees not to
assert any such rights held by the Licensor to the limited
extent necessary to allow You to exercise the Licensed
Rights, but not otherwise.
2. Patent and trademark rights are not licensed under this
Public License.
3. To the extent possible, the Licensor waives any right to
collect royalties from You for the exercise of the Licensed
Rights, whether directly or through a collecting society
under any voluntary or waivable statutory or compulsory
licensing scheme. In all other cases the Licensor expressly
reserves any right to collect such royalties.
Section 3 -- License Conditions.
Your exercise of the Licensed Rights is expressly made subject to the
following conditions.
a. Attribution.
1. If You Share the Licensed Material (including in modified
form), You must:
a. retain the following if it is supplied by the Licensor
with the Licensed Material:
i. identification of the creator(s) of the Licensed
Material and any others designated to receive
attribution, in any reasonable manner requested by
the Licensor (including by pseudonym if
designated);
ii. a copyright notice;
iii. a notice that refers to this Public License;
iv. a notice that refers to the disclaimer of
warranties;
v. a URI or hyperlink to the Licensed Material to the
extent reasonably practicable;
b. indicate if You modified the Licensed Material and
retain an indication of any previous modifications; and
c. indicate the Licensed Material is licensed under this
Public License, and include the text of, or the URI or
hyperlink to, this Public License.
2. You may satisfy the conditions in Section 3(a)(1) in any
reasonable manner based on the medium, means, and context in
which You Share the Licensed Material. For example, it may be
reasonable to satisfy the conditions by providing a URI or
hyperlink to a resource that includes the required
information.
3. If requested by the Licensor, You must remove any of the
information required by Section 3(a)(1)(A) to the extent
reasonably practicable.
4. If You Share Adapted Material You produce, the Adapter's
License You apply must not prevent recipients of the Adapted
Material from complying with this Public License.
Section 4 -- Sui Generis Database Rights.
Where the Licensed Rights include Sui Generis Database Rights that
apply to Your use of the Licensed Material:
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
to extract, reuse, reproduce, and Share all or a substantial
portion of the contents of the database;
b. if You include all or a substantial portion of the database
contents in a database in which You have Sui Generis Database
Rights, then the database in which You have Sui Generis Database
Rights (but not its individual contents) is Adapted Material; and
c. You must comply with the conditions in Section 3(a) if You Share
all or a substantial portion of the contents of the database.
For the avoidance of doubt, this Section 4 supplements and does not
replace Your obligations under this Public License where the Licensed
Rights include other Copyright and Similar Rights.
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
c. The disclaimer of warranties and limitation of liability provided
above shall be interpreted in a manner that, to the extent
possible, most closely approximates an absolute disclaimer and
waiver of all liability.
Section 6 -- Term and Termination.
a. This Public License applies for the term of the Copyright and
Similar Rights licensed here. However, if You fail to comply with
this Public License, then Your rights under this Public License
terminate automatically.
b. Where Your right to use the Licensed Material has terminated under
Section 6(a), it reinstates:
1. automatically as of the date the violation is cured, provided
it is cured within 30 days of Your discovery of the
violation; or
2. upon express reinstatement by the Licensor.
For the avoidance of doubt, this Section 6(b) does not affect any
right the Licensor may have to seek remedies for Your violations
of this Public License.
c. For the avoidance of doubt, the Licensor may also offer the
Licensed Material under separate terms or conditions or stop
distributing the Licensed Material at any time; however, doing so
will not terminate this Public License.
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
License.
Section 7 -- Other Terms and Conditions.
a. The Licensor shall not be bound by any additional or different
terms or conditions communicated by You unless expressly agreed.
b. Any arrangements, understandings, or agreements regarding the
Licensed Material not stated herein are separate from and
independent of the terms and conditions of this Public License.
Section 8 -- Interpretation.
a. For the avoidance of doubt, this Public License does not, and
shall not be interpreted to, reduce, limit, restrict, or impose
conditions on any use of the Licensed Material that could lawfully
be made without permission under this Public License.
b. To the extent possible, if any provision of this Public License is
deemed unenforceable, it shall be automatically reformed to the
minimum extent necessary to make it enforceable. If the provision
cannot be reformed, it shall be severed from this Public License
without affecting the enforceability of the remaining terms and
conditions.
c. No term or condition of this Public License will be waived and no
failure to comply consented to unless expressly agreed to by the
Licensor.
d. Nothing in this Public License constitutes or may be interpreted
as a limitation upon, or waiver of, any privileges and immunities
that apply to the Licensor or You, including from the legal
processes of any jurisdiction or authority.
=======================================================================
Creative Commons is not a party to its public
licenses. Notwithstanding, Creative Commons may elect to apply one of
its public licenses to material it publishes and in those instances
will be considered the “Licensor.” The text of the Creative Commons
public licenses is dedicated to the public domain under the CC0 Public
Domain Dedication. Except for the limited purpose of indicating that
material is shared under a Creative Commons public license or as
otherwise permitted by the Creative Commons policies published at
creativecommons.org/policies, Creative Commons does not authorize the
use of the trademark "Creative Commons" or any other trademark or logo
of Creative Commons without its prior written consent including,
without limitation, in connection with any unauthorized modifications
to any of its public licenses or any other arrangements,
understandings, or agreements concerning use of licensed material. For
the avoidance of doubt, this paragraph does not form part of the
public licenses.
Creative Commons may be contacted at creativecommons.org.

26
LICENSE-MIT Normal file
View File

@@ -0,0 +1,26 @@
Copyright (c) 2018 Michael Droogleever
Copyright (c) 2016 Jorge Aparicio
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

26
README.md Normal file
View File

@@ -0,0 +1,26 @@
# MicroRust
> Learn embedded software in Rust on the micro:bit
## License
The documentation is licensed under
- Creative Commons Attribution 4.0 License ([LICENSE-CC-BY](LICENSE-CC-BY)
or https://creativecommons.org/licenses/by/4.0/legalcode)
And the source code is licensed under either of
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
http://www.apache.org/licenses/LICENSE-2.0)
- MIT License ([LICENSE-MIT](LICENSE-MIT) or
https://opensource.org/licenses/MIT)
at your option.
### Contribution
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
licensed as above, without any additional terms or conditions.

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

@@ -0,0 +1,19 @@
set -euxo pipefail
main() {
mdbook build
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 book
set +x
git push -fq https://$GH_TOKEN@github.com/$TRAVIS_REPO_SLUG.git gh-pages && echo OK
}
if [ $TRAVIS_BRANCH = master ]; then
main
fi

19
ci/install.sh Normal file
View File

@@ -0,0 +1,19 @@
set -euxo pipefail
main() {
curl -LSfs https://japaric.github.io/trust/install.sh | \
sh -s -- \
--force \
--git rust-lang-nursery/mdBook \
--tag v0.1.5 \
--target x86_64-unknown-linux-musl
rustup target add thumbv6m-none-eabi
pip install linkchecker --user
# sanity check that a linker is present
which arm-none-eabi-ld
}
main

35
ci/script.sh Normal file
View File

@@ -0,0 +1,35 @@
set -euxo pipefail
main() {
# test that building the book works
mdbook build
linkchecker book
# first (fast) pass: check that examples compile
for chapter in $(echo src/*); do
if [ ! -f $chapter/Cargo.toml ]; then
continue
fi
pushd $chapter
cargo check
popd
done
# second (slow) pass: check that examples link
for chapter in $(echo src/*); do
if [ ! -f $chapter/Cargo.toml ]; then
continue
fi
pushd $chapter
cargo build
cargo build --release
popd
done
}
if [ $TRAVIS_BRANCH != master ]; then
main
fi

65
src/README.md Normal file
View File

@@ -0,0 +1,65 @@
# MicroRust
> Discover the world of microcontrollers through [Rust] on the [BBC micro:bit][microbit]!
[Rust]: https://www.rust-lang.org/
[microbit]: https://microbit.org/
This book is an introductory course on microcontroller-based embedded systems that uses Rust as the
teaching language (rather than the usual C/C++), and the micro:bit as target system.
## Scope
The following topics will be covered:
- How to write, build, flash and debug an embedded program.
- Functionality ("peripherals") commonly found in microcontrollers:
- Digital input and output, using buttons and LEDs
<!-- - Functionality ("peripherals") commonly found in microcontrollers: Digital input and output, Pulse
Width Modulation (PWM), Analog to Digital Converters (ADC), common communication protocols like
Serial, I2C and SPI, etc. -->
<!-- - Multitasking concepts: cooperative vs preemptive multitasking, interrupts, schedulers, etc. -->
<!-- - Control systems concepts: sensors, calibration, digital filters, actuators, open loop control,
closed loop control, etc. -->
## Approach
- Beginner friendly.
No previous experience with microcontrollers or embedded systems is required.
- Hands on.
*You* will be doing most of the work here.
When possible, pages will end on a problem for you to solve, with the solution on the next page.
Plenty of exercises to put the theory into practice.
- Standard. We'll make plenty use of standard tooling and processes to ease development.
Fixing compiler errors, debugging with GDB, and logging will be introduced early on.
Using LEDs as a debugging mechanism has no place here.
## Non-goals
What's out of scope for this book:
- Teaching Rust.
There's plenty of material on that topic already.
We'll focus on microcontrollers and embedded systems.
- Teaching electric circuit theory or electronics.
We'll cover the minimum required to understand how some devices work along the way.
- Covering Rustic, low level details.
We won't be talking about linker scripts, the boot process,
or how to glue those two into a minimally working Rust program.
## Reporting problems
The source of this book is in [this repository].
If you encounter any typo or problem with the code report it on the [issue tracker],
or even submit a pull request.
[this repository]: https://github.com/droogmic/microrust
[issue tracker]: https://github.com/droogmic/microrust/issues

34
src/SUMMARY.md Normal file
View File

@@ -0,0 +1,34 @@
[Introduction](README.md)
[Background](background/README.md)
[Requirements](requirements/README.md)
- [Meet your hardware](hardware/README.md)
- [Development environment setup](setup/README.md)
- [Linux](setup/LINUX.md)
- [Windows](setup/WINDOWS.md)
- [macOS](setup/MACOS.md)
- [Verify the installation](setup/VERIFY.md)
- [Getting started](getting-started/00.00.README.md)
- [Building](getting-started/01.00.PROJECT.md)
- [Flashing](getting-started/02.00.FLASH.md)
- [LED](getting-started/03.00.LED.md)
- [Debugging](getting-started/04.00.DEBUGGING.md)
[Explore](appendix/explore.md)
[General troubleshooting](appendix/troubleshooting.md)
<!-- - [LED roulette](05-led-roulette/README.md)
- [Build it](05-led-roulette/build-it.md)
- [Flash it](05-led-roulette/flash-it.md)
- [Debug it](05-led-roulette/debug-it.md)
- [The `led` and `delay` abstractions](05-led-roulette/the-led-and-delay-abstractions.md)
- [The challenge](05-led-roulette/the-challenge.md)
- [My solution](05-led-roulette/my-solution.md) -->
<!-- - [Hello, world!](06-hello-world/README.md)
- [`panic!`](06-hello-world/panic.md) -->

162
src/appendix/explore.md Normal file
View File

@@ -0,0 +1,162 @@
# What's left for you to explore
We have barely scratched the surface! There's lots of stuff left for you to explore:
## Multitasking
All our programs executed a single task. How could we achieve multitasking in a system with no OS,
and thus no threads. There are two main approaches to multitasking: preemptive multitasking and
cooperative multitasking.
In preemptive multitasking a task that's currently being executed can, at any point in time, be
*preempted* (interrupted) by another task. On preemption, the first task will be suspended and the
processor will instead execute the second task. At some point the first task will be resumed.
Microcontrollers provide hardware support for preemption in the form of *interrupts*.
In cooperative multitasking a task that's being executed will run until it reaches a *suspension
point*. When the processor reaches that suspension point it will stop executing the current task and
instead go and execute a different task. At some point the first task will be resumed. The main
difference between these two approaches to multitasking is that in cooperative multitasking *yields*
execution control at *known* suspension points instead of being forcefully preempted at any point of
its execution.
## Direct Memory Access (DMA).
This peripheral is a kind of *asynchronous* `memcpy`. So far our programs have
been pumping data, byte by byte, into peripherals like UART and I2C. This DMA
peripheral can be used to perform bulk transfers of data. Either from RAM to
RAM, from a peripheral, like a UART, to RAM or from RAM to a peripheral. You can
schedule a DMA transfer, like read 256 bytes from USART1 into this buffer, leave
it running in the background and then poll some register to see if it has
completed so you can do other stuff while the transfer is ongoing.
## Sleeping
All our programs have been continuously polling peripherals to see if there's
anything that needs to be done. However, some times there's nothing to be done!
At those times, the microcontroller should "sleep".
When the processor sleeps, it stops executing instructions and this saves power.
It's almost always a good idea to save power so your microcontroller should be
sleeping as much as possible. But, how does it know when it has to wake up to
perform some action? "Interrupts" are one of the events that wake up the
microcontroller but there are others and the `wfi` and `wfe` are the
instructions that make the processor "sleep".
## Pulse Width Modulation (PWM)
In a nutshell, PWM is turning on something and then turning it off periodically
while keeping some proportion ("duty cycle") between the "on time" and the "off
time". When used on a LED with a sufficiently high frequency, this can be used
to dim the LED. A low duty cycle, say 10% on time and 90% off time, will make
the LED very dim wheres a high duty cycle, say 90% on time and 10% off time,
will make the LED much brighter (almost as if it were fully powered).
In general, PWM can be used to control how much *power* is given to some
electric device. With proper (power) electronics between a microcontroller and
an electrical motor, PWM can be used to control how much power is given to the
motor thus it can be used to control its torque and speed. Then you can add an
angular position sensor and you got yourself a closed loop controller that can
control the position of the motor at different loads.
## Digital input
We have used the microcontroller pins as digital outputs, to drive LEDs. But
these pins can also be configured as digital inputs. As digital inputs, these
pins can read the binary state of switches (on/off) or buttons (pressed/not
pressed).
(*spoilers* reading the binary state of switches / buttons is not as
straightforward as it sounds ;-)
## Sensor fusion
The STM32F3DISCOVERY contains three motion sensors: an accelerometer, a
gyroscope and a magnetometer. On their own these measure: (proper) acceleration,
angular speed and (the Earth's) magnetic field. But these magnitudes can be
"fused" into something more useful: a "robust" measurement of the orientation of
the board. Where robust means with less measurement error than a single sensor
would be capable of.
This idea of deriving more reliable data from different sources is known as
sensor fusion.
## Analog-to-Digital Converters (ADC)
There are a lots of digital sensors out there. You can use a protocol like I2C
and SPI to read them. But analog sensors also exist! These sensors just output a
voltage level that's proportional to the magnitude they are sensing.
The ADC peripheral can be use to convert that "analog" voltage level, say `1.25`
Volts,into a "digital" number, say in the `[0, 65535]` range, that the processor
can use in its calculations.
## Digital-to-Analog Converters (DAC)
As you might expect a DAC is exactly the opposite of ADC. You can write some
digital value into a register to produce a voltage in the `[0, 3.3V]` range
(assuming a `3.3V` power supply) on some "analog" pin. When this analog pin is
connected to some appropriate electronics and the register is written to at some
constant, fast rate (frequency) with the right values you can produce sounds or
even music!
## Real Time Clock (RTC)
This peripheral can be used to track time in "human format". Seconds, minutes,
hours, days, months and years. This peripheral handles the translation from
"ticks" to these human friendly units of time. It even handles leap years and
Daylight Save Time for you!
## Other communication protocols
SPI, I2S, SMBUS, CAN, IrDA, Ethernet, USB, Bluetooth, etc.
Different applications use different communication protocols. User facing
applications usually have an USB connector because USB is an ubiquitous
protocol in PCs and smartphones. Whereas inside cars you'll find plenty of CAN
"buses". Some digital sensors use SPI, others use I2C and others, SMBUS.
---
So where to next? There are several options:
- You could check out the examples in the [`microbit`] board support crate repository. All those examples work for
the micro:bit board you have.
[`f3`]: https://docs.rs/f3
- You could try out [this motion sensors demo][madgwick]. Details about the implementation and
source code are available in [this blog post][wd-1-2].
[madgwick]: https://mobile.twitter.com/japaricious/status/962770003325005824
[wd-1-2]: http://blog.japaric.io/wd-1-2-l3gd20-lsm303dlhc-madgwick/
- You could check out [Real Time for The Masses]. A very efficient preemptive multitasking framework
that supports task prioritization and dead lock free execution.
[Real Time for The Masses]: https://docs.rs/cortex-m-rtfm
- You could try running Rust on a different development board. The easiest way to get started is to
use the [`cortex-m-quickstart`] Cargo project template.
[`cortex-m-quickstart`]: https://docs.rs/cortex-m-quickstart/0.2.4/cortex_m_quickstart
- You could check out [this blog post][brave-new-io] which describes how Rust type system can
prevent bugs in I/O configuration.
[brave-new-io]: http://blog.japaric.io/brave-new-io/
- You could check out my [blog] for miscellaneous topics about embedded development with Rust.
[blog]: http://blog.japaric.io
- You could check out the [`embedded-hal`] project which aims to build abstractions (traits) for all
the embedded I/O functionality commonly found on microcontrollers.
[`embedded-hal`]: https://github.com/japaric/embedded-hal
- You could join the [Weekly driver initiative] and help us write generic drivers on top of the
`embedded-hal` traits and that work for all sorts of platforms (ARM Cortex-M, AVR, MSP430, RISCV,
etc.)
[Weekly driver initiative]: https://github.com/rust-lang-nursery/embedded-wg/issues/39

View File

@@ -0,0 +1,170 @@
# General troubleshooting
## OpenOCD problems
### can't connect to OpenOCD - "Error: open failed"
#### Symptoms
Upon trying to establish a *new connection* with the device you get an error
that looks like this:
```
$ openocd -f (..)
(..)
Error: open failed
in procedure 'init'
in procedure 'ocd_bouncer'
```
#### Cause + Fix
- All: The device is not (properly) connected. Check the USB connection using
`lsusb` or the Device Manager.
- Linux: You may not have enough permission to open the device. Try again with
`sudo`. If that works, you can use [these instructions] to make OpenOCD work
without root privilege.
- Windows: You are probably missing the ST-LINK USB driver. Installation
instructions [here].
[these instructions]: 03-setup/linux.html#udev%20rules
[here]: 03-setup/windows.html#ST-LINK%20USB%20driver
### can't connect to OpenOCD - "Polling again in X00ms"
#### Symptoms
Upon trying to establish a *new connection* with the device you get an error
that looks like this:
```
$ openocd -f (..)
(..)
Error: jtag status contains invalid mode value - communication failure
Polling target stm32f3x.cpu failed, trying to reexamine
Examination failed, GDB will be halted. Polling again in 100ms
Info : Previous state query failed, trying to reconnect
Error: jtag status contains invalid mode value - communication failure
Polling target stm32f3x.cpu failed, trying to reexamine
Examination failed, GDB will be halted. Polling again in 300ms
Info : Previous state query failed, trying to reconnect
```
#### Cause
The microcontroller may have get stuck in some tight infinite loop or it may be
continuously raising an exception, e.g. the exception handler is raising an
exception.
#### Fix
- Close OpenOCD, if running
- Press and hold the reset (black) button
- Launch the OpenOCD command
- Now, release the reset button
### OpenOCD connection lost - "Polling again in X00ms"
#### Symptoms
A *running* OpenOCD session suddenly errors with:
```
# openocd -f (..)
Error: jtag status contains invalid mode value - communication failure
Polling target stm32f3x.cpu failed, trying to reexamine
Examination failed, GDB will be halted. Polling again in 100ms
Info : Previous state query failed, trying to reconnect
Error: jtag status contains invalid mode value - communication failure
Polling target stm32f3x.cpu failed, trying to reexamine
Examination failed, GDB will be halted. Polling again in 300ms
Info : Previous state query failed, trying to reconnect
```
#### Cause
The USB connection was lost.
#### Fix
- Close OpenOCD
- Disconnect and re-connect the USB cable.
- Re-launch OpenOCD
### Can't flash the device - "Ignoring packet error, continuing..."
#### Symptoms
While flashing the device, you get:
```
$ arm-none-eabi-gdb $file
Start address 0x8000194, load size 31588
Transfer rate: 22 KB/sec, 5264 bytes/write.
Ignoring packet error, continuing...
Ignoring packet error, continuing...
```
#### Cause
Closed `itmdump` while a program that "printed" to the ITM was running. The
current GDB session will appear to work normally, just without ITM output but
the next GDB session will error with the message that was shown in the previous
section.
Or, `itmdump` was called **after** the `monitor tpiu` was issued thus making
`itmdump` delete the file / named-pipe that OpenOCD was writing to.
#### Fix
- Close/kill GDB, OpenOCD and `itmdump`
- Remove the file / named-pipe that `itmdump` was using (for example,
`itm.txt`).
- Launch OpenOCD
- Then, launch `itmdump`
- Then, launch the GDB session that executes the `monitor tpiu` command.
## Cargo problems
### "can't find crate for `core`"
#### Symptoms
```
Compiling volatile-register v0.1.2
Compiling rlibc v1.0.0
Compiling r0 v0.1.0
error[E0463]: can't find crate for `core`
error: aborting due to previous error
error[E0463]: can't find crate for `core`
error: aborting due to previous error
error[E0463]: can't find crate for `core`
error: aborting due to previous error
Build failed, waiting for other jobs to finish...
Build failed, waiting for other jobs to finish...
error: Could not compile `r0`.
To learn more, run the command again with --verbose.
```
#### Cause
You are using a toolchain older than `nightly-2018-04-08` and forgot to call `rustup target add
thumbv7m-none-eabi`.
#### Fix
Update your nightly and install the `thumbv7em-none-eabihf` target.
``` console
$ rustup update nightly
$ rustup target add thumbv7em-none-eabihf
```

78
src/background/README.md Normal file
View File

@@ -0,0 +1,78 @@
# Background
## What is a microcontroller?
A microcontroller is a *system* on a chip. Whereas your laptop is made up of several discrete
components: a processor, RAM sticks, a hard drive, an ethernet port, etc.; a microcontroller has all
those components built into a single "chip" or package. This makes it possible to build systems with
minimal part count.
## What can you do with a microcontroller?
Lots of things! Microcontrollers are the central part of systems known as *embedded* systems. These
systems are everywhere but you don't usually notice them. These systems control the brakes of your
car, wash your clothes, print your documents, keep you warm, keep you cool, optimize the fuel
consumption of your car, etc.
The main trait of these systems is that they operate without user intervention even if they expose a
user interface like a washing machine does; most of their operation is done on their own.
The other common trait of these systems is that they *control* a process. And for that these systems
usually have one or more sensors and one or more actuators. For example, an HVAC system has several
sensors, thermometers and humidy sensors spread across some area, and several actuators as well,
heating elements and fans connected to ducts.
## When should I use a microcontroller?
All these application I've mentioned, you can probably implement with a Raspberry Pi, a computer
that runs Linux. Why should I bother with a microcontroller that operates without an OS? Sounds like
it would be harder to develop a program.
One main reason is cost. A microcontroller is much cheaper than a general purpose computer. Not only
the microcontroller is cheaper; it also requires much less external electrical components to
operate. This makes Printed Circuit Boards (PCB) smaller and cheaper to design and manufacture.
Another big reason is power consumption. A microcontroller consumes orders of magnitude less power
than a full blown processor. If your application will run on batteries that makes a huge difference.
And last but not least: (hard) *real time* constraints. Some processes require their controllers to
respond to some events within some time interval (e.g. a quadcopter/drone hit by a wind gust). If
this *deadline* is not met, the process could end in catastrophic failure (e.g. the drone crashes to
the ground). A general purpose computer running a general purpose OS has many services running in
the background. This makes it hard to guarantee execution of a program within tight time constraints.
## When should I *not* use a microcontroller?
Where heavy computations are involved. To keep their power consumption low, microcontrollers have
very limited computational resources available to them. For example, some microcontrollers don't
even have hardware support for floating point operations. On those devices, performing a simple
addition of single precision numbers can take hundreds of CPU cycles.
## Development on the micro:bit
The [micro:bit website](https://microbit.org/code/) offers several very simple ways of programming a
microbit, aimed at teaching school children how to program. This is a very good introduction to the
world of microcontollers **and** programming, but falls short of teaching true embedded development.
From there you would usually move to C to develop skills useful in industry, developing performant
embedded software.
## Why use Rust and not C?
Hopefully I don't need to convince you here as you are probably familiar with the language
differences between Rust and C. One point I do want to bring up is package management. C lacks an
official, widely accepted package management solution whereas Rust has Cargo. This makes development
*much* easier. And, IMO, easy package management encourages code reuse because libraries can be
easily integrated into an application which is also a good thing as libraries get more "battle
testing".
## Why should I not use Rust?
Or why should I prefer C over Rust?
The C ecosystem is way more mature. Off the shelf solution for several problems already exist. If
you need to control a time sensitive process, you can grab one of the existing commercial Real Time
Operating Systems (RTOS) out there and solve your problem. There are no commercial, production-grade
RTOSes in Rust yet so you would have to either create one yourself or try one of the ones that are
in development. If you are looking to develop your skills to find a job, it is currently unlikely
that a company doing embedded software development will be using Rust, and so your time would be
better spent learning normal embedded development using C.

View File

@@ -0,0 +1,9 @@
[target.thumbv6m-none-eabi]
runner = "arm-none-eabi-gdb"
rustflags = [
"-C", "link-arg=-Wl,-Tlink.x",
"-C", "link-arg=-nostartfiles",
]
[build]
target = "thumbv6m-none-eabi"

View File

@@ -0,0 +1,4 @@
target remote :3333
load
break main
continue

View File

@@ -0,0 +1,13 @@
# Getting started
Alright, let's start as you usually would with Rust.
``` console
$ rustup update
```
It is always good to keep your toolchain up to date.
Now let's make a new binary project.
You might not do this often, so it is understandeable to forget.
If you run `$ cargo`, you will be given a hint.

View File

@@ -0,0 +1,388 @@
# New Project
``` console
$ cargo new rustled
Created binary (application) `rustled` project
$ cd rustled
Cargo.toml src
```
This has created a binary crate.
Now we could `$ cargo build` this, and even `$ cargo run` it,
but everything is being compiled for, and run on, your computer.
## Targets
The micro:bit has a different architecture than your computer,
so the first step will be to cross compile for the micro:bit's architecture.
If you were to do an internet search, you would find a [platform support list for Rust][platforms].
Looking into this page, you will find the micro:bit's nRF51822 Cortex-M0 microprocessor:
> `thumbv6m-none-eabi [*] [ ] [ ] Bare Cortex-M0, M0+, M1`
"thumbv6m-none-eabi" is known a a target triple. Note what the star represents:
> These are bare-metal microcontroller targets that only have access to the core library, not std.
To install this target:
``` console
$ rustup target add thumbv6m-none-eabi
```
## Build 1
Now how should we use this? Well, if you were to take a look at `$ cargo build -h`, you would try:
``` console
$ cargo build --target thumbv6m-none-eabi
```
```
error[E0463]: can't find crate for `std`
|
= note: the `thumbv6m-none-eabi` target may not be installed
error: aborting due to previous error
For more information about this error, try `rustc --explain E0463`.
error: Could not compile `rustled`.
To learn more, run the command again with --verbose.
```
The help note is rather unhelpful because we just installed that target.
We also just noted that the thumbv6m-none-eabi target does not include std,
only the core crate, which is has a platform independent subset of the std features.
Why is it still looking for the std crate when we build?
### `no_std`
It turns out, rust will always look for the std crate unless explicitly disabled,
so we will add the no_std attribute
`src/main.rs`
``` rust
#![no_std]
fn main() {
println!("Hello, world!");
}
```
## Build 2
``` console
$ cargo build --target thumbv6m-none-eabi
```
```
error: cannot find macro `println!` in this scope
--> src/main.rs:4:5
|
4 | println!("Hello, world!");
| ^^^^^^^
```
`println` is a macro found in the std crate.
We don't need it at the moment, so we can remove it and try to compile again:
```
error: language item required, but not found: `panic_impl`
```
This error, is because the panic macro is unimplemented,
when rustc needs it to have an implementation.
### `panic_impl`
We could try and implement the panic macro ourselves,
but it's easier and more portable to use a crate that does it for us.
If we look on [crates.io for the panic-impl keyword][panic] we will find some examples.
Let us pic the simplest one, and add it to our Cargo.toml.
If you have forgotten how to do this, try looking at [the cargo book][cargo].
[platforms]: https://forge.rust-lang.org/platform-support.html
[panic]: https://crates.io/keywords/panic-impl
[cargo]: https://doc.rust-lang.org/stable/cargo/
`Cargo.toml`
```
[dependencies]
panic-abort = "~0.2"
```
`src/main.rs`
```
#![no_std]
extern crate panic_abort;
fn main() {
}
```
## Build 3
``` console
$ cargo build --target thumbv6m-none-eabi
```
```
error: requires `start` lang_item
```
### `no_main`
In the normal command line rust binaries you would be used to making,
executing the binary usually has the operating system start by executing the C runtime library (crt0).
This in turn invokes the Rust runtime, as marked by the `start` language item,
which in turn invokes the main function.
Having enabled `no_std`, as we are targeting on a microcontroller,
neither the crt0 nor the rust runtime are available,
so even implementing `start` would not help us.
We need to replace the operating system entry point.
You could for example name a function after the default entry point, which for linux is `_main`,
and start that way. Note, you would also need to disable [name mangling][nm]:
```
#![no_std]
#![no_main]
#[no_mangle]
pub extern "C" fn _start() -> ! {
loop {}
}
```
[nm]: https://en.wikipedia.org/wiki/Name_mangling
This is the end of the road for trying to get this to work on our own.
At this point we need the help of a board specific crate and a few cargo tweaks to get this working.
## microbit crate
Let us add a dependency on the board crate for the micro:bit.
```
[dependencies]
panic-abort = "~0.2"
microbit="~0.5"
```
The microbit crate has 2 notable dependencies:
### `embedded-hal`
This crate is a HAL implementation crate, where HAL stands for *hardware abstraction layer*.
As rust becomes more and more popular in embedded development,
it is desireable to have as little hardware specific implementation as possible.
For this reason, the `embedded-hal` crate contains a range of hardware abstraction traits which can
be implemented by board specific crates.
### `cortex-m-rt`
This crate implements the minimal startup / runtime for Cortex-M microcontrollers.
Among other things this crate provides:
- the `entry!` macro, to define the entry point of the program.
- the `exception!` macro, to set or override a processor core exception handler.
This crate requires:
- a definition of the specific microcontroller's memory layout as a memory.x file.
- a definition of the hard fault handler
- a definition of the default exception handler
For more detailed information,
you can use the helpful [cortex-m-quickstart crate][qs] and [its documentation][doc].
[qs]: https://docs.rs/crate/cortex-m-quickstart
[doc]: https://docs.rs/cortex-m-quickstart
## cargo config
Before we go any further,
we are going to tweak the cargo's configuration by editing `rustled/.cargo/config`.
For more information, you can read [the documentation here][cargoconfig].
[cargoconfig]: https://doc.rust-lang.org/cargo/reference/config.html
``` toml
# Configure builds for our target
[target.thumbv6m-none-eabi]
# Execute binary using gdb
runner = "arm-none-eabi-gdb"
# Tweak to the linking process required by the cortex-m-rt crate
rustflags = [
"-C", "link-arg=-Tlink.x",
"-C", "link-arg=-nostartfiles",
]
# Automatically select this target when running cargo for this project
[build]
target = "thumbv6m-none-eabi"
```
### arm-none-eabi-gdb
This is a version of gdb (the GNU debugger) for the ARM EABI (embedded application binary interface).
It will allow us to debug the code running on our micro:bit, from your computer.
### Build target
Now, all you need to do is run `$ cargo build`,
and cargo will automatically add `--target thumbv6m-none-eabi`.
## Build 4
`Cargo.toml`
```
[dependencies]
panic-abort = "~0.2"
microbit="~0.5"
```
`src/main.rs`
```
#![no_std]
#![no_main]
extern crate panic_abort;
entry!(main);
fn main() {
}
```
``` console
cargo build
```
```
error[E0308]: mismatched types
--> src/main.rs:9:1
|
8 | entry!(main);
| ^^^^^^^^^^^^^ expected !, found ()
|
= note: expected type `fn() -> !`
found type `fn() {main}`
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
```
## `!` return type
A little known rust feature, so I will forgive you if you do not know what this means.
A return type of `!` means that the function cannot return
An easy way to implement this, is by using an infinite loop.
`src/main.rs`
```
#![no_std]
#![no_main]
extern crate panic_abort;
#[macro_use(entry)]
extern crate microbit;
entry!(main);
fn main() -> ! {
loop {}
}
```
## Build 5
```
error: linking with `arm-none-eabi-gcc` failed: exit code: 1
|
= note: "arm-none-eabi-gcc" "-L" "/home/xxx/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/thumbv6m-none-eabi/lib" "/home/xxx/rust/rustled/target/thumbv6m-none-eabi/debug/deps/rustled-e6053d34b0422141.2yhvr0tmp69gb94x.rcgu.o" "-o"
# SNIP
"/home/xxx/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/thumbv6m-none-eabi/lib/libcore-fb37a4ea1db1e473.rlib" "-Wl,--end-group" "/home/xxx/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/thumbv6m-none-eabi/lib/libcompiler_builtins-f2357c0397dd7e0d.rlib" "-Wl,-Tlink.x" "-nostartfiles" "-Wl,-Bdynamic"
= note: /usr/lib/gcc/arm-none-eabi/8.1.0/../../../../arm-none-eabi/bin/ld: cannot open linker script file memory.x: No such file or directory
collect2: error: ld returned 1 exit status
```
A scary error, but if you look closely you will see `cannot open linker script file memory.x: No such file or directory`.
We mentioned something a little earlier about memory.x file.
To save you the hassle of scouring the internet for one or creating your own, you can copy it over into your project:
``` console
cp ../getting-started/memory.x
```
> Often a board support crate will already include this, so this step will not be necessary.
## Build 6
```
error: linking with `arm-none-eabi-gcc` failed: exit code: 1
|
= note: "arm-none-eabi-gcc" "-L" "/home/xxx/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/thumbv6m-none-eabi/lib" "/home/xxx/rust/rustled/target/thumbv6m-none-eabi/debug/deps/rustled-e6053d34b0422141.2yhvr0tmp69gb94x.rcgu.o" "-o"
# SNIP
"/home/xxx/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/thumbv6m-none-eabi/lib/libcompiler_builtins-f2357c0397dd7e0d.rlib" "-Wl,-Tlink.x" "-nostartfiles" "-Wl,-Bdynamic"
= note: device.x:1: undefined symbol `DefaultHandler' referenced in expression
collect2: error: ld returned 1 exit status
```
Notice `undefined symbol 'DefaultHandler' referenced in expression`.
We said earlier, as with the memory,
that the hard fault handler and default exception handler both need defining.
`Cargo.toml`
```
[dependencies]
panic-abort = "~0.2"
cortex-m-rt="~0.5"
microbit="~0.5"
```
`src/main.rs`
```
#![no_std]
#![no_main]
extern crate panic_abort;
extern crate cortex_m_rt as rt;
#[macro_use(entry, exception)]
extern crate microbit;
use rt::ExceptionFrame;
entry!(main);
fn main() -> ! {
loop {}
}
exception!(HardFault, hard_fault);
fn hard_fault(ef: &ExceptionFrame) -> ! {
panic!("{:#?}", ef);
}
exception!(*, default_handler);
fn default_handler(irqn: i16) {
panic!("Unhandled exception (IRQn = {})", irqn);
}
```
It is all a bit ugly, but fortunately it only needs to be done once.
If you try building now, you should finally be greeted with `Finished`!
## Build Complete
As a sanity check, let's verify that the produced executable is actually an ARM binary:
``` console
$ file target/thumbv6m-none-eabi/debug/rustled
target/thumbv6m-none-eabi/debug/rustled: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, with debug_info, not stripped
^^^ ^^^^
```

View File

@@ -0,0 +1,192 @@
# Flashing
Flashing is the process of moving our program into the microcontroller's (persistent) memory. Once flashed, the microcontroller will execute the flashed program every time it is powered on.
In this case, our `rustled` program will be the only program in the microcontroller memory. By this I mean that there's nothing else running on the microcontroller: no OS, no "daemon", nothing. `rustled` has full control over the device. This is what is meant by *bare-metal* programming.
Onto the actual flashing. First thing we need is to do is launch OpenOCD. We did that in the previous section but this time we'll run the command inside a temporary directory (/tmp on *nix; %TEMP% on Windows).
Connect the mirco:bit to your computer and run the following commands on a new terminal.
``` console
$ # *nix
$ cd /tmp
$ # Windows
$ cd %TEMP%
```
We need to give OCD the name of the interfaces we are using:
``` console
$ # All
$ # Windows: remember that you need an extra `-s %PATH_TO_OPENOCD%\share\scripts`
$ openocd -f interface/cmsis-dap.cfg -f target/nrf51.cfg
```
The program will block; leave that terminal open.
Now it's a good time to explain what this command is actually doing.
I mentioned that the micro:bit actually has two microcontrollers.
One of them is used as a USB interface and programmer/debugger.
This microcontroller is connected to the target microcontroller using a Serial Wire Debug (SWD) interface
(this interface is an ARM standard so you'll run into it when dealing with other Cortex-M based microcontrollers).
This SWD interface can be used to flash and debug a microcontroller.
It uses the CMSIS-DAP protocol for host debugging of application programs.
It will appear as a USB device when you connect the micro:bit to your laptop.
As for OpenOCD, it's software that provides some services like a *GDB server* on top of USB
devices that expose a debugging protocol like SWD or JTAG.
Onto the actual command: those `.cfg` files we are using instruct OpenOCD to look for
- a CMSIS-DAP USB interface device (`interface/cmsis-dap.cfg`)
- a nRF51XXX microcontroller target (`target/nrf51.cfg`) to be connected to the USB interface.
The OpenOCD output looks like this:
``` console
Open On-Chip Debugger 0.9.0 (2016-04-27-23:18)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "hla_swd". To override use 'transport select <transport>'.
adapter speed: 1000 kHz
adapter_nsrst_delay: 100
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
none separate
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : clock speed 950 kHz
Info : STLINK v2 JTAG v27 API v2 SWIM v15 VID 0x0483 PID 0x374B
Info : using stlink api v2
Info : Target voltage: 2.919073
Info : stm32f3x.cpu: hardware has 6 breakpoints, 4 watchpoints
```
The "6 breakpoints, 4 watchpoints" part indicates the debugging features the processor has
available.
I mentioned that OpenOCD provides a GDB server so let's connect to that right now:
``` console
$ arm-none-eabi-gdb -q target/thumbv7em-none-eabihf/debug/led-roulette
Reading symbols from target/thumbv7em-none-eabihf/debug/led-roulette...done.
(gdb)
```
This only opens a GDB shell. To actually connect to the OpenOCD GDB server, use the following
command within the GDB shell:
```
(gdb) target remote :3333
Remote debugging using :3333
0x00000000 in ?? ()
```
By default OpenOCD's GDB server listens on TCP port 3333 (localhost). This command is connecting to
that port.
After entering this command, you'll see new output in the OpenOCD terminal:
``` diff
Info : stm32f3x.cpu: hardware has 6 breakpoints, 4 watchpoints
+Info : accepting 'gdb' connection on tcp/3333
+Info : device id = 0x10036422
+Info : flash size = 256kbytes
```
Almost there. To flash the device, we'll use the `load` command inside the GDB shell:
```
(gdb) load
Loading section .vector_table, size 0x188 lma 0x8000000
Loading section .text, size 0x38a lma 0x8000188
Loading section .rodata, size 0x8 lma 0x8000514
Start address 0x8000188, load size 1306
Transfer rate: 6 KB/sec, 435 bytes/write.
```
And that's it. You'll also see new output in the OpenOCD terminal.
``` diff
Info : flash size = 256kbytes
+Info : Unable to match requested speed 1000 kHz, using 950 kHz
+Info : Unable to match requested speed 1000 kHz, using 950 kHz
+adapter speed: 950 kHz
+target state: halted
+target halted due to debug-request, current mode: Thread
+xPSR: 0x01000000 pc: 0x08000194 msp: 0x2000a000
+Info : Unable to match requested speed 8000 kHz, using 4000 kHz
+Info : Unable to match requested speed 8000 kHz, using 4000 kHz
+adapter speed: 4000 kHz
+target state: halted
+target halted due to breakpoint, current mode: Thread
+xPSR: 0x61000000 pc: 0x2000003a msp: 0x2000a000
+Info : Unable to match requested speed 1000 kHz, using 950 kHz
+Info : Unable to match requested speed 1000 kHz, using 950 kHz
+adapter speed: 950 kHz
+target state: halted
+target halted due to debug-request, current mode: Thread
+xPSR: 0x01000000 pc: 0x08000194 msp: 0x2000a000
```
Our program is loaded, we can now run it!
```
(gdb) continue
Continuing.
```
Continue runs the program until the next breakpoint.
This time it blocks, nothing happens.
This is because all we have in our code is a loop!
## `.gdbinit`
Before we move on though, we are going to add one more file to our project.
This will automate the last few steps so we don't need to repeatedly do the same actions in gdb:
`.gdbinit`
```
target remote :3333
load
```
## LED
Let us now turn on an LED! But how?
Well, first we should look at the documentation of our crate,
and you should be able to figure out how to get access to the gpio,
and set individual pins high and low:
``` rust
if let Some(p) = microbit::Peripherals::take() {
let mut gpio = p.GPIO.split();
let mut pin1 = gpio.pin1.into_push_pull_output();
pin1.set_high();
}
```
Next we need to see how these pins are hooked up,
for that we need [the micro:bit schematics][schematics] linked to at the bottom of [the hardware overview][hw].
On the first sheet you should find a diagram with a grid of numbered LEDs.
> If you do not know much about electronics:
> Each row and column (labelled ROW and COL) represent a GPIO output pin.
> The components labelled LED are light emitting diodes;
> LEDs only let current flow one way, and only emit light when current is flowing.
> If a row is set high, high voltage, and a column is set low, low voltage,
> the LED at the point that they cross will have a potential difference across it,
> so current will flow and it will light up.
It is worth noting that the 5x5 array of LEDs is wired up as a 9x3 array, with 2 missing.
This is usually done to make the circuit design easier.
The fifth sheet shows how each row and column correspond to each GPIO pin.
[hw]: http://tech.microbit.org/hardware/
[schematics]: https://github.com/bbcmicrobit/hardware/blob/master/SCH_BBC-Microbit_V1.3B.pdf
You should now have enough information to try and turn on an LED.

View File

@@ -0,0 +1,41 @@
# LED
This is my solution:
``` rust
#![no_std]
#![no_main]
extern crate panic_abort;
extern crate cortex_m_rt as rt;
#[macro_use(entry, exception)]
extern crate microbit;
use rt::ExceptionFrame;
use microbit::hal::prelude::*;
entry!(main);
fn main() -> ! {
if let Some(p) = microbit::Peripherals::take() {
let mut gpio = p.GPIO.split();
let mut led = gpio.pin13.into_push_pull_output();
let _ = gpio.pin4.into_push_pull_output();
led.set_high();
}
loop {}
}
exception!(HardFault, hard_fault);
fn hard_fault(ef: &ExceptionFrame) -> ! {
panic!("{:#?}", ef);
}
exception!(*, default_handler);
fn default_handler(irqn: i16) {
panic!("Unhandled exception (IRQn = {})", irqn);
}
```
It is worth noting that pin4 starts low, so does not need to be explicitly set low.

View File

@@ -0,0 +1 @@
# Debugging

View File

@@ -0,0 +1,8 @@
[package]
name = "rustled"
version = "0.1.0"
[dependencies]
panic-abort = "~0.2"
cortex-m-rt="~0.5"
microbit="~0.5"

View File

@@ -0,0 +1,11 @@
MEMORY
{
/* NOTE K = KiBi = 1024 bytes */
FLASH : ORIGIN = 0x00000000, LENGTH = 256K
RAM : ORIGIN = 0x20000000, LENGTH = 16K
}
/* This is where the call stack will be allocated. */
/* The stack is of the full descending type. */
/* NOTE Do NOT modify `_stack_start` unless you know what you are doing */
_stack_start = ORIGIN(RAM) + LENGTH(RAM);

View File

@@ -0,0 +1,29 @@
#![deny(unsafe_code)]
#![no_std]
extern crate aux5;
use aux5::prelude::*;
use aux5::{Delay, Leds};
fn main() {
let (mut delay, mut leds): (Delay, Leds) = aux5::init();
let period = 50_u16;
let mut step: usize = 0;
loop {
match step % 2 {
0 => leds[step/2].on(),
1 => {
let wrap_step = ((step + 16 - 3) / 2) % 8;
leds[wrap_step].off();
},
_ => unreachable!(),
}
delay.delay_ms(period);
match step {
15 => step = 0,
_ => step += 1,
}
}
}

58
src/hardware/README.md Normal file
View File

@@ -0,0 +1,58 @@
# Meet your hardware
Let's get familiar with the hardware we'll be working with.
## BBC micro:bit (the "microbit")
<p align="center">
<img title="microbit" src="http://tech.microbit.org/docs/hardware/assets/microbit-overview.png">
</p>
What does this board contain? For full details see the [microbit hardware page][microbit].
[microbit]: http://tech.microbit.org/hardware
- A Nordic nRF51822 microcontroller. This microcontroller has
- A single core ARM Cortex-M0 processor with a maximum clock frequency of 16 MHz.
- 256 KB of flash memory. (1 KB = 10**24** bytes)
- 16 KB of static RAM.
- many "peripherals": timers, GPIO, I2C, SPI, UART, etc.
- This microcontroller operates at (around) 3.3V.
- 2 user buttons on the front and 1 reset button on the back.
- A 5x5 array of user LEDs.
- A configureable 23-pin edge connector
- A 2.4GHz radio transciever with support for [bluetooth low energy][ble] (BLE).
[ble]: https://en.wikipedia.org/wiki/Bluetooth_Low_Energy
- An on-core nRF51 temperature sensor.
- An NXP/Freescale MMA8652 3-axis [accelerometer].
[accelerometer]: https://en.wikipedia.org/wiki/Accelerometer
- An NXP/Freescale MAG3110 3-axis [magnetometer].
[magnetometer]: https://en.wikipedia.org/wiki/Magnetometer
- A second microcontroller: NXP/Freescale KL26Z. This microcontroller handles the USB interface,
communication between your computer and the main microcontroller,
and changing the USB's input voltage from 5V to 3.3V.
## Micro-USB Cable
This can be any generic cable, and is used to connect the microbit to your computer.
## External battery pack
The external battery pack that comes with the microbit will not be used explicitly as part of this guide,
but feel free to use it to test your software without being tethered to a computer.

View File

@@ -0,0 +1,52 @@
# Requirements
## Knowledge
The only knowledge requirement to read this book is to know *some* Rust. It's hard to
quantify *some* but a good benchmark is having read and understood the first 14 chapters of [the Rust book][thebook].
[thebook]: https://doc.rust-lang.org/nightly/book/
## Hardware
To follow this material you'll only need a [micro:bit].
[micro:bit]: http://tech.microbit.org/hardware/
You can purchase the BBC micro:bit from [a large list of international resellers][resellers].
[resellers]: https://microbit.org/resellers/
<p align="center">
<img title="microbit" src="https://microbit.org/images/microbit-front.png" width="45%">
<img title="microbit" src="https://microbit.org/images/microbit-back.png" width="45%">
</p>
> **FAQ**: Wait, why do I need this specific device?
It makes my life and yours much easier.
The material is much, much more approachable if we don't have to worry about hardware differences.
Trust me on this one.
> **FAQ**: Can I follow this material with a different development board?
Maybe? It depends mainly on two things: your previous experience with microcontrollers and/or
whether there already exists a high level crate. A list of boards with high level crates available can be found [here][bsc].
[bsc]: https://github.com/rust-embedded/awesome-embedded-rust#board-support-crates
With other development boards, this text would lose most if not all its beginner friendliness
and "easy to follow"-ness, IMO.
There are other similar guides for different hardware. For a full list see [this list][books].
[books]: https://github.com/rust-embedded/awesome-embedded-rust/#books-blogs-and-training-materials
The following are worth a special mention:
- [Discovery](https://japaric.github.io/discovery/) by @japaric: The genesis guide which this is based on. Uses the STM32F3DISCOVERY.
If you have a different cortex-m development board and you don't consider yourself a total beginner, you are
better off starting with the [cortex-m-quickstart] project template.
[cortex-m-quickstart]: https://docs.rs/crate/cortex-m-quickstart

158
src/setup/LINUX.md Normal file
View File

@@ -0,0 +1,158 @@
# Linux
Here are the installation commands for a few Linux distributions.
## REQUIRED packages
- Ubuntu 16.04 or newer / Debian Jessie or newer
``` console
$ sudo apt-get install \
gcc-arm-none-eabi \
gdb-arm-none-eabi \
minicom \
openocd
```
- Fedora 23 or newer
``` console
$ sudo dnf install \
arm-none-eabi-gcc-cs \
arm-none-eabi-gdb \
minicom \
openocd
```
- Arch Linux
``` console
$ sudo pacman -S \
arm-none-eabi-gcc \
arm-none-eabi-gdb \
minicom \
openocd
```
- Other distros
For distros that don't have packages for [ARM's pre-built toolchain](https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads), download the "Linux 64-bit" file and put its `bin` directory on your path. Here's one way to do it:
``` console
$ mkdir -p ~/local && cd ~/local
$ tar xjf /path/to/downloaded/file/gcc-arm-none-eabi-7-2017-q4-major-linux.tar.bz2.tbz
```
Then, use your editor of choice to append to your `PATH` in the appropriate shell init file (e.g. `~/.zshrc` or `~/.bashrc`):
```
PATH=$PATH:$HOME/local/gcc-arm-none-eabi-7-2017-q4-major/bin
```
## Optional packages
- Ubuntu / Debian
``` console
$ sudo apt-get install \
bluez \
rfkill
```
- Fedora
``` console
$ sudo dnf install \
bluez \
rfkill
```
- Arch Linux
``` console
$ sudo pacman -S \
bluez \
bluez-utils \
rfkill
```
## udev rules
These rules let you use USB devices like the F3 and the Serial module without root privilege, i.e.
`sudo`.
Create these two files in `/etc/udev/rules.d` with the contents shown below.
``` console
$ cat /etc/udev/rules.d/99-ftdi.rules
```
``` text
# FT232 - USB <-> Serial Converter
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", GROUP="uucp"
```
``` console
$ cat /etc/udev/rules.d/99-openocd.rules
```
``` text
# STM32F3DISCOVERY rev A/B - ST-LINK/V2
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3748", GROUP="uucp"
# STM32F3DISCOVERY rev C+ - ST-LINK/V2-1
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374b", GROUP="uucp"
```
Then reload the udev rules with:
``` console
$ sudo udevadm control --reload-rules
```
If you had any board plugged to your laptop, unplug them and then plug them in again.
Finally, check if you are in the `uucp` group.
``` console
$ groups $(id -nu)
(..) uucp (..)
$ # ^^^^
```
(`$(id -nu)` returns your user name. In my case it's `japaric`.)
If `uucp` appears in the output. You are all set! Go to the [next section]. Otherwise, keep reading:
[next section]: 03-setup/verify.html
- Add yourself to the `uucp` group.
``` console
$ sudo usermod -a -G uucp $(id -u -n)
```
- Check again the output of `groups`. `uucp` should be there this time!
``` console
$ groups $(id -nu)
(..) uucp (..)
$ # ^^^^
```
You'll have to re-log for these changes to take effect. You have two options:
You can reboot or log out from your current session and then log in; this will close all the
programs you have open right now.
The other option is to use the command below:
``` console
$ su - $(id -nu)
```
to re-log *only in the current shell* and get access to `uucp` devices *only on that shell*. Other
shells *won't* have access to `uucp` devices unless you manually re-log on them with the same `su`
command.
Now, go to the [next section].

17
src/setup/MACOS.md Normal file
View File

@@ -0,0 +1,17 @@
# macOS
All the tools can be install using [Homebrew]:
[Homebrew]: http://brew.sh/
``` console
$ brew cask install gcc-arm-embedded
$ brew install minicom openocd
```
If the `brew cask` command doesn't work (`Error: Unknown command: cask`), then run `brew tap
Caskroom/tap` first and try again.
That's all! Go to the [next section].
[next section]: 03-setup/verify.html

66
src/setup/README.md Normal file
View File

@@ -0,0 +1,66 @@
# Development environment setup
Dealing with microcontrollers involves several tools as we'll be dealing with an architecture
different than your laptop's and we'll have to run and debug programs on a "remote" device.
## Documentation
Without documentation it is pretty much impossible to work with microcontrollers.
We'll be referring to the [micro:bit hardware page][microbit] and the links found within.
[microbit]: http://tech.microbit.org/hardware
*HEADS UP* Some of the links point to large PDF files several MBs in size.
## Tools
We'll use all the tools listed below. Where a minimum version is not specified, any recent version
should work but we have listed the version we have tested.
- Cargo & `rustc`.
- OpenOCD. version >=0.8
- `arm-none-eabi` toolchain. Tested version: gcc 8.1.0, binutils 2.30.
- `arm-none-eabi-gdb`.
- `minicom` on Linux and macOS. Tested version: 2.7.
Readers report that `picocom` also works but we'll use `minicom` in this book.
- `PuTTY` on Windows.
Next, follow OS-agnostic installation instructions for a few of the tools:
### `rustc` & Cargo
Install rustup by following the instructions at [https://rustup.rs](https://rustup.rs).
Then, install or switch to the nightly channel.
``` console
$ rustup default nightly
```
**NOTE** Make sure you have a nightly newer than `nightly-2018-06-22`.
`rustc -V` should return a date newer than the one shown below:
``` console
$ rustc -V
rustc 1.28.0-nightly (056f589fb 2018-06-22)
```
### `itmdump`
``` console
$ cargo install itm
```
### OS specific instructions
Now follow the instructions specific to the OS you are using:
- [Linux](setup/linux.html)
- [Windows](setup/windows.html)
- [macOS](setup/macos.html)

114
src/setup/VERIFY.md Normal file
View File

@@ -0,0 +1,114 @@
# Verify the installation
Let's verify that all the tools were installed correctly.
## Linux only
### Verify permissions
Connect the F3 to your laptop using an USB cable. Be sure to connect the cable to the "USB ST-LINK"
port, the USB port in the center of the edge of the board.
The F3 should now appear as a USB device (file) in `/dev/bus/usb`. Let's find out how it got
enumerated:
``` console
$ lsusb | grep -i stm
Bus 003 Device 004: ID 0483:374b STMicroelectronics ST-LINK/V2.1
$ # ^^^ ^^^
```
In my case, the F3 got connected to the bus #3 and got enumerated as the device #4. This means the
file `/dev/bus/usb/003/004` *is* the F3. Let's check its permissions:
``` console
$ ls -l /dev/bus/usb/003/004
crw-rw-r-- 1 root uucp 189, 262 Oct 27 00:00 /dev/bus/usb/003/004
```
The group should be `uucp`. If it's not ... then check your [udev rules] and try re-loading them
with:
[udev rules]: 03-setup/linux.html#udev%20rules
``` console
$ sudo udevadm control --reload-rules
```
Now let's repeat the procedure for the Serial module.
Unplug the F3 and plug the Serial module. Now, figure out what's its associated file:
``` console
$ lsusb | grep -i ft232
Bus 003 Device 005: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC
```
In my case, it's the `/dev/bus/usb/003/005`. Now, check its permissions:
``` console
$ ls -l /dev/bus/usb/003/005
crw-rw-r--+ 1 root uucp 189, 261 Oct 27 00:00 /dev/bus/usb/003/005
```
As before, the group should be `uucp`.
## All
### First OpenOCD connection
First, connect the F3 to your laptop using an USB cable. Connect the cable to the USB port in the
center of edge of the board, the one that's labeled "USB ST-LINK".
Two *red* LEDs should turn on right after connecting the USB cable to the board.
Next, run this command:
``` console
$ # *nix
$ openocd -f interface/stlink-v2-1.cfg -f target/stm32f3x.cfg
$ # Windows
$ # NOTE cygwin users have reported problems with the -s flag. If you run into
$ # that you can call openocd from the `C:\OpenOCD\share\scripts` directory
$ openocd -s C:\OpenOCD\share\scripts -f interface/stlink-v2-1.cfg -f target/stm32f3x.cfg
```
> **NOTE** Windows users: `C:\OpenOCD` is the directory where you installed OpenOCD to.
> **IMPORTANT** There is more than one hardware revision of the STM32F3DISCOVERY board. For older
> revisions, you'll need to change the "interface" argument to `-f interface/stlink-v2.cfg` (note:
> no `-1` at the end). Alternatively, older revisions can use `-f board/stm32f3discovery.cfg`
> instead of `-f interface/stlink-v2-1.cfg -f target/stm32f3x.cfg`.
You should see output like this:
``` console
Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "hla_swd". To override use 'transport select <transport>'.
adapter speed: 1000 kHz
adapter_nsrst_delay: 100
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
none separate
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : clock speed 950 kHz
Info : STLINK v2 JTAG v27 API v2 SWIM v15 VID 0x0483 PID 0x374B
Info : using stlink api v2
Info : Target voltage: 2.915608
Info : stm32f3x.cpu: hardware has 6 breakpoints, 4 watchpoints
```
(If you don't ... then check the [general troubleshooting] instructions.)
[general troubleshooting]: appendix/1-general-troubleshooting/README.html
`openocd` will block the terminal. That's fine.
Also, one of the red LEDs, the one closest to the USB port, should start oscillating between red
light and green light.
That's it! It works. You can now close/kill `openocd`.

50
src/setup/WINDOWS.md Normal file
View File

@@ -0,0 +1,50 @@
# Windows
## `arm-none-eabi-*`
ARM provides `.exe` installers for Windows. Grab one from [here][gcc], and follow the instructions.
Just before the installation process finishes tick/select the "Add path to environment variable"
option. Then verify that the tools are in your `%PATH%`:
``` console
$ arm-none-eabi-gcc -v
(..)
gcc version 5.4.1 20160919 (release) (..)
```
[gcc]: https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads
## OpenOCD
There's no official binary release of OpenOCD for Windows but there are unofficial releases
available [here][openocd]. Grab the 0.10.x zipfile and extract it somewhere in your drive (I
recommend `C:\OpenOCD` but with the drive letter that makes sense to you) then update your `%PATH%`
environment variable to include the following path: `C:\OpenOCD\bin` (or the path that you used
before).
[openocd]: https://github.com/gnu-mcu-eclipse/openocd/releases
Verify that OpenOCD is in yout `%PATH%` with:
``` console
$ openocd -v
Open On-Chip Debugger 0.10.0
(..)
```
## PuTTY
Download the latest `putty.exe` from [this site] and place it somewhere in your `%PATH%`.
[this site]: http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html
## ST-LINK USB driver
You'll also need to install [this USB driver] or OpenOCD won't work. Follow the installer
instructions and make sure you install the right (32-bit or 64-bit) version of the driver.
[this USB driver]: http://www.st.com/en/embedded-software/stsw-link009.html
That's all! Go to the [next section].
[next section]: 03-setup/verify.html