diff --git a/.cargo/config b/.cargo/config index 78c1305..adce874 100644 --- a/.cargo/config +++ b/.cargo/config @@ -1,3 +1,32 @@ [target.armv7-unknown-linux-gnueabihf] linker = "arm-linux-gnueabihf-gcc" + +[target.thumbv7m-none-eabi] +#runner = 'arm-none-eabi-gdb' +runner = "gdb-multiarch -q -x openocd.gdb" +rustflags = [ + "-C", "link-arg=-Tlink.x", +] + +[target.thumbv7em-none-eabi] +#runner = 'arm-none-eabi-gdb' +runner = "gdb-multiarch -q -x openocd.gdb" +rustflags = [ + "-C", "link-arg=-Tlink.x", +] + +[target.thumbv7em-none-eabihf] +#runner = 'arm-none-eabi-gdb' +runner = "gdb-multiarch -q -x openocd.gdb" +rustflags = [ + "-C", "link-arg=-Tlink.x", +] + +[target.riscv32imac-unknown-none-elf] +#runner = 'riscv64-unknown-elf-gdb -x openocd.gdb' +runner = "gdb-multiarch -q -x openocd.gdb" +rustflags = [ + #"-C", "link-arg=-memory-CB.x", + "-C", "link-arg=-Tlink.x", +] diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index d5153c7..85c2f2d 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -2,7 +2,7 @@ name: Rust on: push: - branches: [ master ] + branches: [ master] tags: [ 'v*' ] pull_request: branches: [ master ] @@ -26,12 +26,15 @@ jobs: use_cross: false experimental: false args: --features util,driver-pal/hal-cp2130,driver-pal/hal-linux - - target: armv7-unknown-linux-gnueabihf + + # probably want next three targets on master, but they are time consuming when testing examples + - target: armv7-unknown-linux-gnueabihf os: ubuntu-latest output: sx127x-util use_cross: false experimental: true args: --features util,driver-pal/hal-cp2130,driver-pal/hal-linux + - target: x86_64-apple-darwin os: macos-latest output: sx127x-util @@ -92,7 +95,8 @@ jobs: with: key: ${{ matrix.os }}-${{ matrix.target }} path: $VCPKG_DIRECTORY - + + # probably want next 4 name sections on master, but not on forks and branches - name: Build release uses: actions-rs/cargo@v1 with: @@ -121,6 +125,51 @@ jobs: tag: ${{ github.ref }} overwrite: true + test_examples: + name: Test examples + runs-on: ubuntu-latest + continue-on-error: true + strategy: + matrix: + mcu: [stm32f103, stm32f411 ] + include: + - mcu: stm32f103 + hal: "stm32f1xx" + trg: "thumbv7m-none-eabi" + - mcu: stm32f411 + hal: "stm32f4xx" + trg: "thumbv7em-none-eabihf" + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + #- name: Build + # uses: actions-rs/cargo@v1 + # with: + # command: build + # args: --no-default-features --release --target ${{ matrix.trg }} --features ${{ matrix.mcu }},compat + - name: Build example lora_spi_send + uses: actions-rs/cargo@v1 + with: + command: build + args: --no-default-features --release --target ${{ matrix.trg }} --features ${{ matrix.hal }},${{ matrix.mcu }},compat --example lora_spi_send + use-cross: true + - name: Build example lora_spi_receive + uses: actions-rs/cargo@v1 + with: + command: build + args: --no-default-features --release --target ${{ matrix.trg }} --features ${{ matrix.hal }},${{ matrix.mcu }},compat --example lora_spi_receive + use-cross: true + - name: Build example lora_spi_gps + uses: actions-rs/cargo@v1 + with: + command: build + args: --no-default-features --release --target ${{ matrix.trg }} --features ${{ matrix.hal }},${{ matrix.mcu }},compat --example lora_spi_gps + use-cross: true + + # probably want release on master, but not on forks and branches release: name: Create release runs-on: ubuntu-latest diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 20797bf..0000000 --- a/.travis.yml +++ /dev/null @@ -1,39 +0,0 @@ -language: rust -cache: cargo -matrix: - include: - - env: TARGET=x86_64-unknown-linux-gnu - os: linux - - env: TARGET=armv7-unknown-linux-gnueabihf - os: linux - addons: - apt: - packages: - - libc6-i386 - - libc6-dev-i386 - - gcc-arm-linux-gnueabihf - - libc6-armhf-cross - - libc6-dev-armhf-cross -install: -- cargo fetch -- rustup target add armv7-unknown-linux-gnueabihf -- rustup component add rustfmt -script: -- cargo build && cargo test && cargo build --target=$TARGET --release -before_deploy: -- tar -cvf target/sx127x-util-$TARGET-$TRAVIS_TAG.tgz -C target/$TARGET/release/ sx127x-util - -notifications: - email: - on_success: never - on_failure: never -deploy: - provider: releases - api_key: - secure: KwL6ue3wNTQiUM05SxMUNlcOnlkCHxpZIKRNmpqhdT0F27RxNIl4DD0wcrA9yD1IB2jv+ZOiXeQGgYEu5s/uYpoNul9lEk3K3UxxxnzKxKH/ByaeiPnlzymBnaN47QFcjFEk5uY8eLHdtXzk6Ku6YbmSJ4uS2WSq3+Q/hnS2od/jqGi2aYy/RBHrS7oFirpcEDYQWfBDftn8vRtVSVPrv+kdBV1qKI5GhP7nodApC3g/LJHeoXHfJo9gxf4PxyCsrFKrjWvUPVkHAq62+J2ETzWNupMYpj8t23Ip+1KxTQd2MLL2epUggTvLA6nunwI3877Trjy76b4F1Ic72GD1WbL3o4UXG/9QRfAGXfjfDnp2W52v0L9uW9URF4qmBI1NY0lceQOmaSyYSJz/4xMV6Txbx+MPoISpsgVsdieMkRFUPo9cm/Lj4+TTgbLVXl2iNZU6H9ezbkx8K0gdrqGZIUJmpsPmONl7nqSNKHHtmyE0xME6TlRDwHWnLizRe4XfoIN89Fj3IM9I6AHx96gK8T7SRWBhIyVsJmuM13E1rbmKyaamB7onBjbay2rXeeO89f2uqvRBjcdsMecH85uUw0H5DnC4mPBJE8bGHnwm3sHx25a6ZP+vBS/Dza33Nqodh3KgNDOPSEK15Vn7+zB5Z5YhERhiL81bke3NF2irSko= - file: target/*.tgz - file_glob: true - skip_cleanup: true - on: - tags: true - repo: ryankurte/rust-radio-sx127x diff --git a/Cargo.lock b/Cargo.lock index 8195544..d303c17 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,7 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 - [[package]] name = "addr2line" version = "0.15.1" @@ -23,6 +21,15 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" +[[package]] +name = "aligned" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c19796bd8d477f1a9d4ac2465b464a8b1359474f06a96bb3cda650b4fca309bf" +dependencies = [ + "as-slice", +] + [[package]] name = "ansi_term" version = "0.11.0" @@ -32,6 +39,27 @@ dependencies = [ "winapi", ] +[[package]] +name = "as-slice" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45403b49e3954a4b8428a0ac21a4b7afadccf92bfd96273f1a58cd4812496ae0" +dependencies = [ + "generic-array 0.12.4", + "generic-array 0.13.3", + "generic-array 0.14.4", + "stable_deref_trait", +] + +[[package]] +name = "atomic-polyfill" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30302dda7a66f8c55932ebf208f7def840743ff64d495e9ceffcd97c18f11d39" +dependencies = [ + "cortex-m 0.7.2", +] + [[package]] name = "atty" version = "0.2.14" @@ -64,6 +92,21 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "bare-metal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" +dependencies = [ + "rustc_version 0.2.3", +] + +[[package]] +name = "bitfield" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" + [[package]] name = "bitflags" version = "1.2.1" @@ -82,7 +125,7 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57cdfa5d50aad6cb4d44dcab6101a7f79925bd59d82ca42f38a9856a28865374" dependencies = [ - "rustc_version", + "rustc_version 0.3.3", ] [[package]] @@ -132,14 +175,58 @@ dependencies = [ ] [[package]] -name = "color-backtrace" -version = "0.5.1" +name = "cortex-m" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd6c04463c99389fff045d2b90ce84f5131332712c7ffbede020f5e9ad1ed685" +checksum = "9075300b07c6a56263b9b582c214d0ff037b00d45ec9fde1cc711490c56f1bb9" dependencies = [ - "atty", - "backtrace", - "termcolor", + "aligned", + "bare-metal", + "bitfield", + "cortex-m 0.7.2", + "volatile-register", +] + +[[package]] +name = "cortex-m" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643a210c1bdc23d0db511e2a576082f4ff4dcae9d0c37f50b431b8f8439d6d6b" +dependencies = [ + "bare-metal", + "bitfield", + "embedded-hal 0.2.5", + "volatile-register", +] + +[[package]] +name = "cortex-m-rt" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d8353767db816419630a76d5f1ad5b09610d22b67ceb59647df6a8abc667f8" +dependencies = [ + "cortex-m-rt-macros", + "r0", +] + +[[package]] +name = "cortex-m-rt-macros" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4717562afbba06e760d34451919f5c3bf3ac15c7bb897e8b04862a7428378647" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "cortex-m-semihosting" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bffa6c1454368a6aa4811ae60964c38e6996d397ff8095a8b9211b1c1f749bc" +dependencies = [ + "cortex-m 0.7.2", ] [[package]] @@ -159,7 +246,7 @@ checksum = "f4eac76f1aa9cf700bb7e905fc3212014878bfd27571df5db648189c8d2e1d4b" dependencies = [ "bitflags", "byteorder", - "embedded-hal", + "embedded-hal 1.0.0-alpha.4", "failure", "hex", "lazy_static", @@ -178,7 +265,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a7483af22e06f2b2fff6ebcaf2724aa29d47c29fa5dcadfc1f71ef862de5b40" dependencies = [ "driver-cp2130", - "embedded-hal", + "embedded-hal 1.0.0-alpha.4", "linux-embedded-hal", "log", "serde", @@ -187,13 +274,42 @@ dependencies = [ "toml", ] +[[package]] +name = "embedded-dma" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c8c02e4347a0267ca60813c952017f4c5948c232474c6010a381a337f1bda4" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "embedded-hal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db184d3fa27bc7a2344250394c0264144dfe0bc81a4401801dcb964b8dd172ad" +dependencies = [ + "nb 0.1.3", + "void", +] + [[package]] name = "embedded-hal" version = "1.0.0-alpha.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2260cabeacf4bda1df1a8d54f67047a9aadf02fe14cfab07649f2cec6a4693b" dependencies = [ - "nb", + "nb 1.0.0", +] + +[[package]] +name = "embedded-hal-compat" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2afb504e8ae78ede52799ea060abb3836fe2f7a24e8ac1cacb9086c5cfcabf7" +dependencies = [ + "embedded-hal 0.2.5", + "embedded-hal 1.0.0-alpha.4", ] [[package]] @@ -230,6 +346,34 @@ dependencies = [ "winapi", ] +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum", +] + +[[package]] +name = "generic-array" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f797e67af32588215eaaab8327027ee8e71b9dd0b2b26996aedf20c030fce309" +dependencies = [ + "typenum", +] + +[[package]] +name = "generic-array" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" version = "0.2.3" @@ -258,6 +402,26 @@ dependencies = [ "nix", ] +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + +[[package]] +name = "heapless" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7ee8a997d259962217f40279f34201fdf06e669bafa69d7c1f4c7ff1893b5f6" +dependencies = [ + "atomic-polyfill", + "hash32", + "stable_deref_trait", +] + [[package]] name = "heck" version = "0.3.2" @@ -362,10 +526,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf344a431d851ca3181405a708961535366e167b28e51aa644488435512d0a8a" dependencies = [ "cast", - "embedded-hal", + "embedded-hal 1.0.0-alpha.4", "gpio-cdev", "i2cdev", - "nb", + "nb 1.0.0", "serial-core", "serial-unix", "spidev", @@ -391,6 +555,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.0.0", +] + [[package]] name = "nb" version = "1.0.0" @@ -435,6 +608,22 @@ version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a5b3dd1c072ee7963717671d1ca129f1048fda25edea6b752bfc71ac8854170" +[[package]] +name = "panic-halt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de96540e0ebde571dc55c73d60ef407c653844e6f9a1e2fdbd40c07b9252d812" + +[[package]] +name = "panic-semihosting" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d55dedd501dfd02514646e0af4d7016ce36bc12ae177ef52056989966a1eec" +dependencies = [ + "cortex-m 0.7.2", + "cortex-m-semihosting", +] + [[package]] name = "pest" version = "2.1.3" @@ -498,6 +687,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r0" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f" + [[package]] name = "radio" version = "0.9.0" @@ -505,9 +700,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5b2be51c82da34d592a00dbb008f651a30a4162668647482adaeef6453055de" dependencies = [ "chrono", - "embedded-hal", + "embedded-hal 1.0.0-alpha.4", "log", - "nb", + "nb 1.0.0", ] [[package]] @@ -515,17 +710,27 @@ name = "radio-sx127x" version = "0.11.0" dependencies = [ "bitflags", - "color-backtrace", + "cortex-m 0.6.7", + "cortex-m-rt", + "cortex-m-semihosting", "driver-cp2130", "driver-pal", - "embedded-hal", + "embedded-hal 0.2.5", + "embedded-hal 1.0.0-alpha.4", + "embedded-hal-compat", + "heapless", "humantime", "libc", "linux-embedded-hal", "log", + "nb 1.0.0", + "panic-halt", + "panic-semihosting", "radio", "serde", "simplelog 0.8.0", + "stm32f1xx-hal", + "stm32f4xx-hal", "structopt", ] @@ -537,7 +742,7 @@ checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" dependencies = [ "libc", "rand_chacha", - "rand_core", + "rand_core 0.6.2", "rand_hc", ] @@ -548,9 +753,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.2", ] +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" + [[package]] name = "rand_core" version = "0.6.2" @@ -566,7 +777,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" dependencies = [ - "rand_core", + "rand_core 0.6.2", ] [[package]] @@ -600,13 +811,31 @@ version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "410f7acf3cb3a44527c5d9546bad4bf4e6c460915d5f9f2fc524498bfe8f70ce" +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + [[package]] name = "rustc_version" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" dependencies = [ - "semver", + "semver 0.11.0", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser 0.7.0", ] [[package]] @@ -615,9 +844,15 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" dependencies = [ - "semver-parser", + "semver-parser 0.10.2", ] +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + [[package]] name = "semver-parser" version = "0.10.2" @@ -701,6 +936,69 @@ dependencies = [ "nix", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "stm32f1" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "849b1e8d9bcfd792c9d9178cf86165d299a661c26e35d9322ae9382d3f3fe460" +dependencies = [ + "bare-metal", + "cortex-m 0.6.7", + "cortex-m-rt", + "vcell", +] + +[[package]] +name = "stm32f1xx-hal" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf679de34580d2f8806d9a6384c110b6df002404e1ff024cf8d567c91df4d4b2" +dependencies = [ + "cast", + "cortex-m 0.6.7", + "cortex-m-rt", + "embedded-dma", + "embedded-hal 0.2.5", + "nb 0.1.3", + "stm32f1", + "void", +] + +[[package]] +name = "stm32f4" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11460b4de3a84f072e2cf6e76306c64d27f405a0e83bace0a726f555ddf4bf33" +dependencies = [ + "bare-metal", + "cortex-m 0.6.7", + "cortex-m-rt", + "vcell", +] + +[[package]] +name = "stm32f4xx-hal" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3a2f044469d1e3aff2cd02bee8b2724f3d5d91f3175e5d1ec99770320d16192" +dependencies = [ + "bare-metal", + "cast", + "cortex-m 0.6.7", + "cortex-m-rt", + "embedded-hal 0.2.5", + "nb 0.1.3", + "rand_core 0.5.1", + "stm32f4", + "void", +] + [[package]] name = "strsim" version = "0.8.0" @@ -820,6 +1118,12 @@ dependencies = [ "serde", ] +[[package]] +name = "typenum" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" + [[package]] name = "ucd-trie" version = "0.1.3" @@ -844,6 +1148,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + [[package]] name = "vcpkg" version = "0.2.13" @@ -868,6 +1178,15 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +[[package]] +name = "volatile-register" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d67cb4616d99b940db1d6bd28844ff97108b498a6ca850e5b6191a532063286" +dependencies = [ + "vcell", +] + [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index 1149d2c..de39f02 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,19 @@ edition = "2018" util = [ "structopt", "driver-pal/hal", "simplelog", "humantime" ] default = [ "util", "serde", "driver-pal/hal-cp2130", "driver-pal/hal-linux" ] +# features for examples +examples = [] +compat = ["embedded-hal-compat"] + +stm32f1xx = [] +stm32f4xx = [] + +stm32f103 = ["stm32f1xx-hal/stm32f103", "stm32f1xx-hal/rt", "examples"] +stm32f411 = ["stm32f4xx-hal/stm32f411", "stm32f4xx-hal/rt", "examples"] + [dependencies] +embedded-hal-compat = { version = "0.1.3", optional = true} +#embedded-hal-compat = { git = "https://github.com/ryankurte/embedded-hal-compat.git", branch = "main", optional = true} libc = "0.2" log = { version = "0.4" } bitflags = "1.0" @@ -23,15 +35,28 @@ structopt = { version = "0.3.21", optional = true } simplelog = { version = "0.8.0", optional = true } humantime = { version = "2.0.0", optional = true } linux-embedded-hal = { version = "0.4.0-alpha.0", optional = true } -driver-cp2130 = { version = "1.0.0-alpha.2", optional = true } +# Next could be dev-dependencies since they are only for examples, but +# dev-dependencies do not allow optional (as of cargo 1.44.1). +stm32f1xx-hal = {version = "^0.7.0", optional = true} +stm32f4xx-hal = {version = "^0.8.3", optional = true} + +old-e-h = {version = "0.2.4", package = "embedded-hal" } + +driver-cp2130 = { version = "1.0.0-alpha.2", optional = true } [dependencies.driver-pal] version = "0.8.0-alpha.2" default-features = false -[dev-dependencies] -color-backtrace = "0.5" +[dev-dependencies] # for examples +cortex-m = "0.6.7" +cortex-m-rt = "0.6.13" +cortex-m-semihosting = "0.3.7" +panic-halt = "0.2.0" +panic-semihosting = ">=0.5.2" +heapless = ">=0.7.0" # for example lora_spi_gps +nb = ">=0.1.2" # for example lora_spi_gps [[bin]] @@ -42,5 +67,20 @@ required-features = ["util"] [[test]] name = "integration" path = "tests/integration.rs" -required-features = ["utils"] +required-features = ["default", "util"] + + +[[example]] +name = "lora_spi_send" +path = "examples/lora_spi_send.rs" +required-features = ["examples"] + +[[example]] +name = "lora_spi_receive" +path = "examples/lora_spi_receive.rs" +required-features = ["examples"] +[[example]] +name = "lora_spi_gps" +path = "examples/lora_spi_gps.rs" +required-features = ["examples"] diff --git a/README.md b/README.md index 939ef28..953d189 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,10 @@ Install the utility with one of the following methods: The radio-sx127x crate can be used as an interface library for the sx127x radio on other embedded devices. To enable `no_std` usage, add `default-features = false` to your -`Cargo.toml` +`Cargo.toml`. +See examples `lora_spi_send`, `lora_spi_receive`, and `lora_spi_gps`. +Comments in the `file examples/lora_spi_send.rs` show how to build and run the examples +on several different MCUs. ## Useful Resources diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..ebef9f7 --- /dev/null +++ b/build.rs @@ -0,0 +1,108 @@ +// following https://doc.rust-lang.org/cargo/reference/build-scripts.html +use std::env; +//use std::io::Write; //needed for debugging +//use std::path::PathBuf; //needed for one approach +//use std::fs; //needed for one approach + +fn main() { + // This file (build.rs) needs to be in the package root. + // It is called before the linker and used to arrange for the linker to find the + // proper memory.x file for the MCU. The memory.x files are assumed to be in a + // directory examples/memoryMaps/xxx/ where xxx is replaced by an one of + + let mcus = [ + "STM32F042", + "STM32F030XC", + "STM32F100", + "STM32F101", + "STM32F103", + "STM32F303XC", + "STM32F401", + "STM32F411", + "STM32F722", + "STM32H742", + "STM32L0X2", + "STM32L100", + "STM32L151", + "STM32L4X2", + "LM3S6965", + "GD32VF103CB", + "GD32VF103C8", + "GD32VF103_EXTRA", + ]; + + // For example, examples/memoryMaps/STM32F401/memory.x + // Note that the MCU string must be in upper case because it is also used to + // find the CARGO_FEATURE_xxx environment variable (eg CARGO_FEATURE_STM32F401) + // which is in upper case. + + // There are two possible appraches: one is to copy the appropriate memory.x file into the OUT_DIR + // where compiled pieces are placed for linking, then add that dir to the linker search path. + // (Adding to path may be redundant, the OUT_DIR is probably already in the search path.) + // The second approach is to simply add the location of the appropriate memory.x file to + // the search path. This is not only quicker, but has the advantage that the memory.x file + // can be MCU specific. In the copy appraoch the OUT_DIR is only MCU triple specific, so there + // could be conflicts (in the unlikely situation) where two mcu's have the same triple and + // different memory layouts. + + // The memoryNote.txt file is just to record some debugging information + //let mut df = std::fs::File::create("memoryNote.txt").unwrap(); + + // It is assumed that only one MCU feature will be specified. If there are more then + // only the first is found (but actual code may be a mess if cargo really lets you do that). + + let pre = "CARGO_FEATURE_".to_owned(); + + // For debugging. Write all CARGO_FEATURE_ mcu variables to file + //for m in &mcus { + // match env::var_os(pre.clone() + m) { + // None => df.write(format!("{}{} is not set\n", pre, m).as_bytes()).unwrap(), + // Some(x) => df.write(format!("{}{} is {:?}\n", pre, m, x).as_bytes()).unwrap() + // }; + // }; + + // For debugging. Write all env variables to file + //df.write(format!("env::vars() gives\n").as_bytes()).unwrap(); + //for (key, value) in env::vars() { + // df.write(format!(" {:?}: {:?}\n", key, value).as_bytes()).unwrap(); + // }; + + // Compare mcus elements against CARGO_FEATURE_* env variables to determine directory of + // memory.x file to use. + // If there is no MCU feature identified then the usual default is that memory.x is + // searched for in the package root. + + let mut indir: String = "".to_string(); + let d = "examples/memoryMaps/".to_owned(); + for m in &mcus { + let v = env::var_os(pre.clone() + m); + if v.is_some() { + indir = d + m; + break; + }; + } + + // Adding an empty search path causes problems compiling the crate, so skip if memory.x not found. + // This allows 'cargo build --features $MCU ' to work + // but do not expect to compile examples. (There will be a 'cannot find linker script memory.x' error.) + + if !indir.is_empty() { + //df.write(format!("in mcu found condition.\n").as_bytes()).unwrap(); + let infile = indir.clone() + "/memory.x"; + + // one approach + //let outdir = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + //let outfile = &PathBuf::from(env::var_os("OUT_DIR").unwrap()).join("memory.x"); + //fs::copy(&infile, outfile).unwrap(); // Copy memory.x to OUT_DIR. Possibly should handle error. + //println!("cargo:rustc-link-search={}", outdir.display()); + + // other approach + println!("cargo:rustc-link-search={}", indir); + + println!("cargo:rerun-if-changed=build.rs"); + println!("cargo:rerun-if-changed={}", infile); + } else { + //df.write(format!("mcu NOT found condition.\n").as_bytes()).unwrap(); + println!(); + } +} diff --git a/examples/lora_spi_gps.rs b/examples/lora_spi_gps.rs new file mode 100644 index 0000000..488bfef --- /dev/null +++ b/examples/lora_spi_gps.rs @@ -0,0 +1,372 @@ +//! Serial interface read GPS on usart and transmit with LoRa using crate radio_sx127x (on SPI). +//! See example lora_spi_send for more details. +//! See the MCU device setup() sections for details on pin connections. + +//https://www.rfwireless-world.com/Tutorials/LoRa-channels-list.html +// channels are as follows +// 'CH_00_900': 903.08, 'CH_01_900': 905.24, 'CH_02_900': 907.40, +// 'CH_03_900': 909.56, 'CH_04_900': 911.72, 'CH_05_900': 913.88, +// 'CH_06_900': 916.04, 'CH_07_900': 918.20, 'CH_08_900': 920.36, +// 'CH_09_900': 922.52, 'CH_10_900': 924.68, 'CH_11_900': 926.84, 'CH_12_900': 915, +// +// 'CH_10_868': 865.20, 'CH_11_868': 865.50, 'CH_12_868': 865.80, +// 'CH_13_868': 866.10, 'CH_14_868': 866.40, 'CH_15_868': 866.70, +// 'CH_16_868': 867 , 'CH_17_868': 868 , + +// See FREQUENCY below to set the channel. + +#![no_std] +#![no_main] + +#[cfg(debug_assertions)] +extern crate panic_semihosting; + +#[cfg(not(debug_assertions))] +extern crate panic_halt; +//extern crate panic_reset; + +use core::convert::Infallible; + +use cortex_m_rt::entry; +use cortex_m_semihosting::*; +use nb::block; + +use heapless; + +use embedded_hal::blocking::delay::DelayMs; + +use embedded_hal_compat::IntoCompat; + +// MODE needs the old version as it is passed to the device hal crates +//use embedded_hal::{spi::{Mode, Phase, Polarity}, }; +use old_e_h::spi::{Mode, Phase, Polarity}; + +//use asm_delay::{ AsmDelay, bitrate, }; + +//use cortex_m::asm; //for breakpoint + +use radio_sx127x::Error as sx127xError; // Error name conflict with hals +use radio_sx127x::{ + device::lora::{ + Bandwidth, CodingRate, FrequencyHopping, LoRaChannel, LoRaConfig, PayloadCrc, + PayloadLength, SpreadingFactor, + }, + device::{Channel, Modem, PaConfig, PaSelect}, + prelude::*, // prelude has Sx127x, +}; + +//use radio::{Receive, Transmit}; +use radio::Transmit; // trait needs to be in scope to find methods start_transmit and check_transmit. + +// lora and radio parameters + +pub const MODE: Mode = Mode { + // SPI mode for radio + phase: Phase::CaptureOnSecondTransition, + polarity: Polarity::IdleHigh, +}; + +const FREQUENCY: u32 = 907_400_000; // frequency in hertz ch_12_900: 915_000_000, ch_2_900: 907_400_000 + +const CONFIG_CH: LoRaChannel = LoRaChannel { + freq: FREQUENCY as u32, // frequency in hertz + bw: Bandwidth::Bw125kHz, + sf: SpreadingFactor::Sf7, + cr: CodingRate::Cr4_8, +}; + +const CONFIG_LORA: LoRaConfig = LoRaConfig { + preamble_len: 0x8, + symbol_timeout: 0x64, + payload_len: PayloadLength::Variable, + payload_crc: PayloadCrc::Enabled, + frequency_hop: FrequencyHopping::Disabled, + invert_iq: false, +}; + +const CONFIG_PA: PaConfig = PaConfig { + output: PaSelect::Boost, + power: 10, +}; + +//let CONFIG_RADIO = Config::default() ; + +const CONFIG_RADIO: radio_sx127x::device::Config = radio_sx127x::device::Config { + modem: Modem::LoRa(CONFIG_LORA), + channel: Channel::LoRa(CONFIG_CH), + pa_config: CONFIG_PA, + xtal_freq: 32000000, // CHECK + timeout_ms: 100, +}; + +// setup() does all hal/MCU specific setup and returns generic hal device for use in main code. + +#[cfg(feature = "stm32f1xx")] // eg blue pill stm32f103 +use stm32f1xx_hal::{ + delay::Delay, + device::USART2, + pac::Peripherals, + prelude::*, + serial::{Config, Rx, Serial, Tx}, //, StopBits + spi::{Error, Spi}, +}; + +#[cfg(feature = "stm32f1xx")] +fn setup() -> ( + Tx, + Rx, + impl DelayMs + Transmit>, +) { + let cp = cortex_m::Peripherals::take().unwrap(); + let p = Peripherals::take().unwrap(); + + let mut rcc = p.RCC.constrain(); + let clocks = rcc + .cfgr + .sysclk(64.mhz()) + .pclk1(32.mhz()) + .freeze(&mut p.FLASH.constrain().acr); + + let mut afio = p.AFIO.constrain(&mut rcc.apb2); + let mut gpioa = p.GPIOA.split(&mut rcc.apb2); + let mut gpiob = p.GPIOB.split(&mut rcc.apb2); + + let (tx, rx) = Serial::usart2( + p.USART2, + ( + gpioa.pa2.into_alternate_push_pull(&mut gpioa.crl), //tx pa2 for GPS rx + gpioa.pa3, + ), //rx pa3 for GPS tx + &mut afio.mapr, + Config::default().baudrate(9_600.bps()), + clocks, + &mut rcc.apb1, + ) + .split(); + + let spi = Spi::spi1( + p.SPI1, + ( + gpioa.pa5.into_alternate_push_pull(&mut gpioa.crl), // sck on PA5 + gpioa.pa6.into_floating_input(&mut gpioa.crl), // miso on PA6 + gpioa.pa7.into_alternate_push_pull(&mut gpioa.crl), // mosi on PA7 + ), + &mut afio.mapr, + MODE, + 8.mhz(), + clocks, + &mut rcc.apb2, + ); + + let delay = Delay::new(cp.SYST, clocks); + + // Create lora radio instance + + let lora = Sx127x::spi( + spi.compat(), //Spi + gpioa.pa1.into_push_pull_output(&mut gpioa.crl).compat(), //CsPin on PA1 + gpiob.pb8.into_floating_input(&mut gpiob.crh).compat(), //BusyPin DIO0 on PB8 + gpiob.pb9.into_floating_input(&mut gpiob.crh).compat(), //ReadyPin DIO1 on PB9 + gpioa.pa0.into_push_pull_output(&mut gpioa.crl).compat(), //ResetPin on PA0 + delay.compat(), //Delay + &CONFIG_RADIO, //&Config + ) + .unwrap(); // should handle error + + (tx, rx, lora) +} + +#[cfg(feature = "stm32f4xx")] +// eg Nucleo-64 stm32f411, blackpill stm32f411, blackpill stm32f401 +use stm32f4xx_hal::{ + delay::Delay, + prelude::*, + serial::{config::Config, Rx, Serial, Tx}, + spi::{Error, Spi}, + stm32::Peripherals, + stm32::USART2, + time::MegaHertz, +}; + +#[cfg(feature = "stm32f4xx")] +fn setup() -> ( + Tx, + Rx, + impl DelayMs + Transmit>, +) { + let cp = cortex_m::Peripherals::take().unwrap(); + let p = Peripherals::take().unwrap(); + + let rcc = p.RCC.constrain(); + let clocks = rcc.cfgr.sysclk(64.mhz()).pclk1(32.mhz()).freeze(); + + let gpioa = p.GPIOA.split(); + let gpiob = p.GPIOB.split(); + + let (tx, rx) = Serial::usart2( + p.USART2, + ( + gpioa.pa2.into_alternate_af7(), //tx pa2 for GPS rx + gpioa.pa3.into_alternate_af7(), + ), //rx pa3 for GPS tx + Config::default().baudrate(9600.bps()), + clocks, + ) + .unwrap() + .split(); + + let spi = Spi::spi1( + p.SPI1, + ( + gpioa.pa5.into_alternate_af5(), // sck on PA5 + gpioa.pa6.into_alternate_af5(), // miso on PA6 + gpioa.pa7.into_alternate_af5(), // mosi on PA7 + ), + MODE, + MegaHertz(8).into(), + clocks, + ); + + let delay = Delay::new(cp.SYST, clocks); + + // Create lora radio instance + + // open_drain_output is really input and output. BusyPin is just input, but I think this should work + // gpiob.pb8.into_alternate_open_drain(&mut gpiob.crh), + // however, gives trait bound ... InputPin` is not satisfied + + let lora = Sx127x::spi( + spi.compat(), //Spi + gpioa.pa1.into_push_pull_output().compat(), //CsPin on PA1 + gpiob.pb8.into_floating_input().compat(), //BusyPin DIO0 on PB8 + gpiob.pb9.into_floating_input().compat(), //ReadyPin DIO1 on PB9 + gpioa.pa0.into_push_pull_output().compat(), //ResetPin on PA0 + delay.compat(), //Delay + &CONFIG_RADIO, //&Config + ) + .unwrap(); // should handle error + + //DIO0 triggers RxDone/TxDone status. + //DIO1 triggers RxTimeout and other errors status. + //D02, D03 ? + + //lora.lora_configure( config_lora, &config_ch ).unwrap(); # not yet pub, to change something + + (tx, rx, lora) +} + +// End of hal/MCU specific setup. Following should be generic code. + +#[entry] +fn main() -> ! { + let (mut _tx_gps, mut rx_gps, mut lora) = setup(); // GPS, lora (delay is available in lora) + + // byte buffer Nov 2020 limit data.len() < 255 in radio_sx127x .start_transmit + let mut buffer: heapless::Vec = heapless::Vec::new(); + let mut buf2: heapless::Vec = heapless::Vec::new(); + + //hprintln!("buffer at {} of {}", buffer.len(), buffer.capacity()).unwrap(); //0 of 80 + //hprintln!("buf2 at {} of {}", buf2.len(), buf2.capacity()).unwrap(); //0 of 80 + buffer.clear(); + buf2.clear(); + + //hprintln!("going into write/read loop ^C to exit ...").unwrap(); + + let e: u8 = 9; // replace char errors with "9" + let mut good = false; // true while capturing a line + + //let mut size: usize; // buffer size should not be needed + //size = buffer.len(); //packet size + //hprintln!("read buffer {} of {}", size, buffer.capacity()).unwrap(); + hprintln!("entering transmit loop").unwrap(); + + loop { + let byte = match block!(rx_gps.read()) { + Ok(byt) => byt, + Err(_error) => e, + }; + + if byte == 36 { + // $ is 36. start of a line + buffer.clear(); + good = true; //start capturing line + }; + + if good { + if buffer.push(byte).is_err() || byte == 13 { + //transmit if end of line. \r is 13, \n is 10 + + //hprintln!("{:?}", &buffer).unwrap(); + + // this transmits the whole GPS message string + + match lora.start_transmit(&buffer) { + Ok(b) => b, // b is () + Err(_err) => { + hprintln!("Error returned from lora.start_transmit().").unwrap(); + panic!("should reset in release mode."); + } + }; + + // this transmits GPS N and E coordinates in hundredths of degrees + + if &buffer[0..6] == [36, 71, 80, 82, 77, 67] { + // if message id is $GPRMC + + for v in buffer[19..31].iter() { + buf2.push(*v).unwrap(); + } // [19..31] is north/south. + for v in b" ".iter() { + buf2.push(*v).unwrap(); + } + for v in buffer[32..45].iter() { + buf2.push(*v).unwrap(); + } // [32..45] is east/west + + //hprintln!("{:?}", &buf2).unwrap(); + hprint!(".").unwrap(); // print "." on transmit of $GPRMC message (but not others) + + match lora.start_transmit(&buf2) { + Ok(b) => b, // b is () + Err(_err) => { + hprintln!("Error returned from lora.start_transmit().").unwrap(); + panic!("should reset in release mode."); + } + }; + }; + + // Note hprintln! requires semihosting. If hprintln! (thus also match section below) are + // removed then this example works on battery power with no computer attached. + // (tested only on blackpill with stm32f411 ) + + // The first transmission often return false and prints "TX not complete", but works after that. + // If this continually returns "TX not complete" then the radio should probably be reset, + // but should avoid panic_reset after first transmission. + + match lora.check_transmit() { + Ok(b) => { + if !b { + hprintln!("TX not complete").unwrap(); + // if multible times then panic!("should reset in release mode."); + } + } + Err(_err) => { + hprintln!("Error returned from lora.check_transmit().").unwrap(); + panic!("should reset in release mode."); + } + }; + + buffer.clear(); + buf2.clear(); + good = false; + match lora.try_delay_ms(5000u32) { + Ok(b) => b, // b is () + Err(_err) => { + hprintln!("Error returned from lora.try_delay_ms().").unwrap(); + panic!("should reset in release mode."); + } + }; + }; + }; + } +} diff --git a/examples/lora_spi_receive.rs b/examples/lora_spi_receive.rs new file mode 100644 index 0000000..dba3350 --- /dev/null +++ b/examples/lora_spi_receive.rs @@ -0,0 +1,267 @@ +//! Receive message with LoRa using crate radio_sx127x (on SPI). +//! See example lora_spi_send for more details. +//! See the MCU device setup() sections for details on pin connections. + +// Using sck, miso, mosi, cs, reset and D00, D01. Not yet using D02, D03 +// See setup() sections below for pins. + +//https://www.rfwireless-world.com/Tutorials/LoRa-channels-list.html +// channels are as follows +// 'CH_00_900': 903.08, 'CH_01_900': 905.24, 'CH_02_900': 907.40, +// 'CH_03_900': 909.56, 'CH_04_900': 911.72, 'CH_05_900': 913.88, +// 'CH_06_900': 916.04, 'CH_07_900': 918.20, 'CH_08_900': 920.36, +// 'CH_09_900': 922.52, 'CH_10_900': 924.68, 'CH_11_900': 926.84, 'CH_12_900': 915, +// +// 'CH_10_868': 865.20, 'CH_11_868': 865.50, 'CH_12_868': 865.80, +// 'CH_13_868': 866.10, 'CH_14_868': 866.40, 'CH_15_868': 866.70, +// 'CH_16_868': 867 , 'CH_17_868': 868 , + +// See FREQUENCY below to set the channel. + +#![no_std] +#![no_main] + +#[cfg(debug_assertions)] +extern crate panic_semihosting; + +#[cfg(not(debug_assertions))] +extern crate panic_halt; + +use core::convert::Infallible; + +// use nb::block; +use cortex_m_rt::entry; +use cortex_m_semihosting::*; + +use embedded_hal::blocking::delay::DelayMs; + +use embedded_hal_compat::IntoCompat; + +// MODE needs the old version as it is passed to the device hal crates +//use embedded_hal::{spi::{Mode, Phase, Polarity}, }; +use old_e_h::spi::{Mode, Phase, Polarity}; + +//use asm_delay::{ AsmDelay, bitrate, }; + +//use cortex_m::asm; //for breakpoint + +use radio_sx127x::Error as sx127xError; // Error name conflict with hals +use radio_sx127x::{ + device::lora::{ + Bandwidth, CodingRate, FrequencyHopping, LoRaChannel, LoRaConfig, PayloadCrc, + PayloadLength, SpreadingFactor, + }, + device::{Channel, Modem, PaConfig, PaSelect, PacketInfo}, + prelude::*, // prelude has Sx127x, +}; + +// trait needs to be in scope to find methods start_transmit and check_transmit. +use radio::Receive; + +// lora and radio parameters + +pub const MODE: Mode = Mode { + // SPI mode for radio + phase: Phase::CaptureOnSecondTransition, + polarity: Polarity::IdleHigh, +}; + +const FREQUENCY: u32 = 907_400_000; // frequency in hertz ch_12: 915_000_000, ch_2: 907_400_000 + +const CONFIG_CH: LoRaChannel = LoRaChannel { + freq: FREQUENCY as u32, // frequency in hertz + bw: Bandwidth::Bw125kHz, + sf: SpreadingFactor::Sf7, + cr: CodingRate::Cr4_8, +}; + +const CONFIG_LORA: LoRaConfig = LoRaConfig { + preamble_len: 0x8, + symbol_timeout: 0x64, + payload_len: PayloadLength::Variable, + payload_crc: PayloadCrc::Enabled, + frequency_hop: FrequencyHopping::Disabled, + invert_iq: false, +}; + +const CONFIG_PA: PaConfig = PaConfig { + output: PaSelect::Boost, + power: 10, +}; + +//let CONFIG_RADIO = Config::default() ; + +const CONFIG_RADIO: radio_sx127x::device::Config = radio_sx127x::device::Config { + modem: Modem::LoRa(CONFIG_LORA), + channel: Channel::LoRa(CONFIG_CH), + pa_config: CONFIG_PA, + xtal_freq: 32000000, // CHECK + timeout_ms: 100, +}; + +// setup() does all hal/MCU specific setup and returns generic hal device for use in main code. + +#[cfg(feature = "stm32f1xx")] // eg blue pill stm32f103 +use stm32f1xx_hal::{ + delay::Delay, + pac::Peripherals, + prelude::*, + spi::{Error, Spi}, +}; + +#[cfg(feature = "stm32f1xx")] +fn setup( +) -> impl DelayMs + Receive> +{ + let cp = cortex_m::Peripherals::take().unwrap(); + let p = Peripherals::take().unwrap(); + + let mut rcc = p.RCC.constrain(); + let clocks = rcc + .cfgr + .sysclk(64.mhz()) + .pclk1(32.mhz()) + .freeze(&mut p.FLASH.constrain().acr); + + let mut afio = p.AFIO.constrain(&mut rcc.apb2); + let mut gpioa = p.GPIOA.split(&mut rcc.apb2); + let mut gpiob = p.GPIOB.split(&mut rcc.apb2); + + let spi = Spi::spi1( + p.SPI1, + ( + gpioa.pa5.into_alternate_push_pull(&mut gpioa.crl), // sck on PA5 + gpioa.pa6.into_floating_input(&mut gpioa.crl), // miso on PA6 + gpioa.pa7.into_alternate_push_pull(&mut gpioa.crl), // mosi on PA7 + ), + &mut afio.mapr, + MODE, + 8.mhz(), + clocks, + &mut rcc.apb2, + ); + + let delay = Delay::new(cp.SYST, clocks); + + // Create lora radio instance + + let lora = Sx127x::spi( + spi.compat(), //Spi + gpioa.pa1.into_push_pull_output(&mut gpioa.crl).compat(), //CsPin on PA1 + gpiob.pb8.into_floating_input(&mut gpiob.crh).compat(), //BusyPin DIO0 on PB8 + gpiob.pb9.into_floating_input(&mut gpiob.crh).compat(), //ReadyPin DIO1 on PB9 + gpioa.pa0.into_push_pull_output(&mut gpioa.crl).compat(), //ResetPin on PA0 + delay.compat(), //Delay + &CONFIG_RADIO, //&Config + ) + .unwrap(); // should handle error + + lora +} + +// eg Nucleo-64 stm32f411, blackpill stm32f411, blackpill stm32f401 +#[cfg(feature = "stm32f4xx")] +use stm32f4xx_hal::{ + delay::Delay, + prelude::*, + spi::{Error, Spi}, + stm32::Peripherals, + time::MegaHertz, +}; + +#[cfg(feature = "stm32f4xx")] +fn setup( +) -> impl DelayMs + Receive> +{ + let cp = cortex_m::Peripherals::take().unwrap(); + let p = Peripherals::take().unwrap(); + + let rcc = p.RCC.constrain(); + let clocks = rcc.cfgr.sysclk(64.mhz()).pclk1(32.mhz()).freeze(); + + let gpioa = p.GPIOA.split(); + let gpiob = p.GPIOB.split(); + + let spi = Spi::spi1( + p.SPI1, + ( + gpioa.pa5.into_alternate_af5(), // sck on PA5 + gpioa.pa6.into_alternate_af5(), // miso on PA6 + gpioa.pa7.into_alternate_af5(), // mosi on PA7 + ), + MODE, + MegaHertz(8).into(), + clocks, + ); + + let delay = Delay::new(cp.SYST, clocks); + + // Create lora radio instance + + let lora = Sx127x::spi( + spi.compat(), //Spi + gpioa.pa1.into_push_pull_output().compat(), //CsPin on PA1 + gpiob.pb8.into_floating_input().compat(), //BusyPin DI00 on PB8 + gpiob.pb9.into_floating_input().compat(), //ReadyPin DI01 on PB9 + gpioa.pa0.into_push_pull_output().compat(), //ResetPin on PA0 + delay.compat(), //Delay + &CONFIG_RADIO, //&Config + ) + .unwrap(); // should handle error + + //DIO0 triggers RxDone/TxDone status. + //DIO1 triggers RxTimeout and other errors status. + //D02, D03 ? + + //lora.lora_configure( config_lora, &config_ch ).unwrap(); # not yet pub, to change something + + lora +} + +// End of hal/MCU specific setup. Following should be generic code. + +fn to_str(x: &[u8]) -> &str { + match core::str::from_utf8(x) { + Ok(str) => &str, + Err(_error) => "problem converting u8 to str ", + } +} + +#[entry] +fn main() -> ! { + let mut lora = setup(); //delay is available in lora.delay_ms() + + lora.start_receive().unwrap(); // should handle error + + let mut buff = [0u8; 1024]; + let mut n: usize; + let mut info = PacketInfo::default(); + + loop { + let poll = lora.check_receive(false); + // false (the restart option) specifies whether transient timeout or CRC errors should be + // internally handled (returning Ok(false) or passed back to the caller as errors. + + match poll { + Ok(v) if v => { + n = lora.get_received(&mut info, &mut buff).unwrap(); + //hprintln!("RX complete ({:?}, length: {})", info, n).unwrap(); + //hprintln!("{:?}", &buff[..n]).unwrap(); + // for some reason the next prints twice? + hprintln!("{}", to_str(&buff[..n])).unwrap() + } + + Ok(_v) => (), // hprint!(".").unwrap(), // print "." if nothing received + + Err(err) => hprintln!("poll error {:?} ", err).unwrap(), + }; + + match lora.try_delay_ms(100u32) { + Ok(b) => b, // b is () + Err(_err) => { + hprintln!("Error returned from lora.try_delay_ms().").unwrap(); + panic!("should reset in release mode."); + } + }; + } +} diff --git a/examples/lora_spi_send.rs b/examples/lora_spi_send.rs new file mode 100644 index 0000000..12a2f33 --- /dev/null +++ b/examples/lora_spi_send.rs @@ -0,0 +1,321 @@ +//! Transmit a simple message with LoRa using crate radio_sx127x (on SPI). +//! See the MCU device setup() sections for details on pin connections. +//! +//! The largest part of this file is the setup() functions used for each hal. +//! These make the application code common. +//! +//! In the following +//! - replace xxx with the example name lora_spi_send, lora_spi_receive, or lora_spi_gps. +//! - set TARGET, HAL, and MCU from a line in the table below (linux syntax). +//! - no-default-features is because some default-features require std. +//! +//! The examples can be compiled with: +//! cargo build --no-default-features --target $TARGET --features=$HAL,$MCU,compat --example xxx [ --release ] +//! +//! Before running, check FREQUENCY below to be sure you have a channel setting appropriate for +//! your country, hardware and any testing sender/receiver on the other end of the communication. +//! +//! To link, loaded and run using gdb and openocd (with INTERFACE and PROC set as below): +//! openocd -f interface/$INTERFACE.cfg -f target/$PROC.cfg +//! and in another window (with TARGET, HAL, and MCU set as below): +//! cargo run --no-default-features --target $TARGET --features $HAL,$MCU,compat --example xxx [ --release ] +//! +//! If --release is omitted then some MCUs do not have sufficient memory and loading results in +//! '.rodata will not fit in region FLASH ' +//! Even with sufficient memory the code without --release is slower and may result in errors. +//! +//! +//! cargo run environment variables openocd test board and processor +//! _____________________________________________________________ _____________ ___________________________ +//! export HAL=stm32f1xx MCU=stm32f103 TARGET=thumbv7m-none-eabi PROC=stm32f1x # bluepill Cortex-M3 +//! export HAL=stm32f4xx MCU=stm32f411 TARGET=thumbv7em-none-eabihf PROC=stm32f4x # blackpill-stm32f411 Cortex-M4 +//! +//! Depending on the MCU connection to the computer, in the openocd command use +//! export INTERFACE=stlink-v2 +//! export INTERFACE=stlink-v2-1 +//! +//! Instruction and test results for HALs stm32f0xx, stm32f1xx, stm32f3xx, stm32f4xx, stm32f7xx, +//! stm32h7xx, stm32l0xx, stm32l1xx, and stm32l4xx are reported for fork branch all-devices-examples at +//! https://github.com/pdgilbert/rust-radio-sx127x/actions +//! +//! A version of this example is also reported at https://pdgilbert.github.io/eg_stm_hal/. +//! The results reported there use current git versions of the MCU device hals, +//! whereas the example here uses release versions of the MCU device hals. + +//https://www.rfwireless-world.com/Tutorials/LoRa-channels-list.html +// channels are as follows +// 'CH_00_900': 903.08, 'CH_01_900': 905.24, 'CH_02_900': 907.40, +// 'CH_03_900': 909.56, 'CH_04_900': 911.72, 'CH_05_900': 913.88, +// 'CH_06_900': 916.04, 'CH_07_900': 918.20, 'CH_08_900': 920.36, +// 'CH_09_900': 922.52, 'CH_10_900': 924.68, 'CH_11_900': 926.84, 'CH_12_900': 915, +// +// 'CH_10_868': 865.20, 'CH_11_868': 865.50, 'CH_12_868': 865.80, +// 'CH_13_868': 866.10, 'CH_14_868': 866.40, 'CH_15_868': 866.70, +// 'CH_16_868': 867 , 'CH_17_868': 868 , + +// See FREQUENCY below to set the channel. + +#![no_std] +#![no_main] + +#[cfg(debug_assertions)] +extern crate panic_semihosting; + +#[cfg(not(debug_assertions))] +extern crate panic_halt; + +use core::convert::Infallible; + +// use nb::block; +use cortex_m_rt::entry; +use cortex_m_semihosting::*; + +use embedded_hal::blocking::delay::DelayMs; + +// The embedded_hal_compat crate is to smooth the transition for hal crates that are +// not yet based on embedded_hal 1.0.0-alpha while rust-radio-sx127x is. +// When passing the older hal crate objects to the newer rust-radio-sx127x methods +// the objects are appended with .compat(). + +use embedded_hal_compat::IntoCompat; + +// MODE needs the old version as it is passed to the device hal crates +//use embedded_hal::{spi::{Mode, Phase, Polarity}, }; +use old_e_h::spi::{Mode, Phase, Polarity}; + +//use asm_delay::{ AsmDelay, bitrate, }; + +//use cortex_m::asm; //for breakpoint + +use radio_sx127x::Error as sx127xError; // Error name conflict with hals +use radio_sx127x::{ + device::lora::{ + Bandwidth, CodingRate, FrequencyHopping, LoRaChannel, LoRaConfig, PayloadCrc, + PayloadLength, SpreadingFactor, + }, + device::{Channel, Modem, PaConfig, PaSelect}, + prelude::*, // prelude has Sx127x, +}; + +//use radio::{Receive, Transmit}; +use radio::Transmit; // trait needs to be in scope to find methods start_transmit and check_transmit. + +// lora and radio parameters + +pub const MODE: Mode = Mode { + // SPI mode for radio + phase: Phase::CaptureOnSecondTransition, + polarity: Polarity::IdleHigh, +}; + +const FREQUENCY: u32 = 907_400_000; // frequency in hertz ch_12: 915_000_000, ch_2: 907_400_000 + +const CONFIG_CH: LoRaChannel = LoRaChannel { + freq: FREQUENCY as u32, // frequency in hertz + bw: Bandwidth::Bw125kHz, + sf: SpreadingFactor::Sf7, + cr: CodingRate::Cr4_8, +}; + +const CONFIG_LORA: LoRaConfig = LoRaConfig { + preamble_len: 0x8, + symbol_timeout: 0x64, + payload_len: PayloadLength::Variable, + payload_crc: PayloadCrc::Enabled, + frequency_hop: FrequencyHopping::Disabled, + invert_iq: false, +}; + +const CONFIG_PA: PaConfig = PaConfig { + output: PaSelect::Boost, + power: 10, +}; + +//let CONFIG_RADIO = Config::default() ; + +const CONFIG_RADIO: radio_sx127x::device::Config = radio_sx127x::device::Config { + modem: Modem::LoRa(CONFIG_LORA), + channel: Channel::LoRa(CONFIG_CH), + pa_config: CONFIG_PA, + xtal_freq: 32000000, // CHECK + timeout_ms: 100, +}; + +// setup() does all hal/MCU specific setup and returns generic object for use in main code. + +#[cfg(feature = "stm32f1xx")] // eg blue pill stm32f103 +use stm32f1xx_hal::{ + delay::Delay, + pac::{CorePeripherals, Peripherals}, + prelude::*, + spi::{Error, Spi}, +}; + +#[cfg(feature = "stm32f1xx")] +fn setup() -> impl DelayMs + Transmit> { + let cp = CorePeripherals::take().unwrap(); + let p = Peripherals::take().unwrap(); + + let mut rcc = p.RCC.constrain(); + let clocks = rcc + .cfgr + .sysclk(64.mhz()) + .pclk1(32.mhz()) + .freeze(&mut p.FLASH.constrain().acr); + + let mut afio = p.AFIO.constrain(&mut rcc.apb2); + let mut gpioa = p.GPIOA.split(&mut rcc.apb2); + let mut gpiob = p.GPIOB.split(&mut rcc.apb2); + + let spi = Spi::spi1( + p.SPI1, + ( + gpioa.pa5.into_alternate_push_pull(&mut gpioa.crl), // sck on PA5 + gpioa.pa6.into_floating_input(&mut gpioa.crl), // miso on PA6 + gpioa.pa7.into_alternate_push_pull(&mut gpioa.crl), // mosi on PA7 + ), + &mut afio.mapr, + MODE, + 8.mhz(), + clocks, + &mut rcc.apb2, + ); + + let delay = Delay::new(cp.SYST, clocks); + + // Create lora radio instance + + let lora = Sx127x::spi( + spi.compat(), //Spi + gpioa.pa1.into_push_pull_output(&mut gpioa.crl).compat(), //CsPin on PA1 + gpiob.pb8.into_floating_input(&mut gpiob.crh).compat(), //BusyPin DIO0 on PB8 + gpiob.pb9.into_floating_input(&mut gpiob.crh).compat(), //ReadyPin DIO1 on PB9 + gpioa.pa0.into_push_pull_output(&mut gpioa.crl).compat(), //ResetPin on PA0 + delay.compat(), //Delay + &CONFIG_RADIO, //&Config + ) + .unwrap(); // should handle error + + lora +} + +#[cfg(feature = "stm32f4xx")] +// eg Nucleo-64 stm32f411, blackpill stm32f411, blackpill stm32f401 +use stm32f4xx_hal::{ + delay::Delay, + prelude::*, + spi::{Error, Spi}, + stm32::Peripherals, + time::MegaHertz, +}; + +#[cfg(feature = "stm32f4xx")] +fn setup() -> impl DelayMs + Transmit> { + let cp = cortex_m::Peripherals::take().unwrap(); + let p = Peripherals::take().unwrap(); + + let rcc = p.RCC.constrain(); + let clocks = rcc.cfgr.sysclk(64.mhz()).pclk1(32.mhz()).freeze(); + + let gpioa = p.GPIOA.split(); + let gpiob = p.GPIOB.split(); + + let spi = Spi::spi1( + p.SPI1, + ( + gpioa.pa5.into_alternate_af5(), // sck on PA5 + gpioa.pa6.into_alternate_af5(), // miso on PA6 + gpioa.pa7.into_alternate_af5(), // mosi on PA7 + ), + MODE, + MegaHertz(8).into(), + clocks, + ); + + let delay = Delay::new(cp.SYST, clocks); + + // Create lora radio instance + + // open_drain_output is really input and output. BusyPin is just input, but I think this should work + // gpiob.pb8.into_alternate_open_drain(&mut gpiob.crh), + // however, gives trait bound ... InputPin` is not satisfied + + let lora = Sx127x::spi( + spi.compat(), //Spi + gpioa.pa1.into_push_pull_output().compat(), //CsPin on PA1 + gpiob.pb8.into_floating_input().compat(), //BusyPin DI00 on PB8 + gpiob.pb9.into_floating_input().compat(), //ReadyPin DI01 on PB9 + gpioa.pa0.into_push_pull_output().compat(), //ResetPin on PA0 + delay.compat(), //Delay + &CONFIG_RADIO, //&Config + ) + .unwrap(); // should handle error + + //DIO0 triggers RxDone/TxDone status. + //DIO1 triggers RxTimeout and other errors status. + //D02, D03 ? + + //lora.lora_configure( config_lora, &config_ch ).unwrap(); # not yet pub, to change something + + lora +} + +// End of hal/MCU specific setup. Following should be generic code. + +#[entry] +fn main() -> ! { + let mut lora = setup(); //delay is available in lora + + // print out configuration (for debugging) + + // let v = lora.lora_get_config(); + // hprintln!("configuration {}", v).unwrap(); + + // hprintln!("chammel {}", lora.get_chammel()).unwrap(); + + //hprintln!("mode {}", lora.get_mode()).unwrap(); + //hprintln!("mode {}", lora.read_register(Register::RegOpMode.addr())).unwrap(); + //hprintln!("bandwidth {:?}", lora.get_signal_bandwidth()).unwrap(); + //hprintln!("coding_rate {:?}", lora.get_coding_rate_4()).unwrap(); + //hprintln!("spreading_factor {:?}", lora.get_spreading_factor()).unwrap(); + //hprintln!("spreading_factor {:?}", + //hprintln!("invert_iq {:?}", lora.get_invert_iq()).unwrap(); + //hprintln!("tx_power {:?}", lora.get_tx_power()).unwrap(); + + // transmit something + + //let buffer = &[0xaa, 0xbb, 0xcc]; + + let message = b"Hello, LoRa!"; + + //let mut buffer = [0;100]; //Nov 2020 limit data.len() < 255 in radio_sx127x .start_transmit + //for (i,c) in message.chars().enumerate() { + // buffer[i] = c as u8; + // } + + loop { + lora.start_transmit(message).unwrap(); // should handle error + + match lora.check_transmit() { + Ok(b) => { + if b { + hprintln!("TX complete").unwrap() + } else { + hprintln!("TX not complete").unwrap() + } + } + + Err(_err) => { + hprintln!("Error in lora.check_transmit(). Should return True or False.").unwrap() + } + }; + + match lora.try_delay_ms(5000u32) { + Ok(b) => b, // b is () + Err(_err) => { + hprintln!("Error returned from lora.try_delay_ms().").unwrap(); + panic!("should reset in release mode."); + } + }; + } +} diff --git a/examples/memoryMaps/GD32VF103C8/memory.x b/examples/memoryMaps/GD32VF103C8/memory.x new file mode 100644 index 0000000..d90d86e --- /dev/null +++ b/examples/memoryMaps/GD32VF103C8/memory.x @@ -0,0 +1,13 @@ +/* GD32VF103C8 */ +MEMORY +{ + FLASH : ORIGIN = 0x08000000, LENGTH = 64k + RAM : ORIGIN = 0x20000000, LENGTH = 20k +} + +REGION_ALIAS("REGION_TEXT", FLASH); +REGION_ALIAS("REGION_RODATA", FLASH); +REGION_ALIAS("REGION_DATA", RAM); +REGION_ALIAS("REGION_BSS", RAM); +REGION_ALIAS("REGION_HEAP", RAM); +REGION_ALIAS("REGION_STACK", RAM); diff --git a/examples/memoryMaps/GD32VF103CB/memory.xA b/examples/memoryMaps/GD32VF103CB/memory.xA new file mode 100644 index 0000000..74b09ab --- /dev/null +++ b/examples/memoryMaps/GD32VF103CB/memory.xA @@ -0,0 +1,13 @@ +/* GD32VF103CB */ +MEMORY +{ + FLASH : ORIGIN = 0x08000000, LENGTH = 128k + RAM : ORIGIN = 0x20000000, LENGTH = 32k +} + +REGION_ALIAS("REGION_TEXT", FLASH); +REGION_ALIAS("REGION_RODATA", FLASH); +REGION_ALIAS("REGION_DATA", RAM); +REGION_ALIAS("REGION_BSS", RAM); +REGION_ALIAS("REGION_HEAP", RAM); +REGION_ALIAS("REGION_STACK", RAM); diff --git a/examples/memoryMaps/GD32VF103_EXTRA/memory.x b/examples/memoryMaps/GD32VF103_EXTRA/memory.x new file mode 100644 index 0000000..ee91ca8 --- /dev/null +++ b/examples/memoryMaps/GD32VF103_EXTRA/memory.x @@ -0,0 +1,27 @@ +MEMORY +{ + /* 87*4=348 (0x15C) */ + VECTORS (RX): ORIGIN = 0x08000000, LENGTH = 0x015C + MAIN_FLASH (RX): ORIGIN = 0x0800015C, LENGTH = 64K - 348 + SRAM (RW): ORIGIN = 0x20000000, LENGTH = 20K +} + +REGION_ALIAS("REGION_TEXT", MAIN_FLASH); +REGION_ALIAS("REGION_RODATA", MAIN_FLASH); +REGION_ALIAS("REGION_DATA", SRAM); +REGION_ALIAS("REGION_BSS", SRAM); +REGION_ALIAS("REGION_HEAP", SRAM); +REGION_ALIAS("REGION_STACK", SRAM); + +ENTRY(_gd32vf103_vectors) +EXTERN(_gd32vf103_vectors) +EXTERN(_gd32vf103_trap_entry) +EXTERN(_gd32vf103_irq_entry) + +SECTIONS +{ + .vectors : + { + KEEP(*(.vectors)); + } > VECTORS +} diff --git a/examples/memoryMaps/LM3S6965/memory.x b/examples/memoryMaps/LM3S6965/memory.x new file mode 100644 index 0000000..b271f22 --- /dev/null +++ b/examples/memoryMaps/LM3S6965/memory.x @@ -0,0 +1,34 @@ +MEMORY +{ + /* NOTE 1 K = 1 KiBi = 1024 bytes */ + /* TODO Adjust these memory regions to match your device memory layout */ + /* These values correspond to the LM3S6965, one of the few devices QEMU can emulate */ + FLASH : ORIGIN = 0x00000000, LENGTH = 256K + RAM : ORIGIN = 0x20000000, LENGTH = 64K +} + +/* This is where the call stack will be allocated. */ +/* The stack is of the full descending type. */ +/* You may want to use this variable to locate the call stack and static + variables in different memory regions. Below is shown the default value */ +/* _stack_start = ORIGIN(RAM) + LENGTH(RAM); */ + +/* You can use this symbol to customize the location of the .text section */ +/* If omitted the .text section will be placed right after the .vector_table + section */ +/* This is required only on microcontrollers that store some configuration right + after the vector table */ +/* _stext = ORIGIN(FLASH) + 0x400; */ + +/* Example of putting non-initialized variables into custom RAM locations. */ +/* This assumes you have defined a region RAM2 above, and in the Rust + sources added the attribute `#[link_section = ".ram2bss"]` to the data + you want to place there. */ +/* Note that the section will not be zero-initialized by the runtime! */ +/* SECTIONS { + .ram2bss (NOLOAD) : ALIGN(4) { + *(.ram2bss); + . = ALIGN(4); + } > RAM2 + } INSERT AFTER .bss; +*/ diff --git a/examples/memoryMaps/STM32F030XC/memory.x b/examples/memoryMaps/STM32F030XC/memory.x new file mode 100644 index 0000000..4b487c1 --- /dev/null +++ b/examples/memoryMaps/STM32F030XC/memory.x @@ -0,0 +1,8 @@ +MEMORY +{ + /* Define memory regions for STM32F030 */ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 16K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 4K +} +/* see https://github.com/stm32-rs/stm32f0xx-hal/memory.x */ +_stack_start = ORIGIN(RAM) + LENGTH(RAM); diff --git a/examples/memoryMaps/STM32F042/memory.x b/examples/memoryMaps/STM32F042/memory.x new file mode 100644 index 0000000..51b2492 --- /dev/null +++ b/examples/memoryMaps/STM32F042/memory.x @@ -0,0 +1,11 @@ +MEMORY +{ + /* NOTE K = KiBi = 1024 bytes */ + FLASH : ORIGIN = 0x08000000, LENGTH = 32K + RAM : ORIGIN = 0x20000000, LENGTH = 6K +} + +/* This is where the call stack will be allocated. */ +/* The stack is of the full descending type. */ +/* NOTE Do NOT modify `_stack_start` unless you know what you are doing */ +_stack_start = ORIGIN(RAM) + LENGTH(RAM); diff --git a/examples/memoryMaps/STM32F100/memory.x b/examples/memoryMaps/STM32F100/memory.x new file mode 100644 index 0000000..4556f77 --- /dev/null +++ b/examples/memoryMaps/STM32F100/memory.x @@ -0,0 +1,6 @@ +MEMORY +{ + /* Define memory regions for STM32F103C8T6 */ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 20K +} diff --git a/examples/memoryMaps/STM32F101/memory.x b/examples/memoryMaps/STM32F101/memory.x new file mode 100644 index 0000000..4556f77 --- /dev/null +++ b/examples/memoryMaps/STM32F101/memory.x @@ -0,0 +1,6 @@ +MEMORY +{ + /* Define memory regions for STM32F103C8T6 */ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 20K +} diff --git a/examples/memoryMaps/STM32F103/memory.x b/examples/memoryMaps/STM32F103/memory.x new file mode 100644 index 0000000..4556f77 --- /dev/null +++ b/examples/memoryMaps/STM32F103/memory.x @@ -0,0 +1,6 @@ +MEMORY +{ + /* Define memory regions for STM32F103C8T6 */ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 20K +} diff --git a/examples/memoryMaps/STM32F303XC/memory.x b/examples/memoryMaps/STM32F303XC/memory.x new file mode 100644 index 0000000..7eb5be8 --- /dev/null +++ b/examples/memoryMaps/STM32F303XC/memory.x @@ -0,0 +1,6 @@ +MEMORY +{ + /* Define memory regions for STM32F303VCT6 */ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 40K +} diff --git a/examples/memoryMaps/STM32F401/memory.x b/examples/memoryMaps/STM32F401/memory.x new file mode 100644 index 0000000..41cfd26 --- /dev/null +++ b/examples/memoryMaps/STM32F401/memory.x @@ -0,0 +1,6 @@ +MEMORY +{ + /* Define memory regions. STM32F401CC */ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 64K +} diff --git a/examples/memoryMaps/STM32F411/memory.x b/examples/memoryMaps/STM32F411/memory.x new file mode 100644 index 0000000..3c1e02b --- /dev/null +++ b/examples/memoryMaps/STM32F411/memory.x @@ -0,0 +1,6 @@ +MEMORY +{ + /* Define memory regions. STM32F411RE */ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128K +} diff --git a/examples/memoryMaps/STM32F722/memory.x b/examples/memoryMaps/STM32F722/memory.x new file mode 100644 index 0000000..912c8ec --- /dev/null +++ b/examples/memoryMaps/STM32F722/memory.x @@ -0,0 +1,9 @@ +/* STM32F722 */ +MEMORY +{ + FLASH : ORIGIN = 0x08000000, LENGTH = 512K + RAM : ORIGIN = 0x20000000, LENGTH = 176K + 16K +} + +/* Do NOT modify */ +_stack_start = ORIGIN(RAM) + LENGTH(RAM); diff --git a/examples/memoryMaps/STM32H742/memory.x b/examples/memoryMaps/STM32H742/memory.x new file mode 100644 index 0000000..0d6ff2f --- /dev/null +++ b/examples/memoryMaps/STM32H742/memory.x @@ -0,0 +1,10 @@ +MEMORY +{ + /* see https://github.com/stm32-rs/stm32h7xx-hal/blob/master/memory.x + for much better information + */ + + FLASH : ORIGIN = 0x08000000, LENGTH = 2M + RAM : ORIGIN = 0x20000000, LENGTH = 128K + +} diff --git a/examples/memoryMaps/STM32L0X2/memory.x b/examples/memoryMaps/STM32L0X2/memory.x new file mode 100644 index 0000000..2e04e72 --- /dev/null +++ b/examples/memoryMaps/STM32L0X2/memory.x @@ -0,0 +1,5 @@ +MEMORY +{ /* see https://github.com/stm32-rs/stm32l0xx-hal/blob/master/ */ + FLASH : ORIGIN = 0x08000000, LENGTH = 16K + RAM : ORIGIN = 0x20000000, LENGTH = 2K +} diff --git a/examples/memoryMaps/STM32L100/memory.x b/examples/memoryMaps/STM32L100/memory.x new file mode 100644 index 0000000..e4e6f6f --- /dev/null +++ b/examples/memoryMaps/STM32L100/memory.x @@ -0,0 +1,6 @@ +MEMORY +{ + /* Define memory regions. STM32L100RCT6 */ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 16K +} diff --git a/examples/memoryMaps/STM32L151/memory.x b/examples/memoryMaps/STM32L151/memory.x new file mode 100644 index 0000000..f187798 --- /dev/null +++ b/examples/memoryMaps/STM32L151/memory.x @@ -0,0 +1,7 @@ +MEMORY +{ + /* Define memory regions. STM32L151CCU6 */ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 32K +} + diff --git a/examples/memoryMaps/STM32L4X2/memory.x b/examples/memoryMaps/STM32L4X2/memory.x new file mode 100644 index 0000000..0c4c312 --- /dev/null +++ b/examples/memoryMaps/STM32L4X2/memory.x @@ -0,0 +1,6 @@ +MEMORY +{ + /* see https://github.com/stm32-rs/stm32l4xx-hal/blob/master/memory.x */ + FLASH : ORIGIN = 0x8000000, LENGTH = 256K + RAM : ORIGIN = 0x20000000, LENGTH = 64K +} diff --git a/openocd.gdb b/openocd.gdb new file mode 100644 index 0000000..7795319 --- /dev/null +++ b/openocd.gdb @@ -0,0 +1,40 @@ +target extended-remote :3333 + +# print demangled symbols +set print asm-demangle on + +# set backtrace limit to not have infinite backtrace loops +set backtrace limit 32 + +# detect unhandled exceptions, hard faults and panics +break DefaultHandler +break HardFault +break rust_begin_unwind +# # run the next few lines so the panic message is printed immediately +# # the number needs to be adjusted for your panic handler +# commands $bpnum +# next 4 +# end + +# *try* to stop at the user entry point (it might be gone due to inlining) +break main + +monitor arm semihosting enable + +# # send captured ITM to the file itm.fifo +# # (the microcontroller SWO pin must be connected to the programmer SWO pin) +# # 8000000 must match the core clock frequency +# monitor tpiu config internal itm.txt uart off 8000000 + +# # OR: make the microcontroller SWO pin output compatible with UART (8N1) +# # 8000000 must match the core clock frequency +# # 2000000 is the frequency of the SWO pin +# monitor tpiu config external uart off 8000000 2000000 + +# # enable ITM port 0 +# monitor itm port 0 on + +load + +# start the process but immediately halt the processor +stepi