From 541173bfcb929a13d0757a48b354dc3091223193 Mon Sep 17 00:00:00 2001 From: Filipriec Date: Tue, 11 Nov 2025 15:51:37 +0100 Subject: [PATCH] semestralka joinig all worlds together --- semestralka_1/Cargo.lock | 477 ++++++++++++++---- semestralka_1/Cargo.toml | 20 +- semestralka_1/datasheet.txt | 1 - semestralka_1/src/bin/main.rs | 195 +++---- semestralka_1/src/config.rs | 16 + semestralka_1/src/lib.rs | 5 +- semestralka_1/src/safety.rs | 57 --- .../software_uart/.gpio_dma_uart_tx.rs.swp | Bin 0 -> 12288 bytes semestralka_1/src/software_uart/debug.rs | 43 ++ semestralka_1/src/software_uart/dma_timer.rs | 58 +++ .../src/software_uart/gpio_dma_uart_rx.rs | 44 ++ .../src/software_uart/gpio_dma_uart_tx.rs | 75 +++ semestralka_1/src/software_uart/mod.rs | 13 +- semestralka_1/src/software_uart/suart.rs | 19 - .../src/software_uart/uart_emulation.rs | 151 ++++++ semestralka_1/tests/integration.rs | 2 + 16 files changed, 865 insertions(+), 311 deletions(-) delete mode 100644 semestralka_1/datasheet.txt create mode 100644 semestralka_1/src/config.rs delete mode 100644 semestralka_1/src/safety.rs create mode 100644 semestralka_1/src/software_uart/.gpio_dma_uart_tx.rs.swp create mode 100644 semestralka_1/src/software_uart/debug.rs create mode 100644 semestralka_1/src/software_uart/dma_timer.rs create mode 100644 semestralka_1/src/software_uart/gpio_dma_uart_rx.rs create mode 100644 semestralka_1/src/software_uart/gpio_dma_uart_tx.rs delete mode 100644 semestralka_1/src/software_uart/suart.rs create mode 100644 semestralka_1/src/software_uart/uart_emulation.rs diff --git a/semestralka_1/Cargo.lock b/semestralka_1/Cargo.lock index b595c7c..2cf9391 100644 --- a/semestralka_1/Cargo.lock +++ b/semestralka_1/Cargo.lock @@ -14,6 +14,15 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + [[package]] name = "aligned" version = "0.4.2" @@ -32,33 +41,6 @@ dependencies = [ "stable_deref_trait", ] -[[package]] -name = "async_uart" -version = "0.1.0" -dependencies = [ - "cortex-m", - "cortex-m-rt", - "defmt 1.0.1", - "defmt-rtt", - "defmt-test", - "embassy-executor", - "embassy-futures", - "embassy-stm32", - "embassy-sync", - "embassy-time", - "embassy-usb", - "embedded-graphics", - "embedded-hal 1.0.0", - "embedded-io", - "embedded-io-async", - "heapless 0.9.1", - "micromath", - "panic-halt", - "panic-probe", - "static_cell", - "tinybmp", -] - [[package]] name = "autocfg" version = "1.5.0" @@ -125,12 +107,32 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "cc" +version = "1.2.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37521ac7aabe3d13122dc382493e20c9416f299d2ccd5b3a5340a2570cdeb0f3" +dependencies = [ + "find-msvc-tools", + "shlex", +] + [[package]] name = "cfg-if" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "cordyceps" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "688d7fbb8092b8de775ef2536f36c8c31f2bc4006ece2e8d8ad2d17d00ce0a2a" +dependencies = [ + "loom", + "tracing", +] + [[package]] name = "cortex-m" version = "0.7.7" @@ -164,15 +166,6 @@ dependencies = [ "syn 2.0.107", ] -[[package]] -name = "cortex-m-semihosting" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c23234600452033cc77e4b761e740e02d2c4168e11dbf36ab14a0f58973592b0" -dependencies = [ - "cortex-m", -] - [[package]] name = "critical-section" version = "1.2.0" @@ -266,26 +259,28 @@ dependencies = [ ] [[package]] -name = "defmt-test" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24076cc7203c365e7febfcec15d6667a9ef780bd2c5fd3b2a197400df78f299b" +name = "dma_gpio" +version = "0.1.0" dependencies = [ + "cortex-m", "cortex-m-rt", - "cortex-m-semihosting", "defmt 1.0.1", - "defmt-test-macros", -] - -[[package]] -name = "defmt-test-macros" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe5520fd36862f281c026abeaab153ebbc001717c29a9b8e5ba9704d8f3a879d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.107", + "defmt-rtt", + "embassy-executor", + "embassy-futures", + "embassy-hal-internal", + "embassy-stm32", + "embassy-sync", + "embassy-time", + "embassy-usb", + "embedded-graphics", + "embedded-hal 1.0.0", + "heapless 0.9.1", + "micromath", + "panic-halt", + "panic-probe", + "static_cell", + "tinybmp", ] [[package]] @@ -300,8 +295,7 @@ dependencies = [ [[package]] name = "embassy-embedded-hal" version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "554e3e840696f54b4c9afcf28a0f24da431c927f4151040020416e7393d6d0d8" +source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20" dependencies = [ "defmt 1.0.1", "embassy-futures", @@ -319,9 +313,9 @@ dependencies = [ [[package]] name = "embassy-executor" version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06070468370195e0e86f241c8e5004356d696590a678d47d6676795b2e439c6b" +source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20" dependencies = [ + "cordyceps", "cortex-m", "critical-section", "document-features", @@ -332,8 +326,7 @@ dependencies = [ [[package]] name = "embassy-executor-macros" version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfdddc3a04226828316bf31393b6903ee162238576b1584ee2669af215d55472" +source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20" dependencies = [ "darling", "proc-macro2", @@ -344,20 +337,17 @@ dependencies = [ [[package]] name = "embassy-executor-timer-queue" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fc328bf943af66b80b98755db9106bf7e7471b0cf47dc8559cd9a6be504cc9c" +source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20" [[package]] name = "embassy-futures" version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc2d050bdc5c21e0862a89256ed8029ae6c290a93aecefc73084b3002cdebb01" +source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20" [[package]] name = "embassy-hal-internal" version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95285007a91b619dc9f26ea8f55452aa6c60f7115a4edc05085cd2bd3127cd7a" +source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20" dependencies = [ "cortex-m", "critical-section", @@ -368,17 +358,15 @@ dependencies = [ [[package]] name = "embassy-net-driver" version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524eb3c489760508f71360112bca70f6e53173e6fe48fc5f0efd0f5ab217751d" +source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20" dependencies = [ - "defmt 0.3.100", + "defmt 1.0.1", ] [[package]] name = "embassy-net-driver-channel" version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7b2739fbcf6cd206ae08779c7d709087b16577d255f2ea4a45bc4bbbf305b3f" +source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20" dependencies = [ "embassy-futures", "embassy-net-driver", @@ -388,8 +376,7 @@ dependencies = [ [[package]] name = "embassy-stm32" version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d972eab325cc96afee98f80a91ca6b00249b6356dc0fdbff68b70c200df9fae" +source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20" dependencies = [ "aligned", "bit_field", @@ -421,6 +408,7 @@ dependencies = [ "embedded-storage", "embedded-storage-async", "futures-util", + "heapless 0.9.1", "nb 1.1.0", "proc-macro2", "quote", @@ -437,8 +425,7 @@ dependencies = [ [[package]] name = "embassy-sync" version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73974a3edbd0bd286759b3d483540f0ebef705919a5f56f4fc7709066f71689b" +source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20" dependencies = [ "cfg-if", "critical-section", @@ -452,8 +439,7 @@ dependencies = [ [[package]] name = "embassy-time" version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fa65b9284d974dad7a23bb72835c4ec85c0b540d86af7fc4098c88cff51d65" +source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20" dependencies = [ "cfg-if", "critical-section", @@ -469,8 +455,7 @@ dependencies = [ [[package]] name = "embassy-time-driver" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0a244c7dc22c8d0289379c8d8830cae06bb93d8f990194d0de5efb3b5ae7ba6" +source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20" dependencies = [ "document-features", ] @@ -478,8 +463,7 @@ dependencies = [ [[package]] name = "embassy-time-queue-utils" version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e2ee86063bd028a420a5fb5898c18c87a8898026da1d4c852af2c443d0a454" +source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20" dependencies = [ "embassy-executor-timer-queue", "heapless 0.8.0", @@ -488,8 +472,7 @@ dependencies = [ [[package]] name = "embassy-usb" version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4462e48b19a4f401a11901bdd981aab80c6a826608016a0bdc73cbbab31954" +source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20" dependencies = [ "embassy-futures", "embassy-net-driver-channel", @@ -504,8 +487,7 @@ dependencies = [ [[package]] name = "embassy-usb-driver" version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17119855ccc2d1f7470a39756b12068454ae27a3eabb037d940b5c03d9c77b7a" +source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20" dependencies = [ "defmt 1.0.1", "embedded-io-async", @@ -514,8 +496,7 @@ dependencies = [ [[package]] name = "embassy-usb-synopsys-otg" version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "288751f8eaa44a5cf2613f13cee0ca8e06e6638cb96e897e6834702c79084b23" +source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20" dependencies = [ "critical-section", "defmt 1.0.1", @@ -630,6 +611,12 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" +[[package]] +name = "find-msvc-tools" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" + [[package]] name = "float-cmp" version = "0.9.0" @@ -675,6 +662,20 @@ dependencies = [ "pin-utils", ] +[[package]] +name = "generator" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "605183a538e3e2a9c1038635cc5c2d194e2ee8fd0d1b66b8349fad7dbacce5a2" +dependencies = [ + "cc", + "cfg-if", + "libc", + "log", + "rustversion", + "windows", +] + [[package]] name = "hash32" version = "0.3.1" @@ -719,6 +720,18 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.177" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" + [[package]] name = "litrs" version = "0.4.2" @@ -731,6 +744,34 @@ version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +[[package]] +name = "loom" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + [[package]] name = "micromath" version = "2.1.0" @@ -752,6 +793,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -853,6 +903,23 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + [[package]] name = "rustc_version" version = "0.2.3" @@ -862,6 +929,18 @@ dependencies = [ "semver", ] +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "sdio-host" version = "0.9.0" @@ -912,6 +991,27 @@ dependencies = [ "syn 2.0.107", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + [[package]] name = "ssmarshal" version = "1.0.0" @@ -955,8 +1055,7 @@ dependencies = [ [[package]] name = "stm32-metapac" version = "18.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fd8ec3a292a0d9fc4798416a61b21da5ae50341b2e7b8d12e662bf305366097" +source = "git+https://github.com/embassy-rs/stm32-data-generated?tag=stm32-data-b9f6b0c542d85ee695d71c35ced195e0cef51ac0#9b8fb67703361e2237b6c1ec4f1ee5949223d412" dependencies = [ "cortex-m", "cortex-m-rt", @@ -1011,6 +1110,15 @@ dependencies = [ "syn 2.0.107", ] +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + [[package]] name = "tinybmp" version = "0.6.0" @@ -1020,6 +1128,67 @@ dependencies = [ "embedded-graphics", ] +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.107", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + [[package]] name = "unicode-ident" version = "1.0.19" @@ -1073,6 +1242,12 @@ dependencies = [ "usbd-hid-descriptors", ] +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + [[package]] name = "vcell" version = "0.1.3" @@ -1100,6 +1275,132 @@ dependencies = [ "vcell", ] +[[package]] +name = "windows" +version = "0.61.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +dependencies = [ + "windows-collections", + "windows-core", + "windows-future", + "windows-link 0.1.3", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +dependencies = [ + "windows-core", +] + +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.1.3", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core", + "windows-link 0.1.3", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.107", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.107", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core", + "windows-link 0.1.3", +] + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-threading" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link 0.1.3", +] + [[package]] name = "zerocopy" version = "0.8.27" diff --git a/semestralka_1/Cargo.toml b/semestralka_1/Cargo.toml index 4f40948..a13e99c 100644 --- a/semestralka_1/Cargo.toml +++ b/semestralka_1/Cargo.toml @@ -1,6 +1,6 @@ [package] authors = ["Priec "] -name = "async_uart" +name = "dma_gpio" edition = "2024" version = "0.1.0" @@ -10,12 +10,13 @@ cortex-m = { version = "0.7.7", features = ["inline-asm", "critical-section-sing cortex-m-rt = "0.7.5" panic-halt = "1.0.0" -embassy-executor = { version = "0.9.1", features = ["arch-cortex-m", "executor-thread"] } -embassy-futures = "0.1.2" -embassy-stm32 = { version = "0.4.0", features = ["unstable-pac", "stm32u575zi", "time-driver-any", "memory-x", "defmt"] } -embassy-sync = "0.7.2" -embassy-time = { version = "0.5.0", features = ["tick-hz-32_768"] } -embassy-usb = "0.5.1" +embassy-executor = { git = "https://github.com/embassy-rs/embassy.git", branch = "main", features = ["arch-cortex-m", "executor-thread"] } +embassy-futures = { git = "https://github.com/embassy-rs/embassy.git", branch = "main" } +embassy-sync = { git = "https://github.com/embassy-rs/embassy.git", branch = "main" } +embassy-time = { git = "https://github.com/embassy-rs/embassy.git", branch = "main", features = ["tick-hz-32_768"] } +embassy-hal-internal = { git = "https://github.com/embassy-rs/embassy.git", branch = "main" } +embassy-usb = { git = "https://github.com/embassy-rs/embassy.git", branch = "main" } +embassy-stm32 = { git = "https://github.com/embassy-rs/embassy.git", branch = "main", features = ["unstable-pac", "stm32u575zi", "time-driver-tim2", "memory-x", "defmt"] } embedded-hal = "1.0.0" embedded-graphics = "0.8.1" @@ -26,8 +27,3 @@ panic-probe = { version = "1.0.0", features = ["defmt"] } defmt-rtt = "1.1.0" defmt = "1.0.1" static_cell = "2.1.1" -embedded-io-async = "0.6.0" -embedded-io = "0.6.1" - -[dev-dependencies] -defmt-test = "0.4.0" diff --git a/semestralka_1/datasheet.txt b/semestralka_1/datasheet.txt deleted file mode 100644 index fad9635..0000000 --- a/semestralka_1/datasheet.txt +++ /dev/null @@ -1 +0,0 @@ -https://www.ti.com/lit/ug/sprugp1/sprugp1.pdf?ts=1761641486453 diff --git a/semestralka_1/src/bin/main.rs b/semestralka_1/src/bin/main.rs index ac9d619..7db42bc 100644 --- a/semestralka_1/src/bin/main.rs +++ b/semestralka_1/src/bin/main.rs @@ -1,157 +1,92 @@ // src/bin/main.rs - #![no_std] #![no_main] + use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::bind_interrupts; -use embassy_stm32::peripherals; -use embassy_stm32::peripherals::{PA2, PA3}; -use embassy_stm32::gpio::{Input, Output, Pull, Speed, Level}; -use embassy_stm32::Peripherals; -use embassy_stm32::usart::{BufferedInterruptHandler, BufferedUart, Config}; -use embassy_stm32::timer::low_level::Timer as HardwareTimer; -use embassy_stm32::interrupt::{self, typelevel::TIM2 as TIM2_IRQ, Priority}; -use embassy_stm32::peripherals::TIM2; -use embedded_io_async::{Read, Write}; -use embassy_stm32::time::Hertz; -use embassy_time::{Timer, Duration, Instant}; -use embassy_futures::yield_now; -use embassy_futures::select::{select, Either}; -use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; -use embassy_sync::pipe::Pipe; -use embassy_sync::signal::Signal; +use embassy_stm32::dma::Request; +use embassy_stm32::gpio::{Input, Output, Level, Pull, Speed}; +use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, pipe::Pipe}; +use embassy_stm32::dma::{TransferOptions, WritableRingBuffer}; +use dma_gpio::software_uart::{ + dma_timer::{init_tim6_for_uart, init_tim7_for_uart}, + gpio_dma_uart_tx::encode_uart_frames, + gpio_dma_uart_rx::rx_dma_task, + debug::dump_tim6_regs, +}; +use dma_gpio::config::{BAUD, TX_PIN_BIT, RX_OVERSAMPLE, TX_OVERSAMPLE}; +use dma_gpio::config::{TX_RING_BYTES, RX_RING_BYTES, PIPE_RX_SIZE}; use static_cell::StaticCell; +use embassy_futures::yield_now; use {defmt_rtt as _, panic_probe as _}; -use async_uart::safety::{preflight_and_suggest_yield_period, RX_PIPE_CAP, TX_PIPE_CAP}; -static UART_TX: Pipe = Pipe::new(); -static UART_RX: Pipe = Pipe::new(); -static TIM2_TICK: Signal = Signal::new(); +pub const TIM6_UP_REQ: Request = 4; -bind_interrupts!( - struct Irqs { - USART1 => BufferedInterruptHandler; - } -); - -#[embassy_executor::task] -async fn uart_task(mut uart: BufferedUart<'static>) { - let mut rx_byte = [0u8; 1]; - let mut tx_buf = [0u8; 64]; - loop { - // Wait for either RX or TX events. - let rx_fut = uart.read(&mut rx_byte); - let tx_fut = async { - // Until there's outgoing data in TX pipe - let n = UART_TX.read(&mut tx_buf).await; - n - }; - match select(rx_fut, tx_fut).await { - // Incoming data from UART hardware - Either::First(res) => { - if let Ok(_) = res { - // Forward to RX pipe - let _ = UART_RX.write(&rx_byte).await; - let _ = UART_TX.try_write(&rx_byte); - } - } - // Outgoing data waiting in TX pipe - Either::Second(n) => { - unwrap!(uart.write(&tx_buf[..n]).await); - } - } - } -} +static PIPE_RX: Pipe = Pipe::new(); +static TX_RING: StaticCell<[u32; TX_RING_BYTES]> = StaticCell::new(); +static RX_RING: StaticCell<[u8; RX_RING_BYTES]> = StaticCell::new(); #[embassy_executor::main] async fn main(spawner: Spawner) { - info!("tititititi"); let p = embassy_stm32::init(Default::default()); - static TX_BUF: StaticCell<[u8; 256]> = StaticCell::new(); - static RX_BUF: StaticCell<[u8; 256]> = StaticCell::new(); - let tx_buf = TX_BUF.init([0; 256]); - let rx_buf = RX_BUF.init([0; 256]); - let mut cfg = Config::default(); - cfg.baudrate = 230_400; + info!("Hehe"); - // Call preflight and get the computed yield period - let yield_period = preflight_and_suggest_yield_period(cfg.baudrate); - - let usart = BufferedUart::new( - p.USART1, - p.PA10, // RX - p.PA9, // TX - tx_buf, - rx_buf, - Irqs, - cfg, - ).unwrap(); - info!("starting uart task"); - spawner.spawn(uart_task(usart)).unwrap(); - - let mut transfer: u32 = 16; - let mut rx_buf = [0u8; 64]; - let mut last_yield = Instant::now(); - - // Software UART bits init - let mut tx = Output::new(p.PA2, Level::Low, Speed::Low); let _rx = Input::new(p.PA3, Pull::Up); + let _tx = Output::new(p.PA2, Level::High, Speed::VeryHigh); - let tim = HardwareTimer::new(p.TIM2); + init_tim6_for_uart(p.TIM6, BAUD, TX_OVERSAMPLE); + init_tim7_for_uart(p.TIM7, BAUD, RX_OVERSAMPLE); - // Configure for 230_400 Hz - tim.set_frequency(Hertz(cfg.baudrate*transfer)); - tim.enable_update_interrupt(true); - tim.start(); + dump_tim6_regs(); - tx.set_high(); - loop { + // Safe one-time init from StaticCell + let rx_ring: &mut [u8; RX_RING_BYTES] = RX_RING.init([0; RX_RING_BYTES]); + let tx_ring_mem: &mut [u32; TX_RING_BYTES] = TX_RING.init([0; TX_RING_BYTES]); - TIM2_TICK.wait().await; - tx.set_low(); - TIM2_TICK.wait().await; + // Spawn tasks + spawner.spawn(rx_dma_task(p.GPDMA1_CH1, &PIPE_RX, rx_ring).unwrap()); - Timer::after(Duration::from_millis(1000)).await; - // Poll RX pipe for new data (non-blocking) - if let Ok(n) = UART_RX.try_read(&mut rx_buf) { - if n > 0 { - if let Ok(s) = core::str::from_utf8(&rx_buf[..n]) { - info!("RX got: {}", s); - } else { - info!("RX got (non‑utf8): {:?}", &rx_buf[..n]); - } - } - } + // Create and start the TX DMA ring in main. + // let bsrr_ptr = embassy_stm32::pac::GPIOA.bsrr().as_ptr() as *mut u32; + let odr_ptr = embassy_stm32::pac::GPIOA.odr().as_ptr() as *mut u32; + let mut tx_opts = TransferOptions::default(); + tx_opts.half_transfer_ir = true; + tx_opts.complete_transfer_ir = true; - // Guaranteed to yield before ISR RX buffer can overflow - if Instant::now().duration_since(last_yield) >= yield_period { - yield_now().await; - last_yield = Instant::now(); - // info!("Yield mf {}", counter); - } - // Timer::after(Duration::from_micros(1)).await; - // Timer::after(Duration::from_secs(5)).await; - } -} - -#[embassy_stm32::interrupt] -fn TIM2() { - use embassy_stm32::timer::CoreInstance; - - // Access TIM2 core registers directly. - let regs = unsafe { - embassy_stm32::pac::timer::TimCore::from_ptr( - ::regs(), + // SAFETY: tx_ring_mem is exclusive + let mut tx_ring = unsafe { + WritableRingBuffer::new( + p.GPDMA1_CH0, + TIM6_UP_REQ, + odr_ptr, + tx_ring_mem, + tx_opts, ) }; + // Start DMA + tx_ring.start(); + info!("TX DMA ring started"); - // Clear update flag to avoid retriggering. - let sr = regs.sr().read(); - if sr.uif() { - regs.sr().modify(|r| r.set_uif(false)); + let mut frame_buf = [0u32; 4096]; - // Signal the waiting task that a tick occurred. - TIM2_TICK.signal(()); + loop { + info!("tick start"); + // Timer::after(Duration::from_millis(100)).await; + // info!("tick end"); + let used = encode_uart_frames( + TX_PIN_BIT, + b"Hello marshmallow\r\n", + &mut frame_buf, + ) + .await; + + if used == 0 { + info!("encode_uart_frames() produced 0 words, skipping write"); + yield_now().await; + continue; + } + let _ = tx_ring.write_exact(&frame_buf[..used]).await; + info!("text"); + yield_now().await; } } diff --git a/semestralka_1/src/config.rs b/semestralka_1/src/config.rs new file mode 100644 index 0000000..048e9f5 --- /dev/null +++ b/semestralka_1/src/config.rs @@ -0,0 +1,16 @@ +// src/config.rs +use crate::software_uart::uart_emulation::{Parity, StopBits, UartConfig}; + +pub const BAUD: u32 = 115_200; +pub const TX_PIN_BIT: u8 = 2; // PA2 +pub const TX_OVERSAMPLE: u16 = 1; +pub const RX_OVERSAMPLE: u16 = 16; +pub const RX_RING_BYTES: usize = 4096; +pub const TX_RING_BYTES: usize = 4096; +pub const PIPE_RX_SIZE: usize = 256; + +pub const UART_CFG: UartConfig = UartConfig { + data_bits: 8, + parity: Parity::None, + stop_bits: StopBits::One, +}; diff --git a/semestralka_1/src/lib.rs b/semestralka_1/src/lib.rs index 44115bb..9123142 100644 --- a/semestralka_1/src/lib.rs +++ b/semestralka_1/src/lib.rs @@ -1,3 +1,4 @@ #![no_std] -pub mod safety; -// pub mod software_uart; + +pub mod software_uart; +pub mod config; diff --git a/semestralka_1/src/safety.rs b/semestralka_1/src/safety.rs deleted file mode 100644 index ad12a1d..0000000 --- a/semestralka_1/src/safety.rs +++ /dev/null @@ -1,57 +0,0 @@ -// src/safety.rs -use defmt::info; -use embassy_time::Duration; - -// ISR RX ring capacity = RX_BUF len -const ISR_RX_BUF_CAP: usize = 256; -// Yield 1/2 the time it takes to fill ISR RX ring. -const YIELD_MARGIN_NUM: u32 = 1; -const YIELD_MARGIN_DEN: u32 = 2; -// Ensure RX_PIPE_CAP can hold this. -const WORST_MAIN_LATENCY_MS: u32 = 20; - -pub const TX_PIPE_CAP: usize = 1024; -pub const RX_PIPE_CAP: usize = 1024; - - - -/// Perform safety checks and compute yield timing to avoid buffer overflow. -/// -/// # Panics -/// Panics if pipe capacities are too small for the configured baud. -pub fn preflight_and_suggest_yield_period(baud: u32) -> Duration { - // Approx bytes per second for 8N1 (10 bits per byte on the wire) - let bytes_per_sec = (baud / 10).max(1); - - // Time until ISR RX ring fills, in microseconds. - let t_fill_us = (ISR_RX_BUF_CAP as u64) * 1_000_000u64 / (bytes_per_sec as u64); - - // Choose a yield period as a fraction of t_fill. - let yield_us = (t_fill_us as u64) - .saturating_mul(YIELD_MARGIN_NUM as u64) - / (YIELD_MARGIN_DEN as u64); - - // Verify RX pipe can absorb a worst-case app latency so uart_task - // can always forward without dropping when it runs. - let required_rx_pipe = (bytes_per_sec as u64) * (WORST_MAIN_LATENCY_MS as u64) / 1000; - - if (RX_PIPE_CAP as u64) < required_rx_pipe { - core::panic!( - "RX pipe too small: have {}B, need >= {}B for {}ms at {} bps", - RX_PIPE_CAP, required_rx_pipe, WORST_MAIN_LATENCY_MS, baud - ); - } - - info!( - "Preflight: baud={}, rx_isr={}B, rx_pipe={}B, bytes/s={}, t_fill_us={}, yield_us={}", - baud, - ISR_RX_BUF_CAP, - RX_PIPE_CAP, - bytes_per_sec, - t_fill_us, - yield_us - ); - - // Never choose zero. - Duration::from_micros(yield_us.max(1) as u64) -} diff --git a/semestralka_1/src/software_uart/.gpio_dma_uart_tx.rs.swp b/semestralka_1/src/software_uart/.gpio_dma_uart_tx.rs.swp new file mode 100644 index 0000000000000000000000000000000000000000..51c04ac5c957b35e8a303778d03206b2f6c14c5c GIT binary patch literal 12288 zcmeI2O^g&p6vqop1V2y$2Tz(}iOZ~xGrJ4fKrc&NmIYQ>8HNEN%ciaAsotq>JMfImX9l>I{8h{)W@rO|9bBw zo2~Zv`GrM#s5U|H>?GuiQ@e$H|2(;IYb!~l)Ta4CPbB(MJ!la6>s=Z0dYlOE)sIOp z4SA#$e#@1Fg`tR6>S-kEN{9O=-6U1Iu6W3mPFS$Y+=;qMytV7SGm~A}7PVEq@z~iXE4zho8V%&JPcVrLUz3bfL=%n?@Dqt0`3RnfK0#*U5 zfK|XMU=_HB0y^G8uA*;i(f?-g-g3vg_-S8O0jq#jz$#!BunJfOtO8a6tAJI&Dqt0` z3Os@eunr;DpCsg;ZP+~i|6l(7|LgOFd-`@3>;!*3O~{|%d+-U+K!Ky+=2L|H0=@!Yf)Bw5;3{|rxZu`yLjDCe!N*_?c;F(q z0A2zwg00{dG&8#WZM3tGRlq7>6|f3e1s(|n)(ORvf0}P=f(IQplD*1UjrEw&(}b9I z^8{Q|m(EaJvFjy5bC>s-rz@jAF79!+o%&0)TB>+w`R=KM1&kq2Mp{HEpC;y4`E0Uu z*=61$^5ve&2#-A3$#4F-*}|$aMsa(vlX|>E$7xR{9aW`jRm3qa6Vhy_BV&W5gip;T z>C6m9Um5l;@1UEk(YoL^7T$7?F0`t&J#vxrP|egT)xujXw-!hlm)kKy4_SifOXKPO$!U6E{Ls{LaV7(6#};R4V!TxvHzIkb zG>VhTS}KMArD5HN#WYgP=kyAF8;8l-0dK;>(bV^O;y4lSRlIJMwiXtr+;a`LIe(@~ zWhZfCom3G4u2~K(u~uVrJy*A0r)Ou6&$li*SDXi{_#6($A21qul%L4zNBTB!_NK9=NhEB&?$VfR(hx;rIw2@&9BAak3 zTyW^NJ>L7vEDGwCl zCR@_;HKei(T@?tA7xm@X^xz$# zc6Z4-ypJ8JkSrikZ&e;SMJhYA$=^+Js~XN6KsCXcQO^XG;|$%cb{uoV+T~#yAX;SP zI2+d~wVb}s{4D-OXiAERgm$$Er(EcjUDh6&h)w!p#c{5n)Sf;+-#k0J*f=$h3bdi} zmgj_mldXxo4z;oD%iIxR1BlB-3!f?OIP{)Zy438W5+^n}9NN*KY&PD$7 zzT+gU=QwkymBM4eS?(D@nyj~IdZ$TI15Ihj3k5Pv#9gFWfNczFMBWKm;AwFP@Nu|c lRW~Wg>($KT(!uP0JWLEV@;>)cEupokEYm18^x>|{{|~HQ;hF#d literal 0 HcmV?d00001 diff --git a/semestralka_1/src/software_uart/debug.rs b/semestralka_1/src/software_uart/debug.rs new file mode 100644 index 0000000..ae6a256 --- /dev/null +++ b/semestralka_1/src/software_uart/debug.rs @@ -0,0 +1,43 @@ +// src/software_uart/debug.rs +use defmt::info; + +pub fn dump_tim6_regs() { + use embassy_stm32::pac::timer::TimBasic; + let tim = unsafe { TimBasic::from_ptr(0x4000_1000usize as _) }; + let sr = tim.sr().read(); + let dier = tim.dier().read(); + let cr1 = tim.cr1().read(); + let arr = tim.arr().read().arr(); + let psc = tim.psc().read(); + info!( + "TIM6: CR1.CEN={} DIER.UDE={} SR.UIF={} PSC={} ARR={}", + cr1.cen(), + dier.ude(), + sr.uif(), + psc, + arr + ); +} + +pub fn dump_dma_ch0_regs() { + use embassy_stm32::pac::gpdma::Gpdma; + let dma = unsafe { Gpdma::from_ptr(0x4002_0000usize as _) }; + let ch = dma.ch(0); + let cr = ch.cr().read(); + let tr1 = ch.tr1().read(); + let tr2 = ch.tr2().read(); + let br1 = ch.br1().read(); + info!( + "GPDMA1_CH0: EN={} PRIO={} SDW={} DDW={} SINC={} DINC={} REQSEL={} SWREQ={} DREQ={} BNDT={}", + cr.en(), + cr.prio(), + tr1.sdw(), + tr1.ddw(), + tr1.sinc(), + tr1.dinc(), + tr2.reqsel(), + tr2.swreq(), + tr2.dreq(), + br1.bndt() + ); +} diff --git a/semestralka_1/src/software_uart/dma_timer.rs b/semestralka_1/src/software_uart/dma_timer.rs new file mode 100644 index 0000000..6979383 --- /dev/null +++ b/semestralka_1/src/software_uart/dma_timer.rs @@ -0,0 +1,58 @@ +// src/dma_timer.rs + +use embassy_stm32::{ + peripherals::{TIM6, TIM7}, + rcc, + timer::low_level::Timer, + Peri, +}; +use core::mem; +use embassy_stm32::timer::BasicInstance; +use embassy_stm32::pac::timer::vals::Urs; + +/// Initializes TIM6 to tick at `baud * oversample` frequency. +/// Each TIM6 update event triggers one DMA beat. +pub fn init_tim6_for_uart<'d>(tim6: Peri<'d, TIM6>, baud: u32, oversample: u16) { + rcc::enable_and_reset::(); + let ll = Timer::new(tim6); + configure_basic_timer(&ll, baud, oversample); + mem::forget(ll); +} + +/// Initializes TIM7 to tick at `baud * oversample` frequency. +/// Each TIM7 update event triggers one DMA beat. +pub fn init_tim7_for_uart<'d>(tim7: Peri<'d, TIM7>, baud: u32, oversample: u16) { + rcc::enable_and_reset::(); + let ll = Timer::new(tim7); + configure_basic_timer(&ll, baud, oversample); + mem::forget(ll); +} + +// Shared internal helper — identical CR1/ARR setup +fn configure_basic_timer(ll: &Timer<'_, T>, baud: u32, oversample: u16) { + let f_timer = rcc::frequency::().0; + let target = baud.saturating_mul(oversample.max(1) as u32).max(1); + + // Compute ARR (prescaler = 0) + let mut arr = (f_timer / target).saturating_sub(1) as u16; + if arr == 0 { arr = 1; } + + ll.regs_basic().cr1().write(|w| { + w.set_cen(false); + w.set_opm(false); + w.set_udis(false); + w.set_urs(Urs::ANY_EVENT); + }); + + ll.regs_basic().psc().write_value(0u16); + ll.regs_basic().arr().write(|w| w.set_arr(arr)); + ll.regs_basic().dier().modify(|w| w.set_ude(true)); + ll.regs_basic().egr().write(|w| w.set_ug(true)); + + ll.regs_basic().cr1().write(|w| { + w.set_opm(false); + w.set_cen(true); + w.set_udis(false); + w.set_urs(Urs::ANY_EVENT); + }); +} diff --git a/semestralka_1/src/software_uart/gpio_dma_uart_rx.rs b/semestralka_1/src/software_uart/gpio_dma_uart_rx.rs new file mode 100644 index 0000000..b8170cc --- /dev/null +++ b/semestralka_1/src/software_uart/gpio_dma_uart_rx.rs @@ -0,0 +1,44 @@ +// src/software_uart/runtime.rs +use embassy_executor::task; +use embassy_stm32::{ + dma::Request, + peripherals::GPDMA1_CH1, + Peri, +}; +use embassy_stm32::dma::{ + ReadableRingBuffer, + TransferOptions, +}; +use crate::config::{RX_OVERSAMPLE, UART_CFG}; +use crate::software_uart::decode_uart_samples; +use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, pipe::Pipe}; +use embassy_futures::yield_now; + +// datasheet tabulka 137 +pub const TIM7_UP_REQ: Request = 5; + +/// RX DMA task: reads GPIO samples paced by TIM7 and fills PIPE_RX +#[task] +pub async fn rx_dma_task( + ch: Peri<'static, GPDMA1_CH1>, + pipe_rx: &'static Pipe, + ring: &'static mut [u8], +) { + let gpioa_idr = embassy_stm32::pac::GPIOA.idr().as_ptr() as *mut u8; + + let mut opts = TransferOptions::default(); + opts.half_transfer_ir = true; + opts.complete_transfer_ir = true; + + // SAFETY: ring is exclusive to this task + let mut rx = unsafe { ReadableRingBuffer::new(ch, TIM7_UP_REQ, gpioa_idr, ring, opts) }; + rx.start(); + + let mut chunk = [0u8; 256]; + loop { + let _ = rx.read_exact(&mut chunk).await; + let decoded = decode_uart_samples(&chunk, RX_OVERSAMPLE, &UART_CFG); + pipe_rx.write(&decoded).await; + yield_now().await; + } +} diff --git a/semestralka_1/src/software_uart/gpio_dma_uart_tx.rs b/semestralka_1/src/software_uart/gpio_dma_uart_tx.rs new file mode 100644 index 0000000..aaf37de --- /dev/null +++ b/semestralka_1/src/software_uart/gpio_dma_uart_tx.rs @@ -0,0 +1,75 @@ +// src/software_uart/gpio_dma_uart_tx.rs +use embassy_executor::task; +use embassy_stm32::{ + dma::{Request, TransferOptions, WritableRingBuffer}, + peripherals::GPDMA1_CH0, + Peri, +}; +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +use embassy_sync::pipe::Pipe; +use embassy_futures::yield_now; +use defmt::info; + +use crate::config::{TX_OVERSAMPLE, TX_PIN_BIT, UART_CFG}; +use crate::software_uart::dma_timer::init_tim6_for_uart; +use crate::software_uart::uart_emulation::encode_uart_byte_cfg; + +pub const TIM6_UP_REQ: Request = 4; + +pub async fn encode_uart_frames<'a>( + pin_bit: u8, + bytes: &[u8], + out_buf: &'a mut [u32], +) -> usize { + let mut offset = 0; + for &b in bytes { + let mut frame = [0u32; 12]; + let used = encode_uart_byte_cfg(pin_bit, b, &UART_CFG, &mut frame); + + if offset + used <= out_buf.len() { + out_buf[offset..offset + used].copy_from_slice(&frame[..used]); + offset += used; + } else { + break; + } + + // cooperative async yield + yield_now().await; + } + offset +} + +/// TX DMA task: encodes UART frames and sends them via DMA at TIM6 rate +#[task] +pub async fn tx_dma_task( + ch: Peri<'static, GPDMA1_CH0>, + odr_ptr: *mut u32, + tx_ring: &'static mut [u32], +) { + let mut opts = TransferOptions::default(); + opts.half_transfer_ir = true; + opts.complete_transfer_ir = true; + + // SAFETY: tx_ring is exclusive to this task + let mut tx = unsafe { WritableRingBuffer::new(ch, TIM6_UP_REQ, odr_ptr, tx_ring, opts) }; + tx.start(); + info!("TX DMA ring started"); + + let mut frame_buf = [0u32; 4096]; + + loop { + info!("TX task tick"); + + let used = encode_uart_frames(TX_PIN_BIT, b"Hello marshmallow\r\n", &mut frame_buf).await; + + if used == 0 { + info!("encode_uart_frames() produced 0 words, skipping write"); + yield_now().await; + continue; + } + + let _ = tx.write_exact(&frame_buf[..used]).await; + + yield_now().await; + } +} diff --git a/semestralka_1/src/software_uart/mod.rs b/semestralka_1/src/software_uart/mod.rs index 0be64c0..3ecae27 100644 --- a/semestralka_1/src/software_uart/mod.rs +++ b/semestralka_1/src/software_uart/mod.rs @@ -1,4 +1,13 @@ // src/software_uart/mod.rs -pub mod suart; -pub use suart::*; +pub mod gpio_dma_uart_tx; +pub mod gpio_dma_uart_rx; +pub mod dma_timer; +pub mod uart_emulation; +pub mod debug; + +pub use gpio_dma_uart_tx::*; +pub use gpio_dma_uart_rx::*; +pub use dma_timer::*; +pub use uart_emulation::*; +pub use debug::*; diff --git a/semestralka_1/src/software_uart/suart.rs b/semestralka_1/src/software_uart/suart.rs deleted file mode 100644 index a733b32..0000000 --- a/semestralka_1/src/software_uart/suart.rs +++ /dev/null @@ -1,19 +0,0 @@ -// src/software_uart/suart.rs - -use embassy_stm32::peripherals::{PA2, PA3}; -use embassy_stm32::gpio::{Input, Output, Pull, Speed, Level}; -use embassy_stm32::Peripherals; -use embassy_time::Timer; - -pub async fn suart_test(mut tx_pin: PA2, rx_pin: PA3) { - let mut tx = Output::new(tx_pin.into(), Level::Low, Speed::Low); - let _rx = Input::new(rx_pin.into(), Pull::Up); - - loop { - tx.set_high(); - Timer::after_millis(500).await; - - tx.set_low(); - Timer::after_millis(500).await; - } -} diff --git a/semestralka_1/src/software_uart/uart_emulation.rs b/semestralka_1/src/software_uart/uart_emulation.rs new file mode 100644 index 0000000..8d677e5 --- /dev/null +++ b/semestralka_1/src/software_uart/uart_emulation.rs @@ -0,0 +1,151 @@ +// src/software_uart/uart_emulation.rs +use heapless::Vec; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Parity { + None, + Even, + Odd, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum StopBits { + One, + Two, +} + +#[derive(Clone, Copy, Debug)] +pub struct UartConfig { + pub data_bits: u8, + pub parity: Parity, + pub stop_bits: StopBits, +} + +impl Default for UartConfig { + fn default() -> Self { + Self { + data_bits: 8, + parity: Parity::None, + stop_bits: StopBits::One, + } + } +} + +/// Encodes one byte into a sequence of GPIO BSRR words +pub fn encode_uart_byte_cfg( + pin_bit: u8, + data: u8, + cfg: &UartConfig, + out: &mut [u32; 12], +) -> usize { + // GPIOx_BSRR register str. 636 kap. 13.4.7 + let set_high = |bit: u8| -> u32 { 1u32 << bit }; + let set_low = |bit: u8| -> u32 { 0 }; + // let set_low = |bit: u8| -> u32 { 1u32 << (bit as u32 + 16) }; + + let mut idx = 0usize; + + // START bit (LOW) + out[idx] = set_low(pin_bit); + idx += 1; + + // Data bits, LSB-first + let nbits = cfg.data_bits.clamp(5, 8); + for i in 0..nbits { + let one = ((data >> i) & 1) != 0; + out[idx] = if one { set_high(pin_bit) } else { set_low(pin_bit) }; + idx += 1; + } + + // Parity + match cfg.parity { + Parity::None => {} + Parity::Even | Parity::Odd => { + let mask: u8 = if nbits == 8 { 0xFF } else { (1u16 << nbits) as u8 - 1 }; + let ones = (data & mask).count_ones() & 1; + let par_bit_is_one = match cfg.parity { + Parity::Even => ones == 1, + Parity::Odd => ones == 0, + _ => false, + }; + out[idx] = if par_bit_is_one { + set_high(pin_bit) + } else { + set_low(pin_bit) + }; + idx += 1; + } + } + + // STOP bits (HIGH) + let stop_ticks = match cfg.stop_bits { + StopBits::One => 1usize, + StopBits::Two => 2usize, + }; + for _ in 0..stop_ticks { + out[idx] = set_high(pin_bit); + idx += 1; + } + + idx +} + +/// Decode an oversampled stream of logic levels into UART bytes. +pub fn decode_uart_samples( + samples: &[u8], + oversample: u16, + cfg: &UartConfig, +) -> heapless::Vec { + + let mut out = Vec::::new(); + let mut idx = 0usize; + let nbits = cfg.data_bits as usize; + + while idx + (oversample as usize * (nbits + 3)) < samples.len() { + // Wait for start bit (falling edge: high -> low) + if samples[idx] != 0 && samples[idx + 1] == 0 { + // Align to middle of start bit + idx += (oversample / 2) as usize; + + // Sanity check start bit really low + if samples.get(idx).copied().unwrap_or(1) != 0 { + idx += 1; + continue; + } + + // Sample data bits + let mut data: u8 = 0; + for bit in 0..nbits { + idx += oversample as usize; + let bit_val = samples + .get(idx) + .map(|&b| if b != 0 { 1u8 } else { 0u8 }) + .unwrap_or(1); + data |= bit_val << bit; + } + + // Parity: skip / verify + match cfg.parity { + Parity::None => {} + Parity::Even | Parity::Odd => { + idx += oversample as usize; + // You can optionally add parity check here if needed + } + } + + // Move past stop bits + let stop_skip = match cfg.stop_bits { + StopBits::One => oversample as usize, + StopBits::Two => (oversample * 2) as usize, + }; + idx += stop_skip; + + // Push decoded byte + let _ = out.push(data); + } else { + idx += 1; + } + } + + out +} diff --git a/semestralka_1/tests/integration.rs b/semestralka_1/tests/integration.rs index ee17e36..1f33de6 100644 --- a/semestralka_1/tests/integration.rs +++ b/semestralka_1/tests/integration.rs @@ -1,6 +1,8 @@ #![no_std] #![no_main] +use stm32u5_blinky as _; // memory layout + panic handler + // See https://crates.io/crates/defmt-test/0.3.0 for more documentation (e.g. about the 'state' // feature) #[defmt_test::tests]