├── .cargo └── config.toml ├── .gdbinit ├── .github ├── bors.toml ├── dependabot.yml └── workflows │ └── ci.yml ├── .gitignore ├── .vscode └── settings.json ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Cargo.ci.toml ├── Cargo.example.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── examples ├── .cargo │ └── config.toml ├── README.md ├── blinky-button-demo │ ├── Cargo.toml │ ├── Embed.toml │ ├── README.md │ └── src │ │ └── main.rs ├── ccm-demo │ ├── Cargo.toml │ ├── Embed.toml │ ├── README.md │ └── src │ │ ├── main.rs │ │ └── stopwatch.rs ├── comp-demo │ ├── Cargo.toml │ ├── Embed.toml │ ├── README.md │ └── src │ │ └── main.rs ├── ecb-demo │ ├── Cargo.toml │ ├── Embed.toml │ ├── README.md │ └── src │ │ └── main.rs ├── gpiote-demo │ ├── Cargo.toml │ ├── Embed.toml │ ├── README.md │ └── src │ │ └── main.rs ├── hello-world │ ├── Cargo.toml │ ├── Embed.toml │ └── src │ │ └── main.rs ├── i2s-controller-demo │ ├── Cargo.toml │ ├── Embed.toml │ ├── README.md │ └── src │ │ └── main.rs ├── i2s-peripheral-demo │ ├── Cargo.toml │ ├── Embed.toml │ ├── README.md │ └── src │ │ └── main.rs ├── lpcomp-demo │ ├── Cargo.toml │ ├── Embed.toml │ ├── README.md │ └── src │ │ └── main.rs ├── monotonic-blinky │ ├── .cargo │ │ └── config.toml │ ├── .gitignore │ ├── Cargo.toml │ ├── Embed.toml │ ├── README.md │ └── src │ │ ├── rtc.rs │ │ └── timer.rs ├── nvmc-demo │ ├── Cargo.toml │ ├── Embed.toml │ ├── build.rs │ ├── memory.x │ └── src │ │ └── main.rs ├── ppi-demo │ ├── Cargo.toml │ ├── Embed.toml │ ├── README.md │ └── src │ │ └── main.rs ├── pwm-blinky-demo │ ├── Cargo.toml │ ├── Embed.toml │ ├── build.rs │ ├── memory.x │ └── src │ │ └── main.rs ├── pwm-demo │ ├── Cargo.toml │ ├── Embed.toml │ ├── README.md │ └── src │ │ └── main.rs ├── qdec-demo │ ├── Cargo.toml │ ├── Embed.toml │ ├── README.md │ └── src │ │ └── main.rs ├── rtc-demo │ ├── Cargo.toml │ ├── Embed.toml │ ├── README.md │ └── src │ │ └── main.rs ├── rtic-demo │ ├── .cargo │ │ └── config.toml │ ├── .gdbinit │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── spi-demo │ ├── .cargo │ │ └── config.toml │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── spis-demo │ ├── Cargo.toml │ ├── Embed.toml │ ├── README.md │ └── src │ │ └── main.rs ├── twi-ssd1306 │ ├── .cargo │ │ └── config.toml │ ├── .gdbinit │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── twim-demo │ ├── Cargo.toml │ ├── Embed.toml │ ├── README.md │ └── src │ │ └── main.rs ├── twis-demo │ ├── Cargo.toml │ ├── Embed.toml │ ├── README.md │ └── src │ │ └── main.rs ├── twis-dma-demo │ ├── Cargo.toml │ ├── Embed.toml │ └── src │ │ └── main.rs ├── usb │ ├── .gdbinit │ ├── Cargo.toml │ ├── Embed.toml │ ├── README.md │ └── src │ │ └── bin │ │ ├── serial.rs │ │ └── test_class.rs └── wdt-demo │ ├── Cargo.toml │ ├── Embed.toml │ ├── README.md │ └── src │ └── main.rs ├── nrf-hal-common ├── Cargo.toml ├── build.rs └── src │ ├── adc.rs │ ├── ccm.rs │ ├── clocks.rs │ ├── comp.rs │ ├── delay.rs │ ├── ecb.rs │ ├── gpio.rs │ ├── gpiote.rs │ ├── i2s.rs │ ├── ieee802154.rs │ ├── lib.rs │ ├── lpcomp.rs │ ├── monotonic.rs │ ├── nvmc.rs │ ├── ppi │ ├── event_nrf51.rs │ ├── event_nrf52805.rs │ ├── event_nrf52810.rs │ ├── event_nrf52811.rs │ ├── event_nrf52832.rs │ ├── event_nrf52833.rs │ ├── event_nrf52840.rs │ ├── mod.rs │ ├── task_nrf51.rs │ ├── task_nrf52805.rs │ ├── task_nrf52810.rs │ ├── task_nrf52811.rs │ ├── task_nrf52832.rs │ ├── task_nrf52833.rs │ └── task_nrf52840.rs │ ├── pwm.rs │ ├── qdec.rs │ ├── rng.rs │ ├── rtc.rs │ ├── saadc.rs │ ├── spi.rs │ ├── spim.rs │ ├── spis.rs │ ├── temp.rs │ ├── time.rs │ ├── timer.rs │ ├── twi.rs │ ├── twim.rs │ ├── twis.rs │ ├── uart.rs │ ├── uarte.rs │ ├── uicr.rs │ ├── usbd.rs │ └── wdt.rs ├── nrf51-hal ├── Cargo.toml ├── build.rs └── src │ └── lib.rs ├── nrf52805-hal ├── Cargo.toml ├── build.rs ├── memory.x └── src │ └── lib.rs ├── nrf52810-hal ├── Cargo.toml ├── build.rs ├── memory.x └── src │ └── lib.rs ├── nrf52811-hal ├── Cargo.toml ├── build.rs ├── memory.x └── src │ └── lib.rs ├── nrf52832-hal ├── Cargo.toml ├── build.rs └── src │ └── lib.rs ├── nrf52833-hal ├── Cargo.toml ├── build.rs ├── memory.x └── src │ └── lib.rs ├── nrf52840-hal-tests ├── .cargo │ └── config.toml ├── .gitignore ├── Cargo.toml ├── README.md ├── build.rs ├── memory.x └── tests │ ├── gpio-input-floating.rs │ ├── gpio-input-pulled.rs │ ├── gpio-output-open-drain-io.rs │ ├── gpio-output-open-drain.rs │ ├── gpio-output-push-pull.rs │ ├── nvmc.rs │ └── serial.rs ├── nrf52840-hal ├── Cargo.toml ├── build.rs ├── memory.x └── src │ └── lib.rs ├── nrf5340-app-hal ├── Cargo.toml ├── README.md ├── build.rs ├── memory.x └── src │ └── lib.rs ├── nrf5340-net-hal ├── Cargo.toml ├── build.rs ├── memory.x └── src │ └── lib.rs ├── nrf9160-hal ├── Cargo.toml ├── README.md ├── build.rs ├── memory.x └── src │ └── lib.rs └── xtask ├── Cargo.toml ├── src ├── lib.rs └── main.rs └── tests └── ci.rs /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [alias] 2 | xtask = "run -p xtask --" 3 | -------------------------------------------------------------------------------- /.gdbinit: -------------------------------------------------------------------------------- 1 | # print demangled symbols by default 2 | set print asm-demangle on 3 | 4 | # JLink 5 | target extended-remote :2331 6 | monitor flash breakpoints 1 7 | # allow hprints to show up in gdb 8 | monitor semihosting enable 9 | monitor semihosting IOClient 3 10 | 11 | monitor reset 12 | load 13 | 14 | # OpenOCD 15 | #target extended-remote :3333 16 | #monitor arm semihosting enable 17 | # send captured ITM to the file itm.fifo 18 | # (the microcontroller SWO pin must be connected to the programmer SWO pin) 19 | # 8000000 must match the core clock frequency 20 | # monitor tpiu config internal itm.fifo uart off 8000000 21 | # OR: make the microcontroller SWO pin output compatible with UART (8N1) 22 | # 2000000 is the frequency of the SWO pin 23 | # monitor tpiu config external uart off 8000000 2000000 24 | # enable ITM port 0 25 | # monitor itm port 0 on 26 | 27 | #load 28 | #step 29 | -------------------------------------------------------------------------------- /.github/bors.toml: -------------------------------------------------------------------------------- 1 | status = ["ci"] 2 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [ master, staging, trying ] 6 | pull_request: 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | timeout-minutes: 30 12 | continue-on-error: ${{ matrix.rust_version == 'nightly' }} 13 | 14 | steps: 15 | - uses: actions/checkout@v4 16 | - name: Install Rust stable 17 | uses: actions-rs/toolchain@v1 18 | with: 19 | toolchain: stable 20 | profile: minimal 21 | components: rustfmt 22 | - name: Install Rust 23 | uses: actions-rs/toolchain@v1 24 | with: 25 | toolchain: ${{ matrix.rust_version }} 26 | profile: minimal 27 | override: true 28 | - name: Install Arm targets 29 | run: > 30 | rustup target add 31 | thumbv6m-none-eabi 32 | thumbv7em-none-eabi 33 | thumbv7em-none-eabihf 34 | thumbv8m.main-none-eabi 35 | - name: Build Crates 36 | run: mv Cargo.ci.toml Cargo.toml && cargo test 37 | env: 38 | RUSTFLAGS: ${{ matrix.rustflags }} 39 | 40 | strategy: 41 | matrix: 42 | rust_version: [beta, nightly] 43 | include: 44 | - rust_version: stable 45 | rustflags: --deny warnings 46 | 47 | format: 48 | name: Format 49 | runs-on: ubuntu-latest 50 | steps: 51 | - uses: actions/checkout@v4 52 | - name: Copy Cargo.toml 53 | run: cp Cargo.ci.toml Cargo.toml 54 | - name: Format Rust code 55 | run: cargo fmt --all -- --check 56 | 57 | ci: 58 | if: ${{ success() }} 59 | # all new jobs must be added to this list 60 | needs: [build, format] 61 | runs-on: ubuntu-latest 62 | steps: 63 | - name: CI succeeded 64 | run: exit 0 65 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | .gdb_history 3 | [._]*.sw[a-p] 4 | **/*.rs.bk 5 | Cargo.lock 6 | /Cargo.toml 7 | /Cargo.my.toml 8 | 9 | # Created by https://www.gitignore.io/api/intellij+all 10 | 11 | ### Intellij+all ### 12 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 13 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 14 | 15 | # User-specific stuff 16 | .idea/**/workspace.xml 17 | .idea/**/tasks.xml 18 | .idea/**/usage.statistics.xml 19 | .idea/**/dictionaries 20 | .idea/**/shelf 21 | 22 | # Sensitive or high-churn files 23 | .idea/**/dataSources/ 24 | .idea/**/dataSources.ids 25 | .idea/**/dataSources.local.xml 26 | .idea/**/sqlDataSources.xml 27 | .idea/**/dynamic.xml 28 | .idea/**/uiDesigner.xml 29 | .idea/**/dbnavigator.xml 30 | 31 | # Gradle 32 | .idea/**/gradle.xml 33 | .idea/**/libraries 34 | 35 | # Gradle and Maven with auto-import 36 | # When using Gradle or Maven with auto-import, you should exclude module files, 37 | # since they will be recreated, and may cause churn. Uncomment if using 38 | # auto-import. 39 | # .idea/modules.xml 40 | # .idea/*.iml 41 | # .idea/modules 42 | 43 | # CMake 44 | cmake-build-*/ 45 | 46 | # Mongo Explorer plugin 47 | .idea/**/mongoSettings.xml 48 | 49 | # File-based project format 50 | *.iws 51 | 52 | # IntelliJ 53 | out/ 54 | 55 | # mpeltonen/sbt-idea plugin 56 | .idea_modules/ 57 | 58 | # JIRA plugin 59 | atlassian-ide-plugin.xml 60 | 61 | # Cursive Clojure plugin 62 | .idea/replstate.xml 63 | 64 | # Crashlytics plugin (for Android Studio and IntelliJ) 65 | com_crashlytics_export_strings.xml 66 | crashlytics.properties 67 | crashlytics-build.properties 68 | fabric.properties 69 | 70 | # Editor-based Rest Client 71 | .idea/httpRequests 72 | 73 | ### Intellij+all Patch ### 74 | # Ignores the whole .idea folder and all .iml files 75 | # See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 76 | 77 | .idea/ 78 | 79 | # Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 80 | 81 | *.iml 82 | modules.xml 83 | .idea/misc.xml 84 | *.ipr 85 | 86 | 87 | # End of https://www.gitignore.io/api/intellij+all 88 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "rust-analyzer.cargo.target": "thumbv7em-none-eabi", 3 | "rust-analyzer.checkOnSave.allTargets": false, 4 | "rust-analyzer.cargo.allFeatures": false, 5 | } 6 | -------------------------------------------------------------------------------- /Cargo.ci.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | members = [ 4 | "xtask", 5 | "nrf52805-hal", 6 | "nrf52810-hal", 7 | "nrf52811-hal", 8 | "nrf52832-hal", 9 | "nrf52833-hal", 10 | "nrf52840-hal", 11 | "nrf52840-hal-tests", 12 | "nrf5340-app-hal", 13 | "nrf5340-net-hal", 14 | "nrf9160-hal", 15 | "examples/*", 16 | ] 17 | default-members = ["xtask"] 18 | exclude = ["examples/.cargo"] 19 | 20 | [profile.dev] 21 | incremental = false 22 | codegen-units = 1 23 | debug = true 24 | lto = false 25 | 26 | [profile.release] 27 | debug = true 28 | lto = true 29 | opt-level = "s" 30 | -------------------------------------------------------------------------------- /Cargo.example.toml: -------------------------------------------------------------------------------- 1 | # This file is a template for a Cargo workspace for developer convenience. 2 | # 3 | # Since Cargo resolves all features for all crates in the workspace together, 4 | # it is not possible to have a workspace with all the crates together, since they 5 | # enable incompatible features. 6 | # 7 | # Instead, we provide this template so you can enable only the crates you're going to 8 | # work on. This makes eg rust-analyzer check-on-save and autocomplete work, but only 9 | # in these crates, without any feature conflict. 10 | # 11 | # Copy this file to `Cargo.toml` and uncomment one group of crates below. 12 | # 13 | # `/Cargo.toml` is already in .gitignore, so you don't commit it accidentally. 14 | 15 | [workspace] 16 | resolver = "2" 17 | members = [ 18 | # Uncomment ONLY ONE of the hals below, depending on your target 19 | # "nrf52805-hal", 20 | # "nrf52810-hal", 21 | # "nrf52811-hal", 22 | # "nrf52832-hal", 23 | # "nrf52833-hal", 24 | "nrf52840-hal", 25 | "nrf52840-hal-tests", 26 | # "nrf9160-hal", 27 | ] 28 | exclude = ["examples"] 29 | 30 | [profile.dev] 31 | incremental = false 32 | codegen-units = 1 33 | debug = true 34 | lto = false 35 | 36 | [profile.release] 37 | debug = true 38 | lto = true 39 | opt-level = "s" 40 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Anthony James Munns 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 | -------------------------------------------------------------------------------- /examples/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] 2 | runner = 'arm-none-eabi-gdb' 3 | rustflags = [ 4 | "-C", "link-arg=-Tlink.x", 5 | ] -------------------------------------------------------------------------------- /examples/blinky-button-demo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blinky-button-demo" 3 | version = "0.1.0" 4 | authors = ["Andres O. Vela"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | cortex-m = { version = "0.7.3", features = ["critical-section-single-core"] } 9 | cortex-m-rt = "0.7.0" 10 | embedded-hal = "1.0.0" 11 | rtt-target = "0.6.0" 12 | nrf52832-hal = { features = ["rt"], path = "../../nrf52832-hal" } 13 | -------------------------------------------------------------------------------- /examples/blinky-button-demo/Embed.toml: -------------------------------------------------------------------------------- 1 | [default.probe] 2 | # USB vendor ID 3 | # usb_vid = "1337" 4 | # USB product ID 5 | # usb_pid = "1337" 6 | # Serial number 7 | # serial = "12345678" 8 | # The protocol to be used for communicating with the target. 9 | protocol = "Swd" 10 | # The speed in kHz of the data link to the target. 11 | # speed = 1337 12 | 13 | [default.flashing] 14 | # Whether or not the target should be flashed. 15 | enabled = true 16 | # Whether or not the target should be halted after reset. 17 | # DEPRECATED, moved to reset section 18 | halt_afterwards = false 19 | # Whether or not bytes erased but not rewritten with data from the ELF 20 | # should be restored with their contents before erasing. 21 | restore_unwritten_bytes = false 22 | # The path where an SVG of the assembled flash layout should be written to. 23 | # flash_layout_output_path = "out.svg" 24 | 25 | [default.reset] 26 | # Whether or not the target should be reset. 27 | # When flashing is enabled as well, the target will be reset after flashing. 28 | enabled = true 29 | # Whether or not the target should be halted after reset. 30 | halt_afterwards = false 31 | 32 | [default.general] 33 | # The chip name of the chip to be debugged. 34 | chip = "nRF52832_xxAA" 35 | # A list of chip descriptions to be loaded during runtime. 36 | chip_descriptions = [] 37 | # The default log level to be used. Possible values are one of: 38 | # "OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" 39 | log_level = "WARN" 40 | 41 | [default.rtt] 42 | # Whether or not an RTTUI should be opened after flashing. 43 | # This is exclusive and cannot be used with GDB at the moment. 44 | enabled = true 45 | # A list of channel associations to be displayed. If left empty, all channels are displayed. 46 | channels = [ 47 | # { up = 0, down = 0, name = "name", format = "String" } 48 | ] 49 | # The duration in ms for which the logger should retry to attach to RTT. 50 | timeout = 3000 51 | # Whether timestamps in the RTTUI are enabled 52 | show_timestamps = true 53 | # Whether to save rtt history buffer on exit. 54 | log_enabled = false 55 | # Where to save rtt history buffer relative to manifest path. 56 | log_path = "./logs" 57 | 58 | [default.gdb] 59 | # Whether or not a GDB server should be opened after flashing. 60 | # This is exclusive and cannot be used with RTT at the moment. 61 | enabled = false 62 | # The connection string in host:port format wher the GDB server will open a socket. 63 | # gdb_connection_string 64 | -------------------------------------------------------------------------------- /examples/blinky-button-demo/README.md: -------------------------------------------------------------------------------- 1 | # Blinky button demo 2 | 3 | This hello world example turns on LED 1 when you press Button 1 on the nrf52-dk (PCA10040). 4 | > Note: You will have to change the pin numbers if you use a different device. 5 | 6 | ## Set up with `cargo-embed` 7 | 8 | Install `cargo-embed` if you don't have it already: 9 | 10 | ```console 11 | $ cargo install probe-rs-tools 12 | ``` 13 | 14 | Then just `cd` to the example folder and run 15 | 16 | ```console 17 | $ cargo embed --target thumbv7em-none-eabihf 18 | ``` 19 | 20 | -------------------------------------------------------------------------------- /examples/blinky-button-demo/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | 4 | use embedded_hal::digital::InputPin; 5 | use embedded_hal::digital::OutputPin; 6 | use nrf52832_hal as hal; 7 | use nrf52832_hal::gpio::Level; 8 | use rtt_target::{rprintln, rtt_init_print}; 9 | 10 | #[panic_handler] // panicking behavior 11 | fn panic(_: &core::panic::PanicInfo) -> ! { 12 | loop { 13 | cortex_m::asm::bkpt(); 14 | } 15 | } 16 | 17 | #[cortex_m_rt::entry] 18 | fn main() -> ! { 19 | rtt_init_print!(); 20 | let p = hal::pac::Peripherals::take().unwrap(); 21 | let port0 = hal::gpio::p0::Parts::new(p.P0); 22 | let mut button = port0.p0_13.into_pullup_input(); 23 | let mut led = port0.p0_17.into_push_pull_output(Level::Low); 24 | 25 | rprintln!("Blinky button demo starting"); 26 | loop { 27 | if button.is_high().unwrap() { 28 | led.set_high().unwrap(); 29 | } else { 30 | led.set_low().unwrap(); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /examples/ccm-demo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ccm-demo" 3 | version = "0.0.1" 4 | edition = "2018" 5 | authors = [ "Thales Fragoso "] 6 | publish = false 7 | 8 | [dependencies] 9 | cortex-m = { version = "0.7.3", features = ["critical-section-single-core"] } 10 | cortex-m-rt = "0.7.0" 11 | rtt-target = "0.6.0" 12 | rand_core = "0.9.0" 13 | 14 | nrf52805-hal = { path = "../../nrf52805-hal", features = ["rt"], optional = true } 15 | nrf52810-hal = { path = "../../nrf52810-hal", features = ["rt"], optional = true } 16 | nrf52811-hal = { path = "../../nrf52811-hal", features = ["rt"], optional = true } 17 | nrf52832-hal = { path = "../../nrf52832-hal", features = ["rt"], optional = true } 18 | nrf52840-hal = { path = "../../nrf52840-hal", features = ["rt"], optional = true } 19 | nrf52833-hal = { path = "../../nrf52833-hal", features = ["rt"], optional = true } 20 | 21 | [[bin]] 22 | name = "ccm-demo" 23 | doc = false 24 | test = false 25 | 26 | [features] 27 | 52805 = ["nrf52805-hal"] 28 | 52810 = ["nrf52810-hal"] 29 | 52811 = ["nrf52811-hal"] 30 | 52832 = ["nrf52832-hal"] 31 | 52840 = ["nrf52840-hal"] 32 | 52833 = ["nrf52833-hal"] 33 | -------------------------------------------------------------------------------- /examples/ccm-demo/Embed.toml: -------------------------------------------------------------------------------- 1 | [default.probe] 2 | # USB vendor ID 3 | # usb_vid = "1337" 4 | # USB product ID 5 | # usb_pid = "1337" 6 | # Serial number 7 | # serial = "12345678" 8 | # The protocol to be used for communicating with the target. 9 | protocol = "Swd" 10 | # The speed in kHz of the data link to the target. 11 | # speed = 1337 12 | 13 | [default.flashing] 14 | # Whether or not the target should be flashed. 15 | enabled = true 16 | # Whether or not the target should be halted after reset. 17 | # DEPRECATED, moved to reset section 18 | halt_afterwards = false 19 | # Whether or not bytes erased but not rewritten with data from the ELF 20 | # should be restored with their contents before erasing. 21 | restore_unwritten_bytes = false 22 | # The path where an SVG of the assembled flash layout should be written to. 23 | # flash_layout_output_path = "out.svg" 24 | 25 | [default.reset] 26 | # Whether or not the target should be reset. 27 | # When flashing is enabled as well, the target will be reset after flashing. 28 | enabled = true 29 | # Whether or not the target should be halted after reset. 30 | halt_afterwards = false 31 | 32 | [default.general] 33 | # The chip name of the chip to be debugged. 34 | chip = "nRF52832_xxAA" 35 | # A list of chip descriptions to be loaded during runtime. 36 | chip_descriptions = [] 37 | # The default log level to be used. Possible values are one of: 38 | # "OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" 39 | log_level = "WARN" 40 | 41 | [default.rtt] 42 | # Whether or not an RTTUI should be opened after flashing. 43 | # This is exclusive and cannot be used with GDB at the moment. 44 | enabled = true 45 | # A list of channel associations to be displayed. If left empty, all channels are displayed. 46 | channels = [ 47 | # { up = 0, down = 0, name = "name", format = "String" } 48 | ] 49 | # The duration in ms for which the logger should retry to attach to RTT. 50 | timeout = 3000 51 | # Whether timestamps in the RTTUI are enabled 52 | show_timestamps = true 53 | # Whether to save rtt history buffer on exit. 54 | log_enabled = false 55 | # Where to save rtt history buffer relative to manifest path. 56 | log_path = "./logs" 57 | 58 | [default.gdb] 59 | # Whether or not a GDB server should be opened after flashing. 60 | # This is exclusive and cannot be used with RTT at the moment. 61 | enabled = false 62 | # The connection string in host:port format wher the GDB server will open a socket. 63 | # gdb_connection_string 64 | -------------------------------------------------------------------------------- /examples/ccm-demo/README.md: -------------------------------------------------------------------------------- 1 | # CCM encryption demo 2 | 3 | This CCM (cipher block chaining) encryption demo initialises a text message of the maximum size of 251 bytes and encrypts and decrypts it, measuring the time it takes. It then repeats the process with smaller and smaller chunks of data to demonstrate how long smaller packets take to process. 4 | 5 | ## How to run 6 | 7 | Choose the microcontroller with one of the following features: 8 | - 52805 9 | - 52810 10 | - 52811 11 | - 52832 12 | - 52840 13 | 14 | Also, if using `cargo-embed`, change the `chip` and `protocol` fields in [Embed.toml](Embed.toml). 15 | 16 | This demo uses the [rtt-target](https://crates.io/crates/rtt-target) crate for communication. 17 | 18 | If using `cargo-embed`, just run 19 | 20 | ```console 21 | $ cargo embed --release --features=52832 --target=thumbv7em-none-eabihf 22 | ``` 23 | 24 | Replace `52832` and `thumbv7em-none-eabihf` with the correct feature and target for your microcontroller. 25 | -------------------------------------------------------------------------------- /examples/ccm-demo/src/stopwatch.rs: -------------------------------------------------------------------------------- 1 | use super::hal::pac::TIMER0; 2 | 3 | pub struct StopWatch { 4 | regs: TIMER0, 5 | } 6 | 7 | impl StopWatch { 8 | pub fn new(regs: TIMER0) -> Self { 9 | // NOTE(unsafe) 1 is a valid pattern to write to this register 10 | regs.tasks_stop.write(|w| unsafe { w.bits(1) }); 11 | 12 | regs.bitmode.write(|w| w.bitmode()._32bit()); 13 | 14 | // 16 Mhz / 2**4 = 1 Mhz = µs resolution 15 | // NOTE(unsafe) 4 is a valid pattern to write to this register 16 | regs.prescaler.write(|w| unsafe { w.prescaler().bits(4) }); 17 | // NOTE(unsafe) 1 is a valid pattern to write to this register 18 | regs.tasks_clear.write(|w| unsafe { w.bits(1) }); 19 | 20 | Self { regs } 21 | } 22 | 23 | #[inline(always)] 24 | pub fn start(&mut self) { 25 | // NOTE(unsafe) 1 is a valid pattern to write to this register 26 | self.regs.tasks_start.write(|w| unsafe { w.bits(1) }); 27 | } 28 | 29 | #[inline(always)] 30 | pub fn now(&self) -> u32 { 31 | // NOTE(unsafe) 1 is a valid pattern to write to this register 32 | self.regs.tasks_capture[0].write(|w| unsafe { w.bits(1) }); 33 | self.regs.cc[0].read().bits() 34 | } 35 | 36 | #[inline(always)] 37 | pub fn stop(&mut self) { 38 | // NOTE(unsafe) 1 is a valid pattern to write to this register 39 | self.regs.tasks_stop.write(|w| unsafe { w.bits(1) }); 40 | 41 | // NOTE(unsafe) 1 is a valid pattern to write to this register 42 | self.regs.tasks_clear.write(|w| unsafe { w.bits(1) }); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /examples/comp-demo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "comp-demo" 3 | version = "0.1.0" 4 | authors = ["Henrik Alsér"] 5 | edition = "2018" 6 | publish = false 7 | 8 | [dependencies] 9 | cortex-m = { version = "0.7.3", features = ["critical-section-single-core"] } 10 | cortex-m-rt = { version = "0.7.0", features = ["device"] } 11 | cortex-m-rtic = { version = "1.0.0", default-features = false } 12 | embedded-hal = "1.0.0" 13 | rtt-target = "0.6.0" 14 | nrf52840-hal = { features = ["rt"], path = "../../nrf52840-hal" } 15 | -------------------------------------------------------------------------------- /examples/comp-demo/Embed.toml: -------------------------------------------------------------------------------- 1 | [default.probe] 2 | # USB vendor ID 3 | # usb_vid = "1337" 4 | # USB product ID 5 | # usb_pid = "1337" 6 | # Serial number 7 | # serial = "12345678" 8 | # The protocol to be used for communicating with the target. 9 | protocol = "Swd" 10 | # The speed in kHz of the data link to the target. 11 | # speed = 1337 12 | 13 | [default.flashing] 14 | # Whether or not the target should be flashed. 15 | enabled = true 16 | # Whether or not the target should be halted after reset. 17 | # DEPRECATED, moved to reset section 18 | halt_afterwards = false 19 | # Whether or not bytes erased but not rewritten with data from the ELF 20 | # should be restored with their contents before erasing. 21 | restore_unwritten_bytes = false 22 | # The path where an SVG of the assembled flash layout should be written to. 23 | # flash_layout_output_path = "out.svg" 24 | 25 | [default.reset] 26 | # Whether or not the target should be reset. 27 | # When flashing is enabled as well, the target will be reset after flashing. 28 | enabled = true 29 | # Whether or not the target should be halted after reset. 30 | halt_afterwards = false 31 | 32 | [default.general] 33 | # The chip name of the chip to be debugged. 34 | chip = "nRF52840" 35 | # A list of chip descriptions to be loaded during runtime. 36 | chip_descriptions = [] 37 | # The default log level to be used. Possible values are one of: 38 | # "OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" 39 | log_level = "WARN" 40 | 41 | [default.rtt] 42 | # Whether or not an RTTUI should be opened after flashing. 43 | # This is exclusive and cannot be used with GDB at the moment. 44 | enabled = true 45 | # A list of channel associations to be displayed. If left empty, all channels are displayed. 46 | channels = [ 47 | # { up = 0, down = 0, name = "name", format = "String" } 48 | ] 49 | # The duration in ms for which the logger should retry to attach to RTT. 50 | timeout = 3000 51 | # Whether timestamps in the RTTUI are enabled 52 | show_timestamps = true 53 | # Whether to save rtt history buffer on exit. 54 | log_enabled = false 55 | # Where to save rtt history buffer relative to manifest path. 56 | log_path = "./logs" 57 | 58 | [default.gdb] 59 | # Whether or not a GDB server should be opened after flashing. 60 | # This is exclusive and cannot be used with RTT at the moment. 61 | enabled = false 62 | # The connection string in host:port format wher the GDB server will open a socket. 63 | # gdb_connection_string 64 | -------------------------------------------------------------------------------- /examples/comp-demo/README.md: -------------------------------------------------------------------------------- 1 | # Comp demo 2 | 3 | This demo uses the Comparator (comp) peripheral to compare the differential voltages between two pins. If the voltage on Pin 30 is higher than Pin 31 (reference voltage) the built in LED will switch off otherwise it will switch on. The demo uses `nrf52840-hal` but this can be swapped out with an alternative if required. 4 | 5 | ## How to run 6 | 7 | If using `cargo-embed`, just run 8 | 9 | ```console 10 | $ cargo embed --release --target=thumbv7em-none-eabihf 11 | ``` -------------------------------------------------------------------------------- /examples/comp-demo/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use {core::panic::PanicInfo, rtt_target::rprintln}; 5 | 6 | #[rtic::app(device = nrf52840_hal::pac, peripherals = true)] 7 | mod app { 8 | use embedded_hal::digital::OutputPin; 9 | use nrf52840_hal::clocks::Clocks; 10 | use nrf52840_hal::comp::*; 11 | use nrf52840_hal::gpio::{self, Level, Output, Pin, PushPull}; 12 | use rtt_target::{rprintln, rtt_init_print}; 13 | 14 | #[shared] 15 | struct Shared {} 16 | 17 | #[local] 18 | struct Local { 19 | comp: Comp, 20 | led1: Pin>, 21 | } 22 | 23 | #[init] 24 | fn init(ctx: init::Context) -> (Shared, Local, init::Monotonics) { 25 | let _clocks = Clocks::new(ctx.device.CLOCK).enable_ext_hfosc(); 26 | rtt_init_print!(); 27 | 28 | let p0 = gpio::p0::Parts::new(ctx.device.P0); 29 | let led1 = p0.p0_13.into_push_pull_output(Level::High).degrade(); 30 | let in_pin = p0.p0_30.into_floating_input(); 31 | let ref_pin = p0.p0_31.into_floating_input(); 32 | 33 | let comp = Comp::new(ctx.device.COMP, &in_pin); 34 | comp.differential(&ref_pin) 35 | .hysteresis(true) 36 | .enable_interrupt(Transition::Cross) 37 | .enable(); 38 | 39 | (Shared {}, Local { comp, led1 }, init::Monotonics()) 40 | } 41 | 42 | #[task(binds = COMP_LPCOMP, local = [comp, led1])] 43 | fn on_comp(ctx: on_comp::Context) { 44 | ctx.local.comp.reset_event(Transition::Cross); 45 | match ctx.local.comp.read() { 46 | CompResult::Above => { 47 | rprintln!("Vin > Vref"); 48 | ctx.local.led1.set_low().ok(); 49 | } 50 | CompResult::Below => { 51 | rprintln!("Vin < Vref"); 52 | ctx.local.led1.set_high().ok(); 53 | } 54 | } 55 | } 56 | } 57 | 58 | #[inline(never)] 59 | #[panic_handler] 60 | fn panic(info: &PanicInfo) -> ! { 61 | cortex_m::interrupt::disable(); 62 | rprintln!("{}", info); 63 | loop {} 64 | } 65 | -------------------------------------------------------------------------------- /examples/ecb-demo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ecb-demo" 3 | version = "0.0.1" 4 | edition = "2018" 5 | authors = [ "Thales Fragoso "] 6 | publish = false 7 | 8 | [dependencies] 9 | cortex-m = { version = "0.7.3", features = ["critical-section-single-core"] } 10 | cortex-m-rt = "0.7.0" 11 | rtt-target = "0.6.0" 12 | 13 | nrf52805-hal = { path = "../../nrf52805-hal", features = ["rt"], optional = true } 14 | nrf52810-hal = { path = "../../nrf52810-hal", features = ["rt"], optional = true } 15 | nrf52811-hal = { path = "../../nrf52811-hal", features = ["rt"], optional = true } 16 | nrf52832-hal = { path = "../../nrf52832-hal", features = ["rt"], optional = true } 17 | nrf52840-hal = { path = "../../nrf52840-hal", features = ["rt"], optional = true } 18 | nrf52833-hal = { path = "../../nrf52833-hal", features = ["rt"], optional = true } 19 | nrf51-hal = { path = "../../nrf51-hal", features = ["rt"], optional = true} 20 | 21 | [[bin]] 22 | name = "ecb-demo" 23 | doc = false 24 | test = false 25 | 26 | [features] 27 | 51 = ["nrf51-hal"] 28 | 52805 = ["nrf52805-hal"] 29 | 52810 = ["nrf52810-hal"] 30 | 52811 = ["nrf52811-hal"] 31 | 52832 = ["nrf52832-hal"] 32 | 52840 = ["nrf52840-hal"] 33 | 52833 = ["nrf52833-hal"] 34 | -------------------------------------------------------------------------------- /examples/ecb-demo/Embed.toml: -------------------------------------------------------------------------------- 1 | [default.probe] 2 | # USB vendor ID 3 | # usb_vid = "1337" 4 | # USB product ID 5 | # usb_pid = "1337" 6 | # Serial number 7 | # serial = "12345678" 8 | # The protocol to be used for communicating with the target. 9 | protocol = "Swd" 10 | # The speed in kHz of the data link to the target. 11 | # speed = 1337 12 | 13 | [default.flashing] 14 | # Whether or not the target should be flashed. 15 | enabled = true 16 | # Whether or not the target should be halted after reset. 17 | # DEPRECATED, moved to reset section 18 | halt_afterwards = false 19 | # Whether or not bytes erased but not rewritten with data from the ELF 20 | # should be restored with their contents before erasing. 21 | restore_unwritten_bytes = false 22 | # The path where an SVG of the assembled flash layout should be written to. 23 | # flash_layout_output_path = "out.svg" 24 | 25 | [default.reset] 26 | # Whether or not the target should be reset. 27 | # When flashing is enabled as well, the target will be reset after flashing. 28 | enabled = true 29 | # Whether or not the target should be halted after reset. 30 | halt_afterwards = false 31 | 32 | [default.general] 33 | # The chip name of the chip to be debugged. 34 | chip = "nRF52832_xxAA" 35 | # A list of chip descriptions to be loaded during runtime. 36 | chip_descriptions = [] 37 | # The default log level to be used. Possible values are one of: 38 | # "OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" 39 | log_level = "WARN" 40 | 41 | [default.rtt] 42 | # Whether or not an RTTUI should be opened after flashing. 43 | # This is exclusive and cannot be used with GDB at the moment. 44 | enabled = true 45 | # A list of channel associations to be displayed. If left empty, all channels are displayed. 46 | channels = [ 47 | # { up = 0, down = 0, name = "name", format = "String" } 48 | ] 49 | # The duration in ms for which the logger should retry to attach to RTT. 50 | timeout = 3000 51 | # Whether timestamps in the RTTUI are enabled 52 | show_timestamps = true 53 | # Whether to save rtt history buffer on exit. 54 | log_enabled = false 55 | # Where to save rtt history buffer relative to manifest path. 56 | log_path = "./logs" 57 | 58 | [default.gdb] 59 | # Whether or not a GDB server should be opened after flashing. 60 | # This is exclusive and cannot be used with RTT at the moment. 61 | enabled = false 62 | # The connection string in host:port format wher the GDB server will open a socket. 63 | # gdb_connection_string 64 | -------------------------------------------------------------------------------- /examples/ecb-demo/README.md: -------------------------------------------------------------------------------- 1 | # ECB encryption demo 2 | 3 | The AES electronic codebook mode (ECB) demo demonstrates a blocking 128-bit AES encryption of 16 bytes of data using a 16 byte key. Encryption only, no decryption. 4 | 5 | ## How to run 6 | 7 | Choose the microcontroller with one of the following features: 8 | - 51 9 | - 52805 10 | - 52810 11 | - 52811 12 | - 52832 13 | - 52840 14 | 15 | Also, if using `cargo-embed`, change the `chip` and `protocol` fields in [Embed.toml](Embed.toml). 16 | 17 | This demo uses the [rtt-target](https://crates.io/crates/rtt-target) crate for communication. 18 | 19 | If using `cargo-embed`, just run 20 | 21 | ```console 22 | $ cargo embed --release --features=52832 --target=thumbv7em-none-eabihf 23 | ``` 24 | 25 | Replace `52832` and `thumbv7em-none-eabihf` with the correct feature and target for your microcontroller. 26 | -------------------------------------------------------------------------------- /examples/ecb-demo/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | // Import the right HAL/PAC crate, depending on the target chip 5 | #[cfg(feature = "51")] 6 | pub use nrf51_hal as hal; 7 | #[cfg(feature = "52805")] 8 | pub use nrf52805_hal as hal; 9 | #[cfg(feature = "52810")] 10 | pub use nrf52810_hal as hal; 11 | #[cfg(feature = "52811")] 12 | pub use nrf52811_hal as hal; 13 | #[cfg(feature = "52832")] 14 | pub use nrf52832_hal as hal; 15 | #[cfg(feature = "52833")] 16 | pub use nrf52833_hal as hal; 17 | #[cfg(feature = "52840")] 18 | pub use nrf52840_hal as hal; 19 | 20 | use { 21 | core::{ 22 | panic::PanicInfo, 23 | sync::atomic::{compiler_fence, Ordering}, 24 | }, 25 | cortex_m_rt::entry, 26 | hal::{Clocks, Ecb}, 27 | rtt_target::{rprint, rprintln, rtt_init_print}, 28 | }; 29 | 30 | const MSG: [u8; 16] = *b"Message to encry"; 31 | const KEY: [u8; 16] = *b"aaaaaaaaaaaaaaaa"; 32 | const CIPHER_MSG: [u8; 16] = [ 33 | 0xFE, 0xF1, 0x63, 0x82, 0xB4, 0x54, 0x6B, 0xE4, 0xEB, 0x9A, 0x5C, 0x0E, 0xB6, 0x0E, 0x49, 0x2F, 34 | ]; 35 | 36 | #[entry] 37 | fn main() -> ! { 38 | let p = hal::pac::Peripherals::take().unwrap(); 39 | 40 | let _clocks = Clocks::new(p.CLOCK).enable_ext_hfosc(); 41 | rtt_init_print!(); 42 | 43 | let mut ecb = Ecb::init(p.ECB); 44 | 45 | loop { 46 | rprintln!("Starting Encryption\n"); 47 | rprintln!("Clear text: {}", core::str::from_utf8(&MSG[..]).unwrap()); 48 | 49 | let cipher_text = ecb.encrypt_block(MSG, KEY).unwrap(); 50 | rprint!("Cipher Text: "); 51 | for number in cipher_text.iter() { 52 | rprint!("{:x} ", *number); 53 | } 54 | assert_eq!(cipher_text, CIPHER_MSG); 55 | rprintln!("\r\n Encryption Done\n"); 56 | 57 | cortex_m::asm::delay(136_000_000); 58 | } 59 | } 60 | 61 | #[inline(never)] 62 | #[panic_handler] 63 | fn panic(info: &PanicInfo) -> ! { 64 | rprintln!("{}", info); 65 | loop { 66 | compiler_fence(Ordering::SeqCst); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /examples/gpiote-demo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "gpiote-demo" 3 | version = "0.1.0" 4 | authors = ["Henrik Alsér"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | cortex-m = { version = "0.7.3", features = ["critical-section-single-core"] } 9 | cortex-m-rt = { version = "0.7.0", features = ["device"] } 10 | cortex-m-rtic = { version = "1.0.0", default-features = false } 11 | embedded-hal = "1.0.0" 12 | systick-monotonic = "1.0.0" 13 | rtt-target = "0.6.0" 14 | nrf52840-hal = { features = ["rt"], path = "../../nrf52840-hal" } 15 | -------------------------------------------------------------------------------- /examples/gpiote-demo/Embed.toml: -------------------------------------------------------------------------------- 1 | [default.probe] 2 | # USB vendor ID 3 | # usb_vid = "1337" 4 | # USB product ID 5 | # usb_pid = "1337" 6 | # Serial number 7 | # serial = "12345678" 8 | # The protocol to be used for communicating with the target. 9 | protocol = "Swd" 10 | # The speed in kHz of the data link to the target. 11 | # speed = 1337 12 | 13 | [default.flashing] 14 | # Whether or not the target should be flashed. 15 | enabled = true 16 | # Whether or not the target should be halted after reset. 17 | # DEPRECATED, moved to reset section 18 | halt_afterwards = false 19 | # Whether or not bytes erased but not rewritten with data from the ELF 20 | # should be restored with their contents before erasing. 21 | restore_unwritten_bytes = false 22 | # The path where an SVG of the assembled flash layout should be written to. 23 | # flash_layout_output_path = "out.svg" 24 | 25 | [default.reset] 26 | # Whether or not the target should be reset. 27 | # When flashing is enabled as well, the target will be reset after flashing. 28 | enabled = true 29 | # Whether or not the target should be halted after reset. 30 | halt_afterwards = false 31 | 32 | [default.general] 33 | # The chip name of the chip to be debugged. 34 | chip = "nRF52840" 35 | # A list of chip descriptions to be loaded during runtime. 36 | chip_descriptions = [] 37 | # The default log level to be used. Possible values are one of: 38 | # "OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" 39 | log_level = "WARN" 40 | 41 | [default.rtt] 42 | # Whether or not an RTTUI should be opened after flashing. 43 | # This is exclusive and cannot be used with GDB at the moment. 44 | enabled = true 45 | # A list of channel associations to be displayed. If left empty, all channels are displayed. 46 | channels = [ 47 | # { up = 0, down = 0, name = "name", format = "String" } 48 | ] 49 | # The duration in ms for which the logger should retry to attach to RTT. 50 | timeout = 3000 51 | # Whether timestamps in the RTTUI are enabled 52 | show_timestamps = true 53 | # Whether to save rtt history buffer on exit. 54 | log_enabled = false 55 | # Where to save rtt history buffer relative to manifest path. 56 | log_path = "./logs" 57 | 58 | [default.gdb] 59 | # Whether or not a GDB server should be opened after flashing. 60 | # This is exclusive and cannot be used with RTT at the moment. 61 | enabled = false 62 | # The connection string in host:port format wher the GDB server will open a socket. 63 | # gdb_connection_string 64 | -------------------------------------------------------------------------------- /examples/gpiote-demo/README.md: -------------------------------------------------------------------------------- 1 | # Gpiote demo 2 | 3 | The General-Purpose Input Output Tasks and Events (gpiote) module demo targets the nRF52840-DK in particular because of the 4 available hardware buttons on the board itself. The demo shows how you can use the `cortex-m-rtic` crate to easily debounce some buttons without blocking the CPU. GPIO pin state changes fire events which can be used to carry out tasks. This showcases the PPI (programmable peripheral interconnect) system for which there is also a dedicated demo. 4 | 5 | ## How to run 6 | 7 | If using `cargo-embed`, just run 8 | 9 | ```console 10 | $ cargo embed --release --target=thumbv7em-none-eabihf 11 | ``` -------------------------------------------------------------------------------- /examples/hello-world/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hello-world" 3 | version = "0.1.0" 4 | authors = ["Christopher Hunt"] 5 | edition = "2018" 6 | publish = false 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | 10 | [dependencies] 11 | cortex-m = "0.7.3" 12 | cortex-m-rt = "0.7.0" 13 | 14 | [dependencies.nrf9160-hal] 15 | features = ["rt"] 16 | path = "../../nrf9160-hal" 17 | optional = true 18 | 19 | [dependencies.nrf52840-hal] 20 | features = ["rt"] 21 | path = "../../nrf52840-hal" 22 | optional = true 23 | 24 | [features] 25 | 9160 = ["nrf9160-hal"] 26 | 52840 = ["nrf52840-hal"] 27 | -------------------------------------------------------------------------------- /examples/hello-world/Embed.toml: -------------------------------------------------------------------------------- 1 | [default.probe] 2 | # USB vendor ID 3 | # usb_vid = "1337" 4 | # USB product ID 5 | # usb_pid = "1337" 6 | # Serial number 7 | # serial = "12345678" 8 | # The protocol to be used for communicating with the target. 9 | protocol = "Swd" 10 | # The speed in kHz of the data link to the target. 11 | # speed = 1337 12 | 13 | [default.flashing] 14 | # Whether or not the target should be flashed. 15 | enabled = true 16 | # Whether or not the target should be halted after reset. 17 | # DEPRECATED, moved to reset section 18 | halt_afterwards = false 19 | # Whether or not bytes erased but not rewritten with data from the ELF 20 | # should be restored with their contents before erasing. 21 | restore_unwritten_bytes = false 22 | # The path where an SVG of the assembled flash layout should be written to. 23 | # flash_layout_output_path = "out.svg" 24 | 25 | [default.reset] 26 | # Whether or not the target should be reset. 27 | # When flashing is enabled as well, the target will be reset after flashing. 28 | enabled = true 29 | # Whether or not the target should be halted after reset. 30 | halt_afterwards = false 31 | 32 | [default.general] 33 | # The chip name of the chip to be debugged. 34 | chip = "nRF52840_xxAA" 35 | # A list of chip descriptions to be loaded during runtime. 36 | chip_descriptions = [] 37 | # The default log level to be used. Possible values are one of: 38 | # "OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" 39 | log_level = "WARN" 40 | 41 | [default.rtt] 42 | # Whether or not an RTTUI should be opened after flashing. 43 | # This is exclusive and cannot be used with GDB at the moment. 44 | enabled = false 45 | # A list of channel associations to be displayed. If left empty, all channels are displayed. 46 | channels = [ 47 | # { up = 0, down = 0, name = "name", format = "String" } 48 | ] 49 | # The duration in ms for which the logger should retry to attach to RTT. 50 | timeout = 3000 51 | # Whether timestamps in the RTTUI are enabled 52 | show_timestamps = true 53 | # Whether to save rtt history buffer on exit. 54 | log_enabled = false 55 | # Where to save rtt history buffer relative to manifest path. 56 | log_path = "./logs" 57 | 58 | [default.gdb] 59 | # Whether or not a GDB server should be opened after flashing. 60 | # This is exclusive and cannot be used with RTT at the moment. 61 | enabled = false 62 | # The connection string in host:port format wher the GDB server will open a socket. 63 | # gdb_connection_string 64 | -------------------------------------------------------------------------------- /examples/hello-world/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | // Simple UART example 5 | 6 | #[cfg(feature = "52840")] 7 | use nrf52840_hal as hal; 8 | #[cfg(feature = "9160")] 9 | use nrf9160_hal as hal; 10 | 11 | use core::fmt::Write; 12 | use hal::{gpio, uarte, uarte::Uarte}; 13 | 14 | #[cortex_m_rt::entry] 15 | fn main() -> ! { 16 | let p = hal::pac::Peripherals::take().unwrap(); 17 | 18 | #[cfg(feature = "52840")] 19 | let (uart0, cdc_pins) = { 20 | let p0 = gpio::p0::Parts::new(p.P0); 21 | ( 22 | p.UARTE0, 23 | uarte::Pins { 24 | txd: p0.p0_06.into_push_pull_output(gpio::Level::High).degrade(), 25 | rxd: p0.p0_08.into_floating_input().degrade(), 26 | cts: Some(p0.p0_07.into_floating_input().degrade()), 27 | rts: Some(p0.p0_05.into_push_pull_output(gpio::Level::High).degrade()), 28 | }, 29 | ) 30 | }; 31 | #[cfg(feature = "9160")] 32 | let (uart0, cdc_pins) = { 33 | let p0 = gpio::p0::Parts::new(p.P0_NS); 34 | ( 35 | p.UARTE0_NS, 36 | uarte::Pins { 37 | txd: p0.p0_29.into_push_pull_output(gpio::Level::High).degrade(), 38 | rxd: p0.p0_28.into_floating_input().degrade(), 39 | cts: Some(p0.p0_26.into_floating_input().degrade()), 40 | rts: Some(p0.p0_27.into_push_pull_output(gpio::Level::High).degrade()), 41 | }, 42 | ) 43 | }; 44 | 45 | let mut uarte = Uarte::new( 46 | uart0, 47 | cdc_pins, 48 | uarte::Parity::EXCLUDED, 49 | uarte::Baudrate::BAUD115200, 50 | ); 51 | 52 | write!(uarte, "Hello, World!\r\n").unwrap(); 53 | 54 | loop { 55 | cortex_m::asm::wfi(); 56 | } 57 | } 58 | 59 | #[panic_handler] // panicking behavior 60 | fn panic(_: &core::panic::PanicInfo) -> ! { 61 | loop { 62 | cortex_m::asm::bkpt(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /examples/i2s-controller-demo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "i2s-controller-demo" 3 | version = "0.1.0" 4 | authors = ["Henrik Alsér"] 5 | edition = "2018" 6 | publish = false 7 | 8 | [dependencies] 9 | cortex-m = { version = "0.7.3", features = ["critical-section-single-core"] } 10 | cortex-m-rt = { version = "0.7.0", features = ["device"] } 11 | cortex-m-rtic = { version = "1.0.0", default-features = false } 12 | embedded-hal = "1.0.0" 13 | systick-monotonic = "1.0.0" 14 | rtt-target = "0.6.0" 15 | nrf52840-hal = { features = ["rt"], path = "../../nrf52840-hal" } 16 | heapless = "0.8.0" 17 | small_morse = "0.1.0" 18 | -------------------------------------------------------------------------------- /examples/i2s-controller-demo/Embed.toml: -------------------------------------------------------------------------------- 1 | [default.probe] 2 | # USB vendor ID 3 | # usb_vid = "1337" 4 | # USB product ID 5 | # usb_pid = "1337" 6 | # Serial number 7 | # serial = "12345678" 8 | # The protocol to be used for communicating with the target. 9 | protocol = "Swd" 10 | # The speed in kHz of the data link to the target. 11 | # speed = 1337 12 | 13 | [default.flashing] 14 | # Whether or not the target should be flashed. 15 | enabled = true 16 | # Whether or not the target should be halted after reset. 17 | # DEPRECATED, moved to reset section 18 | halt_afterwards = false 19 | # Whether or not bytes erased but not rewritten with data from the ELF 20 | # should be restored with their contents before erasing. 21 | restore_unwritten_bytes = false 22 | # The path where an SVG of the assembled flash layout should be written to. 23 | # flash_layout_output_path = "out.svg" 24 | 25 | [default.reset] 26 | # Whether or not the target should be reset. 27 | # When flashing is enabled as well, the target will be reset after flashing. 28 | enabled = true 29 | # Whether or not the target should be halted after reset. 30 | halt_afterwards = false 31 | 32 | [default.general] 33 | # The chip name of the chip to be debugged. 34 | chip = "nRF52840" 35 | # A list of chip descriptions to be loaded during runtime. 36 | chip_descriptions = [] 37 | # The default log level to be used. Possible values are one of: 38 | # "OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" 39 | log_level = "WARN" 40 | 41 | [default.rtt] 42 | # Whether or not an RTTUI should be opened after flashing. 43 | # This is exclusive and cannot be used with GDB at the moment. 44 | enabled = true 45 | # A list of channel associations to be displayed. If left empty, all channels are displayed. 46 | channels = [ 47 | # { up = 0, down = 0, name = "name", format = "String" } 48 | ] 49 | # The duration in ms for which the logger should retry to attach to RTT. 50 | timeout = 3000 51 | # Whether timestamps in the RTTUI are enabled 52 | show_timestamps = true 53 | # Whether to save rtt history buffer on exit. 54 | log_enabled = false 55 | # Where to save rtt history buffer relative to manifest path. 56 | log_path = "./logs" 57 | 58 | [default.gdb] 59 | # Whether or not a GDB server should be opened after flashing. 60 | # This is exclusive and cannot be used with RTT at the moment. 61 | enabled = false 62 | # The connection string in host:port format wher the GDB server will open a socket. 63 | # gdb_connection_string 64 | -------------------------------------------------------------------------------- /examples/i2s-controller-demo/README.md: -------------------------------------------------------------------------------- 1 | # I2S controller demo 2 | 3 | The Inter-IC Sound interface (I2S) controller mode (aka master mode) demo. This demo generates Morse code audio signals from text received over UART and plays them back over I2S. Tested with nRF52840-DK and a UDA1334a DAC. 4 | 5 | ## How to run 6 | 7 | If using `cargo-embed`, just run 8 | 9 | ```console 10 | $ cargo embed --release --target=thumbv7em-none-eabihf 11 | ``` -------------------------------------------------------------------------------- /examples/i2s-peripheral-demo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "i2s-peripheral-demo" 3 | version = "0.1.0" 4 | authors = ["Henrik Alsér"] 5 | edition = "2018" 6 | publish = false 7 | 8 | [dependencies] 9 | cortex-m = { version = "0.7.3", features = ["critical-section-single-core"] } 10 | cortex-m-rt = { version = "0.7.0", features = ["device"] } 11 | cortex-m-rtic = { version = "1.0.0", default-features = false } 12 | embedded-hal = "1.0.0" 13 | rtt-target = "0.6.0" 14 | nrf52840-hal = { features = ["rt"], path = "../../nrf52840-hal" } 15 | -------------------------------------------------------------------------------- /examples/i2s-peripheral-demo/Embed.toml: -------------------------------------------------------------------------------- 1 | [default.probe] 2 | # USB vendor ID 3 | # usb_vid = "1337" 4 | # USB product ID 5 | # usb_pid = "1337" 6 | # Serial number 7 | # serial = "12345678" 8 | # The protocol to be used for communicating with the target. 9 | protocol = "Swd" 10 | # The speed in kHz of the data link to the target. 11 | # speed = 1337 12 | 13 | [default.flashing] 14 | # Whether or not the target should be flashed. 15 | enabled = true 16 | # Whether or not the target should be halted after reset. 17 | # DEPRECATED, moved to reset section 18 | halt_afterwards = false 19 | # Whether or not bytes erased but not rewritten with data from the ELF 20 | # should be restored with their contents before erasing. 21 | restore_unwritten_bytes = false 22 | # The path where an SVG of the assembled flash layout should be written to. 23 | # flash_layout_output_path = "out.svg" 24 | 25 | [default.reset] 26 | # Whether or not the target should be reset. 27 | # When flashing is enabled as well, the target will be reset after flashing. 28 | enabled = true 29 | # Whether or not the target should be halted after reset. 30 | halt_afterwards = false 31 | 32 | [default.general] 33 | # The chip name of the chip to be debugged. 34 | chip = "nRF52840" 35 | # A list of chip descriptions to be loaded during runtime. 36 | chip_descriptions = [] 37 | # The default log level to be used. Possible values are one of: 38 | # "OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" 39 | log_level = "WARN" 40 | 41 | [default.rtt] 42 | # Whether or not an RTTUI should be opened after flashing. 43 | # This is exclusive and cannot be used with GDB at the moment. 44 | enabled = true 45 | # A list of channel associations to be displayed. If left empty, all channels are displayed. 46 | channels = [ 47 | # { up = 0, down = 0, name = "name", format = "String" } 48 | ] 49 | # The duration in ms for which the logger should retry to attach to RTT. 50 | timeout = 3000 51 | # Whether timestamps in the RTTUI are enabled 52 | show_timestamps = true 53 | # Whether to save rtt history buffer on exit. 54 | log_enabled = false 55 | # Where to save rtt history buffer relative to manifest path. 56 | log_path = "./logs" 57 | 58 | [default.gdb] 59 | # Whether or not a GDB server should be opened after flashing. 60 | # This is exclusive and cannot be used with RTT at the moment. 61 | enabled = false 62 | # The connection string in host:port format wher the GDB server will open a socket. 63 | # gdb_connection_string 64 | -------------------------------------------------------------------------------- /examples/i2s-peripheral-demo/README.md: -------------------------------------------------------------------------------- 1 | # I2S peripheral demo 2 | 3 | The Inter-IC Sound interface (I2S) peripheral mode (aka slave mode) demo. This demonstrates full duplex communication between a controller and peripheral mode I2S peripheral using the EasyDMA capabilities of the chip. This targets the nrf52840 family of devices. 4 | 5 | ## How to run 6 | 7 | If using `cargo-embed`, just run 8 | 9 | ```console 10 | $ cargo embed --release --target=thumbv7em-none-eabihf 11 | ``` -------------------------------------------------------------------------------- /examples/lpcomp-demo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "lpcomp-demo" 3 | version = "0.1.0" 4 | authors = ["Henrik Alsér"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | cortex-m = { version = "0.7.3", features = ["critical-section-single-core"] } 9 | cortex-m-rt = { version = "0.7.0", features = ["device"] } 10 | cortex-m-rtic = { version = "1.0.0", default-features = false } 11 | embedded-hal = "1.0.0" 12 | rtt-target = "0.6.0" 13 | nrf52840-hal = { features = ["rt"], path = "../../nrf52840-hal" } 14 | -------------------------------------------------------------------------------- /examples/lpcomp-demo/Embed.toml: -------------------------------------------------------------------------------- 1 | [default.probe] 2 | # USB vendor ID 3 | # usb_vid = "1337" 4 | # USB product ID 5 | # usb_pid = "1337" 6 | # Serial number 7 | # serial = "12345678" 8 | # The protocol to be used for communicating with the target. 9 | protocol = "Swd" 10 | # The speed in kHz of the data link to the target. 11 | # speed = 1337 12 | 13 | [default.flashing] 14 | # Whether or not the target should be flashed. 15 | enabled = true 16 | # Whether or not the target should be halted after reset. 17 | # DEPRECATED, moved to reset section 18 | halt_afterwards = false 19 | # Whether or not bytes erased but not rewritten with data from the ELF 20 | # should be restored with their contents before erasing. 21 | restore_unwritten_bytes = false 22 | # The path where an SVG of the assembled flash layout should be written to. 23 | # flash_layout_output_path = "out.svg" 24 | 25 | [default.reset] 26 | # Whether or not the target should be reset. 27 | # When flashing is enabled as well, the target will be reset after flashing. 28 | enabled = true 29 | # Whether or not the target should be halted after reset. 30 | halt_afterwards = false 31 | 32 | [default.general] 33 | # The chip name of the chip to be debugged. 34 | chip = "nRF52840" 35 | # A list of chip descriptions to be loaded during runtime. 36 | chip_descriptions = [] 37 | # The default log level to be used. Possible values are one of: 38 | # "OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" 39 | log_level = "WARN" 40 | 41 | [default.rtt] 42 | # Whether or not an RTTUI should be opened after flashing. 43 | # This is exclusive and cannot be used with GDB at the moment. 44 | enabled = true 45 | # A list of channel associations to be displayed. If left empty, all channels are displayed. 46 | channels = [ 47 | # { up = 0, down = 0, name = "name", format = "String" } 48 | ] 49 | # The duration in ms for which the logger should retry to attach to RTT. 50 | timeout = 3000 51 | # Whether timestamps in the RTTUI are enabled 52 | show_timestamps = true 53 | # Whether to save rtt history buffer on exit. 54 | log_enabled = false 55 | # Where to save rtt history buffer relative to manifest path. 56 | log_path = "./logs" 57 | 58 | [default.gdb] 59 | # Whether or not a GDB server should be opened after flashing. 60 | # This is exclusive and cannot be used with RTT at the moment. 61 | enabled = false 62 | # The connection string in host:port format wher the GDB server will open a socket. 63 | # gdb_connection_string 64 | -------------------------------------------------------------------------------- /examples/lpcomp-demo/README.md: -------------------------------------------------------------------------------- 1 | # Lpcomp demo 2 | 3 | This low power voltage comparator (lpcomp) demo shows how you would keep the device in low power mode and power it up when an analog voltage on a pin changes with respect to a voltage on a reference pin. This targets the nrf52840 family of devices. 4 | 5 | ## How to run 6 | 7 | If using `cargo-embed`, just run 8 | 9 | ```console 10 | $ cargo embed --release --target=thumbv7em-none-eabihf 11 | ``` -------------------------------------------------------------------------------- /examples/monotonic-blinky/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] 2 | runner = "probe-run --chip nRF52840_xxAA" 3 | 4 | rustflags = [ 5 | "-C", "link-arg=--nmagic", 6 | ] 7 | 8 | [build] 9 | target = "thumbv7em-none-eabi" 10 | 11 | -------------------------------------------------------------------------------- /examples/monotonic-blinky/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | -------------------------------------------------------------------------------- /examples/monotonic-blinky/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "monotonic-blinky" 3 | version = "0.1.0" 4 | edition = "2021" 5 | authors = ["Ivar Jönsson "] 6 | 7 | [dependencies] 8 | embedded-hal = "1.0.0" 9 | rtt-target = "0.5.0" 10 | panic-halt = "0.2.0" 11 | nrf52840-hal = { path = "../../nrf52840-hal/", features = ["rtic-monotonic"] } 12 | cortex-m-rtic = "1.1.4" 13 | fugit = "0.3.7" 14 | cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] } 15 | 16 | [[bin]] 17 | name = "rtc" 18 | path = "src/rtc.rs" 19 | 20 | [[bin]] 21 | name = "timer" 22 | path = "src/timer.rs" 23 | -------------------------------------------------------------------------------- /examples/monotonic-blinky/Embed.toml: -------------------------------------------------------------------------------- 1 | [default.probe] 2 | protocol = "Swd" 3 | 4 | [default.flashing] 5 | enabled = true 6 | halt_afterwards = false 7 | restore_unwritten_bytes = false 8 | do_chip_erase = false 9 | 10 | [default.reset] 11 | enabled = true 12 | halt_afterwards = false 13 | 14 | [default.general] 15 | chip = "nRF52840_xxAA" 16 | chip_descriptions = [] 17 | log_level = "WARN" 18 | connect_under_reset = false 19 | 20 | [default.rtt] 21 | enabled = true 22 | channels = [ 23 | ] 24 | timeout = 3000 25 | show_timestamps = true 26 | log_enabled = false 27 | log_path = "./logs" 28 | 29 | [default.gdb] 30 | enabled = false 31 | gdb_connection_string = "127.0.0.1:1337" 32 | -------------------------------------------------------------------------------- /examples/monotonic-blinky/README.md: -------------------------------------------------------------------------------- 1 | # Monotonic demo 2 | 3 | This crate defines a minimal [`corex-m-rtic`](https://docs.rs/cortex-m-rtic/latest/rtic/)-app using the [`rtc`](../../nrf-hal-common/src/rtc.rs) or [`timer`](../../nrf-hal-common/src/timer.rs) 4 | for software task scheduling. This example shows how to use the different clocks and how to switch inbetween them. 5 | 6 | ## How to run 7 | 8 | To run the example using the `rtc` 9 | ```bash 10 | cargo embed --release --bin rtc 11 | ``` 12 | To run the example using the `timer` 13 | ```bash 14 | cargo embed --release --bin timer 15 | ``` 16 | 17 | -------------------------------------------------------------------------------- /examples/monotonic-blinky/src/rtc.rs: -------------------------------------------------------------------------------- 1 | //! A minimal blinky example using `MonotonicRtc`. 2 | #![no_main] 3 | #![no_std] 4 | 5 | use hal::pac; 6 | use nrf52840_hal as hal; 7 | use panic_halt as _; 8 | #[rtic::app(device = pac, dispatchers = [UARTE1])] 9 | mod app { 10 | use super::*; 11 | use cortex_m::asm; 12 | use embedded_hal::digital::{OutputPin, StatefulOutputPin}; 13 | use hal::{ 14 | gpio::{p0::Parts, Level, Output, Pin, PushPull}, 15 | monotonic::MonotonicRtc, 16 | }; 17 | use pac::RTC0; 18 | use rtt_target::{rprintln, rtt_init_print}; 19 | 20 | #[monotonic(binds = RTC0, default = true)] 21 | type MyMono = MonotonicRtc; 22 | 23 | #[shared] 24 | struct Shared {} 25 | 26 | #[local] 27 | struct Local { 28 | led: Pin>, 29 | } 30 | 31 | #[init] 32 | fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { 33 | rtt_init_print!(); 34 | rprintln!("init"); 35 | 36 | let p0 = Parts::new(cx.device.P0); 37 | let led = p0.p0_13.into_push_pull_output(Level::High).degrade(); 38 | 39 | let clocks = hal::clocks::Clocks::new(cx.device.CLOCK); 40 | let clocks = clocks.start_lfclk(); 41 | // Will throw error if freq is invalid 42 | let mono = MyMono::new(cx.device.RTC0, &clocks).unwrap(); 43 | 44 | blink::spawn().ok(); 45 | (Shared {}, Local { led }, init::Monotonics(mono)) 46 | } 47 | 48 | #[idle] 49 | fn idle(_: idle::Context) -> ! { 50 | loop { 51 | rprintln!("idle"); 52 | // Put core to sleep until next interrupt 53 | asm::wfe(); 54 | } 55 | } 56 | 57 | #[task(local = [led])] 58 | fn blink(ctx: blink::Context) { 59 | rprintln!("Blink!"); 60 | let led = ctx.local.led; 61 | // Note this unwrap is safe since is_set_low is allways Ok 62 | if led.is_set_low().unwrap() { 63 | led.set_high().ok(); 64 | } else { 65 | led.set_low().ok(); 66 | } 67 | // spawn after current time + 1 second 68 | blink::spawn_after(fugit::ExtU32::millis(1000)).ok(); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /examples/monotonic-blinky/src/timer.rs: -------------------------------------------------------------------------------- 1 | //! A minimal blinky example using `MonotonicTimer`. 2 | #![no_main] 3 | #![no_std] 4 | 5 | use hal::pac; 6 | use nrf52840_hal as hal; 7 | use panic_halt as _; 8 | #[rtic::app(device = pac, dispatchers = [UARTE1])] 9 | mod app { 10 | use super::*; 11 | use cortex_m::asm; 12 | use embedded_hal::digital::{OutputPin, StatefulOutputPin}; 13 | use hal::{ 14 | gpio::{p0::Parts, Level, Output, Pin, PushPull}, 15 | monotonic::MonotonicTimer, 16 | }; 17 | use pac::TIMER0; 18 | use rtt_target::{rprintln, rtt_init_print}; 19 | 20 | #[monotonic(binds = TIMER0, default = true)] 21 | type MyMono = MonotonicTimer; 22 | 23 | #[shared] 24 | struct Shared {} 25 | 26 | #[local] 27 | struct Local { 28 | led: Pin>, 29 | } 30 | 31 | #[init] 32 | fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { 33 | rtt_init_print!(); 34 | rprintln!("init"); 35 | 36 | let p0 = Parts::new(cx.device.P0); 37 | let led = p0.p0_13.into_push_pull_output(Level::High).degrade(); 38 | 39 | // New does not exists for invalid frequencies 40 | let mono = MyMono::new(cx.device.TIMER0); 41 | blink::spawn().ok(); 42 | (Shared {}, Local { led }, init::Monotonics(mono)) 43 | } 44 | 45 | #[idle] 46 | fn idle(_: idle::Context) -> ! { 47 | loop { 48 | rprintln!("idle"); 49 | // Put core to sleep until next interrupt 50 | asm::wfe(); 51 | } 52 | } 53 | 54 | #[task(local = [led])] 55 | fn blink(ctx: blink::Context) { 56 | rprintln!("Blink!"); 57 | let led = ctx.local.led; 58 | // Note this unwrap is safe since is_set_low is allways Ok 59 | if led.is_set_low().unwrap() { 60 | led.set_high().ok(); 61 | } else { 62 | led.set_low().ok(); 63 | } 64 | // spawn after current time + 1 second 65 | blink::spawn_after(fugit::ExtU32::millis(1000)).ok(); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /examples/nvmc-demo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "nvmc-demo" 3 | version = "0.1.0" 4 | authors = ["Christopher Hunt"] 5 | edition = "2018" 6 | publish = false 7 | 8 | [dependencies] 9 | cortex-m = { version = "0.7.3", features = ["critical-section-single-core"] } 10 | cortex-m-rt = "0.7.0" 11 | embedded-storage = "0.3.0" 12 | rtt-target = "0.6.0" 13 | panic-probe = { version = "1.0.0", features = ["print-rtt"] } 14 | 15 | [dependencies.nrf52840-hal] 16 | features = ["rt"] 17 | path = "../../nrf52840-hal" 18 | optional = true 19 | 20 | [features] 21 | 52840 = ["nrf52840-hal"] 22 | -------------------------------------------------------------------------------- /examples/nvmc-demo/Embed.toml: -------------------------------------------------------------------------------- 1 | [default.probe] 2 | # USB vendor ID 3 | # usb_vid = "1337" 4 | # USB product ID 5 | # usb_pid = "1337" 6 | # Serial number 7 | # serial = "12345678" 8 | # The protocol to be used for communicating with the target. 9 | protocol = "Swd" 10 | # The speed in kHz of the data link to the target. 11 | # speed = 1337 12 | 13 | [default.flashing] 14 | # Whether or not the target should be flashed. 15 | enabled = true 16 | # Whether or not the target should be halted after reset. 17 | # DEPRECATED, moved to reset section 18 | halt_afterwards = false 19 | # Whether or not bytes erased but not rewritten with data from the ELF 20 | # should be restored with their contents before erasing. 21 | restore_unwritten_bytes = false 22 | # The path where an SVG of the assembled flash layout should be written to. 23 | # flash_layout_output_path = "out.svg" 24 | 25 | [default.reset] 26 | # Whether or not the target should be reset. 27 | # When flashing is enabled as well, the target will be reset after flashing. 28 | enabled = true 29 | # Whether or not the target should be halted after reset. 30 | halt_afterwards = false 31 | 32 | [default.general] 33 | # The chip name of the chip to be debugged. 34 | chip = "nRF52840_xxAA" 35 | # A list of chip descriptions to be loaded during runtime. 36 | chip_descriptions = [] 37 | # The default log level to be used. Possible values are one of: 38 | # "OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" 39 | log_level = "WARN" 40 | 41 | [default.rtt] 42 | # Whether or not an RTTUI should be opened after flashing. 43 | # This is exclusive and cannot be used with GDB at the moment. 44 | enabled = true 45 | # A list of channel associations to be displayed. If left empty, all channels are displayed. 46 | channels = [ 47 | # { up = 0, down = 0, name = "name", format = "String" } 48 | ] 49 | # The duration in ms for which the logger should retry to attach to RTT. 50 | timeout = 3000 51 | # Whether timestamps in the RTTUI are enabled 52 | show_timestamps = true 53 | # Whether to save rtt history buffer on exit. 54 | log_enabled = false 55 | # Where to save rtt history buffer relative to manifest path. 56 | log_path = "./logs" 57 | 58 | [default.gdb] 59 | # Whether or not a GDB server should be opened after flashing. 60 | # This is exclusive and cannot be used with RTT at the moment. 61 | enabled = false 62 | # The connection string in host:port format wher the GDB server will open a socket. 63 | # gdb_connection_string 64 | -------------------------------------------------------------------------------- /examples/nvmc-demo/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 | -------------------------------------------------------------------------------- /examples/nvmc-demo/memory.x: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | /* NOTE 1 K = 1 KiB = 1024 bytes */ 4 | FLASH : ORIGIN = 0x00000000, LENGTH = 1024K - NUM_PAGES * 4K 5 | CONFIG : ORIGIN = ORIGIN(FLASH) + LENGTH(FLASH), LENGTH = NUM_PAGES * 4K 6 | RAM : ORIGIN = 0x20000000, LENGTH = 256K 7 | } 8 | 9 | NUM_PAGES = 6; 10 | _config = ORIGIN(CONFIG); 11 | 12 | /* This is where the call stack will be allocated. */ 13 | /* The stack is of the full descending type. */ 14 | /* You may want to use this variable to locate the call stack and static 15 | variables in different memory regions. Below is shown the default value */ 16 | /* _stack_start = ORIGIN(RAM) + LENGTH(RAM); */ 17 | 18 | /* You can use this symbol to customize the location of the .text section */ 19 | /* If omitted the .text section will be placed right after the .vector_table 20 | section */ 21 | /* This is required only on microcontrollers that store some configuration right 22 | after the vector table */ 23 | /* _stext = ORIGIN(FLASH) + 0x400; */ 24 | 25 | /* Example of putting non-initialized variables into custom RAM locations. */ 26 | /* This assumes you have defined a region RAM2 above, and in the Rust 27 | sources added the attribute `#[link_section = ".ram2bss"]` to the data 28 | you want to place there. */ 29 | /* Note that the section will not be zero-initialized by the runtime! */ 30 | /* SECTIONS { 31 | .ram2bss (NOLOAD) : ALIGN(4) { 32 | *(.ram2bss); 33 | . = ALIGN(4); 34 | } > RAM2 35 | } INSERT AFTER .bss; 36 | */ 37 | -------------------------------------------------------------------------------- /examples/ppi-demo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ppi-demo" 3 | version = "0.0.1" 4 | edition = "2018" 5 | authors = [ "Thales Fragoso "] 6 | publish = false 7 | 8 | [dependencies] 9 | cortex-m = { version = "0.7.3", features = ["critical-section-single-core"] } 10 | cortex-m-rt = "0.7.0" 11 | rtt-target = "0.6.0" 12 | 13 | nrf52805-hal = { path = "../../nrf52805-hal", features = ["rt"], optional = true } 14 | nrf52810-hal = { path = "../../nrf52810-hal", features = ["rt"], optional = true } 15 | nrf52811-hal = { path = "../../nrf52811-hal", features = ["rt"], optional = true } 16 | nrf52832-hal = { path = "../../nrf52832-hal", features = ["rt"], optional = true } 17 | nrf52840-hal = { path = "../../nrf52840-hal", features = ["rt"], optional = true } 18 | nrf52833-hal = { path = "../../nrf52833-hal", features = ["rt"], optional = true } 19 | nrf51-hal = { path = "../../nrf51-hal", features = ["rt"], optional = true} 20 | 21 | [[bin]] 22 | name = "ppi-demo" 23 | doc = false 24 | test = false 25 | 26 | [features] 27 | 51 = ["nrf51-hal"] 28 | 52805 = ["nrf52805-hal"] 29 | 52810 = ["nrf52810-hal"] 30 | 52811 = ["nrf52811-hal"] 31 | 52832 = ["nrf52832-hal"] 32 | 52840 = ["nrf52840-hal"] 33 | 52833 = ["nrf52833-hal"] 34 | -------------------------------------------------------------------------------- /examples/ppi-demo/Embed.toml: -------------------------------------------------------------------------------- 1 | [default.probe] 2 | # USB vendor ID 3 | # usb_vid = "1337" 4 | # USB product ID 5 | # usb_pid = "1337" 6 | # Serial number 7 | # serial = "12345678" 8 | # The protocol to be used for communicating with the target. 9 | protocol = "Swd" 10 | # The speed in kHz of the data link to the target. 11 | # speed = 1337 12 | 13 | [default.flashing] 14 | # Whether or not the target should be flashed. 15 | enabled = true 16 | # Whether or not the target should be halted after reset. 17 | # DEPRECATED, moved to reset section 18 | halt_afterwards = false 19 | # Whether or not bytes erased but not rewritten with data from the ELF 20 | # should be restored with their contents before erasing. 21 | restore_unwritten_bytes = false 22 | # The path where an SVG of the assembled flash layout should be written to. 23 | # flash_layout_output_path = "out.svg" 24 | 25 | [default.reset] 26 | # Whether or not the target should be reset. 27 | # When flashing is enabled as well, the target will be reset after flashing. 28 | enabled = true 29 | # Whether or not the target should be halted after reset. 30 | halt_afterwards = false 31 | 32 | [default.general] 33 | # The chip name of the chip to be debugged. 34 | chip = "nRF52832_xxAA" 35 | # A list of chip descriptions to be loaded during runtime. 36 | chip_descriptions = [] 37 | # The default log level to be used. Possible values are one of: 38 | # "OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" 39 | log_level = "WARN" 40 | 41 | [default.rtt] 42 | # Whether or not an RTTUI should be opened after flashing. 43 | # This is exclusive and cannot be used with GDB at the moment. 44 | enabled = true 45 | # A list of channel associations to be displayed. If left empty, all channels are displayed. 46 | channels = [ 47 | # { up = 0, down = 0, name = "name", format = "String" } 48 | ] 49 | # The duration in ms for which the logger should retry to attach to RTT. 50 | timeout = 3000 51 | # Whether timestamps in the RTTUI are enabled 52 | show_timestamps = true 53 | # Whether to save rtt history buffer on exit. 54 | log_enabled = false 55 | # Where to save rtt history buffer relative to manifest path. 56 | log_path = "./logs" 57 | 58 | [default.gdb] 59 | # Whether or not a GDB server should be opened after flashing. 60 | # This is exclusive and cannot be used with RTT at the moment. 61 | enabled = false 62 | # The connection string in host:port format wher the GDB server will open a socket. 63 | # gdb_connection_string 64 | -------------------------------------------------------------------------------- /examples/ppi-demo/README.md: -------------------------------------------------------------------------------- 1 | # PPI demo 2 | 3 | The Programmable Peripheral Interconnect (PPI) allows peripherals to interact with each other without having to go through the CPU. Note that you need to choose a chip feature in order for this demo to build. See above. This demo uses the Bluetooth RADIO peripheral as an example but does nothing special with Bluetooth itself so this is not the demo to learn about that capability. 4 | 5 | ## How to run 6 | 7 | Choose the microcontroller with one of the following features: 8 | - 51 9 | - 52805 10 | - 52810 11 | - 52811 12 | - 52832 13 | - 52840 14 | 15 | Also, if using `cargo-embed`, change the `chip` and `protocol` fields in [Embed.toml](Embed.toml). 16 | 17 | This demo uses the [rtt-target](https://crates.io/crates/rtt-target) crate for communication. 18 | 19 | If using `cargo-embed`, just run 20 | 21 | ```console 22 | $ cargo embed --release --features=52832 --target=thumbv7em-none-eabihf 23 | ``` 24 | 25 | Replace `52832` and `thumbv7em-none-eabihf` with the correct feature and target for your microcontroller. 26 | -------------------------------------------------------------------------------- /examples/ppi-demo/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | #[cfg(not(any( 5 | feature = "51", 6 | feature = "52805", 7 | feature = "52810", 8 | feature = "52811", 9 | feature = "52832", 10 | feature = "52833", 11 | feature = "52840" 12 | )))] 13 | compile_error!( 14 | "This example requires one of the following device features enabled: 15 | 51 16 | 52805 17 | 52810 18 | 52811 19 | 52832 20 | 52833 21 | 52840" 22 | ); 23 | 24 | // Import the right HAL/PAC crate, depending on the target chip 25 | #[cfg(feature = "51")] 26 | pub use nrf51_hal as hal; 27 | #[cfg(feature = "52805")] 28 | pub use nrf52805_hal as hal; 29 | #[cfg(feature = "52810")] 30 | pub use nrf52810_hal as hal; 31 | #[cfg(feature = "52811")] 32 | pub use nrf52811_hal as hal; 33 | #[cfg(feature = "52832")] 34 | pub use nrf52832_hal as hal; 35 | #[cfg(feature = "52833")] 36 | pub use nrf52833_hal as hal; 37 | #[cfg(feature = "52840")] 38 | pub use nrf52840_hal as hal; 39 | 40 | use { 41 | core::{ 42 | cell::RefCell, 43 | panic::PanicInfo, 44 | sync::atomic::{compiler_fence, Ordering}, 45 | }, 46 | cortex_m::interrupt::Mutex, 47 | cortex_m_rt::entry, 48 | hal::{ 49 | pac::{interrupt, Interrupt, RADIO}, 50 | ppi, 51 | prelude::*, 52 | timer::Timer, 53 | Clocks, 54 | }, 55 | rtt_target::{rprintln, rtt_init_print}, 56 | }; 57 | 58 | static RADIO_REGS: Mutex>> = Mutex::new(RefCell::new(None)); 59 | 60 | #[entry] 61 | fn main() -> ! { 62 | let p = hal::pac::Peripherals::take().unwrap(); 63 | 64 | let _clocks = Clocks::new(p.CLOCK).enable_ext_hfosc(); 65 | rtt_init_print!(); 66 | 67 | let ppi_channels = ppi::Parts::new(p.PPI); 68 | let mut channel0 = ppi_channels.ppi0; 69 | 70 | channel0.set_task_endpoint(&p.RADIO.tasks_disable); 71 | channel0.set_event_endpoint(&p.TIMER0.events_compare[0]); 72 | channel0.enable(); 73 | 74 | let radio = p.RADIO; 75 | radio.intenset.write(|w| w.disabled().set()); 76 | cortex_m::interrupt::free(|cs| RADIO_REGS.borrow(cs).replace(Some(radio))); 77 | // NOTE(unsafe) There isn't any abstraction depending on this interrupt being masked 78 | unsafe { 79 | cortex_m::peripheral::NVIC::unmask(Interrupt::RADIO); 80 | } 81 | 82 | let mut timer = Timer::one_shot(p.TIMER0); 83 | timer.start(0xFFFFu32); 84 | 85 | loop { 86 | // Prevent empty loop optimizations 87 | compiler_fence(Ordering::SeqCst); 88 | } 89 | } 90 | 91 | #[interrupt] 92 | fn RADIO() { 93 | cortex_m::interrupt::free(|cs| { 94 | if let Some(regs) = RADIO_REGS.borrow(cs).borrow_mut().as_mut() { 95 | if regs.events_disabled.read().bits() == 1 { 96 | rprintln!("We hit the RADIO disabled interrupt"); 97 | 98 | // Clear the disabled flag 99 | // NOTE(unsafe) 0 is a valid value to write to this register 100 | regs.events_disabled.write(|w| unsafe { w.bits(0) }); 101 | } 102 | } 103 | }); 104 | } 105 | 106 | #[inline(never)] 107 | #[panic_handler] 108 | fn panic(info: &PanicInfo) -> ! { 109 | cortex_m::interrupt::disable(); 110 | rprintln!("{}", info); 111 | loop { 112 | compiler_fence(Ordering::SeqCst); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /examples/pwm-blinky-demo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pwm-blinky-demo" 3 | version = "0.1.0" 4 | authors = ["Christopher Hunt "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | cortex-m = { version = "0.7.3", features = ["critical-section-single-core"] } 9 | cortex-m-rt = "0.7.0" 10 | rtt-target = "0.6.0" 11 | nb = "1.0.0" 12 | 13 | [dependencies.nrf9160-hal] 14 | features = ["rt"] 15 | path = "../../nrf9160-hal" 16 | optional = true 17 | 18 | [dependencies.nrf52832-hal] 19 | features = ["rt"] 20 | path = "../../nrf52832-hal" 21 | optional = true 22 | 23 | [dependencies.nrf52840-hal] 24 | features = ["rt"] 25 | path = "../../nrf52840-hal" 26 | optional = true 27 | 28 | [features] 29 | 9160 = ["nrf9160-hal"] 30 | 52840 = ["nrf52840-hal"] 31 | 52832 = ["nrf52832-hal"] 32 | -------------------------------------------------------------------------------- /examples/pwm-blinky-demo/Embed.toml: -------------------------------------------------------------------------------- 1 | [default.probe] 2 | # USB vendor ID 3 | # usb_vid = "1337" 4 | # USB product ID 5 | # usb_pid = "1337" 6 | # Serial number 7 | # serial = "12345678" 8 | # The protocol to be used for communicating with the target. 9 | protocol = "Swd" 10 | # The speed in kHz of the data link to the target. 11 | # speed = 1337 12 | 13 | [default.flashing] 14 | # Whether or not the target should be flashed. 15 | enabled = true 16 | # Whether or not the target should be halted after reset. 17 | # DEPRECATED, moved to reset section 18 | halt_afterwards = false 19 | # Whether or not bytes erased but not rewritten with data from the ELF 20 | # should be restored with their contents before erasing. 21 | restore_unwritten_bytes = false 22 | # The path where an SVG of the assembled flash layout should be written to. 23 | # flash_layout_output_path = "out.svg" 24 | 25 | [default.reset] 26 | # Whether or not the target should be reset. 27 | # When flashing is enabled as well, the target will be reset after flashing. 28 | enabled = true 29 | # Whether or not the target should be halted after reset. 30 | halt_afterwards = false 31 | 32 | [default.general] 33 | # The chip name of the chip to be debugged. 34 | chip = "nRF52840_xxAA" 35 | # A list of chip descriptions to be loaded during runtime. 36 | chip_descriptions = [] 37 | # The default log level to be used. Possible values are one of: 38 | # "OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" 39 | log_level = "WARN" 40 | 41 | [default.rtt] 42 | # Whether or not an RTTUI should be opened after flashing. 43 | # This is exclusive and cannot be used with GDB at the moment. 44 | enabled = true 45 | # A list of channel associations to be displayed. If left empty, all channels are displayed. 46 | channels = [ 47 | # { up = 0, down = 0, name = "name", format = "String" } 48 | ] 49 | # The duration in ms for which the logger should retry to attach to RTT. 50 | timeout = 3000 51 | # Whether timestamps in the RTTUI are enabled 52 | show_timestamps = true 53 | # Whether to save rtt history buffer on exit. 54 | log_enabled = false 55 | # Where to save rtt history buffer relative to manifest path. 56 | log_path = "./logs" 57 | 58 | [default.gdb] 59 | # Whether or not a GDB server should be opened after flashing. 60 | # This is exclusive and cannot be used with RTT at the moment. 61 | enabled = false 62 | # The connection string in host:port format wher the GDB server will open a socket. 63 | # gdb_connection_string 64 | -------------------------------------------------------------------------------- /examples/pwm-blinky-demo/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 | fn main() { 12 | // We only need the memory.x file for the nRF9160 as our program 13 | // must then reside in a location where unsecure programs need to be. 14 | #[cfg(feature = "9160")] 15 | { 16 | use std::env; 17 | use std::fs::File; 18 | use std::io::Write; 19 | use std::path::PathBuf; 20 | 21 | // Put `memory.x` in our output directory and ensure it's 22 | // on the linker search path. 23 | let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); 24 | File::create(out.join("memory.x")) 25 | .unwrap() 26 | .write_all(include_bytes!("memory.x")) 27 | .unwrap(); 28 | println!("cargo:rustc-link-search={}", out.display()); 29 | 30 | // By default, Cargo will re-run a build script whenever 31 | // any file in the project changes. By specifying `memory.x` 32 | // here, we ensure the build script is only re-run when 33 | // `memory.x` is changed. 34 | println!("cargo:rerun-if-changed=memory.x"); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /examples/pwm-blinky-demo/memory.x: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | /* NOTE 1 K = 1 KiBi = 1024 bytes */ 4 | FLASH : ORIGIN = 0x00050000, LENGTH = 768K 5 | RAM : ORIGIN = 0x20020000, LENGTH = 128K 6 | } 7 | 8 | /* This is where the call stack will be allocated. */ 9 | /* The stack is of the full descending type. */ 10 | /* You may want to use this variable to locate the call stack and static 11 | variables in different memory regions. Below is shown the default value */ 12 | /* _stack_start = ORIGIN(RAM) + LENGTH(RAM); */ 13 | 14 | /* You can use this symbol to customize the location of the .text section */ 15 | /* If omitted the .text section will be placed right after the .vector_table 16 | section */ 17 | /* This is required only on microcontrollers that store some configuration right 18 | after the vector table */ 19 | /* _stext = ORIGIN(FLASH) + 0x400; */ 20 | 21 | /* Example of putting non-initialized variables into custom RAM locations. */ 22 | /* This assumes you have defined a region RAM2 above, and in the Rust 23 | sources added the attribute `#[link_section = ".ram2bss"]` to the data 24 | you want to place there. */ 25 | /* Note that the section will not be zero-initialized by the runtime! */ 26 | /* SECTIONS { 27 | .ram2bss (NOLOAD) : ALIGN(4) { 28 | *(.ram2bss); 29 | . = ALIGN(4); 30 | } > RAM2 31 | } INSERT AFTER .bss; 32 | */ 33 | -------------------------------------------------------------------------------- /examples/pwm-blinky-demo/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | 4 | use hal::{ 5 | gpio, 6 | prelude::*, 7 | pwm::{Channel, Pwm}, 8 | timer::Timer, 9 | }; 10 | #[cfg(feature = "52832")] 11 | use nrf52832_hal as hal; 12 | #[cfg(feature = "52840")] 13 | use nrf52840_hal as hal; 14 | #[cfg(feature = "9160")] 15 | use nrf9160_hal as hal; 16 | use rtt_target::{rprintln, rtt_init_print}; 17 | 18 | #[panic_handler] // panicking behavior 19 | fn panic(_: &core::panic::PanicInfo) -> ! { 20 | loop { 21 | cortex_m::asm::bkpt(); 22 | } 23 | } 24 | 25 | #[cortex_m_rt::entry] 26 | fn main() -> ! { 27 | rtt_init_print!(); 28 | 29 | let p = hal::pac::Peripherals::take().unwrap(); 30 | 31 | let (pwm, mut timer) = init_device(p); 32 | 33 | pwm.set_period(500u32.hz()); 34 | 35 | rprintln!("PWM Blinky demo starting"); 36 | 37 | let wait_time = 1_000_000u32 / pwm.max_duty() as u32; 38 | loop { 39 | for duty in 0..pwm.max_duty() { 40 | pwm.set_duty_on_common(duty); 41 | timer.delay(wait_time); 42 | } 43 | } 44 | } 45 | 46 | #[cfg(feature = "9160")] 47 | fn init_device(p: hal::pac::Peripherals) -> (Pwm, Timer) { 48 | let p0 = gpio::p0::Parts::new(p.P0_NS); 49 | 50 | let pwm = Pwm::new(p.PWM0_NS); 51 | pwm.set_output_pin( 52 | Channel::C0, 53 | p0.p0_02.into_push_pull_output(gpio::Level::High).degrade(), 54 | ); 55 | 56 | let timer = Timer::new(p.TIMER0_NS); 57 | 58 | (pwm, timer) 59 | } 60 | 61 | #[cfg(feature = "52840")] 62 | fn init_device(p: hal::pac::Peripherals) -> (Pwm, Timer) { 63 | let p0 = gpio::p0::Parts::new(p.P0); 64 | 65 | let pwm = Pwm::new(p.PWM0); 66 | pwm.set_output_pin( 67 | Channel::C0, 68 | p0.p0_13.into_push_pull_output(gpio::Level::High).degrade(), 69 | ); 70 | 71 | let timer = Timer::new(p.TIMER0); 72 | 73 | (pwm, timer) 74 | } 75 | 76 | #[cfg(feature = "52832")] 77 | fn init_device(p: hal::pac::Peripherals) -> (Pwm, Timer) { 78 | let p0 = gpio::p0::Parts::new(p.P0); 79 | 80 | let pwm = Pwm::new(p.PWM0); 81 | pwm.set_output_pin( 82 | Channel::C0, 83 | p0.p0_30.into_push_pull_output(gpio::Level::High).degrade(), 84 | ); 85 | 86 | let timer = Timer::new(p.TIMER0); 87 | 88 | (pwm, timer) 89 | } 90 | -------------------------------------------------------------------------------- /examples/pwm-demo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pwm-demo" 3 | version = "0.1.0" 4 | authors = ["Henrik Alsér"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | cortex-m = { version = "0.7.3", features = ["critical-section-single-core"] } 9 | cortex-m-rt = { version = "0.7.0", features = ["device"] } 10 | cortex-m-rtic = { version = "1.0.0", default-features = false } 11 | embedded-hal = "1.0" 12 | systick-monotonic = "1.0.0" 13 | rtt-target = "0.6.0" 14 | 15 | [dependencies.nrf52840-hal] 16 | features = ["rt"] 17 | path = "../../nrf52840-hal" 18 | -------------------------------------------------------------------------------- /examples/pwm-demo/Embed.toml: -------------------------------------------------------------------------------- 1 | [default.probe] 2 | # USB vendor ID 3 | # usb_vid = "1337" 4 | # USB product ID 5 | # usb_pid = "1337" 6 | # Serial number 7 | # serial = "12345678" 8 | # The protocol to be used for communicating with the target. 9 | protocol = "Swd" 10 | # The speed in kHz of the data link to the target. 11 | # speed = 1337 12 | 13 | [default.flashing] 14 | # Whether or not the target should be flashed. 15 | enabled = true 16 | # Whether or not the target should be halted after reset. 17 | # DEPRECATED, moved to reset section 18 | halt_afterwards = false 19 | # Whether or not bytes erased but not rewritten with data from the ELF 20 | # should be restored with their contents before erasing. 21 | restore_unwritten_bytes = false 22 | # The path where an SVG of the assembled flash layout should be written to. 23 | # flash_layout_output_path = "out.svg" 24 | 25 | [default.reset] 26 | # Whether or not the target should be reset. 27 | # When flashing is enabled as well, the target will be reset after flashing. 28 | enabled = true 29 | # Whether or not the target should be halted after reset. 30 | halt_afterwards = false 31 | 32 | [default.general] 33 | # The chip name of the chip to be debugged. 34 | chip = "nRF52832_xxAA" 35 | # A list of chip descriptions to be loaded during runtime. 36 | chip_descriptions = [] 37 | # The default log level to be used. Possible values are one of: 38 | # "OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" 39 | log_level = "WARN" 40 | 41 | [default.rtt] 42 | # Whether or not an RTTUI should be opened after flashing. 43 | # This is exclusive and cannot be used with GDB at the moment. 44 | enabled = true 45 | # A list of channel associations to be displayed. If left empty, all channels are displayed. 46 | channels = [ 47 | # { up = 0, down = 0, name = "name", format = "String" } 48 | ] 49 | # The duration in ms for which the logger should retry to attach to RTT. 50 | timeout = 3000 51 | # Whether timestamps in the RTTUI are enabled 52 | show_timestamps = true 53 | # Whether to save rtt history buffer on exit. 54 | log_enabled = false 55 | # Where to save rtt history buffer relative to manifest path. 56 | log_path = "./logs" 57 | 58 | [default.gdb] 59 | # Whether or not a GDB server should be opened after flashing. 60 | # This is exclusive and cannot be used with RTT at the moment. 61 | enabled = false 62 | # The connection string in host:port format wher the GDB server will open a socket. 63 | # gdb_connection_string 64 | -------------------------------------------------------------------------------- /examples/pwm-demo/README.md: -------------------------------------------------------------------------------- 1 | # PWM demo 2 | 3 | The pulse width modulation (PWM) demo allows the user to press buttons to change demo modes. This outputs PWM signals to the built in LEDs on the nRF52840-DK. 4 | 5 | ## How to run 6 | 7 | If using `cargo-embed`, just run 8 | 9 | ```console 10 | $ cargo embed --release --target=thumbv7em-none-eabihf 11 | ``` -------------------------------------------------------------------------------- /examples/qdec-demo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "qdec-demo" 3 | version = "0.1.0" 4 | authors = ["Henrik Alsér"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | cortex-m = { version = "0.7.3", features = ["critical-section-single-core"] } 9 | cortex-m-rt = { version = "0.7.0", features = ["device"] } 10 | cortex-m-rtic = { version = "1.0.0", default-features = false } 11 | rtt-target = "0.6.0" 12 | nrf52840-hal = { features = ["rt"], path = "../../nrf52840-hal" } 13 | -------------------------------------------------------------------------------- /examples/qdec-demo/Embed.toml: -------------------------------------------------------------------------------- 1 | [default.probe] 2 | # USB vendor ID 3 | # usb_vid = "1337" 4 | # USB product ID 5 | # usb_pid = "1337" 6 | # Serial number 7 | # serial = "12345678" 8 | # The protocol to be used for communicating with the target. 9 | protocol = "Swd" 10 | # The speed in kHz of the data link to the target. 11 | # speed = 1337 12 | 13 | [default.flashing] 14 | # Whether or not the target should be flashed. 15 | enabled = true 16 | # Whether or not the target should be halted after reset. 17 | # DEPRECATED, moved to reset section 18 | halt_afterwards = false 19 | # Whether or not bytes erased but not rewritten with data from the ELF 20 | # should be restored with their contents before erasing. 21 | restore_unwritten_bytes = false 22 | # The path where an SVG of the assembled flash layout should be written to. 23 | # flash_layout_output_path = "out.svg" 24 | 25 | [default.reset] 26 | # Whether or not the target should be reset. 27 | # When flashing is enabled as well, the target will be reset after flashing. 28 | enabled = true 29 | # Whether or not the target should be halted after reset. 30 | halt_afterwards = false 31 | 32 | [default.general] 33 | # The chip name of the chip to be debugged. 34 | chip = "nRF52840" 35 | # A list of chip descriptions to be loaded during runtime. 36 | chip_descriptions = [] 37 | # The default log level to be used. Possible values are one of: 38 | # "OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" 39 | log_level = "WARN" 40 | 41 | [default.rtt] 42 | # Whether or not an RTTUI should be opened after flashing. 43 | # This is exclusive and cannot be used with GDB at the moment. 44 | enabled = true 45 | # A list of channel associations to be displayed. If left empty, all channels are displayed. 46 | channels = [ 47 | # { up = 0, down = 0, name = "name", format = "String" } 48 | ] 49 | # The duration in ms for which the logger should retry to attach to RTT. 50 | timeout = 3000 51 | # Whether timestamps in the RTTUI are enabled 52 | show_timestamps = true 53 | # Whether to save rtt history buffer on exit. 54 | log_enabled = false 55 | # Where to save rtt history buffer relative to manifest path. 56 | log_path = "./logs" 57 | 58 | [default.gdb] 59 | # Whether or not a GDB server should be opened after flashing. 60 | # This is exclusive and cannot be used with RTT at the moment. 61 | enabled = false 62 | # The connection string in host:port format wher the GDB server will open a socket. 63 | # gdb_connection_string 64 | -------------------------------------------------------------------------------- /examples/qdec-demo/README.md: -------------------------------------------------------------------------------- 1 | # QDEC demo 2 | 3 | The quadrature decoder (QDEC) is used to read sensor information. This peripheral supports buffered decoding of quadrature-encoded sensor signals (typically used for mechanical and optical sensors). The demo shows how to use a rotary encoder to trigger an interrupt and update a variable by the amount of rotation. (nRF52840 + Bourns PEC11R rotary encoder) 4 | 5 | ## How to run 6 | 7 | If using `cargo-embed`, just run 8 | 9 | ```console 10 | $ cargo embed --release --target=thumbv7em-none-eabihf 11 | ``` -------------------------------------------------------------------------------- /examples/qdec-demo/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use {core::panic::PanicInfo, nrf52840_hal as hal, rtt_target::rprintln}; 5 | 6 | #[rtic::app(device = crate::hal::pac, peripherals = true)] 7 | mod app { 8 | use { 9 | hal::qdec::*, 10 | nrf52840_hal as hal, 11 | rtt_target::{rprintln, rtt_init_print}, 12 | }; 13 | 14 | #[shared] 15 | struct Shared {} 16 | 17 | #[local] 18 | struct Local { 19 | qdec: Qdec, 20 | value: i16, 21 | } 22 | 23 | #[init] 24 | fn init(ctx: init::Context) -> (Shared, Local, init::Monotonics) { 25 | let _clocks = hal::clocks::Clocks::new(ctx.device.CLOCK).enable_ext_hfosc(); 26 | rtt_init_print!(); 27 | 28 | let p0 = hal::gpio::p0::Parts::new(ctx.device.P0); 29 | let pins = Pins { 30 | a: p0.p0_31.into_pullup_input().degrade(), 31 | b: p0.p0_30.into_pullup_input().degrade(), 32 | led: None, 33 | }; 34 | 35 | let qdec = Qdec::new(ctx.device.QDEC, pins, SamplePeriod::_128us); 36 | qdec.debounce(true) 37 | .enable_interrupt(NumSamples::_1smpl) 38 | .enable(); 39 | 40 | (Shared {}, Local { qdec, value: 0 }, init::Monotonics()) 41 | } 42 | 43 | #[task(binds = QDEC, local = [qdec, value])] 44 | fn on_qdec(ctx: on_qdec::Context) { 45 | ctx.local.qdec.reset_events(); 46 | *ctx.local.value += ctx.local.qdec.read(); 47 | rprintln!("Value: {}", ctx.local.value); 48 | } 49 | } 50 | 51 | #[inline(never)] 52 | #[panic_handler] 53 | fn panic(info: &PanicInfo) -> ! { 54 | cortex_m::interrupt::disable(); 55 | rprintln!("{}", info); 56 | loop {} 57 | } 58 | -------------------------------------------------------------------------------- /examples/rtc-demo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rtc-demo" 3 | version = "0.1.0" 4 | authors = ["Timo Kröger"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | cortex-m = { version = "0.7.3", features = ["critical-section-single-core"] } 9 | cortex-m-rt = "0.7.0" 10 | rtt-target = "0.6.0" 11 | nrf52840-hal = { features = ["rt"], path = "../../nrf52840-hal" } 12 | -------------------------------------------------------------------------------- /examples/rtc-demo/Embed.toml: -------------------------------------------------------------------------------- 1 | [default.rtt] 2 | enabled = true 3 | -------------------------------------------------------------------------------- /examples/rtc-demo/README.md: -------------------------------------------------------------------------------- 1 | # RTC demo 2 | 3 | This example shows how to use the compare functionality of the real-time counter peripheral. 4 | Runs on the nRF52840_DK but can easily be adapted for other hardware. 5 | 6 | ## Set up with `cargo-embed` 7 | 8 | Install `cargo-embed` if you don't have it already: 9 | 10 | ```console 11 | $ cargo install probe-rs-tools 12 | ``` 13 | 14 | Then just `cd` to the example folder and run 15 | 16 | ```console 17 | $ cargo embed --target thumbv7em-none-eabihf 18 | ``` 19 | -------------------------------------------------------------------------------- /examples/rtc-demo/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | 4 | use nrf52840_hal as hal; 5 | 6 | use core::{ 7 | cell::RefCell, 8 | sync::atomic::{AtomicBool, Ordering}, 9 | }; 10 | use cortex_m::interrupt::Mutex; 11 | use hal::pac::interrupt; 12 | use hal::rtc::{Rtc, RtcCompareReg, RtcInterrupt}; 13 | use rtt_target::{rprintln, rtt_init_print}; 14 | 15 | #[panic_handler] // panicking behavior 16 | fn panic(_: &core::panic::PanicInfo) -> ! { 17 | loop { 18 | cortex_m::asm::bkpt(); 19 | } 20 | } 21 | 22 | // We need to share the RTC between the main execution thread and an interrupt, hence the mutex. 23 | // They'll never be any contention though as interrupts cannot fire while there's a critical 24 | // section. Also note that the Mutex here is from cortex_m and is designed to work 25 | // only with single core processors. 26 | static RTC: Mutex>>> = Mutex::new(RefCell::new(None)); 27 | 28 | // Keep a flag to indicate that our timer has expired. 29 | static TIMER_EXPIRED: AtomicBool = AtomicBool::new(false); 30 | 31 | #[interrupt] 32 | fn RTC0() { 33 | cortex_m::interrupt::free(|cs| { 34 | let rtc = RTC.borrow(cs).borrow(); 35 | if let Some(rtc) = rtc.as_ref() { 36 | rtc.reset_event(RtcInterrupt::Compare0); 37 | rtc.clear_counter(); 38 | } 39 | }); 40 | 41 | TIMER_EXPIRED.store(true, Ordering::Relaxed); 42 | } 43 | 44 | #[cortex_m_rt::entry] 45 | fn main() -> ! { 46 | rtt_init_print!(); 47 | 48 | let mut cp = hal::pac::CorePeripherals::take().unwrap(); 49 | let p = hal::pac::Peripherals::take().unwrap(); 50 | 51 | // Enable the low-power/low-frequency clock which is required by the RTC. 52 | let clocks = hal::clocks::Clocks::new(p.CLOCK); 53 | let clocks = clocks.start_lfclk(); 54 | 55 | // Run RTC for 1 second (1hz == LFCLK_FREQ) 56 | let mut rtc = Rtc::new(p.RTC0, 0).unwrap(); 57 | rtc.set_compare(RtcCompareReg::Compare0, hal::clocks::LFCLK_FREQ) 58 | .unwrap(); 59 | rtc.enable_event(RtcInterrupt::Compare0); 60 | rtc.enable_interrupt(RtcInterrupt::Compare0, Some(&mut cp.NVIC)); 61 | 62 | rprintln!("Starting RTC"); 63 | rtc.enable_counter(); 64 | 65 | // Permit the interrupt to gain access to the RTC for the purpsoes of resetting etc 66 | cortex_m::interrupt::free(|cs| { 67 | RTC.borrow(cs).replace(Some(rtc)); 68 | }); 69 | 70 | rprintln!("Waiting for compare match"); 71 | 72 | while TIMER_EXPIRED.compare_exchange(true, false, Ordering::Relaxed, Ordering::Relaxed) 73 | != Ok(true) 74 | { 75 | // Go to sleep until we get an event (typically our RTC interrupt) 76 | cortex_m::asm::wfe(); 77 | } 78 | 79 | rprintln!("Compare match, stopping RTC"); 80 | 81 | if let Some(rtc) = cortex_m::interrupt::free(|cs| RTC.borrow(cs).replace(None)) { 82 | rtc.disable_counter(); 83 | 84 | rprintln!("Counter stopped at {} ticks", rtc.get_counter()); 85 | 86 | rtc.release(); 87 | } 88 | 89 | // Stop LfClk when RTC is not used anymore. 90 | clocks.stop_lfclk(); 91 | 92 | loop { 93 | cortex_m::asm::nop(); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /examples/rtic-demo/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.thumbv7em-none-eabihf] 2 | runner = "arm-none-eabi-gdb -tui" 3 | -------------------------------------------------------------------------------- /examples/rtic-demo/.gdbinit: -------------------------------------------------------------------------------- 1 | set remotetimeout 60000 2 | target remote :2331 3 | set arm force-mode thumb 4 | 5 | # Uncomment to enable semihosting, when necessary 6 | monitor semihosting enable 7 | 8 | layout split 9 | monitor reset 10 | load 11 | -------------------------------------------------------------------------------- /examples/rtic-demo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rtic-demo" 3 | version = "0.1.0" 4 | authors = ["James Munns "] 5 | edition = "2018" 6 | publish = false 7 | 8 | [dependencies] 9 | cortex-m-rtic = "1.0.0" 10 | panic-semihosting = "0.6.0" 11 | cortex-m-semihosting = "0.5.0" 12 | 13 | [dependencies.nrf51-hal] 14 | path = "../../nrf51-hal" 15 | optional = true 16 | 17 | [dependencies.nrf52805-hal] 18 | path = "../../nrf52805-hal" 19 | optional = true 20 | 21 | [dependencies.nrf52810-hal] 22 | path = "../../nrf52810-hal" 23 | optional = true 24 | 25 | [dependencies.nrf52811-hal] 26 | path = "../../nrf52811-hal" 27 | optional = true 28 | 29 | [dependencies.nrf52832-hal] 30 | path = "../../nrf52832-hal" 31 | optional = true 32 | 33 | [dependencies.nrf52840-hal] 34 | path = "../../nrf52840-hal" 35 | optional = true 36 | 37 | [features] 38 | 51 = ["nrf51-hal"] 39 | 52805 = ["nrf52805-hal"] 40 | 52810 = ["nrf52810-hal"] 41 | 52811 = ["nrf52811-hal"] 42 | 52832 = ["nrf52832-hal"] 43 | 52840 = ["nrf52840-hal"] 44 | -------------------------------------------------------------------------------- /examples/rtic-demo/README.md: -------------------------------------------------------------------------------- 1 | # RTIC demo 2 | 3 | The Real-Time Interrupt-driven Concurrency (RTIC) framework demo. Many of the demos in this project use RTIC and demonstrate its capabilities in more detail but this is a bare-bones default template for you to build off. RTIC is not unique to the nRF series but very useful for a program that requires concurrency. -------------------------------------------------------------------------------- /examples/rtic-demo/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | #![no_std] 3 | 4 | #[allow(unused_imports)] 5 | use panic_semihosting; 6 | 7 | use rtic::app; 8 | 9 | #[cfg(feature = "51")] 10 | use nrf51_hal as hal; 11 | 12 | #[cfg(feature = "52805")] 13 | use nrf52805_hal as hal; 14 | 15 | #[cfg(feature = "52810")] 16 | use nrf52810_hal as hal; 17 | 18 | #[cfg(feature = "52811")] 19 | use nrf52811_hal as hal; 20 | 21 | #[cfg(feature = "52832")] 22 | use nrf52832_hal as hal; 23 | 24 | #[cfg(feature = "52840")] 25 | use nrf52840_hal as hal; 26 | 27 | #[app(device = crate::hal::pac)] 28 | mod app { 29 | use cortex_m_semihosting::{debug, hprintln}; 30 | 31 | #[shared] 32 | struct Shared {} 33 | 34 | #[local] 35 | struct Local {} 36 | 37 | #[init] 38 | fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { 39 | hprintln!("init"); 40 | 41 | (Shared {}, Local {}, init::Monotonics()) 42 | } 43 | 44 | #[idle] 45 | fn idle(_: idle::Context) -> ! { 46 | hprintln!("idle"); 47 | 48 | debug::exit(debug::EXIT_SUCCESS); 49 | 50 | loop {} 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /examples/spi-demo/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.thumbv7em-none-eabihf] 2 | runner = "arm-none-eabi-gdb -tui" 3 | -------------------------------------------------------------------------------- /examples/spi-demo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "spi-demo" 3 | version = "0.1.0" 4 | authors = ["Fredrik Simonsson "] 5 | edition = "2018" 6 | publish = false 7 | 8 | [dependencies] 9 | cortex-m-rt = "0.7.0" 10 | embedded-hal = "1.0.0" 11 | panic-halt = "1.0.0" 12 | 13 | [dependencies.nrf52832-hal] 14 | path = "../../nrf52832-hal" 15 | optional = true 16 | 17 | [features] 18 | 52832 = ["nrf52832-hal"] 19 | default = ["52832"] 20 | -------------------------------------------------------------------------------- /examples/spi-demo/README.md: -------------------------------------------------------------------------------- 1 | # SPI master demo 2 | 3 | The Serial peripheral interface master (SPIM) with EasyDMA demo. Sends some text out on the SPI peripheral and loops it back on itself to demonstrate full duplex direct-memory-access based SPI data transfer. You'll need a resistor to connect the output to the input. Connect a resistor between pin 22 and 23 on the demo board to feed MOSI directly back to MISO. If all tests pass all four Led (Led1 to Led4) will light up, in case of error only at least one of the LEDs will remain turned off. 4 | 5 | ## HW connections 6 | 7 | Pin Connection 8 | P0.24 SPIclk 9 | P0.23 MOSI 10 | P0.22 MISO 11 | 12 | This is designed for nRF52-DK board: 13 | https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52-DK 14 | -------------------------------------------------------------------------------- /examples/spis-demo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "spis-demo" 3 | version = "0.1.0" 4 | authors = ["Henrik Alsér"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | cortex-m = { version = "0.7.3", features = ["critical-section-single-core"] } 9 | cortex-m-rt = { version = "0.7.0", features = ["device"] } 10 | cortex-m-rtic = { version = "1.0.0", default-features = false } 11 | rtt-target = "0.6.0" 12 | nrf52840-hal = { features = ["rt"], path = "../../nrf52840-hal" } 13 | -------------------------------------------------------------------------------- /examples/spis-demo/Embed.toml: -------------------------------------------------------------------------------- 1 | [default.probe] 2 | # USB vendor ID 3 | # usb_vid = "1337" 4 | # USB product ID 5 | # usb_pid = "1337" 6 | # Serial number 7 | # serial = "12345678" 8 | # The protocol to be used for communicating with the target. 9 | protocol = "Swd" 10 | # The speed in kHz of the data link to the target. 11 | # speed = 1337 12 | 13 | [default.flashing] 14 | # Whether or not the target should be flashed. 15 | enabled = true 16 | # Whether or not the target should be halted after reset. 17 | # DEPRECATED, moved to reset section 18 | halt_afterwards = false 19 | # Whether or not bytes erased but not rewritten with data from the ELF 20 | # should be restored with their contents before erasing. 21 | restore_unwritten_bytes = false 22 | # The path where an SVG of the assembled flash layout should be written to. 23 | # flash_layout_output_path = "out.svg" 24 | 25 | [default.reset] 26 | # Whether or not the target should be reset. 27 | # When flashing is enabled as well, the target will be reset after flashing. 28 | enabled = true 29 | # Whether or not the target should be halted after reset. 30 | halt_afterwards = false 31 | 32 | [default.general] 33 | # The chip name of the chip to be debugged. 34 | chip = "nRF52840" 35 | # A list of chip descriptions to be loaded during runtime. 36 | chip_descriptions = [] 37 | # The default log level to be used. Possible values are one of: 38 | # "OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" 39 | log_level = "WARN" 40 | 41 | [default.rtt] 42 | # Whether or not an RTTUI should be opened after flashing. 43 | # This is exclusive and cannot be used with GDB at the moment. 44 | enabled = true 45 | # A list of channel associations to be displayed. If left empty, all channels are displayed. 46 | channels = [ 47 | # { up = 0, down = 0, name = "name", format = "String" } 48 | ] 49 | # The duration in ms for which the logger should retry to attach to RTT. 50 | timeout = 3000 51 | # Whether timestamps in the RTTUI are enabled 52 | show_timestamps = true 53 | # Whether to save rtt history buffer on exit. 54 | log_enabled = false 55 | # Where to save rtt history buffer relative to manifest path. 56 | log_path = "./logs" 57 | 58 | [default.gdb] 59 | # Whether or not a GDB server should be opened after flashing. 60 | # This is exclusive and cannot be used with RTT at the moment. 61 | enabled = false 62 | # The connection string in host:port format wher the GDB server will open a socket. 63 | # gdb_connection_string 64 | -------------------------------------------------------------------------------- /examples/spis-demo/README.md: -------------------------------------------------------------------------------- 1 | # SPI slave demo 2 | 3 | The Serial peripheral interface slave (SPIS) demo. This demonstrates the SPIS module, transmitting the current buffer contents while receiving new data. Press the button to zero the buffer. 4 | 5 | ## How to run 6 | 7 | If using `cargo-embed`, just run 8 | 9 | ```console 10 | $ cargo embed --release --target=thumbv7em-none-eabihf 11 | ``` -------------------------------------------------------------------------------- /examples/spis-demo/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | // Demo for the SPIS module, transmitting the current buffer contents while receiving new data. 5 | // Press button to zero the buffer. 6 | 7 | use {core::panic::PanicInfo, nrf52840_hal as hal, rtt_target::rprintln}; 8 | 9 | #[rtic::app(device = crate::hal::pac, peripherals = true)] 10 | mod app { 11 | use { 12 | hal::{gpiote::Gpiote, pac::SPIS0, spis::*}, 13 | nrf52840_hal as hal, 14 | rtt_target::{rprintln, rtt_init_print}, 15 | }; 16 | 17 | #[shared] 18 | struct Shared { 19 | #[lock_free] 20 | transfer: Option>, 21 | } 22 | 23 | #[local] 24 | struct Local { 25 | gpiote: Gpiote, 26 | } 27 | 28 | #[init(local = [ 29 | BUF: [u8; 8] = [0; 8], 30 | ])] 31 | fn init(ctx: init::Context) -> (Shared, Local, init::Monotonics) { 32 | let BUF = ctx.local.BUF; 33 | 34 | let _clocks = hal::clocks::Clocks::new(ctx.device.CLOCK).enable_ext_hfosc(); 35 | rtt_init_print!(); 36 | rprintln!("Send me [u8; 8] over SPI"); 37 | rprintln!("Press button to reset buffer"); 38 | 39 | let p0 = hal::gpio::p0::Parts::new(ctx.device.P0); 40 | let cs_pin = p0.p0_25.into_floating_input().degrade(); 41 | let sck_pin = p0.p0_24.into_floating_input().degrade(); 42 | let copi_pin = p0.p0_16.into_floating_input().degrade(); 43 | let cipo_pin = p0.p0_14.into_floating_input().degrade(); 44 | 45 | let spis = Spis::new( 46 | ctx.device.SPIS0, 47 | Pins { 48 | sck: sck_pin, 49 | cs: cs_pin, 50 | copi: Some(copi_pin), 51 | cipo: Some(cipo_pin), 52 | }, 53 | ); 54 | spis.enable_interrupt(SpisEvent::End); 55 | 56 | let btn = p0.p0_29.into_pullup_input().degrade(); 57 | let gpiote = Gpiote::new(ctx.device.GPIOTE); 58 | gpiote.port().input_pin(&btn).low(); 59 | gpiote.port().enable_interrupt(); 60 | 61 | ( 62 | Shared { 63 | transfer: spis.transfer(BUF).ok(), 64 | }, 65 | Local { gpiote }, 66 | init::Monotonics(), 67 | ) 68 | } 69 | 70 | #[task(binds = GPIOTE, local = [gpiote], shared = [transfer])] 71 | fn on_gpiote(ctx: on_gpiote::Context) { 72 | ctx.local.gpiote.reset_events(); 73 | rprintln!("Reset buffer"); 74 | let (buf, spis) = ctx.shared.transfer.take().unwrap().wait(); 75 | buf.copy_from_slice(&[0; 8][..]); 76 | rprintln!("{:?}", buf); 77 | *ctx.shared.transfer = spis.transfer(buf).ok(); 78 | } 79 | 80 | #[task(binds = SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0, shared = [transfer])] 81 | fn on_spis(ctx: on_spis::Context) { 82 | let (buf, spis) = ctx.shared.transfer.take().unwrap().wait(); 83 | spis.reset_event(SpisEvent::End); 84 | rprintln!("Received: {:?}", buf); 85 | *ctx.shared.transfer = spis.transfer(buf).ok(); 86 | } 87 | } 88 | 89 | #[inline(never)] 90 | #[panic_handler] 91 | fn panic(info: &PanicInfo) -> ! { 92 | cortex_m::interrupt::disable(); 93 | rprintln!("{}", info); 94 | loop {} 95 | } 96 | -------------------------------------------------------------------------------- /examples/twi-ssd1306/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.thumbv7em-none-eabihf] 2 | runner = "arm-none-eabi-gdb -tui" 3 | -------------------------------------------------------------------------------- /examples/twi-ssd1306/.gdbinit: -------------------------------------------------------------------------------- 1 | set remotetimeout 60000 2 | target remote :2331 3 | set arm force-mode thumb 4 | 5 | # Uncomment to enable semihosting, when necessary 6 | monitor semihosting enable 7 | 8 | layout split 9 | monitor reset 10 | load 11 | -------------------------------------------------------------------------------- /examples/twi-ssd1306/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "twi-ssd1306" 3 | version = "0.1.0" 4 | authors = [ 5 | "James Waples ", 6 | "Ruben Paz ", 7 | ] 8 | edition = "2018" 9 | publish = false 10 | 11 | [dependencies] 12 | cortex-m-rt = "0.7.0" 13 | ssd1306 = "0.10.0" 14 | embedded-graphics = "0.8.1" 15 | panic-semihosting = "0.6.0" 16 | 17 | [dependencies.nrf52832-hal] 18 | path = "../../nrf52832-hal" 19 | optional = true 20 | 21 | [dependencies.nrf52840-hal] 22 | path = "../../nrf52840-hal" 23 | optional = true 24 | 25 | [features] 26 | 52832 = ["nrf52832-hal"] 27 | 52840 = ["nrf52840-hal"] 28 | -------------------------------------------------------------------------------- /examples/twi-ssd1306/README.md: -------------------------------------------------------------------------------- 1 | # TWI master with SSD1306 display demo 2 | 3 | The I2C compatible Two-Wire Interface Master (TWIM) communicating with an SSD1306 OLED Display demo. This demo uses the TWIM peripheral along with the embedded_graphics library to draw "Hello Rust!" to an SSD1306 OLED screen. Note that you need to set a chip feature to get this to compile. 4 | 5 | TWI write example using an SSD1306 OLED display: 6 | https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf 7 | 8 | After running it you should see the words "Hello Rust!" on the display. 9 | 10 | ## HW connections 11 | Pin Connection 12 | P0.26 SCL 13 | P0.27 SDA 14 | 15 | This is designed for the nRF52-DK & the nRF52840-DK board: 16 | https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52-DK 17 | https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK 18 | 19 | The TWI device is a 128x64px SSD1306 20 | https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf 21 | 22 | ## How to run 23 | 24 | If using `probe-run`, see parent folder readme for setup and then just run 25 | 26 | ```console 27 | $ cargo run 28 | ``` 29 | -------------------------------------------------------------------------------- /examples/twi-ssd1306/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | extern crate panic_semihosting; 5 | 6 | use cortex_m_rt::entry; 7 | use embedded_graphics::{mono_font::ascii::FONT_5X8, text::Text}; 8 | use embedded_graphics::{mono_font::MonoTextStyle, pixelcolor::BinaryColor, prelude::*}; 9 | use ssd1306::{prelude::*, I2CDisplayInterface, Ssd1306}; 10 | 11 | #[cfg(feature = "52832")] 12 | use nrf52832_hal::{ 13 | gpio::*, 14 | pac, 15 | twim::{self, Twim}, 16 | }; 17 | 18 | #[cfg(feature = "52840")] 19 | use nrf52840_hal::{ 20 | gpio::*, 21 | pac, 22 | twim::{self, Twim}, 23 | }; 24 | 25 | /// TWI write example code using an SSD1306 OLED display: 26 | /// https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf 27 | /// 28 | /// Connect SDA to P0.27 and SCL to pin P0.26 29 | /// 30 | /// You should see the words "Hello Rust!" on the display. 31 | #[entry] 32 | fn main() -> ! { 33 | let p = pac::Peripherals::take().unwrap(); 34 | let port0 = p0::Parts::new(p.P0); 35 | 36 | let scl = port0.p0_26.into_floating_input().degrade(); 37 | let sda = port0.p0_27.into_floating_input().degrade(); 38 | 39 | let pins = twim::Pins { scl, sda }; 40 | 41 | let i2c = Twim::new(p.TWIM0, pins, twim::Frequency::K100); 42 | 43 | let interface = I2CDisplayInterface::new(i2c); 44 | let mut disp = Ssd1306::new(interface, DisplaySize128x64, DisplayRotation::Rotate0) 45 | .into_buffered_graphics_mode(); 46 | 47 | disp.init().expect("Display initialization"); 48 | disp.flush().expect("Cleans the display"); 49 | 50 | let style = MonoTextStyle::new(&FONT_5X8, BinaryColor::On); 51 | Text::new("Hello Rust!", Point::new(10, 24), style) 52 | .draw(&mut disp) 53 | .expect("Drawing text"); 54 | 55 | disp.flush().expect("Render display"); 56 | 57 | loop {} 58 | } 59 | -------------------------------------------------------------------------------- /examples/twim-demo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "twim-demo" 3 | version = "0.1.0" 4 | authors = ["Henrik Alsér"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | cortex-m = { version = "0.7.3", features = ["critical-section-single-core"] } 9 | cortex-m-rt = { version = "0.7.0", features = ["device"] } 10 | cortex-m-rtic = { version = "1.0.0", default-features = false } 11 | embedded-hal = "1.0.0" 12 | systick-monotonic = "1.0.0" 13 | rtt-target = "0.6.0" 14 | nrf52840-hal = { features = ["rt"], path = "../../nrf52840-hal" } 15 | -------------------------------------------------------------------------------- /examples/twim-demo/Embed.toml: -------------------------------------------------------------------------------- 1 | [default.probe] 2 | # USB vendor ID 3 | # usb_vid = "1337" 4 | # USB product ID 5 | # usb_pid = "1337" 6 | # Serial number 7 | # serial = "12345678" 8 | # The protocol to be used for communicating with the target. 9 | protocol = "Swd" 10 | # The speed in kHz of the data link to the target. 11 | # speed = 1337 12 | 13 | [default.flashing] 14 | # Whether or not the target should be flashed. 15 | enabled = true 16 | # Whether or not the target should be halted after reset. 17 | # DEPRECATED, moved to reset section 18 | halt_afterwards = false 19 | # Whether or not bytes erased but not rewritten with data from the ELF 20 | # should be restored with their contents before erasing. 21 | restore_unwritten_bytes = false 22 | # The path where an SVG of the assembled flash layout should be written to. 23 | # flash_layout_output_path = "out.svg" 24 | 25 | [default.reset] 26 | # Whether or not the target should be reset. 27 | # When flashing is enabled as well, the target will be reset after flashing. 28 | enabled = true 29 | # Whether or not the target should be halted after reset. 30 | halt_afterwards = false 31 | 32 | [default.general] 33 | # The chip name of the chip to be debugged. 34 | chip = "nRF52840" 35 | # A list of chip descriptions to be loaded during runtime. 36 | chip_descriptions = [] 37 | # The default log level to be used. Possible values are one of: 38 | # "OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" 39 | log_level = "WARN" 40 | 41 | [default.rtt] 42 | # Whether or not an RTTUI should be opened after flashing. 43 | # This is exclusive and cannot be used with GDB at the moment. 44 | enabled = true 45 | # A list of channel associations to be displayed. If left empty, all channels are displayed. 46 | channels = [ 47 | # { up = 0, down = 0, name = "name", format = "String" } 48 | ] 49 | # The duration in ms for which the logger should retry to attach to RTT. 50 | timeout = 3000 51 | # Whether timestamps in the RTTUI are enabled 52 | show_timestamps = true 53 | # Whether to save rtt history buffer on exit. 54 | log_enabled = false 55 | # Where to save rtt history buffer relative to manifest path. 56 | log_path = "./logs" 57 | 58 | [default.gdb] 59 | # Whether or not a GDB server should be opened after flashing. 60 | # This is exclusive and cannot be used with RTT at the moment. 61 | enabled = false 62 | # The connection string in host:port format wher the GDB server will open a socket. 63 | # gdb_connection_string 64 | -------------------------------------------------------------------------------- /examples/twim-demo/README.md: -------------------------------------------------------------------------------- 1 | # TWIM demo 2 | 3 | The I2C compatible Two-Wire Interface Master mode (TWIM) demo. This demo uses the TWIM peripheral to read and write 8 bytes of data to arbitrary addresses on a device that are connected to the I2C pins p0_30 and p0_31. It demonstrates error handling if the device does not respond properly (or it is not connected). 4 | 5 | ## How to run 6 | 7 | If using `cargo-embed`, just run 8 | 9 | ```console 10 | $ cargo embed --release --target=thumbv7em-none-eabihf 11 | ``` -------------------------------------------------------------------------------- /examples/twis-demo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "twis-demo" 3 | version = "0.1.0" 4 | authors = ["Henrik Alsér"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | cortex-m = { version = "0.7.3", features = ["critical-section-single-core"] } 9 | cortex-m-rt = { version = "0.7.0", features = ["device"] } 10 | cortex-m-rtic = { version = "1.0.0", default-features = false } 11 | embedded-hal = "1.0.0" 12 | rtt-target = "0.6.0" 13 | nrf52840-hal = { features = ["rt"], path = "../../nrf52840-hal" } 14 | -------------------------------------------------------------------------------- /examples/twis-demo/Embed.toml: -------------------------------------------------------------------------------- 1 | [default.probe] 2 | # USB vendor ID 3 | # usb_vid = "1337" 4 | # USB product ID 5 | # usb_pid = "1337" 6 | # Serial number 7 | # serial = "12345678" 8 | # The protocol to be used for communicating with the target. 9 | protocol = "Swd" 10 | # The speed in kHz of the data link to the target. 11 | # speed = 1337 12 | 13 | [default.flashing] 14 | # Whether or not the target should be flashed. 15 | enabled = true 16 | # Whether or not the target should be halted after reset. 17 | # DEPRECATED, moved to reset section 18 | halt_afterwards = false 19 | # Whether or not bytes erased but not rewritten with data from the ELF 20 | # should be restored with their contents before erasing. 21 | restore_unwritten_bytes = false 22 | # The path where an SVG of the assembled flash layout should be written to. 23 | # flash_layout_output_path = "out.svg" 24 | 25 | [default.reset] 26 | # Whether or not the target should be reset. 27 | # When flashing is enabled as well, the target will be reset after flashing. 28 | enabled = true 29 | # Whether or not the target should be halted after reset. 30 | halt_afterwards = false 31 | 32 | [default.general] 33 | # The chip name of the chip to be debugged. 34 | chip = "nRF52840" 35 | # A list of chip descriptions to be loaded during runtime. 36 | chip_descriptions = [] 37 | # The default log level to be used. Possible values are one of: 38 | # "OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" 39 | log_level = "WARN" 40 | 41 | [default.rtt] 42 | # Whether or not an RTTUI should be opened after flashing. 43 | # This is exclusive and cannot be used with GDB at the moment. 44 | enabled = true 45 | # A list of channel associations to be displayed. If left empty, all channels are displayed. 46 | channels = [ 47 | # { up = 0, down = 0, name = "name", format = "String" } 48 | ] 49 | # The duration in ms for which the logger should retry to attach to RTT. 50 | timeout = 3000 51 | # Whether timestamps in the RTTUI are enabled 52 | show_timestamps = true 53 | # Whether to save rtt history buffer on exit. 54 | log_enabled = false 55 | # Where to save rtt history buffer relative to manifest path. 56 | log_path = "./logs" 57 | 58 | [default.gdb] 59 | # Whether or not a GDB server should be opened after flashing. 60 | # This is exclusive and cannot be used with RTT at the moment. 61 | enabled = false 62 | # The connection string in host:port format wher the GDB server will open a socket. 63 | # gdb_connection_string 64 | -------------------------------------------------------------------------------- /examples/twis-demo/README.md: -------------------------------------------------------------------------------- 1 | # TWIS demo 2 | 3 | I2C compatible Two-Wire Interface Slave mode (TWIS) demo. This demo uses the TWIS peripheral with RTIC (Real-Time Interrupt-driven Concurrency) to listen for I2C signals which are exposed as events. The event handler reads data from the peripheral at the address specified. 4 | 5 | ## How to run 6 | 7 | If using `cargo-embed`, just run 8 | 9 | ```console 10 | $ cargo embed --release --target=thumbv7em-none-eabihf 11 | ``` -------------------------------------------------------------------------------- /examples/twis-dma-demo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "twis-dma-demo" 3 | version = "0.1.0" 4 | authors = ["Henrik Alsér"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | cortex-m = { version = "0.7.3", features = ["critical-section-single-core"] } 9 | cortex-m-rt = { version = "0.7.0", features = ["device"] } 10 | cortex-m-rtic = { version = "1.0.0", default-features = false } 11 | rtt-target = "0.6.0" 12 | nrf52840-hal = { features = ["rt"], path = "../../nrf52840-hal" } 13 | -------------------------------------------------------------------------------- /examples/twis-dma-demo/Embed.toml: -------------------------------------------------------------------------------- 1 | [default.probe] 2 | # The index of the probe in the connected probe list. 3 | # probe_index = 0 4 | # The protocol to be used for communicating with the target. 5 | protocol = "Swd" 6 | # The speed in kHz of the data link to the target. 7 | # speed = 1337 8 | 9 | [default.flashing] 10 | # Whether or not the target should be flashed. 11 | enabled = true 12 | # Whether or not the target should be halted after flashing. 13 | halt_afterwards = false 14 | # Whether or not bytes erased but not rewritten with data from the ELF 15 | # should be restored with their contents before erasing. 16 | restore_unwritten_bytes = false 17 | # The path where an SVG of the assembled flash layout should be written to. 18 | # flash_layout_output_path = "out.svg" 19 | 20 | [default.general] 21 | # The chip name of the chip to be debugged. 22 | chip = "nRF52840" 23 | # A list of chip descriptions to be loaded during runtime. 24 | chip_descriptions = [] 25 | # The default log level to be used. 26 | log_level = "Warn" 27 | 28 | [default.rtt] 29 | # Whether or not an RTTUI should be opened after flashing. 30 | # This is exclusive and cannot be used with GDB at the moment. 31 | enabled = true 32 | # A list of channel associations to be displayed. If left empty, all channels are displayed. 33 | channels = [ 34 | # { up = 0, down = 0, name = "name" } 35 | ] 36 | # The duration in ms for which the logger should retry to attach to RTT. 37 | timeout = 3000 38 | # Whether timestamps in the RTTUI are enabled 39 | show_timestamps = true 40 | 41 | [default.gdb] 42 | # Whether or not a GDB server should be opened after flashing. 43 | # This is exclusive and cannot be used with RTT at the moment. 44 | enabled = false 45 | # The connection string in host:port format wher the GDB server will open a socket. 46 | # gdb_connection_string -------------------------------------------------------------------------------- /examples/usb/.gdbinit: -------------------------------------------------------------------------------- 1 | # disable "are you sure you want to quit?" 2 | define hook-quit 3 | set confirm off 4 | end 5 | 6 | target remote :3333 7 | 8 | # print demangled symbols by default 9 | set print asm-demangle on 10 | 11 | monitor arm semihosting enable 12 | load 13 | cont 14 | -------------------------------------------------------------------------------- /examples/usb/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "usb" 3 | version = "0.1.0" 4 | authors = ["Jonas Schievink "] 5 | edition = "2018" 6 | publish = false 7 | 8 | [dependencies] 9 | cortex-m-rt = "0.7.3" 10 | panic-semihosting = "0.6.0" 11 | usb-device = "0.3.2" 12 | usbd-serial = "0.2.1" 13 | 14 | [dependencies.nrf52840-hal] 15 | path = "../../nrf52840-hal" 16 | -------------------------------------------------------------------------------- /examples/usb/Embed.toml: -------------------------------------------------------------------------------- 1 | [default.probe] 2 | # USB vendor ID 3 | # usb_vid = "1337" 4 | # USB product ID 5 | # usb_pid = "1337" 6 | # Serial number 7 | # serial = "12345678" 8 | # The protocol to be used for communicating with the target. 9 | protocol = "Swd" 10 | # The speed in kHz of the data link to the target. 11 | # speed = 1337 12 | 13 | [default.flashing] 14 | # Whether or not the target should be flashed. 15 | enabled = true 16 | # Whether or not the target should be halted after reset. 17 | # DEPRECATED, moved to reset section 18 | halt_afterwards = false 19 | # Whether or not bytes erased but not rewritten with data from the ELF 20 | # should be restored with their contents before erasing. 21 | restore_unwritten_bytes = false 22 | # The path where an SVG of the assembled flash layout should be written to. 23 | # flash_layout_output_path = "out.svg" 24 | 25 | [default.reset] 26 | # Whether or not the target should be reset. 27 | # When flashing is enabled as well, the target will be reset after flashing. 28 | enabled = true 29 | # Whether or not the target should be halted after reset. 30 | halt_afterwards = false 31 | 32 | [default.general] 33 | # The chip name of the chip to be debugged. 34 | chip = "nRF52840" 35 | # A list of chip descriptions to be loaded during runtime. 36 | chip_descriptions = [] 37 | # The default log level to be used. Possible values are one of: 38 | # "OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" 39 | log_level = "WARN" 40 | 41 | [default.rtt] 42 | # Whether or not an RTTUI should be opened after flashing. 43 | # This is exclusive and cannot be used with GDB at the moment. 44 | enabled = false 45 | # A list of channel associations to be displayed. If left empty, all channels are displayed. 46 | channels = [ 47 | # { up = 0, down = 0, name = "name", format = "String" } 48 | ] 49 | # The duration in ms for which the logger should retry to attach to RTT. 50 | timeout = 3000 51 | # Whether timestamps in the RTTUI are enabled 52 | show_timestamps = true 53 | # Whether to save rtt history buffer on exit. 54 | log_enabled = false 55 | # Where to save rtt history buffer relative to manifest path. 56 | log_path = "./logs" 57 | 58 | [default.gdb] 59 | # Whether or not a GDB server should be opened after flashing. 60 | # This is exclusive and cannot be used with RTT at the moment. 61 | enabled = false 62 | # The connection string in host:port format wher the GDB server will open a socket. 63 | # gdb_connection_string 64 | -------------------------------------------------------------------------------- /examples/usb/README.md: -------------------------------------------------------------------------------- 1 | # USB examples 2 | 3 | This demo provides two binaries: 4 | 5 | - `serial`: a USB serial "echo" example. 6 | - `test_class`: exposes the test device from the `usb-device` crate. 7 | -------------------------------------------------------------------------------- /examples/usb/src/bin/serial.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use panic_semihosting as _; 5 | 6 | use cortex_m_rt::entry; 7 | use nrf52840_hal::clocks::Clocks; 8 | use nrf52840_hal::usbd::{UsbPeripheral, Usbd}; 9 | use usb_device::class_prelude::UsbBusAllocator; 10 | use usb_device::device::{StringDescriptors, UsbDeviceBuilder, UsbVidPid}; 11 | use usbd_serial::{SerialPort, USB_CLASS_CDC}; 12 | 13 | #[entry] 14 | fn main() -> ! { 15 | let periph = nrf52840_hal::pac::Peripherals::take().unwrap(); 16 | let clocks = Clocks::new(periph.CLOCK); 17 | let clocks = clocks.enable_ext_hfosc(); 18 | 19 | let usb_bus = UsbBusAllocator::new(Usbd::new(UsbPeripheral::new(periph.USBD, &clocks))); 20 | let mut serial = SerialPort::new(&usb_bus); 21 | 22 | let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x27dd)) 23 | .strings(&[StringDescriptors::default() 24 | .manufacturer("Fake company") 25 | .product("Serial port") 26 | .serial_number("TEST")]) 27 | .unwrap() 28 | .device_class(USB_CLASS_CDC) 29 | .max_packet_size_0(64) // (makes control transfers 8x faster) 30 | .unwrap() 31 | .build(); 32 | 33 | loop { 34 | if !usb_dev.poll(&mut [&mut serial]) { 35 | continue; 36 | } 37 | 38 | let mut buf = [0u8; 64]; 39 | 40 | match serial.read(&mut buf) { 41 | Ok(count) if count > 0 => { 42 | // Echo back in upper case 43 | for c in buf[0..count].iter_mut() { 44 | if 0x61 <= *c && *c <= 0x7a { 45 | *c &= !0x20; 46 | } 47 | } 48 | 49 | let mut write_offset = 0; 50 | while write_offset < count { 51 | match serial.write(&buf[write_offset..count]) { 52 | Ok(len) if len > 0 => { 53 | write_offset += len; 54 | } 55 | _ => {} 56 | } 57 | } 58 | } 59 | _ => {} 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /examples/usb/src/bin/test_class.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use panic_semihosting as _; 5 | 6 | use cortex_m_rt::entry; 7 | use nrf52840_hal::clocks::Clocks; 8 | use nrf52840_hal::usbd::{UsbPeripheral, Usbd}; 9 | use usb_device::class_prelude::UsbBusAllocator; 10 | use usb_device::test_class::TestClass; 11 | 12 | #[entry] 13 | fn main() -> ! { 14 | let periph = nrf52840_hal::pac::Peripherals::take().unwrap(); 15 | let clocks = Clocks::new(periph.CLOCK); 16 | let clocks = clocks.enable_ext_hfosc(); 17 | 18 | let usb_bus = UsbBusAllocator::new(Usbd::new(UsbPeripheral::new(periph.USBD, &clocks))); 19 | 20 | let mut test = TestClass::new(&usb_bus); 21 | 22 | let mut usb_dev = { test.make_device(&usb_bus) }; 23 | 24 | loop { 25 | if usb_dev.poll(&mut [&mut test]) { 26 | test.poll(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /examples/wdt-demo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wdt-demo" 3 | version = "0.1.0" 4 | authors = ["James Munns "] 5 | edition = "2018" 6 | publish = false 7 | 8 | [dependencies] 9 | cortex-m = { version = "0.7.3", features = ["critical-section-single-core"] } 10 | cortex-m-rt = { version = "0.7.0", features = ["device"] } 11 | embedded-hal = "1.0.0" 12 | rtt-target = "0.6.0" 13 | nrf52840-hal = { features = ["rt"], path = "../../nrf52840-hal" } 14 | -------------------------------------------------------------------------------- /examples/wdt-demo/Embed.toml: -------------------------------------------------------------------------------- 1 | [default.probe] 2 | # USB vendor ID 3 | # usb_vid = "1337" 4 | # USB product ID 5 | # usb_pid = "1337" 6 | # Serial number 7 | # serial = "12345678" 8 | # The protocol to be used for communicating with the target. 9 | protocol = "Swd" 10 | # The speed in kHz of the data link to the target. 11 | # speed = 1337 12 | 13 | [default.flashing] 14 | # Whether or not the target should be flashed. 15 | enabled = true 16 | # Whether or not the target should be halted after reset. 17 | # DEPRECATED, moved to reset section 18 | halt_afterwards = false 19 | # Whether or not bytes erased but not rewritten with data from the ELF 20 | # should be restored with their contents before erasing. 21 | restore_unwritten_bytes = false 22 | # The path where an SVG of the assembled flash layout should be written to. 23 | # flash_layout_output_path = "out.svg" 24 | 25 | [default.reset] 26 | # Whether or not the target should be reset. 27 | # When flashing is enabled as well, the target will be reset after flashing. 28 | enabled = true 29 | # Whether or not the target should be halted after reset. 30 | halt_afterwards = false 31 | 32 | [default.general] 33 | # The chip name of the chip to be debugged. 34 | chip = "nRF52840" 35 | # A list of chip descriptions to be loaded during runtime. 36 | chip_descriptions = [] 37 | # The default log level to be used. Possible values are one of: 38 | # "OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" 39 | log_level = "WARN" 40 | 41 | [default.rtt] 42 | # Whether or not an RTTUI should be opened after flashing. 43 | # This is exclusive and cannot be used with GDB at the moment. 44 | enabled = true 45 | # A list of channel associations to be displayed. If left empty, all channels are displayed. 46 | channels = [ 47 | # { up = 0, down = 0, name = "name", format = "String" } 48 | ] 49 | # The duration in ms for which the logger should retry to attach to RTT. 50 | timeout = 3000 51 | # Whether timestamps in the RTTUI are enabled 52 | show_timestamps = true 53 | # Whether to save rtt history buffer on exit. 54 | log_enabled = false 55 | # Where to save rtt history buffer relative to manifest path. 56 | log_path = "./logs" 57 | 58 | [default.gdb] 59 | # Whether or not a GDB server should be opened after flashing. 60 | # This is exclusive and cannot be used with RTT at the moment. 61 | enabled = false 62 | # The connection string in host:port format wher the GDB server will open a socket. 63 | # gdb_connection_string 64 | -------------------------------------------------------------------------------- /examples/wdt-demo/README.md: -------------------------------------------------------------------------------- 1 | # WDT demo 2 | 3 | This demo uses the watchdog timer (WDT) to show how the entire device can be set to automatically reset if certain conditions are not met within a certain period of time. In this case you have to press all 4 buttons at least once within a 5 second period to prevent a reset. 4 | 5 | > Can you spot an opportunity to crash the program? 6 | > 7 | > If you mash the buttons as the time approaches zero you will encounter an 'attempt to subtract with overflow' panic at `main.rs:205` which is ultimately cleared by the watchdog timer. This demonstrates the ability to recover from a panic. Use `probe-run` to see the actual panic message. 8 | 9 | ## How to run 10 | 11 | If using `cargo-embed`, just run 12 | 13 | ```console 14 | $ cargo embed --release --target=thumbv7em-none-eabihf 15 | ``` -------------------------------------------------------------------------------- /nrf-hal-common/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "nrf-hal-common" 3 | version = "0.18.0" 4 | description = "Implementation details of the nRF HAL crates. Don't use this directly, use one of the specific HAL crates instead (`nrfXYZ-hal`)." 5 | readme = "../README.md" 6 | 7 | repository = "https://github.com/nrf-rs/nrf-hal" 8 | authors = [ 9 | "James Munns ", 10 | "Hanno Braun ", 11 | "John Scarrott ", 12 | "Wez Furlong ", 13 | "Daniel Egger ", 14 | "Ferdia McKeogh ", 15 | ] 16 | 17 | categories = ["embedded", "hardware-support", "no-std"] 18 | keywords = ["arm", "cortex-m", "nrf52", "nrf", "hal"] 19 | license = "MIT OR Apache-2.0" 20 | edition = "2018" 21 | 22 | [dependencies] 23 | cfg-if = "1.0.0" 24 | cortex-m = "0.7.7" 25 | embedded-dma = "0.2.0" 26 | embedded-hal = "1.0.0" 27 | embedded-io = "0.6.1" 28 | embedded-storage = "0.3.1" 29 | fixed = "1.25.1" 30 | nb = "1.1.0" 31 | rand_core = "0.9.0" 32 | 33 | [dependencies.void] 34 | default-features = false 35 | version = "1.0.2" 36 | 37 | [dependencies.cast] 38 | default-features = false 39 | version = "0.3.0" 40 | 41 | [dependencies.nrf51-pac] 42 | optional = true 43 | version = "0.12.2" 44 | 45 | [dependencies.nrf52805-pac] 46 | optional = true 47 | version = "0.12.2" 48 | 49 | [dependencies.nrf52810-pac] 50 | optional = true 51 | version = "0.12.2" 52 | 53 | [dependencies.nrf52811-pac] 54 | optional = true 55 | version = "0.12.2" 56 | 57 | [dependencies.nrf52832-pac] 58 | optional = true 59 | version = "0.12.2" 60 | 61 | [dependencies.nrf52833-pac] 62 | optional = true 63 | version = "0.12.2" 64 | 65 | [dependencies.nrf52840-pac] 66 | optional = true 67 | version = "0.12.2" 68 | 69 | [dependencies.nrf5340-app-pac] 70 | optional = true 71 | version = "0.12.2" 72 | 73 | [dependencies.nrf5340-net-pac] 74 | optional = true 75 | version = "0.12.2" 76 | 77 | [dependencies.nrf9160-pac] 78 | optional = true 79 | version = "0.12.2" 80 | 81 | [dependencies.nrf-usbd] 82 | version = "0.3.0" 83 | optional = true 84 | 85 | [dependencies.embedded-hal-02] 86 | package = "embedded-hal" 87 | features = ["unproven"] 88 | version = "0.2.7" 89 | optional = true 90 | 91 | [dependencies.rtic-monotonic] 92 | version = "1.0.0" 93 | optional = true 94 | 95 | [dependencies.fugit] 96 | version = "0.3.7" 97 | optional = true 98 | 99 | [features] 100 | doc = [] 101 | 51 = ["nrf51-pac"] 102 | 52805 = ["nrf52805-pac"] 103 | 52810 = ["nrf52810-pac"] 104 | 52811 = ["nrf52811-pac"] 105 | 52832 = ["nrf52832-pac"] 106 | 52833 = ["nrf52833-pac", "nrf-usbd"] 107 | 52840 = ["nrf52840-pac", "nrf-usbd"] 108 | 5340-app = ["nrf5340-app-pac"] 109 | 5340-net = ["nrf5340-net-pac"] 110 | 9160 = ["nrf9160-pac"] 111 | rtic-monotonic = ["dep:rtic-monotonic", "dep:fugit"] 112 | -------------------------------------------------------------------------------- /nrf-hal-common/build.rs: -------------------------------------------------------------------------------- 1 | use std::{env, process}; 2 | 3 | fn main() { 4 | if env::var_os("CARGO_FEATURE_51").is_none() { 5 | // Not building for the nRF51. 52+ use too many interrupts for the thumbv6 target, so detect 6 | // that early. 7 | if env::var("TARGET").unwrap() == "thumbv6m-none-eabi" { 8 | eprintln!( 9 | "this nRF device does not support the `thumbv6m-none-eabi` target; \ 10 | build for `thumbv7em-none-eabi(hf)` instead" 11 | ); 12 | process::exit(1); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /nrf-hal-common/src/delay.rs: -------------------------------------------------------------------------------- 1 | //! Delays. 2 | 3 | use crate::clocks::HFCLK_FREQ; 4 | use core::convert::TryInto; 5 | use cortex_m::peripheral::syst::SystClkSource; 6 | use cortex_m::peripheral::SYST; 7 | use embedded_hal::delay::DelayNs; 8 | 9 | /// System timer (SysTick) as a delay provider. 10 | pub struct Delay { 11 | syst: SYST, 12 | } 13 | 14 | impl Delay { 15 | /// Configures the system timer (SysTick) as a delay provider. 16 | pub fn new(mut syst: SYST) -> Self { 17 | syst.set_clock_source(SystClkSource::Core); 18 | 19 | Delay { syst } 20 | } 21 | 22 | /// Releases the system timer (SysTick) resource. 23 | pub fn free(self) -> SYST { 24 | self.syst 25 | } 26 | } 27 | 28 | #[cfg(feature = "embedded-hal-02")] 29 | impl embedded_hal_02::blocking::delay::DelayMs for Delay { 30 | fn delay_ms(&mut self, ms: u32) { 31 | DelayNs::delay_ms(self, ms); 32 | } 33 | } 34 | 35 | #[cfg(feature = "embedded-hal-02")] 36 | impl embedded_hal_02::blocking::delay::DelayMs for Delay { 37 | fn delay_ms(&mut self, ms: u16) { 38 | DelayNs::delay_ms(self, ms.into()); 39 | } 40 | } 41 | 42 | #[cfg(feature = "embedded-hal-02")] 43 | impl embedded_hal_02::blocking::delay::DelayMs for Delay { 44 | fn delay_ms(&mut self, ms: u8) { 45 | DelayNs::delay_ms(self, ms.into()); 46 | } 47 | } 48 | 49 | #[cfg(feature = "embedded-hal-02")] 50 | impl embedded_hal_02::blocking::delay::DelayUs for Delay { 51 | fn delay_us(&mut self, us: u32) { 52 | DelayNs::delay_us(self, us); 53 | } 54 | } 55 | 56 | #[cfg(feature = "embedded-hal-02")] 57 | impl embedded_hal_02::blocking::delay::DelayUs for Delay { 58 | fn delay_us(&mut self, us: u16) { 59 | DelayNs::delay_us(self, us.into()); 60 | } 61 | } 62 | 63 | #[cfg(feature = "embedded-hal-02")] 64 | impl embedded_hal_02::blocking::delay::DelayUs for Delay { 65 | fn delay_us(&mut self, us: u8) { 66 | DelayNs::delay_us(self, us.into()); 67 | } 68 | } 69 | 70 | impl DelayNs for Delay { 71 | fn delay_ns(&mut self, ns: u32) { 72 | // The SysTick Reload Value register supports values between 1 and 0x00FFFFFF. 73 | const MAX_RVR: u32 = 0x00FF_FFFF; 74 | 75 | let mut total_rvr: u32 = (u64::from(ns) * u64::from(HFCLK_FREQ) / 1_000_000_000) 76 | .try_into() 77 | .unwrap(); 78 | 79 | while total_rvr != 0 { 80 | let current_rvr = if total_rvr <= MAX_RVR { 81 | total_rvr 82 | } else { 83 | MAX_RVR 84 | }; 85 | 86 | self.syst.set_reload(current_rvr); 87 | self.syst.clear_current(); 88 | self.syst.enable_counter(); 89 | 90 | // Update the tracking variable while we are waiting... 91 | total_rvr -= current_rvr; 92 | 93 | while !self.syst.has_wrapped() {} 94 | 95 | self.syst.disable_counter(); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /nrf-hal-common/src/ppi/event_nrf51.rs: -------------------------------------------------------------------------------- 1 | use crate::ppi::Event; 2 | 3 | // Event impls 4 | // 5 | // To reproduce, in the pac crate, search 6 | // `rg 'type EVENTS_.*crate::Reg' --type rust` 7 | // Find (regex): 8 | // `^src/(.*)\.rs:pub type (.*) = .*$` 9 | // Replace (regex): 10 | // `impl Event for crate::pac::$1::$2 { }` 11 | impl Event for crate::pac::ecb::EVENTS_ENDECB {} 12 | impl Event for crate::pac::ecb::EVENTS_ERRORECB {} 13 | impl Event for crate::pac::rng::EVENTS_VALRDY {} 14 | impl Event for crate::pac::timer0::EVENTS_COMPARE {} 15 | impl Event for crate::pac::uart0::EVENTS_CTS {} 16 | impl Event for crate::pac::uart0::EVENTS_NCTS {} 17 | impl Event for crate::pac::uart0::EVENTS_RXDRDY {} 18 | impl Event for crate::pac::uart0::EVENTS_TXDRDY {} 19 | impl Event for crate::pac::uart0::EVENTS_ERROR {} 20 | impl Event for crate::pac::uart0::EVENTS_RXTO {} 21 | impl Event for crate::pac::gpiote::EVENTS_IN {} 22 | impl Event for crate::pac::gpiote::EVENTS_PORT {} 23 | impl Event for crate::pac::power::EVENTS_POFWARN {} 24 | impl Event for crate::pac::clock::EVENTS_HFCLKSTARTED {} 25 | impl Event for crate::pac::clock::EVENTS_LFCLKSTARTED {} 26 | impl Event for crate::pac::clock::EVENTS_DONE {} 27 | impl Event for crate::pac::clock::EVENTS_CTTO {} 28 | impl Event for crate::pac::spi0::EVENTS_READY {} 29 | impl Event for crate::pac::twi0::EVENTS_STOPPED {} 30 | impl Event for crate::pac::twi0::EVENTS_RXDREADY {} 31 | impl Event for crate::pac::twi0::EVENTS_TXDSENT {} 32 | impl Event for crate::pac::twi0::EVENTS_ERROR {} 33 | impl Event for crate::pac::twi0::EVENTS_BB {} 34 | impl Event for crate::pac::twi0::EVENTS_SUSPENDED {} 35 | impl Event for crate::pac::spis1::EVENTS_END {} 36 | impl Event for crate::pac::spis1::EVENTS_ENDRX {} 37 | impl Event for crate::pac::spis1::EVENTS_ACQUIRED {} 38 | impl Event for crate::pac::rtc0::EVENTS_TICK {} 39 | impl Event for crate::pac::rtc0::EVENTS_OVRFLW {} 40 | impl Event for crate::pac::rtc0::EVENTS_COMPARE {} 41 | impl Event for crate::pac::wdt::EVENTS_TIMEOUT {} 42 | impl Event for crate::pac::temp::EVENTS_DATARDY {} 43 | impl Event for crate::pac::radio::EVENTS_READY {} 44 | impl Event for crate::pac::radio::EVENTS_ADDRESS {} 45 | impl Event for crate::pac::radio::EVENTS_PAYLOAD {} 46 | impl Event for crate::pac::radio::EVENTS_END {} 47 | impl Event for crate::pac::radio::EVENTS_DISABLED {} 48 | impl Event for crate::pac::radio::EVENTS_DEVMATCH {} 49 | impl Event for crate::pac::radio::EVENTS_DEVMISS {} 50 | impl Event for crate::pac::radio::EVENTS_RSSIEND {} 51 | impl Event for crate::pac::radio::EVENTS_BCMATCH {} 52 | impl Event for crate::pac::lpcomp::EVENTS_READY {} 53 | impl Event for crate::pac::lpcomp::EVENTS_DOWN {} 54 | impl Event for crate::pac::lpcomp::EVENTS_UP {} 55 | impl Event for crate::pac::lpcomp::EVENTS_CROSS {} 56 | impl Event for crate::pac::ccm::EVENTS_ENDKSGEN {} 57 | impl Event for crate::pac::ccm::EVENTS_ENDCRYPT {} 58 | impl Event for crate::pac::ccm::EVENTS_ERROR {} 59 | impl Event for crate::pac::aar::EVENTS_END {} 60 | impl Event for crate::pac::aar::EVENTS_RESOLVED {} 61 | impl Event for crate::pac::aar::EVENTS_NOTRESOLVED {} 62 | impl Event for crate::pac::qdec::EVENTS_SAMPLERDY {} 63 | impl Event for crate::pac::qdec::EVENTS_REPORTRDY {} 64 | impl Event for crate::pac::qdec::EVENTS_ACCOF {} 65 | impl Event for crate::pac::adc::EVENTS_END {} 66 | -------------------------------------------------------------------------------- /nrf-hal-common/src/ppi/task_nrf51.rs: -------------------------------------------------------------------------------- 1 | use crate::ppi::Task; 2 | 3 | // Task Impls 4 | // 5 | // To reproduce, in the pac crate, search 6 | // `rg 'type TASKS_.*crate::Reg' --type rust` 7 | // Find (regex): 8 | // `^src/(.*)\.rs:pub type (.*) = .*$` 9 | // Replace (regex): 10 | // `impl Task for crate::pac::$1::$2 { }` 11 | impl Task for crate::pac::rng::TASKS_START {} 12 | impl Task for crate::pac::rng::TASKS_STOP {} 13 | impl Task for crate::pac::timer0::TASKS_START {} 14 | impl Task for crate::pac::timer0::TASKS_STOP {} 15 | impl Task for crate::pac::timer0::TASKS_COUNT {} 16 | impl Task for crate::pac::timer0::TASKS_CLEAR {} 17 | impl Task for crate::pac::timer0::TASKS_SHUTDOWN {} 18 | impl Task for crate::pac::timer0::TASKS_CAPTURE {} 19 | impl Task for crate::pac::uart0::TASKS_STARTRX {} 20 | impl Task for crate::pac::uart0::TASKS_STOPRX {} 21 | impl Task for crate::pac::uart0::TASKS_STARTTX {} 22 | impl Task for crate::pac::uart0::TASKS_STOPTX {} 23 | impl Task for crate::pac::uart0::TASKS_SUSPEND {} 24 | impl Task for crate::pac::gpiote::TASKS_OUT {} 25 | impl Task for crate::pac::clock::TASKS_HFCLKSTART {} 26 | impl Task for crate::pac::clock::TASKS_HFCLKSTOP {} 27 | impl Task for crate::pac::clock::TASKS_LFCLKSTART {} 28 | impl Task for crate::pac::clock::TASKS_LFCLKSTOP {} 29 | impl Task for crate::pac::clock::TASKS_CAL {} 30 | impl Task for crate::pac::clock::TASKS_CTSTART {} 31 | impl Task for crate::pac::clock::TASKS_CTSTOP {} 32 | impl Task for crate::pac::power::TASKS_CONSTLAT {} 33 | impl Task for crate::pac::power::TASKS_LOWPWR {} 34 | impl Task for crate::pac::twi0::TASKS_STARTRX {} 35 | impl Task for crate::pac::twi0::TASKS_STARTTX {} 36 | impl Task for crate::pac::twi0::TASKS_STOP {} 37 | impl Task for crate::pac::twi0::TASKS_SUSPEND {} 38 | impl Task for crate::pac::twi0::TASKS_RESUME {} 39 | impl Task for crate::pac::ecb::TASKS_STARTECB {} 40 | impl Task for crate::pac::ecb::TASKS_STOPECB {} 41 | impl Task for crate::pac::wdt::TASKS_START {} 42 | impl Task for crate::pac::spis1::TASKS_ACQUIRE {} 43 | impl Task for crate::pac::spis1::TASKS_RELEASE {} 44 | impl Task for crate::pac::rtc0::TASKS_START {} 45 | impl Task for crate::pac::rtc0::TASKS_STOP {} 46 | impl Task for crate::pac::rtc0::TASKS_CLEAR {} 47 | impl Task for crate::pac::rtc0::TASKS_TRIGOVRFLW {} 48 | impl Task for crate::pac::lpcomp::TASKS_START {} 49 | impl Task for crate::pac::lpcomp::TASKS_STOP {} 50 | impl Task for crate::pac::lpcomp::TASKS_SAMPLE {} 51 | impl Task for crate::pac::radio::TASKS_TXEN {} 52 | impl Task for crate::pac::radio::TASKS_RXEN {} 53 | impl Task for crate::pac::radio::TASKS_START {} 54 | impl Task for crate::pac::radio::TASKS_STOP {} 55 | impl Task for crate::pac::radio::TASKS_DISABLE {} 56 | impl Task for crate::pac::radio::TASKS_RSSISTART {} 57 | impl Task for crate::pac::radio::TASKS_RSSISTOP {} 58 | impl Task for crate::pac::radio::TASKS_BCSTART {} 59 | impl Task for crate::pac::radio::TASKS_BCSTOP {} 60 | impl Task for crate::pac::temp::TASKS_START {} 61 | impl Task for crate::pac::temp::TASKS_STOP {} 62 | impl Task for crate::pac::ccm::TASKS_KSGEN {} 63 | impl Task for crate::pac::ccm::TASKS_CRYPT {} 64 | impl Task for crate::pac::ccm::TASKS_STOP {} 65 | impl Task for crate::pac::adc::TASKS_START {} 66 | impl Task for crate::pac::adc::TASKS_STOP {} 67 | impl Task for crate::pac::aar::TASKS_START {} 68 | impl Task for crate::pac::aar::TASKS_STOP {} 69 | impl Task for crate::pac::qdec::TASKS_START {} 70 | impl Task for crate::pac::qdec::TASKS_STOP {} 71 | impl Task for crate::pac::qdec::TASKS_READCLRACC {} 72 | -------------------------------------------------------------------------------- /nrf-hal-common/src/rng.rs: -------------------------------------------------------------------------------- 1 | //! HAL interface to the RNG peripheral. 2 | //! 3 | //! See nRF52832 product specification, chapter 26. 4 | 5 | use rand_core::{CryptoRng, RngCore}; 6 | 7 | #[cfg(not(feature = "5340-net"))] 8 | use crate::pac::RNG; 9 | #[cfg(feature = "5340-net")] 10 | use crate::pac::RNG_NS as RNG; 11 | 12 | /// Interface to the RNG peripheral. 13 | /// 14 | /// Right now, this is very basic, only providing blocking interfaces. 15 | pub struct Rng(RNG); 16 | 17 | impl Rng { 18 | pub fn new(rng: RNG) -> Self { 19 | rng.config.write(|w| w.dercen().enabled()); 20 | Self(rng) 21 | } 22 | 23 | /// Fill the provided buffer with random bytes. 24 | /// 25 | /// Will block until the buffer is full. 26 | pub fn random(&mut self, buf: &mut [u8]) { 27 | self.0.tasks_start.write(|w| unsafe { w.bits(1) }); 28 | 29 | for b in buf { 30 | // Wait for random byte to become ready, reset the flag once it is. 31 | while self.0.events_valrdy.read().bits() == 0 {} 32 | self.0.events_valrdy.write(|w| unsafe { w.bits(0) }); 33 | 34 | *b = self.0.value.read().value().bits(); 35 | } 36 | 37 | self.0.tasks_stop.write(|w| unsafe { w.bits(1) }); 38 | } 39 | 40 | /// Return a random `u8`. 41 | pub fn random_u8(&mut self) -> u8 { 42 | let mut buf = [0; 1]; 43 | self.random(&mut buf); 44 | buf[0] 45 | } 46 | 47 | /// Return a random `u16`. 48 | pub fn random_u16(&mut self) -> u16 { 49 | let mut buf = [0; 2]; 50 | self.random(&mut buf); 51 | buf[0] as u16 | (buf[1] as u16) << 8 52 | } 53 | 54 | /// Return a random `u32`. 55 | pub fn random_u32(&mut self) -> u32 { 56 | let mut buf = [0; 4]; 57 | self.random(&mut buf); 58 | buf[0] as u32 | (buf[1] as u32) << 8 | (buf[2] as u32) << 16 | (buf[3] as u32) << 24 59 | } 60 | 61 | /// Return a random `u64`. 62 | pub fn random_u64(&mut self) -> u64 { 63 | let mut buf = [0; 8]; 64 | self.random(&mut buf); 65 | buf[0] as u64 66 | | (buf[1] as u64) << 8 67 | | (buf[2] as u64) << 16 68 | | (buf[3] as u64) << 24 69 | | (buf[4] as u64) << 32 70 | | (buf[5] as u64) << 40 71 | | (buf[6] as u64) << 48 72 | | (buf[7] as u64) << 56 73 | } 74 | } 75 | 76 | impl RngCore for Rng { 77 | fn next_u32(&mut self) -> u32 { 78 | self.random_u32() 79 | } 80 | 81 | fn next_u64(&mut self) -> u64 { 82 | self.random_u64() 83 | } 84 | 85 | fn fill_bytes(&mut self, dest: &mut [u8]) { 86 | self.random(dest) 87 | } 88 | } 89 | 90 | impl CryptoRng for Rng {} 91 | -------------------------------------------------------------------------------- /nrf-hal-common/src/temp.rs: -------------------------------------------------------------------------------- 1 | //! Temperature sensor interface. 2 | 3 | #[cfg(not(feature = "5340-net"))] 4 | use crate::pac::TEMP; 5 | #[cfg(feature = "5340-net")] 6 | use crate::pac::TEMP_NS as TEMP; 7 | 8 | use fixed::types::I30F2; 9 | use void::Void; 10 | 11 | /// Integrated temperature sensor. 12 | pub struct Temp(TEMP); 13 | 14 | impl Temp { 15 | /// Creates a new `Temp`, taking ownership of the temperature sensor's register block. 16 | pub fn new(raw: TEMP) -> Self { 17 | Temp(raw) 18 | } 19 | 20 | /// Starts a new measurement and blocks until completion. 21 | /// 22 | /// If a measurement was already started, it will be canceled. 23 | /// 24 | /// Returns the measured temperature in °C. 25 | /// 26 | /// Note: This return type is [fixed::types::I30F2]. It 27 | /// can be converted into [f32] or [f64] (or other numeric types) 28 | /// via the `to_num()` method. 29 | /// 30 | /// # Examples 31 | /// 32 | /// ```ignore 33 | /// let mut temp = Temp::new(board.TEMP); 34 | /// let deg_c: f32 = temp.measure().to_num(); 35 | /// ``` 36 | pub fn measure(&mut self) -> I30F2 { 37 | self.stop_measurement(); 38 | self.start_measurement(); 39 | 40 | nb::block!(self.read()).unwrap() 41 | } 42 | 43 | /// Kicks off a temperature measurement. 44 | /// 45 | /// The measurement can be retrieved by calling `read`. 46 | pub fn start_measurement(&mut self) { 47 | unsafe { 48 | self.0.tasks_start.write(|w| w.bits(1)); 49 | } 50 | } 51 | 52 | /// Cancels an in-progress temperature measurement. 53 | pub fn stop_measurement(&mut self) { 54 | unsafe { 55 | self.0.tasks_stop.write(|w| w.bits(1)); 56 | self.0.events_datardy.reset(); 57 | } 58 | } 59 | 60 | /// Tries to read a started measurement (non-blocking). 61 | /// 62 | /// Before calling this, `start_measurement` must be called. 63 | /// 64 | /// Returns the measured temperature in °C. 65 | pub fn read(&mut self) -> nb::Result { 66 | if self.0.events_datardy.read().bits() == 0 { 67 | Err(nb::Error::WouldBlock) 68 | } else { 69 | self.0.events_datardy.reset(); // clear event 70 | let raw = self.0.temp.read().bits(); 71 | Ok(I30F2::from_bits(raw as i32)) 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /nrf-hal-common/src/time.rs: -------------------------------------------------------------------------------- 1 | //! Time units. 2 | 3 | /// Bits per second. 4 | #[derive(Clone, Copy)] 5 | pub struct Bps(pub u32); 6 | 7 | /// Hertz. 8 | #[derive(Clone, Copy)] 9 | pub struct Hertz(pub u32); 10 | 11 | /// KiloHertz. 12 | #[derive(Clone, Copy)] 13 | pub struct KiloHertz(pub u32); 14 | 15 | /// MegaHertz. 16 | #[derive(Clone, Copy)] 17 | pub struct MegaHertz(pub u32); 18 | 19 | /// Extension trait that adds convenience methods to the `u32` type. 20 | pub trait U32Ext { 21 | /// Wrap in `Bps`. 22 | fn bps(self) -> Bps; 23 | 24 | /// Wrap in `Hertz`. 25 | fn hz(self) -> Hertz; 26 | 27 | /// Wrap in `KiloHertz`. 28 | fn khz(self) -> KiloHertz; 29 | 30 | /// Wrap in `MegaHertz`. 31 | fn mhz(self) -> MegaHertz; 32 | } 33 | 34 | impl U32Ext for u32 { 35 | fn bps(self) -> Bps { 36 | Bps(self) 37 | } 38 | 39 | fn hz(self) -> Hertz { 40 | Hertz(self) 41 | } 42 | 43 | fn khz(self) -> KiloHertz { 44 | KiloHertz(self) 45 | } 46 | 47 | fn mhz(self) -> MegaHertz { 48 | MegaHertz(self) 49 | } 50 | } 51 | 52 | impl Into for KiloHertz { 53 | fn into(self) -> Hertz { 54 | Hertz(self.0 * 1_000) 55 | } 56 | } 57 | 58 | impl Into for MegaHertz { 59 | fn into(self) -> Hertz { 60 | Hertz(self.0 * 1_000_000) 61 | } 62 | } 63 | 64 | impl Into for MegaHertz { 65 | fn into(self) -> KiloHertz { 66 | KiloHertz(self.0 * 1_000) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /nrf-hal-common/src/uicr.rs: -------------------------------------------------------------------------------- 1 | //! HAL interface to the UICR core component. 2 | //! 3 | //! See product specification: 4 | //! 5 | //! - nrf52805: Section 4.5 6 | //! - nrf52810: Section 4.5 7 | //! - nrf52811: Section 4.5 8 | //! - nrf52832: Section 14 9 | //! - nrf52840: Section 4.5 10 | use crate::pac::{NVMC, UICR}; 11 | 12 | /// Interface to a UICR instance. 13 | /// 14 | /// This is a very basic interface that comes with the following limitations: 15 | /// - Only `customer` registers are usable for storing and loading of data 16 | /// - Erase must be performed in order to write bits with value `1` over `0` 17 | pub struct Uicr(UICR); 18 | 19 | impl Uicr { 20 | /// Construct a new `Uicr` from `pac::UICR`. 21 | pub fn new(uicr: UICR) -> Self { 22 | Self(uicr) 23 | } 24 | 25 | /// Release the `pac::UICR` instance back. 26 | pub fn free(self) -> UICR { 27 | self.0 28 | } 29 | 30 | /// Erase the UICR registers. 31 | /// 32 | /// UICR registers can only be set to `0` bits, additional overrides back to `1` can only be 33 | /// performed by erasing the UICR registers. 34 | /// - Sets all registers to 0xFFFF_FFFFu32 35 | pub fn erase(&mut self, nvmc: &mut NVMC) { 36 | assert!(!nvmc.config.read().wen().is_wen()); // write + erase is forbidden! 37 | 38 | nvmc.config.write(|w| w.wen().een()); 39 | nvmc.eraseuicr.write(|w| w.eraseuicr().erase()); 40 | nvmc.config.reset() 41 | } 42 | 43 | /// Store a slice of `&[u32]` values to the customer registers with given offset. 44 | /// 45 | /// - offset + slice length must be less than 32 46 | /// - initial value after erase is 0xFFFF_FFFFu32 47 | /// - UICR registers can only be set to `0` bits, additional overrides back to `1` can only be 48 | /// performed by erasing the UICR registers 49 | pub fn store_customer(&mut self, nvmc: &mut NVMC, offset: usize, values: &[u32]) { 50 | assert!(values.len() + offset <= self.0.customer.len()); // ensure we fit 51 | assert!(!nvmc.config.read().wen().is_een()); // write + erase is forbidden! 52 | 53 | nvmc.config.write(|w| w.wen().wen()); 54 | for (i, value) in values.iter().enumerate() { 55 | #[cfg(feature = "51")] 56 | self.0.customer[offset + i].write(|w| unsafe { w.bits(*value) }); 57 | 58 | #[cfg(not(feature = "51"))] 59 | self.0.customer[offset + i].write(|w| unsafe { w.customer().bits(*value) }); 60 | } 61 | nvmc.config.reset() 62 | } 63 | 64 | /// Load a slice of `&[u32]` values to the customer registers from given offset. 65 | /// 66 | /// - offset + slice length must be less than 32 67 | /// - returns the loaded slice 68 | pub fn load_customer<'a>(&mut self, offset: usize, values: &'a mut [u32]) -> &'a [u32] { 69 | assert!(values.len() + offset <= self.0.customer.len()); // ensure we fit 70 | 71 | let range = offset..offset + values.len(); 72 | for (i, reg_i) in range.enumerate() { 73 | #[cfg(feature = "51")] 74 | { 75 | values[i] = self.0.customer[reg_i].read().bits() 76 | } 77 | 78 | #[cfg(not(feature = "51"))] 79 | { 80 | values[i] = self.0.customer[reg_i].read().customer().bits() 81 | } 82 | } 83 | 84 | values 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /nrf-hal-common/src/usbd.rs: -------------------------------------------------------------------------------- 1 | use core::marker::PhantomData; 2 | 3 | use crate::clocks::ExternalOscillator; 4 | use crate::pac::USBD; 5 | use crate::Clocks; 6 | 7 | pub use nrf_usbd::Usbd; 8 | 9 | pub struct UsbPeripheral<'a> { 10 | _usbd: USBD, 11 | _clocks: PhantomData<&'a ()>, 12 | } 13 | 14 | impl<'a> UsbPeripheral<'a> { 15 | pub fn new(usbd: USBD, _clocks: &'a Clocks) -> Self { 16 | Self { 17 | _usbd: usbd, 18 | _clocks: PhantomData, 19 | } 20 | } 21 | } 22 | 23 | unsafe impl<'a> nrf_usbd::UsbPeripheral for UsbPeripheral<'a> { 24 | const REGISTERS: *const () = USBD::ptr() as *const _; 25 | } 26 | -------------------------------------------------------------------------------- /nrf51-hal/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "nrf51-hal" 3 | version = "0.18.0" 4 | edition = "2018" 5 | description = "HAL for nRF51 microcontrollers" 6 | readme = "../README.md" 7 | 8 | repository = "https://github.com/nrf-rs/nrf-hal" 9 | authors = [ 10 | "James Munns ", 11 | "Hanno Braun ", 12 | "John Scarrott ", 13 | "Wez Furlong ", 14 | "Ferdia McKeogh ", 15 | "Daniel Egger ", 16 | ] 17 | categories = ["embedded", "hardware-support", "no-std"] 18 | keywords = ["arm", "cortex-m", "nrf52", "hal", "nrf51"] 19 | license = "MIT OR Apache-2.0" 20 | 21 | [dependencies] 22 | nrf51-pac = "0.12.2" 23 | 24 | [dependencies.nrf-hal-common] 25 | path = "../nrf-hal-common" 26 | default-features = false 27 | features = ["51"] 28 | version = "=0.18.0" 29 | 30 | [features] 31 | doc = [] 32 | embedded-hal-02 = ["nrf-hal-common/embedded-hal-02"] 33 | rt = ["nrf51-pac/rt"] 34 | rtic-monotonic = ["nrf-hal-common/rtic-monotonic"] 35 | # Note: We use the xxAB package by default because it has the least amount of available resources. 36 | default = ["rt", "xxAB-package", "embedded-hal-02"] 37 | xxAA-package = [] 38 | xxAB-package = [] 39 | xxAC-package = [] 40 | -------------------------------------------------------------------------------- /nrf51-hal/build.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::fs::File; 3 | use std::io::Write; 4 | use std::path::PathBuf; 5 | 6 | fn main() { 7 | let target = env::var("TARGET").unwrap(); 8 | if target.starts_with("thumbv7") || target.starts_with("thumbv8") { 9 | panic!( 10 | "nrf51-hal only supports thumbv6 targets (attempting to build for `{}`)", 11 | target 12 | ); 13 | } 14 | 15 | if let Some((flash, mem)) = memory_sizes() { 16 | let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); 17 | 18 | let mut file = File::create(out.join("memory.x")).unwrap(); 19 | 20 | write!( 21 | file, 22 | r#"MEMORY 23 | {{ 24 | FLASH : ORIGIN = 0x00000000, LENGTH = {} 25 | RAM : ORIGIN = 0x20000000, LENGTH = {} 26 | }} 27 | "#, 28 | flash, mem 29 | ) 30 | .unwrap(); 31 | 32 | println!("cargo:rustc-link-search={}", out.display()); 33 | } 34 | 35 | println!("cargo:rerun-if-changed=build.rs"); 36 | } 37 | 38 | fn memory_sizes() -> Option<(&'static str, &'static str)> { 39 | match ( 40 | cfg!(feature = "xxAA-package"), 41 | cfg!(feature = "xxAB-package"), 42 | cfg!(feature = "xxAC-package"), 43 | ) { 44 | // Allow users to provide their own memory.x by disabling all features 45 | (false, false, false) => None, 46 | (true, false, false) => Some(("256K", "16K")), 47 | (false, true, false) => Some(("128K", "16K")), 48 | (false, false, true) => Some(("256K", "32K")), 49 | _ => panic!("Multiple memory configuration features specified"), 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /nrf51-hal/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![doc(html_root_url = "https://docs.rs/nrf51-hal/0.18.0")] 3 | 4 | pub use nrf_hal_common::*; 5 | 6 | pub mod prelude { 7 | pub use nrf_hal_common::prelude::*; 8 | } 9 | 10 | pub use crate::adc::Adc; 11 | pub use crate::ccm::Ccm; 12 | pub use crate::clocks::Clocks; 13 | pub use crate::ecb::Ecb; 14 | pub use crate::rtc::Rtc; 15 | pub use crate::spi::Spi; 16 | pub use crate::temp::Temp; 17 | pub use crate::timer::Timer; 18 | pub use crate::twi::Twi; 19 | pub use crate::uart::Uart; 20 | -------------------------------------------------------------------------------- /nrf52805-hal/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "nrf52805-hal" 3 | version = "0.18.0" 4 | edition = "2018" 5 | description = "HAL for nRF52805 microcontrollers" 6 | readme = "../README.md" 7 | 8 | repository = "https://github.com/nrf-rs/nrf-hal" 9 | authors = [ 10 | "James Munns ", 11 | "Hanno Braun ", 12 | "John Scarrott ", 13 | "Wez Furlong ", 14 | "Ferdia McKeogh ", 15 | ] 16 | categories = ["embedded", "hardware-support", "no-std"] 17 | keywords = ["arm", "cortex-m", "nrf52", "hal", "nrf52805"] 18 | license = "MIT OR Apache-2.0" 19 | 20 | [dependencies] 21 | nrf52805-pac = "0.12.2" 22 | 23 | [dependencies.nrf-hal-common] 24 | path = "../nrf-hal-common" 25 | default-features = false 26 | features = ["52805"] 27 | version = "=0.18.0" 28 | 29 | [features] 30 | doc = [] 31 | embedded-hal-02 = ["nrf-hal-common/embedded-hal-02"] 32 | rt = ["nrf52805-pac/rt"] 33 | rtic-monotonic = ["nrf-hal-common/rtic-monotonic"] 34 | default = ["rt", "embedded-hal-02"] 35 | -------------------------------------------------------------------------------- /nrf52805-hal/build.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::fs::File; 3 | use std::io::Write; 4 | use std::path::PathBuf; 5 | 6 | fn main() { 7 | let target = env::var("TARGET").unwrap(); 8 | if target.ends_with("eabihf") { 9 | panic!("attempting to build nrf52805-hal for target `{}`, but the nRF52805 does not have an FPU", target); 10 | } 11 | 12 | // Put the linker script somewhere the linker can find it 13 | let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); 14 | File::create(out.join("memory.x")) 15 | .unwrap() 16 | .write_all(include_bytes!("memory.x")) 17 | .unwrap(); 18 | println!("cargo:rustc-link-search={}", out.display()); 19 | 20 | println!("cargo:rerun-if-changed=build.rs"); 21 | println!("cargo:rerun-if-changed=memory.x"); 22 | } 23 | -------------------------------------------------------------------------------- /nrf52805-hal/memory.x: -------------------------------------------------------------------------------- 1 | /* Linker script for the nRF52 - WITHOUT SOFT DEVICE */ 2 | MEMORY 3 | { 4 | /* NOTE K = KiBi = 1024 bytes */ 5 | FLASH : ORIGIN = 0x00000000, LENGTH = 192K 6 | RAM : ORIGIN = 0x20000000, LENGTH = 24K 7 | } 8 | 9 | /* This is where the call stack will be allocated. */ 10 | /* The stack is of the full descending type. */ 11 | /* You may want to use this variable to locate the call stack and static 12 | variables in different memory regions. Below is shown the default value */ 13 | /* _stack_start = ORIGIN(RAM) + LENGTH(RAM); */ 14 | 15 | /* You can use this symbol to customize the location of the .text section */ 16 | /* If omitted the .text section will be placed right after the .vector_table 17 | section */ 18 | /* This is required only on microcontrollers that store some configuration right 19 | after the vector table */ 20 | /* _stext = ORIGIN(FLASH) + 0x400; */ 21 | 22 | /* Size of the heap (in bytes) */ 23 | /* _heap_size = 1024; */ -------------------------------------------------------------------------------- /nrf52805-hal/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![doc(html_root_url = "https://docs.rs/nrf52805-hal/0.18.0")] 3 | 4 | pub use nrf_hal_common::*; 5 | 6 | pub mod prelude { 7 | pub use nrf_hal_common::prelude::*; 8 | } 9 | 10 | pub use crate::ccm::Ccm; 11 | pub use crate::clocks::Clocks; 12 | pub use crate::delay::Delay; 13 | pub use crate::ecb::Ecb; 14 | pub use crate::saadc::Saadc; 15 | pub use crate::spim::Spim; 16 | pub use crate::temp::Temp; 17 | pub use crate::timer::Timer; 18 | pub use crate::uarte::Uarte; 19 | -------------------------------------------------------------------------------- /nrf52810-hal/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "nrf52810-hal" 3 | version = "0.18.0" 4 | edition = "2018" 5 | description = "HAL for nRF52810 microcontrollers" 6 | readme = "../README.md" 7 | 8 | repository = "https://github.com/nrf-rs/nrf-hal" 9 | authors = [ 10 | "James Munns ", 11 | "Hanno Braun ", 12 | "John Scarrott ", 13 | "Wez Furlong ", 14 | "Ferdia McKeogh ", 15 | ] 16 | categories = ["embedded", "hardware-support", "no-std"] 17 | keywords = ["arm", "cortex-m", "nrf52", "hal", "nrf52810"] 18 | license = "MIT OR Apache-2.0" 19 | 20 | [dependencies] 21 | nrf52810-pac = "0.12.2" 22 | 23 | [dependencies.nrf-hal-common] 24 | path = "../nrf-hal-common" 25 | default-features = false 26 | features = ["52810"] 27 | version = "=0.18.0" 28 | 29 | [features] 30 | doc = [] 31 | embedded-hal-02 = ["nrf-hal-common/embedded-hal-02"] 32 | rt = ["nrf52810-pac/rt"] 33 | rtic-monotonic = ["nrf-hal-common/rtic-monotonic"] 34 | default = ["rt", "embedded-hal-02"] 35 | -------------------------------------------------------------------------------- /nrf52810-hal/build.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::fs::File; 3 | use std::io::Write; 4 | use std::path::PathBuf; 5 | 6 | fn main() { 7 | let target = env::var("TARGET").unwrap(); 8 | if target.ends_with("eabihf") { 9 | panic!("attempting to build nrf52810-hal for target `{}`, but the nRF52810 does not have an FPU", target); 10 | } 11 | 12 | // Put the linker script somewhere the linker can find it 13 | let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); 14 | File::create(out.join("memory.x")) 15 | .unwrap() 16 | .write_all(include_bytes!("memory.x")) 17 | .unwrap(); 18 | println!("cargo:rustc-link-search={}", out.display()); 19 | 20 | println!("cargo:rerun-if-changed=build.rs"); 21 | println!("cargo:rerun-if-changed=memory.x"); 22 | } 23 | -------------------------------------------------------------------------------- /nrf52810-hal/memory.x: -------------------------------------------------------------------------------- 1 | /* Linker script for the nRF52 - WITHOUT SOFT DEVICE */ 2 | MEMORY 3 | { 4 | /* NOTE K = KiBi = 1024 bytes */ 5 | FLASH : ORIGIN = 0x00000000, LENGTH = 192K 6 | RAM : ORIGIN = 0x20000000, LENGTH = 24K 7 | } 8 | 9 | /* This is where the call stack will be allocated. */ 10 | /* The stack is of the full descending type. */ 11 | /* You may want to use this variable to locate the call stack and static 12 | variables in different memory regions. Below is shown the default value */ 13 | /* _stack_start = ORIGIN(RAM) + LENGTH(RAM); */ 14 | 15 | /* You can use this symbol to customize the location of the .text section */ 16 | /* If omitted the .text section will be placed right after the .vector_table 17 | section */ 18 | /* This is required only on microcontrollers that store some configuration right 19 | after the vector table */ 20 | /* _stext = ORIGIN(FLASH) + 0x400; */ 21 | 22 | /* Size of the heap (in bytes) */ 23 | /* _heap_size = 1024; */ -------------------------------------------------------------------------------- /nrf52810-hal/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![doc(html_root_url = "https://docs.rs/nrf52810-hal/0.18.0")] 3 | 4 | pub use nrf_hal_common::*; 5 | 6 | pub mod prelude { 7 | pub use nrf_hal_common::prelude::*; 8 | } 9 | 10 | pub use crate::ccm::Ccm; 11 | pub use crate::clocks::Clocks; 12 | pub use crate::delay::Delay; 13 | pub use crate::ecb::Ecb; 14 | pub use crate::saadc::Saadc; 15 | pub use crate::spim::Spim; 16 | pub use crate::temp::Temp; 17 | pub use crate::timer::Timer; 18 | pub use crate::uarte::Uarte; 19 | -------------------------------------------------------------------------------- /nrf52811-hal/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "nrf52811-hal" 3 | version = "0.18.0" 4 | edition = "2018" 5 | description = "HAL for nRF52811 microcontrollers" 6 | readme = "../README.md" 7 | 8 | repository = "https://github.com/nrf-rs/nrf-hal" 9 | authors = [ 10 | "James Munns ", 11 | "Hanno Braun ", 12 | "John Scarrott ", 13 | "Wez Furlong ", 14 | "Ferdia McKeogh ", 15 | ] 16 | categories = ["embedded", "hardware-support", "no-std"] 17 | keywords = ["arm", "cortex-m", "nrf52", "hal", "nrf52811"] 18 | license = "MIT OR Apache-2.0" 19 | 20 | [dependencies] 21 | nrf52811-pac = "0.12.2" 22 | 23 | [dependencies.nrf-hal-common] 24 | path = "../nrf-hal-common" 25 | default-features = false 26 | features = ["52811"] 27 | version = "=0.18.0" 28 | 29 | [features] 30 | embedded-hal-02 = ["nrf-hal-common/embedded-hal-02"] 31 | rt = ["nrf52811-pac/rt"] 32 | rtic-monotonic = ["nrf-hal-common/rtic-monotonic"] 33 | default = ["rt", "embedded-hal-02"] 34 | -------------------------------------------------------------------------------- /nrf52811-hal/build.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::fs::File; 3 | use std::io::Write; 4 | use std::path::PathBuf; 5 | 6 | fn main() { 7 | let target = env::var("TARGET").unwrap(); 8 | if target.ends_with("eabihf") { 9 | panic!("attempting to build nrf52811-hal for target `{}`, but the nRF52811 does not have an FPU", target); 10 | } 11 | 12 | // Put the linker script somewhere the linker can find it 13 | let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); 14 | File::create(out.join("memory.x")) 15 | .unwrap() 16 | .write_all(include_bytes!("memory.x")) 17 | .unwrap(); 18 | println!("cargo:rustc-link-search={}", out.display()); 19 | 20 | println!("cargo:rerun-if-changed=build.rs"); 21 | println!("cargo:rerun-if-changed=memory.x"); 22 | } 23 | -------------------------------------------------------------------------------- /nrf52811-hal/memory.x: -------------------------------------------------------------------------------- 1 | /* Linker script for the nRF52 - WITHOUT SOFT DEVICE */ 2 | MEMORY 3 | { 4 | /* NOTE K = KiBi = 1024 bytes */ 5 | FLASH : ORIGIN = 0x00000000, LENGTH = 192K 6 | RAM : ORIGIN = 0x20000000, LENGTH = 24K 7 | } 8 | 9 | /* This is where the call stack will be allocated. */ 10 | /* The stack is of the full descending type. */ 11 | /* You may want to use this variable to locate the call stack and static 12 | variables in different memory regions. Below is shown the default value */ 13 | /* _stack_start = ORIGIN(RAM) + LENGTH(RAM); */ 14 | 15 | /* You can use this symbol to customize the location of the .text section */ 16 | /* If omitted the .text section will be placed right after the .vector_table 17 | section */ 18 | /* This is required only on microcontrollers that store some configuration right 19 | after the vector table */ 20 | /* _stext = ORIGIN(FLASH) + 0x400; */ 21 | 22 | /* Size of the heap (in bytes) */ 23 | /* _heap_size = 1024; */ -------------------------------------------------------------------------------- /nrf52811-hal/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![doc(html_root_url = "https://docs.rs/nrf52811-hal/0.18.0")] 3 | 4 | pub use nrf_hal_common::*; 5 | 6 | pub mod prelude { 7 | pub use nrf_hal_common::prelude::*; 8 | } 9 | 10 | pub use crate::ccm::Ccm; 11 | pub use crate::clocks::Clocks; 12 | pub use crate::delay::Delay; 13 | pub use crate::ecb::Ecb; 14 | pub use crate::saadc::Saadc; 15 | pub use crate::spim::Spim; 16 | pub use crate::temp::Temp; 17 | pub use crate::timer::Timer; 18 | pub use crate::uarte::Uarte; 19 | -------------------------------------------------------------------------------- /nrf52832-hal/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "nrf52832-hal" 3 | version = "0.18.0" 4 | description = "HAL for nRF52832 microcontrollers" 5 | readme = "../README.md" 6 | 7 | repository = "https://github.com/nrf-rs/nrf-hal" 8 | authors = [ 9 | "James Munns ", 10 | "Hanno Braun ", 11 | ] 12 | 13 | categories = ["embedded", "hardware-support", "no-std"] 14 | keywords = ["arm", "cortex-m", "nrf52", "hal", "nrf52832"] 15 | license = "MIT OR Apache-2.0" 16 | edition = "2018" 17 | 18 | [dependencies] 19 | nrf52832-pac = "0.12.2" 20 | 21 | [dependencies.nrf-hal-common] 22 | path = "../nrf-hal-common" 23 | default-features = false 24 | features = ["52832"] 25 | version = "=0.18.0" 26 | 27 | [features] 28 | doc = [] 29 | embedded-hal-02 = ["nrf-hal-common/embedded-hal-02"] 30 | rt = ["nrf52832-pac/rt"] 31 | xxAA-package = [] 32 | xxAB-package = [] 33 | rtic-monotonic = ["nrf-hal-common/rtic-monotonic"] 34 | 35 | # Note: We use the xxAB package because it has the least amount of available resources. 36 | # However, most users will want to use the xxAA package. 37 | default = ["rt", "xxAB-package", "embedded-hal-02"] 38 | -------------------------------------------------------------------------------- /nrf52832-hal/build.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::fs::File; 3 | use std::io::Write; 4 | use std::path::PathBuf; 5 | 6 | fn main() { 7 | if let Some((flash, mem)) = memory_sizes() { 8 | let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); 9 | 10 | let mut file = File::create(out.join("memory.x")).unwrap(); 11 | 12 | write!( 13 | file, 14 | r#"MEMORY 15 | {{ 16 | FLASH : ORIGIN = 0x00000000, LENGTH = {} 17 | RAM : ORIGIN = 0x20000000, LENGTH = {} 18 | }} 19 | "#, 20 | flash, mem 21 | ) 22 | .unwrap(); 23 | 24 | println!("cargo:rustc-link-search={}", out.display()); 25 | } 26 | 27 | println!("cargo:rerun-if-changed=build.rs"); 28 | } 29 | 30 | fn memory_sizes() -> Option<(&'static str, &'static str)> { 31 | match ( 32 | cfg!(feature = "xxAA-package"), 33 | cfg!(feature = "xxAB-package"), 34 | ) { 35 | // Allow users to provide their own memory.x by disabling both features 36 | (false, false) => None, 37 | (true, false) => Some(("512K", "64K")), 38 | (false, true) => Some(("256K", "32K")), 39 | _ => panic!("Multiple memory configuration features specified"), 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /nrf52832-hal/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![doc(html_root_url = "https://docs.rs/nrf52832-hal/0.18.0")] 3 | 4 | pub use nrf_hal_common::*; 5 | 6 | pub mod prelude { 7 | pub use nrf_hal_common::prelude::*; 8 | } 9 | 10 | pub use crate::ccm::Ccm; 11 | pub use crate::clocks::Clocks; 12 | pub use crate::delay::Delay; 13 | pub use crate::ecb::Ecb; 14 | pub use crate::rtc::Rtc; 15 | pub use crate::saadc::Saadc; 16 | pub use crate::spim::Spim; 17 | pub use crate::temp::Temp; 18 | pub use crate::timer::Timer; 19 | pub use crate::uarte::Uarte; 20 | -------------------------------------------------------------------------------- /nrf52833-hal/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "nrf52833-hal" 3 | version = "0.18.0" 4 | description = "HAL for nRF52833 microcontrollers" 5 | readme = "../README.md" 6 | 7 | repository = "https://github.com/nrf-rs/nrf-hal" 8 | authors = [ 9 | "James Munns ", 10 | "Hanno Braun ", 11 | "John Scarrott ", 12 | "Wez Furlong ", 13 | "Erik Svensson ", 14 | ] 15 | 16 | categories = ["embedded", "hardware-support", "no-std"] 17 | keywords = ["arm", "cortex-m", "nrf52", "hal", "nrf52833"] 18 | license = "MIT OR Apache-2.0" 19 | edition = "2018" 20 | 21 | [dependencies] 22 | nrf52833-pac = "0.12.2" 23 | 24 | [dependencies.nrf-hal-common] 25 | path = "../nrf-hal-common" 26 | default-features = false 27 | features = ["52833"] 28 | version = "=0.18.0" 29 | 30 | [features] 31 | doc = [] 32 | embedded-hal-02 = ["nrf-hal-common/embedded-hal-02"] 33 | rt = ["nrf52833-pac/rt"] 34 | rtic-monotonic = ["nrf-hal-common/rtic-monotonic"] 35 | default = ["rt", "embedded-hal-02"] 36 | -------------------------------------------------------------------------------- /nrf52833-hal/build.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::fs::File; 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 = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); 9 | File::create(out.join("memory.x")) 10 | .unwrap() 11 | .write_all(include_bytes!("memory.x")) 12 | .unwrap(); 13 | println!("cargo:rustc-link-search={}", out.display()); 14 | 15 | println!("cargo:rerun-if-changed=build.rs"); 16 | println!("cargo:rerun-if-changed=memory.x"); 17 | } 18 | -------------------------------------------------------------------------------- /nrf52833-hal/memory.x: -------------------------------------------------------------------------------- 1 | /* Linker script for the nRF52 - WITHOUT SOFT DEVICE */ 2 | MEMORY 3 | { 4 | /* NOTE K = KiBi = 1024 bytes */ 5 | FLASH : ORIGIN = 0x00000000, LENGTH = 512K 6 | RAM : ORIGIN = 0x20000000, LENGTH = 128K 7 | } 8 | 9 | /* This is where the call stack will be allocated. */ 10 | /* The stack is of the full descending type. */ 11 | /* You may want to use this variable to locate the call stack and static 12 | variables in different memory regions. Below is shown the default value */ 13 | /* _stack_start = ORIGIN(RAM) + LENGTH(RAM); */ 14 | 15 | /* You can use this symbol to customize the location of the .text section */ 16 | /* If omitted the .text section will be placed right after the .vector_table 17 | section */ 18 | /* This is required only on microcontrollers that store some configuration right 19 | after the vector table */ 20 | /* _stext = ORIGIN(FLASH) + 0x400; */ 21 | 22 | /* Size of the heap (in bytes) */ 23 | /* _heap_size = 1024; */ 24 | -------------------------------------------------------------------------------- /nrf52833-hal/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![doc(html_root_url = "https://docs.rs/nrf52833-hal/0.18.0")] 3 | 4 | pub use nrf_hal_common::*; 5 | 6 | pub mod prelude { 7 | pub use nrf_hal_common::prelude::*; 8 | } 9 | 10 | pub use crate::ccm::Ccm; 11 | pub use crate::clocks::Clocks; 12 | pub use crate::delay::Delay; 13 | pub use crate::ecb::Ecb; 14 | pub use crate::saadc::Saadc; 15 | pub use crate::spim::Spim; 16 | pub use crate::temp::Temp; 17 | pub use crate::timer::Timer; 18 | pub use crate::uarte::Uarte; 19 | -------------------------------------------------------------------------------- /nrf52840-hal-tests/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.thumbv7em-none-eabihf] 2 | runner = "probe-run --chip nRF52840_xxAA --probe 1366:1015" 3 | rustflags = [ 4 | "-C", "link-arg=--nmagic", 5 | "-C", "link-arg=-Tlink.x", 6 | "-C", "link-arg=-Tdefmt.x", 7 | "-C", "linker=flip-link", 8 | ] 9 | 10 | [build] 11 | target = "thumbv7em-none-eabihf" -------------------------------------------------------------------------------- /nrf52840-hal-tests/.gitignore: -------------------------------------------------------------------------------- 1 | target -------------------------------------------------------------------------------- /nrf52840-hal-tests/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | edition = "2018" 3 | name = "nrf52840-hal-tests" 4 | publish = false 5 | version = "0.0.0" 6 | 7 | [[test]] 8 | name = "gpio-input-floating" 9 | harness = false 10 | 11 | [[test]] 12 | name = "gpio-input-pulled" 13 | harness = false 14 | 15 | [[test]] 16 | name = "gpio-output-push-pull" 17 | harness = false 18 | 19 | [[test]] 20 | name = "gpio-output-open-drain" 21 | harness = false 22 | 23 | [[test]] 24 | name = "gpio-output-open-drain-io" 25 | harness = false 26 | 27 | [[test]] 28 | name = "nvmc" 29 | harness = false 30 | 31 | [[test]] 32 | name = "serial" 33 | harness = false 34 | 35 | [dev-dependencies] 36 | cortex-m = "0.7.3" 37 | cortex-m-rt = { version = "0.7.1", features = ["device"] } 38 | defmt = "1.0.1" 39 | defmt-rtt = "1.0.0" 40 | defmt-test = "0.4.0" 41 | embedded-hal = "1.0.0" 42 | embedded-storage = "0.3.0" 43 | nrf52840-hal = { path = "../nrf52840-hal" } 44 | panic-probe = { version = "1.0.0", features = ["print-defmt"] } 45 | -------------------------------------------------------------------------------- /nrf52840-hal-tests/README.md: -------------------------------------------------------------------------------- 1 | # nRF52840 HAL tests 2 | 3 | Run tests from the `cd nrf52840-hal-tests` folder as they require their own build considerations. 4 | 5 | Run `cargo test` to test the HAL on a nRF52840. 6 | 7 | To run a specific test: `cargo test --test nvmc`. 8 | 9 | The crate assumes that you'll test the HAL on a nRF52840 Development Kit. 10 | If you wish to use a different development board you'll need to update the flags passed to `probe-run` in `.cargo/config.toml`. 11 | 12 | The following wiring is required: 13 | 14 | - P0.03 <-> GND 15 | - P0.04 <-> VDD 16 | - P0.28 <-> P0.29 17 | -------------------------------------------------------------------------------- /nrf52840-hal-tests/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 | -------------------------------------------------------------------------------- /nrf52840-hal-tests/memory.x: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | /* NOTE 1 K = 1 KiB = 1024 bytes */ 4 | FLASH : ORIGIN = 0x00000000, LENGTH = 1024K - NUM_PAGES * 4K 5 | CONFIG : ORIGIN = ORIGIN(FLASH) + LENGTH(FLASH), LENGTH = NUM_PAGES * 4K 6 | RAM : ORIGIN = 0x20000000, LENGTH = 256K 7 | } 8 | 9 | NUM_PAGES = 6; 10 | _config = ORIGIN(CONFIG); 11 | 12 | /* This is where the call stack will be allocated. */ 13 | /* The stack is of the full descending type. */ 14 | /* You may want to use this variable to locate the call stack and static 15 | variables in different memory regions. Below is shown the default value */ 16 | /* _stack_start = ORIGIN(RAM) + LENGTH(RAM); */ 17 | 18 | /* You can use this symbol to customize the location of the .text section */ 19 | /* If omitted the .text section will be placed right after the .vector_table 20 | section */ 21 | /* This is required only on microcontrollers that store some configuration right 22 | after the vector table */ 23 | /* _stext = ORIGIN(FLASH) + 0x400; */ 24 | 25 | /* Example of putting non-initialized variables into custom RAM locations. */ 26 | /* This assumes you have defined a region RAM2 above, and in the Rust 27 | sources added the attribute `#[link_section = ".ram2bss"]` to the data 28 | you want to place there. */ 29 | /* Note that the section will not be zero-initialized by the runtime! */ 30 | /* SECTIONS { 31 | .ram2bss (NOLOAD) : ALIGN(4) { 32 | *(.ram2bss); 33 | . = ALIGN(4); 34 | } > RAM2 35 | } INSERT AFTER .bss; 36 | */ 37 | -------------------------------------------------------------------------------- /nrf52840-hal-tests/tests/gpio-input-floating.rs: -------------------------------------------------------------------------------- 1 | // Required connections: 2 | // 3 | // - P0.03 <-> GND 4 | // - P0.04 <-> VDD 5 | 6 | #![deny(warnings)] 7 | #![no_std] 8 | #![no_main] 9 | 10 | use defmt_rtt as _; 11 | use nrf52840_hal as _; 12 | use panic_probe as _; 13 | 14 | use nrf52840_hal::gpio::{Floating, Input, Pin}; 15 | 16 | struct State { 17 | input_ground: Pin>, 18 | input_vdd: Pin>, 19 | } 20 | 21 | #[defmt_test::tests] 22 | mod tests { 23 | use defmt::{assert, unwrap}; 24 | use embedded_hal::digital::InputPin; 25 | use nrf52840_hal::{gpio::p0, pac}; 26 | 27 | use super::State; 28 | 29 | #[init] 30 | fn init() -> State { 31 | let p = unwrap!(pac::Peripherals::take()); 32 | let port0 = p0::Parts::new(p.P0); 33 | 34 | let input_ground = port0.p0_03.into_floating_input().degrade(); 35 | let input_vdd = port0.p0_04.into_floating_input().degrade(); 36 | 37 | State { 38 | input_ground, 39 | input_vdd, 40 | } 41 | } 42 | 43 | #[test] 44 | fn ground_is_low(state: &mut State) { 45 | assert!(state.input_ground.is_low().unwrap()); 46 | } 47 | 48 | #[test] 49 | fn vdd_is_high(state: &mut State) { 50 | assert!(state.input_vdd.is_high().unwrap()); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /nrf52840-hal-tests/tests/gpio-input-pulled.rs: -------------------------------------------------------------------------------- 1 | // Required connections: 2 | // 3 | // - P0.28 <-> P0.29 4 | 5 | #![deny(warnings)] 6 | #![no_std] 7 | #![no_main] 8 | 9 | use defmt_rtt as _; 10 | use nrf52840_hal as _; 11 | use nrf52840_hal::gpio::{Floating, Input, Pin}; 12 | use panic_probe as _; 13 | 14 | struct State { 15 | input_pin: Pin>, 16 | puller_pin: Option>>, 17 | } 18 | 19 | #[defmt_test::tests] 20 | mod tests { 21 | use cortex_m::asm; 22 | use defmt::{assert, unwrap}; 23 | use embedded_hal::digital::InputPin; 24 | use nrf52840_hal::{gpio::p0, pac}; 25 | 26 | use super::State; 27 | 28 | #[init] 29 | fn init() -> State { 30 | let p = unwrap!(pac::Peripherals::take()); 31 | let port0 = p0::Parts::new(p.P0); 32 | 33 | let input_pin = port0.p0_28.into_floating_input().degrade(); 34 | let puller_pin = Some(port0.p0_29.into_floating_input().degrade()); 35 | 36 | State { 37 | input_pin, 38 | puller_pin, 39 | } 40 | } 41 | 42 | #[test] 43 | fn pulldown_is_low(state: &mut State) { 44 | let puller_pin = unwrap!(state.puller_pin.take()); 45 | 46 | let mut pulldown_pin = puller_pin.into_pulldown_input(); 47 | // GPIO re-configuration is not instantaneous so a delay is needed 48 | asm::delay(100); 49 | assert!(pulldown_pin.is_low().unwrap()); 50 | 51 | state.puller_pin = Some(pulldown_pin.into_floating_input()); 52 | } 53 | 54 | #[test] 55 | fn pulldown_drives_low(state: &mut State) { 56 | let puller_pin = unwrap!(state.puller_pin.take()); 57 | 58 | let pulldown_pin = puller_pin.into_pulldown_input(); 59 | assert!(state.input_pin.is_low().unwrap()); 60 | 61 | state.puller_pin = Some(pulldown_pin.into_floating_input()); 62 | } 63 | 64 | #[test] 65 | fn pullup_is_high(state: &mut State) { 66 | let puller_pin = unwrap!(state.puller_pin.take()); 67 | 68 | let mut pullup_pin = puller_pin.into_pullup_input(); 69 | // GPIO re-configuration is not instantaneous so a delay is needed 70 | asm::delay(100); 71 | assert!(pullup_pin.is_high().unwrap()); 72 | 73 | state.puller_pin = Some(pullup_pin.into_floating_input()); 74 | } 75 | 76 | #[test] 77 | fn pullup_drives_high(state: &mut State) { 78 | let puller_pin = unwrap!(state.puller_pin.take()); 79 | 80 | let pullup_pin = puller_pin.into_pullup_input(); 81 | // GPIO re-configuration is not instantaneous so a delay is needed 82 | asm::delay(100); 83 | assert!(state.input_pin.is_high().unwrap()); 84 | 85 | state.puller_pin = Some(pullup_pin.into_floating_input()); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /nrf52840-hal-tests/tests/gpio-output-open-drain-io.rs: -------------------------------------------------------------------------------- 1 | // Required connections: 2 | // 3 | // - P0.28 <-> P0.29 4 | 5 | #![deny(warnings)] 6 | #![no_std] 7 | #![no_main] 8 | 9 | use defmt_rtt as _; 10 | use nrf52840_hal as _; 11 | use nrf52840_hal::gpio::{Input, OpenDrainIO, Output, Pin, PullUp}; 12 | use panic_probe as _; 13 | 14 | struct State { 15 | input_pin: Option>>, 16 | output_pin: Pin>, 17 | } 18 | 19 | #[defmt_test::tests] 20 | mod tests { 21 | use cortex_m::asm; 22 | use defmt::{assert, unwrap}; 23 | use embedded_hal::digital::{InputPin, OutputPin}; 24 | use nrf52840_hal::{ 25 | gpio::{p0, Level, OpenDrainConfig}, 26 | pac, 27 | }; 28 | 29 | use super::State; 30 | 31 | #[init] 32 | fn init() -> State { 33 | let p = unwrap!(pac::Peripherals::take()); 34 | let port0 = p0::Parts::new(p.P0); 35 | 36 | let input_pin = Some(port0.p0_28.into_pullup_input().degrade()); 37 | let output_pin = port0 38 | .p0_29 39 | .into_open_drain_input_output(OpenDrainConfig::Standard0Disconnect1, Level::High) 40 | .degrade(); 41 | 42 | State { 43 | input_pin, 44 | output_pin, 45 | } 46 | } 47 | 48 | #[test] 49 | fn set_low_is_low(state: &mut State) { 50 | state.output_pin.set_low().unwrap(); 51 | // GPIO operations are not instantaneous so a delay is needed 52 | asm::delay(100); 53 | assert!(state.input_pin.as_mut().unwrap().is_low().unwrap()); 54 | } 55 | 56 | #[test] 57 | fn set_high_is_open(state: &mut State) { 58 | state.output_pin.set_high().unwrap(); 59 | // GPIO operations are not instantaneous so a delay is needed 60 | asm::delay(100); 61 | assert!(state.input_pin.as_mut().unwrap().is_high().unwrap()); 62 | 63 | let mut pulled_down_input_pin = state.input_pin.take().unwrap().into_pulldown_input(); 64 | // GPIO operations are not instantaneous so a delay is needed 65 | asm::delay(100); 66 | assert!(pulled_down_input_pin.is_low().unwrap()); 67 | 68 | // Restore original input pin state 69 | state.input_pin = Some(pulled_down_input_pin.into_pullup_input()); 70 | } 71 | 72 | #[test] 73 | fn open_pullup_reads_high(state: &mut State) { 74 | state.output_pin.set_high().unwrap(); 75 | // GPIO operations are not instantaneous so a delay is needed 76 | asm::delay(100); 77 | assert!(state.output_pin.is_high().unwrap()); 78 | } 79 | 80 | #[test] 81 | fn open_pulldown_reads_low(state: &mut State) { 82 | state.output_pin.set_high().unwrap(); 83 | 84 | let mut pulled_down_input_pin = state.input_pin.take().unwrap().into_pulldown_input(); 85 | // GPIO operations are not instantaneous so a delay is needed 86 | asm::delay(100); 87 | assert!(pulled_down_input_pin.is_low().unwrap()); 88 | 89 | // Restore original input pin state 90 | state.input_pin = Some(pulled_down_input_pin.into_pullup_input()); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /nrf52840-hal-tests/tests/gpio-output-open-drain.rs: -------------------------------------------------------------------------------- 1 | // Required connections: 2 | // 3 | // - P0.28 <-> P0.29 4 | 5 | #![deny(warnings)] 6 | #![no_std] 7 | #![no_main] 8 | 9 | use defmt_rtt as _; 10 | use nrf52840_hal as _; 11 | use nrf52840_hal::gpio::{Input, OpenDrain, Output, Pin, PullUp}; 12 | use panic_probe as _; 13 | 14 | struct State { 15 | input_pin: Option>>, 16 | output_pin: Pin>, 17 | } 18 | 19 | #[defmt_test::tests] 20 | mod tests { 21 | use cortex_m::asm; 22 | use defmt::{assert, unwrap}; 23 | use embedded_hal::digital::{InputPin, OutputPin}; 24 | use nrf52840_hal::{ 25 | gpio::{p0, Level, OpenDrainConfig}, 26 | pac, 27 | }; 28 | 29 | use super::State; 30 | 31 | #[init] 32 | fn init() -> State { 33 | let p = unwrap!(pac::Peripherals::take()); 34 | let port0 = p0::Parts::new(p.P0); 35 | 36 | let input_pin = Some(port0.p0_28.into_pullup_input().degrade()); 37 | let output_pin = port0 38 | .p0_29 39 | .into_open_drain_output(OpenDrainConfig::Standard0Disconnect1, Level::High) 40 | .degrade(); 41 | 42 | State { 43 | input_pin, 44 | output_pin, 45 | } 46 | } 47 | 48 | #[test] 49 | fn set_low_is_low(state: &mut State) { 50 | state.output_pin.set_low().unwrap(); 51 | // GPIO operations are not instantaneous so a delay is needed 52 | asm::delay(100); 53 | assert!(state.input_pin.as_mut().unwrap().is_low().unwrap()); 54 | } 55 | 56 | #[test] 57 | fn set_high_is_open(state: &mut State) { 58 | state.output_pin.set_high().unwrap(); 59 | // GPIO operations are not instantaneous so a delay is needed 60 | asm::delay(100); 61 | assert!(state.input_pin.as_mut().unwrap().is_high().unwrap()); 62 | 63 | let mut pulled_down_input_pin = state.input_pin.take().unwrap().into_pulldown_input(); 64 | // GPIO operations are not instantaneous so a delay is needed 65 | asm::delay(100); 66 | assert!(pulled_down_input_pin.is_low().unwrap()); 67 | 68 | // Restore original input pin state 69 | state.input_pin = Some(pulled_down_input_pin.into_pullup_input()); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /nrf52840-hal-tests/tests/gpio-output-push-pull.rs: -------------------------------------------------------------------------------- 1 | // Required connections: 2 | // 3 | // - P0.28 <-> P0.29 4 | 5 | #![deny(warnings)] 6 | #![no_std] 7 | #![no_main] 8 | 9 | use defmt_rtt as _; 10 | use nrf52840_hal as _; 11 | use nrf52840_hal::gpio::{Floating, Input, Output, Pin, PushPull}; 12 | use panic_probe as _; 13 | 14 | struct State { 15 | input_pin: Pin>, 16 | output_pin: Pin>, 17 | } 18 | 19 | #[defmt_test::tests] 20 | mod tests { 21 | use cortex_m::asm; 22 | use defmt::{assert, unwrap}; 23 | use embedded_hal::digital::{InputPin, OutputPin}; 24 | use nrf52840_hal::{ 25 | gpio::{p0, Level}, 26 | pac, 27 | }; 28 | 29 | use super::State; 30 | 31 | #[init] 32 | fn init() -> State { 33 | let p = unwrap!(pac::Peripherals::take()); 34 | let port0 = p0::Parts::new(p.P0); 35 | 36 | let input_pin = port0.p0_28.into_floating_input().degrade(); 37 | let output_pin = port0.p0_29.into_push_pull_output(Level::High).degrade(); 38 | 39 | State { 40 | input_pin, 41 | output_pin, 42 | } 43 | } 44 | 45 | #[test] 46 | fn set_low_is_low(state: &mut State) { 47 | state.output_pin.set_low().unwrap(); 48 | // GPIO operations are not instantaneous so a delay is needed 49 | asm::delay(100); 50 | assert!(state.input_pin.is_low().unwrap()); 51 | } 52 | 53 | #[test] 54 | fn set_high_is_high(state: &mut State) { 55 | state.output_pin.set_high().unwrap(); 56 | // GPIO operations are not instantaneous so a delay is needed 57 | asm::delay(100); 58 | assert!(state.input_pin.is_high().unwrap()); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /nrf52840-hal-tests/tests/nvmc.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use defmt_rtt as _; 5 | use nrf52840_hal as _; 6 | use panic_probe as _; 7 | 8 | use core::ptr::addr_of_mut; 9 | use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; 10 | use nrf52840_hal::{nvmc::Nvmc, pac}; 11 | 12 | const NUM_PAGES: u32 = 6; // must match memory.x 13 | const PAGE_SIZE: u32 = 4 * 1024; 14 | const LAST_PAGE: u32 = (NUM_PAGES - 1) * PAGE_SIZE; 15 | const CONFIG_SIZE: u32 = NUM_PAGES * PAGE_SIZE; 16 | extern "C" { 17 | #[link_name = "_config"] 18 | static mut CONFIG: [u8; CONFIG_SIZE as usize]; 19 | } 20 | 21 | struct State { 22 | nvmc: Nvmc, 23 | } 24 | 25 | #[defmt_test::tests] 26 | mod tests { 27 | use defmt::{assert, unwrap}; 28 | 29 | use super::*; 30 | 31 | #[init] 32 | fn init() -> State { 33 | let p = unwrap!(pac::Peripherals::take()); 34 | 35 | State { 36 | nvmc: Nvmc::new(p.NVMC, unsafe { addr_of_mut!(CONFIG).as_mut().unwrap() }), 37 | } 38 | } 39 | 40 | #[test] 41 | fn check_capacity(state: &mut State) { 42 | assert_eq!(state.nvmc.capacity(), CONFIG_SIZE as usize); 43 | } 44 | 45 | #[test] 46 | fn read_outofbounds(state: &mut State) { 47 | assert!(state.nvmc.read(CONFIG_SIZE, &mut [0]).is_err()); 48 | assert!(state.nvmc.read(CONFIG_SIZE - 1, &mut [0, 0]).is_err()); 49 | } 50 | 51 | #[test] 52 | fn erase_unaligned(state: &mut State) { 53 | assert!(state.nvmc.erase(LAST_PAGE + 1, PAGE_SIZE).is_err()); 54 | assert!(state.nvmc.erase(LAST_PAGE, PAGE_SIZE + 1).is_err()); 55 | } 56 | 57 | #[test] 58 | fn erase_outofbounds(state: &mut State) { 59 | assert!(state 60 | .nvmc 61 | .erase(CONFIG_SIZE, CONFIG_SIZE + PAGE_SIZE) 62 | .is_err()); 63 | assert!(state 64 | .nvmc 65 | .erase(LAST_PAGE, LAST_PAGE + 2 * PAGE_SIZE) 66 | .is_err()); 67 | } 68 | 69 | #[test] 70 | fn write_unaligned(state: &mut State) { 71 | let buf = [0u8; 4]; 72 | assert!(state.nvmc.write(LAST_PAGE + 1, &buf).is_err()); 73 | assert!(state.nvmc.write(LAST_PAGE, &buf[..1]).is_err()); 74 | } 75 | 76 | #[test] 77 | fn read_write_and_then_read(state: &mut State) { 78 | assert!(state.nvmc.erase(LAST_PAGE, CONFIG_SIZE).is_ok()); 79 | let mut read_buf = [0]; 80 | assert!(state.nvmc.read(LAST_PAGE, &mut read_buf).is_ok()); 81 | assert_eq!(read_buf[0], 0xff); 82 | let write_buf = [1, 2, 3, 4]; 83 | assert!(state.nvmc.write(LAST_PAGE, &write_buf).is_ok()); 84 | assert!(state.nvmc.read(LAST_PAGE, &mut read_buf).is_ok()); 85 | assert_eq!(read_buf[0], 1); 86 | } 87 | 88 | #[test] 89 | fn read_what_is_written(state: &mut State) { 90 | assert!(state.nvmc.erase(LAST_PAGE, CONFIG_SIZE).is_ok()); 91 | let write_buf: [u8; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; 92 | assert!(state.nvmc.write(LAST_PAGE, &write_buf).is_ok()); 93 | let mut read_buf = [0u8; 8]; 94 | assert!(state.nvmc.read(LAST_PAGE, &mut read_buf).is_ok()); 95 | assert_eq!(read_buf, write_buf); 96 | let mut partial_read_buf = [0u8; 4]; 97 | assert!(state 98 | .nvmc 99 | .read(LAST_PAGE + 2, &mut partial_read_buf) 100 | .is_ok()); 101 | assert_eq!(partial_read_buf, write_buf[2..][..4]); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /nrf52840-hal-tests/tests/serial.rs: -------------------------------------------------------------------------------- 1 | // Required connections: 2 | // 3 | // - P0.28 <-> P0.29 4 | 5 | #![no_std] 6 | #![no_main] 7 | 8 | use defmt_rtt as _; 9 | use nrf52840_hal as _; 10 | use panic_probe as _; 11 | 12 | use nrf52840_hal::{ 13 | pac::{TIMER0, UARTE0}, 14 | timer::OneShot, 15 | uarte::Uarte, 16 | Timer, 17 | }; 18 | 19 | struct State { 20 | _uarte: Uarte, 21 | _timer: Timer, 22 | } 23 | 24 | #[defmt_test::tests] 25 | mod tests { 26 | use defmt::unwrap; 27 | use nrf52840_hal::{ 28 | gpio::{p0, Level}, 29 | pac, 30 | }; 31 | use nrf52840_hal::{ 32 | uarte::{Baudrate, Parity, Pins, Uarte}, 33 | Timer, 34 | }; 35 | 36 | use super::State; 37 | 38 | #[init] 39 | fn init() -> State { 40 | let p = unwrap!(pac::Peripherals::take()); 41 | let port0 = p0::Parts::new(p.P0); 42 | 43 | let _timer = Timer::one_shot(p.TIMER0); 44 | 45 | let rxd = port0.p0_28.into_floating_input().degrade(); 46 | let txd = port0.p0_29.into_push_pull_output(Level::High).degrade(); 47 | 48 | let pins = Pins { 49 | rxd, 50 | txd, 51 | cts: None, 52 | rts: None, 53 | }; 54 | 55 | let _uarte = Uarte::new(p.UARTE0, pins, Parity::EXCLUDED, Baudrate::BAUD9600); 56 | 57 | State { _uarte, _timer } 58 | } 59 | 60 | // won't work because of how the `read` API work 61 | /* 62 | #[test] 63 | fn loopback(state: &mut State) { 64 | const BYTE: u8 = 0x42; 65 | const TIMEOUT: u32 = 1_000_000; 66 | 67 | let mut buffer = [BYTE]; 68 | 69 | // NOTE we pass a mutable reference to prevent the buffer from being allocated in Flash 70 | // (.rodata) as that results in an error 71 | state.uarte.write(&mut buffer).unwrap(); 72 | 73 | // clear this to detect the issue of `read` not writing to the buffer 74 | buffer[0] = 0; 75 | state 76 | .uarte 77 | .read_timeout(&mut buffer, &mut state.timer, TIMEOUT) 78 | .unwrap(); 79 | 80 | defmt::assert_eq!(buffer[0], BYTE) 81 | } 82 | */ 83 | } 84 | -------------------------------------------------------------------------------- /nrf52840-hal/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "nrf52840-hal" 3 | version = "0.18.0" 4 | description = "HAL for nRF52840 microcontrollers" 5 | readme = "../README.md" 6 | 7 | repository = "https://github.com/nrf-rs/nrf-hal" 8 | authors = [ 9 | "James Munns ", 10 | "Hanno Braun ", 11 | "John Scarrott ", 12 | "Wez Furlong ", 13 | ] 14 | 15 | categories = ["embedded", "hardware-support", "no-std"] 16 | keywords = ["arm", "cortex-m", "nrf52", "hal", "nrf52840"] 17 | license = "MIT OR Apache-2.0" 18 | edition = "2018" 19 | 20 | [dependencies] 21 | nrf52840-pac = "0.12.2" 22 | 23 | [dependencies.nrf-hal-common] 24 | path = "../nrf-hal-common" 25 | default-features = false 26 | features = ["52840"] 27 | version = "=0.18.0" 28 | 29 | [features] 30 | doc = [] 31 | embedded-hal-02 = ["nrf-hal-common/embedded-hal-02"] 32 | rt = ["nrf52840-pac/rt"] 33 | rtic-monotonic = ["nrf-hal-common/rtic-monotonic"] 34 | default = ["rt", "embedded-hal-02"] 35 | -------------------------------------------------------------------------------- /nrf52840-hal/build.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::fs::File; 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 = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); 9 | File::create(out.join("memory.x")) 10 | .unwrap() 11 | .write_all(include_bytes!("memory.x")) 12 | .unwrap(); 13 | println!("cargo:rustc-link-search={}", out.display()); 14 | 15 | println!("cargo:rerun-if-changed=build.rs"); 16 | println!("cargo:rerun-if-changed=memory.x"); 17 | } 18 | -------------------------------------------------------------------------------- /nrf52840-hal/memory.x: -------------------------------------------------------------------------------- 1 | /* Linker script for the nRF52 - WITHOUT SOFT DEVICE */ 2 | MEMORY 3 | { 4 | /* NOTE K = KiBi = 1024 bytes */ 5 | FLASH : ORIGIN = 0x00000000, LENGTH = 1024K 6 | RAM : ORIGIN = 0x20000000, LENGTH = 256K 7 | } 8 | 9 | /* This is where the call stack will be allocated. */ 10 | /* The stack is of the full descending type. */ 11 | /* You may want to use this variable to locate the call stack and static 12 | variables in different memory regions. Below is shown the default value */ 13 | /* _stack_start = ORIGIN(RAM) + LENGTH(RAM); */ 14 | 15 | /* You can use this symbol to customize the location of the .text section */ 16 | /* If omitted the .text section will be placed right after the .vector_table 17 | section */ 18 | /* This is required only on microcontrollers that store some configuration right 19 | after the vector table */ 20 | /* _stext = ORIGIN(FLASH) + 0x400; */ 21 | 22 | /* Size of the heap (in bytes) */ 23 | /* _heap_size = 1024; */ 24 | -------------------------------------------------------------------------------- /nrf52840-hal/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![doc(html_root_url = "https://docs.rs/nrf52840-hal/0.18.0")] 3 | 4 | pub use nrf_hal_common::*; 5 | 6 | pub mod prelude { 7 | pub use nrf_hal_common::prelude::*; 8 | } 9 | 10 | pub use crate::ccm::Ccm; 11 | pub use crate::clocks::Clocks; 12 | pub use crate::delay::Delay; 13 | pub use crate::ecb::Ecb; 14 | pub use crate::saadc::Saadc; 15 | pub use crate::spim::Spim; 16 | pub use crate::temp::Temp; 17 | pub use crate::timer::Timer; 18 | pub use crate::uarte::Uarte; 19 | -------------------------------------------------------------------------------- /nrf5340-app-hal/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "nrf5340-app-hal" 3 | version = "0.18.0" 4 | description = "HAL for nRF5340 app SoC" 5 | readme = "README.md" 6 | 7 | repository = "https://github.com/nrf-rs/nrf-hal" 8 | authors = [ 9 | "Jonathan Pallant (42 Technology) ", 10 | "Sascha Wise ", 10 | ] 11 | 12 | categories = ["embedded", "hardware-support", "no-std"] 13 | keywords = ["arm", "cortex-m", "nrf91", "hal", "nrf9160"] 14 | license = "MIT OR Apache-2.0" 15 | edition = "2018" 16 | 17 | [dependencies] 18 | nrf9160-pac = "0.12.2" 19 | 20 | [dependencies.nrf-hal-common] 21 | path = "../nrf-hal-common" 22 | default-features = false 23 | features = ["9160"] 24 | version = "=0.18.0" 25 | 26 | [features] 27 | doc = [] 28 | embedded-hal-02 = ["nrf-hal-common/embedded-hal-02"] 29 | rt = ["nrf9160-pac/rt"] 30 | rtic-monotonic = ["nrf-hal-common/rtic-monotonic"] 31 | default = ["rt", "embedded-hal-02"] 32 | -------------------------------------------------------------------------------- /nrf9160-hal/README.md: -------------------------------------------------------------------------------- 1 | # Hardware Abstration Layer for the Nordic nRF9160 2 | 3 | This crate is a Hardware Abstraction Layer (HAL) for the Nordic nRF9160. It 4 | wraps the PAC (`nrf9160-pac`) and provides high level wrappers for the chip's 5 | peripherals. 6 | 7 | This crate knows nothing about your PCB layout, or which pins you have assigned 8 | to which functions. The only exception are the examples, which are written to 9 | run on the official nRF9160-DK developer kit. 10 | 11 | ## Usage 12 | 13 | You will require the `thumbv8m.main-none-eabihf` target installed. 14 | 15 | ```console 16 | $ rustup target add thumbv8m.main-none-eabihf 17 | ``` 18 | 19 | ## Secure vs Non-Secure 20 | 21 | This HAL is designed to run in non-secure mode, as should most of your 22 | application code. You will therefore need a 'bootloader' which starts in secure 23 | mode, moves the required peripherals into 'non-secure' world, and then jumps to 24 | your application. 25 | 26 | We have succesfully used Nordic's [Secure Partition Manager](https://github.com/nrfconnect/sdk-nrf/tree/v1.5.1/samples/spm) 27 | from nRF SDK v1.5.1. SPM v1.5.1 is configured to expect your application at address 28 | `0x0005_0000` and so that is what `memory.x` must specify as the start of Flash. 29 | 30 | _Note:_ Other versions of SPM might expect a different start address - 31 | especially those compiled as a child image of another application (like 32 | `at_sample`)! You can see the start address on boot-up: 33 | 34 | ``` 35 | SPM: NS image at 0x50000 36 | ``` 37 | 38 | This tells you SPM is looking for a non-secure (NS) image at `0x0005_0000`. 39 | 40 | To build SPM, run: 41 | 42 | ```console 43 | $ west init -m https://github.com/nrfconnect/sdk-nrf --mr v1.5.1 ncs 44 | $ cd ncs 45 | $ west update # This takes *ages* 46 | $ cd nrf/examples/spm 47 | $ west build --board=nrf9160dk_nrf9160 48 | $ west flash 49 | ``` 50 | 51 | West is a Python tool supplied by Nordic for building the nRF Connect SDK. See 52 | [Nordic's website](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.5.1/nrf/gs_installing.html) 53 | for more details. 54 | 55 | Your nRF9160-DK will now have SPM installed between `0x0000_0000` and 56 | `0x0004_FFFF`. Flashing your application at `0x0005_0000` should not affect SPM, 57 | provided you do not select *erase entire chip* or somesuch! 58 | 59 | If you want to change the flash address, supply your own `memory.x` file in your 60 | application crate (or your Board Support Crate) and write a `build.rs` file that 61 | copies your `memory.x` over the top of this one. 62 | 63 | ## Licence 64 | 65 | Licensed under either of 66 | 67 | - Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or 68 | http://www.apache.org/licenses/LICENSE-2.0) 69 | - MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) 70 | 71 | at your option. 72 | 73 | ## Contribution 74 | 75 | Unless you explicitly state otherwise, any contribution intentionally 76 | submitted for inclusion in the work by you, as defined in the Apache-2.0 77 | license, shall be dual licensed as above, without any additional terms or 78 | conditions. 79 | -------------------------------------------------------------------------------- /nrf9160-hal/build.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::fs::File; 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 = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); 9 | File::create(out.join("memory.x")) 10 | .unwrap() 11 | .write_all(include_bytes!("memory.x")) 12 | .unwrap(); 13 | println!("cargo:rustc-link-search={}", out.display()); 14 | 15 | println!("cargo:rerun-if-changed=build.rs"); 16 | println!("cargo:rerun-if-changed=memory.x"); 17 | } 18 | -------------------------------------------------------------------------------- /nrf9160-hal/memory.x: -------------------------------------------------------------------------------- 1 | /* Linker script for the nRF9160 in Non-secure mode. It assumes you have the 2 | Nordic Secure Partition Manager installed at the bottom of flash and that 3 | the SPM is set to boot a non-secure application from the FLASH origin below. */ 4 | 5 | MEMORY 6 | { 7 | /* 8 | * This is where the Bootloader, Secure Partition Manager or 9 | * Trusted-Firmware-M lives. 10 | */ 11 | SECURE_FLASH : ORIGIN = 0x00000000, LENGTH = 256K 12 | /* 13 | * This is where your non-secure Rust application lives. Note that SPM must agree this 14 | * is where your application lives, or it will jump to garbage and crash the CPU. 15 | */ 16 | FLASH : ORIGIN = 0x00050000, LENGTH = 768K 17 | /* 18 | * This RAM is reserved for the Secure-Mode code located in the `SECURE_FLASH` region. 19 | */ 20 | SECURE_RAM : ORIGIN = 0x20000000, LENGTH = 64K 21 | /* 22 | * This RAM is available to both the Cortex-M33 and the LTE core (well, 23 | technically anything between `0x2000_0000` and `0x2001_FFFF` is 24 | shareable, but we just gave the first 64 KiB to Secure Mode). Shared 25 | buffers must be placed here. 26 | */ 27 | SHARED_RAM : ORIGIN = 0x20010000, LENGTH = 64K 28 | /* 29 | * This RAM is available to your non-secure Rust application. 30 | */ 31 | RAM : ORIGIN = 0x20020000, LENGTH = 128K 32 | } 33 | 34 | SECTIONS 35 | { 36 | /* This section contains the buffers used by `libnrf_modem` to talk between the Cortex-M33 and the LTE core */ 37 | .shared_ram (NOLOAD) : ALIGN(4) 38 | { 39 | . = ALIGN(4); 40 | *(.shared_ram .shared_ram.*); 41 | . = ALIGN(4); 42 | } > SHARED_RAM 43 | } 44 | -------------------------------------------------------------------------------- /nrf9160-hal/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![doc(html_root_url = "https://docs.rs/nrf9160-hal/0.18.0")] 3 | 4 | pub use nrf_hal_common::*; 5 | 6 | pub mod prelude { 7 | pub use nrf_hal_common::prelude::*; 8 | } 9 | 10 | pub use crate::clocks::Clocks; 11 | pub use crate::delay::Delay; 12 | pub use crate::rtc::Rtc; 13 | pub use crate::saadc::Saadc; 14 | pub use crate::spim::Spim; 15 | pub use crate::timer::Timer; 16 | pub use crate::twim::Twim; 17 | pub use crate::uarte::Uarte; 18 | -------------------------------------------------------------------------------- /xtask/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "xtask" 3 | version = "0.0.0" 4 | authors = ["Jonas Schievink "] 5 | edition = "2018" 6 | publish = false 7 | 8 | [[test]] 9 | name = "ci" 10 | harness = false 11 | -------------------------------------------------------------------------------- /xtask/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | 3 | fn main() { 4 | let mut args = env::args().skip(1); 5 | let subcommand = args.next(); 6 | match subcommand.as_deref() { 7 | Some("bump") => { 8 | let new_version = args.next().expect("missing argument"); 9 | xtask::bump_versions(&new_version, false); 10 | } 11 | _ => { 12 | eprintln!("usage: cargo xtask "); 13 | eprintln!(); 14 | eprintln!("subcommands:"); 15 | eprintln!(" bump - bump crate versions to "); 16 | } 17 | } 18 | } 19 | --------------------------------------------------------------------------------