eth: sketch

eth: rework

ethernet: wip

eth: simplify

cargo: bump stm32h7

ethmac: rework

ethmac: fixup

cargo: semihosting version bump

ethmac: fixup

eth: tweak

eth: cleanup

eth: tweaks

eth: more debug

eth: tweak

memory: rename for clarity

eth: tweak

eth: pings

eth: cleanup

eth: cleanup, use interrupts, tighten filter
This commit is contained in:
Robert Jördens 2019-04-22 21:31:59 +02:00
parent 8ff8a4ce31
commit 0fafd7aa42
5 changed files with 825 additions and 72 deletions

107
Cargo.lock generated
View File

@ -2,8 +2,20 @@
# It is not intended for manual editing. # It is not intended for manual editing.
[[package]] [[package]]
name = "aligned" name = "aligned"
version = "0.2.0" version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"as-slice 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "as-slice"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "bare-metal" name = "bare-metal"
@ -46,21 +58,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "cortex-m" name = "cortex-m"
version = "0.5.8" version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"aligned 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "aligned 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"bare-metal 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "bare-metal 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"volatile-register 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "volatile-register 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "cortex-m-log" name = "cortex-m-log"
version = "0.4.0" version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"cortex-m 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "cortex-m 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cortex-m-semihosting 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "cortex-m-semihosting 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -78,18 +90,26 @@ name = "cortex-m-rt-macros"
version = "0.1.5" version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.31 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "cortex-m-semihosting" name = "cortex-m-semihosting"
version = "0.3.2" version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"cortex-m 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "cortex-m 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "generic-array"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -141,14 +161,6 @@ dependencies = [
"vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "log"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.6" version = "0.4.6"
@ -175,10 +187,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "panic-semihosting" name = "panic-semihosting"
version = "0.5.1" version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/rust-embedded/panic-semihosting?rev=aef8231a521aa4197cdb5c3b0bc2b435ed663e2b#aef8231a521aa4197cdb5c3b0bc2b435ed663e2b"
dependencies = [ dependencies = [
"cortex-m 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "cortex-m 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cortex-m-semihosting 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "cortex-m-semihosting 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -193,7 +205,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "0.4.27" version = "0.4.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -204,7 +216,7 @@ name = "quote"
version = "0.6.12" version = "0.6.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -276,7 +288,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"managed 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "managed 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -284,34 +295,40 @@ dependencies = [
name = "stabilizer" name = "stabilizer"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"aligned 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"built 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "built 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cortex-m 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "cortex-m 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cortex-m-log 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "cortex-m-log 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cortex-m-rt 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "cortex-m-rt 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"panic-abort 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "panic-abort 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"panic-semihosting 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "panic-semihosting 0.5.1 (git+https://github.com/rust-embedded/panic-semihosting?rev=aef8231a521aa4197cdb5c3b0bc2b435ed663e2b)",
"smoltcp 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "smoltcp 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"stm32h7 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "stm32h7 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "stable_deref_trait"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "stm32h7" name = "stm32h7"
version = "0.6.0" version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"bare-metal 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "bare-metal 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"cortex-m 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "cortex-m 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cortex-m-rt 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "cortex-m-rt 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
"vcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "vcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "syn" name = "syn"
version = "0.15.31" version = "0.15.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -334,6 +351,11 @@ dependencies = [
"serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "typenum"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "unicode-bidi" name = "unicode-bidi"
version = "0.3.4" version = "0.3.4"
@ -403,32 +425,33 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata] [metadata]
"checksum aligned 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d39da9b88ae1a81c03c9c082b8db83f1d0e93914126041962af61034ab44c4a5" "checksum aligned 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d3a316c7ea8e1e9ece54862c992def5a7ac14de9f5832b69d71760680efeeefa"
"checksum as-slice 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "293dac66b274fab06f95e7efb05ec439a6b70136081ea522d270bc351ae5bb27"
"checksum bare-metal 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a3caf393d93b2d453e80638d0674597020cef3382ada454faacd43d1a55a735a" "checksum bare-metal 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a3caf393d93b2d453e80638d0674597020cef3382ada454faacd43d1a55a735a"
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
"checksum built 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "61f5aae2fa15b68fbcf0cbab64e659a55d10e9bacc55d3470ef77ae73030d755" "checksum built 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "61f5aae2fa15b68fbcf0cbab64e659a55d10e9bacc55d3470ef77ae73030d755"
"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb"
"checksum cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)" = "5e5f3fee5eeb60324c2781f1e41286bdee933850fff9b3c672587fed5ec58c83" "checksum cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)" = "5e5f3fee5eeb60324c2781f1e41286bdee933850fff9b3c672587fed5ec58c83"
"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" "checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4"
"checksum cortex-m 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dab2164a0fc216781a47fc343347365112ae6917421d3fa4bac6faf0fbaaaec7" "checksum cortex-m 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f3c18719fdc57db65668bfc977db9a0fa1a41d718c5d9cd4f652c9d4b0e0956a"
"checksum cortex-m-log 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "62d666a7362a29620140c5a0a8149dd31f06bd6a804240f32359a83ded1e210a" "checksum cortex-m-log 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "584a62cf37ddd834b8bfc21317bf3396915844298bf346dd1f4ca0572180ac7f"
"checksum cortex-m-rt 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7e1ccc9052352415ec4e3f762f4541098d012016f9354a1a5b2dede39b67f426" "checksum cortex-m-rt 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7e1ccc9052352415ec4e3f762f4541098d012016f9354a1a5b2dede39b67f426"
"checksum cortex-m-rt-macros 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d7ae692573e0acccb1579fef1abf5a5bf1d2f3f0149a22b16870ec9309aee25f" "checksum cortex-m-rt-macros 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d7ae692573e0acccb1579fef1abf5a5bf1d2f3f0149a22b16870ec9309aee25f"
"checksum cortex-m-semihosting 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d1dc2abec1a772e8bb697cad17d5710f180043caf8939820f0f6ba4b7ae2a4b5" "checksum cortex-m-semihosting 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "165f3f86f4d1031351a6c9dc8d5a3f8fae2050f9dd6ef925e3d675c232cc0e46"
"checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592"
"checksum git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "591f8be1674b421644b6c030969520bc3fa12114d2eb467471982ed3e9584e71" "checksum git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "591f8be1674b421644b6c030969520bc3fa12114d2eb467471982ed3e9584e71"
"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e"
"checksum libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)" = "bedcc7a809076656486ffe045abeeac163da1b558e963a31e29fbfbeba916917" "checksum libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)" = "bedcc7a809076656486ffe045abeeac163da1b558e963a31e29fbfbeba916917"
"checksum libgit2-sys 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "48441cb35dc255da8ae72825689a95368bf510659ae1ad55dc4aa88cb1789bf1" "checksum libgit2-sys 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "48441cb35dc255da8ae72825689a95368bf510659ae1ad55dc4aa88cb1789bf1"
"checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe" "checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe"
"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
"checksum managed 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcec5e97041c7f0f1c5b7d93f12e57293c831c646f4cc7a5db59460c7ea8de6" "checksum managed 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcec5e97041c7f0f1c5b7d93f12e57293c831c646f4cc7a5db59460c7ea8de6"
"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
"checksum panic-abort 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c14a66511ed17b6a8b4256b868d7fd207836d891db15eea5195dbcaf87e630f" "checksum panic-abort 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c14a66511ed17b6a8b4256b868d7fd207836d891db15eea5195dbcaf87e630f"
"checksum panic-semihosting 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a647d81e7b00f69deac766cd96d69fc11c95c18657d2448b539ae93e4c558689" "checksum panic-semihosting 0.5.1 (git+https://github.com/rust-embedded/panic-semihosting?rev=aef8231a521aa4197cdb5c3b0bc2b435ed663e2b)" = "<none>"
"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c"
"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" "checksum proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)" = "ba92c84f814b3f9a44c5cfca7d2ad77fa10710867d2bbb1b3d175ab5f47daa12"
"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db" "checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db"
"checksum r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f" "checksum r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f"
"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" "checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9"
@ -441,10 +464,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)" = "aa5f7c20820475babd2c077c3ab5f8c77a31c15e16ea38687b4c02d3e48680f4" "checksum serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)" = "aa5f7c20820475babd2c077c3ab5f8c77a31c15e16ea38687b4c02d3e48680f4"
"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" "checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be"
"checksum smoltcp 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fef582369edb298c6c41319a544ca9c4e83622f226055ccfcb35974fbb55ed34" "checksum smoltcp 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fef582369edb298c6c41319a544ca9c4e83622f226055ccfcb35974fbb55ed34"
"checksum stm32h7 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2756cb97ac50836393814072493107a42701fecd11a6d228527292479bb1f25" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
"checksum syn 0.15.31 (registry+https://github.com/rust-lang/crates.io-index)" = "d2b4cfac95805274c6afdb12d8f770fa2d27c045953e7b630a81801953699a9a" "checksum stm32h7 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "64173a3f8edb1bf9e17b14861695da2a7e6ca98afc99e0f249b62e4962cc478d"
"checksum syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)" = "846620ec526c1599c070eff393bfeeeb88a93afa2513fc3b49f1fea84cf7b0ed"
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
"checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" "checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f"
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" "checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"

View File

@ -27,15 +27,23 @@ features = []
default-target = "thumbv7em-none-eabihf" default-target = "thumbv7em-none-eabihf"
[dependencies] [dependencies]
cortex-m = { version = "0.5", features = ["inline-asm", "const-fn"] } cortex-m = { version = "0.6", features = ["inline-asm", "const-fn"] }
cortex-m-rt = { version = "0.6", features = ["device"] } cortex-m-rt = { version = "0.6", features = ["device"] }
cortex-m-log = { version = "0.4", features = ["log-integration"] } cortex-m-log = { version = "0.5", features = ["log-integration"] }
stm32h7 = { version = "0.6", features = ["stm32h7x3", "rt"] } stm32h7 = { version = "0.7", features = ["stm32h7x3", "rt"] }
# stm32h7 = { path = "../stm32-rs/stm32h7", features = ["stm32h7x3", "rt"] }
log = "0.4" log = "0.4"
panic-abort = "0.3" panic-abort = "0.3"
panic-semihosting = { version = "0.5", optional = true } # https://github.com/rust-embedded/panic-semihosting/issues/16
smoltcp = { version = "0.5", default-features = false, features = ["proto-ipv4", "socket-tcp", "log"] } # panic-semihosting = { version = "0.6", optional = true }
panic-semihosting = { git = "https://github.com/rust-embedded/panic-semihosting", rev = "aef8231a521aa4197cdb5c3b0bc2b435ed663e2b", optional = true }
aligned = "0.3"
[dependencies.smoltcp]
#git = "https://github.com/m-labs/smoltcp"
#rev = "cd893e6"
version = "0.5"
features = ["proto-ipv4", "socket-tcp"]
default-features = false
[features] [features]
semihosting = ["panic-semihosting", "cortex-m-log/semihosting"] semihosting = ["panic-semihosting", "cortex-m-log/semihosting"]

View File

@ -2,9 +2,11 @@ MEMORY
{ {
ITCM (rwx) : ORIGIN = 0x00000000, LENGTH = 64K ITCM (rwx) : ORIGIN = 0x00000000, LENGTH = 64K
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128K RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128K
RAM_D1 (rwx) : ORIGIN = 0x24000000, LENGTH = 512K AXISRAM (rwx) : ORIGIN = 0x24000000, LENGTH = 512K
RAM_D2 (rwx) : ORIGIN = 0x30000000, LENGTH = 288K SRAM1 (rwx) : ORIGIN = 0x30000000, LENGTH = 128K
RAM_D3 (rwx) : ORIGIN = 0x38000000, LENGTH = 64K SRAM2 (rwx) : ORIGIN = 0x30020000, LENGTH = 128K
SRAM3 (rwx) : ORIGIN = 0x30040000, LENGTH = 32K
BACKUPSRAM (rwx) : ORIGIN = 0x38000000, LENGTH = 64K
RAM_B (rwx) : ORIGIN = 0x38800000, LENGTH = 4K RAM_B (rwx) : ORIGIN = 0x38800000, LENGTH = 4K
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
FLASH1 (rx) : ORIGIN = 0x08100000, LENGTH = 1024K FLASH1 (rx) : ORIGIN = 0x08100000, LENGTH = 1024K
@ -14,5 +16,17 @@ SECTIONS {
.sram1 (NOLOAD) : ALIGN(4) { .sram1 (NOLOAD) : ALIGN(4) {
*(.sram1); *(.sram1);
. = ALIGN(4); . = ALIGN(4);
} > RAM_D2 } > SRAM1
.sram2 (NOLOAD) : ALIGN(4) {
*(.sram2);
. = ALIGN(4);
} > SRAM2
.sram3 (NOLOAD) : ALIGN(4) {
*(.sram3);
. = ALIGN(4);
} > SRAM3
.axisram (NOLOAD) : ALIGN(8) {
*(.axisram);
. = ALIGN(8);
} > AXISRAM
} INSERT AFTER .bss; } INSERT AFTER .bss;

611
src/eth.rs Normal file
View File

@ -0,0 +1,611 @@
use core::{slice, cmp};
use cortex_m;
use stm32h7::stm32h7x3 as stm32;
use smoltcp::Result;
use smoltcp::time::Instant;
use smoltcp::wire::EthernetAddress;
use smoltcp::phy;
#[allow(dead_code)]
mod phy_consts {
pub const PHY_REG_BCR: u8 = 0x00;
pub const PHY_REG_BSR: u8 = 0x01;
pub const PHY_REG_ID1: u8 = 0x02;
pub const PHY_REG_ID2: u8 = 0x03;
pub const PHY_REG_ANTX: u8 = 0x04;
pub const PHY_REG_ANRX: u8 = 0x05;
pub const PHY_REG_ANEXP: u8 = 0x06;
pub const PHY_REG_ANNPTX: u8 = 0x07;
pub const PHY_REG_ANNPRX: u8 = 0x08;
pub const PHY_REG_SSR: u8 = 0x1F; // Special Status Register
pub const PHY_REG_CTL: u8 = 0x0D; // Ethernet PHY Register Control
pub const PHY_REG_ADDAR: u8 = 0x0E; // Ethernet PHY Address or Data
pub const PHY_REG_WUCSR: u16 = 08010;
pub const PHY_REG_BCR_COLTEST: u16 = 1 << 7;
pub const PHY_REG_BCR_FD: u16 = 1 << 8;
pub const PHY_REG_BCR_ANRST: u16 = 1 << 9;
pub const PHY_REG_BCR_ISOLATE: u16 = 1 << 10;
pub const PHY_REG_BCR_POWERDN: u16 = 1 << 11;
pub const PHY_REG_BCR_AN: u16 = 1 << 12;
pub const PHY_REG_BCR_100M: u16 = 1 << 13;
pub const PHY_REG_BCR_LOOPBACK: u16 = 1 << 14;
pub const PHY_REG_BCR_RESET: u16 = 1 << 15;
pub const PHY_REG_BSR_JABBER: u16 = 1 << 1;
pub const PHY_REG_BSR_UP: u16 = 1 << 2;
pub const PHY_REG_BSR_FAULT: u16 = 1 << 4;
pub const PHY_REG_BSR_ANDONE: u16 = 1 << 5;
pub const PHY_REG_SSR_ANDONE: u16 = 1 << 12;
pub const PHY_REG_SSR_SPEED: u16 = 0b111 << 2;
pub const PHY_REG_SSR_10BASE_HD: u16 = 0b001 << 2;
pub const PHY_REG_SSR_10BASE_FD: u16 = 0b101 << 2;
pub const PHY_REG_SSR_100BASE_HD: u16 = 0b010 << 2;
pub const PHY_REG_SSR_100BASE_FD: u16 = 0b110 << 2;
}
use self::phy_consts::*;
pub const MTU: usize = 1522;
const EMAC_DES3_OWN: u32 = 0x80000000;
const EMAC_DES3_CTXT: u32 = 0x40000000;
const EMAC_DES3_FD: u32 = 0x20000000;
const EMAC_DES3_LD: u32 = 0x10000000;
const EMAC_DES3_ES: u32 = 0x00008000;
const EMAC_TDES2_IOC: u32 = 0x80000000;
const EMAC_RDES3_IOC: u32 = 0x40000000;
const EMAC_RDES3_PL: u32 = 0x00007FFF;
const EMAC_RDES3_BUF1V: u32 = 0x01000000;
const EMAC_TDES2_B1L: u32 = 0x00003FFF;
const EMAC_DES0_BUF1AP: u32 = 0xFFFFFFFF;
const ETH_DESC_U32_SIZE: usize = 4;
const ETH_TX_BUFFER_COUNT: usize = 4;
const ETH_TX_BUFFER_SIZE: usize = 1536;
const ETH_RX_BUFFER_COUNT: usize = 4;
const ETH_RX_BUFFER_SIZE: usize = 1536;
#[allow(dead_code)]
mod cr_consts {
/* For HCLK 60-100 MHz */
pub const ETH_MACMIIAR_CR_HCLK_DIV_42: u8 = 0;
/* For HCLK 100-150 MHz */
pub const ETH_MACMIIAR_CR_HCLK_DIV_62: u8 = 1;
/* For HCLK 20-35 MHz */
pub const ETH_MACMIIAR_CR_HCLK_DIV_16: u8 = 2;
/* For HCLK 35-60 MHz */
pub const ETH_MACMIIAR_CR_HCLK_DIV_26: u8 = 3;
/* For HCLK 150-250 MHz */
pub const ETH_MACMIIAR_CR_HCLK_DIV_102: u8 = 4;
/* For HCLK 250-300 MHz */
pub const ETH_MACMIIAR_CR_HCLK_DIV_124: u8 = 5;
}
use self::cr_consts::*;
// set clock range in MAC MII address register
// 200 MHz AHB clock = eth_hclk
const CLOCK_RANGE: u8 = ETH_MACMIIAR_CR_HCLK_DIV_102;
pub fn setup(rcc: &stm32::RCC, syscfg: &stm32::SYSCFG) {
rcc.apb4enr.modify(|_, w| w.syscfgen().set_bit());
rcc.ahb1enr.modify(|_, w| {
w.eth1macen().set_bit()
.eth1txen().set_bit()
.eth1rxen().set_bit()
});
syscfg.pmcr.modify(|_, w| unsafe { w.epis().bits(0b100) }); // RMII
//rcc.ahb1rstr.modify(|_, w| w.eth1macrst().set_bit());
//rcc.ahb1rstr.modify(|_, w| w.eth1macrst().clear_bit());
}
pub fn setup_pins(gpioa: &stm32::GPIOA, gpiob: &stm32::GPIOB,
gpioc: &stm32::GPIOC, gpiog: &stm32::GPIOG) {
// PA1 RMII_REF_CLK
gpioa.moder.modify(|_, w| w.moder1().alternate());
gpioa.afrl.modify(|_, w| w.afr1().af11());
gpioa.ospeedr.modify(|_, w| w.ospeedr1().very_high_speed());
// PA2 RMII_MDIO
gpioa.moder.modify(|_, w| w.moder2().alternate());
gpioa.afrl.modify(|_, w| w.afr2().af11());
gpioa.ospeedr.modify(|_, w| w.ospeedr2().very_high_speed());
// PC1 RMII_MDC
gpioc.moder.modify(|_, w| w.moder1().alternate());
gpioc.afrl.modify(|_, w| w.afr1().af11());
gpioc.ospeedr.modify(|_, w| w.ospeedr1().very_high_speed());
// PA7 RMII_CRS_DV
gpioa.moder.modify(|_, w| w.moder7().alternate());
gpioa.afrl.modify(|_, w| w.afr7().af11());
gpioa.ospeedr.modify(|_, w| w.ospeedr7().very_high_speed());
// PC4 RMII_RXD0
gpioc.moder.modify(|_, w| w.moder4().alternate());
gpioc.afrl.modify(|_, w| w.afr4().af11());
gpioc.ospeedr.modify(|_, w| w.ospeedr4().very_high_speed());
// PC5 RMII_RXD1
gpioc.moder.modify(|_, w| w.moder5().alternate());
gpioc.afrl.modify(|_, w| w.afr5().af11());
gpioc.ospeedr.modify(|_, w| w.ospeedr5().very_high_speed());
// PB11 RMII_TX_EN
gpiob.moder.modify(|_, w| w.moder11().alternate());
gpiob.afrh.modify(|_, w| w.afr11().af11());
gpiob.ospeedr.modify(|_, w| w.ospeedr11().very_high_speed());
// PB12 RXII_TXD0
gpiob.moder.modify(|_, w| w.moder12().alternate());
gpiob.afrh.modify(|_, w| w.afr12().af11());
gpiob.ospeedr.modify(|_, w| w.ospeedr12().very_high_speed());
// PG14 RMII TXD1
gpiog.moder.modify(|_, w| w.moder14().alternate());
gpiog.afrh.modify(|_, w| w.afr14().af11());
gpiog.ospeedr.modify(|_, w| w.ospeedr14().very_high_speed());
}
const PHY_ADDR: u8 = 0;
fn phy_read(reg_addr: u8) -> u16 {
cortex_m::interrupt::free(|_cs| {
let mac = unsafe { &*stm32::ETHERNET_MAC::ptr() };
while mac.macmdioar.read().mb().bit_is_set() {}
mac.macmdioar.modify(|_, w| unsafe {
w
.pa().bits(PHY_ADDR)
.rda().bits(reg_addr)
.goc().bits(0b11) // read
.cr().bits(CLOCK_RANGE)
.mb().set_bit()
});
while mac.macmdioar.read().mb().bit_is_set() {}
mac.macmdiodr.read().md().bits()
})
}
fn phy_write(reg_addr: u8, reg_data: u16) {
cortex_m::interrupt::free(|_cs| {
let mac = unsafe { &*stm32::ETHERNET_MAC::ptr() };
while mac.macmdioar.read().mb().bit_is_set() {}
mac.macmdiodr.write(|w| unsafe { w.md().bits(reg_data) });
mac.macmdioar.modify(|_, w| unsafe {
w
.pa().bits(PHY_ADDR)
.rda().bits(reg_addr)
.goc().bits(0b01) // read
.cr().bits(CLOCK_RANGE)
.mb().set_bit()
});
while mac.macmdioar.read().mb().bit_is_set() {}
})
}
// Writes a value to an extended PHY register in MMD address space
fn phy_write_ext(reg_addr: u16, reg_data: u16) {
phy_write(PHY_REG_CTL, 0x0003); // set address
phy_write(PHY_REG_ADDAR, reg_addr);
phy_write(PHY_REG_CTL, 0x4003); // set data
phy_write(PHY_REG_ADDAR, reg_data);
}
#[repr(align(4))]
struct RxRing {
desc_buf: [[u32; ETH_DESC_U32_SIZE]; ETH_RX_BUFFER_COUNT],
pkt_buf: [[u8; ETH_RX_BUFFER_SIZE]; ETH_RX_BUFFER_COUNT],
cur_desc: usize,
counter: u32,
}
impl RxRing {
const fn new() -> Self {
Self {
desc_buf: [[0; ETH_DESC_U32_SIZE]; ETH_RX_BUFFER_COUNT],
pkt_buf: [[0; ETH_RX_BUFFER_SIZE]; ETH_RX_BUFFER_COUNT],
cur_desc: 0,
counter: 0,
}
}
fn init(&mut self) {
for i in 0..self.desc_buf.len() {
for j in 0..self.desc_buf[0].len() {
self.desc_buf[i][j] = 0;
}
for j in 0..self.pkt_buf[0].len() {
self.pkt_buf[i][j] = 0;
}
}
cortex_m::interrupt::free(|_cs| unsafe {
let dma = &*stm32::ETHERNET_DMA::ptr();
dma.dmacrx_dlar.write(|w| {
w.bits(&self.desc_buf as *const _ as u32)
});
dma.dmacrx_rlr.write(|w| {
w.rdrl().bits(self.desc_buf.len() as u16 - 1) // FIXME: unclear
});
});
self.cur_desc = 0;
for _ in 0..self.desc_buf.len() {
self.buf_release()
}
self.counter = 0;
}
fn next_desc(&self) -> usize {
(self.cur_desc + 1) % self.desc_buf.len()
}
// not owned by DMA
fn buf_owned(&self) -> bool {
self.desc_buf[self.cur_desc][3] & EMAC_DES3_OWN == 0
}
fn buf_valid(&self) -> bool {
self.desc_buf[self.cur_desc][3] &
(EMAC_DES3_FD | EMAC_DES3_LD | EMAC_DES3_ES | EMAC_DES3_CTXT) ==
(EMAC_DES3_FD | EMAC_DES3_LD)
}
unsafe fn buf_as_slice<'a>(&self) -> &'a [u8] {
let len = (self.desc_buf[self.cur_desc][3] & EMAC_RDES3_PL) as usize;
let len = cmp::min(len, ETH_RX_BUFFER_SIZE);
let addr = &self.pkt_buf[self.cur_desc] as *const u8;
slice::from_raw_parts(addr, len)
}
fn buf_release(&mut self) {
let addr = &self.pkt_buf[self.cur_desc] as *const _;
self.desc_buf[self.cur_desc][0] = addr as u32 & EMAC_DES0_BUF1AP;
self.desc_buf[self.cur_desc][3] = EMAC_RDES3_BUF1V | EMAC_RDES3_IOC | EMAC_DES3_OWN;
let addr = &self.desc_buf[self.cur_desc] as *const _;
cortex_m::interrupt::free(|_cs| {
let dma = unsafe { &*stm32::ETHERNET_DMA::ptr() };
dma.dmacrx_dtpr.write(|w| unsafe { w.bits(addr as u32) });
});
self.cur_desc = self.next_desc();
self.counter += 1;
}
}
#[repr(align(4))]
struct TxRing {
desc_buf: [[u32; ETH_DESC_U32_SIZE]; ETH_TX_BUFFER_COUNT],
pkt_buf: [[u8; ETH_TX_BUFFER_SIZE]; ETH_TX_BUFFER_COUNT],
cur_desc: usize,
counter: u32,
}
impl TxRing {
const fn new() -> Self {
Self {
desc_buf: [[0; ETH_DESC_U32_SIZE]; ETH_TX_BUFFER_COUNT],
pkt_buf: [[0; ETH_TX_BUFFER_SIZE]; ETH_TX_BUFFER_COUNT],
cur_desc: 0,
counter: 0,
}
}
fn init(&mut self) {
for i in 0..self.desc_buf.len() {
for j in 0..self.desc_buf[0].len() {
self.desc_buf[i][j] = 0;
}
for j in 0..self.pkt_buf[0].len() {
self.pkt_buf[i][j] = 0;
}
}
self.cur_desc = 0;
self.counter = 0;
cortex_m::interrupt::free(|_cs| unsafe {
let dma = &*stm32::ETHERNET_DMA::ptr();
dma.dmactx_dlar.write(|w| {
w.bits(&self.desc_buf as *const _ as u32)
});
dma.dmactx_rlr.write(|w| {
w.tdrl().bits(self.desc_buf.len() as u16 - 1) // FIXME: unclear
});
dma.dmactx_dtpr.write(|w| {
w.bits(&self.desc_buf[0] as *const _ as u32)
});
});
}
fn next_desc(&self) -> usize {
(self.cur_desc + 1) % self.desc_buf.len()
}
// not owned by DMA
fn buf_owned(&self) -> bool {
self.desc_buf[self.cur_desc][3] & EMAC_DES3_OWN == 0
}
unsafe fn buf_as_slice_mut<'a>(&mut self, len: usize) -> &'a mut [u8] {
let len = cmp::min(len, ETH_TX_BUFFER_SIZE);
self.desc_buf[self.cur_desc][2] = EMAC_TDES2_IOC | (len as u32 & EMAC_TDES2_B1L);
let addr = &self.pkt_buf[self.cur_desc] as *const _ as *mut u8;
self.desc_buf[self.cur_desc][0] = addr as u32 & EMAC_DES0_BUF1AP;
slice::from_raw_parts_mut(addr, len)
}
fn buf_release(&mut self) {
self.desc_buf[self.cur_desc][3] = EMAC_DES3_OWN | EMAC_DES3_FD | EMAC_DES3_LD;
self.cur_desc = self.next_desc();
self.counter += 1;
let addr = &self.desc_buf[self.cur_desc] as *const _;
cortex_m::interrupt::free(|_cs| {
let dma = unsafe { &*stm32::ETHERNET_DMA::ptr() };
dma.dmactx_dtpr.write(|w| unsafe { w.bits(addr as u32) });
});
}
}
pub struct Device {
rx: RxRing,
tx: TxRing,
}
impl Device {
pub const fn new() -> Self {
Self{ rx: RxRing::new(), tx: TxRing::new() }
}
// After `init` is called, `Device` shall not be moved.
pub unsafe fn init(&mut self, mac: EthernetAddress) {
cortex_m::interrupt::free(|_cs| {
let eth_mac = &*stm32::ETHERNET_MAC::ptr();
let eth_dma = &*stm32::ETHERNET_DMA::ptr();
let _eth_mmc = &*stm32::ETHERNET_MMC::ptr();
let eth_mtl = &*stm32::ETHERNET_MTL::ptr();
eth_dma.dmamr.modify(|_, w| w.swr().set_bit());
while eth_dma.dmamr.read().swr().bit_is_set() {}
// 200 MHz
eth_mac.mac1ustcr.modify(|_, w| w.tic_1us_cntr().bits(200 - 1));
// Configuration Register
eth_mac.maccr.modify(|_, w| {
w
.arpen().clear_bit()
.ipc().set_bit()
.ipg().bits(0b000) // 96 bit
.ecrsfd().clear_bit()
.dcrs().clear_bit()
.bl().bits(0b00) // 19
.prelen().bits(0b00) // 7
// CRC stripping for Type frames
.cst().set_bit()
// Fast Ethernet speed
.fes().set_bit()
// Duplex mode
.dm().set_bit()
// Automatic pad/CRC stripping
.acs().set_bit()
// Retry disable in half-duplex mode
.dr().set_bit()
});
eth_mac.macecr.modify(|_, w| {
w
.eipgen().clear_bit()
.usp().clear_bit()
.spen().clear_bit()
.dcrcc().clear_bit()
});
// Set the MAC address
eth_mac.maca0lr.write(|w|
w.addrlo().bits( mac.0[0] as u32 |
((mac.0[1] as u32) << 8) |
((mac.0[2] as u32) << 16) |
((mac.0[3] as u32) << 24))
);
eth_mac.maca0hr.write(|w|
w.addrhi().bits( mac.0[4] as u16 |
((mac.0[5] as u16) << 8))
//.ae().set_bit()
//.sa().clear_bit()
//.mbc().bits(0b000000)
);
// frame filter register
eth_mac.macpfr.modify(|_, w| {
w
.dntu().clear_bit()
.ipfe().clear_bit()
.vtfe().clear_bit()
.hpf().clear_bit()
.saf().clear_bit()
.saif().clear_bit()
.pcf().bits(0b00)
.dbf().clear_bit()
.pm().clear_bit()
.daif().clear_bit()
.hmc().clear_bit()
.huc().clear_bit()
// Receive All
.ra().clear_bit()
// Promiscuous mode
.pr().clear_bit()
});
eth_mac.macwtr.write(|w| w.pwe().clear_bit());
// Flow Control Register
eth_mac.macqtxfcr.modify(|_, w| {
// Pause time
w.pt().bits(0x100)
});
eth_mac.macrxfcr.modify(|_, w| w);
eth_mtl.mtlrxqomr.modify(|_, w|
w
// Receive store and forward
.rsf().set_bit()
// Dropping of TCP/IP checksum error frames disable
.dis_tcp_ef().clear_bit()
// Forward error frames
.fep().clear_bit()
// Forward undersized good packets
.fup().clear_bit()
);
eth_mtl.mtltxqomr.modify(|_, w| {
w
// Transmit store and forward
.tsf().set_bit()
});
if (phy_read(PHY_REG_ID1) != 0x0007) | (phy_read(PHY_REG_ID2) != 0xC131) {
error!("PHY ID error!");
}
phy_write(PHY_REG_BCR, PHY_REG_BCR_RESET);
while phy_read(PHY_REG_BCR) & PHY_REG_BCR_RESET == PHY_REG_BCR_RESET {};
phy_write_ext(PHY_REG_WUCSR, 0);
phy_write(PHY_REG_BCR, PHY_REG_BCR_AN | PHY_REG_BCR_ANRST | PHY_REG_BCR_100M);
/*
while phy_read(PHY_REG_BSR) & PHY_REG_BSR_UP == 0 {};
while phy_read(PHY_REG_BSR) & PHY_REG_BSR_ANDONE == 0 {};
while phy_read(PHY_REG_SSR) & (PHY_REG_SSR_ANDONE | PHY_REG_SSR_SPEED)
!= PHY_REG_SSR_ANDONE | PHY_REG_SSR_100BASE_FD {};
*/
// operation mode register
eth_dma.dmamr.modify(|_, w| {
w
.intm().clear_bit() // FIXME: bits(0b00)
// Rx Tx priority ratio 1:1
.pr().bits(0b000)
.txpr().clear_bit()
.da().clear_bit()
});
// bus mode register
eth_dma.dmasbmr.modify(|_, w| {
// Address-aligned beats
w.aal().set_bit()
// Fixed burst
.fb().set_bit()
});
eth_dma.dmaccr.modify(|_, w| {
w
.dsl().bits(0)
.pblx8().clear_bit()
.mss().bits(536)
});
eth_dma.dmactx_cr.modify(|_, w| {
w
// Tx DMA PBL
.txpbl().bits(32)
.tse().clear_bit()
// Operate on second frame
.osf().clear_bit()
});
eth_dma.dmacrx_cr.modify(|_, w| {
w
// receive buffer size
.rbsz().bits(MTU as u16)
// Rx DMA PBL
.rxpbl().bits(32)
// Disable flushing of received frames
.rpf().clear_bit()
});
self.rx.init();
self.tx.init();
// Manage MAC transmission and reception
eth_mac.maccr.modify(|_, w| {
w.re().bit(true) // Receiver Enable
.te().bit(true) // Transmiter Enable
});
eth_mtl.mtltxqomr.modify(|_, w| w.ftq().set_bit());
// Manage DMA transmission and reception
eth_dma.dmactx_cr.modify(|_, w| w.st().set_bit());
eth_dma.dmacrx_cr.modify(|_, w| w.sr().set_bit());
eth_dma.dmacsr.modify(|_, w|
w.tps().set_bit()
.rps().set_bit()
);
});
}
}
impl<'a, 'b> phy::Device<'a> for &'b mut Device {
type RxToken = RxToken<'a>;
type TxToken = TxToken<'a>;
fn capabilities(&self) -> phy::DeviceCapabilities {
let mut capabilities = phy::DeviceCapabilities::default();
capabilities.max_transmission_unit = 1500;
capabilities.max_burst_size = Some(self.tx.desc_buf.len());
capabilities
}
fn receive(&mut self) -> Option<(RxToken, TxToken)> {
// Skip all queued packets with errors.
while self.rx.buf_owned() && !self.rx.buf_valid() {
self.rx.buf_release()
}
if !(self.rx.buf_owned() && self.tx.buf_owned()) {
return None
}
Some((RxToken(&mut self.rx), TxToken(&mut self.tx)))
}
fn transmit(&mut self) -> Option<TxToken> {
if !self.tx.buf_owned() {
return None
}
Some(TxToken(&mut self.tx))
}
}
pub struct RxToken<'a>(&'a mut RxRing);
impl<'a> phy::RxToken for RxToken<'a> {
fn consume<R, F>(self, _timestamp: Instant, f: F) -> Result<R>
where F: FnOnce(&[u8]) -> Result<R> {
let result = f(unsafe { self.0.buf_as_slice() });
self.0.buf_release();
result
}
}
pub struct TxToken<'a>(&'a mut TxRing);
impl<'a> phy::TxToken for TxToken<'a> {
fn consume<R, F>(self, _timestamp: Instant, len: usize, f: F) -> Result<R>
where F: FnOnce(&mut [u8]) -> Result<R> {
let result = f(unsafe { self.0.buf_as_slice_mut(len) });
self.0.buf_release();
result
}
}
pub fn eth_interrupt_handler(eth_dma: &stm32::ETHERNET_DMA) {
eth_dma.dmacsr.write(|w|
w
.nis().set_bit()
.ri().set_bit()
.ti().set_bit()
);
}
pub fn enable_interrupt(dma: &stm32::ETHERNET_DMA) {
dma.dmacier.modify(|_, w|
w
.nie().set_bit()
.rie().set_bit()
.tie().set_bit()
);
}

