forked from M-Labs/zynq-rs
Compare commits
162 Commits
Author | SHA1 | Date |
---|---|---|
Sebastien Bourdeauducq | 12975de2e1 | |
Sebastien Bourdeauducq | 8c404829ef | |
Sebastien Bourdeauducq | 8f041b017c | |
newell | 5815baf88b | |
newell | cc20478d91 | |
Sebastien Bourdeauducq | 5ef3016554 | |
newell | 6a45a0dfd0 | |
Sebastien Bourdeauducq | b2b3e5c933 | |
Simon Renblad | 0efbbe39fe | |
Sebastien Bourdeauducq | 51b8111e79 | |
Simon Renblad | 46dc25b89e | |
Sebastien Bourdeauducq | 731684abb4 | |
Florian Agbuya | 195a21fe78 | |
Florian Agbuya | 96cefe6f06 | |
morgan | 7c58c0cf43 | |
morgan | 9005b73316 | |
morgan | b1994dbe16 | |
morgan | 5bd336c961 | |
morgan | 298f64a2f9 | |
morgan | 4168eb63a7 | |
Sebastien Bourdeauducq | a43b8bf64e | |
Sebastien Bourdeauducq | 91bae572f9 | |
Sebastien Bourdeauducq | 301f9236e5 | |
Sebastien Bourdeauducq | 55b36ee37e | |
morgan | 24c804e6f0 | |
Sebastien Bourdeauducq | be672ab662 | |
mwojcik | 0106430805 | |
jmatyas | c15b54f92b | |
Sebastien Bourdeauducq | de42a5d1b2 | |
Sebastien Bourdeauducq | ff03bf92a3 | |
Sebastien Bourdeauducq | f20c008264 | |
Sebastien Bourdeauducq | 67dbb5932f | |
Sebastien Bourdeauducq | dab5c6f070 | |
Egor Savkin | 0a3a777652 | |
mwojcik | 92b3f3e1dd | |
mwojcik | f586ba5a13 | |
mwojcik | 42cc256812 | |
occheung | 043a152b91 | |
Sebastien Bourdeauducq | 6cd32f6ee0 | |
mwojcik | 605c8f73a6 | |
mwojcik | 56c27e98e4 | |
mwojcik | f496da4f3e | |
mwojcik | 1c8e2c318c | |
mwojcik | 67880b4e0b | |
Sebastien Bourdeauducq | e96222ff6f | |
mwojcik | dc1ca3d3d0 | |
mwojcik | c4c52c33b4 | |
mwojcik | 072fd5f015 | |
mwojcik | 2b3c7e4b2f | |
mwojcik | 84d6d391ce | |
mwojcik | 43e0440911 | |
mwojcik | 3e95df1f64 | |
mwojcik | 26ab2927b9 | |
mwojcik | dacc816eb4 | |
mwojcik | fbc783d7ad | |
mwojcik | 14b0247716 | |
mwojcik | bc41b91192 | |
mwojcik | 3efc682bd6 | |
mwojcik | e5e646f40e | |
Sebastien Bourdeauducq | 2e7cfe04c8 | |
mwojcik | 24e0d724f2 | |
Sebastien Bourdeauducq | 823e909281 | |
Sebastien Bourdeauducq | 57d8d8fbc7 | |
Sebastien Bourdeauducq | a4902966d1 | |
Sebastien Bourdeauducq | 2c161720fa | |
topquark12 | a42e5a95ff | |
Sebastien Bourdeauducq | 03122f810a | |
Sebastien Bourdeauducq | c7e9f85de2 | |
Sebastien Bourdeauducq | 104d1ef232 | |
Sebastien Bourdeauducq | b0ec74d764 | |
Sebastien Bourdeauducq | 4159aab6c8 | |
Sebastien Bourdeauducq | d18c77c0eb | |
Sebastien Bourdeauducq | 8dbe2cf9f3 | |
Sebastien Bourdeauducq | 040d41fd76 | |
Sebastien Bourdeauducq | 9180918619 | |
Sebastien Bourdeauducq | 8ec7216e9a | |
Sebastien Bourdeauducq | 0e9d3f146a | |
Sebastien Bourdeauducq | 411eebd96c | |
sb10q | e31adb722d | |
Sebastien Bourdeauducq | 759bf95a76 | |
Sebastien Bourdeauducq | f83ef218de | |
Sebastien Bourdeauducq | 062b894a4b | |
Sebastien Bourdeauducq | 2f9019ca0f | |
Sebastien Bourdeauducq | 7b29ab2628 | |
Sebastien Bourdeauducq | a9697ec8d8 | |
Sebastien Bourdeauducq | 0220cf19eb | |
Sebastien Bourdeauducq | a11cb852a8 | |
Sebastien Bourdeauducq | 42cdedae91 | |
Sebastien Bourdeauducq | 823ec374ba | |
Sebastien Bourdeauducq | 666c077cef | |
Sebastien Bourdeauducq | def17829d9 | |
Astro | ba252e72da | |
Astro | a2416f26a0 | |
Astro | bf9f1e33c8 | |
Astro | 481a0eb25f | |
Astro | 05c30dd52e | |
Astro | f816a04cef | |
Astro | faa64c2ce8 | |
Astro | 89e4d61dc0 | |
Astro | 0b07e9fefc | |
Astro | ccf758cc85 | |
pca006132 | 78d58d17ec | |
pca006132 | 06c646e61f | |
pca006132 | 7681745282 | |
pca006132 | 6e6612bc3e | |
pca006132 | b50540915d | |
pca006132 | 4aa252546f | |
pca006132 | b42869e655 | |
pca006132 | d62c77e6e0 | |
pca006132 | 4555afa624 | |
pca006132 | 5923a66512 | |
pca006132 | 2c6cc58c07 | |
Astro | b4d91e7904 | |
Astro | 4c79c797d5 | |
Astro | 966e43e14e | |
Astro | 8432ff3e30 | |
Astro | 1cd4056370 | |
Astro | ddff295ae1 | |
Astro | 379b6b973a | |
Astro | 178ab38e35 | |
Astro | 3172aba1a8 | |
Astro | a62ca507d0 | |
Astro | 975202a653 | |
Astro | d76a77b443 | |
Astro | 500472b2a8 | |
Astro | 02217f27d1 | |
Astro | a3eabf1947 | |
Astro | a32d7abb9a | |
Sebastien Bourdeauducq | 0e8354faa1 | |
Sebastien Bourdeauducq | 07f161d9d8 | |
Sebastien Bourdeauducq | ef160aa841 | |
Astro | cb50c8d61b | |
Astro | 7bbd16f143 | |
Astro | 0714162113 | |
Astro | 5b2c779cba | |
Astro | 0a40d4f36d | |
Astro | 55f8d02da8 | |
Astro | 990fa56d6a | |
Astro | 8fd317d580 | |
Astro | 07fedddad9 | |
Astro | 0fde82a982 | |
Astro | dffe3cb251 | |
Astro | b9323653bb | |
Astro | 515d3bb381 | |
Astro | 7e22010d7d | |
Astro | 9ee77d8f44 | |
Astro | e508b78b3e | |
Astro | aef010cb14 | |
pca006132 | d623913535 | |
pca006132 | 0efc7a616f | |
pca006132 | 22833ef0c6 | |
Sebastien Bourdeauducq | 80d12d5780 | |
Sebastien Bourdeauducq | 4dd8c93729 | |
Sebastien Bourdeauducq | 6266d28095 | |
Sebastien Bourdeauducq | 1796d4e236 | |
Sebastien Bourdeauducq | 56c94b0855 | |
Sebastien Bourdeauducq | 34a63d7732 | |
Sebastien Bourdeauducq | 27d310a937 | |
pca006132 | f60d0589cc | |
Sebastien Bourdeauducq | 7c9edfdbd5 | |
pca006132 | c336e450b1 | |
pca006132 | 6af453494b |
|
@ -1 +1,2 @@
|
||||||
/target
|
/target
|
||||||
|
result*
|
||||||
|
|
|
@ -4,238 +4,255 @@
|
||||||
name = "bit_field"
|
name = "bit_field"
|
||||||
version = "0.10.1"
|
version = "0.10.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.2.1"
|
version = "1.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.3.4"
|
version = "1.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.0.73"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "0.1.10"
|
version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "compiler_builtins"
|
name = "compiler_builtins"
|
||||||
version = "0.1.35"
|
version = "0.1.39"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3748f82c7d366a0b4950257d19db685d4958d2fa27c6d164a3f069fec42b748b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core_io"
|
name = "core_io"
|
||||||
version = "0.1.20200410"
|
version = "0.1.20210325"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "97f8932064288cc79feb4d343a399d353a6f6f001e586ece47fe518a9e8507df"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc_version",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embedded-hal"
|
name = "embedded-hal"
|
||||||
version = "0.2.4"
|
version = "0.2.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nb 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"nb 0.1.3",
|
||||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"void",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "experiments"
|
name = "experiments"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"embedded-hal 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"embedded-hal",
|
||||||
"libasync 0.0.0",
|
"libasync",
|
||||||
"libboard_zynq 0.0.0",
|
"libboard_zynq",
|
||||||
"libcortex_a9 0.0.0",
|
"libcortex_a9",
|
||||||
"libregister 0.0.0",
|
"libregister",
|
||||||
"libsupport_zynq 0.0.0",
|
"libsupport_zynq",
|
||||||
"log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fatfs"
|
name = "fatfs"
|
||||||
version = "0.3.4"
|
version = "0.3.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e18f80a87439240dac45d927fd8f8081b6f1e34c03e97271189fa8a8c2e96c8f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags",
|
||||||
"byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder",
|
||||||
"core_io 0.1.20200410",
|
"core_io",
|
||||||
"log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libasync"
|
name = "libasync"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"embedded-hal 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"embedded-hal",
|
||||||
"libcortex_a9 0.0.0",
|
"libcortex_a9",
|
||||||
"nb 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"nb 1.0.0",
|
||||||
"pin-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pin-utils",
|
||||||
"smoltcp 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"smoltcp",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libboard_zynq"
|
name = "libboard_zynq"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bit_field 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bit_field",
|
||||||
"embedded-hal 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"embedded-hal",
|
||||||
"libcortex_a9 0.0.0",
|
"libasync",
|
||||||
"libregister 0.0.0",
|
"libcortex_a9",
|
||||||
"log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libregister",
|
||||||
"nb 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log",
|
||||||
"smoltcp 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"nb 0.1.3",
|
||||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"smoltcp",
|
||||||
"volatile-register 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"void",
|
||||||
|
"volatile-register",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libconfig"
|
name = "libconfig"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"core_io 0.1.20200410",
|
"core_io",
|
||||||
"fatfs 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fatfs",
|
||||||
"libboard_zynq 0.0.0",
|
"libboard_zynq",
|
||||||
"log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libcortex_a9"
|
name = "libcortex_a9"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bit_field 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bit_field",
|
||||||
"libregister 0.0.0",
|
"libregister",
|
||||||
"volatile-register 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"volatile-register",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libregister"
|
name = "libregister"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bit_field 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bit_field",
|
||||||
"vcell 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"vcell",
|
||||||
"volatile-register 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"volatile-register",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libsupport_zynq"
|
name = "libsupport_zynq"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"compiler_builtins 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cc",
|
||||||
"libboard_zynq 0.0.0",
|
"compiler_builtins",
|
||||||
"libcortex_a9 0.0.0",
|
"libboard_zynq",
|
||||||
"libregister 0.0.0",
|
"libcortex_a9",
|
||||||
"linked_list_allocator 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libregister",
|
||||||
"r0 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"linked_list_allocator",
|
||||||
|
"r0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linked_list_allocator"
|
name = "linked_list_allocator"
|
||||||
version = "0.8.5"
|
version = "0.8.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "822add9edb1860698b79522510da17bef885171f75aa395cff099d770c609c24"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.11"
|
version = "0.4.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "managed"
|
name = "managed"
|
||||||
version = "0.7.2"
|
version = "0.7.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c75de51135344a4f8ed3cfe2720dc27736f7711989703a0b43aadf3753c55577"
|
||||||
[[package]]
|
|
||||||
name = "memchr"
|
|
||||||
version = "2.3.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nb"
|
name = "nb"
|
||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nb 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"nb 1.0.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nb"
|
name = "nb"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-utils"
|
name = "pin-utils"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "r0"
|
name = "r0"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bd7a31eed1591dcbc95d92ad7161908e72f4677f8fabf2a32ca49b4237cbf211"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc_version"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084"
|
||||||
|
dependencies = [
|
||||||
|
"semver",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver"
|
||||||
|
version = "0.1.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smoltcp"
|
name = "smoltcp"
|
||||||
version = "0.6.0"
|
version = "0.7.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3e4a069bef843d170df47e7c0a8bf8d037f217d9f5b325865acc3e466ffe40d3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags",
|
||||||
"byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder",
|
||||||
"managed 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"managed",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "szl"
|
name = "szl"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder",
|
||||||
"core_io 0.1.20200410",
|
"core_io",
|
||||||
"libboard_zynq 0.0.0",
|
"libboard_zynq",
|
||||||
"libconfig 0.1.0",
|
"libconfig",
|
||||||
"libcortex_a9 0.0.0",
|
"libcortex_a9",
|
||||||
"libregister 0.0.0",
|
"libregister",
|
||||||
"libsupport_zynq 0.0.0",
|
"libsupport_zynq",
|
||||||
"log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vcell"
|
name = "vcell"
|
||||||
version = "0.1.2"
|
version = "0.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "void"
|
name = "void"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "volatile-register"
|
name = "volatile-register"
|
||||||
version = "0.2.0"
|
version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"vcell 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"vcell",
|
||||||
]
|
]
|
||||||
|
|
||||||
[metadata]
|
|
||||||
"checksum bit_field 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4"
|
|
||||||
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
|
||||||
"checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
|
|
||||||
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
|
||||||
"checksum compiler_builtins 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "e3fcd8aba10d17504c87ef12d4f62ef404c6a4703d16682a9eb5543e6cf24455"
|
|
||||||
"checksum embedded-hal 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fa998ce59ec9765d15216393af37a58961ddcefb14c753b4816ba2191d865fcb"
|
|
||||||
"checksum fatfs 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "93079df23039e52059e1f03b4c29fb0c72da2c792aad91bb2236c9fb81d3592e"
|
|
||||||
"checksum linked_list_allocator 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)" = "660b26e6156a7d00eefb19052fe1943cf5ab2f353a723a577fad6ba2f99d1f90"
|
|
||||||
"checksum log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
|
|
||||||
"checksum managed 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c75de51135344a4f8ed3cfe2720dc27736f7711989703a0b43aadf3753c55577"
|
|
||||||
"checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
|
|
||||||
"checksum nb 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f"
|
|
||||||
"checksum nb 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae"
|
|
||||||
"checksum pin-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
|
||||||
"checksum r0 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd7a31eed1591dcbc95d92ad7161908e72f4677f8fabf2a32ca49b4237cbf211"
|
|
||||||
"checksum smoltcp 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0fe46639fd2ec79eadf8fe719f237a7a0bd4dac5d957f1ca5bbdbc1c3c39e53a"
|
|
||||||
"checksum vcell 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "876e32dcadfe563a4289e994f7cb391197f362b6315dc45e8ba4aa6f564a4b3c"
|
|
||||||
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
|
||||||
"checksum volatile-register 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d67cb4616d99b940db1d6bd28844ff97108b498a6ca850e5b6191a532063286"
|
|
||||||
|
|
|
@ -6,7 +6,6 @@ members = [
|
||||||
"libsupport_zynq",
|
"libsupport_zynq",
|
||||||
"libasync",
|
"libasync",
|
||||||
"libconfig",
|
"libconfig",
|
||||||
"libcoreio",
|
|
||||||
"experiments",
|
"experiments",
|
||||||
"szl",
|
"szl",
|
||||||
]
|
]
|
||||||
|
@ -15,10 +14,7 @@ members = [
|
||||||
panic = "abort"
|
panic = "abort"
|
||||||
debug = true
|
debug = true
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
opt-level = 'z'
|
opt-level = 's'
|
||||||
lto = true
|
lto = true
|
||||||
debug-assertions = false
|
debug-assertions = false
|
||||||
overflow-checks = false
|
overflow-checks = false
|
||||||
|
|
||||||
[patch.crates-io]
|
|
||||||
core_io = { path = "./libcoreio" }
|
|
||||||
|
|
|
@ -0,0 +1,165 @@
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
|
||||||
|
This version of the GNU Lesser General Public License incorporates
|
||||||
|
the terms and conditions of version 3 of the GNU General Public
|
||||||
|
License, supplemented by the additional permissions listed below.
|
||||||
|
|
||||||
|
0. Additional Definitions.
|
||||||
|
|
||||||
|
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||||
|
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||||
|
General Public License.
|
||||||
|
|
||||||
|
"The Library" refers to a covered work governed by this License,
|
||||||
|
other than an Application or a Combined Work as defined below.
|
||||||
|
|
||||||
|
An "Application" is any work that makes use of an interface provided
|
||||||
|
by the Library, but which is not otherwise based on the Library.
|
||||||
|
Defining a subclass of a class defined by the Library is deemed a mode
|
||||||
|
of using an interface provided by the Library.
|
||||||
|
|
||||||
|
A "Combined Work" is a work produced by combining or linking an
|
||||||
|
Application with the Library. The particular version of the Library
|
||||||
|
with which the Combined Work was made is also called the "Linked
|
||||||
|
Version".
|
||||||
|
|
||||||
|
The "Minimal Corresponding Source" for a Combined Work means the
|
||||||
|
Corresponding Source for the Combined Work, excluding any source code
|
||||||
|
for portions of the Combined Work that, considered in isolation, are
|
||||||
|
based on the Application, and not on the Linked Version.
|
||||||
|
|
||||||
|
The "Corresponding Application Code" for a Combined Work means the
|
||||||
|
object code and/or source code for the Application, including any data
|
||||||
|
and utility programs needed for reproducing the Combined Work from the
|
||||||
|
Application, but excluding the System Libraries of the Combined Work.
|
||||||
|
|
||||||
|
1. Exception to Section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
You may convey a covered work under sections 3 and 4 of this License
|
||||||
|
without being bound by section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
2. Conveying Modified Versions.
|
||||||
|
|
||||||
|
If you modify a copy of the Library, and, in your modifications, a
|
||||||
|
facility refers to a function or data to be supplied by an Application
|
||||||
|
that uses the facility (other than as an argument passed when the
|
||||||
|
facility is invoked), then you may convey a copy of the modified
|
||||||
|
version:
|
||||||
|
|
||||||
|
a) under this License, provided that you make a good faith effort to
|
||||||
|
ensure that, in the event an Application does not supply the
|
||||||
|
function or data, the facility still operates, and performs
|
||||||
|
whatever part of its purpose remains meaningful, or
|
||||||
|
|
||||||
|
b) under the GNU GPL, with none of the additional permissions of
|
||||||
|
this License applicable to that copy.
|
||||||
|
|
||||||
|
3. Object Code Incorporating Material from Library Header Files.
|
||||||
|
|
||||||
|
The object code form of an Application may incorporate material from
|
||||||
|
a header file that is part of the Library. You may convey such object
|
||||||
|
code under terms of your choice, provided that, if the incorporated
|
||||||
|
material is not limited to numerical parameters, data structure
|
||||||
|
layouts and accessors, or small macros, inline functions and templates
|
||||||
|
(ten or fewer lines in length), you do both of the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the object code that the
|
||||||
|
Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
4. Combined Works.
|
||||||
|
|
||||||
|
You may convey a Combined Work under terms of your choice that,
|
||||||
|
taken together, effectively do not restrict modification of the
|
||||||
|
portions of the Library contained in the Combined Work and reverse
|
||||||
|
engineering for debugging such modifications, if you also do each of
|
||||||
|
the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the Combined Work that
|
||||||
|
the Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
c) For a Combined Work that displays copyright notices during
|
||||||
|
execution, include the copyright notice for the Library among
|
||||||
|
these notices, as well as a reference directing the user to the
|
||||||
|
copies of the GNU GPL and this license document.
|
||||||
|
|
||||||
|
d) Do one of the following:
|
||||||
|
|
||||||
|
0) Convey the Minimal Corresponding Source under the terms of this
|
||||||
|
License, and the Corresponding Application Code in a form
|
||||||
|
suitable for, and under terms that permit, the user to
|
||||||
|
recombine or relink the Application with a modified version of
|
||||||
|
the Linked Version to produce a modified Combined Work, in the
|
||||||
|
manner specified by section 6 of the GNU GPL for conveying
|
||||||
|
Corresponding Source.
|
||||||
|
|
||||||
|
1) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (a) uses at run time
|
||||||
|
a copy of the Library already present on the user's computer
|
||||||
|
system, and (b) will operate properly with a modified version
|
||||||
|
of the Library that is interface-compatible with the Linked
|
||||||
|
Version.
|
||||||
|
|
||||||
|
e) Provide Installation Information, but only if you would otherwise
|
||||||
|
be required to provide such information under section 6 of the
|
||||||
|
GNU GPL, and only to the extent that such information is
|
||||||
|
necessary to install and execute a modified version of the
|
||||||
|
Combined Work produced by recombining or relinking the
|
||||||
|
Application with a modified version of the Linked Version. (If
|
||||||
|
you use option 4d0, the Installation Information must accompany
|
||||||
|
the Minimal Corresponding Source and Corresponding Application
|
||||||
|
Code. If you use option 4d1, you must provide the Installation
|
||||||
|
Information in the manner specified by section 6 of the GNU GPL
|
||||||
|
for conveying Corresponding Source.)
|
||||||
|
|
||||||
|
5. Combined Libraries.
|
||||||
|
|
||||||
|
You may place library facilities that are a work based on the
|
||||||
|
Library side by side in a single library together with other library
|
||||||
|
facilities that are not Applications and are not covered by this
|
||||||
|
License, and convey such a combined library under terms of your
|
||||||
|
choice, if you do both of the following:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work based
|
||||||
|
on the Library, uncombined with any other library facilities,
|
||||||
|
conveyed under the terms of this License.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library that part of it
|
||||||
|
is a work based on the Library, and explaining where to find the
|
||||||
|
accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
6. Revised Versions of the GNU Lesser General Public License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the GNU Lesser General Public License from time to time. Such new
|
||||||
|
versions will be similar in spirit to the present version, but may
|
||||||
|
differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Library as you received it specifies that a certain numbered version
|
||||||
|
of the GNU Lesser General Public License "or any later version"
|
||||||
|
applies to it, you have the option of following the terms and
|
||||||
|
conditions either of that published version or of any later version
|
||||||
|
published by the Free Software Foundation. If the Library as you
|
||||||
|
received it does not specify a version number of the GNU Lesser
|
||||||
|
General Public License, you may choose any version of the GNU Lesser
|
||||||
|
General Public License ever published by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Library as you received it specifies that a proxy can decide
|
||||||
|
whether future versions of the GNU Lesser General Public License shall
|
||||||
|
apply, that proxy's public statement of acceptance of any version is
|
||||||
|
permanent authorization for you to choose that version for the
|
||||||
|
Library.
|
60
README.md
60
README.md
|
@ -1,31 +1,69 @@
|
||||||
# Build
|
# Bare-metal Rust on Zynq-7000
|
||||||
|
|
||||||
|
Supported features:
|
||||||
|
|
||||||
|
* Clocking setup
|
||||||
|
* UART
|
||||||
|
* SDRAM setup
|
||||||
|
* Ethernet with smoltcp and async-await on TCP sockets
|
||||||
|
* SD card
|
||||||
|
* PL programming and startup
|
||||||
|
* Pure Rust SZL first-stage bootloader, with SD boot and netboot
|
||||||
|
* Control of second CPU core and message passing, with async-await support
|
||||||
|
|
||||||
|
|
||||||
|
Supported boards:
|
||||||
|
* Kasli-SoC
|
||||||
|
* ZC706
|
||||||
|
* Red Pitaya
|
||||||
|
* Cora Z7-10 (seems to also run on Cora Z7-07S, including dual-core support)
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
Zynq-rs is packaged using the [Nix](https://nixos.org) Flakes system. Install Nix 2.4+ and enable flakes by adding ``experimental-features = nix-command flakes`` to ``nix.conf`` (e.g. ``~/.config/nix/nix.conf``).
|
||||||
|
|
||||||
|
You can build SZL or experiments crate for the platform of your choice by using ``nix build`` command, e.g.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
nix-shell --command "cargo xbuild --release -p experiments"
|
nix build .#coraz7-experiments
|
||||||
```
|
```
|
||||||
|
|
||||||
Currently the ELF output is placed at `target/armv7-none-eabihf/release/experiments`
|
Alternatively, you can still use ``cargo xbuild`` within ``nix develop`` shell.
|
||||||
|
|
||||||
# Debug
|
|
||||||
|
|
||||||
## Running on the ZC706
|
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
nix-shell --command "cargo xbuild --release -p experiments"
|
nix develop
|
||||||
|
cargo xbuild --release -p experiments
|
||||||
|
```
|
||||||
|
|
||||||
|
Currently the ELF output is placed at `target/armv7-none-eabihf/release/experiments`, or `result/experiments.elf` for Nix Flakes build.
|
||||||
|
|
||||||
|
## Debug
|
||||||
|
|
||||||
|
### Running on the ZC706
|
||||||
|
|
||||||
|
```shell
|
||||||
|
nix develop
|
||||||
|
cargo xbuild --release -p experiments
|
||||||
cd openocd
|
cd openocd
|
||||||
openocd -f zc706.cfg
|
openocd -f zc706.cfg
|
||||||
```
|
```
|
||||||
|
|
||||||
## Running on the Cora Z7-10
|
### Running on the Cora Z7-10
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
nix-shell --command "cd experiments && cargo xbuild --release --no-default-features --features=target_cora_z7_10"
|
nix develop
|
||||||
|
cargo xbuild --release -p experiments --no-default-features --features=target_coraz7
|
||||||
cd openocd
|
cd openocd
|
||||||
openocd -f cora-z7-10.cfg
|
openocd -f cora-z7-10.cfg
|
||||||
```
|
```
|
||||||
|
|
||||||
## Loading a bitstream into volatile memory
|
### Loading a bitstream into volatile memory
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
openocd -f zc706.cfg -c "pld load 0 blinker_migen.bit; exit"
|
openocd -f zc706.cfg -c "pld load 0 blinker_migen.bit; exit"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Copyright (C) 2019-2022 M-Labs Limited.
|
||||||
|
Released under the GNU LGPL v3. See the LICENSE file for details.
|
||||||
|
|
38
default.nix
38
default.nix
|
@ -1,38 +0,0 @@
|
||||||
let
|
|
||||||
pkgs = import <nixpkgs> { overlays = [ (import ./nix/mozilla-overlay.nix) ]; };
|
|
||||||
rustPlatform = (import ./nix/rust-platform.nix { inherit pkgs; });
|
|
||||||
build-crate = name: crate: features:
|
|
||||||
rustPlatform.buildRustPackage rec {
|
|
||||||
name = "${crate}";
|
|
||||||
|
|
||||||
src = ./.;
|
|
||||||
cargoSha256 = "1f2psa1g41pl2j8n60hhik2s2pqdfjhr5capimvajf81kxrnn2ck";
|
|
||||||
|
|
||||||
nativeBuildInputs = [ pkgs.cargo-xbuild ];
|
|
||||||
buildPhase = ''
|
|
||||||
export XARGO_RUST_SRC="${rustPlatform.rust.rustc.src}/src"
|
|
||||||
export CARGO_HOME=$(mktemp -d cargo-home.XXX)
|
|
||||||
pushd ${crate}
|
|
||||||
cargo xbuild --release --frozen \
|
|
||||||
--no-default-features \
|
|
||||||
--features=${features}
|
|
||||||
popd
|
|
||||||
'';
|
|
||||||
|
|
||||||
installPhase = ''
|
|
||||||
mkdir -p $out $out/nix-support
|
|
||||||
cp target/armv7-none-eabihf/release/${name} $out/${name}.elf
|
|
||||||
echo file binary-dist $out/${name}.elf >> $out/nix-support/hydra-build-products
|
|
||||||
'';
|
|
||||||
|
|
||||||
doCheck = false;
|
|
||||||
dontFixup = true;
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
zc706-experiments = build-crate "zc706-experiments" "experiments" "target_zc706";
|
|
||||||
cora-experiments = build-crate "cora-experiments" "experiments" "target_cora_z7_10";
|
|
||||||
redpitaya-experiments = build-crate "redpitaya-experiments" "experiments" "target_redpitaya";
|
|
||||||
zc706-fsbl = (import ./nix/fsbl.nix { inherit pkgs; });
|
|
||||||
zc706-szl = build-crate "zc706-szl" "szl" "target_zc706";
|
|
||||||
}
|
|
|
@ -7,8 +7,10 @@ edition = "2018"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
target_zc706 = ["libboard_zynq/target_zc706", "libsupport_zynq/target_zc706"]
|
target_zc706 = ["libboard_zynq/target_zc706", "libsupport_zynq/target_zc706"]
|
||||||
target_cora_z7_10 = ["libboard_zynq/target_cora_z7_10", "libsupport_zynq/target_cora_z7_10"]
|
target_coraz7 = ["libboard_zynq/target_coraz7", "libsupport_zynq/target_coraz7"]
|
||||||
|
target_ebaz4205 = ["libboard_zynq/target_ebaz4205", "libsupport_zynq/target_ebaz4205"]
|
||||||
target_redpitaya = ["libboard_zynq/target_redpitaya", "libsupport_zynq/target_redpitaya"]
|
target_redpitaya = ["libboard_zynq/target_redpitaya", "libsupport_zynq/target_redpitaya"]
|
||||||
|
target_kasli_soc = ["libboard_zynq/target_kasli_soc", "libsupport_zynq/target_kasli_soc"]
|
||||||
default = ["target_zc706"]
|
default = ["target_zc706"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
@ -17,5 +19,5 @@ embedded-hal = "0.2"
|
||||||
libregister = { path = "../libregister" }
|
libregister = { path = "../libregister" }
|
||||||
libcortex_a9 = { path = "../libcortex_a9" }
|
libcortex_a9 = { path = "../libcortex_a9" }
|
||||||
libboard_zynq = { path = "../libboard_zynq" }
|
libboard_zynq = { path = "../libboard_zynq" }
|
||||||
libsupport_zynq = { path = "../libsupport_zynq", default-features = false, features = ["panic_handler"]}
|
libsupport_zynq = { path = "../libsupport_zynq", default-features = false, features = ["panic_handler", "dummy_fiq_handler"]}
|
||||||
libasync = { path = "../libasync" }
|
libasync = { path = "../libasync" }
|
||||||
|
|
|
@ -34,6 +34,20 @@ SECTIONS
|
||||||
__bss_end = .;
|
__bss_end = .;
|
||||||
} > OCM3
|
} > OCM3
|
||||||
|
|
||||||
|
.irq_stack1 (NOLOAD) : ALIGN(8)
|
||||||
|
{
|
||||||
|
__irq_stack1_end = .;
|
||||||
|
. += 0x100;
|
||||||
|
__irq_stack1_start = .;
|
||||||
|
} > OCM3
|
||||||
|
|
||||||
|
.irq_stack0 (NOLOAD) : ALIGN(8)
|
||||||
|
{
|
||||||
|
__irq_stack0_end = .;
|
||||||
|
. += 0x100;
|
||||||
|
__irq_stack0_start = .;
|
||||||
|
} > OCM3
|
||||||
|
|
||||||
.stack1 (NOLOAD) : ALIGN(8) {
|
.stack1 (NOLOAD) : ALIGN(8) {
|
||||||
__stack1_end = .;
|
__stack1_end = .;
|
||||||
. += 0x200;
|
. += 0x200;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#![no_main]
|
#![no_main]
|
||||||
#![feature(const_in_array_repeat_expressions)]
|
#![feature(const_in_array_repeat_expressions)]
|
||||||
#![feature(naked_functions)]
|
#![feature(naked_functions)]
|
||||||
|
#![feature(asm)]
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
|
@ -34,11 +35,11 @@ use libcortex_a9::{
|
||||||
sync_channel,
|
sync_channel,
|
||||||
regs::{MPIDR, SP},
|
regs::{MPIDR, SP},
|
||||||
spin_lock_yield, notify_spin_lock,
|
spin_lock_yield, notify_spin_lock,
|
||||||
asm
|
asm, interrupt_handler
|
||||||
};
|
};
|
||||||
use libregister::{RegisterR, RegisterW};
|
use libregister::{RegisterR, RegisterW};
|
||||||
use libsupport_zynq::{
|
use libsupport_zynq::{
|
||||||
boot, ram,
|
boot, exception_vectors, ram,
|
||||||
};
|
};
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use core::sync::atomic::{AtomicBool, Ordering};
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
@ -54,28 +55,35 @@ extern "C" {
|
||||||
|
|
||||||
static CORE1_RESTART: AtomicBool = AtomicBool::new(false);
|
static CORE1_RESTART: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
||||||
#[link_section = ".text.boot"]
|
interrupt_handler!(IRQ, irq, __irq_stack0_start, __irq_stack1_start, {
|
||||||
#[no_mangle]
|
let mpcore = mpcore::RegisterBlock::mpcore();
|
||||||
#[naked]
|
let mut gic = gic::InterruptController::gic(mpcore);
|
||||||
pub unsafe extern "C" fn IRQ() {
|
let id = gic.get_interrupt_id();
|
||||||
if MPIDR.read().cpu_id() == 1{
|
match MPIDR.read().cpu_id(){
|
||||||
let mpcore = mpcore::RegisterBlock::mpcore();
|
0 => {
|
||||||
let mut gic = gic::InterruptController::gic(mpcore);
|
if id.0 == 0 {
|
||||||
let id = gic.get_interrupt_id();
|
println!("Interrupting core0...");
|
||||||
if id.0 == 0 {
|
gic.end_interrupt(id);
|
||||||
gic.end_interrupt(id);
|
return;
|
||||||
asm::exit_irq();
|
}
|
||||||
SP.write(&mut __stack1_start as *mut _ as u32);
|
},
|
||||||
asm::enable_irq();
|
1 => {
|
||||||
CORE1_RESTART.store(false, Ordering::Relaxed);
|
if id.0 == 0 {
|
||||||
notify_spin_lock();
|
gic.end_interrupt(id);
|
||||||
main_core1();
|
asm::exit_irq();
|
||||||
}
|
SP.write(&mut __stack1_start as *mut _ as u32);
|
||||||
|
asm::enable_irq();
|
||||||
|
CORE1_RESTART.store(false, Ordering::Relaxed);
|
||||||
|
notify_spin_lock();
|
||||||
|
main_core1();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
stdio::drop_uart();
|
stdio::drop_uart();
|
||||||
println!("IRQ");
|
println!("IRQ");
|
||||||
loop {}
|
loop {}
|
||||||
}
|
});
|
||||||
|
|
||||||
pub fn restart_core1() {
|
pub fn restart_core1() {
|
||||||
let mut interrupt_controller = gic::InterruptController::gic(mpcore::RegisterBlock::mpcore());
|
let mut interrupt_controller = gic::InterruptController::gic(mpcore::RegisterBlock::mpcore());
|
||||||
|
@ -88,13 +96,12 @@ pub fn restart_core1() {
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn main_core0() {
|
pub fn main_core0() {
|
||||||
|
exception_vectors::set_vector_table(0x0);
|
||||||
// zynq::clocks::CpuClocks::enable_io(1_250_000_000);
|
// zynq::clocks::CpuClocks::enable_io(1_250_000_000);
|
||||||
enable_l2_cache();
|
enable_l2_cache(0x8);
|
||||||
println!("\nZynq experiments");
|
println!("\nZynq experiments");
|
||||||
let mut interrupt_controller = gic::InterruptController::gic(mpcore::RegisterBlock::mpcore());
|
let mut interrupt_controller = gic::InterruptController::gic(mpcore::RegisterBlock::mpcore());
|
||||||
interrupt_controller.enable_interrupts();
|
interrupt_controller.enable_interrupts();
|
||||||
// ps7_init::apply();
|
|
||||||
libboard_zynq::stdio::drop_uart();
|
|
||||||
|
|
||||||
libboard_zynq::logger::init().unwrap();
|
libboard_zynq::logger::init().unwrap();
|
||||||
log::set_max_level(log::LevelFilter::Trace);
|
log::set_max_level(log::LevelFilter::Trace);
|
||||||
|
@ -107,31 +114,21 @@ pub fn main_core0() {
|
||||||
.boot_mode_pins()
|
.boot_mode_pins()
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(feature = "target_zc706")]
|
#[cfg(any(
|
||||||
|
feature = "target_zc706",
|
||||||
|
feature = "target_ebaz4205",
|
||||||
|
feature = "target_redpitaya",
|
||||||
|
feature = "target_kasli_soc",
|
||||||
|
))]
|
||||||
const CPU_FREQ: u32 = 800_000_000;
|
const CPU_FREQ: u32 = 800_000_000;
|
||||||
#[cfg(feature = "target_cora_z7_10")]
|
#[cfg(feature = "target_coraz7")]
|
||||||
const CPU_FREQ: u32 = 650_000_000;
|
const CPU_FREQ: u32 = 650_000_000;
|
||||||
#[cfg(feature = "target_redpitaya")]
|
|
||||||
const CPU_FREQ: u32 = 800_000_000;
|
|
||||||
|
|
||||||
info!("Setup clock sources...");
|
info!("Setup clock sources...");
|
||||||
ArmPll::setup(2 * CPU_FREQ);
|
ArmPll::setup(2 * CPU_FREQ);
|
||||||
Clocks::set_cpu_freq(CPU_FREQ);
|
Clocks::set_cpu_freq(CPU_FREQ);
|
||||||
#[cfg(feature = "target_zc706")]
|
IoPll::setup(1_000_000_000);
|
||||||
{
|
libboard_zynq::stdio::drop_uart();
|
||||||
IoPll::setup(1_000_000_000);
|
|
||||||
libboard_zynq::stdio::drop_uart();
|
|
||||||
}
|
|
||||||
#[cfg(feature = "target_cora_z7_10")]
|
|
||||||
{
|
|
||||||
IoPll::setup(1_000_000_000);
|
|
||||||
libboard_zynq::stdio::drop_uart();
|
|
||||||
}
|
|
||||||
#[cfg(feature = "target_redpitaya")]
|
|
||||||
{
|
|
||||||
IoPll::setup(1_000_000_000);
|
|
||||||
libboard_zynq::stdio::drop_uart();
|
|
||||||
}
|
|
||||||
info!("PLLs set up");
|
info!("PLLs set up");
|
||||||
let clocks = zynq::clocks::Clocks::get();
|
let clocks = zynq::clocks::Clocks::get();
|
||||||
info!(
|
info!(
|
||||||
|
@ -149,6 +146,10 @@ pub fn main_core0() {
|
||||||
ddr.memtest();
|
ddr.memtest();
|
||||||
ram::init_alloc_ddr(&mut ddr);
|
ram::init_alloc_ddr(&mut ddr);
|
||||||
|
|
||||||
|
info!("Send software interrupt to core0");
|
||||||
|
interrupt_controller.send_sgi(gic::InterruptId(0), gic::CPUCore::Core0.into());
|
||||||
|
info!("Core0 returned from interrupt");
|
||||||
|
|
||||||
boot::Core1::start(false);
|
boot::Core1::start(false);
|
||||||
|
|
||||||
let core1_req = unsafe { &mut CORE1_REQ.0 };
|
let core1_req = unsafe { &mut CORE1_REQ.0 };
|
||||||
|
@ -198,6 +199,20 @@ pub fn main_core0() {
|
||||||
println!("");
|
println!("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
{
|
||||||
|
let mut err_cdwn = timer.countdown();
|
||||||
|
let mut err_state = true;
|
||||||
|
let mut led = zynq::error_led::ErrorLED::error_led();
|
||||||
|
task::spawn( async move {
|
||||||
|
loop {
|
||||||
|
led.toggle(err_state);
|
||||||
|
err_state = !err_state;
|
||||||
|
delay(&mut err_cdwn, Milliseconds(1000)).await;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
let eth = zynq::eth::Eth::eth0(HWADDR.clone());
|
let eth = zynq::eth::Eth::eth0(HWADDR.clone());
|
||||||
println!("Eth on");
|
println!("Eth on");
|
||||||
|
|
||||||
|
@ -231,12 +246,12 @@ pub fn main_core0() {
|
||||||
while let Ok(stream) = TcpStream::accept(TCP_PORT, 0x10_0000, 0x10_0000).await {
|
while let Ok(stream) = TcpStream::accept(TCP_PORT, 0x10_0000, 0x10_0000).await {
|
||||||
let stats_tx = stats_tx.clone();
|
let stats_tx = stats_tx.clone();
|
||||||
task::spawn(async move {
|
task::spawn(async move {
|
||||||
let tx_data = (0..=255).take(4096).collect::<alloc::vec::Vec<u8>>();
|
let tx_data = (0..=255).cycle().take(4096).collect::<alloc::vec::Vec<u8>>();
|
||||||
loop {
|
loop {
|
||||||
// const CHUNK_SIZE: usize = 65536;
|
// const CHUNK_SIZE: usize = 65536;
|
||||||
// match stream.send((0..=255).cycle().take(CHUNK_SIZE)).await {
|
// match stream.send((0..=255).cycle().take(CHUNK_SIZE)).await {
|
||||||
match stream.send_slice(&tx_data[..]).await {
|
match stream.send_slice(&tx_data[..]).await {
|
||||||
Ok(len) => stats_tx.borrow_mut().1 += tx_data.len(), //CHUNK_SIZE,
|
Ok(_len) => stats_tx.borrow_mut().1 += tx_data.len(), //CHUNK_SIZE,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!("tx: {:?}", e);
|
warn!("tx: {:?}", e);
|
||||||
break
|
break
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1731652201,
|
||||||
|
"narHash": "sha256-XUO0JKP1hlww0d7mm3kpmIr4hhtR4zicg5Wwes9cPMg=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "c21b77913ea840f8bcf9adf4c41cecc2abffd38d",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-24.05",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"rust-overlay": "rust-overlay"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rust-overlay": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1719454714,
|
||||||
|
"narHash": "sha256-MojqG0lyUINkEk0b3kM2drsU5vyaF8DFZe/FAlZVOGs=",
|
||||||
|
"owner": "oxalica",
|
||||||
|
"repo": "rust-overlay",
|
||||||
|
"rev": "d1c527659cf076ecc4b96a91c702d080b213801e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "oxalica",
|
||||||
|
"ref": "snapshot/2024-08-01",
|
||||||
|
"repo": "rust-overlay",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
|
@ -0,0 +1,179 @@
|
||||||
|
{
|
||||||
|
description = "Bare-metal Rust on Zynq-7000";
|
||||||
|
|
||||||
|
inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-24.05;
|
||||||
|
inputs.rust-overlay = {
|
||||||
|
url = "github:oxalica/rust-overlay?ref=snapshot/2024-08-01";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, rust-overlay }:
|
||||||
|
let
|
||||||
|
pkgs = import nixpkgs { system = "x86_64-linux"; overlays = [ (import rust-overlay) crosspkgs-overlay ]; };
|
||||||
|
|
||||||
|
rust = pkgs.rust-bin.nightly."2021-01-28".default.override {
|
||||||
|
extensions = [ "rust-src" ];
|
||||||
|
targets = [ ];
|
||||||
|
};
|
||||||
|
rustPlatform = pkgs.makeRustPlatform {
|
||||||
|
rustc = rust // {
|
||||||
|
# https://github.com/oxalica/rust-overlay/commit/c48c2d76b68dd9ede0815fec53479375c61af857
|
||||||
|
targetPlatforms = pkgs.lib.platforms.all;
|
||||||
|
tier1TargetPlatforms = pkgs.lib.platforms.all;
|
||||||
|
badTargetPlatforms = [ ];
|
||||||
|
};
|
||||||
|
cargo = rust;
|
||||||
|
};
|
||||||
|
|
||||||
|
# https://doc.rust-lang.org/rustc/linker-plugin-lto.html#toolchain-compatibility
|
||||||
|
llvmPackages_11 = pkgs.recurseIntoAttrs (pkgs.callPackage (import ./llvm/11) ({
|
||||||
|
inherit (pkgs.stdenvAdapters) overrideCC;
|
||||||
|
buildLlvmTools = null;
|
||||||
|
targetLlvmLibraries = null;
|
||||||
|
targetLlvm = null;
|
||||||
|
}));
|
||||||
|
|
||||||
|
crosspkgs-overlay = (self: super: {
|
||||||
|
pkgsCross = super.pkgsCross // {
|
||||||
|
zynq-baremetal = import super.path {
|
||||||
|
system = "x86_64-linux";
|
||||||
|
crossSystem = {
|
||||||
|
config = "arm-none-eabihf";
|
||||||
|
libc = "newlib";
|
||||||
|
gcc.cpu = "cortex-a9";
|
||||||
|
gcc.fpu = "vfpv3";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
mkbootimage = pkgs.stdenv.mkDerivation {
|
||||||
|
pname = "mkbootimage";
|
||||||
|
version = "2.3dev";
|
||||||
|
|
||||||
|
src = pkgs.fetchFromGitHub {
|
||||||
|
owner = "antmicro";
|
||||||
|
repo = "zynq-mkbootimage";
|
||||||
|
rev = "872363ce32c249f8278cf107bc6d3bdeb38d849f";
|
||||||
|
sha256 = "sha256-5FPyAhUWZDwHbqmp9J2ZXTmjaXPz+dzrJMolaNwADHs=";
|
||||||
|
};
|
||||||
|
|
||||||
|
propagatedBuildInputs = [ pkgs.libelf pkgs.pcre ];
|
||||||
|
patchPhase =
|
||||||
|
''
|
||||||
|
substituteInPlace Makefile --replace "git rev-parse --short HEAD" "echo nix"
|
||||||
|
'';
|
||||||
|
installPhase =
|
||||||
|
''
|
||||||
|
mkdir -p $out/bin
|
||||||
|
cp mkbootimage $out/bin
|
||||||
|
'';
|
||||||
|
hardeningDisable = [ "fortify" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
fsbl = { board ? "zc706" }: pkgs.stdenv.mkDerivation {
|
||||||
|
name = "${board}-fsbl";
|
||||||
|
src = pkgs.fetchFromGitHub {
|
||||||
|
owner = "Xilinx";
|
||||||
|
repo = "embeddedsw";
|
||||||
|
rev = "xilinx_v2022.2";
|
||||||
|
sha256 = "sha256-UDz9KK/Hw3qM1BAeKif30rE8Bi6C2uvuZlvyvtJCMfw=";
|
||||||
|
};
|
||||||
|
nativeBuildInputs = [
|
||||||
|
pkgs.pkgsCross.zynq-baremetal.buildPackages.binutils
|
||||||
|
pkgs.pkgsCross.zynq-baremetal.buildPackages.gcc
|
||||||
|
];
|
||||||
|
patchPhase = ''
|
||||||
|
patchShebangs lib/sw_apps/zynq_fsbl/misc/copy_bsp.sh
|
||||||
|
|
||||||
|
for x in lib/sw_apps/zynq_fsbl/src/Makefile lib/sw_apps/zynq_fsbl/misc/copy_bsp.sh lib/bsp/standalone/src/arm/cortexa9/gcc/Makefile; do
|
||||||
|
substituteInPlace $x \
|
||||||
|
--replace "arm-none-eabi-" "arm-none-eabihf-"
|
||||||
|
done
|
||||||
|
'';
|
||||||
|
buildPhase = ''
|
||||||
|
cd lib/sw_apps/zynq_fsbl/src
|
||||||
|
make BOARD=${board} "CFLAGS=-DFSBL_DEBUG_INFO -g"
|
||||||
|
'';
|
||||||
|
installPhase = ''
|
||||||
|
mkdir $out
|
||||||
|
cp fsbl.elf $out
|
||||||
|
'';
|
||||||
|
doCheck = false;
|
||||||
|
dontFixup = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
cargo-xbuild = pkgs.cargo-xbuild.overrideAttrs(oa: {
|
||||||
|
postPatch = "substituteInPlace src/sysroot.rs --replace 2021 2018";
|
||||||
|
});
|
||||||
|
|
||||||
|
build-crate = name: crate: features: rustPlatform.buildRustPackage rec {
|
||||||
|
name = "${crate}";
|
||||||
|
|
||||||
|
src = builtins.filterSource (path: type:
|
||||||
|
baseNameOf path != "target"
|
||||||
|
) ./.;
|
||||||
|
cargoLock = { lockFile = ./Cargo.lock; };
|
||||||
|
|
||||||
|
nativeBuildInputs = [ cargo-xbuild llvmPackages_11.clang-unwrapped ];
|
||||||
|
buildPhase = ''
|
||||||
|
export XARGO_RUST_SRC="${rust}/lib/rustlib/src/rust/library"
|
||||||
|
export CARGO_HOME=$(mktemp -d cargo-home.XXX)
|
||||||
|
pushd ${crate}
|
||||||
|
cargo xbuild --release --frozen \
|
||||||
|
--no-default-features \
|
||||||
|
--features=${features}
|
||||||
|
popd
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out $out/nix-support
|
||||||
|
cp target/armv7-none-eabihf/release/${name} $out/${name}.elf
|
||||||
|
echo file binary-dist $out/${name}.elf >> $out/nix-support/hydra-build-products
|
||||||
|
'';
|
||||||
|
|
||||||
|
doCheck = false;
|
||||||
|
dontFixup = true;
|
||||||
|
auditable = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
targetCrates = target: {
|
||||||
|
"${target}-experiments" = build-crate "${target}-experiments" "experiments" "target_${target}";
|
||||||
|
"${target}-szl" = build-crate "${target}-szl" "szl" "target_${target}";
|
||||||
|
};
|
||||||
|
targets = ["zc706" "coraz7" "redpitaya" "kasli_soc" "ebaz4205"];
|
||||||
|
allTargetCrates = (builtins.foldl' (results: target:
|
||||||
|
results // targetCrates target
|
||||||
|
) {} targets);
|
||||||
|
|
||||||
|
szl = pkgs.runCommand "szl" {} (builtins.foldl' (commands: target:
|
||||||
|
let
|
||||||
|
szlResult = builtins.getAttr "${target}-szl" allTargetCrates;
|
||||||
|
in
|
||||||
|
commands + "ln -s ${szlResult}/szl.elf $out/szl-${target}.elf\n"
|
||||||
|
) "mkdir $out\n" targets);
|
||||||
|
in rec {
|
||||||
|
packages.x86_64-linux = {
|
||||||
|
inherit cargo-xbuild szl mkbootimage;
|
||||||
|
zc706-fsbl = fsbl { board = "zc706"; };
|
||||||
|
} // allTargetCrates ;
|
||||||
|
|
||||||
|
hydraJobs = packages.x86_64-linux;
|
||||||
|
|
||||||
|
inherit rust rustPlatform llvmPackages_11;
|
||||||
|
|
||||||
|
devShell.x86_64-linux = pkgs.mkShell {
|
||||||
|
name = "zynq-rs-dev-shell";
|
||||||
|
buildInputs = [
|
||||||
|
rust
|
||||||
|
cargo-xbuild
|
||||||
|
mkbootimage
|
||||||
|
|
||||||
|
pkgs.openocd pkgs.gdb
|
||||||
|
pkgs.openssh pkgs.rsync
|
||||||
|
llvmPackages_11.clang-unwrapped
|
||||||
|
(pkgs.python3.withPackages(ps: [ ps.pyftdi ]))
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
from time import sleep
|
||||||
|
from pyftdi.ftdi import Ftdi
|
||||||
|
|
||||||
|
POR = 1 << 7
|
||||||
|
|
||||||
|
def main():
|
||||||
|
dev = Ftdi()
|
||||||
|
dev.open_bitbang_from_url("ftdi://ftdi:4232h/0")
|
||||||
|
dev.set_bitmode(POR, Ftdi.BitMode.BITBANG)
|
||||||
|
dev.write_data(bytes([0]))
|
||||||
|
sleep(0.1)
|
||||||
|
dev.write_data(bytes([POR]))
|
||||||
|
sleep(0.1)
|
||||||
|
dev.close()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
|
@ -9,10 +9,10 @@ edition = "2018"
|
||||||
#futures = { version = "0.3", default-features = false }
|
#futures = { version = "0.3", default-features = false }
|
||||||
pin-utils = "0.1.0-alpha.4"
|
pin-utils = "0.1.0-alpha.4"
|
||||||
embedded-hal = "0.2"
|
embedded-hal = "0.2"
|
||||||
nb = "0.1"
|
nb = "1.0"
|
||||||
libcortex_a9 = { path = "../libcortex_a9" }
|
libcortex_a9 = { path = "../libcortex_a9" }
|
||||||
|
|
||||||
[dependencies.smoltcp]
|
[dependencies.smoltcp]
|
||||||
version = "0.6"
|
version = "0.7"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["alloc"]
|
features = ["alloc"]
|
||||||
|
|
|
@ -7,17 +7,23 @@ use smoltcp::{
|
||||||
iface::EthernetInterface,
|
iface::EthernetInterface,
|
||||||
phy::Device,
|
phy::Device,
|
||||||
socket::SocketSet,
|
socket::SocketSet,
|
||||||
time::Instant,
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
use crate::task;
|
use crate::task;
|
||||||
|
|
||||||
mod tcp_stream;
|
mod tcp_stream;
|
||||||
pub use tcp_stream::TcpStream;
|
pub use tcp_stream::TcpStream;
|
||||||
|
|
||||||
|
pub trait LinkCheck {
|
||||||
|
type Link;
|
||||||
|
fn is_idle(&self) -> bool;
|
||||||
|
fn check_link_change(&mut self) -> Option<Self::Link>;
|
||||||
|
}
|
||||||
|
|
||||||
static mut SOCKETS: Option<Sockets> = None;
|
static mut SOCKETS: Option<Sockets> = None;
|
||||||
|
|
||||||
pub struct Sockets {
|
pub struct Sockets {
|
||||||
sockets: RefCell<SocketSet<'static, 'static, 'static>>,
|
sockets: RefCell<SocketSet<'static>>,
|
||||||
wakers: RefCell<Vec<Waker>>,
|
wakers: RefCell<Vec<Waker>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,14 +47,24 @@ impl Sockets {
|
||||||
|
|
||||||
/// Block and run executor indefinitely while polling the smoltcp
|
/// Block and run executor indefinitely while polling the smoltcp
|
||||||
/// iface
|
/// iface
|
||||||
pub fn run<'b, 'c, 'e, D: for<'d> Device<'d>>(
|
pub fn run<'b, D: for<'d> Device<'d> + LinkCheck>(
|
||||||
iface: &mut EthernetInterface<'b, 'c, 'e, D>,
|
iface: &mut EthernetInterface<'b, D>,
|
||||||
mut get_time: impl FnMut() -> Instant,
|
mut get_time: impl FnMut() -> Instant,
|
||||||
) -> ! {
|
) -> ! {
|
||||||
task::block_on(async {
|
task::block_on(async {
|
||||||
|
let mut last_link_check = Instant::from_millis(0);
|
||||||
|
const LINK_CHECK_INTERVAL: u64 = 500;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let instant = get_time();
|
let instant = get_time();
|
||||||
Self::instance().poll(iface, instant);
|
Self::instance().poll(iface, instant);
|
||||||
|
|
||||||
|
let dev = iface.device_mut();
|
||||||
|
if dev.is_idle() && instant >= last_link_check + Duration::from_millis(LINK_CHECK_INTERVAL) {
|
||||||
|
dev.check_link_change();
|
||||||
|
last_link_check = instant;
|
||||||
|
}
|
||||||
|
|
||||||
task::r#yield().await;
|
task::r#yield().await;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -58,9 +74,9 @@ impl Sockets {
|
||||||
unsafe { SOCKETS.as_ref().expect("Sockets") }
|
unsafe { SOCKETS.as_ref().expect("Sockets") }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll<'b, 'c, 'e, D: for<'d> Device<'d>>(
|
fn poll<'b, D: for<'d> Device<'d>>(
|
||||||
&self,
|
&self,
|
||||||
iface: &mut EthernetInterface<'b, 'c, 'e, D>,
|
iface: &mut EthernetInterface<'b, D>,
|
||||||
instant: Instant
|
instant: Instant
|
||||||
) {
|
) {
|
||||||
let processed = {
|
let processed = {
|
||||||
|
|
|
@ -262,6 +262,14 @@ impl TcpStream {
|
||||||
pub fn set_timeout(&mut self, duration: Option<Duration>) {
|
pub fn set_timeout(&mut self, duration: Option<Duration>) {
|
||||||
self.with_socket(|mut socket| socket.set_timeout(duration));
|
self.with_socket(|mut socket| socket.set_timeout(duration));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn ack_delay(&self) -> Option<Duration> {
|
||||||
|
self.with_socket(|socket| socket.ack_delay())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_ack_delay(&mut self, duration: Option<Duration>) {
|
||||||
|
self.with_socket(|mut socket| socket.set_ack_delay(duration));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for TcpStream {
|
impl Drop for TcpStream {
|
||||||
|
|
|
@ -7,8 +7,10 @@ edition = "2018"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
target_zc706 = []
|
target_zc706 = []
|
||||||
target_cora_z7_10 = []
|
target_coraz7 = []
|
||||||
|
target_ebaz4205 = []
|
||||||
target_redpitaya = []
|
target_redpitaya = []
|
||||||
|
target_kasli_soc = []
|
||||||
ipv6 = [ "smoltcp/proto-ipv6" ]
|
ipv6 = [ "smoltcp/proto-ipv6" ]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
@ -20,8 +22,9 @@ void = { version = "1", default-features = false }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
libregister = { path = "../libregister" }
|
libregister = { path = "../libregister" }
|
||||||
libcortex_a9 = { path = "../libcortex_a9" }
|
libcortex_a9 = { path = "../libcortex_a9" }
|
||||||
|
libasync = { path = "../libasync" }
|
||||||
|
|
||||||
[dependencies.smoltcp]
|
[dependencies.smoltcp]
|
||||||
version = "0.6"
|
version = "0.7"
|
||||||
features = ["ethernet", "proto-ipv4", "socket-tcp"]
|
features = ["ethernet", "proto-ipv4", "socket-tcp"]
|
||||||
default-features = false
|
default-features = false
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use core::unimplemented;
|
||||||
|
|
||||||
use libregister::{RegisterR, RegisterRW};
|
use libregister::{RegisterR, RegisterRW};
|
||||||
use super::slcr;
|
use super::slcr;
|
||||||
pub use slcr::ArmPllSource;
|
pub use slcr::ArmPllSource;
|
||||||
|
@ -101,6 +103,8 @@ impl Clocks {
|
||||||
self.ddr,
|
self.ddr,
|
||||||
slcr::PllSource::IoPll =>
|
slcr::PllSource::IoPll =>
|
||||||
self.io,
|
self.io,
|
||||||
|
slcr::PllSource::Emio =>
|
||||||
|
unimplemented!(),
|
||||||
};
|
};
|
||||||
pll / u32::from(uart_clk_ctrl.divisor())
|
pll / u32::from(uart_clk_ctrl.divisor())
|
||||||
}
|
}
|
||||||
|
@ -115,6 +119,8 @@ impl Clocks {
|
||||||
self.ddr,
|
self.ddr,
|
||||||
slcr::PllSource::IoPll =>
|
slcr::PllSource::IoPll =>
|
||||||
self.io,
|
self.io,
|
||||||
|
slcr::PllSource::Emio =>
|
||||||
|
unimplemented!(),
|
||||||
};
|
};
|
||||||
pll / u32::from(sdio_clk_ctrl.divisor())
|
pll / u32::from(sdio_clk_ctrl.divisor())
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,14 @@ use super::slcr;
|
||||||
|
|
||||||
#[cfg(feature = "target_zc706")]
|
#[cfg(feature = "target_zc706")]
|
||||||
pub const PS_CLK: u32 = 33_333_333;
|
pub const PS_CLK: u32 = 33_333_333;
|
||||||
#[cfg(feature = "target_cora_z7_10")]
|
#[cfg(feature = "target_coraz7")]
|
||||||
pub const PS_CLK: u32 = 50_000_000;
|
pub const PS_CLK: u32 = 50_000_000;
|
||||||
|
#[cfg(feature = "target_ebaz4205")]
|
||||||
|
pub const PS_CLK: u32 = 33_333_333;
|
||||||
#[cfg(feature = "target_redpitaya")]
|
#[cfg(feature = "target_redpitaya")]
|
||||||
pub const PS_CLK: u32 = 33_333_333;
|
pub const PS_CLK: u32 = 33_333_333;
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
pub const PS_CLK: u32 = 33_333_333;
|
||||||
|
|
||||||
/// (pll_fdiv_max, (pll_cp, pll_res, lock_cnt))
|
/// (pll_fdiv_max, (pll_cp, pll_res, lock_cnt))
|
||||||
const PLL_FDIV_LOCK_PARAM: &[(u16, (u8, u8, u16))] = &[
|
const PLL_FDIV_LOCK_PARAM: &[(u16, (u8, u8, u16))] = &[
|
||||||
|
@ -57,7 +61,7 @@ pub trait ClockSource {
|
||||||
/// 25.10.4 PLLs
|
/// 25.10.4 PLLs
|
||||||
fn setup(target_freq: u32) {
|
fn setup(target_freq: u32) {
|
||||||
let fdiv = (target_freq / PS_CLK).min(66) as u16;
|
let fdiv = (target_freq / PS_CLK).min(66) as u16;
|
||||||
let (pll_res, pll_cp, lock_cnt) = PLL_FDIV_LOCK_PARAM.iter()
|
let (pll_cp, pll_res, lock_cnt) = PLL_FDIV_LOCK_PARAM.iter()
|
||||||
.filter(|(fdiv_max, _)| fdiv <= *fdiv_max)
|
.filter(|(fdiv_max, _)| fdiv <= *fdiv_max)
|
||||||
.nth(0)
|
.nth(0)
|
||||||
.expect("PLL_FDIV_LOCK_PARAM")
|
.expect("PLL_FDIV_LOCK_PARAM")
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
use libregister::{RegisterR, RegisterW, RegisterRW};
|
use libregister::{RegisterR, RegisterW, RegisterRW};
|
||||||
use log::{debug, info, error};
|
use log::{debug, info, error};
|
||||||
use crate::{print, println};
|
use crate::{print, println};
|
||||||
use super::slcr::{self, DdriobVrefSel};
|
use super::slcr;
|
||||||
|
#[cfg(feature = "target_zc706")]
|
||||||
|
use super::slcr::DdriobVrefSel;
|
||||||
use super::clocks::{Clocks, source::{DdrPll, ClockSource}};
|
use super::clocks::{Clocks, source::{DdrPll, ClockSource}};
|
||||||
|
|
||||||
mod regs;
|
mod regs;
|
||||||
|
@ -10,16 +12,23 @@ mod regs;
|
||||||
/// Micron MT41J256M8HX-15E: 667 MHz DDR3
|
/// Micron MT41J256M8HX-15E: 667 MHz DDR3
|
||||||
const DDR_FREQ: u32 = 666_666_666;
|
const DDR_FREQ: u32 = 666_666_666;
|
||||||
|
|
||||||
#[cfg(feature = "target_cora_z7_10")]
|
#[cfg(feature = "target_coraz7")]
|
||||||
/// Micron MT41K256M16HA-125: 800 MHz DDR3L, max supported 533 MHz
|
/// Micron MT41K256M16HA-125: 800 MHz DDR3L, max supported 533 MHz
|
||||||
const DDR_FREQ: u32 = 525_000_000;
|
const DDR_FREQ: u32 = 525_000_000;
|
||||||
|
|
||||||
#[cfg(feature = "target_redpitaya")]
|
#[cfg(feature = "target_ebaz4205")]
|
||||||
/// Alliance Memory AS4C256M16D3B: 800 MHz DDR3
|
/// EtronTech Memory EM6GD16EWKG-12H: 800 MHz DDR3 at 533 MHz
|
||||||
const DDR_FREQ: u32 = 800_000_000;
|
const DDR_FREQ: u32 = 533_333_333;
|
||||||
|
|
||||||
/// MT41K256M16HA-125
|
#[cfg(feature = "target_redpitaya")]
|
||||||
const DCI_FREQ: u32 = 10_000_000;
|
/// Alliance Memory AS4C256M16D3B: 800 MHz DDR3 at 533 MHz
|
||||||
|
const DDR_FREQ: u32 = 533_333_333;
|
||||||
|
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
/// MT41K256M16HA-125:E: 800 MHz DDR3L at 533 MHz
|
||||||
|
const DDR_FREQ: u32 = 533_333_333;
|
||||||
|
|
||||||
|
const DCI_MAX_FREQ: u32 = 10_000_000;
|
||||||
|
|
||||||
pub struct DdrRam {
|
pub struct DdrRam {
|
||||||
regs: &'static mut regs::RegisterBlock,
|
regs: &'static mut regs::RegisterBlock,
|
||||||
|
@ -28,13 +37,11 @@ pub struct DdrRam {
|
||||||
impl DdrRam {
|
impl DdrRam {
|
||||||
pub fn ddrram() -> Self {
|
pub fn ddrram() -> Self {
|
||||||
let clocks = Self::clock_setup();
|
let clocks = Self::clock_setup();
|
||||||
Self::calibrate_iob_impedance(&clocks);
|
|
||||||
Self::configure_iob();
|
Self::configure_iob();
|
||||||
|
Self::calibrate_iob_impedance(&clocks);
|
||||||
let regs = regs::RegisterBlock::ddrc();
|
let regs = regs::RegisterBlock::ddrc();
|
||||||
let mut ddr = DdrRam { regs };
|
let mut ddr = DdrRam { regs };
|
||||||
ddr.configure();
|
ddr.reset_ddrc(|ddr| ddr.configure());
|
||||||
ddr.reset_ddrc();
|
|
||||||
ddr
|
ddr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +68,7 @@ impl DdrRam {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate_dci_divisors(clocks: &Clocks) -> (u8, u8) {
|
fn calculate_dci_divisors(clocks: &Clocks) -> (u8, u8) {
|
||||||
let target = (DCI_FREQ - 1 + clocks.ddr) / DCI_FREQ;
|
let target = (DCI_MAX_FREQ - 1 + clocks.ddr) / DCI_MAX_FREQ;
|
||||||
|
|
||||||
let mut best = None;
|
let mut best = None;
|
||||||
let mut best_error = 0;
|
let mut best_error = 0;
|
||||||
|
@ -144,22 +151,23 @@ impl DdrRam {
|
||||||
.output_en(slcr::DdriobOutputEn::Obuf);
|
.output_en(slcr::DdriobOutputEn::Obuf);
|
||||||
#[cfg(feature = "target_zc706")]
|
#[cfg(feature = "target_zc706")]
|
||||||
let data1_config = data0_config.clone();
|
let data1_config = data0_config.clone();
|
||||||
#[cfg(feature = "target_cora_z7_10")]
|
#[cfg(any(
|
||||||
|
feature = "target_coraz7",
|
||||||
|
feature = "target_ebaz4205",
|
||||||
|
feature = "target_redpitaya",
|
||||||
|
feature = "target_kasli_soc",
|
||||||
|
))]
|
||||||
let data0_config = slcr::DdriobConfig::zeroed()
|
let data0_config = slcr::DdriobConfig::zeroed()
|
||||||
.inp_type(slcr::DdriobInputType::VrefDifferential)
|
.inp_type(slcr::DdriobInputType::VrefDifferential)
|
||||||
.term_en(true)
|
.term_en(true)
|
||||||
.dci_type(slcr::DdriobDciType::Termination)
|
.dci_type(slcr::DdriobDciType::Termination)
|
||||||
.output_en(slcr::DdriobOutputEn::Obuf);
|
.output_en(slcr::DdriobOutputEn::Obuf);
|
||||||
#[cfg(feature = "target_cora_z7_10")]
|
#[cfg(any(
|
||||||
let data1_config = slcr::DdriobConfig::zeroed()
|
feature = "target_coraz7",
|
||||||
.pullup_en(true);
|
feature = "target_ebaz4205",
|
||||||
#[cfg(feature = "target_redpitaya")]
|
feature = "target_redpitaya",
|
||||||
let data0_config = slcr::DdriobConfig::zeroed()
|
feature = "target_kasli_soc",
|
||||||
.inp_type(slcr::DdriobInputType::VrefDifferential)
|
))]
|
||||||
.term_en(true)
|
|
||||||
.dci_type(slcr::DdriobDciType::Termination)
|
|
||||||
.output_en(slcr::DdriobOutputEn::Obuf);
|
|
||||||
#[cfg(feature = "target_redpitaya")]
|
|
||||||
let data1_config = slcr::DdriobConfig::zeroed()
|
let data1_config = slcr::DdriobConfig::zeroed()
|
||||||
.pullup_en(true);
|
.pullup_en(true);
|
||||||
slcr.ddriob_data0.write(data0_config);
|
slcr.ddriob_data0.write(data0_config);
|
||||||
|
@ -173,22 +181,23 @@ impl DdrRam {
|
||||||
.output_en(slcr::DdriobOutputEn::Obuf);
|
.output_en(slcr::DdriobOutputEn::Obuf);
|
||||||
#[cfg(feature = "target_zc706")]
|
#[cfg(feature = "target_zc706")]
|
||||||
let diff1_config = diff0_config.clone();
|
let diff1_config = diff0_config.clone();
|
||||||
#[cfg(feature = "target_cora_z7_10")]
|
#[cfg(any(
|
||||||
|
feature = "target_coraz7",
|
||||||
|
feature = "target_ebaz4205",
|
||||||
|
feature = "target_redpitaya",
|
||||||
|
feature = "target_kasli_soc",
|
||||||
|
))]
|
||||||
let diff0_config = slcr::DdriobConfig::zeroed()
|
let diff0_config = slcr::DdriobConfig::zeroed()
|
||||||
.inp_type(slcr::DdriobInputType::Differential)
|
.inp_type(slcr::DdriobInputType::Differential)
|
||||||
.term_en(true)
|
.term_en(true)
|
||||||
.dci_type(slcr::DdriobDciType::Termination)
|
.dci_type(slcr::DdriobDciType::Termination)
|
||||||
.output_en(slcr::DdriobOutputEn::Obuf);
|
.output_en(slcr::DdriobOutputEn::Obuf);
|
||||||
#[cfg(feature = "target_cora_z7_10")]
|
#[cfg(any(
|
||||||
let diff1_config = slcr::DdriobConfig::zeroed()
|
feature = "target_coraz7",
|
||||||
.pullup_en(true);
|
feature = "target_ebaz4205",
|
||||||
#[cfg(feature = "target_redpitaya")]
|
feature = "target_redpitaya",
|
||||||
let diff0_config = slcr::DdriobConfig::zeroed()
|
feature = "target_kasli_soc",
|
||||||
.inp_type(slcr::DdriobInputType::Differential)
|
))]
|
||||||
.term_en(true)
|
|
||||||
.dci_type(slcr::DdriobDciType::Termination)
|
|
||||||
.output_en(slcr::DdriobOutputEn::Obuf);
|
|
||||||
#[cfg(feature = "target_redpitaya")]
|
|
||||||
let diff1_config = slcr::DdriobConfig::zeroed()
|
let diff1_config = slcr::DdriobConfig::zeroed()
|
||||||
.pullup_en(true);
|
.pullup_en(true);
|
||||||
slcr.ddriob_diff0.write(diff0_config);
|
slcr.ddriob_diff0.write(diff0_config);
|
||||||
|
@ -207,12 +216,17 @@ impl DdrRam {
|
||||||
slcr.ddriob_drive_slew_clock.write(0x00F9861C);
|
slcr.ddriob_drive_slew_clock.write(0x00F9861C);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable external V[REF]
|
#[cfg(any(
|
||||||
#[cfg(feature = "target_cora_z7_10")]
|
feature = "target_coraz7",
|
||||||
|
feature = "target_ebaz4205",
|
||||||
|
feature = "target_redpitaya",
|
||||||
|
feature = "target_kasli_soc",
|
||||||
|
))]
|
||||||
slcr.ddriob_ddr_ctrl.modify(|_, w| w
|
slcr.ddriob_ddr_ctrl.modify(|_, w| w
|
||||||
.vref_int_en(false)
|
.vref_int_en(false)
|
||||||
.vref_ext_en_lower(true)
|
.vref_ext_en_lower(true)
|
||||||
.vref_ext_en_upper(false)
|
.vref_ext_en_upper(false)
|
||||||
|
.refio_en(true)
|
||||||
);
|
);
|
||||||
#[cfg(feature = "target_zc706")]
|
#[cfg(feature = "target_zc706")]
|
||||||
slcr.ddriob_ddr_ctrl.modify(|_, w| w
|
slcr.ddriob_ddr_ctrl.modify(|_, w| w
|
||||||
|
@ -221,22 +235,54 @@ impl DdrRam {
|
||||||
.vref_ext_en_lower(false)
|
.vref_ext_en_lower(false)
|
||||||
.vref_ext_en_upper(false)
|
.vref_ext_en_upper(false)
|
||||||
);
|
);
|
||||||
#[cfg(feature = "target_redpitaya")]
|
|
||||||
slcr.ddriob_ddr_ctrl.modify(|_, w| w
|
|
||||||
.vref_int_en(false)
|
|
||||||
.vref_ext_en_lower(true)
|
|
||||||
.vref_ext_en_upper(false)
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn configure(&mut self) {
|
fn configure(&mut self) {
|
||||||
|
#[cfg(any(feature = "target_coraz7", feature = "target_kasli_soc"))]
|
||||||
|
self.regs.dram_param0.write(
|
||||||
|
regs::DramParam0::zeroed()
|
||||||
|
.t_rc(0x1a)
|
||||||
|
.t_rfc_min(0x9e)
|
||||||
|
.post_selfref_gap_x32(0x10)
|
||||||
|
);
|
||||||
|
#[cfg(feature = "target_ebaz4205")]
|
||||||
|
self.regs.dram_param0.write(
|
||||||
|
regs::DramParam0::zeroed()
|
||||||
|
.t_rc(0x1a)
|
||||||
|
.t_rfc_min(0x56)
|
||||||
|
.post_selfref_gap_x32(0x10)
|
||||||
|
);
|
||||||
|
#[cfg(feature = "target_redpitaya")]
|
||||||
|
self.regs.dram_param0.write(
|
||||||
|
regs::DramParam0::zeroed()
|
||||||
|
.t_rc(0x1b)
|
||||||
|
.t_rfc_min(0xa0)
|
||||||
|
.post_selfref_gap_x32(0x10)
|
||||||
|
);
|
||||||
|
#[cfg(feature = "target_zc706")]
|
||||||
self.regs.dram_param0.write(
|
self.regs.dram_param0.write(
|
||||||
regs::DramParam0::zeroed()
|
regs::DramParam0::zeroed()
|
||||||
.t_rc(0x1b)
|
.t_rc(0x1b)
|
||||||
.t_rfc_min(0x56)
|
.t_rfc_min(0x56)
|
||||||
.post_selfref_gap_x32(0x10)
|
.post_selfref_gap_x32(0x10)
|
||||||
);
|
);
|
||||||
|
#[cfg(feature = "target_ebaz4205")]
|
||||||
|
self.regs.dram_param1.modify(
|
||||||
|
|_, w| w
|
||||||
|
.t_faw(0x16)
|
||||||
|
.t_ras_min(0x13)
|
||||||
|
);
|
||||||
|
#[cfg(feature = "target_redpitaya")]
|
||||||
|
self.regs.dram_param1.modify(
|
||||||
|
|_, w| w
|
||||||
|
.wr2pre(0x12)
|
||||||
|
.powerdown_to_x32(6)
|
||||||
|
.t_faw(0x16)
|
||||||
|
.t_ras_max(0x24)
|
||||||
|
.t_ras_min(0x13)
|
||||||
|
.t_cke(4)
|
||||||
|
);
|
||||||
|
|
||||||
self.regs.dram_param2.write(
|
self.regs.dram_param2.write(
|
||||||
regs::DramParam2::zeroed()
|
regs::DramParam2::zeroed()
|
||||||
|
@ -248,6 +294,25 @@ impl DdrRam {
|
||||||
.rd2pre(0x4)
|
.rd2pre(0x4)
|
||||||
.t_rcd(0x7)
|
.t_rcd(0x7)
|
||||||
);
|
);
|
||||||
|
#[cfg(feature = "target_ebaz4205")]
|
||||||
|
self.regs.dram_param3.modify(
|
||||||
|
|_, w| w
|
||||||
|
.t_rp(7)
|
||||||
|
);
|
||||||
|
#[cfg(feature = "target_redpitaya")]
|
||||||
|
self.regs.dram_param3.modify(
|
||||||
|
|_, w| w
|
||||||
|
.t_ccd(4)
|
||||||
|
.t_rrd(6)
|
||||||
|
.refresh_margin(2)
|
||||||
|
.t_rp(7)
|
||||||
|
.refresh_to_x32(8)
|
||||||
|
.mobile(false)
|
||||||
|
.dfi_dram_clk_disable(false)
|
||||||
|
.read_latency(7)
|
||||||
|
.mode_ddr1_ddr2(true)
|
||||||
|
.dis_pad_pd(false)
|
||||||
|
);
|
||||||
|
|
||||||
self.regs.dram_emr_mr.write(
|
self.regs.dram_emr_mr.write(
|
||||||
regs::DramEmrMr::zeroed()
|
regs::DramEmrMr::zeroed()
|
||||||
|
@ -255,6 +320,25 @@ impl DdrRam {
|
||||||
.emr(0x4)
|
.emr(0x4)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#[cfg(any(
|
||||||
|
feature = "target_coraz7",
|
||||||
|
feature = "target_ebaz4205",
|
||||||
|
feature = "target_redpitaya",
|
||||||
|
feature = "target_kasli_soc",
|
||||||
|
))]
|
||||||
|
self.regs.phy_configs[2].modify(
|
||||||
|
|_, w| w.data_slice_in_use(false)
|
||||||
|
);
|
||||||
|
#[cfg(any(
|
||||||
|
feature = "target_coraz7",
|
||||||
|
feature = "target_ebaz4205",
|
||||||
|
feature = "target_redpitaya",
|
||||||
|
feature = "target_kasli_soc",
|
||||||
|
))]
|
||||||
|
self.regs.phy_configs[3].modify(
|
||||||
|
|_, w| w.data_slice_in_use(false)
|
||||||
|
);
|
||||||
|
|
||||||
self.regs.phy_cmd_timeout_rddata_cpt.modify(
|
self.regs.phy_cmd_timeout_rddata_cpt.modify(
|
||||||
|_, w| w
|
|_, w| w
|
||||||
.rd_cmd_to_data(0x0)
|
.rd_cmd_to_data(0x0)
|
||||||
|
@ -287,12 +371,36 @@ impl DdrRam {
|
||||||
.ctrlup_max(0x40)
|
.ctrlup_max(0x40)
|
||||||
);
|
);
|
||||||
|
|
||||||
self.regs.phy_init_ratio3.write(
|
#[cfg(feature = "target_zc706")]
|
||||||
|
self.regs.phy_init_ratios[3].write(
|
||||||
regs::PhyInitRatio::zeroed()
|
regs::PhyInitRatio::zeroed()
|
||||||
.wrlvl_init_ratio(0x21)
|
.wrlvl_init_ratio(0x21)
|
||||||
.gatelvl_init_ratio(0xee)
|
.gatelvl_init_ratio(0xee)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#[cfg(any(
|
||||||
|
feature = "target_coraz7",
|
||||||
|
feature = "target_ebaz4205",
|
||||||
|
feature = "target_kasli_soc"),
|
||||||
|
)]
|
||||||
|
self.regs.reg_64.modify(
|
||||||
|
|_, w| w
|
||||||
|
.phy_ctrl_slave_ratio(0x100)
|
||||||
|
.phy_invert_clkout(true)
|
||||||
|
);
|
||||||
|
#[cfg(feature = "target_redpitaya")]
|
||||||
|
self.regs.reg_64.modify(
|
||||||
|
|_, w| w
|
||||||
|
.phy_bl2(false)
|
||||||
|
.phy_invert_clkout(true)
|
||||||
|
.phy_sel_logic(false)
|
||||||
|
.phy_ctrl_slave_ratio(0x100)
|
||||||
|
.phy_ctrl_slave_force(false)
|
||||||
|
.phy_ctrl_slave_delay(0)
|
||||||
|
.phy_lpddr(false)
|
||||||
|
.phy_cmd_latency(false)
|
||||||
|
);
|
||||||
|
|
||||||
self.regs.reg_65.write(
|
self.regs.reg_65.write(
|
||||||
regs::Reg65::zeroed()
|
regs::Reg65::zeroed()
|
||||||
.wr_rl_delay(0x2)
|
.wr_rl_delay(0x2)
|
||||||
|
@ -307,7 +415,23 @@ impl DdrRam {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reset DDR controller
|
/// Reset DDR controller
|
||||||
fn reset_ddrc(&mut self) {
|
fn reset_ddrc<F: FnMut(&mut Self)>(&mut self, mut f: F) {
|
||||||
|
#[cfg(feature = "target_zc706")]
|
||||||
|
let width = regs::DataBusWidth::Width32bit;
|
||||||
|
#[cfg(any(
|
||||||
|
feature = "target_coraz7",
|
||||||
|
feature = "target_ebaz4205",
|
||||||
|
feature = "target_redpitaya",
|
||||||
|
feature = "target_kasli_soc",
|
||||||
|
))]
|
||||||
|
let width = regs::DataBusWidth::Width16bit;
|
||||||
|
self.regs.ddrc_ctrl.modify(|_, w| w
|
||||||
|
.soft_rstb(false)
|
||||||
|
.powerdown_en(false)
|
||||||
|
.data_bus_width(width)
|
||||||
|
);
|
||||||
|
f(self);
|
||||||
|
|
||||||
#[cfg(feature = "target_zc706")]
|
#[cfg(feature = "target_zc706")]
|
||||||
unsafe {
|
unsafe {
|
||||||
// row/column address bits
|
// row/column address bits
|
||||||
|
@ -315,18 +439,19 @@ impl DdrRam {
|
||||||
self.regs.dram_addr_map_col.write(0xFFF00000);
|
self.regs.dram_addr_map_col.write(0xFFF00000);
|
||||||
self.regs.dram_addr_map_row.write(0x0F666666);
|
self.regs.dram_addr_map_row.write(0x0F666666);
|
||||||
}
|
}
|
||||||
|
#[cfg(any(
|
||||||
|
feature = "target_coraz7",
|
||||||
|
feature = "target_ebaz4205",
|
||||||
|
feature = "target_redpitaya",
|
||||||
|
feature = "target_kasli_soc",
|
||||||
|
))]
|
||||||
|
unsafe {
|
||||||
|
// row/column address bits
|
||||||
|
self.regs.dram_addr_map_bank.write(0x00000666);
|
||||||
|
self.regs.dram_addr_map_col.write(0xFFFF0000);
|
||||||
|
self.regs.dram_addr_map_row.write(0x0F555555);
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "target_zc706")]
|
|
||||||
let width = regs::DataBusWidth::Width32bit;
|
|
||||||
#[cfg(feature = "target_cora_z7_10")]
|
|
||||||
let width = regs::DataBusWidth::Width16bit;
|
|
||||||
#[cfg(feature = "target_redpitaya")]
|
|
||||||
let width = regs::DataBusWidth::Width16bit;
|
|
||||||
self.regs.ddrc_ctrl.modify(|_, w| w
|
|
||||||
.soft_rstb(false)
|
|
||||||
.powerdown_en(false)
|
|
||||||
.data_bus_width(width)
|
|
||||||
);
|
|
||||||
self.regs.ddrc_ctrl.modify(|_, w| w
|
self.regs.ddrc_ctrl.modify(|_, w| w
|
||||||
.soft_rstb(true)
|
.soft_rstb(true)
|
||||||
.powerdown_en(false)
|
.powerdown_en(false)
|
||||||
|
@ -347,12 +472,18 @@ impl DdrRam {
|
||||||
/// actually there's 1 MB more but starting at 0x0000_0000
|
/// actually there's 1 MB more but starting at 0x0000_0000
|
||||||
/// overlaps with OCM.
|
/// overlaps with OCM.
|
||||||
pub fn size(&self) -> usize {
|
pub fn size(&self) -> usize {
|
||||||
|
// DDR range ends at 0x3FFF_FFFF in the default SCU address
|
||||||
|
// filtering address map
|
||||||
#[cfg(feature = "target_zc706")]
|
#[cfg(feature = "target_zc706")]
|
||||||
let megabytes = 1023;
|
let megabytes = 1023;
|
||||||
#[cfg(feature = "target_cora_z7_10")]
|
#[cfg(any(
|
||||||
let megabytes = 511;
|
feature = "target_coraz7",
|
||||||
#[cfg(feature = "target_redpitaya")]
|
feature = "target_redpitaya",
|
||||||
let megabytes = 511;
|
feature = "target_kasli_soc",
|
||||||
|
))]
|
||||||
|
let megabytes = 512;
|
||||||
|
#[cfg(feature = "target_ebaz4205")]
|
||||||
|
let megabytes = 256;
|
||||||
|
|
||||||
megabytes * 1024 * 1024
|
megabytes * 1024 * 1024
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,14 +33,14 @@ pub struct RegisterBlock {
|
||||||
pub lpr: RW<u32>,
|
pub lpr: RW<u32>,
|
||||||
pub wr: RW<u32>,
|
pub wr: RW<u32>,
|
||||||
pub dram_param0: DramParam0,
|
pub dram_param0: DramParam0,
|
||||||
pub dram_param1: RW<u32>,
|
pub dram_param1: DramParam1,
|
||||||
pub dram_param2: DramParam2,
|
pub dram_param2: DramParam2,
|
||||||
pub dram_param3: RW<u32>,
|
pub dram_param3: DramParam3,
|
||||||
pub dram_param4: RW<u32>,
|
pub dram_param4: RW<u32>,
|
||||||
pub dram_init_param: RW<u32>,
|
pub dram_init_param: RW<u32>,
|
||||||
pub dram_emr: RW<u32>,
|
pub dram_emr: RW<u32>,
|
||||||
pub dram_emr_mr: DramEmrMr,
|
pub dram_emr_mr: DramEmrMr,
|
||||||
pub dram_burst8_rdwr: RW<u32>,
|
pub dram_burst8_rdwr: Burst8Rdwr,
|
||||||
pub dram_disable_dq: RW<u32>,
|
pub dram_disable_dq: RW<u32>,
|
||||||
pub dram_addr_map_bank: RW<u32>,
|
pub dram_addr_map_bank: RW<u32>,
|
||||||
pub dram_addr_map_col: RW<u32>,
|
pub dram_addr_map_col: RW<u32>,
|
||||||
|
@ -60,7 +60,7 @@ pub struct RegisterBlock {
|
||||||
pub ctrl6: RW<u32>,
|
pub ctrl6: RW<u32>,
|
||||||
_unused1: [RO<u32>; 8],
|
_unused1: [RO<u32>; 8],
|
||||||
pub che_refresh_timer01: RW<u32>,
|
pub che_refresh_timer01: RW<u32>,
|
||||||
pub che_t_zq: RW<u32>,
|
pub che_t_zq: CheTZq,
|
||||||
pub che_t_zq_short_interval: RW<u32>,
|
pub che_t_zq_short_interval: RW<u32>,
|
||||||
pub deep_pwrdwn: RW<u32>,
|
pub deep_pwrdwn: RW<u32>,
|
||||||
pub reg_2c: Reg2C,
|
pub reg_2c: Reg2C,
|
||||||
|
@ -84,15 +84,9 @@ pub struct RegisterBlock {
|
||||||
pub che_ecc_corr_bit_mask_63_32_offset: RW<u32>,
|
pub che_ecc_corr_bit_mask_63_32_offset: RW<u32>,
|
||||||
_unused3: [RO<u32>; 5],
|
_unused3: [RO<u32>; 5],
|
||||||
pub phy_rcvr_enable: RW<u32>,
|
pub phy_rcvr_enable: RW<u32>,
|
||||||
pub phy_config0: RW<u32>,
|
pub phy_configs: [PhyConfig; 4],
|
||||||
pub phy_config1: RW<u32>,
|
|
||||||
pub phy_config2: RW<u32>,
|
|
||||||
pub phy_config3: RW<u32>,
|
|
||||||
_unused4: RO<u32>,
|
_unused4: RO<u32>,
|
||||||
pub phy_init_ratio0: PhyInitRatio,
|
pub phy_init_ratios: [PhyInitRatio; 4],
|
||||||
pub phy_init_ratio1: PhyInitRatio,
|
|
||||||
pub phy_init_ratio2: PhyInitRatio,
|
|
||||||
pub phy_init_ratio3: PhyInitRatio,
|
|
||||||
_unused5: RO<u32>,
|
_unused5: RO<u32>,
|
||||||
pub phy_rd_dqs_cfg0: RW<u32>,
|
pub phy_rd_dqs_cfg0: RW<u32>,
|
||||||
pub phy_rd_dqs_cfg1: RW<u32>,
|
pub phy_rd_dqs_cfg1: RW<u32>,
|
||||||
|
@ -114,7 +108,7 @@ pub struct RegisterBlock {
|
||||||
pub wr_data_slv2: RW<u32>,
|
pub wr_data_slv2: RW<u32>,
|
||||||
pub wr_data_slv3: RW<u32>,
|
pub wr_data_slv3: RW<u32>,
|
||||||
_unused9: RO<u32>,
|
_unused9: RO<u32>,
|
||||||
pub reg_64: RW<u32>,
|
pub reg_64: Reg64,
|
||||||
pub reg_65: Reg65,
|
pub reg_65: Reg65,
|
||||||
_unused10: [RO<u32>; 3],
|
_unused10: [RO<u32>; 3],
|
||||||
pub reg69_6a0: RW<u32>,
|
pub reg69_6a0: RW<u32>,
|
||||||
|
@ -138,14 +132,8 @@ pub struct RegisterBlock {
|
||||||
_unused14: [RO<u32>; 5],
|
_unused14: [RO<u32>; 5],
|
||||||
pub axi_id: RW<u32>,
|
pub axi_id: RW<u32>,
|
||||||
pub page_mask: RW<u32>,
|
pub page_mask: RW<u32>,
|
||||||
pub axi_priority_wr_port0: RW<u32>,
|
pub axi_priority_wr_ports: [RW<u32>; 4],
|
||||||
pub axi_priority_wr_port1: RW<u32>,
|
pub axi_priority_rd_ports: [AxiPriorityRd; 4],
|
||||||
pub axi_priority_wr_port2: RW<u32>,
|
|
||||||
pub axi_priority_wr_port3: RW<u32>,
|
|
||||||
pub axi_priority_rd_port0: RW<u32>,
|
|
||||||
pub axi_priority_rd_port1: RW<u32>,
|
|
||||||
pub axi_priority_rd_port2: RW<u32>,
|
|
||||||
pub axi_priority_rd_port3: RW<u32>,
|
|
||||||
_unused15: [RO<u32>; 27],
|
_unused15: [RO<u32>; 27],
|
||||||
pub excl_access_cfg0: RW<u32>,
|
pub excl_access_cfg0: RW<u32>,
|
||||||
pub excl_access_cfg1: RW<u32>,
|
pub excl_access_cfg1: RW<u32>,
|
||||||
|
@ -173,6 +161,14 @@ register_bits!(dram_param0, t_rc, u8, 0, 5);
|
||||||
register_bits!(dram_param0, t_rfc_min, u8, 6, 13);
|
register_bits!(dram_param0, t_rfc_min, u8, 6, 13);
|
||||||
register_bits!(dram_param0, post_selfref_gap_x32, u8, 14, 20);
|
register_bits!(dram_param0, post_selfref_gap_x32, u8, 14, 20);
|
||||||
|
|
||||||
|
register!(dram_param1, DramParam1, RW, u32);
|
||||||
|
register_bits!(dram_param1, wr2pre, u8, 0, 4);
|
||||||
|
register_bits!(dram_param1, powerdown_to_x32, u8, 5, 9);
|
||||||
|
register_bits!(dram_param1, t_faw, u8, 10, 15);
|
||||||
|
register_bits!(dram_param1, t_ras_max, u8, 16, 21);
|
||||||
|
register_bits!(dram_param1, t_ras_min, u8, 22, 26);
|
||||||
|
register_bits!(dram_param1, t_cke, u8, 28, 31);
|
||||||
|
|
||||||
register!(dram_param2, DramParam2, RW, u32);
|
register!(dram_param2, DramParam2, RW, u32);
|
||||||
register_bits!(dram_param2, write_latency, u8, 0, 4);
|
register_bits!(dram_param2, write_latency, u8, 0, 4);
|
||||||
register_bits!(dram_param2, rd2wr, u8, 5, 9);
|
register_bits!(dram_param2, rd2wr, u8, 5, 9);
|
||||||
|
@ -182,10 +178,29 @@ register_bits!(dram_param2, pad_pd, u8, 20, 22);
|
||||||
register_bits!(dram_param2, rd2pre, u8, 23, 27);
|
register_bits!(dram_param2, rd2pre, u8, 23, 27);
|
||||||
register_bits!(dram_param2, t_rcd, u8, 28, 31);
|
register_bits!(dram_param2, t_rcd, u8, 28, 31);
|
||||||
|
|
||||||
|
register!(dram_param3, DramParam3, RW, u32);
|
||||||
|
register_bits!(dram_param3, t_ccd, u8, 2, 4);
|
||||||
|
register_bits!(dram_param3, t_rrd, u8, 5, 7);
|
||||||
|
register_bits!(dram_param3, refresh_margin, u8, 8, 11);
|
||||||
|
register_bits!(dram_param3, t_rp, u8, 12, 15);
|
||||||
|
register_bits!(dram_param3, refresh_to_x32, u8, 16, 20);
|
||||||
|
register_bit!(dram_param3, sdram, 21);
|
||||||
|
register_bit!(dram_param3, mobile, 22);
|
||||||
|
register_bit!(dram_param3, dfi_dram_clk_disable, 23);
|
||||||
|
register_bits!(dram_param3, read_latency, u8, 24, 28);
|
||||||
|
register_bit!(dram_param3, mode_ddr1_ddr2, 29);
|
||||||
|
register_bit!(dram_param3, dis_pad_pd, 30);
|
||||||
|
|
||||||
register!(dram_emr_mr, DramEmrMr, RW, u32);
|
register!(dram_emr_mr, DramEmrMr, RW, u32);
|
||||||
register_bits!(dram_emr_mr, mr, u16, 0, 15);
|
register_bits!(dram_emr_mr, mr, u16, 0, 15);
|
||||||
register_bits!(dram_emr_mr, emr, u16, 16, 31);
|
register_bits!(dram_emr_mr, emr, u16, 16, 31);
|
||||||
|
|
||||||
|
register!(burst8_rdwr, Burst8Rdwr, RW, u32);
|
||||||
|
register_bits!(burst8_rdwr, burst_rdwr, u8, 0, 3);
|
||||||
|
register_bits!(burst8_rdwr, pre_cke_x1024, u16, 4, 13);
|
||||||
|
register_bits!(burst8_rdwr, post_cke_x1024, u16, 16, 25);
|
||||||
|
register_bit!(burst8_rdwr, burstchop, 28);
|
||||||
|
|
||||||
register!(phy_cmd_timeout_rddata_cpt, PhyCmdTimeoutRddataCpt, RW, u32);
|
register!(phy_cmd_timeout_rddata_cpt, PhyCmdTimeoutRddataCpt, RW, u32);
|
||||||
register_bits!(phy_cmd_timeout_rddata_cpt, rd_cmd_to_data, u8, 0, 3);
|
register_bits!(phy_cmd_timeout_rddata_cpt, rd_cmd_to_data, u8, 0, 3);
|
||||||
register_bits!(phy_cmd_timeout_rddata_cpt, wr_cmd_to_data, u8, 4, 7);
|
register_bits!(phy_cmd_timeout_rddata_cpt, wr_cmd_to_data, u8, 4, 7);
|
||||||
|
@ -198,6 +213,13 @@ register_bit!(phy_cmd_timeout_rddata_cpt, clk_stall_level, 19);
|
||||||
register_bits!(phy_cmd_timeout_rddata_cpt, gatelvl_num_of_dq0, u8, 24, 27);
|
register_bits!(phy_cmd_timeout_rddata_cpt, gatelvl_num_of_dq0, u8, 24, 27);
|
||||||
register_bits!(phy_cmd_timeout_rddata_cpt, wrlvl_num_of_dq0, u8, 28, 31);
|
register_bits!(phy_cmd_timeout_rddata_cpt, wrlvl_num_of_dq0, u8, 28, 31);
|
||||||
|
|
||||||
|
register!(che_t_zq, CheTZq, RW, u32);
|
||||||
|
register_bit!(che_t_zq, dis_auto_zq, 0);
|
||||||
|
register_bit!(che_t_zq, ddr3, 1);
|
||||||
|
register_bits!(che_t_zq, t_mod, u8, 2, 11);
|
||||||
|
register_bits!(che_t_zq, t_zq_long_nop, u16, 12, 21);
|
||||||
|
register_bits!(che_t_zq, t_zq_short_nop, u16, 22, 31);
|
||||||
|
|
||||||
register!(reg_2c, Reg2C, RW, u32);
|
register!(reg_2c, Reg2C, RW, u32);
|
||||||
register_bits!(reg_2c, wrlvl_max_x1024, u16, 0, 11);
|
register_bits!(reg_2c, wrlvl_max_x1024, u16, 0, 11);
|
||||||
register_bits!(reg_2c, rdlvl_max_x1024, u16, 12, 23);
|
register_bits!(reg_2c, rdlvl_max_x1024, u16, 12, 23);
|
||||||
|
@ -212,10 +234,27 @@ register_bits!(dfi_timing, rddata_en, u8, 0, 4);
|
||||||
register_bits!(dfi_timing, ctrlup_min, u16, 5, 14);
|
register_bits!(dfi_timing, ctrlup_min, u16, 5, 14);
|
||||||
register_bits!(dfi_timing, ctrlup_max, u16, 15, 24);
|
register_bits!(dfi_timing, ctrlup_max, u16, 15, 24);
|
||||||
|
|
||||||
|
register!(phy_config, PhyConfig, RW, u32);
|
||||||
|
register_bit!(phy_config, data_slice_in_use, 0);
|
||||||
|
register_bit!(phy_config, rdlvl_inc_mode, 1);
|
||||||
|
register_bit!(phy_config, gatelvl_inc_mode, 2);
|
||||||
|
register_bit!(phy_config, wrlvl_inc_mode, 3);
|
||||||
|
register_bits!(phy_config, dq_offset, u8, 24, 30);
|
||||||
|
|
||||||
register!(phy_init_ratio, PhyInitRatio, RW, u32);
|
register!(phy_init_ratio, PhyInitRatio, RW, u32);
|
||||||
register_bits!(phy_init_ratio, wrlvl_init_ratio, u16, 0, 9);
|
register_bits!(phy_init_ratio, wrlvl_init_ratio, u16, 0, 9);
|
||||||
register_bits!(phy_init_ratio, gatelvl_init_ratio, u16, 10, 19);
|
register_bits!(phy_init_ratio, gatelvl_init_ratio, u16, 10, 19);
|
||||||
|
|
||||||
|
register!(reg_64, Reg64, RW, u32);
|
||||||
|
register_bit!(reg_64, phy_bl2, 1);
|
||||||
|
register_bit!(reg_64, phy_invert_clkout, 7);
|
||||||
|
register_bit!(reg_64, phy_sel_logic, 9);
|
||||||
|
register_bits!(reg_64, phy_ctrl_slave_ratio, u16, 10, 19);
|
||||||
|
register_bit!(reg_64, phy_ctrl_slave_force, 20);
|
||||||
|
register_bits!(reg_64, phy_ctrl_slave_delay, u8, 21, 27);
|
||||||
|
register_bit!(reg_64, phy_lpddr, 29);
|
||||||
|
register_bit!(reg_64, phy_cmd_latency, 30);
|
||||||
|
|
||||||
register!(reg_65, Reg65, RW, u32);
|
register!(reg_65, Reg65, RW, u32);
|
||||||
register_bits!(reg_65, wr_rl_delay, u8, 0, 4);
|
register_bits!(reg_65, wr_rl_delay, u8, 0, 4);
|
||||||
register_bits!(reg_65, rd_rl_delay, u8, 5, 9);
|
register_bits!(reg_65, rd_rl_delay, u8, 5, 9);
|
||||||
|
@ -231,3 +270,10 @@ register!(mode_sts_reg,
|
||||||
ModeStsReg, RO, u32);
|
ModeStsReg, RO, u32);
|
||||||
register_bits_typed!(mode_sts_reg, operating_mode, u8, ControllerStatus, 0, 2);
|
register_bits_typed!(mode_sts_reg, operating_mode, u8, ControllerStatus, 0, 2);
|
||||||
// (mode_sts_reg) ...
|
// (mode_sts_reg) ...
|
||||||
|
|
||||||
|
register!(axi_priority_rd, AxiPriorityRd, RW, u32);
|
||||||
|
register_bits!(axi_priority_rd, arb_pri_rd_portn, u16, 0, 9);
|
||||||
|
register_bit!(axi_priority_rd, arb_disable_aging_rd_portn, 16);
|
||||||
|
register_bit!(axi_priority_rd, arb_disable_urgent_rd_portn, 17);
|
||||||
|
register_bit!(axi_priority_rd, arb_disable_page_match_rd_portn, 18);
|
||||||
|
register_bit!(axi_priority_rd, arb_set_hpr_rd_portn, 19);
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
use libregister::{RegisterRW, RegisterW};
|
||||||
|
use libregister::{register, register_at, register_bit, register_bits};
|
||||||
|
use super::slcr;
|
||||||
|
|
||||||
|
pub struct ErrorLED {
|
||||||
|
regs: RegisterBlock,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ErrorLED {
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
pub fn error_led() -> Self {
|
||||||
|
slcr::RegisterBlock::unlocked(|slcr| {
|
||||||
|
// Error LED at MIO pin 37
|
||||||
|
slcr.mio_pin_37.write(
|
||||||
|
slcr::MioPin37::zeroed()
|
||||||
|
.l3_sel(0b000)
|
||||||
|
.io_type(slcr::IoBufferType::Lvcmos25)
|
||||||
|
.pullup(true)
|
||||||
|
.disable_rcvr(true)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Self::error_led_common(0xFFFF - 0x0080)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn error_led_common(gpio_output_mask: u16) -> Self {
|
||||||
|
// Setup register block
|
||||||
|
let self_ = Self {
|
||||||
|
regs: RegisterBlock::error_led(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Setup GPIO output mask
|
||||||
|
self_.regs.gpio_output_mask.modify(|_, w| {
|
||||||
|
w.mask(gpio_output_mask)
|
||||||
|
});
|
||||||
|
|
||||||
|
self_.regs.gpio_direction.modify(|_, w| {
|
||||||
|
w.lederr(true)
|
||||||
|
});
|
||||||
|
|
||||||
|
self_
|
||||||
|
}
|
||||||
|
|
||||||
|
fn led_oe(&mut self, oe: bool) {
|
||||||
|
self.regs.gpio_output_enable.modify(|_, w| {
|
||||||
|
w.lederr(oe)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn led_o(&mut self, o: bool) {
|
||||||
|
self.regs.gpio_output_mask.modify(|_, w| {
|
||||||
|
w.lederr_o(o)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn toggle(&mut self, state: bool) {
|
||||||
|
self.led_o(state);
|
||||||
|
self.led_oe(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub struct RegisterBlock {
|
||||||
|
pub gpio_output_mask: &'static mut GPIOOutputMask,
|
||||||
|
pub gpio_direction: &'static mut GPIODirection,
|
||||||
|
pub gpio_output_enable: &'static mut GPIOOutputEnable,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RegisterBlock {
|
||||||
|
pub fn error_led() -> Self {
|
||||||
|
Self {
|
||||||
|
gpio_output_mask: GPIOOutputMask::new(),
|
||||||
|
gpio_direction: GPIODirection::new(),
|
||||||
|
gpio_output_enable: GPIOOutputEnable::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
register!(gpio_output_mask,
|
||||||
|
/// MASK_DATA_1_LSW:
|
||||||
|
/// Maskable output data for MIO[47:32]
|
||||||
|
GPIOOutputMask, RW, u32);
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
register_at!(GPIOOutputMask, 0xE000A008, new);
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
register_bit!(gpio_output_mask,
|
||||||
|
/// Output for LED_ERR (MIO[37])
|
||||||
|
lederr_o, 5);
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
register_bits!(gpio_output_mask,
|
||||||
|
mask, u16, 16, 31);
|
||||||
|
|
||||||
|
register!(gpio_direction,
|
||||||
|
/// DIRM_1:
|
||||||
|
/// Direction mode for MIO[53:32]; 0/1 = in/out
|
||||||
|
GPIODirection, RW, u32);
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
register_at!(GPIODirection, 0xE000A244, new);
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
register_bit!(gpio_direction,
|
||||||
|
/// Direction for LED_ERR
|
||||||
|
lederr, 5);
|
||||||
|
|
||||||
|
register!(gpio_output_enable,
|
||||||
|
/// OEN_1:
|
||||||
|
/// Output enable for MIO[53:32]
|
||||||
|
GPIOOutputEnable, RW, u32);
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
register_at!(GPIOOutputEnable, 0xE000A248, new);
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
register_bit!(gpio_output_enable,
|
||||||
|
/// Output enable for LED_ERR
|
||||||
|
lederr, 5);
|
||||||
|
|
|
@ -13,6 +13,9 @@ mod regs;
|
||||||
pub mod rx;
|
pub mod rx;
|
||||||
pub mod tx;
|
pub mod tx;
|
||||||
|
|
||||||
|
use super::time::Milliseconds;
|
||||||
|
use embedded_hal::timer::CountDown;
|
||||||
|
|
||||||
/// Size of all the buffers
|
/// Size of all the buffers
|
||||||
pub const MTU: usize = 1536;
|
pub const MTU: usize = 1536;
|
||||||
/// Maximum MDC clock
|
/// Maximum MDC clock
|
||||||
|
@ -62,17 +65,31 @@ impl Gem for Gem0 {
|
||||||
slcr.gem0_clk_ctrl.write(
|
slcr.gem0_clk_ctrl.write(
|
||||||
// 0x0050_0801: 8, 5: 100 Mb/s
|
// 0x0050_0801: 8, 5: 100 Mb/s
|
||||||
// ...: 8, 1: 1000 Mb/s
|
// ...: 8, 1: 1000 Mb/s
|
||||||
|
#[cfg(not(feature = "target_ebaz4205"))]
|
||||||
slcr::GemClkCtrl::zeroed()
|
slcr::GemClkCtrl::zeroed()
|
||||||
.clkact(true)
|
.clkact(true)
|
||||||
.srcsel(slcr::PllSource::IoPll)
|
.srcsel(slcr::PllSource::IoPll)
|
||||||
.divisor(divisor0 as u8)
|
.divisor(divisor0 as u8)
|
||||||
|
.divisor1(divisor1 as u8),
|
||||||
|
// ebaz4205 -- EMIO
|
||||||
|
#[cfg(feature = "target_ebaz4205")]
|
||||||
|
slcr::GemClkCtrl::zeroed()
|
||||||
|
.clkact(true)
|
||||||
|
.srcsel(slcr::PllSource::Emio)
|
||||||
|
.divisor(divisor0 as u8)
|
||||||
.divisor1(divisor1 as u8)
|
.divisor1(divisor1 as u8)
|
||||||
);
|
);
|
||||||
// Enable gem0 recv clock
|
// Enable gem0 recv clock
|
||||||
slcr.gem0_rclk_ctrl.write(
|
slcr.gem0_rclk_ctrl.write(
|
||||||
// 0x0000_0801
|
// 0x0000_0801
|
||||||
|
#[cfg(not(feature = "target_ebaz4205"))]
|
||||||
|
slcr::RclkCtrl::zeroed()
|
||||||
|
.clkact(true),
|
||||||
|
// ebaz4205 -- EMIO
|
||||||
|
#[cfg(feature = "target_ebaz4205")]
|
||||||
slcr::RclkCtrl::zeroed()
|
slcr::RclkCtrl::zeroed()
|
||||||
.clkact(true)
|
.clkact(true)
|
||||||
|
.srcsel(true)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -145,10 +162,13 @@ pub struct Eth<GEM: Gem, RX, TX> {
|
||||||
tx: TX,
|
tx: TX,
|
||||||
inner: EthInner<GEM>,
|
inner: EthInner<GEM>,
|
||||||
phy: Phy,
|
phy: Phy,
|
||||||
|
/// keep track of RX path occupation to avoid needless `check_link_change()`
|
||||||
|
idle: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eth<Gem0, (), ()> {
|
impl Eth<Gem0, (), ()> {
|
||||||
pub fn eth0(macaddr: [u8; 6]) -> Self {
|
pub fn eth0(macaddr: [u8; 6]) -> Self {
|
||||||
|
#[cfg(not(feature = "target_ebaz4205"))]
|
||||||
slcr::RegisterBlock::unlocked(|slcr| {
|
slcr::RegisterBlock::unlocked(|slcr| {
|
||||||
// Manual example: 0x0000_1280
|
// Manual example: 0x0000_1280
|
||||||
// MDIO
|
// MDIO
|
||||||
|
@ -298,22 +318,32 @@ impl<GEM: Gem> Eth<GEM, (), ()> {
|
||||||
fn gem_common(macaddr: [u8; 6]) -> Self {
|
fn gem_common(macaddr: [u8; 6]) -> Self {
|
||||||
GEM::setup_clock(TX_1000);
|
GEM::setup_clock(TX_1000);
|
||||||
|
|
||||||
|
#[cfg(feature="target_kasli_soc")]
|
||||||
|
{
|
||||||
|
let mut eth_reset_pin = PhyRst::rst_pin();
|
||||||
|
eth_reset_pin.reset();
|
||||||
|
}
|
||||||
|
|
||||||
let mut inner = EthInner {
|
let mut inner = EthInner {
|
||||||
gem: PhantomData,
|
gem: PhantomData,
|
||||||
link: None,
|
link: None,
|
||||||
};
|
};
|
||||||
inner.init();
|
inner.init();
|
||||||
|
|
||||||
inner.configure(macaddr);
|
inner.configure(macaddr);
|
||||||
|
|
||||||
let phy = Phy::find(&mut inner).expect("phy");
|
let phy = Phy::find(&mut inner).expect("phy");
|
||||||
phy.reset(&mut inner);
|
phy.reset(&mut inner);
|
||||||
phy.restart_autoneg(&mut inner);
|
phy.restart_autoneg(&mut inner);
|
||||||
|
#[cfg(feature="target_kasli_soc")]
|
||||||
|
phy.set_leds(&mut inner);
|
||||||
|
|
||||||
Eth {
|
Eth {
|
||||||
rx: (),
|
rx: (),
|
||||||
tx: (),
|
tx: (),
|
||||||
inner,
|
inner,
|
||||||
phy,
|
phy,
|
||||||
|
idle: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -325,6 +355,7 @@ impl<GEM: Gem, RX, TX> Eth<GEM, RX, TX> {
|
||||||
tx: self.tx,
|
tx: self.tx,
|
||||||
inner: self.inner,
|
inner: self.inner,
|
||||||
phy: self.phy,
|
phy: self.phy,
|
||||||
|
idle: self.idle,
|
||||||
};
|
};
|
||||||
let list_addr = new_self.rx.list_addr();
|
let list_addr = new_self.rx.list_addr();
|
||||||
assert!(list_addr & 0b11 == 0);
|
assert!(list_addr & 0b11 == 0);
|
||||||
|
@ -344,6 +375,7 @@ impl<GEM: Gem, RX, TX> Eth<GEM, RX, TX> {
|
||||||
tx: tx::DescList::new(tx_size),
|
tx: tx::DescList::new(tx_size),
|
||||||
inner: self.inner,
|
inner: self.inner,
|
||||||
phy: self.phy,
|
phy: self.phy,
|
||||||
|
idle: self.idle,
|
||||||
};
|
};
|
||||||
let list_addr = &new_self.tx.list_addr();
|
let list_addr = &new_self.tx.list_addr();
|
||||||
assert!(list_addr & 0b11 == 0);
|
assert!(list_addr & 0b11 == 0);
|
||||||
|
@ -395,17 +427,31 @@ impl<GEM: Gem, TX> Eth<GEM, rx::DescList, TX> {
|
||||||
regs::RxStatus::zeroed()
|
regs::RxStatus::zeroed()
|
||||||
.frame_recd(true)
|
.frame_recd(true)
|
||||||
);
|
);
|
||||||
|
self.idle = true;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ =>
|
||||||
|
self.idle = false,
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
} else {
|
} else {
|
||||||
self.inner.check_link_change(&self.phy);
|
self.idle = true;
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<GEM: Gem, TX> libasync::smoltcp::LinkCheck for &mut Eth<GEM, rx::DescList, TX> {
|
||||||
|
type Link = Option<phy::Link>;
|
||||||
|
|
||||||
|
fn check_link_change(&mut self) -> Option<Self::Link> {
|
||||||
|
self.inner.check_link_change(&self.phy)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_idle(&self) -> bool {
|
||||||
|
self.idle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<GEM: Gem, RX> Eth<GEM, RX, tx::DescList> {
|
impl<GEM: Gem, RX> Eth<GEM, RX, tx::DescList> {
|
||||||
pub fn send<'s: 'p, 'p>(&'s mut self, length: usize) -> Option<tx::PktRef<'p>> {
|
pub fn send<'s: 'p, 'p>(&'s mut self, length: usize) -> Option<tx::PktRef<'p>> {
|
||||||
self.tx.send(GEM::regs(), length)
|
self.tx.send(GEM::regs(), length)
|
||||||
|
@ -439,10 +485,11 @@ impl<'a, GEM: Gem> smoltcp::phy::Device<'a> for &mut Eth<GEM, rx::DescList, tx::
|
||||||
regs: GEM::regs(),
|
regs: GEM::regs(),
|
||||||
desc_list: &mut self.tx,
|
desc_list: &mut self.tx,
|
||||||
};
|
};
|
||||||
|
self.idle = false;
|
||||||
Some((pktref, tx_token))
|
Some((pktref, tx_token))
|
||||||
}
|
}
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
self.inner.check_link_change(&self.phy);
|
self.idle = true;
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -460,6 +507,69 @@ impl<'a, GEM: Gem> smoltcp::phy::Device<'a> for &mut Eth<GEM, rx::DescList, tx::
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct PhyRst {
|
||||||
|
regs: regs::GpioRegisterBlock,
|
||||||
|
count_down: super::timer::global::CountDown<Milliseconds>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PhyRst {
|
||||||
|
pub fn rst_pin() -> Self {
|
||||||
|
slcr::RegisterBlock::unlocked(|slcr| {
|
||||||
|
// Hardware Reset for PHY
|
||||||
|
slcr.mio_pin_47.write(
|
||||||
|
slcr::MioPin47::zeroed()
|
||||||
|
.l3_sel(0b000)
|
||||||
|
.io_type(slcr::IoBufferType::Lvcmos18)
|
||||||
|
.pullup(true)
|
||||||
|
.disable_rcvr(true)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
Self::eth_reset_common(0xFFFF - 0x8000)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn delay_ms(&mut self, ms: u64) {
|
||||||
|
self.count_down.start(Milliseconds(ms));
|
||||||
|
nb::block!(self.count_down.wait()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eth_reset_common(gpio_output_mask: u16) -> Self {
|
||||||
|
let self_ = Self {
|
||||||
|
regs: regs::GpioRegisterBlock::regs(),
|
||||||
|
count_down: unsafe { super::timer::GlobalTimer::get() }.countdown(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Setup GPIO output mask
|
||||||
|
self_.regs.gpio_output_mask.modify(|_, w| {
|
||||||
|
w.mask(gpio_output_mask)
|
||||||
|
});
|
||||||
|
|
||||||
|
self_.regs.gpio_direction.modify(|_, w| {
|
||||||
|
w.phy_rst(true)
|
||||||
|
});
|
||||||
|
|
||||||
|
self_
|
||||||
|
}
|
||||||
|
|
||||||
|
fn oe(&mut self, oe: bool) {
|
||||||
|
self.regs.gpio_output_enable.modify(|_, w| {
|
||||||
|
w.phy_rst(oe)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn toggle(&mut self, o: bool) {
|
||||||
|
self.regs.gpio_output_mask.modify(|_, w| {
|
||||||
|
w.phy_rst(o)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reset(&mut self) {
|
||||||
|
self.toggle(false); // drive phy_rst (active LOW) pin low
|
||||||
|
self.oe(true); // enable pin's output
|
||||||
|
self.delay_ms(10);
|
||||||
|
self.toggle(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct EthInner<GEM: Gem> {
|
struct EthInner<GEM: Gem> {
|
||||||
gem: PhantomData<GEM>,
|
gem: PhantomData<GEM>,
|
||||||
|
@ -602,13 +712,7 @@ impl<GEM: Gem> EthInner<GEM> {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn check_link_change(&mut self, phy: &Phy) {
|
fn check_link_change(&mut self, phy: &Phy) -> Option<Option<phy::Link>> {
|
||||||
// As the PHY access takes some time, exit early if there was
|
|
||||||
// already a link. TODO: check once per second.
|
|
||||||
if self.link.is_some() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let link = phy.get_link(self);
|
let link = phy.get_link(self);
|
||||||
|
|
||||||
// Check link state transition
|
// Check link state transition
|
||||||
|
@ -640,6 +744,9 @@ impl<GEM: Gem> EthInner<GEM> {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.link = link;
|
self.link = link;
|
||||||
|
Some(link)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,6 +82,10 @@ impl PhyRegister for Control {
|
||||||
fn addr() -> u8 {
|
fn addr() -> u8 {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn page() -> u8 {
|
||||||
|
0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<u16> for Control {
|
impl From<u16> for Control {
|
||||||
|
|
|
@ -11,6 +11,9 @@ pub struct PhyIdentifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn identify_phy<PA: PhyAccess>(pa: &mut PA, addr: u8) -> Option<PhyIdentifier> {
|
pub fn identify_phy<PA: PhyAccess>(pa: &mut PA, addr: u8) -> Option<PhyIdentifier> {
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
pa.write_phy(addr, 0x16, 0); //reset page
|
||||||
|
|
||||||
let id1 = pa.read_phy(addr, 2);
|
let id1 = pa.read_phy(addr, 2);
|
||||||
let id2 = pa.read_phy(addr, 3);
|
let id2 = pa.read_phy(addr, 3);
|
||||||
if id1 != 0xFFFF || id2 != 0xFFFF {
|
if id1 != 0xFFFF || id2 != 0xFFFF {
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
use bit_field::BitField;
|
||||||
|
use super::{PhyRegister, Led0Control, Led1Control};
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
/// LED Control Register
|
||||||
|
pub struct Leds(pub u16);
|
||||||
|
|
||||||
|
impl Leds {
|
||||||
|
pub fn led0(&self) -> Led0Control {
|
||||||
|
match self.0.get_bits(0..=3) {
|
||||||
|
0b0000 => Led0Control::OnLinkOffNoLink,
|
||||||
|
0b0001 => Led0Control::OnLinkBlinkActivityOffNoLink,
|
||||||
|
0b0010 => Led0Control::BlinkDependingOnLink,
|
||||||
|
0b0011 => Led0Control::OnActivityOffNoActivity,
|
||||||
|
0b0100 => Led0Control::BlinkActivityOffNoActivity,
|
||||||
|
0b0101 => Led0Control::OnTransmitOffNoTransmit,
|
||||||
|
0b0110 => Led0Control::OnCopperLinkOffElse,
|
||||||
|
0b0111 => Led0Control::On1000LinkOffElse,
|
||||||
|
0b1000 => Led0Control::ForceOff,
|
||||||
|
0b1001 => Led0Control::ForceOn,
|
||||||
|
0b1010 => Led0Control::ForceHiZ,
|
||||||
|
0b1011 => Led0Control::ForceBlink,
|
||||||
|
0b1100 => Led0Control::Mode1,
|
||||||
|
0b1101 => Led0Control::Mode2,
|
||||||
|
0b1110 => Led0Control::Mode3,
|
||||||
|
0b1111 => Led0Control::Mode4,
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn led1(&self) -> Led1Control {
|
||||||
|
match self.0.get_bits(4..=7) {
|
||||||
|
0b0000 => Led1Control::OnReceiveOffNoReceive,
|
||||||
|
0b0001 => Led1Control::OnLinkBlinkActivityOffNoLink,
|
||||||
|
0b0010 => Led1Control::OnLinkBlinkReceiveOffNoLink,
|
||||||
|
0b0011 => Led1Control::OnActivityOffNoActivity,
|
||||||
|
0b0100 => Led1Control::BlinkActivityOffNoActivity,
|
||||||
|
0b0101 => Led1Control::On100OrFiberOffElse,
|
||||||
|
0b0110 => Led1Control::On1001000LinkOffElse,
|
||||||
|
0b0111 => Led1Control::On100LinkOffElse,
|
||||||
|
0b1000 => Led1Control::ForceOff,
|
||||||
|
0b1001 => Led1Control::ForceOn,
|
||||||
|
0b1010 => Led1Control::ForceHiZ,
|
||||||
|
0b1011 => Led1Control::ForceBlink,
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_led0(mut self, setting: Led0Control) -> Self {
|
||||||
|
self.0.set_bits(0..=3, setting as u16);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_led1(mut self, setting: Led1Control) -> Self {
|
||||||
|
self.0.set_bits(4..=7, setting as u16);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PhyRegister for Leds {
|
||||||
|
fn addr() -> u8 {
|
||||||
|
0x10
|
||||||
|
}
|
||||||
|
|
||||||
|
fn page() -> u8 {
|
||||||
|
3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u16> for Leds {
|
||||||
|
fn from(value: u16) -> Self {
|
||||||
|
Leds(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<u16> for Leds {
|
||||||
|
fn into(self) -> u16 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,8 +6,10 @@ mod control;
|
||||||
pub use control::Control;
|
pub use control::Control;
|
||||||
mod pssr;
|
mod pssr;
|
||||||
pub use pssr::PSSR;
|
pub use pssr::PSSR;
|
||||||
|
mod leds;
|
||||||
|
pub use leds::Leds;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
pub struct Link {
|
pub struct Link {
|
||||||
pub speed: LinkSpeed,
|
pub speed: LinkSpeed,
|
||||||
pub duplex: LinkDuplex,
|
pub duplex: LinkDuplex,
|
||||||
|
@ -26,51 +28,105 @@ pub enum LinkDuplex {
|
||||||
Full,
|
Full,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
|
pub enum Led0Control {
|
||||||
|
OnLinkOffNoLink = 0b0000,
|
||||||
|
OnLinkBlinkActivityOffNoLink = 0b0001,
|
||||||
|
BlinkDependingOnLink = 0b0010,
|
||||||
|
OnActivityOffNoActivity = 0b0011,
|
||||||
|
BlinkActivityOffNoActivity = 0b0100,
|
||||||
|
OnTransmitOffNoTransmit = 0b0101,
|
||||||
|
OnCopperLinkOffElse = 0b0110,
|
||||||
|
On1000LinkOffElse = 0b0111,
|
||||||
|
ForceOff = 0b1000,
|
||||||
|
ForceOn = 0b1001,
|
||||||
|
ForceHiZ = 0b1010,
|
||||||
|
ForceBlink = 0b1011,
|
||||||
|
Mode1 = 0b1100,
|
||||||
|
Mode2 = 0b1101,
|
||||||
|
Mode3 = 0b1110,
|
||||||
|
Mode4 = 0b1111
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
|
pub enum Led1Control {
|
||||||
|
OnReceiveOffNoReceive = 0b0000,
|
||||||
|
OnLinkBlinkActivityOffNoLink = 0b0001,
|
||||||
|
OnLinkBlinkReceiveOffNoLink = 0b0010,
|
||||||
|
OnActivityOffNoActivity = 0b0011,
|
||||||
|
BlinkActivityOffNoActivity = 0b0100,
|
||||||
|
On100OrFiberOffElse = 0b0101,
|
||||||
|
On1001000LinkOffElse = 0b0110,
|
||||||
|
On100LinkOffElse = 0b0111,
|
||||||
|
ForceOff = 0b1000,
|
||||||
|
ForceOn = 0b1001,
|
||||||
|
ForceHiZ = 0b1010,
|
||||||
|
ForceBlink = 0b1011,
|
||||||
|
}
|
||||||
|
|
||||||
pub trait PhyAccess {
|
pub trait PhyAccess {
|
||||||
fn read_phy(&mut self, addr: u8, reg: u8) -> u16;
|
fn read_phy(&mut self, addr: u8, reg: u8) -> u16;
|
||||||
fn write_phy(&mut self, addr: u8, reg: u8, data: u16);
|
fn write_phy(&mut self, addr: u8, reg: u8, data: u16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait PhyRegister {
|
||||||
|
fn addr() -> u8;
|
||||||
|
fn page() -> u8;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Phy {
|
pub struct Phy {
|
||||||
pub addr: u8,
|
pub addr: u8,
|
||||||
device: PhyDevice,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
pub enum PhyDevice {
|
|
||||||
Marvell88E1116R,
|
|
||||||
Rtl8211E,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const OUI_MARVELL: u32 = 0x005043;
|
const OUI_MARVELL: u32 = 0x005043;
|
||||||
const OUI_REALTEK: u32 = 0x000732;
|
const OUI_REALTEK: u32 = 0x000732;
|
||||||
|
const OUI_LANTIQ : u32 = 0x355969;
|
||||||
|
const OUI_ICPLUS : u32 = 0x0090c3;
|
||||||
|
|
||||||
|
//only change pages on Kasli-SoC's Marvel 88E11xx
|
||||||
|
#[cfg(feature="target_kasli_soc")]
|
||||||
|
const PAGE_REGISTER: u8 = 0x16;
|
||||||
|
|
||||||
impl Phy {
|
impl Phy {
|
||||||
/// Probe all addresses on MDIO for a known PHY
|
/// Probe all addresses on MDIO for a known PHY
|
||||||
pub fn find<PA: PhyAccess>(pa: &mut PA) -> Option<Phy> {
|
pub fn find<PA: PhyAccess>(pa: &mut PA) -> Option<Phy> {
|
||||||
(1..32).filter_map(|addr| {
|
(0..32).find(|addr| {
|
||||||
match identify_phy(pa, addr) {
|
match identify_phy(pa, *addr) {
|
||||||
Some(PhyIdentifier {
|
Some(PhyIdentifier {
|
||||||
oui: OUI_MARVELL,
|
oui: OUI_MARVELL,
|
||||||
|
// Marvell 88E1116R
|
||||||
model: 36,
|
model: 36,
|
||||||
..
|
..
|
||||||
}) => Some(PhyDevice::Marvell88E1116R),
|
}) => true,
|
||||||
|
Some(PhyIdentifier {
|
||||||
|
oui: OUI_MARVELL,
|
||||||
|
// Marvell 88E1512
|
||||||
|
model: 29,
|
||||||
|
..
|
||||||
|
}) => true,
|
||||||
Some(PhyIdentifier {
|
Some(PhyIdentifier {
|
||||||
oui: OUI_REALTEK,
|
oui: OUI_REALTEK,
|
||||||
|
// RTL 8211E
|
||||||
model: 0b010001,
|
model: 0b010001,
|
||||||
rev: 0b0101,
|
rev: 0b0101,
|
||||||
}) => Some(PhyDevice::Rtl8211E),
|
}) => true,
|
||||||
_ => None,
|
Some(PhyIdentifier {
|
||||||
}.map(|device| Phy { addr, device })
|
oui: OUI_LANTIQ,
|
||||||
}).next()
|
// Intel XWAY PHY11G (PEF 7071/PEF 7072) v1.5 / v1.6
|
||||||
}
|
model: 0,
|
||||||
|
..
|
||||||
pub fn name(&self) -> &'static str {
|
}) => true,
|
||||||
match self.device {
|
Some(PhyIdentifier {
|
||||||
PhyDevice::Marvell88E1116R => &"Marvell 88E1116R",
|
oui: OUI_ICPLUS,
|
||||||
PhyDevice::Rtl8211E => &"RTL8211E",
|
// IP101G-DS-R01
|
||||||
}
|
model: 5,
|
||||||
|
rev: 4,
|
||||||
|
}) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}).map(|addr| Phy { addr })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_reg<PA, PR>(&self, pa: &mut PA) -> PR
|
pub fn read_reg<PA, PR>(&self, pa: &mut PA) -> PR
|
||||||
|
@ -78,6 +134,9 @@ impl Phy {
|
||||||
PA: PhyAccess,
|
PA: PhyAccess,
|
||||||
PR: PhyRegister + From<u16>,
|
PR: PhyRegister + From<u16>,
|
||||||
{
|
{
|
||||||
|
#[cfg(feature="target_kasli_soc")]
|
||||||
|
pa.write_phy(self.addr, PAGE_REGISTER, PR::page().into());
|
||||||
|
|
||||||
pa.read_phy(self.addr, PR::addr()).into()
|
pa.read_phy(self.addr, PR::addr()).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,6 +146,9 @@ impl Phy {
|
||||||
PR: PhyRegister + From<u16> + Into<u16>,
|
PR: PhyRegister + From<u16> + Into<u16>,
|
||||||
F: FnMut(PR) -> PR,
|
F: FnMut(PR) -> PR,
|
||||||
{
|
{
|
||||||
|
#[cfg(feature="target_kasli_soc")]
|
||||||
|
pa.write_phy(self.addr, PAGE_REGISTER, PR::page().into());
|
||||||
|
|
||||||
let reg = pa.read_phy(self.addr, PR::addr()).into();
|
let reg = pa.read_phy(self.addr, PR::addr()).into();
|
||||||
let reg = f(reg);
|
let reg = f(reg);
|
||||||
pa.write_phy(self.addr, PR::addr(), reg.into())
|
pa.write_phy(self.addr, PR::addr(), reg.into())
|
||||||
|
@ -100,6 +162,14 @@ impl Phy {
|
||||||
self.modify_reg(pa, f)
|
self.modify_reg(pa, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn modify_leds<PA, F>(&self, pa: &mut PA, f: F)
|
||||||
|
where
|
||||||
|
PA: PhyAccess,
|
||||||
|
F: FnMut(Leds) -> Leds,
|
||||||
|
{
|
||||||
|
self.modify_reg(pa, f)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_control<PA: PhyAccess>(&self, pa: &mut PA) -> Control {
|
pub fn get_control<PA: PhyAccess>(&self, pa: &mut PA) -> Control {
|
||||||
self.read_reg(pa)
|
self.read_reg(pa)
|
||||||
}
|
}
|
||||||
|
@ -133,8 +203,12 @@ impl Phy {
|
||||||
.set_restart_autoneg(true)
|
.set_restart_autoneg(true)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub trait PhyRegister {
|
#[cfg(feature="target_kasli_soc")]
|
||||||
fn addr() -> u8;
|
pub fn set_leds<PA: PhyAccess>(&self, pa: &mut PA) {
|
||||||
|
self.modify_leds(pa, |leds|
|
||||||
|
leds.set_led0(Led0Control::OnCopperLinkOffElse)
|
||||||
|
.set_led1(Led1Control::BlinkActivityOffNoActivity)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,10 @@ impl PhyRegister for PSSR {
|
||||||
fn addr() -> u8 {
|
fn addr() -> u8 {
|
||||||
0x11
|
0x11
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn page() -> u8 {
|
||||||
|
0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<u16> for PSSR {
|
impl From<u16> for PSSR {
|
||||||
|
|
|
@ -55,12 +55,22 @@ impl Status {
|
||||||
pub fn get_link(&self) -> Option<Link> {
|
pub fn get_link(&self) -> Option<Link> {
|
||||||
if ! self.link_status() {
|
if ! self.link_status() {
|
||||||
None
|
None
|
||||||
} else if self.cap_10base_t_half() {
|
} else if self.cap_100base_tx_full() {
|
||||||
Some(Link {
|
Some(Link {
|
||||||
speed: LinkSpeed::S10,
|
speed: LinkSpeed::S100,
|
||||||
|
duplex: LinkDuplex::Full,
|
||||||
|
})
|
||||||
|
} else if self.cap_100base_tx_half() {
|
||||||
|
Some(Link {
|
||||||
|
speed: LinkSpeed::S100,
|
||||||
duplex: LinkDuplex::Half,
|
duplex: LinkDuplex::Half,
|
||||||
})
|
})
|
||||||
} else if self.cap_10base_t_full() {
|
} else if self.cap_100base_t4() {
|
||||||
|
Some(Link {
|
||||||
|
speed: LinkSpeed::S100,
|
||||||
|
duplex: LinkDuplex::Half,
|
||||||
|
})
|
||||||
|
} else if self.cap_10base_t2_full() {
|
||||||
Some(Link {
|
Some(Link {
|
||||||
speed: LinkSpeed::S10,
|
speed: LinkSpeed::S10,
|
||||||
duplex: LinkDuplex::Full,
|
duplex: LinkDuplex::Full,
|
||||||
|
@ -70,26 +80,16 @@ impl Status {
|
||||||
speed: LinkSpeed::S10,
|
speed: LinkSpeed::S10,
|
||||||
duplex: LinkDuplex::Half,
|
duplex: LinkDuplex::Half,
|
||||||
})
|
})
|
||||||
} else if self.cap_10base_t2_full() {
|
} else if self.cap_10base_t_full() {
|
||||||
Some(Link {
|
Some(Link {
|
||||||
speed: LinkSpeed::S10,
|
speed: LinkSpeed::S10,
|
||||||
duplex: LinkDuplex::Full,
|
duplex: LinkDuplex::Full,
|
||||||
})
|
})
|
||||||
} else if self.cap_100base_t4() {
|
} else if self.cap_10base_t_half() {
|
||||||
Some(Link {
|
Some(Link {
|
||||||
speed: LinkSpeed::S100,
|
speed: LinkSpeed::S10,
|
||||||
duplex: LinkDuplex::Half,
|
duplex: LinkDuplex::Half,
|
||||||
})
|
})
|
||||||
} else if self.cap_100base_tx_half() {
|
|
||||||
Some(Link {
|
|
||||||
speed: LinkSpeed::S100,
|
|
||||||
duplex: LinkDuplex::Half,
|
|
||||||
})
|
|
||||||
} else if self.cap_100base_tx_full() {
|
|
||||||
Some(Link {
|
|
||||||
speed: LinkSpeed::S100,
|
|
||||||
duplex: LinkDuplex::Full,
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -100,6 +100,10 @@ impl PhyRegister for Status {
|
||||||
fn addr() -> u8 {
|
fn addr() -> u8 {
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn page() -> u8 {
|
||||||
|
0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<u16> for Status {
|
impl From<u16> for Status {
|
||||||
|
|
|
@ -110,6 +110,49 @@ pub struct RegisterBlock {
|
||||||
pub design_cfg5: RO<u32>,
|
pub design_cfg5: RO<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct GpioRegisterBlock {
|
||||||
|
pub gpio_output_mask: &'static mut OutputMask,
|
||||||
|
pub gpio_direction: &'static mut Direction,
|
||||||
|
pub gpio_output_enable: &'static mut OutputEnable,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GpioRegisterBlock {
|
||||||
|
pub fn regs() -> Self {
|
||||||
|
Self {
|
||||||
|
gpio_output_mask: OutputMask::new(),
|
||||||
|
gpio_direction: Direction::new(),
|
||||||
|
gpio_output_enable: OutputEnable::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
register!(gpio_output_mask,
|
||||||
|
/// MASK_DATA_1_SW:
|
||||||
|
/// Maskable output data for MIO[47:32]
|
||||||
|
OutputMask, RW, u32);
|
||||||
|
register_at!(OutputMask, 0xE000A008, new);
|
||||||
|
register_bit!(gpio_output_mask,
|
||||||
|
/// Output for PHY_RST (MIO[47])
|
||||||
|
phy_rst, 15);
|
||||||
|
register_bits!(gpio_output_mask,
|
||||||
|
mask, u16, 16, 31);
|
||||||
|
register!(gpio_direction,
|
||||||
|
/// DIRM_1:
|
||||||
|
/// Direction mode for MIO[53:32]; 0/1 = in/out
|
||||||
|
Direction, RW, u32);
|
||||||
|
register_at!(Direction, 0xE000A244, new);
|
||||||
|
register_bit!(gpio_direction,
|
||||||
|
/// Direction for PHY_RST
|
||||||
|
phy_rst, 15);
|
||||||
|
register!(gpio_output_enable,
|
||||||
|
/// OEN_1:
|
||||||
|
/// Output enable for MIO[53:32]
|
||||||
|
OutputEnable, RW, u32);
|
||||||
|
register_at!(OutputEnable, 0xE000A248, new);
|
||||||
|
register_bit!(gpio_output_enable,
|
||||||
|
/// Output enable for PHY_RST
|
||||||
|
phy_rst, 15);
|
||||||
|
|
||||||
register_at!(RegisterBlock, 0xE000B000, gem0);
|
register_at!(RegisterBlock, 0xE000B000, gem0);
|
||||||
register_at!(RegisterBlock, 0xE000C000, gem1);
|
register_at!(RegisterBlock, 0xE000C000, gem1);
|
||||||
|
|
||||||
|
|
|
@ -115,7 +115,7 @@ impl InterruptController {
|
||||||
let m = (id.0 >> 2) as usize;
|
let m = (id.0 >> 2) as usize;
|
||||||
let n = (8 * (id.0 & 3)) as usize;
|
let n = (8 * (id.0 & 3)) as usize;
|
||||||
unsafe {
|
unsafe {
|
||||||
self.mpcore.icdiptr[m].modify(|mut icdiptr| *icdiptr.set_bits(n..=n+1, target_cpu as u32 + 1));
|
self.mpcore.icdiptr[m].modify(|mut icdiptr| *icdiptr.set_bits(n..=n+1, target_cpu as u32));
|
||||||
}
|
}
|
||||||
|
|
||||||
// sensitivity
|
// sensitivity
|
||||||
|
|
|
@ -4,6 +4,7 @@ use embedded_hal::timer::CountDown;
|
||||||
|
|
||||||
pub struct EEPROM<'a> {
|
pub struct EEPROM<'a> {
|
||||||
i2c: &'a mut I2c,
|
i2c: &'a mut I2c,
|
||||||
|
#[cfg(not(feature = "target_ebaz4205"))]
|
||||||
port: u8,
|
port: u8,
|
||||||
address: u8,
|
address: u8,
|
||||||
page_size: u8,
|
page_size: u8,
|
||||||
|
@ -22,10 +23,32 @@ impl<'a> EEPROM<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
pub fn new(i2c: &'a mut I2c, page_size: u8) -> Self {
|
||||||
|
EEPROM {
|
||||||
|
i2c: i2c,
|
||||||
|
port: 3,
|
||||||
|
address: 0x57,
|
||||||
|
page_size: page_size,
|
||||||
|
count_down: unsafe { crate::timer::GlobalTimer::get() }.countdown()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "target_zc706")]
|
#[cfg(feature = "target_zc706")]
|
||||||
fn select(&mut self) -> Result<(), &'static str> {
|
fn select(&mut self) -> Result<(), &'static str> {
|
||||||
let mask: u16 = 1 << self.port;
|
self.i2c.pca954x_select(0b1110100, Some(self.port))?;
|
||||||
self.i2c.pca9548_select(0b1110100, mask as u8)?;
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
fn select(&mut self) -> Result<(), &'static str> {
|
||||||
|
// tca9548 is compatible with pca9548
|
||||||
|
self.i2c.pca954x_select(0b1110001, Some(self.port))?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "target_ebaz4205")]
|
||||||
|
fn select(&mut self) -> Result<(), &'static str> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,20 +2,33 @@
|
||||||
|
|
||||||
mod regs;
|
mod regs;
|
||||||
pub mod eeprom;
|
pub mod eeprom;
|
||||||
|
#[cfg(not(feature = "target_ebaz4205"))]
|
||||||
use super::slcr;
|
use super::slcr;
|
||||||
use super::time::Microseconds;
|
use super::time::Microseconds;
|
||||||
use embedded_hal::timer::CountDown;
|
use embedded_hal::timer::CountDown;
|
||||||
use libregister::{RegisterR, RegisterRW, RegisterW};
|
use libregister::{RegisterR, RegisterRW};
|
||||||
|
#[cfg(not(feature = "target_ebaz4205"))]
|
||||||
|
use libregister::RegisterW;
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
use log::info;
|
||||||
|
|
||||||
|
pub enum I2cMultiplexer {
|
||||||
|
PCA9548 = 0,
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
PCA9547 = 1,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct I2c {
|
pub struct I2c {
|
||||||
regs: regs::RegisterBlock,
|
regs: regs::RegisterBlock,
|
||||||
count_down: super::timer::global::CountDown<Microseconds>
|
count_down: super::timer::global::CountDown<Microseconds>,
|
||||||
|
pca_type: I2cMultiplexer
|
||||||
}
|
}
|
||||||
|
|
||||||
impl I2c {
|
impl I2c {
|
||||||
#[cfg(feature = "target_zc706")]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
pub fn i2c0() -> Self {
|
pub fn i2c0() -> Self {
|
||||||
// Route I2C 0 SCL / SDA Signals to MIO Pins 50 / 51
|
// Route I2C 0 SCL / SDA Signals to MIO Pins 50 / 51
|
||||||
|
#[cfg(not(feature = "target_ebaz4205"))]
|
||||||
slcr::RegisterBlock::unlocked(|slcr| {
|
slcr::RegisterBlock::unlocked(|slcr| {
|
||||||
// SCL
|
// SCL
|
||||||
slcr.mio_pin_50.write(
|
slcr.mio_pin_50.write(
|
||||||
|
@ -33,18 +46,28 @@ impl I2c {
|
||||||
.pullup(true)
|
.pullup(true)
|
||||||
.disable_rcvr(true)
|
.disable_rcvr(true)
|
||||||
);
|
);
|
||||||
// Reset
|
// On Kasli-SoC prototype, leakage through the unconfigured I2C_SW_RESET
|
||||||
slcr.gpio_rst_ctrl.reset_gpio();
|
// MIO pin develops enough voltage on the T21 gate to assert the reset.
|
||||||
|
// Configure the pin to avoid this problem.
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
slcr.mio_pin_33.write(
|
||||||
|
slcr::MioPin33::zeroed()
|
||||||
|
.l3_sel(0b000)
|
||||||
|
.io_type(slcr::IoBufferType::Lvcmos33)
|
||||||
|
.pullup(false)
|
||||||
|
.disable_rcvr(true)
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
Self::i2c_common(0xFFFF - 0x000C)
|
Self::i2c_common(0xFFFF - 0x000C, 0xFFFF - 0x0002)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn i2c_common(gpio_output_mask: u16) -> Self {
|
fn i2c_common(gpio_output_mask: u16, _gpio_output_mask_lower: u16) -> Self {
|
||||||
// Setup register block
|
// Setup register block
|
||||||
let self_ = Self {
|
let self_ = Self {
|
||||||
regs: regs::RegisterBlock::i2c(),
|
regs: regs::RegisterBlock::i2c(),
|
||||||
count_down: unsafe { super::timer::GlobalTimer::get() }.countdown()
|
count_down: unsafe { super::timer::GlobalTimer::get() }.countdown(),
|
||||||
|
pca_type: I2cMultiplexer::PCA9548 //default for zc706
|
||||||
};
|
};
|
||||||
|
|
||||||
// Setup GPIO output mask
|
// Setup GPIO output mask
|
||||||
|
@ -56,6 +79,17 @@ impl I2c {
|
||||||
w.scl(true).sda(true)
|
w.scl(true).sda(true)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//Kasli-SoC only: I2C_SW_RESET configuration
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
{
|
||||||
|
self_.regs.gpio_output_mask_lower.modify(|_, w| {
|
||||||
|
w.mask(_gpio_output_mask_lower)
|
||||||
|
});
|
||||||
|
self_.regs.gpio_direction.modify(|_, w| {
|
||||||
|
w.i2cswr(true)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
self_
|
self_
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +99,7 @@ impl I2c {
|
||||||
nb::block!(self.count_down.wait()).unwrap();
|
nb::block!(self.count_down.wait()).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn half_period(&mut self) { self.delay_us(100) }
|
fn unit_delay(&mut self) { self.delay_us(100) }
|
||||||
|
|
||||||
fn sda_i(&mut self) -> bool {
|
fn sda_i(&mut self) -> bool {
|
||||||
self.regs.gpio_input.read().sda()
|
self.regs.gpio_input.read().sda()
|
||||||
|
@ -99,6 +133,48 @@ impl I2c {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
fn i2cswr_oe(&mut self, oe: bool) {
|
||||||
|
self.regs.gpio_output_enable.modify(|_, w| {
|
||||||
|
w.i2cswr(oe)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
fn i2cswr_o(&mut self, o: bool) {
|
||||||
|
self.regs.gpio_output_mask_lower.modify(|_, w| {
|
||||||
|
w.i2cswr_o(o)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
fn pca_autodetect(&mut self) -> Result<I2cMultiplexer, &'static str> {
|
||||||
|
// start with resetting the PCA954X
|
||||||
|
// SDA must be clear (before start)
|
||||||
|
// reset time is 500ns, unit_delay (100us) to account for propagation
|
||||||
|
self.i2cswr_o(true);
|
||||||
|
self.unit_delay();
|
||||||
|
self.i2cswr_o(false);
|
||||||
|
self.unit_delay();
|
||||||
|
|
||||||
|
let pca954x_read_addr = (0x71 << 1) | 0x01;
|
||||||
|
|
||||||
|
self.start()?;
|
||||||
|
// read the config register
|
||||||
|
if !self.write(pca954x_read_addr)? {
|
||||||
|
return Err("PCA954X failed to ack read address");
|
||||||
|
}
|
||||||
|
let config = self.read(false)?;
|
||||||
|
|
||||||
|
let pca = match config {
|
||||||
|
0x00 => { info!("PCA9548 detected"); I2cMultiplexer::PCA9548 },
|
||||||
|
0x08 => { info!("PCA9547 detected"); I2cMultiplexer::PCA9547 },
|
||||||
|
_ => { return Err("Unknown response for PCA954X autodetect")},
|
||||||
|
};
|
||||||
|
self.stop()?;
|
||||||
|
Ok(pca)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn init(&mut self) -> Result<(), &'static str> {
|
pub fn init(&mut self) -> Result<(), &'static str> {
|
||||||
self.scl_oe(false);
|
self.scl_oe(false);
|
||||||
self.sda_oe(false);
|
self.sda_oe(false);
|
||||||
|
@ -106,15 +182,15 @@ impl I2c {
|
||||||
self.sda_o(false);
|
self.sda_o(false);
|
||||||
|
|
||||||
// Check the I2C bus is ready
|
// Check the I2C bus is ready
|
||||||
self.half_period();
|
self.unit_delay();
|
||||||
self.half_period();
|
self.unit_delay();
|
||||||
if !self.sda_i() {
|
if !self.sda_i() {
|
||||||
// Try toggling SCL a few times
|
// Try toggling SCL a few times
|
||||||
for _bit in 0..8 {
|
for _bit in 0..8 {
|
||||||
self.scl_oe(true);
|
self.scl_oe(true);
|
||||||
self.half_period();
|
self.unit_delay();
|
||||||
self.scl_oe(false);
|
self.scl_oe(false);
|
||||||
self.half_period();
|
self.unit_delay();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,23 +198,31 @@ impl I2c {
|
||||||
return Err("SDA is stuck low and doesn't get unstuck");
|
return Err("SDA is stuck low and doesn't get unstuck");
|
||||||
}
|
}
|
||||||
if !self.scl_i() {
|
if !self.scl_i() {
|
||||||
return Err("SCL is stuck low and doesn't get unstuck");
|
return Err("SCL is stuck low");
|
||||||
}
|
}
|
||||||
// postcondition: SCL and SDA high
|
// postcondition: SCL and SDA high
|
||||||
|
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
{
|
||||||
|
self.i2cswr_oe(true);
|
||||||
|
self.pca_type = self.pca_autodetect()?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(&mut self) -> Result<(), &'static str> {
|
pub fn start(&mut self) -> Result<(), &'static str> {
|
||||||
// precondition: SCL and SDA high
|
// precondition: SCL and SDA high
|
||||||
if !self.scl_i() {
|
if !self.scl_i() {
|
||||||
return Err("SCL is stuck low and doesn't get unstuck");
|
return Err("SCL is stuck low");
|
||||||
}
|
}
|
||||||
if !self.sda_i() {
|
if !self.sda_i() {
|
||||||
return Err("SDA arbitration lost");
|
return Err("SDA arbitration lost");
|
||||||
}
|
}
|
||||||
self.sda_oe(true);
|
self.sda_oe(true);
|
||||||
self.half_period();
|
self.unit_delay();
|
||||||
self.scl_oe(true);
|
self.scl_oe(true);
|
||||||
|
self.unit_delay();
|
||||||
// postcondition: SCL and SDA low
|
// postcondition: SCL and SDA low
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -146,9 +230,9 @@ impl I2c {
|
||||||
pub fn restart(&mut self) -> Result<(), &'static str> {
|
pub fn restart(&mut self) -> Result<(), &'static str> {
|
||||||
// precondition SCL and SDA low
|
// precondition SCL and SDA low
|
||||||
self.sda_oe(false);
|
self.sda_oe(false);
|
||||||
self.half_period();
|
self.unit_delay();
|
||||||
self.scl_oe(false);
|
self.scl_oe(false);
|
||||||
self.half_period();
|
self.unit_delay();
|
||||||
self.start()?;
|
self.start()?;
|
||||||
// postcondition: SCL and SDA low
|
// postcondition: SCL and SDA low
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -156,11 +240,11 @@ impl I2c {
|
||||||
|
|
||||||
pub fn stop(&mut self) -> Result<(), &'static str> {
|
pub fn stop(&mut self) -> Result<(), &'static str> {
|
||||||
// precondition: SCL and SDA low
|
// precondition: SCL and SDA low
|
||||||
self.half_period();
|
self.unit_delay();
|
||||||
self.scl_oe(false);
|
self.scl_oe(false);
|
||||||
self.half_period();
|
self.unit_delay();
|
||||||
self.sda_oe(false);
|
self.sda_oe(false);
|
||||||
self.half_period();
|
self.unit_delay();
|
||||||
if !self.sda_i() {
|
if !self.sda_i() {
|
||||||
return Err("SDA arbitration lost");
|
return Err("SDA arbitration lost");
|
||||||
}
|
}
|
||||||
|
@ -173,18 +257,20 @@ impl I2c {
|
||||||
// MSB first
|
// MSB first
|
||||||
for bit in (0..8).rev() {
|
for bit in (0..8).rev() {
|
||||||
self.sda_oe(data & (1 << bit) == 0);
|
self.sda_oe(data & (1 << bit) == 0);
|
||||||
self.half_period();
|
self.unit_delay();
|
||||||
self.scl_oe(false);
|
self.scl_oe(false);
|
||||||
self.half_period();
|
self.unit_delay();
|
||||||
self.scl_oe(true);
|
self.scl_oe(true);
|
||||||
|
self.unit_delay();
|
||||||
}
|
}
|
||||||
self.sda_oe(false);
|
self.sda_oe(false);
|
||||||
self.half_period();
|
self.unit_delay();
|
||||||
self.scl_oe(false);
|
self.scl_oe(false);
|
||||||
self.half_period();
|
self.unit_delay();
|
||||||
// Read ack/nack
|
// Read ack/nack
|
||||||
let ack = !self.sda_i();
|
let ack = !self.sda_i();
|
||||||
self.scl_oe(true);
|
self.scl_oe(true);
|
||||||
|
self.unit_delay();
|
||||||
self.sda_oe(true);
|
self.sda_oe(true);
|
||||||
// postcondition: SCL and SDA low
|
// postcondition: SCL and SDA low
|
||||||
|
|
||||||
|
@ -199,17 +285,17 @@ impl I2c {
|
||||||
|
|
||||||
// MSB first
|
// MSB first
|
||||||
for bit in (0..8).rev() {
|
for bit in (0..8).rev() {
|
||||||
self.half_period();
|
self.unit_delay();
|
||||||
self.scl_oe(false);
|
self.scl_oe(false);
|
||||||
self.half_period();
|
self.unit_delay();
|
||||||
if self.sda_i() { data |= 1 << bit }
|
if self.sda_i() { data |= 1 << bit }
|
||||||
self.scl_oe(true);
|
self.scl_oe(true);
|
||||||
}
|
}
|
||||||
// Send ack/nack
|
// Send ack/nack (true = nack, false = ack)
|
||||||
self.sda_oe(ack);
|
self.sda_oe(ack);
|
||||||
self.half_period();
|
self.unit_delay();
|
||||||
self.scl_oe(false);
|
self.scl_oe(false);
|
||||||
self.half_period();
|
self.unit_delay();
|
||||||
self.scl_oe(true);
|
self.scl_oe(true);
|
||||||
self.sda_oe(true);
|
self.sda_oe(true);
|
||||||
// postcondition: SCL and SDA low
|
// postcondition: SCL and SDA low
|
||||||
|
@ -217,13 +303,32 @@ impl I2c {
|
||||||
Ok(data)
|
Ok(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pca9548_select(&mut self, address: u8, channels: u8) -> Result<(), &'static str> {
|
pub fn pca954x_select(&mut self, address: u8, channel: Option<u8>) -> Result<(), &'static str> {
|
||||||
self.start()?;
|
self.start()?;
|
||||||
|
// PCA9547 supports only one channel at a time
|
||||||
|
// for compatibility, PCA9548 is treated as such too
|
||||||
|
// channel - Some(x) - # of the channel [0,7], or None for all disabled
|
||||||
|
let setting = match self.pca_type {
|
||||||
|
I2cMultiplexer::PCA9548 => {
|
||||||
|
match channel {
|
||||||
|
Some(ch) => 1 << ch,
|
||||||
|
None => 0,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
I2cMultiplexer::PCA9547 => {
|
||||||
|
match channel {
|
||||||
|
Some(ch) => ch | 0x08,
|
||||||
|
None => 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if !self.write(address << 1)? {
|
if !self.write(address << 1)? {
|
||||||
return Err("PCA9548 failed to ack write address")
|
return Err("PCA954X failed to ack write address")
|
||||||
}
|
}
|
||||||
if !self.write(channels)? {
|
if !self.write(setting)? {
|
||||||
return Err("PCA9548 failed to ack control word")
|
return Err("PCA954X failed to ack control word")
|
||||||
}
|
}
|
||||||
self.stop()?;
|
self.stop()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -20,12 +20,16 @@ use libregister::{
|
||||||
//
|
//
|
||||||
// Current compatibility:
|
// Current compatibility:
|
||||||
// zc706: GPIO 50, 51 == SCL, SDA
|
// zc706: GPIO 50, 51 == SCL, SDA
|
||||||
|
// kasli_soc: GPIO 50, 51 == SCL, SDA; GPIO 33 == I2C_SW_RESET
|
||||||
|
// ebaz4205: GPIO (EMIO)
|
||||||
|
|
||||||
pub struct RegisterBlock {
|
pub struct RegisterBlock {
|
||||||
pub gpio_output_mask: &'static mut GPIOOutputMask,
|
pub gpio_output_mask: &'static mut GPIOOutputMask,
|
||||||
pub gpio_input: &'static mut GPIOInput,
|
pub gpio_input: &'static mut GPIOInput,
|
||||||
pub gpio_direction: &'static mut GPIODirection,
|
pub gpio_direction: &'static mut GPIODirection,
|
||||||
pub gpio_output_enable: &'static mut GPIOOutputEnable,
|
pub gpio_output_enable: &'static mut GPIOOutputEnable,
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
pub gpio_output_mask_lower: &'static mut GPIOOutputMaskLower,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RegisterBlock {
|
impl RegisterBlock {
|
||||||
|
@ -34,58 +38,98 @@ impl RegisterBlock {
|
||||||
gpio_output_mask: GPIOOutputMask::new(),
|
gpio_output_mask: GPIOOutputMask::new(),
|
||||||
gpio_input: GPIOInput::new(),
|
gpio_input: GPIOInput::new(),
|
||||||
gpio_direction: GPIODirection::new(),
|
gpio_direction: GPIODirection::new(),
|
||||||
gpio_output_enable: GPIOOutputEnable::new()
|
gpio_output_enable: GPIOOutputEnable::new(),
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
gpio_output_mask_lower: GPIOOutputMaskLower::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MASK_DATA_1_MSW:
|
register!(gpio_output_mask,
|
||||||
// Maskable output data for MIO[53:48]
|
/// MASK_DATA_1_MSW:
|
||||||
register!(gpio_output_mask, GPIOOutputMask, RW, u32);
|
/// Maskable output data for MIO[53:48]
|
||||||
#[cfg(feature = "target_zc706")]
|
GPIOOutputMask, RW, u32);
|
||||||
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
register_at!(GPIOOutputMask, 0xE000A00C, new);
|
register_at!(GPIOOutputMask, 0xE000A00C, new);
|
||||||
// Output for SCL
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
#[cfg(feature = "target_zc706")]
|
register_bit!(gpio_output_mask,
|
||||||
register_bit!(gpio_output_mask, scl_o, 2);
|
/// Output for SCL
|
||||||
// Output for SDA
|
scl_o, 2);
|
||||||
#[cfg(feature = "target_zc706")]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
register_bit!(gpio_output_mask, sda_o, 3);
|
register_bit!(gpio_output_mask,
|
||||||
// Mask for keeping bits except SCL and SDA unchanged
|
/// Output for SDA
|
||||||
#[cfg(feature = "target_zc706")]
|
sda_o, 3);
|
||||||
register_bits!(gpio_output_mask, mask, u16, 16, 31);
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
|
register_bits!(gpio_output_mask,
|
||||||
|
/// Mask for keeping bits except SCL and SDA unchanged
|
||||||
|
mask, u16, 16, 31);
|
||||||
|
|
||||||
// DATA_1_RO:
|
|
||||||
// Input data for MIO[53:32]
|
register!(gpio_output_mask_lower,
|
||||||
register!(gpio_input, GPIOInput, RO, u32);
|
/// MASK_DATA_1_LSW:
|
||||||
#[cfg(feature = "target_zc706")]
|
/// Maskable output data for MIO[47:32]
|
||||||
|
GPIOOutputMaskLower, RW, u32);
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
register_at!(GPIOOutputMaskLower, 0xE000A008, new);
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
register_bit!(gpio_output_mask_lower,
|
||||||
|
/// Output for I2C_SW_RESET (MIO[33])
|
||||||
|
i2cswr_o, 1);
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
register_bits!(gpio_output_mask_lower,
|
||||||
|
mask, u16, 16, 31);
|
||||||
|
|
||||||
|
register!(gpio_input,
|
||||||
|
/// DATA_1_RO:
|
||||||
|
/// Input data for MIO[53:32]
|
||||||
|
GPIOInput, RO, u32);
|
||||||
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
register_at!(GPIOInput, 0xE000A064, new);
|
register_at!(GPIOInput, 0xE000A064, new);
|
||||||
// Input for SCL
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
#[cfg(feature = "target_zc706")]
|
register_bit!(gpio_input,
|
||||||
register_bit!(gpio_input, scl, 18);
|
/// Input for SCL
|
||||||
// Input for SDA
|
scl, 18);
|
||||||
#[cfg(feature = "target_zc706")]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
register_bit!(gpio_input, sda, 19);
|
register_bit!(gpio_input,
|
||||||
|
/// Input for SDA
|
||||||
|
sda, 19);
|
||||||
|
|
||||||
// DIRM_1:
|
|
||||||
// Direction mode for MIO[53:32]; 0/1 = in/out
|
register!(gpio_direction,
|
||||||
register!(gpio_direction, GPIODirection, RW, u32);
|
/// DIRM_1:
|
||||||
#[cfg(feature = "target_zc706")]
|
/// Direction mode for MIO[53:32]; 0/1 = in/out
|
||||||
|
GPIODirection, RW, u32);
|
||||||
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
register_at!(GPIODirection, 0xE000A244, new);
|
register_at!(GPIODirection, 0xE000A244, new);
|
||||||
// Direction for SCL
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
#[cfg(feature = "target_zc706")]
|
register_bit!(gpio_direction,
|
||||||
register_bit!(gpio_direction, scl, 18);
|
/// Direction for SCL
|
||||||
// Direction for SDA
|
scl, 18);
|
||||||
#[cfg(feature = "target_zc706")]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
register_bit!(gpio_direction, sda, 19);
|
register_bit!(gpio_direction,
|
||||||
|
/// Direction for SDA
|
||||||
|
sda, 19);
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
register_bit!(gpio_direction,
|
||||||
|
/// Direction for I2C_SW_RESET
|
||||||
|
i2cswr, 1);
|
||||||
|
|
||||||
// OEN_1:
|
register!(gpio_output_enable,
|
||||||
// Output enable for MIO[53:32]
|
/// OEN_1:
|
||||||
register!(gpio_output_enable, GPIOOutputEnable, RW, u32);
|
/// Output enable for MIO[53:32]
|
||||||
#[cfg(feature = "target_zc706")]
|
GPIOOutputEnable, RW, u32);
|
||||||
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
register_at!(GPIOOutputEnable, 0xE000A248, new);
|
register_at!(GPIOOutputEnable, 0xE000A248, new);
|
||||||
// Output enable for SCL
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
#[cfg(feature = "target_zc706")]
|
register_bit!(gpio_output_enable,
|
||||||
register_bit!(gpio_output_enable, scl, 18);
|
/// Output enable for SCL
|
||||||
// Output enable for SDA
|
scl, 18);
|
||||||
#[cfg(feature = "target_zc706")]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
register_bit!(gpio_output_enable, sda, 19);
|
register_bit!(gpio_output_enable,
|
||||||
|
/// Output enable for SDA
|
||||||
|
sda, 19);
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
register_bit!(gpio_output_enable,
|
||||||
|
/// Output enable for I2C_SW_RESET
|
||||||
|
i2cswr, 1);
|
||||||
|
|
|
@ -19,7 +19,9 @@ pub mod gic;
|
||||||
pub mod time;
|
pub mod time;
|
||||||
pub mod timer;
|
pub mod timer;
|
||||||
pub mod sdio;
|
pub mod sdio;
|
||||||
#[cfg(feature = "target_zc706")]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
||||||
pub mod i2c;
|
pub mod i2c;
|
||||||
pub mod logger;
|
pub mod logger;
|
||||||
pub mod ps7_init;
|
pub mod ps7_init;
|
||||||
|
#[cfg(feature="target_kasli_soc")]
|
||||||
|
pub mod error_led;
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
#![cfg(feature = "target_zc706")]
|
|
||||||
|
|
||||||
use crate::println;
|
use crate::println;
|
||||||
|
|
||||||
|
#[cfg(feature = "target_zc706")]
|
||||||
mod zc706;
|
mod zc706;
|
||||||
// mod cora_z7_10;
|
#[cfg(not(feature = "target_zc706"))]
|
||||||
|
mod none;
|
||||||
|
|
||||||
#[cfg(feature = "target_zc706")]
|
#[cfg(feature = "target_zc706")]
|
||||||
use zc706 as target;
|
use zc706 as target;
|
||||||
// #[cfg(feature = "target_cora_z7_10")]
|
#[cfg(not(feature = "target_zc706"))]
|
||||||
// use cora_z7_10 as target;
|
use none as target;
|
||||||
|
|
||||||
pub fn report_differences() {
|
pub fn report_differences() {
|
||||||
for (i, op) in target::INIT_DATA.iter().enumerate() {
|
for (i, op) in target::INIT_DATA.iter().enumerate() {
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
use super::InitOp;
|
||||||
|
|
||||||
|
pub const INIT_DATA: &'static [InitOp] = &[
|
||||||
|
];
|
|
@ -105,7 +105,7 @@ impl Sdio {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// cora card detect pin
|
// cora card detect pin
|
||||||
#[cfg(feature = "target_cora_z7_10")]
|
#[cfg(feature = "target_coraz7")]
|
||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
slcr.sd0_wp_cd_sel.write(47 << 16);
|
slcr.sd0_wp_cd_sel.write(47 << 16);
|
||||||
|
@ -116,8 +116,8 @@ impl Sdio {
|
||||||
.speed(true),
|
.speed(true),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// redpitaya card detect pin
|
// kasli_soc and redpitaya card detect pin
|
||||||
#[cfg(feature = "target_redpitaya")]
|
#[cfg(any(feature = "target_kasli_soc", feature = "target_redpitaya"))]
|
||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
slcr.sd0_wp_cd_sel.write(46 << 16);
|
slcr.sd0_wp_cd_sel.write(46 << 16);
|
||||||
|
@ -128,6 +128,20 @@ impl Sdio {
|
||||||
.speed(true),
|
.speed(true),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
// ebaz4205 card detect pin
|
||||||
|
#[cfg(feature = "target_ebaz4205")]
|
||||||
|
{
|
||||||
|
unsafe {
|
||||||
|
slcr.sd0_wp_cd_sel.write(34 << 16);
|
||||||
|
}
|
||||||
|
slcr.mio_pin_34.write(
|
||||||
|
slcr::MioPin34::zeroed()
|
||||||
|
.io_type(slcr::IoBufferType::Lvcmos33)
|
||||||
|
.pullup(true)
|
||||||
|
.speed(true),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
slcr.sdio_rst_ctrl.reset_sdio0();
|
slcr.sdio_rst_ctrl.reset_sdio0();
|
||||||
slcr.aper_clk_ctrl.enable_sdio0();
|
slcr.aper_clk_ctrl.enable_sdio0();
|
||||||
slcr.sdio_clk_ctrl.enable_sdio0();
|
slcr.sdio_clk_ctrl.enable_sdio0();
|
||||||
|
|
|
@ -9,9 +9,11 @@ use libregister::{
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum PllSource {
|
pub enum PllSource {
|
||||||
IoPll = 0b00,
|
IoPll = 0b000,
|
||||||
ArmPll = 0b10,
|
ArmPll = 0b010,
|
||||||
DdrPll = 0b11,
|
DdrPll = 0b011,
|
||||||
|
// Ethernet controller 0 EMIO clock
|
||||||
|
Emio = 0b100,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
|
@ -587,6 +589,17 @@ register_bit!(a9_cpu_rst_ctrl, a9_clkstop0, 4);
|
||||||
register_bit!(a9_cpu_rst_ctrl, a9_rst1, 1);
|
register_bit!(a9_cpu_rst_ctrl, a9_rst1, 1);
|
||||||
register_bit!(a9_cpu_rst_ctrl, a9_rst0, 0);
|
register_bit!(a9_cpu_rst_ctrl, a9_rst0, 0);
|
||||||
|
|
||||||
|
pub fn reboot() {
|
||||||
|
RegisterBlock::unlocked(|slcr| {
|
||||||
|
unsafe {
|
||||||
|
let reboot = slcr.reboot_status.read();
|
||||||
|
slcr.reboot_status.write(reboot & 0xF0FFFFFF);
|
||||||
|
slcr.pss_rst_ctrl.modify(|_, w| w.soft_rst(true));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum BootModePins {
|
pub enum BootModePins {
|
||||||
|
@ -605,7 +618,7 @@ register_bit!(boot_mode, jtag_routing, 3);
|
||||||
register_bits_typed!(boot_mode, boot_mode_pins, u8, BootModePins, 0, 2);
|
register_bits_typed!(boot_mode, boot_mode_pins, u8, BootModePins, 0, 2);
|
||||||
|
|
||||||
register!(pss_rst_ctrl, PssRstCtrl, RW, u32);
|
register!(pss_rst_ctrl, PssRstCtrl, RW, u32);
|
||||||
register_bit!(pss_rst_ctrl, soft_rst, 1);
|
register_bit!(pss_rst_ctrl, soft_rst, 0);
|
||||||
|
|
||||||
/// Used for MioPin*.io_type
|
/// Used for MioPin*.io_type
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
|
|
|
@ -45,9 +45,13 @@ impl DerefMut for LazyUart {
|
||||||
fn deref_mut(&mut self) -> &mut Uart {
|
fn deref_mut(&mut self) -> &mut Uart {
|
||||||
match self {
|
match self {
|
||||||
LazyUart::Uninitialized => {
|
LazyUart::Uninitialized => {
|
||||||
#[cfg(any(feature = "target_cora_z7_10", feature = "target_redpitaya"))]
|
#[cfg(any(feature = "target_coraz7", feature = "target_redpitaya"))]
|
||||||
let uart = Uart::uart0(UART_RATE);
|
let uart = Uart::uart0(UART_RATE);
|
||||||
#[cfg(feature = "target_zc706")]
|
#[cfg(any(
|
||||||
|
feature = "target_zc706",
|
||||||
|
feature = "target_ebaz4205",
|
||||||
|
feature = "target_kasli_soc",
|
||||||
|
))]
|
||||||
let uart = Uart::uart1(UART_RATE);
|
let uart = Uart::uart1(UART_RATE);
|
||||||
*self = LazyUart::Initialized(uart);
|
*self = LazyUart::Initialized(uart);
|
||||||
self
|
self
|
||||||
|
|
|
@ -13,7 +13,7 @@ pub struct Uart {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Uart {
|
impl Uart {
|
||||||
#[cfg(any(feature = "target_cora_z7_10", feature = "target_redpitaya"))]
|
#[cfg(any(feature = "target_coraz7", feature = "target_redpitaya"))]
|
||||||
pub fn uart0(baudrate: u32) -> Self {
|
pub fn uart0(baudrate: u32) -> Self {
|
||||||
slcr::RegisterBlock::unlocked(|slcr| {
|
slcr::RegisterBlock::unlocked(|slcr| {
|
||||||
// Route UART 0 RxD/TxD Signals to MIO Pins
|
// Route UART 0 RxD/TxD Signals to MIO Pins
|
||||||
|
@ -46,7 +46,7 @@ impl Uart {
|
||||||
self_
|
self_
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "target_zc706")]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||||
pub fn uart1(baudrate: u32) -> Self {
|
pub fn uart1(baudrate: u32) -> Self {
|
||||||
slcr::RegisterBlock::unlocked(|slcr| {
|
slcr::RegisterBlock::unlocked(|slcr| {
|
||||||
// Route UART 1 RxD/TxD Signals to MIO Pins
|
// Route UART 1 RxD/TxD Signals to MIO Pins
|
||||||
|
@ -79,6 +79,39 @@ impl Uart {
|
||||||
self_
|
self_
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "target_ebaz4205")]
|
||||||
|
pub fn uart1(baudrate: u32) -> Self {
|
||||||
|
slcr::RegisterBlock::unlocked(|slcr| {
|
||||||
|
// Route UART 1 RxD/TxD Signals to MIO Pins
|
||||||
|
// TX pin
|
||||||
|
slcr.mio_pin_24.write(
|
||||||
|
slcr::MioPin24::zeroed()
|
||||||
|
.l3_sel(0b111)
|
||||||
|
.io_type(slcr::IoBufferType::Lvcmos33)
|
||||||
|
.pullup(true)
|
||||||
|
);
|
||||||
|
// RX pin
|
||||||
|
slcr.mio_pin_25.write(
|
||||||
|
slcr::MioPin25::zeroed()
|
||||||
|
.tri_enable(true)
|
||||||
|
.l3_sel(0b111)
|
||||||
|
.io_type(slcr::IoBufferType::Lvcmos33)
|
||||||
|
.pullup(true)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
slcr::RegisterBlock::unlocked(|slcr| {
|
||||||
|
slcr.uart_rst_ctrl.reset_uart1();
|
||||||
|
slcr.aper_clk_ctrl.enable_uart1();
|
||||||
|
slcr.uart_clk_ctrl.enable_uart1();
|
||||||
|
});
|
||||||
|
let mut self_ = Uart {
|
||||||
|
regs: regs::RegisterBlock::uart1(),
|
||||||
|
};
|
||||||
|
self_.configure(baudrate);
|
||||||
|
self_
|
||||||
|
}
|
||||||
|
|
||||||
pub fn write_byte(&mut self, value: u8) {
|
pub fn write_byte(&mut self, value: u8) {
|
||||||
while self.tx_fifo_full() {}
|
while self.tx_fifo_full() {}
|
||||||
|
|
||||||
|
|
|
@ -11,5 +11,10 @@ fatfs = { version = "0.3", features = ["core_io"], default-features = false }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
target_zc706 = []
|
||||||
|
target_coraz7 = []
|
||||||
|
target_ebaz4205 = []
|
||||||
|
target_redpitaya = []
|
||||||
|
target_kasli_soc = []
|
||||||
ipv6 = []
|
ipv6 = []
|
||||||
|
fat_lfn = [ "fatfs/alloc" ]
|
|
@ -3,7 +3,7 @@ extern crate alloc;
|
||||||
|
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use alloc::{string::FromUtf8Error, string::String, vec::Vec, rc::Rc};
|
use alloc::{string::FromUtf8Error, string::String, vec::Vec, rc::Rc};
|
||||||
use core_io::{self as io, BufRead, BufReader, Read};
|
use core_io::{self as io, BufRead, BufReader, Read, Write, Seek, SeekFrom};
|
||||||
use libboard_zynq::sdio;
|
use libboard_zynq::sdio;
|
||||||
|
|
||||||
pub mod sd_reader;
|
pub mod sd_reader;
|
||||||
|
@ -56,9 +56,9 @@ fn parse_config<'a>(
|
||||||
buffer: &mut Vec<u8>,
|
buffer: &mut Vec<u8>,
|
||||||
file: fatfs::File<sd_reader::SdReader>,
|
file: fatfs::File<sd_reader::SdReader>,
|
||||||
) -> Result<'a, ()> {
|
) -> Result<'a, ()> {
|
||||||
let prefix = [key, "="].concat();
|
let prefix = [key, "="].concat().to_ascii_lowercase();
|
||||||
for line in BufReader::new(file).lines() {
|
for line in BufReader::new(file).lines() {
|
||||||
let line = line?;
|
let line = line?.to_ascii_lowercase();
|
||||||
if line.starts_with(&prefix) {
|
if line.starts_with(&prefix) {
|
||||||
buffer.extend(line[prefix.len()..].as_bytes());
|
buffer.extend(line[prefix.len()..].as_bytes());
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
@ -71,6 +71,8 @@ pub struct Config {
|
||||||
fs: Option<Rc<fatfs::FileSystem<sd_reader::SdReader>>>,
|
fs: Option<Rc<fatfs::FileSystem<sd_reader::SdReader>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const NEWLINE: &[u8] = b"\n";
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
pub fn new() -> Result<'static, Self> {
|
pub fn new() -> Result<'static, Self> {
|
||||||
let sdio = sdio::Sdio::sdio0(true);
|
let sdio = sdio::Sdio::sdio0(true);
|
||||||
|
@ -112,4 +114,61 @@ impl Config {
|
||||||
pub fn read_str<'b>(&self, key: &'b str) -> Result<'b, String> {
|
pub fn read_str<'b>(&self, key: &'b str) -> Result<'b, String> {
|
||||||
Ok(String::from_utf8(self.read(key)?)?)
|
Ok(String::from_utf8(self.read(key)?)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn remove<'b>(&self, key: &'b str) -> Result<'b, ()> {
|
||||||
|
if let Some(fs) = &self.fs {
|
||||||
|
let root_dir = fs.root_dir();
|
||||||
|
match root_dir.remove(&["/CONFIG/", key, ".BIN"].concat()) {
|
||||||
|
Ok(()) => Ok(()),
|
||||||
|
Err(_) => {
|
||||||
|
let prefix = [key, "="].concat().to_ascii_lowercase();
|
||||||
|
match root_dir.create_file("/CONFIG.TXT") {
|
||||||
|
Ok(mut f) => {
|
||||||
|
let mut buffer = String::new();
|
||||||
|
f.read_to_string(&mut buffer)?;
|
||||||
|
f.seek(SeekFrom::Start(0))?;
|
||||||
|
f.truncate()?;
|
||||||
|
for line in buffer.lines() {
|
||||||
|
if line.len() > 0 && !line.to_ascii_lowercase().starts_with(&prefix) {
|
||||||
|
f.write(line.as_bytes())?;
|
||||||
|
f.write(NEWLINE)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
Err(_) => Err(Error::KeyNotFoundError(key))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(Error::NoConfig)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write<'b>(&self, key: &'b str, value: Vec<u8>) -> Result<'b, ()> {
|
||||||
|
if self.fs.is_none() {
|
||||||
|
return Err(Error::NoConfig);
|
||||||
|
}
|
||||||
|
let fs = self.fs.as_ref().unwrap();
|
||||||
|
let root_dir = fs.root_dir();
|
||||||
|
let is_str = value.len() <= 100 && value.is_ascii() && !value.contains(&b'\n');
|
||||||
|
if key == "boot" {
|
||||||
|
let mut f = root_dir.create_file("/BOOT.BIN")?;
|
||||||
|
f.truncate()?;
|
||||||
|
f.write_all(&value)?;
|
||||||
|
drop(f);
|
||||||
|
} else {
|
||||||
|
let _ = self.remove(key);
|
||||||
|
if is_str {
|
||||||
|
let mut f = root_dir.create_file("/CONFIG.TXT")?;
|
||||||
|
f.seek(SeekFrom::End(0))?;
|
||||||
|
write!(f, "{}={}\n", key, String::from_utf8(value).unwrap())?;
|
||||||
|
} else {
|
||||||
|
let dir = root_dir.create_dir("/CONFIG")?;
|
||||||
|
let mut f = dir.create_file(&[key, ".BIN"].concat())?;
|
||||||
|
f.write_all(&value)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,9 +30,39 @@ impl fmt::Display for NetAddresses {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_adresses(cfg: &Config) -> NetAddresses {
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
fn get_address_from_eeprom() -> EthernetAddress {
|
||||||
|
use libboard_zynq::i2c::{I2c, eeprom};
|
||||||
|
|
||||||
|
let mut i2c = I2c::i2c0();
|
||||||
|
i2c.init().unwrap();
|
||||||
|
let mut eeprom = eeprom::EEPROM::new(&mut i2c, 16);
|
||||||
|
let address = eeprom.read_eui48().unwrap_or([0x02, 0x00, 0x00, 0x00, 0x00, 0x56]);
|
||||||
|
|
||||||
|
EthernetAddress(address)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_addresses(cfg: &Config) -> NetAddresses {
|
||||||
|
#[cfg(feature = "target_zc706")]
|
||||||
let mut hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x52]);
|
let mut hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x52]);
|
||||||
|
#[cfg(feature = "target_zc706")]
|
||||||
let mut ipv4_addr = IpAddress::v4(192, 168, 1, 52);
|
let mut ipv4_addr = IpAddress::v4(192, 168, 1, 52);
|
||||||
|
#[cfg(feature = "target_coraz7")]
|
||||||
|
let mut hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x54]);
|
||||||
|
#[cfg(feature = "target_coraz7")]
|
||||||
|
let mut ipv4_addr = IpAddress::v4(192, 168, 1, 54);
|
||||||
|
#[cfg(feature = "target_redpitaya")]
|
||||||
|
let mut hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x55]);
|
||||||
|
#[cfg(feature = "target_redpitaya")]
|
||||||
|
let mut ipv4_addr = IpAddress::v4(192, 168, 1, 55);
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
let mut hardware_addr = get_address_from_eeprom();
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
let mut ipv4_addr = IpAddress::v4(192, 168, 1, 56);
|
||||||
|
#[cfg(feature = "target_ebaz4205")]
|
||||||
|
let mut hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x57]);
|
||||||
|
#[cfg(feature = "target_ebaz4205")]
|
||||||
|
let mut ipv4_addr = IpAddress::v4(192, 168, 1, 57);
|
||||||
|
|
||||||
if let Ok(Ok(addr)) = cfg.read_str("mac").map(|s| s.parse()) {
|
if let Ok(Ok(addr)) = cfg.read_str("mac").map(|s| s.parse()) {
|
||||||
hardware_addr = addr;
|
hardware_addr = addr;
|
||||||
|
@ -41,7 +71,7 @@ pub fn get_adresses(cfg: &Config) -> NetAddresses {
|
||||||
ipv4_addr = addr;
|
ipv4_addr = addr;
|
||||||
}
|
}
|
||||||
#[cfg(feature = "ipv6")]
|
#[cfg(feature = "ipv6")]
|
||||||
let ipv6_addr = cfg.read_str("ipv6").ok().and_then(|s| s.parse().ok());
|
let ipv6_addr = cfg.read_str("ip6").ok().and_then(|s| s.parse().ok());
|
||||||
|
|
||||||
#[cfg(feature = "ipv6")]
|
#[cfg(feature = "ipv6")]
|
||||||
let ipv6_ll_addr = IpAddress::v6(
|
let ipv6_ll_addr = IpAddress::v6(
|
||||||
|
|
|
@ -10,6 +10,7 @@ const PARTID_FAT16_LESS32M: u8 = 0x04;
|
||||||
const PARTID_FAT16: u8 = 0x06;
|
const PARTID_FAT16: u8 = 0x06;
|
||||||
const PARTID_FAT32: u8 = 0x0B;
|
const PARTID_FAT32: u8 = 0x0B;
|
||||||
const PARTID_FAT32_LBA: u8 = 0x0C;
|
const PARTID_FAT32_LBA: u8 = 0x0C;
|
||||||
|
const PARTID_FAT16_LBA: u8 = 0x0E;
|
||||||
|
|
||||||
fn cmd_error_to_io_error(_: CmdTransferError) -> Error {
|
fn cmd_error_to_io_error(_: CmdTransferError) -> Error {
|
||||||
Error::new(ErrorKind::Other, "Command transfer error")
|
Error::new(ErrorKind::Other, "Command transfer error")
|
||||||
|
@ -161,7 +162,7 @@ impl SdReader {
|
||||||
debug!("Partition ID: {:0X}", buffer[0]);
|
debug!("Partition ID: {:0X}", buffer[0]);
|
||||||
match buffer[0] {
|
match buffer[0] {
|
||||||
PARTID_FAT12 | PARTID_FAT16_LESS32M | PARTID_FAT16 |
|
PARTID_FAT12 | PARTID_FAT16_LESS32M | PARTID_FAT16 |
|
||||||
PARTID_FAT32 | PARTID_FAT32_LBA => {}
|
PARTID_FAT16_LBA | PARTID_FAT32 | PARTID_FAT32_LBA => {}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
ErrorKind::InvalidData,
|
ErrorKind::InvalidData,
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
[package]
|
|
||||||
authors = ["M-Labs"]
|
|
||||||
name = "core_io"
|
|
||||||
version = "0.1.20200410"
|
|
||||||
|
|
||||||
[lib]
|
|
||||||
name = "core_io"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
memchr = { version = "2", default-features = false, optional = true }
|
|
||||||
|
|
||||||
[features]
|
|
||||||
alloc = []
|
|
||||||
collections = ["alloc", "memchr"]
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,896 +0,0 @@
|
||||||
use crate::io::prelude::*;
|
|
||||||
|
|
||||||
use core::cmp;
|
|
||||||
use crate::io::{self, Error, ErrorKind, Initializer, SeekFrom};
|
|
||||||
|
|
||||||
#[cfg(feature = "collections")]
|
|
||||||
use core::convert::TryInto;
|
|
||||||
|
|
||||||
#[cfg(feature="collections")]
|
|
||||||
use collections::vec::Vec;
|
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
|
||||||
use alloc::boxed::Box;
|
|
||||||
|
|
||||||
/// A `Cursor` wraps an in-memory buffer and provides it with a
|
|
||||||
/// [`Seek`] implementation.
|
|
||||||
///
|
|
||||||
/// `Cursor`s are used with in-memory buffers, anything implementing
|
|
||||||
/// `AsRef<[u8]>`, to allow them to implement [`Read`] and/or [`Write`],
|
|
||||||
/// allowing these buffers to be used anywhere you might use a reader or writer
|
|
||||||
/// that does actual I/O.
|
|
||||||
///
|
|
||||||
/// The standard library implements some I/O traits on various types which
|
|
||||||
/// are commonly used as a buffer, like `Cursor<`[`Vec`]`<u8>>` and
|
|
||||||
/// `Cursor<`[`&[u8]`][bytes]`>`.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// We may want to write bytes to a [`File`] in our production
|
|
||||||
/// code, but use an in-memory buffer in our tests. We can do this with
|
|
||||||
/// `Cursor`:
|
|
||||||
///
|
|
||||||
/// [`Seek`]: trait.Seek.html
|
|
||||||
/// [`Read`]: ../../std/io/trait.Read.html
|
|
||||||
/// [`Write`]: ../../std/io/trait.Write.html
|
|
||||||
/// [`Vec`]: ../../std/vec/struct.Vec.html
|
|
||||||
/// [bytes]: ../../std/primitive.slice.html
|
|
||||||
/// [`File`]: ../fs/struct.File.html
|
|
||||||
///
|
|
||||||
/// ```no_run
|
|
||||||
/// use std::io::prelude::*;
|
|
||||||
/// use std::io::{self, SeekFrom};
|
|
||||||
/// use std::fs::File;
|
|
||||||
///
|
|
||||||
/// // a library function we've written
|
|
||||||
/// fn write_ten_bytes_at_end<W: Write + Seek>(writer: &mut W) -> io::Result<()> {
|
|
||||||
/// writer.seek(SeekFrom::End(-10))?;
|
|
||||||
///
|
|
||||||
/// for i in 0..10 {
|
|
||||||
/// writer.write(&[i])?;
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// // all went well
|
|
||||||
/// Ok(())
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// # fn foo() -> io::Result<()> {
|
|
||||||
/// // Here's some code that uses this library function.
|
|
||||||
/// //
|
|
||||||
/// // We might want to use a BufReader here for efficiency, but let's
|
|
||||||
/// // keep this example focused.
|
|
||||||
/// let mut file = File::create("foo.txt")?;
|
|
||||||
///
|
|
||||||
/// write_ten_bytes_at_end(&mut file)?;
|
|
||||||
/// # Ok(())
|
|
||||||
/// # }
|
|
||||||
///
|
|
||||||
/// // now let's write a test
|
|
||||||
/// #[test]
|
|
||||||
/// fn test_writes_bytes() {
|
|
||||||
/// // setting up a real File is much slower than an in-memory buffer,
|
|
||||||
/// // let's use a cursor instead
|
|
||||||
/// use std::io::Cursor;
|
|
||||||
/// let mut buff = Cursor::new(vec![0; 15]);
|
|
||||||
///
|
|
||||||
/// write_ten_bytes_at_end(&mut buff).unwrap();
|
|
||||||
///
|
|
||||||
/// assert_eq!(&buff.get_ref()[5..15], &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
|
||||||
pub struct Cursor<T> {
|
|
||||||
inner: T,
|
|
||||||
pos: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Cursor<T> {
|
|
||||||
/// Creates a new cursor wrapping the provided underlying in-memory buffer.
|
|
||||||
///
|
|
||||||
/// Cursor initial position is `0` even if underlying buffer (e.g., `Vec`)
|
|
||||||
/// is not empty. So writing to cursor starts with overwriting `Vec`
|
|
||||||
/// content, not with appending to it.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use std::io::Cursor;
|
|
||||||
///
|
|
||||||
/// let buff = Cursor::new(Vec::new());
|
|
||||||
/// # fn force_inference(_: &Cursor<Vec<u8>>) {}
|
|
||||||
/// # force_inference(&buff);
|
|
||||||
/// ```
|
|
||||||
pub fn new(inner: T) -> Cursor<T> {
|
|
||||||
Cursor { pos: 0, inner }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Consumes this cursor, returning the underlying value.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use std::io::Cursor;
|
|
||||||
///
|
|
||||||
/// let buff = Cursor::new(Vec::new());
|
|
||||||
/// # fn force_inference(_: &Cursor<Vec<u8>>) {}
|
|
||||||
/// # force_inference(&buff);
|
|
||||||
///
|
|
||||||
/// let vec = buff.into_inner();
|
|
||||||
/// ```
|
|
||||||
pub fn into_inner(self) -> T {
|
|
||||||
self.inner
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets a reference to the underlying value in this cursor.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use std::io::Cursor;
|
|
||||||
///
|
|
||||||
/// let buff = Cursor::new(Vec::new());
|
|
||||||
/// # fn force_inference(_: &Cursor<Vec<u8>>) {}
|
|
||||||
/// # force_inference(&buff);
|
|
||||||
///
|
|
||||||
/// let reference = buff.get_ref();
|
|
||||||
/// ```
|
|
||||||
pub fn get_ref(&self) -> &T {
|
|
||||||
&self.inner
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets a mutable reference to the underlying value in this cursor.
|
|
||||||
///
|
|
||||||
/// Care should be taken to avoid modifying the internal I/O state of the
|
|
||||||
/// underlying value as it may corrupt this cursor's position.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use std::io::Cursor;
|
|
||||||
///
|
|
||||||
/// let mut buff = Cursor::new(Vec::new());
|
|
||||||
/// # fn force_inference(_: &Cursor<Vec<u8>>) {}
|
|
||||||
/// # force_inference(&buff);
|
|
||||||
///
|
|
||||||
/// let reference = buff.get_mut();
|
|
||||||
/// ```
|
|
||||||
pub fn get_mut(&mut self) -> &mut T {
|
|
||||||
&mut self.inner
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the current position of this cursor.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use std::io::Cursor;
|
|
||||||
/// use std::io::prelude::*;
|
|
||||||
/// use std::io::SeekFrom;
|
|
||||||
///
|
|
||||||
/// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]);
|
|
||||||
///
|
|
||||||
/// assert_eq!(buff.position(), 0);
|
|
||||||
///
|
|
||||||
/// buff.seek(SeekFrom::Current(2)).unwrap();
|
|
||||||
/// assert_eq!(buff.position(), 2);
|
|
||||||
///
|
|
||||||
/// buff.seek(SeekFrom::Current(-1)).unwrap();
|
|
||||||
/// assert_eq!(buff.position(), 1);
|
|
||||||
/// ```
|
|
||||||
pub fn position(&self) -> u64 {
|
|
||||||
self.pos
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets the position of this cursor.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use std::io::Cursor;
|
|
||||||
///
|
|
||||||
/// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]);
|
|
||||||
///
|
|
||||||
/// assert_eq!(buff.position(), 0);
|
|
||||||
///
|
|
||||||
/// buff.set_position(2);
|
|
||||||
/// assert_eq!(buff.position(), 2);
|
|
||||||
///
|
|
||||||
/// buff.set_position(4);
|
|
||||||
/// assert_eq!(buff.position(), 4);
|
|
||||||
/// ```
|
|
||||||
pub fn set_position(&mut self, pos: u64) {
|
|
||||||
self.pos = pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> io::Seek for Cursor<T>
|
|
||||||
where
|
|
||||||
T: AsRef<[u8]>,
|
|
||||||
{
|
|
||||||
fn seek(&mut self, style: SeekFrom) -> io::Result<u64> {
|
|
||||||
let (base_pos, offset) = match style {
|
|
||||||
SeekFrom::Start(n) => {
|
|
||||||
self.pos = n;
|
|
||||||
return Ok(n);
|
|
||||||
}
|
|
||||||
SeekFrom::End(n) => (self.inner.as_ref().len() as u64, n),
|
|
||||||
SeekFrom::Current(n) => (self.pos, n),
|
|
||||||
};
|
|
||||||
let new_pos = if offset >= 0 {
|
|
||||||
base_pos.checked_add(offset as u64)
|
|
||||||
} else {
|
|
||||||
base_pos.checked_sub((offset.wrapping_neg()) as u64)
|
|
||||||
};
|
|
||||||
match new_pos {
|
|
||||||
Some(n) => {
|
|
||||||
self.pos = n;
|
|
||||||
Ok(self.pos)
|
|
||||||
}
|
|
||||||
None => Err(Error::new(
|
|
||||||
ErrorKind::InvalidInput,
|
|
||||||
"invalid seek to a negative or overflowing position",
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn stream_len(&mut self) -> io::Result<u64> {
|
|
||||||
Ok(self.inner.as_ref().len() as u64)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn stream_position(&mut self) -> io::Result<u64> {
|
|
||||||
Ok(self.pos)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Read for Cursor<T>
|
|
||||||
where
|
|
||||||
T: AsRef<[u8]>,
|
|
||||||
{
|
|
||||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
|
||||||
let n = Read::read(&mut self.get_ref().as_ref(), buf)?;
|
|
||||||
self.pos += n as u64;
|
|
||||||
Ok(n)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
|
|
||||||
let n = buf.len();
|
|
||||||
Read::read_exact(&mut self.get_ref().as_ref(), buf)?;
|
|
||||||
self.pos += n as u64;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn initializer(&self) -> Initializer {
|
|
||||||
Initializer::nop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "collections")]
|
|
||||||
impl<T> BufRead for Cursor<T>
|
|
||||||
where
|
|
||||||
T: AsRef<[u8]>,
|
|
||||||
{
|
|
||||||
fn fill_buf(&mut self) -> io::Result<&[u8]> {
|
|
||||||
let amt = cmp::min(self.pos, self.inner.as_ref().len() as u64);
|
|
||||||
Ok(&self.inner.as_ref()[(amt as usize)..])
|
|
||||||
}
|
|
||||||
fn consume(&mut self, amt: usize) {
|
|
||||||
self.pos += amt as u64;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Non-resizing write implementation
|
|
||||||
#[inline]
|
|
||||||
fn slice_write(pos_mut: &mut u64, slice: &mut [u8], buf: &[u8]) -> io::Result<usize> {
|
|
||||||
let pos = cmp::min(*pos_mut, slice.len() as u64);
|
|
||||||
let amt = (&mut slice[(pos as usize)..]).write(buf)?;
|
|
||||||
*pos_mut += amt as u64;
|
|
||||||
Ok(amt)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resizing write implementation
|
|
||||||
#[cfg(feature = "collections")]
|
|
||||||
fn vec_write(pos_mut: &mut u64, vec: &mut Vec<u8>, buf: &[u8]) -> io::Result<usize> {
|
|
||||||
let pos: usize = (*pos_mut).try_into().map_err(|_| {
|
|
||||||
Error::new(
|
|
||||||
ErrorKind::InvalidInput,
|
|
||||||
"cursor position exceeds maximum possible vector length",
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
// Make sure the internal buffer is as least as big as where we
|
|
||||||
// currently are
|
|
||||||
let len = vec.len();
|
|
||||||
if len < pos {
|
|
||||||
// use `resize` so that the zero filling is as efficient as possible
|
|
||||||
vec.resize(pos, 0);
|
|
||||||
}
|
|
||||||
// Figure out what bytes will be used to overwrite what's currently
|
|
||||||
// there (left), and what will be appended on the end (right)
|
|
||||||
{
|
|
||||||
let space = vec.len() - pos;
|
|
||||||
let (left, right) = buf.split_at(cmp::min(space, buf.len()));
|
|
||||||
vec[pos..pos + left.len()].copy_from_slice(left);
|
|
||||||
vec.extend_from_slice(right);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bump us forward
|
|
||||||
*pos_mut = (pos + buf.len()) as u64;
|
|
||||||
Ok(buf.len())
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Write for Cursor<&mut [u8]> {
|
|
||||||
#[inline]
|
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
|
||||||
slice_write(&mut self.pos, self.inner, buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn flush(&mut self) -> io::Result<()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "collections")]
|
|
||||||
impl Write for Cursor<&mut Vec<u8>> {
|
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
|
||||||
vec_write(&mut self.pos, self.inner, buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn flush(&mut self) -> io::Result<()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "collections")]
|
|
||||||
impl Write for Cursor<Vec<u8>> {
|
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
|
||||||
vec_write(&mut self.pos, &mut self.inner, buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn flush(&mut self) -> io::Result<()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
|
||||||
impl Write for Cursor<Box<[u8]>> {
|
|
||||||
#[inline]
|
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
|
||||||
slice_write(&mut self.pos, &mut self.inner, buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn flush(&mut self) -> io::Result<()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use crate::io::prelude::*;
|
|
||||||
use crate::io::{Cursor, IoSlice, IoSliceMut, SeekFrom};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_vec_writer() {
|
|
||||||
let mut writer = Vec::new();
|
|
||||||
assert_eq!(writer.write(&[0]).unwrap(), 1);
|
|
||||||
assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
|
|
||||||
assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
|
|
||||||
assert_eq!(
|
|
||||||
writer
|
|
||||||
.write_vectored(&[IoSlice::new(&[]), IoSlice::new(&[8, 9]), IoSlice::new(&[10])],)
|
|
||||||
.unwrap(),
|
|
||||||
3
|
|
||||||
);
|
|
||||||
let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
|
||||||
assert_eq!(writer, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_mem_writer() {
|
|
||||||
let mut writer = Cursor::new(Vec::new());
|
|
||||||
assert_eq!(writer.write(&[0]).unwrap(), 1);
|
|
||||||
assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
|
|
||||||
assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
|
|
||||||
assert_eq!(
|
|
||||||
writer
|
|
||||||
.write_vectored(&[IoSlice::new(&[]), IoSlice::new(&[8, 9]), IoSlice::new(&[10])],)
|
|
||||||
.unwrap(),
|
|
||||||
3
|
|
||||||
);
|
|
||||||
let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
|
||||||
assert_eq!(&writer.get_ref()[..], b);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_mem_mut_writer() {
|
|
||||||
let mut vec = Vec::new();
|
|
||||||
let mut writer = Cursor::new(&mut vec);
|
|
||||||
assert_eq!(writer.write(&[0]).unwrap(), 1);
|
|
||||||
assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
|
|
||||||
assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
|
|
||||||
assert_eq!(
|
|
||||||
writer
|
|
||||||
.write_vectored(&[IoSlice::new(&[]), IoSlice::new(&[8, 9]), IoSlice::new(&[10])],)
|
|
||||||
.unwrap(),
|
|
||||||
3
|
|
||||||
);
|
|
||||||
let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
|
||||||
assert_eq!(&writer.get_ref()[..], b);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_box_slice_writer() {
|
|
||||||
let mut writer = Cursor::new(vec![0u8; 9].into_boxed_slice());
|
|
||||||
assert_eq!(writer.position(), 0);
|
|
||||||
assert_eq!(writer.write(&[0]).unwrap(), 1);
|
|
||||||
assert_eq!(writer.position(), 1);
|
|
||||||
assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
|
|
||||||
assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
|
|
||||||
assert_eq!(writer.position(), 8);
|
|
||||||
assert_eq!(writer.write(&[]).unwrap(), 0);
|
|
||||||
assert_eq!(writer.position(), 8);
|
|
||||||
|
|
||||||
assert_eq!(writer.write(&[8, 9]).unwrap(), 1);
|
|
||||||
assert_eq!(writer.write(&[10]).unwrap(), 0);
|
|
||||||
let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8];
|
|
||||||
assert_eq!(&**writer.get_ref(), b);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_box_slice_writer_vectored() {
|
|
||||||
let mut writer = Cursor::new(vec![0u8; 9].into_boxed_slice());
|
|
||||||
assert_eq!(writer.position(), 0);
|
|
||||||
assert_eq!(writer.write_vectored(&[IoSlice::new(&[0])]).unwrap(), 1);
|
|
||||||
assert_eq!(writer.position(), 1);
|
|
||||||
assert_eq!(
|
|
||||||
writer
|
|
||||||
.write_vectored(&[IoSlice::new(&[1, 2, 3]), IoSlice::new(&[4, 5, 6, 7]),])
|
|
||||||
.unwrap(),
|
|
||||||
7,
|
|
||||||
);
|
|
||||||
assert_eq!(writer.position(), 8);
|
|
||||||
assert_eq!(writer.write_vectored(&[]).unwrap(), 0);
|
|
||||||
assert_eq!(writer.position(), 8);
|
|
||||||
|
|
||||||
assert_eq!(writer.write_vectored(&[IoSlice::new(&[8, 9])]).unwrap(), 1);
|
|
||||||
assert_eq!(writer.write_vectored(&[IoSlice::new(&[10])]).unwrap(), 0);
|
|
||||||
let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8];
|
|
||||||
assert_eq!(&**writer.get_ref(), b);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_buf_writer() {
|
|
||||||
let mut buf = [0 as u8; 9];
|
|
||||||
{
|
|
||||||
let mut writer = Cursor::new(&mut buf[..]);
|
|
||||||
assert_eq!(writer.position(), 0);
|
|
||||||
assert_eq!(writer.write(&[0]).unwrap(), 1);
|
|
||||||
assert_eq!(writer.position(), 1);
|
|
||||||
assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
|
|
||||||
assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
|
|
||||||
assert_eq!(writer.position(), 8);
|
|
||||||
assert_eq!(writer.write(&[]).unwrap(), 0);
|
|
||||||
assert_eq!(writer.position(), 8);
|
|
||||||
|
|
||||||
assert_eq!(writer.write(&[8, 9]).unwrap(), 1);
|
|
||||||
assert_eq!(writer.write(&[10]).unwrap(), 0);
|
|
||||||
}
|
|
||||||
let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8];
|
|
||||||
assert_eq!(buf, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_buf_writer_vectored() {
|
|
||||||
let mut buf = [0 as u8; 9];
|
|
||||||
{
|
|
||||||
let mut writer = Cursor::new(&mut buf[..]);
|
|
||||||
assert_eq!(writer.position(), 0);
|
|
||||||
assert_eq!(writer.write_vectored(&[IoSlice::new(&[0])]).unwrap(), 1);
|
|
||||||
assert_eq!(writer.position(), 1);
|
|
||||||
assert_eq!(
|
|
||||||
writer
|
|
||||||
.write_vectored(&[IoSlice::new(&[1, 2, 3]), IoSlice::new(&[4, 5, 6, 7])],)
|
|
||||||
.unwrap(),
|
|
||||||
7,
|
|
||||||
);
|
|
||||||
assert_eq!(writer.position(), 8);
|
|
||||||
assert_eq!(writer.write_vectored(&[]).unwrap(), 0);
|
|
||||||
assert_eq!(writer.position(), 8);
|
|
||||||
|
|
||||||
assert_eq!(writer.write_vectored(&[IoSlice::new(&[8, 9])]).unwrap(), 1);
|
|
||||||
assert_eq!(writer.write_vectored(&[IoSlice::new(&[10])]).unwrap(), 0);
|
|
||||||
}
|
|
||||||
let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8];
|
|
||||||
assert_eq!(buf, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_buf_writer_seek() {
|
|
||||||
let mut buf = [0 as u8; 8];
|
|
||||||
{
|
|
||||||
let mut writer = Cursor::new(&mut buf[..]);
|
|
||||||
assert_eq!(writer.position(), 0);
|
|
||||||
assert_eq!(writer.write(&[1]).unwrap(), 1);
|
|
||||||
assert_eq!(writer.position(), 1);
|
|
||||||
|
|
||||||
assert_eq!(writer.seek(SeekFrom::Start(2)).unwrap(), 2);
|
|
||||||
assert_eq!(writer.position(), 2);
|
|
||||||
assert_eq!(writer.write(&[2]).unwrap(), 1);
|
|
||||||
assert_eq!(writer.position(), 3);
|
|
||||||
|
|
||||||
assert_eq!(writer.seek(SeekFrom::Current(-2)).unwrap(), 1);
|
|
||||||
assert_eq!(writer.position(), 1);
|
|
||||||
assert_eq!(writer.write(&[3]).unwrap(), 1);
|
|
||||||
assert_eq!(writer.position(), 2);
|
|
||||||
|
|
||||||
assert_eq!(writer.seek(SeekFrom::End(-1)).unwrap(), 7);
|
|
||||||
assert_eq!(writer.position(), 7);
|
|
||||||
assert_eq!(writer.write(&[4]).unwrap(), 1);
|
|
||||||
assert_eq!(writer.position(), 8);
|
|
||||||
}
|
|
||||||
let b: &[_] = &[1, 3, 2, 0, 0, 0, 0, 4];
|
|
||||||
assert_eq!(buf, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_buf_writer_error() {
|
|
||||||
let mut buf = [0 as u8; 2];
|
|
||||||
let mut writer = Cursor::new(&mut buf[..]);
|
|
||||||
assert_eq!(writer.write(&[0]).unwrap(), 1);
|
|
||||||
assert_eq!(writer.write(&[0, 0]).unwrap(), 1);
|
|
||||||
assert_eq!(writer.write(&[0, 0]).unwrap(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_mem_reader() {
|
|
||||||
let mut reader = Cursor::new(vec![0, 1, 2, 3, 4, 5, 6, 7]);
|
|
||||||
let mut buf = [];
|
|
||||||
assert_eq!(reader.read(&mut buf).unwrap(), 0);
|
|
||||||
assert_eq!(reader.position(), 0);
|
|
||||||
let mut buf = [0];
|
|
||||||
assert_eq!(reader.read(&mut buf).unwrap(), 1);
|
|
||||||
assert_eq!(reader.position(), 1);
|
|
||||||
let b: &[_] = &[0];
|
|
||||||
assert_eq!(buf, b);
|
|
||||||
let mut buf = [0; 4];
|
|
||||||
assert_eq!(reader.read(&mut buf).unwrap(), 4);
|
|
||||||
assert_eq!(reader.position(), 5);
|
|
||||||
let b: &[_] = &[1, 2, 3, 4];
|
|
||||||
assert_eq!(buf, b);
|
|
||||||
assert_eq!(reader.read(&mut buf).unwrap(), 3);
|
|
||||||
let b: &[_] = &[5, 6, 7];
|
|
||||||
assert_eq!(&buf[..3], b);
|
|
||||||
assert_eq!(reader.read(&mut buf).unwrap(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_mem_reader_vectored() {
|
|
||||||
let mut reader = Cursor::new(vec![0, 1, 2, 3, 4, 5, 6, 7]);
|
|
||||||
let mut buf = [];
|
|
||||||
assert_eq!(reader.read_vectored(&mut [IoSliceMut::new(&mut buf)]).unwrap(), 0);
|
|
||||||
assert_eq!(reader.position(), 0);
|
|
||||||
let mut buf = [0];
|
|
||||||
assert_eq!(
|
|
||||||
reader
|
|
||||||
.read_vectored(&mut [IoSliceMut::new(&mut []), IoSliceMut::new(&mut buf),])
|
|
||||||
.unwrap(),
|
|
||||||
1,
|
|
||||||
);
|
|
||||||
assert_eq!(reader.position(), 1);
|
|
||||||
let b: &[_] = &[0];
|
|
||||||
assert_eq!(buf, b);
|
|
||||||
let mut buf1 = [0; 4];
|
|
||||||
let mut buf2 = [0; 4];
|
|
||||||
assert_eq!(
|
|
||||||
reader
|
|
||||||
.read_vectored(&mut [IoSliceMut::new(&mut buf1), IoSliceMut::new(&mut buf2),])
|
|
||||||
.unwrap(),
|
|
||||||
7,
|
|
||||||
);
|
|
||||||
let b1: &[_] = &[1, 2, 3, 4];
|
|
||||||
let b2: &[_] = &[5, 6, 7];
|
|
||||||
assert_eq!(buf1, b1);
|
|
||||||
assert_eq!(&buf2[..3], b2);
|
|
||||||
assert_eq!(reader.read(&mut buf).unwrap(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_boxed_slice_reader() {
|
|
||||||
let mut reader = Cursor::new(vec![0, 1, 2, 3, 4, 5, 6, 7].into_boxed_slice());
|
|
||||||
let mut buf = [];
|
|
||||||
assert_eq!(reader.read(&mut buf).unwrap(), 0);
|
|
||||||
assert_eq!(reader.position(), 0);
|
|
||||||
let mut buf = [0];
|
|
||||||
assert_eq!(reader.read(&mut buf).unwrap(), 1);
|
|
||||||
assert_eq!(reader.position(), 1);
|
|
||||||
let b: &[_] = &[0];
|
|
||||||
assert_eq!(buf, b);
|
|
||||||
let mut buf = [0; 4];
|
|
||||||
assert_eq!(reader.read(&mut buf).unwrap(), 4);
|
|
||||||
assert_eq!(reader.position(), 5);
|
|
||||||
let b: &[_] = &[1, 2, 3, 4];
|
|
||||||
assert_eq!(buf, b);
|
|
||||||
assert_eq!(reader.read(&mut buf).unwrap(), 3);
|
|
||||||
let b: &[_] = &[5, 6, 7];
|
|
||||||
assert_eq!(&buf[..3], b);
|
|
||||||
assert_eq!(reader.read(&mut buf).unwrap(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_boxed_slice_reader_vectored() {
|
|
||||||
let mut reader = Cursor::new(vec![0, 1, 2, 3, 4, 5, 6, 7].into_boxed_slice());
|
|
||||||
let mut buf = [];
|
|
||||||
assert_eq!(reader.read_vectored(&mut [IoSliceMut::new(&mut buf)]).unwrap(), 0);
|
|
||||||
assert_eq!(reader.position(), 0);
|
|
||||||
let mut buf = [0];
|
|
||||||
assert_eq!(
|
|
||||||
reader
|
|
||||||
.read_vectored(&mut [IoSliceMut::new(&mut []), IoSliceMut::new(&mut buf),])
|
|
||||||
.unwrap(),
|
|
||||||
1,
|
|
||||||
);
|
|
||||||
assert_eq!(reader.position(), 1);
|
|
||||||
let b: &[_] = &[0];
|
|
||||||
assert_eq!(buf, b);
|
|
||||||
let mut buf1 = [0; 4];
|
|
||||||
let mut buf2 = [0; 4];
|
|
||||||
assert_eq!(
|
|
||||||
reader
|
|
||||||
.read_vectored(&mut [IoSliceMut::new(&mut buf1), IoSliceMut::new(&mut buf2)],)
|
|
||||||
.unwrap(),
|
|
||||||
7,
|
|
||||||
);
|
|
||||||
let b1: &[_] = &[1, 2, 3, 4];
|
|
||||||
let b2: &[_] = &[5, 6, 7];
|
|
||||||
assert_eq!(buf1, b1);
|
|
||||||
assert_eq!(&buf2[..3], b2);
|
|
||||||
assert_eq!(reader.read(&mut buf).unwrap(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn read_to_end() {
|
|
||||||
let mut reader = Cursor::new(vec![0, 1, 2, 3, 4, 5, 6, 7]);
|
|
||||||
let mut v = Vec::new();
|
|
||||||
reader.read_to_end(&mut v).unwrap();
|
|
||||||
assert_eq!(v, [0, 1, 2, 3, 4, 5, 6, 7]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_slice_reader() {
|
|
||||||
let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];
|
|
||||||
let reader = &mut &in_buf[..];
|
|
||||||
let mut buf = [];
|
|
||||||
assert_eq!(reader.read(&mut buf).unwrap(), 0);
|
|
||||||
let mut buf = [0];
|
|
||||||
assert_eq!(reader.read(&mut buf).unwrap(), 1);
|
|
||||||
assert_eq!(reader.len(), 7);
|
|
||||||
let b: &[_] = &[0];
|
|
||||||
assert_eq!(&buf[..], b);
|
|
||||||
let mut buf = [0; 4];
|
|
||||||
assert_eq!(reader.read(&mut buf).unwrap(), 4);
|
|
||||||
assert_eq!(reader.len(), 3);
|
|
||||||
let b: &[_] = &[1, 2, 3, 4];
|
|
||||||
assert_eq!(&buf[..], b);
|
|
||||||
assert_eq!(reader.read(&mut buf).unwrap(), 3);
|
|
||||||
let b: &[_] = &[5, 6, 7];
|
|
||||||
assert_eq!(&buf[..3], b);
|
|
||||||
assert_eq!(reader.read(&mut buf).unwrap(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_slice_reader_vectored() {
|
|
||||||
let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];
|
|
||||||
let reader = &mut &in_buf[..];
|
|
||||||
let mut buf = [];
|
|
||||||
assert_eq!(reader.read_vectored(&mut [IoSliceMut::new(&mut buf)]).unwrap(), 0);
|
|
||||||
let mut buf = [0];
|
|
||||||
assert_eq!(
|
|
||||||
reader
|
|
||||||
.read_vectored(&mut [IoSliceMut::new(&mut []), IoSliceMut::new(&mut buf),])
|
|
||||||
.unwrap(),
|
|
||||||
1,
|
|
||||||
);
|
|
||||||
assert_eq!(reader.len(), 7);
|
|
||||||
let b: &[_] = &[0];
|
|
||||||
assert_eq!(buf, b);
|
|
||||||
let mut buf1 = [0; 4];
|
|
||||||
let mut buf2 = [0; 4];
|
|
||||||
assert_eq!(
|
|
||||||
reader
|
|
||||||
.read_vectored(&mut [IoSliceMut::new(&mut buf1), IoSliceMut::new(&mut buf2)],)
|
|
||||||
.unwrap(),
|
|
||||||
7,
|
|
||||||
);
|
|
||||||
let b1: &[_] = &[1, 2, 3, 4];
|
|
||||||
let b2: &[_] = &[5, 6, 7];
|
|
||||||
assert_eq!(buf1, b1);
|
|
||||||
assert_eq!(&buf2[..3], b2);
|
|
||||||
assert_eq!(reader.read(&mut buf).unwrap(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_read_exact() {
|
|
||||||
let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];
|
|
||||||
let reader = &mut &in_buf[..];
|
|
||||||
let mut buf = [];
|
|
||||||
assert!(reader.read_exact(&mut buf).is_ok());
|
|
||||||
let mut buf = [8];
|
|
||||||
assert!(reader.read_exact(&mut buf).is_ok());
|
|
||||||
assert_eq!(buf[0], 0);
|
|
||||||
assert_eq!(reader.len(), 7);
|
|
||||||
let mut buf = [0, 0, 0, 0, 0, 0, 0];
|
|
||||||
assert!(reader.read_exact(&mut buf).is_ok());
|
|
||||||
assert_eq!(buf, [1, 2, 3, 4, 5, 6, 7]);
|
|
||||||
assert_eq!(reader.len(), 0);
|
|
||||||
let mut buf = [0];
|
|
||||||
assert!(reader.read_exact(&mut buf).is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_buf_reader() {
|
|
||||||
let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];
|
|
||||||
let mut reader = Cursor::new(&in_buf[..]);
|
|
||||||
let mut buf = [];
|
|
||||||
assert_eq!(reader.read(&mut buf).unwrap(), 0);
|
|
||||||
assert_eq!(reader.position(), 0);
|
|
||||||
let mut buf = [0];
|
|
||||||
assert_eq!(reader.read(&mut buf).unwrap(), 1);
|
|
||||||
assert_eq!(reader.position(), 1);
|
|
||||||
let b: &[_] = &[0];
|
|
||||||
assert_eq!(buf, b);
|
|
||||||
let mut buf = [0; 4];
|
|
||||||
assert_eq!(reader.read(&mut buf).unwrap(), 4);
|
|
||||||
assert_eq!(reader.position(), 5);
|
|
||||||
let b: &[_] = &[1, 2, 3, 4];
|
|
||||||
assert_eq!(buf, b);
|
|
||||||
assert_eq!(reader.read(&mut buf).unwrap(), 3);
|
|
||||||
let b: &[_] = &[5, 6, 7];
|
|
||||||
assert_eq!(&buf[..3], b);
|
|
||||||
assert_eq!(reader.read(&mut buf).unwrap(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn seek_past_end() {
|
|
||||||
let buf = [0xff];
|
|
||||||
let mut r = Cursor::new(&buf[..]);
|
|
||||||
assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10);
|
|
||||||
assert_eq!(r.read(&mut [0]).unwrap(), 0);
|
|
||||||
|
|
||||||
let mut r = Cursor::new(vec![10]);
|
|
||||||
assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10);
|
|
||||||
assert_eq!(r.read(&mut [0]).unwrap(), 0);
|
|
||||||
|
|
||||||
let mut buf = [0];
|
|
||||||
let mut r = Cursor::new(&mut buf[..]);
|
|
||||||
assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10);
|
|
||||||
assert_eq!(r.write(&[3]).unwrap(), 0);
|
|
||||||
|
|
||||||
let mut r = Cursor::new(vec![10].into_boxed_slice());
|
|
||||||
assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10);
|
|
||||||
assert_eq!(r.write(&[3]).unwrap(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn seek_past_i64() {
|
|
||||||
let buf = [0xff];
|
|
||||||
let mut r = Cursor::new(&buf[..]);
|
|
||||||
assert_eq!(r.seek(SeekFrom::Start(6)).unwrap(), 6);
|
|
||||||
assert_eq!(r.seek(SeekFrom::Current(0x7ffffffffffffff0)).unwrap(), 0x7ffffffffffffff6);
|
|
||||||
assert_eq!(r.seek(SeekFrom::Current(0x10)).unwrap(), 0x8000000000000006);
|
|
||||||
assert_eq!(r.seek(SeekFrom::Current(0)).unwrap(), 0x8000000000000006);
|
|
||||||
assert!(r.seek(SeekFrom::Current(0x7ffffffffffffffd)).is_err());
|
|
||||||
assert_eq!(r.seek(SeekFrom::Current(-0x8000000000000000)).unwrap(), 6);
|
|
||||||
|
|
||||||
let mut r = Cursor::new(vec![10]);
|
|
||||||
assert_eq!(r.seek(SeekFrom::Start(6)).unwrap(), 6);
|
|
||||||
assert_eq!(r.seek(SeekFrom::Current(0x7ffffffffffffff0)).unwrap(), 0x7ffffffffffffff6);
|
|
||||||
assert_eq!(r.seek(SeekFrom::Current(0x10)).unwrap(), 0x8000000000000006);
|
|
||||||
assert_eq!(r.seek(SeekFrom::Current(0)).unwrap(), 0x8000000000000006);
|
|
||||||
assert!(r.seek(SeekFrom::Current(0x7ffffffffffffffd)).is_err());
|
|
||||||
assert_eq!(r.seek(SeekFrom::Current(-0x8000000000000000)).unwrap(), 6);
|
|
||||||
|
|
||||||
let mut buf = [0];
|
|
||||||
let mut r = Cursor::new(&mut buf[..]);
|
|
||||||
assert_eq!(r.seek(SeekFrom::Start(6)).unwrap(), 6);
|
|
||||||
assert_eq!(r.seek(SeekFrom::Current(0x7ffffffffffffff0)).unwrap(), 0x7ffffffffffffff6);
|
|
||||||
assert_eq!(r.seek(SeekFrom::Current(0x10)).unwrap(), 0x8000000000000006);
|
|
||||||
assert_eq!(r.seek(SeekFrom::Current(0)).unwrap(), 0x8000000000000006);
|
|
||||||
assert!(r.seek(SeekFrom::Current(0x7ffffffffffffffd)).is_err());
|
|
||||||
assert_eq!(r.seek(SeekFrom::Current(-0x8000000000000000)).unwrap(), 6);
|
|
||||||
|
|
||||||
let mut r = Cursor::new(vec![10].into_boxed_slice());
|
|
||||||
assert_eq!(r.seek(SeekFrom::Start(6)).unwrap(), 6);
|
|
||||||
assert_eq!(r.seek(SeekFrom::Current(0x7ffffffffffffff0)).unwrap(), 0x7ffffffffffffff6);
|
|
||||||
assert_eq!(r.seek(SeekFrom::Current(0x10)).unwrap(), 0x8000000000000006);
|
|
||||||
assert_eq!(r.seek(SeekFrom::Current(0)).unwrap(), 0x8000000000000006);
|
|
||||||
assert!(r.seek(SeekFrom::Current(0x7ffffffffffffffd)).is_err());
|
|
||||||
assert_eq!(r.seek(SeekFrom::Current(-0x8000000000000000)).unwrap(), 6);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn seek_before_0() {
|
|
||||||
let buf = [0xff];
|
|
||||||
let mut r = Cursor::new(&buf[..]);
|
|
||||||
assert!(r.seek(SeekFrom::End(-2)).is_err());
|
|
||||||
|
|
||||||
let mut r = Cursor::new(vec![10]);
|
|
||||||
assert!(r.seek(SeekFrom::End(-2)).is_err());
|
|
||||||
|
|
||||||
let mut buf = [0];
|
|
||||||
let mut r = Cursor::new(&mut buf[..]);
|
|
||||||
assert!(r.seek(SeekFrom::End(-2)).is_err());
|
|
||||||
|
|
||||||
let mut r = Cursor::new(vec![10].into_boxed_slice());
|
|
||||||
assert!(r.seek(SeekFrom::End(-2)).is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_seekable_mem_writer() {
|
|
||||||
let mut writer = Cursor::new(Vec::<u8>::new());
|
|
||||||
assert_eq!(writer.position(), 0);
|
|
||||||
assert_eq!(writer.write(&[0]).unwrap(), 1);
|
|
||||||
assert_eq!(writer.position(), 1);
|
|
||||||
assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
|
|
||||||
assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
|
|
||||||
assert_eq!(writer.position(), 8);
|
|
||||||
let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
|
|
||||||
assert_eq!(&writer.get_ref()[..], b);
|
|
||||||
|
|
||||||
assert_eq!(writer.seek(SeekFrom::Start(0)).unwrap(), 0);
|
|
||||||
assert_eq!(writer.position(), 0);
|
|
||||||
assert_eq!(writer.write(&[3, 4]).unwrap(), 2);
|
|
||||||
let b: &[_] = &[3, 4, 2, 3, 4, 5, 6, 7];
|
|
||||||
assert_eq!(&writer.get_ref()[..], b);
|
|
||||||
|
|
||||||
assert_eq!(writer.seek(SeekFrom::Current(1)).unwrap(), 3);
|
|
||||||
assert_eq!(writer.write(&[0, 1]).unwrap(), 2);
|
|
||||||
let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 7];
|
|
||||||
assert_eq!(&writer.get_ref()[..], b);
|
|
||||||
|
|
||||||
assert_eq!(writer.seek(SeekFrom::End(-1)).unwrap(), 7);
|
|
||||||
assert_eq!(writer.write(&[1, 2]).unwrap(), 2);
|
|
||||||
let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2];
|
|
||||||
assert_eq!(&writer.get_ref()[..], b);
|
|
||||||
|
|
||||||
assert_eq!(writer.seek(SeekFrom::End(1)).unwrap(), 10);
|
|
||||||
assert_eq!(writer.write(&[1]).unwrap(), 1);
|
|
||||||
let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1];
|
|
||||||
assert_eq!(&writer.get_ref()[..], b);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn vec_seek_past_end() {
|
|
||||||
let mut r = Cursor::new(Vec::new());
|
|
||||||
assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10);
|
|
||||||
assert_eq!(r.write(&[3]).unwrap(), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn vec_seek_before_0() {
|
|
||||||
let mut r = Cursor::new(Vec::new());
|
|
||||||
assert!(r.seek(SeekFrom::End(-2)).is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[cfg(target_pointer_width = "32")]
|
|
||||||
fn vec_seek_and_write_past_usize_max() {
|
|
||||||
let mut c = Cursor::new(Vec::new());
|
|
||||||
c.set_position(<usize>::max_value() as u64 + 1);
|
|
||||||
assert!(c.write_all(&[1, 2, 3]).is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_partial_eq() {
|
|
||||||
assert_eq!(Cursor::new(Vec::<u8>::new()), Cursor::new(Vec::<u8>::new()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_eq() {
|
|
||||||
struct AssertEq<T: Eq>(pub T);
|
|
||||||
|
|
||||||
let _: AssertEq<Cursor<Vec<u8>>> = AssertEq(Cursor::new(Vec::new()));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,551 +0,0 @@
|
||||||
#[cfg(feature="alloc")] use alloc::boxed::Box;
|
|
||||||
#[cfg(not(feature="alloc"))] use ::FakeBox as Box;
|
|
||||||
use core::convert::Into;
|
|
||||||
use core::fmt;
|
|
||||||
use core::marker::{Send, Sync};
|
|
||||||
use core::option::Option::{self, Some, None};
|
|
||||||
use core::result;
|
|
||||||
#[cfg(feature="collections")] use collections::string::String;
|
|
||||||
#[cfg(not(feature="collections"))] use ::ErrorString as String;
|
|
||||||
use core::convert::From;
|
|
||||||
|
|
||||||
/// A specialized [`Result`](../result/enum.Result.html) type for I/O
|
|
||||||
/// operations.
|
|
||||||
///
|
|
||||||
/// This type is broadly used across [`std::io`] for any operation which may
|
|
||||||
/// produce an error.
|
|
||||||
///
|
|
||||||
/// This typedef is generally used to avoid writing out [`io::Error`] directly and
|
|
||||||
/// is otherwise a direct mapping to [`Result`].
|
|
||||||
///
|
|
||||||
/// While usual Rust style is to import types directly, aliases of [`Result`]
|
|
||||||
/// often are not, to make it easier to distinguish between them. [`Result`] is
|
|
||||||
/// generally assumed to be [`std::result::Result`][`Result`], and so users of this alias
|
|
||||||
/// will generally use `io::Result` instead of shadowing the prelude's import
|
|
||||||
/// of [`std::result::Result`][`Result`].
|
|
||||||
///
|
|
||||||
/// [`std::io`]: ../io/index.html
|
|
||||||
/// [`io::Error`]: ../io/struct.Error.html
|
|
||||||
/// [`Result`]: ../result/enum.Result.html
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// A convenience function that bubbles an `io::Result` to its caller:
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use std::io;
|
|
||||||
///
|
|
||||||
/// fn get_string() -> io::Result<String> {
|
|
||||||
/// let mut buffer = String::new();
|
|
||||||
///
|
|
||||||
/// io::stdin().read_line(&mut buffer)?;
|
|
||||||
///
|
|
||||||
/// Ok(buffer)
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub type Result<T> = result::Result<T, Error>;
|
|
||||||
|
|
||||||
/// The error type for I/O operations of the [`Read`], [`Write`], [`Seek`], and
|
|
||||||
/// associated traits.
|
|
||||||
///
|
|
||||||
/// Errors mostly originate from the underlying OS, but custom instances of
|
|
||||||
/// `Error` can be created with crafted error messages and a particular value of
|
|
||||||
/// [`ErrorKind`].
|
|
||||||
///
|
|
||||||
/// [`Read`]: ../io/trait.Read.html
|
|
||||||
/// [`Write`]: ../io/trait.Write.html
|
|
||||||
/// [`Seek`]: ../io/trait.Seek.html
|
|
||||||
/// [`ErrorKind`]: enum.ErrorKind.html
|
|
||||||
pub struct Error {
|
|
||||||
repr: Repr,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for Error {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
fmt::Debug::fmt(&self.repr, f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Repr {
|
|
||||||
Os(i32),
|
|
||||||
Simple(ErrorKind),
|
|
||||||
#[cfg(feature="alloc")]
|
|
||||||
Custom(Box<Custom>),
|
|
||||||
#[cfg(not(feature="alloc"))]
|
|
||||||
Custom(Custom),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct Custom {
|
|
||||||
kind: ErrorKind,
|
|
||||||
error: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A list specifying general categories of I/O error.
|
|
||||||
///
|
|
||||||
/// This list is intended to grow over time and it is not recommended to
|
|
||||||
/// exhaustively match against it.
|
|
||||||
///
|
|
||||||
/// It is used with the [`io::Error`] type.
|
|
||||||
///
|
|
||||||
/// [`io::Error`]: struct.Error.html
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
|
||||||
#[allow(deprecated)]
|
|
||||||
#[non_exhaustive]
|
|
||||||
pub enum ErrorKind {
|
|
||||||
/// An entity was not found, often a file.
|
|
||||||
NotFound,
|
|
||||||
/// The operation lacked the necessary privileges to complete.
|
|
||||||
PermissionDenied,
|
|
||||||
/// The connection was refused by the remote server.
|
|
||||||
ConnectionRefused,
|
|
||||||
/// The connection was reset by the remote server.
|
|
||||||
ConnectionReset,
|
|
||||||
/// The connection was aborted (terminated) by the remote server.
|
|
||||||
ConnectionAborted,
|
|
||||||
/// The network operation failed because it was not connected yet.
|
|
||||||
NotConnected,
|
|
||||||
/// A socket address could not be bound because the address is already in
|
|
||||||
/// use elsewhere.
|
|
||||||
AddrInUse,
|
|
||||||
/// A nonexistent interface was requested or the requested address was not
|
|
||||||
/// local.
|
|
||||||
AddrNotAvailable,
|
|
||||||
/// The operation failed because a pipe was closed.
|
|
||||||
BrokenPipe,
|
|
||||||
/// An entity already exists, often a file.
|
|
||||||
AlreadyExists,
|
|
||||||
/// The operation needs to block to complete, but the blocking operation was
|
|
||||||
/// requested to not occur.
|
|
||||||
WouldBlock,
|
|
||||||
/// A parameter was incorrect.
|
|
||||||
InvalidInput,
|
|
||||||
/// Data not valid for the operation were encountered.
|
|
||||||
///
|
|
||||||
/// Unlike [`InvalidInput`], this typically means that the operation
|
|
||||||
/// parameters were valid, however the error was caused by malformed
|
|
||||||
/// input data.
|
|
||||||
///
|
|
||||||
/// For example, a function that reads a file into a string will error with
|
|
||||||
/// `InvalidData` if the file's contents are not valid UTF-8.
|
|
||||||
///
|
|
||||||
/// [`InvalidInput`]: #variant.InvalidInput
|
|
||||||
InvalidData,
|
|
||||||
/// The I/O operation's timeout expired, causing it to be canceled.
|
|
||||||
TimedOut,
|
|
||||||
/// An error returned when an operation could not be completed because a
|
|
||||||
/// call to [`write`] returned [`Ok(0)`].
|
|
||||||
///
|
|
||||||
/// This typically means that an operation could only succeed if it wrote a
|
|
||||||
/// particular number of bytes but only a smaller number of bytes could be
|
|
||||||
/// written.
|
|
||||||
///
|
|
||||||
/// [`write`]: ../../std/io/trait.Write.html#tymethod.write
|
|
||||||
/// [`Ok(0)`]: ../../std/io/type.Result.html
|
|
||||||
WriteZero,
|
|
||||||
/// This operation was interrupted.
|
|
||||||
///
|
|
||||||
/// Interrupted operations can typically be retried.
|
|
||||||
Interrupted,
|
|
||||||
/// Any I/O error not part of this list.
|
|
||||||
Other,
|
|
||||||
|
|
||||||
/// An error returned when an operation could not be completed because an
|
|
||||||
/// "end of file" was reached prematurely.
|
|
||||||
///
|
|
||||||
/// This typically means that an operation could only succeed if it read a
|
|
||||||
/// particular number of bytes but only a smaller number of bytes could be
|
|
||||||
/// read.
|
|
||||||
UnexpectedEof,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ErrorKind {
|
|
||||||
pub(crate) fn as_str(&self) -> &'static str {
|
|
||||||
match *self {
|
|
||||||
ErrorKind::NotFound => "entity not found",
|
|
||||||
ErrorKind::PermissionDenied => "permission denied",
|
|
||||||
ErrorKind::ConnectionRefused => "connection refused",
|
|
||||||
ErrorKind::ConnectionReset => "connection reset",
|
|
||||||
ErrorKind::ConnectionAborted => "connection aborted",
|
|
||||||
ErrorKind::NotConnected => "not connected",
|
|
||||||
ErrorKind::AddrInUse => "address in use",
|
|
||||||
ErrorKind::AddrNotAvailable => "address not available",
|
|
||||||
ErrorKind::BrokenPipe => "broken pipe",
|
|
||||||
ErrorKind::AlreadyExists => "entity already exists",
|
|
||||||
ErrorKind::WouldBlock => "operation would block",
|
|
||||||
ErrorKind::InvalidInput => "invalid input parameter",
|
|
||||||
ErrorKind::InvalidData => "invalid data",
|
|
||||||
ErrorKind::TimedOut => "timed out",
|
|
||||||
ErrorKind::WriteZero => "write zero",
|
|
||||||
ErrorKind::Interrupted => "operation interrupted",
|
|
||||||
ErrorKind::Other => "other os error",
|
|
||||||
ErrorKind::UnexpectedEof => "unexpected end of file",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Intended for use for errors not exposed to the user, where allocating onto
|
|
||||||
/// the heap (for normal construction via Error::new) is too costly.
|
|
||||||
impl From<ErrorKind> for Error {
|
|
||||||
/// Converts an [`ErrorKind`] into an [`Error`].
|
|
||||||
///
|
|
||||||
/// This conversion allocates a new error with a simple representation of error kind.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use std::io::{Error, ErrorKind};
|
|
||||||
///
|
|
||||||
/// let not_found = ErrorKind::NotFound;
|
|
||||||
/// let error = Error::from(not_found);
|
|
||||||
/// assert_eq!("entity not found", format!("{}", error));
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// [`ErrorKind`]: ../../std/io/enum.ErrorKind.html
|
|
||||||
/// [`Error`]: ../../std/io/struct.Error.html
|
|
||||||
#[inline]
|
|
||||||
fn from(kind: ErrorKind) -> Error {
|
|
||||||
Error { repr: Repr::Simple(kind) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Error {
|
|
||||||
/// Creates a new I/O error from a known kind of error as well as an
|
|
||||||
/// arbitrary error payload.
|
|
||||||
///
|
|
||||||
/// This function is used to generically create I/O errors which do not
|
|
||||||
/// originate from the OS itself. The `error` argument is an arbitrary
|
|
||||||
/// payload which will be contained in this `Error`.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use std::io::{Error, ErrorKind};
|
|
||||||
///
|
|
||||||
/// // errors can be created from strings
|
|
||||||
/// let custom_error = Error::new(ErrorKind::Other, "oh no!");
|
|
||||||
///
|
|
||||||
/// // errors can also be created from other errors
|
|
||||||
/// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error);
|
|
||||||
/// ```
|
|
||||||
pub fn new<E>(kind: ErrorKind, error: E) -> Error
|
|
||||||
where
|
|
||||||
E: Into<String>,
|
|
||||||
{
|
|
||||||
Self::_new(kind, error.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn _new(kind: ErrorKind, error: String) -> Error {
|
|
||||||
Error { repr: Repr::Custom(Box::new(Custom { kind, error })) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a new instance of an `Error` from a particular OS error code.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// On Linux:
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # if cfg!(target_os = "linux") {
|
|
||||||
/// use std::io;
|
|
||||||
///
|
|
||||||
/// let error = io::Error::from_raw_os_error(22);
|
|
||||||
/// assert_eq!(error.kind(), io::ErrorKind::InvalidInput);
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// On Windows:
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # if cfg!(windows) {
|
|
||||||
/// use std::io;
|
|
||||||
///
|
|
||||||
/// let error = io::Error::from_raw_os_error(10022);
|
|
||||||
/// assert_eq!(error.kind(), io::ErrorKind::InvalidInput);
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
pub fn from_raw_os_error(code: i32) -> Error {
|
|
||||||
Error { repr: Repr::Os(code) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the OS error that this error represents (if any).
|
|
||||||
///
|
|
||||||
/// If this `Error` was constructed via `last_os_error` or
|
|
||||||
/// `from_raw_os_error`, then this function will return `Some`, otherwise
|
|
||||||
/// it will return `None`.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use std::io::{Error, ErrorKind};
|
|
||||||
///
|
|
||||||
/// fn print_os_error(err: &Error) {
|
|
||||||
/// if let Some(raw_os_err) = err.raw_os_error() {
|
|
||||||
/// println!("raw OS error: {:?}", raw_os_err);
|
|
||||||
/// } else {
|
|
||||||
/// println!("Not an OS error");
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn main() {
|
|
||||||
/// // Will print "raw OS error: ...".
|
|
||||||
/// print_os_error(&Error::last_os_error());
|
|
||||||
/// // Will print "Not an OS error".
|
|
||||||
/// print_os_error(&Error::new(ErrorKind::Other, "oh no!"));
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub fn raw_os_error(&self) -> Option<i32> {
|
|
||||||
match self.repr {
|
|
||||||
Repr::Os(i) => Some(i),
|
|
||||||
Repr::Custom(..) => None,
|
|
||||||
Repr::Simple(..) => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a reference to the inner error wrapped by this error (if any).
|
|
||||||
///
|
|
||||||
/// If this `Error` was constructed via `new` then this function will
|
|
||||||
/// return `Some`, otherwise it will return `None`.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use std::io::{Error, ErrorKind};
|
|
||||||
///
|
|
||||||
/// fn print_error(err: &Error) {
|
|
||||||
/// if let Some(inner_err) = err.get_ref() {
|
|
||||||
/// println!("Inner error: {:?}", inner_err);
|
|
||||||
/// } else {
|
|
||||||
/// println!("No inner error");
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn main() {
|
|
||||||
/// // Will print "No inner error".
|
|
||||||
/// print_error(&Error::last_os_error());
|
|
||||||
/// // Will print "Inner error: ...".
|
|
||||||
/// print_error(&Error::new(ErrorKind::Other, "oh no!"));
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub fn get_ref(&self) -> Option<&String> {
|
|
||||||
match self.repr {
|
|
||||||
Repr::Os(..) => None,
|
|
||||||
Repr::Simple(..) => None,
|
|
||||||
Repr::Custom(ref c) => Some(&c.error),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a mutable reference to the inner error wrapped by this error
|
|
||||||
/// (if any).
|
|
||||||
///
|
|
||||||
/// If this `Error` was constructed via `new` then this function will
|
|
||||||
/// return `Some`, otherwise it will return `None`.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use std::io::{Error, ErrorKind};
|
|
||||||
/// use std::{error, fmt};
|
|
||||||
/// use std::fmt::Display;
|
|
||||||
///
|
|
||||||
/// #[derive(Debug)]
|
|
||||||
/// struct MyError {
|
|
||||||
/// v: String,
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// impl MyError {
|
|
||||||
/// fn new() -> MyError {
|
|
||||||
/// MyError {
|
|
||||||
/// v: "oh no!".to_string()
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn change_message(&mut self, new_message: &str) {
|
|
||||||
/// self.v = new_message.to_string();
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// impl error::Error for MyError {}
|
|
||||||
///
|
|
||||||
/// impl Display for MyError {
|
|
||||||
/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
/// write!(f, "MyError: {}", &self.v)
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn change_error(mut err: Error) -> Error {
|
|
||||||
/// if let Some(inner_err) = err.get_mut() {
|
|
||||||
/// inner_err.downcast_mut::<MyError>().unwrap().change_message("I've been changed!");
|
|
||||||
/// }
|
|
||||||
/// err
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn print_error(err: &Error) {
|
|
||||||
/// if let Some(inner_err) = err.get_ref() {
|
|
||||||
/// println!("Inner error: {}", inner_err);
|
|
||||||
/// } else {
|
|
||||||
/// println!("No inner error");
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn main() {
|
|
||||||
/// // Will print "No inner error".
|
|
||||||
/// print_error(&change_error(Error::last_os_error()));
|
|
||||||
/// // Will print "Inner error: ...".
|
|
||||||
/// print_error(&change_error(Error::new(ErrorKind::Other, MyError::new())));
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub fn get_mut(&mut self) -> Option<&mut String> {
|
|
||||||
match self.repr {
|
|
||||||
Repr::Os(..) => None,
|
|
||||||
Repr::Simple(..) => None,
|
|
||||||
Repr::Custom(ref mut c) => Some(&mut c.error),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Consumes the `Error`, returning its inner error (if any).
|
|
||||||
///
|
|
||||||
/// If this `Error` was constructed via `new` then this function will
|
|
||||||
/// return `Some`, otherwise it will return `None`.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use std::io::{Error, ErrorKind};
|
|
||||||
///
|
|
||||||
/// fn print_error(err: Error) {
|
|
||||||
/// if let Some(inner_err) = err.into_inner() {
|
|
||||||
/// println!("Inner error: {}", inner_err);
|
|
||||||
/// } else {
|
|
||||||
/// println!("No inner error");
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn main() {
|
|
||||||
/// // Will print "No inner error".
|
|
||||||
/// print_error(Error::last_os_error());
|
|
||||||
/// // Will print "Inner error: ...".
|
|
||||||
/// print_error(Error::new(ErrorKind::Other, "oh no!"));
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub fn into_inner(self) -> Option<String> {
|
|
||||||
match self.repr {
|
|
||||||
Repr::Os(..) => None,
|
|
||||||
Repr::Simple(..) => None,
|
|
||||||
Repr::Custom(c) => Some(c.error),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the corresponding `ErrorKind` for this error.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use std::io::{Error, ErrorKind};
|
|
||||||
///
|
|
||||||
/// fn print_error(err: Error) {
|
|
||||||
/// println!("{:?}", err.kind());
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn main() {
|
|
||||||
/// // Will print "No inner error".
|
|
||||||
/// print_error(Error::last_os_error());
|
|
||||||
/// // Will print "Inner error: ...".
|
|
||||||
/// print_error(Error::new(ErrorKind::AddrInUse, "oh no!"));
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub fn kind(&self) -> ErrorKind {
|
|
||||||
match self.repr {
|
|
||||||
Repr::Os(_code) => ErrorKind::Other,
|
|
||||||
Repr::Custom(ref c) => c.kind,
|
|
||||||
Repr::Simple(kind) => kind,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for Repr {
|
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
match *self {
|
|
||||||
Repr::Os(code) => fmt
|
|
||||||
.debug_struct("Os")
|
|
||||||
.field("code", &code)
|
|
||||||
.finish(),
|
|
||||||
Repr::Custom(ref c) => fmt::Debug::fmt(&c, fmt),
|
|
||||||
Repr::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
match self.repr {
|
|
||||||
Repr::Os(code) => {
|
|
||||||
write!(fmt, "os error {}", code)
|
|
||||||
}
|
|
||||||
Repr::Custom(ref c) => c.error.fmt(fmt),
|
|
||||||
Repr::Simple(kind) => write!(fmt, "{}", kind.as_str()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn _assert_error_is_sync_send() {
|
|
||||||
fn _is_sync_send<T: Sync + Send>() {}
|
|
||||||
_is_sync_send::<Error>();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use super::{Custom, Error, ErrorKind, Repr};
|
|
||||||
use crate::error;
|
|
||||||
use crate::fmt;
|
|
||||||
use crate::sys::decode_error_kind;
|
|
||||||
use crate::sys::os::error_string;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_debug_error() {
|
|
||||||
let code = 6;
|
|
||||||
let msg = error_string(code);
|
|
||||||
let kind = decode_error_kind(code);
|
|
||||||
let err = Error {
|
|
||||||
repr: Repr::Custom(box Custom {
|
|
||||||
kind: ErrorKind::InvalidInput,
|
|
||||||
error: box Error { repr: super::Repr::Os(code) },
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
let expected = format!(
|
|
||||||
"Custom {{ \
|
|
||||||
kind: InvalidInput, \
|
|
||||||
error: Os {{ \
|
|
||||||
code: {:?}, \
|
|
||||||
kind: {:?}, \
|
|
||||||
message: {:?} \
|
|
||||||
}} \
|
|
||||||
}}",
|
|
||||||
code, kind, msg
|
|
||||||
);
|
|
||||||
assert_eq!(format!("{:?}", err), expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_downcasting() {
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct TestError;
|
|
||||||
|
|
||||||
impl fmt::Display for TestError {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
f.write_str("asdf")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl error::Error for TestError {}
|
|
||||||
|
|
||||||
// we have to call all of these UFCS style right now since method
|
|
||||||
// resolution won't implicitly drop the Send+Sync bounds
|
|
||||||
let mut err = Error::new(ErrorKind::Other, TestError);
|
|
||||||
assert!(err.get_ref().unwrap().is::<TestError>());
|
|
||||||
assert_eq!("asdf", err.get_ref().unwrap().to_string());
|
|
||||||
assert!(err.get_mut().unwrap().is::<TestError>());
|
|
||||||
let extracted = err.into_inner().unwrap();
|
|
||||||
extracted.downcast::<TestError>().unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,378 +0,0 @@
|
||||||
use core::cmp;
|
|
||||||
use core::fmt;
|
|
||||||
use crate::io::{
|
|
||||||
self, Error, ErrorKind, Initializer, Read, Seek, SeekFrom, Write,
|
|
||||||
};
|
|
||||||
#[cfg(feature = "collections")] use crate::io::BufRead;
|
|
||||||
use core::mem;
|
|
||||||
|
|
||||||
#[cfg(feature="collections")]
|
|
||||||
use collections::{
|
|
||||||
vec::Vec,
|
|
||||||
string::String,
|
|
||||||
};
|
|
||||||
#[cfg(feature = "alloc")]
|
|
||||||
use alloc::boxed::Box;
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
// Forwarding implementations
|
|
||||||
|
|
||||||
impl<R: Read + ?Sized> Read for &mut R {
|
|
||||||
#[inline]
|
|
||||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
|
||||||
(**self).read(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn initializer(&self) -> Initializer {
|
|
||||||
(**self).initializer()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature="collections")]
|
|
||||||
#[inline]
|
|
||||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
|
||||||
(**self).read_to_end(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature="collections")]
|
|
||||||
#[inline]
|
|
||||||
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
|
|
||||||
(**self).read_to_string(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
|
|
||||||
(**self).read_exact(buf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<W: Write + ?Sized> Write for &mut W {
|
|
||||||
#[inline]
|
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
|
||||||
(**self).write(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn flush(&mut self) -> io::Result<()> {
|
|
||||||
(**self).flush()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
|
|
||||||
(**self).write_all(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
|
|
||||||
(**self).write_fmt(fmt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<S: Seek + ?Sized> Seek for &mut S {
|
|
||||||
#[inline]
|
|
||||||
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
|
|
||||||
(**self).seek(pos)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(feature = "collections")]
|
|
||||||
impl<B: BufRead + ?Sized> BufRead for &mut B {
|
|
||||||
#[inline]
|
|
||||||
fn fill_buf(&mut self) -> io::Result<&[u8]> {
|
|
||||||
(**self).fill_buf()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn consume(&mut self, amt: usize) {
|
|
||||||
(**self).consume(amt)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature="collections")]
|
|
||||||
#[inline]
|
|
||||||
fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> {
|
|
||||||
(**self).read_until(byte, buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature="collections")]
|
|
||||||
#[inline]
|
|
||||||
fn read_line(&mut self, buf: &mut String) -> io::Result<usize> {
|
|
||||||
(**self).read_line(buf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature="alloc")]
|
|
||||||
#[cfg(feature="collections")]
|
|
||||||
impl<R: Read + ?Sized> Read for Box<R> {
|
|
||||||
#[inline]
|
|
||||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
|
||||||
(**self).read(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature="collections")]
|
|
||||||
#[inline]
|
|
||||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
|
||||||
(**self).read_to_end(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature="collections")]
|
|
||||||
#[inline]
|
|
||||||
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
|
|
||||||
(**self).read_to_string(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
|
|
||||||
(**self).read_exact(buf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(feature="alloc")]
|
|
||||||
#[cfg(feature="collections")]
|
|
||||||
impl<W: Write + ?Sized> Write for Box<W> {
|
|
||||||
#[inline]
|
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
|
||||||
(**self).write(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn flush(&mut self) -> io::Result<()> {
|
|
||||||
(**self).flush()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
|
|
||||||
(**self).write_all(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
|
|
||||||
(**self).write_fmt(fmt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(feature="collections")]
|
|
||||||
impl<S: Seek + ?Sized> Seek for Box<S> {
|
|
||||||
#[inline]
|
|
||||||
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
|
|
||||||
(**self).seek(pos)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(feature="collections")]
|
|
||||||
impl<B: BufRead + ?Sized> BufRead for Box<B> {
|
|
||||||
#[inline]
|
|
||||||
fn fill_buf(&mut self) -> io::Result<&[u8]> {
|
|
||||||
(**self).fill_buf()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn consume(&mut self, amt: usize) {
|
|
||||||
(**self).consume(amt)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> {
|
|
||||||
(**self).read_until(byte, buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn read_line(&mut self, buf: &mut String) -> io::Result<usize> {
|
|
||||||
(**self).read_line(buf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used by panicking::default_hook
|
|
||||||
#[cfg(test)]
|
|
||||||
/// This impl is only used by printing logic, so any error returned is always
|
|
||||||
/// of kind `Other`, and should be ignored.
|
|
||||||
#[cfg(feature="collections")]
|
|
||||||
impl Write for Box<dyn (::realstd::io::Write) + Send> {
|
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
|
||||||
(**self).write(buf).map_err(|_| ErrorKind::Other.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn flush(&mut self) -> io::Result<()> {
|
|
||||||
(**self).flush().map_err(|_| ErrorKind::Other.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
// In-memory buffer implementations
|
|
||||||
|
|
||||||
/// Read is implemented for `&[u8]` by copying from the slice.
|
|
||||||
///
|
|
||||||
/// Note that reading updates the slice to point to the yet unread part.
|
|
||||||
/// The slice will be empty when EOF is reached.
|
|
||||||
impl Read for &[u8] {
|
|
||||||
#[inline]
|
|
||||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
|
||||||
let amt = cmp::min(buf.len(), self.len());
|
|
||||||
let (a, b) = self.split_at(amt);
|
|
||||||
|
|
||||||
// First check if the amount of bytes we want to read is small:
|
|
||||||
// `copy_from_slice` will generally expand to a call to `memcpy`, and
|
|
||||||
// for a single byte the overhead is significant.
|
|
||||||
if amt == 1 {
|
|
||||||
buf[0] = a[0];
|
|
||||||
} else {
|
|
||||||
buf[..amt].copy_from_slice(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
*self = b;
|
|
||||||
Ok(amt)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn initializer(&self) -> Initializer {
|
|
||||||
Initializer::nop()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
|
|
||||||
if buf.len() > self.len() {
|
|
||||||
return Err(Error::new(ErrorKind::UnexpectedEof, "failed to fill whole buffer"));
|
|
||||||
}
|
|
||||||
let (a, b) = self.split_at(buf.len());
|
|
||||||
|
|
||||||
// First check if the amount of bytes we want to read is small:
|
|
||||||
// `copy_from_slice` will generally expand to a call to `memcpy`, and
|
|
||||||
// for a single byte the overhead is significant.
|
|
||||||
if buf.len() == 1 {
|
|
||||||
buf[0] = a[0];
|
|
||||||
} else {
|
|
||||||
buf.copy_from_slice(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
*self = b;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature="collections")]
|
|
||||||
#[inline]
|
|
||||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
|
||||||
buf.extend_from_slice(*self);
|
|
||||||
let len = self.len();
|
|
||||||
*self = &self[len..];
|
|
||||||
Ok(len)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature="collections")]
|
|
||||||
impl BufRead for &[u8] {
|
|
||||||
#[inline]
|
|
||||||
fn fill_buf(&mut self) -> io::Result<&[u8]> {
|
|
||||||
Ok(*self)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn consume(&mut self, amt: usize) {
|
|
||||||
*self = &self[amt..];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Write is implemented for `&mut [u8]` by copying into the slice, overwriting
|
|
||||||
/// its data.
|
|
||||||
///
|
|
||||||
/// Note that writing updates the slice to point to the yet unwritten part.
|
|
||||||
/// The slice will be empty when it has been completely overwritten.
|
|
||||||
impl Write for &mut [u8] {
|
|
||||||
#[inline]
|
|
||||||
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
|
|
||||||
let amt = cmp::min(data.len(), self.len());
|
|
||||||
let (a, b) = mem::replace(self, &mut []).split_at_mut(amt);
|
|
||||||
a.copy_from_slice(&data[..amt]);
|
|
||||||
*self = b;
|
|
||||||
Ok(amt)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn write_all(&mut self, data: &[u8]) -> io::Result<()> {
|
|
||||||
if self.write(data)? == data.len() {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn flush(&mut self) -> io::Result<()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Write is implemented for `Vec<u8>` by appending to the vector.
|
|
||||||
/// The vector will grow as needed.
|
|
||||||
#[cfg(feature="collections")]
|
|
||||||
impl Write for Vec<u8> {
|
|
||||||
#[inline]
|
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
|
||||||
self.extend_from_slice(buf);
|
|
||||||
Ok(buf.len())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
|
|
||||||
self.extend_from_slice(buf);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn flush(&mut self) -> io::Result<()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use crate::io::prelude::*;
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
fn bench_read_slice(b: &mut test::Bencher) {
|
|
||||||
let buf = [5; 1024];
|
|
||||||
let mut dst = [0; 128];
|
|
||||||
|
|
||||||
b.iter(|| {
|
|
||||||
let mut rd = &buf[..];
|
|
||||||
for _ in 0..8 {
|
|
||||||
let _ = rd.read(&mut dst);
|
|
||||||
test::black_box(&dst);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
fn bench_write_slice(b: &mut test::Bencher) {
|
|
||||||
let mut buf = [0; 1024];
|
|
||||||
let src = [5; 128];
|
|
||||||
|
|
||||||
b.iter(|| {
|
|
||||||
let mut wr = &mut buf[..];
|
|
||||||
for _ in 0..8 {
|
|
||||||
let _ = wr.write_all(&src);
|
|
||||||
test::black_box(&wr);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
fn bench_read_vec(b: &mut test::Bencher) {
|
|
||||||
let buf = vec![5; 1024];
|
|
||||||
let mut dst = [0; 128];
|
|
||||||
|
|
||||||
b.iter(|| {
|
|
||||||
let mut rd = &buf[..];
|
|
||||||
for _ in 0..8 {
|
|
||||||
let _ = rd.read(&mut dst);
|
|
||||||
test::black_box(&dst);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
fn bench_write_vec(b: &mut test::Bencher) {
|
|
||||||
let mut buf = Vec::with_capacity(1024);
|
|
||||||
let src = [5; 128];
|
|
||||||
|
|
||||||
b.iter(|| {
|
|
||||||
let mut wr = &mut buf[..];
|
|
||||||
for _ in 0..8 {
|
|
||||||
let _ = wr.write_all(&src);
|
|
||||||
test::black_box(&wr);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,13 +0,0 @@
|
||||||
//! The I/O Prelude
|
|
||||||
//!
|
|
||||||
//! The purpose of this module is to alleviate imports of many common I/O traits
|
|
||||||
//! by adding a glob import to the top of I/O heavy modules:
|
|
||||||
//!
|
|
||||||
//! ```
|
|
||||||
//! # #![allow(unused_imports)]
|
|
||||||
//! use std::io::prelude::*;
|
|
||||||
//! ```
|
|
||||||
|
|
||||||
|
|
||||||
pub use super::{Read, Seek, Write};
|
|
||||||
#[cfg(feature = "collections")] pub use super::BufRead;
|
|
|
@ -1,269 +0,0 @@
|
||||||
#![allow(missing_copy_implementations)]
|
|
||||||
|
|
||||||
use core::fmt;
|
|
||||||
use core::mem;
|
|
||||||
use crate::io::{self, ErrorKind, Initializer, Read, Write};
|
|
||||||
#[cfg(feature = "collections")] use crate::io::BufRead;
|
|
||||||
|
|
||||||
/// Copies the entire contents of a reader into a writer.
|
|
||||||
///
|
|
||||||
/// This function will continuously read data from `reader` and then
|
|
||||||
/// write it into `writer` in a streaming fashion until `reader`
|
|
||||||
/// returns EOF.
|
|
||||||
///
|
|
||||||
/// On success, the total number of bytes that were copied from
|
|
||||||
/// `reader` to `writer` is returned.
|
|
||||||
///
|
|
||||||
/// If you’re wanting to copy the contents of one file to another and you’re
|
|
||||||
/// working with filesystem paths, see the [`fs::copy`] function.
|
|
||||||
///
|
|
||||||
/// [`fs::copy`]: ../fs/fn.copy.html
|
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
///
|
|
||||||
/// This function will return an error immediately if any call to `read` or
|
|
||||||
/// `write` returns an error. All instances of `ErrorKind::Interrupted` are
|
|
||||||
/// handled by this function and the underlying operation is retried.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use std::io;
|
|
||||||
///
|
|
||||||
/// fn main() -> io::Result<()> {
|
|
||||||
/// let mut reader: &[u8] = b"hello";
|
|
||||||
/// let mut writer: Vec<u8> = vec![];
|
|
||||||
///
|
|
||||||
/// io::copy(&mut reader, &mut writer)?;
|
|
||||||
///
|
|
||||||
/// assert_eq!(&b"hello"[..], &writer[..]);
|
|
||||||
/// Ok(())
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<u64>
|
|
||||||
where
|
|
||||||
R: Read,
|
|
||||||
W: Write,
|
|
||||||
{
|
|
||||||
let mut buf = unsafe {
|
|
||||||
#[allow(deprecated)]
|
|
||||||
let mut buf: [u8; super::DEFAULT_BUF_SIZE] = mem::uninitialized();
|
|
||||||
reader.initializer().initialize(&mut buf);
|
|
||||||
buf
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut written = 0;
|
|
||||||
loop {
|
|
||||||
let len = match reader.read(&mut buf) {
|
|
||||||
Ok(0) => return Ok(written),
|
|
||||||
Ok(len) => len,
|
|
||||||
Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
|
|
||||||
Err(e) => return Err(e),
|
|
||||||
};
|
|
||||||
writer.write_all(&buf[..len])?;
|
|
||||||
written += len as u64;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A reader which is always at EOF.
|
|
||||||
///
|
|
||||||
/// This struct is generally created by calling [`empty`]. Please see
|
|
||||||
/// the documentation of [`empty()`][`empty`] for more details.
|
|
||||||
///
|
|
||||||
/// [`empty`]: fn.empty.html
|
|
||||||
pub struct Empty {
|
|
||||||
_priv: (),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Constructs a new handle to an empty reader.
|
|
||||||
///
|
|
||||||
/// All reads from the returned reader will return [`Ok`]`(0)`.
|
|
||||||
///
|
|
||||||
/// [`Ok`]: ../result/enum.Result.html#variant.Ok
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// A slightly sad example of not reading anything into a buffer:
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use std::io::{self, Read};
|
|
||||||
///
|
|
||||||
/// let mut buffer = String::new();
|
|
||||||
/// io::empty().read_to_string(&mut buffer).unwrap();
|
|
||||||
/// assert!(buffer.is_empty());
|
|
||||||
/// ```
|
|
||||||
pub fn empty() -> Empty {
|
|
||||||
Empty { _priv: () }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Read for Empty {
|
|
||||||
#[inline]
|
|
||||||
fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
|
|
||||||
Ok(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn initializer(&self) -> Initializer {
|
|
||||||
Initializer::nop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature="collections")]
|
|
||||||
impl BufRead for Empty {
|
|
||||||
#[inline]
|
|
||||||
fn fill_buf(&mut self) -> io::Result<&[u8]> {
|
|
||||||
Ok(&[])
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn consume(&mut self, _n: usize) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for Empty {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
f.pad("Empty { .. }")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A reader which yields one byte over and over and over and over and over and...
|
|
||||||
///
|
|
||||||
/// This struct is generally created by calling [`repeat`][repeat]. Please
|
|
||||||
/// see the documentation of `repeat()` for more details.
|
|
||||||
///
|
|
||||||
/// [repeat]: fn.repeat.html
|
|
||||||
pub struct Repeat {
|
|
||||||
byte: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates an instance of a reader that infinitely repeats one byte.
|
|
||||||
///
|
|
||||||
/// All reads from this reader will succeed by filling the specified buffer with
|
|
||||||
/// the given byte.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use std::io::{self, Read};
|
|
||||||
///
|
|
||||||
/// let mut buffer = [0; 3];
|
|
||||||
/// io::repeat(0b101).read_exact(&mut buffer).unwrap();
|
|
||||||
/// assert_eq!(buffer, [0b101, 0b101, 0b101]);
|
|
||||||
/// ```
|
|
||||||
pub fn repeat(byte: u8) -> Repeat {
|
|
||||||
Repeat { byte }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Read for Repeat {
|
|
||||||
#[inline]
|
|
||||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
|
||||||
for slot in &mut *buf {
|
|
||||||
*slot = self.byte;
|
|
||||||
}
|
|
||||||
Ok(buf.len())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn initializer(&self) -> Initializer {
|
|
||||||
Initializer::nop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for Repeat {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
f.pad("Repeat { .. }")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A writer which will move data into the void.
|
|
||||||
///
|
|
||||||
/// This struct is generally created by calling [`sink`][sink]. Please
|
|
||||||
/// see the documentation of `sink()` for more details.
|
|
||||||
///
|
|
||||||
/// [sink]: fn.sink.html
|
|
||||||
pub struct Sink {
|
|
||||||
_priv: (),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates an instance of a writer which will successfully consume all data.
|
|
||||||
///
|
|
||||||
/// All calls to `write` on the returned instance will return `Ok(buf.len())`
|
|
||||||
/// and the contents of the buffer will not be inspected.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// use std::io::{self, Write};
|
|
||||||
///
|
|
||||||
/// let buffer = vec![1, 2, 3, 5, 8];
|
|
||||||
/// let num_bytes = io::sink().write(&buffer).unwrap();
|
|
||||||
/// assert_eq!(num_bytes, 5);
|
|
||||||
/// ```
|
|
||||||
pub fn sink() -> Sink {
|
|
||||||
Sink { _priv: () }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Write for Sink {
|
|
||||||
#[inline]
|
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
|
||||||
Ok(buf.len())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn flush(&mut self) -> io::Result<()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for Sink {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
f.pad("Sink { .. }")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use crate::io::prelude::*;
|
|
||||||
use crate::io::{copy, empty, repeat, sink};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn copy_copies() {
|
|
||||||
let mut r = repeat(0).take(4);
|
|
||||||
let mut w = sink();
|
|
||||||
assert_eq!(copy(&mut r, &mut w).unwrap(), 4);
|
|
||||||
|
|
||||||
let mut r = repeat(0).take(1 << 17);
|
|
||||||
assert_eq!(copy(&mut r as &mut dyn Read, &mut w as &mut dyn Write).unwrap(), 1 << 17);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn sink_sinks() {
|
|
||||||
let mut s = sink();
|
|
||||||
assert_eq!(s.write(&[]).unwrap(), 0);
|
|
||||||
assert_eq!(s.write(&[0]).unwrap(), 1);
|
|
||||||
assert_eq!(s.write(&[0; 1024]).unwrap(), 1024);
|
|
||||||
assert_eq!(s.by_ref().write(&[0; 1024]).unwrap(), 1024);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn empty_reads() {
|
|
||||||
let mut e = empty();
|
|
||||||
assert_eq!(e.read(&mut []).unwrap(), 0);
|
|
||||||
assert_eq!(e.read(&mut [0]).unwrap(), 0);
|
|
||||||
assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0);
|
|
||||||
assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn repeat_repeats() {
|
|
||||||
let mut r = repeat(4);
|
|
||||||
let mut b = [0; 1024];
|
|
||||||
assert_eq!(r.read(&mut b).unwrap(), 1024);
|
|
||||||
assert!(b.iter().all(|b| *b == 4));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn take_some_bytes() {
|
|
||||||
assert_eq!(repeat(4).take(100).bytes().count(), 100);
|
|
||||||
assert_eq!(repeat(4).take(100).bytes().next().unwrap().unwrap(), 4);
|
|
||||||
assert_eq!(repeat(1).take(10).chain(repeat(2).take(10)).bytes().count(), 20);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
//! <p id="core_io-show-docblock"></p>
|
|
||||||
//! This is just a listing of the functionality available in this crate. See
|
|
||||||
//! the [std documentation](https://doc.rust-lang.org/nightly/std/io/index.html)
|
|
||||||
//! for a full description of the functionality.
|
|
||||||
#![allow(stable_features,unused_features)]
|
|
||||||
#![feature(question_mark,const_fn,copy_from_slice,try_from,str_internals,align_offset,slice_internals)]
|
|
||||||
#![cfg_attr(any(feature="alloc",feature="collections"),feature(alloc))]
|
|
||||||
#![cfg_attr(pattern_guards,feature(bind_by_move_pattern_guards,nll))]
|
|
||||||
#![cfg_attr(non_exhaustive,feature(non_exhaustive))]
|
|
||||||
#![cfg_attr(unicode,feature(str_char))]
|
|
||||||
#![cfg_attr(unicode,feature(unicode))]
|
|
||||||
#![no_std]
|
|
||||||
|
|
||||||
#[cfg_attr(feature="collections",macro_use)]
|
|
||||||
#[cfg_attr(feature="collections",allow(unused_imports))]
|
|
||||||
#[cfg(feature="collections")] extern crate alloc as collections;
|
|
||||||
#[cfg(feature="alloc")] extern crate alloc;
|
|
||||||
#[cfg(rustc_unicode)]
|
|
||||||
extern crate rustc_unicode;
|
|
||||||
#[cfg(std_unicode)]
|
|
||||||
extern crate std_unicode;
|
|
||||||
|
|
||||||
#[cfg(not(feature="collections"))]
|
|
||||||
pub type ErrorString = &'static str;
|
|
||||||
|
|
||||||
// Provide Box::new wrapper
|
|
||||||
#[cfg(not(feature="alloc"))]
|
|
||||||
struct FakeBox<T>(core::marker::PhantomData<T>);
|
|
||||||
#[cfg(not(feature="alloc"))]
|
|
||||||
impl<T> FakeBox<T> {
|
|
||||||
fn new(val: T) -> T {
|
|
||||||
val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Needed for older compilers, to ignore vec!/format! macros in tests
|
|
||||||
#[cfg(not(feature="collections"))]
|
|
||||||
#[allow(unused)]
|
|
||||||
macro_rules! vec (
|
|
||||||
( $ elem : expr ; $ n : expr ) => { () };
|
|
||||||
( $ ( $ x : expr ) , * ) => { () };
|
|
||||||
( $ ( $ x : expr , ) * ) => { () };
|
|
||||||
);
|
|
||||||
#[cfg(not(feature="collections"))]
|
|
||||||
#[allow(unused)]
|
|
||||||
macro_rules! format {
|
|
||||||
( $ ( $ arg : tt ) * ) => { () };
|
|
||||||
}
|
|
||||||
|
|
||||||
mod io;
|
|
||||||
pub use io::*;
|
|
|
@ -5,11 +5,8 @@ authors = ["M-Labs"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
target_zc706 = []
|
|
||||||
target_cora_z7_10 = []
|
|
||||||
target_redpitaya = []
|
|
||||||
power_saving = []
|
power_saving = []
|
||||||
default = ["target_zc706"]
|
default = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bit_field = "0.10"
|
bit_field = "0.10"
|
||||||
|
|
|
@ -34,6 +34,12 @@ pub fn isb() {
|
||||||
unsafe { llvm_asm!("isb" :::: "volatile") }
|
unsafe { llvm_asm!("isb" :::: "volatile") }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enable FIQ
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn enable_fiq() {
|
||||||
|
llvm_asm!("cpsie f":::: "volatile");
|
||||||
|
}
|
||||||
|
|
||||||
/// Enable IRQ
|
/// Enable IRQ
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn enable_irq() {
|
pub unsafe fn enable_irq() {
|
||||||
|
|
|
@ -2,7 +2,9 @@ use libregister::{register, register_at, register_bit, register_bits, RegisterRW
|
||||||
use super::asm::dmb;
|
use super::asm::dmb;
|
||||||
use volatile_register::RW;
|
use volatile_register::RW;
|
||||||
|
|
||||||
pub fn enable_l2_cache() {
|
/// enable L2 cache with specific prefetch offset
|
||||||
|
/// prefetch offset requires manual tuning, it seems that 8 is good for ZC706 current settings
|
||||||
|
pub fn enable_l2_cache(offset: u8) {
|
||||||
dmb();
|
dmb();
|
||||||
let regs = RegisterBlock::new();
|
let regs = RegisterBlock::new();
|
||||||
// disable L2 cache
|
// disable L2 cache
|
||||||
|
@ -14,6 +16,7 @@ pub fn enable_l2_cache() {
|
||||||
.double_linefill_en(true)
|
.double_linefill_en(true)
|
||||||
.incr_double_linefill_en(true)
|
.incr_double_linefill_en(true)
|
||||||
.pref_drop_en(true)
|
.pref_drop_en(true)
|
||||||
|
.prefetch_offset(offset)
|
||||||
);
|
);
|
||||||
regs.reg1_aux_control.modify(|_, w| {
|
regs.reg1_aux_control.modify(|_, w| {
|
||||||
w.early_bresp_en(true)
|
w.early_bresp_en(true)
|
||||||
|
@ -326,3 +329,5 @@ register_bit!(reg15_prefetch_ctrl, instr_prefetch_en, 29);
|
||||||
register_bit!(reg15_prefetch_ctrl, data_prefetch_en, 28);
|
register_bit!(reg15_prefetch_ctrl, data_prefetch_en, 28);
|
||||||
register_bit!(reg15_prefetch_ctrl, pref_drop_en, 24);
|
register_bit!(reg15_prefetch_ctrl, pref_drop_en, 24);
|
||||||
register_bit!(reg15_prefetch_ctrl, incr_double_linefill_en, 23);
|
register_bit!(reg15_prefetch_ctrl, incr_double_linefill_en, 23);
|
||||||
|
register_bits!(reg15_prefetch_ctrl, prefetch_offset, u8, 0, 4);
|
||||||
|
|
||||||
|
|
|
@ -6,17 +6,17 @@
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
pub mod asm;
|
pub mod asm;
|
||||||
pub mod regs;
|
|
||||||
pub mod cache;
|
pub mod cache;
|
||||||
|
mod fpu;
|
||||||
|
pub mod l2c;
|
||||||
pub mod mmu;
|
pub mod mmu;
|
||||||
pub mod mutex;
|
pub mod mutex;
|
||||||
pub mod sync_channel;
|
pub mod regs;
|
||||||
pub mod semaphore;
|
pub mod semaphore;
|
||||||
pub mod l2c;
|
pub mod sync_channel;
|
||||||
mod uncached;
|
mod uncached;
|
||||||
mod fpu;
|
|
||||||
pub use uncached::UncachedSlice;
|
|
||||||
pub use fpu::enable_fpu;
|
pub use fpu::enable_fpu;
|
||||||
|
pub use uncached::UncachedSlice;
|
||||||
|
|
||||||
global_asm!(include_str!("exceptions.s"));
|
global_asm!(include_str!("exceptions.s"));
|
||||||
|
|
||||||
|
@ -35,3 +35,47 @@ pub fn notify_spin_lock() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
/// Interrupt handler, which setup the stack and preserve registers before jumping to actual interrupt handler.
|
||||||
|
/// Registers r0-r12, PC, SP and CPSR are restored after the actual handler.
|
||||||
|
///
|
||||||
|
/// - `name` is the name of the interrupt, should be the same as the one defined in vector table.
|
||||||
|
/// - `name2` is the name for the actual handler, should be different from name.
|
||||||
|
/// - `stack0` is the stack for the interrupt handler when called from core0.
|
||||||
|
/// - `stack1` is the stack for the interrupt handler when called from core1.
|
||||||
|
/// - `body` is the body of the actual interrupt handler, should be a normal unsafe rust function
|
||||||
|
/// body.
|
||||||
|
///
|
||||||
|
/// Note that the interrupt handler would use the same stack as normal programs by default.
|
||||||
|
macro_rules! interrupt_handler {
|
||||||
|
($name:ident, $name2:ident, $stack0:ident, $stack1:ident, $body:block) => {
|
||||||
|
#[link_section = ".text.boot"]
|
||||||
|
#[no_mangle]
|
||||||
|
#[naked]
|
||||||
|
pub unsafe extern "C" fn $name() -> ! {
|
||||||
|
asm!(
|
||||||
|
// setup SP, depending on CPU 0 or 1
|
||||||
|
// and preserve registers
|
||||||
|
"sub lr, lr, #4",
|
||||||
|
"stmfd sp!, {{r0-r12, lr}}",
|
||||||
|
"mrc p15, #0, r0, c0, c0, #5",
|
||||||
|
concat!("movw r1, :lower16:", stringify!($stack0)),
|
||||||
|
concat!("movt r1, :upper16:", stringify!($stack0)),
|
||||||
|
"tst r0, #3",
|
||||||
|
concat!("movwne r1, :lower16:", stringify!($stack1)),
|
||||||
|
concat!("movtne r1, :upper16:", stringify!($stack1)),
|
||||||
|
"mov r0, sp",
|
||||||
|
"mov sp, r1",
|
||||||
|
"push {{r0, r1}}", // 2 registers are pushed to maintain 8 byte stack alignment
|
||||||
|
concat!("bl ", stringify!($name2)),
|
||||||
|
"pop {{r0, r1}}",
|
||||||
|
"mov sp, r0",
|
||||||
|
"ldmfd sp!, {{r0-r12, pc}}^", // caret ^ : copy SPSR to the CPSR
|
||||||
|
options(noreturn)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn $name2() $body
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
use core::ops::{Deref, DerefMut};
|
use core::ops::{Deref, DerefMut};
|
||||||
use core::sync::atomic::{AtomicU32, Ordering};
|
use core::sync::atomic::{AtomicU32, Ordering};
|
||||||
use core::cell::UnsafeCell;
|
use core::cell::UnsafeCell;
|
||||||
|
use core::task::{Context, Poll};
|
||||||
|
use core::pin::Pin;
|
||||||
|
use core::future::Future;
|
||||||
use super::{
|
use super::{
|
||||||
spin_lock_yield, notify_spin_lock,
|
spin_lock_yield, notify_spin_lock,
|
||||||
asm::{enter_critical, exit_critical}
|
asm::{enter_critical, exit_critical}
|
||||||
|
@ -20,6 +23,23 @@ pub struct Mutex<T> {
|
||||||
unsafe impl<T: Send> Sync for Mutex<T> {}
|
unsafe impl<T: Send> Sync for Mutex<T> {}
|
||||||
unsafe impl<T: Send> Send for Mutex<T> {}
|
unsafe impl<T: Send> Send for Mutex<T> {}
|
||||||
|
|
||||||
|
struct Fut<'a, T>(&'a Mutex<T>);
|
||||||
|
|
||||||
|
impl<'a, T> Future for Fut<'a, T> {
|
||||||
|
type Output = MutexGuard<'a, T>;
|
||||||
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
|
let irq = unsafe { enter_critical() };
|
||||||
|
if self.0.locked.compare_exchange_weak(UNLOCKED, LOCKED, Ordering::AcqRel, Ordering::Relaxed).is_err() {
|
||||||
|
unsafe { exit_critical(irq) };
|
||||||
|
cx.waker().wake_by_ref();
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Poll::Ready(MutexGuard { mutex: self.0, irq })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> Mutex<T> {
|
impl<T> Mutex<T> {
|
||||||
/// Constructor, const-fn
|
/// Constructor, const-fn
|
||||||
pub const fn new(inner: T) -> Self {
|
pub const fn new(inner: T) -> Self {
|
||||||
|
@ -32,7 +52,7 @@ impl<T> Mutex<T> {
|
||||||
/// Lock the Mutex, blocks when already locked
|
/// Lock the Mutex, blocks when already locked
|
||||||
pub fn lock(&self) -> MutexGuard<T> {
|
pub fn lock(&self) -> MutexGuard<T> {
|
||||||
let mut irq = unsafe { enter_critical() };
|
let mut irq = unsafe { enter_critical() };
|
||||||
while self.locked.compare_and_swap(UNLOCKED, LOCKED, Ordering::AcqRel) != UNLOCKED {
|
while self.locked.compare_exchange_weak(UNLOCKED, LOCKED, Ordering::AcqRel, Ordering::Relaxed).is_err() {
|
||||||
unsafe {
|
unsafe {
|
||||||
exit_critical(irq);
|
exit_critical(irq);
|
||||||
spin_lock_yield();
|
spin_lock_yield();
|
||||||
|
@ -42,9 +62,13 @@ impl<T> Mutex<T> {
|
||||||
MutexGuard { mutex: self, irq }
|
MutexGuard { mutex: self, irq }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn async_lock(&self) -> MutexGuard<'_, T> {
|
||||||
|
Fut(&self).await
|
||||||
|
}
|
||||||
|
|
||||||
pub fn try_lock(&self) -> Option<MutexGuard<T>> {
|
pub fn try_lock(&self) -> Option<MutexGuard<T>> {
|
||||||
let irq = unsafe { enter_critical() };
|
let irq = unsafe { enter_critical() };
|
||||||
if self.locked.compare_and_swap(UNLOCKED, LOCKED, Ordering::AcqRel) != UNLOCKED {
|
if self.locked.compare_exchange_weak(UNLOCKED, LOCKED, Ordering::AcqRel, Ordering::Relaxed).is_err() {
|
||||||
unsafe { exit_critical(irq) };
|
unsafe { exit_critical(irq) };
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -173,7 +173,7 @@ impl RegisterRW for ACTLR {
|
||||||
|
|
||||||
impl ACTLR {
|
impl ACTLR {
|
||||||
pub fn enable_smp(&mut self) {
|
pub fn enable_smp(&mut self) {
|
||||||
self.modify(|_, w| w.smp(true).fw(true));
|
self.modify(|_, w| w.smp(true).fw(true).alloc_one_way(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enable_prefetch(&mut self) {
|
pub fn enable_prefetch(&mut self) {
|
||||||
|
|
|
@ -20,7 +20,7 @@ impl Semaphore {
|
||||||
loop {
|
loop {
|
||||||
let value = self.value.load(Ordering::Relaxed);
|
let value = self.value.load(Ordering::Relaxed);
|
||||||
if value > 0 {
|
if value > 0 {
|
||||||
if self.value.compare_and_swap(value, value - 1, Ordering::SeqCst) == value {
|
if self.value.compare_exchange_weak(value, value - 1, Ordering::SeqCst, Ordering::Relaxed).is_ok() {
|
||||||
return Some(());
|
return Some(());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -58,7 +58,7 @@ impl Semaphore {
|
||||||
loop {
|
loop {
|
||||||
let value = self.value.load(Ordering::Relaxed);
|
let value = self.value.load(Ordering::Relaxed);
|
||||||
if value < self.max {
|
if value < self.max {
|
||||||
if self.value.compare_and_swap(value, value + 1, Ordering::SeqCst) == value {
|
if self.value.compare_exchange_weak(value, value + 1, Ordering::SeqCst, Ordering::Relaxed).is_ok() {
|
||||||
notify_spin_lock();
|
notify_spin_lock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use core::{
|
||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
mem::{align_of, size_of},
|
mem::{align_of, size_of},
|
||||||
};
|
};
|
||||||
use alloc::alloc::{dealloc, Layout, LayoutErr};
|
use alloc::alloc::{dealloc, Layout, LayoutError};
|
||||||
use crate::mmu::{L1_PAGE_SIZE, L1Table};
|
use crate::mmu::{L1_PAGE_SIZE, L1Table};
|
||||||
|
|
||||||
pub struct UncachedSlice<T: 'static> {
|
pub struct UncachedSlice<T: 'static> {
|
||||||
|
@ -12,7 +12,7 @@ pub struct UncachedSlice<T: 'static> {
|
||||||
|
|
||||||
impl<T> UncachedSlice<T> {
|
impl<T> UncachedSlice<T> {
|
||||||
/// allocates in chunks of 1 MB
|
/// allocates in chunks of 1 MB
|
||||||
pub fn new<F: Fn() -> T>(len: usize, default: F) -> Result<Self, LayoutErr> {
|
pub fn new<F: Fn() -> T>(len: usize, default: F) -> Result<Self, LayoutError> {
|
||||||
// round to full pages
|
// round to full pages
|
||||||
let size = ((len * size_of::<T>() - 1) | (L1_PAGE_SIZE - 1)) + 1;
|
let size = ((len * size_of::<T>() - 1) | (L1_PAGE_SIZE - 1)) + 1;
|
||||||
let align = align_of::<T>()
|
let align = align_of::<T>()
|
||||||
|
|
|
@ -30,8 +30,9 @@ pub trait RegisterRW: RegisterR + RegisterW {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! register_common {
|
macro_rules! register_common {
|
||||||
($mod_name: ident, $struct_name: ident, $access: ty, $inner: ty) => (
|
($mod_name: ident, $(#[$outer:meta])* $struct_name: ident, $access: ty, $inner: ty) => (
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
$(#[$outer])*
|
||||||
pub struct $struct_name {
|
pub struct $struct_name {
|
||||||
inner: $access,
|
inner: $access,
|
||||||
}
|
}
|
||||||
|
@ -52,7 +53,7 @@ macro_rules! register_common {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! register_r {
|
macro_rules! register_r {
|
||||||
($mod_name: ident, $struct_name: ident) => (
|
($mod_name: ident, $struct_name: ident) => (
|
||||||
impl libregister::RegisterR for $struct_name {
|
impl $crate::RegisterR for $struct_name {
|
||||||
type R = $mod_name::Read;
|
type R = $mod_name::Read;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -67,7 +68,7 @@ macro_rules! register_r {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! register_w {
|
macro_rules! register_w {
|
||||||
($mod_name: ident, $struct_name: ident) => (
|
($mod_name: ident, $struct_name: ident) => (
|
||||||
impl libregister::RegisterW for $struct_name {
|
impl $crate::RegisterW for $struct_name {
|
||||||
type W = $mod_name::Write;
|
type W = $mod_name::Write;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -88,7 +89,7 @@ macro_rules! register_w {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! register_rw {
|
macro_rules! register_rw {
|
||||||
($mod_name: ident, $struct_name: ident) => (
|
($mod_name: ident, $struct_name: ident) => (
|
||||||
impl libregister::RegisterRW for $struct_name {
|
impl $crate::RegisterRW for $struct_name {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn modify<F: FnOnce(Self::R, Self::W) -> Self::W>(&mut self, f: F) {
|
fn modify<F: FnOnce(Self::R, Self::W) -> Self::W>(&mut self, f: F) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -101,7 +102,7 @@ macro_rules! register_rw {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
($mod_name: ident, $struct_name: ident, $mask: expr) => (
|
($mod_name: ident, $struct_name: ident, $mask: expr) => (
|
||||||
impl libregister::RegisterRW for $struct_name {
|
impl $crate::RegisterRW for $struct_name {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn modify<F: FnOnce(Self::R, Self::W) -> Self::W>(&mut self, f: F) {
|
fn modify<F: FnOnce(Self::R, Self::W) -> Self::W>(&mut self, f: F) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -119,7 +120,7 @@ macro_rules! register_rw {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! register_vcell {
|
macro_rules! register_vcell {
|
||||||
($mod_name: ident, $struct_name: ident) => (
|
($mod_name: ident, $struct_name: ident) => (
|
||||||
impl libregister::RegisterR for $struct_name {
|
impl $crate::RegisterR for $struct_name {
|
||||||
type R = $mod_name::Read;
|
type R = $mod_name::Read;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -128,7 +129,7 @@ macro_rules! register_vcell {
|
||||||
$mod_name::Read { inner }
|
$mod_name::Read { inner }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl libregister::RegisterW for $struct_name {
|
impl $crate::RegisterW for $struct_name {
|
||||||
type W = $mod_name::Write;
|
type W = $mod_name::Write;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -141,7 +142,7 @@ macro_rules! register_vcell {
|
||||||
self.inner.set(w.inner);
|
self.inner.set(w.inner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl libregister::RegisterRW for $struct_name {
|
impl $crate::RegisterRW for $struct_name {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn modify<F: FnOnce(Self::R, Self::W) -> Self::W>(&mut self, f: F) {
|
fn modify<F: FnOnce(Self::R, Self::W) -> Self::W>(&mut self, f: F) {
|
||||||
let r = self.read();
|
let r = self.read();
|
||||||
|
@ -157,37 +158,37 @@ macro_rules! register_vcell {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! register {
|
macro_rules! register {
|
||||||
// Define read-only register
|
// Define read-only register
|
||||||
($mod_name: ident, $struct_name: ident, RO, $inner: ty) => (
|
($mod_name: ident, $(#[$outer:meta])* $struct_name: ident, RO, $inner: ty) => (
|
||||||
libregister::register_common!($mod_name, $struct_name, libregister::RO<$inner>, $inner);
|
$crate::register_common!($mod_name, $(#[$outer])* $struct_name, $crate::RO<$inner>, $inner);
|
||||||
libregister::register_r!($mod_name, $struct_name);
|
$crate::register_r!($mod_name, $struct_name);
|
||||||
);
|
);
|
||||||
|
|
||||||
// Define write-only register
|
// Define write-only register
|
||||||
($mod_name: ident, $struct_name: ident, WO, $inner: ty) => (
|
($mod_name: ident, $(#[$outer:meta])* $struct_name: ident, WO, $inner: ty) => (
|
||||||
libregister::register_common!($mod_name, $struct_name, volatile_register::WO<$inner>, $inner);
|
$crate::register_common!($mod_name, $(#[$outer])* $struct_name, volatile_register::WO<$inner>, $inner);
|
||||||
libregister::register_w!($mod_name, $struct_name);
|
$crate::register_w!($mod_name, $struct_name);
|
||||||
);
|
);
|
||||||
|
|
||||||
// Define read-write register
|
// Define read-write register
|
||||||
($mod_name: ident, $struct_name: ident, RW, $inner: ty) => (
|
($mod_name: ident, $(#[$outer:meta])* $struct_name: ident, RW, $inner: ty) => (
|
||||||
libregister::register_common!($mod_name, $struct_name, volatile_register::RW<$inner>, $inner);
|
$crate::register_common!($mod_name, $(#[$outer])* $struct_name, volatile_register::RW<$inner>, $inner);
|
||||||
libregister::register_r!($mod_name, $struct_name);
|
$crate::register_r!($mod_name, $struct_name);
|
||||||
libregister::register_w!($mod_name, $struct_name);
|
$crate::register_w!($mod_name, $struct_name);
|
||||||
libregister::register_rw!($mod_name, $struct_name);
|
$crate::register_rw!($mod_name, $struct_name);
|
||||||
);
|
);
|
||||||
|
|
||||||
// Define read-write register
|
// Define read-write register
|
||||||
($mod_name: ident, $struct_name: ident, VolatileCell, $inner: ty) => (
|
($mod_name: ident, $(#[$outer:meta])* $struct_name: ident, VolatileCell, $inner: ty) => (
|
||||||
libregister::register_common!($mod_name, $struct_name, VolatileCell<$inner>, $inner);
|
$crate::register_common!($mod_name, $(#[$outer])* $struct_name, VolatileCell<$inner>, $inner);
|
||||||
libregister::register_vcell!($mod_name, $struct_name);
|
$crate::register_vcell!($mod_name, $struct_name);
|
||||||
);
|
);
|
||||||
|
|
||||||
// Define read-write register with mask on write (for WTC mixed access.)
|
// Define read-write register with mask on write (for WTC mixed access.)
|
||||||
($mod_name: ident, $struct_name: ident, RW, $inner: ty, $mask: expr) => (
|
($mod_name: ident, $(#[$outer:meta])* $struct_name: ident, RW, $inner: ty, $mask: expr) => (
|
||||||
libregister::register_common!($mod_name, $struct_name, volatile_register::RW<$inner>, $inner);
|
$crate::register_common!($mod_name, $(#[$outer])* $struct_name, volatile_register::RW<$inner>, $inner);
|
||||||
libregister::register_r!($mod_name, $struct_name);
|
$crate::register_r!($mod_name, $struct_name);
|
||||||
libregister::register_w!($mod_name, $struct_name);
|
$crate::register_w!($mod_name, $struct_name);
|
||||||
libregister::register_rw!($mod_name, $struct_name, $mask);
|
$crate::register_rw!($mod_name, $struct_name, $mask);
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,18 +7,24 @@ edition = "2018"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
target_zc706 = ["libboard_zynq/target_zc706"]
|
target_zc706 = ["libboard_zynq/target_zc706"]
|
||||||
target_cora_z7_10 = ["libboard_zynq/target_cora_z7_10"]
|
target_coraz7 = ["libboard_zynq/target_coraz7"]
|
||||||
|
target_ebaz4205 = ["libboard_zynq/target_ebaz4205"]
|
||||||
target_redpitaya = ["libboard_zynq/target_redpitaya"]
|
target_redpitaya = ["libboard_zynq/target_redpitaya"]
|
||||||
|
target_kasli_soc = ["libboard_zynq/target_kasli_soc"]
|
||||||
panic_handler = []
|
panic_handler = []
|
||||||
dummy_irq_handler = []
|
dummy_irq_handler = []
|
||||||
|
dummy_fiq_handler = []
|
||||||
alloc_core = []
|
alloc_core = []
|
||||||
|
|
||||||
default = ["panic_handler", "dummy_irq_handler"]
|
default = ["panic_handler", "dummy_irq_handler", "dummy_fiq_handler"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
r0 = "1"
|
r0 = "1"
|
||||||
compiler_builtins = "0.1"
|
compiler_builtins = "=0.1.39"
|
||||||
linked_list_allocator = { version = "0.8", default-features = false }
|
linked_list_allocator = { version = "0.8", default-features = false, features = ["const_mut_refs"] }
|
||||||
libregister = { path = "../libregister" }
|
libregister = { path = "../libregister" }
|
||||||
libcortex_a9 = { path = "../libcortex_a9" }
|
libcortex_a9 = { path = "../libcortex_a9" }
|
||||||
libboard_zynq = { path = "../libboard_zynq" }
|
libboard_zynq = { path = "../libboard_zynq" }
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
cc = { version = "1.0" }
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
fn main() {
|
||||||
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
|
compile_memcpy();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compile_memcpy() {
|
||||||
|
use std::path::Path;
|
||||||
|
extern crate cc;
|
||||||
|
let cfg = &mut cc::Build::new();
|
||||||
|
cfg.compiler("clang");
|
||||||
|
cfg.no_default_flags(true);
|
||||||
|
cfg.warnings(false);
|
||||||
|
cfg.flag("--target=armv7-none-eabihf");
|
||||||
|
let sources = vec![
|
||||||
|
"memcpy.S",
|
||||||
|
];
|
||||||
|
let root = Path::new("src/asm");
|
||||||
|
for src in sources {
|
||||||
|
println!("cargo:rerun-if-changed={}", src);
|
||||||
|
cfg.file(root.join(src));
|
||||||
|
}
|
||||||
|
cfg.compile("memcpy");
|
||||||
|
}
|
||||||
|
|
|
@ -1,70 +0,0 @@
|
||||||
use libregister::RegisterR;
|
|
||||||
use libcortex_a9::regs::{DFSR, MPIDR};
|
|
||||||
use libboard_zynq::{println, stdio};
|
|
||||||
|
|
||||||
#[link_section = ".text.boot"]
|
|
||||||
#[no_mangle]
|
|
||||||
#[naked]
|
|
||||||
pub unsafe extern "C" fn UndefinedInstruction() {
|
|
||||||
stdio::drop_uart();
|
|
||||||
println!("UndefinedInstruction");
|
|
||||||
loop {}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[link_section = ".text.boot"]
|
|
||||||
#[no_mangle]
|
|
||||||
#[naked]
|
|
||||||
pub unsafe extern "C" fn SoftwareInterrupt() {
|
|
||||||
stdio::drop_uart();
|
|
||||||
println!("SoftwareInterrupt");
|
|
||||||
loop {}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[link_section = ".text.boot"]
|
|
||||||
#[no_mangle]
|
|
||||||
#[naked]
|
|
||||||
pub unsafe extern "C" fn PrefetchAbort() {
|
|
||||||
stdio::drop_uart();
|
|
||||||
println!("PrefetchAbort");
|
|
||||||
loop {}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[link_section = ".text.boot"]
|
|
||||||
#[no_mangle]
|
|
||||||
#[naked]
|
|
||||||
pub unsafe extern "C" fn DataAbort() {
|
|
||||||
stdio::drop_uart();
|
|
||||||
|
|
||||||
println!("DataAbort on core {}", MPIDR.read().cpu_id());
|
|
||||||
println!("DFSR: {:03X}", DFSR.read());
|
|
||||||
|
|
||||||
loop {}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[link_section = ".text.boot"]
|
|
||||||
#[no_mangle]
|
|
||||||
#[naked]
|
|
||||||
pub unsafe extern "C" fn ReservedException() {
|
|
||||||
stdio::drop_uart();
|
|
||||||
println!("ReservedException");
|
|
||||||
loop {}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[link_section = ".text.boot"]
|
|
||||||
#[no_mangle]
|
|
||||||
#[naked]
|
|
||||||
#[cfg(feature = "dummy_irq_handler")]
|
|
||||||
pub unsafe extern "C" fn IRQ() {
|
|
||||||
stdio::drop_uart();
|
|
||||||
println!("IRQ");
|
|
||||||
loop {}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[link_section = ".text.boot"]
|
|
||||||
#[no_mangle]
|
|
||||||
#[naked]
|
|
||||||
pub unsafe extern "C" fn FIQ() {
|
|
||||||
stdio::drop_uart();
|
|
||||||
println!("FIQ");
|
|
||||||
loop {}
|
|
||||||
}
|
|
|
@ -0,0 +1,626 @@
|
||||||
|
/* Copyright (c) 2013, Linaro Limited
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of Linaro Limited nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
This memcpy routine is optimised for Cortex-A15 cores and takes advantage
|
||||||
|
of VFP or NEON when built with the appropriate flags.
|
||||||
|
|
||||||
|
Assumptions:
|
||||||
|
|
||||||
|
ARMv6 (ARMv7-a if using Neon)
|
||||||
|
ARM state
|
||||||
|
Unaligned accesses
|
||||||
|
LDRD/STRD support unaligned word accesses
|
||||||
|
|
||||||
|
If compiled with GCC, this file should be enclosed within following
|
||||||
|
pre-processing check:
|
||||||
|
if defined (__ARM_ARCH_7A__) && defined (__ARM_FEATURE_UNALIGNED)
|
||||||
|
|
||||||
|
*/
|
||||||
|
.syntax unified
|
||||||
|
/* This implementation requires ARM state. */
|
||||||
|
.arm
|
||||||
|
|
||||||
|
#ifdef __ARM_NEON__
|
||||||
|
|
||||||
|
.fpu neon
|
||||||
|
.arch armv7-a
|
||||||
|
# define FRAME_SIZE 4
|
||||||
|
# define USE_VFP
|
||||||
|
# define USE_NEON
|
||||||
|
|
||||||
|
#elif !defined (__SOFTFP__)
|
||||||
|
|
||||||
|
.arch armv6
|
||||||
|
.fpu vfpv2
|
||||||
|
# define FRAME_SIZE 32
|
||||||
|
# define USE_VFP
|
||||||
|
|
||||||
|
#else
|
||||||
|
.arch armv6
|
||||||
|
# define FRAME_SIZE 32
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Old versions of GAS incorrectly implement the NEON align semantics. */
|
||||||
|
#ifdef BROKEN_ASM_NEON_ALIGN
|
||||||
|
#define ALIGN(addr, align) addr,:align
|
||||||
|
#else
|
||||||
|
#define ALIGN(addr, align) addr:align
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PC_OFFSET 8 /* PC pipeline compensation. */
|
||||||
|
#define INSN_SIZE 4
|
||||||
|
|
||||||
|
/* Call parameters. */
|
||||||
|
#define dstin r0
|
||||||
|
#define src r1
|
||||||
|
#define count r2
|
||||||
|
|
||||||
|
/* Locals. */
|
||||||
|
#define tmp1 r3
|
||||||
|
#define dst ip
|
||||||
|
#define tmp2 r10
|
||||||
|
|
||||||
|
#ifndef USE_NEON
|
||||||
|
/* For bulk copies using GP registers. */
|
||||||
|
#define A_l r2 /* Call-clobbered. */
|
||||||
|
#define A_h r3 /* Call-clobbered. */
|
||||||
|
#define B_l r4
|
||||||
|
#define B_h r5
|
||||||
|
#define C_l r6
|
||||||
|
#define C_h r7
|
||||||
|
#define D_l r8
|
||||||
|
#define D_h r9
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Number of lines ahead to pre-fetch data. If you change this the code
|
||||||
|
below will need adjustment to compensate. */
|
||||||
|
|
||||||
|
#define prefetch_lines 5
|
||||||
|
|
||||||
|
#ifdef USE_VFP
|
||||||
|
.macro cpy_line_vfp vreg, base
|
||||||
|
vstr \vreg, [dst, #\base]
|
||||||
|
vldr \vreg, [src, #\base]
|
||||||
|
vstr d0, [dst, #\base + 8]
|
||||||
|
vldr d0, [src, #\base + 8]
|
||||||
|
vstr d1, [dst, #\base + 16]
|
||||||
|
vldr d1, [src, #\base + 16]
|
||||||
|
vstr d2, [dst, #\base + 24]
|
||||||
|
vldr d2, [src, #\base + 24]
|
||||||
|
vstr \vreg, [dst, #\base + 32]
|
||||||
|
vldr \vreg, [src, #\base + prefetch_lines * 64 - 32]
|
||||||
|
vstr d0, [dst, #\base + 40]
|
||||||
|
vldr d0, [src, #\base + 40]
|
||||||
|
vstr d1, [dst, #\base + 48]
|
||||||
|
vldr d1, [src, #\base + 48]
|
||||||
|
vstr d2, [dst, #\base + 56]
|
||||||
|
vldr d2, [src, #\base + 56]
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro cpy_tail_vfp vreg, base
|
||||||
|
vstr \vreg, [dst, #\base]
|
||||||
|
vldr \vreg, [src, #\base]
|
||||||
|
vstr d0, [dst, #\base + 8]
|
||||||
|
vldr d0, [src, #\base + 8]
|
||||||
|
vstr d1, [dst, #\base + 16]
|
||||||
|
vldr d1, [src, #\base + 16]
|
||||||
|
vstr d2, [dst, #\base + 24]
|
||||||
|
vldr d2, [src, #\base + 24]
|
||||||
|
vstr \vreg, [dst, #\base + 32]
|
||||||
|
vstr d0, [dst, #\base + 40]
|
||||||
|
vldr d0, [src, #\base + 40]
|
||||||
|
vstr d1, [dst, #\base + 48]
|
||||||
|
vldr d1, [src, #\base + 48]
|
||||||
|
vstr d2, [dst, #\base + 56]
|
||||||
|
vldr d2, [src, #\base + 56]
|
||||||
|
.endm
|
||||||
|
#endif
|
||||||
|
|
||||||
|
.macro def_fn f p2align=0
|
||||||
|
.text
|
||||||
|
.p2align \p2align
|
||||||
|
.global \f
|
||||||
|
.type \f, %function
|
||||||
|
\f:
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.global __aeabi_memcpy
|
||||||
|
.global __aeabi_memcpy4
|
||||||
|
.global __aeabi_memcpy8
|
||||||
|
.set __aeabi_memcpy, fast_memcpy
|
||||||
|
.set __aeabi_memcpy4, fast_memcpy
|
||||||
|
.set __aeabi_memcpy8, fast_memcpy
|
||||||
|
def_fn fast_memcpy p2align=6
|
||||||
|
|
||||||
|
mov dst, dstin /* Preserve dstin, we need to return it. */
|
||||||
|
cmp count, #64
|
||||||
|
bge .Lcpy_not_short
|
||||||
|
/* Deal with small copies quickly by dropping straight into the
|
||||||
|
exit block. */
|
||||||
|
|
||||||
|
.Ltail63unaligned:
|
||||||
|
#ifdef USE_NEON
|
||||||
|
and tmp1, count, #0x38
|
||||||
|
rsb tmp1, tmp1, #(56 - PC_OFFSET + INSN_SIZE)
|
||||||
|
add pc, pc, tmp1
|
||||||
|
vld1.8 {d0}, [src]! /* 14 words to go. */
|
||||||
|
vst1.8 {d0}, [dst]!
|
||||||
|
vld1.8 {d0}, [src]! /* 12 words to go. */
|
||||||
|
vst1.8 {d0}, [dst]!
|
||||||
|
vld1.8 {d0}, [src]! /* 10 words to go. */
|
||||||
|
vst1.8 {d0}, [dst]!
|
||||||
|
vld1.8 {d0}, [src]! /* 8 words to go. */
|
||||||
|
vst1.8 {d0}, [dst]!
|
||||||
|
vld1.8 {d0}, [src]! /* 6 words to go. */
|
||||||
|
vst1.8 {d0}, [dst]!
|
||||||
|
vld1.8 {d0}, [src]! /* 4 words to go. */
|
||||||
|
vst1.8 {d0}, [dst]!
|
||||||
|
vld1.8 {d0}, [src]! /* 2 words to go. */
|
||||||
|
vst1.8 {d0}, [dst]!
|
||||||
|
|
||||||
|
tst count, #4
|
||||||
|
ldrne tmp1, [src], #4
|
||||||
|
strne tmp1, [dst], #4
|
||||||
|
#else
|
||||||
|
/* Copy up to 15 full words of data. May not be aligned. */
|
||||||
|
/* Cannot use VFP for unaligned data. */
|
||||||
|
and tmp1, count, #0x3c
|
||||||
|
add dst, dst, tmp1
|
||||||
|
add src, src, tmp1
|
||||||
|
rsb tmp1, tmp1, #(60 - PC_OFFSET/2 + INSN_SIZE/2)
|
||||||
|
/* Jump directly into the sequence below at the correct offset. */
|
||||||
|
add pc, pc, tmp1, lsl #1
|
||||||
|
|
||||||
|
ldr tmp1, [src, #-60] /* 15 words to go. */
|
||||||
|
str tmp1, [dst, #-60]
|
||||||
|
|
||||||
|
ldr tmp1, [src, #-56] /* 14 words to go. */
|
||||||
|
str tmp1, [dst, #-56]
|
||||||
|
ldr tmp1, [src, #-52]
|
||||||
|
str tmp1, [dst, #-52]
|
||||||
|
|
||||||
|
ldr tmp1, [src, #-48] /* 12 words to go. */
|
||||||
|
str tmp1, [dst, #-48]
|
||||||
|
ldr tmp1, [src, #-44]
|
||||||
|
str tmp1, [dst, #-44]
|
||||||
|
|
||||||
|
ldr tmp1, [src, #-40] /* 10 words to go. */
|
||||||
|
str tmp1, [dst, #-40]
|
||||||
|
ldr tmp1, [src, #-36]
|
||||||
|
str tmp1, [dst, #-36]
|
||||||
|
|
||||||
|
ldr tmp1, [src, #-32] /* 8 words to go. */
|
||||||
|
str tmp1, [dst, #-32]
|
||||||
|
ldr tmp1, [src, #-28]
|
||||||
|
str tmp1, [dst, #-28]
|
||||||
|
|
||||||
|
ldr tmp1, [src, #-24] /* 6 words to go. */
|
||||||
|
str tmp1, [dst, #-24]
|
||||||
|
ldr tmp1, [src, #-20]
|
||||||
|
str tmp1, [dst, #-20]
|
||||||
|
|
||||||
|
ldr tmp1, [src, #-16] /* 4 words to go. */
|
||||||
|
str tmp1, [dst, #-16]
|
||||||
|
ldr tmp1, [src, #-12]
|
||||||
|
str tmp1, [dst, #-12]
|
||||||
|
|
||||||
|
ldr tmp1, [src, #-8] /* 2 words to go. */
|
||||||
|
str tmp1, [dst, #-8]
|
||||||
|
ldr tmp1, [src, #-4]
|
||||||
|
str tmp1, [dst, #-4]
|
||||||
|
#endif
|
||||||
|
|
||||||
|
lsls count, count, #31
|
||||||
|
ldrhcs tmp1, [src], #2
|
||||||
|
ldrbne src, [src] /* Src is dead, use as a scratch. */
|
||||||
|
strhcs tmp1, [dst], #2
|
||||||
|
strbne src, [dst]
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
.Lcpy_not_short:
|
||||||
|
/* At least 64 bytes to copy, but don't know the alignment yet. */
|
||||||
|
str tmp2, [sp, #-FRAME_SIZE]!
|
||||||
|
and tmp2, src, #7
|
||||||
|
and tmp1, dst, #7
|
||||||
|
cmp tmp1, tmp2
|
||||||
|
bne .Lcpy_notaligned
|
||||||
|
|
||||||
|
#ifdef USE_VFP
|
||||||
|
/* Magic dust alert! Force VFP on Cortex-A9. Experiments show
|
||||||
|
that the FP pipeline is much better at streaming loads and
|
||||||
|
stores. This is outside the critical loop. */
|
||||||
|
vmov.f32 s0, s0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* SRC and DST have the same mutual 32-bit alignment, but we may
|
||||||
|
still need to pre-copy some bytes to get to natural alignment.
|
||||||
|
We bring DST into full 64-bit alignment. */
|
||||||
|
lsls tmp2, dst, #29
|
||||||
|
beq 1f
|
||||||
|
rsbs tmp2, tmp2, #0
|
||||||
|
sub count, count, tmp2, lsr #29
|
||||||
|
ldrmi tmp1, [src], #4
|
||||||
|
strmi tmp1, [dst], #4
|
||||||
|
lsls tmp2, tmp2, #2
|
||||||
|
ldrhcs tmp1, [src], #2
|
||||||
|
ldrbne tmp2, [src], #1
|
||||||
|
strhcs tmp1, [dst], #2
|
||||||
|
strbne tmp2, [dst], #1
|
||||||
|
|
||||||
|
1:
|
||||||
|
subs tmp2, count, #64 /* Use tmp2 for count. */
|
||||||
|
blt .Ltail63aligned
|
||||||
|
|
||||||
|
cmp tmp2, #512
|
||||||
|
bge .Lcpy_body_long
|
||||||
|
|
||||||
|
.Lcpy_body_medium: /* Count in tmp2. */
|
||||||
|
#ifdef USE_VFP
|
||||||
|
1:
|
||||||
|
vldr d0, [src, #0]
|
||||||
|
subs tmp2, tmp2, #64
|
||||||
|
vldr d1, [src, #8]
|
||||||
|
vstr d0, [dst, #0]
|
||||||
|
vldr d0, [src, #16]
|
||||||
|
vstr d1, [dst, #8]
|
||||||
|
vldr d1, [src, #24]
|
||||||
|
vstr d0, [dst, #16]
|
||||||
|
vldr d0, [src, #32]
|
||||||
|
vstr d1, [dst, #24]
|
||||||
|
vldr d1, [src, #40]
|
||||||
|
vstr d0, [dst, #32]
|
||||||
|
vldr d0, [src, #48]
|
||||||
|
vstr d1, [dst, #40]
|
||||||
|
vldr d1, [src, #56]
|
||||||
|
vstr d0, [dst, #48]
|
||||||
|
add src, src, #64
|
||||||
|
vstr d1, [dst, #56]
|
||||||
|
add dst, dst, #64
|
||||||
|
bge 1b
|
||||||
|
tst tmp2, #0x3f
|
||||||
|
beq .Ldone
|
||||||
|
|
||||||
|
.Ltail63aligned: /* Count in tmp2. */
|
||||||
|
and tmp1, tmp2, #0x38
|
||||||
|
add dst, dst, tmp1
|
||||||
|
add src, src, tmp1
|
||||||
|
rsb tmp1, tmp1, #(56 - PC_OFFSET + INSN_SIZE)
|
||||||
|
add pc, pc, tmp1
|
||||||
|
|
||||||
|
vldr d0, [src, #-56] /* 14 words to go. */
|
||||||
|
vstr d0, [dst, #-56]
|
||||||
|
vldr d0, [src, #-48] /* 12 words to go. */
|
||||||
|
vstr d0, [dst, #-48]
|
||||||
|
vldr d0, [src, #-40] /* 10 words to go. */
|
||||||
|
vstr d0, [dst, #-40]
|
||||||
|
vldr d0, [src, #-32] /* 8 words to go. */
|
||||||
|
vstr d0, [dst, #-32]
|
||||||
|
vldr d0, [src, #-24] /* 6 words to go. */
|
||||||
|
vstr d0, [dst, #-24]
|
||||||
|
vldr d0, [src, #-16] /* 4 words to go. */
|
||||||
|
vstr d0, [dst, #-16]
|
||||||
|
vldr d0, [src, #-8] /* 2 words to go. */
|
||||||
|
vstr d0, [dst, #-8]
|
||||||
|
#else
|
||||||
|
sub src, src, #8
|
||||||
|
sub dst, dst, #8
|
||||||
|
1:
|
||||||
|
ldrd A_l, A_h, [src, #8]
|
||||||
|
strd A_l, A_h, [dst, #8]
|
||||||
|
ldrd A_l, A_h, [src, #16]
|
||||||
|
strd A_l, A_h, [dst, #16]
|
||||||
|
ldrd A_l, A_h, [src, #24]
|
||||||
|
strd A_l, A_h, [dst, #24]
|
||||||
|
ldrd A_l, A_h, [src, #32]
|
||||||
|
strd A_l, A_h, [dst, #32]
|
||||||
|
ldrd A_l, A_h, [src, #40]
|
||||||
|
strd A_l, A_h, [dst, #40]
|
||||||
|
ldrd A_l, A_h, [src, #48]
|
||||||
|
strd A_l, A_h, [dst, #48]
|
||||||
|
ldrd A_l, A_h, [src, #56]
|
||||||
|
strd A_l, A_h, [dst, #56]
|
||||||
|
ldrd A_l, A_h, [src, #64]!
|
||||||
|
strd A_l, A_h, [dst, #64]!
|
||||||
|
subs tmp2, tmp2, #64
|
||||||
|
bge 1b
|
||||||
|
tst tmp2, #0x3f
|
||||||
|
bne 1f
|
||||||
|
ldr tmp2,[sp], #FRAME_SIZE
|
||||||
|
bx lr
|
||||||
|
1:
|
||||||
|
add src, src, #8
|
||||||
|
add dst, dst, #8
|
||||||
|
|
||||||
|
.Ltail63aligned: /* Count in tmp2. */
|
||||||
|
/* Copy up to 7 d-words of data. Similar to Ltail63unaligned, but
|
||||||
|
we know that the src and dest are 32-bit aligned so we can use
|
||||||
|
LDRD/STRD to improve efficiency. */
|
||||||
|
/* TMP2 is now negative, but we don't care about that. The bottom
|
||||||
|
six bits still tell us how many bytes are left to copy. */
|
||||||
|
|
||||||
|
and tmp1, tmp2, #0x38
|
||||||
|
add dst, dst, tmp1
|
||||||
|
add src, src, tmp1
|
||||||
|
rsb tmp1, tmp1, #(56 - PC_OFFSET + INSN_SIZE)
|
||||||
|
add pc, pc, tmp1
|
||||||
|
ldrd A_l, A_h, [src, #-56] /* 14 words to go. */
|
||||||
|
strd A_l, A_h, [dst, #-56]
|
||||||
|
ldrd A_l, A_h, [src, #-48] /* 12 words to go. */
|
||||||
|
strd A_l, A_h, [dst, #-48]
|
||||||
|
ldrd A_l, A_h, [src, #-40] /* 10 words to go. */
|
||||||
|
strd A_l, A_h, [dst, #-40]
|
||||||
|
ldrd A_l, A_h, [src, #-32] /* 8 words to go. */
|
||||||
|
strd A_l, A_h, [dst, #-32]
|
||||||
|
ldrd A_l, A_h, [src, #-24] /* 6 words to go. */
|
||||||
|
strd A_l, A_h, [dst, #-24]
|
||||||
|
ldrd A_l, A_h, [src, #-16] /* 4 words to go. */
|
||||||
|
strd A_l, A_h, [dst, #-16]
|
||||||
|
ldrd A_l, A_h, [src, #-8] /* 2 words to go. */
|
||||||
|
strd A_l, A_h, [dst, #-8]
|
||||||
|
|
||||||
|
#endif
|
||||||
|
tst tmp2, #4
|
||||||
|
ldrne tmp1, [src], #4
|
||||||
|
strne tmp1, [dst], #4
|
||||||
|
lsls tmp2, tmp2, #31 /* Count (tmp2) now dead. */
|
||||||
|
ldrhcs tmp1, [src], #2
|
||||||
|
ldrbne tmp2, [src]
|
||||||
|
strhcs tmp1, [dst], #2
|
||||||
|
strbne tmp2, [dst]
|
||||||
|
|
||||||
|
.Ldone:
|
||||||
|
ldr tmp2, [sp], #FRAME_SIZE
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
.Lcpy_body_long: /* Count in tmp2. */
|
||||||
|
|
||||||
|
/* Long copy. We know that there's at least (prefetch_lines * 64)
|
||||||
|
bytes to go. */
|
||||||
|
#ifdef USE_VFP
|
||||||
|
/* Don't use PLD. Instead, read some data in advance of the current
|
||||||
|
copy position into a register. This should act like a PLD
|
||||||
|
operation but we won't have to repeat the transfer. */
|
||||||
|
|
||||||
|
vldr d3, [src, #0]
|
||||||
|
vldr d4, [src, #64]
|
||||||
|
vldr d5, [src, #128]
|
||||||
|
vldr d6, [src, #192]
|
||||||
|
vldr d7, [src, #256]
|
||||||
|
|
||||||
|
vldr d0, [src, #8]
|
||||||
|
vldr d1, [src, #16]
|
||||||
|
vldr d2, [src, #24]
|
||||||
|
add src, src, #32
|
||||||
|
|
||||||
|
subs tmp2, tmp2, #prefetch_lines * 64 * 2
|
||||||
|
blt 2f
|
||||||
|
1:
|
||||||
|
cpy_line_vfp d3, 0
|
||||||
|
cpy_line_vfp d4, 64
|
||||||
|
cpy_line_vfp d5, 128
|
||||||
|
add dst, dst, #3 * 64
|
||||||
|
add src, src, #3 * 64
|
||||||
|
cpy_line_vfp d6, 0
|
||||||
|
cpy_line_vfp d7, 64
|
||||||
|
add dst, dst, #2 * 64
|
||||||
|
add src, src, #2 * 64
|
||||||
|
subs tmp2, tmp2, #prefetch_lines * 64
|
||||||
|
bge 1b
|
||||||
|
|
||||||
|
2:
|
||||||
|
cpy_tail_vfp d3, 0
|
||||||
|
cpy_tail_vfp d4, 64
|
||||||
|
cpy_tail_vfp d5, 128
|
||||||
|
add src, src, #3 * 64
|
||||||
|
add dst, dst, #3 * 64
|
||||||
|
cpy_tail_vfp d6, 0
|
||||||
|
vstr d7, [dst, #64]
|
||||||
|
vldr d7, [src, #64]
|
||||||
|
vstr d0, [dst, #64 + 8]
|
||||||
|
vldr d0, [src, #64 + 8]
|
||||||
|
vstr d1, [dst, #64 + 16]
|
||||||
|
vldr d1, [src, #64 + 16]
|
||||||
|
vstr d2, [dst, #64 + 24]
|
||||||
|
vldr d2, [src, #64 + 24]
|
||||||
|
vstr d7, [dst, #64 + 32]
|
||||||
|
add src, src, #96
|
||||||
|
vstr d0, [dst, #64 + 40]
|
||||||
|
vstr d1, [dst, #64 + 48]
|
||||||
|
vstr d2, [dst, #64 + 56]
|
||||||
|
add dst, dst, #128
|
||||||
|
add tmp2, tmp2, #prefetch_lines * 64
|
||||||
|
b .Lcpy_body_medium
|
||||||
|
#else
|
||||||
|
/* Long copy. Use an SMS style loop to maximize the I/O
|
||||||
|
bandwidth of the core. We don't have enough spare registers
|
||||||
|
to synthesise prefetching, so use PLD operations. */
|
||||||
|
/* Pre-bias src and dst. */
|
||||||
|
sub src, src, #8
|
||||||
|
sub dst, dst, #8
|
||||||
|
pld [src, #8]
|
||||||
|
pld [src, #72]
|
||||||
|
subs tmp2, tmp2, #64
|
||||||
|
pld [src, #136]
|
||||||
|
ldrd A_l, A_h, [src, #8]
|
||||||
|
strd B_l, B_h, [sp, #8]
|
||||||
|
ldrd B_l, B_h, [src, #16]
|
||||||
|
strd C_l, C_h, [sp, #16]
|
||||||
|
ldrd C_l, C_h, [src, #24]
|
||||||
|
strd D_l, D_h, [sp, #24]
|
||||||
|
pld [src, #200]
|
||||||
|
ldrd D_l, D_h, [src, #32]!
|
||||||
|
b 1f
|
||||||
|
.p2align 6
|
||||||
|
2:
|
||||||
|
pld [src, #232]
|
||||||
|
strd A_l, A_h, [dst, #40]
|
||||||
|
ldrd A_l, A_h, [src, #40]
|
||||||
|
strd B_l, B_h, [dst, #48]
|
||||||
|
ldrd B_l, B_h, [src, #48]
|
||||||
|
strd C_l, C_h, [dst, #56]
|
||||||
|
ldrd C_l, C_h, [src, #56]
|
||||||
|
strd D_l, D_h, [dst, #64]!
|
||||||
|
ldrd D_l, D_h, [src, #64]!
|
||||||
|
subs tmp2, tmp2, #64
|
||||||
|
1:
|
||||||
|
strd A_l, A_h, [dst, #8]
|
||||||
|
ldrd A_l, A_h, [src, #8]
|
||||||
|
strd B_l, B_h, [dst, #16]
|
||||||
|
ldrd B_l, B_h, [src, #16]
|
||||||
|
strd C_l, C_h, [dst, #24]
|
||||||
|
ldrd C_l, C_h, [src, #24]
|
||||||
|
strd D_l, D_h, [dst, #32]
|
||||||
|
ldrd D_l, D_h, [src, #32]
|
||||||
|
bcs 2b
|
||||||
|
/* Save the remaining bytes and restore the callee-saved regs. */
|
||||||
|
strd A_l, A_h, [dst, #40]
|
||||||
|
add src, src, #40
|
||||||
|
strd B_l, B_h, [dst, #48]
|
||||||
|
ldrd B_l, B_h, [sp, #8]
|
||||||
|
strd C_l, C_h, [dst, #56]
|
||||||
|
ldrd C_l, C_h, [sp, #16]
|
||||||
|
strd D_l, D_h, [dst, #64]
|
||||||
|
ldrd D_l, D_h, [sp, #24]
|
||||||
|
add dst, dst, #72
|
||||||
|
tst tmp2, #0x3f
|
||||||
|
bne .Ltail63aligned
|
||||||
|
ldr tmp2, [sp], #FRAME_SIZE
|
||||||
|
bx lr
|
||||||
|
#endif
|
||||||
|
|
||||||
|
.Lcpy_notaligned:
|
||||||
|
pld [src]
|
||||||
|
pld [src, #64]
|
||||||
|
/* There's at least 64 bytes to copy, but there is no mutual
|
||||||
|
alignment. */
|
||||||
|
/* Bring DST to 64-bit alignment. */
|
||||||
|
lsls tmp2, dst, #29
|
||||||
|
pld [src, #(2 * 64)]
|
||||||
|
beq 1f
|
||||||
|
rsbs tmp2, tmp2, #0
|
||||||
|
sub count, count, tmp2, lsr #29
|
||||||
|
ldrmi tmp1, [src], #4
|
||||||
|
strmi tmp1, [dst], #4
|
||||||
|
lsls tmp2, tmp2, #2
|
||||||
|
ldrbne tmp1, [src], #1
|
||||||
|
ldrhcs tmp2, [src], #2
|
||||||
|
strbne tmp1, [dst], #1
|
||||||
|
strhcs tmp2, [dst], #2
|
||||||
|
1:
|
||||||
|
pld [src, #(3 * 64)]
|
||||||
|
subs count, count, #64
|
||||||
|
ldrmi tmp2, [sp], #FRAME_SIZE
|
||||||
|
bmi .Ltail63unaligned
|
||||||
|
pld [src, #(4 * 64)]
|
||||||
|
|
||||||
|
#ifdef USE_NEON
|
||||||
|
vld1.8 {d0-d3}, [src]!
|
||||||
|
vld1.8 {d4-d7}, [src]!
|
||||||
|
subs count, count, #64
|
||||||
|
bmi 2f
|
||||||
|
1:
|
||||||
|
pld [src, #(4 * 64)]
|
||||||
|
vst1.8 {d0-d3}, [ALIGN (dst, 64)]!
|
||||||
|
vld1.8 {d0-d3}, [src]!
|
||||||
|
vst1.8 {d4-d7}, [ALIGN (dst, 64)]!
|
||||||
|
vld1.8 {d4-d7}, [src]!
|
||||||
|
subs count, count, #64
|
||||||
|
bpl 1b
|
||||||
|
2:
|
||||||
|
vst1.8 {d0-d3}, [ALIGN (dst, 64)]!
|
||||||
|
vst1.8 {d4-d7}, [ALIGN (dst, 64)]!
|
||||||
|
ands count, count, #0x3f
|
||||||
|
#else
|
||||||
|
/* Use an SMS style loop to maximize the I/O bandwidth. */
|
||||||
|
sub src, src, #4
|
||||||
|
sub dst, dst, #8
|
||||||
|
subs tmp2, count, #64 /* Use tmp2 for count. */
|
||||||
|
ldr A_l, [src, #4]
|
||||||
|
ldr A_h, [src, #8]
|
||||||
|
strd B_l, B_h, [sp, #8]
|
||||||
|
ldr B_l, [src, #12]
|
||||||
|
ldr B_h, [src, #16]
|
||||||
|
strd C_l, C_h, [sp, #16]
|
||||||
|
ldr C_l, [src, #20]
|
||||||
|
ldr C_h, [src, #24]
|
||||||
|
strd D_l, D_h, [sp, #24]
|
||||||
|
ldr D_l, [src, #28]
|
||||||
|
ldr D_h, [src, #32]!
|
||||||
|
b 1f
|
||||||
|
.p2align 6
|
||||||
|
2:
|
||||||
|
pld [src, #(5 * 64) - (32 - 4)]
|
||||||
|
strd A_l, A_h, [dst, #40]
|
||||||
|
ldr A_l, [src, #36]
|
||||||
|
ldr A_h, [src, #40]
|
||||||
|
strd B_l, B_h, [dst, #48]
|
||||||
|
ldr B_l, [src, #44]
|
||||||
|
ldr B_h, [src, #48]
|
||||||
|
strd C_l, C_h, [dst, #56]
|
||||||
|
ldr C_l, [src, #52]
|
||||||
|
ldr C_h, [src, #56]
|
||||||
|
strd D_l, D_h, [dst, #64]!
|
||||||
|
ldr D_l, [src, #60]
|
||||||
|
ldr D_h, [src, #64]!
|
||||||
|
subs tmp2, tmp2, #64
|
||||||
|
1:
|
||||||
|
strd A_l, A_h, [dst, #8]
|
||||||
|
ldr A_l, [src, #4]
|
||||||
|
ldr A_h, [src, #8]
|
||||||
|
strd B_l, B_h, [dst, #16]
|
||||||
|
ldr B_l, [src, #12]
|
||||||
|
ldr B_h, [src, #16]
|
||||||
|
strd C_l, C_h, [dst, #24]
|
||||||
|
ldr C_l, [src, #20]
|
||||||
|
ldr C_h, [src, #24]
|
||||||
|
strd D_l, D_h, [dst, #32]
|
||||||
|
ldr D_l, [src, #28]
|
||||||
|
ldr D_h, [src, #32]
|
||||||
|
bcs 2b
|
||||||
|
|
||||||
|
/* Save the remaining bytes and restore the callee-saved regs. */
|
||||||
|
strd A_l, A_h, [dst, #40]
|
||||||
|
add src, src, #36
|
||||||
|
strd B_l, B_h, [dst, #48]
|
||||||
|
ldrd B_l, B_h, [sp, #8]
|
||||||
|
strd C_l, C_h, [dst, #56]
|
||||||
|
ldrd C_l, C_h, [sp, #16]
|
||||||
|
strd D_l, D_h, [dst, #64]
|
||||||
|
ldrd D_l, D_h, [sp, #24]
|
||||||
|
add dst, dst, #72
|
||||||
|
ands count, tmp2, #0x3f
|
||||||
|
#endif
|
||||||
|
ldr tmp2, [sp], #FRAME_SIZE
|
||||||
|
bne .Ltail63unaligned
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
.size memcpy, . - memcpy
|
||||||
|
|
|
@ -2,9 +2,9 @@ use r0::zero_bss;
|
||||||
use core::ptr::write_volatile;
|
use core::ptr::write_volatile;
|
||||||
use libregister::{
|
use libregister::{
|
||||||
VolatileCell,
|
VolatileCell,
|
||||||
RegisterR, RegisterW, RegisterRW,
|
RegisterR, RegisterRW,
|
||||||
};
|
};
|
||||||
use libcortex_a9::{asm, l2c, regs::*, cache, mmu, spin_lock_yield, notify_spin_lock};
|
use libcortex_a9::{asm, l2c, regs::*, cache, mmu, spin_lock_yield, notify_spin_lock, enable_fpu, interrupt_handler};
|
||||||
use libboard_zynq::{slcr, mpcore};
|
use libboard_zynq::{slcr, mpcore};
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -18,31 +18,27 @@ extern "C" {
|
||||||
|
|
||||||
static mut CORE1_ENABLED: VolatileCell<bool> = VolatileCell::new(false);
|
static mut CORE1_ENABLED: VolatileCell<bool> = VolatileCell::new(false);
|
||||||
|
|
||||||
#[link_section = ".text.boot"]
|
interrupt_handler!(Reset, reset_irq, __stack0_start, __stack1_start, {
|
||||||
#[no_mangle]
|
// no need to setup stack here, as we already did when entering the handler
|
||||||
#[naked]
|
|
||||||
pub unsafe extern "C" fn Reset() -> ! {
|
|
||||||
match MPIDR.read().cpu_id() {
|
match MPIDR.read().cpu_id() {
|
||||||
0 => {
|
0 => {
|
||||||
SP.write(&mut __stack0_start as *mut _ as u32);
|
|
||||||
boot_core0();
|
boot_core0();
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
while !CORE1_ENABLED.get() {
|
while !CORE1_ENABLED.get() {
|
||||||
spin_lock_yield();
|
spin_lock_yield();
|
||||||
}
|
}
|
||||||
SP.write(&mut __stack1_start as *mut _ as u32);
|
|
||||||
boot_core1();
|
boot_core1();
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
#[naked]
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
unsafe fn boot_core0() -> ! {
|
unsafe extern "C" fn boot_core0() -> ! {
|
||||||
l1_cache_init();
|
l1_cache_init();
|
||||||
|
|
||||||
|
enable_fpu();
|
||||||
let mpcore = mpcore::RegisterBlock::mpcore();
|
let mpcore = mpcore::RegisterBlock::mpcore();
|
||||||
mpcore.scu_invalidate.invalidate_all_cores();
|
mpcore.scu_invalidate.invalidate_all_cores();
|
||||||
|
|
||||||
|
@ -58,15 +54,15 @@ unsafe fn boot_core0() -> ! {
|
||||||
asm::dmb();
|
asm::dmb();
|
||||||
asm::dsb();
|
asm::dsb();
|
||||||
|
|
||||||
|
asm::enable_fiq();
|
||||||
asm::enable_irq();
|
asm::enable_irq();
|
||||||
main_core0();
|
main_core0();
|
||||||
panic!("return from main");
|
panic!("return from main");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[naked]
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
unsafe fn boot_core1() -> ! {
|
unsafe extern "C" fn boot_core1() -> ! {
|
||||||
l1_cache_init();
|
l1_cache_init();
|
||||||
|
|
||||||
let mpcore = mpcore::RegisterBlock::mpcore();
|
let mpcore = mpcore::RegisterBlock::mpcore();
|
||||||
|
@ -80,6 +76,7 @@ unsafe fn boot_core1() -> ! {
|
||||||
asm::dmb();
|
asm::dmb();
|
||||||
asm::dsb();
|
asm::dsb();
|
||||||
|
|
||||||
|
asm::enable_fiq();
|
||||||
asm::enable_irq();
|
asm::enable_irq();
|
||||||
main_core1();
|
main_core1();
|
||||||
panic!("return from main_core1");
|
panic!("return from main_core1");
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
use libregister::{RegisterR, RegisterW};
|
||||||
|
use libcortex_a9::{regs::{DFSR, MPIDR, VBAR}, interrupt_handler};
|
||||||
|
use libboard_zynq::{println, stdio};
|
||||||
|
|
||||||
|
pub fn set_vector_table(base_addr: u32){
|
||||||
|
VBAR.write(base_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
interrupt_handler!(UndefinedInstruction, undefined_instruction, __irq_stack0_start, __irq_stack1_start, {
|
||||||
|
stdio::drop_uart();
|
||||||
|
println!("UndefinedInstruction");
|
||||||
|
loop {}
|
||||||
|
});
|
||||||
|
|
||||||
|
interrupt_handler!(SoftwareInterrupt, software_interrupt, __irq_stack0_start, __irq_stack1_start, {
|
||||||
|
stdio::drop_uart();
|
||||||
|
println!("SoftwareInterrupt");
|
||||||
|
loop {}
|
||||||
|
});
|
||||||
|
|
||||||
|
interrupt_handler!(PrefetchAbort, prefetch_abort, __irq_stack0_start, __irq_stack1_start, {
|
||||||
|
stdio::drop_uart();
|
||||||
|
println!("PrefetchAbort");
|
||||||
|
loop {}
|
||||||
|
});
|
||||||
|
|
||||||
|
interrupt_handler!(DataAbort, data_abort, __irq_stack0_start, __irq_stack1_start, {
|
||||||
|
stdio::drop_uart();
|
||||||
|
|
||||||
|
println!("DataAbort on core {}", MPIDR.read().cpu_id());
|
||||||
|
println!("DFSR: {:03X}", DFSR.read());
|
||||||
|
|
||||||
|
loop {}
|
||||||
|
});
|
||||||
|
|
||||||
|
interrupt_handler!(ReservedException, reserved_exception, __irq_stack0_start, __irq_stack1_start, {
|
||||||
|
stdio::drop_uart();
|
||||||
|
println!("ReservedException");
|
||||||
|
loop {}
|
||||||
|
});
|
||||||
|
|
||||||
|
#[cfg(feature = "dummy_irq_handler")]
|
||||||
|
interrupt_handler!(IRQ, irq, __irq_stack0_start, __irq_stack1_start, {
|
||||||
|
stdio::drop_uart();
|
||||||
|
println!("IRQ");
|
||||||
|
loop {}
|
||||||
|
});
|
||||||
|
|
||||||
|
#[cfg(feature = "dummy_fiq_handler")]
|
||||||
|
interrupt_handler!(FIQ, fiq, __irq_stack0_start, __irq_stack1_start, {
|
||||||
|
stdio::drop_uart();
|
||||||
|
println!("FIQ");
|
||||||
|
loop {}
|
||||||
|
});
|
|
@ -1,14 +1,16 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
#![feature(naked_functions)]
|
|
||||||
#![feature(alloc_error_handler)]
|
#![feature(alloc_error_handler)]
|
||||||
#![feature(panic_info_message)]
|
#![feature(panic_info_message)]
|
||||||
|
#![feature(naked_functions)]
|
||||||
|
#![feature(asm)]
|
||||||
|
|
||||||
pub extern crate alloc;
|
pub extern crate alloc;
|
||||||
pub extern crate compiler_builtins;
|
pub extern crate compiler_builtins;
|
||||||
|
|
||||||
pub mod boot;
|
pub mod boot;
|
||||||
mod abort;
|
pub mod exception_vectors;
|
||||||
#[cfg(feature = "panic_handler")]
|
#[cfg(feature = "panic_handler")]
|
||||||
mod panic;
|
mod panic;
|
||||||
pub mod ram;
|
pub mod ram;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
use libboard_zynq::{print, println};
|
use libboard_zynq::{print, println};
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
use libboard_zynq::error_led::ErrorLED;
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(info: &core::panic::PanicInfo) -> ! {
|
fn panic(info: &core::panic::PanicInfo) -> ! {
|
||||||
|
@ -13,6 +15,10 @@ fn panic(info: &core::panic::PanicInfo) -> ! {
|
||||||
} else {
|
} else {
|
||||||
println!("");
|
println!("");
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
{
|
||||||
|
let mut err_led = ErrorLED::error_led();
|
||||||
|
err_led.toggle(true);
|
||||||
|
}
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,138 @@
|
||||||
|
{ lib, stdenv, llvm_meta, fetch, fetchpatch, substituteAll, cmake, libxml2, libllvm, version, clang-tools-extra_src, python3
|
||||||
|
, buildLlvmTools
|
||||||
|
, fixDarwinDylibNames
|
||||||
|
, enableManpages ? false
|
||||||
|
, enablePolly ? false
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
self = stdenv.mkDerivation ({
|
||||||
|
pname = "clang";
|
||||||
|
inherit version;
|
||||||
|
|
||||||
|
src = fetch "clang" "12sm91qx2m79cvj75a9aazf2x8xybjbd593dv6v7rxficpq8i0ha";
|
||||||
|
inherit clang-tools-extra_src;
|
||||||
|
|
||||||
|
unpackPhase = ''
|
||||||
|
unpackFile $src
|
||||||
|
mv clang-* clang
|
||||||
|
sourceRoot=$PWD/clang
|
||||||
|
unpackFile ${clang-tools-extra_src}
|
||||||
|
mv clang-tools-extra-* $sourceRoot/tools/extra
|
||||||
|
'';
|
||||||
|
|
||||||
|
nativeBuildInputs = [ cmake python3 ]
|
||||||
|
++ lib.optional enableManpages python3.pkgs.sphinx
|
||||||
|
++ lib.optional stdenv.hostPlatform.isDarwin fixDarwinDylibNames;
|
||||||
|
|
||||||
|
buildInputs = [ libxml2 libllvm ];
|
||||||
|
|
||||||
|
cmakeFlags = [
|
||||||
|
"-DCLANGD_BUILD_XPC=OFF"
|
||||||
|
"-DLLVM_ENABLE_RTTI=ON"
|
||||||
|
] ++ lib.optionals enableManpages [
|
||||||
|
"-DCLANG_INCLUDE_DOCS=ON"
|
||||||
|
"-DLLVM_ENABLE_SPHINX=ON"
|
||||||
|
"-DSPHINX_OUTPUT_MAN=ON"
|
||||||
|
"-DSPHINX_OUTPUT_HTML=OFF"
|
||||||
|
"-DSPHINX_WARNINGS_AS_ERRORS=OFF"
|
||||||
|
] ++ lib.optionals (stdenv.hostPlatform != stdenv.buildPlatform) [
|
||||||
|
"-DLLVM_TABLEGEN_EXE=${buildLlvmTools.llvm}/bin/llvm-tblgen"
|
||||||
|
"-DCLANG_TABLEGEN=${buildLlvmTools.libclang.dev}/bin/clang-tblgen"
|
||||||
|
] ++ lib.optionals enablePolly [
|
||||||
|
"-DWITH_POLLY=ON"
|
||||||
|
"-DLINK_POLLY_INTO_TOOLS=ON"
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
patches = [
|
||||||
|
./purity.patch
|
||||||
|
# https://reviews.llvm.org/D51899
|
||||||
|
./gnu-install-dirs.patch
|
||||||
|
(substituteAll {
|
||||||
|
src = ../../clang-11-12-LLVMgold-path.patch;
|
||||||
|
libllvmLibdir = "${libllvm.lib}/lib";
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
postPatch = ''
|
||||||
|
sed -i -e 's/DriverArgs.hasArg(options::OPT_nostdlibinc)/true/' \
|
||||||
|
-e 's/Args.hasArg(options::OPT_nostdlibinc)/true/' \
|
||||||
|
lib/Driver/ToolChains/*.cpp
|
||||||
|
'' + lib.optionalString stdenv.hostPlatform.isMusl ''
|
||||||
|
sed -i -e 's/lgcc_s/lgcc_eh/' lib/Driver/ToolChains/*.cpp
|
||||||
|
'' + lib.optionalString stdenv.hostPlatform.isDarwin ''
|
||||||
|
substituteInPlace tools/extra/clangd/CMakeLists.txt \
|
||||||
|
--replace "NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB" FALSE
|
||||||
|
'';
|
||||||
|
|
||||||
|
outputs = [ "out" "lib" "dev" "python" ];
|
||||||
|
|
||||||
|
postInstall = ''
|
||||||
|
ln -sv $out/bin/clang $out/bin/cpp
|
||||||
|
|
||||||
|
# Move libclang to 'lib' output
|
||||||
|
moveToOutput "lib/libclang.*" "$lib"
|
||||||
|
moveToOutput "lib/libclang-cpp.*" "$lib"
|
||||||
|
substituteInPlace $out/lib/cmake/clang/ClangTargets-release.cmake \
|
||||||
|
--replace "\''${_IMPORT_PREFIX}/lib/libclang." "$lib/lib/libclang." \
|
||||||
|
--replace "\''${_IMPORT_PREFIX}/lib/libclang-cpp." "$lib/lib/libclang-cpp."
|
||||||
|
|
||||||
|
mkdir -p $python/bin $python/share/{clang,scan-view}
|
||||||
|
mv $out/bin/{git-clang-format,scan-view} $python/bin
|
||||||
|
if [ -e $out/bin/set-xcode-analyzer ]; then
|
||||||
|
mv $out/bin/set-xcode-analyzer $python/bin
|
||||||
|
fi
|
||||||
|
mv $out/share/clang/*.py $python/share/clang
|
||||||
|
mv $out/share/scan-view/*.py $python/share/scan-view
|
||||||
|
rm $out/bin/c-index-test
|
||||||
|
patchShebangs $python/bin
|
||||||
|
|
||||||
|
mkdir -p $dev/bin
|
||||||
|
cp bin/clang-tblgen $dev/bin
|
||||||
|
'';
|
||||||
|
|
||||||
|
passthru = {
|
||||||
|
inherit libllvm;
|
||||||
|
isClang = true;
|
||||||
|
hardeningUnsupportedFlags = [ "fortify3" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
meta = llvm_meta // {
|
||||||
|
homepage = "https://clang.llvm.org/";
|
||||||
|
description = "A C language family frontend for LLVM";
|
||||||
|
longDescription = ''
|
||||||
|
The Clang project provides a language front-end and tooling
|
||||||
|
infrastructure for languages in the C language family (C, C++, Objective
|
||||||
|
C/C++, OpenCL, CUDA, and RenderScript) for the LLVM project.
|
||||||
|
It aims to deliver amazingly fast compiles, extremely useful error and
|
||||||
|
warning messages and to provide a platform for building great source
|
||||||
|
level tools. The Clang Static Analyzer and clang-tidy are tools that
|
||||||
|
automatically find bugs in your code, and are great examples of the sort
|
||||||
|
of tools that can be built using the Clang frontend as a library to
|
||||||
|
parse C/C++ code.
|
||||||
|
'';
|
||||||
|
mainProgram = "clang";
|
||||||
|
};
|
||||||
|
} // lib.optionalAttrs enableManpages {
|
||||||
|
pname = "clang-manpages";
|
||||||
|
|
||||||
|
buildPhase = ''
|
||||||
|
make docs-clang-man
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out/share/man/man1
|
||||||
|
# Manually install clang manpage
|
||||||
|
cp docs/man/*.1 $out/share/man/man1/
|
||||||
|
'';
|
||||||
|
|
||||||
|
outputs = [ "out" ];
|
||||||
|
|
||||||
|
doCheck = false;
|
||||||
|
|
||||||
|
meta = llvm_meta // {
|
||||||
|
description = "man page for Clang ${version}";
|
||||||
|
};
|
||||||
|
});
|
||||||
|
in self
|
|
@ -0,0 +1,235 @@
|
||||||
|
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||||
|
index bb4b801f01c8..77a8b43b22c8 100644
|
||||||
|
--- a/CMakeLists.txt
|
||||||
|
+++ b/CMakeLists.txt
|
||||||
|
@@ -9,6 +9,8 @@ endif()
|
||||||
|
if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR )
|
||||||
|
project(Clang)
|
||||||
|
|
||||||
|
+ include(GNUInstallDirs)
|
||||||
|
+
|
||||||
|
set(CMAKE_CXX_STANDARD 14 CACHE STRING "C++ standard to conform to")
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED YES)
|
||||||
|
set(CMAKE_CXX_EXTENSIONS NO)
|
||||||
|
@@ -447,7 +449,7 @@ include_directories(BEFORE
|
||||||
|
|
||||||
|
if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
|
||||||
|
install(DIRECTORY include/clang include/clang-c
|
||||||
|
- DESTINATION include
|
||||||
|
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||||
|
COMPONENT clang-headers
|
||||||
|
FILES_MATCHING
|
||||||
|
PATTERN "*.def"
|
||||||
|
@@ -457,7 +459,7 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
|
||||||
|
)
|
||||||
|
|
||||||
|
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/clang
|
||||||
|
- DESTINATION include
|
||||||
|
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||||
|
COMPONENT clang-headers
|
||||||
|
FILES_MATCHING
|
||||||
|
PATTERN "CMakeFiles" EXCLUDE
|
||||||
|
@@ -477,7 +479,7 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
|
||||||
|
|
||||||
|
add_custom_target(bash-autocomplete DEPENDS utils/bash-autocomplete.sh)
|
||||||
|
install(PROGRAMS utils/bash-autocomplete.sh
|
||||||
|
- DESTINATION share/clang
|
||||||
|
+ DESTINATION ${CMAKE_INSTALL_DATADIR}/clang
|
||||||
|
COMPONENT bash-autocomplete)
|
||||||
|
if(NOT LLVM_ENABLE_IDE)
|
||||||
|
add_llvm_install_targets(install-bash-autocomplete
|
||||||
|
diff --git a/cmake/modules/AddClang.cmake b/cmake/modules/AddClang.cmake
|
||||||
|
index 704278a0e93b..d25c8d325c71 100644
|
||||||
|
--- a/cmake/modules/AddClang.cmake
|
||||||
|
+++ b/cmake/modules/AddClang.cmake
|
||||||
|
@@ -123,9 +123,9 @@ macro(add_clang_library name)
|
||||||
|
install(TARGETS ${lib}
|
||||||
|
COMPONENT ${lib}
|
||||||
|
${export_to_clangtargets}
|
||||||
|
- LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX}
|
||||||
|
- ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX}
|
||||||
|
- RUNTIME DESTINATION bin)
|
||||||
|
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}
|
||||||
|
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}
|
||||||
|
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
|
||||||
|
if (NOT LLVM_ENABLE_IDE)
|
||||||
|
add_llvm_install_targets(install-${lib}
|
||||||
|
@@ -170,7 +170,7 @@ macro(add_clang_tool name)
|
||||||
|
|
||||||
|
install(TARGETS ${name}
|
||||||
|
${export_to_clangtargets}
|
||||||
|
- RUNTIME DESTINATION bin
|
||||||
|
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
COMPONENT ${name})
|
||||||
|
|
||||||
|
if(NOT LLVM_ENABLE_IDE)
|
||||||
|
@@ -185,7 +185,7 @@ endmacro()
|
||||||
|
macro(add_clang_symlink name dest)
|
||||||
|
add_llvm_tool_symlink(${name} ${dest} ALWAYS_GENERATE)
|
||||||
|
# Always generate install targets
|
||||||
|
- llvm_install_symlink(${name} ${dest} ALWAYS_GENERATE)
|
||||||
|
+ llvm_install_symlink(${name} ${dest} ${CMAKE_INSTALL_FULL_BINDIR} ALWAYS_GENERATE)
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
function(clang_target_link_libraries target type)
|
||||||
|
diff --git a/lib/Headers/CMakeLists.txt b/lib/Headers/CMakeLists.txt
|
||||||
|
index 0692fe75a441..6f201e7207d0 100644
|
||||||
|
--- a/lib/Headers/CMakeLists.txt
|
||||||
|
+++ b/lib/Headers/CMakeLists.txt
|
||||||
|
@@ -208,7 +208,7 @@ set_target_properties(clang-resource-headers PROPERTIES
|
||||||
|
FOLDER "Misc"
|
||||||
|
RUNTIME_OUTPUT_DIRECTORY "${output_dir}")
|
||||||
|
|
||||||
|
-set(header_install_dir lib${LLVM_LIBDIR_SUFFIX}/clang/${CLANG_VERSION}/include)
|
||||||
|
+set(header_install_dir ${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}/clang/${CLANG_VERSION}/include)
|
||||||
|
|
||||||
|
install(
|
||||||
|
FILES ${files} ${generated_files}
|
||||||
|
diff --git a/tools/c-index-test/CMakeLists.txt b/tools/c-index-test/CMakeLists.txt
|
||||||
|
index ceef4b08637c..8efad5520ca4 100644
|
||||||
|
--- a/tools/c-index-test/CMakeLists.txt
|
||||||
|
+++ b/tools/c-index-test/CMakeLists.txt
|
||||||
|
@@ -54,7 +54,7 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
|
||||||
|
set_property(TARGET c-index-test APPEND PROPERTY INSTALL_RPATH
|
||||||
|
"@executable_path/../../lib")
|
||||||
|
else()
|
||||||
|
- set(INSTALL_DESTINATION bin)
|
||||||
|
+ set(INSTALL_DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
install(TARGETS c-index-test
|
||||||
|
diff --git a/tools/clang-format/CMakeLists.txt b/tools/clang-format/CMakeLists.txt
|
||||||
|
index 35ecdb11253c..d77d75de0094 100644
|
||||||
|
--- a/tools/clang-format/CMakeLists.txt
|
||||||
|
+++ b/tools/clang-format/CMakeLists.txt
|
||||||
|
@@ -21,20 +21,20 @@ if( LLVM_LIB_FUZZING_ENGINE OR LLVM_USE_SANITIZE_COVERAGE )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
install(PROGRAMS clang-format-bbedit.applescript
|
||||||
|
- DESTINATION share/clang
|
||||||
|
+ DESTINATION ${CMAKE_INSTALL_DATADIR}/clang
|
||||||
|
COMPONENT clang-format)
|
||||||
|
install(PROGRAMS clang-format-diff.py
|
||||||
|
- DESTINATION share/clang
|
||||||
|
+ DESTINATION ${CMAKE_INSTALL_DATADIR}/clang
|
||||||
|
COMPONENT clang-format)
|
||||||
|
install(PROGRAMS clang-format-sublime.py
|
||||||
|
- DESTINATION share/clang
|
||||||
|
+ DESTINATION ${CMAKE_INSTALL_DATADIR}/clang
|
||||||
|
COMPONENT clang-format)
|
||||||
|
install(PROGRAMS clang-format.el
|
||||||
|
- DESTINATION share/clang
|
||||||
|
+ DESTINATION ${CMAKE_INSTALL_DATADIR}/clang
|
||||||
|
COMPONENT clang-format)
|
||||||
|
install(PROGRAMS clang-format.py
|
||||||
|
- DESTINATION share/clang
|
||||||
|
+ DESTINATION ${CMAKE_INSTALL_DATADIR}/clang
|
||||||
|
COMPONENT clang-format)
|
||||||
|
install(PROGRAMS git-clang-format
|
||||||
|
- DESTINATION bin
|
||||||
|
+ DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
COMPONENT clang-format)
|
||||||
|
diff --git a/tools/clang-rename/CMakeLists.txt b/tools/clang-rename/CMakeLists.txt
|
||||||
|
index cda8e29ec5b1..0134d8ccd70b 100644
|
||||||
|
--- a/tools/clang-rename/CMakeLists.txt
|
||||||
|
+++ b/tools/clang-rename/CMakeLists.txt
|
||||||
|
@@ -19,8 +19,8 @@ clang_target_link_libraries(clang-rename
|
||||||
|
)
|
||||||
|
|
||||||
|
install(PROGRAMS clang-rename.py
|
||||||
|
- DESTINATION share/clang
|
||||||
|
+ DESTINATION ${CMAKE_INSTALL_DATADIR}/clang
|
||||||
|
COMPONENT clang-rename)
|
||||||
|
install(PROGRAMS clang-rename.el
|
||||||
|
- DESTINATION share/clang
|
||||||
|
+ DESTINATION ${CMAKE_INSTALL_DATADIR}/clang
|
||||||
|
COMPONENT clang-rename)
|
||||||
|
diff --git a/tools/libclang/CMakeLists.txt b/tools/libclang/CMakeLists.txt
|
||||||
|
index 5cd9ac5cddc1..a197676fedbd 100644
|
||||||
|
--- a/tools/libclang/CMakeLists.txt
|
||||||
|
+++ b/tools/libclang/CMakeLists.txt
|
||||||
|
@@ -165,7 +165,7 @@ endif()
|
||||||
|
if(INTERNAL_INSTALL_PREFIX)
|
||||||
|
set(LIBCLANG_HEADERS_INSTALL_DESTINATION "${INTERNAL_INSTALL_PREFIX}/include")
|
||||||
|
else()
|
||||||
|
- set(LIBCLANG_HEADERS_INSTALL_DESTINATION include)
|
||||||
|
+ set(LIBCLANG_HEADERS_INSTALL_DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
install(DIRECTORY ../../include/clang-c
|
||||||
|
@@ -196,7 +196,7 @@ foreach(PythonVersion ${CLANG_PYTHON_BINDINGS_VERSIONS})
|
||||||
|
COMPONENT
|
||||||
|
libclang-python-bindings
|
||||||
|
DESTINATION
|
||||||
|
- "lib${LLVM_LIBDIR_SUFFIX}/python${PythonVersion}/site-packages")
|
||||||
|
+ "${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}/python${PythonVersion}/site-packages")
|
||||||
|
endforeach()
|
||||||
|
if(NOT LLVM_ENABLE_IDE)
|
||||||
|
add_custom_target(libclang-python-bindings)
|
||||||
|
diff --git a/tools/scan-build/CMakeLists.txt b/tools/scan-build/CMakeLists.txt
|
||||||
|
index ec0702d76f18..d25d982f51da 100644
|
||||||
|
--- a/tools/scan-build/CMakeLists.txt
|
||||||
|
+++ b/tools/scan-build/CMakeLists.txt
|
||||||
|
@@ -47,7 +47,7 @@ if(CLANG_INSTALL_SCANBUILD)
|
||||||
|
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/bin/${BinFile})
|
||||||
|
list(APPEND Depends ${CMAKE_BINARY_DIR}/bin/${BinFile})
|
||||||
|
install(PROGRAMS bin/${BinFile}
|
||||||
|
- DESTINATION bin
|
||||||
|
+ DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
COMPONENT scan-build)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
@@ -61,7 +61,7 @@ if(CLANG_INSTALL_SCANBUILD)
|
||||||
|
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/libexec/${LibexecFile})
|
||||||
|
list(APPEND Depends ${CMAKE_BINARY_DIR}/libexec/${LibexecFile})
|
||||||
|
install(PROGRAMS libexec/${LibexecFile}
|
||||||
|
- DESTINATION libexec
|
||||||
|
+ DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}
|
||||||
|
COMPONENT scan-build)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
@@ -89,7 +89,7 @@ if(CLANG_INSTALL_SCANBUILD)
|
||||||
|
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/share/scan-build/${ShareFile})
|
||||||
|
list(APPEND Depends ${CMAKE_BINARY_DIR}/share/scan-build/${ShareFile})
|
||||||
|
install(FILES share/scan-build/${ShareFile}
|
||||||
|
- DESTINATION share/scan-build
|
||||||
|
+ DESTINATION ${CMAKE_INSTALL_DATADIR}/scan-build
|
||||||
|
COMPONENT scan-build)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
diff --git a/tools/scan-view/CMakeLists.txt b/tools/scan-view/CMakeLists.txt
|
||||||
|
index 22edb974bac7..9f140a9a4538 100644
|
||||||
|
--- a/tools/scan-view/CMakeLists.txt
|
||||||
|
+++ b/tools/scan-view/CMakeLists.txt
|
||||||
|
@@ -22,7 +22,7 @@ if(CLANG_INSTALL_SCANVIEW)
|
||||||
|
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/bin/${BinFile})
|
||||||
|
list(APPEND Depends ${CMAKE_BINARY_DIR}/bin/${BinFile})
|
||||||
|
install(PROGRAMS bin/${BinFile}
|
||||||
|
- DESTINATION bin
|
||||||
|
+ DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
COMPONENT scan-view)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
@@ -36,7 +36,7 @@ if(CLANG_INSTALL_SCANVIEW)
|
||||||
|
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/share/${ShareFile})
|
||||||
|
list(APPEND Depends ${CMAKE_BINARY_DIR}/share/scan-view/${ShareFile})
|
||||||
|
install(FILES share/${ShareFile}
|
||||||
|
- DESTINATION share/scan-view
|
||||||
|
+ DESTINATION ${CMAKE_INSTALL_DATADIR}/scan-view
|
||||||
|
COMPONENT scan-view)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
diff --git a/utils/hmaptool/CMakeLists.txt b/utils/hmaptool/CMakeLists.txt
|
||||||
|
index 62f2de0cb15c..6aa66825b6ec 100644
|
||||||
|
--- a/utils/hmaptool/CMakeLists.txt
|
||||||
|
+++ b/utils/hmaptool/CMakeLists.txt
|
||||||
|
@@ -10,7 +10,7 @@ add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/${CLANG_HM
|
||||||
|
|
||||||
|
list(APPEND Depends ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/${CLANG_HMAPTOOL})
|
||||||
|
install(PROGRAMS ${CLANG_HMAPTOOL}
|
||||||
|
- DESTINATION bin
|
||||||
|
+ DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
COMPONENT hmaptool)
|
||||||
|
|
||||||
|
add_custom_target(hmaptool ALL DEPENDS ${Depends})
|
|
@ -0,0 +1,28 @@
|
||||||
|
From 4add81bba40dcec62c4ea4481be8e35ac53e89d8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Will Dietz <w@wdtz.org>
|
||||||
|
Date: Thu, 18 May 2017 11:56:12 -0500
|
||||||
|
Subject: [PATCH] "purity" patch for 5.0
|
||||||
|
|
||||||
|
---
|
||||||
|
lib/Driver/ToolChains/Gnu.cpp | 7 -------
|
||||||
|
1 file changed, 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/lib/Driver/ToolChains/Gnu.cpp b/lib/Driver/ToolChains/Gnu.cpp
|
||||||
|
index fe3c0191bb..c6a482bece 100644
|
||||||
|
--- a/lib/Driver/ToolChains/Gnu.cpp
|
||||||
|
+++ b/lib/Driver/ToolChains/Gnu.cpp
|
||||||
|
@@ -487,12 +487,6 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
||||||
|
if (!IsStatic) {
|
||||||
|
if (Args.hasArg(options::OPT_rdynamic))
|
||||||
|
CmdArgs.push_back("-export-dynamic");
|
||||||
|
-
|
||||||
|
- if (!Args.hasArg(options::OPT_shared) && !IsStaticPIE) {
|
||||||
|
- CmdArgs.push_back("-dynamic-linker");
|
||||||
|
- CmdArgs.push_back(Args.MakeArgString(Twine(D.DyldPrefix) +
|
||||||
|
- ToolChain.getDynamicLinker(Args)));
|
||||||
|
- }
|
||||||
|
}
|
||||||
|
|
||||||
|
CmdArgs.push_back("-o");
|
||||||
|
--
|
||||||
|
2.11.0
|
|
@ -0,0 +1,296 @@
|
||||||
|
{ lowPrio, newScope, pkgs, lib, stdenv, cmake
|
||||||
|
, gccForLibs, preLibcCrossHeaders
|
||||||
|
, libxml2, python3, isl, fetchurl, overrideCC, wrapCCWith, wrapBintoolsWith
|
||||||
|
, buildLlvmTools # tools, but from the previous stage, for cross
|
||||||
|
, targetLlvmLibraries # libraries, but from the next stage, for cross
|
||||||
|
, targetLlvm
|
||||||
|
# This is the default binutils, but with *this* version of LLD rather
|
||||||
|
# than the default LLVM version's, if LLD is the choice. We use these for
|
||||||
|
# the `useLLVM` bootstrapping below.
|
||||||
|
, bootBintoolsNoLibc ?
|
||||||
|
if stdenv.targetPlatform.linker == "lld"
|
||||||
|
then null
|
||||||
|
else pkgs.bintoolsNoLibc
|
||||||
|
, bootBintools ?
|
||||||
|
if stdenv.targetPlatform.linker == "lld"
|
||||||
|
then null
|
||||||
|
else pkgs.bintools
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
release_version = "11.1.0";
|
||||||
|
candidate = ""; # empty or "rcN"
|
||||||
|
dash-candidate = lib.optionalString (candidate != "") "-${candidate}";
|
||||||
|
version = "${release_version}${dash-candidate}"; # differentiating these (variables) is important for RCs
|
||||||
|
targetConfig = stdenv.targetPlatform.config;
|
||||||
|
|
||||||
|
fetch = name: sha256: fetchurl {
|
||||||
|
url = "https://github.com/llvm/llvm-project/releases/download/llvmorg-${version}/${name}-${release_version}${candidate}.src.tar.xz";
|
||||||
|
inherit sha256;
|
||||||
|
};
|
||||||
|
|
||||||
|
clang-tools-extra_src = fetch "clang-tools-extra" "18n1w1hkv931xzq02b34wglbv6zd6sd0r5kb8piwvag7klj7qw3n";
|
||||||
|
|
||||||
|
llvm_meta = {
|
||||||
|
license = lib.licenses.ncsa;
|
||||||
|
|
||||||
|
# See llvm/cmake/config-ix.cmake.
|
||||||
|
platforms =
|
||||||
|
lib.platforms.aarch64 ++
|
||||||
|
lib.platforms.arm ++
|
||||||
|
lib.platforms.mips ++
|
||||||
|
lib.platforms.riscv ++
|
||||||
|
lib.platforms.wasi ++
|
||||||
|
lib.platforms.x86;
|
||||||
|
};
|
||||||
|
|
||||||
|
tools = lib.makeExtensible (tools: let
|
||||||
|
callPackage = newScope (tools // { inherit stdenv cmake libxml2 python3 isl release_version version fetch buildLlvmTools; });
|
||||||
|
mkExtraBuildCommands0 = cc: ''
|
||||||
|
rsrc="$out/resource-root"
|
||||||
|
mkdir "$rsrc"
|
||||||
|
ln -s "${cc.lib}/lib/clang/${release_version}/include" "$rsrc"
|
||||||
|
echo "-resource-dir=$rsrc" >> $out/nix-support/cc-cflags
|
||||||
|
'';
|
||||||
|
mkExtraBuildCommands = cc: mkExtraBuildCommands0 cc + ''
|
||||||
|
ln -s "${targetLlvmLibraries.compiler-rt.out}/lib" "$rsrc/lib"
|
||||||
|
ln -s "${targetLlvmLibraries.compiler-rt.out}/share" "$rsrc/share"
|
||||||
|
'';
|
||||||
|
|
||||||
|
bintoolsNoLibc' =
|
||||||
|
if bootBintoolsNoLibc == null
|
||||||
|
then tools.bintoolsNoLibc
|
||||||
|
else bootBintoolsNoLibc;
|
||||||
|
bintools' =
|
||||||
|
if bootBintools == null
|
||||||
|
then tools.bintools
|
||||||
|
else bootBintools;
|
||||||
|
|
||||||
|
in {
|
||||||
|
|
||||||
|
libllvm = callPackage ./llvm {
|
||||||
|
inherit llvm_meta;
|
||||||
|
};
|
||||||
|
|
||||||
|
# `llvm` historically had the binaries. When choosing an output explicitly,
|
||||||
|
# we need to reintroduce `outputSpecified` to get the expected behavior e.g. of lib.get*
|
||||||
|
llvm = tools.libllvm;
|
||||||
|
|
||||||
|
libllvm-polly = callPackage ./llvm {
|
||||||
|
inherit llvm_meta;
|
||||||
|
enablePolly = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
llvm-polly = tools.libllvm-polly.lib // { outputSpecified = false; };
|
||||||
|
|
||||||
|
libclang = callPackage ./clang {
|
||||||
|
inherit clang-tools-extra_src llvm_meta;
|
||||||
|
};
|
||||||
|
|
||||||
|
clang-unwrapped = tools.libclang;
|
||||||
|
|
||||||
|
clang-polly-unwrapped = callPackage ./clang {
|
||||||
|
inherit llvm_meta;
|
||||||
|
inherit clang-tools-extra_src;
|
||||||
|
libllvm = tools.libllvm-polly;
|
||||||
|
enablePolly = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
llvm-manpages = lowPrio (tools.libllvm.override {
|
||||||
|
enableManpages = true;
|
||||||
|
python3 = pkgs.python3; # don't use python-boot
|
||||||
|
});
|
||||||
|
|
||||||
|
clang-manpages = lowPrio (tools.libclang.override {
|
||||||
|
enableManpages = true;
|
||||||
|
python3 = pkgs.python3; # don't use python-boot
|
||||||
|
});
|
||||||
|
|
||||||
|
# disabled until recommonmark supports sphinx 3
|
||||||
|
# lldb-manpages = lowPrio (tools.lldb.override {
|
||||||
|
# enableManpages = true;
|
||||||
|
# python3 = pkgs.python3; # don't use python-boot
|
||||||
|
# });
|
||||||
|
|
||||||
|
# pick clang appropriate for package set we are targeting
|
||||||
|
clang =
|
||||||
|
/**/ if stdenv.targetPlatform.libc == null then tools.clangNoLibc
|
||||||
|
else if stdenv.targetPlatform.useLLVM or false then tools.clangUseLLVM
|
||||||
|
else if (pkgs.targetPackages.stdenv or stdenv).cc.isGNU then tools.libstdcxxClang
|
||||||
|
else tools.libcxxClang;
|
||||||
|
|
||||||
|
libstdcxxClang = wrapCCWith rec {
|
||||||
|
cc = tools.clang-unwrapped;
|
||||||
|
# libstdcxx is taken from gcc in an ad-hoc way in cc-wrapper.
|
||||||
|
libcxx = null;
|
||||||
|
extraPackages = [
|
||||||
|
targetLlvmLibraries.compiler-rt
|
||||||
|
];
|
||||||
|
extraBuildCommands = mkExtraBuildCommands cc;
|
||||||
|
};
|
||||||
|
|
||||||
|
libcxxClang = wrapCCWith rec {
|
||||||
|
cc = tools.clang-unwrapped;
|
||||||
|
libcxx = targetLlvmLibraries.libcxx;
|
||||||
|
extraPackages = [
|
||||||
|
libcxx.cxxabi
|
||||||
|
targetLlvmLibraries.compiler-rt
|
||||||
|
];
|
||||||
|
extraBuildCommands = mkExtraBuildCommands cc;
|
||||||
|
};
|
||||||
|
|
||||||
|
lld = callPackage ./lld {
|
||||||
|
inherit llvm_meta;
|
||||||
|
};
|
||||||
|
|
||||||
|
lldb = callPackage ../common/lldb.nix {
|
||||||
|
src = fetch "lldb" "1vlyg015dyng43xqb8cg2l6r9ix8klibxsajazbfnckdnh54hwxj";
|
||||||
|
patches = [
|
||||||
|
./lldb/procfs.patch
|
||||||
|
./lldb/gnu-install-dirs.patch
|
||||||
|
];
|
||||||
|
inherit llvm_meta;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Below, is the LLVM bootstrapping logic. It handles building a
|
||||||
|
# fully LLVM toolchain from scratch. No GCC toolchain should be
|
||||||
|
# pulled in. As a consequence, it is very quick to build different
|
||||||
|
# targets provided by LLVM and we can also build for what GCC
|
||||||
|
# doesn’t support like LLVM. Probably we should move to some other
|
||||||
|
# file.
|
||||||
|
|
||||||
|
bintools-unwrapped = callPackage ../common/bintools.nix { };
|
||||||
|
|
||||||
|
bintoolsNoLibc = wrapBintoolsWith {
|
||||||
|
bintools = tools.bintools-unwrapped;
|
||||||
|
libc = preLibcCrossHeaders;
|
||||||
|
};
|
||||||
|
|
||||||
|
bintools = wrapBintoolsWith {
|
||||||
|
bintools = tools.bintools-unwrapped;
|
||||||
|
};
|
||||||
|
|
||||||
|
clangUseLLVM = wrapCCWith rec {
|
||||||
|
cc = tools.clang-unwrapped;
|
||||||
|
libcxx = targetLlvmLibraries.libcxx;
|
||||||
|
bintools = bintools';
|
||||||
|
extraPackages = [
|
||||||
|
libcxx.cxxabi
|
||||||
|
targetLlvmLibraries.compiler-rt
|
||||||
|
] ++ lib.optionals (!stdenv.targetPlatform.isWasm) [
|
||||||
|
targetLlvmLibraries.libunwind
|
||||||
|
];
|
||||||
|
extraBuildCommands = ''
|
||||||
|
echo "-rtlib=compiler-rt -Wno-unused-command-line-argument" >> $out/nix-support/cc-cflags
|
||||||
|
echo "-B${targetLlvmLibraries.compiler-rt}/lib" >> $out/nix-support/cc-cflags
|
||||||
|
'' + lib.optionalString (!stdenv.targetPlatform.isWasm) ''
|
||||||
|
echo "--unwindlib=libunwind" >> $out/nix-support/cc-cflags
|
||||||
|
'' + lib.optionalString (!stdenv.targetPlatform.isWasm && stdenv.targetPlatform.useLLVM or false) ''
|
||||||
|
echo "-lunwind" >> $out/nix-support/cc-ldflags
|
||||||
|
'' + lib.optionalString stdenv.targetPlatform.isWasm ''
|
||||||
|
echo "-fno-exceptions" >> $out/nix-support/cc-cflags
|
||||||
|
'' + mkExtraBuildCommands cc;
|
||||||
|
};
|
||||||
|
|
||||||
|
clangNoLibcxx = wrapCCWith rec {
|
||||||
|
cc = tools.clang-unwrapped;
|
||||||
|
libcxx = null;
|
||||||
|
bintools = bintools';
|
||||||
|
extraPackages = [
|
||||||
|
targetLlvmLibraries.compiler-rt
|
||||||
|
];
|
||||||
|
extraBuildCommands = ''
|
||||||
|
echo "-rtlib=compiler-rt" >> $out/nix-support/cc-cflags
|
||||||
|
echo "-B${targetLlvmLibraries.compiler-rt}/lib" >> $out/nix-support/cc-cflags
|
||||||
|
echo "-nostdlib++" >> $out/nix-support/cc-cflags
|
||||||
|
'' + mkExtraBuildCommands cc;
|
||||||
|
};
|
||||||
|
|
||||||
|
clangNoLibc = wrapCCWith rec {
|
||||||
|
cc = tools.clang-unwrapped;
|
||||||
|
libcxx = null;
|
||||||
|
bintools = bintoolsNoLibc';
|
||||||
|
extraPackages = [
|
||||||
|
targetLlvmLibraries.compiler-rt
|
||||||
|
];
|
||||||
|
extraBuildCommands = ''
|
||||||
|
echo "-rtlib=compiler-rt" >> $out/nix-support/cc-cflags
|
||||||
|
echo "-B${targetLlvmLibraries.compiler-rt}/lib" >> $out/nix-support/cc-cflags
|
||||||
|
'' + mkExtraBuildCommands cc;
|
||||||
|
};
|
||||||
|
|
||||||
|
clangNoCompilerRt = wrapCCWith rec {
|
||||||
|
cc = tools.clang-unwrapped;
|
||||||
|
libcxx = null;
|
||||||
|
bintools = bintoolsNoLibc';
|
||||||
|
extraPackages = [ ];
|
||||||
|
extraBuildCommands = ''
|
||||||
|
echo "-nostartfiles" >> $out/nix-support/cc-cflags
|
||||||
|
'' + mkExtraBuildCommands0 cc;
|
||||||
|
};
|
||||||
|
|
||||||
|
clangNoCompilerRtWithLibc = wrapCCWith rec {
|
||||||
|
cc = tools.clang-unwrapped;
|
||||||
|
libcxx = null;
|
||||||
|
bintools = bintools';
|
||||||
|
extraPackages = [ ];
|
||||||
|
extraBuildCommands = mkExtraBuildCommands0 cc;
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
libraries = lib.makeExtensible (libraries: let
|
||||||
|
callPackage = newScope (libraries // buildLlvmTools // { inherit stdenv cmake libxml2 python3 isl release_version version fetch; });
|
||||||
|
in {
|
||||||
|
|
||||||
|
compiler-rt-libc = callPackage ./compiler-rt {
|
||||||
|
inherit llvm_meta;
|
||||||
|
stdenv = if (stdenv.hostPlatform.useLLVM or false) || (stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isAarch64) || (stdenv.hostPlatform.isRiscV && stdenv.hostPlatform.is32bit)
|
||||||
|
then overrideCC stdenv buildLlvmTools.clangNoCompilerRtWithLibc
|
||||||
|
else stdenv;
|
||||||
|
};
|
||||||
|
|
||||||
|
compiler-rt-no-libc = callPackage ./compiler-rt {
|
||||||
|
inherit llvm_meta;
|
||||||
|
stdenv = if (stdenv.hostPlatform.useLLVM or false) || (stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isAarch64)
|
||||||
|
then overrideCC stdenv buildLlvmTools.clangNoCompilerRt
|
||||||
|
else stdenv;
|
||||||
|
};
|
||||||
|
|
||||||
|
# N.B. condition is safe because without useLLVM both are the same.
|
||||||
|
compiler-rt = if stdenv.hostPlatform.isAndroid || (stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isAarch64) || (stdenv.hostPlatform.libc == "newlib")
|
||||||
|
then libraries.compiler-rt-libc
|
||||||
|
else libraries.compiler-rt-no-libc;
|
||||||
|
|
||||||
|
stdenv = overrideCC stdenv buildLlvmTools.clang;
|
||||||
|
|
||||||
|
libcxxStdenv = overrideCC stdenv buildLlvmTools.libcxxClang;
|
||||||
|
|
||||||
|
libcxx = callPackage ./libcxx {
|
||||||
|
inherit llvm_meta;
|
||||||
|
stdenv = if (stdenv.hostPlatform.useLLVM or false) || (stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isAarch64)
|
||||||
|
then overrideCC stdenv buildLlvmTools.clangNoLibcxx
|
||||||
|
else stdenv;
|
||||||
|
};
|
||||||
|
|
||||||
|
libcxxabi = callPackage ./libcxxabi {
|
||||||
|
inherit llvm_meta;
|
||||||
|
stdenv = if (stdenv.hostPlatform.useLLVM or false) || (stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isAarch64)
|
||||||
|
then overrideCC stdenv buildLlvmTools.clangNoLibcxx
|
||||||
|
else stdenv;
|
||||||
|
};
|
||||||
|
|
||||||
|
libunwind = callPackage ./libunwind {
|
||||||
|
inherit llvm_meta;
|
||||||
|
stdenv = if (stdenv.hostPlatform.useLLVM or false) || (stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isAarch64)
|
||||||
|
then overrideCC stdenv buildLlvmTools.clangNoLibcxx
|
||||||
|
else stdenv;
|
||||||
|
};
|
||||||
|
|
||||||
|
openmp = callPackage ./openmp {
|
||||||
|
inherit llvm_meta targetLlvm;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
noExtend = extensible: builtins.removeAttrs extensible [ "extend" ];
|
||||||
|
|
||||||
|
in { inherit tools libraries release_version; } // (noExtend libraries) // (noExtend tools)
|
|
@ -0,0 +1,363 @@
|
||||||
|
{ lib, stdenv, llvm_meta
|
||||||
|
, pkgsBuildBuild
|
||||||
|
, fetch
|
||||||
|
, fetchpatch
|
||||||
|
, cmake
|
||||||
|
, python3
|
||||||
|
, libffi
|
||||||
|
, enableGoldPlugin ? false
|
||||||
|
, libbfd
|
||||||
|
, libpfm
|
||||||
|
, libxml2
|
||||||
|
, ncurses
|
||||||
|
, version
|
||||||
|
, release_version
|
||||||
|
, zlib
|
||||||
|
, buildLlvmTools
|
||||||
|
, debugVersion ? false
|
||||||
|
, doCheck ? stdenv.isLinux && (!stdenv.isx86_32) && (!stdenv.hostPlatform.isMusl) && (!stdenv.hostPlatform.isRiscV)
|
||||||
|
&& (stdenv.hostPlatform == stdenv.buildPlatform)
|
||||||
|
, enableManpages ? false
|
||||||
|
, enableSharedLibraries ? !stdenv.hostPlatform.isStatic
|
||||||
|
# broken for Ampere eMAG 8180 (c2.large.arm on Packet) #56245
|
||||||
|
# broken for the armv7l builder
|
||||||
|
, enablePFM ? stdenv.isLinux && !stdenv.hostPlatform.isAarch
|
||||||
|
, enablePolly ? false # TODO should be on by default
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (lib) optional optionals optionalString;
|
||||||
|
|
||||||
|
# Used when creating a version-suffixed symlink of libLLVM.dylib
|
||||||
|
shortVersion = with lib;
|
||||||
|
concatStringsSep "." (take 1 (splitString "." release_version));
|
||||||
|
|
||||||
|
# Ordinarily we would just the `doCheck` and `checkDeps` functionality
|
||||||
|
# `mkDerivation` gives us to manage our test dependencies (instead of breaking
|
||||||
|
# out `doCheck` as a package level attribute).
|
||||||
|
#
|
||||||
|
# Unfortunately `lit` does not forward `$PYTHONPATH` to children processes, in
|
||||||
|
# particular the children it uses to do feature detection.
|
||||||
|
#
|
||||||
|
# This means that python deps we add to `checkDeps` (which the python
|
||||||
|
# interpreter is made aware of via `$PYTHONPATH` – populated by the python
|
||||||
|
# setup hook) are not picked up by `lit` which causes it to skip tests.
|
||||||
|
#
|
||||||
|
# Adding `python3.withPackages (ps: [ ... ])` to `checkDeps` also doesn't work
|
||||||
|
# because this package is shadowed in `$PATH` by the regular `python3`
|
||||||
|
# package.
|
||||||
|
#
|
||||||
|
# So, we "manually" assemble one python derivation for the package to depend
|
||||||
|
# on, taking into account whether checks are enabled or not:
|
||||||
|
python = if doCheck then
|
||||||
|
let
|
||||||
|
checkDeps = ps: with ps; [ psutil ];
|
||||||
|
in python3.withPackages checkDeps
|
||||||
|
else python3;
|
||||||
|
|
||||||
|
in stdenv.mkDerivation (rec {
|
||||||
|
pname = "llvm";
|
||||||
|
inherit version;
|
||||||
|
|
||||||
|
src = fetch pname "199yq3a214avcbi4kk2q0ajriifkvsr0l2dkx3a666m033ihi1ff";
|
||||||
|
polly_src = fetch "polly" "031r23ijhx7v93a5n33m2nc0x9xyqmx0d8xg80z7q971p6qd63sq";
|
||||||
|
|
||||||
|
unpackPhase = ''
|
||||||
|
unpackFile $src
|
||||||
|
mv llvm-${release_version}* llvm
|
||||||
|
sourceRoot=$PWD/llvm
|
||||||
|
'' + optionalString enablePolly ''
|
||||||
|
unpackFile $polly_src
|
||||||
|
mv polly-* $sourceRoot/tools/polly
|
||||||
|
'';
|
||||||
|
|
||||||
|
outputs = [ "out" "lib" "dev" "python" ];
|
||||||
|
|
||||||
|
nativeBuildInputs = [ cmake python ]
|
||||||
|
++ optionals enableManpages [ python3.pkgs.sphinx python3.pkgs.recommonmark ];
|
||||||
|
|
||||||
|
buildInputs = [ libxml2 libffi ]
|
||||||
|
++ optional enablePFM libpfm; # exegesis
|
||||||
|
|
||||||
|
propagatedBuildInputs = [ ncurses zlib ];
|
||||||
|
|
||||||
|
patches = [
|
||||||
|
# When cross-compiling we configure llvm-config-native with an approximation
|
||||||
|
# of the flags used for the normal LLVM build. To avoid the need for building
|
||||||
|
# a native libLLVM.so (which would fail) we force llvm-config to be linked
|
||||||
|
# statically against the necessary LLVM components always.
|
||||||
|
../../llvm-config-link-static.patch
|
||||||
|
|
||||||
|
./gnu-install-dirs.patch
|
||||||
|
# On older CPUs (e.g. Hydra/wendy) we'd be getting an error in this test.
|
||||||
|
(fetchpatch {
|
||||||
|
name = "uops-CMOV16rm-noreg.diff";
|
||||||
|
url = "https://github.com/llvm/llvm-project/commit/9e9f991ac033.diff";
|
||||||
|
sha256 = "sha256:12s8vr6ibri8b48h2z38f3afhwam10arfiqfy4yg37bmc054p5hi";
|
||||||
|
stripLen = 1;
|
||||||
|
})
|
||||||
|
# gcc-11 compat upstream patch
|
||||||
|
(fetchpatch {
|
||||||
|
url = "https://github.com/llvm/llvm-project/commit/b498303066a63a203d24f739b2d2e0e56dca70d1.patch";
|
||||||
|
sha256 = "sha256:0nh123kld0dgz2h941lng331dkj3wbm5lfxm375k1f569gv83hlk";
|
||||||
|
stripLen = 1;
|
||||||
|
})
|
||||||
|
|
||||||
|
# Fix invalid std::string(nullptr) for GCC 12
|
||||||
|
(fetchpatch {
|
||||||
|
name = "nvptx-gcc-12.patch";
|
||||||
|
url = "https://github.com/llvm/llvm-project/commit/99e64623ec9b31def9375753491cc6093c831809.patch";
|
||||||
|
sha256 = "0zjfjgavqzi2ypqwqnlvy6flyvdz8hi1anwv0ybwnm2zqixg7za3";
|
||||||
|
stripLen = 1;
|
||||||
|
})
|
||||||
|
(fetchpatch {
|
||||||
|
name = "dfaemitter-gcc-12.patch";
|
||||||
|
url = "https://github.com/llvm/llvm-project/commit/0841916e87a39e3c223c986e8da31e4a9a1432e3.patch";
|
||||||
|
sha256 = "1kckghvsngs51mqm82asy0s9vr19h8aqbw43a0w44mccqw6bzrwf";
|
||||||
|
stripLen = 1;
|
||||||
|
})
|
||||||
|
|
||||||
|
# Fix musl build.
|
||||||
|
(fetchpatch {
|
||||||
|
url = "https://github.com/llvm/llvm-project/commit/5cd554303ead0f8891eee3cd6d25cb07f5a7bf67.patch";
|
||||||
|
relative = "llvm";
|
||||||
|
hash = "sha256-XPbvNJ45SzjMGlNUgt/IgEvM2dHQpDOe6woUJY+nUYA=";
|
||||||
|
})
|
||||||
|
|
||||||
|
# Backport gcc-13 fixes with missing includes.
|
||||||
|
(fetchpatch {
|
||||||
|
name = "signals-gcc-13.patch";
|
||||||
|
url = "https://github.com/llvm/llvm-project/commit/ff1681ddb303223973653f7f5f3f3435b48a1983.patch";
|
||||||
|
hash = "sha256-CXwYxQezTq5vdmc8Yn88BUAEly6YZ5VEIA6X3y5NNOs=";
|
||||||
|
stripLen = 1;
|
||||||
|
})
|
||||||
|
(fetchpatch {
|
||||||
|
name = "base64-gcc-13.patch";
|
||||||
|
url = "https://github.com/llvm/llvm-project/commit/5e9be93566f39ee6cecd579401e453eccfbe81e5.patch";
|
||||||
|
hash = "sha256-PAwrVrvffPd7tphpwCkYiz+67szPRzRB2TXBvKfzQ7U=";
|
||||||
|
stripLen = 1;
|
||||||
|
})
|
||||||
|
] ++ lib.optional enablePolly ./gnu-install-dirs-polly.patch;
|
||||||
|
|
||||||
|
postPatch = optionalString stdenv.isDarwin ''
|
||||||
|
substituteInPlace cmake/modules/AddLLVM.cmake \
|
||||||
|
--replace 'set(_install_name_dir INSTALL_NAME_DIR "@rpath")' "set(_install_name_dir)" \
|
||||||
|
--replace 'set(_install_rpath "@loader_path/../''${CMAKE_INSTALL_LIBDIR}''${LLVM_LIBDIR_SUFFIX}" ''${extra_libdir})' ""
|
||||||
|
'' + ''
|
||||||
|
# FileSystem permissions tests fail with various special bits
|
||||||
|
substituteInPlace unittests/Support/CMakeLists.txt \
|
||||||
|
--replace "Path.cpp" ""
|
||||||
|
rm unittests/Support/Path.cpp
|
||||||
|
'' + optionalString stdenv.hostPlatform.isMusl ''
|
||||||
|
patch -p1 -i ${../../TLI-musl.patch}
|
||||||
|
substituteInPlace unittests/Support/CMakeLists.txt \
|
||||||
|
--replace "add_subdirectory(DynamicLibrary)" ""
|
||||||
|
rm unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp
|
||||||
|
# valgrind unhappy with musl or glibc, but fails w/musl only
|
||||||
|
rm test/CodeGen/AArch64/wineh4.mir
|
||||||
|
'' + optionalString stdenv.hostPlatform.isAarch32 ''
|
||||||
|
# skip failing X86 test cases on 32-bit ARM
|
||||||
|
rm test/DebugInfo/X86/convert-debugloc.ll
|
||||||
|
rm test/DebugInfo/X86/convert-inlined.ll
|
||||||
|
rm test/DebugInfo/X86/convert-linked.ll
|
||||||
|
rm test/tools/dsymutil/X86/op-convert.test
|
||||||
|
rm test/tools/gold/X86/split-dwarf.ll
|
||||||
|
rm test/tools/llvm-readobj/ELF/dependent-libraries.test
|
||||||
|
'' + optionalString (stdenv.hostPlatform.system == "armv6l-linux") ''
|
||||||
|
# Seems to require certain floating point hardware (NEON?)
|
||||||
|
rm test/ExecutionEngine/frem.ll
|
||||||
|
'' + ''
|
||||||
|
patchShebangs test/BugPoint/compile-custom.ll.py
|
||||||
|
'' + ''
|
||||||
|
# Tweak tests to ignore namespace part of type to support
|
||||||
|
# gcc-12: https://gcc.gnu.org/PR103598.
|
||||||
|
# The change below mangles strings like:
|
||||||
|
# CHECK-NEXT: Starting llvm::Function pass manager run.
|
||||||
|
# to:
|
||||||
|
# CHECK-NEXT: Starting {{.*}}Function pass manager run.
|
||||||
|
for f in \
|
||||||
|
test/Other/new-pass-manager.ll \
|
||||||
|
test/Other/new-pm-defaults.ll \
|
||||||
|
test/Other/new-pm-lto-defaults.ll \
|
||||||
|
test/Other/new-pm-thinlto-defaults.ll \
|
||||||
|
test/Other/pass-pipeline-parsing.ll \
|
||||||
|
test/Transforms/Inline/cgscc-incremental-invalidate.ll \
|
||||||
|
test/Transforms/Inline/clear-analyses.ll \
|
||||||
|
test/Transforms/LoopUnroll/unroll-loop-invalidation.ll \
|
||||||
|
test/Transforms/SCCP/ipsccp-preserve-analysis.ll \
|
||||||
|
test/Transforms/SCCP/preserve-analysis.ll \
|
||||||
|
test/Transforms/SROA/dead-inst.ll \
|
||||||
|
test/tools/gold/X86/new-pm.ll \
|
||||||
|
; do
|
||||||
|
echo "PATCH: $f"
|
||||||
|
substituteInPlace $f \
|
||||||
|
--replace 'Starting llvm::' 'Starting {{.*}}' \
|
||||||
|
--replace 'Finished llvm::' 'Finished {{.*}}'
|
||||||
|
done
|
||||||
|
'';
|
||||||
|
|
||||||
|
preConfigure = ''
|
||||||
|
# Workaround for configure flags that need to have spaces
|
||||||
|
cmakeFlagsArray+=(
|
||||||
|
-DLLVM_LIT_ARGS='-svj''${NIX_BUILD_CORES} --no-progress-bar'
|
||||||
|
)
|
||||||
|
'';
|
||||||
|
|
||||||
|
# hacky fix: created binaries need to be run before installation
|
||||||
|
preBuild = ''
|
||||||
|
mkdir -p $out/
|
||||||
|
ln -sv $PWD/lib $out
|
||||||
|
'';
|
||||||
|
|
||||||
|
# E.g. mesa.drivers use the build-id as a cache key (see #93946):
|
||||||
|
LDFLAGS = optionalString (enableSharedLibraries && !stdenv.isDarwin) "-Wl,--build-id=sha1";
|
||||||
|
|
||||||
|
cmakeBuildType = if debugVersion then "Debug" else "Release";
|
||||||
|
|
||||||
|
cmakeFlags = with stdenv; let
|
||||||
|
# These flags influence llvm-config's BuildVariables.inc in addition to the
|
||||||
|
# general build. We need to make sure these are also passed via
|
||||||
|
# CROSS_TOOLCHAIN_FLAGS_NATIVE when cross-compiling or llvm-config-native
|
||||||
|
# will return different results from the cross llvm-config.
|
||||||
|
#
|
||||||
|
# Some flags don't need to be repassed because LLVM already does so (like
|
||||||
|
# CMAKE_BUILD_TYPE), others are irrelevant to the result.
|
||||||
|
flagsForLlvmConfig = [
|
||||||
|
"-DLLVM_INSTALL_CMAKE_DIR=${placeholder "dev"}/lib/cmake/llvm/"
|
||||||
|
"-DLLVM_ENABLE_RTTI=ON"
|
||||||
|
] ++ optionals enableSharedLibraries [
|
||||||
|
"-DLLVM_LINK_LLVM_DYLIB=ON"
|
||||||
|
];
|
||||||
|
in flagsForLlvmConfig ++ [
|
||||||
|
"-DLLVM_INSTALL_UTILS=ON" # Needed by rustc
|
||||||
|
"-DLLVM_BUILD_TESTS=${if doCheck then "ON" else "OFF"}"
|
||||||
|
"-DLLVM_ENABLE_FFI=ON"
|
||||||
|
"-DLLVM_HOST_TRIPLE=${stdenv.hostPlatform.config}"
|
||||||
|
"-DLLVM_DEFAULT_TARGET_TRIPLE=${stdenv.hostPlatform.config}"
|
||||||
|
"-DLLVM_ENABLE_DUMP=ON"
|
||||||
|
] ++ optionals stdenv.hostPlatform.isStatic [
|
||||||
|
# Disables building of shared libs, -fPIC is still injected by cc-wrapper
|
||||||
|
"-DLLVM_ENABLE_PIC=OFF"
|
||||||
|
"-DLLVM_BUILD_STATIC=ON"
|
||||||
|
# libxml2 needs to be disabled because the LLVM build system ignores its .la
|
||||||
|
# file and doesn't link zlib as well.
|
||||||
|
# https://github.com/ClangBuiltLinux/tc-build/issues/150#issuecomment-845418812
|
||||||
|
"-DLLVM_ENABLE_LIBXML2=OFF"
|
||||||
|
# This is a Shared Library not tied to LLVM_ENABLE_PIC
|
||||||
|
"-DLLVM_TOOL_REMARKS_SHLIB_BUILD=OFF"
|
||||||
|
] ++ optionals enableManpages [
|
||||||
|
"-DLLVM_BUILD_DOCS=ON"
|
||||||
|
"-DLLVM_ENABLE_SPHINX=ON"
|
||||||
|
"-DSPHINX_OUTPUT_MAN=ON"
|
||||||
|
"-DSPHINX_OUTPUT_HTML=OFF"
|
||||||
|
"-DSPHINX_WARNINGS_AS_ERRORS=OFF"
|
||||||
|
] ++ optionals (enableGoldPlugin) [
|
||||||
|
"-DLLVM_BINUTILS_INCDIR=${libbfd.dev}/include"
|
||||||
|
] ++ optionals isDarwin [
|
||||||
|
"-DLLVM_ENABLE_LIBCXX=ON"
|
||||||
|
"-DCAN_TARGET_i386=false"
|
||||||
|
] ++ optionals (stdenv.hostPlatform != stdenv.buildPlatform) [
|
||||||
|
"-DCMAKE_CROSSCOMPILING=True"
|
||||||
|
"-DLLVM_TABLEGEN=${buildLlvmTools.llvm}/bin/llvm-tblgen"
|
||||||
|
(
|
||||||
|
let
|
||||||
|
nativeCC = pkgsBuildBuild.targetPackages.stdenv.cc;
|
||||||
|
nativeBintools = nativeCC.bintools.bintools;
|
||||||
|
nativeToolchainFlags = [
|
||||||
|
"-DCMAKE_C_COMPILER=${nativeCC}/bin/${nativeCC.targetPrefix}cc"
|
||||||
|
"-DCMAKE_CXX_COMPILER=${nativeCC}/bin/${nativeCC.targetPrefix}c++"
|
||||||
|
"-DCMAKE_AR=${nativeBintools}/bin/${nativeBintools.targetPrefix}ar"
|
||||||
|
"-DCMAKE_STRIP=${nativeBintools}/bin/${nativeBintools.targetPrefix}strip"
|
||||||
|
"-DCMAKE_RANLIB=${nativeBintools}/bin/${nativeBintools.targetPrefix}ranlib"
|
||||||
|
];
|
||||||
|
# We need to repass the custom GNUInstallDirs values, otherwise CMake
|
||||||
|
# will choose them for us, leading to wrong results in llvm-config-native
|
||||||
|
nativeInstallFlags = [
|
||||||
|
"-DCMAKE_INSTALL_PREFIX=${placeholder "out"}"
|
||||||
|
"-DCMAKE_INSTALL_BINDIR=${placeholder "out"}/bin"
|
||||||
|
"-DCMAKE_INSTALL_INCLUDEDIR=${placeholder "dev"}/include"
|
||||||
|
"-DCMAKE_INSTALL_LIBDIR=${placeholder "lib"}/lib"
|
||||||
|
"-DCMAKE_INSTALL_LIBEXECDIR=${placeholder "lib"}/libexec"
|
||||||
|
];
|
||||||
|
in "-DCROSS_TOOLCHAIN_FLAGS_NATIVE:list="
|
||||||
|
+ lib.concatStringsSep ";" (lib.concatLists [
|
||||||
|
flagsForLlvmConfig
|
||||||
|
nativeToolchainFlags
|
||||||
|
nativeInstallFlags
|
||||||
|
])
|
||||||
|
)
|
||||||
|
];
|
||||||
|
|
||||||
|
postBuild = ''
|
||||||
|
rm -fR $out
|
||||||
|
'';
|
||||||
|
|
||||||
|
preCheck = ''
|
||||||
|
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH''${LD_LIBRARY_PATH:+:}$PWD/lib
|
||||||
|
'';
|
||||||
|
|
||||||
|
postInstall = ''
|
||||||
|
mkdir -p $python/share
|
||||||
|
mv $out/share/opt-viewer $python/share/opt-viewer
|
||||||
|
moveToOutput "bin/llvm-config*" "$dev"
|
||||||
|
substituteInPlace "$dev/lib/cmake/llvm/LLVMExports-${if debugVersion then "debug" else "release"}.cmake" \
|
||||||
|
--replace "\''${_IMPORT_PREFIX}/lib/lib" "$lib/lib/lib" \
|
||||||
|
--replace "$out/bin/llvm-config" "$dev/bin/llvm-config"
|
||||||
|
substituteInPlace "$dev/lib/cmake/llvm/LLVMConfig.cmake" \
|
||||||
|
--replace 'set(LLVM_BINARY_DIR "''${LLVM_INSTALL_PREFIX}")' 'set(LLVM_BINARY_DIR "''${LLVM_INSTALL_PREFIX}'"$lib"'")'
|
||||||
|
''
|
||||||
|
+ optionalString (stdenv.isDarwin && enableSharedLibraries) ''
|
||||||
|
ln -s $lib/lib/libLLVM.dylib $lib/lib/libLLVM-${shortVersion}.dylib
|
||||||
|
ln -s $lib/lib/libLLVM.dylib $lib/lib/libLLVM-${release_version}.dylib
|
||||||
|
''
|
||||||
|
+ optionalString (stdenv.buildPlatform != stdenv.hostPlatform) ''
|
||||||
|
cp NATIVE/bin/llvm-config $dev/bin/llvm-config-native
|
||||||
|
'';
|
||||||
|
|
||||||
|
inherit doCheck;
|
||||||
|
|
||||||
|
checkTarget = "check-all";
|
||||||
|
|
||||||
|
requiredSystemFeatures = [ "big-parallel" ];
|
||||||
|
meta = llvm_meta // {
|
||||||
|
homepage = "https://llvm.org/";
|
||||||
|
description = "A collection of modular and reusable compiler and toolchain technologies";
|
||||||
|
longDescription = ''
|
||||||
|
The LLVM Project is a collection of modular and reusable compiler and
|
||||||
|
toolchain technologies. Despite its name, LLVM has little to do with
|
||||||
|
traditional virtual machines. The name "LLVM" itself is not an acronym; it
|
||||||
|
is the full name of the project.
|
||||||
|
LLVM began as a research project at the University of Illinois, with the
|
||||||
|
goal of providing a modern, SSA-based compilation strategy capable of
|
||||||
|
supporting both static and dynamic compilation of arbitrary programming
|
||||||
|
languages. Since then, LLVM has grown to be an umbrella project consisting
|
||||||
|
of a number of subprojects, many of which are being used in production by
|
||||||
|
a wide variety of commercial and open source projects as well as being
|
||||||
|
widely used in academic research. Code in the LLVM project is licensed
|
||||||
|
under the "Apache 2.0 License with LLVM exceptions".
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
} // lib.optionalAttrs enableManpages {
|
||||||
|
pname = "llvm-manpages";
|
||||||
|
|
||||||
|
buildPhase = ''
|
||||||
|
make docs-llvm-man
|
||||||
|
'';
|
||||||
|
|
||||||
|
propagatedBuildInputs = [];
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
make -C docs install
|
||||||
|
'';
|
||||||
|
|
||||||
|
postPatch = null;
|
||||||
|
postInstall = null;
|
||||||
|
|
||||||
|
outputs = [ "out" ];
|
||||||
|
|
||||||
|
doCheck = false;
|
||||||
|
|
||||||
|
meta = llvm_meta // {
|
||||||
|
description = "man pages for LLVM ${version}";
|
||||||
|
};
|
||||||
|
})
|
|
@ -0,0 +1,106 @@
|
||||||
|
diff --git a/tools/polly/CMakeLists.txt b/tools/polly/CMakeLists.txt
|
||||||
|
index 9939097f743e..8cc538da912a 100644
|
||||||
|
--- a/tools/polly/CMakeLists.txt
|
||||||
|
+++ b/tools/polly/CMakeLists.txt
|
||||||
|
@@ -2,7 +2,11 @@
|
||||||
|
if (NOT DEFINED LLVM_MAIN_SRC_DIR)
|
||||||
|
project(Polly)
|
||||||
|
cmake_minimum_required(VERSION 3.4.3)
|
||||||
|
+endif()
|
||||||
|
+
|
||||||
|
+include(GNUInstallDirs)
|
||||||
|
|
||||||
|
+if (NOT DEFINED LLVM_MAIN_SRC_DIR)
|
||||||
|
# Where is LLVM installed?
|
||||||
|
find_package(LLVM CONFIG REQUIRED)
|
||||||
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${LLVM_CMAKE_DIR})
|
||||||
|
@@ -145,14 +149,14 @@ include_directories(
|
||||||
|
|
||||||
|
if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
|
||||||
|
install(DIRECTORY include/
|
||||||
|
- DESTINATION include
|
||||||
|
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||||
|
FILES_MATCHING
|
||||||
|
PATTERN "*.h"
|
||||||
|
PATTERN ".svn" EXCLUDE
|
||||||
|
)
|
||||||
|
|
||||||
|
install(DIRECTORY ${POLLY_BINARY_DIR}/include/
|
||||||
|
- DESTINATION include
|
||||||
|
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||||
|
FILES_MATCHING
|
||||||
|
PATTERN "*.h"
|
||||||
|
PATTERN "CMakeFiles" EXCLUDE
|
||||||
|
diff --git a/tools/polly/cmake/CMakeLists.txt b/tools/polly/cmake/CMakeLists.txt
|
||||||
|
index 211f95512717..f9e04a4844b6 100644
|
||||||
|
--- a/tools/polly/cmake/CMakeLists.txt
|
||||||
|
+++ b/tools/polly/cmake/CMakeLists.txt
|
||||||
|
@@ -79,18 +79,18 @@ file(GENERATE
|
||||||
|
|
||||||
|
# Generate PollyConfig.cmake for the install tree.
|
||||||
|
unset(POLLY_EXPORTS)
|
||||||
|
-set(POLLY_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
|
||||||
|
+set(POLLY_INSTALL_PREFIX "")
|
||||||
|
set(POLLY_CONFIG_LLVM_CMAKE_DIR "${LLVM_BINARY_DIR}/${LLVM_INSTALL_PACKAGE_DIR}")
|
||||||
|
-set(POLLY_CONFIG_CMAKE_DIR "${POLLY_INSTALL_PREFIX}/${POLLY_INSTALL_PACKAGE_DIR}")
|
||||||
|
-set(POLLY_CONFIG_LIBRARY_DIRS "${POLLY_INSTALL_PREFIX}/lib${LLVM_LIBDIR_SUFFIX}")
|
||||||
|
+set(POLLY_CONFIG_CMAKE_DIR "${POLLY_INSTALL_PREFIX}${CMAKE_INSTALL_PREFIX}/${POLLY_INSTALL_PACKAGE_DIR}")
|
||||||
|
+set(POLLY_CONFIG_LIBRARY_DIRS "${POLLY_INSTALL_PREFIX}${CMAKE_INSTALL_FULL_LIBDIR}${LLVM_LIBDIR_SUFFIX}")
|
||||||
|
if (POLLY_BUNDLED_ISL)
|
||||||
|
set(POLLY_CONFIG_INCLUDE_DIRS
|
||||||
|
- "${POLLY_INSTALL_PREFIX}/include"
|
||||||
|
- "${POLLY_INSTALL_PREFIX}/include/polly"
|
||||||
|
+ "${POLLY_INSTALL_PREFIX}${CMAKE_INSTALL_FULL_LIBDIR}"
|
||||||
|
+ "${POLLY_INSTALL_PREFIX}${CMAKE_INSTALL_FULL_LIBDIR}/polly"
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
set(POLLY_CONFIG_INCLUDE_DIRS
|
||||||
|
- "${POLLY_INSTALL_PREFIX}/include"
|
||||||
|
+ "${POLLY_INSTALL_PREFIX}${CMAKE_INSTALL_FULL_INCLUDEDIR}"
|
||||||
|
${ISL_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
@@ -100,12 +100,12 @@ endif()
|
||||||
|
foreach(tgt IN LISTS POLLY_CONFIG_EXPORTED_TARGETS)
|
||||||
|
get_target_property(tgt_type ${tgt} TYPE)
|
||||||
|
if (tgt_type STREQUAL "EXECUTABLE")
|
||||||
|
- set(tgt_prefix "bin/")
|
||||||
|
+ set(tgt_prefix "${CMAKE_INSTALL_BINDIR}/")
|
||||||
|
else()
|
||||||
|
- set(tgt_prefix "lib/")
|
||||||
|
+ set(tgt_prefix "${CMAKE_INSTALL_LIBDIR}/")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
- set(tgt_path "${CMAKE_INSTALL_PREFIX}/${tgt_prefix}$<TARGET_FILE_NAME:${tgt}>")
|
||||||
|
+ set(tgt_path "${tgt_prefix}$<TARGET_FILE_NAME:${tgt}>")
|
||||||
|
file(RELATIVE_PATH tgt_path ${POLLY_CONFIG_CMAKE_DIR} ${tgt_path})
|
||||||
|
|
||||||
|
if (NOT tgt_type STREQUAL "INTERFACE_LIBRARY")
|
||||||
|
diff --git a/tools/polly/cmake/polly_macros.cmake b/tools/polly/cmake/polly_macros.cmake
|
||||||
|
index 86de6f10686e..91f30891ccbe 100644
|
||||||
|
--- a/tools/polly/cmake/polly_macros.cmake
|
||||||
|
+++ b/tools/polly/cmake/polly_macros.cmake
|
||||||
|
@@ -44,8 +44,8 @@ macro(add_polly_library name)
|
||||||
|
if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY OR ${name} STREQUAL "LLVMPolly")
|
||||||
|
install(TARGETS ${name}
|
||||||
|
EXPORT LLVMExports
|
||||||
|
- LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX}
|
||||||
|
- ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX})
|
||||||
|
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}
|
||||||
|
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX})
|
||||||
|
endif()
|
||||||
|
set_property(GLOBAL APPEND PROPERTY LLVM_EXPORTS ${name})
|
||||||
|
endmacro(add_polly_library)
|
||||||
|
diff --git a/tools/polly/lib/External/CMakeLists.txt b/tools/polly/lib/External/CMakeLists.txt
|
||||||
|
index 1039079cb49c..28b499ae1e9e 100644
|
||||||
|
--- a/tools/polly/lib/External/CMakeLists.txt
|
||||||
|
+++ b/tools/polly/lib/External/CMakeLists.txt
|
||||||
|
@@ -275,7 +275,7 @@ if (POLLY_BUNDLED_ISL)
|
||||||
|
install(DIRECTORY
|
||||||
|
${ISL_SOURCE_DIR}/include/
|
||||||
|
${ISL_BINARY_DIR}/include/
|
||||||
|
- DESTINATION include/polly
|
||||||
|
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/polly
|
||||||
|
FILES_MATCHING
|
||||||
|
PATTERN "*.h"
|
||||||
|
PATTERN "CMakeFiles" EXCLUDE
|
|
@ -0,0 +1,417 @@
|
||||||
|
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||||
|
index 247ad36d3845..815e2c4ba955 100644
|
||||||
|
--- a/CMakeLists.txt
|
||||||
|
+++ b/CMakeLists.txt
|
||||||
|
@@ -269,15 +269,21 @@ if (CMAKE_BUILD_TYPE AND
|
||||||
|
message(FATAL_ERROR "Invalid value for CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
+include(GNUInstallDirs)
|
||||||
|
+
|
||||||
|
set(LLVM_LIBDIR_SUFFIX "" CACHE STRING "Define suffix of library directory name (32/64)" )
|
||||||
|
|
||||||
|
-set(LLVM_TOOLS_INSTALL_DIR "bin" CACHE STRING "Path for binary subdirectory (defaults to 'bin')")
|
||||||
|
+set(LLVM_TOOLS_INSTALL_DIR "${CMAKE_INSTALL_BINDIR}" CACHE STRING
|
||||||
|
+ "Path for binary subdirectory (defaults to 'bin')")
|
||||||
|
mark_as_advanced(LLVM_TOOLS_INSTALL_DIR)
|
||||||
|
|
||||||
|
set(LLVM_UTILS_INSTALL_DIR "${LLVM_TOOLS_INSTALL_DIR}" CACHE STRING
|
||||||
|
"Path to install LLVM utilities (enabled by LLVM_INSTALL_UTILS=ON) (defaults to LLVM_TOOLS_INSTALL_DIR)")
|
||||||
|
mark_as_advanced(LLVM_UTILS_INSTALL_DIR)
|
||||||
|
|
||||||
|
+set(LLVM_INSTALL_CMAKE_DIR "${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}/cmake/llvm" CACHE STRING
|
||||||
|
+ "Path for CMake subdirectory (defaults to lib/cmake/llvm)" )
|
||||||
|
+
|
||||||
|
# They are used as destination of target generators.
|
||||||
|
set(LLVM_RUNTIME_OUTPUT_INTDIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin)
|
||||||
|
set(LLVM_LIBRARY_OUTPUT_INTDIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX})
|
||||||
|
@@ -559,9 +565,9 @@ option (LLVM_ENABLE_SPHINX "Use Sphinx to generate llvm documentation." OFF)
|
||||||
|
option (LLVM_ENABLE_OCAMLDOC "Build OCaml bindings documentation." ON)
|
||||||
|
option (LLVM_ENABLE_BINDINGS "Build bindings." ON)
|
||||||
|
|
||||||
|
-set(LLVM_INSTALL_DOXYGEN_HTML_DIR "share/doc/llvm/doxygen-html"
|
||||||
|
+set(LLVM_INSTALL_DOXYGEN_HTML_DIR "${CMAKE_INSTALL_DOCDIR}/${project}/doxygen-html"
|
||||||
|
CACHE STRING "Doxygen-generated HTML documentation install directory")
|
||||||
|
-set(LLVM_INSTALL_OCAMLDOC_HTML_DIR "share/doc/llvm/ocaml-html"
|
||||||
|
+set(LLVM_INSTALL_OCAMLDOC_HTML_DIR "${CMAKE_INSTALL_DOCDIR}/${project}/ocaml-html"
|
||||||
|
CACHE STRING "OCamldoc-generated HTML documentation install directory")
|
||||||
|
|
||||||
|
option (LLVM_BUILD_EXTERNAL_COMPILER_RT
|
||||||
|
@@ -1107,7 +1113,7 @@ endif()
|
||||||
|
|
||||||
|
if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
|
||||||
|
install(DIRECTORY include/llvm include/llvm-c
|
||||||
|
- DESTINATION include
|
||||||
|
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||||
|
COMPONENT llvm-headers
|
||||||
|
FILES_MATCHING
|
||||||
|
PATTERN "*.def"
|
||||||
|
@@ -1119,7 +1125,7 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
|
||||||
|
)
|
||||||
|
|
||||||
|
install(DIRECTORY ${LLVM_INCLUDE_DIR}/llvm ${LLVM_INCLUDE_DIR}/llvm-c
|
||||||
|
- DESTINATION include
|
||||||
|
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||||
|
COMPONENT llvm-headers
|
||||||
|
FILES_MATCHING
|
||||||
|
PATTERN "*.def"
|
||||||
|
@@ -1134,13 +1140,13 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
|
||||||
|
|
||||||
|
if (LLVM_INSTALL_MODULEMAPS)
|
||||||
|
install(DIRECTORY include/llvm include/llvm-c
|
||||||
|
- DESTINATION include
|
||||||
|
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||||
|
COMPONENT llvm-headers
|
||||||
|
FILES_MATCHING
|
||||||
|
PATTERN "module.modulemap"
|
||||||
|
)
|
||||||
|
install(FILES include/llvm/module.install.modulemap
|
||||||
|
- DESTINATION include/llvm
|
||||||
|
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/llvm
|
||||||
|
COMPONENT llvm-headers
|
||||||
|
RENAME "module.extern.modulemap"
|
||||||
|
)
|
||||||
|
diff --git a/cmake/modules/AddLLVM.cmake b/cmake/modules/AddLLVM.cmake
|
||||||
|
index b74adc11ade9..a5aa258cde30 100644
|
||||||
|
--- a/cmake/modules/AddLLVM.cmake
|
||||||
|
+++ b/cmake/modules/AddLLVM.cmake
|
||||||
|
@@ -766,9 +766,9 @@ macro(add_llvm_library name)
|
||||||
|
|
||||||
|
install(TARGETS ${name}
|
||||||
|
${export_to_llvmexports}
|
||||||
|
- LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX} COMPONENT ${name}
|
||||||
|
- ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX} COMPONENT ${name}
|
||||||
|
- RUNTIME DESTINATION bin COMPONENT ${name})
|
||||||
|
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX} COMPONENT ${name}
|
||||||
|
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX} COMPONENT ${name}
|
||||||
|
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${name})
|
||||||
|
|
||||||
|
if (NOT LLVM_ENABLE_IDE)
|
||||||
|
add_llvm_install_targets(install-${name}
|
||||||
|
@@ -981,7 +981,7 @@ function(process_llvm_pass_plugins)
|
||||||
|
"set(LLVM_STATIC_EXTENSIONS ${LLVM_STATIC_EXTENSIONS})")
|
||||||
|
install(FILES
|
||||||
|
${llvm_cmake_builddir}/LLVMConfigExtensions.cmake
|
||||||
|
- DESTINATION ${LLVM_INSTALL_PACKAGE_DIR}
|
||||||
|
+ DESTINATION ${LLVM_INSTALL_CMAKE_DIR}
|
||||||
|
COMPONENT cmake-exports)
|
||||||
|
|
||||||
|
set(ExtensionDef "${LLVM_BINARY_DIR}/include/llvm/Support/Extension.def")
|
||||||
|
@@ -1201,7 +1201,7 @@ macro(add_llvm_example name)
|
||||||
|
endif()
|
||||||
|
add_llvm_executable(${name} ${ARGN})
|
||||||
|
if( LLVM_BUILD_EXAMPLES )
|
||||||
|
- install(TARGETS ${name} RUNTIME DESTINATION examples)
|
||||||
|
+ install(TARGETS ${name} RUNTIME DESTINATION ${CMAKE_INSTALL_DOCDIR}/examples)
|
||||||
|
endif()
|
||||||
|
set_target_properties(${name} PROPERTIES FOLDER "Examples")
|
||||||
|
endmacro(add_llvm_example name)
|
||||||
|
@@ -1819,7 +1819,7 @@ function(llvm_install_library_symlink name dest type)
|
||||||
|
set(full_name ${CMAKE_${type}_LIBRARY_PREFIX}${name}${CMAKE_${type}_LIBRARY_SUFFIX})
|
||||||
|
set(full_dest ${CMAKE_${type}_LIBRARY_PREFIX}${dest}${CMAKE_${type}_LIBRARY_SUFFIX})
|
||||||
|
|
||||||
|
- set(output_dir lib${LLVM_LIBDIR_SUFFIX})
|
||||||
|
+ set(output_dir ${CMAKE_INSTALL_FULL_LIBDIR}${LLVM_LIBDIR_SUFFIX})
|
||||||
|
if(WIN32 AND "${type}" STREQUAL "SHARED")
|
||||||
|
set(output_dir bin)
|
||||||
|
endif()
|
||||||
|
@@ -1836,7 +1836,7 @@ function(llvm_install_library_symlink name dest type)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
-function(llvm_install_symlink name dest)
|
||||||
|
+function(llvm_install_symlink name dest output_dir)
|
||||||
|
cmake_parse_arguments(ARG "ALWAYS_GENERATE" "COMPONENT" "" ${ARGN})
|
||||||
|
foreach(path ${CMAKE_MODULE_PATH})
|
||||||
|
if(EXISTS ${path}/LLVMInstallSymlink.cmake)
|
||||||
|
@@ -1859,7 +1859,7 @@ function(llvm_install_symlink name dest)
|
||||||
|
set(full_dest ${dest}${CMAKE_EXECUTABLE_SUFFIX})
|
||||||
|
|
||||||
|
install(SCRIPT ${INSTALL_SYMLINK}
|
||||||
|
- CODE "install_symlink(${full_name} ${full_dest} ${LLVM_TOOLS_INSTALL_DIR})"
|
||||||
|
+ CODE "install_symlink(${full_name} ${full_dest} ${output_dir})"
|
||||||
|
COMPONENT ${component})
|
||||||
|
|
||||||
|
if (NOT LLVM_ENABLE_IDE AND NOT ARG_ALWAYS_GENERATE)
|
||||||
|
@@ -1942,7 +1942,8 @@ function(add_llvm_tool_symlink link_name target)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if ((TOOL_IS_TOOLCHAIN OR NOT LLVM_INSTALL_TOOLCHAIN_ONLY) AND LLVM_BUILD_TOOLS)
|
||||||
|
- llvm_install_symlink(${link_name} ${target})
|
||||||
|
+ GNUInstallDirs_get_absolute_install_dir(output_dir LLVM_TOOLS_INSTALL_DIR)
|
||||||
|
+ llvm_install_symlink(${link_name} ${target} ${output_dir})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
@@ -2064,9 +2065,9 @@ function(llvm_setup_rpath name)
|
||||||
|
|
||||||
|
if (APPLE)
|
||||||
|
set(_install_name_dir INSTALL_NAME_DIR "@rpath")
|
||||||
|
- set(_install_rpath "@loader_path/../lib${LLVM_LIBDIR_SUFFIX}" ${extra_libdir})
|
||||||
|
+ set(_install_rpath "@loader_path/../${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}" ${extra_libdir})
|
||||||
|
elseif(UNIX)
|
||||||
|
- set(_install_rpath "\$ORIGIN/../lib${LLVM_LIBDIR_SUFFIX}" ${extra_libdir})
|
||||||
|
+ set(_install_rpath "\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}" ${extra_libdir})
|
||||||
|
if(${CMAKE_SYSTEM_NAME} MATCHES "(FreeBSD|DragonFly)")
|
||||||
|
set_property(TARGET ${name} APPEND_STRING PROPERTY
|
||||||
|
LINK_FLAGS " -Wl,-z,origin ")
|
||||||
|
diff --git a/cmake/modules/AddOCaml.cmake b/cmake/modules/AddOCaml.cmake
|
||||||
|
index 554046b20edf..4d1ad980641e 100644
|
||||||
|
--- a/cmake/modules/AddOCaml.cmake
|
||||||
|
+++ b/cmake/modules/AddOCaml.cmake
|
||||||
|
@@ -144,9 +144,9 @@ function(add_ocaml_library name)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
if( APPLE )
|
||||||
|
- set(ocaml_rpath "@executable_path/../../../lib${LLVM_LIBDIR_SUFFIX}")
|
||||||
|
+ set(ocaml_rpath "@executable_path/../../../${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}")
|
||||||
|
elseif( UNIX )
|
||||||
|
- set(ocaml_rpath "\\$ORIGIN/../../../lib${LLVM_LIBDIR_SUFFIX}")
|
||||||
|
+ set(ocaml_rpath "\\$ORIGIN/../../../${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}")
|
||||||
|
endif()
|
||||||
|
list(APPEND ocaml_flags "-ldopt" "-Wl,-rpath,${ocaml_rpath}")
|
||||||
|
|
||||||
|
diff --git a/cmake/modules/AddSphinxTarget.cmake b/cmake/modules/AddSphinxTarget.cmake
|
||||||
|
index b5babb30abcf..190b1222a9f9 100644
|
||||||
|
--- a/cmake/modules/AddSphinxTarget.cmake
|
||||||
|
+++ b/cmake/modules/AddSphinxTarget.cmake
|
||||||
|
@@ -84,7 +84,7 @@ function (add_sphinx_target builder project)
|
||||||
|
endif()
|
||||||
|
elseif (builder STREQUAL html)
|
||||||
|
string(TOUPPER "${project}" project_upper)
|
||||||
|
- set(${project_upper}_INSTALL_SPHINX_HTML_DIR "share/doc/${project}/html"
|
||||||
|
+ set(${project_upper}_INSTALL_SPHINX_HTML_DIR "${CMAKE_INSTALL_DOCDIR}/${project}/html"
|
||||||
|
CACHE STRING "HTML documentation install directory for ${project}")
|
||||||
|
|
||||||
|
# '/.' indicates: copy the contents of the directory directly into
|
||||||
|
diff --git a/cmake/modules/CMakeLists.txt b/cmake/modules/CMakeLists.txt
|
||||||
|
index 4b8879f65fe4..f01920bcc60f 100644
|
||||||
|
--- a/cmake/modules/CMakeLists.txt
|
||||||
|
+++ b/cmake/modules/CMakeLists.txt
|
||||||
|
@@ -1,4 +1,4 @@
|
||||||
|
-set(LLVM_INSTALL_PACKAGE_DIR lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm)
|
||||||
|
+set(LLVM_INSTALL_PACKAGE_DIR ${LLVM_INSTALL_CMAKE_DIR} CACHE STRING "Path for CMake subdirectory (defaults to 'cmake/llvm')")
|
||||||
|
set(llvm_cmake_builddir "${LLVM_BINARY_DIR}/${LLVM_INSTALL_PACKAGE_DIR}")
|
||||||
|
|
||||||
|
# First for users who use an installed LLVM, create the LLVMExports.cmake file.
|
||||||
|
@@ -108,13 +108,13 @@ foreach(p ${_count})
|
||||||
|
set(LLVM_CONFIG_CODE "${LLVM_CONFIG_CODE}
|
||||||
|
get_filename_component(LLVM_INSTALL_PREFIX \"\${LLVM_INSTALL_PREFIX}\" PATH)")
|
||||||
|
endforeach(p)
|
||||||
|
-set(LLVM_CONFIG_INCLUDE_DIRS "\${LLVM_INSTALL_PREFIX}/include")
|
||||||
|
+set(LLVM_CONFIG_INCLUDE_DIRS "\${LLVM_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}")
|
||||||
|
set(LLVM_CONFIG_INCLUDE_DIR "${LLVM_CONFIG_INCLUDE_DIRS}")
|
||||||
|
set(LLVM_CONFIG_MAIN_INCLUDE_DIR "${LLVM_CONFIG_INCLUDE_DIRS}")
|
||||||
|
-set(LLVM_CONFIG_LIBRARY_DIRS "\${LLVM_INSTALL_PREFIX}/lib\${LLVM_LIBDIR_SUFFIX}")
|
||||||
|
+set(LLVM_CONFIG_LIBRARY_DIRS "\${LLVM_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}\${LLVM_LIBDIR_SUFFIX}")
|
||||||
|
set(LLVM_CONFIG_CMAKE_DIR "\${LLVM_INSTALL_PREFIX}/${LLVM_INSTALL_PACKAGE_DIR}")
|
||||||
|
set(LLVM_CONFIG_BINARY_DIR "\${LLVM_INSTALL_PREFIX}")
|
||||||
|
-set(LLVM_CONFIG_TOOLS_BINARY_DIR "\${LLVM_INSTALL_PREFIX}/bin")
|
||||||
|
+set(LLVM_CONFIG_TOOLS_BINARY_DIR "\${LLVM_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}")
|
||||||
|
|
||||||
|
# Generate a default location for lit
|
||||||
|
if (LLVM_INSTALL_UTILS AND LLVM_BUILD_UTILS)
|
||||||
|
diff --git a/cmake/modules/LLVMInstallSymlink.cmake b/cmake/modules/LLVMInstallSymlink.cmake
|
||||||
|
index 09fed8085c23..aa79f192abf0 100644
|
||||||
|
--- a/cmake/modules/LLVMInstallSymlink.cmake
|
||||||
|
+++ b/cmake/modules/LLVMInstallSymlink.cmake
|
||||||
|
@@ -10,7 +10,7 @@ function(install_symlink name target outdir)
|
||||||
|
set(LINK_OR_COPY copy)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
- set(bindir "${DESTDIR}${CMAKE_INSTALL_PREFIX}/${outdir}/")
|
||||||
|
+ set(bindir "${DESTDIR}${outdir}/")
|
||||||
|
|
||||||
|
message(STATUS "Creating ${name}")
|
||||||
|
|
||||||
|
diff --git a/docs/CMake.rst b/docs/CMake.rst
|
||||||
|
index 1f908d3e95b1..1315e0aa40e1 100644
|
||||||
|
--- a/docs/CMake.rst
|
||||||
|
+++ b/docs/CMake.rst
|
||||||
|
@@ -196,7 +196,7 @@ CMake manual, or execute ``cmake --help-variable VARIABLE_NAME``.
|
||||||
|
**LLVM_LIBDIR_SUFFIX**:STRING
|
||||||
|
Extra suffix to append to the directory where libraries are to be
|
||||||
|
installed. On a 64-bit architecture, one could use ``-DLLVM_LIBDIR_SUFFIX=64``
|
||||||
|
- to install libraries to ``/usr/lib64``.
|
||||||
|
+ to install libraries to ``/usr/lib64``. See also ``CMAKE_INSTALL_LIBDIR``.
|
||||||
|
|
||||||
|
**CMAKE_C_FLAGS**:STRING
|
||||||
|
Extra flags to use when compiling C source files.
|
||||||
|
@@ -516,8 +516,8 @@ LLVM-specific variables
|
||||||
|
|
||||||
|
**LLVM_INSTALL_DOXYGEN_HTML_DIR**:STRING
|
||||||
|
The path to install Doxygen-generated HTML documentation to. This path can
|
||||||
|
- either be absolute or relative to the CMAKE_INSTALL_PREFIX. Defaults to
|
||||||
|
- `share/doc/llvm/doxygen-html`.
|
||||||
|
+ either be absolute or relative to the ``CMAKE_INSTALL_PREFIX``. Defaults to
|
||||||
|
+ `${CMAKE_INSTALL_DOCDIR}/${project}/doxygen-html`.
|
||||||
|
|
||||||
|
**LLVM_ENABLE_SPHINX**:BOOL
|
||||||
|
If specified, CMake will search for the ``sphinx-build`` executable and will make
|
||||||
|
@@ -548,13 +548,33 @@ LLVM-specific variables
|
||||||
|
|
||||||
|
**LLVM_INSTALL_SPHINX_HTML_DIR**:STRING
|
||||||
|
The path to install Sphinx-generated HTML documentation to. This path can
|
||||||
|
- either be absolute or relative to the CMAKE_INSTALL_PREFIX. Defaults to
|
||||||
|
- `share/doc/llvm/html`.
|
||||||
|
+ either be absolute or relative to the ``CMAKE_INSTALL_PREFIX``. Defaults to
|
||||||
|
+ `${CMAKE_INSTALL_DOCDIR}/${project}/html`.
|
||||||
|
|
||||||
|
**LLVM_INSTALL_OCAMLDOC_HTML_DIR**:STRING
|
||||||
|
The path to install OCamldoc-generated HTML documentation to. This path can
|
||||||
|
- either be absolute or relative to the CMAKE_INSTALL_PREFIX. Defaults to
|
||||||
|
- `share/doc/llvm/ocaml-html`.
|
||||||
|
+ either be absolute or relative to the ``CMAKE_INSTALL_PREFIX``. Defaults to
|
||||||
|
+ `${CMAKE_INSTALL_DOCDIR}/${project}/ocaml-html`.
|
||||||
|
+
|
||||||
|
+**CMAKE_INSTALL_BINDIR**:STRING
|
||||||
|
+ The path to install binary tools, relative to the ``CMAKE_INSTALL_PREFIX``.
|
||||||
|
+ Defaults to `bin`.
|
||||||
|
+
|
||||||
|
+**CMAKE_INSTALL_LIBDIR**:STRING
|
||||||
|
+ The path to install libraries, relative to the ``CMAKE_INSTALL_PREFIX``.
|
||||||
|
+ Defaults to `lib`.
|
||||||
|
+
|
||||||
|
+**CMAKE_INSTALL_INCLUDEDIR**:STRING
|
||||||
|
+ The path to install header files, relative to the ``CMAKE_INSTALL_PREFIX``.
|
||||||
|
+ Defaults to `include`.
|
||||||
|
+
|
||||||
|
+**CMAKE_INSTALL_DOCDIR**:STRING
|
||||||
|
+ The path to install documentation, relative to the ``CMAKE_INSTALL_PREFIX``.
|
||||||
|
+ Defaults to `share/doc`.
|
||||||
|
+
|
||||||
|
+**CMAKE_INSTALL_MANDIR**:STRING
|
||||||
|
+ The path to install manpage files, relative to the ``CMAKE_INSTALL_PREFIX``.
|
||||||
|
+ Defaults to `share/man`.
|
||||||
|
|
||||||
|
**LLVM_CREATE_XCODE_TOOLCHAIN**:BOOL
|
||||||
|
macOS Only: If enabled CMake will generate a target named
|
||||||
|
@@ -752,9 +772,11 @@ the ``cmake`` command or by setting it directly in ``ccmake`` or ``cmake-gui``).
|
||||||
|
|
||||||
|
This file is available in two different locations.
|
||||||
|
|
||||||
|
-* ``<INSTALL_PREFIX>/lib/cmake/llvm/LLVMConfig.cmake`` where
|
||||||
|
- ``<INSTALL_PREFIX>`` is the install prefix of an installed version of LLVM.
|
||||||
|
- On Linux typically this is ``/usr/lib/cmake/llvm/LLVMConfig.cmake``.
|
||||||
|
+* ``<LLVM_INSTALL_PACKAGE_DIR>LLVMConfig.cmake`` where
|
||||||
|
+ ``<LLVM_INSTALL_PACKAGE_DIR>`` is the location where LLVM CMake modules are
|
||||||
|
+ installed as part of an installed version of LLVM. This is typically
|
||||||
|
+ ``cmake/llvm/`` within the lib directory. On Linux, this is typically
|
||||||
|
+ ``/usr/lib/cmake/llvm/LLVMConfig.cmake``.
|
||||||
|
|
||||||
|
* ``<LLVM_BUILD_ROOT>/lib/cmake/llvm/LLVMConfig.cmake`` where
|
||||||
|
``<LLVM_BUILD_ROOT>`` is the root of the LLVM build tree. **Note: this is only
|
||||||
|
diff --git a/examples/Bye/CMakeLists.txt b/examples/Bye/CMakeLists.txt
|
||||||
|
index bb96edb4b4bf..678c22fb43c8 100644
|
||||||
|
--- a/examples/Bye/CMakeLists.txt
|
||||||
|
+++ b/examples/Bye/CMakeLists.txt
|
||||||
|
@@ -14,6 +14,6 @@ if (NOT WIN32)
|
||||||
|
BUILDTREE_ONLY
|
||||||
|
)
|
||||||
|
|
||||||
|
- install(TARGETS ${name} RUNTIME DESTINATION examples)
|
||||||
|
+ install(TARGETS ${name} RUNTIME DESTINATION ${CMAKE_INSTALL_DOCDIR}/examples)
|
||||||
|
set_target_properties(${name} PROPERTIES FOLDER "Examples")
|
||||||
|
endif()
|
||||||
|
diff --git a/include/llvm/CMakeLists.txt b/include/llvm/CMakeLists.txt
|
||||||
|
index b46319f24fc8..2feabd1954e4 100644
|
||||||
|
--- a/include/llvm/CMakeLists.txt
|
||||||
|
+++ b/include/llvm/CMakeLists.txt
|
||||||
|
@@ -5,5 +5,5 @@ add_subdirectory(Frontend)
|
||||||
|
# If we're doing an out-of-tree build, copy a module map for generated
|
||||||
|
# header files into the build area.
|
||||||
|
if (NOT "${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
|
||||||
|
- configure_file(module.modulemap.build module.modulemap COPYONLY)
|
||||||
|
+ configure_file(module.modulemap.build ${LLVM_INCLUDE_DIR}/module.modulemap COPYONLY)
|
||||||
|
endif (NOT "${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
|
||||||
|
diff --git a/tools/llvm-config/BuildVariables.inc.in b/tools/llvm-config/BuildVariables.inc.in
|
||||||
|
index 63cef75368b7..6295478b1f3d 100644
|
||||||
|
--- a/tools/llvm-config/BuildVariables.inc.in
|
||||||
|
+++ b/tools/llvm-config/BuildVariables.inc.in
|
||||||
|
@@ -23,6 +23,10 @@
|
||||||
|
#define LLVM_CXXFLAGS "@LLVM_CXXFLAGS@"
|
||||||
|
#define LLVM_BUILDMODE "@LLVM_BUILDMODE@"
|
||||||
|
#define LLVM_LIBDIR_SUFFIX "@LLVM_LIBDIR_SUFFIX@"
|
||||||
|
+#define LLVM_INSTALL_BINDIR "@CMAKE_INSTALL_BINDIR@"
|
||||||
|
+#define LLVM_INSTALL_LIBDIR "@CMAKE_INSTALL_LIBDIR@"
|
||||||
|
+#define LLVM_INSTALL_INCLUDEDIR "@CMAKE_INSTALL_INCLUDEDIR@"
|
||||||
|
+#define LLVM_INSTALL_CMAKEDIR "@LLVM_INSTALL_CMAKE_DIR@"
|
||||||
|
#define LLVM_TARGETS_BUILT "@LLVM_TARGETS_BUILT@"
|
||||||
|
#define LLVM_SYSTEM_LIBS "@LLVM_SYSTEM_LIBS@"
|
||||||
|
#define LLVM_BUILD_SYSTEM "@LLVM_BUILD_SYSTEM@"
|
||||||
|
diff --git a/tools/llvm-config/llvm-config.cpp b/tools/llvm-config/llvm-config.cpp
|
||||||
|
index 7e74b7c90816..f185e9283f83 100644
|
||||||
|
--- a/tools/llvm-config/llvm-config.cpp
|
||||||
|
+++ b/tools/llvm-config/llvm-config.cpp
|
||||||
|
@@ -358,12 +358,26 @@ int main(int argc, char **argv) {
|
||||||
|
("-I" + ActiveIncludeDir + " " + "-I" + ActiveObjRoot + "/include");
|
||||||
|
} else {
|
||||||
|
ActivePrefix = CurrentExecPrefix;
|
||||||
|
- ActiveIncludeDir = ActivePrefix + "/include";
|
||||||
|
- SmallString<256> path(StringRef(LLVM_TOOLS_INSTALL_DIR));
|
||||||
|
- sys::fs::make_absolute(ActivePrefix, path);
|
||||||
|
- ActiveBinDir = std::string(path.str());
|
||||||
|
- ActiveLibDir = ActivePrefix + "/lib" + LLVM_LIBDIR_SUFFIX;
|
||||||
|
- ActiveCMakeDir = ActiveLibDir + "/cmake/llvm";
|
||||||
|
+ {
|
||||||
|
+ SmallString<256> path(StringRef(LLVM_INSTALL_INCLUDEDIR));
|
||||||
|
+ sys::fs::make_absolute(ActivePrefix, path);
|
||||||
|
+ ActiveIncludeDir = std::string(path.str());
|
||||||
|
+ }
|
||||||
|
+ {
|
||||||
|
+ SmallString<256> path(StringRef(LLVM_INSTALL_BINDIR));
|
||||||
|
+ sys::fs::make_absolute(ActivePrefix, path);
|
||||||
|
+ ActiveBinDir = std::string(path.str());
|
||||||
|
+ }
|
||||||
|
+ {
|
||||||
|
+ SmallString<256> path(StringRef(LLVM_INSTALL_LIBDIR LLVM_LIBDIR_SUFFIX));
|
||||||
|
+ sys::fs::make_absolute(ActivePrefix, path);
|
||||||
|
+ ActiveLibDir = std::string(path.str());
|
||||||
|
+ }
|
||||||
|
+ {
|
||||||
|
+ SmallString<256> path(StringRef(LLVM_INSTALL_CMAKEDIR));
|
||||||
|
+ sys::fs::make_absolute(ActivePrefix, path);
|
||||||
|
+ ActiveCMakeDir = std::string(path.str());
|
||||||
|
+ }
|
||||||
|
ActiveIncludeOption = "-I" + ActiveIncludeDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/tools/lto/CMakeLists.txt b/tools/lto/CMakeLists.txt
|
||||||
|
index 2963f97cad88..69d66c9c9ca1 100644
|
||||||
|
--- a/tools/lto/CMakeLists.txt
|
||||||
|
+++ b/tools/lto/CMakeLists.txt
|
||||||
|
@@ -25,7 +25,7 @@ add_llvm_library(LTO SHARED INSTALL_WITH_TOOLCHAIN ${SOURCES} DEPENDS
|
||||||
|
intrinsics_gen)
|
||||||
|
|
||||||
|
install(FILES ${LLVM_MAIN_INCLUDE_DIR}/llvm-c/lto.h
|
||||||
|
- DESTINATION include/llvm-c
|
||||||
|
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/llvm-c
|
||||||
|
COMPONENT LTO)
|
||||||
|
|
||||||
|
if (APPLE)
|
||||||
|
diff --git a/tools/opt-viewer/CMakeLists.txt b/tools/opt-viewer/CMakeLists.txt
|
||||||
|
index ead73ec13a8f..250362021f17 100644
|
||||||
|
--- a/tools/opt-viewer/CMakeLists.txt
|
||||||
|
+++ b/tools/opt-viewer/CMakeLists.txt
|
||||||
|
@@ -8,7 +8,7 @@ set (files
|
||||||
|
|
||||||
|
foreach (file ${files})
|
||||||
|
install(PROGRAMS ${file}
|
||||||
|
- DESTINATION share/opt-viewer
|
||||||
|
+ DESTINATION ${CMAKE_INSTALL_DATADIR}/opt-viewer
|
||||||
|
COMPONENT opt-viewer)
|
||||||
|
endforeach (file)
|
||||||
|
|
||||||
|
diff --git a/tools/remarks-shlib/CMakeLists.txt b/tools/remarks-shlib/CMakeLists.txt
|
||||||
|
index e948496c603a..1f4df8a98b10 100644
|
||||||
|
--- a/tools/remarks-shlib/CMakeLists.txt
|
||||||
|
+++ b/tools/remarks-shlib/CMakeLists.txt
|
||||||
|
@@ -11,7 +11,7 @@ set(LLVM_EXPORTED_SYMBOL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/Remarks.exports)
|
||||||
|
add_llvm_library(Remarks SHARED INSTALL_WITH_TOOLCHAIN ${SOURCES})
|
||||||
|
|
||||||
|
install(FILES ${LLVM_MAIN_INCLUDE_DIR}/llvm-c/Remarks.h
|
||||||
|
- DESTINATION include/llvm-c
|
||||||
|
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/llvm-c
|
||||||
|
COMPONENT Remarks)
|
||||||
|
|
||||||
|
if (APPLE)
|
|
@ -0,0 +1,35 @@
|
||||||
|
From 5c571082fdaf61f6df19d9b7137dc26d71334058 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Natanael Copa <ncopa@alpinelinux.org>
|
||||||
|
Date: Thu, 18 Feb 2016 10:33:04 +0100
|
||||||
|
Subject: [PATCH 2/3] Fix build with musl libc
|
||||||
|
|
||||||
|
On musl libc the fopen64 and fopen are the same thing, but for
|
||||||
|
compatibility they have a `#define fopen64 fopen`. Same applies for
|
||||||
|
fseek64, fstat64, fstatvfs64, ftello64, lstat64, stat64 and tmpfile64.
|
||||||
|
---
|
||||||
|
include/llvm/Analysis/TargetLibraryInfo.h | 9 +++++++++
|
||||||
|
1 file changed, 9 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/include/llvm/Analysis/TargetLibraryInfo.h b/include/llvm/Analysis/TargetLibraryInfo.h
|
||||||
|
index 7becdf0..7f14427 100644
|
||||||
|
--- a/include/llvm/Analysis/TargetLibraryInfo.h
|
||||||
|
+++ b/include/llvm/Analysis/TargetLibraryInfo.h
|
||||||
|
@@ -18,6 +18,15 @@
|
||||||
|
#include "llvm/IR/Module.h"
|
||||||
|
#include "llvm/Pass.h"
|
||||||
|
|
||||||
|
+#undef fopen64
|
||||||
|
+#undef fseeko64
|
||||||
|
+#undef fstat64
|
||||||
|
+#undef fstatvfs64
|
||||||
|
+#undef ftello64
|
||||||
|
+#undef lstat64
|
||||||
|
+#undef stat64
|
||||||
|
+#undef tmpfile64
|
||||||
|
+
|
||||||
|
namespace llvm {
|
||||||
|
/// VecDesc - Describes a possible vectorization of a function.
|
||||||
|
/// Function 'VectorFnName' is equivalent to 'ScalarFnName' vectorized
|
||||||
|
--
|
||||||
|
2.7.3
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
--- lib/Support/Unix/Memory.inc
|
||||||
|
+++ lib/Support/Unix/Memory.inc
|
||||||
|
@@ -126,8 +126,12 @@
|
||||||
|
Result.Address = Addr;
|
||||||
|
Result.Size = NumPages*PageSize;
|
||||||
|
|
||||||
|
- if (PFlags & MF_EXEC)
|
||||||
|
- Memory::InvalidateInstructionCache(Result.Address, Result.Size);
|
||||||
|
+ // Rely on protectMappedMemory to invalidate instruction cache.
|
||||||
|
+ if (PFlags & MF_EXEC) {
|
||||||
|
+ EC = Memory::protectMappedMemory (Result, PFlags);
|
||||||
|
+ if (EC != std::error_code())
|
||||||
|
+ return MemoryBlock();
|
||||||
|
+ }
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
@@ -156,15 +160,31 @@
|
||||||
|
return std::error_code(EINVAL, std::generic_category());
|
||||||
|
|
||||||
|
int Protect = getPosixProtectionFlags(Flags);
|
||||||
|
-
|
||||||
|
uintptr_t Start = alignAddr((uint8_t *)M.Address - PageSize + 1, PageSize);
|
||||||
|
uintptr_t End = alignAddr((uint8_t *)M.Address + M.Size, PageSize);
|
||||||
|
+
|
||||||
|
+ bool InvalidateCache = (Flags & MF_EXEC);
|
||||||
|
+
|
||||||
|
+#if defined(__arm__) || defined(__aarch64__)
|
||||||
|
+ // Certain ARM implementations treat icache clear instruction as a memory read,
|
||||||
|
+ // and CPU segfaults on trying to clear cache on !PROT_READ page. Therefore we need
|
||||||
|
+ // to temporarily add PROT_READ for the sake of flushing the instruction caches.
|
||||||
|
+ if (InvalidateCache && !(Protect & PROT_READ)) {
|
||||||
|
+ int Result = ::mprotect((void *)Start, End - Start, Protect | PROT_READ);
|
||||||
|
+ if (Result != 0)
|
||||||
|
+ return std::error_code(errno, std::generic_category());
|
||||||
|
+
|
||||||
|
+ Memory::InvalidateInstructionCache(M.Address, M.Size);
|
||||||
|
+ InvalidateCache = false;
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
int Result = ::mprotect((void *)Start, End - Start, Protect);
|
||||||
|
|
||||||
|
if (Result != 0)
|
||||||
|
return std::error_code(errno, std::generic_category());
|
||||||
|
|
||||||
|
- if (Flags & MF_EXEC)
|
||||||
|
+ if (InvalidateCache)
|
||||||
|
Memory::InvalidateInstructionCache(M.Address, M.Size);
|
||||||
|
|
||||||
|
return std::error_code();
|
|
@ -0,0 +1,13 @@
|
||||||
|
diff --git a/lib/Driver/ToolChains/CommonArgs.cpp b/lib/Driver/ToolChains/CommonArgs.cpp
|
||||||
|
index 6b6e276b8ce7..7896542a1202 100644
|
||||||
|
--- a/lib/Driver/ToolChains/CommonArgs.cpp
|
||||||
|
+++ b/lib/Driver/ToolChains/CommonArgs.cpp
|
||||||
|
@@ -409,7 +409,7 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args,
|
||||||
|
|
||||||
|
SmallString<1024> Plugin;
|
||||||
|
llvm::sys::path::native(
|
||||||
|
- Twine(D.Dir) + "/../lib" CLANG_LIBDIR_SUFFIX "/LLVMgold" + Suffix,
|
||||||
|
+ Twine("@libllvmLibdir@" "/LLVMgold") + Suffix,
|
||||||
|
Plugin);
|
||||||
|
CmdArgs.push_back(Args.MakeArgString(Plugin));
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
diff --git a/lib/Driver/ToolChains/CommonArgs.cpp b/lib/Driver/ToolChains/CommonArgs.cpp
|
||||||
|
index 37ec73468570..b73e75aa6e59 100644
|
||||||
|
--- a/lib/Driver/ToolChains/CommonArgs.cpp
|
||||||
|
+++ b/lib/Driver/ToolChains/CommonArgs.cpp
|
||||||
|
@@ -370,8 +370,8 @@ void tools::AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SmallString<1024> Plugin;
|
||||||
|
- llvm::sys::path::native(Twine(ToolChain.getDriver().Dir) +
|
||||||
|
- "/../lib" CLANG_LIBDIR_SUFFIX "/LLVMgold" +
|
||||||
|
+ llvm::sys::path::native(Twine("@libllvmLibdir@"
|
||||||
|
+ "/LLVMgold") +
|
||||||
|
Suffix,
|
||||||
|
Plugin);
|
||||||
|
CmdArgs.push_back(Args.MakeArgString(Plugin));
|
|
@ -0,0 +1,48 @@
|
||||||
|
{ lib, runCommand, stdenv, llvm, lld, version, release_version }:
|
||||||
|
|
||||||
|
let
|
||||||
|
targetPrefix = lib.optionalString (stdenv.hostPlatform != stdenv.targetPlatform) "${stdenv.targetPlatform.config}-";
|
||||||
|
in
|
||||||
|
runCommand "llvm-binutils-${version}"
|
||||||
|
{
|
||||||
|
preferLocalBuild = true;
|
||||||
|
passthru = {
|
||||||
|
isLLVM = true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
(''
|
||||||
|
mkdir -p $out/bin
|
||||||
|
for prog in ${lld}/bin/*; do
|
||||||
|
ln -s $prog $out/bin/${targetPrefix}$(basename $prog)
|
||||||
|
done
|
||||||
|
for prog in ${llvm}/bin/*; do
|
||||||
|
ln -sf $prog $out/bin/${targetPrefix}$(basename $prog)
|
||||||
|
done
|
||||||
|
|
||||||
|
llvmBin="${llvm}/bin"
|
||||||
|
|
||||||
|
ln -s $llvmBin/llvm-ar $out/bin/${targetPrefix}ar
|
||||||
|
ln -s $llvmBin/llvm-ar $out/bin/${targetPrefix}dlltool
|
||||||
|
ln -s $llvmBin/llvm-ar $out/bin/${targetPrefix}ranlib
|
||||||
|
ln -s $llvmBin/llvm-cxxfilt $out/bin/${targetPrefix}c++filt
|
||||||
|
ln -s $llvmBin/llvm-dwp $out/bin/${targetPrefix}dwp
|
||||||
|
ln -s $llvmBin/llvm-nm $out/bin/${targetPrefix}nm
|
||||||
|
ln -s $llvmBin/llvm-objcopy $out/bin/${targetPrefix}objcopy
|
||||||
|
ln -s $llvmBin/llvm-objcopy $out/bin/${targetPrefix}strip
|
||||||
|
ln -s $llvmBin/llvm-objdump $out/bin/${targetPrefix}objdump
|
||||||
|
ln -s $llvmBin/llvm-readobj $out/bin/${targetPrefix}readelf
|
||||||
|
ln -s $llvmBin/llvm-size $out/bin/${targetPrefix}size
|
||||||
|
ln -s $llvmBin/llvm-strings $out/bin/${targetPrefix}strings
|
||||||
|
ln -s $llvmBin/llvm-symbolizer $out/bin/${targetPrefix}addr2line
|
||||||
|
|
||||||
|
if [ -e "$llvmBin/llvm-debuginfod" ]; then
|
||||||
|
ln -s $llvmBin/llvm-debuginfod $out/bin/${targetPrefix}debuginfod
|
||||||
|
ln -s $llvmBin/llvm-debuginfod-find $out/bin/${targetPrefix}debuginfod-find
|
||||||
|
fi
|
||||||
|
|
||||||
|
ln -s ${lld}/bin/lld $out/bin/${targetPrefix}ld
|
||||||
|
|
||||||
|
# Only >=13 show GNU windres compatible in help
|
||||||
|
'' + lib.optionalString (lib.versionAtLeast release_version "13") ''
|
||||||
|
ln -s $llvmBin/llvm-rc $out/bin/${targetPrefix}windres
|
||||||
|
'')
|
|
@ -0,0 +1,30 @@
|
||||||
|
From 4add81bba40dcec62c4ea4481be8e35ac53e89d8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Will Dietz <w@wdtz.org>
|
||||||
|
Date: Thu, 18 May 2017 11:56:12 -0500
|
||||||
|
Subject: [PATCH] "purity" patch for 5.0
|
||||||
|
|
||||||
|
---
|
||||||
|
lib/Driver/ToolChains/Gnu.cpp | 7 -------
|
||||||
|
1 file changed, 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/lib/Driver/ToolChains/Gnu.cpp b/lib/Driver/ToolChains/Gnu.cpp
|
||||||
|
index fe3c0191bb..c6a482bece 100644
|
||||||
|
--- a/lib/Driver/ToolChains/Gnu.cpp
|
||||||
|
+++ b/lib/Driver/ToolChains/Gnu.cpp
|
||||||
|
@@ -494,13 +494,6 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
||||||
|
if (!Args.hasArg(options::OPT_static)) {
|
||||||
|
if (Args.hasArg(options::OPT_rdynamic))
|
||||||
|
CmdArgs.push_back("-export-dynamic");
|
||||||
|
-
|
||||||
|
- if (!Args.hasArg(options::OPT_shared)) {
|
||||||
|
- const std::string Loader =
|
||||||
|
- D.DyldPrefix + ToolChain.getDynamicLinker(Args);
|
||||||
|
- CmdArgs.push_back("-dynamic-linker");
|
||||||
|
- CmdArgs.push_back(Args.MakeArgString(Loader));
|
||||||
|
- }
|
||||||
|
}
|
||||||
|
|
||||||
|
CmdArgs.push_back("-o");
|
||||||
|
--
|
||||||
|
2.11.0
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
|
||||||
|
index 3f29afd35971..223d2769cdfc 100644
|
||||||
|
--- a/lib/Driver/Driver.cpp
|
||||||
|
+++ b/lib/Driver/Driver.cpp
|
||||||
|
@@ -491,6 +491,13 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+ {
|
||||||
|
+ Arg *A = DAL->MakeFlagArg(/*BaseArg=*/nullptr,
|
||||||
|
+ Opts.getOption(options::OPT_nostdlibinc));
|
||||||
|
+ A->claim();
|
||||||
|
+ DAL->append(A);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
return DAL;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,196 @@
|
||||||
|
{ lib
|
||||||
|
, stdenv
|
||||||
|
, llvm_meta
|
||||||
|
, release_version
|
||||||
|
, cmake
|
||||||
|
, zlib
|
||||||
|
, ncurses
|
||||||
|
, swig
|
||||||
|
, which
|
||||||
|
, libedit
|
||||||
|
, libxml2
|
||||||
|
, libllvm
|
||||||
|
, libclang
|
||||||
|
, python3
|
||||||
|
, version
|
||||||
|
, darwin
|
||||||
|
, lit
|
||||||
|
, makeWrapper
|
||||||
|
, lua5_3
|
||||||
|
, ninja
|
||||||
|
, runCommand
|
||||||
|
, src ? null
|
||||||
|
, monorepoSrc ? null
|
||||||
|
, patches ? [ ]
|
||||||
|
, enableManpages ? false
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
src' =
|
||||||
|
if monorepoSrc != null then
|
||||||
|
runCommand "lldb-src-${version}" { } ''
|
||||||
|
mkdir -p "$out"
|
||||||
|
cp -r ${monorepoSrc}/cmake "$out"
|
||||||
|
cp -r ${monorepoSrc}/lldb "$out"
|
||||||
|
'' else src;
|
||||||
|
in
|
||||||
|
|
||||||
|
stdenv.mkDerivation (rec {
|
||||||
|
passthru.monorepoSrc = monorepoSrc;
|
||||||
|
pname = "lldb";
|
||||||
|
inherit version;
|
||||||
|
|
||||||
|
src = src';
|
||||||
|
inherit patches;
|
||||||
|
|
||||||
|
outputs = [ "out" "lib" "dev" ];
|
||||||
|
|
||||||
|
sourceRoot = lib.optional (lib.versionAtLeast release_version "13") "${src.name}/${pname}";
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
cmake
|
||||||
|
python3
|
||||||
|
which
|
||||||
|
swig
|
||||||
|
lit
|
||||||
|
makeWrapper
|
||||||
|
lua5_3
|
||||||
|
] ++ lib.optionals enableManpages [
|
||||||
|
python3.pkgs.sphinx
|
||||||
|
python3.pkgs.recommonmark
|
||||||
|
] ++ lib.optionals (lib.versionAtLeast release_version "14") [
|
||||||
|
ninja
|
||||||
|
];
|
||||||
|
|
||||||
|
buildInputs = [
|
||||||
|
ncurses
|
||||||
|
zlib
|
||||||
|
libedit
|
||||||
|
libxml2
|
||||||
|
libllvm
|
||||||
|
] ++ lib.optionals stdenv.isDarwin [
|
||||||
|
darwin.libobjc
|
||||||
|
darwin.apple_sdk.libs.xpc
|
||||||
|
darwin.apple_sdk.frameworks.Foundation
|
||||||
|
darwin.bootstrap_cmds
|
||||||
|
darwin.apple_sdk.frameworks.Carbon
|
||||||
|
darwin.apple_sdk.frameworks.Cocoa
|
||||||
|
]
|
||||||
|
# The older libSystem used on x86_64 macOS is missing the
|
||||||
|
# `<bsm/audit_session.h>` header which `lldb` uses.
|
||||||
|
#
|
||||||
|
# We copy this header over from macOS 10.12 SDK.
|
||||||
|
#
|
||||||
|
# See here for context:
|
||||||
|
# https://github.com/NixOS/nixpkgs/pull/194634#issuecomment-1272129132
|
||||||
|
++ lib.optional
|
||||||
|
(
|
||||||
|
stdenv.targetPlatform.isDarwin
|
||||||
|
&& !stdenv.targetPlatform.isAarch64
|
||||||
|
&& (lib.versionAtLeast release_version "15")
|
||||||
|
)
|
||||||
|
(
|
||||||
|
runCommand "bsm-audit-session-header" { } ''
|
||||||
|
install -Dm444 \
|
||||||
|
"${lib.getDev darwin.apple_sdk.sdk}/include/bsm/audit_session.h" \
|
||||||
|
"$out/include/bsm/audit_session.h"
|
||||||
|
''
|
||||||
|
);
|
||||||
|
|
||||||
|
hardeningDisable = [ "format" ];
|
||||||
|
|
||||||
|
cmakeFlags = [
|
||||||
|
"-DLLDB_INCLUDE_TESTS=${if doCheck then "YES" else "NO"}"
|
||||||
|
"-DLLVM_ENABLE_RTTI=OFF"
|
||||||
|
"-DClang_DIR=${lib.getDev libclang}/lib/cmake"
|
||||||
|
"-DLLVM_EXTERNAL_LIT=${lit}/bin/lit"
|
||||||
|
] ++ lib.optionals stdenv.isDarwin [
|
||||||
|
"-DLLDB_USE_SYSTEM_DEBUGSERVER=ON"
|
||||||
|
] ++ lib.optionals (!stdenv.isDarwin) [
|
||||||
|
"-DLLDB_CODESIGN_IDENTITY=" # codesigning makes nondeterministic
|
||||||
|
] ++ lib.optionals enableManpages ([
|
||||||
|
"-DLLVM_ENABLE_SPHINX=ON"
|
||||||
|
"-DSPHINX_OUTPUT_MAN=ON"
|
||||||
|
"-DSPHINX_OUTPUT_HTML=OFF"
|
||||||
|
] ++ lib.optionals (lib.versionAtLeast release_version "15") [
|
||||||
|
# docs reference `automodapi` but it's not added to the extensions list when
|
||||||
|
# only building the manpages:
|
||||||
|
# https://github.com/llvm/llvm-project/blob/af6ec9200b09039573d85e349496c4f5b17c3d7f/lldb/docs/conf.py#L54
|
||||||
|
#
|
||||||
|
# so, we just ignore the resulting errors
|
||||||
|
"-DSPHINX_WARNINGS_AS_ERRORS=OFF"
|
||||||
|
]) ++ lib.optionals doCheck [
|
||||||
|
"-DLLDB_TEST_C_COMPILER=${stdenv.cc}/bin/${stdenv.cc.targetPrefix}cc"
|
||||||
|
"-DLLDB_TEST_CXX_COMPILER=${stdenv.cc}/bin/${stdenv.cc.targetPrefix}c++"
|
||||||
|
];
|
||||||
|
|
||||||
|
doCheck = false;
|
||||||
|
doInstallCheck = lib.versionOlder release_version "15";
|
||||||
|
|
||||||
|
# TODO: cleanup with mass-rebuild
|
||||||
|
installCheckPhase = ''
|
||||||
|
if [ ! -e $lib/${python3.sitePackages}/lldb/_lldb*.so ] ; then
|
||||||
|
echo "ERROR: python files not installed where expected!";
|
||||||
|
return 1;
|
||||||
|
fi
|
||||||
|
'' # Something lua is built on older versions but this file doesn't exist.
|
||||||
|
+ lib.optionalString (lib.versionAtLeast release_version "14") ''
|
||||||
|
if [ ! -e "$lib/lib/lua/${lua5_3.luaversion}/lldb.so" ] ; then
|
||||||
|
echo "ERROR: lua files not installed where expected!";
|
||||||
|
return 1;
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
|
||||||
|
postInstall = ''
|
||||||
|
wrapProgram $out/bin/lldb --prefix PYTHONPATH : $lib/${python3.sitePackages}/
|
||||||
|
|
||||||
|
# Editor support
|
||||||
|
# vscode:
|
||||||
|
install -D ../tools/lldb-vscode/package.json $out/share/vscode/extensions/llvm-org.lldb-vscode-0.1.0/package.json
|
||||||
|
mkdir -p $out/share/vscode/extensions/llvm-org.lldb-vscode-0.1.0/bin
|
||||||
|
ln -s $out/bin/*-vscode $out/share/vscode/extensions/llvm-org.lldb-vscode-0.1.0/bin
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = llvm_meta // {
|
||||||
|
homepage = "https://lldb.llvm.org/";
|
||||||
|
description = "A next-generation high-performance debugger";
|
||||||
|
longDescription = ''
|
||||||
|
LLDB is a next generation, high-performance debugger. It is built as a set
|
||||||
|
of reusable components which highly leverage existing libraries in the
|
||||||
|
larger LLVM Project, such as the Clang expression parser and LLVM
|
||||||
|
disassembler.
|
||||||
|
'';
|
||||||
|
# llvm <10 never built on aarch64-darwin since first introduction in nixpkgs
|
||||||
|
broken =
|
||||||
|
(lib.versionOlder release_version "11" && stdenv.isDarwin && stdenv.isAarch64)
|
||||||
|
|| (((lib.versions.major release_version) == "13") && stdenv.isDarwin);
|
||||||
|
};
|
||||||
|
} // lib.optionalAttrs enableManpages {
|
||||||
|
pname = "lldb-manpages";
|
||||||
|
|
||||||
|
buildPhase = lib.optionalString (lib.versionOlder release_version "15") ''
|
||||||
|
make ${if (lib.versionOlder release_version "12") then "docs-man" else "docs-lldb-man"}
|
||||||
|
'';
|
||||||
|
|
||||||
|
|
||||||
|
ninjaFlags = lib.optionals (lib.versionAtLeast release_version "15") [ "docs-lldb-man" ];
|
||||||
|
|
||||||
|
propagatedBuildInputs = [ ];
|
||||||
|
|
||||||
|
# manually install lldb man page
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out/share/man/man1
|
||||||
|
install docs/man/lldb.1 -t $out/share/man/man1/
|
||||||
|
'';
|
||||||
|
|
||||||
|
postPatch = null;
|
||||||
|
postInstall = null;
|
||||||
|
|
||||||
|
outputs = [ "out" ];
|
||||||
|
|
||||||
|
doCheck = false;
|
||||||
|
|
||||||
|
meta = llvm_meta // {
|
||||||
|
description = "man pages for LLDB ${version}";
|
||||||
|
};
|
||||||
|
})
|
|
@ -0,0 +1,11 @@
|
||||||
|
diff --git a/test/tools/llvm-exegesis/X86/uops-CMOV16rm-noreg.s b/test/tools/llvm-exegesis/X86/uops-CMOV16rm-noreg.s
|
||||||
|
index 3fc1f31d54dc..a4c9bdd92131 100644
|
||||||
|
--- a/test/tools/llvm-exegesis/X86/uops-CMOV16rm-noreg.s
|
||||||
|
+++ b/test/tools/llvm-exegesis/X86/uops-CMOV16rm-noreg.s
|
||||||
|
@@ -1,5 +1,6 @@
|
||||||
|
# RUN: llvm-exegesis -mode=uops -opcode-name=CMOV16rm -benchmarks-file=%t.CMOV16rm-uops.yaml
|
||||||
|
# RUN: FileCheck -check-prefixes=CHECK-YAML -input-file=%t.CMOV16rm-uops.yaml %s
|
||||||
|
+# RUN: sed -i 's,cpu_name:.*,cpu_name: bdver2,g' %t.CMOV16rm-uops.yaml
|
||||||
|
# RUN: llvm-exegesis -mcpu=bdver2 -mode=analysis -benchmarks-file=%t.CMOV16rm-uops.yaml -analysis-clusters-output-file=- -analysis-clustering-epsilon=0.1 -analysis-inconsistency-epsilon=0.1 -analysis-numpoints=1 -analysis-clustering=naive | FileCheck -check-prefixes=CHECK-CLUSTERS %s
|
||||||
|
|
||||||
|
# https://bugs.llvm.org/show_bug.cgi?id=41448
|
|
@ -0,0 +1,39 @@
|
||||||
|
From 1c936d7fda3275265e37f93697232a1ed652390f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Will Dietz <w@wdtz.org>
|
||||||
|
Date: Sat, 9 Jul 2016 19:22:54 -0500
|
||||||
|
Subject: [PATCH] musl fixes/hacks
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
|
||||||
|
include/__config
|
||||||
|
include/locale
|
||||||
|
src/locale.cpp
|
||||||
|
---
|
||||||
|
include/locale | 4 ++--
|
||||||
|
1 files changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/include/locale b/include/locale
|
||||||
|
index 3d804e8..9b01f5b 100644
|
||||||
|
--- a/include/locale
|
||||||
|
+++ b/include/locale
|
||||||
|
@@ -695,7 +695,7 @@ __num_get_signed_integral(const char* __a, const char* __a_end,
|
||||||
|
typename remove_reference<decltype(errno)>::type __save_errno = errno;
|
||||||
|
errno = 0;
|
||||||
|
char *__p2;
|
||||||
|
- long long __ll = strtoll_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
|
||||||
|
+ long long __ll = strtoll(__a, &__p2, __base);
|
||||||
|
typename remove_reference<decltype(errno)>::type __current_errno = errno;
|
||||||
|
if (__current_errno == 0)
|
||||||
|
errno = __save_errno;
|
||||||
|
@@ -735,7 +735,7 @@ __num_get_unsigned_integral(const char* __a, const char* __a_end,
|
||||||
|
typename remove_reference<decltype(errno)>::type __save_errno = errno;
|
||||||
|
errno = 0;
|
||||||
|
char *__p2;
|
||||||
|
- unsigned long long __ll = strtoull_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
|
||||||
|
+ unsigned long long __ll = strtoull(__a, &__p2, __base);
|
||||||
|
typename remove_reference<decltype(errno)>::type __current_errno = errno;
|
||||||
|
if (__current_errno == 0)
|
||||||
|
errno = __save_errno;
|
||||||
|
--
|
||||||
|
1.7.1
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
From 8c747d3157df2830eed9205e7caf1203b345de17 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Khem Raj <raj.khem@gmail.com>
|
||||||
|
Date: Sat, 4 Feb 2023 13:54:41 -0800
|
||||||
|
Subject: [PATCH] cmake: Enable 64bit off_t on 32bit glibc systems
|
||||||
|
|
||||||
|
Pass -D_FILE_OFFSET_BITS=64 to compiler flags on 32bit glibc based
|
||||||
|
systems. This will make sure that 64bit versions of LFS functions are
|
||||||
|
used e.g. seek will behave same as lseek64. Also revert [1] partially
|
||||||
|
because this added a cmake test to detect lseek64 but then forgot to
|
||||||
|
pass the needed macro to actual compile, this test was incomplete too
|
||||||
|
since libc implementations like musl has 64bit off_t by default on 32bit
|
||||||
|
systems and does not bundle[2] -D_LARGEFILE64_SOURCE under -D_GNU_SOURCE
|
||||||
|
like glibc, which means the compile now fails on musl because the cmake
|
||||||
|
check passes but we do not have _LARGEFILE64_SOURCE defined. Using the
|
||||||
|
*64 function was transitional anyways so use -D_FILE_OFFSET_BITS=64
|
||||||
|
instead
|
||||||
|
|
||||||
|
[1] https://github.com/llvm/llvm-project/commit/8db7e5e4eed4c4e697dc3164f2c9351d8c3e942b
|
||||||
|
[2] https://git.musl-libc.org/cgit/musl/commit/?id=25e6fee27f4a293728dd15b659170e7b9c7db9bc
|
||||||
|
|
||||||
|
Reviewed By: MaskRay
|
||||||
|
|
||||||
|
Differential Revision: https://reviews.llvm.org/D139752
|
||||||
|
|
||||||
|
(cherry picked from commit 5cd554303ead0f8891eee3cd6d25cb07f5a7bf67)
|
||||||
|
---
|
||||||
|
cmake/config-ix.cmake | 13 ++++++++++---
|
||||||
|
include/llvm/Config/config.h.cmake | 3 ---
|
||||||
|
lib/Support/raw_ostream.cpp | 2 --
|
||||||
|
3 files changed, 10 insertions(+), 8 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/cmake/config-ix.cmake b/cmake/config-ix.cmake
|
||||||
|
index 18977d9950ff..b558aa83fa62 100644
|
||||||
|
--- a/cmake/config-ix.cmake
|
||||||
|
+++ b/cmake/config-ix.cmake
|
||||||
|
@@ -197,9 +197,6 @@ check_symbol_exists(posix_fallocate fcntl.h HAVE_POSIX_FALLOCATE)
|
||||||
|
if( HAVE_SIGNAL_H AND NOT LLVM_USE_SANITIZER MATCHES ".*Address.*" AND NOT APPLE )
|
||||||
|
check_symbol_exists(sigaltstack signal.h HAVE_SIGALTSTACK)
|
||||||
|
endif()
|
||||||
|
-set(CMAKE_REQUIRED_DEFINITIONS "-D_LARGEFILE64_SOURCE")
|
||||||
|
-check_symbol_exists(lseek64 "sys/types.h;unistd.h" HAVE_LSEEK64)
|
||||||
|
-set(CMAKE_REQUIRED_DEFINITIONS "")
|
||||||
|
check_symbol_exists(mallctl malloc_np.h HAVE_MALLCTL)
|
||||||
|
check_symbol_exists(mallinfo malloc.h HAVE_MALLINFO)
|
||||||
|
check_symbol_exists(malloc_zone_statistics malloc/malloc.h
|
||||||
|
@@ -237,6 +234,16 @@ if( PURE_WINDOWS )
|
||||||
|
check_function_exists(__main HAVE___MAIN)
|
||||||
|
check_function_exists(__cmpdi2 HAVE___CMPDI2)
|
||||||
|
endif()
|
||||||
|
+
|
||||||
|
+check_symbol_exists(__GLIBC__ stdio.h LLVM_USING_GLIBC)
|
||||||
|
+if( LLVM_USING_GLIBC )
|
||||||
|
+# enable 64bit off_t on 32bit systems using glibc
|
||||||
|
+ if (CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||||
|
+ add_compile_definitions(_FILE_OFFSET_BITS=64)
|
||||||
|
+ list(APPEND CMAKE_REQUIRED_DEFINITIONS "-D_FILE_OFFSET_BITS=64")
|
||||||
|
+ endif()
|
||||||
|
+endif()
|
||||||
|
+
|
||||||
|
if( HAVE_DLFCN_H )
|
||||||
|
if( HAVE_LIBDL )
|
||||||
|
list(APPEND CMAKE_REQUIRED_LIBRARIES dl)
|
||||||
|
diff --git a/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake
|
||||||
|
index e934617d7ec7..3c39c373b3c1 100644
|
||||||
|
--- a/include/llvm/Config/config.h.cmake
|
||||||
|
+++ b/include/llvm/Config/config.h.cmake
|
||||||
|
@@ -112,9 +112,6 @@
|
||||||
|
/* Define to 1 if you have the <link.h> header file. */
|
||||||
|
#cmakedefine HAVE_LINK_H ${HAVE_LINK_H}
|
||||||
|
|
||||||
|
-/* Define to 1 if you have the `lseek64' function. */
|
||||||
|
-#cmakedefine HAVE_LSEEK64 ${HAVE_LSEEK64}
|
||||||
|
-
|
||||||
|
/* Define to 1 if you have the <mach/mach.h> header file. */
|
||||||
|
#cmakedefine HAVE_MACH_MACH_H ${HAVE_MACH_MACH_H}
|
||||||
|
|
||||||
|
diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp
|
||||||
|
index 038ad00bd608..921ab8409008 100644
|
||||||
|
--- a/lib/Support/raw_ostream.cpp
|
||||||
|
+++ b/lib/Support/raw_ostream.cpp
|
||||||
|
@@ -677,8 +677,6 @@ uint64_t raw_fd_ostream::seek(uint64_t off) {
|
||||||
|
flush();
|
||||||
|
#ifdef _WIN32
|
||||||
|
pos = ::_lseeki64(FD, off, SEEK_SET);
|
||||||
|
-#elif defined(HAVE_LSEEK64)
|
||||||
|
- pos = ::lseek64(FD, off, SEEK_SET);
|
||||||
|
#else
|
||||||
|
pos = ::lseek(FD, off, SEEK_SET);
|
||||||
|
#endif
|
||||||
|
--
|
||||||
|
2.37.1
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
diff --git llvm/tools/llvm-config/CMakeLists.txt llvm/tools/llvm-config/CMakeLists.txt
|
||||||
|
index 16ba54c0cf2f..20b017195e84 100644
|
||||||
|
--- llvm/tools/llvm-config/CMakeLists.txt
|
||||||
|
+++ llvm/tools/llvm-config/CMakeLists.txt
|
||||||
|
@@ -6,6 +6,7 @@ set(BUILDVARIABLES_OBJPATH ${CMAKE_CURRENT_BINARY_DIR}/BuildVariables.inc)
|
||||||
|
# Add the llvm-config tool.
|
||||||
|
add_llvm_tool(llvm-config
|
||||||
|
llvm-config.cpp
|
||||||
|
+ DISABLE_LLVM_LINK_LLVM_DYLIB
|
||||||
|
)
|
||||||
|
|
||||||
|
# Compute the substitution values for various items.
|
|
@ -0,0 +1,60 @@
|
||||||
|
{ runCommand,
|
||||||
|
clang,
|
||||||
|
gcc64,
|
||||||
|
gcc32,
|
||||||
|
glibc_multi
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
combine = basegcc: runCommand "combine-gcc-libc" {} ''
|
||||||
|
mkdir -p $out
|
||||||
|
cp -r ${basegcc.cc}/lib $out/lib
|
||||||
|
|
||||||
|
chmod u+rw -R $out/lib
|
||||||
|
cp -r ${basegcc.libc}/lib/* $(ls -d $out/lib/gcc/*/*)
|
||||||
|
'';
|
||||||
|
gcc_multi_sysroot = runCommand "gcc-multi-sysroot" {
|
||||||
|
passthru = {
|
||||||
|
inherit (gcc64) version;
|
||||||
|
lib = gcc_multi_sysroot;
|
||||||
|
};
|
||||||
|
} ''
|
||||||
|
mkdir -p $out/lib{,64}/gcc
|
||||||
|
|
||||||
|
ln -s ${combine gcc64}/lib/gcc/* $out/lib64/gcc/
|
||||||
|
ln -s ${combine gcc32}/lib/gcc/* $out/lib/gcc/
|
||||||
|
# XXX: This shouldn't be needed, clang just doesn't look for "i686-unknown"
|
||||||
|
ln -s $out/lib/gcc/i686-unknown-linux-gnu $out/lib/gcc/i686-pc-linux-gnu
|
||||||
|
|
||||||
|
|
||||||
|
# includes
|
||||||
|
mkdir -p $out/include
|
||||||
|
ln -s ${glibc_multi.dev}/include/* $out/include
|
||||||
|
ln -s ${gcc64.cc}/include/c++ $out/include/c++
|
||||||
|
|
||||||
|
# dynamic linkers
|
||||||
|
mkdir -p $out/lib/32
|
||||||
|
ln -s ${glibc_multi.out}/lib/ld-linux* $out/lib
|
||||||
|
ln -s ${glibc_multi.out}/lib/32/ld-linux* $out/lib/32/
|
||||||
|
'';
|
||||||
|
|
||||||
|
clangMulti = clang.override {
|
||||||
|
# Only used for providing expected structure re:dynamic linkers, AFAIK Most
|
||||||
|
# of the magic is done by setting the --gcc-toolchain option via
|
||||||
|
# `gccForLibs`.
|
||||||
|
libc = gcc_multi_sysroot;
|
||||||
|
|
||||||
|
bintools = clang.bintools.override {
|
||||||
|
libc = gcc_multi_sysroot;
|
||||||
|
};
|
||||||
|
|
||||||
|
gccForLibs = gcc_multi_sysroot // {
|
||||||
|
inherit (glibc_multi) libgcc;
|
||||||
|
langCC =
|
||||||
|
assert (gcc64.cc.langCC != gcc32.cc.langCC)
|
||||||
|
-> throw "(gcc64.cc.langCC=${gcc64.cc.langCC}) != (gcc32.cc.langCC=${gcc32.cc.langCC})";
|
||||||
|
gcc64.cc.langCC;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
in clangMulti
|
File diff suppressed because it is too large
Load Diff
37
nix/fsbl.nix
37
nix/fsbl.nix
|
@ -1,37 +0,0 @@
|
||||||
{ pkgs, board ? "zc706" }:
|
|
||||||
let
|
|
||||||
gnutoolchain = import ./gnutoolchain.nix { inherit pkgs; };
|
|
||||||
in
|
|
||||||
pkgs.stdenv.mkDerivation {
|
|
||||||
name = "${board}-fsbl";
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "Xilinx";
|
|
||||||
repo = "embeddedsw";
|
|
||||||
rev = "65c849ed46c88c67457e1fc742744f96db968ff1";
|
|
||||||
sha256 = "1rvl06ha40dzd6s9aa4sylmksh4xb9dqaxq462lffv1fdk342pda";
|
|
||||||
};
|
|
||||||
patches = [ ./fsbl.patch ];
|
|
||||||
nativeBuildInputs = [
|
|
||||||
pkgs.gnumake
|
|
||||||
gnutoolchain.binutils
|
|
||||||
gnutoolchain.gcc
|
|
||||||
];
|
|
||||||
patchPhase =
|
|
||||||
''
|
|
||||||
patch -p1 -i ${./fsbl.patch}
|
|
||||||
patchShebangs lib/sw_apps/zynq_fsbl/misc/copy_bsp.sh
|
|
||||||
echo 'SEARCH_DIR("${gnutoolchain.newlib}/arm-none-eabi/lib");' >> lib/sw_apps/zynq_fsbl/src/lscript.ld
|
|
||||||
'';
|
|
||||||
buildPhase =
|
|
||||||
''
|
|
||||||
cd lib/sw_apps/zynq_fsbl/src
|
|
||||||
make BOARD=${board} "CFLAGS=-DFSBL_DEBUG_INFO -g"
|
|
||||||
'';
|
|
||||||
installPhase =
|
|
||||||
''
|
|
||||||
mkdir $out
|
|
||||||
cp fsbl.elf $out
|
|
||||||
'';
|
|
||||||
doCheck = false;
|
|
||||||
dontFixup = true;
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
diff --git a/lib/sw_apps/zynq_fsbl/src/Makefile b/lib/sw_apps/zynq_fsbl/src/Makefile
|
|
||||||
index 0e3ccdf1c5..a5b02f386e 100644
|
|
||||||
--- a/lib/sw_apps/zynq_fsbl/src/Makefile
|
|
||||||
+++ b/lib/sw_apps/zynq_fsbl/src/Makefile
|
|
||||||
@@ -71,11 +71,14 @@ endif
|
|
||||||
all: $(EXEC)
|
|
||||||
|
|
||||||
$(EXEC): $(LIBS) $(OBJS) $(INCLUDES)
|
|
||||||
- cp $(BSP_DIR)/$(BOARD)/ps7_init.* .
|
|
||||||
$(LINKER) $(LD1FLAGS) -o $@ $(OBJS) $(LDFLAGS)
|
|
||||||
rm -rf $(OBJS)
|
|
||||||
-
|
|
||||||
-
|
|
||||||
+
|
|
||||||
+.PHONY: ps7_init
|
|
||||||
+
|
|
||||||
+ps7_init:
|
|
||||||
+ cp $(BSP_DIR)/$(BOARD)/ps7_init.* .
|
|
||||||
+
|
|
||||||
$(LIBS):
|
|
||||||
echo "Copying BSP files"
|
|
||||||
$(BSP_DIR)/copy_bsp.sh $(BOARD) $(CC)
|
|
||||||
@@ -86,7 +89,7 @@ $(LIBS):
|
|
||||||
make -C $(BSP_DIR) -k all "CC=armcc" "AR=armar" "C_FLAGS= -O2 -c" "EC_FLAGS=--debug --wchar32"; \
|
|
||||||
fi;
|
|
||||||
|
|
||||||
-%.o:%.c
|
|
||||||
+%.o:%.c ps7_init
|
|
||||||
$(CC) $(CC_FLAGS) $(CFLAGS) $(ECFLAGS) -c $< -o $@ $(INCLUDEPATH)
|
|
||||||
|
|
||||||
%.o:%.S
|
|
|
@ -1,134 +0,0 @@
|
||||||
{ pkgs ? import <nixpkgs> }:
|
|
||||||
let
|
|
||||||
|
|
||||||
platform = "arm-none-eabi";
|
|
||||||
|
|
||||||
binutils-pkg = { stdenv, buildPackages
|
|
||||||
, fetchurl, zlib
|
|
||||||
, extraConfigureFlags ? []
|
|
||||||
}:
|
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
|
||||||
basename = "binutils";
|
|
||||||
version = "2.30";
|
|
||||||
name = "${basename}-${platform}-${version}";
|
|
||||||
src = fetchurl {
|
|
||||||
url = "https://ftp.gnu.org/gnu/binutils/binutils-${version}.tar.bz2";
|
|
||||||
sha256 = "028cklfqaab24glva1ks2aqa1zxa6w6xmc8q34zs1sb7h22dxspg";
|
|
||||||
};
|
|
||||||
configureFlags = [
|
|
||||||
"--enable-deterministic-archives"
|
|
||||||
"--target=${platform}"
|
|
||||||
"--with-cpu=cortex-a9"
|
|
||||||
"--with-fpu=vfpv3"
|
|
||||||
"--with-float=hard"
|
|
||||||
"--with-mode=thumb"
|
|
||||||
] ++ extraConfigureFlags;
|
|
||||||
outputs = [ "out" "info" "man" ];
|
|
||||||
depsBuildBuild = [ buildPackages.stdenv.cc ];
|
|
||||||
buildInputs = [ zlib ];
|
|
||||||
enableParallelBuilding = true;
|
|
||||||
meta = {
|
|
||||||
description = "Tools for manipulating binaries (linker, assembler, etc.)";
|
|
||||||
longDescription = ''
|
|
||||||
The GNU Binutils are a collection of binary tools. The main
|
|
||||||
ones are `ld' (the GNU linker) and `as' (the GNU assembler).
|
|
||||||
They also include the BFD (Binary File Descriptor) library,
|
|
||||||
`gprof', `nm', `strip', etc.
|
|
||||||
'';
|
|
||||||
homepage = http://www.gnu.org/software/binutils/;
|
|
||||||
license = stdenv.lib.licenses.gpl3Plus;
|
|
||||||
/* Give binutils a lower priority than gcc-wrapper to prevent a
|
|
||||||
collision due to the ld/as wrappers/symlinks in the latter. */
|
|
||||||
priority = "10";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
gcc-pkg = { stdenv, buildPackages
|
|
||||||
, fetchurl, gmp, mpfr, libmpc, platform-binutils
|
|
||||||
, extraConfigureFlags ? []
|
|
||||||
}:
|
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
|
||||||
basename = "gcc";
|
|
||||||
version = "9.1.0";
|
|
||||||
name = "${basename}-${platform}-${version}";
|
|
||||||
src = fetchurl {
|
|
||||||
url = "https://ftp.gnu.org/gnu/gcc/gcc-${version}/gcc-${version}.tar.xz";
|
|
||||||
sha256 = "1817nc2bqdc251k0lpc51cimna7v68xjrnvqzvc50q3ax4s6i9kr";
|
|
||||||
};
|
|
||||||
preConfigure =
|
|
||||||
''
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
'';
|
|
||||||
configureScript = "../configure";
|
|
||||||
configureFlags =
|
|
||||||
[ "--target=${platform}"
|
|
||||||
"--with-arch=armv7-a"
|
|
||||||
"--with-tune=cortex-a9"
|
|
||||||
"--with-fpu=vfpv3"
|
|
||||||
"--with-float=hard"
|
|
||||||
"--disable-libssp"
|
|
||||||
"--enable-languages=c"
|
|
||||||
"--with-as=${platform-binutils}/bin/${platform}-as"
|
|
||||||
"--with-ld=${platform-binutils}/bin/${platform}-ld" ] ++ extraConfigureFlags;
|
|
||||||
outputs = [ "out" "info" "man" ];
|
|
||||||
hardeningDisable = [ "format" "pie" ];
|
|
||||||
propagatedBuildInputs = [ gmp mpfr libmpc platform-binutils ];
|
|
||||||
enableParallelBuilding = true;
|
|
||||||
dontFixup = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
newlib-pkg = { stdenv, fetchurl, buildPackages, platform-binutils, platform-gcc }:
|
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
|
||||||
pname = "newlib";
|
|
||||||
version = "3.1.0";
|
|
||||||
src = fetchurl {
|
|
||||||
url = "ftp://sourceware.org/pub/newlib/newlib-${version}.tar.gz";
|
|
||||||
sha256 = "0ahh3n079zjp7d9wynggwrnrs27440aac04340chf1p9476a2kzv";
|
|
||||||
};
|
|
||||||
|
|
||||||
nativeBuildInputs = [ platform-binutils platform-gcc ];
|
|
||||||
|
|
||||||
configureFlags = [
|
|
||||||
"--target=${platform}"
|
|
||||||
|
|
||||||
"--with-cpu=cortex-a9"
|
|
||||||
"--with-fpu=vfpv3"
|
|
||||||
"--with-float=hard"
|
|
||||||
"--with-mode=thumb"
|
|
||||||
"--enable-interwork"
|
|
||||||
"--disable-multilib"
|
|
||||||
|
|
||||||
"--disable-newlib-supplied-syscalls"
|
|
||||||
"--with-gnu-ld"
|
|
||||||
"--with-gnu-as"
|
|
||||||
"--disable-newlib-io-float"
|
|
||||||
"--disable-werror"
|
|
||||||
];
|
|
||||||
dontFixup = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
in rec {
|
|
||||||
binutils-bootstrap = pkgs.callPackage binutils-pkg { };
|
|
||||||
gcc-bootstrap = pkgs.callPackage gcc-pkg {
|
|
||||||
platform-binutils = binutils-bootstrap;
|
|
||||||
extraConfigureFlags = [ "--disable-libgcc" ];
|
|
||||||
};
|
|
||||||
newlib = pkgs.callPackage newlib-pkg {
|
|
||||||
platform-binutils = binutils-bootstrap;
|
|
||||||
platform-gcc = gcc-bootstrap;
|
|
||||||
};
|
|
||||||
binutils = pkgs.callPackage binutils-pkg {
|
|
||||||
extraConfigureFlags = [ "--with-lib-path=${newlib}/arm-none-eabi/lib" ];
|
|
||||||
};
|
|
||||||
gcc = pkgs.callPackage gcc-pkg {
|
|
||||||
platform-binutils = binutils;
|
|
||||||
extraConfigureFlags = [ "--enable-newlib" "--with-headers=${newlib}/arm-none-eabi/include" ];
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
{ pkgs }:
|
|
||||||
|
|
||||||
pkgs.stdenv.mkDerivation {
|
|
||||||
pname = "mkbootimage";
|
|
||||||
version = "2.2";
|
|
||||||
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "antmicro";
|
|
||||||
repo = "zynq-mkbootimage";
|
|
||||||
rev = "4ee42d782a9ba65725ed165a4916853224a8edf7";
|
|
||||||
sha256 = "1k1mbsngqadqihzjgvwvsrkvryxy5ladpxd9yh9iqn2s7fxqwqa9";
|
|
||||||
};
|
|
||||||
|
|
||||||
propagatedBuildInputs = [ pkgs.libelf pkgs.pcre ];
|
|
||||||
patchPhase =
|
|
||||||
''
|
|
||||||
substituteInPlace Makefile --replace "git rev-parse --short HEAD" "echo nix"
|
|
||||||
'';
|
|
||||||
installPhase =
|
|
||||||
''
|
|
||||||
mkdir -p $out/bin
|
|
||||||
cp mkbootimage $out/bin
|
|
||||||
'';
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
let
|
|
||||||
pkgs = import <nixpkgs> {};
|
|
||||||
overlay = pkgs.fetchFromGitHub {
|
|
||||||
owner = "mozilla";
|
|
||||||
repo = "nixpkgs-mozilla";
|
|
||||||
rev = "efda5b357451dbb0431f983cca679ae3cd9b9829";
|
|
||||||
sha256 = "11wqrg86g3qva67vnk81ynvqyfj0zxk83cbrf0p9hsvxiwxs8469";
|
|
||||||
};
|
|
||||||
in
|
|
||||||
import overlay
|
|
|
@ -1,24 +0,0 @@
|
||||||
{ pkgs }:
|
|
||||||
|
|
||||||
let
|
|
||||||
rustcSrc = pkgs.fetchgit {
|
|
||||||
url = "https://github.com/rust-lang/rust.git";
|
|
||||||
# sync with git_commit_hash from pkg.rust in channel-rust-nightly.toml
|
|
||||||
rev = "5ef299eb9805b4c86b227b718b39084e8bf24454";
|
|
||||||
sha256 = "0gc9hmb1sfkaf3ba8fsynl1n6bs8nk65hbhhx7ss89dfkrsxrn0x";
|
|
||||||
fetchSubmodules = true;
|
|
||||||
};
|
|
||||||
rustManifest = ./channel-rust-nightly.toml;
|
|
||||||
|
|
||||||
targets = [];
|
|
||||||
rustChannelOfTargets = _channel: _date: targets:
|
|
||||||
(pkgs.lib.rustLib.fromManifestFile rustManifest {
|
|
||||||
inherit (pkgs) stdenv fetchurl patchelf;
|
|
||||||
}).rust.override { inherit targets; };
|
|
||||||
rust =
|
|
||||||
rustChannelOfTargets "nightly" null targets;
|
|
||||||
in
|
|
||||||
pkgs.recurseIntoAttrs (pkgs.makeRustPlatform {
|
|
||||||
rustc = rust // { src = rustcSrc; };
|
|
||||||
cargo = rust;
|
|
||||||
})
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
set XC7_JSHUTDOWN 0x0d
|
||||||
|
set XC7_JPROGRAM 0x0b
|
||||||
|
set XC7_JSTART 0x0c
|
||||||
|
set XC7_BYPASS 0x3f
|
||||||
|
|
||||||
|
proc xc7_program {tap} {
|
||||||
|
global XC7_JSHUTDOWN XC7_JPROGRAM XC7_JSTART XC7_BYPASS
|
||||||
|
irscan $tap $XC7_JSHUTDOWN
|
||||||
|
irscan $tap $XC7_JPROGRAM
|
||||||
|
runtest 60000
|
||||||
|
#JSTART prevents this from working...
|
||||||
|
#irscan $tap $XC7_JSTART
|
||||||
|
runtest 2000
|
||||||
|
irscan $tap $XC7_BYPASS
|
||||||
|
runtest 2000
|
||||||
|
}
|
||||||
|
|
||||||
|
pld device virtex2 zynq.tap 1
|
||||||
|
init
|
||||||
|
xc7_program zynq.tap
|
|
@ -5,35 +5,15 @@ set PL_TAPID 0x13722093
|
||||||
set SMP 1
|
set SMP 1
|
||||||
|
|
||||||
source ./zynq-7000.cfg
|
source ./zynq-7000.cfg
|
||||||
source ./xilinx-tcl.cfg
|
|
||||||
|
|
||||||
reset_config srst_only srst_push_pull
|
reset_config srst_only srst_push_pull
|
||||||
|
|
||||||
set XC7_JSHUTDOWN 0x0d
|
source ./common.cfg
|
||||||
set XC7_JPROGRAM 0x0b
|
|
||||||
set XC7_JSTART 0x0c
|
|
||||||
set XC7_BYPASS 0x3f
|
|
||||||
|
|
||||||
proc xc7_program {tap} {
|
|
||||||
global XC7_JSHUTDOWN XC7_JPROGRAM XC7_JSTART XC7_BYPASS
|
|
||||||
irscan $tap $XC7_JSHUTDOWN
|
|
||||||
irscan $tap $XC7_JPROGRAM
|
|
||||||
runtest 60000
|
|
||||||
#JSTART prevents this from working...
|
|
||||||
#irscan $tap $XC7_JSTART
|
|
||||||
runtest 2000
|
|
||||||
irscan $tap $XC7_BYPASS
|
|
||||||
runtest 2000
|
|
||||||
}
|
|
||||||
|
|
||||||
pld device virtex2 zynq.tap 1
|
|
||||||
init
|
|
||||||
xc7_program zynq.tap
|
|
||||||
|
|
||||||
reset halt
|
reset halt
|
||||||
|
|
||||||
# Disable MMU
|
# Disable MMU
|
||||||
targets $_TARGETNAME_1
|
targets $_TARGETNAME_1
|
||||||
arm mcr 15 0 1 0 0 [expr [arm mrc 15 0 1 0 0] & ~0xd]
|
arm mcr 15 0 1 0 0 [expr { [arm mrc 15 0 1 0 0] & ~0xd }]
|
||||||
targets $_TARGETNAME_0
|
targets $_TARGETNAME_0
|
||||||
arm mcr 15 0 1 0 0 [expr [arm mrc 15 0 1 0 0] & ~0xd]
|
arm mcr 15 0 1 0 0 [expr { [arm mrc 15 0 1 0 0] & ~0xd }]
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
# this supports JTAG-HS2 (and apparently Nexys4 as well)
|
# this supports JTAG-HS2 (and apparently Nexys4 as well)
|
||||||
|
|
||||||
interface ftdi
|
adapter driver ftdi
|
||||||
ftdi_vid_pid 0x0403 0x6014
|
ftdi_vid_pid 0x0403 0x6014
|
||||||
|
|
||||||
ftdi_channel 0
|
ftdi_channel 0
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue