diff --git a/Cargo.lock b/Cargo.lock index 6133b9e..65045c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,8 +2,20 @@ # It is not intended for manual editing. [[package]] name = "aligned" -version = "0.2.0" +version = "0.3.1" 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]] name = "bare-metal" @@ -46,21 +58,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cortex-m" -version = "0.5.8" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" 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)", "volatile-register 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cortex-m-log" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cortex-m 0.5.8 (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 0.6.0 (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)", ] @@ -78,18 +90,26 @@ name = "cortex-m-rt-macros" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" 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)", "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]] name = "cortex-m-semihosting" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" 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]] @@ -141,14 +161,6 @@ dependencies = [ "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]] name = "log" version = "0.4.6" @@ -175,10 +187,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "panic-semihosting" 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 = [ - "cortex-m 0.5.8 (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 0.6.0 (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]] @@ -193,7 +205,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "proc-macro2" -version = "0.4.27" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -204,7 +216,7 @@ name = "quote" version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" 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]] @@ -276,7 +288,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "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)", - "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)", ] @@ -284,34 +295,40 @@ dependencies = [ name = "stabilizer" version = "0.1.0" 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)", - "cortex-m 0.5.8 (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 0.6.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)", "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-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)", - "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]] name = "stm32h7" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "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)", "vcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syn" -version = "0.15.31" +version = "0.15.32" source = "registry+https://github.com/rust-lang/crates.io-index" 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)", "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)", ] +[[package]] +name = "typenum" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicode-bidi" version = "0.3.4" @@ -403,32 +425,33 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [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 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 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 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-log 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "62d666a7362a29620140c5a0a8149dd31f06bd6a804240f32359a83ded1e210a" +"checksum cortex-m 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f3c18719fdc57db65668bfc977db9a0fa1a41d718c5d9cd4f652c9d4b0e0956a" +"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-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 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 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 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 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 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)" = "" "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 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 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" @@ -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 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 stm32h7 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2756cb97ac50836393814072493107a42701fecd11a6d228527292479bb1f25" -"checksum syn 0.15.31 (registry+https://github.com/rust-lang/crates.io-index)" = "d2b4cfac95805274c6afdb12d8f770fa2d27c045953e7b630a81801953699a9a" +"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" +"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 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-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" diff --git a/Cargo.toml b/Cargo.toml index 1e12749..2dbfb7b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,15 +27,23 @@ features = [] default-target = "thumbv7em-none-eabihf" [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-log = { version = "0.4", features = ["log-integration"] } -stm32h7 = { version = "0.6", features = ["stm32h7x3", "rt"] } -# stm32h7 = { path = "../stm32-rs/stm32h7", features = ["stm32h7x3", "rt"] } +cortex-m-log = { version = "0.5", features = ["log-integration"] } +stm32h7 = { version = "0.7", features = ["stm32h7x3", "rt"] } log = "0.4" panic-abort = "0.3" -panic-semihosting = { version = "0.5", optional = true } -smoltcp = { version = "0.5", default-features = false, features = ["proto-ipv4", "socket-tcp", "log"] } +# https://github.com/rust-embedded/panic-semihosting/issues/16 +# 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] semihosting = ["panic-semihosting", "cortex-m-log/semihosting"] diff --git a/memory.x b/memory.x index 6aafe08..3b91155 100644 --- a/memory.x +++ b/memory.x @@ -2,9 +2,11 @@ MEMORY { ITCM (rwx) : ORIGIN = 0x00000000, LENGTH = 64K RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128K - RAM_D1 (rwx) : ORIGIN = 0x24000000, LENGTH = 512K - RAM_D2 (rwx) : ORIGIN = 0x30000000, LENGTH = 288K - RAM_D3 (rwx) : ORIGIN = 0x38000000, LENGTH = 64K + AXISRAM (rwx) : ORIGIN = 0x24000000, LENGTH = 512K + SRAM1 (rwx) : ORIGIN = 0x30000000, LENGTH = 128K + 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 FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K FLASH1 (rx) : ORIGIN = 0x08100000, LENGTH = 1024K @@ -14,5 +16,17 @@ SECTIONS { .sram1 (NOLOAD) : ALIGN(4) { *(.sram1); . = 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; diff --git a/src/eth.rs b/src/eth.rs new file mode 100644 index 0000000..b776590 --- /dev/null +++ b/src/eth.rs @@ -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 { + 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(self, _timestamp: Instant, f: F) -> Result + where F: FnOnce(&[u8]) -> Result { + 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(self, _timestamp: Instant, len: usize, f: F) -> Result + where F: FnOnce(&mut [u8]) -> Result { + 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() + ); +} diff --git a/src/main.rs b/src/main.rs index 2131ae1..2f89741 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,10 +14,15 @@ extern crate log; use core::ptr; use core::cell::RefCell; +use core::fmt::Write; use cortex_m_rt::{entry, exception}; use stm32h7::stm32h7x3::{self as stm32, Peripherals, CorePeripherals, interrupt}; use cortex_m::interrupt::Mutex; +use smoltcp as net; + +mod eth; + mod iir; use iir::*; @@ -49,14 +54,14 @@ mod build_info { fn pwr_setup(pwr: &stm32::PWR) { // go to VOS1 voltage scale for high perf - pwr.pwr_cr3.write(|w| + pwr.cr3.write(|w| w.sden().set_bit() .ldoen().set_bit() .bypass().clear_bit() ); - while pwr.pwr_csr1.read().actvosrdy().bit_is_clear() {} - pwr.pwr_d3cr.write(|w| unsafe { w.vos().bits(0b11) }); // vos1 - while pwr.pwr_d3cr.read().vosrdy().bit_is_clear() {} + while pwr.csr1.read().actvosrdy().bit_is_clear() {} + pwr.d3cr.write(|w| unsafe { w.vos().bits(0b11) }); // vos1 + while pwr.d3cr.read().vosrdy().bit_is_clear() {} } fn rcc_reset(rcc: &stm32::RCC) { @@ -327,7 +332,7 @@ fn gpio_setup(gpioa: &stm32::GPIOA, gpiob: &stm32::GPIOB, gpiod: &stm32::GPIOD, // ADC0 fn spi1_setup(spi1: &stm32::SPI1) { - spi1.cfg1.modify(|_, w| unsafe { + spi1.cfg1.modify(|_, w| { w.mbr().bits(1) // clk/4 .dsize().bits(16 - 1) .fthvl().bits(1 - 1) // one data @@ -348,7 +353,7 @@ fn spi1_setup(spi1: &stm32::SPI1) { .midi().bits(0) // master inter data idle .mssi().bits(6) // master SS idle }); - spi1.cr2.modify(|_, w| unsafe { + spi1.cr2.modify(|_, w| { w.tsize().bits(1) }); spi1.cr1.write(|w| w.spe().set_bit()); @@ -356,7 +361,7 @@ fn spi1_setup(spi1: &stm32::SPI1) { // ADC1 fn spi5_setup(spi5: &stm32::SPI5) { - spi5.cfg1.modify(|_, w| unsafe { + spi5.cfg1.modify(|_, w| { w.mbr().bits(1) // clk/4 .dsize().bits(16 - 1) .fthvl().bits(1 - 1) // one data @@ -377,7 +382,7 @@ fn spi5_setup(spi5: &stm32::SPI5) { .midi().bits(0) // master inter data idle .mssi().bits(6) // master SS idle }); - spi5.cr2.modify(|_, w| unsafe { + spi5.cr2.modify(|_, w| { w.tsize().bits(1) }); spi5.cr1.write(|w| w.spe().set_bit()); @@ -385,7 +390,7 @@ fn spi5_setup(spi5: &stm32::SPI5) { // DAC0 fn spi2_setup(spi2: &stm32::SPI2) { - spi2.cfg1.modify(|_, w| unsafe { + spi2.cfg1.modify(|_, w| { w.mbr().bits(0) // clk/2 .dsize().bits(16 - 1) .fthvl().bits(1 - 1) // one data @@ -406,7 +411,7 @@ fn spi2_setup(spi2: &stm32::SPI2) { .midi().bits(0) // master inter data idle .mssi().bits(0) // master SS idle }); - spi2.cr2.modify(|_, w| unsafe { + spi2.cr2.modify(|_, w| { w.tsize().bits(0) }); spi2.cr1.write(|w| w.spe().set_bit()); @@ -415,7 +420,7 @@ fn spi2_setup(spi2: &stm32::SPI2) { // DAC1 fn spi4_setup(spi4: &stm32::SPI4) { - spi4.cfg1.modify(|_, w| unsafe { + spi4.cfg1.modify(|_, w| { w.mbr().bits(0) // clk/2 .dsize().bits(16 - 1) .fthvl().bits(1 - 1) // one data @@ -436,7 +441,7 @@ fn spi4_setup(spi4: &stm32::SPI4) { .midi().bits(0) // master inter data idle .mssi().bits(0) // master SS idle }); - spi4.cr2.modify(|_, w| unsafe { + spi4.cr2.modify(|_, w| { w.tsize().bits(0) }); 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.s0m0ar.write(|w| unsafe { w.m0a().bits(ma as u32) }); 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 { w.pl().bits(0b01) // medium .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.s1m0ar.write(|w| unsafe { w.m0a().bits(ma as u32) }); 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 { w.pl().bits(0b01) // medium .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.s1cr.modify(|_, w| w.en().set_bit()); - } static SPIP: Mutex> = 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] fn main() -> ! { let mut cp = CorePeripherals::take().unwrap(); @@ -527,13 +551,22 @@ fn main() -> ! { rcc.apb4enr.modify(|_, w| w.syscfgen().set_bit()); 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_dcache(&mut cp.CPUID); + // TODO: ETH DMA coherence issues + // cp.SCB.enable_dcache(&mut cp.CPUID); cp.DWT.enable_cycle_counter(); rcc.ahb4enr.modify(|_, w| w.gpioaen().set_bit() .gpioben().set_bit() + .gpiocen().set_bit() .gpioden().set_bit() .gpioeen().set_bit() .gpiofen().set_bit() @@ -559,7 +592,12 @@ fn main() -> ! { spi5_setup(&spi5); // 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()); unsafe { DAT = (1 << 9) | (1 << 0) }; // init SRAM1 rodata can't load with sram1 disabled cortex_m::asm::dsb(); @@ -589,16 +627,62 @@ fn main() -> ! { IIR_CH[1].get_x_offset().unwrap(); } + unsafe { cp.NVIC.set_priority(stm32::Interrupt::SPI1, 0); } // highest prio cortex_m::interrupt::free(|cs| { cp.NVIC.enable(stm32::Interrupt::SPI1); 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 { - for _ in 0..1_000_000 { cortex_m::asm::wfi(); } - 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 time = cortex_m::interrupt::free(|cs| *TIME.borrow(cs).borrow()); + + { + let socket = &mut *sockets.get::(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(); } +#[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] fn HardFault(ef: &cortex_m_rt::ExceptionFrame) -> ! { panic!("HardFault at {:#?}", ef);