diff --git a/.cargo/config b/.cargo/config new file mode 100644 index 0000000..9461136 --- /dev/null +++ b/.cargo/config @@ -0,0 +1,11 @@ +[target.thumbv7em-none-eabi] +runner = "dk-run" +rustflags = [ + "-C", "link-arg=-Tlink.x", +] + +[build] +target = "thumbv7em-none-eabi" # = ARM Cortex-M4 + +[alias] +flash-nrf = ["flash", "--chip", "nRF52840_xxAA"] \ No newline at end of file diff --git a/.github/workflows/flow.yml b/.github/workflows/flow.yml new file mode 100644 index 0000000..352157c --- /dev/null +++ b/.github/workflows/flow.yml @@ -0,0 +1,81 @@ +name: Suite + +on: + push: + branches: + - root + tags: + - v* + pull_request: {} + +env: + RELEASE: true + CHECK: true + +jobs: + suite: + name: Suite + runs-on: ubuntu-20.04 + steps: + + - name: Checkout + uses: actions/checkout@v2 + + - name: Cargo cache restore + id: cargo-cache + uses: actions/cache@v2 + with: + path: | + ~/.cargo + target + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + + - name: Get pip cache dir + id: pip-cache + run: | + echo "::set-output name=dir::$(pip cache dir)" + - name: Pip cache restore + uses: actions/cache@v2 + with: + path: ${{ steps.pip-cache.outputs.dir }} + key: ${{ runner.os }}-${{ hashFiles('**/requirements.txt') }} + + - name: Run CI make task + run: make --trace ci + + - name: Upload artifact + uses: actions/upload-artifact@v2 + with: + name: junctor + path: target/thumbv7em-none-eabi/release/junctor + + - name: Upload artifact + uses: actions/upload-artifact@v2 + with: + name: CHANGELOG.md + path: CHANGELOG.md + + - name: Cut a release if needed + if: startsWith(github.ref, 'refs/tags/v') + id: cut_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.ref }} + release_name: Release ${{ github.ref }} + body_path: CHANGELOG.md + draft: true + prerelease: false + + - name: Upload release if needed + if: startsWith(github.ref, 'refs/tags/v') + id: upload-release-asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.cut_release.outputs.upload_url }} + asset_path: target/thumbv7em-none-eabi/release/junctor + asset_name: junctor + asset_content_type: application/octet-stream \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..46a7077 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,16 @@ +# Changelog + +### [v0.1.1](https://github.com/Hoverbear-Consulting/junctor/compare/v0.1.0...v0.1.1) (2020-07-26) + +#### Features + +* **kettlehead:** Fixup kettlehead 4d2dcdb + + +## v0.1.0 (2020-07-26) + +### Features + +* **init:** Initialize repository. c6298de + + diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..56c62a1 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,392 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "aligned" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb1ce8b3382016136ab1d31a1b5ce807144f8b7eb2d5f16b2108f0f07edceb94" +dependencies = [ + "as-slice", +] + +[[package]] +name = "as-slice" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37dfb65bc03b2bc85ee827004f14a6817e04160e3b1a28931986a666a9290e70" +dependencies = [ + "generic-array 0.12.3", + "generic-array 0.13.2", + "stable_deref_trait", +] + +[[package]] +name = "bare-metal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" +dependencies = [ + "rustc_version", +] + +[[package]] +name = "bitfield" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" + +[[package]] +name = "byteorder" +version = "1.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" + +[[package]] +name = "cast" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0" +dependencies = [ + "rustc_version", +] + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "compiler_builtins" +version = "0.1.32" +source = "git+https://github.com/rust-lang-nursery/compiler-builtins#f3846bc05da87b8a71cd1a5a6ff9d980f46b2d0f" + +[[package]] +name = "cortex-m" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2be99930c99669a74d986f7fd2162085498b322e6daae8ef63a97cc9ac1dc73c" +dependencies = [ + "aligned", + "bare-metal", + "bitfield", + "volatile-register", +] + +[[package]] +name = "cortex-m-rt" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00d518da72bba39496024b62607c1d8e37bcece44b2536664f1132a73a499a28" +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 = "dk" +version = "0.0.0" +source = "git+https://github.com/ferrous-systems/embedded-trainings-2020.git#030886870274bfb2b7d97afb8c6fd8d878c98d9e" +dependencies = [ + "cortex-m", + "cortex-m-rt", + "embedded-hal", + "log", + "nrf52840-hal", + "rtt-target", +] + +[[package]] +name = "embedded-hal" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa998ce59ec9765d15216393af37a58961ddcefb14c753b4816ba2191d865fcb" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "fpa" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f074479d683e5a8fd0bf1251d0a5d91b0d9178b867b44962191ed0eaaf8d4009" +dependencies = [ + "cast", + "typenum", +] + +[[package]] +name = "generic-array" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" +dependencies = [ + "typenum", +] + +[[package]] +name = "generic-array" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ed1e761351b56f54eb9dcd0cfaca9fd0daecf93918e1cfc01c8a3d26ee7adcd" +dependencies = [ + "typenum", +] + +[[package]] +name = "hash32" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4041af86e63ac4298ce40e5cca669066e75b6f1aa3390fe2561ffa5e1d9f4cc" +dependencies = [ + "byteorder", +] + +[[package]] +name = "heapless" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73a8a2391a3bc70b31f60e7a90daa5755a360559c0b6b9c5cfc0fee482362dc0" +dependencies = [ + "as-slice", + "generic-array 0.13.2", + "hash32", + "stable_deref_trait", +] + +[[package]] +name = "junctor" +version = "0.1.0" +dependencies = [ + "cortex-m", + "cortex-m-rt", + "dk", + "heapless", + "log", + "test", + "utest-cortex-m-qemu", + "utest-macros", +] + +[[package]] +name = "log" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" +dependencies = [ + "cfg-if", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae" + +[[package]] +name = "nrf-hal-common" +version = "0.10.0" +source = "git+https://github.com/japaric/nrf-hal?branch=radio#b57ba8100eda0145de9823e63c7f5e2cf5d888d1" +dependencies = [ + "cast", + "cortex-m", + "embedded-hal", + "fpa", + "nb 0.1.3", + "nrf52840-pac", + "rand_core", + "void", +] + +[[package]] +name = "nrf52840-hal" +version = "0.10.0" +source = "git+https://github.com/japaric/nrf-hal?branch=radio#b57ba8100eda0145de9823e63c7f5e2cf5d888d1" +dependencies = [ + "cast", + "cortex-m", + "embedded-hal", + "nb 0.1.3", + "nrf-hal-common", + "nrf52840-pac", + "void", +] + +[[package]] +name = "nrf52840-pac" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1b780a5afd2621774652f28c82837f6aa6d19cf0ad71c734fc1fe53298a2d73" +dependencies = [ + "bare-metal", + "cortex-m", + "cortex-m-rt", + "vcell", +] + +[[package]] +name = "proc-macro2" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r0" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f" + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" + +[[package]] +name = "rtt-target" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58b1f36984bbcf227044b3b7af1de14a6ebe51b9d21cd856a3d5ba41c70ec191" +dependencies = [ + "cortex-m", + "ufmt-write", + "vcell", +] + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver", +] + +[[package]] +name = "sc" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebbb026ba4a707c25caec2db5ef59ad8b41f7ad77cad06257e06229c891f376" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "syn" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb7f4c519df8c117855e19dd8cc851e89eb746fe7a73f0157e0d95fdec5369b0" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "test" +version = "0.1.0" +source = "git+https://github.com/japaric/utest#70dd2f2c1b6b38ed203c031b487d67507e26fae8" + +[[package]] +name = "typenum" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" + +[[package]] +name = "ufmt-write" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e87a2ed6b42ec5e28cc3b94c09982969e9227600b2e3dcbc1db927a84c06bd69" + +[[package]] +name = "unicode-xid" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" + +[[package]] +name = "utest-cortex-m-qemu" +version = "0.1.0" +source = "git+https://github.com/japaric/utest#70dd2f2c1b6b38ed203c031b487d67507e26fae8" +dependencies = [ + "compiler_builtins", + "sc", +] + +[[package]] +name = "utest-macros" +version = "0.1.0" +source = "git+https://github.com/japaric/utest#70dd2f2c1b6b38ed203c031b487d67507e26fae8" + +[[package]] +name = "vcell" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876e32dcadfe563a4289e994f7cb391197f362b6315dc45e8ba4aa6f564a4b3c" + +[[package]] +name = "void" +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", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..6b59e22 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,60 @@ +[package] +name = "junctor" +version = "0.1.1" +authors = ["Ana Hobden "] +edition = "2018" +description = "Nothing quite yet!" +license = "MIT OR Apache-2.0" +repository = "https://github.com/Hoverbear-Consulting/junctor" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +cortex-m = "0.6.2" +cortex-m-rt = "0.6.12" +heapless = "0.5.5" +log = "0.4.8" +dk = { git = "https://github.com/ferrous-systems/embedded-trainings-2020.git", features = ["beginner"] } + +# optimize code in both profiles +[profile.dev] +codegen-units = 1 +debug = 1 +debug-assertions = true # ! +incremental = false +lto = "fat" +opt-level = 'z' # ! +overflow-checks = false + +[profile.release] +codegen-units = 1 +debug = 1 +debug-assertions = false +incremental = false +lto = "fat" +opt-level = 3 +overflow-checks = false + +# faster builds from scratch +[profile.dev.build-override] +codegen-units = 8 +debug = false +debug-assertions = false +opt-level = 0 +overflow-checks = false + +[profile.release.build-override] +codegen-units = 8 +debug = false +debug-assertions = false +opt-level = 0 +overflow-checks = false + +[target.thumbv7m-linux-eabi.dev-dependencies.utest-macros] +git = "https://github.com/japaric/utest" + +[target.thumbv7m-linux-eabi.dev-dependencies.test] +git = "https://github.com/japaric/utest" + +[target.thumbv7m-linux-eabi.dev-dependencies.utest-cortex-m-qemu] +git = "https://github.com/japaric/utest" \ No newline at end of file diff --git a/Embed.toml b/Embed.toml new file mode 100644 index 0000000..503a4eb --- /dev/null +++ b/Embed.toml @@ -0,0 +1,6 @@ +[default.general] +chip = "nRF52840_xxAA" + +[default.rtt] +enabled = true +channels = [{ up = 0 }] \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6bd58f0 --- /dev/null +++ b/Makefile @@ -0,0 +1,232 @@ + +## Configurables. +export BIN ?= junctor ## Main binary name. +export ARCH ?= thumbv7em-none-eabi ## Rust compile target. +export CHIP ?= nRF52840_xxAA ## Flash/embed target. +export RELEASE ?= false ## Release mode. +export CHECK ?= false ## Prefer checks to mutations. +export PREREQS ?= true ## Provision preresuites as needed. +export OS ?= ubuntu-20.04 ## The hosting OS. (Only Ubuntu 20.04 is supported.) + +# Pretty stuff! +FORMATTING_BEGIN_TASK = \033[0;33m +FORMATTING_BEGIN_KNOBS = \033[0;93m +FORMATTING_BEGIN_CONFIGURED = \033[1;36m +FORMATTING_BEGIN_DEFAULT = \033[0;36m +FORMATTING_BEGIN_HEADING = \033[1;32m +FORMATTING_BEGIN_HINT = \033[0;90m +FORMATTING_BEGIN_COMMAND = \033[1;37m +FORMATTING_END = \033[0m +define AWK + @gawk \ + -v FORMATTING_BEGIN_TASK="${FORMATTING_BEGIN_TASK}" \ + -v FORMATTING_BEGIN_KNOBS="${FORMATTING_BEGIN_KNOBS}" \ + -v FORMATTING_BEGIN_CONFIGURED="${FORMATTING_BEGIN_CONFIGURED}" \ + -v FORMATTING_BEGIN_DEFAULT="${FORMATTING_BEGIN_DEFAULT}" \ + -v FORMATTING_BEGIN_HEADING="${FORMATTING_BEGIN_HEADING}" \ + -v FORMATTING_BEGIN_HINT="${FORMATTING_BEGIN_HINT}" \ + -v FORMATTING_BEGIN_COMMAND="${FORMATTING_BEGIN_COMMAND}" \ + -v FORMATTING_END="${FORMATTING_END}" +endef + +## Non-configurables. +# Touch these and you will start mysteriously breaking things and I will not help you. +override ARTIFACT_BIN = target/${ARCH}/${BUILD_MODE}/${BIN} +override BUILD_MODE = $(if $(findstring true,$(RELEASE)),release,debug) +override MAYBE_RELEASE_FLAG = $(if $(findstring true,$(RELEASE)),--release,) +override MAYBE_CHECK_FLAG = $(if $(findstring true,$(CHECK)),--check,) +override ROOT_DIR = $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) + +help: ## Print this message. + @printf -- "\n" + @printf -- " ${FORMATTING_BEGIN_TASK}Junctor${FORMATTING_END}\n" + @printf -- " ${FORMATTING_BEGIN_HEADING}A Hoverbear Consulting nRF52840 Experiment${FORMATTING_END}\n" + @printf -- "\n" + @printf -- "Prior to usage, please run \`${FORMATTING_BEGIN_COMMAND}make${FORMATTING_END} ${FORMATTING_BEGIN_TASK}prerequisites${FORMATTING_END}\`. Thanks!\n" + @printf -- "\n" + @printf -- "${FORMATTING_BEGIN_HEADING}Usage${FORMATTING_END}\n" + @printf -- " ${FORMATTING_BEGIN_COMMAND}make${FORMATTING_END} ${FORMATTING_BEGIN_TASK}${FORMATTING_END} ${FORMATTING_BEGIN_KNOBS}[RELEASE=true CHECK=true ...]${FORMATTING_END} \n" + @printf -- "\n" + @printf -- "${FORMATTING_BEGIN_HEADING}Knobs${FORMATTING_END} ${FORMATTING_BEGIN_HINT}Configured Default Description${FORMATTING_END}\n" + ${AWK} -f hack/variables.awk $(MAKEFILE_LIST) + @printf -- "\n" + @printf -- "${FORMATTING_BEGIN_HEADING}Tasks${FORMATTING_END} ${FORMATTING_BEGIN_HINT}Task${FORMATTING_END} ${FORMATTING_BEGIN_HINT}Description${FORMATTING_END}\n" + ${AWK} -f hack/targets.awk $(MAKEFILE_LIST) + +##@ Code +.PHONY := build format + +build: rust-target-${ARCH} ## Build the binary. + cargo build ${MAYBE_RELEASE_FLAG} + +size: tool-cargo-binutils ## Show size of code. + cargo size ${MAYBE_RELEASE_FLAG} --bin ${BIN} + +bloat: tool-cargo-bloat ## Show bloat in code + cargo bloat ${MAYBE_RELEASE_FLAG} --bin ${BIN} + +fetch: ## Fetch a local copy of the dependencies. + cargo fetch + +clean: ## Clean up the working environment. + cargo clean + +##@ Hardware +.PHONY := flash embed + +run: rust-target-${ARCH} ## Run the binary. + cargo run ${MAYBE_RELEASE_FLAG} --bin ${BIN} + +flash: rust-target-${ARCH} tool-cargo-flash ## Flash the device. + cargo flash ${MAYBE_RELEASE_FLAG} --chip ${CHIP} + +embed: rust-target-${ARCH} tool-cargo-embed ## Embed into the device. + cargo embed ${MAYBE_RELEASE_FLAG} + +recover: tool-nrf-recover ## Recover the nRF device. + nrf-recover -y + +##@ Validation +.PHONY := audit format lint conventional version release-needed + +audit: tool-cargo-audit rust-target-${ARCH} ## Audit the depenencies. + cargo audit + +format: rust-target-${ARCH} rust-component-rustfmt ## Run formatting pass. + cargo fmt -- ${MAYBE_CHECK_FLAG} + +lint: rust-target-${ARCH} rust-component-clippy ## Run linting pass. + cargo clippy + +conventional: tool-convco ## Ensures the commits are all conventional. + convco check + +version: tool-convco apt-jq apt-gawk ## Sync version to Cargo + $(eval override CARGO_VERSION = $(shell cargo pkgid | gawk --file hack/version.awk)) + $(eval override CONVCO_VERSION = $(shell convco version)) + $(if $(findstring true,$(CHECK)),@test "${CARGO_VERSION}" = "${CONVCO_VERSION}",) + $(if $(findstring true,$(CHECK)),,@sed -i 's/version = "${CARGO_VERSION}"/version = "${CONVCO_VERSION}"/g' Cargo.toml) + $(if $(findstring true,$(CHECK)),,@git add Cargo.toml) + +release-needed: tool-convco ## Determine if a release is needed. + $(eval override CARGO_VERSION = $(shell cargo pkgid | gawk --file hack/version.awk)) + $(eval override CONVCO_VERSION = $(shell convco version)) + $(eval override NEW_CONVCO_VERSION = $(shell convco version --bump)) + # Make sure this is required. + test "${CONVCO_VERSION}" != "${NEW_CONVCO_VERSION}" || test -z "${TAG_OF_THIS_VERSION_EXISTS}" + +##@ Committing +.PHONY := commit-build commit-chore commit-ci commit-docs commit-feat commit-fix commit-perf commit-refactor commit-style commit-test push + +commit-build: changelog version ## Make a build change. + @convco commit --build -- --patch + +commit-chore: changelog version ## Make a chore change. + @convco commit --chore -- --patch + +commit-ci: changelog version ## Make a ci change. + @convco commit --ci -- --patch + +commit-docs: changelog version ## Make a docs change. + @convco commit --docs -- --patch + +commit-feat: changelog version ## Make a feat change. + @convco commit --feat -- --patch + +commit-fix: changelog version ## Make a fix change. + @convco commit --fix -- --patch + +commit-perf: changelog version ## Make a perf change. + @convco commit --perf -- --patch + +commit-refactor: changelog version ## Make a refactor change. + @convco commit --refactor -- --patch + +commit-style: changelog version ## Make a style change. + @convco commit --style -- --patch + +commit-test: changelog version ## Make a test change. + @convco commit --test -- --patch + +push: FORCE ?= true +push: ## Push the latest code & tags. + git push --follow-tag $(if $(findstring true,$(FORCE)),--force,) + +##@ Releasing +.PHONY := changelog release update reset + +changelog: tool-convco ## Update the changelog. + $(if $(findstring true,$(CHECK)),@convco check,) + @convco changelog > CHANGELOG.md + $(if $(findstring true,$(CHECK)),,@test -z "$(git ls-files CHANGELOG.md --modified)") + $(if $(findstring true,$(CHECK)),,@git add CHANGELOG.md) + $(if $(findstring true,$(CHECK)),@git restore CHANGELOG.md,) + +release: release-needed ## Cut a release, if required. + $(eval override CARGO_VERSION = $(shell cargo pkgid | gawk --file hack/version.awk)) + $(eval override CONVCO_VERSION = $(shell convco version)) + $(eval override NEW_CONVCO_VERSION = $(shell convco version --bump)) + sed -i 's/version = "${CARGO_VERSION}"/version = "${NEW_CONVCO_VERSION}"/g' Cargo.toml + git add CHANGELOG.md Cargo.toml + git commit --no-verify --message "chore(release): Prepare v${NEW_CONVCO_VERSION}" + git tag v${NEW_CONVCO_VERSION} + make changelog version + + @echo "chore(release): Release v${NEW_CONVCO_VERSION}" > MESSAGE + @echo "" >> MESSAGE + @cat CHANGELOG.md >> MESSAGE + git commit --amend --no-verify --file MESSAGE + git tag -d v${NEW_CONVCO_VERSION} + git tag --annotate --file MESSAGE v${NEW_CONVCO_VERSION} + rm MESSAGE + +update: ## Update all dependencies. + cargo update + +reset: # (Hidden from users) This resets the repo completely back to a squashed commit with a tagged version. + @echo -n "This is going to do some bad stuff. Why would you do this? Are you sure? [y/N] " && read ans && [ $${ans:-N} = y ] + # Reset + git tag | xargs git tag -d + echo "" > CHANGELOG.md + git reset $(shell git commit-tree HEAD^{tree} -m 'feat(init): Initialize repository.') + make release + +##@ Provisioning +.PHONY := ci prerequisites + +ci: prerequisites format lint build changelog ## Run the CI pass locally. + +prerequisites: inject-hooks ## Bootstrap the machine. + $(if $(findstring true,$(PREREQS)),@bash ./distribution/bootstraps/ubuntu-20.04.sh,) + # We just always need this. + @rustup +stable component add llvm-tools-preview + +##@ Hooks +.PHONY := inject-hooks hook-pre-commit + +inject-hooks: ## Inject the git hooks used. + @ln \ + --symbolic \ + --force \ + ../../hack/git/hooks/pre-commit .git/hooks/pre-commit + +hook-pre-commit: override CHECK = true +hook-pre-commit: ci + +.PHONY := apt-% tool-% rust-component-% rust-target-% + +apt-%: override PACKAGE = $(@:apt-%=%) +apt-%: + $(if $(findstring true,$(PREREQS)),@sudo apt install ${PACKAGE} --yes -qqq,) + +tool-%: override TOOL = $(@:tool-%=%) +tool-%: + $(if $(findstring true,$(PREREQS)),@cargo install ${TOOL} --quiet,) + +rust-component-%: override COMPONENT = $(@:rust-component-%=%) +rust-component-%: + $(if $(findstring true,$(PREREQS)),@rustup +stable component add ${COMPONENT},) + +rust-target-%: override ARCH = $(@:rust-target-%=%) +rust-target-%: + $(if $(findstring true,$(PREREQS)),@rustup +stable target add ${ARCH},) \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..af6acbb --- /dev/null +++ b/README.md @@ -0,0 +1,53 @@ +# Junctor + +Right now, this is just a project that is slowly evolving as I learn through some material. + +> This is a project for [nRF52840-DK](https://www.mouser.ca/ProductDetail/Nordic-Semiconductor/nRF52840-DK?qs=F5EMLAvA7IA76ZLjlwrwMw%3D%3D). + +Eventual goals are some mesh networking, some sensor collection, and some data processing. + +## Usage + +This project only supports Ubuntu 20.04 right now. + +You can emulate a full CI run, which will properly set up your machine, including installing all `apt` packages, bootstrapping Rustup, setting up the necessary tools, and getting Python untangled. + +```bash +make ci +``` + +Once you've done that, I suggest you enjoy the `make help` command. + +If you're on Ubuntu 20.04, these should all just work and I'd love it if you reported a bug if they didn't. + +😊 + +## Mentoring Available / Requested + +I'm learning at my own pace on this through [The Embedded Trainings 2020](https://github.com/ferrous-systems/embedded-trainings-2020) series from Ferrous Systems. + +If you're someone who doesn't really know what all this is, and you want to learn about it with me, let me know. You can [email me](mailto:operator@hoverbear.org) if you don't want to post publicly on issues. + +If you want to mentor me and/or others who might get involved, I'd love it if you opened an issue and said hi! I frequently like to rubber ducky debug against live humans, and people seeing that they might have some help beyond me might encourage them to try things out. + +## Contributing + +* Please commit using [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/). I provide Git hooks and Make targets to help you, please use them! +* Please don't get mad if I say something isn't in scope and close it! I'm just hacking! + +## Code of Conduct / Licensing + +You're welcome to try out, interact with, or contribute to, or derive from this repo anything you wish, but if you make this project not fun for anyone working on it, you will be immediately banned without recourse or discussion. + +## License + +``` +Copyright 2020 Ana Hobden (Hoverbear Consulting) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +This software is not used to oppress or detain living creatures. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +``` \ No newline at end of file diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..f626838 --- /dev/null +++ b/build.rs @@ -0,0 +1,12 @@ +use std::{env, error::Error, fs, path::PathBuf}; + +fn main() -> Result<(), Box> { + let out_dir = PathBuf::from(env::var("OUT_DIR")?); + + // put memory layout (linker script) in the linker search path + fs::copy("src/memory.x", out_dir.join("memory.x"))?; + + println!("cargo:rustc-link-search={}", out_dir.display()); + + Ok(()) +} diff --git a/distribution/bootstraps/components/python.sh b/distribution/bootstraps/components/python.sh new file mode 100755 index 0000000..8197f6d --- /dev/null +++ b/distribution/bootstraps/components/python.sh @@ -0,0 +1,5 @@ +#! /usr/bin/env bash + +set -e + +pip3 install -r requirements.txt --quiet \ No newline at end of file diff --git a/distribution/bootstraps/components/rust.sh b/distribution/bootstraps/components/rust.sh new file mode 100755 index 0000000..cbb9286 --- /dev/null +++ b/distribution/bootstraps/components/rust.sh @@ -0,0 +1,18 @@ +#! /usr/bin/env bash + +set -e + +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --quiet + +source ~/.cargo/env +export PATH="$HOME/.cargo/bin:$PATH" + +# TODO: Take off my training wheels. :) +cargo install --quiet \ + --git https://github.com/ferrous-systems/embedded-trainings-2020/ \ + --bins \ + dk-run \ + dongle-flash \ + serial-term \ + usb-list \ + change-channel diff --git a/distribution/bootstraps/ubuntu-20.04.sh b/distribution/bootstraps/ubuntu-20.04.sh new file mode 100755 index 0000000..53793d1 --- /dev/null +++ b/distribution/bootstraps/ubuntu-20.04.sh @@ -0,0 +1,32 @@ +#! /usr/bin/env bash + +set -e + +sudo apt update --yes -qqq +sudo apt install --yes -qqq \ + gawk \ + make \ + build-essential \ + pkg-config \ + libusb-1.0-0-dev \ + libudev-dev \ + libssl-dev \ + python3-pip + +./distribution/bootstraps/components/rust.sh +./distribution/bootstraps/components/python.sh + +cat <<-EOF | sudo dd of=/etc/udev/rules.d/50-nRF52840.rules +# udev rules to allow access to USB devices as a non-root user + +# nRF52840 Dongle in bootloader mode +ATTRS{idVendor}=="1915", ATTRS{idProduct}=="521f", TAG+="uaccess" + +# nRF52840 Dongle applications +ATTRS{idVendor}=="2020", TAG+="uaccess" + +# nRF52840 Development Kit +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1015", TAG+="uaccess" +EOF + +sudo udevadm control --reload-rules \ No newline at end of file diff --git a/hack/git/hooks/pre-commit b/hack/git/hooks/pre-commit new file mode 100755 index 0000000..c1f1fae --- /dev/null +++ b/hack/git/hooks/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -e + +make hook-pre-commit \ No newline at end of file diff --git a/hack/targets.awk b/hack/targets.awk new file mode 100644 index 0000000..cfd7fcd --- /dev/null +++ b/hack/targets.awk @@ -0,0 +1,19 @@ +BEGIN {}; + +# Headers +match($0, /^##@ (.*?)/, matches) { + printf "%s%40s%s\n", + FORMATTING_BEGIN_COMMAND, + matches[1], + FORMATTING_END +} + +# Tasks +match($0, /^([a-zA-Z0-9_-]+): ?(.*?) ## (.*?)/, matches) { + printf "%s%40s%s %-20s\n", + FORMATTING_BEGIN_TASK, + matches[1], + FORMATTING_END, + + matches[3] +} diff --git a/hack/variables.awk b/hack/variables.awk new file mode 100644 index 0000000..f09cd27 --- /dev/null +++ b/hack/variables.awk @@ -0,0 +1,19 @@ +BEGIN {}; + +# Variables +match($0, /^export ([a-zA-Z_-]+) \?= (.*) ## (.*?)/, matches) { + printf "%s%20s%s %s%20s%s %s%-20s%s %-20s\n", + FORMATTING_BEGIN_KNOBS, + matches[1], + FORMATTING_END, + + FORMATTING_BEGIN_CONFIGURED, + ENVIRON[matches[1]], + FORMATTING_END, + + FORMATTING_BEGIN_DEFAULT, + matches[2], + FORMATTING_END, + + matches[3] +} \ No newline at end of file diff --git a/hack/version.awk b/hack/version.awk new file mode 100644 index 0000000..08d0920 --- /dev/null +++ b/hack/version.awk @@ -0,0 +1,5 @@ +# Version +match($0, /^(.*?)#(.*?)/, matches) { + printf "%s", + matches[2] +} \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..c4d4d7a --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +nrfutil==6.1.0 +pc-ble-driver-py==0.14.2 diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..ccc902b --- /dev/null +++ b/src/main.rs @@ -0,0 +1,27 @@ +#![no_main] +#![no_std] + +use cortex_m::asm; +use cortex_m_rt::entry; + +#[entry] +fn main() -> ! { + // initializes the peripherals + dk::init().unwrap(); + + log::info!("Hello, world!"); // :wave: + + loop { + // breakpoint: halts the program's execution + asm::bkpt(); + } +} + +#[panic_handler] +fn panic(info: &core::panic::PanicInfo) -> ! { + log::error!("{}", info); + + loop { + asm::bkpt() + } +} diff --git a/src/memory.x b/src/memory.x new file mode 100644 index 0000000..0067a73 --- /dev/null +++ b/src/memory.x @@ -0,0 +1,5 @@ +MEMORY +{ + FLASH : ORIGIN = 0x00000000, LENGTH = 1024K + RAM : ORIGIN = 0x20000000, LENGTH = 256K +} \ No newline at end of file