Compare commits
No commits in common. "master" and "master" have entirely different histories.
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1 @@
|
|||||||
/target
|
/target
|
||||||
result*
|
|
||||||
|
63
Cargo.lock
generated
63
Cargo.lock
generated
@ -1,7 +1,5 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bit_field"
|
name = "bit_field"
|
||||||
version = "0.10.1"
|
version = "0.10.1"
|
||||||
@ -10,44 +8,46 @@ checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.3.2"
|
version = "1.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.3.0"
|
version = "1.3.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "60f0b0d4c0a382d2734228fd12b5a6b5dac185c60e938026fd31b265b94f9bd2"
|
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.73"
|
version = "1.0.66"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.0"
|
version = "0.1.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "compiler_builtins"
|
name = "compiler_builtins"
|
||||||
version = "0.1.49"
|
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 = "20b1438ef42c655665a8ab2c1c6d605a305f031d38d9be689ddfef41a20f3aa2"
|
checksum = "3748f82c7d366a0b4950257d19db685d4958d2fa27c6d164a3f069fec42b748b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core_io"
|
name = "core_io"
|
||||||
version = "0.1.0"
|
version = "0.1.20200410"
|
||||||
source = "git+https://git.m-labs.hk/M-Labs/rs-core_io.git?rev=e9d3edf027#e9d3edf0272502b0dd6c26e8a4869c2912657615"
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embedded-hal"
|
name = "embedded-hal"
|
||||||
version = "0.2.7"
|
version = "0.2.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff"
|
checksum = "fa998ce59ec9765d15216393af37a58961ddcefb14c753b4816ba2191d865fcb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nb 0.1.3",
|
"nb 0.1.3",
|
||||||
"void",
|
"void",
|
||||||
@ -68,8 +68,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fatfs"
|
name = "fatfs"
|
||||||
version = "0.3.6"
|
version = "0.3.4"
|
||||||
source = "git+https://git.m-labs.hk/M-Labs/rust-fatfs.git?rev=4b5e420084#4b5e420084fd1c4a9c105680b687523909b6469c"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "93079df23039e52059e1f03b4c29fb0c72da2c792aad91bb2236c9fb81d3592e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
@ -147,15 +148,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linked_list_allocator"
|
name = "linked_list_allocator"
|
||||||
version = "0.8.11"
|
version = "0.8.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "822add9edb1860698b79522510da17bef885171f75aa395cff099d770c609c24"
|
checksum = "4e6766dff3bf932e0d1c7f1cf27c0a46008f7839f85b015a312c276a4570a399"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.14"
|
version = "0.4.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
@ -166,6 +167,12 @@ 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"
|
checksum = "c75de51135344a4f8ed3cfe2720dc27736f7711989703a0b43aadf3753c55577"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nb"
|
name = "nb"
|
||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
@ -195,9 +202,9 @@ checksum = "bd7a31eed1591dcbc95d92ad7161908e72f4677f8fabf2a32ca49b4237cbf211"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smoltcp"
|
name = "smoltcp"
|
||||||
version = "0.7.5"
|
version = "0.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3e4a069bef843d170df47e7c0a8bf8d037f217d9f5b325865acc3e466ffe40d3"
|
checksum = "0fe46639fd2ec79eadf8fe719f237a7a0bd4dac5d957f1ca5bbdbc1c3c39e53a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
@ -220,9 +227,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vcell"
|
name = "vcell"
|
||||||
version = "0.1.3"
|
version = "0.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002"
|
checksum = "876e32dcadfe563a4289e994f7cb391197f362b6315dc45e8ba4aa6f564a4b3c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "void"
|
name = "void"
|
||||||
@ -232,9 +239,9 @@ checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "volatile-register"
|
name = "volatile-register"
|
||||||
version = "0.2.1"
|
version = "0.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6"
|
checksum = "0d67cb4616d99b940db1d6bd28844ff97108b498a6ca850e5b6191a532063286"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"vcell",
|
"vcell",
|
||||||
]
|
]
|
||||||
|
@ -6,6 +6,7 @@ members = [
|
|||||||
"libsupport_zynq",
|
"libsupport_zynq",
|
||||||
"libasync",
|
"libasync",
|
||||||
"libconfig",
|
"libconfig",
|
||||||
|
"libcoreio",
|
||||||
"experiments",
|
"experiments",
|
||||||
"szl",
|
"szl",
|
||||||
]
|
]
|
||||||
@ -14,7 +15,10 @@ members = [
|
|||||||
panic = "abort"
|
panic = "abort"
|
||||||
debug = true
|
debug = true
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
opt-level = 's'
|
opt-level = 'z'
|
||||||
lto = true
|
lto = true
|
||||||
debug-assertions = false
|
debug-assertions = false
|
||||||
overflow-checks = false
|
overflow-checks = false
|
||||||
|
|
||||||
|
[patch.crates-io]
|
||||||
|
core_io = { path = "./libcoreio" }
|
||||||
|
165
LICENSE
165
LICENSE
@ -1,165 +0,0 @@
|
|||||||
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.
|
|
27
README.md
27
README.md
@ -13,37 +13,24 @@ Supported features:
|
|||||||
|
|
||||||
|
|
||||||
Supported boards:
|
Supported boards:
|
||||||
* Kasli-SoC
|
|
||||||
* ZC706
|
* ZC706
|
||||||
* Red Pitaya
|
* Red Pitaya
|
||||||
* Cora Z7-10 (seems to also run on Cora Z7-07S, including dual-core support)
|
* Cora Z7-10 (seems to also run on Cora Z7-07S, including dual-core support)
|
||||||
|
|
||||||
## Build
|
## 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 build .#coraz7-experiments
|
nix-shell --command "cargo xbuild --release -p experiments"
|
||||||
```
|
```
|
||||||
|
|
||||||
Alternatively, you can still use ``cargo xbuild`` within ``nix develop`` shell.
|
Currently the ELF output is placed at `target/armv7-none-eabihf/release/experiments`
|
||||||
|
|
||||||
```shell
|
|
||||||
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
|
## Debug
|
||||||
|
|
||||||
### Running on the ZC706
|
### Running on the ZC706
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
nix develop
|
nix-shell --command "cargo xbuild --release -p experiments"
|
||||||
cargo xbuild --release -p experiments
|
|
||||||
cd openocd
|
cd openocd
|
||||||
openocd -f zc706.cfg
|
openocd -f zc706.cfg
|
||||||
```
|
```
|
||||||
@ -51,8 +38,7 @@ openocd -f zc706.cfg
|
|||||||
### Running on the Cora Z7-10
|
### Running on the Cora Z7-10
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
nix develop
|
nix-shell --command "cd experiments && cargo xbuild --release --no-default-features --features=target_coraz7"
|
||||||
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
|
||||||
```
|
```
|
||||||
@ -62,8 +48,3 @@ openocd -f cora-z7-10.cfg
|
|||||||
```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.
|
|
||||||
|
@ -1,4 +1,12 @@
|
|||||||
{
|
{
|
||||||
|
"abi-blacklist": [
|
||||||
|
"stdcall",
|
||||||
|
"fastcall",
|
||||||
|
"vectorcall",
|
||||||
|
"thiscall",
|
||||||
|
"win64",
|
||||||
|
"sysv64"
|
||||||
|
],
|
||||||
"arch": "arm",
|
"arch": "arm",
|
||||||
"data-layout": "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",
|
"data-layout": "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",
|
||||||
"emit-debug-gdb-scripts": false,
|
"emit-debug-gdb-scripts": false,
|
||||||
|
48
default.nix
Normal file
48
default.nix
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
let
|
||||||
|
pkgs = import <nixpkgs> { overlays = [ (import ./nix/mozilla-overlay.nix) ]; };
|
||||||
|
rustPlatform = (import ./nix/rust-platform.nix { inherit pkgs; });
|
||||||
|
cargo-xbuild = (pkgs.cargo-xbuild.overrideAttrs(oa: { patches = oa.patches ++ [ ./xbuild_writable_lockfile.diff ]; } ));
|
||||||
|
cargoSha256Experiments = "034l4sxy4adgd97v0ldk844j6m62v8lflavzhs9wnk82mzihglgp";
|
||||||
|
cargoSha256SZL = "0p9bvydk8jrzpc57cn7x9k5m89x1g0vfvar7i5gph7q9pvnkh6sh";
|
||||||
|
build-crate = name: crate: features: cargoSha256:
|
||||||
|
rustPlatform.buildRustPackage rec {
|
||||||
|
name = "${crate}";
|
||||||
|
|
||||||
|
src = builtins.filterSource (path: type:
|
||||||
|
baseNameOf path != "target"
|
||||||
|
) ./.;
|
||||||
|
inherit cargoSha256;
|
||||||
|
|
||||||
|
nativeBuildInputs = [ cargo-xbuild pkgs.llvmPackages_9.clang-unwrapped ];
|
||||||
|
buildPhase = ''
|
||||||
|
export XARGO_RUST_SRC="${rustPlatform.rust.rustc}/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;
|
||||||
|
};
|
||||||
|
|
||||||
|
targetCrates = target: {
|
||||||
|
"${target}-experiments" = build-crate "${target}-experiments" "experiments" "target_${target}" cargoSha256Experiments;
|
||||||
|
"${target}-szl" = build-crate "${target}-szl" "szl" "target_${target}" cargoSha256SZL;
|
||||||
|
};
|
||||||
|
targets = ["zc706" "coraz7" "redpitaya" "kasli_soc"];
|
||||||
|
in
|
||||||
|
{
|
||||||
|
inherit cargo-xbuild;
|
||||||
|
zc706-fsbl = import ./nix/fsbl.nix { inherit pkgs; };
|
||||||
|
} // (builtins.foldl' (results: target:
|
||||||
|
results // targetCrates target
|
||||||
|
) {} targets)
|
@ -8,7 +8,6 @@ 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_coraz7 = ["libboard_zynq/target_coraz7", "libsupport_zynq/target_coraz7"]
|
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"]
|
target_kasli_soc = ["libboard_zynq/target_kasli_soc", "libsupport_zynq/target_kasli_soc"]
|
||||||
default = ["target_zc706"]
|
default = ["target_zc706"]
|
||||||
@ -19,5 +18,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", "dummy_fiq_handler"]}
|
libsupport_zynq = { path = "../libsupport_zynq", default-features = false, features = ["panic_handler"]}
|
||||||
libasync = { path = "../libasync" }
|
libasync = { path = "../libasync" }
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
#![allow(incomplete_features)]
|
#![feature(const_in_array_repeat_expressions)]
|
||||||
#![feature(naked_functions)]
|
#![feature(naked_functions)]
|
||||||
#![feature(asm)]
|
#![feature(asm)]
|
||||||
#![feature(inline_const)]
|
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
use alloc::collections::BTreeMap;
|
use alloc::collections::BTreeMap;
|
||||||
use core::arch::asm;
|
|
||||||
use libasync::{
|
use libasync::{
|
||||||
delay,
|
delay,
|
||||||
smoltcp::{Sockets, TcpStream},
|
smoltcp::{Sockets, TcpStream},
|
||||||
@ -41,7 +39,7 @@ use libcortex_a9::{
|
|||||||
};
|
};
|
||||||
use libregister::{RegisterR, RegisterW};
|
use libregister::{RegisterR, RegisterW};
|
||||||
use libsupport_zynq::{
|
use libsupport_zynq::{
|
||||||
boot, exception_vectors, ram,
|
boot, ram,
|
||||||
};
|
};
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use core::sync::atomic::{AtomicBool, Ordering};
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
@ -58,29 +56,19 @@ extern "C" {
|
|||||||
static CORE1_RESTART: AtomicBool = AtomicBool::new(false);
|
static CORE1_RESTART: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
||||||
interrupt_handler!(IRQ, irq, __irq_stack0_start, __irq_stack1_start, {
|
interrupt_handler!(IRQ, irq, __irq_stack0_start, __irq_stack1_start, {
|
||||||
let mpcore = mpcore::RegisterBlock::mpcore();
|
if MPIDR.read().cpu_id() == 1{
|
||||||
let mut gic = gic::InterruptController::gic(mpcore);
|
let mpcore = mpcore::RegisterBlock::mpcore();
|
||||||
let id = gic.get_interrupt_id();
|
let mut gic = gic::InterruptController::gic(mpcore);
|
||||||
match MPIDR.read().cpu_id(){
|
let id = gic.get_interrupt_id();
|
||||||
0 => {
|
if id.0 == 0 {
|
||||||
if id.0 == 0 {
|
gic.end_interrupt(id);
|
||||||
println!("Interrupting core0...");
|
asm::exit_irq();
|
||||||
gic.end_interrupt(id);
|
SP.write(&mut __stack1_start as *mut _ as u32);
|
||||||
return;
|
asm::enable_irq();
|
||||||
}
|
CORE1_RESTART.store(false, Ordering::Relaxed);
|
||||||
},
|
notify_spin_lock();
|
||||||
1 => {
|
main_core1();
|
||||||
if id.0 == 0 {
|
}
|
||||||
gic.end_interrupt(id);
|
|
||||||
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");
|
||||||
@ -98,7 +86,6 @@ 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(0x8);
|
enable_l2_cache(0x8);
|
||||||
println!("\nZynq experiments");
|
println!("\nZynq experiments");
|
||||||
@ -118,7 +105,6 @@ pub fn main_core0() {
|
|||||||
|
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
feature = "target_zc706",
|
feature = "target_zc706",
|
||||||
feature = "target_ebaz4205",
|
|
||||||
feature = "target_redpitaya",
|
feature = "target_redpitaya",
|
||||||
feature = "target_kasli_soc",
|
feature = "target_kasli_soc",
|
||||||
))]
|
))]
|
||||||
@ -148,10 +134,6 @@ 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 };
|
||||||
@ -201,20 +183,6 @@ 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");
|
||||||
|
|
||||||
|
49
flake.lock
generated
49
flake.lock
generated
@ -1,49 +0,0 @@
|
|||||||
{
|
|
||||||
"nodes": {
|
|
||||||
"nixpkgs": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1734529975,
|
|
||||||
"narHash": "sha256-ze3IJksru9dN0keqUxY0WNf8xrwfs8Ty/z9v/keyBbg=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "72d11d40b9878a67c38f003c240c2d2e1811e72a",
|
|
||||||
"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
|
|
||||||
}
|
|
177
flake.nix
177
flake.nix
@ -1,177 +0,0 @@
|
|||||||
{
|
|
||||||
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-09-01".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;
|
|
||||||
};
|
|
||||||
|
|
||||||
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;
|
|
||||||
outputHashes = {
|
|
||||||
"core_io-0.1.0" = "sha256-0HINFWRiJx8pjMgUOL/CS336ih7SENSRh3Kah9LPRrw=";
|
|
||||||
"fatfs-0.3.6" = "sha256-Nz9hCq/1YgSXF8ltJ5ZawV0Hc8WV44KNK0tJdVnNb4U=";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
nativeBuildInputs = [ cargo-xbuild pkgs.llvmPackages_13.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;
|
|
||||||
|
|
||||||
devShell.x86_64-linux = pkgs.mkShell {
|
|
||||||
name = "zynq-rs-dev-shell";
|
|
||||||
buildInputs = [
|
|
||||||
rust
|
|
||||||
cargo-xbuild
|
|
||||||
mkbootimage
|
|
||||||
|
|
||||||
pkgs.openocd pkgs.gdb
|
|
||||||
pkgs.openssh pkgs.rsync
|
|
||||||
pkgs.llvmPackages_13.clang-unwrapped
|
|
||||||
(pkgs.python3.withPackages(ps: [ ps.pyftdi ]))
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
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()
|
|
@ -13,6 +13,6 @@ nb = "1.0"
|
|||||||
libcortex_a9 = { path = "../libcortex_a9" }
|
libcortex_a9 = { path = "../libcortex_a9" }
|
||||||
|
|
||||||
[dependencies.smoltcp]
|
[dependencies.smoltcp]
|
||||||
version = "0.7"
|
version = "0.6"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["alloc"]
|
features = ["alloc"]
|
||||||
|
@ -23,7 +23,7 @@ pub trait LinkCheck {
|
|||||||
static mut SOCKETS: Option<Sockets> = None;
|
static mut SOCKETS: Option<Sockets> = None;
|
||||||
|
|
||||||
pub struct Sockets {
|
pub struct Sockets {
|
||||||
sockets: RefCell<SocketSet<'static>>,
|
sockets: RefCell<SocketSet<'static, 'static, 'static>>,
|
||||||
wakers: RefCell<Vec<Waker>>,
|
wakers: RefCell<Vec<Waker>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,8 +47,8 @@ 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, D: for<'d> Device<'d> + LinkCheck>(
|
pub fn run<'b, 'c, 'e, D: for<'d> Device<'d> + LinkCheck>(
|
||||||
iface: &mut EthernetInterface<'b, D>,
|
iface: &mut EthernetInterface<'b, 'c, 'e, D>,
|
||||||
mut get_time: impl FnMut() -> Instant,
|
mut get_time: impl FnMut() -> Instant,
|
||||||
) -> ! {
|
) -> ! {
|
||||||
task::block_on(async {
|
task::block_on(async {
|
||||||
@ -74,9 +74,9 @@ impl Sockets {
|
|||||||
unsafe { SOCKETS.as_ref().expect("Sockets") }
|
unsafe { SOCKETS.as_ref().expect("Sockets") }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll<'b, D: for<'d> Device<'d>>(
|
fn poll<'b, 'c, 'e, D: for<'d> Device<'d>>(
|
||||||
&self,
|
&self,
|
||||||
iface: &mut EthernetInterface<'b, D>,
|
iface: &mut EthernetInterface<'b, 'c, 'e, D>,
|
||||||
instant: Instant
|
instant: Instant
|
||||||
) {
|
) {
|
||||||
let processed = {
|
let processed = {
|
||||||
|
@ -262,14 +262,6 @@ 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 {
|
||||||
|
@ -8,7 +8,6 @@ edition = "2018"
|
|||||||
[features]
|
[features]
|
||||||
target_zc706 = []
|
target_zc706 = []
|
||||||
target_coraz7 = []
|
target_coraz7 = []
|
||||||
target_ebaz4205 = []
|
|
||||||
target_redpitaya = []
|
target_redpitaya = []
|
||||||
target_kasli_soc = []
|
target_kasli_soc = []
|
||||||
ipv6 = [ "smoltcp/proto-ipv6" ]
|
ipv6 = [ "smoltcp/proto-ipv6" ]
|
||||||
@ -25,6 +24,6 @@ libcortex_a9 = { path = "../libcortex_a9" }
|
|||||||
libasync = { path = "../libasync" }
|
libasync = { path = "../libasync" }
|
||||||
|
|
||||||
[dependencies.smoltcp]
|
[dependencies.smoltcp]
|
||||||
version = "0.7"
|
version = "0.6"
|
||||||
features = ["ethernet", "proto-ipv4", "socket-tcp"]
|
features = ["ethernet", "proto-ipv4", "socket-tcp"]
|
||||||
default-features = false
|
default-features = false
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
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;
|
||||||
@ -103,8 +101,6 @@ 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())
|
||||||
}
|
}
|
||||||
@ -119,8 +115,6 @@ 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())
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,6 @@ use super::slcr;
|
|||||||
pub const PS_CLK: u32 = 33_333_333;
|
pub const PS_CLK: u32 = 33_333_333;
|
||||||
#[cfg(feature = "target_coraz7")]
|
#[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")]
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
@ -16,10 +16,6 @@ const DDR_FREQ: u32 = 666_666_666;
|
|||||||
/// 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_ebaz4205")]
|
|
||||||
/// EtronTech Memory EM6GD16EWKG-12H: 800 MHz DDR3 at 533 MHz
|
|
||||||
const DDR_FREQ: u32 = 533_333_333;
|
|
||||||
|
|
||||||
#[cfg(feature = "target_redpitaya")]
|
#[cfg(feature = "target_redpitaya")]
|
||||||
/// Alliance Memory AS4C256M16D3B: 800 MHz DDR3 at 533 MHz
|
/// Alliance Memory AS4C256M16D3B: 800 MHz DDR3 at 533 MHz
|
||||||
const DDR_FREQ: u32 = 533_333_333;
|
const DDR_FREQ: u32 = 533_333_333;
|
||||||
@ -151,23 +147,22 @@ 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(any(
|
#[cfg(any(feature = "target_coraz7", feature = "target_kasli_soc"))]
|
||||||
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(any(
|
#[cfg(any(feature = "target_coraz7", feature = "target_kasli_soc"))]
|
||||||
feature = "target_coraz7",
|
let data1_config = slcr::DdriobConfig::zeroed()
|
||||||
feature = "target_ebaz4205",
|
.pullup_en(true);
|
||||||
feature = "target_redpitaya",
|
#[cfg(feature = "target_redpitaya")]
|
||||||
feature = "target_kasli_soc",
|
let data0_config = slcr::DdriobConfig::zeroed()
|
||||||
))]
|
.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);
|
||||||
@ -181,23 +176,22 @@ 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(any(
|
#[cfg(any(feature = "target_coraz7", feature = "target_kasli_soc"))]
|
||||||
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(any(
|
#[cfg(any(feature = "target_coraz7", feature = "target_kasli_soc"))]
|
||||||
feature = "target_coraz7",
|
let diff1_config = slcr::DdriobConfig::zeroed()
|
||||||
feature = "target_ebaz4205",
|
.pullup_en(true);
|
||||||
feature = "target_redpitaya",
|
#[cfg(feature = "target_redpitaya")]
|
||||||
feature = "target_kasli_soc",
|
let diff0_config = slcr::DdriobConfig::zeroed()
|
||||||
))]
|
.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);
|
||||||
@ -216,12 +210,7 @@ impl DdrRam {
|
|||||||
slcr.ddriob_drive_slew_clock.write(0x00F9861C);
|
slcr.ddriob_drive_slew_clock.write(0x00F9861C);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(
|
#[cfg(any(feature = "target_coraz7", feature = "target_kasli_soc"))]
|
||||||
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)
|
||||||
@ -235,6 +224,13 @@ 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)
|
||||||
|
.refio_en(true)
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,13 +242,6 @@ impl DdrRam {
|
|||||||
.t_rfc_min(0x9e)
|
.t_rfc_min(0x9e)
|
||||||
.post_selfref_gap_x32(0x10)
|
.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")]
|
#[cfg(feature = "target_redpitaya")]
|
||||||
self.regs.dram_param0.write(
|
self.regs.dram_param0.write(
|
||||||
regs::DramParam0::zeroed()
|
regs::DramParam0::zeroed()
|
||||||
@ -267,12 +256,6 @@ impl DdrRam {
|
|||||||
.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")]
|
#[cfg(feature = "target_redpitaya")]
|
||||||
self.regs.dram_param1.modify(
|
self.regs.dram_param1.modify(
|
||||||
|_, w| w
|
|_, w| w
|
||||||
@ -294,11 +277,6 @@ 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")]
|
#[cfg(feature = "target_redpitaya")]
|
||||||
self.regs.dram_param3.modify(
|
self.regs.dram_param3.modify(
|
||||||
|_, w| w
|
|_, w| w
|
||||||
@ -320,21 +298,19 @@ impl DdrRam {
|
|||||||
.emr(0x4)
|
.emr(0x4)
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(any(
|
#[cfg(any(feature = "target_coraz7", feature = "target_kasli_soc"))]
|
||||||
feature = "target_coraz7",
|
|
||||||
feature = "target_ebaz4205",
|
|
||||||
feature = "target_redpitaya",
|
|
||||||
feature = "target_kasli_soc",
|
|
||||||
))]
|
|
||||||
self.regs.phy_configs[2].modify(
|
self.regs.phy_configs[2].modify(
|
||||||
|_, w| w.data_slice_in_use(false)
|
|_, w| w.data_slice_in_use(false)
|
||||||
);
|
);
|
||||||
#[cfg(any(
|
#[cfg(any(feature = "target_coraz7", feature = "target_kasli_soc"))]
|
||||||
feature = "target_coraz7",
|
self.regs.phy_configs[3].modify(
|
||||||
feature = "target_ebaz4205",
|
|_, w| w.data_slice_in_use(false)
|
||||||
feature = "target_redpitaya",
|
);
|
||||||
feature = "target_kasli_soc",
|
#[cfg(feature = "target_redpitaya")]
|
||||||
))]
|
self.regs.phy_configs[2].modify(
|
||||||
|
|_, w| w.data_slice_in_use(false)
|
||||||
|
);
|
||||||
|
#[cfg(feature = "target_redpitaya")]
|
||||||
self.regs.phy_configs[3].modify(
|
self.regs.phy_configs[3].modify(
|
||||||
|_, w| w.data_slice_in_use(false)
|
|_, w| w.data_slice_in_use(false)
|
||||||
);
|
);
|
||||||
@ -378,11 +354,7 @@ impl DdrRam {
|
|||||||
.gatelvl_init_ratio(0xee)
|
.gatelvl_init_ratio(0xee)
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(any(
|
#[cfg(any(feature = "target_coraz7", feature = "target_kasli_soc"))]
|
||||||
feature = "target_coraz7",
|
|
||||||
feature = "target_ebaz4205",
|
|
||||||
feature = "target_kasli_soc"),
|
|
||||||
)]
|
|
||||||
self.regs.reg_64.modify(
|
self.regs.reg_64.modify(
|
||||||
|_, w| w
|
|_, w| w
|
||||||
.phy_ctrl_slave_ratio(0x100)
|
.phy_ctrl_slave_ratio(0x100)
|
||||||
@ -418,12 +390,9 @@ impl DdrRam {
|
|||||||
fn reset_ddrc<F: FnMut(&mut Self)>(&mut self, mut f: F) {
|
fn reset_ddrc<F: FnMut(&mut Self)>(&mut self, mut f: F) {
|
||||||
#[cfg(feature = "target_zc706")]
|
#[cfg(feature = "target_zc706")]
|
||||||
let width = regs::DataBusWidth::Width32bit;
|
let width = regs::DataBusWidth::Width32bit;
|
||||||
#[cfg(any(
|
#[cfg(any(feature = "target_coraz7", feature = "target_kasli_soc"))]
|
||||||
feature = "target_coraz7",
|
let width = regs::DataBusWidth::Width16bit;
|
||||||
feature = "target_ebaz4205",
|
#[cfg(feature = "target_redpitaya")]
|
||||||
feature = "target_redpitaya",
|
|
||||||
feature = "target_kasli_soc",
|
|
||||||
))]
|
|
||||||
let width = regs::DataBusWidth::Width16bit;
|
let width = regs::DataBusWidth::Width16bit;
|
||||||
self.regs.ddrc_ctrl.modify(|_, w| w
|
self.regs.ddrc_ctrl.modify(|_, w| w
|
||||||
.soft_rstb(false)
|
.soft_rstb(false)
|
||||||
@ -441,7 +410,6 @@ impl DdrRam {
|
|||||||
}
|
}
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
feature = "target_coraz7",
|
feature = "target_coraz7",
|
||||||
feature = "target_ebaz4205",
|
|
||||||
feature = "target_redpitaya",
|
feature = "target_redpitaya",
|
||||||
feature = "target_kasli_soc",
|
feature = "target_kasli_soc",
|
||||||
))]
|
))]
|
||||||
@ -482,8 +450,6 @@ impl DdrRam {
|
|||||||
feature = "target_kasli_soc",
|
feature = "target_kasli_soc",
|
||||||
))]
|
))]
|
||||||
let megabytes = 512;
|
let megabytes = 512;
|
||||||
#[cfg(feature = "target_ebaz4205")]
|
|
||||||
let megabytes = 256;
|
|
||||||
|
|
||||||
megabytes * 1024 * 1024
|
megabytes * 1024 * 1024
|
||||||
}
|
}
|
||||||
|
@ -1,114 +0,0 @@
|
|||||||
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,9 +13,6 @@ 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
|
||||||
@ -65,31 +62,17 @@ 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)
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -168,7 +151,6 @@ pub struct Eth<GEM: Gem, RX, TX> {
|
|||||||
|
|
||||||
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
|
||||||
@ -318,25 +300,16 @@ 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: (),
|
||||||
@ -507,69 +480,6 @@ 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>,
|
||||||
|
@ -82,10 +82,6 @@ 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,9 +11,6 @@ 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 {
|
||||||
|
@ -1,79 +0,0 @@
|
|||||||
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,6 @@ 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(Copy, Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
pub struct Link {
|
pub struct Link {
|
||||||
@ -28,53 +26,11 @@ 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,
|
||||||
@ -83,16 +39,11 @@ pub struct Phy {
|
|||||||
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_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> {
|
||||||
(0..32).find(|addr| {
|
(1..32).find(|addr| {
|
||||||
match identify_phy(pa, *addr) {
|
match identify_phy(pa, *addr) {
|
||||||
Some(PhyIdentifier {
|
Some(PhyIdentifier {
|
||||||
oui: OUI_MARVELL,
|
oui: OUI_MARVELL,
|
||||||
@ -118,12 +69,6 @@ impl Phy {
|
|||||||
model: 0,
|
model: 0,
|
||||||
..
|
..
|
||||||
}) => true,
|
}) => true,
|
||||||
Some(PhyIdentifier {
|
|
||||||
oui: OUI_ICPLUS,
|
|
||||||
// IP101G-DS-R01
|
|
||||||
model: 5,
|
|
||||||
rev: 4,
|
|
||||||
}) => true,
|
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}).map(|addr| Phy { addr })
|
}).map(|addr| Phy { addr })
|
||||||
@ -134,9 +79,6 @@ 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()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,9 +88,6 @@ 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())
|
||||||
@ -162,14 +101,6 @@ 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)
|
||||||
}
|
}
|
||||||
@ -203,12 +134,8 @@ impl Phy {
|
|||||||
.set_restart_autoneg(true)
|
.set_restart_autoneg(true)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#[cfg(feature="target_kasli_soc")]
|
|
||||||
pub fn set_leds<PA: PhyAccess>(&self, pa: &mut PA) {
|
pub trait PhyRegister {
|
||||||
self.modify_leds(pa, |leds|
|
fn addr() -> u8;
|
||||||
leds.set_led0(Led0Control::OnCopperLinkOffElse)
|
|
||||||
.set_led1(Led1Control::BlinkActivityOffNoActivity)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -43,10 +43,6 @@ 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,27 +55,7 @@ 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_100base_tx_full() {
|
} else if self.cap_10base_t_half() {
|
||||||
Some(Link {
|
|
||||||
speed: LinkSpeed::S100,
|
|
||||||
duplex: LinkDuplex::Full,
|
|
||||||
})
|
|
||||||
} else if self.cap_100base_tx_half() {
|
|
||||||
Some(Link {
|
|
||||||
speed: LinkSpeed::S100,
|
|
||||||
duplex: LinkDuplex::Half,
|
|
||||||
})
|
|
||||||
} else if self.cap_100base_t4() {
|
|
||||||
Some(Link {
|
|
||||||
speed: LinkSpeed::S100,
|
|
||||||
duplex: LinkDuplex::Half,
|
|
||||||
})
|
|
||||||
} else if self.cap_10base_t2_full() {
|
|
||||||
Some(Link {
|
|
||||||
speed: LinkSpeed::S10,
|
|
||||||
duplex: LinkDuplex::Full,
|
|
||||||
})
|
|
||||||
} else if self.cap_10base_t2_half() {
|
|
||||||
Some(Link {
|
Some(Link {
|
||||||
speed: LinkSpeed::S10,
|
speed: LinkSpeed::S10,
|
||||||
duplex: LinkDuplex::Half,
|
duplex: LinkDuplex::Half,
|
||||||
@ -85,11 +65,31 @@ impl Status {
|
|||||||
speed: LinkSpeed::S10,
|
speed: LinkSpeed::S10,
|
||||||
duplex: LinkDuplex::Full,
|
duplex: LinkDuplex::Full,
|
||||||
})
|
})
|
||||||
} else if self.cap_10base_t_half() {
|
} else if self.cap_10base_t2_half() {
|
||||||
Some(Link {
|
Some(Link {
|
||||||
speed: LinkSpeed::S10,
|
speed: LinkSpeed::S10,
|
||||||
duplex: LinkDuplex::Half,
|
duplex: LinkDuplex::Half,
|
||||||
})
|
})
|
||||||
|
} else if self.cap_10base_t2_full() {
|
||||||
|
Some(Link {
|
||||||
|
speed: LinkSpeed::S10,
|
||||||
|
duplex: LinkDuplex::Full,
|
||||||
|
})
|
||||||
|
} else if self.cap_100base_t4() {
|
||||||
|
Some(Link {
|
||||||
|
speed: LinkSpeed::S100,
|
||||||
|
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,10 +100,6 @@ 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,49 +110,6 @@ 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));
|
self.mpcore.icdiptr[m].modify(|mut icdiptr| *icdiptr.set_bits(n..=n+1, target_cpu as u32 + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// sensitivity
|
// sensitivity
|
||||||
|
@ -4,7 +4,6 @@ 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,
|
||||||
@ -36,19 +35,16 @@ impl<'a> EEPROM<'a> {
|
|||||||
|
|
||||||
#[cfg(feature = "target_zc706")]
|
#[cfg(feature = "target_zc706")]
|
||||||
fn select(&mut self) -> Result<(), &'static str> {
|
fn select(&mut self) -> Result<(), &'static str> {
|
||||||
self.i2c.pca954x_select(0b1110100, Some(self.port))?;
|
let mask: u16 = 1 << self.port;
|
||||||
|
self.i2c.pca9548_select(0b1110100, mask as u8)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "target_kasli_soc")]
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
fn select(&mut self) -> Result<(), &'static str> {
|
fn select(&mut self) -> Result<(), &'static str> {
|
||||||
|
let mask: u16 = 1 << self.port;
|
||||||
// tca9548 is compatible with pca9548
|
// tca9548 is compatible with pca9548
|
||||||
self.i2c.pca954x_select(0b1110001, Some(self.port))?;
|
self.i2c.pca9548_select(0b1110001, mask as u8)?;
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "target_ebaz4205")]
|
|
||||||
fn select(&mut self) -> Result<(), &'static str> {
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,33 +2,20 @@
|
|||||||
|
|
||||||
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};
|
use libregister::{RegisterR, RegisterRW, RegisterW};
|
||||||
#[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(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||||
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(
|
||||||
@ -46,28 +33,18 @@ impl I2c {
|
|||||||
.pullup(true)
|
.pullup(true)
|
||||||
.disable_rcvr(true)
|
.disable_rcvr(true)
|
||||||
);
|
);
|
||||||
// On Kasli-SoC prototype, leakage through the unconfigured I2C_SW_RESET
|
// Reset
|
||||||
// MIO pin develops enough voltage on the T21 gate to assert the reset.
|
slcr.gpio_rst_ctrl.reset_gpio();
|
||||||
// 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, 0xFFFF - 0x0002)
|
Self::i2c_common(0xFFFF - 0x000C)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn i2c_common(gpio_output_mask: u16, _gpio_output_mask_lower: u16) -> Self {
|
fn i2c_common(gpio_output_mask: 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
|
||||||
@ -79,17 +56,6 @@ 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_
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,7 +65,7 @@ impl I2c {
|
|||||||
nb::block!(self.count_down.wait()).unwrap();
|
nb::block!(self.count_down.wait()).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unit_delay(&mut self) { self.delay_us(100) }
|
fn half_period(&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()
|
||||||
@ -133,48 +99,6 @@ 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);
|
||||||
@ -182,15 +106,15 @@ impl I2c {
|
|||||||
self.sda_o(false);
|
self.sda_o(false);
|
||||||
|
|
||||||
// Check the I2C bus is ready
|
// Check the I2C bus is ready
|
||||||
self.unit_delay();
|
self.half_period();
|
||||||
self.unit_delay();
|
self.half_period();
|
||||||
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.unit_delay();
|
self.half_period();
|
||||||
self.scl_oe(false);
|
self.scl_oe(false);
|
||||||
self.unit_delay();
|
self.half_period();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,31 +122,23 @@ 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");
|
return Err("SCL is stuck low and doesn't get unstuck");
|
||||||
}
|
}
|
||||||
// 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");
|
return Err("SCL is stuck low and doesn't get unstuck");
|
||||||
}
|
}
|
||||||
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.unit_delay();
|
self.half_period();
|
||||||
self.scl_oe(true);
|
self.scl_oe(true);
|
||||||
self.unit_delay();
|
|
||||||
// postcondition: SCL and SDA low
|
// postcondition: SCL and SDA low
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -230,9 +146,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.unit_delay();
|
self.half_period();
|
||||||
self.scl_oe(false);
|
self.scl_oe(false);
|
||||||
self.unit_delay();
|
self.half_period();
|
||||||
self.start()?;
|
self.start()?;
|
||||||
// postcondition: SCL and SDA low
|
// postcondition: SCL and SDA low
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -240,11 +156,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.unit_delay();
|
self.half_period();
|
||||||
self.scl_oe(false);
|
self.scl_oe(false);
|
||||||
self.unit_delay();
|
self.half_period();
|
||||||
self.sda_oe(false);
|
self.sda_oe(false);
|
||||||
self.unit_delay();
|
self.half_period();
|
||||||
if !self.sda_i() {
|
if !self.sda_i() {
|
||||||
return Err("SDA arbitration lost");
|
return Err("SDA arbitration lost");
|
||||||
}
|
}
|
||||||
@ -257,20 +173,18 @@ 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.unit_delay();
|
self.half_period();
|
||||||
self.scl_oe(false);
|
self.scl_oe(false);
|
||||||
self.unit_delay();
|
self.half_period();
|
||||||
self.scl_oe(true);
|
self.scl_oe(true);
|
||||||
self.unit_delay();
|
|
||||||
}
|
}
|
||||||
self.sda_oe(false);
|
self.sda_oe(false);
|
||||||
self.unit_delay();
|
self.half_period();
|
||||||
self.scl_oe(false);
|
self.scl_oe(false);
|
||||||
self.unit_delay();
|
self.half_period();
|
||||||
// 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
|
||||||
|
|
||||||
@ -285,17 +199,17 @@ impl I2c {
|
|||||||
|
|
||||||
// MSB first
|
// MSB first
|
||||||
for bit in (0..8).rev() {
|
for bit in (0..8).rev() {
|
||||||
self.unit_delay();
|
self.half_period();
|
||||||
self.scl_oe(false);
|
self.scl_oe(false);
|
||||||
self.unit_delay();
|
self.half_period();
|
||||||
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 (true = nack, false = ack)
|
// Send ack/nack
|
||||||
self.sda_oe(ack);
|
self.sda_oe(ack);
|
||||||
self.unit_delay();
|
self.half_period();
|
||||||
self.scl_oe(false);
|
self.scl_oe(false);
|
||||||
self.unit_delay();
|
self.half_period();
|
||||||
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
|
||||||
@ -303,32 +217,13 @@ impl I2c {
|
|||||||
Ok(data)
|
Ok(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pca954x_select(&mut self, address: u8, channel: Option<u8>) -> Result<(), &'static str> {
|
pub fn pca9548_select(&mut self, address: u8, channels: 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("PCA954X failed to ack write address")
|
return Err("PCA9548 failed to ack write address")
|
||||||
}
|
}
|
||||||
if !self.write(setting)? {
|
if !self.write(channels)? {
|
||||||
return Err("PCA954X failed to ack control word")
|
return Err("PCA9548 failed to ack control word")
|
||||||
}
|
}
|
||||||
self.stop()?;
|
self.stop()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -20,16 +20,13 @@ 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
|
// kasli_soc: GPIO 50, 51 == SCL, SDA
|
||||||
// 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 {
|
||||||
@ -38,9 +35,7 @@ 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(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -49,87 +44,62 @@ register!(gpio_output_mask,
|
|||||||
/// MASK_DATA_1_MSW:
|
/// MASK_DATA_1_MSW:
|
||||||
/// Maskable output data for MIO[53:48]
|
/// Maskable output data for MIO[53:48]
|
||||||
GPIOOutputMask, RW, u32);
|
GPIOOutputMask, RW, u32);
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||||
register_at!(GPIOOutputMask, 0xE000A00C, new);
|
register_at!(GPIOOutputMask, 0xE000A00C, new);
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||||
register_bit!(gpio_output_mask,
|
register_bit!(gpio_output_mask,
|
||||||
/// Output for SCL
|
/// Output for SCL
|
||||||
scl_o, 2);
|
scl_o, 2);
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||||
register_bit!(gpio_output_mask,
|
register_bit!(gpio_output_mask,
|
||||||
/// Output for SDA
|
/// Output for SDA
|
||||||
sda_o, 3);
|
sda_o, 3);
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||||
register_bits!(gpio_output_mask,
|
register_bits!(gpio_output_mask,
|
||||||
/// Mask for keeping bits except SCL and SDA unchanged
|
/// Mask for keeping bits except SCL and SDA unchanged
|
||||||
mask, u16, 16, 31);
|
mask, u16, 16, 31);
|
||||||
|
|
||||||
|
|
||||||
register!(gpio_output_mask_lower,
|
|
||||||
/// MASK_DATA_1_LSW:
|
|
||||||
/// 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,
|
register!(gpio_input,
|
||||||
/// DATA_1_RO:
|
/// DATA_1_RO:
|
||||||
/// Input data for MIO[53:32]
|
/// Input data for MIO[53:32]
|
||||||
GPIOInput, RO, u32);
|
GPIOInput, RO, u32);
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||||
register_at!(GPIOInput, 0xE000A064, new);
|
register_at!(GPIOInput, 0xE000A064, new);
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||||
register_bit!(gpio_input,
|
register_bit!(gpio_input,
|
||||||
/// Input for SCL
|
/// Input for SCL
|
||||||
scl, 18);
|
scl, 18);
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||||
register_bit!(gpio_input,
|
register_bit!(gpio_input,
|
||||||
/// Input for SDA
|
/// Input for SDA
|
||||||
sda, 19);
|
sda, 19);
|
||||||
|
|
||||||
|
|
||||||
register!(gpio_direction,
|
register!(gpio_direction,
|
||||||
/// DIRM_1:
|
/// DIRM_1:
|
||||||
/// Direction mode for MIO[53:32]; 0/1 = in/out
|
/// Direction mode for MIO[53:32]; 0/1 = in/out
|
||||||
GPIODirection, RW, u32);
|
GPIODirection, RW, u32);
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||||
register_at!(GPIODirection, 0xE000A244, new);
|
register_at!(GPIODirection, 0xE000A244, new);
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||||
register_bit!(gpio_direction,
|
register_bit!(gpio_direction,
|
||||||
/// Direction for SCL
|
/// Direction for SCL
|
||||||
scl, 18);
|
scl, 18);
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||||
register_bit!(gpio_direction,
|
register_bit!(gpio_direction,
|
||||||
/// Direction for SDA
|
/// Direction for SDA
|
||||||
sda, 19);
|
sda, 19);
|
||||||
#[cfg(feature = "target_kasli_soc")]
|
|
||||||
register_bit!(gpio_direction,
|
|
||||||
/// Direction for I2C_SW_RESET
|
|
||||||
i2cswr, 1);
|
|
||||||
|
|
||||||
register!(gpio_output_enable,
|
register!(gpio_output_enable,
|
||||||
/// OEN_1:
|
/// OEN_1:
|
||||||
/// Output enable for MIO[53:32]
|
/// Output enable for MIO[53:32]
|
||||||
GPIOOutputEnable, RW, u32);
|
GPIOOutputEnable, RW, u32);
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||||
register_at!(GPIOOutputEnable, 0xE000A248, new);
|
register_at!(GPIOOutputEnable, 0xE000A248, new);
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||||
register_bit!(gpio_output_enable,
|
register_bit!(gpio_output_enable,
|
||||||
/// Output enable for SCL
|
/// Output enable for SCL
|
||||||
scl, 18);
|
scl, 18);
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||||
register_bit!(gpio_output_enable,
|
register_bit!(gpio_output_enable,
|
||||||
/// Output enable for SDA
|
/// Output enable for SDA
|
||||||
sda, 19);
|
sda, 19);
|
||||||
#[cfg(feature = "target_kasli_soc")]
|
|
||||||
register_bit!(gpio_output_enable,
|
|
||||||
/// Output enable for I2C_SW_RESET
|
|
||||||
i2cswr, 1);
|
|
||||||
|
|
@ -19,9 +19,7 @@ pub mod gic;
|
|||||||
pub mod time;
|
pub mod time;
|
||||||
pub mod timer;
|
pub mod timer;
|
||||||
pub mod sdio;
|
pub mod sdio;
|
||||||
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc", feature = "target_ebaz4205"))]
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||||
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;
|
|
||||||
|
@ -116,8 +116,8 @@ impl Sdio {
|
|||||||
.speed(true),
|
.speed(true),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// kasli_soc and redpitaya card detect pin
|
// redpitaya card detect pin
|
||||||
#[cfg(any(feature = "target_kasli_soc", feature = "target_redpitaya"))]
|
#[cfg(any(feature = "target_redpitaya", feature = "target_kasli_soc"))]
|
||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
slcr.sd0_wp_cd_sel.write(46 << 16);
|
slcr.sd0_wp_cd_sel.write(46 << 16);
|
||||||
@ -128,20 +128,6 @@ 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,11 +9,9 @@ use libregister::{
|
|||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum PllSource {
|
pub enum PllSource {
|
||||||
IoPll = 0b000,
|
IoPll = 0b00,
|
||||||
ArmPll = 0b010,
|
ArmPll = 0b10,
|
||||||
DdrPll = 0b011,
|
DdrPll = 0b11,
|
||||||
// Ethernet controller 0 EMIO clock
|
|
||||||
Emio = 0b100,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
@ -589,17 +587,6 @@ 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 {
|
||||||
@ -618,7 +605,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, 0);
|
register_bit!(pss_rst_ctrl, soft_rst, 1);
|
||||||
|
|
||||||
/// Used for MioPin*.io_type
|
/// Used for MioPin*.io_type
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
|
@ -47,11 +47,7 @@ impl DerefMut for LazyUart {
|
|||||||
LazyUart::Uninitialized => {
|
LazyUart::Uninitialized => {
|
||||||
#[cfg(any(feature = "target_coraz7", feature = "target_redpitaya"))]
|
#[cfg(any(feature = "target_coraz7", feature = "target_redpitaya"))]
|
||||||
let uart = Uart::uart0(UART_RATE);
|
let uart = Uart::uart0(UART_RATE);
|
||||||
#[cfg(any(
|
#[cfg(any(feature = "target_zc706", feature = "target_kasli_soc"))]
|
||||||
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
|
||||||
|
@ -79,39 +79,6 @@ 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() {}
|
||||||
|
|
||||||
|
@ -6,24 +6,13 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libboard_zynq = { path = "../libboard_zynq" }
|
libboard_zynq = { path = "../libboard_zynq" }
|
||||||
|
core_io = { version = "0.1", features = ["collections"] }
|
||||||
|
fatfs = { version = "0.3", features = ["core_io"], default-features = false }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
|
||||||
[dependencies.core_io]
|
|
||||||
git = "https://git.m-labs.hk/M-Labs/rs-core_io.git"
|
|
||||||
rev = "e9d3edf027"
|
|
||||||
features = ["collections"]
|
|
||||||
|
|
||||||
[dependencies.fatfs]
|
|
||||||
git = "https://git.m-labs.hk/M-Labs/rust-fatfs.git"
|
|
||||||
rev = "4b5e420084"
|
|
||||||
default-features = false
|
|
||||||
features = ["core_io"]
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
target_zc706 = []
|
target_zc706 = []
|
||||||
target_coraz7 = []
|
target_coraz7 = []
|
||||||
target_ebaz4205 = []
|
|
||||||
target_redpitaya = []
|
target_redpitaya = []
|
||||||
target_kasli_soc = []
|
target_kasli_soc = []
|
||||||
ipv6 = []
|
ipv6 = []
|
||||||
fat_lfn = [ "fatfs/alloc" ]
|
|
||||||
|
@ -164,8 +164,7 @@ impl Config {
|
|||||||
f.seek(SeekFrom::End(0))?;
|
f.seek(SeekFrom::End(0))?;
|
||||||
write!(f, "{}={}\n", key, String::from_utf8(value).unwrap())?;
|
write!(f, "{}={}\n", key, String::from_utf8(value).unwrap())?;
|
||||||
} else {
|
} else {
|
||||||
let dir = root_dir.create_dir("/CONFIG")?;
|
let mut f = root_dir.create_file(&["/CONFIG/", key, ".BIN"].concat())?;
|
||||||
let mut f = dir.create_file(&[key, ".BIN"].concat())?;
|
|
||||||
f.write_all(&value)?;
|
f.write_all(&value)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,19 +30,7 @@ impl fmt::Display for NetAddresses {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "target_kasli_soc")]
|
pub fn get_adresses(cfg: &Config) -> NetAddresses {
|
||||||
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")]
|
#[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")]
|
#[cfg(feature = "target_zc706")]
|
||||||
@ -56,13 +44,9 @@ pub fn get_addresses(cfg: &Config) -> NetAddresses {
|
|||||||
#[cfg(feature = "target_redpitaya")]
|
#[cfg(feature = "target_redpitaya")]
|
||||||
let mut ipv4_addr = IpAddress::v4(192, 168, 1, 55);
|
let mut ipv4_addr = IpAddress::v4(192, 168, 1, 55);
|
||||||
#[cfg(feature = "target_kasli_soc")]
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
let mut hardware_addr = get_address_from_eeprom();
|
let mut hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x56]);
|
||||||
#[cfg(feature = "target_kasli_soc")]
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
let mut ipv4_addr = IpAddress::v4(192, 168, 1, 56);
|
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;
|
||||||
|
14
libcoreio/Cargo.toml
Normal file
14
libcoreio/Cargo.toml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
[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"]
|
1674
libcoreio/src/io/buffered.rs
Normal file
1674
libcoreio/src/io/buffered.rs
Normal file
File diff suppressed because it is too large
Load Diff
896
libcoreio/src/io/cursor.rs
Normal file
896
libcoreio/src/io/cursor.rs
Normal file
@ -0,0 +1,896 @@
|
|||||||
|
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()));
|
||||||
|
}
|
||||||
|
}
|
551
libcoreio/src/io/error.rs
Normal file
551
libcoreio/src/io/error.rs
Normal file
@ -0,0 +1,551 @@
|
|||||||
|
#[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();
|
||||||
|
}
|
||||||
|
}
|
378
libcoreio/src/io/impls.rs
Normal file
378
libcoreio/src/io/impls.rs
Normal file
@ -0,0 +1,378 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
2664
libcoreio/src/io/mod.rs
Normal file
2664
libcoreio/src/io/mod.rs
Normal file
File diff suppressed because it is too large
Load Diff
13
libcoreio/src/io/prelude.rs
Normal file
13
libcoreio/src/io/prelude.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
//! 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;
|
269
libcoreio/src/io/util.rs
Normal file
269
libcoreio/src/io/util.rs
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
#![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);
|
||||||
|
}
|
||||||
|
}
|
51
libcoreio/src/lib.rs
Normal file
51
libcoreio/src/lib.rs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
//! <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::*;
|
@ -1,60 +1,53 @@
|
|||||||
use core::arch::asm;
|
|
||||||
|
|
||||||
/// The classic no-op
|
/// The classic no-op
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn nop() {
|
pub fn nop() {
|
||||||
unsafe { asm!("nop") }
|
unsafe { llvm_asm!("nop" :::: "volatile") }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wait For Event
|
/// Wait For Event
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn wfe() {
|
pub fn wfe() {
|
||||||
unsafe { asm!("wfe") }
|
unsafe { llvm_asm!("wfe" :::: "volatile") }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send Event
|
/// Send Event
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn sev() {
|
pub fn sev() {
|
||||||
unsafe { asm!("sev") }
|
unsafe { llvm_asm!("sev" :::: "volatile") }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Data Memory Barrier
|
/// Data Memory Barrier
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn dmb() {
|
pub fn dmb() {
|
||||||
unsafe { asm!("dmb") }
|
unsafe { llvm_asm!("dmb" :::: "volatile") }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Data Synchronization Barrier
|
/// Data Synchronization Barrier
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn dsb() {
|
pub fn dsb() {
|
||||||
unsafe { asm!("dsb") }
|
unsafe { llvm_asm!("dsb" :::: "volatile") }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Instruction Synchronization Barrier
|
/// Instruction Synchronization Barrier
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn isb() {
|
pub fn isb() {
|
||||||
unsafe { asm!("isb") }
|
unsafe { llvm_asm!("isb" :::: "volatile") }
|
||||||
}
|
|
||||||
|
|
||||||
/// Enable FIQ
|
|
||||||
#[inline]
|
|
||||||
pub unsafe fn enable_fiq() {
|
|
||||||
asm!("cpsie f");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enable IRQ
|
/// Enable IRQ
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn enable_irq() {
|
pub unsafe fn enable_irq() {
|
||||||
asm!("cpsie i");
|
llvm_asm!("cpsie i":::: "volatile");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Disable IRQ, return if IRQ was originally enabled.
|
/// Disable IRQ, return if IRQ was originally enabled.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn enter_critical() -> bool {
|
pub unsafe fn enter_critical() -> bool {
|
||||||
let mut cpsr: u32;
|
let mut cpsr: u32;
|
||||||
asm!(
|
llvm_asm!(
|
||||||
"mrs {}, cpsr
|
"mrs $0, cpsr
|
||||||
cpsid i", lateout(reg) cpsr);
|
cpsid i"
|
||||||
|
: "=r"(cpsr) ::: "volatile");
|
||||||
(cpsr & (1 << 7)) == 0
|
(cpsr & (1 << 7)) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,18 +59,18 @@ pub unsafe fn exit_critical(enable: bool) {
|
|||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
asm!(
|
llvm_asm!(
|
||||||
"mrs r1, cpsr
|
"mrs r1, cpsr
|
||||||
bic r1, r1, {}
|
bic r1, r1, $0
|
||||||
msr cpsr_c, r1"
|
msr cpsr_c, r1"
|
||||||
, in(reg) mask, out("r1") _);
|
:: "r"(mask) : "r1");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Exiting IRQ
|
/// Exiting IRQ
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn exit_irq() {
|
pub unsafe fn exit_irq() {
|
||||||
asm!("
|
llvm_asm!("
|
||||||
mrs r0, SPSR
|
mrs r0, SPSR
|
||||||
msr CPSR, r0
|
msr CPSR, r0
|
||||||
", out("r0") _);
|
" ::: "r0");
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
use super::asm::{dmb, dsb};
|
use super::asm::{dmb, dsb};
|
||||||
use super::l2c::*;
|
use super::l2c::*;
|
||||||
use core::arch::asm;
|
|
||||||
|
|
||||||
/// Invalidate TLBs
|
/// Invalidate TLBs
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn tlbiall() {
|
pub fn tlbiall() {
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!("mcr p15, 0, {}, c8, c7, 0", in(reg) 0);
|
llvm_asm!("mcr p15, 0, $0, c8, c7, 0" :: "r" (0) :: "volatile");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14,7 +13,7 @@ pub fn tlbiall() {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn iciallu() {
|
pub fn iciallu() {
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!("mcr p15, 0, {}, c7, c5, 0", in(reg) 0);
|
llvm_asm!("mcr p15, 0, $0, c7, c5, 0" :: "r" (0) :: "volatile");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,7 +21,7 @@ pub fn iciallu() {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn bpiall() {
|
pub fn bpiall() {
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!("mcr p15, 0, {}, c7, c5, 6", in(reg) 0);
|
llvm_asm!("mcr p15, 0, $0, c7, c5, 6" :: "r" (0) :: "volatile");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,7 +29,7 @@ pub fn bpiall() {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn dccsw(setway: u32) {
|
pub fn dccsw(setway: u32) {
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!("mcr p15, 0, {}, c7, c10, 2", in(reg) setway);
|
llvm_asm!("mcr p15, 0, $0, c7, c10, 2" :: "r" (setway) :: "volatile");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +41,7 @@ pub fn dcisw(setway: u32) {
|
|||||||
// also see example code (for DCCISW, but DCISW will be
|
// also see example code (for DCCISW, but DCISW will be
|
||||||
// analogous) "Example code for cache maintenance operations"
|
// analogous) "Example code for cache maintenance operations"
|
||||||
// on pages B2-1286 and B2-1287.
|
// on pages B2-1286 and B2-1287.
|
||||||
asm!("mcr p15, 0, {}, c7, c6, 2", in(reg) setway);
|
llvm_asm!("mcr p15, 0, $0, c7, c6, 2" :: "r" (setway) :: "volatile");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,7 +49,7 @@ pub fn dcisw(setway: u32) {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn dccisw(setway: u32) {
|
pub fn dccisw(setway: u32) {
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!("mcr p15, 0, {}, c7, c14, 2", in(reg) setway);
|
llvm_asm!("mcr p15, 0, $0, c7, c14, 2" :: "r" (setway) :: "volatile");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +69,7 @@ pub fn dciall_l1() {
|
|||||||
|
|
||||||
// select L1 data cache
|
// select L1 data cache
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!("mcr p15, 2, {}, c0, c0, 0", in(reg) 0);
|
llvm_asm!("mcr p15, 2, $0, c0, c0, 0" :: "r" (0) :: "volatile");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invalidate entire D-Cache by iterating every set and every way
|
// Invalidate entire D-Cache by iterating every set and every way
|
||||||
@ -105,7 +104,7 @@ pub fn dcciall_l1() {
|
|||||||
|
|
||||||
// select L1 data cache
|
// select L1 data cache
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!("mcr p15, 2, {}, c0, c0, 0", in(reg) 0);
|
llvm_asm!("mcr p15, 2, $0, c0, c0, 0" :: "r" (0) :: "volatile");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invalidate entire D-Cache by iterating every set and every way
|
// Invalidate entire D-Cache by iterating every set and every way
|
||||||
@ -157,7 +156,7 @@ fn slice_cache_line_addrs<T>(slice: &[T]) -> impl Iterator<Item = usize> {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn dccimvac(addr: usize) {
|
pub fn dccimvac(addr: usize) {
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!("mcr p15, 0, {}, c7, c14, 1", in(reg) addr);
|
llvm_asm!("mcr p15, 0, $0, c7, c14, 1" :: "r" (addr) :: "volatile");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,9 +198,10 @@ pub fn dcci_slice<T>(slice: &[T]) {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn dccmvac(addr: usize) {
|
pub fn dccmvac(addr: usize) {
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!("mcr p15, 0, {}, c7, c10, 1", in(reg) addr);
|
llvm_asm!("mcr p15, 0, $0, c7, c10, 1" :: "r" (addr) :: "volatile");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Data cache clean for an object.
|
/// Data cache clean for an object.
|
||||||
pub fn dcc<T>(object: &T) {
|
pub fn dcc<T>(object: &T) {
|
||||||
dmb();
|
dmb();
|
||||||
@ -239,7 +239,7 @@ pub fn dcc_slice<T>(slice: &[T]) {
|
|||||||
/// affecting more data than intended.
|
/// affecting more data than intended.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn dcimvac(addr: usize) {
|
pub unsafe fn dcimvac(addr: usize) {
|
||||||
asm!("mcr p15, 0, {}, c7, c6, 1", in(reg) addr);
|
llvm_asm!("mcr p15, 0, $0, c7, c6, 1" :: "r" (addr) :: "volatile");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Data cache clean and invalidate for an object.
|
/// Data cache clean and invalidate for an object.
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
use core::arch::asm;
|
|
||||||
/// Enable FPU in the current core.
|
/// Enable FPU in the current core.
|
||||||
pub fn enable_fpu() {
|
pub fn enable_fpu() {
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!("
|
llvm_asm!("
|
||||||
mrc p15, 0, r1, c1, c0, 2
|
mrc p15, 0, r1, c1, c0, 2
|
||||||
orr r1, r1, (0b1111<<20)
|
orr r1, r1, (0b1111<<20)
|
||||||
mcr p15, 0, r1, c1, c0, 2
|
mcr p15, 0, r1, c1, c0, 2
|
||||||
@ -10,6 +9,6 @@ pub fn enable_fpu() {
|
|||||||
vmrs r1, fpexc
|
vmrs r1, fpexc
|
||||||
orr r1, r1, (1<<30)
|
orr r1, r1, (1<<30)
|
||||||
vmsr fpexc, r1
|
vmsr fpexc, r1
|
||||||
", out("r1") _);
|
":::"r1");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
|
#![feature(llvm_asm, global_asm)]
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
#![feature(global_asm)]
|
#![feature(const_fn)]
|
||||||
#![feature(asm)]
|
|
||||||
#![allow(incomplete_features)]
|
|
||||||
#![feature(inline_const)]
|
|
||||||
#![feature(const_fn_trait_bound)]
|
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
@ -20,7 +17,6 @@ pub mod sync_channel;
|
|||||||
mod uncached;
|
mod uncached;
|
||||||
pub use fpu::enable_fpu;
|
pub use fpu::enable_fpu;
|
||||||
pub use uncached::UncachedSlice;
|
pub use uncached::UncachedSlice;
|
||||||
use core::arch::global_asm;
|
|
||||||
|
|
||||||
global_asm!(include_str!("exceptions.s"));
|
global_asm!(include_str!("exceptions.s"));
|
||||||
|
|
||||||
@ -40,9 +36,7 @@ pub fn notify_spin_lock() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
/// Interrupt handler, which setup the stack and preserve registers before jumping to actual interrupt handler.
|
/// Interrupt handler, which setup the stack and jump 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.
|
/// - `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.
|
/// - `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.
|
/// - `stack0` is the stack for the interrupt handler when called from core0.
|
||||||
@ -50,7 +44,8 @@ pub fn notify_spin_lock() {
|
|||||||
/// - `body` is the body of the actual interrupt handler, should be a normal unsafe rust function
|
/// - `body` is the body of the actual interrupt handler, should be a normal unsafe rust function
|
||||||
/// body.
|
/// body.
|
||||||
///
|
///
|
||||||
/// Note that the interrupt handler would use the same stack as normal programs by default.
|
/// Note that the interrupt handler would use the same stack as normal programs by default, so
|
||||||
|
/// interrupt handlers should not return to normal program or it may corrupt the stack.
|
||||||
macro_rules! interrupt_handler {
|
macro_rules! interrupt_handler {
|
||||||
($name:ident, $name2:ident, $stack0:ident, $stack1:ident, $body:block) => {
|
($name:ident, $name2:ident, $stack0:ident, $stack1:ident, $body:block) => {
|
||||||
#[link_section = ".text.boot"]
|
#[link_section = ".text.boot"]
|
||||||
@ -59,27 +54,19 @@ macro_rules! interrupt_handler {
|
|||||||
pub unsafe extern "C" fn $name() -> ! {
|
pub unsafe extern "C" fn $name() -> ! {
|
||||||
asm!(
|
asm!(
|
||||||
// setup SP, depending on CPU 0 or 1
|
// 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",
|
"mrc p15, #0, r0, c0, c0, #5",
|
||||||
concat!("movw r1, :lower16:", stringify!($stack0)),
|
concat!("movw r1, :lower16:", stringify!($stack0)),
|
||||||
concat!("movt r1, :upper16:", stringify!($stack0)),
|
concat!("movt r1, :upper16:", stringify!($stack0)),
|
||||||
"tst r0, #3",
|
"tst r0, #3",
|
||||||
concat!("movwne r1, :lower16:", stringify!($stack1)),
|
concat!("movwne r1, :lower16:", stringify!($stack1)),
|
||||||
concat!("movtne r1, :upper16:", stringify!($stack1)),
|
concat!("movtne r1, :upper16:", stringify!($stack1)),
|
||||||
"mov r0, sp",
|
|
||||||
"mov sp, r1",
|
"mov sp, r1",
|
||||||
"push {{r0, r1}}", // 2 registers are pushed to maintain 8 byte stack alignment
|
|
||||||
concat!("bl ", stringify!($name2)),
|
concat!("bl ", stringify!($name2)),
|
||||||
"pop {{r0, r1}}",
|
|
||||||
"mov sp, r0",
|
|
||||||
"ldmfd sp!, {{r0-r12, pc}}^", // caret ^ : copy SPSR to the CPSR
|
|
||||||
options(noreturn)
|
options(noreturn)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn $name2() $body
|
pub unsafe extern "C" fn $name2() -> ! $body
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
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}
|
||||||
@ -23,23 +20,6 @@ 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 {
|
||||||
@ -62,10 +42,6 @@ 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_exchange_weak(UNLOCKED, LOCKED, Ordering::AcqRel, Ordering::Relaxed).is_err() {
|
if self.locked.compare_exchange_weak(UNLOCKED, LOCKED, Ordering::AcqRel, Ordering::Relaxed).is_err() {
|
||||||
|
@ -2,7 +2,6 @@ use libregister::{
|
|||||||
register_bit, register_bits,
|
register_bit, register_bits,
|
||||||
RegisterR, RegisterW, RegisterRW,
|
RegisterR, RegisterW, RegisterRW,
|
||||||
};
|
};
|
||||||
use core::arch::asm;
|
|
||||||
|
|
||||||
macro_rules! def_reg_r {
|
macro_rules! def_reg_r {
|
||||||
($name:tt, $type: ty, $asm_instr:tt) => {
|
($name:tt, $type: ty, $asm_instr:tt) => {
|
||||||
@ -12,7 +11,7 @@ macro_rules! def_reg_r {
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn read(&self) -> Self::R {
|
fn read(&self) -> Self::R {
|
||||||
let mut value: u32;
|
let mut value: u32;
|
||||||
unsafe { asm!($asm_instr, lateout(reg) value) }
|
unsafe { llvm_asm!($asm_instr : "=r" (value) ::: "volatile") }
|
||||||
value.into()
|
value.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -27,7 +26,7 @@ macro_rules! def_reg_w {
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn write(&mut self, value: Self::W) {
|
fn write(&mut self, value: Self::W) {
|
||||||
let value: u32 = value.into();
|
let value: u32 = value.into();
|
||||||
unsafe { asm!($asm_instr, in(reg) value) }
|
unsafe { llvm_asm!($asm_instr :: "r" (value) :: "volatile") }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -72,29 +71,29 @@ macro_rules! wrap_reg {
|
|||||||
|
|
||||||
/// Stack Pointer
|
/// Stack Pointer
|
||||||
pub struct SP;
|
pub struct SP;
|
||||||
def_reg_r!(SP, u32, "mov {}, sp");
|
def_reg_r!(SP, u32, "mov $0, sp");
|
||||||
def_reg_w!(SP, u32, "mov sp, {}");
|
def_reg_w!(SP, u32, "mov sp, $0");
|
||||||
|
|
||||||
/// Link register (function call return address)
|
/// Link register (function call return address)
|
||||||
pub struct LR;
|
pub struct LR;
|
||||||
def_reg_r!(LR, u32, "mov {}, lr");
|
def_reg_r!(LR, u32, "mov $0, lr");
|
||||||
def_reg_w!(LR, u32, "mov lr, {}");
|
def_reg_w!(LR, u32, "mov lr, $0");
|
||||||
|
|
||||||
pub struct VBAR;
|
pub struct VBAR;
|
||||||
def_reg_r!(VBAR, u32, "mrc p15, 0, {}, c12, c0, 0");
|
def_reg_r!(VBAR, u32, "mrc p15, 0, $0, c12, c0, 0");
|
||||||
def_reg_w!(VBAR, u32, "mcr p15, 0, {}, c12, c0, 0");
|
def_reg_w!(VBAR, u32, "mcr p15, 0, $0, c12, c0, 0");
|
||||||
|
|
||||||
pub struct MVBAR;
|
pub struct MVBAR;
|
||||||
def_reg_r!(MVBAR, u32, "mrc p15, 0, {}, c12, c0, 1");
|
def_reg_r!(MVBAR, u32, "mrc p15, 0, $0, c12, c0, 1");
|
||||||
def_reg_w!(MVBAR, u32, "mcr p15, 0, {}, c12, c0, 1");
|
def_reg_w!(MVBAR, u32, "mcr p15, 0, $0, c12, c0, 1");
|
||||||
|
|
||||||
pub struct HVBAR;
|
pub struct HVBAR;
|
||||||
def_reg_r!(HVBAR, u32, "mrc p15, 4, {}, c12, c0, 0");
|
def_reg_r!(HVBAR, u32, "mrc p15, 4, $0, c12, c0, 0");
|
||||||
def_reg_w!(HVBAR, u32, "mcr p15, 4, {}, c12, c0, 0");
|
def_reg_w!(HVBAR, u32, "mcr p15, 4, $0, c12, c0, 0");
|
||||||
|
|
||||||
/// Multiprocess Affinity Register
|
/// Multiprocess Affinity Register
|
||||||
pub struct MPIDR;
|
pub struct MPIDR;
|
||||||
def_reg_r!(MPIDR, mpidr::Read, "mrc p15, 0, {}, c0, c0, 5");
|
def_reg_r!(MPIDR, mpidr::Read, "mrc p15, 0, $0, c0, c0, 5");
|
||||||
wrap_reg!(mpidr);
|
wrap_reg!(mpidr);
|
||||||
register_bits!(mpidr,
|
register_bits!(mpidr,
|
||||||
/// CPU core index
|
/// CPU core index
|
||||||
@ -107,15 +106,15 @@ register_bit!(mpidr,
|
|||||||
u, 30);
|
u, 30);
|
||||||
|
|
||||||
pub struct DFAR;
|
pub struct DFAR;
|
||||||
def_reg_r!(DFAR, u32, "mrc p15, 0, {}, c6, c0, 0");
|
def_reg_r!(DFAR, u32, "mrc p15, 0, $0, c6, c0, 0");
|
||||||
|
|
||||||
pub struct DFSR;
|
pub struct DFSR;
|
||||||
def_reg_r!(DFSR, u32, "mrc p15, 0, {}, c5, c0, 0");
|
def_reg_r!(DFSR, u32, "mrc p15, 0, $0, c5, c0, 0");
|
||||||
|
|
||||||
pub struct SCTLR;
|
pub struct SCTLR;
|
||||||
wrap_reg!(sctlr);
|
wrap_reg!(sctlr);
|
||||||
def_reg_r!(SCTLR, sctlr::Read, "mrc p15, 0, {}, c1, c0, 0");
|
def_reg_r!(SCTLR, sctlr::Read, "mrc p15, 0, $0, c1, c0, 0");
|
||||||
def_reg_w!(SCTLR, sctlr::Write, "mcr p15, 0, {}, c1, c0, 0");
|
def_reg_w!(SCTLR, sctlr::Write, "mcr p15, 0, $0, c1, c0, 0");
|
||||||
register_bit!(sctlr,
|
register_bit!(sctlr,
|
||||||
/// Enables MMU
|
/// Enables MMU
|
||||||
m, 0);
|
m, 0);
|
||||||
@ -148,8 +147,8 @@ register_bit!(sctlr,
|
|||||||
/// Auxiliary Control Register
|
/// Auxiliary Control Register
|
||||||
pub struct ACTLR;
|
pub struct ACTLR;
|
||||||
wrap_reg!(actlr);
|
wrap_reg!(actlr);
|
||||||
def_reg_r!(ACTLR, actlr::Read, "mrc p15, 0, {}, c1, c0, 1");
|
def_reg_r!(ACTLR, actlr::Read, "mrc p15, 0, $0, c1, c0, 1");
|
||||||
def_reg_w!(ACTLR, actlr::Write, "mcr p15, 0, {}, c1, c0, 1");
|
def_reg_w!(ACTLR, actlr::Write, "mcr p15, 0, $0, c1, c0, 1");
|
||||||
// SMP bit
|
// SMP bit
|
||||||
register_bit!(actlr, parity_on, 9);
|
register_bit!(actlr, parity_on, 9);
|
||||||
register_bit!(actlr, alloc_one_way, 8);
|
register_bit!(actlr, alloc_one_way, 8);
|
||||||
@ -184,17 +183,17 @@ impl ACTLR {
|
|||||||
|
|
||||||
/// Domain Access Control Register
|
/// Domain Access Control Register
|
||||||
pub struct DACR;
|
pub struct DACR;
|
||||||
def_reg_r!(DACR, u32, "mrc p15, 0, {}, c3, c0, 0");
|
def_reg_r!(DACR, u32, "mrc p15, 0, $0, c3, c0, 0");
|
||||||
def_reg_w!(DACR, u32, "mcr p15, 0, {}, c3, c0, 0");
|
def_reg_w!(DACR, u32, "mcr p15, 0, $0, c3, c0, 0");
|
||||||
|
|
||||||
/// Translation Table Base Register 0
|
/// Translation Table Base Register 0
|
||||||
pub struct TTBR0;
|
pub struct TTBR0;
|
||||||
/// Translation Table Base Register 1
|
/// Translation Table Base Register 1
|
||||||
pub struct TTBR1;
|
pub struct TTBR1;
|
||||||
def_reg_r!(TTBR0, ttbr::Read, "mrc p15, 0, {}, c2, c0, 0");
|
def_reg_r!(TTBR0, ttbr::Read, "mrc p15, 0, $0, c2, c0, 0");
|
||||||
def_reg_w!(TTBR0, ttbr::Write, "mcr p15, 0, {}, c2, c0, 0");
|
def_reg_w!(TTBR0, ttbr::Write, "mcr p15, 0, $0, c2, c0, 0");
|
||||||
def_reg_r!(TTBR1, ttbr::Read, "mrc p15, 0, {}, c2, c0, 1");
|
def_reg_r!(TTBR1, ttbr::Read, "mrc p15, 0, $0, c2, c0, 1");
|
||||||
def_reg_w!(TTBR1, ttbr::Write, "mcr p15, 0, {}, c2, c0, 1");
|
def_reg_w!(TTBR1, ttbr::Write, "mcr p15, 0, $0, c2, c0, 1");
|
||||||
wrap_reg!(ttbr);
|
wrap_reg!(ttbr);
|
||||||
register_bits!(ttbr, table_base, u32, 14, 31);
|
register_bits!(ttbr, table_base, u32, 14, 31);
|
||||||
register_bit!(ttbr, irgn0, 6);
|
register_bit!(ttbr, irgn0, 6);
|
||||||
|
@ -172,15 +172,13 @@ impl<'a, T> Iterator for Receiver<'a, T> where T: Clone {
|
|||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
/// Macro for initializing the sync_channel with static buffer and indexes.
|
/// Macro for initializing the sync_channel with static buffer and indexes.
|
||||||
|
/// Note that this requires `#![feature(const_in_array_repeat_expressions)]`
|
||||||
macro_rules! sync_channel {
|
macro_rules! sync_channel {
|
||||||
($t: ty, $cap: expr) => {
|
($t: ty, $cap: expr) => {
|
||||||
{
|
{
|
||||||
use core::sync::atomic::{AtomicUsize, AtomicPtr};
|
use core::sync::atomic::{AtomicUsize, AtomicPtr};
|
||||||
use $crate::sync_channel::{Sender, Receiver};
|
use $crate::sync_channel::{Sender, Receiver};
|
||||||
const fn new_atomic() -> AtomicPtr<$t> {
|
static LIST: [AtomicPtr<$t>; $cap + 1] = [AtomicPtr::new(core::ptr::null_mut()); $cap + 1];
|
||||||
AtomicPtr::new(core::ptr::null_mut())
|
|
||||||
}
|
|
||||||
static LIST: [AtomicPtr<$t>; $cap + 1] = [const { new_atomic() }; $cap + 1];
|
|
||||||
static WRITE: AtomicUsize = AtomicUsize::new(0);
|
static WRITE: AtomicUsize = AtomicUsize::new(0);
|
||||||
static READ: AtomicUsize = AtomicUsize::new(0);
|
static READ: AtomicUsize = AtomicUsize::new(0);
|
||||||
(Sender::new(&LIST, &WRITE, &READ), Receiver::new(&LIST, &WRITE, &READ))
|
(Sender::new(&LIST, &WRITE, &READ), Receiver::new(&LIST, &WRITE, &READ))
|
||||||
|
@ -8,19 +8,17 @@ edition = "2018"
|
|||||||
[features]
|
[features]
|
||||||
target_zc706 = ["libboard_zynq/target_zc706"]
|
target_zc706 = ["libboard_zynq/target_zc706"]
|
||||||
target_coraz7 = ["libboard_zynq/target_coraz7"]
|
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"]
|
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", "dummy_fiq_handler"]
|
default = ["panic_handler", "dummy_irq_handler"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
r0 = "1"
|
r0 = "1"
|
||||||
compiler_builtins = "=0.1.49"
|
compiler_builtins = "=0.1.39"
|
||||||
linked_list_allocator = { version = "0.8", default-features = false, features = ["const_mut_refs"] }
|
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" }
|
||||||
|
@ -1,11 +1,6 @@
|
|||||||
use libregister::{RegisterR, RegisterW};
|
use libregister::RegisterR;
|
||||||
use libcortex_a9::{regs::{DFSR, MPIDR, VBAR}, interrupt_handler};
|
use libcortex_a9::{regs::{DFSR, MPIDR}, interrupt_handler};
|
||||||
use libboard_zynq::{println, stdio};
|
use libboard_zynq::{println, stdio};
|
||||||
use core::arch::asm;
|
|
||||||
|
|
||||||
pub fn set_vector_table(base_addr: u32){
|
|
||||||
VBAR.write(base_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
interrupt_handler!(UndefinedInstruction, undefined_instruction, __irq_stack0_start, __irq_stack1_start, {
|
interrupt_handler!(UndefinedInstruction, undefined_instruction, __irq_stack0_start, __irq_stack1_start, {
|
||||||
stdio::drop_uart();
|
stdio::drop_uart();
|
||||||
@ -47,7 +42,6 @@ interrupt_handler!(IRQ, irq, __irq_stack0_start, __irq_stack1_start, {
|
|||||||
loop {}
|
loop {}
|
||||||
});
|
});
|
||||||
|
|
||||||
#[cfg(feature = "dummy_fiq_handler")]
|
|
||||||
interrupt_handler!(FIQ, fiq, __irq_stack0_start, __irq_stack1_start, {
|
interrupt_handler!(FIQ, fiq, __irq_stack0_start, __irq_stack1_start, {
|
||||||
stdio::drop_uart();
|
stdio::drop_uart();
|
||||||
println!("FIQ");
|
println!("FIQ");
|
@ -1,6 +1,5 @@
|
|||||||
use r0::zero_bss;
|
use r0::zero_bss;
|
||||||
use core::ptr::write_volatile;
|
use core::ptr::write_volatile;
|
||||||
use core::arch::asm;
|
|
||||||
use libregister::{
|
use libregister::{
|
||||||
VolatileCell,
|
VolatileCell,
|
||||||
RegisterR, RegisterRW,
|
RegisterR, RegisterRW,
|
||||||
@ -55,7 +54,6 @@ unsafe extern "C" 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");
|
||||||
@ -77,7 +75,6 @@ unsafe extern "C" 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");
|
||||||
|
@ -3,14 +3,13 @@
|
|||||||
#![feature(alloc_error_handler)]
|
#![feature(alloc_error_handler)]
|
||||||
#![feature(panic_info_message)]
|
#![feature(panic_info_message)]
|
||||||
#![feature(naked_functions)]
|
#![feature(naked_functions)]
|
||||||
#![feature(global_asm)]
|
|
||||||
#![feature(asm)]
|
#![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;
|
||||||
pub mod exception_vectors;
|
mod abort;
|
||||||
#[cfg(feature = "panic_handler")]
|
#[cfg(feature = "panic_handler")]
|
||||||
mod panic;
|
mod panic;
|
||||||
pub mod ram;
|
pub mod ram;
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
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) -> ! {
|
||||||
@ -15,10 +13,6 @@ 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 {}
|
||||||
}
|
}
|
||||||
|
22144
nix/channel-rust-nightly.toml
Normal file
22144
nix/channel-rust-nightly.toml
Normal file
File diff suppressed because it is too large
Load Diff
37
nix/fsbl.nix
Normal file
37
nix/fsbl.nix
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
{ 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;
|
||||||
|
}
|
31
nix/fsbl.patch
Normal file
31
nix/fsbl.patch
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
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
|
134
nix/gnutoolchain.nix
Normal file
134
nix/gnutoolchain.nix
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
{ 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" ];
|
||||||
|
};
|
||||||
|
}
|
24
nix/mkbootimage.nix
Normal file
24
nix/mkbootimage.nix
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{ 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
|
||||||
|
'';
|
||||||
|
}
|
10
nix/mozilla-overlay.nix
Normal file
10
nix/mozilla-overlay.nix
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
let
|
||||||
|
pkgs = import <nixpkgs> {};
|
||||||
|
overlay = pkgs.fetchFromGitHub {
|
||||||
|
owner = "mozilla";
|
||||||
|
repo = "nixpkgs-mozilla";
|
||||||
|
rev = "efda5b357451dbb0431f983cca679ae3cd9b9829";
|
||||||
|
sha256 = "11wqrg86g3qva67vnk81ynvqyfj0zxk83cbrf0p9hsvxiwxs8469";
|
||||||
|
};
|
||||||
|
in
|
||||||
|
import overlay
|
20
nix/rust-platform.nix
Normal file
20
nix/rust-platform.nix
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{ pkgs }:
|
||||||
|
|
||||||
|
let
|
||||||
|
rustManifest = ./channel-rust-nightly.toml;
|
||||||
|
|
||||||
|
targets = [];
|
||||||
|
rustChannelOfTargets = _channel: _date: targets:
|
||||||
|
(pkgs.lib.rustLib.fromManifestFile rustManifest {
|
||||||
|
inherit (pkgs) stdenv fetchurl patchelf;
|
||||||
|
}).rust.override {
|
||||||
|
inherit targets;
|
||||||
|
extensions = ["rust-src"];
|
||||||
|
};
|
||||||
|
rust =
|
||||||
|
rustChannelOfTargets "nightly" null targets;
|
||||||
|
in
|
||||||
|
pkgs.recurseIntoAttrs (pkgs.makeRustPlatform {
|
||||||
|
rustc = rust;
|
||||||
|
cargo = rust;
|
||||||
|
})
|
@ -1,20 +0,0 @@
|
|||||||
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
|
|
@ -8,12 +8,31 @@ source ./zynq-7000.cfg
|
|||||||
|
|
||||||
reset_config srst_only srst_push_pull
|
reset_config srst_only srst_push_pull
|
||||||
|
|
||||||
source ./common.cfg
|
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
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
adapter driver ftdi
|
interface ftdi
|
||||||
ftdi_vid_pid 0x0403 0x6014
|
ftdi_vid_pid 0x0403 0x6014
|
||||||
|
|
||||||
ftdi_channel 0
|
ftdi_channel 0
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
# The contents of this file are partially dependend on
|
|
||||||
# the adapter that you have. Please modify accordingly.
|
|
||||||
adapter driver ftdi
|
|
||||||
ftdi vid_pid 0x0403 0x6010
|
|
||||||
ftdi channel 0
|
|
||||||
# Every pin set as high impedance except TCK, TDI, TDO and TMS
|
|
||||||
ftdi layout_init 0x0088 0x008b
|
|
||||||
|
|
||||||
# nSRST defined on pin CN2-13 of the MiniModule (pin ADBUS5 [AD5] on the FT2232H chip)
|
|
||||||
# This choice is arbitrary. Use other GPIO pin if desired.
|
|
||||||
ftdi layout_signal nSRST -data 0x0020 -oe 0x0020
|
|
||||||
|
|
||||||
transport select jtag
|
|
||||||
adapter speed 10000
|
|
||||||
|
|
||||||
set PL_TAPID 0x13722093
|
|
||||||
set SMP 1
|
|
||||||
|
|
||||||
source ./zynq-7000.cfg
|
|
||||||
|
|
||||||
reset_config srst_only srst_open_drain
|
|
||||||
adapter srst pulse_width 250
|
|
||||||
adapter srst delay 400
|
|
||||||
|
|
||||||
source ./common.cfg
|
|
||||||
|
|
||||||
reset halt
|
|
||||||
|
|
||||||
# Disable MMU
|
|
||||||
targets $_TARGETNAME_1
|
|
||||||
arm mcr 15 0 1 0 0 [expr { [arm mrc 15 0 1 0 0] & ~0xd }]
|
|
||||||
targets $_TARGETNAME_0
|
|
||||||
arm mcr 15 0 1 0 0 [expr { [arm mrc 15 0 1 0 0] & ~0xd }]
|
|
@ -1,28 +0,0 @@
|
|||||||
adapter driver ftdi
|
|
||||||
ftdi_device_desc "Quad RS232-HS"
|
|
||||||
ftdi_vid_pid 0x0403 0x6011
|
|
||||||
ftdi_channel 0
|
|
||||||
# some GPIOs need to be set, otherwise the FTDI chip craps out for some reason.
|
|
||||||
ftdi_layout_init 0x0098 0x008b
|
|
||||||
transport select jtag
|
|
||||||
adapter speed 1000
|
|
||||||
|
|
||||||
set PL_TAPID 0x1372c093
|
|
||||||
set SMP 1
|
|
||||||
|
|
||||||
source ./zynq-7000.cfg
|
|
||||||
|
|
||||||
ftdi_layout_signal nSRST -oe 0x0004
|
|
||||||
reset_config srst_only srst_open_drain
|
|
||||||
adapter srst pulse_width 250
|
|
||||||
adapter srst delay 400
|
|
||||||
|
|
||||||
source ./common.cfg
|
|
||||||
|
|
||||||
reset halt
|
|
||||||
|
|
||||||
# Disable MMU
|
|
||||||
targets $_TARGETNAME_1
|
|
||||||
arm mcr 15 0 1 0 0 [expr { [arm mrc 15 0 1 0 0] & ~0xd }]
|
|
||||||
targets $_TARGETNAME_0
|
|
||||||
arm mcr 15 0 1 0 0 [expr { [arm mrc 15 0 1 0 0] & ~0xd }]
|
|
@ -1,5 +1,5 @@
|
|||||||
source ./digilent-hs2.cfg
|
source ./digilent-hs2.cfg
|
||||||
adapter speed 1000
|
adapter_khz 1000
|
||||||
|
|
||||||
set PL_TAPID 0x13722093
|
set PL_TAPID 0x13722093
|
||||||
set SMP 1
|
set SMP 1
|
||||||
@ -8,12 +8,31 @@ source ./zynq-7000.cfg
|
|||||||
|
|
||||||
reset_config none
|
reset_config none
|
||||||
|
|
||||||
source ./common.cfg
|
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
|
||||||
|
|
||||||
halt
|
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]
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
source [find interface/ftdi/olimex-arm-usb-tiny-h.cfg]
|
source [find interface/ftdi/olimex-arm-usb-tiny-h.cfg]
|
||||||
adapter speed 1000
|
adapter_khz 1000
|
||||||
|
|
||||||
set PL_TAPID 0x23731093
|
set PL_TAPID 0x23731093
|
||||||
set SMP 1
|
set SMP 1
|
||||||
@ -7,15 +7,34 @@ set SMP 1
|
|||||||
source ./zynq-7000.cfg
|
source ./zynq-7000.cfg
|
||||||
|
|
||||||
reset_config srst_only srst_open_drain
|
reset_config srst_only srst_open_drain
|
||||||
adapter srst pulse_width 250
|
adapter_nsrst_assert_width 250
|
||||||
adapter srst delay 400
|
adapter_nsrst_delay 400
|
||||||
|
|
||||||
source ./common.cfg
|
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
|
||||||
|
|
||||||
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]
|
||||||
|
@ -81,16 +81,15 @@ jtag newtap $_CHIPNAME dap -irlen 4 -ircapture 0x01 -irmask 0x03 \
|
|||||||
set _TARGETNAME_0 $_CHIPNAME.cpu.0
|
set _TARGETNAME_0 $_CHIPNAME.cpu.0
|
||||||
set _TARGETNAME_1 $_CHIPNAME.cpu.1
|
set _TARGETNAME_1 $_CHIPNAME.cpu.1
|
||||||
|
|
||||||
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.dap
|
|
||||||
target create $_TARGETNAME_0 cortex_a -coreid 0 \
|
target create $_TARGETNAME_0 cortex_a -coreid 0 \
|
||||||
-endian $_ENDIAN \
|
-endian $_ENDIAN \
|
||||||
-dap $_CHIPNAME.dap \
|
-chain-position $_CHIPNAME.dap \
|
||||||
-dbgbase 0x80090000
|
-dbgbase 0x80090000
|
||||||
if { $_SMP } {
|
if { $_SMP } {
|
||||||
echo "Zynq CPU1."
|
echo "Zynq CPU1."
|
||||||
target create $_TARGETNAME_1 cortex_a -coreid 1 \
|
target create $_TARGETNAME_1 cortex_a -coreid 1 \
|
||||||
-endian $_ENDIAN \
|
-endian $_ENDIAN \
|
||||||
-dap $_CHIPNAME.dap \
|
-chain-position $_CHIPNAME.dap \
|
||||||
-dbgbase 0x80092000
|
-dbgbase 0x80092000
|
||||||
target smp $_TARGETNAME_0 $_TARGETNAME_1
|
target smp $_TARGETNAME_0 $_TARGETNAME_1
|
||||||
}
|
}
|
||||||
|
26
shell.nix
Normal file
26
shell.nix
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
let
|
||||||
|
pkgs = import <nixpkgs> { overlays = [ (import ./nix/mozilla-overlay.nix) ]; };
|
||||||
|
rustPlatform = (import ./nix/rust-platform.nix { inherit pkgs; });
|
||||||
|
cargo-xbuild = (import ./default.nix).cargo-xbuild;
|
||||||
|
in
|
||||||
|
pkgs.stdenv.mkDerivation {
|
||||||
|
name = "zynq-env";
|
||||||
|
buildInputs = [
|
||||||
|
rustPlatform.rust.rustc
|
||||||
|
rustPlatform.rust.cargo
|
||||||
|
pkgs.cacert
|
||||||
|
cargo-xbuild
|
||||||
|
|
||||||
|
pkgs.openocd pkgs.gdb
|
||||||
|
pkgs.openssh pkgs.rsync
|
||||||
|
pkgs.llvmPackages_9.clang-unwrapped
|
||||||
|
|
||||||
|
(import ./nix/mkbootimage.nix { inherit pkgs; })
|
||||||
|
];
|
||||||
|
|
||||||
|
XARGO_RUST_SRC = "${rustPlatform.rust.rustc}/lib/rustlib/src/rust/library";
|
||||||
|
|
||||||
|
shellHook = ''
|
||||||
|
echo "Run 'cargo xbuild --release -p ...' to build."
|
||||||
|
'';
|
||||||
|
}
|
@ -8,7 +8,6 @@ edition = "2018"
|
|||||||
[features]
|
[features]
|
||||||
target_zc706 = ["libboard_zynq/target_zc706", "libsupport_zynq/target_zc706", "libconfig/target_zc706"]
|
target_zc706 = ["libboard_zynq/target_zc706", "libsupport_zynq/target_zc706", "libconfig/target_zc706"]
|
||||||
target_coraz7 = ["libboard_zynq/target_coraz7", "libsupport_zynq/target_coraz7", "libconfig/target_coraz7"]
|
target_coraz7 = ["libboard_zynq/target_coraz7", "libsupport_zynq/target_coraz7", "libconfig/target_coraz7"]
|
||||||
target_ebaz4205 = ["libboard_zynq/target_ebaz4205", "libsupport_zynq/target_ebaz4205", "libconfig/target_ebaz4205"]
|
|
||||||
target_redpitaya = ["libboard_zynq/target_redpitaya", "libsupport_zynq/target_redpitaya", "libconfig/target_redpitaya"]
|
target_redpitaya = ["libboard_zynq/target_redpitaya", "libsupport_zynq/target_redpitaya", "libconfig/target_redpitaya"]
|
||||||
target_kasli_soc = ["libboard_zynq/target_kasli_soc", "libsupport_zynq/target_kasli_soc", "libconfig/target_kasli_soc"]
|
target_kasli_soc = ["libboard_zynq/target_kasli_soc", "libsupport_zynq/target_kasli_soc", "libconfig/target_kasli_soc"]
|
||||||
default = ["target_zc706"]
|
default = ["target_zc706"]
|
||||||
@ -16,14 +15,10 @@ default = ["target_zc706"]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
byteorder = { version = "1.3", default-features = false }
|
byteorder = { version = "1.3", default-features = false }
|
||||||
|
core_io = { version = "0.1", features = ["collections"] }
|
||||||
|
|
||||||
libboard_zynq = { path = "../libboard_zynq" }
|
libboard_zynq = { path = "../libboard_zynq" }
|
||||||
libsupport_zynq = { path = "../libsupport_zynq" }
|
libsupport_zynq = { path = "../libsupport_zynq" }
|
||||||
libcortex_a9 = { path = "../libcortex_a9" }
|
libcortex_a9 = { path = "../libcortex_a9" }
|
||||||
libregister = { path = "../libregister" }
|
libregister = { path = "../libregister" }
|
||||||
libconfig = { path = "../libconfig" }
|
libconfig = { path = "../libconfig" }
|
||||||
|
|
||||||
[dependencies.core_io]
|
|
||||||
git = "https://git.m-labs.hk/M-Labs/rs-core_io.git"
|
|
||||||
rev = "e9d3edf027"
|
|
||||||
features = ["collections"]
|
|
||||||
|
|
||||||
|
@ -75,20 +75,13 @@ pub fn main_core0() {
|
|||||||
___/ / / /__/ /___
|
___/ / / /__/ /___
|
||||||
/____/ /____/_____/
|
/____/ /____/_____/
|
||||||
|
|
||||||
(C) 2020-2022 M-Labs
|
(C) 2020 M-Labs
|
||||||
"#
|
"#
|
||||||
);
|
);
|
||||||
info!("Simple Zynq Loader starting...");
|
info!("Simple Zynq Loader starting...");
|
||||||
|
|
||||||
#[cfg(not(any(feature = "target_kasli_soc", feature = "target_ebaz4205")))]
|
|
||||||
const CPU_FREQ: u32 = 800_000_000;
|
const CPU_FREQ: u32 = 800_000_000;
|
||||||
|
|
||||||
#[cfg(feature = "target_kasli_soc")]
|
|
||||||
const CPU_FREQ: u32 = 1_000_000_000;
|
|
||||||
|
|
||||||
#[cfg(feature = "target_ebaz4205")]
|
|
||||||
const CPU_FREQ: u32 = 666_666_666;
|
|
||||||
|
|
||||||
ArmPll::setup(2 * CPU_FREQ);
|
ArmPll::setup(2 * CPU_FREQ);
|
||||||
Clocks::set_cpu_freq(CPU_FREQ);
|
Clocks::set_cpu_freq(CPU_FREQ);
|
||||||
IoPll::setup(1_000_000_000);
|
IoPll::setup(1_000_000_000);
|
||||||
@ -143,14 +136,7 @@ pub fn main_core0() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
v => {
|
v => {
|
||||||
log::error!("Boot mode {:?} not supported", v);
|
panic!("Boot mode {:?} not supported", v);
|
||||||
log::info!("Fall back on netboot");
|
|
||||||
netboot::netboot(
|
|
||||||
&mut bootgen_file,
|
|
||||||
config,
|
|
||||||
&mut __runtime_start as *mut usize as *mut u8,
|
|
||||||
max_len,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -316,7 +316,7 @@ pub fn netboot<File: Read + Seek>(
|
|||||||
runtime_max_len: usize,
|
runtime_max_len: usize,
|
||||||
) {
|
) {
|
||||||
log::info!("Preparing network for netboot");
|
log::info!("Preparing network for netboot");
|
||||||
let net_addresses = net_settings::get_addresses(&cfg);
|
let net_addresses = net_settings::get_adresses(&cfg);
|
||||||
log::info!("Network addresses: {}", net_addresses);
|
log::info!("Network addresses: {}", net_addresses);
|
||||||
let eth = Eth::eth0(net_addresses.hardware_addr.0.clone());
|
let eth = Eth::eth0(net_addresses.hardware_addr.0.clone());
|
||||||
let eth = eth.start_rx(8);
|
let eth = eth.start_rx(8);
|
||||||
|
27
xbuild_writable_lockfile.diff
Normal file
27
xbuild_writable_lockfile.diff
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
diff --git a/src/sysroot.rs b/src/sysroot.rs
|
||||||
|
index 1f3c8d1..422d3d0 100644
|
||||||
|
--- a/src/sysroot.rs
|
||||||
|
+++ b/src/sysroot.rs
|
||||||
|
@@ -85,10 +85,20 @@ fn build_crate(
|
||||||
|
}
|
||||||
|
|
||||||
|
util::write(&td.join("Cargo.toml"), &stoml)?;
|
||||||
|
- fs::copy(lockfile, &td.join("Cargo.lock")).chain_err(||
|
||||||
|
+ let dst_file = td.join("Cargo.lock");
|
||||||
|
+ fs::copy(lockfile, &dst_file).chain_err(||
|
||||||
|
format!("failed to copy Cargo.lock from `{}` to `{}`",
|
||||||
|
- lockfile.display(), &td.join("Cargo.lock").display())
|
||||||
|
+ lockfile.display(), &dst_file.display())
|
||||||
|
)?;
|
||||||
|
+ let mut perms = fs::metadata(&dst_file).chain_err(||
|
||||||
|
+ format!("failed to retrieve permissions for `{}`",
|
||||||
|
+ dst_file.display())
|
||||||
|
+ )?.permissions();
|
||||||
|
+ perms.set_readonly(false);
|
||||||
|
+ fs::set_permissions(&dst_file, perms).chain_err(||
|
||||||
|
+ format!("failed to update permissions for `{}`",
|
||||||
|
+ dst_file.display())
|
||||||
|
+ );
|
||||||
|
util::mkdir(&td.join("src"))?;
|
||||||
|
util::write(&td.join("src/lib.rs"), "")?;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user