From f8fe672cb959b2b3346dfcb9c77810560fd2bb6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E7=9D=BF?= Date: Sun, 2 Nov 2025 14:04:26 +0800 Subject: [PATCH 1/9] Bump version to 0.3.0 and update dependencies - Updated version in Cargo.toml from 0.2.4 to 0.3.0. - Changed rdif-serial dependency to a local path. - Refactored `write_reg` method in `Kind` trait and its implementations to take `&self` instead of `&mut self`. - Updated `Ns16550` struct to include IRQ, TX, and RX handlers. - Implemented `InterfaceRaw` for `Ns16550` to manage IRQ and data transmission. - Added `Pl011Sender`, `Pl011Reciever`, and `Pl011IrqHandler` structs with appropriate methods for handling UART operations. - Removed unused methods and cleaned up code for better readability and maintainability. --- .vscode/settings.json | 3 +- Cargo.lock | 208 +++++++--------- Cargo.toml | 8 +- src/ns16550/mmio.rs | 14 +- src/ns16550/mod.rs | 556 ++++++++++++++++++++---------------------- src/ns16550/pio.rs | 10 +- src/pl011.rs | 242 ++++++++++++------ 7 files changed, 545 insertions(+), 496 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 1cca68b..7a44704 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,5 @@ { "rust-analyzer.cargo.allTargets": false, - "rust-analyzer.cargo.target": "x86_64-unknown-none" + "rust-analyzer.cargo.target": "aarch64-unknown-none-softfloat" + // "rust-analyzer.cargo.target": "x86_64-unknown-none" } \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 4170ddf..1d5e13b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,7 +18,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52dad5cf7342926ce1c375ec680834e56dd3cdbe8b7adf8a6f99b2854cc52c17" dependencies = [ "aarch64-cpu", - "tock-registers 0.10.0", + "tock-registers 0.10.1", ] [[package]] @@ -278,9 +278,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.41" +version = "1.2.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac9fe6cdbb24b6ade63616c0a0688e45bb56732262c158df3c0c4bea4ca47cb7" +checksum = "37521ac7aabe3d13122dc382493e20c9416f299d2ccd5b3a5340a2570cdeb0f3" dependencies = [ "find-msvc-tools", "shlex", @@ -374,9 +374,9 @@ dependencies = [ [[package]] name = "dma-api" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bef2303b0bbacb23e7e1990fb31bed5cb46bc67aa4f307c03117b81bdee4d9f" +checksum = "3816a852c6c71653e1941cfe22f215eca41c14fd45ec9b32c0fa82fe57fe0989" dependencies = [ "aarch64-cpu-ext", "cfg-if", @@ -480,9 +480,9 @@ checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" [[package]] name = "flate2" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc5a4e564e38c699f2880d3fda590bedc2e69f3f84cd48b457bd892ce61d0aa9" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" dependencies = [ "crc32fast", "miniz_oxide", @@ -890,9 +890,9 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" dependencies = [ "displaydoc", "potential_utf", @@ -903,9 +903,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" dependencies = [ "displaydoc", "litemap", @@ -916,11 +916,10 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", @@ -931,42 +930,38 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", - "potential_utf", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" [[package]] name = "icu_provider" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" dependencies = [ "displaydoc", "icu_locale_core", - "stable_deref_trait", - "tinystr", "writeable", "yoke", "zerofrom", @@ -1003,9 +998,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.11.4" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" dependencies = [ "equivalent", "hashbrown", @@ -1035,9 +1030,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "js-sys" -version = "0.3.81" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" +checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" dependencies = [ "once_cell", "wasm-bindgen", @@ -1130,9 +1125,9 @@ checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "litemap" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "lock_api" @@ -1185,13 +1180,13 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" dependencies = [ "libc", "wasi", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1440,9 +1435,9 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "potential_utf" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" dependencies = [ "zerovec", ] @@ -1468,9 +1463,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.101" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] @@ -1528,6 +1523,17 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "rdif-base" +version = "0.7.0" +dependencies = [ + "as-any", + "async-trait", + "paste", + "rdif-def", + "thiserror 2.0.17", +] + [[package]] name = "rdif-base" version = "0.7.0" @@ -1557,7 +1563,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "170ec813e6cf4d1e5fa53fa8fed0fadc7aaab96683d4f1d44c602a6109931eb4" dependencies = [ "cfg-if", - "rdif-base", + "rdif-base 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "thiserror 2.0.17", ] @@ -1568,7 +1574,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60c6e8dea6d432b2c03bc3f4238dc59a276aacac6f688a937351e7a313918738" dependencies = [ "pci_types", - "rdif-base", + "rdif-base 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "thiserror 2.0.17", ] @@ -1578,19 +1584,16 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7b6eefca0d1b44a5bef1e934d8ab2c8e00e19dd3d9e071855c0933637ee17a0" dependencies = [ - "rdif-base", + "rdif-base 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rdif-serial" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d68d515cc651b11ef2c323914f64627c5341af83049881f567f9879ec3b86b8f" +version = "0.6.0" dependencies = [ "bitflags 2.10.0", "futures", - "mbarrier", - "rdif-base", + "rdif-base 0.7.0", "spin 0.10.0", "thiserror 2.0.17", ] @@ -1601,7 +1604,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e11da4f362ab6cdcdee9d8e795faabd0f15e04167cb17939fd3aca19c2ef3421" dependencies = [ - "rdif-base", + "rdif-base 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1614,7 +1617,7 @@ dependencies = [ "log", "paste", "pcie", - "rdif-base", + "rdif-base 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "rdif-pcie", "rdrive-macros", "spin 0.10.0", @@ -1798,9 +1801,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.32" +version = "0.23.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd3c25631629d034ce7cd9940adc9d45762d46de2b0f57193c4443b92c6d4d40" +checksum = "6a9586e9ee2b4f8fab52a0048ca7334d7024eef48e2cb9407e3497bb7cab7fa7" dependencies = [ "once_cell", "rustls-pki-types", @@ -1820,18 +1823,18 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "94182ad936a0c91c324cd46c6511b9510ed16af436d7b5bab34beab0afd55f7a" dependencies = [ "zeroize", ] [[package]] name = "rustls-webpki" -version = "0.103.7" +version = "0.103.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10b3f4191e8a80e6b43eebabfac91e5dcecebb27a71f04e820c47ec41d314bf" +checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" dependencies = [ "ring", "rustls-pki-types", @@ -2057,7 +2060,7 @@ dependencies = [ [[package]] name = "some-serial" -version = "0.2.4" +version = "0.3.0" dependencies = [ "bare-test", "bare-test-macros", @@ -2066,11 +2069,10 @@ dependencies = [ "heapless 0.9.1", "log", "mbarrier", - "rdif-base", "rdif-serial", "spin 0.10.0", "thiserror 2.0.17", - "tock-registers 0.10.0", + "tock-registers 0.10.1", "x86", ] @@ -2216,9 +2218,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.106" +version = "2.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917" dependencies = [ "proc-macro2", "quote", @@ -2359,9 +2361,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" dependencies = [ "displaydoc", "zerovec", @@ -2375,9 +2377,9 @@ checksum = "2b9e2fdb3a1e862c0661768b7ed25390811df1947a8acbfbefe09b47078d93c4" [[package]] name = "tock-registers" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0293f99756f16ff352cc78c99673766a305bdb5ed7652e78df649e9967c885a" +checksum = "8d2d250f87fb3fb6f225c907cf54381509f47b40b74b1d1f12d2dccbc915bdfe" [[package]] name = "tokio" @@ -2611,9 +2613,9 @@ checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" [[package]] name = "unicode-ident" -version = "1.0.19" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-segmentation" @@ -2695,9 +2697,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" +checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" dependencies = [ "cfg-if", "once_cell", @@ -2706,25 +2708,11 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - [[package]] name = "wasm-bindgen-futures" -version = "0.4.54" +version = "0.4.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e038d41e478cc73bae0ff9b36c60cff1c98b8f38f8d7e8061e79ee63608ac5c" +checksum = "551f88106c6d5e7ccc7cd9a16f312dd3b5d36ea8b4954304657d5dfba115d4a0" dependencies = [ "cfg-if", "js-sys", @@ -2735,9 +2723,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" +checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2745,31 +2733,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" +checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" +checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" -version = "0.3.81" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" +checksum = "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1" dependencies = [ "js-sys", "wasm-bindgen", @@ -2834,15 +2822,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - [[package]] name = "windows-sys" version = "0.60.2" @@ -3074,9 +3053,9 @@ checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "writeable" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "x86" @@ -3113,11 +3092,10 @@ dependencies = [ [[package]] name = "yoke" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" dependencies = [ - "serde", "stable_deref_trait", "yoke-derive", "zerofrom", @@ -3125,9 +3103,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", @@ -3184,9 +3162,9 @@ checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" [[package]] name = "zerotrie" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" dependencies = [ "displaydoc", "yoke", @@ -3195,9 +3173,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.4" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" dependencies = [ "yoke", "zerofrom", @@ -3206,9 +3184,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 0ecaf40..bc4b4d2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ keywords = ["serial", "uart", "embedded", "bare-metal"] license = "MIT OR Apache-2.0" name = "some-serial" repository = "https://github.com/drivercraft/some-serial" -version = "0.2.4" +version = "0.3.0" [dependencies] bitflags = "2.10" @@ -17,8 +17,10 @@ dma-api = {version = "0.5", features = ["alloc"]} heapless = "0.9" log = "0.4" mbarrier = "0.1" -rdif-base = {version = "0.7"} -rdif-serial = {version = "0.5.4"} +# rdif-base = {version = "0.7"} +# rdif-serial = {version = "0.6.0"} +rdif-serial = {path = "C:\\Users\\zhoudongsheng\\Documents\\opensource\\rdrive\\interface\\rdif-serial"} + thiserror = {version = "2.0", default-features = false} tock-registers = "0.10" diff --git a/src/ns16550/mmio.rs b/src/ns16550/mmio.rs index 39b1e69..ecf8164 100644 --- a/src/ns16550/mmio.rs +++ b/src/ns16550/mmio.rs @@ -4,8 +4,8 @@ use super::{Kind, Ns16550}; use core::ptr::NonNull; -use rdif_serial::Serial; +#[derive(Clone)] pub struct Mmio { base: usize, } @@ -18,7 +18,7 @@ impl Kind for Mmio { } } - fn write_reg(&mut self, reg: u8, val: u8) { + fn write_reg(&self, reg: u8, val: u8) { unsafe { let addr = self.base + (reg as usize) * 4; core::ptr::write_volatile(addr as *mut u8, val); @@ -28,17 +28,13 @@ impl Kind for Mmio { fn get_base(&self) -> usize { self.base } - - fn set_base(&mut self, base: usize) { - self.base = base; - } } impl Ns16550 { - pub fn new_mmio(base: NonNull, clock_freq: u32) -> Serial { - Self::new( + pub fn new_mmio(base: NonNull, clock_freq: u32) -> Ns16550 { + Ns16550::new( Mmio { - base: base.as_ptr() as _, + base: base.as_ptr() as usize, }, clock_freq, ) diff --git a/src/ns16550/mod.rs b/src/ns16550/mod.rs index 8520de9..b37626b 100644 --- a/src/ns16550/mod.rs +++ b/src/ns16550/mod.rs @@ -7,11 +7,12 @@ // 公共寄存器定义 mod registers; +use core::usize; + use bitflags::Flags; -use heapless::Deque; use rdif_serial::{ - Config, ConfigError, DataBits, InterruptMask, LineStatus, Parity, Register, Serial, StopBits, - TransferError, + Config, ConfigError, DataBits, InterfaceRaw, InterruptMask, Parity, SetBackError, StopBits, + TIrqHandler, TReciever, TSender, TransferError, }; use registers::*; @@ -24,32 +25,231 @@ pub use mmio::*; #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub use pio::*; -pub trait Kind: Send + Sync + 'static { +pub trait Kind: Clone + Send + Sync + 'static { fn read_reg(&self, reg: u8) -> u8; - fn write_reg(&mut self, reg: u8, val: u8); + fn write_reg(&self, reg: u8, val: u8); fn get_base(&self) -> usize; - fn set_base(&mut self, base: usize); + + // 类型安全的 bitflags 寄存器访问 + fn read_flags>(&self, reg: u8) -> F { + F::from_bits_retain(self.read_reg(reg)) + } + + fn write_flags>(&mut self, reg: u8, val: F) { + self.write_reg(reg, val.bits()); + } } -#[derive(Clone, Debug)] -#[repr(align(64))] pub struct Ns16550 { - rcv_fifo: Deque, base: T, clock_freq: u32, - is_tx_empty_int_enabled: bool, - err: Option, + irq: Option>, + tx: Option>, + rx: Option>, +} + +impl InterfaceRaw for Ns16550 { + type Sender = Ns16550Sender; + type Reciever = Ns16550Reciever; + type IrqHandler = Ns16550IrqHandler; + + fn base_addr(&self) -> usize { + self.base.get_base() + } + + fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { + // 配置波特率 + if let Some(baudrate) = config.baudrate { + self.set_baudrate_internal(baudrate)?; + } + + // 配置数据位 + if let Some(data_bits) = config.data_bits { + self.set_data_bits_internal(data_bits)?; + } + + // 配置停止位 + if let Some(stop_bits) = config.stop_bits { + self.set_stop_bits_internal(stop_bits)?; + } + + // 配置奇偶校验 + if let Some(parity) = config.parity { + self.set_parity_internal(parity)?; + } + Ok(()) + } + + fn baudrate(&self) -> u32 { + // 只读方式获取波特率,通过读取 DLL 和 DLH + // 注意:如果 DLAB 未设置,读取的可能不是除数值 + let dll = self.read_reg_u8(UART_DLL) as u16; + let dlh = self.read_reg_u8(UART_DLH) as u16; + let divisor = dll | (dlh << 8); + + if divisor == 0 { + return 0; + } + + self.clock_freq / (16 * divisor as u32) + } + + fn data_bits(&self) -> DataBits { + let lcr: LineControlFlags = self.read_flags(UART_LCR); + let wlen = lcr & LineControlFlags::WORD_LENGTH_MASK; + if wlen == LineControlFlags::WORD_LENGTH_5 { + DataBits::Five + } else if wlen == LineControlFlags::WORD_LENGTH_6 { + DataBits::Six + } else if wlen == LineControlFlags::WORD_LENGTH_7 { + DataBits::Seven + } else { + DataBits::Eight // 默认值 + } + } + + fn stop_bits(&self) -> StopBits { + let lcr: LineControlFlags = self.read_flags(UART_LCR); + if lcr.contains(LineControlFlags::STOP_BITS) { + StopBits::Two + } else { + StopBits::One + } + } + + fn parity(&self) -> Parity { + let lcr: LineControlFlags = self.read_flags(UART_LCR); + + if !lcr.contains(LineControlFlags::PARITY_ENABLE) { + Parity::None + } else if lcr.contains(LineControlFlags::STICK_PARITY) { + // Stick parity + if lcr.contains(LineControlFlags::EVEN_PARITY) { + Parity::Space + } else { + Parity::Mark + } + } else { + // Normal parity + if lcr.contains(LineControlFlags::EVEN_PARITY) { + Parity::Even + } else { + Parity::Odd + } + } + } + + fn clock_freq(&self) -> Option { + self.clock_freq.try_into().ok() + } + + fn open(&mut self) { + self.init(); + } + + fn close(&mut self) { + // 禁用所有中断 + self.write_flags(UART_IER, InterruptEnableFlags::empty()); + + // 禁用 DTR 和 RTS + let mut mcr: ModemControlFlags = self.read_flags(UART_MCR); + mcr.remove(ModemControlFlags::DATA_TERMINAL_READY | ModemControlFlags::REQUEST_TO_SEND); + self.write_flags(UART_MCR, mcr); + } + + fn enable_loopback(&mut self) { + let mut mcr: ModemControlFlags = self.read_flags(UART_MCR); + mcr.insert(ModemControlFlags::LOOPBACK_ENABLE); + self.write_flags(UART_MCR, mcr); + } + + fn disable_loopback(&mut self) { + let mut mcr: ModemControlFlags = self.read_flags(UART_MCR); + mcr.remove(ModemControlFlags::LOOPBACK_ENABLE); + self.write_flags(UART_MCR, mcr); + } + + fn is_loopback_enabled(&self) -> bool { + let mcr: ModemControlFlags = self.read_flags(UART_MCR); + mcr.contains(ModemControlFlags::LOOPBACK_ENABLE) + } + + fn set_irq_mask(&mut self, mask: InterruptMask) { + let mut ier = InterruptEnableFlags::empty(); + + if mask.contains(InterruptMask::RX_AVAILABLE) { + ier.insert(InterruptEnableFlags::RECEIVED_DATA_AVAILABLE); + ier.insert(InterruptEnableFlags::RECEIVER_LINE_STATUS); + } + if mask.contains(InterruptMask::TX_EMPTY) { + ier.insert(InterruptEnableFlags::TRANSMITTER_HOLDING_EMPTY); + } + + self.write_flags(UART_IER, ier); + } + + fn get_irq_mask(&self) -> InterruptMask { + let ier: InterruptEnableFlags = self.read_flags(UART_IER); + let mut mask = InterruptMask::empty(); + + if ier.contains(InterruptEnableFlags::RECEIVED_DATA_AVAILABLE) { + mask |= InterruptMask::RX_AVAILABLE; + } + if ier.contains(InterruptEnableFlags::TRANSMITTER_HOLDING_EMPTY) { + mask |= InterruptMask::TX_EMPTY; + } + // 错误中断暂不映射到 InterruptMask + // 用户需要通过状态寄存器检查错误 + + mask + } + + fn irq_handler(&mut self) -> Option { + self.irq.take() + } + + fn take_tx(&mut self) -> Option { + self.tx.take() + } + + fn take_rx(&mut self) -> Option { + self.rx.take() + } + + fn set_tx(&mut self, tx: Self::Sender) -> Result<(), SetBackError> { + let want = self.base.get_base(); + let actual = tx.base.get_base(); + if tx.base.get_base() != want { + return Err(SetBackError::new(want, actual)); + } + self.tx = Some(tx); + Ok(()) + } + + fn set_rx(&mut self, rx: Self::Reciever) -> Result<(), SetBackError> { + let want = self.base.get_base(); + let actual = rx.base.get_base(); + if rx.base.get_base() != want { + return Err(SetBackError::new(want, actual)); + } + self.rx = Some(rx); + Ok(()) + } } impl Ns16550 { - fn new(base: T, clock_freq: u32) -> Serial { - Serial::new(Self { - rcv_fifo: Deque::new(), + fn new(base: T, clock_freq: u32) -> Self { + let irq = Some(Ns16550IrqHandler { base: base.clone() }); + let tx = Some(Ns16550Sender { base: base.clone() }); + let rx = Some(Ns16550Reciever { base: base.clone() }); + + Self { base, clock_freq, - is_tx_empty_int_enabled: false, - err: None, - }) + irq, + tx, + rx, + } } // 基础 u8 寄存器访问(用于除数寄存器等特殊场景) @@ -218,25 +418,6 @@ impl Ns16550 { self.write_flags(UART_MCR, mcr); } - /// 清空接收 FIFO - pub fn clear_receive_fifo(&mut self) { - if self.is_16550_plus() { - let mut fcr = FifoControlFlags::ENABLE_FIFO; - fcr.insert(FifoControlFlags::CLEAR_RECEIVER_FIFO); - self.write_flags(UART_FCR, fcr); - } - self.rcv_fifo.clear(); - } - - /// 清空发送 FIFO - pub fn clear_transmit_fifo(&mut self) { - if self.is_16550_plus() { - let mut fcr = FifoControlFlags::ENABLE_FIFO; - fcr.insert(FifoControlFlags::CLEAR_TRANSMITTER_FIFO); - self.write_flags(UART_FCR, fcr); - } - } - /// 检查 FIFO 是否启用 pub fn is_fifo_enabled(&self) -> bool { if !self.is_16550_plus() { @@ -248,127 +429,72 @@ impl Ns16550 { } } -impl Register for Ns16550 { - fn write_byte(&mut self, byte: u8) { - self.write_reg_u8(UART_THR, byte); - // 如果启用了发送中断模式,在写入数据后重新启用 THRE 中断 - // 这样当 THR 的数据被转移到 TSR 后会再次触发中断 - if self.is_tx_empty_int_enabled { - let mut ier: InterruptEnableFlags = self.read_flags(UART_IER); - ier.insert(InterruptEnableFlags::TRANSMITTER_HOLDING_EMPTY); - self.write_flags(UART_IER, ier); - } - } +pub struct Ns16550Sender { + base: T, +} - fn read_byte(&mut self) -> Result { - if let Some(e) = self.err.take() { - return Err(e); +impl TSender for Ns16550Sender { + fn write_byte(&mut self, byte: u8) -> bool { + let lsr: LineStatusFlags = self.base.read_flags(UART_LSR); + if lsr.contains(LineStatusFlags::TRANSMITTER_HOLDING_EMPTY) { + self.base.write_reg(UART_THR, byte); + true + } else { + false } - Ok(self - .rcv_fifo - .pop_front() - .expect("should check line status first")) } +} - fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { - // 配置波特率 - if let Some(baudrate) = config.baudrate { - self.set_baudrate_internal(baudrate)?; - } - - // 配置数据位 - if let Some(data_bits) = config.data_bits { - self.set_data_bits_internal(data_bits)?; - } - - // 配置停止位 - if let Some(stop_bits) = config.stop_bits { - self.set_stop_bits_internal(stop_bits)?; - } - - // 配置奇偶校验 - if let Some(parity) = config.parity { - self.set_parity_internal(parity)?; - } +pub struct Ns16550Reciever { + base: T, +} - Ok(()) +impl Ns16550Reciever { + fn new(base: T) -> Self { + Self { base } } +} - fn baudrate(&self) -> u32 { - // 只读方式获取波特率,通过读取 DLL 和 DLH - // 注意:如果 DLAB 未设置,读取的可能不是除数值 - let dll = self.read_reg_u8(UART_DLL) as u16; - let dlh = self.read_reg_u8(UART_DLH) as u16; - let divisor = dll | (dlh << 8); +impl TReciever for Ns16550Reciever { + fn read_byte(&mut self) -> Result, TransferError> { + let lsr: LineStatusFlags = self.base.read_flags(UART_LSR); - if divisor == 0 { - return 0; + // 按优先级检查错误(从高到低) + if lsr.contains(LineStatusFlags::OVERRUN_ERROR) { + let b = self.base.read_reg(UART_RBR); + return Err(TransferError::Overrun(b)); } - self.clock_freq / (16 * divisor as u32) - } - - fn data_bits(&self) -> DataBits { - let lcr: LineControlFlags = self.read_flags(UART_LCR); - let wlen = lcr & LineControlFlags::WORD_LENGTH_MASK; - if wlen == LineControlFlags::WORD_LENGTH_5 { - DataBits::Five - } else if wlen == LineControlFlags::WORD_LENGTH_6 { - DataBits::Six - } else if wlen == LineControlFlags::WORD_LENGTH_7 { - DataBits::Seven - } else { - DataBits::Eight // 默认值 + if lsr.contains(LineStatusFlags::PARITY_ERROR) { + let _b = self.base.read_reg(UART_RBR); + return Err(TransferError::Parity); } - } - fn stop_bits(&self) -> StopBits { - let lcr: LineControlFlags = self.read_flags(UART_LCR); - if lcr.contains(LineControlFlags::STOP_BITS) { - StopBits::Two - } else { - StopBits::One + if lsr.contains(LineStatusFlags::FRAMING_ERROR) { + let _b = self.base.read_reg(UART_RBR); + return Err(TransferError::Framing); } - } - - fn parity(&self) -> Parity { - let lcr: LineControlFlags = self.read_flags(UART_LCR); - if !lcr.contains(LineControlFlags::PARITY_ENABLE) { - Parity::None - } else if lcr.contains(LineControlFlags::STICK_PARITY) { - // Stick parity - if lcr.contains(LineControlFlags::EVEN_PARITY) { - Parity::Space - } else { - Parity::Mark - } - } else { - // Normal parity - if lcr.contains(LineControlFlags::EVEN_PARITY) { - Parity::Even - } else { - Parity::Odd - } + if lsr.contains(LineStatusFlags::BREAK_INTERRUPT) { + let _b = self.base.read_reg(UART_RBR); + return Err(TransferError::Break); } - } - fn open(&mut self) { - self.init(); + if lsr.contains(LineStatusFlags::DATA_READY) { + let b = self.base.read_reg(UART_RBR); + return Ok(Some(b)); + } + Ok(None) } +} - fn close(&mut self) { - // 禁用所有中断 - self.write_flags(UART_IER, InterruptEnableFlags::empty()); - - // 禁用 DTR 和 RTS - let mut mcr: ModemControlFlags = self.read_flags(UART_MCR); - mcr.remove(ModemControlFlags::DATA_TERMINAL_READY | ModemControlFlags::REQUEST_TO_SEND); - self.write_flags(UART_MCR, mcr); - } +pub struct Ns16550IrqHandler { + base: T, +} - fn clean_interrupt_status(&mut self) -> InterruptMask { - let iir: InterruptIdentificationFlags = self.read_flags(UART_IIR); +impl TIrqHandler for Ns16550IrqHandler { + fn clean_interrupt_status(&self) -> InterruptMask { + let iir: InterruptIdentificationFlags = self.base.read_flags(UART_IIR); let mut mask = InterruptMask::empty(); // 检查是否有中断挂起 @@ -380,164 +506,18 @@ impl Register for Ns16550 { let interrupt_id = iir & InterruptIdentificationFlags::INTERRUPT_ID_MASK; // 使用精确匹配而不是 contains - if interrupt_id == InterruptIdentificationFlags::RECEIVER_LINE_STATUS { - // 接收线路状态错误中断 - let lsr: LineStatusFlags = self.read_flags(UART_LSR); - - // 读取 RBR 以清除错误状态(即使有错误也需要读取) - let d = self.read_reg_u8(UART_RBR); - - // 按优先级检查错误(从高到低) - if lsr.contains(LineStatusFlags::OVERRUN_ERROR) { - self.err = Some(TransferError::Overrun(d)); - mask |= InterruptMask::RX_AVAILABLE; - } else if lsr.contains(LineStatusFlags::PARITY_ERROR) { - self.err = Some(TransferError::Parity); - mask |= InterruptMask::RX_AVAILABLE; - } else if lsr.contains(LineStatusFlags::FRAMING_ERROR) { - self.err = Some(TransferError::Framing); - mask |= InterruptMask::RX_AVAILABLE; - } else if lsr.contains(LineStatusFlags::BREAK_INTERRUPT) { - self.err = Some(TransferError::Break); - mask |= InterruptMask::RX_AVAILABLE; - } else if lsr.contains(LineStatusFlags::DATA_READY) { - // 没有错误,保存数据到 FIFO - if self.rcv_fifo.push_back(d).is_err() { - self.err = Some(TransferError::Overrun(d)); - } - mask |= InterruptMask::RX_AVAILABLE; - } - } else if interrupt_id == InterruptIdentificationFlags::RECEIVED_DATA_AVAILABLE + if interrupt_id == InterruptIdentificationFlags::RECEIVER_LINE_STATUS + || interrupt_id == InterruptIdentificationFlags::RECEIVED_DATA_AVAILABLE || interrupt_id == InterruptIdentificationFlags::CHARACTER_TIMEOUT { // 接收数据可用中断或字符超时中断 mask |= InterruptMask::RX_AVAILABLE; - - // 读取所有可用数据 - while self - .read_flags::(UART_LSR) - .contains(LineStatusFlags::DATA_READY) - { - let d = self.read_reg_u8(UART_RBR); - if self.rcv_fifo.push_back(d).is_err() { - self.err = Some(TransferError::Overrun(d)); - break; - } - } } else if interrupt_id == InterruptIdentificationFlags::TRANSMITTER_HOLDING_EMPTY { // 发送保持寄存器空中断 - // 关闭 THRI 使能位,避免持续触发中断 - // 用户在 write_byte 时会重新启用 - let mut ier: InterruptEnableFlags = self.read_flags(UART_IER); - ier.remove(InterruptEnableFlags::TRANSMITTER_HOLDING_EMPTY); - self.write_flags(UART_IER, ier); - if self.is_tx_empty_int_enabled { - mask |= InterruptMask::TX_EMPTY; - } - } else if interrupt_id == InterruptIdentificationFlags::MODEM_STATUS { - // Modem 状态中断,读取 MSR 清除 - let _ = self.read_flags::(UART_MSR); - } - - mask - } - - fn line_status(&mut self) -> LineStatus { - let lsr: LineStatusFlags = self.read_flags(UART_LSR); - let mut status = LineStatus::empty(); - if self.err.is_some() { - status |= LineStatus::DATA_READY; - } - - if lsr.contains(LineStatusFlags::TRANSMITTER_HOLDING_EMPTY) { - status |= LineStatus::TX_HOLDING_EMPTY; - } - - if !self - .read_flags::(UART_IER) - .contains(InterruptEnableFlags::RECEIVED_DATA_AVAILABLE) - { - // 如果未启用接收中断,则直接检查 LSR 的 DATA_READY 位 - if lsr.contains(LineStatusFlags::DATA_READY) { - let b = self.read_reg_u8(UART_RBR); - if self.rcv_fifo.push_back(b).is_err() { - self.err = Some(TransferError::Overrun(b)); - } - } - } - // 检查 FIFO 中是否有数据 - if !self.rcv_fifo.is_empty() { - status |= LineStatus::DATA_READY; - } - - status - } - - fn read_reg(&self, offset: usize) -> u32 { - self.read_reg_u8(offset as u8) as u32 - } - - fn write_reg(&mut self, offset: usize, value: u32) { - self.write_reg_u8(offset as u8, value as u8); - } - - fn get_base(&self) -> usize { - self.base.get_base() - } - - fn set_base(&mut self, base: usize) { - self.base.set_base(base); - } - - fn clock_freq(&self) -> u32 { - self.clock_freq - } - - fn enable_loopback(&mut self) { - let mut mcr: ModemControlFlags = self.read_flags(UART_MCR); - mcr.insert(ModemControlFlags::LOOPBACK_ENABLE); - self.write_flags(UART_MCR, mcr); - } - - fn disable_loopback(&mut self) { - let mut mcr: ModemControlFlags = self.read_flags(UART_MCR); - mcr.remove(ModemControlFlags::LOOPBACK_ENABLE); - self.write_flags(UART_MCR, mcr); - } - - fn is_loopback_enabled(&self) -> bool { - let mcr: ModemControlFlags = self.read_flags(UART_MCR); - mcr.contains(ModemControlFlags::LOOPBACK_ENABLE) - } - - fn set_irq_mask(&mut self, mask: InterruptMask) { - let mut ier = InterruptEnableFlags::empty(); - self.is_tx_empty_int_enabled = false; - - if mask.contains(InterruptMask::RX_AVAILABLE) { - ier.insert(InterruptEnableFlags::RECEIVED_DATA_AVAILABLE); - ier.insert(InterruptEnableFlags::RECEIVER_LINE_STATUS); - } - if mask.contains(InterruptMask::TX_EMPTY) { - ier.insert(InterruptEnableFlags::TRANSMITTER_HOLDING_EMPTY); - self.is_tx_empty_int_enabled = true; - } - - self.write_flags(UART_IER, ier); - } - - fn get_irq_mask(&self) -> InterruptMask { - let ier: InterruptEnableFlags = self.read_flags(UART_IER); - let mut mask = InterruptMask::empty(); - - if ier.contains(InterruptEnableFlags::RECEIVED_DATA_AVAILABLE) { - mask |= InterruptMask::RX_AVAILABLE; - } - if self.is_tx_empty_int_enabled { mask |= InterruptMask::TX_EMPTY; + } else if interrupt_id == InterruptIdentificationFlags::MODEM_STATUS { + // Modem 状态中断 } - // 错误中断暂不映射到 InterruptMask - // 用户需要通过状态寄存器检查错误 mask } diff --git a/src/ns16550/pio.rs b/src/ns16550/pio.rs index 5cae5d2..0810c6b 100644 --- a/src/ns16550/pio.rs +++ b/src/ns16550/pio.rs @@ -17,17 +17,13 @@ impl Kind for Port { unsafe { x86::io::inb(self.port + reg as u16) } } - fn write_reg(&mut self, reg: u8, val: u8) { + fn write_reg(&self, reg: u8, val: u8) { unsafe { x86::io::outb(self.port + reg as u16, val) } } fn get_base(&self) -> usize { self.port as _ } - - fn set_base(&mut self, base: usize) { - self.port = base as _; - } } impl Ns16550 { @@ -37,7 +33,7 @@ impl Ns16550 { /// /// * `port` - 串口基地址 (如 COM1 为 0x3F8) /// * `clock_freq` - UART 时钟频率,通常为 1.8432 MHz - pub fn new_port(port: u16, clock_freq: u32) -> crate::Serial { - Self::new(Port { port }, clock_freq) + pub fn new_port(port: u16, clock_freq: u32) -> Ns16550 { + Ns16550::new(Port { port }, clock_freq) } } diff --git a/src/pl011.rs b/src/pl011.rs index 9348718..e62fe46 100644 --- a/src/pl011.rs +++ b/src/pl011.rs @@ -1,10 +1,12 @@ -use core::ptr::NonNull; +use core::{num::NonZeroU32, ptr::NonNull}; -use crate::Register; -use rdif_serial::{Serial, TransferError}; +use rdif_serial::{ + BSerial, InterfaceRaw, SerialDyn, SetBackError, TIrqHandler, TReciever, TSender, + TransBytesError, TransferError, +}; use tock_registers::{interfaces::*, register_bitfields, register_structs, registers::*}; -use crate::{Config, ConfigError, DataBits, InterruptMask, LineStatus, Parity, StopBits}; +use crate::{Config, ConfigError, DataBits, InterruptMask, Parity, StopBits}; register_bitfields! [ u32, @@ -137,35 +139,43 @@ register_structs! { unsafe impl Sync for Pl011Registers {} /// PL011 UART 驱动结构体 -#[derive(Clone)] pub struct Pl011 { - base: NonNull, + base: Reg, clock_freq: u32, + tx: Option, + rx: Option, + irq: Option, } -unsafe impl Send for Pl011 {} -unsafe impl Sync for Pl011 {} - impl Pl011 { /// 创建新的 PL011 实例(仅基地址,使用默认配置) /// /// # Arguments /// * `base` - UART 寄存器基地址 - pub fn new_no_clock(base: NonNull) -> Serial { + pub fn new_no_clock(base: NonNull) -> Self { // 自动检测时钟频率或使用合理的默认值 let clock_freq = Self::detect_clock_frequency(base.as_ptr() as usize); Self::new(base, clock_freq) } - pub fn new(base: NonNull, clock_freq: u32) -> Serial { - Serial::new(Self { - base: base.cast(), + pub fn new(base: NonNull, clock_freq: u32) -> Self { + let base = Reg(base.cast()); + + Self { + base, clock_freq, - }) + tx: Some(Pl011Sender { base }), + rx: Some(Pl011Reciever { base }), + irq: Some(Pl011IrqHandler { base }), + } + } + + pub fn new_boxed(base: NonNull, clock_freq: u32) -> BSerial { + SerialDyn::new_boxed(Self::new(base, clock_freq)) } fn registers(&self) -> &Pl011Registers { - unsafe { self.base.as_ref() } + unsafe { &*self.base.0.as_ptr() } } /// 自动检测或确定合理的时钟频率 @@ -307,13 +317,44 @@ impl Pl011 { } } -impl Register for Pl011 { - fn write_byte(&mut self, byte: u8) { - self.registers().uartdr.write(UARTDR::DATA.val(byte as u32)); +#[derive(Clone, Copy, PartialEq, Eq)] +struct Reg(NonNull); + +unsafe impl Send for Reg {} + +impl Reg { + fn registers(&self) -> &Pl011Registers { + unsafe { self.0.as_ref() } } +} - fn read_byte(&mut self) -> Result { - let dr = self.registers().uartdr.extract(); +pub struct Pl011Sender { + base: Reg, +} + +impl TSender for Pl011Sender { + fn write_byte(&mut self, byte: u8) -> bool { + if self.base.registers().uartfr.is_set(UARTFR::TXFF) { + return false; + } + + self.base.registers().uartdr.set(byte as _); + + true + } +} + +pub struct Pl011Reciever { + base: Reg, +} + +impl TReciever for Pl011Reciever { + fn read_byte(&mut self) -> Result, TransferError> { + if self.base.registers().uartfr.is_set(UARTFR::RXFE) { + return Ok(None); + } + + let dr = self.base.registers().uartdr.extract(); let data = dr.read(UARTDR::DATA) as u8; if dr.is_set(UARTDR::FE) { @@ -332,8 +373,73 @@ impl Register for Pl011 { return Err(TransferError::Break); } - Ok(data) + Ok(Some(data)) + } + + fn read_bytes(&mut self, bytes: &mut [u8]) -> Result { + let mut count = 0; + let mut overrun_data = None; + for byte in bytes.iter_mut() { + match self.read_byte() { + Ok(Some(b)) => { + *byte = b; + count += 1; + } + Ok(None) => { + if let Some(data) = overrun_data { + return Err(TransBytesError { + bytes_transferred: count, + kind: TransferError::Overrun(data), + }); + } + break; + } // 无更多数据 + Err(TransferError::Overrun(data)) => { + overrun_data = Some(data); + *byte = data; + } + Err(e) => { + return Err(TransBytesError { + bytes_transferred: count, + kind: e, + }); + } + } + } + Ok(count) + } +} + +pub struct Pl011IrqHandler { + base: Reg, +} + +unsafe impl Sync for Pl011IrqHandler {} + +impl TIrqHandler for Pl011IrqHandler { + fn clean_interrupt_status(&self) -> InterruptMask { + let mis = self.base.registers().uartmis.extract(); + let mut mask = InterruptMask::empty(); + + if mis.is_set(UARTIS::RX) { + mask |= InterruptMask::RX_AVAILABLE; + } + if mis.is_set(UARTIS::TX) { + mask |= InterruptMask::TX_EMPTY; + } + + self.base.registers().uarticr.set(mis.get()); + + mask } +} + +impl InterfaceRaw for Pl011 { + type IrqHandler = Pl011IrqHandler; + + type Sender = Pl011Sender; + + type Reciever = Pl011Reciever; fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { use tock_registers::interfaces::Readable; @@ -439,58 +545,8 @@ impl Register for Pl011 { self.registers().uartcr.modify(UARTCR::UARTEN::CLEAR); } - fn clean_interrupt_status(&mut self) -> InterruptMask { - let mis = self.registers().uartmis.extract(); - let mut mask = InterruptMask::empty(); - - if mis.is_set(UARTIS::RX) { - mask |= InterruptMask::RX_AVAILABLE; - } - if mis.is_set(UARTIS::TX) { - mask |= InterruptMask::TX_EMPTY; - } - - self.registers().uarticr.set(mis.get()); - - mask - } - - fn line_status(&mut self) -> LineStatus { - let mut status = LineStatus::empty(); - - let fr = self.registers().uartfr.extract(); - - if !fr.is_set(UARTFR::RXFE) { - status |= LineStatus::DATA_READY; - } - - if !fr.is_set(UARTFR::TXFF) { - status |= LineStatus::TX_HOLDING_EMPTY; - } - - status - } - - fn read_reg(&self, offset: usize) -> u32 { - let addr = unsafe { self.base.cast::().add(offset) }; - unsafe { addr.cast().read_volatile() } - } - - fn write_reg(&mut self, offset: usize, value: u32) { - let addr = unsafe { self.base.cast::().add(offset) }; - unsafe { addr.cast().write_volatile(value) }; - } - - fn get_base(&self) -> usize { - self.base.as_ptr() as usize - } - - fn set_base(&mut self, base: usize) { - self.base = NonNull::new(base as *mut Pl011Registers).unwrap(); - } - - fn clock_freq(&self) -> u32 { - self.clock_freq + fn clock_freq(&self) -> Option { + self.clock_freq.try_into().ok() } fn enable_loopback(&mut self) { @@ -530,6 +586,46 @@ impl Register for Pl011 { mask } + + fn base_addr(&self) -> usize { + self.base.0.as_ptr() as usize + } + + fn irq_handler(&mut self) -> Option { + self.irq.take() + } + + fn take_tx(&mut self) -> Option { + self.tx.take() + } + + fn take_rx(&mut self) -> Option { + self.rx.take() + } + + fn set_tx(&mut self, tx: Self::Sender) -> Result<(), SetBackError> { + if self.base != tx.base { + return Err(SetBackError::new( + self.base.0.as_ptr() as _, + tx.base.0.as_ptr() as _, + )); + } + + self.tx = Some(tx); + Ok(()) + } + + fn set_rx(&mut self, rx: Self::Reciever) -> Result<(), SetBackError> { + if self.base != rx.base { + return Err(SetBackError::new( + self.base.0.as_ptr() as _, + rx.base.0.as_ptr() as _, + )); + } + + self.rx = Some(rx); + Ok(()) + } } // 额外的便利方法,用于 FIFO 和流控制 From ef926c1952ddbc25aa241c68083441af7206377b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E7=9D=BF?= Date: Sun, 2 Nov 2025 16:10:04 +0800 Subject: [PATCH 2/9] feat(serial): add configurable register width and improve receiver interface - Add configurable register width parameter to MMIO interface - Add boxed constructors for dynamic trait object creation - Refactor receiver interface to return Option instead of Result