commit:be0e9113b39cb7e1a9ad702392031c79f9911eca
author:Chip
committer:Chip
date:Sat Aug 26 00:11:15 2023 -0500
parents:
Kinda working version?
diff --git a/.cargo/config b/.cargo/config
line changes: +23/-0
index 0000000..a12b9c1
--- /dev/null
+++ b/.cargo/config
@@ -0,0 +1,23 @@
+[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",
+]
+

diff --git a/.gitignore b/.gitignore
line changes: +1/-0
index 0000000..ea8c4bf
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/target

diff --git a/.vscode/launch.json b/.vscode/launch.json
line changes: +25/-0
index 0000000..4eea281
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,25 @@
+{
+    "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"
+            ]
+        }
+    ]
+}

diff --git a/.vscode/settings.json b/.vscode/settings.json
line changes: +7/-0
index 0000000..b682814
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,7 @@
+{
+    "rust-analyzer.checkOnSave.allTargets": false,
+    "rust-analyzer.checkOnSave.arguments": [
+        "--target",
+        "thumbv7m-none-eabi"
+    ]
+} 
\ No newline at end of file

diff --git a/.vscode/tasks.json b/.vscode/tasks.json
line changes: +17/-0
index 0000000..054ef8c
--- /dev/null
+++ b/.vscode/tasks.json
@@ -0,0 +1,17 @@
+{
+    // 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

diff --git a/Cargo.lock b/Cargo.lock
line changes: +629/-0
index 0000000..084812d
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,629 @@
+# 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",
+]

diff --git a/Cargo.toml b/Cargo.toml
line changes: +75/-0
index 0000000..fbb4c1e
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,75 @@
+[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

diff --git a/memory.x b/memory.x
line changes: +42/-0
index 0000000..e6eaa2f
--- /dev/null
+++ b/memory.x
@@ -0,0 +1,42 @@
+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

diff --git a/src/allocator.rs b/src/allocator.rs
line changes: +16/-0
index 0000000..c5ca87c
--- /dev/null
+++ b/src/allocator.rs
@@ -0,0 +1,16 @@
+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

diff --git a/src/console.rs b/src/console.rs
line changes: +66/-0
index 0000000..6c2d1a7
--- /dev/null
+++ b/src/console.rs
@@ -0,0 +1,66 @@
+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

diff --git a/src/main.rs b/src/main.rs
line changes: +64/-0
index 0000000..1d28f0a
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,64 @@
+#![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 {}
+}

diff --git a/src/panic.rs b/src/panic.rs
line changes: +71/-0
index 0000000..c1cbbcf
--- /dev/null
+++ b/src/panic.rs
@@ -0,0 +1,71 @@
+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

diff --git a/src/peripherals.rs b/src/peripherals.rs
line changes: +108/-0
index 0000000..7a2a64d
--- /dev/null
+++ b/src/peripherals.rs
@@ -0,0 +1,108 @@
+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

diff --git a/src/peripherals/usbdev.rs b/src/peripherals/usbdev.rs
line changes: +114/-0
index 0000000..64c5a00
--- /dev/null
+++ b/src/peripherals/usbdev.rs
@@ -0,0 +1,114 @@
+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

diff --git a/src/timer.rs b/src/timer.rs
line changes: +116/-0
index 0000000..2f5d362
--- /dev/null
+++ b/src/timer.rs
@@ -0,0 +1,116 @@
+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)();
+    }
+}