├── .github ├── dependabot.yml └── workflows │ ├── build.yml │ └── properties │ └── build.properties.json ├── CHANGELOG.md ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── rtic_v0.5 ├── nrf52_monotonic │ ├── .cargo │ │ └── config │ ├── .embed.toml │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── README.md │ └── src │ │ ├── main.rs │ │ └── monotonic_nrf52.rs ├── stm32f0_hid_mouse │ ├── .cargo │ │ └── config │ ├── .embed.toml │ ├── Cargo.lock │ ├── Cargo.toml │ ├── README.md │ ├── build.rs │ ├── memory.x │ └── src │ │ └── main.rs ├── stm32f1_bluepill_blinky │ ├── .cargo │ │ └── config │ ├── .embed.toml │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── README.md │ ├── memory.x │ └── src │ │ └── main.rs ├── stm32f3_blinky │ ├── .cargo │ │ └── config │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── memory.x │ ├── readme.md │ └── src │ │ └── main.rs ├── stm32l0_monotonic │ ├── .cargo │ │ └── config │ ├── .embed.toml │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── README.md │ └── src │ │ ├── main.rs │ │ └── monotonic_stm32l0.rs └── stm32l4_heartbeat │ ├── .cargo │ └── config │ ├── .embed.toml │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── README.md │ ├── memory.x │ └── src │ └── main.rs ├── rtic_v1 ├── nrf52_monotonic │ ├── .cargo │ │ └── config │ ├── .embed.toml │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── README.md │ └── src │ │ ├── main.rs │ │ └── monotonic_nrf52.rs ├── rp-pico_local_initilzd_resources │ ├── .cargo │ │ └── config.toml │ ├── Cargo.lock │ ├── Cargo.toml │ ├── build.rs │ ├── memory.x │ └── src │ │ └── main.rs ├── stm32f0_hid_mouse │ ├── .cargo │ │ └── config │ ├── .embed.toml │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── README.md │ ├── build.rs │ ├── memory.x │ └── src │ │ └── main.rs ├── stm32f1_bluepill_blinky │ ├── .cargo │ │ └── config │ ├── .embed.toml │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── README.md │ ├── memory.x │ └── src │ │ └── main.rs ├── stm32f3_blinky │ ├── .cargo │ │ └── config │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── Embed.toml │ ├── memory.x │ ├── readme.md │ └── src │ │ └── main.rs ├── stm32f411_edge_counter │ ├── .cargo │ │ └── config │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── memory.x │ └── src │ │ └── main.rs ├── stm32f4_independent_watchdog │ ├── .cargo │ │ └── config │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── README.md │ ├── memory.x │ └── src │ │ └── main.rs ├── stm32f4_pwm_monitor │ ├── .cargo │ │ └── config │ ├── Cargo.lock │ ├── Cargo.toml │ ├── memory.x │ └── src │ │ ├── main.rs │ │ └── tim8.rs ├── stm32l0_monotonic │ ├── .cargo │ │ └── config │ ├── .embed.toml │ ├── .gitignore │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs └── stm32l4_heartbeat │ ├── .cargo │ └── config │ ├── .embed.toml │ ├── .gitignore │ ├── Cargo.toml │ ├── memory.x │ └── src │ └── main.rs └── update_dependabot_config.sh /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # file automatically generated using update_dependabot.sh, re-run the script to update this file! 2 | version: 2 3 | updates: 4 | - package-ecosystem: "github-actions" 5 | directory: "/" 6 | schedule: 7 | interval: "weekly" 8 | - package-ecosystem: "cargo" 9 | directory: "/rtic_v0.5/nrf52_monotonic" 10 | schedule: 11 | interval: "weekly" 12 | rebase-strategy: "disabled" 13 | - package-ecosystem: "cargo" 14 | directory: "/rtic_v0.5/stm32f0_hid_mouse" 15 | schedule: 16 | interval: "weekly" 17 | rebase-strategy: "disabled" 18 | - package-ecosystem: "cargo" 19 | directory: "/rtic_v0.5/stm32f1_bluepill_blinky" 20 | schedule: 21 | interval: "weekly" 22 | rebase-strategy: "disabled" 23 | - package-ecosystem: "cargo" 24 | directory: "/rtic_v0.5/stm32f3_blinky" 25 | schedule: 26 | interval: "weekly" 27 | rebase-strategy: "disabled" 28 | - package-ecosystem: "cargo" 29 | directory: "/rtic_v0.5/stm32l0_monotonic" 30 | schedule: 31 | interval: "weekly" 32 | rebase-strategy: "disabled" 33 | - package-ecosystem: "cargo" 34 | directory: "/rtic_v0.5/stm32l4_heartbeat" 35 | schedule: 36 | interval: "weekly" 37 | rebase-strategy: "disabled" 38 | - package-ecosystem: "cargo" 39 | directory: "/rtic_v1/nrf52_monotonic" 40 | schedule: 41 | interval: "weekly" 42 | rebase-strategy: "disabled" 43 | - package-ecosystem: "cargo" 44 | directory: "/rtic_v1/rp-pico_local_initilzd_resources" 45 | schedule: 46 | interval: "weekly" 47 | rebase-strategy: "disabled" 48 | - package-ecosystem: "cargo" 49 | directory: "/rtic_v1/stm32f0_hid_mouse" 50 | schedule: 51 | interval: "weekly" 52 | rebase-strategy: "disabled" 53 | - package-ecosystem: "cargo" 54 | directory: "/rtic_v1/stm32f1_bluepill_blinky" 55 | schedule: 56 | interval: "weekly" 57 | rebase-strategy: "disabled" 58 | - package-ecosystem: "cargo" 59 | directory: "/rtic_v1/stm32f3_blinky" 60 | schedule: 61 | interval: "weekly" 62 | rebase-strategy: "disabled" 63 | - package-ecosystem: "cargo" 64 | directory: "/rtic_v1/stm32f411_edge_counter" 65 | schedule: 66 | interval: "weekly" 67 | rebase-strategy: "disabled" 68 | - package-ecosystem: "cargo" 69 | directory: "/rtic_v1/stm32f4_independent_watchdog" 70 | schedule: 71 | interval: "weekly" 72 | rebase-strategy: "disabled" 73 | - package-ecosystem: "cargo" 74 | directory: "/rtic_v1/stm32f4_pwm_monitor" 75 | schedule: 76 | interval: "weekly" 77 | rebase-strategy: "disabled" 78 | - package-ecosystem: "cargo" 79 | directory: "/rtic_v1/stm32l0_monotonic" 80 | schedule: 81 | interval: "weekly" 82 | rebase-strategy: "disabled" 83 | - package-ecosystem: "cargo" 84 | directory: "/rtic_v1/stm32l4_heartbeat" 85 | schedule: 86 | interval: "weekly" 87 | rebase-strategy: "disabled" 88 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: 3 | merge_group: 4 | pull_request: 5 | push: 6 | branches: 7 | - master 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | # Run cargo fmt --check 14 | style: 15 | name: style 16 | runs-on: ubuntu-22.04 17 | steps: 18 | - name: Checkout 19 | uses: actions/checkout@v4 20 | 21 | - name: Configure Rust target (v6, v7, v8.b v8.m) 22 | run: | 23 | rustup target add thumbv6m-none-eabi 24 | rustup target add thumbv7m-none-eabi 25 | rustup target add thumbv7em-none-eabihf 26 | rustup target add thumbv8m.base-none-eabi 27 | rustup target add thumbv8m.main-none-eabi 28 | 29 | - name: cargo fmt --check 30 | run: find . -type f -name Cargo.toml -execdir cargo fmt --check --manifest-path {} + 31 | 32 | # Compilation check 33 | check: 34 | name: check 35 | runs-on: ubuntu-22.04 36 | strategy: 37 | matrix: 38 | rticversion: 39 | - v0.5 40 | - v1 41 | steps: 42 | - name: Checkout 43 | uses: actions/checkout@v4 44 | 45 | - name: Cache Dependencies 46 | uses: Swatinem/rust-cache@v2 47 | 48 | - name: Configure Rust target (v6, v7, v8.b v8.m) 49 | run: | 50 | rustup target add thumbv6m-none-eabi 51 | rustup target add thumbv7m-none-eabi 52 | rustup target add thumbv7em-none-eabihf 53 | rustup target add thumbv8m.base-none-eabi 54 | rustup target add thumbv8m.main-none-eabi 55 | 56 | - name: Install flip-link 57 | run: cargo install flip-link 58 | 59 | - name: cargo check 60 | run: find rtic_${{ matrix.rticversion }} -type f -name Cargo.toml -execdir cargo build --release --manifest-path {} + 61 | 62 | # Clippy 63 | clippy: 64 | name: Cargo clippy 65 | runs-on: ubuntu-22.04 66 | strategy: 67 | matrix: 68 | rticversion: 69 | - v0.5 70 | - v1 71 | 72 | steps: 73 | - name: Checkout 74 | uses: actions/checkout@v4 75 | 76 | - name: Cache Dependencies 77 | uses: Swatinem/rust-cache@v2 78 | 79 | - name: Configure Rust target (v6, v7, v8.b v8.m) 80 | run: | 81 | rustup target add thumbv6m-none-eabi 82 | rustup target add thumbv7m-none-eabi 83 | rustup target add thumbv7em-none-eabihf 84 | rustup target add thumbv8m.base-none-eabi 85 | rustup target add thumbv8m.main-none-eabi 86 | 87 | - name: cargo clippy 88 | run: find rtic_${{ matrix.rticversion }} -type f -name Cargo.toml -execdir cargo clippy --target-dir /tmp/build --manifest-path {} + 89 | 90 | # Compilation 91 | build: 92 | name: build 93 | runs-on: ubuntu-22.04 94 | strategy: 95 | matrix: 96 | rticversion: 97 | - v0.5 98 | - v1 99 | steps: 100 | - name: Checkout 101 | uses: actions/checkout@v4 102 | 103 | - name: Cache Dependencies 104 | uses: Swatinem/rust-cache@v2 105 | 106 | - name: Configure Rust target (v6, v7, v8.b v8.m) 107 | run: | 108 | rustup target add thumbv6m-none-eabi 109 | rustup target add thumbv7m-none-eabi 110 | rustup target add thumbv7em-none-eabihf 111 | rustup target add thumbv8m.base-none-eabi 112 | rustup target add thumbv8m.main-none-eabi 113 | 114 | - name: Install flip-link 115 | run: cargo install flip-link 116 | 117 | - name: cargo build 118 | run: find rtic_${{ matrix.rticversion }} -type f -name Cargo.toml -execdir cargo build --release --manifest-path {} + 119 | 120 | check-dependabot-config: 121 | name: Ensure that `dependabot.yml` is up to date 122 | runs-on: ubuntu-22.04 123 | steps: 124 | - name: Checkout 125 | uses: actions/checkout@v4 126 | - name: Run the update script 127 | run: ./update_dependabot_config.sh 128 | - name: Ensure that nothing has changed 129 | run: git diff && git diff --quiet 130 | 131 | # Refs: https://github.com/rust-lang/crater/blob/9ab6f9697c901c4a44025cf0a39b73ad5b37d198/.github/workflows/bors.yml#L125-L149 132 | # 133 | # ALL THE PREVIOUS JOBS NEEDS TO BE ADDED TO THE `needs` SECTION OF THIS JOB! 134 | 135 | ci-success: 136 | name: ci 137 | if: github.event_name == 'push' && success() 138 | needs: 139 | - style 140 | - check 141 | - clippy 142 | - build 143 | - check-dependabot-config 144 | runs-on: ubuntu-22.04 145 | steps: 146 | - name: Mark the job as a success 147 | run: exit 0 148 | -------------------------------------------------------------------------------- /.github/workflows/properties/build.properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Build", 3 | "description": "RTIC Examples Test Suite", 4 | "iconName": "rust", 5 | "categories": ["Rust"] 6 | } 7 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](http://keepachangelog.com/) 6 | and this project adheres to [Semantic Versioning](http://semver.org/). 7 | 8 | For each category, *Added*, *Changed*, *Fixed* add new entries at the top! 9 | 10 | ## Unreleased 11 | 12 | ### Added 13 | 14 | - Added Clippy to CI 15 | - Add `flip-link` to support examples using it 16 | - Add example for an IWDG on an STM32F4 with RTIC v1.0 17 | 18 | ### Changed 19 | 20 | - CI: Use native Rust/Rustup 21 | - Updated v0.6-alpha.5 project to RTIC v1.0 22 | 23 | ### Fixed 24 | 25 | - Use rust-cache instead of native GHA cache 26 | - Update stm32l4 to use heapless 0.6 27 | - Fix cargo fmt to actually fail CI 28 | - Fixed folder structure to better match RTIC versions 29 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Jorge Aparicio 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `RTIC examples` 2 | 3 | > Here you can find examples on different aspects of the RTIC scheduler for older versions fo the framework. 4 | 5 | > To see examples for the Latest Version of RTIC, see the [main repo](https://github.com/rtic-rs/rtic). 6 | 7 | ## Structure 8 | 9 | This repo does have example applications based on RTIC framework for popular hardware platforms (for example nRF series and Bluepill). 10 | 11 | `rtic_v0.5` dir is for `RTIC` version `v0.5.x`, `rtic_v1` for `v1.0`. 12 | Each folder does have a full project structure with `README.md`, `Cargo.toml` and everything else needed to get the project to compile. 13 | 14 | ## Requirements 15 | 16 | To run these examples, you need to have working environment as described in [Installing the tools](https://rust-embedded.github.io/book/intro/install.html) chapter of **The Embedded Rust Book**. 17 | 18 | Short list: 19 | 20 | * Rust and cargo 21 | * Toolchain for your microcontroller 22 | * OpenOCD 23 | 24 | ## Contributing 25 | New examples are always welcome! 26 | 27 | When contributing a new example you must make sure to also add it to `.github/dependabot.yml`. To do so, run `update_dependabot_config.sh` which will update the file for you. 28 | 29 | ## External examples 30 | 31 | Some projects maintain RTIC examples in their own repository. Follow these links to find more RTIC examples. 32 | 33 | - The [`teensy4-rs` project](https://github.com/mciantyre/teensy4-rs) maintains `RTIC v1.0` examples that run on the Teensy 4.0 and 4.1. 34 | 35 | ## License 36 | 37 | Licensed under either of 38 | 39 | * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or 40 | [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)) 41 | * MIT license ([LICENSE-MIT](LICENSE-MIT) or [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT)) 42 | 43 | at your option. 44 | 45 | ### Contribution 46 | 47 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the 48 | work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any 49 | additional terms or conditions. 50 | -------------------------------------------------------------------------------- /rtic_v0.5/nrf52_monotonic/.cargo/config: -------------------------------------------------------------------------------- 1 | [target.thumbv7m-none-eabi] 2 | # uncomment this to make `cargo run` execute programs on QEMU 3 | # runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel" 4 | 5 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] 6 | # uncomment ONE of these three option to make `cargo run` start a GDB session 7 | # which option to pick depends on your system 8 | # runner = "arm-none-eabi-gdb -q -x jlink.gdb" 9 | runner = "arm-none-eabi-gdb -q -x openocd.gdb" 10 | # runner = "gdb-multiarch -q -x openocd.gdb" 11 | # runner = "gdb -q -x openocd.gdb" 12 | 13 | rustflags = [ 14 | # LLD (shipped with the Rust toolchain) is used as the default linker 15 | "-C", "link-arg=-Tlink.x", 16 | 17 | # if you run into problems with LLD switch to the GNU linker by commenting out 18 | # this line 19 | # "-C", "linker=arm-none-eabi-ld", 20 | 21 | # if you need to link to pre-compiled C libraries provided by a C toolchain 22 | # use GCC as the linker by commenting out both lines above and then 23 | # uncommenting the three lines below 24 | # "-C", "linker=arm-none-eabi-gcc", 25 | # "-C", "link-arg=-Wl,-Tlink.x", 26 | # "-C", "link-arg=-nostartfiles", 27 | 28 | # uncomment for unchecked wrapping arithmetics also in dev mode 29 | # "-Z", "force-overflow-checks=off", 30 | ] 31 | 32 | [build] 33 | # Pick ONE of these compilation targets 34 | # target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+ 35 | # target = "thumbv7m-none-eabi" # Cortex-M3 36 | # target = "thumbv7em-none-eabi" # Cortex-M4 and Cortex-M7 (no FPU) 37 | target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU) 38 | -------------------------------------------------------------------------------- /rtic_v0.5/nrf52_monotonic/.embed.toml: -------------------------------------------------------------------------------- 1 | # Refer to https://github.com/probe-rs/cargo-embed/blob/master/src/config/default.toml 2 | # for the comprehensive list of options 3 | 4 | [default.general] 5 | chip = "nrf52832" 6 | 7 | [default.rtt] 8 | enabled = true 9 | show_timestamps = true 10 | 11 | [default.gdb] 12 | # Whether or not a GDB server should be opened after flashing. 13 | # This is exclusive and cannot be used with RTT at the moment. 14 | enabled = false 15 | # The connection string in host:port format wher the GDB server will open a socket. 16 | # gdb_connection_string 17 | -------------------------------------------------------------------------------- /rtic_v0.5/nrf52_monotonic/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | -------------------------------------------------------------------------------- /rtic_v0.5/nrf52_monotonic/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "app" 7 | version = "0.1.0" 8 | dependencies = [ 9 | "cortex-m-rtic", 10 | "cortex-m-semihosting 0.5.0", 11 | "nrf52832-hal", 12 | "panic-semihosting", 13 | ] 14 | 15 | [[package]] 16 | name = "as-slice" 17 | version = "0.1.5" 18 | source = "registry+https://github.com/rust-lang/crates.io-index" 19 | checksum = "45403b49e3954a4b8428a0ac21a4b7afadccf92bfd96273f1a58cd4812496ae0" 20 | dependencies = [ 21 | "generic-array 0.12.4", 22 | "generic-array 0.13.3", 23 | "generic-array 0.14.6", 24 | "stable_deref_trait", 25 | ] 26 | 27 | [[package]] 28 | name = "autocfg" 29 | version = "1.1.0" 30 | source = "registry+https://github.com/rust-lang/crates.io-index" 31 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 32 | 33 | [[package]] 34 | name = "az" 35 | version = "1.2.1" 36 | source = "registry+https://github.com/rust-lang/crates.io-index" 37 | checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" 38 | 39 | [[package]] 40 | name = "bare-metal" 41 | version = "0.2.5" 42 | source = "registry+https://github.com/rust-lang/crates.io-index" 43 | checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" 44 | dependencies = [ 45 | "rustc_version", 46 | ] 47 | 48 | [[package]] 49 | name = "bitfield" 50 | version = "0.13.2" 51 | source = "registry+https://github.com/rust-lang/crates.io-index" 52 | checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" 53 | 54 | [[package]] 55 | name = "bytemuck" 56 | version = "1.12.3" 57 | source = "registry+https://github.com/rust-lang/crates.io-index" 58 | checksum = "aaa3a8d9a1ca92e282c96a32d6511b695d7d994d1d102ba85d279f9b2756947f" 59 | 60 | [[package]] 61 | name = "byteorder" 62 | version = "1.4.3" 63 | source = "registry+https://github.com/rust-lang/crates.io-index" 64 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 65 | 66 | [[package]] 67 | name = "cast" 68 | version = "0.3.0" 69 | source = "registry+https://github.com/rust-lang/crates.io-index" 70 | checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" 71 | 72 | [[package]] 73 | name = "cfg-if" 74 | version = "1.0.0" 75 | source = "registry+https://github.com/rust-lang/crates.io-index" 76 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 77 | 78 | [[package]] 79 | name = "cortex-m" 80 | version = "0.7.6" 81 | source = "registry+https://github.com/rust-lang/crates.io-index" 82 | checksum = "70858629a458fdfd39f9675c4dc309411f2a3f83bede76988d81bf1a0ecee9e0" 83 | dependencies = [ 84 | "bare-metal", 85 | "bitfield", 86 | "embedded-hal", 87 | "volatile-register", 88 | ] 89 | 90 | [[package]] 91 | name = "cortex-m-rt" 92 | version = "0.7.2" 93 | source = "registry+https://github.com/rust-lang/crates.io-index" 94 | checksum = "d6d3328b8b5534f0c90acd66b68950f2763b37e0173cac4d8b4937c4a80761f9" 95 | dependencies = [ 96 | "cortex-m-rt-macros", 97 | ] 98 | 99 | [[package]] 100 | name = "cortex-m-rt-macros" 101 | version = "0.7.0" 102 | source = "registry+https://github.com/rust-lang/crates.io-index" 103 | checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7" 104 | dependencies = [ 105 | "proc-macro2", 106 | "quote", 107 | "syn", 108 | ] 109 | 110 | [[package]] 111 | name = "cortex-m-rtic" 112 | version = "0.5.9" 113 | source = "registry+https://github.com/rust-lang/crates.io-index" 114 | checksum = "fb77bb72c171d0aa52a2954d8dc7e3f0800ab54b8df7d826f138abbea9eb2794" 115 | dependencies = [ 116 | "cortex-m", 117 | "cortex-m-rtic-macros", 118 | "heapless", 119 | "rtic-core", 120 | "version_check", 121 | ] 122 | 123 | [[package]] 124 | name = "cortex-m-rtic-macros" 125 | version = "0.5.3" 126 | source = "registry+https://github.com/rust-lang/crates.io-index" 127 | checksum = "cc874eda99515b15e67f03562726a530388f454431096d30131051b52b840559" 128 | dependencies = [ 129 | "proc-macro2", 130 | "quote", 131 | "rtic-syntax", 132 | "syn", 133 | ] 134 | 135 | [[package]] 136 | name = "cortex-m-semihosting" 137 | version = "0.3.7" 138 | source = "registry+https://github.com/rust-lang/crates.io-index" 139 | checksum = "6bffa6c1454368a6aa4811ae60964c38e6996d397ff8095a8b9211b1c1f749bc" 140 | dependencies = [ 141 | "cortex-m", 142 | ] 143 | 144 | [[package]] 145 | name = "cortex-m-semihosting" 146 | version = "0.5.0" 147 | source = "registry+https://github.com/rust-lang/crates.io-index" 148 | checksum = "c23234600452033cc77e4b761e740e02d2c4168e11dbf36ab14a0f58973592b0" 149 | dependencies = [ 150 | "cortex-m", 151 | ] 152 | 153 | [[package]] 154 | name = "crunchy" 155 | version = "0.2.2" 156 | source = "registry+https://github.com/rust-lang/crates.io-index" 157 | checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" 158 | 159 | [[package]] 160 | name = "embedded-dma" 161 | version = "0.2.0" 162 | source = "registry+https://github.com/rust-lang/crates.io-index" 163 | checksum = "994f7e5b5cb23521c22304927195f236813053eb9c065dd2226a32ba64695446" 164 | dependencies = [ 165 | "stable_deref_trait", 166 | ] 167 | 168 | [[package]] 169 | name = "embedded-hal" 170 | version = "0.2.7" 171 | source = "registry+https://github.com/rust-lang/crates.io-index" 172 | checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" 173 | dependencies = [ 174 | "nb 0.1.3", 175 | "void", 176 | ] 177 | 178 | [[package]] 179 | name = "embedded-storage" 180 | version = "0.3.0" 181 | source = "registry+https://github.com/rust-lang/crates.io-index" 182 | checksum = "156d7a2fdd98ebbf9ae579cbceca3058cff946e13f8e17b90e3511db0508c723" 183 | 184 | [[package]] 185 | name = "fixed" 186 | version = "1.20.0" 187 | source = "registry+https://github.com/rust-lang/crates.io-index" 188 | checksum = "418922d2c280b8c68f82699494cc8c48f392233233a9a8b9a48a57a36c0ad0ef" 189 | dependencies = [ 190 | "az", 191 | "bytemuck", 192 | "half", 193 | "typenum", 194 | ] 195 | 196 | [[package]] 197 | name = "generic-array" 198 | version = "0.12.4" 199 | source = "registry+https://github.com/rust-lang/crates.io-index" 200 | checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" 201 | dependencies = [ 202 | "typenum", 203 | ] 204 | 205 | [[package]] 206 | name = "generic-array" 207 | version = "0.13.3" 208 | source = "registry+https://github.com/rust-lang/crates.io-index" 209 | checksum = "f797e67af32588215eaaab8327027ee8e71b9dd0b2b26996aedf20c030fce309" 210 | dependencies = [ 211 | "typenum", 212 | ] 213 | 214 | [[package]] 215 | name = "generic-array" 216 | version = "0.14.6" 217 | source = "registry+https://github.com/rust-lang/crates.io-index" 218 | checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" 219 | dependencies = [ 220 | "typenum", 221 | "version_check", 222 | ] 223 | 224 | [[package]] 225 | name = "half" 226 | version = "2.1.0" 227 | source = "registry+https://github.com/rust-lang/crates.io-index" 228 | checksum = "ad6a9459c9c30b177b925162351f97e7d967c7ea8bab3b8352805327daf45554" 229 | dependencies = [ 230 | "crunchy", 231 | ] 232 | 233 | [[package]] 234 | name = "hash32" 235 | version = "0.1.1" 236 | source = "registry+https://github.com/rust-lang/crates.io-index" 237 | checksum = "d4041af86e63ac4298ce40e5cca669066e75b6f1aa3390fe2561ffa5e1d9f4cc" 238 | dependencies = [ 239 | "byteorder", 240 | ] 241 | 242 | [[package]] 243 | name = "hashbrown" 244 | version = "0.12.3" 245 | source = "registry+https://github.com/rust-lang/crates.io-index" 246 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 247 | 248 | [[package]] 249 | name = "heapless" 250 | version = "0.6.1" 251 | source = "registry+https://github.com/rust-lang/crates.io-index" 252 | checksum = "634bd4d29cbf24424d0a4bfcbf80c6960129dc24424752a7d1d1390607023422" 253 | dependencies = [ 254 | "as-slice", 255 | "generic-array 0.14.6", 256 | "hash32", 257 | "stable_deref_trait", 258 | ] 259 | 260 | [[package]] 261 | name = "indexmap" 262 | version = "1.9.2" 263 | source = "registry+https://github.com/rust-lang/crates.io-index" 264 | checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" 265 | dependencies = [ 266 | "autocfg", 267 | "hashbrown", 268 | ] 269 | 270 | [[package]] 271 | name = "nb" 272 | version = "0.1.3" 273 | source = "registry+https://github.com/rust-lang/crates.io-index" 274 | checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" 275 | dependencies = [ 276 | "nb 1.0.0", 277 | ] 278 | 279 | [[package]] 280 | name = "nb" 281 | version = "1.0.0" 282 | source = "registry+https://github.com/rust-lang/crates.io-index" 283 | checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae" 284 | 285 | [[package]] 286 | name = "nrf-hal-common" 287 | version = "0.16.0" 288 | source = "registry+https://github.com/rust-lang/crates.io-index" 289 | checksum = "cd244c63d588066d75cffdcae8a03299fd5fb272e36bdde4a9f922f3e4bc6e4b" 290 | dependencies = [ 291 | "cast", 292 | "cfg-if", 293 | "cortex-m", 294 | "embedded-dma", 295 | "embedded-hal", 296 | "embedded-storage", 297 | "fixed", 298 | "nb 1.0.0", 299 | "nrf52832-pac", 300 | "rand_core", 301 | "void", 302 | ] 303 | 304 | [[package]] 305 | name = "nrf52832-hal" 306 | version = "0.16.0" 307 | source = "registry+https://github.com/rust-lang/crates.io-index" 308 | checksum = "4e2e1d21d08826c02a2292d75f46a20e134c879dd2fcf09aa9bbca3d0d40db98" 309 | dependencies = [ 310 | "embedded-hal", 311 | "nrf-hal-common", 312 | "nrf52832-pac", 313 | ] 314 | 315 | [[package]] 316 | name = "nrf52832-pac" 317 | version = "0.12.2" 318 | source = "registry+https://github.com/rust-lang/crates.io-index" 319 | checksum = "0242b685c9c15648fb803e155628f42ace457478b2cb930868f40cae2db925e0" 320 | dependencies = [ 321 | "cortex-m", 322 | "cortex-m-rt", 323 | "vcell", 324 | ] 325 | 326 | [[package]] 327 | name = "panic-semihosting" 328 | version = "0.5.6" 329 | source = "registry+https://github.com/rust-lang/crates.io-index" 330 | checksum = "c3d55dedd501dfd02514646e0af4d7016ce36bc12ae177ef52056989966a1eec" 331 | dependencies = [ 332 | "cortex-m", 333 | "cortex-m-semihosting 0.3.7", 334 | ] 335 | 336 | [[package]] 337 | name = "proc-macro2" 338 | version = "1.0.49" 339 | source = "registry+https://github.com/rust-lang/crates.io-index" 340 | checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" 341 | dependencies = [ 342 | "unicode-ident", 343 | ] 344 | 345 | [[package]] 346 | name = "quote" 347 | version = "1.0.23" 348 | source = "registry+https://github.com/rust-lang/crates.io-index" 349 | checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" 350 | dependencies = [ 351 | "proc-macro2", 352 | ] 353 | 354 | [[package]] 355 | name = "rand_core" 356 | version = "0.6.4" 357 | source = "registry+https://github.com/rust-lang/crates.io-index" 358 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 359 | 360 | [[package]] 361 | name = "rtic-core" 362 | version = "0.3.1" 363 | source = "registry+https://github.com/rust-lang/crates.io-index" 364 | checksum = "8bd58a6949de8ff797a346a28d9f13f7b8f54fa61bb5e3cb0985a4efb497a5ef" 365 | 366 | [[package]] 367 | name = "rtic-syntax" 368 | version = "0.4.0" 369 | source = "registry+https://github.com/rust-lang/crates.io-index" 370 | checksum = "8152fcaa845720d61e6cc570548b89144c2c307f18a480bbd97e55e9f6eeff04" 371 | dependencies = [ 372 | "indexmap", 373 | "proc-macro2", 374 | "syn", 375 | ] 376 | 377 | [[package]] 378 | name = "rustc_version" 379 | version = "0.2.3" 380 | source = "registry+https://github.com/rust-lang/crates.io-index" 381 | checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 382 | dependencies = [ 383 | "semver", 384 | ] 385 | 386 | [[package]] 387 | name = "semver" 388 | version = "0.9.0" 389 | source = "registry+https://github.com/rust-lang/crates.io-index" 390 | checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 391 | dependencies = [ 392 | "semver-parser", 393 | ] 394 | 395 | [[package]] 396 | name = "semver-parser" 397 | version = "0.7.0" 398 | source = "registry+https://github.com/rust-lang/crates.io-index" 399 | checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 400 | 401 | [[package]] 402 | name = "stable_deref_trait" 403 | version = "1.2.0" 404 | source = "registry+https://github.com/rust-lang/crates.io-index" 405 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 406 | 407 | [[package]] 408 | name = "syn" 409 | version = "1.0.107" 410 | source = "registry+https://github.com/rust-lang/crates.io-index" 411 | checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" 412 | dependencies = [ 413 | "proc-macro2", 414 | "quote", 415 | "unicode-ident", 416 | ] 417 | 418 | [[package]] 419 | name = "typenum" 420 | version = "1.16.0" 421 | source = "registry+https://github.com/rust-lang/crates.io-index" 422 | checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" 423 | 424 | [[package]] 425 | name = "unicode-ident" 426 | version = "1.0.6" 427 | source = "registry+https://github.com/rust-lang/crates.io-index" 428 | checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" 429 | 430 | [[package]] 431 | name = "vcell" 432 | version = "0.1.3" 433 | source = "registry+https://github.com/rust-lang/crates.io-index" 434 | checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" 435 | 436 | [[package]] 437 | name = "version_check" 438 | version = "0.9.4" 439 | source = "registry+https://github.com/rust-lang/crates.io-index" 440 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 441 | 442 | [[package]] 443 | name = "void" 444 | version = "1.0.2" 445 | source = "registry+https://github.com/rust-lang/crates.io-index" 446 | checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" 447 | 448 | [[package]] 449 | name = "volatile-register" 450 | version = "0.2.1" 451 | source = "registry+https://github.com/rust-lang/crates.io-index" 452 | checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6" 453 | dependencies = [ 454 | "vcell", 455 | ] 456 | -------------------------------------------------------------------------------- /rtic_v0.5/nrf52_monotonic/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "app" 3 | categories = ["embedded", "no-std"] 4 | authors = ["Emil Fresk "] 5 | description = "Example Monotonic trait" 6 | keywords = ["arm", "cortex-m"] 7 | license = "MIT OR Apache-2.0" 8 | version = "0.1.0" 9 | edition = "2018" 10 | 11 | [dependencies] 12 | panic-semihosting = "0.6" 13 | cortex-m-rtic = { version = "0.5.9", default-features = false, features = ["cortex-m-7"] } 14 | 15 | cortex-m-semihosting = "0.5.0" 16 | 17 | [dependencies.nrf52832-hal] 18 | version = "0.16" 19 | default-features = false 20 | features = [ "xxAA-package", "rt" ] 21 | 22 | # this lets you use `cargo fix`! 23 | [[bin]] 24 | name = "app" 25 | test = false 26 | bench = false 27 | 28 | [profile.dev] 29 | opt-level = 1 30 | codegen-units = 16 31 | debug = true 32 | lto = false 33 | 34 | [profile.release] 35 | opt-level = "s" # optimize for size 36 | codegen-units = 1 # better optimizations 37 | debug = true # symbols are nice and they don't increase the size on Flash 38 | lto = true # better optimizations 39 | -------------------------------------------------------------------------------- /rtic_v0.5/nrf52_monotonic/README.md: -------------------------------------------------------------------------------- 1 | # nRF52 Monotonic 2 | 3 | In this example we show the use of a custom `rtic::Monotonic` implementation which uses a timer of the `nRF52832` MCU. 4 | 5 | ### Flashing and running 6 | 7 | Flashing with a standard STLink v2 is easy with `cargo-embed`: 8 | 9 | ```shell 10 | $ cargo install cargo-embed 11 | $ cargo embed --release 12 | ``` 13 | 14 | Please review the `.embed.toml` file to change your target IC among other options. 15 | -------------------------------------------------------------------------------- /rtic_v0.5/nrf52_monotonic/src/main.rs: -------------------------------------------------------------------------------- 1 | //! In here all hardware dependent code is kept, and to run the independent parts the firmware crate 2 | //! is called. 3 | 4 | #![no_main] 5 | #![no_std] 6 | 7 | mod monotonic_nrf52; 8 | 9 | use monotonic_nrf52::*; 10 | use nrf52832_hal as _; 11 | // use panic_halt as _; 12 | use cortex_m_semihosting::hprintln; 13 | use panic_semihosting as _; 14 | use rtic::app; 15 | 16 | #[app(device = nrf52832_hal::pac, peripherals = true, monotonic = crate::monotonic_nrf52::Tim1)] 17 | const APP: () = { 18 | #[init (spawn = [task1])] 19 | fn init(cx: init::Context) { 20 | Tim1::initialize(cx.device.TIMER1); 21 | hprintln!("init"); 22 | cx.spawn.task1().ok(); 23 | } 24 | 25 | #[task(schedule = [task1])] 26 | fn task1(cx: task1::Context) { 27 | hprintln!("here"); 28 | cx.schedule.task1(cx.scheduled + 2000.millis()).ok(); 29 | } 30 | 31 | extern "C" { 32 | fn SWI0_EGU0(); 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /rtic_v0.5/nrf52_monotonic/src/monotonic_nrf52.rs: -------------------------------------------------------------------------------- 1 | //! Using NRF52 as monotonic timer 2 | 3 | use crate::monotonic_nrf52::pac::TIMER1; 4 | use core::u32; 5 | use core::{ 6 | cmp::Ordering, 7 | convert::{Infallible, TryInto}, 8 | fmt, ops, 9 | }; 10 | use nrf52832_hal::pac; 11 | use rtic::Monotonic; 12 | 13 | /// A measurement of the counter. Opaque and useful only with `Duration` 14 | /// 15 | /// # Correctness 16 | /// 17 | /// Adding or subtracting a `Duration` of more than `(1 << 31)` cycles to an `Instant` effectively 18 | /// makes it "wrap around" and creates an incorrect value. This is also true if the operation is 19 | /// done in steps, e.g. `(instant + dur) + dur` where `dur` is `(1 << 30)` ticks. 20 | #[derive(Clone, Copy, Eq, PartialEq)] 21 | pub struct Instant { 22 | inner: i32, 23 | } 24 | 25 | impl Instant { 26 | /// Returns an instant corresponding to "now" 27 | pub fn now() -> Self { 28 | let now = { 29 | let timer = unsafe { &*TIMER1::ptr() }; 30 | timer.tasks_capture[0].write(|w| unsafe { w.bits(1) }); 31 | timer.cc[0].read().bits() 32 | }; 33 | 34 | Instant { inner: now as i32 } 35 | } 36 | 37 | /// Returns the amount of time elapsed since this instant was created. 38 | pub fn elapsed(&self) -> Duration { 39 | Instant::now() - *self 40 | } 41 | 42 | /// Returns the underlying count 43 | pub fn counts(&self) -> u32 { 44 | self.inner as u32 45 | } 46 | 47 | /// Returns the amount of time elapsed from another instant to this one. 48 | pub fn duration_since(&self, earlier: Instant) -> Duration { 49 | let diff = self.inner.wrapping_sub(earlier.inner); 50 | assert!(diff >= 0, "second instant is later than self"); 51 | Duration { inner: diff as u32 } 52 | } 53 | } 54 | 55 | impl fmt::Debug for Instant { 56 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 57 | f.debug_tuple("Instant") 58 | .field(&(self.inner as u32)) 59 | .finish() 60 | } 61 | } 62 | 63 | impl ops::AddAssign for Instant { 64 | fn add_assign(&mut self, dur: Duration) { 65 | // NOTE this is a debug assertion because there's no foolproof way to detect a wrap around; 66 | // the user may write `(instant + dur) + dur` where `dur` is `(1<<31)-1` ticks. 67 | debug_assert!(dur.inner < (1 << 31)); 68 | self.inner = self.inner.wrapping_add(dur.inner as i32); 69 | } 70 | } 71 | 72 | impl ops::Add for Instant { 73 | type Output = Self; 74 | 75 | fn add(mut self, dur: Duration) -> Self { 76 | self += dur; 77 | self 78 | } 79 | } 80 | 81 | impl ops::SubAssign for Instant { 82 | fn sub_assign(&mut self, dur: Duration) { 83 | // NOTE see the NOTE in `>::add_assign` 84 | debug_assert!(dur.inner < (1 << 31)); 85 | self.inner = self.inner.wrapping_sub(dur.inner as i32); 86 | } 87 | } 88 | 89 | impl ops::Sub for Instant { 90 | type Output = Self; 91 | 92 | fn sub(mut self, dur: Duration) -> Self { 93 | self -= dur; 94 | self 95 | } 96 | } 97 | 98 | impl ops::Sub for Instant { 99 | type Output = Duration; 100 | 101 | fn sub(self, other: Instant) -> Duration { 102 | self.duration_since(other) 103 | } 104 | } 105 | 106 | impl Ord for Instant { 107 | fn cmp(&self, rhs: &Self) -> Ordering { 108 | self.inner.wrapping_sub(rhs.inner).cmp(&0) 109 | } 110 | } 111 | 112 | impl PartialOrd for Instant { 113 | fn partial_cmp(&self, rhs: &Self) -> Option { 114 | Some(self.cmp(rhs)) 115 | } 116 | } 117 | 118 | /// A `Duration` type to represent a span of time. 119 | /// 120 | /// This data type is only available on ARMv7-M 121 | /// 122 | /// # Correctness 123 | /// 124 | /// This type is *not* appropriate for representing time spans in the order of, or larger than, 125 | /// seconds because it can hold a maximum of `(1 << 31)` "ticks" where each tick is the inverse of 126 | /// the CPU frequency, which usually is dozens of MHz. 127 | #[derive(Clone, Copy, Default, Eq, Ord, PartialEq, PartialOrd)] 128 | pub struct Duration { 129 | inner: u32, 130 | } 131 | 132 | impl Duration { 133 | /// Creates a new `Duration` from the specified number of clock cycles 134 | pub fn from_cycles(cycles: u32) -> Self { 135 | Duration { inner: cycles } 136 | } 137 | 138 | /// Returns the total number of clock cycles contained by this `Duration` 139 | pub fn as_cycles(&self) -> u32 { 140 | self.inner 141 | } 142 | } 143 | 144 | // Used internally by RTIC to convert the duration into a known type 145 | impl TryInto for Duration { 146 | type Error = Infallible; 147 | 148 | fn try_into(self) -> Result { 149 | Ok(self.as_cycles()) 150 | } 151 | } 152 | 153 | impl ops::AddAssign for Duration { 154 | fn add_assign(&mut self, dur: Duration) { 155 | self.inner += dur.inner; 156 | } 157 | } 158 | 159 | impl ops::Add for Duration { 160 | type Output = Self; 161 | 162 | fn add(self, other: Self) -> Self { 163 | Duration { 164 | inner: self.inner + other.inner, 165 | } 166 | } 167 | } 168 | 169 | impl ops::Mul for Duration { 170 | type Output = Self; 171 | 172 | fn mul(self, other: u32) -> Self { 173 | Duration { 174 | inner: self.inner * other, 175 | } 176 | } 177 | } 178 | 179 | impl ops::MulAssign for Duration { 180 | fn mul_assign(&mut self, other: u32) { 181 | *self = *self * other; 182 | } 183 | } 184 | 185 | impl ops::SubAssign for Duration { 186 | fn sub_assign(&mut self, rhs: Duration) { 187 | self.inner -= rhs.inner; 188 | } 189 | } 190 | 191 | impl ops::Sub for Duration { 192 | type Output = Self; 193 | 194 | fn sub(self, rhs: Self) -> Self { 195 | Duration { 196 | inner: self.inner - rhs.inner, 197 | } 198 | } 199 | } 200 | 201 | /// Adds the `secs`, `millis` and `micros` methods to the `u32` type 202 | /// 203 | /// This trait is only available on ARMv7-M 204 | pub trait U32Ext { 205 | /// Converts the `u32` value as seconds into ticks 206 | fn secs(self) -> Duration; 207 | 208 | /// Converts the `u32` value as milliseconds into ticks 209 | fn millis(self) -> Duration; 210 | 211 | /// Converts the `u32` value as microseconds into ticks 212 | fn micros(self) -> Duration; 213 | } 214 | 215 | impl U32Ext for u32 { 216 | fn secs(self) -> Duration { 217 | self.millis() * 1_000 218 | } 219 | 220 | fn millis(self) -> Duration { 221 | self.micros() * 1_000 222 | } 223 | 224 | fn micros(self) -> Duration { 225 | let frac = Tim1::ratio(); 226 | 227 | // 64 MHz / fraction / 1_000_000 228 | Duration { 229 | inner: (64 * frac.denominator * self) / frac.numerator, 230 | } 231 | } 232 | } 233 | 234 | /// Implementor of the `rtic::Monotonic` traits and used to "eat" the timer to not allow for 235 | /// erroneous configuration 236 | pub struct Tim1; 237 | 238 | impl Tim1 { 239 | pub fn initialize(timer: TIMER1) { 240 | // Auto restart, make sure the entire timer won't stop for any event 241 | timer.shorts.write(|w| { 242 | w.compare0_clear() 243 | .enabled() 244 | .compare0_stop() 245 | .disabled() 246 | .compare1_clear() 247 | .enabled() 248 | .compare1_stop() 249 | .disabled() 250 | .compare2_clear() 251 | .enabled() 252 | .compare2_stop() 253 | .disabled() 254 | .compare3_clear() 255 | .enabled() 256 | .compare3_stop() 257 | .disabled() 258 | }); 259 | 260 | // 1 MHz mode 261 | timer.prescaler.write(|w| unsafe { w.prescaler().bits(4) }); 262 | 263 | // 32 bit mode 264 | timer.bitmode.write(|w| w.bitmode()._32bit()); 265 | 266 | // Set compare value to max, not sure if this is needed 267 | timer.cc[0].write(|w| unsafe { w.cc().bits(u32::MAX) }); 268 | 269 | // Clear the counter value 270 | timer.tasks_clear.write(|w| unsafe { w.bits(1) }); 271 | 272 | // Start the timer 273 | timer.tasks_start.write(|w| unsafe { w.bits(1) }); 274 | 275 | // The timer is dropped as it goes out of scope, 276 | // thus initializing it consumes it and the configuration 277 | // becomes "persistent" 278 | } 279 | } 280 | 281 | impl rtic::Monotonic for Tim1 { 282 | type Instant = Instant; 283 | 284 | fn ratio() -> rtic::Fraction { 285 | // monotonic * fraction = sys clock 286 | rtic::Fraction { 287 | numerator: 64, 288 | denominator: 1, 289 | } 290 | } 291 | 292 | fn now() -> Self::Instant { 293 | Instant::now() 294 | } 295 | 296 | unsafe fn reset() { 297 | let timer = &*TIMER1::ptr(); 298 | 299 | // Clear the counter value 300 | timer.tasks_clear.write(|w| w.bits(1)); 301 | } 302 | 303 | fn zero() -> Self::Instant { 304 | Instant { inner: 0 } 305 | } 306 | } 307 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32f0_hid_mouse/.cargo/config: -------------------------------------------------------------------------------- 1 | [target.thumbv6m-none-eabi] 2 | rustflags = [ 3 | "-C", "link-arg=-Tlink.x", 4 | ] 5 | 6 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] 7 | runner = "probe-run --chip STM32F042G6Ux --defmt" 8 | 9 | [build] 10 | target = "thumbv6m-none-eabi" 11 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32f0_hid_mouse/.embed.toml: -------------------------------------------------------------------------------- 1 | # Refer to https://github.com/probe-rs/cargo-embed/blob/master/src/config/default.toml 2 | # for the comprehensive list of options 3 | 4 | [default.general] 5 | chip = "STM32F042G6Ux" 6 | 7 | [default.rtt] 8 | enabled = true 9 | show_timestamps = true 10 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32f0_hid_mouse/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "stm32f042" 3 | version = "0.1.0" 4 | authors = ["Roman Valls Guimera ", "Josh Johnson"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | embedded-hal = "1.0.0" 9 | defmt = "0.3.5" 10 | usb-device = "0.2.5" 11 | usbd-hid = "0.6.1" 12 | rtt-target = { version = "0.3.1", features = ["cortex-m"] } 13 | panic-halt = "0.2.0" 14 | panic-rtt-target = { version = "0.1.1", features = ["cortex-m"] } 15 | cortex-m = "0.7.7" 16 | cortex-m-rtic = { version = "0.5.9", default-features = false, features = ["cortex-m-7"] } 17 | stm32f0xx-hal = { version = "0.18.0", features = ["rt", "stm32f042", "stm32-usbd"] } 18 | stm32-usbd = { version = "0.6.0" } 19 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32f0_hid_mouse/README.md: -------------------------------------------------------------------------------- 1 | # Rust STM32 blackberry trackball firmware 2 | 3 | Getting onboard with Rust for embedded devices is like 1,2,3 (more details on the [Rust embedded book](https://rust-embedded.github.io/book/)): 4 | 5 | ```shell 6 | $ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh 7 | $ rustup target add thumbv6m-none-eabi 8 | $ cargo install cargo-embed 9 | ``` 10 | 11 | Flashing with a standard STLink v2 is easy with `cargo-embed`: 12 | 13 | ```shell 14 | $ cargo embed --release 15 | Finished release [optimized] target(s) in 0.04s 16 | Flashing /Users/romanvg/dev/cchs/keyboard_trackball/software/stm32f04/target/thumbv6m-none-eabi/release/stm32f042 17 | Erasing sectors ✔ [00:00:00] [#################################################################] 23.00KB/ 23.00KB @ 28.29KB/s (eta 0s ) 18 | Programming pages ✔ [00:00:02] [#################################################################] 23.00KB/ 23.00KB @ 7.24KB/s (eta 0s ) 19 | Finished in 2.942s 20 | ``` 21 | 22 | More context and possible future extensions [at the original repo for this example](https://github.com/brainstorm/bbtrackball-rs). 23 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32f0_hid_mouse/build.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::fs; 3 | use std::io::Write; 4 | use std::path::PathBuf; 5 | 6 | fn main() { 7 | // Put the linker script somewhere the linker can find it 8 | let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); 9 | fs::File::create(out_dir.join("memory.x")) 10 | .unwrap() 11 | .write_all(include_bytes!("memory.x")) 12 | .unwrap(); 13 | println!("cargo:rustc-link-search={}", out_dir.display()); 14 | println!("cargo:rerun-if-changed=memory.x"); 15 | } 16 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32f0_hid_mouse/memory.x: -------------------------------------------------------------------------------- 1 | /* STM32F042G6 */ 2 | MEMORY 3 | { 4 | FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K 5 | RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 6K 6 | } 7 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32f0_hid_mouse/src/main.rs: -------------------------------------------------------------------------------- 1 | #![deny(unsafe_code)] 2 | #![deny(warnings)] 3 | #![no_std] 4 | #![no_main] 5 | 6 | use cortex_m::interrupt::free as disable_interrupts; 7 | use panic_halt as _; 8 | use rtic::app; 9 | use rtic::{Exclusive, Mutex}; 10 | use rtt_target::{rprintln, rtt_init_print}; 11 | 12 | use stm32f0xx_hal::{ 13 | gpio::gpioa::{PA0, PA1, PA15, PA2, PA3, PA4, PA5, PA6, PA7}, 14 | gpio::gpiob::{PB1, PB3, PB4}, 15 | gpio::{Input, Output, PullUp, PushPull}, 16 | pac, 17 | prelude::*, 18 | usb, 19 | }; 20 | 21 | use usb_device::{bus::UsbBusAllocator, prelude::*}; 22 | use usbd_hid::{ 23 | descriptor::{MouseReport, SerializedDescriptor}, 24 | hid_class::HIDClass, 25 | }; 26 | 27 | #[app(device = stm32f0xx_hal::pac, peripherals = true)] 28 | const APP: () = { 29 | struct Resources { 30 | usb_bus: &'static UsbBusAllocator, 31 | usb_device: UsbDevice<'static, usb::UsbBusType>, 32 | usb_hid: HIDClass<'static, usb::UsbBusType>, 33 | exti: pac::EXTI, 34 | usr_led: PB1>, 35 | button3: PA15>, 36 | button4: PB4>, 37 | button5: PB3>, 38 | tb_left: PA4>, 39 | tb_up: PA5>, 40 | tb_right: PA6>, 41 | tb_down: PA7>, 42 | bbled_red: PA0>, 43 | bbled_grn: PA1>, 44 | bbled_blu: PA2>, 45 | bbled_wht: PA3>, 46 | } 47 | 48 | #[init] 49 | fn init(ctx: init::Context) -> init::LateResources { 50 | static mut USB_BUS: Option> = None; 51 | 52 | // RTT handler 53 | rtt_init_print!(); 54 | 55 | // Alias peripherals 56 | let mut dp: pac::Peripherals = ctx.device; 57 | 58 | // This enables clock for SYSCFG and remaps USB pins to PA9 and PA10. 59 | usb::remap_pins(&mut dp.RCC, &mut dp.SYSCFG); 60 | 61 | // Power on bbled dance 62 | //bbled_red.toggle().ok(); 63 | 64 | rprintln!("Initializing peripherals"); 65 | let mut rcc = dp 66 | .RCC 67 | .configure() 68 | .usbsrc(stm32f0xx_hal::rcc::USBClockSource::HSI48) 69 | .hsi48() 70 | .enable_crs(dp.CRS) 71 | .sysclk(48.mhz()) 72 | .pclk(24.mhz()) 73 | .freeze(&mut dp.FLASH); 74 | 75 | // Set up GPIO registers for USR LED and Buttons 76 | let gpiob = dp.GPIOB.split(&mut rcc); 77 | let (usr_led, button4, button5) = disable_interrupts(|cs| { 78 | ( 79 | gpiob.pb1.into_push_pull_output(cs), 80 | gpiob.pb4.into_pull_up_input(cs), 81 | gpiob.pb3.into_pull_up_input(cs), 82 | ) 83 | }); 84 | 85 | // LEDs and USB 86 | let gpioa = dp.GPIOA.split(&mut rcc); 87 | let ( 88 | bbled_red, 89 | bbled_grn, 90 | bbled_blu, 91 | bbled_wht, 92 | tb_left, 93 | tb_up, 94 | tb_right, 95 | tb_down, 96 | button3, 97 | usb_dm, 98 | usb_dp, 99 | ) = disable_interrupts(|cs| { 100 | ( 101 | gpioa.pa0.into_push_pull_output(cs), 102 | gpioa.pa1.into_push_pull_output(cs), 103 | gpioa.pa2.into_push_pull_output(cs), 104 | gpioa.pa3.into_push_pull_output(cs), 105 | gpioa.pa4.into_pull_up_input(cs), 106 | gpioa.pa5.into_pull_up_input(cs), 107 | gpioa.pa6.into_pull_up_input(cs), 108 | gpioa.pa7.into_pull_up_input(cs), 109 | gpioa.pa15.into_pull_up_input(cs), 110 | gpioa.pa11, 111 | gpioa.pa12, 112 | ) 113 | }); 114 | 115 | // Enable external interrupt for 3 aux buttons... 116 | dp.SYSCFG.exticr1.write(|w| w.exti3().pb3()); 117 | // dp.SYSCFG.exticr2.write(|w| { w.exti4().pb4() }); // Disable spare button in favor of tb_left 118 | dp.SYSCFG.exticr4.write(|w| w.exti15().pa15()); 119 | //... and for pulses on trackball 120 | dp.SYSCFG.exticr2.write(|w| w.exti4().pa4()); 121 | dp.SYSCFG.exticr2.write(|w| w.exti5().pa5()); 122 | dp.SYSCFG.exticr2.write(|w| w.exti6().pa6()); 123 | dp.SYSCFG.exticr2.write(|w| w.exti7().pa7()); 124 | 125 | // Set interrupt mask for all the above 126 | dp.EXTI.imr.write(|w| { 127 | w.mr3().set_bit(); 128 | w.mr4().set_bit(); 129 | w.mr5().set_bit(); 130 | w.mr6().set_bit(); 131 | w.mr7().set_bit(); 132 | w.mr15().set_bit() 133 | }); 134 | 135 | // Set interrupt rising trigger 136 | dp.EXTI.rtsr.write(|w| { 137 | w.tr3().set_bit(); 138 | w.tr4().set_bit(); 139 | w.tr5().set_bit(); 140 | w.tr6().set_bit(); 141 | w.tr7().set_bit(); 142 | w.tr15().set_bit() 143 | }); 144 | 145 | let usb = usb::Peripheral { 146 | usb: dp.USB, 147 | pin_dm: usb_dm, 148 | pin_dp: usb_dp, 149 | }; 150 | 151 | *USB_BUS = Some(usb::UsbBus::new(usb)); 152 | 153 | rprintln!("Preparing HID mouse..."); 154 | let usb_hid = HIDClass::new(USB_BUS.as_ref().unwrap(), MouseReport::desc(), 60); 155 | 156 | rprintln!("Defining USB parameters..."); 157 | let usb_device = UsbDeviceBuilder::new(USB_BUS.as_ref().unwrap(), UsbVidPid(0, 0x3821)) 158 | .manufacturer("JoshFTW") 159 | .product("BBTrackball") 160 | .serial_number("RustFW") 161 | .device_class(0x00) 162 | .device_sub_class(0x00) 163 | .device_protocol(0x00) 164 | .build(); 165 | 166 | rprintln!("Instantiating dp.EXTI..."); 167 | let exti = dp.EXTI; 168 | rprintln!("Defining late resources..."); 169 | 170 | init::LateResources { 171 | usb_bus: USB_BUS.as_ref().unwrap(), 172 | usb_device, 173 | usb_hid, 174 | exti, 175 | usr_led, 176 | button3, 177 | button4, 178 | button5, 179 | tb_left, 180 | tb_up, 181 | tb_right, 182 | tb_down, 183 | bbled_red, 184 | bbled_grn, 185 | bbled_blu, 186 | bbled_wht, 187 | } 188 | } 189 | 190 | #[idle(resources = [usb_device, usb_hid])] 191 | fn idle(_: idle::Context) -> ! { 192 | loop { 193 | cortex_m::asm::nop(); 194 | cortex_m::asm::wfi(); 195 | } 196 | } 197 | 198 | #[task(binds = EXTI2_3, resources = [exti])] 199 | fn exti2_3_interrupt(ctx: exti2_3_interrupt::Context) { 200 | rprintln!("Interrupts happening on EXTI2_3"); 201 | 202 | match ctx.resources.exti.pr.read().bits() { 203 | 0x8 => { 204 | rprintln!("PB3 triggered"); 205 | ctx.resources.exti.pr.write(|w| w.pif3().set_bit()); // Clear interrupt 206 | } 207 | 208 | _ => rprintln!("Some other bits were pushed around on EXTI2_3 ;)"), 209 | } 210 | } 211 | 212 | #[task(binds = EXTI4_15, resources = [exti, usb_device, usb_hid, usr_led, bbled_red, bbled_grn, bbled_wht, bbled_blu])] 213 | fn exti_4_15_interrupt(ctx: exti_4_15_interrupt::Context) { 214 | rprintln!("Interrupts happening on EXTI for PA15..."); 215 | 216 | let hid = ctx.resources.usb_hid; 217 | let usr_led = ctx.resources.usr_led; 218 | 219 | match ctx.resources.exti.pr.read().bits() { 220 | 0x8000 => { 221 | rprintln!("PA15 triggered"); 222 | ctx.resources.exti.pr.write(|w| w.pif15().set_bit()); // Clear interrupt 223 | send_mouse_report(Exclusive(hid), 0, 0, 1, 0, 0); 224 | usr_led.toggle().ok(); 225 | } 226 | 0x10 => { 227 | rprintln!("tb_left triggered!"); 228 | ctx.resources.exti.pr.write(|w| w.pif4().set_bit()); 229 | send_mouse_report(Exclusive(hid), 5, 0, 0, 0, 0); 230 | usr_led.toggle().ok(); 231 | } 232 | 0x20 => { 233 | rprintln!("tb_up triggered!"); 234 | ctx.resources.exti.pr.write(|w| w.pif5().set_bit()); 235 | send_mouse_report(Exclusive(hid), 0, 5, 0, 0, 0); 236 | usr_led.toggle().ok(); 237 | } 238 | 0x40 => { 239 | rprintln!("tb_right triggered!"); 240 | ctx.resources.exti.pr.write(|w| w.pif6().set_bit()); 241 | send_mouse_report(Exclusive(hid), -5, 0, 0, 0, 0); 242 | usr_led.toggle().ok(); 243 | } 244 | 0x80 => { 245 | rprintln!("tb_down triggered!"); 246 | ctx.resources.exti.pr.write(|w| w.pif7().set_bit()); 247 | send_mouse_report(Exclusive(hid), 0, -5, 0, 0, 0); 248 | usr_led.toggle().ok(); 249 | } 250 | 251 | _ => rprintln!("Some other bits were pushed around on EXTI4_15 ;)"), 252 | } 253 | } 254 | 255 | #[task(binds = USB, resources = [usb_device, usb_hid])] 256 | fn usb_handler(ctx: usb_handler::Context) { 257 | rprintln!("USB interrupt received."); 258 | 259 | let dev = ctx.resources.usb_device; 260 | let hid = ctx.resources.usb_hid; 261 | 262 | // USB dev poll only in the interrupt handler 263 | dev.poll(&mut [hid]); 264 | } 265 | }; 266 | 267 | fn send_mouse_report( 268 | mut shared_hid: impl Mutex>, 269 | x: i8, 270 | y: i8, 271 | buttons: u8, 272 | wheel: i8, 273 | pan: i8, 274 | ) { 275 | let mr = MouseReport { 276 | x, 277 | y, 278 | buttons, 279 | wheel, 280 | pan, 281 | }; 282 | 283 | shared_hid.lock(|hid| { 284 | rprintln!("Sending mouse report..."); 285 | hid.push_input(&mr).ok(); 286 | }); 287 | } 288 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32f1_bluepill_blinky/.cargo/config: -------------------------------------------------------------------------------- 1 | [target.thumbv7m-none-eabi] 2 | # uncomment this to make `cargo run` execute programs on QEMU 3 | # runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel" 4 | 5 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] 6 | # uncomment ONE of these three option to make `cargo run` start a GDB session 7 | # which option to pick depends on your system 8 | # runner = "arm-none-eabi-gdb -q -x jlink.gdb" 9 | runner = "arm-none-eabi-gdb -q -x openocd.gdb" 10 | # runner = "gdb-multiarch -q -x openocd.gdb" 11 | # runner = "gdb -q -x openocd.gdb" 12 | 13 | rustflags = [ 14 | # LLD (shipped with the Rust toolchain) is used as the default linker 15 | "-C", "link-arg=-Tlink.x", 16 | 17 | # if you run into problems with LLD switch to the GNU linker by commenting out 18 | # this line 19 | # "-C", "linker=arm-none-eabi-ld", 20 | 21 | # if you need to link to pre-compiled C libraries provided by a C toolchain 22 | # use GCC as the linker by commenting out both lines above and then 23 | # uncommenting the three lines below 24 | # "-C", "linker=arm-none-eabi-gcc", 25 | # "-C", "link-arg=-Wl,-Tlink.x", 26 | # "-C", "link-arg=-nostartfiles", 27 | 28 | # uncomment for unchecked wrapping arithmetics also in dev mode 29 | # "-Z", "force-overflow-checks=off", 30 | ] 31 | 32 | [build] 33 | # Pick ONE of these compilation targets 34 | # target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+ 35 | target = "thumbv7m-none-eabi" # Cortex-M3 36 | # target = "thumbv7em-none-eabi" # Cortex-M4 and Cortex-M7 (no FPU) 37 | # target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU) 38 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32f1_bluepill_blinky/.embed.toml: -------------------------------------------------------------------------------- 1 | # Refer to https://github.com/probe-rs/cargo-embed/blob/master/src/config/default.toml 2 | # for the comprehensive list of options 3 | 4 | [default.general] 5 | chip = "STM32F103" 6 | 7 | [default.rtt] 8 | enabled = true 9 | show_timestamps = true 10 | 11 | [default.gdb] 12 | # Whether or not a GDB server should be opened after flashing. 13 | # This is exclusive and cannot be used with RTT at the moment. 14 | enabled = false 15 | # The connection string in host:port format wher the GDB server will open a socket. 16 | # gdb_connection_string 17 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32f1_bluepill_blinky/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | 4 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32f1_bluepill_blinky/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "app" 7 | version = "0.1.0" 8 | dependencies = [ 9 | "cortex-m-rtic", 10 | "cortex-m-semihosting", 11 | "embedded-hal 1.0.0", 12 | "panic-semihosting", 13 | "stm32f1xx-hal", 14 | ] 15 | 16 | [[package]] 17 | name = "as-slice" 18 | version = "0.1.5" 19 | source = "registry+https://github.com/rust-lang/crates.io-index" 20 | checksum = "45403b49e3954a4b8428a0ac21a4b7afadccf92bfd96273f1a58cd4812496ae0" 21 | dependencies = [ 22 | "generic-array 0.12.4", 23 | "generic-array 0.13.3", 24 | "generic-array 0.14.6", 25 | "stable_deref_trait", 26 | ] 27 | 28 | [[package]] 29 | name = "autocfg" 30 | version = "1.1.0" 31 | source = "registry+https://github.com/rust-lang/crates.io-index" 32 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 33 | 34 | [[package]] 35 | name = "bare-metal" 36 | version = "0.2.5" 37 | source = "registry+https://github.com/rust-lang/crates.io-index" 38 | checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" 39 | dependencies = [ 40 | "rustc_version", 41 | ] 42 | 43 | [[package]] 44 | name = "bare-metal" 45 | version = "1.0.0" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" 48 | 49 | [[package]] 50 | name = "bitfield" 51 | version = "0.13.2" 52 | source = "registry+https://github.com/rust-lang/crates.io-index" 53 | checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" 54 | 55 | [[package]] 56 | name = "bitflags" 57 | version = "1.3.2" 58 | source = "registry+https://github.com/rust-lang/crates.io-index" 59 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 60 | 61 | [[package]] 62 | name = "bxcan" 63 | version = "0.7.0" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | checksum = "40ac3d0c0a542d0ab5521211f873f62706a7136df415676f676d347e5a41dd80" 66 | dependencies = [ 67 | "bitflags", 68 | "embedded-hal 0.2.7", 69 | "nb 1.0.0", 70 | "vcell", 71 | ] 72 | 73 | [[package]] 74 | name = "byteorder" 75 | version = "1.4.3" 76 | source = "registry+https://github.com/rust-lang/crates.io-index" 77 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 78 | 79 | [[package]] 80 | name = "cortex-m" 81 | version = "0.7.6" 82 | source = "registry+https://github.com/rust-lang/crates.io-index" 83 | checksum = "70858629a458fdfd39f9675c4dc309411f2a3f83bede76988d81bf1a0ecee9e0" 84 | dependencies = [ 85 | "bare-metal 0.2.5", 86 | "bitfield", 87 | "embedded-hal 0.2.7", 88 | "volatile-register", 89 | ] 90 | 91 | [[package]] 92 | name = "cortex-m-rt" 93 | version = "0.7.2" 94 | source = "registry+https://github.com/rust-lang/crates.io-index" 95 | checksum = "d6d3328b8b5534f0c90acd66b68950f2763b37e0173cac4d8b4937c4a80761f9" 96 | dependencies = [ 97 | "cortex-m-rt-macros", 98 | ] 99 | 100 | [[package]] 101 | name = "cortex-m-rt-macros" 102 | version = "0.7.0" 103 | source = "registry+https://github.com/rust-lang/crates.io-index" 104 | checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7" 105 | dependencies = [ 106 | "proc-macro2", 107 | "quote", 108 | "syn", 109 | ] 110 | 111 | [[package]] 112 | name = "cortex-m-rtic" 113 | version = "0.5.9" 114 | source = "registry+https://github.com/rust-lang/crates.io-index" 115 | checksum = "fb77bb72c171d0aa52a2954d8dc7e3f0800ab54b8df7d826f138abbea9eb2794" 116 | dependencies = [ 117 | "cortex-m", 118 | "cortex-m-rtic-macros", 119 | "heapless", 120 | "rtic-core", 121 | "version_check", 122 | ] 123 | 124 | [[package]] 125 | name = "cortex-m-rtic-macros" 126 | version = "0.5.3" 127 | source = "registry+https://github.com/rust-lang/crates.io-index" 128 | checksum = "cc874eda99515b15e67f03562726a530388f454431096d30131051b52b840559" 129 | dependencies = [ 130 | "proc-macro2", 131 | "quote", 132 | "rtic-syntax", 133 | "syn", 134 | ] 135 | 136 | [[package]] 137 | name = "cortex-m-semihosting" 138 | version = "0.5.0" 139 | source = "registry+https://github.com/rust-lang/crates.io-index" 140 | checksum = "c23234600452033cc77e4b761e740e02d2c4168e11dbf36ab14a0f58973592b0" 141 | dependencies = [ 142 | "cortex-m", 143 | ] 144 | 145 | [[package]] 146 | name = "embedded-dma" 147 | version = "0.2.0" 148 | source = "registry+https://github.com/rust-lang/crates.io-index" 149 | checksum = "994f7e5b5cb23521c22304927195f236813053eb9c065dd2226a32ba64695446" 150 | dependencies = [ 151 | "stable_deref_trait", 152 | ] 153 | 154 | [[package]] 155 | name = "embedded-hal" 156 | version = "0.2.7" 157 | source = "registry+https://github.com/rust-lang/crates.io-index" 158 | checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" 159 | dependencies = [ 160 | "nb 0.1.3", 161 | "void", 162 | ] 163 | 164 | [[package]] 165 | name = "embedded-hal" 166 | version = "1.0.0" 167 | source = "registry+https://github.com/rust-lang/crates.io-index" 168 | checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" 169 | 170 | [[package]] 171 | name = "fugit" 172 | version = "0.3.6" 173 | source = "registry+https://github.com/rust-lang/crates.io-index" 174 | checksum = "7ab17bb279def6720d058cb6c052249938e7f99260ab534879281a95367a87e5" 175 | dependencies = [ 176 | "gcd", 177 | ] 178 | 179 | [[package]] 180 | name = "fugit-timer" 181 | version = "0.1.3" 182 | source = "registry+https://github.com/rust-lang/crates.io-index" 183 | checksum = "d9607bfc4c388f9d629704f56ede4a007546cad417b3bcd6fc7c87dc7edce04a" 184 | dependencies = [ 185 | "fugit", 186 | "nb 1.0.0", 187 | ] 188 | 189 | [[package]] 190 | name = "gcd" 191 | version = "2.2.0" 192 | source = "registry+https://github.com/rust-lang/crates.io-index" 193 | checksum = "a4b1b088ad0a967aa29540456b82fc8903f854775d33f71e9709c4efb3dfbfd2" 194 | 195 | [[package]] 196 | name = "generic-array" 197 | version = "0.12.4" 198 | source = "registry+https://github.com/rust-lang/crates.io-index" 199 | checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" 200 | dependencies = [ 201 | "typenum", 202 | ] 203 | 204 | [[package]] 205 | name = "generic-array" 206 | version = "0.13.3" 207 | source = "registry+https://github.com/rust-lang/crates.io-index" 208 | checksum = "f797e67af32588215eaaab8327027ee8e71b9dd0b2b26996aedf20c030fce309" 209 | dependencies = [ 210 | "typenum", 211 | ] 212 | 213 | [[package]] 214 | name = "generic-array" 215 | version = "0.14.6" 216 | source = "registry+https://github.com/rust-lang/crates.io-index" 217 | checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" 218 | dependencies = [ 219 | "typenum", 220 | "version_check", 221 | ] 222 | 223 | [[package]] 224 | name = "hash32" 225 | version = "0.1.1" 226 | source = "registry+https://github.com/rust-lang/crates.io-index" 227 | checksum = "d4041af86e63ac4298ce40e5cca669066e75b6f1aa3390fe2561ffa5e1d9f4cc" 228 | dependencies = [ 229 | "byteorder", 230 | ] 231 | 232 | [[package]] 233 | name = "hashbrown" 234 | version = "0.12.3" 235 | source = "registry+https://github.com/rust-lang/crates.io-index" 236 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 237 | 238 | [[package]] 239 | name = "heapless" 240 | version = "0.6.1" 241 | source = "registry+https://github.com/rust-lang/crates.io-index" 242 | checksum = "634bd4d29cbf24424d0a4bfcbf80c6960129dc24424752a7d1d1390607023422" 243 | dependencies = [ 244 | "as-slice", 245 | "generic-array 0.14.6", 246 | "hash32", 247 | "stable_deref_trait", 248 | ] 249 | 250 | [[package]] 251 | name = "indexmap" 252 | version = "1.9.2" 253 | source = "registry+https://github.com/rust-lang/crates.io-index" 254 | checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" 255 | dependencies = [ 256 | "autocfg", 257 | "hashbrown", 258 | ] 259 | 260 | [[package]] 261 | name = "nb" 262 | version = "0.1.3" 263 | source = "registry+https://github.com/rust-lang/crates.io-index" 264 | checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" 265 | dependencies = [ 266 | "nb 1.0.0", 267 | ] 268 | 269 | [[package]] 270 | name = "nb" 271 | version = "1.0.0" 272 | source = "registry+https://github.com/rust-lang/crates.io-index" 273 | checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae" 274 | 275 | [[package]] 276 | name = "panic-semihosting" 277 | version = "0.6.0" 278 | source = "registry+https://github.com/rust-lang/crates.io-index" 279 | checksum = "ee8a3e1233d9073d76a870223512ce4eeea43c067a94a445c13bd6d792d7b1ab" 280 | dependencies = [ 281 | "cortex-m", 282 | "cortex-m-semihosting", 283 | ] 284 | 285 | [[package]] 286 | name = "proc-macro2" 287 | version = "1.0.49" 288 | source = "registry+https://github.com/rust-lang/crates.io-index" 289 | checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" 290 | dependencies = [ 291 | "unicode-ident", 292 | ] 293 | 294 | [[package]] 295 | name = "quote" 296 | version = "1.0.23" 297 | source = "registry+https://github.com/rust-lang/crates.io-index" 298 | checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" 299 | dependencies = [ 300 | "proc-macro2", 301 | ] 302 | 303 | [[package]] 304 | name = "rtic-core" 305 | version = "0.3.1" 306 | source = "registry+https://github.com/rust-lang/crates.io-index" 307 | checksum = "8bd58a6949de8ff797a346a28d9f13f7b8f54fa61bb5e3cb0985a4efb497a5ef" 308 | 309 | [[package]] 310 | name = "rtic-syntax" 311 | version = "0.4.0" 312 | source = "registry+https://github.com/rust-lang/crates.io-index" 313 | checksum = "8152fcaa845720d61e6cc570548b89144c2c307f18a480bbd97e55e9f6eeff04" 314 | dependencies = [ 315 | "indexmap", 316 | "proc-macro2", 317 | "syn", 318 | ] 319 | 320 | [[package]] 321 | name = "rustc_version" 322 | version = "0.2.3" 323 | source = "registry+https://github.com/rust-lang/crates.io-index" 324 | checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 325 | dependencies = [ 326 | "semver", 327 | ] 328 | 329 | [[package]] 330 | name = "semver" 331 | version = "0.9.0" 332 | source = "registry+https://github.com/rust-lang/crates.io-index" 333 | checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 334 | dependencies = [ 335 | "semver-parser", 336 | ] 337 | 338 | [[package]] 339 | name = "semver-parser" 340 | version = "0.7.0" 341 | source = "registry+https://github.com/rust-lang/crates.io-index" 342 | checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 343 | 344 | [[package]] 345 | name = "stable_deref_trait" 346 | version = "1.2.0" 347 | source = "registry+https://github.com/rust-lang/crates.io-index" 348 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 349 | 350 | [[package]] 351 | name = "stm32-usbd" 352 | version = "0.6.0" 353 | source = "registry+https://github.com/rust-lang/crates.io-index" 354 | checksum = "c6c94998f166d66b210a164648a0b7866428d8f1e0740bf8a4c5edd89d4750c1" 355 | dependencies = [ 356 | "cortex-m", 357 | "usb-device", 358 | "vcell", 359 | ] 360 | 361 | [[package]] 362 | name = "stm32f1" 363 | version = "0.15.1" 364 | source = "registry+https://github.com/rust-lang/crates.io-index" 365 | checksum = "f2dc80735831c28fe85384e1e28428fb6d201f67c696e369a239ed9c5eba369d" 366 | dependencies = [ 367 | "bare-metal 1.0.0", 368 | "cortex-m", 369 | "cortex-m-rt", 370 | "vcell", 371 | ] 372 | 373 | [[package]] 374 | name = "stm32f1xx-hal" 375 | version = "0.10.0" 376 | source = "registry+https://github.com/rust-lang/crates.io-index" 377 | checksum = "30845662b9ce46a2ec04da97666a2b32458bee5032bb0452d0caf1536a96a542" 378 | dependencies = [ 379 | "bitflags", 380 | "bxcan", 381 | "cortex-m", 382 | "cortex-m-rt", 383 | "embedded-dma", 384 | "embedded-hal 0.2.7", 385 | "fugit", 386 | "fugit-timer", 387 | "nb 1.0.0", 388 | "stm32-usbd", 389 | "stm32f1", 390 | "void", 391 | ] 392 | 393 | [[package]] 394 | name = "syn" 395 | version = "1.0.107" 396 | source = "registry+https://github.com/rust-lang/crates.io-index" 397 | checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" 398 | dependencies = [ 399 | "proc-macro2", 400 | "quote", 401 | "unicode-ident", 402 | ] 403 | 404 | [[package]] 405 | name = "typenum" 406 | version = "1.16.0" 407 | source = "registry+https://github.com/rust-lang/crates.io-index" 408 | checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" 409 | 410 | [[package]] 411 | name = "unicode-ident" 412 | version = "1.0.6" 413 | source = "registry+https://github.com/rust-lang/crates.io-index" 414 | checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" 415 | 416 | [[package]] 417 | name = "usb-device" 418 | version = "0.2.9" 419 | source = "registry+https://github.com/rust-lang/crates.io-index" 420 | checksum = "1f6cc3adc849b5292b4075fc0d5fdcf2f24866e88e336dd27a8943090a520508" 421 | 422 | [[package]] 423 | name = "vcell" 424 | version = "0.1.3" 425 | source = "registry+https://github.com/rust-lang/crates.io-index" 426 | checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" 427 | 428 | [[package]] 429 | name = "version_check" 430 | version = "0.9.4" 431 | source = "registry+https://github.com/rust-lang/crates.io-index" 432 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 433 | 434 | [[package]] 435 | name = "void" 436 | version = "1.0.2" 437 | source = "registry+https://github.com/rust-lang/crates.io-index" 438 | checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" 439 | 440 | [[package]] 441 | name = "volatile-register" 442 | version = "0.2.1" 443 | source = "registry+https://github.com/rust-lang/crates.io-index" 444 | checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6" 445 | dependencies = [ 446 | "vcell", 447 | ] 448 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32f1_bluepill_blinky/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "app" 3 | categories = ["embedded", "no-std"] 4 | authors = ["arrowcircle", "Emil Fresk "] 5 | description = "Example blinky for BluePill" 6 | keywords = ["arm", "cortex-m"] 7 | license = "MIT OR Apache-2.0" 8 | version = "0.1.0" 9 | edition = "2018" 10 | 11 | [dependencies] 12 | panic-semihosting = "0.6" 13 | cortex-m-semihosting = "0.5.0" 14 | embedded-hal = "1.0.0" 15 | cortex-m-rtic = { version = "0.5.9", default-features = false, features = ["cortex-m-7"] } 16 | 17 | 18 | [dependencies.stm32f1xx-hal] 19 | version = "0.10.0" 20 | features = ["rt", "stm32f103", "medium"] 21 | 22 | # this lets you use `cargo fix`! 23 | [[bin]] 24 | name = "app" 25 | test = false 26 | bench = false 27 | 28 | [profile.dev] 29 | opt-level = 1 30 | codegen-units = 16 31 | debug = true 32 | lto = false 33 | 34 | [profile.release] 35 | opt-level = "s" # optimize for size 36 | codegen-units = 1 # better optimizations 37 | debug = true # symbols are nice and they don't increase the size on Flash 38 | lto = true # better optimizations 39 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32f1_bluepill_blinky/README.md: -------------------------------------------------------------------------------- 1 | # STM32F103 Bluepill RTIC Blink example 2 | 3 | Working example of simple LED blinking application for popular Bluepill boards based on the STM32F103C8 chip. Example uses schedule API and peripherials access. You will need `stlink v2` tool or other programmer to flash the board. 4 | 5 | ## How-to 6 | 7 | ### Terminal workflow 8 | 9 | Rust embedded relies heavily on `terminal workflow`, you will enter commands in the terminal. This can be strange at first, but this enables usage of great things like continious integration tools. 10 | 11 | For Mac OS X consider using `iTerm2` instead of Terminal application. 12 | For Windows consider using `powershell` (win + r -> powershell -> enter -> cd C:\examples\rtic_v5\bluepill_blinky) 13 | 14 | ### Build 15 | 16 | Run `cargo build` to compile the code. If you run it for the first time, it will take some time to download and compile dependencies. After that, you will see comething like: 17 | 18 | ```bash 19 | >cargo build 20 | Finished dev [optimized + debuginfo] target(s) in 0.10s 21 | ``` 22 | 23 | If you see warnings, feel free to ask for help in chat or issues of this repo. 24 | 25 | ### Connect the board 26 | 27 | You need to connect you bluepill board to ST-Link and connect pins: 28 | 29 | | BOARD | | ST-LINK | 30 | |-------|----|---------| 31 | | GND | -> | GND | 32 | | 3.3V | -> | 3.3V | 33 | | SWCLK | -> | SWCLK | 34 | | SWDIO | -> | SWDIO | 35 | 36 | Plug in ST-Link to USB port and wait it to initialize. 37 | 38 | ### Flashing and running 39 | 40 | Flashing with a standard STLink v2 is easy with `cargo-embed`: 41 | 42 | ```shell 43 | $ cargo install cargo-embed 44 | $ cargo embed --release 45 | ``` 46 | 47 | Please review the `.embed.toml` file to change your target IC among other options. 48 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32f1_bluepill_blinky/memory.x: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | /* NOTE 1 K = 1 KiBi = 1024 bytes */ 4 | /* TODO Adjust these memory regions to match your device memory layout */ 5 | /* These values correspond to the LM3S6965, one of the few devices QEMU can emulate */ 6 | FLASH : ORIGIN = 0x08000000, LENGTH = 64K 7 | RAM : ORIGIN = 0x20000000, LENGTH = 20K 8 | } 9 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32f1_bluepill_blinky/src/main.rs: -------------------------------------------------------------------------------- 1 | #![deny(unsafe_code)] 2 | #![deny(warnings)] 3 | #![no_main] 4 | #![no_std] 5 | 6 | extern crate panic_semihosting; 7 | use rtic::app; 8 | use rtic::cyccnt::U32Ext; 9 | use stm32f1xx_hal::gpio::{gpioc::PC13, Output, PinState, PushPull}; 10 | use stm32f1xx_hal::prelude::*; 11 | 12 | const PERIOD: u32 = 100_000_000; 13 | 14 | // We need to pass monotonic = rtic::cyccnt::CYCCNT to use schedule feature fo RTIC 15 | #[app(device = stm32f1xx_hal::pac, peripherals = true, monotonic = rtic::cyccnt::CYCCNT)] 16 | const APP: () = { 17 | // Global resources (global variables) are defined here and initialized with the 18 | // `LateResources` struct in init 19 | struct Resources { 20 | led: PC13>, 21 | } 22 | 23 | #[init(schedule = [blinker])] 24 | fn init(cx: init::Context) -> init::LateResources { 25 | // Enable cycle counter 26 | let mut core = cx.core; 27 | core.DWT.enable_cycle_counter(); 28 | 29 | let device: stm32f1xx_hal::stm32::Peripherals = cx.device; 30 | 31 | // Setup clocks 32 | let mut flash = device.FLASH.constrain(); 33 | let rcc = device.RCC.constrain(); 34 | let mut _afio = device.AFIO.constrain(); 35 | let _clocks = rcc 36 | .cfgr 37 | .use_hse(8.MHz()) 38 | .sysclk(72.MHz()) 39 | .pclk1(36.MHz()) 40 | .freeze(&mut flash.acr); 41 | 42 | // Setup LED 43 | let mut gpioc = device.GPIOC.split(); 44 | let mut led = gpioc 45 | .pc13 46 | .into_push_pull_output_with_state(&mut gpioc.crh, PinState::Low); 47 | led.set_low(); 48 | 49 | // Schedule the blinking task 50 | cx.schedule.blinker(cx.start + PERIOD.cycles()).unwrap(); 51 | 52 | init::LateResources { led } 53 | } 54 | 55 | #[task(resources = [led], schedule = [blinker])] 56 | fn blinker(cx: blinker::Context) { 57 | // Use the safe local `static mut` of RTIC 58 | static mut LED_STATE: bool = false; 59 | 60 | if *LED_STATE { 61 | cx.resources.led.set_high(); 62 | *LED_STATE = false; 63 | } else { 64 | cx.resources.led.set_low(); 65 | *LED_STATE = true; 66 | } 67 | cx.schedule.blinker(cx.scheduled + PERIOD.cycles()).unwrap(); 68 | } 69 | 70 | extern "C" { 71 | fn EXTI0(); 72 | } 73 | }; 74 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32f3_blinky/.cargo/config: -------------------------------------------------------------------------------- 1 | [target.thumbv7em-none-eabihf] 2 | # uncomment this to make `cargo run` execute programs on QEMU 3 | # runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel" 4 | 5 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] 6 | # uncomment ONE of these three option to make `cargo run` start a GDB session 7 | # which option to pick depends on your system 8 | # runner = "arm-none-eabi-gdb -q -x openocd.gdb" 9 | # runner = "gdb-multiarch -q -x openocd.gdb" 10 | # runner = "gdb -q -x openocd.gdb" 11 | 12 | rustflags = [ 13 | # This is needed if your flash or ram addresses are not aligned to 0x10000 in memory.x 14 | # See https://github.com/rust-embedded/cortex-m-quickstart/pull/95 15 | "-C", "link-arg=--nmagic", 16 | 17 | # LLD (shipped with the Rust toolchain) is used as the default linker 18 | "-C", "link-arg=-Tlink.x", 19 | 20 | # if you run into problems with LLD switch to the GNU linker by commenting out 21 | # this line 22 | # "-C", "linker=arm-none-eabi-ld", 23 | 24 | # if you need to link to pre-compiled C libraries provided by a C toolchain 25 | # use GCC as the linker by commenting out both lines above and then 26 | # uncommenting the three lines below 27 | # "-C", "linker=arm-none-eabi-gcc", 28 | # "-C", "link-arg=-Wl,-Tlink.x", 29 | # "-C", "link-arg=-nostartfiles", 30 | ] 31 | 32 | [build] 33 | # Pick ONE of these compilation targets 34 | # target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+ 35 | # target = "thumbv7m-none-eabi" # Cortex-M3 36 | # target = "thumbv7em-none-eabi" # Cortex-M4 and Cortex-M7 (no FPU) 37 | target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU) 38 | # target = "thumbv8m.base-none-eabi" # Cortex-M23 39 | # target = "thumbv8m.main-none-eabi" # Cortex-M33 (no FPU) 40 | # target = "thumbv8m.main-none-eabihf" # Cortex-M33 (with FPU) 41 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32f3_blinky/.gitignore: -------------------------------------------------------------------------------- 1 | **/*.rs.bk 2 | .#* 3 | .gdb_history 4 | 5 | target/ 6 | 7 | # editor files 8 | .vscode/* 9 | !.vscode/*.md 10 | !.vscode/*.svd 11 | !.vscode/launch.json 12 | !.vscode/tasks.json 13 | !.vscode/extensions.json -------------------------------------------------------------------------------- /rtic_v0.5/stm32f3_blinky/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["Simsys "] 3 | edition = "2018" 4 | readme = "README.md" 5 | name = "stm32f3-blinky" 6 | version = "0.1.0" 7 | 8 | [dependencies] 9 | panic-halt = "0.2" 10 | panic-semihosting = "0.6" 11 | cortex-m-semihosting = "0.5.0" 12 | embedded-hal = "1.0.0" 13 | cortex-m-rtic = { version = "0.5.9", default-features = false, features = ["cortex-m-7"] } 14 | 15 | [dependencies.stm32f3xx-hal] 16 | features = ["stm32f303xc", "rt"] 17 | version = "0.10.0" 18 | 19 | # this lets you use `cargo fix`! 20 | [[bin]] 21 | name = "stm32f3-blinky" 22 | test = false 23 | bench = false 24 | 25 | [profile.dev] 26 | opt-level = 1 27 | codegen-units = 16 28 | debug = true 29 | lto = false 30 | 31 | [profile.release] 32 | opt-level = "s" # optimize for size 33 | codegen-units = 1 # better optimizations 34 | debug = true # symbols are nice and they don't increase the size on Flash 35 | lto = true # better optimizations 36 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32f3_blinky/memory.x: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | FLASH : ORIGIN = 0x08000000, LENGTH = 256K 4 | RAM : ORIGIN = 0x20000000, LENGTH = 40K 5 | } 6 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32f3_blinky/readme.md: -------------------------------------------------------------------------------- 1 | # STM32F3 RTIC Blink example 2 | 3 | Working example of simple LED blinking application for STM32 F3 Discovery boards based on the STM32F303VC chip. Example uses schedule API and peripherials access. This example is based on blue-pill blinky example. 4 | 5 | ## How-to 6 | 7 | ### Build 8 | 9 | Run `cargo build` to compile the code. If you run it for the first time, it will take some time to download and compile dependencies. After that, you will see comething like: 10 | 11 | ```bash 12 | $ cargo build 13 | ``` 14 | 15 | ### Setup environment, flash and run program 16 | 17 | In the [Discovery Book](https://rust-embedded.github.io/discovery) you find all needed informations to setup the environment, flash the controler and run the program. 18 | 19 | 20 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32f3_blinky/src/main.rs: -------------------------------------------------------------------------------- 1 | #![deny(unsafe_code)] 2 | #![deny(warnings)] 3 | #![no_main] 4 | #![no_std] 5 | 6 | extern crate panic_semihosting; 7 | use rtic::app; 8 | use rtic::cyccnt::U32Ext; 9 | use stm32f3xx_hal::gpio::{gpioe::PE10, Output, PushPull}; 10 | use stm32f3xx_hal::prelude::*; 11 | 12 | const PERIOD: u32 = 10_000_000; 13 | 14 | // We need to pass monotonic = rtic::cyccnt::CYCCNT to use schedule feature fo RTIC 15 | #[app(device = stm32f3xx_hal::pac, peripherals = true, monotonic = rtic::cyccnt::CYCCNT)] 16 | const APP: () = { 17 | // Global resources (global variables) are defined here and initialized with the 18 | // `LateResources` struct in init 19 | struct Resources { 20 | led: PE10>, 21 | } 22 | 23 | #[init(schedule = [blinker])] 24 | fn init(cx: init::Context) -> init::LateResources { 25 | // Enable cycle counter 26 | let mut core = cx.core; 27 | core.DWT.enable_cycle_counter(); 28 | 29 | let device: stm32f3xx_hal::pac::Peripherals = cx.device; 30 | 31 | // Setup clocks 32 | let mut flash = device.FLASH.constrain(); 33 | let mut rcc = device.RCC.constrain(); 34 | let _clocks = rcc 35 | .cfgr 36 | .use_hse(8.MHz()) 37 | .sysclk(72.MHz()) 38 | .pclk1(36.MHz()) 39 | .freeze(&mut flash.acr); 40 | 41 | // Setup LED 42 | let mut gpioe = device.GPIOE.split(&mut rcc.ahb); 43 | let mut led = gpioe 44 | .pe10 45 | .into_push_pull_output(&mut gpioe.moder, &mut gpioe.otyper); 46 | led.set_high().unwrap(); 47 | 48 | // Schedule the blinking task 49 | cx.schedule.blinker(cx.start + PERIOD.cycles()).unwrap(); 50 | 51 | init::LateResources { led } 52 | } 53 | 54 | #[task(resources = [led], schedule = [blinker])] 55 | fn blinker(cx: blinker::Context) { 56 | // Use the safe local `static mut` of RTIC 57 | static mut LED_STATE: bool = false; 58 | 59 | if *LED_STATE { 60 | cx.resources.led.set_high().unwrap(); 61 | *LED_STATE = false; 62 | } else { 63 | cx.resources.led.set_low().unwrap(); 64 | *LED_STATE = true; 65 | } 66 | cx.schedule.blinker(cx.scheduled + PERIOD.cycles()).unwrap(); 67 | } 68 | 69 | extern "C" { 70 | fn EXTI0(); 71 | } 72 | }; 73 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32l0_monotonic/.cargo/config: -------------------------------------------------------------------------------- 1 | [target.thumbv7m-none-eabi] 2 | # uncomment this to make `cargo run` execute programs on QEMU 3 | # runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel" 4 | 5 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] 6 | # uncomment ONE of these three option to make `cargo run` start a GDB session 7 | # which option to pick depends on your system 8 | # runner = "arm-none-eabi-gdb -q -x jlink.gdb" 9 | # runner = "arm-none-eabi-gdb -q -x openocd.gdb" 10 | # runner = "gdb-multiarch -q -x openocd.gdb" 11 | # runner = "gdb -q -x openocd.gdb" 12 | 13 | rustflags = [ 14 | # LLD (shipped with the Rust toolchain) is used as the default linker 15 | "-C", "link-arg=-Tlink.x", 16 | 17 | # if you run into problems with LLD switch to the GNU linker by commenting out 18 | # this line 19 | # "-C", "linker=arm-none-eabi-ld", 20 | 21 | # if you need to link to pre-compiled C libraries provided by a C toolchain 22 | # use GCC as the linker by commenting out both lines above and then 23 | # uncommenting the three lines below 24 | # "-C", "linker=arm-none-eabi-gcc", 25 | # "-C", "link-arg=-Wl,-Tlink.x", 26 | # "-C", "link-arg=-nostartfiles", 27 | 28 | # uncomment for unchecked wrapping arithmetics also in dev mode 29 | # "-Z", "force-overflow-checks=off", 30 | ] 31 | 32 | [build] 33 | # Pick ONE of these compilation targets 34 | target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+ 35 | # target = "thumbv7m-none-eabi" # Cortex-M3 36 | # target = "thumbv7em-none-eabi" # Cortex-M4 and Cortex-M7 (no FPU) 37 | # target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU) 38 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32l0_monotonic/.embed.toml: -------------------------------------------------------------------------------- 1 | # Refer to https://github.com/probe-rs/cargo-embed/blob/master/src/config/default.toml 2 | # for the comprehensive list of options 3 | 4 | [default.general] 5 | chip = "STM32L071" 6 | 7 | [default.rtt] 8 | enabled = true 9 | show_timestamps = true 10 | 11 | [default.gdb] 12 | # Whether or not a GDB server should be opened after flashing. 13 | # This is exclusive and cannot be used with RTT at the moment. 14 | enabled = false 15 | # The connection string in host:port format wher the GDB server will open a socket. 16 | # gdb_connection_string 17 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32l0_monotonic/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | 4 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32l0_monotonic/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "app" 3 | categories = ["embedded", "no-std"] 4 | authors = ["Danilo Bargen "] 5 | description = "Example Monotonic trait" 6 | keywords = ["arm", "cortex-m"] 7 | license = "MIT OR Apache-2.0" 8 | version = "0.1.0" 9 | edition = "2018" 10 | 11 | [dependencies] 12 | cortex-m-rtic = { version = "0.5.9", default-features = false, features = ["cortex-m-7"] } 13 | panic-halt = { version = "0.2.0" } 14 | stm32l0xx-hal = { version = "0.9", features = ["rt", "mcu-STM32L071KBTx"] } 15 | 16 | # this lets you use `cargo fix`! 17 | [[bin]] 18 | name = "app" 19 | test = false 20 | bench = false 21 | 22 | [profile.dev] 23 | opt-level = 1 24 | codegen-units = 16 25 | debug = true 26 | lto = false 27 | 28 | [profile.release] 29 | opt-level = "s" # optimize for size 30 | codegen-units = 1 # better optimizations 31 | debug = true # symbols are nice and they don't increase the size on Flash 32 | lto = true # better optimizations 33 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32l0_monotonic/README.md: -------------------------------------------------------------------------------- 1 | # STM32L0 Monotonic 2 | 3 | In this example we show the use of a custom `rtic::Monotonic` implementation 4 | which uses a 16 bit timer of the `STM32L0` MCU. 5 | 6 | ## Flashing and running 7 | 8 | Flashing with a standard STLink v2 is easy with `cargo-embed`: 9 | 10 | ```shell 11 | $ cargo install cargo-embed 12 | $ cargo embed --release 13 | ``` 14 | 15 | Please review the `.embed.toml` file to change your target IC among other options. 16 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32l0_monotonic/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | 4 | mod monotonic_stm32l0; 5 | 6 | use core::fmt::Write; 7 | 8 | use panic_halt as _; 9 | use rtic::app; 10 | use stm32l0xx_hal::{pac, prelude::*, rcc::Config, serial}; 11 | 12 | use crate::monotonic_stm32l0::{Duration, Instant, Tim6Monotonic, U16Ext}; 13 | 14 | const INTERVAL_MS: u16 = 500; 15 | 16 | #[app( 17 | device = stm32l0xx_hal::pac, 18 | peripherals = true, 19 | monotonic = crate::monotonic_stm32l0::Tim6Monotonic, 20 | )] 21 | const APP: () = { 22 | struct Resources { 23 | /// Serial debug output 24 | debug: serial::Serial, 25 | 26 | /// Timer interval 27 | interval: Duration, 28 | } 29 | 30 | #[init(spawn = [fizzbuzz])] 31 | fn init(cx: init::Context) -> init::LateResources { 32 | // Get peripherals 33 | let dp: pac::Peripherals = cx.device; 34 | 35 | // Clock configuration. Use HSI at 16 MHz. 36 | let mut rcc = dp.RCC.freeze(Config::hsi16()); 37 | 38 | // GPIO 39 | let gpiob = dp.GPIOB.split(&mut rcc); 40 | 41 | // Initialize serial port(s) 42 | let mut debug = serial::Serial::usart1( 43 | dp.USART1, 44 | gpiob.pb6.into_floating_input(), 45 | gpiob.pb7.into_floating_input(), 46 | serial::Config { 47 | baudrate: 57_600.Bd(), 48 | wordlength: serial::WordLength::DataBits8, 49 | parity: serial::Parity::ParityNone, 50 | stopbits: serial::StopBits::STOP1, 51 | }, 52 | &mut rcc, 53 | ) 54 | .unwrap(); 55 | 56 | // Initialize the timer TIM6. 57 | writeln!( 58 | debug, 59 | "Initialize monotonic timer (TIM6) at 7.8125 kHz (128 μs)" 60 | ) 61 | .unwrap(); 62 | Tim6Monotonic::initialize(dp.TIM6); 63 | 64 | // Spawn task "fizzbuzz" 65 | let interval = INTERVAL_MS.millis(); 66 | writeln!( 67 | debug, 68 | "Schedule task every {} ms / {} ticks", 69 | INTERVAL_MS, 70 | interval.as_ticks() 71 | ) 72 | .unwrap(); 73 | cx.spawn.fizzbuzz().unwrap(); 74 | 75 | writeln!(debug, "== Init done ==").unwrap(); 76 | 77 | init::LateResources { debug, interval } 78 | } 79 | 80 | #[task(schedule = [fizzbuzz], resources = [debug, interval])] 81 | fn fizzbuzz(cx: fizzbuzz::Context) { 82 | static mut COUNTER: usize = 1; 83 | 84 | // Access resources 85 | let debug = cx.resources.debug; 86 | let scheduled = cx.scheduled.counts(); 87 | let now = Instant::now().counts(); 88 | 89 | // Classic fizzbuzz implementation 90 | if *COUNTER % 15 == 0 { 91 | writeln!(debug, "fizzbuzz (sched={:05}, now={:05})", scheduled, now).unwrap(); 92 | } else if *COUNTER % 3 == 0 { 93 | writeln!(debug, " fizz (sched={:05}, now={:05})", scheduled, now).unwrap(); 94 | } else if *COUNTER % 5 == 0 { 95 | writeln!(debug, " buzz (sched={:05}, now={:05})", scheduled, now).unwrap(); 96 | } else { 97 | writeln!( 98 | debug, 99 | "{:08} (sched={:05}, now={:05})", 100 | *COUNTER, scheduled, now 101 | ) 102 | .unwrap(); 103 | } 104 | 105 | // Increment counter 106 | *COUNTER += 1; 107 | 108 | // Re-schedule 109 | cx.schedule 110 | .fizzbuzz(cx.scheduled + *cx.resources.interval) 111 | .unwrap(); 112 | } 113 | 114 | extern "C" { 115 | fn SPI1(); 116 | } 117 | }; 118 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32l0_monotonic/src/monotonic_stm32l0.rs: -------------------------------------------------------------------------------- 1 | //! Using STM32L0 TIM6 as monotonic 16 bit timer. 2 | //! 3 | //! ## Prescaler Calculations 4 | //! 5 | //! This implementation assumes that the core clock is set to 16 MHz (see 6 | //! `CORE_CLOCK` constant). At 16 MHz, this means 62.5 ns per clock cycle. 7 | //! 8 | //! If we use a prescaler value of 2048, that means 62.5 ns * 2048 = 128 µs per 9 | //! timer tick. This corresponds to a frequency of 16 MHz / 2048 = 7.8125 kHz. 10 | //! 11 | //! Because the timer has 16 bits, it will overflow every 128 µs * 2^16 = 12 | //! ~8.39 seconds. Due to overflow checking, we can only safely use one 13 | //! half of the available timer range, meaning that we can safely schedule 14 | //! tasks ~4.19 seconds into the future, with a resolution of 128 µs. 15 | 16 | use core::u32; 17 | use core::{ 18 | cmp::Ordering, 19 | convert::{Infallible, TryInto}, 20 | fmt, ops, 21 | }; 22 | use rtic::Monotonic; 23 | use stm32l0xx_hal::pac; 24 | 25 | /// Implementor of the `rtic::Monotonic` traits and used to consume the timer 26 | /// to not allow for erroneous configuration. 27 | /// 28 | /// This uses TIM6 internally. 29 | pub struct Tim6Monotonic; 30 | 31 | const CORE_CLOCK: u32 = 16_000_000; 32 | const PRESCALER: u32 = 2048; 33 | const HZ: u32 = CORE_CLOCK / PRESCALER; 34 | 35 | impl Tim6Monotonic { 36 | /// Initialize the timer instance. 37 | pub fn initialize(timer: pac::TIM6) { 38 | // Enable and reset TIM6 in RCC 39 | // 40 | // Correctness: Since we only modify TIM6 related registers in the RCC 41 | // register block, and since we own pac::TIM6, we should be safe. 42 | unsafe { 43 | let rcc = &*pac::RCC::ptr(); 44 | 45 | // Enable timer 46 | rcc.apb1enr.modify(|_, w| w.tim6en().set_bit()); 47 | 48 | // Reset timer 49 | rcc.apb1rstr.modify(|_, w| w.tim6rst().set_bit()); 50 | rcc.apb1rstr.modify(|_, w| w.tim6rst().clear_bit()); 51 | } 52 | 53 | // Set up prescaler 54 | timer.psc.write(|w| w.psc().bits(PRESCALER as u16)); 55 | 56 | // Enable counter 57 | timer.cr1.modify(|_, w| w.cen().set_bit()); 58 | 59 | // The timer is dropped as it goes out of scope, 60 | // thus initializing it consumes it and the configuration 61 | // becomes "persistent" 62 | } 63 | } 64 | 65 | impl Monotonic for Tim6Monotonic { 66 | type Instant = Instant; 67 | 68 | fn ratio() -> rtic::Fraction { 69 | // monotonic * fraction = sys clock 70 | rtic::Fraction { 71 | numerator: PRESCALER, 72 | denominator: 1, 73 | } 74 | } 75 | 76 | /// Returns the current time 77 | /// 78 | /// # Correctness 79 | /// 80 | /// This function is *allowed* to return nonsensical values if called before `reset` is invoked 81 | /// by the runtime. Therefore application authors should *not* call this function during the 82 | /// `#[init]` phase. 83 | fn now() -> Self::Instant { 84 | Instant::now() 85 | } 86 | 87 | /// Resets the counter to *zero* 88 | /// 89 | /// # Safety 90 | /// 91 | /// This function will be called *exactly once* by the RTFM runtime after `#[init]` returns and 92 | /// before tasks can start; this is also the case in multi-core applications. User code must 93 | /// *never* call this function. 94 | unsafe fn reset() { 95 | let tim = &*pac::TIM6::ptr(); 96 | 97 | // Pause 98 | tim.cr1.modify(|_, w| w.cen().clear_bit()); 99 | // Reset counter 100 | tim.cnt.reset(); 101 | // Continue 102 | tim.cr1.modify(|_, w| w.cen().set_bit()); 103 | } 104 | 105 | fn zero() -> Self::Instant { 106 | Instant { inner: 0 } 107 | } 108 | } 109 | 110 | /// A measurement of the counter. Opaque and useful only with `Duration`. 111 | /// 112 | /// # Correctness 113 | /// 114 | /// Adding or subtracting a `Duration` of more than `(1 << 15)` cycles to an `Instant` effectively 115 | /// makes it "wrap around" and creates an incorrect value. This is also true if the operation is 116 | /// done in steps, e.g. `(instant + dur) + dur` where `dur` is `(1 << 14)` ticks. 117 | #[derive(Clone, Copy, Eq, PartialEq)] 118 | pub struct Instant { 119 | inner: i16, 120 | } 121 | 122 | impl Instant { 123 | /// Returns an instant corresponding to "now". 124 | pub fn now() -> Self { 125 | let now = { 126 | let tim = unsafe { &*pac::TIM6::ptr() }; 127 | tim.cnt.read().cnt().bits() 128 | }; 129 | 130 | Instant { inner: now as i16 } 131 | } 132 | 133 | /// Returns the amount of time elapsed since this instant was created. 134 | pub fn elapsed(&self) -> Duration { 135 | Instant::now() - *self 136 | } 137 | 138 | /// Returns the underlying count 139 | pub fn counts(&self) -> u16 { 140 | self.inner as u16 141 | } 142 | 143 | /// Returns the amount of time elapsed from another instant to this one. 144 | pub fn duration_since(&self, earlier: Instant) -> Duration { 145 | let diff = self.inner.wrapping_sub(earlier.inner); 146 | assert!(diff >= 0, "second instant is later than self"); 147 | Duration { inner: diff as u16 } 148 | } 149 | } 150 | 151 | impl fmt::Debug for Instant { 152 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 153 | f.debug_tuple("Instant") 154 | .field(&(self.inner as u16)) 155 | .finish() 156 | } 157 | } 158 | 159 | impl ops::AddAssign for Instant { 160 | fn add_assign(&mut self, dur: Duration) { 161 | // NOTE this is a debug assertion because there's no foolproof way to detect a wrap around; 162 | // the user may write `(instant + dur) + dur` where `dur` is `(1<<15)-1` ticks. 163 | debug_assert!(dur.inner < (1 << 15)); 164 | self.inner = self.inner.wrapping_add(dur.inner as i16); 165 | } 166 | } 167 | 168 | impl ops::Add for Instant { 169 | type Output = Self; 170 | fn add(mut self, dur: Duration) -> Self { 171 | self += dur; 172 | self 173 | } 174 | } 175 | 176 | impl ops::SubAssign for Instant { 177 | fn sub_assign(&mut self, dur: Duration) { 178 | // NOTE see the NOTE in `>::add_assign` 179 | debug_assert!(dur.inner < (1 << 15)); 180 | self.inner = self.inner.wrapping_sub(dur.inner as i16); 181 | } 182 | } 183 | 184 | impl ops::Sub for Instant { 185 | type Output = Self; 186 | fn sub(mut self, dur: Duration) -> Self { 187 | self -= dur; 188 | self 189 | } 190 | } 191 | 192 | impl ops::Sub for Instant { 193 | type Output = Duration; 194 | fn sub(self, other: Instant) -> Duration { 195 | self.duration_since(other) 196 | } 197 | } 198 | 199 | impl Ord for Instant { 200 | fn cmp(&self, rhs: &Self) -> Ordering { 201 | self.inner.wrapping_sub(rhs.inner).cmp(&0) 202 | } 203 | } 204 | 205 | impl PartialOrd for Instant { 206 | fn partial_cmp(&self, rhs: &Self) -> Option { 207 | Some(self.cmp(rhs)) 208 | } 209 | } 210 | 211 | /// A `Duration` type to represent a span of time. 212 | #[derive(Clone, Copy, Default, Eq, Ord, PartialEq, PartialOrd)] 213 | pub struct Duration { 214 | inner: u16, 215 | } 216 | 217 | impl Duration { 218 | /// Creates a new `Duration` from the specified number of timer ticks 219 | pub fn from_ticks(ticks: u16) -> Self { 220 | Duration { inner: ticks } 221 | } 222 | 223 | /// Returns the total number of timer ticks contained by this `Duration` 224 | pub fn as_ticks(&self) -> u16 { 225 | self.inner 226 | } 227 | } 228 | 229 | // Used internally by RTIC to convert the duration into a known type 230 | impl TryInto for Duration { 231 | type Error = Infallible; 232 | 233 | fn try_into(self) -> Result { 234 | Ok(self.as_ticks() as u32) 235 | } 236 | } 237 | 238 | impl ops::AddAssign for Duration { 239 | fn add_assign(&mut self, dur: Duration) { 240 | self.inner += dur.inner; 241 | } 242 | } 243 | 244 | impl ops::Add for Duration { 245 | type Output = Self; 246 | fn add(self, other: Self) -> Self { 247 | Duration { 248 | inner: self.inner + other.inner, 249 | } 250 | } 251 | } 252 | 253 | impl ops::Mul for Duration { 254 | type Output = Self; 255 | fn mul(self, other: u16) -> Self { 256 | Duration { 257 | inner: self.inner * other, 258 | } 259 | } 260 | } 261 | 262 | impl ops::MulAssign for Duration { 263 | fn mul_assign(&mut self, other: u16) { 264 | *self = *self * other; 265 | } 266 | } 267 | 268 | impl ops::SubAssign for Duration { 269 | fn sub_assign(&mut self, rhs: Duration) { 270 | self.inner -= rhs.inner; 271 | } 272 | } 273 | 274 | impl ops::Sub for Duration { 275 | type Output = Self; 276 | fn sub(self, rhs: Self) -> Self { 277 | Duration { 278 | inner: self.inner - rhs.inner, 279 | } 280 | } 281 | } 282 | 283 | /// Adds the `secs`, `millis` and `micros` methods to the `u16` type. 284 | /// 285 | /// WARNING: You cannot represent values higher than 8388 milliseconds without 286 | /// overflow! 287 | pub trait U16Ext { 288 | /// Converts the `u16` value as seconds into ticks 289 | fn secs(self) -> Duration; 290 | 291 | /// Converts the `u16` value as milliseconds into ticks 292 | fn millis(self) -> Duration; 293 | 294 | /// Converts the `u16` value as microseconds into ticks 295 | fn micros(self) -> Duration; 296 | } 297 | 298 | impl U16Ext for u16 { 299 | fn secs(self) -> Duration { 300 | debug_assert!(self <= 8, "Cannot represent values >8s in a `Duration`"); 301 | Duration { 302 | inner: (HZ as u64 * self as u64) as u16, 303 | } 304 | } 305 | 306 | fn millis(self) -> Duration { 307 | debug_assert!( 308 | self <= 8388, 309 | "Cannot represent values >8388 in a `Duration`" 310 | ); 311 | Duration { 312 | inner: (HZ as u64 * self as u64 / 1_000) as u16, 313 | } 314 | } 315 | 316 | fn micros(self) -> Duration { 317 | Duration { 318 | inner: (HZ as u64 * self as u64 / 1_000_000) as u16, 319 | } 320 | } 321 | } 322 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32l4_heartbeat/.cargo/config: -------------------------------------------------------------------------------- 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] 2 | # uncomment ONE of these three option to make `cargo run` start a GDB session 3 | # which option to pick depends on your system 4 | # runner = "arm-none-eabi-gdb -q -x jlink.gdb" 5 | # runner = "arm-none-eabi-gdb -q -x openocd.gdb" 6 | runner = "gdb-multiarch -q -x openocd.gdb" 7 | # runner = "gdb -q -x openocd.gdb" 8 | 9 | rustflags = [ 10 | # LLD (shipped with the Rust toolchain) is used as the default linker 11 | "-C", "link-arg=-Tlink.x", 12 | 13 | # if you run into problems with LLD switch to the GNU linker by commenting out 14 | # this line 15 | # "-C", "linker=arm-none-eabi-ld", 16 | 17 | # if you need to link to pre-compiled C libraries provided by a C toolchain 18 | # use GCC as the linker by commenting out both lines above and then 19 | # uncommenting the three lines below 20 | # "-C", "linker=arm-none-eabi-gcc", 21 | # "-C", "link-arg=-Wl,-Tlink.x", 22 | # "-C", "link-arg=-nostartfiles", 23 | 24 | # uncomment for unchecked wrapping arithmetics also in dev mode 25 | # "-Z", "force-overflow-checks=off", 26 | ] 27 | 28 | [build] 29 | # Pick ONE of these compilation targets 30 | # target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+ 31 | # target = "thumbv7m-none-eabi" # Cortex-M3 32 | # target = "thumbv7em-none-eabi" # Cortex-M4 and Cortex-M7 (no FPU) 33 | target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU) 34 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32l4_heartbeat/.embed.toml: -------------------------------------------------------------------------------- 1 | # Refer to https://github.com/probe-rs/cargo-embed/blob/master/src/config/default.toml 2 | # for the comprehensive list of options 3 | 4 | [default.general] 5 | chip = "STM32L412" 6 | 7 | [default.rtt] 8 | enabled = true 9 | show_timestamps = true 10 | 11 | [default.gdb] 12 | # Whether or not a GDB server should be opened after flashing. 13 | # This is exclusive and cannot be used with RTT at the moment. 14 | enabled = false 15 | # The connection string in host:port format wher the GDB server will open a socket. 16 | # gdb_connection_string 17 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32l4_heartbeat/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | 4 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32l4_heartbeat/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "aligned" 7 | version = "0.3.4" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "c19796bd8d477f1a9d4ac2465b464a8b1359474f06a96bb3cda650b4fca309bf" 10 | dependencies = [ 11 | "as-slice", 12 | ] 13 | 14 | [[package]] 15 | name = "app" 16 | version = "0.1.0" 17 | dependencies = [ 18 | "cortex-m-rtic", 19 | "cortex-m-semihosting", 20 | "embedded-hal 1.0.0", 21 | "heapless 0.8.0", 22 | "panic-semihosting", 23 | "stm32l4xx-hal", 24 | ] 25 | 26 | [[package]] 27 | name = "as-slice" 28 | version = "0.1.5" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "45403b49e3954a4b8428a0ac21a4b7afadccf92bfd96273f1a58cd4812496ae0" 31 | dependencies = [ 32 | "generic-array 0.12.4", 33 | "generic-array 0.13.3", 34 | "generic-array 0.14.4", 35 | "stable_deref_trait", 36 | ] 37 | 38 | [[package]] 39 | name = "autocfg" 40 | version = "1.1.0" 41 | source = "registry+https://github.com/rust-lang/crates.io-index" 42 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 43 | 44 | [[package]] 45 | name = "bare-metal" 46 | version = "0.2.5" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" 49 | dependencies = [ 50 | "rustc_version", 51 | ] 52 | 53 | [[package]] 54 | name = "bitfield" 55 | version = "0.13.2" 56 | source = "registry+https://github.com/rust-lang/crates.io-index" 57 | checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" 58 | 59 | [[package]] 60 | name = "byteorder" 61 | version = "1.4.2" 62 | source = "registry+https://github.com/rust-lang/crates.io-index" 63 | checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b" 64 | 65 | [[package]] 66 | name = "cast" 67 | version = "0.2.3" 68 | source = "registry+https://github.com/rust-lang/crates.io-index" 69 | checksum = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0" 70 | dependencies = [ 71 | "rustc_version", 72 | ] 73 | 74 | [[package]] 75 | name = "cortex-m" 76 | version = "0.6.7" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | checksum = "9075300b07c6a56263b9b582c214d0ff037b00d45ec9fde1cc711490c56f1bb9" 79 | dependencies = [ 80 | "aligned", 81 | "bare-metal", 82 | "bitfield", 83 | "cortex-m 0.7.6", 84 | "volatile-register", 85 | ] 86 | 87 | [[package]] 88 | name = "cortex-m" 89 | version = "0.7.6" 90 | source = "registry+https://github.com/rust-lang/crates.io-index" 91 | checksum = "70858629a458fdfd39f9675c4dc309411f2a3f83bede76988d81bf1a0ecee9e0" 92 | dependencies = [ 93 | "bare-metal", 94 | "bitfield", 95 | "embedded-hal 0.2.7", 96 | "volatile-register", 97 | ] 98 | 99 | [[package]] 100 | name = "cortex-m-rt" 101 | version = "0.6.13" 102 | source = "registry+https://github.com/rust-lang/crates.io-index" 103 | checksum = "980c9d0233a909f355ed297ef122f257942de5e0a2cb1c39f60684b65bcb90fb" 104 | dependencies = [ 105 | "cortex-m-rt-macros", 106 | "r0", 107 | ] 108 | 109 | [[package]] 110 | name = "cortex-m-rt-macros" 111 | version = "0.1.8" 112 | source = "registry+https://github.com/rust-lang/crates.io-index" 113 | checksum = "4717562afbba06e760d34451919f5c3bf3ac15c7bb897e8b04862a7428378647" 114 | dependencies = [ 115 | "proc-macro2", 116 | "quote", 117 | "syn", 118 | ] 119 | 120 | [[package]] 121 | name = "cortex-m-rtic" 122 | version = "0.5.9" 123 | source = "registry+https://github.com/rust-lang/crates.io-index" 124 | checksum = "fb77bb72c171d0aa52a2954d8dc7e3f0800ab54b8df7d826f138abbea9eb2794" 125 | dependencies = [ 126 | "cortex-m 0.7.6", 127 | "cortex-m-rtic-macros", 128 | "heapless 0.6.1", 129 | "rtic-core", 130 | "version_check", 131 | ] 132 | 133 | [[package]] 134 | name = "cortex-m-rtic-macros" 135 | version = "0.5.3" 136 | source = "registry+https://github.com/rust-lang/crates.io-index" 137 | checksum = "cc874eda99515b15e67f03562726a530388f454431096d30131051b52b840559" 138 | dependencies = [ 139 | "proc-macro2", 140 | "quote", 141 | "rtic-syntax", 142 | "syn", 143 | ] 144 | 145 | [[package]] 146 | name = "cortex-m-semihosting" 147 | version = "0.5.0" 148 | source = "registry+https://github.com/rust-lang/crates.io-index" 149 | checksum = "c23234600452033cc77e4b761e740e02d2c4168e11dbf36ab14a0f58973592b0" 150 | dependencies = [ 151 | "cortex-m 0.7.6", 152 | ] 153 | 154 | [[package]] 155 | name = "embedded-hal" 156 | version = "0.2.7" 157 | source = "registry+https://github.com/rust-lang/crates.io-index" 158 | checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" 159 | dependencies = [ 160 | "nb 0.1.3", 161 | "void", 162 | ] 163 | 164 | [[package]] 165 | name = "embedded-hal" 166 | version = "1.0.0" 167 | source = "registry+https://github.com/rust-lang/crates.io-index" 168 | checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" 169 | 170 | [[package]] 171 | name = "generic-array" 172 | version = "0.12.4" 173 | source = "registry+https://github.com/rust-lang/crates.io-index" 174 | checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" 175 | dependencies = [ 176 | "typenum", 177 | ] 178 | 179 | [[package]] 180 | name = "generic-array" 181 | version = "0.13.3" 182 | source = "registry+https://github.com/rust-lang/crates.io-index" 183 | checksum = "f797e67af32588215eaaab8327027ee8e71b9dd0b2b26996aedf20c030fce309" 184 | dependencies = [ 185 | "typenum", 186 | ] 187 | 188 | [[package]] 189 | name = "generic-array" 190 | version = "0.14.4" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" 193 | dependencies = [ 194 | "typenum", 195 | "version_check", 196 | ] 197 | 198 | [[package]] 199 | name = "hash32" 200 | version = "0.1.1" 201 | source = "registry+https://github.com/rust-lang/crates.io-index" 202 | checksum = "d4041af86e63ac4298ce40e5cca669066e75b6f1aa3390fe2561ffa5e1d9f4cc" 203 | dependencies = [ 204 | "byteorder", 205 | ] 206 | 207 | [[package]] 208 | name = "hash32" 209 | version = "0.3.1" 210 | source = "registry+https://github.com/rust-lang/crates.io-index" 211 | checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" 212 | dependencies = [ 213 | "byteorder", 214 | ] 215 | 216 | [[package]] 217 | name = "hashbrown" 218 | version = "0.9.1" 219 | source = "registry+https://github.com/rust-lang/crates.io-index" 220 | checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" 221 | 222 | [[package]] 223 | name = "heapless" 224 | version = "0.6.1" 225 | source = "registry+https://github.com/rust-lang/crates.io-index" 226 | checksum = "634bd4d29cbf24424d0a4bfcbf80c6960129dc24424752a7d1d1390607023422" 227 | dependencies = [ 228 | "as-slice", 229 | "generic-array 0.14.4", 230 | "hash32 0.1.1", 231 | "stable_deref_trait", 232 | ] 233 | 234 | [[package]] 235 | name = "heapless" 236 | version = "0.8.0" 237 | source = "registry+https://github.com/rust-lang/crates.io-index" 238 | checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" 239 | dependencies = [ 240 | "hash32 0.3.1", 241 | "stable_deref_trait", 242 | ] 243 | 244 | [[package]] 245 | name = "indexmap" 246 | version = "1.6.1" 247 | source = "registry+https://github.com/rust-lang/crates.io-index" 248 | checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b" 249 | dependencies = [ 250 | "autocfg", 251 | "hashbrown", 252 | ] 253 | 254 | [[package]] 255 | name = "nb" 256 | version = "0.1.3" 257 | source = "registry+https://github.com/rust-lang/crates.io-index" 258 | checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" 259 | dependencies = [ 260 | "nb 1.0.0", 261 | ] 262 | 263 | [[package]] 264 | name = "nb" 265 | version = "1.0.0" 266 | source = "registry+https://github.com/rust-lang/crates.io-index" 267 | checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae" 268 | 269 | [[package]] 270 | name = "panic-semihosting" 271 | version = "0.6.0" 272 | source = "registry+https://github.com/rust-lang/crates.io-index" 273 | checksum = "ee8a3e1233d9073d76a870223512ce4eeea43c067a94a445c13bd6d792d7b1ab" 274 | dependencies = [ 275 | "cortex-m 0.7.6", 276 | "cortex-m-semihosting", 277 | ] 278 | 279 | [[package]] 280 | name = "proc-macro2" 281 | version = "1.0.24" 282 | source = "registry+https://github.com/rust-lang/crates.io-index" 283 | checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" 284 | dependencies = [ 285 | "unicode-xid", 286 | ] 287 | 288 | [[package]] 289 | name = "quote" 290 | version = "1.0.8" 291 | source = "registry+https://github.com/rust-lang/crates.io-index" 292 | checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df" 293 | dependencies = [ 294 | "proc-macro2", 295 | ] 296 | 297 | [[package]] 298 | name = "r0" 299 | version = "0.2.2" 300 | source = "registry+https://github.com/rust-lang/crates.io-index" 301 | checksum = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f" 302 | 303 | [[package]] 304 | name = "rtic-core" 305 | version = "0.3.1" 306 | source = "registry+https://github.com/rust-lang/crates.io-index" 307 | checksum = "8bd58a6949de8ff797a346a28d9f13f7b8f54fa61bb5e3cb0985a4efb497a5ef" 308 | 309 | [[package]] 310 | name = "rtic-syntax" 311 | version = "0.4.0" 312 | source = "registry+https://github.com/rust-lang/crates.io-index" 313 | checksum = "8152fcaa845720d61e6cc570548b89144c2c307f18a480bbd97e55e9f6eeff04" 314 | dependencies = [ 315 | "indexmap", 316 | "proc-macro2", 317 | "syn", 318 | ] 319 | 320 | [[package]] 321 | name = "rustc_version" 322 | version = "0.2.3" 323 | source = "registry+https://github.com/rust-lang/crates.io-index" 324 | checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 325 | dependencies = [ 326 | "semver", 327 | ] 328 | 329 | [[package]] 330 | name = "semver" 331 | version = "0.9.0" 332 | source = "registry+https://github.com/rust-lang/crates.io-index" 333 | checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 334 | dependencies = [ 335 | "semver-parser", 336 | ] 337 | 338 | [[package]] 339 | name = "semver-parser" 340 | version = "0.7.0" 341 | source = "registry+https://github.com/rust-lang/crates.io-index" 342 | checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 343 | 344 | [[package]] 345 | name = "stable_deref_trait" 346 | version = "1.2.0" 347 | source = "registry+https://github.com/rust-lang/crates.io-index" 348 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 349 | 350 | [[package]] 351 | name = "stm32l4" 352 | version = "0.12.1" 353 | source = "registry+https://github.com/rust-lang/crates.io-index" 354 | checksum = "a9abc2787195d7055b342be5a7934d74099fd7e92b81c0771002b3b35ccfc85b" 355 | dependencies = [ 356 | "bare-metal", 357 | "cortex-m 0.6.7", 358 | "cortex-m-rt", 359 | "vcell", 360 | ] 361 | 362 | [[package]] 363 | name = "stm32l4xx-hal" 364 | version = "0.6.0" 365 | source = "registry+https://github.com/rust-lang/crates.io-index" 366 | checksum = "3fc8fef7443befd04ba8714ccb9475d86639794492e2b2dcbfbe675bbae8fafa" 367 | dependencies = [ 368 | "as-slice", 369 | "cast", 370 | "cortex-m 0.6.7", 371 | "embedded-hal 0.2.7", 372 | "generic-array 0.13.3", 373 | "nb 0.1.3", 374 | "stable_deref_trait", 375 | "stm32l4", 376 | "void", 377 | ] 378 | 379 | [[package]] 380 | name = "syn" 381 | version = "1.0.58" 382 | source = "registry+https://github.com/rust-lang/crates.io-index" 383 | checksum = "cc60a3d73ea6594cd712d830cc1f0390fd71542d8c8cd24e70cc54cdfd5e05d5" 384 | dependencies = [ 385 | "proc-macro2", 386 | "quote", 387 | "unicode-xid", 388 | ] 389 | 390 | [[package]] 391 | name = "typenum" 392 | version = "1.12.0" 393 | source = "registry+https://github.com/rust-lang/crates.io-index" 394 | checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" 395 | 396 | [[package]] 397 | name = "unicode-xid" 398 | version = "0.2.1" 399 | source = "registry+https://github.com/rust-lang/crates.io-index" 400 | checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" 401 | 402 | [[package]] 403 | name = "vcell" 404 | version = "0.1.3" 405 | source = "registry+https://github.com/rust-lang/crates.io-index" 406 | checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" 407 | 408 | [[package]] 409 | name = "version_check" 410 | version = "0.9.2" 411 | source = "registry+https://github.com/rust-lang/crates.io-index" 412 | checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" 413 | 414 | [[package]] 415 | name = "void" 416 | version = "1.0.2" 417 | source = "registry+https://github.com/rust-lang/crates.io-index" 418 | checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" 419 | 420 | [[package]] 421 | name = "volatile-register" 422 | version = "0.2.0" 423 | source = "registry+https://github.com/rust-lang/crates.io-index" 424 | checksum = "0d67cb4616d99b940db1d6bd28844ff97108b498a6ca850e5b6191a532063286" 425 | dependencies = [ 426 | "vcell", 427 | ] 428 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32l4_heartbeat/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "app" 3 | categories = ["embedded", "no-std"] 4 | authors = ["arrowcircle", "Emil Fresk ", "Domenico Andreoli "] 5 | description = "Heartbeat for stm32l4xx" 6 | keywords = ["arm", "cortex-m"] 7 | license = "MIT OR Apache-2.0" 8 | version = "0.1.0" 9 | edition = "2018" 10 | 11 | [dependencies] 12 | panic-semihosting = "0.6" 13 | cortex-m-semihosting = "0.5.0" 14 | embedded-hal = "1.0.0" 15 | cortex-m-rtic = { version = "0.5.9", default-features = false, features = ["cortex-m-7"] } 16 | stm32l4xx-hal = { version = "0.6.0", features = ["rt", "stm32l4x2"] } 17 | heapless = "0.8.0" 18 | 19 | # this lets you use `cargo fix`! 20 | [[bin]] 21 | name = "app" 22 | test = false 23 | bench = false 24 | 25 | [profile.dev] 26 | opt-level = 1 27 | codegen-units = 16 28 | debug = true 29 | lto = false 30 | 31 | [profile.release] 32 | opt-level = "s" # optimize for size 33 | codegen-units = 1 # better optimizations 34 | debug = true # symbols are nice and they don't increase the size on Flash 35 | lto = true # better optimizations 36 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32l4_heartbeat/README.md: -------------------------------------------------------------------------------- 1 | # STM32L4 RTIC Blink example 2 | 3 | Working example of simple LED blinking application for STM32l4xx. 4 | 5 | ## How-to 6 | 7 | ### Terminal workflow 8 | 9 | Rust embedded relies heavily on `terminal workflow`, you will enter commands in the terminal. 10 | This can be strange at first, but this enables usage of great things like continuous integration tools. 11 | 12 | For Mac OS X consider using `iTerm2` instead of Terminal application. 13 | For Windows consider using `powershell` (win + r -> powershell -> enter -> cd C:\examples\rtic_v5\heartbeat_stm32l4) 14 | 15 | ### Build 16 | 17 | Run `cargo build` to compile the code. If you run it for the first time, 18 | it will take some time to download and compile dependencies. After that, you will see something like: 19 | 20 | ```bash 21 | >cargo build 22 | Finished dev [optimized + debuginfo] target(s) in 0.10s 23 | ``` 24 | 25 | If you see warnings, feel free to ask for help in chat or issues of this repo. 26 | 27 | ### Connect the board 28 | 29 | You need to connect you Bluepill board to ST-Link and connect pins: 30 | 31 | | BOARD | | ST-LINK | 32 | |-------|----|---------| 33 | | GND | -> | GND | 34 | | 3.3V | -> | 3.3V | 35 | | SWCLK | -> | SWCLK | 36 | | SWDIO | -> | SWDIO | 37 | 38 | Plug in ST-Link to USB port and wait it to initialize. 39 | 40 | ### Flashing and running 41 | 42 | Flashing with a standard STLink v2 is easy with `cargo-embed`: 43 | 44 | ```shell 45 | $ cargo install cargo-embed 46 | $ cargo embed --release 47 | ``` 48 | 49 | Please review the `.embed.toml` file to change your target IC among other options. 50 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32l4_heartbeat/memory.x: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | /* NOTE 1 K = 1 KiBi = 1024 bytes */ 4 | /* TODO Adjust these memory regions to match your device memory layout */ 5 | /* These values correspond to the LM3S6965, one of the few devices QEMU can emulate */ 6 | FLASH : ORIGIN = 0x08000000, LENGTH = 64K 7 | RAM : ORIGIN = 0x20000000, LENGTH = 20K 8 | } 9 | -------------------------------------------------------------------------------- /rtic_v0.5/stm32l4_heartbeat/src/main.rs: -------------------------------------------------------------------------------- 1 | #![deny(unsafe_code)] 2 | #![deny(warnings)] 3 | #![no_main] 4 | #![no_std] 5 | 6 | extern crate panic_semihosting; 7 | 8 | use heapless::Vec; 9 | 10 | use rtic::app; 11 | use rtic::cyccnt::U32Ext; 12 | 13 | use stm32l4xx_hal::gpio::{gpiob::PB3, Output, PushPull, State}; 14 | use stm32l4xx_hal::prelude::*; 15 | 16 | const BEATS_PER_MIN: u32 = 60; 17 | const CLK_SPEED_MHZ: u32 = 72; 18 | 19 | // Cycles per thousandth of beat 20 | const MILLI_BEAT: u32 = CLK_SPEED_MHZ * 60_000 / BEATS_PER_MIN; 21 | 22 | // We need to pass monotonic = rtic::cyccnt::CYCCNT to use schedule feature fo RTIC 23 | #[app(device = stm32l4xx_hal::pac, peripherals = true, monotonic = rtic::cyccnt::CYCCNT)] 24 | const APP: () = { 25 | // Global resources (global variables) are defined here and initialized with the 26 | // `LateResources` struct in init 27 | struct Resources { 28 | led: PB3>, 29 | intervals: Vec, 30 | } 31 | 32 | #[init(schedule = [blinker])] 33 | fn init(cx: init::Context) -> init::LateResources { 34 | // Enable cycle counter 35 | let mut core = cx.core; 36 | core.DWT.enable_cycle_counter(); 37 | 38 | // Setup clocks 39 | let mut flash = cx.device.FLASH.constrain(); 40 | let mut rcc = cx.device.RCC.constrain(); 41 | let mut pwr = cx.device.PWR.constrain(&mut rcc.apb1r1); 42 | let _clocks = rcc 43 | .cfgr 44 | .sysclk(CLK_SPEED_MHZ.mhz()) 45 | .freeze(&mut flash.acr, &mut pwr); 46 | 47 | // Setup LED 48 | let mut gpiob = cx.device.GPIOB.split(&mut rcc.ahb2); 49 | let led = gpiob.pb3.into_push_pull_output_with_state( 50 | &mut gpiob.moder, 51 | &mut gpiob.otyper, 52 | State::Low, 53 | ); 54 | 55 | // Simple heart beat LED on/off sequence 56 | let mut intervals: Vec = Vec::new(); 57 | intervals.push(MILLI_BEAT * 30).unwrap(); // P Wave 58 | intervals.push(MILLI_BEAT * 40).unwrap(); // PR Segment 59 | intervals.push(MILLI_BEAT * 120).unwrap(); // QRS Complex 60 | intervals.push(MILLI_BEAT * 30).unwrap(); // ST Segment 61 | intervals.push(MILLI_BEAT * 60).unwrap(); // T Wave 62 | intervals.push(MILLI_BEAT * 720).unwrap(); // Rest 63 | 64 | // Schedule the blinking task 65 | cx.schedule.blinker(cx.start, 0).unwrap(); 66 | 67 | init::LateResources { led, intervals } 68 | } 69 | 70 | #[idle] 71 | fn idle(_: idle::Context) -> ! { 72 | loop { 73 | core::hint::spin_loop(); 74 | } 75 | } 76 | 77 | #[task(schedule = [blinker], resources = [led, &intervals])] 78 | fn blinker(cx: blinker::Context, state: usize) { 79 | let led = cx.resources.led; 80 | let intervals = cx.resources.intervals; 81 | let duration = intervals[state].cycles(); 82 | let next_state = (state + 1) % intervals.len(); 83 | 84 | if state % 2 == 0 { 85 | led.set_high().unwrap(); 86 | } else { 87 | led.set_low().unwrap(); 88 | } 89 | 90 | cx.schedule 91 | .blinker(cx.scheduled + duration, next_state) 92 | .unwrap(); 93 | } 94 | 95 | extern "C" { 96 | fn EXTI0(); 97 | } 98 | }; 99 | -------------------------------------------------------------------------------- /rtic_v1/nrf52_monotonic/.cargo/config: -------------------------------------------------------------------------------- 1 | [target.thumbv7m-none-eabi] 2 | # uncomment this to make `cargo run` execute programs on QEMU 3 | # runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel" 4 | 5 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] 6 | # uncomment ONE of these three option to make `cargo run` start a GDB session 7 | # which option to pick depends on your system 8 | # runner = "arm-none-eabi-gdb -q -x jlink.gdb" 9 | runner = "arm-none-eabi-gdb -q -x openocd.gdb" 10 | # runner = "gdb-multiarch -q -x openocd.gdb" 11 | # runner = "gdb -q -x openocd.gdb" 12 | 13 | rustflags = [ 14 | # LLD (shipped with the Rust toolchain) is used as the default linker 15 | "-C", "link-arg=-Tlink.x", 16 | 17 | # if you run into problems with LLD switch to the GNU linker by commenting out 18 | # this line 19 | # "-C", "linker=arm-none-eabi-ld", 20 | 21 | # if you need to link to pre-compiled C libraries provided by a C toolchain 22 | # use GCC as the linker by commenting out both lines above and then 23 | # uncommenting the three lines below 24 | # "-C", "linker=arm-none-eabi-gcc", 25 | # "-C", "link-arg=-Wl,-Tlink.x", 26 | # "-C", "link-arg=-nostartfiles", 27 | 28 | # uncomment for unchecked wrapping arithmetics also in dev mode 29 | # "-Z", "force-overflow-checks=off", 30 | ] 31 | 32 | [build] 33 | # Pick ONE of these compilation targets 34 | # target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+ 35 | # target = "thumbv7m-none-eabi" # Cortex-M3 36 | # target = "thumbv7em-none-eabi" # Cortex-M4 and Cortex-M7 (no FPU) 37 | target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU) 38 | -------------------------------------------------------------------------------- /rtic_v1/nrf52_monotonic/.embed.toml: -------------------------------------------------------------------------------- 1 | # Refer to https://github.com/probe-rs/cargo-embed/blob/master/src/config/default.toml 2 | # for the comprehensive list of options 3 | 4 | [default.general] 5 | chip = "nrf52832" 6 | 7 | [default.rtt] 8 | enabled = true 9 | show_timestamps = true 10 | 11 | [default.gdb] 12 | # Whether or not a GDB server should be opened after flashing. 13 | # This is exclusive and cannot be used with RTT at the moment. 14 | enabled = false 15 | # The connection string in host:port format wher the GDB server will open a socket. 16 | # gdb_connection_string 17 | -------------------------------------------------------------------------------- /rtic_v1/nrf52_monotonic/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | 4 | -------------------------------------------------------------------------------- /rtic_v1/nrf52_monotonic/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "nrf52_monotonic" 3 | categories = ["embedded", "no-std"] 4 | authors = ["Emil Fresk "] 5 | description = "Example Monotonic trait" 6 | keywords = ["arm", "cortex-m"] 7 | license = "MIT OR Apache-2.0" 8 | version = "0.1.0" 9 | edition = "2021" 10 | 11 | [dependencies] 12 | cortex-m-rtic = "1.1.4" 13 | fugit = "0.3.7" 14 | rtic-monotonic = "1.0.0" 15 | panic-rtt-target = { version = "0.1.2", features = ["cortex-m"] } 16 | rtt-target = { version = "0.3.1", features = ["cortex-m"] } 17 | 18 | [dependencies.nrf52832-hal] 19 | version = "0.16.0" 20 | default-features = false 21 | features = ["xxAA-package", "rt"] 22 | 23 | # this lets you use `cargo fix`! 24 | [[bin]] 25 | name = "nrf52_monotonic" 26 | test = false 27 | bench = false 28 | 29 | [profile.dev] 30 | opt-level = 1 31 | codegen-units = 16 32 | debug = true 33 | lto = false 34 | 35 | [profile.release] 36 | opt-level = "s" # optimize for size 37 | codegen-units = 1 # better optimizations 38 | debug = true # symbols are nice and they don't increase the size on Flash 39 | lto = true # better optimizations 40 | -------------------------------------------------------------------------------- /rtic_v1/nrf52_monotonic/README.md: -------------------------------------------------------------------------------- 1 | # nRF52 Monotonic 2 | 3 | In this example we show the use of a custom `rtic::Monotonic` implementation which uses a timer of the `nRF52832` MCU. 4 | 5 | ### Flashing and running 6 | 7 | Flashing with a standard STLink v2 is easy with `cargo-embed`: 8 | 9 | ```shell 10 | $ cargo install cargo-embed 11 | $ cargo embed --release 12 | ``` 13 | 14 | Please review the `.embed.toml` file to change your target IC among other options. 15 | -------------------------------------------------------------------------------- /rtic_v1/nrf52_monotonic/src/main.rs: -------------------------------------------------------------------------------- 1 | //! In here all hardware dependent code is kept, and to run the independent parts the firmware crate 2 | //! is called. 3 | 4 | #![no_main] 5 | #![no_std] 6 | 7 | use crate::monotonic_nrf52::MonoTimer; 8 | use fugit::{self, ExtU32}; 9 | use nrf52832_hal as _; 10 | use panic_rtt_target as _; 11 | use rtic::app; 12 | use rtt_target::{rprintln, rtt_init_print}; 13 | 14 | mod monotonic_nrf52; 15 | 16 | #[app(device = nrf52832_hal::pac, peripherals = true, dispatchers = [SWI0_EGU0])] 17 | mod app { 18 | use super::*; 19 | 20 | #[shared] 21 | struct Shared {} 22 | 23 | #[local] 24 | struct Local {} 25 | 26 | #[monotonic(binds = TIMER1, default = true)] 27 | type Tonic = MonoTimer; 28 | 29 | #[init] 30 | fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { 31 | let mono = MonoTimer::new(cx.device.TIMER1); 32 | 33 | rtt_init_print!(); 34 | rprintln!("init"); 35 | 36 | task1::spawn().ok(); 37 | 38 | (Shared {}, Local {}, init::Monotonics(mono)) 39 | } 40 | 41 | #[task] 42 | fn task1(_cx: task1::Context) { 43 | rprintln!("task1"); 44 | task1::spawn_after(2000.millis()).ok(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /rtic_v1/nrf52_monotonic/src/monotonic_nrf52.rs: -------------------------------------------------------------------------------- 1 | // Taken from: https://github.com/kalkyl/nrf-play/blob/47f4410d4e39374c18ff58dc17c25159085fb526/src/mono.rs 2 | 3 | // RTIC Monotonic impl for the 32-bit timers 4 | pub use fugit::{self, ExtU32}; 5 | use nrf52832_hal::pac::{timer0, TIMER0, TIMER1, TIMER2}; 6 | use rtic_monotonic::Monotonic; 7 | 8 | pub struct MonoTimer(T); 9 | 10 | impl MonoTimer { 11 | pub fn new(timer: T) -> Self { 12 | timer.prescaler.write( 13 | |w| unsafe { w.prescaler().bits(4) }, // 1 MHz 14 | ); 15 | timer.bitmode.write(|w| w.bitmode()._32bit()); 16 | MonoTimer(timer) 17 | } 18 | } 19 | 20 | impl Monotonic for MonoTimer { 21 | type Instant = fugit::TimerInstantU32<1_000_000>; 22 | type Duration = fugit::TimerDurationU32<1_000_000>; 23 | 24 | unsafe fn reset(&mut self) { 25 | self.0.intenset.modify(|_, w| w.compare0().set()); 26 | self.0.tasks_clear.write(|w| w.bits(1)); 27 | self.0.tasks_start.write(|w| w.bits(1)); 28 | } 29 | 30 | #[inline(always)] 31 | fn now(&mut self) -> Self::Instant { 32 | self.0.tasks_capture[1].write(|w| unsafe { w.bits(1) }); 33 | Self::Instant::from_ticks(self.0.cc[1].read().bits()) 34 | } 35 | 36 | fn set_compare(&mut self, instant: Self::Instant) { 37 | self.0.cc[0].write(|w| unsafe { w.cc().bits(instant.duration_since_epoch().ticks()) }); 38 | } 39 | 40 | fn clear_compare_flag(&mut self) { 41 | self.0.events_compare[0].write(|w| w); 42 | } 43 | 44 | #[inline(always)] 45 | fn zero() -> Self::Instant { 46 | Self::Instant::from_ticks(0) 47 | } 48 | } 49 | 50 | pub trait Instance32: core::ops::Deref {} 51 | impl Instance32 for TIMER0 {} 52 | impl Instance32 for TIMER1 {} 53 | impl Instance32 for TIMER2 {} 54 | -------------------------------------------------------------------------------- /rtic_v1/rp-pico_local_initilzd_resources/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | # From rp2040 template repo: 2 | # https://github.com/rp-rs/rp2040-project-template 3 | # 4 | # Choose a default "cargo run" tool. 5 | # probe-run is recommended if you have a debugger 6 | # elf2uf2-rs loads firmware over USB when the rp2040 is in boot mode 7 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] 8 | runner = "probe-run --chip RP2040" 9 | #runner = "elf2uf2-rs -d" 10 | #runner = "gdb-multiarch -q -x openocd.gdb" 11 | 12 | rustflags = [ 13 | #"-C", "linker=flip-link", 14 | #"-C", "link-arg=--nmagic", 15 | "-C", "link-arg=-Tlink.x", 16 | 17 | # Code-size optimizations. 18 | # trap unreachable can save a lot of space, but requires nightly compiler. 19 | # uncomment the next line if you wish to enable it 20 | # "-Z", "trap-unreachable=no", 21 | "-C", "inline-threshold=5", 22 | "-C", "no-vectorize-loops", 23 | ] 24 | 25 | [build] 26 | target = "thumbv6m-none-eabi" -------------------------------------------------------------------------------- /rtic_v1/rp-pico_local_initilzd_resources/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rp-pico_local_initlzd_resources" 3 | categories = ["embedded", "no-std"] 4 | description = "Example task local initialized resources for Raspberry Pi Pico" 5 | license = "MIT OR Apache-2.0" 6 | version = "0.1.0" 7 | edition = "2021" 8 | 9 | [dependencies] 10 | cortex-m = "0.7" 11 | cortex-m-rt = "0.7" 12 | cortex-m-rtic = "1.1.4" 13 | embedded-hal = { version = "0.2.7", features = ["unproven"] } 14 | fugit = "0.3" 15 | rp-pico = "0.7.0" 16 | rp2040-boot2 = { version = "0.3.0" } 17 | rp2040-monotonic = "1.3" 18 | panic-probe = {version = "0.3"} 19 | 20 | [profile.dev] 21 | opt-level = 1 22 | codegen-units = 16 23 | debug = true 24 | lto = false 25 | 26 | [profile.release] 27 | opt-level = "s" # optimize for size 28 | codegen-units = 1 # better optimizations 29 | debug = true # symbols are nice and they don't increase the size on Flash 30 | lto = true # better optimzations -------------------------------------------------------------------------------- /rtic_v1/rp-pico_local_initilzd_resources/build.rs: -------------------------------------------------------------------------------- 1 | //! This build script copies the `memory.x` file from the crate root into 2 | //! a directory where the linker can always find it at build time. 3 | //! For many projects this is optional, as the linker always searches the 4 | //! project root directory -- wherever `Cargo.toml` is. However, if you 5 | //! are using a workspace or have a more complicated build setup, this 6 | //! build script becomes required. Additionally, by requesting that 7 | //! Cargo re-run the build script whenever `memory.x` is changed, 8 | //! updating `memory.x` ensures a rebuild of the application with the 9 | //! new memory settings. 10 | 11 | use std::env; 12 | use std::fs::File; 13 | use std::io::Write; 14 | use std::path::PathBuf; 15 | 16 | fn main() { 17 | // Put `memory.x` in our output directory and ensure it's 18 | // on the linker search path. 19 | let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); 20 | File::create(out.join("memory.x")) 21 | .unwrap() 22 | .write_all(include_bytes!("memory.x")) 23 | .unwrap(); 24 | println!("cargo:rustc-link-search={}", out.display()); 25 | 26 | // By default, Cargo will re-run a build script whenever 27 | // any file in the project changes. By specifying `memory.x` 28 | // here, we ensure the build script is only re-run when 29 | // `memory.x` is changed. 30 | println!("cargo:rerun-if-changed=memory.x"); 31 | } 32 | -------------------------------------------------------------------------------- /rtic_v1/rp-pico_local_initilzd_resources/memory.x: -------------------------------------------------------------------------------- 1 | MEMORY { 2 | BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100 3 | FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100 4 | RAM : ORIGIN = 0x20000000, LENGTH = 256K 5 | } 6 | 7 | EXTERN(BOOT2_FIRMWARE) 8 | 9 | SECTIONS { 10 | /* ### Boot loader */ 11 | .boot2 ORIGIN(BOOT2) : 12 | { 13 | KEEP(*(.boot2)); 14 | } > BOOT2 15 | } INSERT BEFORE .text; 16 | -------------------------------------------------------------------------------- /rtic_v1/rp-pico_local_initilzd_resources/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | #[rtic::app( 5 | device = rp_pico::hal::pac, 6 | dispatchers = [TIMER_IRQ_1] 7 | )] 8 | mod app { 9 | use rp2040_monotonic::{ 10 | fugit::Duration, 11 | fugit::RateExtU32, // For .kHz() conversion funcs 12 | Rp2040Monotonic, 13 | }; 14 | use rp_pico::hal::{ 15 | clocks, gpio, 16 | gpio::pin::bank0::{Gpio2, Gpio25, Gpio3}, 17 | gpio::pin::PushPullOutput, 18 | pac, 19 | sio::Sio, 20 | watchdog::Watchdog, 21 | I2C, 22 | }; 23 | use rp_pico::XOSC_CRYSTAL_FREQ; 24 | 25 | use core::mem::MaybeUninit; 26 | use embedded_hal::digital::v2::{OutputPin, ToggleableOutputPin}; 27 | 28 | use panic_probe as _; 29 | 30 | const MONO_NUM: u32 = 1; 31 | const MONO_DENOM: u32 = 1000000; 32 | const ONE_SEC_TICKS: u64 = 1000000; 33 | 34 | type I2CBus = I2C< 35 | pac::I2C1, 36 | ( 37 | gpio::Pin, 38 | gpio::Pin, 39 | ), 40 | >; 41 | 42 | #[monotonic(binds = TIMER_IRQ_0, default = true)] 43 | type Rp2040Mono = Rp2040Monotonic; 44 | 45 | #[shared] 46 | struct Shared {} 47 | 48 | #[local] 49 | struct Local { 50 | led: gpio::Pin, 51 | i2c: &'static mut I2CBus, 52 | } 53 | 54 | #[init(local=[ 55 | // Task local initialized resources are static 56 | // Here we use MaybeUninit to allow for initialization in init() 57 | // This enables its usage in driver initialization 58 | i2c_ctx: MaybeUninit = MaybeUninit::uninit() 59 | ])] 60 | fn init(mut ctx: init::Context) -> (Shared, Local, init::Monotonics) { 61 | // Configure the clocks, watchdog - The default is to generate a 125 MHz system clock 62 | let mut watchdog = Watchdog::new(ctx.device.WATCHDOG); 63 | let clocks = clocks::init_clocks_and_plls( 64 | XOSC_CRYSTAL_FREQ, 65 | ctx.device.XOSC, 66 | ctx.device.CLOCKS, 67 | ctx.device.PLL_SYS, 68 | ctx.device.PLL_USB, 69 | &mut ctx.device.RESETS, 70 | &mut watchdog, 71 | ) 72 | .ok() 73 | .unwrap(); 74 | 75 | // Init LED pin 76 | let sio = Sio::new(ctx.device.SIO); 77 | let gpioa = rp_pico::Pins::new( 78 | ctx.device.IO_BANK0, 79 | ctx.device.PADS_BANK0, 80 | sio.gpio_bank0, 81 | &mut ctx.device.RESETS, 82 | ); 83 | let mut led = gpioa.led.into_push_pull_output(); 84 | led.set_low().unwrap(); 85 | 86 | // Init I2C pins 87 | let sda_pin = gpioa.gpio2.into_mode::(); 88 | let scl_pin = gpioa.gpio3.into_mode::(); 89 | 90 | // Init I2C itself, using MaybeUninit to overwrite the previously 91 | // uninitialized i2c_ctx variable without dropping its value 92 | // (i2c_ctx definined in init local resources above) 93 | let i2c_tmp: &'static mut _ = ctx.local.i2c_ctx.write(I2C::i2c1( 94 | ctx.device.I2C1, 95 | sda_pin, 96 | scl_pin, 97 | 100.kHz(), 98 | &mut ctx.device.RESETS, 99 | &clocks.system_clock, 100 | )); 101 | 102 | let mono = Rp2040Mono::new(ctx.device.TIMER); 103 | 104 | // Spawn heartbeat task 105 | heartbeat::spawn().unwrap(); 106 | 107 | // Return resources and timer 108 | ( 109 | Shared {}, 110 | Local { led, i2c: i2c_tmp }, 111 | init::Monotonics(mono), 112 | ) 113 | } 114 | 115 | #[task(local = [i2c, led])] 116 | fn heartbeat(ctx: heartbeat::Context) { 117 | // Flicker the built-in LED 118 | _ = ctx.local.led.toggle(); 119 | 120 | // Congrats, you can use your i2c and have access to it here, 121 | // now to do something with it! 122 | 123 | // Re-spawn this task after 1 second 124 | let one_second = Duration::::from_ticks(ONE_SEC_TICKS); 125 | heartbeat::spawn_after(one_second).unwrap(); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /rtic_v1/stm32f0_hid_mouse/.cargo/config: -------------------------------------------------------------------------------- 1 | [target.thumbv6m-none-eabi] 2 | rustflags = [ 3 | "-C", "link-arg=-Tlink.x", 4 | ] 5 | 6 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] 7 | runner = "probe-run --chip STM32F042G6Ux --defmt" 8 | 9 | [build] 10 | target = "thumbv6m-none-eabi" 11 | -------------------------------------------------------------------------------- /rtic_v1/stm32f0_hid_mouse/.embed.toml: -------------------------------------------------------------------------------- 1 | # Refer to https://github.com/probe-rs/cargo-embed/blob/master/src/config/default.toml 2 | # for the comprehensive list of options 3 | 4 | [default.general] 5 | chip = "STM32F042G6Ux" 6 | 7 | [default.rtt] 8 | enabled = true 9 | show_timestamps = true 10 | -------------------------------------------------------------------------------- /rtic_v1/stm32f0_hid_mouse/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | -------------------------------------------------------------------------------- /rtic_v1/stm32f0_hid_mouse/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "stm32f042" 3 | version = "0.1.0" 4 | authors = ["Roman Valls Guimera ", "Josh Johnson"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | embedded-hal = "1.0.0" 9 | usb-device = "0.2.8" 10 | usbd-hid = "0.6.1" 11 | rtt-target = { version = "0.3.1", features = ["cortex-m"] } 12 | panic-halt = "0.2.0" 13 | cortex-m = "0.7.7" 14 | cortex-m-rtic = "1.1.4" 15 | stm32f0xx-hal = { version = "0.18.0", features = [ 16 | "rt", 17 | "stm32f042", 18 | "stm32-usbd", 19 | ] } 20 | stm32-usbd = "0.6.0" 21 | -------------------------------------------------------------------------------- /rtic_v1/stm32f0_hid_mouse/README.md: -------------------------------------------------------------------------------- 1 | # Rust STM32 blackberry trackball firmware 2 | 3 | Getting onboard with Rust for embedded devices is like 1,2,3 (more details on the [Rust embedded book](https://rust-embedded.github.io/book/)): 4 | 5 | ```shell 6 | $ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh 7 | $ rustup target add thumbv6m-none-eabi 8 | $ cargo install cargo-embed 9 | ``` 10 | 11 | Flashing with a standard STLink v2 is easy with `cargo-embed`: 12 | 13 | ```shell 14 | $ cargo embed --release 15 | Finished release [optimized] target(s) in 0.04s 16 | Flashing /Users/romanvg/dev/cchs/keyboard_trackball/software/stm32f04/target/thumbv6m-none-eabi/release/stm32f042 17 | Erasing sectors ✔ [00:00:00] [#################################################################] 23.00KB/ 23.00KB @ 28.29KB/s (eta 0s ) 18 | Programming pages ✔ [00:00:02] [#################################################################] 23.00KB/ 23.00KB @ 7.24KB/s (eta 0s ) 19 | Finished in 2.942s 20 | ``` 21 | 22 | More context and possible future extensions [at the original repo for this example](https://github.com/brainstorm/bbtrackball-rs). 23 | -------------------------------------------------------------------------------- /rtic_v1/stm32f0_hid_mouse/build.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::fs; 3 | use std::io::Write; 4 | use std::path::PathBuf; 5 | 6 | fn main() { 7 | // Put the linker script somewhere the linker can find it 8 | let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); 9 | fs::File::create(out_dir.join("memory.x")) 10 | .unwrap() 11 | .write_all(include_bytes!("memory.x")) 12 | .unwrap(); 13 | println!("cargo:rustc-link-search={}", out_dir.display()); 14 | println!("cargo:rerun-if-changed=memory.x"); 15 | } 16 | -------------------------------------------------------------------------------- /rtic_v1/stm32f0_hid_mouse/memory.x: -------------------------------------------------------------------------------- 1 | /* STM32F042G6 */ 2 | MEMORY 3 | { 4 | FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 32K 5 | RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 6K 6 | } 7 | -------------------------------------------------------------------------------- /rtic_v1/stm32f0_hid_mouse/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | #![deny(unsafe_code)] 3 | */ 4 | #![deny(warnings)] 5 | #![no_std] 6 | #![no_main] 7 | 8 | use cortex_m::interrupt::free as disable_interrupts; 9 | use panic_halt as _; 10 | use rtic::app; 11 | use rtic::{Exclusive, Mutex}; 12 | use rtt_target::{rprintln, rtt_init_print}; 13 | 14 | use stm32f0xx_hal::{ 15 | gpio::gpioa::{PA0, PA1, PA15, PA2, PA3, PA4, PA5, PA6, PA7}, 16 | gpio::gpiob::{PB1, PB3, PB4}, 17 | gpio::{Input, Output, PullUp, PushPull}, 18 | pac, 19 | prelude::*, 20 | usb, 21 | }; 22 | 23 | use usb_device::{bus::UsbBusAllocator, prelude::*}; 24 | use usbd_hid::{ 25 | descriptor::{MouseReport, SerializedDescriptor}, 26 | hid_class::HIDClass, 27 | }; 28 | 29 | #[app(device = stm32f0xx_hal::pac, peripherals = true)] 30 | mod app { 31 | use super::*; 32 | 33 | #[local] 34 | struct Local { 35 | usr_led: PB1>, 36 | usb_device: UsbDevice<'static, usb::UsbBusType>, 37 | } 38 | 39 | #[shared] 40 | struct Shared { 41 | usb_hid: HIDClass<'static, usb::UsbBusType>, 42 | exti: pac::EXTI, 43 | _button3: PA15>, 44 | _button4: PB4>, 45 | _button5: PB3>, 46 | _tb_left: PA4>, 47 | _tb_up: PA5>, 48 | _tb_right: PA6>, 49 | _tb_down: PA7>, 50 | bbled_red: PA0>, 51 | bbled_grn: PA1>, 52 | bbled_blu: PA2>, 53 | bbled_wht: PA3>, 54 | } 55 | 56 | #[init(local = [USB_BUS: Option> = None])] 57 | fn init(ctx: init::Context) -> (Shared, Local, init::Monotonics) { 58 | // RTT handler 59 | rtt_init_print!(); 60 | 61 | // Alias peripherals 62 | let mut dp: pac::Peripherals = ctx.device; 63 | 64 | // This enables clock for SYSCFG and remaps USB pins to PA9 and PA10. 65 | usb::remap_pins(&mut dp.RCC, &mut dp.SYSCFG); 66 | 67 | rprintln!("Initializing peripherals"); 68 | let mut rcc = dp 69 | .RCC 70 | .configure() 71 | .usbsrc(stm32f0xx_hal::rcc::USBClockSource::HSI48) 72 | .hsi48() 73 | .enable_crs(dp.CRS) 74 | .sysclk(48.mhz()) 75 | .pclk(24.mhz()) 76 | .freeze(&mut dp.FLASH); 77 | 78 | // Set up GPIO registers for USR LED and Buttons 79 | let gpiob = dp.GPIOB.split(&mut rcc); 80 | let (usr_led, _button4, _button5) = disable_interrupts(|cs| { 81 | ( 82 | gpiob.pb1.into_push_pull_output(cs), 83 | gpiob.pb4.into_pull_up_input(cs), 84 | gpiob.pb3.into_pull_up_input(cs), 85 | ) 86 | }); 87 | 88 | // LEDs and USB 89 | let gpioa = dp.GPIOA.split(&mut rcc); 90 | let ( 91 | bbled_red, 92 | bbled_grn, 93 | bbled_blu, 94 | bbled_wht, 95 | _tb_left, 96 | _tb_up, 97 | _tb_right, 98 | _tb_down, 99 | _button3, 100 | usb_dm, 101 | usb_dp, 102 | ) = disable_interrupts(|cs| { 103 | ( 104 | gpioa.pa0.into_push_pull_output(cs), 105 | gpioa.pa1.into_push_pull_output(cs), 106 | gpioa.pa2.into_push_pull_output(cs), 107 | gpioa.pa3.into_push_pull_output(cs), 108 | gpioa.pa4.into_pull_up_input(cs), 109 | gpioa.pa5.into_pull_up_input(cs), 110 | gpioa.pa6.into_pull_up_input(cs), 111 | gpioa.pa7.into_pull_up_input(cs), 112 | gpioa.pa15.into_pull_up_input(cs), 113 | gpioa.pa11, 114 | gpioa.pa12, 115 | ) 116 | }); 117 | 118 | // Power on bbled dance 119 | //bbled_red.toggle().ok(); 120 | 121 | // Enable external interrupt for 3 aux buttons... 122 | dp.SYSCFG.exticr1.write(|w| w.exti3().pb3()); 123 | // dp.SYSCFG.exticr2.write(|w| { w.exti4().pb4() }); // Disable spare button in favor of tb_left 124 | dp.SYSCFG.exticr4.write(|w| w.exti15().pa15()); 125 | //... and for pulses on trackball 126 | dp.SYSCFG.exticr2.write(|w| w.exti4().pa4()); 127 | dp.SYSCFG.exticr2.write(|w| w.exti5().pa5()); 128 | dp.SYSCFG.exticr2.write(|w| w.exti6().pa6()); 129 | dp.SYSCFG.exticr2.write(|w| w.exti7().pa7()); 130 | 131 | // Set interrupt mask for all the above 132 | dp.EXTI.imr.write(|w| { 133 | w.mr3().set_bit(); 134 | w.mr4().set_bit(); 135 | w.mr5().set_bit(); 136 | w.mr6().set_bit(); 137 | w.mr7().set_bit(); 138 | w.mr15().set_bit() 139 | }); 140 | 141 | // Set interrupt rising trigger 142 | dp.EXTI.rtsr.write(|w| { 143 | w.tr3().set_bit(); 144 | w.tr4().set_bit(); 145 | w.tr5().set_bit(); 146 | w.tr6().set_bit(); 147 | w.tr7().set_bit(); 148 | w.tr15().set_bit() 149 | }); 150 | 151 | let usb = usb::Peripheral { 152 | usb: dp.USB, 153 | pin_dm: usb_dm, 154 | pin_dp: usb_dp, 155 | }; 156 | 157 | rprintln!("Preparing HID mouse..."); 158 | 159 | let usb_bus = ctx.local.USB_BUS; 160 | *usb_bus = Some(usb::UsbBus::new(usb)); 161 | 162 | let usb_hid = HIDClass::new(usb_bus.as_ref().unwrap(), MouseReport::desc(), 60); 163 | 164 | rprintln!("Defining USB parameters..."); 165 | let usb_device = UsbDeviceBuilder::new(usb_bus.as_ref().unwrap(), UsbVidPid(0, 0x3821)) 166 | .manufacturer("JoshFTW") 167 | .product("BBTrackball") 168 | .serial_number("RustFW") 169 | .device_class(0x00) 170 | .device_sub_class(0x00) 171 | .device_protocol(0x00) 172 | .build(); 173 | 174 | rprintln!("Instantiating dp.EXTI..."); 175 | let exti = dp.EXTI; 176 | 177 | rprintln!("Defining shared resources..."); 178 | let shared = Shared { 179 | usb_hid, 180 | exti, 181 | _button3, 182 | _button4, 183 | _button5, 184 | _tb_left, 185 | _tb_up, 186 | _tb_right, 187 | _tb_down, 188 | bbled_red, 189 | bbled_grn, 190 | bbled_blu, 191 | bbled_wht, 192 | }; 193 | 194 | ( 195 | shared, 196 | Local { 197 | usr_led, 198 | usb_device, 199 | }, 200 | init::Monotonics(), 201 | ) 202 | } 203 | 204 | #[idle] 205 | fn idle(_: idle::Context) -> ! { 206 | loop { 207 | cortex_m::asm::nop(); 208 | cortex_m::asm::wfi(); 209 | } 210 | } 211 | 212 | #[task(binds = EXTI2_3, shared = [exti])] 213 | fn exti2_3_interrupt(mut ctx: exti2_3_interrupt::Context) { 214 | rprintln!("Interrupts happening on EXTI2_3"); 215 | 216 | match ctx.shared.exti.lock(|exti| exti.pr.read().bits()) { 217 | 0x8 => { 218 | rprintln!("PB3 triggered"); 219 | ctx.shared 220 | .exti 221 | .lock(|exti| exti.pr.write(|w| w.pif3().set_bit())); // Clear interrupt 222 | } 223 | 224 | _ => rprintln!("Some other bits were pushed around on EXTI2_3 ;)"), 225 | } 226 | } 227 | 228 | #[task(binds = EXTI4_15, local = [usr_led], shared = [exti, usb_hid, bbled_red, bbled_grn, bbled_wht, bbled_blu])] 229 | fn exti_4_15_interrupt(mut ctx: exti_4_15_interrupt::Context) { 230 | rprintln!("Interrupts happening on EXTI for PA15..."); 231 | 232 | match ctx.shared.exti.lock(|exti| exti.pr.read().bits()) { 233 | 0x8000 => { 234 | rprintln!("PA15 triggered"); 235 | ctx.shared 236 | .exti 237 | .lock(|exti| exti.pr.write(|w| w.pif15().set_bit())); // Clear interrupt 238 | 239 | ctx.shared 240 | .usb_hid 241 | .lock(|hid| super::send_mouse_report(Exclusive(hid), 0, 0, 1)); 242 | ctx.local.usr_led.toggle().ok(); 243 | } 244 | 0x10 => { 245 | rprintln!("tb_left triggered!"); 246 | ctx.shared 247 | .exti 248 | .lock(|exti| exti.pr.write(|w| w.pif4().set_bit())); 249 | ctx.shared 250 | .usb_hid 251 | .lock(|hid| super::send_mouse_report(Exclusive(hid), 5, 0, 0)); 252 | ctx.local.usr_led.toggle().ok(); 253 | } 254 | 0x20 => { 255 | rprintln!("tb_up triggered!"); 256 | ctx.shared 257 | .exti 258 | .lock(|exti| exti.pr.write(|w| w.pif5().set_bit())); 259 | 260 | ctx.shared 261 | .usb_hid 262 | .lock(|hid| super::send_mouse_report(Exclusive(hid), 0, 5, 0)); 263 | ctx.local.usr_led.toggle().ok(); 264 | } 265 | 0x40 => { 266 | rprintln!("tb_right triggered!"); 267 | ctx.shared 268 | .exti 269 | .lock(|exti| exti.pr.write(|w| w.pif6().set_bit())); 270 | 271 | ctx.shared 272 | .usb_hid 273 | .lock(|hid| super::send_mouse_report(Exclusive(hid), -5, 0, 0)); 274 | ctx.local.usr_led.toggle().ok(); 275 | } 276 | 0x80 => { 277 | rprintln!("tb_down triggered!"); 278 | ctx.shared 279 | .exti 280 | .lock(|exti| exti.pr.write(|w| w.pif7().set_bit())); 281 | 282 | ctx.shared 283 | .usb_hid 284 | .lock(|hid| super::send_mouse_report(Exclusive(hid), 0, -5, 0)); 285 | ctx.local.usr_led.toggle().ok(); 286 | } 287 | 288 | _ => rprintln!("Some other bits were pushed around on EXTI4_15 ;)"), 289 | } 290 | } 291 | 292 | #[task(binds = USB, local = [usb_device], shared = [usb_hid])] 293 | fn usb_handler(mut ctx: usb_handler::Context) { 294 | rprintln!("USB interrupt received."); 295 | 296 | let device = ctx.local.usb_device; 297 | ctx.shared.usb_hid.lock(|hid| { 298 | // USB dev poll only in the interrupt handler 299 | device.poll(&mut [hid]); 300 | }); 301 | } 302 | } 303 | 304 | fn send_mouse_report( 305 | mut shared_hid: impl Mutex>, 306 | x: i8, 307 | y: i8, 308 | buttons: u8, 309 | ) { 310 | let mr = MouseReport { 311 | x, 312 | y, 313 | buttons, 314 | wheel: 0, 315 | pan: 0, 316 | }; 317 | 318 | shared_hid.lock(|hid| { 319 | rprintln!("Sending mouse report..."); 320 | hid.push_input(&mr).ok(); 321 | }); 322 | } 323 | -------------------------------------------------------------------------------- /rtic_v1/stm32f1_bluepill_blinky/.cargo/config: -------------------------------------------------------------------------------- 1 | [target.thumbv7m-none-eabi] 2 | # uncomment this to make `cargo run` execute programs on QEMU 3 | # runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel" 4 | 5 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] 6 | # uncomment ONE of these three option to make `cargo run` start a GDB session 7 | # which option to pick depends on your system 8 | # runner = "arm-none-eabi-gdb -q -x jlink.gdb" 9 | runner = "arm-none-eabi-gdb -q -x openocd.gdb" 10 | # runner = "gdb-multiarch -q -x openocd.gdb" 11 | # runner = "gdb -q -x openocd.gdb" 12 | 13 | rustflags = [ 14 | # LLD (shipped with the Rust toolchain) is used as the default linker 15 | "-C", "link-arg=-Tlink.x", 16 | 17 | # if you run into problems with LLD switch to the GNU linker by commenting out 18 | # this line 19 | # "-C", "linker=arm-none-eabi-ld", 20 | 21 | # if you need to link to pre-compiled C libraries provided by a C toolchain 22 | # use GCC as the linker by commenting out both lines above and then 23 | # uncommenting the three lines below 24 | # "-C", "linker=arm-none-eabi-gcc", 25 | # "-C", "link-arg=-Wl,-Tlink.x", 26 | # "-C", "link-arg=-nostartfiles", 27 | 28 | # uncomment for unchecked wrapping arithmetics also in dev mode 29 | # "-Z", "force-overflow-checks=off", 30 | ] 31 | 32 | [build] 33 | # Pick ONE of these compilation targets 34 | # target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+ 35 | target = "thumbv7m-none-eabi" # Cortex-M3 36 | # target = "thumbv7em-none-eabi" # Cortex-M4 and Cortex-M7 (no FPU) 37 | # target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU) 38 | -------------------------------------------------------------------------------- /rtic_v1/stm32f1_bluepill_blinky/.embed.toml: -------------------------------------------------------------------------------- 1 | # Refer to https://github.com/probe-rs/cargo-embed/blob/master/src/config/default.toml 2 | # for the comprehensive list of options 3 | 4 | [default.general] 5 | chip = "STM32F103" 6 | 7 | [default.rtt] 8 | enabled = true 9 | show_timestamps = true 10 | 11 | [default.gdb] 12 | # Whether or not a GDB server should be opened after flashing. 13 | # This is exclusive and cannot be used with RTT at the moment. 14 | enabled = false 15 | # The connection string in host:port format wher the GDB server will open a socket. 16 | # gdb_connection_string 17 | -------------------------------------------------------------------------------- /rtic_v1/stm32f1_bluepill_blinky/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | 4 | -------------------------------------------------------------------------------- /rtic_v1/stm32f1_bluepill_blinky/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bluepill_blinky" 3 | categories = ["embedded", "no-std"] 4 | authors = ["arrowcircle", "Emil Fresk "] 5 | description = "Example blinky for BluePill" 6 | keywords = ["arm", "cortex-m"] 7 | license = "MIT OR Apache-2.0" 8 | version = "0.1.0" 9 | edition = "2021" 10 | 11 | [dependencies] 12 | embedded-hal = "1.0.0" 13 | cortex-m-rtic = "1.1.4" 14 | panic-rtt-target = { version = "0.1.2", features = ["cortex-m"] } 15 | rtt-target = { version = "0.3.1", features = ["cortex-m"] } 16 | systick-monotonic = "1.0.0" 17 | 18 | [dependencies.stm32f1xx-hal] 19 | version = "0.10.0" 20 | features = ["rt", "stm32f103", "medium"] 21 | 22 | # this lets you use `cargo fix`! 23 | [[bin]] 24 | name = "bluepill_blinky" 25 | test = false 26 | bench = false 27 | 28 | [profile.dev] 29 | opt-level = 1 30 | codegen-units = 16 31 | debug = true 32 | lto = false 33 | 34 | [profile.release] 35 | opt-level = "s" # optimize for size 36 | codegen-units = 1 # better optimizations 37 | debug = true # symbols are nice and they don't increase the size on Flash 38 | lto = true # better optimizations 39 | -------------------------------------------------------------------------------- /rtic_v1/stm32f1_bluepill_blinky/README.md: -------------------------------------------------------------------------------- 1 | # STM32F103 Bluepill RTIC Blink example 2 | 3 | Working example of simple LED blinking application for popular Bluepill boards based on the STM32F103C8 chip. Example uses schedule API and peripherials access. You will need `stlink v2` tool or other programmer to flash the board. 4 | 5 | ## How-to 6 | 7 | ### Terminal workflow 8 | 9 | Rust embedded relies heavily on `terminal workflow`, you will enter commands in the terminal. This can be strange at first, but this enables usage of great things like continious integration tools. 10 | 11 | For Mac OS X consider using `iTerm2` instead of Terminal application. 12 | For Windows consider using `powershell` (win + r -> powershell -> enter -> cd C:\examples\rtic_v5\bluepill_blinky) 13 | 14 | ### Build 15 | 16 | Run `cargo build` to compile the code. If you run it for the first time, it will take some time to download and compile dependencies. After that, you will see comething like: 17 | 18 | ```bash 19 | >cargo build 20 | Finished dev [optimized + debuginfo] target(s) in 0.10s 21 | ``` 22 | 23 | If you see warnings, feel free to ask for help in chat or issues of this repo. 24 | 25 | ### Connect the board 26 | 27 | You need to connect you bluepill board to ST-Link and connect pins: 28 | 29 | | BOARD | | ST-LINK | 30 | |-------|----|---------| 31 | | GND | -> | GND | 32 | | 3.3V | -> | 3.3V | 33 | | SWCLK | -> | SWCLK | 34 | | SWDIO | -> | SWDIO | 35 | 36 | Plug in ST-Link to USB port and wait it to initialize. 37 | 38 | ### Flashing and running 39 | 40 | Flashing with a standard STLink v2 is easy with `cargo-embed`: 41 | 42 | ```shell 43 | $ cargo install cargo-embed 44 | $ cargo embed --release 45 | ``` 46 | 47 | Please review the `.embed.toml` file to change your target IC among other options. 48 | -------------------------------------------------------------------------------- /rtic_v1/stm32f1_bluepill_blinky/memory.x: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | /* NOTE 1 K = 1 KiBi = 1024 bytes */ 4 | /* TODO Adjust these memory regions to match your device memory layout */ 5 | /* These values correspond to the LM3S6965, one of the few devices QEMU can emulate */ 6 | FLASH : ORIGIN = 0x08000000, LENGTH = 64K 7 | RAM : ORIGIN = 0x20000000, LENGTH = 20K 8 | } 9 | -------------------------------------------------------------------------------- /rtic_v1/stm32f1_bluepill_blinky/src/main.rs: -------------------------------------------------------------------------------- 1 | #![deny(unsafe_code)] 2 | #![deny(warnings)] 3 | #![no_main] 4 | #![no_std] 5 | 6 | use panic_rtt_target as _; 7 | use rtic::app; 8 | use rtt_target::{rprintln, rtt_init_print}; 9 | use stm32f1xx_hal::gpio::PinState; 10 | use stm32f1xx_hal::gpio::{gpioc::PC13, Output, PushPull}; 11 | use stm32f1xx_hal::prelude::*; 12 | use systick_monotonic::{fugit::Duration, Systick}; 13 | 14 | #[app(device = stm32f1xx_hal::pac, peripherals = true, dispatchers = [SPI1])] 15 | mod app { 16 | use super::*; 17 | 18 | #[shared] 19 | struct Shared {} 20 | 21 | #[local] 22 | struct Local { 23 | led: PC13>, 24 | state: bool, 25 | } 26 | 27 | #[monotonic(binds = SysTick, default = true)] 28 | type MonoTimer = Systick<1000>; 29 | 30 | #[init] 31 | fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { 32 | // Setup clocks 33 | let mut flash = cx.device.FLASH.constrain(); 34 | let rcc = cx.device.RCC.constrain(); 35 | 36 | let mono = Systick::new(cx.core.SYST, 36_000_000); 37 | 38 | rtt_init_print!(); 39 | rprintln!("init"); 40 | 41 | let _clocks = rcc 42 | .cfgr 43 | .use_hse(8.MHz()) 44 | .sysclk(36.MHz()) 45 | .pclk1(36.MHz()) 46 | .freeze(&mut flash.acr); 47 | 48 | // Setup LED 49 | let mut gpioc = cx.device.GPIOC.split(); 50 | let led = gpioc 51 | .pc13 52 | .into_push_pull_output_with_state(&mut gpioc.crh, PinState::Low); 53 | 54 | // Schedule the blinking task 55 | blink::spawn_after(Duration::::from_ticks(1000)).unwrap(); 56 | 57 | ( 58 | Shared {}, 59 | Local { led, state: false }, 60 | init::Monotonics(mono), 61 | ) 62 | } 63 | 64 | #[task(local = [led, state])] 65 | fn blink(cx: blink::Context) { 66 | rprintln!("blink"); 67 | if *cx.local.state { 68 | cx.local.led.set_high(); 69 | *cx.local.state = false; 70 | } else { 71 | cx.local.led.set_low(); 72 | *cx.local.state = true; 73 | } 74 | blink::spawn_after(Duration::::from_ticks(1000)).unwrap(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /rtic_v1/stm32f3_blinky/.cargo/config: -------------------------------------------------------------------------------- 1 | [target.thumbv7m-none-eabi] 2 | # uncomment this to make `cargo run` execute programs on QEMU 3 | # runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel" 4 | 5 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] 6 | # uncomment ONE of these three option to make `cargo run` start a GDB session 7 | # which option to pick depends on your system 8 | # runner = "arm-none-eabi-gdb -q -x openocd.gdb" 9 | # runner = "gdb-multiarch -q -x openocd.gdb" 10 | # runner = "gdb -q -x openocd.gdb" 11 | 12 | rustflags = [ 13 | # This is needed if your flash or ram addresses are not aligned to 0x10000 in memory.x 14 | # See https://github.com/rust-embedded/cortex-m-quickstart/pull/95 15 | "-C", "link-arg=--nmagic", 16 | 17 | # LLD (shipped with the Rust toolchain) is used as the default linker 18 | "-C", "link-arg=-Tlink.x", 19 | 20 | # if you run into problems with LLD switch to the GNU linker by commenting out 21 | # this line 22 | # "-C", "linker=arm-none-eabi-ld", 23 | 24 | # if you need to link to pre-compiled C libraries provided by a C toolchain 25 | # use GCC as the linker by commenting out both lines above and then 26 | # uncommenting the three lines below 27 | # "-C", "linker=arm-none-eabi-gcc", 28 | # "-C", "link-arg=-Wl,-Tlink.x", 29 | # "-C", "link-arg=-nostartfiles", 30 | ] 31 | 32 | [build] 33 | # Pick ONE of these compilation targets 34 | # target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+ 35 | target = "thumbv7m-none-eabi" # Cortex-M3 36 | # target = "thumbv7em-none-eabi" # Cortex-M4 and Cortex-M7 (no FPU) 37 | # target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU) 38 | # target = "thumbv8m.base-none-eabi" # Cortex-M23 39 | # target = "thumbv8m.main-none-eabi" # Cortex-M33 (no FPU) 40 | # target = "thumbv8m.main-none-eabihf" # Cortex-M33 (with FPU) 41 | -------------------------------------------------------------------------------- /rtic_v1/stm32f3_blinky/.gitignore: -------------------------------------------------------------------------------- 1 | **/*.rs.bk 2 | .#* 3 | .gdb_history 4 | 5 | target/ 6 | 7 | # editor files 8 | .vscode/* 9 | !.vscode/*.md 10 | !.vscode/*.svd 11 | !.vscode/launch.json 12 | !.vscode/tasks.json 13 | !.vscode/extensions.json -------------------------------------------------------------------------------- /rtic_v1/stm32f3_blinky/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["Simsys "] 3 | edition = "2021" 4 | readme = "README.md" 5 | name = "stm32f3-blinky" 6 | version = "0.1.0" 7 | 8 | [dependencies] 9 | embedded-hal = "1.0.0" 10 | cortex-m-rtic = "1.1.4" 11 | systick-monotonic = "1.0.1" 12 | panic-rtt-target = { version = "0.1.2", features = ["cortex-m"] } 13 | rtt-target = { version = "0.3.1", features = ["cortex-m"] } 14 | 15 | [dependencies.stm32f3xx-hal] 16 | features = ["stm32f303xc", "rt"] 17 | version = "0.10.0" 18 | 19 | # this lets you use `cargo fix`! 20 | [[bin]] 21 | name = "stm32f3-blinky" 22 | test = false 23 | bench = false 24 | 25 | [profile.dev] 26 | opt-level = 1 27 | codegen-units = 16 28 | debug = true 29 | lto = false 30 | 31 | [profile.release] 32 | opt-level = "s" # optimize for size 33 | codegen-units = 1 # better optimizations 34 | debug = true # symbols are nice and they don't increase the size on Flash 35 | lto = true # better optimizations 36 | -------------------------------------------------------------------------------- /rtic_v1/stm32f3_blinky/Embed.toml: -------------------------------------------------------------------------------- 1 | [default.general] 2 | chip = "stm32f303re" 3 | 4 | 5 | [default.rtt] 6 | enabled = true 7 | 8 | [default.gdb] 9 | enabled = false 10 | -------------------------------------------------------------------------------- /rtic_v1/stm32f3_blinky/memory.x: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | FLASH : ORIGIN = 0x08000000, LENGTH = 256K 4 | RAM : ORIGIN = 0x20000000, LENGTH = 40K 5 | } 6 | -------------------------------------------------------------------------------- /rtic_v1/stm32f3_blinky/readme.md: -------------------------------------------------------------------------------- 1 | # STM32F3 RTIC Blink example 2 | 3 | Working example of simple LED blinking application for STM32 F303 Nucleo-64 board based on the STM32F303RE chip. Example uses schedule API and peripherials access. This example is based on blue-pill blinky example. 4 | 5 | ## How-to 6 | 7 | ### Build 8 | 9 | Run `cargo build` to compile the code. If you run it for the first time, it will take some time to download and compile dependencies. After that, you will see comething like: 10 | 11 | ```bash 12 | $ cargo build 13 | ``` 14 | 15 | ### Setup environment, flash and run program 16 | 17 | In the [Discovery Book](https://rust-embedded.github.io/discovery) you find all needed informations to setup the environment, flash the controler and run the program. 18 | -------------------------------------------------------------------------------- /rtic_v1/stm32f3_blinky/src/main.rs: -------------------------------------------------------------------------------- 1 | #![deny(unsafe_code)] 2 | #![deny(warnings)] 3 | #![no_main] 4 | #![no_std] 5 | 6 | use panic_rtt_target as _; 7 | use rtic::app; 8 | use rtt_target::{rprintln, rtt_init_print}; 9 | use stm32f3xx_hal::gpio::{Output, PushPull, PA5}; 10 | use stm32f3xx_hal::prelude::*; 11 | use systick_monotonic::{fugit::Duration, Systick}; 12 | 13 | #[app(device = stm32f3xx_hal::pac, peripherals = true, dispatchers = [SPI1])] 14 | mod app { 15 | use super::*; 16 | 17 | #[shared] 18 | struct Shared {} 19 | 20 | #[local] 21 | struct Local { 22 | led: PA5>, 23 | state: bool, 24 | } 25 | 26 | #[monotonic(binds = SysTick, default = true)] 27 | type MonoTimer = Systick<1000>; 28 | 29 | #[init] 30 | fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { 31 | // Setup clocks 32 | let mut flash = cx.device.FLASH.constrain(); 33 | let mut rcc = cx.device.RCC.constrain(); 34 | 35 | let mono = Systick::new(cx.core.SYST, 36_000_000); 36 | 37 | rtt_init_print!(); 38 | rprintln!("init"); 39 | 40 | let _clocks = rcc 41 | .cfgr 42 | .use_hse(8.MHz()) 43 | .sysclk(36.MHz()) 44 | .pclk1(36.MHz()) 45 | .freeze(&mut flash.acr); 46 | 47 | // Setup LED 48 | let mut gpioa = cx.device.GPIOA.split(&mut rcc.ahb); 49 | let mut led = gpioa 50 | .pa5 51 | .into_push_pull_output(&mut gpioa.moder, &mut gpioa.otyper); 52 | led.set_high().unwrap(); 53 | 54 | // Schedule the blinking task 55 | blink::spawn_after(Duration::::from_ticks(1000)).unwrap(); 56 | 57 | ( 58 | Shared {}, 59 | Local { led, state: false }, 60 | init::Monotonics(mono), 61 | ) 62 | } 63 | 64 | #[task(local = [led, state])] 65 | fn blink(cx: blink::Context) { 66 | rprintln!("blink"); 67 | if *cx.local.state { 68 | cx.local.led.set_high().unwrap(); 69 | *cx.local.state = false; 70 | } else { 71 | cx.local.led.set_low().unwrap(); 72 | *cx.local.state = true; 73 | } 74 | blink::spawn_after(Duration::::from_ticks(1000)).unwrap(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /rtic_v1/stm32f411_edge_counter/.cargo/config: -------------------------------------------------------------------------------- 1 | 2 | [target.thumbv7em-none-eabihf] 3 | rustflags = [ 4 | "-C", "link-arg=-Tlink.x", 5 | ] 6 | 7 | [build] 8 | target = "thumbv7em-none-eabihf" 9 | 10 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] 11 | runner = "cargo embed --chip STM32F411CEUx " 12 | -------------------------------------------------------------------------------- /rtic_v1/stm32f411_edge_counter/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | 4 | -------------------------------------------------------------------------------- /rtic_v1/stm32f411_edge_counter/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "stm32f411-edge-counter" 3 | version = "0.1.0" 4 | authors = ["Rafael Bachmann , 27 | pin: PA0, 28 | } 29 | 30 | #[monotonic(binds = SysTick, default = true)] 31 | type Tonic = Systick<1000>; 32 | 33 | #[init] 34 | fn init(mut ctx: init::Context) -> (Shared, Local, init::Monotonics) { 35 | rtt_init_print!(); 36 | rprintln!("init"); 37 | 38 | let rcc = ctx.device.RCC.constrain(); 39 | let _clocks = rcc.cfgr.sysclk(48.MHz()).freeze(); 40 | 41 | let gpioc = ctx.device.GPIOC.split(); 42 | let led = gpioc.pc13.into_push_pull_output(); 43 | 44 | let gpioa = ctx.device.GPIOA.split(); 45 | let mut pin = gpioa.pa0.into_pull_up_input(); 46 | let mut sys_cfg = ctx.device.SYSCFG.constrain(); 47 | pin.make_interrupt_source(&mut sys_cfg); 48 | pin.enable_interrupt(&mut ctx.device.EXTI); 49 | pin.trigger_on_edge(&mut ctx.device.EXTI, Edge::Falling); 50 | 51 | let mono = Systick::new(ctx.core.SYST, 48_000_000); 52 | 53 | blink::spawn().ok(); 54 | 55 | (Shared {}, Local { pin, led }, init::Monotonics(mono)) 56 | } 57 | 58 | #[task(local = [led], priority = 4)] 59 | fn blink(ctx: blink::Context) { 60 | let count = COUNTER.swap(0, Ordering::SeqCst); 61 | rprintln!("{}", count); 62 | ctx.local.led.toggle(); 63 | blink::spawn_after(ExtU64::millis(1000)).ok(); 64 | } 65 | 66 | #[task(binds = EXTI0, local = [pin])] 67 | fn on_exti(ctx: on_exti::Context) { 68 | ctx.local.pin.clear_interrupt_pending_bit(); 69 | rprintln!("incrementing"); 70 | COUNTER.fetch_add(1, Ordering::SeqCst); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /rtic_v1/stm32f4_independent_watchdog/.cargo/config: -------------------------------------------------------------------------------- 1 | [target.thumbv7em-none-eabihf] 2 | runner = 'probe-run --chip STM32F401RE' 3 | rustflags = [ 4 | "-C", "link-arg=-Tlink.x", 5 | "-C", "link-arg=-Tdefmt.x", 6 | "-C", "linker=flip-link", 7 | ] 8 | 9 | [build] 10 | target = "thumbv7em-none-eabihf" 11 | 12 | [env] 13 | DEFMT_LOG = "info" 14 | -------------------------------------------------------------------------------- /rtic_v1/stm32f4_independent_watchdog/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | 3 | # IDEs 4 | .idea 5 | .vscode 6 | -------------------------------------------------------------------------------- /rtic_v1/stm32f4_independent_watchdog/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "stm32f4_independent_watchdog" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | cortex-m = { version = "0.7", features = ["critical-section-single-core"]} 8 | cortex-m-rtic = "1.1" 9 | 10 | stm32f4xx-hal = { version = "0.19", features = ["stm32f401", "rtic"] } 11 | 12 | panic-probe = { version = "0.3", features = ["print-defmt"] } 13 | 14 | fugit = "0.3" 15 | 16 | defmt = "0.3" 17 | defmt-rtt = "0.4" 18 | 19 | [profile.release] 20 | codegen-units = 1 21 | lto = true 22 | opt-level = 3 23 | -------------------------------------------------------------------------------- /rtic_v1/stm32f4_independent_watchdog/README.md: -------------------------------------------------------------------------------- 1 | # Independent Watchdog (IWDG) Example 2 | This example showcases how the IWDG can be used. The watchdog is set for 500ms and is fed by a software task every 100ms, 3 | if everything goes well. To showcase the working of the watchdog, a user button (connected to `PC13`) can be used to disable 4 | further feeding of the watchdog, leading to it starving and triggering a device reset. 5 | 6 | The example logs messages using [`defmt`](https://defmt.ferrous-systems.com/) and the logs will show a message when the 7 | button is pressed and another from the init function again, showing that the device has reset and is booting again. 8 | 9 | The example has been tested on a [ST Nucleo-F401RE](https://www.st.com/en/evaluation-tools/nucleo-f401re.html) development 10 | board but should work on any STM32F4xx family microcontroller as long as a button (pulled high by default) is connected 11 | on PC13 (or the code is adapted to an alternative port). 12 | 13 | ## Prerequisites 14 | 1. [Install Rust](https://www.rust-lang.org/tools/install) 15 | 1. Optional: ensure that the rust toolchain is up-to-date: `rustup update` 16 | 1. Install [`probe-run`](https://crates.io/crates/probe-run): `cargo install probe-run` 17 | 1. Install [`flip-link`](https://crates.io/crates/flip-link): `cargo install flip-link` 18 | * Note: `flip-link` is not strictly necessary for this example (it doesn't need 19 | stack protection), however it can be considered best practices to include it. 20 | 1. Install the cross-compile target: `rustup target add thumbv7em-none-eabihf` 21 | 1. Optional: install the LLVM tools: `rustup component add llvm-tools-preview` 22 | 1. Install the STLink drivers 23 | 24 | ## Build & Download to Board 25 | 1. Connect the board via USB 26 | 1. Optional: change your targeted platform in `Cargo.toml` and `.cargo/config` (it defaults to STM32F401RE) 27 | 1. Run `cargo run` 28 | 1. Enjoy your running program :) 29 | -------------------------------------------------------------------------------- /rtic_v1/stm32f4_independent_watchdog/memory.x: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | /* NOTE K = KiBi = 1024 bytes */ 4 | FLASH : ORIGIN = 0x08000000, LENGTH = 512K 5 | RAM : ORIGIN = 0x20000000, LENGTH = 96K 6 | } 7 | -------------------------------------------------------------------------------- /rtic_v1/stm32f4_independent_watchdog/src/main.rs: -------------------------------------------------------------------------------- 1 | //! Demonstrates the use of an independent watchdog (IWDG). 2 | //! The watchdog is activated and will reset the board if it isn't fed every 500ms. 3 | //! Pressing the button connected to PC13 will disable the watchdog feeding which will trigger 4 | //! a hardware reset. 5 | 6 | #![deny(warnings)] 7 | #![deny(unsafe_code)] 8 | #![no_main] 9 | #![no_std] 10 | 11 | use panic_probe as _; 12 | 13 | use defmt_rtt as _; 14 | 15 | #[rtic::app(device = stm32f4xx_hal::pac, dispatchers = [EXTI1])] 16 | mod app { 17 | use stm32f4xx_hal::{ 18 | gpio::{Edge, Input, PC13}, 19 | pac, 20 | prelude::*, 21 | timer::MonoTimerUs, 22 | watchdog::IndependentWatchdog, 23 | }; 24 | 25 | #[monotonic(binds = TIM2, default = true)] 26 | type MicrosecMono = MonoTimerUs; 27 | 28 | #[shared] 29 | struct Shared { 30 | do_feed_watchdog: bool, 31 | } 32 | 33 | #[local] 34 | struct Local { 35 | button: PC13, 36 | watchdog: IndependentWatchdog, 37 | } 38 | 39 | #[init] 40 | fn init(mut ctx: init::Context) -> (Shared, Local, init::Monotonics) { 41 | let mut syscfg = ctx.device.SYSCFG.constrain(); 42 | 43 | let rcc = ctx.device.RCC.constrain(); 44 | let clocks = rcc.cfgr.sysclk(48.MHz()).freeze(); 45 | 46 | let mono = ctx.device.TIM2.monotonic_us(&clocks); 47 | 48 | let gpioc = ctx.device.GPIOC.split(); 49 | 50 | let mut button = gpioc.pc13.into_pull_down_input(); 51 | button.make_interrupt_source(&mut syscfg); 52 | button.enable_interrupt(&mut ctx.device.EXTI); 53 | button.trigger_on_edge(&mut ctx.device.EXTI, Edge::Falling); 54 | 55 | let mut watchdog = IndependentWatchdog::new(ctx.device.IWDG); 56 | watchdog.start(500u32.millis()); 57 | feed_watchdog::spawn().ok(); 58 | 59 | defmt::info!("init done!"); 60 | 61 | ( 62 | Shared { 63 | do_feed_watchdog: true, 64 | }, 65 | Local { button, watchdog }, 66 | init::Monotonics(mono), 67 | ) 68 | } 69 | 70 | /// React on the button click and disable the watchdog. This will trigger a hardware reset. 71 | // see here for why this is EXTI15_10: https://github.com/stm32-rs/stm32f4xx-hal/blob/6d0c29233a4cd1f780b2fef3e47ef091ead6cf4a/src/gpio/exti.rs#L8-L23 72 | #[task(binds = EXTI15_10, local = [button], shared = [do_feed_watchdog])] 73 | fn button_click(mut ctx: button_click::Context) { 74 | ctx.local.button.clear_interrupt_pending_bit(); 75 | defmt::info!("button pressed => not feeding the watchdog anymore."); 76 | ctx.shared.do_feed_watchdog.lock(|do_feed_watchdog| { 77 | *do_feed_watchdog = false; 78 | }); 79 | } 80 | 81 | /// Feed the watchdog to avoid hardware reset. 82 | #[task(priority=1, local=[watchdog], shared=[do_feed_watchdog])] 83 | fn feed_watchdog(mut ctx: feed_watchdog::Context) { 84 | defmt::trace!("feeding the watchdog!"); 85 | ctx.local.watchdog.feed(); 86 | ctx.shared.do_feed_watchdog.lock(|do_feed_watchdog| { 87 | if *do_feed_watchdog { 88 | feed_watchdog::spawn_after(100.millis()).ok(); 89 | } 90 | }); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /rtic_v1/stm32f4_pwm_monitor/.cargo/config: -------------------------------------------------------------------------------- 1 | 2 | [target.thumbv7em-none-eabihf] 3 | rustflags = [ 4 | "-C", "link-arg=-Tlink.x", 5 | ] 6 | 7 | [build] 8 | target = "thumbv7em-none-eabihf" 9 | 10 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] 11 | runner = "cargo embed --chip STM32F446RETx " 12 | -------------------------------------------------------------------------------- /rtic_v1/stm32f4_pwm_monitor/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "stm32f4_pwm_input" 3 | version = "0.1.0" 4 | authors = ["Joshua Salzedo "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | cortex-m-rtic = "1.1.4" 11 | 12 | [dependencies.rtt-target] 13 | version = "0.3.1" 14 | features = ["cortex-m"] 15 | 16 | [dependencies.panic-rtt-target] 17 | version = "0.1.2" 18 | features = ["cortex-m"] 19 | 20 | [dependencies.stm32f4xx-hal] 21 | version = "0.20" 22 | features = ["stm32f446"] 23 | -------------------------------------------------------------------------------- /rtic_v1/stm32f4_pwm_monitor/memory.x: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | /* NOTE K = KiBi = 1024 bytes */ 4 | FLASH : ORIGIN = 0x08000000, LENGTH = 512K 5 | RAM : ORIGIN = 0x20000000, LENGTH = 128K 6 | } 7 | 8 | /* This is where the call stack will be allocated. */ 9 | /* The stack is of the full descending type. */ 10 | /* NOTE Do NOT modify `_stack_start` unless you know what you are doing */ 11 | _stack_start = ORIGIN(RAM) + LENGTH(RAM); 12 | -------------------------------------------------------------------------------- /rtic_v1/stm32f4_pwm_monitor/src/main.rs: -------------------------------------------------------------------------------- 1 | #![deny(unsafe_code)] 2 | #![no_main] 3 | #![no_std] 4 | #![allow(unused_imports)] 5 | 6 | use panic_rtt_target as _panic_handler; 7 | 8 | /* declare a submodule for handling tim8 interrupts */ 9 | mod tim8; 10 | 11 | /* declare the RTIC application itself */ 12 | #[rtic::app(device = stm32f4xx_hal::pac, peripherals = true)] 13 | mod app { 14 | 15 | /* bring dependencies into scope */ 16 | use rtt_target::{rprintln, rtt_init_print}; 17 | use stm32f4xx_hal::{pac::TIM8, prelude::*, timer::PwmInput, timer::Timer}; 18 | /// PWM input monitor type 19 | pub(crate) type PwmMonitor = PwmInput; 20 | 21 | /* resources shared across RTIC tasks */ 22 | #[shared] 23 | struct Shared { 24 | /// the last observed position of the turret 25 | last_observed_turret_position: f32, 26 | } 27 | 28 | /* resources local to specific RTIC tasks */ 29 | #[local] 30 | struct Local { 31 | monitor: PwmMonitor, 32 | } 33 | 34 | #[init] 35 | fn init(ctx: init::Context) -> (Shared, Local, init::Monotonics) { 36 | // Enable RTT logging 37 | rtt_init_print!(); 38 | rprintln!("hello, world!"); 39 | // retrieve the RCC register, which is needed to obtain a handle to the clocks 40 | let rcc = ctx.device.RCC.constrain(); 41 | // then retreive the clocks, so we can configure timers later on 42 | let clocks = rcc.cfgr.freeze(); 43 | 44 | // obtain a reference to the GPIOC register block, so we can configure pins on the PC bus. 45 | let gpioc = ctx.device.GPIOC.split(); 46 | 47 | // Configure one of TIM8's CH1 pins, so that its attached to the peripheral. 48 | // We need to do this since the pins are multiplexed across multiple peripherals 49 | let tim8_cc1 = gpioc.pc6.into_alternate(); 50 | 51 | // Configure TIM8 into PWM input mode. 52 | // This requires a "best guess" of the input frequency in order to be accurate. 53 | // Note: as a side-effect TIM8's interrupt is enabled and fires whenever a capture-compare 54 | // cycle is complete. See the reference manual's paragraphs on PWM Input. 55 | let monitor = Timer::new(ctx.device.TIM8, &clocks).pwm_input(240.Hz(), tim8_cc1); 56 | 57 | // lastly return the shared and local resources, as per RTIC's spec. 58 | ( 59 | Shared { 60 | last_observed_turret_position: 0.0, 61 | }, 62 | Local { monitor }, 63 | init::Monotonics(), 64 | ) 65 | } 66 | 67 | /* bring tim8's interrupt handler into scope */ 68 | use crate::tim8::tim8_cc; 69 | 70 | // RTIC docs specify we can modularize the code by using these `extern` blocks. 71 | // This allows us to specify the tasks in other modules and still work within 72 | // RTIC's infrastructure. 73 | extern "Rust" { 74 | #[task(binds=TIM8_CC, local=[monitor], shared=[last_observed_turret_position])] 75 | fn tim8_cc(context: tim8_cc::Context); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /rtic_v1/stm32f4_pwm_monitor/src/tim8.rs: -------------------------------------------------------------------------------- 1 | use crate::app::{tim8_cc, PwmMonitor}; 2 | use rtic::mutex_prelude::*; 3 | 4 | pub(crate) fn tim8_cc(mut context: tim8_cc::Context) { 5 | let monitor: &PwmMonitor = context.local.monitor; 6 | 7 | // First, check that this interrupt is a valid capture, since this interrupt 8 | // fires twice per period. If not, bail out to speed up the interrupt. 9 | if !monitor.is_valid_capture() { 10 | return; 11 | } 12 | 13 | // observe duty cycle 14 | // This is done up here to minimize time in the critical section. 15 | let observation = monitor.get_duty_cycle(); 16 | 17 | // entering critical section 18 | context.shared.last_observed_turret_position.lock(|guard| { 19 | // update the shared state 20 | *guard = observation; 21 | }); 22 | // leaving critical section 23 | } 24 | -------------------------------------------------------------------------------- /rtic_v1/stm32l0_monotonic/.cargo/config: -------------------------------------------------------------------------------- 1 | [target.thumbv7m-none-eabi] 2 | # uncomment this to make `cargo run` execute programs on QEMU 3 | # runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel" 4 | 5 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] 6 | # uncomment ONE of these three option to make `cargo run` start a GDB session 7 | # which option to pick depends on your system 8 | # runner = "arm-none-eabi-gdb -q -x jlink.gdb" 9 | # runner = "arm-none-eabi-gdb -q -x openocd.gdb" 10 | # runner = "gdb-multiarch -q -x openocd.gdb" 11 | # runner = "gdb -q -x openocd.gdb" 12 | 13 | rustflags = [ 14 | # LLD (shipped with the Rust toolchain) is used as the default linker 15 | "-C", "link-arg=-Tlink.x", 16 | 17 | # if you run into problems with LLD switch to the GNU linker by commenting out 18 | # this line 19 | # "-C", "linker=arm-none-eabi-ld", 20 | 21 | # if you need to link to pre-compiled C libraries provided by a C toolchain 22 | # use GCC as the linker by commenting out both lines above and then 23 | # uncommenting the three lines below 24 | # "-C", "linker=arm-none-eabi-gcc", 25 | # "-C", "link-arg=-Wl,-Tlink.x", 26 | # "-C", "link-arg=-nostartfiles", 27 | 28 | # uncomment for unchecked wrapping arithmetics also in dev mode 29 | # "-Z", "force-overflow-checks=off", 30 | ] 31 | 32 | [build] 33 | # Pick ONE of these compilation targets 34 | target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+ 35 | # target = "thumbv7m-none-eabi" # Cortex-M3 36 | # target = "thumbv7em-none-eabi" # Cortex-M4 and Cortex-M7 (no FPU) 37 | # target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU) 38 | -------------------------------------------------------------------------------- /rtic_v1/stm32l0_monotonic/.embed.toml: -------------------------------------------------------------------------------- 1 | # Refer to https://github.com/probe-rs/cargo-embed/blob/master/src/config/default.toml 2 | # for the comprehensive list of options 3 | 4 | [default.general] 5 | chip = "STM32L071" 6 | 7 | [default.rtt] 8 | enabled = true 9 | show_timestamps = true 10 | 11 | [default.gdb] 12 | # Whether or not a GDB server should be opened after flashing. 13 | # This is exclusive and cannot be used with RTT at the moment. 14 | enabled = false 15 | # The connection string in host:port format wher the GDB server will open a socket. 16 | # gdb_connection_string 17 | -------------------------------------------------------------------------------- /rtic_v1/stm32l0_monotonic/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /rtic_v1/stm32l0_monotonic/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "stm32l0_monotonic" 3 | categories = ["embedded", "no-std"] 4 | authors = ["Danilo Bargen "] 5 | description = "Example Monotonic trait" 6 | keywords = ["arm", "cortex-m"] 7 | license = "MIT OR Apache-2.0" 8 | version = "0.1.0" 9 | edition = "2021" 10 | 11 | [dependencies] 12 | cortex-m-rtic = "1.0.0" 13 | systick-monotonic = "1.0.1" 14 | panic-rtt-target = { version = "0.1.2", features = ["cortex-m"] } 15 | rtt-target = { version = "0.3.1", features = ["cortex-m"] } 16 | stm32l0xx-hal = { version = "0.10.0", features = ["rt", "mcu-STM32L031K6Tx"] } 17 | 18 | # this lets you use `cargo fix`! 19 | [[bin]] 20 | name = "stm32l0_monotonic" 21 | test = false 22 | bench = false 23 | 24 | [profile.dev] 25 | opt-level = 1 26 | codegen-units = 16 27 | debug = true 28 | lto = false 29 | 30 | [profile.release] 31 | opt-level = "s" # optimize for size 32 | codegen-units = 1 # better optimizations 33 | debug = true # symbols are nice and they don't increase the size on Flash 34 | lto = true # better optimizations 35 | -------------------------------------------------------------------------------- /rtic_v1/stm32l0_monotonic/README.md: -------------------------------------------------------------------------------- 1 | # STM32L0 Monotonic 2 | 3 | In this example we show the use of a custom `rtic::Monotonic` implementation 4 | which uses a 16 bit timer of the `STM32L0` MCU. 5 | 6 | ## Flashing and running 7 | 8 | Flashing with a standard STLink v2 is easy with `cargo-embed`: 9 | 10 | ```shell 11 | $ cargo install cargo-embed 12 | $ cargo embed --release 13 | ``` 14 | 15 | Please review the `.embed.toml` file to change your target IC among other options. 16 | -------------------------------------------------------------------------------- /rtic_v1/stm32l0_monotonic/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | 4 | use core::fmt::Write; 5 | 6 | use panic_rtt_target as _; 7 | use rtt_target::{rprintln, rtt_init_print}; 8 | 9 | use rtic::app; 10 | use stm32l0xx_hal::{pac, prelude::*, rcc::Config, serial}; 11 | use systick_monotonic::{ 12 | fugit::{ExtU32, MillisDurationU64}, 13 | Systick, 14 | }; 15 | 16 | const INTERVAL_MS: u32 = 500; 17 | 18 | #[app( 19 | device = stm32l0xx_hal::pac, 20 | peripherals = true, 21 | dispatchers = [SPI1], 22 | )] 23 | mod app { 24 | use super::*; 25 | 26 | // Setting this monotonic as the default 27 | // enables the shorthand fizzbuzz::spawn_after 28 | // without having to specify `Mono` as fizzbuzz::Mono::spawn_after( 29 | #[monotonic(binds = SysTick, default = true)] 30 | type Tonic = Systick<1000>; 31 | 32 | #[local] 33 | struct Local { 34 | /// Serial debug output 35 | serial: serial::Serial, 36 | 37 | /// Timer interval 38 | interval: MillisDurationU64, 39 | 40 | /// Counter 41 | counter: usize, 42 | } 43 | 44 | #[shared] 45 | struct Shared {} 46 | 47 | #[init] 48 | fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { 49 | // Get peripherals 50 | let dp: pac::Peripherals = cx.device; 51 | 52 | // Clock configuration. Use HSI at 16 MHz. 53 | let mut rcc = dp.RCC.freeze(Config::hsi16()); 54 | 55 | rtt_init_print!(); 56 | rprintln!("RTT init"); 57 | 58 | // GPIO 59 | let gpiob = dp.GPIOB.split(&mut rcc); 60 | 61 | // Initialize serial port(s) 62 | let mut serial = serial::Serial::usart2( 63 | dp.USART2, 64 | gpiob.pb6.into_floating_input(), 65 | gpiob.pb7.into_floating_input(), 66 | serial::Config { 67 | baudrate: 57_600.Bd(), 68 | wordlength: serial::WordLength::DataBits8, 69 | parity: serial::Parity::ParityNone, 70 | stopbits: serial::StopBits::STOP1, 71 | }, 72 | &mut rcc, 73 | ) 74 | .unwrap(); 75 | 76 | // Initialize the timer 77 | writeln!(serial, "Initialize monotonic timer using SysTick at 1kHz").unwrap(); 78 | 79 | let mono = Systick::new(cx.core.SYST, 16_000_000); 80 | 81 | let interval: MillisDurationU64 = INTERVAL_MS.millis().into(); 82 | 83 | writeln!( 84 | serial, 85 | "Schedule task every {} ms / {} ticks", 86 | interval, 87 | interval.ticks(), 88 | ) 89 | .unwrap(); 90 | 91 | // Spawn task "fizzbuzz" 92 | let _ = fizzbuzz::spawn(); 93 | 94 | writeln!(serial, "== Init done ==").unwrap(); 95 | 96 | let local = Local { 97 | serial, 98 | interval, 99 | counter: 1, 100 | }; 101 | 102 | (Shared {}, local, init::Monotonics(mono)) 103 | } 104 | 105 | #[task(local = [serial, interval, counter])] 106 | fn fizzbuzz(cx: fizzbuzz::Context) { 107 | rprintln!("fizzbuzz!"); 108 | // Access resources 109 | let serial = cx.local.serial; 110 | let now = monotonics::now(); 111 | let counter = cx.local.counter; 112 | let interval = cx.local.interval; 113 | 114 | // Fancy fizzbuzz implementation 115 | match (*counter % 3 == 0, *counter % 5 == 0) { 116 | (true, true) => { 117 | rprintln!("fizzbuzz (now={:05})", now); 118 | writeln!(serial, "fizzbuzz (now={:05})", now).unwrap(); 119 | } 120 | (true, false) => { 121 | rprintln!(" fizz (now={:05})", now); 122 | writeln!(serial, " fizz (now={:05})", now).unwrap(); 123 | } 124 | (false, true) => { 125 | rprintln!(" buzz (now={:05})", now); 126 | writeln!(serial, " buzz (now={:05})", now).unwrap(); 127 | } 128 | _ => { 129 | rprintln!("{:08} (now={:05})", *counter, now); 130 | writeln!(serial, "{:08} (now={:05})", *counter, now).unwrap(); 131 | } 132 | } 133 | 134 | // Increment counter 135 | *counter += 1; 136 | 137 | // Re-schedule 138 | let _ = fizzbuzz::spawn_after(*interval); 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /rtic_v1/stm32l4_heartbeat/.cargo/config: -------------------------------------------------------------------------------- 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] 2 | # uncomment ONE of these three option to make `cargo run` start a GDB session 3 | # which option to pick depends on your system 4 | # runner = "arm-none-eabi-gdb -q -x jlink.gdb" 5 | # runner = "arm-none-eabi-gdb -q -x openocd.gdb" 6 | runner = "gdb-multiarch -q -x openocd.gdb" 7 | # runner = "gdb -q -x openocd.gdb" 8 | 9 | rustflags = [ 10 | # LLD (shipped with the Rust toolchain) is used as the default linker 11 | "-C", "link-arg=-Tlink.x", 12 | 13 | # if you run into problems with LLD switch to the GNU linker by commenting out 14 | # this line 15 | # "-C", "linker=arm-none-eabi-ld", 16 | 17 | # if you need to link to pre-compiled C libraries provided by a C toolchain 18 | # use GCC as the linker by commenting out both lines above and then 19 | # uncommenting the three lines below 20 | # "-C", "linker=arm-none-eabi-gcc", 21 | # "-C", "link-arg=-Wl,-Tlink.x", 22 | # "-C", "link-arg=-nostartfiles", 23 | 24 | # uncomment for unchecked wrapping arithmetics also in dev mode 25 | # "-Z", "force-overflow-checks=off", 26 | ] 27 | 28 | [build] 29 | # Pick ONE of these compilation targets 30 | # target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+ 31 | # target = "thumbv7m-none-eabi" # Cortex-M3 32 | # target = "thumbv7em-none-eabi" # Cortex-M4 and Cortex-M7 (no FPU) 33 | target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU) 34 | -------------------------------------------------------------------------------- /rtic_v1/stm32l4_heartbeat/.embed.toml: -------------------------------------------------------------------------------- 1 | # Refer to https://github.com/probe-rs/cargo-embed/blob/master/src/config/default.toml 2 | # for the comprehensive list of options 3 | 4 | [default.general] 5 | chip = "STM32L412" 6 | 7 | [default.rtt] 8 | enabled = true 9 | show_timestamps = true 10 | 11 | [default.gdb] 12 | # Whether or not a GDB server should be opened after flashing. 13 | # This is exclusive and cannot be used with RTT at the moment. 14 | enabled = false 15 | # The connection string in host:port format wher the GDB server will open a socket. 16 | # gdb_connection_string 17 | -------------------------------------------------------------------------------- /rtic_v1/stm32l4_heartbeat/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /rtic_v1/stm32l4_heartbeat/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "stm32l4_heartbeat" 3 | categories = ["embedded", "no-std"] 4 | authors = [ 5 | "arrowcircle", 6 | "Emil Fresk ", 7 | "Domenico Andreoli ", 8 | ] 9 | description = "Heartbeat for stm32l4xx" 10 | keywords = ["arm", "cortex-m"] 11 | license = "MIT OR Apache-2.0" 12 | version = "0.1.0" 13 | edition = "2021" 14 | 15 | [dependencies] 16 | embedded-hal = "1.0.0" 17 | cortex-m-rtic = "1.0.0" 18 | stm32l4xx-hal = { version = "0.7.1", features = ["rt", "stm32l412"] } 19 | heapless = "0.8.0" 20 | systick-monotonic = "1.0.0" 21 | panic-rtt-target = { version = "0.1.2", features = ["cortex-m"] } 22 | rtt-target = { version = "0.3.1", features = ["cortex-m"] } 23 | 24 | # this lets you use `cargo fix`! 25 | [[bin]] 26 | name = "stm32l4_heartbeat" 27 | test = false 28 | bench = false 29 | 30 | [profile.dev] 31 | opt-level = 1 32 | codegen-units = 16 33 | debug = true 34 | lto = false 35 | 36 | [profile.release] 37 | opt-level = "s" # optimize for size 38 | codegen-units = 1 # better optimizations 39 | debug = true # symbols are nice and they don't increase the size on Flash 40 | lto = true # better optimizations 41 | -------------------------------------------------------------------------------- /rtic_v1/stm32l4_heartbeat/memory.x: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | /* NOTE 1 K = 1 KiBi = 1024 bytes */ 4 | /* TODO Adjust these memory regions to match your device memory layout */ 5 | /* These values correspond to the LM3S6965, one of the few devices QEMU can emulate */ 6 | FLASH : ORIGIN = 0x08000000, LENGTH = 64K 7 | RAM : ORIGIN = 0x20000000, LENGTH = 20K 8 | } 9 | -------------------------------------------------------------------------------- /rtic_v1/stm32l4_heartbeat/src/main.rs: -------------------------------------------------------------------------------- 1 | #![deny(unsafe_code)] 2 | #![deny(warnings)] 3 | #![no_main] 4 | #![no_std] 5 | 6 | use panic_rtt_target as _; 7 | use rtic::app; 8 | use rtt_target::{rprintln, rtt_init_print}; 9 | use stm32l4xx_hal::gpio::{gpiob::PB3, Output, PushPull}; 10 | use stm32l4xx_hal::prelude::*; 11 | use systick_monotonic::{fugit::Duration, Systick}; 12 | 13 | #[app(device = stm32l4xx_hal::pac, dispatchers = [SPI3])] 14 | mod app { 15 | use super::*; 16 | 17 | #[shared] 18 | struct Shared {} 19 | 20 | #[local] 21 | struct Local { 22 | led: PB3>, 23 | intervals: [u32; 6], 24 | } 25 | 26 | #[monotonic(binds = SysTick, default = true)] 27 | type MonoTimer = Systick<1000>; 28 | 29 | #[init] 30 | fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { 31 | // Setup clocks 32 | let mut flash = cx.device.FLASH.constrain(); 33 | let mut rcc = cx.device.RCC.constrain(); 34 | let mut pwr = cx.device.PWR.constrain(&mut rcc.apb1r1); 35 | let mono = Systick::new(cx.core.SYST, 72_000_000); 36 | 37 | rtt_init_print!(); 38 | rprintln!("init"); 39 | 40 | let _clocks = rcc.cfgr.sysclk(72.MHz()).freeze(&mut flash.acr, &mut pwr); 41 | 42 | // Setup LED 43 | let mut gpiob = cx.device.GPIOB.split(&mut rcc.ahb2); 44 | let mut led = gpiob 45 | .pb3 46 | .into_push_pull_output(&mut gpiob.moder, &mut gpiob.otyper); 47 | led.set_low(); 48 | 49 | // Simple heart beat LED on/off sequence 50 | let intervals: [u32; 6] = [ 51 | 30, // P Wave 52 | 40, // PR Segment 53 | 120, // QRS Complex 54 | 30, // ST Segment 55 | 60, // T Wave 56 | 720, // Rest 57 | ]; 58 | 59 | // Schedule the blinking task 60 | blink::spawn(0).unwrap(); 61 | 62 | (Shared {}, Local { led, intervals }, init::Monotonics(mono)) 63 | } 64 | 65 | #[idle] 66 | fn idle(_: idle::Context) -> ! { 67 | loop { 68 | core::hint::spin_loop(); 69 | } 70 | } 71 | 72 | #[task(local = [led, intervals])] 73 | fn blink(cx: blink::Context, state: usize) { 74 | rprintln!("blink"); 75 | let duration = cx.local.intervals[state]; 76 | let next_state = (state + 1) % cx.local.intervals.len(); 77 | 78 | cx.local.led.toggle(); 79 | 80 | let _ = blink::spawn_after( 81 | Duration::::from_ticks(duration as u64), 82 | next_state, 83 | ); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /update_dependabot_config.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | cat < .github/dependabot.yml 3 | # file automatically generated using update_dependabot.sh, re-run the script to update this file! 4 | version: 2 5 | updates: 6 | - package-ecosystem: "github-actions" 7 | directory: "/" 8 | schedule: 9 | interval: "weekly" 10 | EOF 11 | 12 | export LC_ALL=C 13 | for fld in $(find . -type f -name Cargo.toml | sort | sed 's#/Cargo.toml##' | sed 's#./#/#') ; do 14 | cat <> .github/dependabot.yml 15 | - package-ecosystem: "cargo" 16 | directory: "${fld}" 17 | schedule: 18 | interval: "weekly" 19 | rebase-strategy: "disabled" 20 | EOF 21 | done 22 | --------------------------------------------------------------------------------