View File

@ -14,10 +14,15 @@ extern crate log;
use core::ptr; use core::ptr;
use core::cell::RefCell; use core::cell::RefCell;
use core::fmt::Write;
use cortex_m_rt::{entry, exception}; use cortex_m_rt::{entry, exception};
use stm32h7::stm32h7x3::{self as stm32, Peripherals, CorePeripherals, interrupt}; use stm32h7::stm32h7x3::{self as stm32, Peripherals, CorePeripherals, interrupt};
use cortex_m::interrupt::Mutex; use cortex_m::interrupt::Mutex;
use smoltcp as net;
mod eth;
mod iir; mod iir;
use iir::*; use iir::*;
@ -49,14 +54,14 @@ mod build_info {
fn pwr_setup(pwr: &stm32::PWR) { fn pwr_setup(pwr: &stm32::PWR) {
// go to VOS1 voltage scale for high perf // go to VOS1 voltage scale for high perf
pwr.pwr_cr3.write(|w| pwr.cr3.write(|w|
w.sden().set_bit() w.sden().set_bit()
.ldoen().set_bit() .ldoen().set_bit()
.bypass().clear_bit() .bypass().clear_bit()
); );
while pwr.pwr_csr1.read().actvosrdy().bit_is_clear() {} while pwr.csr1.read().actvosrdy().bit_is_clear() {}
pwr.pwr_d3cr.write(|w| unsafe { w.vos().bits(0b11) }); // vos1 pwr.d3cr.write(|w| unsafe { w.vos().bits(0b11) }); // vos1
while pwr.pwr_d3cr.read().vosrdy().bit_is_clear() {} while pwr.d3cr.read().vosrdy().bit_is_clear() {}
} }
fn rcc_reset(rcc: &stm32::RCC) { fn rcc_reset(rcc: &stm32::RCC) {
@ -327,7 +332,7 @@ fn gpio_setup(gpioa: &stm32::GPIOA, gpiob: &stm32::GPIOB, gpiod: &stm32::GPIOD,
// ADC0 // ADC0
fn spi1_setup(spi1: &stm32::SPI1) { fn spi1_setup(spi1: &stm32::SPI1) {
spi1.cfg1.modify(|_, w| unsafe { spi1.cfg1.modify(|_, w| {
w.mbr().bits(1) // clk/4 w.mbr().bits(1) // clk/4
.dsize().bits(16 - 1) .dsize().bits(16 - 1)
.fthvl().bits(1 - 1) // one data .fthvl().bits(1 - 1) // one data
@ -348,7 +353,7 @@ fn spi1_setup(spi1: &stm32::SPI1) {
.midi().bits(0) // master inter data idle .midi().bits(0) // master inter data idle
.mssi().bits(6) // master SS idle .mssi().bits(6) // master SS idle
}); });
spi1.cr2.modify(|_, w| unsafe { spi1.cr2.modify(|_, w| {
w.tsize().bits(1) w.tsize().bits(1)
}); });
spi1.cr1.write(|w| w.spe().set_bit()); spi1.cr1.write(|w| w.spe().set_bit());
@ -356,7 +361,7 @@ fn spi1_setup(spi1: &stm32::SPI1) {
// ADC1 // ADC1
fn spi5_setup(spi5: &stm32::SPI5) { fn spi5_setup(spi5: &stm32::SPI5) {
spi5.cfg1.modify(|_, w| unsafe { spi5.cfg1.modify(|_, w| {
w.mbr().bits(1) // clk/4 w.mbr().bits(1) // clk/4
.dsize().bits(16 - 1) .dsize().bits(16 - 1)
.fthvl().bits(1 - 1) // one data .fthvl().bits(1 - 1) // one data
@ -377,7 +382,7 @@ fn spi5_setup(spi5: &stm32::SPI5) {
.midi().bits(0) // master inter data idle .midi().bits(0) // master inter data idle
.mssi().bits(6) // master SS idle .mssi().bits(6) // master SS idle
}); });
spi5.cr2.modify(|_, w| unsafe { spi5.cr2.modify(|_, w| {
w.tsize().bits(1) w.tsize().bits(1)
}); });
spi5.cr1.write(|w| w.spe().set_bit()); spi5.cr1.write(|w| w.spe().set_bit());
@ -385,7 +390,7 @@ fn spi5_setup(spi5: &stm32::SPI5) {
// DAC0 // DAC0
fn spi2_setup(spi2: &stm32::SPI2) { fn spi2_setup(spi2: &stm32::SPI2) {
spi2.cfg1.modify(|_, w| unsafe { spi2.cfg1.modify(|_, w| {
w.mbr().bits(0) // clk/2 w.mbr().bits(0) // clk/2
.dsize().bits(16 - 1) .dsize().bits(16 - 1)
.fthvl().bits(1 - 1) // one data .fthvl().bits(1 - 1) // one data
@ -406,7 +411,7 @@ fn spi2_setup(spi2: &stm32::SPI2) {
.midi().bits(0) // master inter data idle .midi().bits(0) // master inter data idle
.mssi().bits(0) // master SS idle .mssi().bits(0) // master SS idle
}); });
spi2.cr2.modify(|_, w| unsafe { spi2.cr2.modify(|_, w| {
w.tsize().bits(0) w.tsize().bits(0)
}); });
spi2.cr1.write(|w| w.spe().set_bit()); spi2.cr1.write(|w| w.spe().set_bit());
@ -415,7 +420,7 @@ fn spi2_setup(spi2: &stm32::SPI2) {
// DAC1 // DAC1
fn spi4_setup(spi4: &stm32::SPI4) { fn spi4_setup(spi4: &stm32::SPI4) {
spi4.cfg1.modify(|_, w| unsafe { spi4.cfg1.modify(|_, w| {
w.mbr().bits(0) // clk/2 w.mbr().bits(0) // clk/2
.dsize().bits(16 - 1) .dsize().bits(16 - 1)
.fthvl().bits(1 - 1) // one data .fthvl().bits(1 - 1) // one data
@ -436,7 +441,7 @@ fn spi4_setup(spi4: &stm32::SPI4) {
.midi().bits(0) // master inter data idle .midi().bits(0) // master inter data idle
.mssi().bits(0) // master SS idle .mssi().bits(0) // master SS idle
}); });
spi4.cr2.modify(|_, w| unsafe { spi4.cr2.modify(|_, w| {
w.tsize().bits(0) w.tsize().bits(0)
}); });
spi4.cr1.write(|w| w.spe().set_bit()); spi4.cr1.write(|w| w.spe().set_bit());
@ -460,7 +465,7 @@ fn dma1_setup(dma1: &stm32::DMA1, dmamux1: &stm32::DMAMUX1, ma: usize, pa0: usiz
dma1.s0par.write(|w| unsafe { w.pa().bits(pa0 as u32) }); dma1.s0par.write(|w| unsafe { w.pa().bits(pa0 as u32) });
dma1.s0m0ar.write(|w| unsafe { w.m0a().bits(ma as u32) }); dma1.s0m0ar.write(|w| unsafe { w.m0a().bits(ma as u32) });
dma1.s0ndtr.write(|w| unsafe { w.ndt().bits(1) }); dma1.s0ndtr.write(|w| unsafe { w.ndt().bits(1) });
dmamux1.dmamux1_c0cr.modify(|_, w| unsafe { w.dmareq_id().bits(22) }); // tim2_up dmamux1.ccr[0].modify(|_, w| unsafe { w.dmareq_id().bits(22) }); // tim2_up
dma1.s0cr.modify(|_, w| unsafe { dma1.s0cr.modify(|_, w| unsafe {
w.pl().bits(0b01) // medium w.pl().bits(0b01) // medium
.circ().set_bit() // reload ndtr .circ().set_bit() // reload ndtr
@ -483,7 +488,7 @@ fn dma1_setup(dma1: &stm32::DMA1, dmamux1: &stm32::DMAMUX1, ma: usize, pa0: usiz
dma1.s1par.write(|w| unsafe { w.pa().bits(pa1 as u32) }); dma1.s1par.write(|w| unsafe { w.pa().bits(pa1 as u32) });
dma1.s1m0ar.write(|w| unsafe { w.m0a().bits(ma as u32) }); dma1.s1m0ar.write(|w| unsafe { w.m0a().bits(ma as u32) });
dma1.s1ndtr.write(|w| unsafe { w.ndt().bits(1) }); dma1.s1ndtr.write(|w| unsafe { w.ndt().bits(1) });
dmamux1.dmamux1_c1cr.modify(|_, w| unsafe { w.dmareq_id().bits(22) }); // tim2_up dmamux1.ccr[1].modify(|_, w| unsafe { w.dmareq_id().bits(22) }); // tim2_up
dma1.s1cr.modify(|_, w| unsafe { dma1.s1cr.modify(|_, w| unsafe {
w.pl().bits(0b01) // medium w.pl().bits(0b01) // medium
.circ().set_bit() // reload ndtr .circ().set_bit() // reload ndtr
@ -499,7 +504,6 @@ fn dma1_setup(dma1: &stm32::DMA1, dmamux1: &stm32::DMAMUX1, ma: usize, pa0: usiz
}); });
dma1.s1fcr.modify(|_, w| w.dmdis().clear_bit()); dma1.s1fcr.modify(|_, w| w.dmdis().clear_bit());
dma1.s1cr.modify(|_, w| w.en().set_bit()); dma1.s1cr.modify(|_, w| w.en().set_bit());
} }
static SPIP: Mutex<RefCell<Option<( static SPIP: Mutex<RefCell<Option<(
@ -509,6 +513,26 @@ static SPIP: Mutex<RefCell<Option<(
#[link_section = ".sram1"] #[link_section = ".sram1"]
static mut DAT: u32 = (1 << 9) | (1 << 0); static mut DAT: u32 = (1 << 9) | (1 << 0);
static TIME: Mutex<RefCell<i64>> = Mutex::new(RefCell::new(0));
#[link_section = ".sram3"]
static mut ETH: eth::Device = eth::Device::new();
const TCP_RX_BUFFER_SIZE: usize = 4096;
const TCP_TX_BUFFER_SIZE: usize = 4096;
macro_rules! create_socket {
($set:ident, $rx_storage:ident, $tx_storage:ident, $target:ident) => (
let mut $rx_storage = [0; TCP_RX_BUFFER_SIZE];
let mut $tx_storage = [0; TCP_TX_BUFFER_SIZE];
let tcp_rx_buffer = net::socket::TcpSocketBuffer::new(&mut $rx_storage[..]);
let tcp_tx_buffer = net::socket::TcpSocketBuffer::new(&mut $tx_storage[..]);
let tcp_socket = net::socket::TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
let $target = $set.add(tcp_socket);
)
}
#[entry] #[entry]
fn main() -> ! { fn main() -> ! {
let mut cp = CorePeripherals::take().unwrap(); let mut cp = CorePeripherals::take().unwrap();
@ -527,13 +551,22 @@ fn main() -> ! {
rcc.apb4enr.modify(|_, w| w.syscfgen().set_bit()); rcc.apb4enr.modify(|_, w| w.syscfgen().set_bit());
io_compensation_setup(&dp.SYSCFG); io_compensation_setup(&dp.SYSCFG);
// 100 MHz
cp.SYST.set_clock_source(cortex_m::peripheral::syst::SystClkSource::Core);
cp.SYST.set_reload(cortex_m::peripheral::SYST::get_ticks_per_10ms()*200/10);
cp.SYST.enable_counter();
cp.SYST.enable_interrupt();
unsafe { cp.SCB.shpr[11].write(128); } // systick exception priority
cp.SCB.enable_icache(); cp.SCB.enable_icache();
cp.SCB.enable_dcache(&mut cp.CPUID); // TODO: ETH DMA coherence issues
// cp.SCB.enable_dcache(&mut cp.CPUID);
cp.DWT.enable_cycle_counter(); cp.DWT.enable_cycle_counter();
rcc.ahb4enr.modify(|_, w| rcc.ahb4enr.modify(|_, w|
w.gpioaen().set_bit() w.gpioaen().set_bit()
.gpioben().set_bit() .gpioben().set_bit()
.gpiocen().set_bit()
.gpioden().set_bit() .gpioden().set_bit()
.gpioeen().set_bit() .gpioeen().set_bit()
.gpiofen().set_bit() .gpiofen().set_bit()
@ -559,7 +592,12 @@ fn main() -> ! {
spi5_setup(&spi5); spi5_setup(&spi5);
// spi5.ier.write(|w| w.eotie().set_bit()); // spi5.ier.write(|w| w.eotie().set_bit());
rcc.ahb2enr.modify(|_, w| w.sram1en().set_bit()); rcc.ahb2enr.modify(|_, w|
w
.sram1en().set_bit()
.sram2en().set_bit()
.sram3en().set_bit()
);
rcc.ahb1enr.modify(|_, w| w.dma1en().set_bit()); rcc.ahb1enr.modify(|_, w| w.dma1en().set_bit());
unsafe { DAT = (1 << 9) | (1 << 0) }; // init SRAM1 rodata can't load with sram1 disabled unsafe { DAT = (1 << 9) | (1 << 0) }; // init SRAM1 rodata can't load with sram1 disabled
cortex_m::asm::dsb(); cortex_m::asm::dsb();
@ -589,16 +627,62 @@ fn main() -> ! {
IIR_CH[1].get_x_offset().unwrap(); IIR_CH[1].get_x_offset().unwrap();
} }
unsafe { cp.NVIC.set_priority(stm32::Interrupt::SPI1, 0); } // highest prio
cortex_m::interrupt::free(|cs| { cortex_m::interrupt::free(|cs| {
cp.NVIC.enable(stm32::Interrupt::SPI1); cp.NVIC.enable(stm32::Interrupt::SPI1);
SPIP.borrow(cs).replace(Some((spi1, spi2, spi4, spi5))); SPIP.borrow(cs).replace(Some((spi1, spi2, spi4, spi5)));
}); });
eth::setup(&rcc, &dp.SYSCFG);
eth::setup_pins(&dp.GPIOA, &dp.GPIOB, &dp.GPIOC, &dp.GPIOG);
let device = unsafe { &mut ETH };
let hardware_addr = net::wire::EthernetAddress([0x10, 0xE2, 0xD5, 0x00, 0x03, 0x00]);
unsafe { device.init(hardware_addr) };
let mut neighbor_cache_storage = [None; 8];
let neighbor_cache = net::iface::NeighborCache::new(&mut neighbor_cache_storage[..]);
let local_addr = net::wire::IpAddress::v4(10, 0, 16, 99);
let mut ip_addrs = [net::wire::IpCidr::new(local_addr, 24)];
let mut iface = net::iface::EthernetInterfaceBuilder::new(device)
.ethernet_addr(hardware_addr)
.neighbor_cache(neighbor_cache)
.ip_addrs(&mut ip_addrs[..])
.finalize();
let mut socket_set_entries: [_; 8] = Default::default();
let mut sockets = net::socket::SocketSet::new(&mut socket_set_entries[..]);
create_socket!(sockets, tcp_rx_storage0, tcp_tx_storage0, tcp_handle0);
eth::enable_interrupt(&dp.ETHERNET_DMA);
unsafe { cp.NVIC.set_priority(stm32::Interrupt::ETH, 196); } // mid prio
cp.NVIC.enable(stm32::Interrupt::ETH);
loop { loop {
for _ in 0..1_000_000 { cortex_m::asm::wfi(); } let time = cortex_m::interrupt::free(|cs| *TIME.borrow(cs).borrow());
let (x0, y0, x1, y1) = unsafe {
(IIR_STATE[0][0], IIR_STATE[0][2], IIR_STATE[1][0], IIR_STATE[1][2]) }; {
info!("x0={} y0={} x1={} y1={}", x0, y0, x1, y1); let socket = &mut *sockets.get::<net::socket::TcpSocket>(tcp_handle0);
if !socket.is_open() {
socket.listen(80).unwrap_or_else(|e| warn!("TCP listen error: {:?}", e));
}
if socket.can_send() {
write!(socket, "hello\n")
.map(|_| socket.close())
.unwrap_or_else(|e| warn!("TCP send error: {:?}", e));
}
}
match iface.poll(&mut sockets, net::time::Instant::from_millis(time)) {
Ok(_) => (),
Err(e) => info!("iface poll error: {:?}", e)
}
if time % 1000 == 0 {
let (x0, y0, x1, y1) = unsafe {
(IIR_STATE[0][0], IIR_STATE[0][2], IIR_STATE[1][0], IIR_STATE[1][2]) };
info!("x0={:.1} y0={:.1} x1={:.1} y1={:.1}", x0, y0, x1, y1);
}
cortex_m::asm::wfi();
} }
} }
@ -648,6 +732,17 @@ fn SPI1() {
cortex_m::asm::bkpt(); cortex_m::asm::bkpt();
} }
#[interrupt]
fn ETH() {
let p = unsafe { Peripherals::steal() };
eth::eth_interrupt_handler(&p.ETHERNET_DMA);
}
#[exception]
fn SysTick() {
cortex_m::interrupt::free(|cs| *TIME.borrow(cs).borrow_mut() += 1);
}
#[exception] #[exception]
fn HardFault(ef: &cortex_m_rt::ExceptionFrame) -> ! { fn HardFault(ef: &cortex_m_rt::ExceptionFrame) -> ! {
panic!("HardFault at {:#?}", ef); panic!("HardFault at {:#?}", ef);