diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..0d031f6 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,24 @@ +[target.'cfg(all(target_arch = "arm", target_os = "none"))'] +# --no-catch-reset: don't trap the reset vector, so pressing the board's NRST +# button re-runs the firmware instead of ending the session with an Exception. +# (hardfault catch stays on by default, so panics still produce a backtrace.) +runner = "probe-rs run --chip STM32F411VETx --no-catch-reset" + +# flip-link: zero-cost stack-overflow protection. It wraps the real linker +# (LLD here), so it stays compatible with the -Tlink.x / -Tdefmt.x args below. +linker = "flip-link" + +rustflags = [ + # LLD (shipped with the Rust toolchain) is used as the default linker + "-C", "link-arg=-Tlink.x", + # defmt's linker script, must come after link.x + "-C", "link-arg=-Tdefmt.x", +] + +[build] +target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU) + +[env] +# defmt filters log levels at COMPILE time; without this, info!/debug! are +# stripped and only println! survives. "debug" enables debug/info/warn/error. +DEFMT_LOG = "debug" diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..9e337f2 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,567 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "ambium" +version = "0.1.0" +dependencies = [ + "cortex-m", + "cortex-m-rt", + "defmt 0.3.100", + "defmt-rtt", + "f411", + "libm", + "panic-probe", +] + +[[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 = "bare-metal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" + +[[package]] +name = "bitfield" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cast" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a" +dependencies = [ + "rustc_version 0.4.1", +] + +[[package]] +name = "cortex-m" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9" +dependencies = [ + "bare-metal 0.2.5", + "bitfield", + "critical-section", + "embedded-hal 0.2.7", + "volatile-register", +] + +[[package]] +name = "cortex-m-rt" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d4dec46b34c299ccf6b036717ae0fce602faa4f4fe816d9013b9a7c9f5ba6" +dependencies = [ + "cortex-m-rt-macros", +] + +[[package]] +name = "cortex-m-rt-macros" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e37549a379a9e0e6e576fd208ee60394ccb8be963889eebba3ffe0980364f472" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "defmt" +version = "0.3.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0963443817029b2024136fc4dd07a5107eb8f977eaf18fcd1fdeb11306b64ad" +dependencies = [ + "defmt 1.1.1", +] + +[[package]] +name = "defmt" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2953bfe4f93bbd20cc71198842756f77d161884c99ebbabc41d80231ded88d1" +dependencies = [ + "bitflags", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad9c72e7ca2137e0dc3813245a0d282fd6daad32fd800af018306a9169b5fe8" +dependencies = [ + "defmt-parser", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "defmt-parser" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" +dependencies = [ + "thiserror", +] + +[[package]] +name = "defmt-rtt" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "757110fd3748162dddbea88854529888a7e9e36929058118efe06f9f88d93b64" +dependencies = [ + "cortex-m", + "defmt 0.3.100", +] + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" + +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", +] + +[[package]] +name = "embedded-dma" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "994f7e5b5cb23521c22304927195f236813053eb9c065dd2226a32ba64695446" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" + +[[package]] +name = "embedded-hal-nb" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605" +dependencies = [ + "embedded-hal 1.0.0", + "nb 1.1.0", +] + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + +[[package]] +name = "embedded-storage" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21dea9854beb860f3062d10228ce9b976da520a73474aed3171ec276bc0c032" + +[[package]] +name = "enumflags2" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" +dependencies = [ + "enumflags2_derive", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "f411" +version = "0.1.0" +dependencies = [ + "cortex-m", + "cortex-m-rt", + "defmt 0.3.100", + "defmt-rtt", + "l3gd20", + "libm", + "lsm303dlhc", + "panic-probe", + "stm32f4", + "stm32f4xx-hal", +] + +[[package]] +name = "fugit" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e639847d312d9a82d2e75b0edcc1e934efcc64e6cb7aa94f0b1fbec0bc231d6" +dependencies = [ + "gcd", +] + +[[package]] +name = "fugit-timer" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9607bfc4c388f9d629704f56ede4a007546cad417b3bcd6fc7c87dc7edce04a" +dependencies = [ + "fugit", + "nb 1.1.0", +] + +[[package]] +name = "gcd" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" + +[[package]] +name = "generic-array" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "667f6ea017b297ec65b8a108c6e9ad6879460721fb3b6b23abf690970147fc28" +dependencies = [ + "typenum", +] + +[[package]] +name = "l3gd20" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86113fcb2b542fbd5636a7057fd1f0c39ea38b516383b557114027d5bd0cf491" +dependencies = [ + "embedded-hal 0.2.7", +] + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "litrs" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" + +[[package]] +name = "lsm303dlhc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5d1a5c290951321d1b0d4a40edd828537de9889134a0e67c5146542ae57706" +dependencies = [ + "cast", + "embedded-hal 0.2.7", + "generic-array", +] + +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "num-conv" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" + +[[package]] +name = "panic-probe" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4047d9235d1423d66cc97da7d07eddb54d4f154d6c13805c6d0793956f4f25b0" +dependencies = [ + "cortex-m", + "defmt 0.3.100", +] + +[[package]] +name = "portable-atomic" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d20d5497ef88037a52ff98267d066e7f11fcc5e99bbfbd58a42336193aacec3" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "proc-macro2" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" + +[[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.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver 1.0.28", +] + +[[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" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "stm32_i2s_v12x" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd7471c971f825e43b8ffbbee67e4db7e3a5b27a89ef698ae7315cfa98d4b946" +dependencies = [ + "nb 1.1.0", + "vcell", +] + +[[package]] +name = "stm32f4" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41bd8922df364cb7054cae71a95dcbb32cffd25b5c0f9c00272ef8c82279a65" +dependencies = [ + "cortex-m", + "cortex-m-rt", + "critical-section", + "portable-atomic", + "vcell", +] + +[[package]] +name = "stm32f4xx-hal" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b5b520616b1ebd18b3ac2d809b8ae47851b14efc63aea7c85d8a45c1daa6fbb" +dependencies = [ + "bare-metal 1.0.0", + "cortex-m", + "cortex-m-rt", + "document-features", + "embedded-dma", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-nb", + "embedded-io", + "embedded-storage", + "enumflags2", + "fugit", + "fugit-timer", + "nb 1.1.0", + "rand_core 0.6.4", + "rand_core 0.9.5", + "stm32_i2s_v12x", + "stm32f4", + "time", + "void", +] + +[[package]] +name = "syn" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "2.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "time" +version = "0.3.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e1d5e639ff6bab73cb6885cc7e7b1de96c3f32c68ec55f3952614bec1092244" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "time-core", +] + +[[package]] +name = "time-core" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" + +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + +[[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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc" +dependencies = [ + "vcell", +] diff --git a/Cargo.toml b/Cargo.toml index e72a960..95fecab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,3 +4,21 @@ version = "0.1.0" edition = "2024" [dependencies] +# board support: re-exports the HAL as `f411::hal`, plus the L3gd20/Lsm303dlhc +# interfaces and the `led` module +f411 = { path = "../../../code/f411" } + +cortex-m = "0.7.7" +cortex-m-rt = "0.7.5" + +defmt = "0.3" +defmt-rtt = "0.3" +panic-probe = { version = "0.3", features = ["print-defmt"] } + +# math for the thermistor Beta equation (ln) in no_std +libm = "0.2" + +[profile.release] +codegen-units = 1 # better optimizations +debug = true # symbols are nice and they don't increase the size on Flash +lto = true # better optimizations diff --git a/ambium.kicad_prl b/ambium.kicad_prl deleted file mode 100644 index e829e10..0000000 --- a/ambium.kicad_prl +++ /dev/null @@ -1,105 +0,0 @@ -{ - "board": { - "active_layer": 0, - "active_layer_preset": "", - "auto_track_width": true, - "hidden_netclasses": [], - "hidden_nets": [], - "high_contrast_mode": 0, - "net_color_mode": 1, - "opacity": { - "images": 0.6, - "pads": 1.0, - "shapes": 1.0, - "tracks": 1.0, - "vias": 1.0, - "zones": 0.6 - }, - "prototype_zone_fills": false, - "selection_filter": { - "dimensions": true, - "footprints": true, - "graphics": true, - "keepouts": true, - "lockedItems": false, - "otherItems": true, - "pads": true, - "text": true, - "tracks": true, - "vias": true, - "zones": true - }, - "visible_items": [ - "vias", - "footprint_text", - "footprint_anchors", - "ratsnest", - "grid", - "footprints_front", - "footprints_back", - "footprint_values", - "footprint_references", - "tracks", - "drc_errors", - "drawing_sheet", - "bitmaps", - "pads", - "zones", - "drc_warnings", - "drc_exclusions", - "locked_item_shadows", - "conflict_shadows", - "shapes", - "board_outline_area", - "ly_points" - ], - "visible_layers": "ffffffff_ffffffff_ffffffff_ffffffff", - "zone_display_mode": 0 - }, - "git": { - "integration_disabled": false, - "repo_type": "", - "repo_username": "", - "ssh_key": "" - }, - "meta": { - "filename": "ambium.kicad_prl", - "version": 5 - }, - "net_inspector_panel": { - "col_hidden": [], - "col_order": [], - "col_widths": [], - "custom_group_rules": [], - "expanded_rows": [], - "filter_by_net_name": true, - "filter_by_netclass": true, - "filter_text": "", - "group_by_constraint": false, - "group_by_netclass": false, - "show_time_domain_details": false, - "show_unconnected_nets": false, - "show_zero_pad_nets": false, - "sort_ascending": true, - "sorting_column": -1 - }, - "open_jobsets": [], - "project": { - "files": [] - }, - "schematic": { - "hierarchy_collapsed": [], - "selection_filter": { - "graphics": true, - "images": true, - "labels": true, - "lockedItems": false, - "otherItems": true, - "pins": true, - "ruleAreas": true, - "symbols": true, - "text": true, - "wires": true - } - } -} diff --git a/ambium.kicad_pro b/ambium.kicad_pro deleted file mode 100644 index 69c4adb..0000000 --- a/ambium.kicad_pro +++ /dev/null @@ -1,443 +0,0 @@ -{ - "board": { - "3dviewports": [], - "ipc2581": { - "bom_rev": "", - "dist": "", - "distpn": "", - "internal_id": "", - "mfg": "", - "mpn": "", - "sch_revision": "" - }, - "layer_pairs": [], - "layer_presets": [], - "viewports": [] - }, - "boards": [], - "component_class_settings": { - "assignments": [], - "meta": { - "version": 0 - }, - "sheet_component_classes": { - "enabled": false - } - }, - "cvpcb": { - "equivalence_files": [] - }, - "erc": { - "erc_exclusions": [], - "meta": { - "version": 0 - }, - "pin_map": [ - [ - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 2 - ], - [ - 0, - 2, - 0, - 1, - 0, - 0, - 1, - 0, - 2, - 2, - 2, - 2 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - 1, - 0, - 1, - 2 - ], - [ - 0, - 1, - 0, - 0, - 0, - 0, - 1, - 1, - 2, - 1, - 1, - 2 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 2 - ], - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2 - ], - [ - 1, - 1, - 1, - 1, - 1, - 0, - 1, - 1, - 1, - 1, - 1, - 2 - ], - [ - 0, - 0, - 0, - 1, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 2 - ], - [ - 0, - 2, - 1, - 2, - 0, - 0, - 1, - 0, - 2, - 2, - 2, - 2 - ], - [ - 0, - 2, - 0, - 1, - 0, - 0, - 1, - 0, - 2, - 0, - 0, - 2 - ], - [ - 0, - 2, - 1, - 1, - 0, - 0, - 1, - 0, - 2, - 0, - 0, - 2 - ], - [ - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2 - ] - ], - "rule_severities": { - "bus_definition_conflict": "error", - "bus_entry_needed": "error", - "bus_to_bus_conflict": "error", - "bus_to_net_conflict": "error", - "different_unit_footprint": "error", - "different_unit_net": "error", - "duplicate_reference": "error", - "duplicate_sheet_names": "error", - "endpoint_off_grid": "warning", - "extra_units": "error", - "field_name_whitespace": "warning", - "footprint_filter": "ignore", - "footprint_link_issues": "warning", - "four_way_junction": "ignore", - "ground_pin_not_ground": "warning", - "hier_label_mismatch": "error", - "isolated_pin_label": "warning", - "label_dangling": "error", - "label_multiple_wires": "warning", - "lib_symbol_issues": "warning", - "lib_symbol_mismatch": "warning", - "missing_bidi_pin": "warning", - "missing_input_pin": "warning", - "missing_power_pin": "error", - "missing_unit": "warning", - "multiple_net_names": "warning", - "net_not_bus_member": "warning", - "no_connect_connected": "warning", - "no_connect_dangling": "warning", - "pin_not_connected": "error", - "pin_not_driven": "error", - "pin_to_pin": "warning", - "power_pin_not_driven": "error", - "same_local_global_label": "warning", - "similar_label_and_power": "warning", - "similar_labels": "warning", - "similar_power": "warning", - "simulation_model_issue": "ignore", - "single_global_label": "ignore", - "stacked_pin_name": "warning", - "unannotated": "error", - "unconnected_wire_endpoint": "warning", - "undefined_netclass": "error", - "unit_value_mismatch": "error", - "unresolved_variable": "error", - "wire_dangling": "error" - } - }, - "libraries": { - "pinned_footprint_libs": [], - "pinned_symbol_libs": [] - }, - "meta": { - "filename": "ambium.kicad_pro", - "version": 3 - }, - "net_settings": { - "classes": [ - { - "bus_width": 12, - "clearance": 0.2, - "diff_pair_gap": 0.25, - "diff_pair_via_gap": 0.25, - "diff_pair_width": 0.2, - "line_style": 0, - "microvia_diameter": 0.3, - "microvia_drill": 0.1, - "name": "Default", - "pcb_color": "rgba(0, 0, 0, 0.000)", - "priority": 2147483647, - "schematic_color": "rgba(0, 0, 0, 0.000)", - "track_width": 0.2, - "tuning_profile": "", - "via_diameter": 0.6, - "via_drill": 0.3, - "wire_width": 6 - } - ], - "meta": { - "version": 5 - }, - "net_colors": null, - "netclass_assignments": null, - "netclass_patterns": [] - }, - "pcbnew": { - "last_paths": { - "idf": "", - "netlist": "", - "plot": "", - "specctra_dsn": "", - "vrml": "" - }, - "page_layout_descr_file": "" - }, - "schematic": { - "annotate_start_num": 0, - "annotation": { - "method": 0, - "sort_order": 0 - }, - "bom_export_filename": "${PROJECTNAME}.csv", - "bom_fmt_presets": [], - "bom_fmt_settings": { - "field_delimiter": ",", - "keep_line_breaks": false, - "keep_tabs": false, - "name": "CSV", - "ref_delimiter": ",", - "ref_range_delimiter": "", - "string_delimiter": "\"" - }, - "bom_presets": [], - "bom_settings": { - "exclude_dnp": false, - "fields_ordered": [ - { - "group_by": false, - "label": "Reference", - "name": "Reference", - "show": true - }, - { - "group_by": false, - "label": "Qty", - "name": "${QUANTITY}", - "show": true - }, - { - "group_by": true, - "label": "Value", - "name": "Value", - "show": true - }, - { - "group_by": true, - "label": "DNP", - "name": "${DNP}", - "show": true - }, - { - "group_by": true, - "label": "Exclude from BOM", - "name": "${EXCLUDE_FROM_BOM}", - "show": true - }, - { - "group_by": true, - "label": "Exclude from Board", - "name": "${EXCLUDE_FROM_BOARD}", - "show": true - }, - { - "group_by": true, - "label": "Footprint", - "name": "Footprint", - "show": true - }, - { - "group_by": false, - "label": "Datasheet", - "name": "Datasheet", - "show": true - } - ], - "filter_string": "", - "group_symbols": true, - "include_excluded_from_bom": true, - "name": "Default Editing", - "sort_asc": true, - "sort_field": "Reference" - }, - "bus_aliases": {}, - "connection_grid_size": 50.0, - "drawing": { - "dashed_lines_dash_length_ratio": 12.0, - "dashed_lines_gap_length_ratio": 3.0, - "default_line_thickness": 6.0, - "default_text_size": 50.0, - "field_names": [], - "hop_over_size_choice": 0, - "intersheets_ref_own_page": false, - "intersheets_ref_prefix": "", - "intersheets_ref_short": false, - "intersheets_ref_show": false, - "intersheets_ref_suffix": "", - "junction_size_choice": 3, - "label_size_ratio": 0.375, - "operating_point_overlay_i_precision": 3, - "operating_point_overlay_i_range": "~A", - "operating_point_overlay_v_precision": 3, - "operating_point_overlay_v_range": "~V", - "overbar_offset_ratio": 1.23, - "pin_symbol_size": 25.0, - "text_offset_ratio": 0.15 - }, - "legacy_lib_dir": "", - "legacy_lib_list": [], - "meta": { - "version": 1 - }, - "ngspice": { - "fix_include_paths": true, - "meta": { - "version": 0 - }, - "model_mode": 4, - "workbook_filename": "" - }, - "page_layout_descr_file": "", - "plot_directory": "", - "reuse_designators": true, - "subpart_first_id": 65, - "subpart_id_separator": 0, - "top_level_sheets": [ - { - "filename": "ambium.kicad_sch", - "name": "Root", - "uuid": "5ab6832c-376c-4ebe-b1c2-82e1b27b6200" - } - ], - "used_designators": "U1", - "variants": [] - }, - "sheets": [ - [ - "5ab6832c-376c-4ebe-b1c2-82e1b27b6200", - "Root" - ] - ], - "text_variables": {}, - "tuning_profiles": { - "meta": { - "version": 0 - }, - "tuning_profiles_impedance_geometric": [] - } -} diff --git a/ambium.sublime-project b/ambium.sublime-project index 028bb92..ada8de2 100644 --- a/ambium.sublime-project +++ b/ambium.sublime-project @@ -13,7 +13,10 @@ "~ambium.kicad_sch.lck", ".DS_Store", "ambium.sublime-workspace" - ] - } - ] + ], + }, + { + "path": "/Users/nathanrashleigh/code/f411" + }, + ], } diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..ed87434 --- /dev/null +++ b/build.rs @@ -0,0 +1,18 @@ +use std::env; +use std::fs::File; +use std::io::Write; +use std::path::PathBuf; + +fn main() { + // Put the linker script (memory.x) somewhere the linker can find it + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + File::create(out.join("memory.x")) + .unwrap() + .write_all(include_bytes!("etc/memory.x")) + .unwrap(); + println!("cargo:rustc-link-search={}", out.display()); + + // Only re-run the build script when memory.x is changed, + // instead of when any part of the source code changes. + println!("cargo:rerun-if-changed=etc/memory.x"); +} diff --git a/etc/.DS_Store b/etc/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/etc/.DS_Store differ diff --git a/etc/69-probe-rs.rules b/etc/69-probe-rs.rules new file mode 100644 index 0000000..5a5e178 --- /dev/null +++ b/etc/69-probe-rs.rules @@ -0,0 +1,151 @@ +# Copy this file to /etc/udev/rules.d/ +# If rules fail to reload automatically, you can refresh udev rules +# with the command "udevadm control --reload" + +# This rules are based on the udev rules from the OpenOCD project, with unsupported probes removed. +# See http://openocd.org/ for more details. +# +# This file is available under the GNU General Public License v2.0 + +ACTION!="add|change", GOTO="probe_rs_rules_end" + +SUBSYSTEM=="gpio", MODE="0660", GROUP="plugdev", TAG+="uaccess" + +SUBSYSTEM!="usb|tty|hidraw", GOTO="probe_rs_rules_end" + +# Please keep this list sorted by VID:PID + +# STMicroelectronics ST-LINK V1 +ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3744", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# STMicroelectronics ST-LINK/V2 +ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3748", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# STMicroelectronics ST-LINK/V2.1 +ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374b", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3752", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# STMicroelectronics STLINK-V3 +ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374d", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374e", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374f", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3753", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3754", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3757", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# SEGGER J-Link +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0101", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0102", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0103", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0104", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0105", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0107", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0108", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1001", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1002", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1003", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1004", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1005", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1006", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1007", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1008", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1009", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="100a", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="100b", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="100c", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="100d", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="100e", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="100f", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1010", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1011", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1012", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1013", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1014", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1015", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1016", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1017", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1018", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1019", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="101a", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="101b", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="101c", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="101d", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="101e", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="101f", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1020", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1021", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1022", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1023", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1024", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1025", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1026", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1027", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1028", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1029", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="102a", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="102b", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="102c", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="102d", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="102e", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="102f", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1050", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1051", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1052", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1053", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1054", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1055", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1056", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1057", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1058", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1059", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="105a", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="105b", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="105c", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="105d", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="105e", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="105f", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1060", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1061", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1062", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1063", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1064", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1065", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1066", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1067", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1068", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1069", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="106a", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="106b", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="106c", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="106d", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="106e", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="106f", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# FT232H +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6014", MODE="660", GROUP="plugdev", TAG+="uaccess" +# FT2232x +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", MODE="660", GROUP="plugdev", TAG+="uaccess" +# FT4232H +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6011", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# FTDI-based Olimex devices +ATTRS{idVendor}=="0x15ba", ATTRS{idProduct}=="0x0003", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="0x15ba", ATTRS{idProduct}=="0x0004", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="0x15ba", ATTRS{idProduct}=="0x002a", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="0x15ba", ATTRS{idProduct}=="0x002b", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Espressif USB JTAG/serial debug unit +ATTRS{idVendor}=="303a", ATTRS{idProduct}=="1001", MODE="660", GROUP="plugdev", TAG+="uaccess" +# Espressif USB Bridge +ATTRS{idVendor}=="303a", ATTRS{idProduct}=="1002", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# CMSIS-DAP compatible adapters +ATTRS{product}=="*CMSIS-DAP*", MODE="660", GROUP="plugdev", TAG+="uaccess" +# WCH Link (CMSIS-DAP compatible adapter) +ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="8010", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="8011", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Infineon KitProg +ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="f155", MODE="660", GROUP="plugdev", TAG+="uaccess" + +LABEL="probe_rs_rules_end" diff --git a/etc/memory.x b/etc/memory.x new file mode 100644 index 0000000..123296d --- /dev/null +++ b/etc/memory.x @@ -0,0 +1,6 @@ +MEMORY +{ + /* NOTE 1 K = 1 KiBi = 1024 bytes */ + FLASH : ORIGIN = 0x08000000, LENGTH = 512K + RAM : ORIGIN = 0x20000000, LENGTH = 128K +} diff --git a/justfile b/justfile new file mode 100644 index 0000000..9d4c333 --- /dev/null +++ b/justfile @@ -0,0 +1,56 @@ +# udev rules shipped with this repo (probe-rs probe permissions on Linux) +rules_src := "etc/69-probe-rs.rules" +rules_dst := "/etc/udev/rules.d/69-probe-rs.rules" + +# Default: show available recipes +default: + @just --list + +# One-shot dev setup: install toolchain bits + probe permissions +setup: install-tools probe-setup + @echo "Setup complete. Plug in the probe (re-plug if it was already connected)." + +# Install the Rust target and the host tools this project links/flashes with +install-tools: + rustup target add thumbv7em-none-eabihf + +# Set up probe-rs probe access on Linux: install udev rules + reload +# https://probe.rs/docs/getting-started/probe-setup/ +probe-setup: + @echo "Installing udev rules -> {{rules_dst}} (needs sudo)" + sudo install -m 0644 {{rules_src}} {{rules_dst}} + sudo udevadm control --reload + sudo udevadm trigger + @# plugdev group is referenced by the rules; create it and add the user if missing + sudo groupadd --system plugdev 2>/dev/null || true + sudo usermod -aG plugdev "$USER" + @echo "If the probe was already plugged in, unplug and reconnect it." + @echo "A new group membership requires a fresh login to take effect." + +# List debug probes probe-rs can see (verifies setup worked) +probes: + probe-rs list + +# Build the firmware (debug) +build: + cargo build + +# Build optimized +release: + cargo build --release + +# Flash + run on the target, streaming defmt logs over RTT +run: + cargo run --release + +# Compile checks / lints / format +check: + cargo check +clippy: + cargo clippy +fmt: + cargo fmt + +# Remove build artifacts +clean: + cargo clean diff --git a/src/main.rs b/src/main.rs index e7a11a9..f600c55 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,177 @@ -fn main() { - println!("Hello, world!"); +//! 400 Hz sawtooth out the F411E-DISCO's 3.5 mm jack. +//! +//! The jack is driven by the on-board CS43L22 codec (see `f411::codec` for +//! the control interface and wiring). I2S3 runs master transmit at 48 kHz +//! with MCLK (256×fs) enabled; the main loop streams a 400 Hz sawtooth +//! (48 000 / 400 = 120 samples per cycle) into both channels. +//! +//! The USER button (B1, PA0, high = pressed) toggles the tone via EXTI0: the +//! interrupt only sets a flag, the audio loop applies it (with a debounce +//! hold-off), so no GPIO polling or I2C traffic happens in the sample path. +//! While off, silence is streamed so the codec keeps its clocks. + +#![no_std] +#![no_main] + +// defmt global logger (RTT transport) + panic handler +use defmt_rtt as _; +use panic_probe as _; + +use core::cell::RefCell; +use core::sync::atomic::{AtomicBool, Ordering}; + +use cortex_m::interrupt::Mutex; +use cortex_m_rt::entry; +// the HAL is re-exported by the f411 board-support crate as `f411::hal` +use f411::{ + codec::Cs43l22, + led::LedCompass, + hal::{ + gpio::{gpioa, gpioa::PA0, gpioc, Edge, Input}, + i2c::{I2c, Mode}, + i2s::stm32_i2s_v12x::transfer::*, + i2s::I2s, + nb::block, + pac, + pac::interrupt, + prelude::*, + rcc::{Config, Rcc}, + }, +}; + +// ---- tone ---- +const SAW_HZ: u32 = 400; +const SAMPLE_RATE_HZ: u32 = 48_000; +const SAMPLES_PER_CYCLE: u32 = SAMPLE_RATE_HZ / SAW_HZ; // 120 +// Full-scale is painfully loud on headphones; run the saw at ~1/8 amplitude. +const AMPLITUDE: i32 = i16::MAX as i32 / 8; + +// ---- button ---- +// After a toggle, ignore further presses for ~20 ms of samples (bounce). +const DEBOUNCE_SAMPLES: u32 = SAMPLE_RATE_HZ / 50; + +/// Button pin, parked here so the EXTI0 handler can clear its pending bit. +static BUTTON: Mutex>>> = Mutex::new(RefCell::new(None)); +/// Set by EXTI0 on a press edge, consumed by the audio loop. +static TOGGLE_REQ: AtomicBool = AtomicBool::new(false); + +type AudioOut = I2sTransfer, Master, Transmit, Philips, Data16Channel16>; + +/// I2S3 master transmit, 16-bit stereo, MCLK out for the codec. +fn audio_out( + spi: pac::SPI3, + pins: (gpioa::PA4, gpioc::PC10, Option, gpioc::PC12), + rcc: &mut Rcc, +) -> AudioOut { + let i2s = I2s::new(spi, pins, rcc); + let config = I2sTransferConfig::new_master() + .transmit() + .standard(Philips) + .data_format(Data16Channel16) + .master_clock(true) + .request_frequency(SAMPLE_RATE_HZ); + I2sTransfer::new(i2s, config) +} + +/// Sample `i` (of SAMPLES_PER_CYCLE) of the sawtooth: a linear ramp from +/// -AMPLITUDE to +AMPLITUDE, wrapping each cycle. +fn saw_sample(i: u32) -> i16 { + (i as i32 * 2 * AMPLITUDE / SAMPLES_PER_CYCLE as i32 - AMPLITUDE) as i16 +} + +#[entry] +fn main() -> ! { + let cp = cortex_m::Peripherals::take().unwrap(); + let mut p = pac::Peripherals::take().unwrap(); + + // PLLI2S tuned to 61.44 MHz so 48 kHz divides exactly (61.44 MHz / 256fs / 5). + let mut rcc = p + .RCC + .freeze(Config::hsi().sysclk(96.MHz()).i2s_clk(61440.kHz())); + let mut delay = cp.SYST.delay(&rcc.clocks); + + let gpioa = p.GPIOA.split(&mut rcc); + let gpiob = p.GPIOB.split(&mut rcc); + let gpioc = p.GPIOC.split(&mut rcc); + let gpiod = p.GPIOD.split(&mut rcc); + + // USER button (B1): rising-edge interrupt on EXTI0. + let mut syscfg = p.SYSCFG.constrain(&mut rcc); + let mut button = gpioa.pa0.into_pull_down_input(); + button.make_interrupt_source(&mut syscfg); + button.trigger_on_edge(&mut p.EXTI, Edge::Rising); + button.enable_interrupt(&mut p.EXTI); + cortex_m::interrupt::free(|cs| BUTTON.borrow(cs).replace(Some(button))); + unsafe { pac::NVIC::unmask(pac::Interrupt::EXTI0) }; + + // CS43L22 codec: control port + reset via the board-support driver. + let i2c = I2c::new( + p.I2C1, + (gpiob.pb6, gpiob.pb9), + Mode::standard(100.kHz()), + &mut rcc, + ); + let mut codec = Cs43l22::new(i2c, gpiod.pd4.into_push_pull_output()); + match codec.init(&mut delay) { + Ok(id) => defmt::info!("codec up, ID reg {=u8:#04x}", id), + Err(e) => defmt::error!("codec init failed: {}", defmt::Debug2Format(&e)), + } + + let mut transfer = audio_out( + p.SPI3, + (gpioa.pa4, gpioc.pc10, Some(gpioc.pc7), gpioc.pc12), + &mut rcc, + ); + + defmt::info!( + "saw: {} Hz, sample rate {} Hz ({} samples/cycle)", + SAW_HZ, + transfer.sample_rate(), + SAMPLES_PER_CYCLE + ); + + // On-board LEDs: south (LD6, blue) = 1 Hz heartbeat so it's visible the + // firmware is alive without a debugger; west (LD4, green) = saw playing. + let compass = LedCompass::new(gpiod.pd12, gpiod.pd13, gpiod.pd14, gpiod.pd15); + let mut heartbeat = compass.s; + let mut saw_led = compass.w; + + let mut i = 0; + let mut frames: u32 = 0; + let mut on = false; // silent at boot; USER button toggles the saw on + let mut holdoff: u32 = 0; + loop { + // Consume any press flag every frame (so bounce during the hold-off + // window is discarded), apply it only outside the window. + holdoff = holdoff.saturating_sub(1); + if TOGGLE_REQ.swap(false, Ordering::AcqRel) && holdoff == 0 { + on = !on; + holdoff = DEBOUNCE_SAMPLES; + saw_led.set(on); + defmt::info!("saw {}", if on { "ON" } else { "OFF" }); + } + + let sample = match on { + true => saw_sample(i), + false => 0, + }; + block!(transfer.write((sample, sample))).unwrap(); + i = (i + 1) % SAMPLES_PER_CYCLE; + + frames += 1; + if frames == SAMPLE_RATE_HZ { + frames = 0; + heartbeat.toggle(); + } + } +} + +#[interrupt] +fn EXTI0() { + cortex_m::interrupt::free(|cs| { + if let Some(pin) = BUTTON.borrow(cs).borrow_mut().as_mut() { + pin.clear_interrupt_pending_bit(); + } + }); + TOGGLE_REQ.store(true, Ordering::Release); }