+[build]
+target = "thumbv6m-none-eabi"
+
+# Target specific options
+[target.thumbv6m-none-eabi]
+# Pass some extra options to rustc, some of which get passed on to the linker.
+#
+# * linker argument --nmagic turns off page alignment of sections (which saves
+# flash space)
+# * linker argument -Tlink.x tells the linker to use link.x as the linker
+# script. This is usually provided by the cortex-m-rt crate, and by default
+# the version in that crate will include a file called `memory.x` which
+# describes the particular memory layout for your specific chip.
+# * inline-threshold=5 makes the compiler more aggressive and inlining functions
+# * no-vectorize-loops turns off the loop vectorizer (seeing as the M0+ doesn't
+# have SIMD)
+rustflags = [
+ "-C", "link-arg=--nmagic",
+ "-C", "link-arg=-Tlink.x",
+ "-C", "inline-threshold=5",
+ "-C", "no-vectorize-loops",
+]
+
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "Pico Debug",
+ "type": "cortex-debug",
+ "request": "launch",
+ "cwd": "${workspaceRoot}",
+ "executable": "${workspaceRoot}/target/thumbv6m-none-eabi/debug/${workspaceRootFolderName}",
+ // This may need to be arm-none-eabi-gdb depending on your system
+ //"gdbPath" : "gdb-multiarch",
+ // Connect to an already running OpenOCD instance
+ "servertype": "external",
+ "gdbTarget": "kirara3:3333",
+ "svdFile": "${env:PICO_SDK_PATH}/src/rp2040/hardware_regs/rp2040.svd",
+ //"runToEntryPoint": "main",
+ "preLaunchTask": "build",
+ // Work around for stopping at main on restart
+ "postRestartCommands": [
+ "break main",
+ "continue"
+ ]
+ }
+ ]
+}
+{
+ "rust-analyzer.checkOnSave.allTargets": false,
+ "rust-analyzer.checkOnSave.arguments": [
+ "--target",
+ "thumbv7m-none-eabi"
+ ]
+}
\ No newline at end of file
+{
+ // See https://go.microsoft.com/fwlink/?LinkId=733558
+ // for the documentation about the tasks.json format
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "build",
+ "type": "shell",
+ "command": "cargo build",
+ "problemMatcher": ["$rustc"],
+ "group": {
+ "kind": "build",
+ "isDefault": true
+ }
+ }
+ ]
+}
\ No newline at end of file
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "arrayvec"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
+
+[[package]]
+name = "atomic-polyfill"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3ff7eb3f316534d83a8a2c3d1674ace8a5a71198eba31e2e2b597833f699b28"
+dependencies = [
+ "critical-section",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[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 = "bitvec"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
+dependencies = [
+ "funty",
+ "radium",
+ "tap",
+ "wyz",
+]
+
+[[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
+[[package]]
+name = "cortex-m"
+version = "0.7.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9"
+dependencies = [
+ "bare-metal",
+ "bitfield",
+ "embedded-hal",
+ "volatile-register",
+]
+
+[[package]]
+name = "cortex-m-rt"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee84e813d593101b1723e13ec38b6ab6abbdbaaa4546553f5395ed274079ddb1"
+dependencies = [
+ "cortex-m-rt-macros",
+]
+
+[[package]]
+name = "cortex-m-rt-macros"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "crc-any"
+version = "2.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "774646b687f63643eb0f4bf13dc263cb581c8c9e57973b6ddf78bda3994d88df"
+dependencies = [
+ "debug-helper",
+]
+
+[[package]]
+name = "critical-section"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216"
+
+[[package]]
+name = "debug-helper"
+version = "0.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f578e8e2c440e7297e008bb5486a3a8a194775224bbc23729b0dbdfaeebf162e"
+
+[[package]]
+name = "doa-hallonbrod"
+version = "0.7.0"
+dependencies = [
+ "cortex-m",
+ "cortex-m-rt",
+ "fugit",
+ "rp2040-boot2",
+ "rp2040-hal",
+ "usb-device",
+]
+
+[[package]]
+name = "either"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
+
+[[package]]
+name = "embedded-alloc"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8931e47e33c5d3194fbcf9cc82df0919193bd2fa40008f388eb1d28fd9c9ea6b"
+dependencies = [
+ "critical-section",
+ "linked_list_allocator",
+]
+
+[[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 = "frunk"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "11a351b59e12f97b4176ee78497dff72e4276fb1ceb13e19056aca7fa0206287"
+dependencies = [
+ "frunk_core",
+ "frunk_derives",
+]
+
+[[package]]
+name = "frunk_core"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af2469fab0bd07e64ccf0ad57a1438f63160c69b2e57f04a439653d68eb558d6"
+
+[[package]]
+name = "frunk_derives"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0fa992f1656e1707946bbba340ad244f0814009ef8c0118eb7b658395f19a2e"
+dependencies = [
+ "frunk_proc_macro_helpers",
+ "quote",
+ "syn 2.0.29",
+]
+
+[[package]]
+name = "frunk_proc_macro_helpers"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "35b54add839292b743aeda6ebedbd8b11e93404f902c56223e51b9ec18a13d2c"
+dependencies = [
+ "frunk_core",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.29",
+]
+
+[[package]]
+name = "fugit"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17186ad64927d5ac8f02c1e77ccefa08ccd9eaa314d5a4772278aa204a22f7e7"
+dependencies = [
+ "gcd",
+]
+
+[[package]]
+name = "funty"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
+
+[[package]]
+name = "gcd"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a"
+
+[[package]]
+name = "hallonbrod-os"
+version = "0.1.0"
+dependencies = [
+ "cortex-m",
+ "cortex-m-rt",
+ "critical-section",
+ "doa-hallonbrod",
+ "embedded-alloc",
+ "embedded-hal",
+ "frunk_core",
+ "fugit",
+ "heapless",
+ "r0",
+ "usb-device",
+ "usbd-human-interface-device",
+ "usbd-serial",
+]
+
+[[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.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743"
+dependencies = [
+ "atomic-polyfill",
+ "hash32",
+ "rustc_version 0.4.0",
+ "spin",
+ "stable_deref_trait",
+]
+
+[[package]]
+name = "itertools"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "linked_list_allocator"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9afa463f5405ee81cdb9cc2baf37e08ec7e4c8209442b5d72c04cfb2cd6e6286"
+
+[[package]]
+name = "lock_api"
+version = "0.4.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
+[[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_enum"
+version = "0.5.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9"
+dependencies = [
+ "num_enum_derive 0.5.11",
+]
+
+[[package]]
+name = "num_enum"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1"
+dependencies = [
+ "num_enum_derive 0.6.1",
+]
+
+[[package]]
+name = "num_enum_derive"
+version = "0.5.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "num_enum_derive"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.29",
+]
+
+[[package]]
+name = "option-block"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0f2c5d345596a14d7c8b032a68f437955f0059f2eb9a5972371c84f7eef3227"
+
+[[package]]
+name = "packed_struct"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36b29691432cc9eff8b282278473b63df73bea49bc3ec5e67f31a3ae9c3ec190"
+dependencies = [
+ "bitvec",
+ "packed_struct_codegen",
+]
+
+[[package]]
+name = "packed_struct_codegen"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9cd6706dfe50d53e0f6aa09e12c034c44faacd23e966ae5a209e8bdb8f179f98"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "paste"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
+
+[[package]]
+name = "pio"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76e09694b50f89f302ed531c1f2a7569f0be5867aee4ab4f8f729bbeec0078e3"
+dependencies = [
+ "arrayvec",
+ "num_enum 0.5.11",
+ "paste",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "r0"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd7a31eed1591dcbc95d92ad7161908e72f4677f8fabf2a32ca49b4237cbf211"
+
+[[package]]
+name = "radium"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+
+[[package]]
+name = "rp2040-boot2"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c773ec49b836077aa144b58dc7654a243e1eecdb6cf0d25361ae7c7600fabd8"
+dependencies = [
+ "crc-any",
+]
+
+[[package]]
+name = "rp2040-hal"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1369bb84862d7f69391a96606b2f29a00bfce7f29a749e23d5f01fc3f607ada0"
+dependencies = [
+ "cortex-m",
+ "critical-section",
+ "embedded-dma",
+ "embedded-hal",
+ "fugit",
+ "itertools",
+ "nb 1.1.0",
+ "paste",
+ "pio",
+ "rand_core",
+ "rp2040-hal-macros",
+ "rp2040-pac",
+ "usb-device",
+ "vcell",
+ "void",
+]
+
+[[package]]
+name = "rp2040-hal-macros"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86479063e497efe1ae81995ef9071f54fd1c7427e04d6c5b84cde545ff672a5e"
+dependencies = [
+ "cortex-m-rt",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "rp2040-pac"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9192cafbb40d717c9e0ddf767aaf9c69fee1b4e48d22ed853b57b11f6d9f3d7e"
+dependencies = [
+ "cortex-m",
+ "cortex-m-rt",
+ "vcell",
+]
+
+[[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.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
+dependencies = [
+ "semver 1.0.18",
+]
+
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
+[[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.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918"
+
+[[package]]
+name = "semver-parser"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
+
+[[package]]
+name = "spin"
+version = "0.9.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
+dependencies = [
+ "lock_api",
+]
+
+[[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.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "tap"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
+
+[[package]]
+name = "usb-device"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f6cc3adc849b5292b4075fc0d5fdcf2f24866e88e336dd27a8943090a520508"
+
+[[package]]
+name = "usbd-human-interface-device"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "809d98d59a6fccbdcf27026101e9a753c5a98d66898061eee7dd8bfd4eff1d03"
+dependencies = [
+ "frunk",
+ "fugit",
+ "heapless",
+ "num_enum 0.6.1",
+ "option-block",
+ "packed_struct",
+ "usb-device",
+]
+
+[[package]]
+name = "usbd-serial"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db75519b86287f12dcf0d171c7cf4ecc839149fe9f3b720ac4cfce52959e1dfe"
+dependencies = [
+ "embedded-hal",
+ "nb 0.1.3",
+ "usb-device",
+]
+
+[[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.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6"
+dependencies = [
+ "vcell",
+]
+
+[[package]]
+name = "wyz"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
+dependencies = [
+ "tap",
+]
+[package]
+name = "hallonbrod-os"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+cortex-m = "0.7"
+cortex-m-rt = "0.7"
+critical-section = "1.1"
+embedded-alloc = "0.5"
+embedded-hal = { version = "0.2.5", features = ["unproven"] }
+frunk_core = { version = "0.4", default-features = false }
+fugit = "0.3.7"
+heapless = "0.7"
+r0 = "1.0"
+
+doa-hallonbrod = { path = "../doa-hallonbrod" }
+usb-device = "0.2.9"
+usbd-serial = "0.1.1"
+usbd-human-interface-device = "0.4.3"
+
+[target.thumbv6m-none-eabi]
+runner = "elf2uf2-rs"
+
+# cargo build/run
+[profile.dev]
+codegen-units = 1
+debug = 2
+debug-assertions = true
+incremental = false
+#opt-level = 3
+overflow-checks = true
+
+# cargo build/run --release
+[profile.release]
+codegen-units = 1
+debug = 2
+debug-assertions = false
+incremental = false
+lto = 'fat'
+opt-level = 3
+overflow-checks = false
+
+# do not optimize proc-macro crates = 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
+
+# cargo test
+[profile.test]
+codegen-units = 1
+debug = 2
+debug-assertions = true
+incremental = false
+opt-level = 3
+overflow-checks = true
+
+# cargo test --release
+[profile.bench]
+codegen-units = 1
+debug = 2
+debug-assertions = false
+incremental = false
+lto = 'fat'
+opt-level = 3
+MEMORY {
+ BOOT2 (r) : ORIGIN = 0x10000000, LENGTH = 0x100
+ FLASH (rx) : ORIGIN = 0x10000100, LENGTH = 1024K - 0x100
+ RAM (rw) : ORIGIN = 0x20000000, LENGTH = 256K
+ SRAM4 (rw) : ORIGIN = 0x20040000, LENGTH = 4K
+ SRAM5 (rw) : ORIGIN = 0x20041000, LENGTH = 4K
+}
+
+EXTERN(BOOT2_FIRMWARE)
+
+SECTIONS {
+ /* ### Boot loader */
+ .boot2 ORIGIN(BOOT2) :
+ {
+ KEEP(*(.boot2));
+ } > BOOT2
+} INSERT BEFORE .text;
+
+SECTIONS {
+ .kgram1 : {
+ *(.kgram1);
+ . = ALIGN(4);
+ } > SRAM4 AT >FLASH
+ __skgram1 = ADDR(.kgram1);
+ __ekgram1 = ADDR(.kgram1) + SIZEOF(.kgram1);
+ __lkgram1 = LOADADDR(.kgram1);
+
+ .kgram2 : {
+ *(.kgram2);
+ . = ALIGN(4);
+ } > SRAM5 AT >FLASH
+ __skgram2 = ADDR(.kgram2);
+ __ekgram2 = ADDR(.kgram2) + SIZEOF(.kgram2);
+ __lkgram2 = LOADADDR(.kgram1);
+} INSERT AFTER .bss;
+
+SECTIONS {
+ .kheap (NOLOAD) : ALIGN(4) {
+ *(.kheap);
+ . = ALIGN(4);
+ } > RAM
+} INSERT AFTER .bss;
\ No newline at end of file
+use embedded_alloc::Heap;
+
+#[global_allocator]
+#[link_section = ".kgram1"]
+static HEAP: Heap = Heap::empty();
+
+#[link_section = ".kheap"]
+static KERNEL_ARENA: [u8; 0x400] = [0u8; 0x400];
+
+pub fn init_allocator() {
+ unsafe {
+ let arena_start = &KERNEL_ARENA as *const u8 as usize;
+ let size = KERNEL_ARENA.len();
+ HEAP.init(arena_start, size);
+ }
+}
\ No newline at end of file
+extern crate alloc;
+use core::cell::RefCell;
+
+use critical_section::Mutex;
+
+use crate::peripherals::with_usb;
+
+#[link_section = ".kgram1"]
+static CONSOLE: Mutex<RefCell<Option<Console>>> = Mutex::new(RefCell::new(None));
+
+pub enum ConsoleError {
+ Read,
+ Write,
+}
+
+struct Console {
+}
+
+impl Console {
+ pub fn new() -> Console {
+ Console { }
+ }
+
+ pub fn write(&mut self, bytes: impl AsRef<[u8]>) -> Result<usize, ConsoleError> {
+ with_usb(|u| {
+ u.serial().write(bytes.as_ref()).map_err(|_| ConsoleError::Write)
+ })
+ }
+}
+
+pub fn init_console() {
+ critical_section::with(|cs| {
+ let mut console = CONSOLE.borrow_ref_mut(cs);
+ *console = Some(Console::new());
+ })
+}
+
+pub fn write(bytes: &[u8]) {
+ critical_section::with(|cs| {
+ let mut console = CONSOLE.borrow_ref_mut(cs);
+ if let Some(ref mut console) = *console {
+ console.write(bytes).ok();
+ }
+ // if the console is not initialized, ignore the write
+ // TODO: buffer writes until console is initialized?
+ });
+}
+
+pub(crate) fn _print(s: core::fmt::Arguments) {
+ let str = alloc::format!("{}", s);
+ write(str.as_bytes());
+}
+
+#[macro_export]
+macro_rules! kprintf {
+ ($($arg:tt)*) => {{
+ $crate::console::_print(core::format_args!($($arg)*));
+ }}
+}
+
+#[macro_export]
+macro_rules! kprint {
+ ($($arg:tt)*) => {{
+ $($crate::console::write($arg.as_bytes());)*
+ }}
+}
\ No newline at end of file
+#![no_std]
+#![no_main]
+
+mod allocator;
+mod console;
+mod panic;
+mod peripherals;
+mod timer;
+
+use allocator::init_allocator;
+use bsp::entry;
+use console::init_console;
+use cortex_m_rt::pre_init;
+use doa_hallonbrod as bsp;
+use embedded_hal::digital::v2::OutputPin;
+use peripherals::{init_peripherals, with_peripherals, with_usb};
+use r0;
+use usbd_human_interface_device::page::Keyboard;
+use usbd_human_interface_device::UsbHidError;
+
+#[pre_init]
+unsafe fn pre_init() {
+ extern "C" {
+ static mut __skgram1: u32;
+ static mut __ekgram1: u32;
+ static mut __lkgram1: u32;
+ }
+
+ r0::init_data(&mut __skgram1, &mut __ekgram1, &mut __lkgram1);
+}
+
+#[entry]
+fn main() -> ! {
+ init_allocator();
+ init_peripherals();
+ init_console();
+
+ let ticks = with_peripherals(|p| p.timer().get_counter().ticks());
+ kprintf!("Kernel started: {} ticks\r\n", ticks);
+
+ timer::schedule(1000, true, || {
+ with_peripherals(|p| p.led().set_high().unwrap());
+ match with_usb(|u| u.keyboard().device().write_report([Keyboard::Keyboard8])) {
+ Err(UsbHidError::WouldBlock) => {}
+ Err(UsbHidError::Duplicate) => {}
+ Ok(_) => {}
+ Err(e) => core::panic!("Failed to write keyboard report: {:?}", e),
+ }
+ let ticks = with_peripherals(|p| p.timer().get_counter().ticks());
+ kprintf!("{} ticks\r\n", ticks);
+ timer::schedule(10, false, || {
+ with_usb(|u| {
+ u.keyboard()
+ .device()
+ .write_report([Keyboard::NoEventIndicated])
+ })
+ .ok();
+ with_peripherals(|p| p.led().set_low().unwrap());
+ }).expect("could not schedule key up");
+ })
+ .expect("could not schedule");
+
+ loop {}
+}
+use core::panic::PanicInfo;
+
+use crate::console::write;
+
+#[link_section = ".kgram1"]
+static mut ALREADY_PANICKING: bool = false;
+
+#[panic_handler]
+fn panic(info: &PanicInfo) -> ! {
+ unsafe {
+ if ALREADY_PANICKING {
+ // welp
+ loop {}
+ }
+ ALREADY_PANICKING = true;
+ }
+ write(b"PANIC!\n");
+
+ if let Some(p) = info.payload().downcast_ref::<&str>() {
+ write(p.as_bytes());
+ } else {
+ write(b"could not get payload");
+ }
+ write(b"\n");
+
+ if let Some(location) = info.location() {
+ write(b"at ");
+ write(location.file().as_bytes());
+ write(b" line ");
+ print_dec(location.line());
+ write(b":");
+ print_dec(location.column());
+ write(b"\n");
+ } else {
+ write(b"Unknown location\n");
+ }
+ write(b"\r\n");
+ loop{}
+}
+
+pub fn dec_digit(n: u32) -> u8 {
+ b'0' + (n % 10) as u8
+}
+
+pub fn format_int_dec(n: u32, buf: &mut [u8]) -> usize {
+ if n == 0 {
+ buf[buf.len() - 1] = b'0';
+ return 1;
+ }
+
+ let mut n = n;
+ let mut c = buf.len() - 1;
+ loop {
+ buf[c] = dec_digit(n);
+ n /= 10;
+ if c == 0 || n == 0 {
+ break;
+ }
+ c -= 1;
+ }
+
+ buf.len() - c
+}
+
+pub fn print_dec<T: Into<u32>>(v: T) {
+ let v: u32 = v.into();
+ let mut buf = [0u8; 10];
+
+ let n = format_int_dec(v, &mut buf);
+ write(&buf[10 - n..]);
+}
\ No newline at end of file
+mod usbdev;
+
+use core::cell::RefCell;
+
+use crate::bsp;
+use crate::timer::init_timer;
+use bsp::hal::clocks::init_clocks_and_plls;
+use bsp::hal::gpio;
+use bsp::hal::pac;
+use bsp::hal::timer::CountDown;
+use bsp::hal::watchdog::Watchdog;
+use bsp::hal::Sio;
+use bsp::hal::Timer;
+use bsp::Pins;
+use critical_section::Mutex;
+
+use usbdev::init_usb;
+pub use usbdev::with_usb;
+
+const EXTERNAL_XTAL_FREQ_HZ: u32 = 12_000_000;
+
+#[link_section = ".kgram1"]
+static PERIPHERALS: Mutex<RefCell<Option<Peripherals>>> = Mutex::new(RefCell::new(None));
+
+type LedPin = gpio::Pin<gpio::bank0::Gpio7, gpio::Output<gpio::PushPull>>;
+pub struct Peripherals {
+ watchdog: Watchdog,
+ timer: Timer,
+ led: LedPin,
+}
+
+impl Peripherals {
+ pub fn timer(&mut self) -> &mut Timer {
+ &mut self.timer
+ }
+
+ pub fn led(&mut self) -> &mut LedPin {
+ &mut self.led
+ }
+}
+
+pub fn init_peripherals() {
+ let core = pac::CorePeripherals::take().unwrap();
+ let mut platform = pac::Peripherals::take().unwrap();
+ let mut watchdog = Watchdog::new(platform.WATCHDOG);
+ let clocks = init_clocks_and_plls(
+ EXTERNAL_XTAL_FREQ_HZ,
+ platform.XOSC,
+ platform.CLOCKS,
+ platform.PLL_SYS,
+ platform.PLL_USB,
+ &mut platform.RESETS,
+ &mut watchdog,
+ )
+ .ok()
+ .unwrap();
+
+ let sio = Sio::new(platform.SIO);
+ let pins = Pins::new(
+ platform.IO_BANK0,
+ platform.PADS_BANK0,
+ sio.gpio_bank0,
+ &mut platform.RESETS,
+ );
+ let led = pins.led.into_push_pull_output();
+
+ init_usb(
+ platform.USBCTRL_REGS,
+ platform.USBCTRL_DPRAM,
+ clocks.usb_clock,
+ &mut platform.RESETS,
+ );
+ unsafe {
+ pac::NVIC::unmask(pac::Interrupt::USBCTRL_IRQ);
+ }
+
+ init_timer(core.SYST);
+ let timer = Timer::new(platform.TIMER, &mut platform.RESETS);
+
+ critical_section::with(|cs| {
+ let mut peripherals = PERIPHERALS.borrow_ref_mut(cs);
+ *peripherals = Some(Peripherals {
+ watchdog,
+ timer,
+ led,
+ });
+ })
+}
+
+pub fn with_peripherals<F, R>(mut f: F) -> R where F: FnMut(&mut Peripherals) -> R {
+ critical_section::with(|cs| {
+ let mut peripherals = PERIPHERALS.borrow_ref_mut(cs);
+ if let Some(ref mut peripherals) = *peripherals {
+ f(peripherals)
+ } else {
+ panic!("Peripherals not initialized");
+ }
+ })
+}
+
+pub fn make_count_down() -> CountDown<'static> {
+ with_peripherals(|p| {
+ unsafe {
+ // This is not interrupt safe but it will work for now
+ core::mem::transmute(p.timer.count_down())
+ }
+ })
+}
\ No newline at end of file
+use core::cell::RefCell;
+
+use crate::bsp;
+use bsp::hal::clocks::UsbClock;
+use bsp::hal::usb::UsbBus;
+use bsp::pac::{RESETS, USBCTRL_DPRAM, USBCTRL_REGS, interrupt};
+use critical_section::Mutex;
+use frunk_core::hlist::{HCons, HNil};
+use usb_device::{class_prelude::*, prelude::*};
+use usbd_human_interface_device::device::keyboard::NKROBootKeyboard;
+use usbd_human_interface_device::prelude::*;
+use usbd_serial::SerialPort;
+
+#[link_section = ".kgram1"]
+static mut USB_ALLOCATOR: Option<UsbBusAllocator<UsbBus>> = None;
+#[link_section = ".kgram1"]
+static USB_MANAGER: Mutex<RefCell<Option<UsbManager>>> = Mutex::new(RefCell::new(None));
+
+pub struct UsbManager<'a> {
+ dev: usb_device::device::UsbDevice<'a, UsbBus>,
+ keyboard: UsbHidClass<'a, UsbBus, HCons<NKROBootKeyboard<'a, UsbBus>, HNil>>,
+ serial: SerialPort<'a, UsbBus>,
+}
+
+impl<'a> UsbManager<'a> {
+ pub fn update(&mut self) {
+ match self.keyboard.tick() {
+ Err(UsbHidError::WouldBlock) => {}
+ Ok(_) => {}
+ Err(e) => {
+ core::panic!("Failed to process keyboard tick: {:?}", e)
+ }
+ }
+
+ if self.dev.poll(&mut [&mut self.keyboard, &mut self.serial]) {
+ match self.keyboard.device().read_report() {
+ Err(UsbError::WouldBlock) => {}
+ Err(e) => {
+ core::panic!("Failed to read keyboard report: {:?}", e)
+ }
+ Ok(_leds) => {}
+ }
+ }
+ }
+
+ pub fn keyboard(
+ &mut self,
+ ) -> &mut UsbHidClass<'a, UsbBus, HCons<NKROBootKeyboard<'a, UsbBus>, HNil>> {
+ &mut self.keyboard
+ }
+
+ pub fn serial(&mut self) -> &mut SerialPort<'a, UsbBus> {
+ &mut self.serial
+ }
+}
+
+pub fn init_usb(
+ ctrl_reg: USBCTRL_REGS,
+ ctrl_dpram: USBCTRL_DPRAM,
+ pll: UsbClock,
+ resets: &mut RESETS,
+) {
+ let bus = UsbBus::new(ctrl_reg, ctrl_dpram, pll, true, resets);
+
+ // The Mutex<RefCell<...>> pattern doesn't work here because
+ // the devices need to keep a reference to the allocator. So
+ // we do something a little unsafe.
+ let usballoc = unsafe {
+ USB_ALLOCATOR = Some(UsbBusAllocator::new(bus));
+ USB_ALLOCATOR.as_ref().unwrap()
+ };
+
+ let keyboard = UsbHidClassBuilder::new()
+ .add_device(
+ usbd_human_interface_device::device::keyboard::NKROBootKeyboardConfig::default(),
+ )
+ .build(usballoc);
+
+ let serial = SerialPort::new(usballoc);
+
+ let dev = UsbDeviceBuilder::new(usballoc, UsbVidPid(0x1209, 0x0001))
+ .manufacturer("The Dominion of Awesome")
+ .product("Smorgasboard")
+ .serial_number("LOLBUTTS")
+ .build();
+
+ critical_section::with(|cs| {
+ let mut usb_manager = USB_MANAGER.borrow_ref_mut(cs);
+ *usb_manager = Some(UsbManager {
+ dev,
+ keyboard,
+ serial,
+ })
+ });
+}
+
+pub fn with_usb<F, R>(mut f: F) -> R
+where
+ F: FnMut(&mut UsbManager) -> R,
+{
+ critical_section::with(|cs| {
+ let mut usb_manager = USB_MANAGER.borrow_ref_mut(cs);
+ if let Some(ref mut usb_manager) = *usb_manager {
+ return f(usb_manager);
+ } else {
+ panic!("USB Manager not initialized");
+ }
+ })
+}
+
+#[interrupt]
+fn USBCTRL_IRQ() {
+ with_usb(|u| u.update());
+}
\ No newline at end of file
+use core::cell::RefCell;
+
+use crate::bsp;
+use cortex_m_rt::exception;
+use critical_section::Mutex;
+
+#[link_section = ".kgram1"]
+static TIMER: Mutex<RefCell<Option<Timer>>> = Mutex::new(RefCell::new(None));
+
+type Ticks = u32;
+
+#[derive(Debug)]
+pub enum TimerError {
+ TooManyTimers,
+}
+
+#[derive(Debug, Clone)]
+enum TimerCallbackType {
+ OneShot,
+ Recurring(Ticks),
+}
+
+#[derive(Debug, Clone)]
+struct TimerCallback {
+ t0: Ticks,
+ f: fn(),
+ t_type: TimerCallbackType,
+}
+
+struct Timer {
+ t: Ticks,
+ callbacks: heapless::Vec<TimerCallback, 10>,
+}
+
+impl Timer {
+ fn tick(&mut self) {
+ self.t += 1;
+ }
+
+ pub fn gather_pending(&mut self) -> heapless::Vec<fn(), 10> {
+ let mut pending = heapless::Vec::new();
+ let mut i = 0;
+ while i < self.callbacks.len() {
+ if self.t >= self.callbacks[i].t0 {
+ let f = match self.callbacks[i].t_type {
+ TimerCallbackType::OneShot => {
+ let tc = self.callbacks.swap_remove(i);
+ tc.f
+ }
+ TimerCallbackType::Recurring(d) => {
+ self.callbacks[i].t0 += d;
+ self.callbacks[i].f
+ }
+ };
+ pending.push(f).ok();
+ } else {
+ i += 1;
+ }
+ }
+ pending
+ }
+}
+
+pub fn init_timer(mut systick: bsp::pac::SYST) {
+ critical_section::with(|cs| {
+ systick.set_reload(bsp::pac::SYST::get_ticks_per_10ms() / 10);
+ systick.clear_current();
+ systick.enable_interrupt();
+ systick.enable_counter();
+ let mut timer = TIMER.borrow_ref_mut(cs);
+ *timer = Some(Timer {
+ t: 0,
+ callbacks: heapless::Vec::new(),
+ })
+ })
+}
+
+pub fn schedule(d: Ticks, recurring: bool, f: fn()) -> Result<usize, TimerError> {
+ critical_section::with(|cs| {
+ let mut timer = TIMER.borrow_ref_mut(cs);
+ if let Some(ref mut timer) = *timer {
+ let t_type = if recurring {
+ TimerCallbackType::Recurring(d)
+ } else {
+ TimerCallbackType::OneShot
+ };
+ match timer.callbacks.push(TimerCallback {
+ t0: timer.t + d,
+ f,
+ t_type,
+ }) {
+ Ok(()) => Ok(timer.callbacks.len() - 1),
+ Err(_) => Err(TimerError::TooManyTimers),
+ }
+ } else {
+ panic!("Timer not initialized");
+ }
+ })
+}
+
+#[exception]
+fn SysTick() {
+ let pending = critical_section::with(|cs| {
+ let mut timer = TIMER.borrow_ref_mut(cs);
+ if let Some(ref mut timer) = *timer {
+ timer.tick();
+ timer.gather_pending()
+ } else {
+ panic!("Timer not initialized");
+ }
+ });
+
+ for f in pending {
+ (f)();
+ }
+}