diff --git a/Client/src/main.rs b/Client/src/main.rs index 98e1b0df836394e5bee1a668c924c27b75924de9..43720055fdcd5eb40c6b58a849d19f0b3eaec485 100644 --- a/Client/src/main.rs +++ b/Client/src/main.rs @@ -13,24 +13,35 @@ fn main() { let addr = "127.0.0.1:5683"; let endpoint = "test"; - coap_get(addr, endpoint); + let c = start_coap_client(addr); //CoAPClient::new(addr).unwrap(); + coap_get(c, addr, endpoint); println!("Request by POST:"); coap_post(addr, endpoint); } +fn start_coap_client(address: &str) -> CoAPClient { + // Creates the CoAP client for the specific IP address + CoAPClient::new(address).unwrap() +} -fn coap_get(address: &str, endpoint: &str) { - let client = CoAPClient::new(address).unwrap(); +fn coap_get(client: CoAPClient, address: &str, endpoint: &str) { + + // Creates a request to be let mut request = CoAPRequest::new(); - request.set_version(1); - request.set_type(MessageType::Confirmable); - request.set_code("0.01"); - request.set_message_id(1); - request.set_token(vec![0x51, 0x55, 0x77, 0xE8]); - request.add_option(CoAPOption::UriPath, endpoint.to_string().into_bytes()); + + // Setup of the message header (4 bytes) + request.set_version(1); + request.set_type(MessageType::Confirmable); // MessageType (Confirmable, Non-confirmable, Acknowledgement, Reset) + request.set_code("0.01"); // Code -> Request code (1-10) or Response code (40-255) + request.set_message_id(1); // 16-bit identifier for matching responses + request.set_token(vec![0x51, 0x55, 0x77, 0xE8]); // optional response matching tokens + request.add_option(CoAPOption::UriPath, endpoint.to_string().into_bytes()); // additional options. eg URI + + // Sends the request client.send(&request).unwrap(); + println!("Client request: coap://{}/{}", address, endpoint); match client.receive() { diff --git a/README.md b/README.md index fdd8822a68505db1631c2d630187afd38da6e1d6..107157af0dfe1816102e4102ede17b61110ba84d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ # Embedded rust with CoAp +This project aims to make CoAP on ARM embedded systems coded with [Rust](https://www.rust-lang.org) a thing. + +This project is part of the course D7018E at [LuleƄ tekniska universitet](https://www.ltu.se) taught by [Per Lindgren](https://www.ltu.se/staff/p/pln-1.11258). ## Installation -## Packages used \ No newline at end of file +## Crates used +- [coap](http://covertness.github.io/coap-rs/coap/index.html) \ No newline at end of file diff --git a/Server/Cargo.toml b/Server/Cargo.toml index e178afb295219df8b49e402d2b1429cd0bd8c8ea..3ce7582636973e4b231d173d24377d8a8c505978 100644 --- a/Server/Cargo.toml +++ b/Server/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "D7018E_CoAp_server" +name = "xoap" version = "0.1.0" authors = ["Joakim Lundberg <joakim@joakimlundberg.com>"] diff --git a/Server/src/main.rs b/Server/src/main.rs index ebfe6e22cce263e5cf0025105417dde51d3a818c..71be1b493d9135d2315003fbb679f5f147f56a97 100644 --- a/Server/src/main.rs +++ b/Server/src/main.rs @@ -1,7 +1,8 @@ -// CoAP Server +// CoAP Server -> Into the embedded system // D7018E - Embedded rust // Joakim Lundberg <joakim@joakimlundberg.com> +// Externally used crates extern crate coap; use std::io; diff --git a/nucleo/Cargo.toml b/nucleo/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..bc7a8bf8ca378e06670989add9607685c9a4618c --- /dev/null +++ b/nucleo/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "D7018E_Embedded_Nucleo" +version = "0.1.0" +authors = ["Joakim Lundberg <joakim@joakimlundberg.com>"] diff --git a/nucleo/app/.cargo/config b/nucleo/app/.cargo/config new file mode 100644 index 0000000000000000000000000000000000000000..b0bb50be8496ec094ac0a3111c0b22dd66d2c2be --- /dev/null +++ b/nucleo/app/.cargo/config @@ -0,0 +1,33 @@ +[target.thumbv6m-none-eabi] +runner = 'arm-none-eabi-gdb' +rustflags = [ + "-C", "link-arg=-Tlink.x", + "-C", "linker=arm-none-eabi-ld", + "-Z", "linker-flavor=ld", +] + +[target.thumbv7m-none-eabi] +runner = 'arm-none-eabi-gdb' +rustflags = [ + "-C", "link-arg=-Tlink.x", + "-C", "linker=arm-none-eabi-ld", + "-Z", "linker-flavor=ld", +] + +[target.thumbv7em-none-eabi] +runner = 'arm-none-eabi-gdb' +rustflags = [ + "-C", "link-arg=-Tlink.x", + "-C", "linker=arm-none-eabi-ld", + "-Z", "linker-flavor=ld", +] + +[target.thumbv7em-none-eabihf] +runner = 'arm-none-eabi-gdb' +rustflags = [ + "-C", "link-arg=-Tlink.x", + "-C", "linker=arm-none-eabi-ld", + "-Z", "linker-flavor=ld", +] +[build] +target = "thumbv7em-none-eabihf" diff --git a/nucleo/app/.gdbinit b/nucleo/app/.gdbinit new file mode 100644 index 0000000000000000000000000000000000000000..098ff6f90cac5691f155e0dfba1ce4e87be3f7f3 --- /dev/null +++ b/nucleo/app/.gdbinit @@ -0,0 +1,18 @@ +target remote :3333 + +monitor arm semihosting enable + +# # send captured ITM to the file itm.fifo +# # (the microcontroller SWO pin must be connected to the programmer SWO pin) +# # 8000000 must match the core clock frequency +# monitor tpiu config internal itm.fifo uart off 8000000 + +# # OR: make the microcontroller SWO pin output compatible with UART (8N1) +# # 2000000 is the frequency of the SWO pin +# monitor tpiu config external uart off 8000000 2000000 + +# # enable ITM port 0 +# monitor itm port 0 on + +load +step diff --git a/nucleo/app/.gitignore b/nucleo/app/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..6cda3bd5bb2701b20eb0c9c4913206aa9cff99d4 --- /dev/null +++ b/nucleo/app/.gitignore @@ -0,0 +1,4 @@ +**/*.rs.bk +.gdb_history +Cargo.lock +target/ diff --git a/nucleo/app/CHANGELOG.md b/nucleo/app/CHANGELOG.md new file mode 100644 index 0000000000000000000000000000000000000000..2392beb8711eec22f165e293820f421c5a3e5435 --- /dev/null +++ b/nucleo/app/CHANGELOG.md @@ -0,0 +1,108 @@ +# Change Log + +All notable changes to this project will be documented in this file. +This project adheres to [Semantic Versioning](http://semver.org/). + +## [Unreleased] + +## [v0.2.1] - 2017-07-14 + +### Added + +- Troubleshooting documentation: how to fix the error of overwriting the + `.cargo/config` file when you meant to append text to it. + +### Changed + +- Xargo.toml: Changed the source of the `compiler-builtins` crate from git to + the `rust-src` component. + +- Expanded the `device` example to do some I/O. + +## [v0.2.0] - 2017-07-07 + +### Changed + +- [breaking-change] Bumped the cortex-m and cortex-m-rt versions to v0.3.0. + +## [v0.1.8] - 2017-05-30 + +### Changed + +- Bumped the cortex-m-rt dependency to v0.2.3, and documented the `_stext` + symbol (see memory.x). + +## [v0.1.7] - 2017-05-27 + +### Added + +- Documentation and an example about how to use the heap and a dynamic memory + allocator. + +### Changed + +- Bumped the `cortex-m-rt` dependency to v0.2.2 +- Bumped the `cortex-m` dependency to v0.2.7 + +## [v0.1.6] - 2017-05-26 + +### Added + +- Set the default runner in .cargo/config to `arm-none-eabi-gdb`. Now `xargo + run` will build the program and start a debug session. + +## [v0.1.5] - 2017-05-16 + +### Added + +- A warning about using CARGO_INCREMENTAL to the how to use and the + troubleshooting sections. + +## [v0.1.4] - 2017-05-13 + +### Added + +- A dependencies section to the documentation + +### Changed + +- Extend troubleshooting section + +## [v0.1.3] - 2017-05-13 + +### Added + +- A troubleshooting section to the documentation + +### Changed + +- Bumped the cortex-m crate version to v0.2.6 + +## [v0.1.2] - 2017-05-07 + +### Fixed + +- .gdbinit: jump to reset handler after loading the program. + +## [v0.1.1] - 2017-04-27 + +### Changed + +- Bumped the version of the `cortex-m-rt` dependency to v0.2.0. NOTE that the + instantiation steps have slightly changed, the `memory.x` file changed, + because of this. + +## v0.1.0 - 2017-04-25 + +- Initial release + +[Unreleased]: https://github.com/japaric/cortex-m-quickstart/compare/v0.2.0...HEAD +[v0.2.0]: https://github.com/japaric/cortex-m-quickstart/compare/v0.1.8...v0.2.0 +[v0.1.8]: https://github.com/japaric/cortex-m-quickstart/compare/v0.1.7...v0.1.8 +[v0.1.7]: https://github.com/japaric/cortex-m-quickstart/compare/v0.1.6...v0.1.7 +[v0.1.6]: https://github.com/japaric/cortex-m-quickstart/compare/v0.1.5...v0.1.6 +[v0.1.5]: https://github.com/japaric/cortex-m-quickstart/compare/v0.1.4...v0.1.5 +[v0.1.4]: https://github.com/japaric/cortex-m-quickstart/compare/v0.1.3...v0.1.4 +[v0.1.3]: https://github.com/japaric/cortex-m-quickstart/compare/v0.1.2...v0.1.3 +[v0.1.2]: https://github.com/japaric/cortex-m-quickstart/compare/v0.1.1...v0.1.2 +[v0.1.1]: https://github.com/japaric/cortex-m-quickstart/compare/v0.1.0...v0.1.1 diff --git a/nucleo/app/Cargo.toml b/nucleo/app/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..0fd4818e4cecc5bc1bab95237e6d2f47bd6167a0 --- /dev/null +++ b/nucleo/app/Cargo.toml @@ -0,0 +1,32 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g. crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +name = "app" +version = "0.1.0" +authors = ["Joakim Lundberg <joakim@joakimlundberg.com>"] +description = "A template for building applications for ARM Cortex-M microcontrollers" +keywords = ["arm", "cortex-m", "template"] +categories = ["embedded", "no-std"] +license = "MIT OR Apache-2.0" +[profile.release] +lto = true +debug = true +[dependencies.cortex-m-semihosting] +version = "0.2.0" + +[dependencies.cortex-m-rt] +version = "0.3.3" +features = ["abort-on-panic"] + +[dependencies.cortex-m] +version = "0.3.0" diff --git a/nucleo/app/Cargo.toml.orig b/nucleo/app/Cargo.toml.orig new file mode 100644 index 0000000000000000000000000000000000000000..9c7018e1c3728d4350b3b04521b3cb62893b3439 --- /dev/null +++ b/nucleo/app/Cargo.toml.orig @@ -0,0 +1,33 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g. crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +name = "cortex-m-quickstart" +version = "0.2.1" +authors = ["Jorge Aparicio <jorge@japaric.io>"] +description = "A template for building applications for ARM Cortex-M microcontrollers" +keywords = ["arm", "cortex-m", "template"] +categories = ["embedded", "no-std"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/japaric/cortex-m-quickstart" +[profile.release] +lto = true +debug = true +[dependencies.cortex-m-semihosting] +version = "0.2.0" + +[dependencies.cortex-m-rt] +version = "0.3.3" +features = ["abort-on-panic"] + +[dependencies.cortex-m] +version = "0.3.0" diff --git a/nucleo/app/LICENSE-APACHE b/nucleo/app/LICENSE-APACHE new file mode 100644 index 0000000000000000000000000000000000000000..16fe87b06e802f094b3fbb0894b137bca2b16ef1 --- /dev/null +++ b/nucleo/app/LICENSE-APACHE @@ -0,0 +1,201 @@ + 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/nucleo/app/LICENSE-MIT b/nucleo/app/LICENSE-MIT new file mode 100644 index 0000000000000000000000000000000000000000..65a232326b2f0b4cfae3d1f2418cc6402e8766a5 --- /dev/null +++ b/nucleo/app/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2017 {{toml-escape author}} + +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/nucleo/app/README.md b/nucleo/app/README.md new file mode 100644 index 0000000000000000000000000000000000000000..cb99f10f14a0aa90b7360988d7f5e89586d4ce11 --- /dev/null +++ b/nucleo/app/README.md @@ -0,0 +1,22 @@ +# `cortex-m-quickstart` + +> A template for building applications for ARM Cortex-M microcontrollers + +# [Documentation](https://docs.rs/cortex-m-quickstart) + +# License + +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 http://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 +dual licensed as above, without any additional terms or conditions. diff --git a/nucleo/app/Xargo.toml b/nucleo/app/Xargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..89ad4cdcaeb6cce198c64fb0e03f570429243b42 --- /dev/null +++ b/nucleo/app/Xargo.toml @@ -0,0 +1,6 @@ +[dependencies.core] +stage = 0 + +[dependencies.compiler_builtins] +features = ["mem"] +stage = 1 \ No newline at end of file diff --git a/nucleo/app/build.rs b/nucleo/app/build.rs new file mode 100644 index 0000000000000000000000000000000000000000..88f7fef81f872bd233dd7c6b13bfe04dccb5a276 --- /dev/null +++ b/nucleo/app/build.rs @@ -0,0 +1,17 @@ +use std::env; +use std::fs::File; +use std::io::Write; +use std::path::PathBuf; + +fn main() { + // Put the linker script somewhere the linker can find it + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + File::create(out.join("memory.x")) + .unwrap() + .write_all(include_bytes!("memory.x")) + .unwrap(); + println!("cargo:rustc-link-search={}", out.display()); + + println!("cargo:rerun-if-changed=build.rs"); + println!("cargo:rerun-if-changed=memory.x"); +} diff --git a/nucleo/app/examples/allocator.rs b/nucleo/app/examples/allocator.rs new file mode 100644 index 0000000000000000000000000000000000000000..7f61af14dcc56667c1b721615d00ea67082a7c4a --- /dev/null +++ b/nucleo/app/examples/allocator.rs @@ -0,0 +1,79 @@ +//! How to use the heap and a dynamic memory allocator +//! +//! To compile this example you'll need to build the collections crate as part +//! of the Xargo sysroot. To do that change the Xargo.toml file to look like +//! this: +//! +//! ``` text +//! [dependencies.core] +//! stage = 0 +//! +//! [dependencies.collections] # NEW +//! stage = 0 +//! +//! [dependencies.compiler_builtins] +//! stage = 1 +//! ``` +//! +//! This example depends on the alloc-cortex-m crate so you'll have to add it +//! to your Cargo.toml: +//! +//! ``` text +//! # or edit the Cargo.toml file manually +//! $ cargo add alloc-cortex-m +//! ``` +//! +//! --- + +#[allow(deprecated)] +#![feature(collections)] +#![feature(used)] +#![no_std] + +// This is the allocator crate; you can use a different one +extern crate alloc_cortex_m; +#[macro_use] +extern crate collections; +extern crate cortex_m; +extern crate cortex_m_rt; +extern crate cortex_m_semihosting; + +use core::fmt::Write; + +use cortex_m::asm; +use cortex_m_semihosting::hio; + +fn main() { + // Initialize the allocator + unsafe { + extern "C" { + // Start of the heap + static mut _sheap: usize; + } + + // Size of the heap in words (1 word = 4 bytes) + // NOTE The bigger the heap the greater the chance to run into a stack + // overflow (collision between the stack and the heap) + const SIZE: isize = 256; + + // End of the heap + let _eheap = (&mut _sheap as *mut _).offset(SIZE); + + alloc_cortex_m::init(&mut _sheap, _eheap); + } + + // Growable array allocated on the heap + let xs = vec![0, 1, 2]; + + let mut stdout = hio::hstdout().unwrap(); + writeln!(stdout, "{:?}", xs).unwrap(); +} + +// As we are not using interrupts, we just register a dummy catch all handler +#[link_section = ".vector_table.interrupts"] +#[used] +static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240]; + +extern "C" fn default_handler() { + asm::bkpt(); +} diff --git a/nucleo/app/examples/crash.rs b/nucleo/app/examples/crash.rs new file mode 100644 index 0000000000000000000000000000000000000000..f0063234b6dcc62ed32df12f9a62e09634440efc --- /dev/null +++ b/nucleo/app/examples/crash.rs @@ -0,0 +1,85 @@ +//! Debugging a crash (exception) +//! +//! The `cortex-m-rt` crate provides functionality for this through a default +//! exception handler. When an exception is hit, the default handler will +//! trigger a breakpoint and in this debugging context the stacked registers +//! are accessible. +//! +//! In you run the example below, you'll be able to inspect the state of your +//! program under the debugger using these commands: +//! +//! ``` text +//! (gdb) # Exception frame = program state during the crash +//! (gdb) print/x *ef +//! $1 = cortex_m::exception::ExceptionFrame { +//! r0 = 0x2fffffff, +//! r1 = 0x2fffffff, +//! r2 = 0x0, +//! r3 = 0x0, +//! r12 = 0x0, +//! lr = 0x8000481, +//! pc = 0x8000460, +//! xpsr = 0x61000000, +//! } +//! +//! (gdb) # Where did we come from? +//! (gdb) backtrace +//! #0 cortex_m_rt::default_handler (ef=0x20004f54) at (..) +//! #1 <signal handler called> +//! #2 0x08000460 in core::ptr::read_volatile<u32> (src=0x2fffffff) at (..) +//! #3 0x08000480 in crash::main () at examples/crash.rs:68 +//! +//! (gdb) # Nail down the location of the crash +//! (gdb) disassemble/m ef.pc +//! Dump of assembler code for function core::ptr::read_volatile<u32>: +//! 408 pub unsafe fn read_volatile<T>(src: *const T) -> T { +//! 0x08000454 <+0>: sub sp, #20 +//! 0x08000456 <+2>: mov r1, r0 +//! 0x08000458 <+4>: str r0, [sp, #8] +//! 0x0800045a <+6>: ldr r0, [sp, #8] +//! 0x0800045c <+8>: str r0, [sp, #12] +//! +//! 409 intrinsics::volatile_load(src) +//! 0x0800045e <+10>: ldr r0, [sp, #12] +//! 0x08000460 <+12>: ldr r0, [r0, #0] +//! 0x08000462 <+14>: str r0, [sp, #16] +//! 0x08000464 <+16>: ldr r0, [sp, #16] +//! 0x08000466 <+18>: str r1, [sp, #4] +//! 0x08000468 <+20>: str r0, [sp, #0] +//! 0x0800046a <+22>: b.n 0x800046c <core::ptr::read_volatile<u32>+24> +//! +//! 410 } +//! 0x0800046c <+24>: ldr r0, [sp, #0] +//! 0x0800046e <+26>: add sp, #20 +//! 0x08000470 <+28>: bx lr +//! +//! End of assembler dump. +//! ``` +//! +//! --- + +#![feature(used)] +#![no_std] + +extern crate cortex_m; +extern crate cortex_m_rt; + +use core::ptr; + +use cortex_m::asm; + +fn main() { + // Read an invalid memory address + unsafe { + ptr::read_volatile(0x2FFF_FFFF as *const u32); + } +} + +// As we are not using interrupts, we just register a dummy catch all handler +#[link_section = ".vector_table.interrupts"] +#[used] +static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240]; + +extern "C" fn default_handler() { + asm::bkpt(); +} diff --git a/nucleo/app/examples/device.rs b/nucleo/app/examples/device.rs new file mode 100644 index 0000000000000000000000000000000000000000..0b28e19bde27a2c40994ac39f136004625d558fa --- /dev/null +++ b/nucleo/app/examples/device.rs @@ -0,0 +1,93 @@ +//! Using a device crate +//! +//! Crates generated using [`svd2rust`] are referred to as device crates. These +//! crates provides an API to access the peripherals of a device. When you +//! depend on one of these crates and the "rt" feature is enabled you don't need +//! link to the cortex-m-rt crate. +//! +//! [`svd2rust`]: https://crates.io/crates/svd2rust +//! +//! Device crates also provide an `interrupt!` macro to register interrupt +//! handlers. +//! +//! This example depends on the [`stm32f103xx`] crate so you'll have to add it +//! to your Cargo.toml. +//! +//! [`stm32f103xx`]: https://crates.io/crates/stm32f103xx +//! +//! ``` +//! $ edit Cargo.toml && cat $_ +//! [dependencies.stm32f103xx] +//! features = ["rt"] +//! version = "0.7.0" +//! ``` +//! +//! --- + +#![deny(warnings)] +#![feature(const_fn)] +#![no_std] + +extern crate cortex_m; +extern crate cortex_m_semihosting; +#[macro_use(exception, interrupt)] +extern crate stm32f103xx; + +use core::cell::RefCell; +use core::fmt::Write; + +use cortex_m::interrupt::{self, Mutex}; +use cortex_m::peripheral::SystClkSource; +use cortex_m_semihosting::hio::{self, HStdout}; +use stm32f103xx::Interrupt; + +static HSTDOUT: Mutex<RefCell<Option<HStdout>>> = + Mutex::new(RefCell::new(None)); + +fn main() { + interrupt::free(|cs| { + let hstdout = HSTDOUT.borrow(cs); + if let Ok(fd) = hio::hstdout() { + *hstdout.borrow_mut() = Some(fd); + } + + let nvic = stm32f103xx::NVIC.borrow(cs); + nvic.enable(Interrupt::TIM2); + + let syst = stm32f103xx::SYST.borrow(cs); + syst.set_clock_source(SystClkSource::Core); + syst.set_reload(8_000_000); // 1s + syst.enable_counter(); + syst.enable_interrupt(); + }); +} + +exception!(SYS_TICK, tick); + +fn tick() { + interrupt::free(|cs| { + let hstdout = HSTDOUT.borrow(cs); + if let Some(hstdout) = hstdout.borrow_mut().as_mut() { + writeln!(*hstdout, "Tick").ok(); + } + + let nvic = stm32f103xx::NVIC.borrow(cs); + + nvic.set_pending(Interrupt::TIM2); + }); +} + +interrupt!(TIM2, tock, locals: { + tocks: u32 = 0; +}); + +fn tock(l: &mut TIM2::Locals) { + l.tocks += 1; + + interrupt::free(|cs| { + let hstdout = HSTDOUT.borrow(cs); + if let Some(hstdout) = hstdout.borrow_mut().as_mut() { + writeln!(*hstdout, "Tock ({})", l.tocks).ok(); + } + }); +} diff --git a/nucleo/app/examples/hello.rs b/nucleo/app/examples/hello.rs new file mode 100644 index 0000000000000000000000000000000000000000..a3f0eb4506e1f12e37abc632b4771c571a1761de --- /dev/null +++ b/nucleo/app/examples/hello.rs @@ -0,0 +1,29 @@ +//! Prints "Hello, world!" on the OpenOCD console using semihosting +//! +//! --- + +#![feature(used)] +#![no_std] + +extern crate cortex_m; +extern crate cortex_m_rt; +extern crate cortex_m_semihosting; + +use core::fmt::Write; + +use cortex_m::asm; +use cortex_m_semihosting::hio; + +fn main() { + let mut stdout = hio::hstdout().unwrap(); + writeln!(stdout, "Hello, world!").unwrap(); +} + +// As we are not using interrupts, we just register a dummy catch all handler +#[link_section = ".vector_table.interrupts"] +#[used] +static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240]; + +extern "C" fn default_handler() { + asm::bkpt(); +} diff --git a/nucleo/app/examples/itm.rs b/nucleo/app/examples/itm.rs new file mode 100644 index 0000000000000000000000000000000000000000..4159c43c31bef75251ee5ea9ab236191ff4a6324 --- /dev/null +++ b/nucleo/app/examples/itm.rs @@ -0,0 +1,40 @@ +//! Sends "Hello, world!" through the ITM port 0 +//! +//! **IMPORTANT** Not all Cortex-M chips support ITM. You'll have to connect the +//! microcontroller's SWO pin to the SWD interface. Note that some development +//! boards don't provide this option. +//! +//! ITM is much faster than semihosting. Like 4 orders of magnitude or so. +//! +//! You'll need [`itmdump`] to receive the message on the host plus you'll need +//! to uncomment the `monitor` commands in the `.gdbinit` file. +//! +//! [`itmdump`]: https://docs.rs/itm/0.1.1/itm/ +//! +//! --- + +#![feature(used)] +#![no_std] + +#[macro_use] +extern crate cortex_m; +extern crate cortex_m_rt; + +use cortex_m::{asm, interrupt, peripheral}; + +fn main() { + interrupt::free(|cs| { + let itm = peripheral::ITM.borrow(&cs); + + iprintln!(&itm.stim[0], "Hello, world!"); + }); +} + +// As we are not using interrupts, we just register a dummy catch all handler +#[link_section = ".vector_table.interrupts"] +#[used] +static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240]; + +extern "C" fn default_handler() { + asm::bkpt(); +} diff --git a/nucleo/app/examples/override-exception-handler.rs b/nucleo/app/examples/override-exception-handler.rs new file mode 100644 index 0000000000000000000000000000000000000000..8785a2c62eccbcac5f381f011c6571d2001955fc --- /dev/null +++ b/nucleo/app/examples/override-exception-handler.rs @@ -0,0 +1,47 @@ +//! Overriding an exception handler +//! +//! You can override an exception handler using the [`exception!`][1] macro. +//! +//! [1]: https://docs.rs/cortex-m-rt/0.3.2/cortex_m_rt/macro.exception.html +//! +//! The default exception handler can be overridden using the +//! [`default_handler!`][2] macro +//! +//! [2]: https://docs.rs/cortex-m-rt/0.3.2/cortex_m_rt/macro.default_handler.html +//! +//! --- + +#![feature(used)] +#![no_std] + +extern crate cortex_m; +#[macro_use(exception)] +extern crate cortex_m_rt; + +use core::ptr; + +use cortex_m::asm; + +fn main() { + unsafe { + // Invalid memory access + ptr::read_volatile(0x2FFF_FFFF as *const u32); + } +} + +exception!(HARD_FAULT, handler); + +fn handler() { + // You'll hit this breakpoint rather than the one in cortex-m-rt + asm::bkpt() +} + +// As we are not using interrupts, we just register a dummy catch all handler +#[allow(dead_code)] +#[used] +#[link_section = ".vector_table.interrupts"] +static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240]; + +extern "C" fn default_handler() { + asm::bkpt(); +} diff --git a/nucleo/app/examples/panic.rs b/nucleo/app/examples/panic.rs new file mode 100644 index 0000000000000000000000000000000000000000..a85f42579a46a30184fd5a5f875396204369313b --- /dev/null +++ b/nucleo/app/examples/panic.rs @@ -0,0 +1,58 @@ +//! Defining the panic handler +//! +//! The panic handler can be defined through the `panic_fmt` [language item][1]. +//! Make sure that the "abort-on-panic" feature of the cortex-m-rt crate is +//! disabled to avoid redefining the language item. +//! +//! [1]: https://doc.rust-lang.org/unstable-book/language-features/lang-items.html +//! +//! --- + +#![feature(core_intrinsics)] +#![feature(lang_items)] +#![feature(used)] +#![no_std] + +extern crate cortex_m; +extern crate cortex_m_rt; +extern crate cortex_m_semihosting; + +use core::fmt::Write; +use core::intrinsics; + +use cortex_m::asm; +use cortex_m_semihosting::hio; + +fn main() { + panic!("Oops"); +} + +#[lang = "panic_fmt"] +#[no_mangle] +unsafe extern "C" fn rust_begin_unwind( + args: core::fmt::Arguments, + file: &'static str, + line: u32, + col: u32, +) -> ! { + if let Ok(mut stdout) = hio::hstdout() { + write!(stdout, "panicked at '") + .and_then(|_| { + stdout + .write_fmt(args) + .and_then(|_| writeln!(stdout, "', {}:{}", file, line)) + }) + .ok(); + } + + intrinsics::abort() +} + +// As we are not using interrupts, we just register a dummy catch all handler +#[link_section = ".vector_table.interrupts"] +#[used] +static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240]; + +extern "C" fn default_handler() { + asm::bkpt(); +} diff --git a/nucleo/app/gen-examples.sh b/nucleo/app/gen-examples.sh new file mode 100644 index 0000000000000000000000000000000000000000..660607b3227fb95ab543aa8d6275ff5c1cd921ae --- /dev/null +++ b/nucleo/app/gen-examples.sh @@ -0,0 +1,55 @@ +# Converts the examples in the `examples` directory into documentation in the +# `examples` module (`src/examples/*.rs`) + +set -ex + +main() { + local examples=( + hello + itm + panic + crash + override-exception-handler + device + allocator + ) + + rm -rf src/examples + + mkdir src/examples + + cat >src/examples/mod.rs <<'EOF' +//! Examples +// Auto-generated. Do not modify. +EOF + + local i=0 out= + for ex in ${examples[@]}; do + name=_${i}_${ex//-/_} + out=src/examples/${name}.rs + + echo "pub mod $name;" >> src/examples/mod.rs + + grep '//!' examples/$ex.rs > $out + echo '//!' >> $out + echo '//! ```' >> $out + grep -v '//!' examples/$ex.rs | ( + IFS='' + + while read line; do + echo "//! $line" >> $out; + done + ) + echo '//! ```' >> $out + echo '// Auto-generated. Do not modify.' >> $out + + + chmod -x $out + + i=$(( i + 1 )) + done + + chmod -x src/examples/mod.rs +} + +main diff --git a/nucleo/app/memory.x b/nucleo/app/memory.x new file mode 100644 index 0000000000000000000000000000000000000000..6eced1e5e6f8f5a91bc4d8805040b3db5e9a4c4e --- /dev/null +++ b/nucleo/app/memory.x @@ -0,0 +1,22 @@ +MEMORY +{ + /* NOTE K = KiBi = 1024 bytes */ + /* TODO Adjust these memory regions to match your device memory layout */ + /* Nucleo */ + FLASH : ORIGIN = 0x08000000, LENGTH = 512K + RAM : ORIGIN = 0x20000000, LENGTH = 96K + +} + +/* This is where the call stack will be allocated. */ +/* The stack is of the full descending type. */ +/* You may want to use this variable to locate the call stack and static + variables in different memory regions. Below is shown the default value */ +/* _stack_start = ORIGIN(RAM) + LENGTH(RAM); */ + +/* You can use this symbol to customize the location of the .text section */ +/* If omitted the .text section will be placed right after the .vector_table + section */ +/* This is required only on microcontrollers that store some configuration right + after the vector table */ +/* _stext = ORIGIN(FLASH) + 0x400; */ diff --git a/nucleo/app/src/main.rs b/nucleo/app/src/main.rs new file mode 100644 index 0000000000000000000000000000000000000000..5a051e2d75a84f23709e568353f66f162755556e --- /dev/null +++ b/nucleo/app/src/main.rs @@ -0,0 +1,44 @@ +// Nucleo +// D7018E - Embedded rust +// Joakim Lundberg <joakim@joakimlundberg.com> + +#![feature(used)] +#![no_std] + +extern crate cortex_m; +extern crate cortex_m_rt; +extern crate cortex_m_semihosting; + +use core::fmt::Write; + +use cortex_m::asm; +use cortex_m_semihosting::hio; + +fn main() { + // get a handle to the *host* standard output + let mut stdout = hio::hstdout().unwrap(); + + for n in 1..101 { + if n % 15 == 0 { + writeln!(stdout,"fizzbuzz"); + } else if n % 3 == 0 { + writeln!(stdout,"fizz"); + } else if n % 5 == 0 { + writeln!(stdout,"buzz"); + } else { + writeln!(stdout,"{}", n); + } + } + + // write "Hello, world!" to it + writeln!(stdout, "Hello, world!").unwrap(); +} + +// As we are not using interrupts, we just register a dummy catch all handler +#[link_section = ".vector_table.interrupts"] +#[used] +static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240]; + +extern "C" fn default_handler() { + asm::bkpt(); +} diff --git a/nucleo/src/main.rs b/nucleo/src/main.rs new file mode 100644 index 0000000000000000000000000000000000000000..12069c549a3de3a95d3866a6096be696f5ad47dd --- /dev/null +++ b/nucleo/src/main.rs @@ -0,0 +1,44 @@ +// Nucleo +// D7018E - Embedded rust +// Joakim Lundberg <joakim@joakimlundberg.com> + +#![feature(used)] +#![no_std] + +extern crate cortex_m; +extern crate cortex_m_rt; +extern crate cortex_m_semihosting; + +use core::fmt::Write; + +use cortex_m::asm; +use cortex_m_semihosting::hio; + +fn main() { + // get a handle to the *host* standard output + let mut stdout = hio::hstdout().unwrap(); + + for n in 1..101 { + if n % 15 == 0 { + writeln!(stdout,"fizzbuzz"); + } else if n % 3 == 0 { + writeln!(stdout,"fizz"); + } else if n % 5 == 0 { + writeln!(stdout,"buzz"); + } else { + writeln!(stdout,"{}", n); + } + } + + // write "Hello, world!" to it + writeln!(stdout, "Hello, world!").unwrap(); +} + +// As we are not using interrupts, we just register a dummy catch all handler +#[link_section = ".vector_table.interrupts"] +#[used] +static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240]; + +extern "C" fn default_handler() { + asm::bkpt(); +}