commit 8e05dfd010c5773685f72e32b91aa96cc3b812c6 Author: Michael Droogleever Date: Mon Jul 2 23:01:03 2018 +0200 Initial commit Much of the content here is a direct port from https://github.com/japaric/discovery diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ec75de4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +# Rust ignores +/target/ +Cargo.lock +**/*.rs.bk + +# mdBook ignores +*.org +.#* +.gdb_history +/template +book/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..02a3e83 --- /dev/null +++ b/.travis.yml @@ -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 diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..55774c9 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,12 @@ +[workspace] +members = [ + "src/getting-started", +] + +[profile.dev] +codegen-units = 1 +incremental = false + +[profile.release] +debug = true +lto = true diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 0000000..dc011d9 --- /dev/null +++ b/LICENSE-APACHE @@ -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. diff --git a/LICENSE-CC-BY b/LICENSE-CC-BY new file mode 100644 index 0000000..52bd145 --- /dev/null +++ b/LICENSE-CC-BY @@ -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. \ No newline at end of file diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000..ade7d05 --- /dev/null +++ b/LICENSE-MIT @@ -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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..e7e0846 --- /dev/null +++ b/README.md @@ -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. diff --git a/ci/after-success.sh b/ci/after-success.sh new file mode 100644 index 0000000..31d0323 --- /dev/null +++ b/ci/after-success.sh @@ -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 diff --git a/ci/install.sh b/ci/install.sh new file mode 100644 index 0000000..60790d9 --- /dev/null +++ b/ci/install.sh @@ -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 diff --git a/ci/script.sh b/ci/script.sh new file mode 100644 index 0000000..aef6a16 --- /dev/null +++ b/ci/script.sh @@ -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 diff --git a/src/README.md b/src/README.md new file mode 100644 index 0000000..4fb3519 --- /dev/null +++ b/src/README.md @@ -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 + + + + + + + +## 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 diff --git a/src/SUMMARY.md b/src/SUMMARY.md new file mode 100644 index 0000000..f1e74c8 --- /dev/null +++ b/src/SUMMARY.md @@ -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) + + + + diff --git a/src/appendix/explore.md b/src/appendix/explore.md new file mode 100644 index 0000000..5bb8fb6 --- /dev/null +++ b/src/appendix/explore.md @@ -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 diff --git a/src/appendix/troubleshooting.md b/src/appendix/troubleshooting.md new file mode 100644 index 0000000..431a3ae --- /dev/null +++ b/src/appendix/troubleshooting.md @@ -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 +``` diff --git a/src/background/README.md b/src/background/README.md new file mode 100644 index 0000000..76f7d35 --- /dev/null +++ b/src/background/README.md @@ -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. diff --git a/src/getting-started/.cargo/config b/src/getting-started/.cargo/config new file mode 100644 index 0000000..532c2e6 --- /dev/null +++ b/src/getting-started/.cargo/config @@ -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" diff --git a/src/getting-started/.gdbinit b/src/getting-started/.gdbinit new file mode 100644 index 0000000..512da1b --- /dev/null +++ b/src/getting-started/.gdbinit @@ -0,0 +1,4 @@ +target remote :3333 +load +break main +continue diff --git a/src/getting-started/00.00.README.md b/src/getting-started/00.00.README.md new file mode 100644 index 0000000..d978e0f --- /dev/null +++ b/src/getting-started/00.00.README.md @@ -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. diff --git a/src/getting-started/01.00.PROJECT.md b/src/getting-started/01.00.PROJECT.md new file mode 100644 index 0000000..ef4657a --- /dev/null +++ b/src/getting-started/01.00.PROJECT.md @@ -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 + ^^^ ^^^^ +``` diff --git a/src/getting-started/02.00.FLASH.md b/src/getting-started/02.00.FLASH.md new file mode 100644 index 0000000..4717cc8 --- /dev/null +++ b/src/getting-started/02.00.FLASH.md @@ -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 '. +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. diff --git a/src/getting-started/03.00.LED.md b/src/getting-started/03.00.LED.md new file mode 100644 index 0000000..b4343de --- /dev/null +++ b/src/getting-started/03.00.LED.md @@ -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. diff --git a/src/getting-started/04.00.DEBUGGING.md b/src/getting-started/04.00.DEBUGGING.md new file mode 100644 index 0000000..1e584c9 --- /dev/null +++ b/src/getting-started/04.00.DEBUGGING.md @@ -0,0 +1 @@ +# Debugging diff --git a/src/getting-started/Cargo.toml b/src/getting-started/Cargo.toml new file mode 100644 index 0000000..c54dec3 --- /dev/null +++ b/src/getting-started/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "rustled" +version = "0.1.0" + +[dependencies] +panic-abort = "~0.2" +cortex-m-rt="~0.5" +microbit="~0.5" diff --git a/src/getting-started/memory.x b/src/getting-started/memory.x new file mode 100644 index 0000000..1c75909 --- /dev/null +++ b/src/getting-started/memory.x @@ -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); diff --git a/src/getting-started/src/main.rs b/src/getting-started/src/main.rs new file mode 100644 index 0000000..87c9520 --- /dev/null +++ b/src/getting-started/src/main.rs @@ -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, + } + } +} diff --git a/src/hardware/README.md b/src/hardware/README.md new file mode 100644 index 0000000..6646823 --- /dev/null +++ b/src/hardware/README.md @@ -0,0 +1,58 @@ +# Meet your hardware + +Let's get familiar with the hardware we'll be working with. + +## BBC micro:bit (the "microbit") + +

+ +

+ +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. diff --git a/src/requirements/README.md b/src/requirements/README.md new file mode 100644 index 0000000..bf5c398 --- /dev/null +++ b/src/requirements/README.md @@ -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/ + +

+ + +

+ +> **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 diff --git a/src/setup/LINUX.md b/src/setup/LINUX.md new file mode 100644 index 0000000..fc22c8a --- /dev/null +++ b/src/setup/LINUX.md @@ -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]. diff --git a/src/setup/MACOS.md b/src/setup/MACOS.md new file mode 100644 index 0000000..fa9935e --- /dev/null +++ b/src/setup/MACOS.md @@ -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 diff --git a/src/setup/README.md b/src/setup/README.md new file mode 100644 index 0000000..ad51fca --- /dev/null +++ b/src/setup/README.md @@ -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) diff --git a/src/setup/VERIFY.md b/src/setup/VERIFY.md new file mode 100644 index 0000000..0350f5b --- /dev/null +++ b/src/setup/VERIFY.md @@ -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 '. +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`. diff --git a/src/setup/WINDOWS.md b/src/setup/WINDOWS.md new file mode 100644 index 0000000..7da7729 --- /dev/null +++ b/src/setup/WINDOWS.md @@ -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