UART and docs update
Some checks are pending
ci / Check build (push) Waiting to run
ci / Check formatting (push) Waiting to run
ci / Check Documentation Build (push) Waiting to run
ci / Clippy (push) Waiting to run
ci / Check build (pull_request) Waiting to run
ci / Check formatting (pull_request) Waiting to run
ci / Check Documentation Build (pull_request) Waiting to run
ci / Clippy (pull_request) Waiting to run
Some checks are pending
ci / Check build (push) Waiting to run
ci / Check formatting (push) Waiting to run
ci / Check Documentation Build (push) Waiting to run
ci / Clippy (push) Waiting to run
ci / Check build (pull_request) Waiting to run
ci / Check formatting (pull_request) Waiting to run
ci / Check Documentation Build (pull_request) Waiting to run
ci / Clippy (pull_request) Waiting to run
This commit is contained in:
@@ -19,3 +19,23 @@ exclude = [
|
|||||||
# Exclude, can not be built with debug optimization level, too large.
|
# Exclude, can not be built with debug optimization level, too large.
|
||||||
"zedboard-fsbl",
|
"zedboard-fsbl",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# cargo build/run
|
||||||
|
[profile.dev]
|
||||||
|
# default is opt-level = '0', but that makes very
|
||||||
|
# verbose machine code
|
||||||
|
opt-level = 's'
|
||||||
|
# trade compile speed for slightly better optimisations
|
||||||
|
codegen-units = 1
|
||||||
|
|
||||||
|
# cargo build/run --release
|
||||||
|
[profile.release]
|
||||||
|
# Optimize for maximum speed.
|
||||||
|
opt-level = 3
|
||||||
|
# trade compile speed for slightly better optimisations
|
||||||
|
codegen-units = 1
|
||||||
|
# Use Link Time Optimisations to further inline things across
|
||||||
|
# crates
|
||||||
|
lto = 'fat'
|
||||||
|
# Leave the debug symbols in (default is no debug info)
|
||||||
|
debug = 2
|
||||||
|
|||||||
@@ -31,24 +31,3 @@ embassy-executor = { version = "0.9", features = [
|
|||||||
]}
|
]}
|
||||||
# TODO: Remove generic-queue-16 feature as soon as upstream executor is used again.
|
# TODO: Remove generic-queue-16 feature as soon as upstream executor is used again.
|
||||||
embassy-time = { version = "0.5", features = ["tick-hz-1_000_000", "generic-queue-16"] }
|
embassy-time = { version = "0.5", features = ["tick-hz-1_000_000", "generic-queue-16"] }
|
||||||
|
|
||||||
# cargo build/run
|
|
||||||
[profile.dev]
|
|
||||||
# default is opt-level = '0', but that makes very
|
|
||||||
# verbose machine code
|
|
||||||
opt-level = 's'
|
|
||||||
# trade compile speed for slightly better optimisations
|
|
||||||
codegen-units = 1
|
|
||||||
|
|
||||||
# cargo build/run --release
|
|
||||||
[profile.release]
|
|
||||||
# default is opt-level = '3', but that makes quite
|
|
||||||
# verbose machine code
|
|
||||||
opt-level = 's'
|
|
||||||
# trade compile speed for slightly better optimisations
|
|
||||||
codegen-units = 1
|
|
||||||
# Use Link Time Optimisations to further inline things across
|
|
||||||
# crates
|
|
||||||
lto = 'fat'
|
|
||||||
# Leave the debug symbols in (default is no debug info)
|
|
||||||
debug = 2
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ async fn main(_spawner: Spawner) -> ! {
|
|||||||
let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0;
|
.0;
|
||||||
let mut uart = Uart::new_with_mio(
|
let mut uart = Uart::new_with_mio_for_uart_1(
|
||||||
dp.uart_1,
|
dp.uart_1,
|
||||||
Config::new_with_clk_config(uart_clk_config),
|
Config::new_with_clk_config(uart_clk_config),
|
||||||
(mio_pins.mio48, mio_pins.mio49),
|
(mio_pins.mio48, mio_pins.mio49),
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ async fn main(_spawner: Spawner) -> ! {
|
|||||||
let uart_clk_config = uart::ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
let uart_clk_config = uart::ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0;
|
.0;
|
||||||
let mut uart = uart::Uart::new_with_mio(
|
let mut uart = uart::Uart::new_with_mio_for_uart_1(
|
||||||
periphs.uart_1,
|
periphs.uart_1,
|
||||||
uart::Config::new_with_clk_config(uart_clk_config),
|
uart::Config::new_with_clk_config(uart_clk_config),
|
||||||
(mio_pins.mio48, mio_pins.mio49),
|
(mio_pins.mio48, mio_pins.mio49),
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ async fn main(spawner: Spawner) -> ! {
|
|||||||
let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0;
|
.0;
|
||||||
let mut uart = Uart::new_with_mio(
|
let mut uart = Uart::new_with_mio_for_uart_1(
|
||||||
dp.uart_1,
|
dp.uart_1,
|
||||||
Config::new_with_clk_config(uart_clk_config),
|
Config::new_with_clk_config(uart_clk_config),
|
||||||
(mio_pins.mio48, mio_pins.mio49),
|
(mio_pins.mio48, mio_pins.mio49),
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ async fn main(_spawner: Spawner) -> ! {
|
|||||||
let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0;
|
.0;
|
||||||
let mut uart = Uart::new_with_mio(
|
let mut uart = Uart::new_with_mio_for_uart_1(
|
||||||
dp.uart_1,
|
dp.uart_1,
|
||||||
Config::new_with_clk_config(uart_clk_config),
|
Config::new_with_clk_config(uart_clk_config),
|
||||||
(mio_pins.mio48, mio_pins.mio49),
|
(mio_pins.mio48, mio_pins.mio49),
|
||||||
|
|||||||
@@ -17,8 +17,3 @@ embedded-io = "0.7"
|
|||||||
embedded-hal = "1"
|
embedded-hal = "1"
|
||||||
fugit = "0.3"
|
fugit = "0.3"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
|
||||||
[profile.release]
|
|
||||||
codegen-units = 1
|
|
||||||
debug = true
|
|
||||||
lto = true
|
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ pub fn main() -> ! {
|
|||||||
|
|
||||||
// This structure holds all MIO pins.
|
// This structure holds all MIO pins.
|
||||||
let mio_pins = mio::Pins::new(dp.gpio);
|
let mio_pins = mio::Pins::new(dp.gpio);
|
||||||
let mut uart = Uart::new_with_mio(
|
let mut uart = Uart::new_with_mio_for_uart_1(
|
||||||
dp.uart_1,
|
dp.uart_1,
|
||||||
Config::new_with_clk_config(uart_clk_config),
|
Config::new_with_clk_config(uart_clk_config),
|
||||||
(mio_pins.mio48, mio_pins.mio49),
|
(mio_pins.mio48, mio_pins.mio49),
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ pub fn main() -> ! {
|
|||||||
gtc.enable();
|
gtc.enable();
|
||||||
let mio_pins = mio::Pins::new(dp.gpio);
|
let mio_pins = mio::Pins::new(dp.gpio);
|
||||||
|
|
||||||
let mut uart = Uart::new_with_mio(
|
let mut uart = Uart::new_with_mio_for_uart_1(
|
||||||
dp.uart_1,
|
dp.uart_1,
|
||||||
Config::new_with_clk_config(uart_clk_config),
|
Config::new_with_clk_config(uart_clk_config),
|
||||||
(mio_pins.mio48, mio_pins.mio49),
|
(mio_pins.mio48, mio_pins.mio49),
|
||||||
|
|||||||
@@ -42,10 +42,5 @@ embassy-net = { version = "0.7", features = ["dhcpv4", "packet-trace", "medium-e
|
|||||||
embassy-sync = { version = "0.7" }
|
embassy-sync = { version = "0.7" }
|
||||||
# TODO: Bump as soon as new compatible smoltcp/embassy-net version is released.
|
# TODO: Bump as soon as new compatible smoltcp/embassy-net version is released.
|
||||||
heapless = "0.8"
|
heapless = "0.8"
|
||||||
axi-uartlite = { git = "https://egit.irs.uni-stuttgart.de/rust/axi-uartlite.git" }
|
axi-uartlite = { version = "0.1" }
|
||||||
axi-uart16550 = { git = "https://egit.irs.uni-stuttgart.de/rust/axi-uart16550.git" }
|
axi-uart16550 = { version = "0.1" }
|
||||||
|
|
||||||
[profile.release]
|
|
||||||
codegen-units = 1
|
|
||||||
debug = true
|
|
||||||
lto = true
|
|
||||||
|
|||||||
@@ -237,7 +237,7 @@ async fn main(spawner: Spawner) -> ! {
|
|||||||
let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0;
|
.0;
|
||||||
let mut uart = Uart::new_with_mio(
|
let mut uart = Uart::new_with_mio_for_uart_1(
|
||||||
dp.uart_1,
|
dp.uart_1,
|
||||||
Config::new_with_clk_config(uart_clk_config),
|
Config::new_with_clk_config(uart_clk_config),
|
||||||
(gpio_pins.mio.mio48, gpio_pins.mio.mio49),
|
(gpio_pins.mio.mio48, gpio_pins.mio.mio49),
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ async fn main(_spawner: Spawner) -> ! {
|
|||||||
let uart_clk_config = uart::ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
let uart_clk_config = uart::ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0;
|
.0;
|
||||||
let mut uart = uart::Uart::new_with_mio(
|
let mut uart = uart::Uart::new_with_mio_for_uart_1(
|
||||||
dp.uart_1,
|
dp.uart_1,
|
||||||
uart::Config::new_with_clk_config(uart_clk_config),
|
uart::Config::new_with_clk_config(uart_clk_config),
|
||||||
(gpio_pins.mio.mio48, gpio_pins.mio.mio49),
|
(gpio_pins.mio.mio48, gpio_pins.mio.mio49),
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ async fn main(spawner: Spawner) -> ! {
|
|||||||
let uart_clk_config = uart::ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
let uart_clk_config = uart::ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0;
|
.0;
|
||||||
let mut uart = uart::Uart::new_with_mio(
|
let mut uart = uart::Uart::new_with_mio_for_uart_1(
|
||||||
dp.uart_1,
|
dp.uart_1,
|
||||||
uart::Config::new_with_clk_config(uart_clk_config),
|
uart::Config::new_with_clk_config(uart_clk_config),
|
||||||
(gpio_pins.mio.mio48, gpio_pins.mio.mio49),
|
(gpio_pins.mio.mio48, gpio_pins.mio.mio49),
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ async fn main(_spawner: Spawner) -> ! {
|
|||||||
let uart_clk_config = uart::ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
let uart_clk_config = uart::ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0;
|
.0;
|
||||||
let mut uart = uart::Uart::new_with_mio(
|
let mut uart = uart::Uart::new_with_mio_for_uart_1(
|
||||||
periphs.uart_1,
|
periphs.uart_1,
|
||||||
uart::Config::new_with_clk_config(uart_clk_config),
|
uart::Config::new_with_clk_config(uart_clk_config),
|
||||||
(gpio_pins.mio.mio48, gpio_pins.mio.mio49),
|
(gpio_pins.mio.mio48, gpio_pins.mio.mio49),
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ async fn main(_spawner: Spawner) -> ! {
|
|||||||
let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0;
|
.0;
|
||||||
let mut log_uart = Uart::new_with_mio(
|
let mut log_uart = Uart::new_with_mio_for_uart_1(
|
||||||
dp.uart_1,
|
dp.uart_1,
|
||||||
Config::new_with_clk_config(uart_clk_config),
|
Config::new_with_clk_config(uart_clk_config),
|
||||||
(gpio_pins.mio.mio48, gpio_pins.mio.mio49),
|
(gpio_pins.mio.mio48, gpio_pins.mio.mio49),
|
||||||
@@ -151,7 +151,7 @@ async fn main(_spawner: Spawner) -> ! {
|
|||||||
|
|
||||||
// TODO: Can we determine/read the clock frequency to the FPGAs as well?
|
// TODO: Can we determine/read the clock frequency to the FPGAs as well?
|
||||||
let (clk_config, error) =
|
let (clk_config, error) =
|
||||||
axi_uart16550::ClkConfig::new_autocalc_with_error(100.MHz(), 115200).unwrap();
|
axi_uart16550::ClockConfig::new_autocalc_with_error(100.MHz(), 115200).unwrap();
|
||||||
assert!(error < 0.02);
|
assert!(error < 0.02);
|
||||||
let mut uart_16550 = unsafe {
|
let mut uart_16550 = unsafe {
|
||||||
AxiUart16550::new(
|
AxiUart16550::new(
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ async fn main(spawner: Spawner) -> ! {
|
|||||||
let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0;
|
.0;
|
||||||
let mut log_uart = Uart::new_with_mio(
|
let mut log_uart = Uart::new_with_mio_for_uart_1(
|
||||||
dp.uart_1,
|
dp.uart_1,
|
||||||
Config::new_with_clk_config(uart_clk_config),
|
Config::new_with_clk_config(uart_clk_config),
|
||||||
(gpio_pins.mio.mio48, gpio_pins.mio.mio49),
|
(gpio_pins.mio.mio48, gpio_pins.mio.mio49),
|
||||||
@@ -245,7 +245,7 @@ async fn main(spawner: Spawner) -> ! {
|
|||||||
uartlite.enable_interrupt();
|
uartlite.enable_interrupt();
|
||||||
|
|
||||||
let (clk_config, error) =
|
let (clk_config, error) =
|
||||||
axi_uart16550::ClkConfig::new_autocalc_with_error(clocks.pl_clocks()[0], 115200).unwrap();
|
axi_uart16550::ClockConfig::new_autocalc_with_error(clocks.pl_clocks()[0], 115200).unwrap();
|
||||||
assert!(error < 0.02);
|
assert!(error < 0.02);
|
||||||
let _uart_16550 = unsafe {
|
let _uart_16550 = unsafe {
|
||||||
AxiUart16550::new(
|
AxiUart16550::new(
|
||||||
@@ -492,19 +492,19 @@ fn on_interrupt_axi_16550() {
|
|||||||
let iir = rx.read_iir();
|
let iir = rx.read_iir();
|
||||||
if let Ok(int_id) = iir.int_id() {
|
if let Ok(int_id) = iir.int_id() {
|
||||||
match int_id {
|
match int_id {
|
||||||
axi_uart16550::registers::IntId2::ReceiverLineStatus => {
|
axi_uart16550::registers::InterruptId2::ReceiverLineStatus => {
|
||||||
let errors = rx.on_interrupt_receiver_line_status(iir);
|
let errors = rx.on_interrupt_receiver_line_status(iir);
|
||||||
warn!("Receiver line status error: {errors:?}");
|
warn!("Receiver line status error: {errors:?}");
|
||||||
}
|
}
|
||||||
axi_uart16550::registers::IntId2::RxDataAvailable
|
axi_uart16550::registers::InterruptId2::RxDataAvailable
|
||||||
| axi_uart16550::registers::IntId2::CharTimeout => {
|
| axi_uart16550::registers::InterruptId2::CharTimeout => {
|
||||||
read_bytes = rx.on_interrupt_data_available_or_char_timeout(int_id, &mut buf);
|
read_bytes = rx.on_interrupt_data_available_or_char_timeout(int_id, &mut buf);
|
||||||
}
|
}
|
||||||
axi_uart16550::registers::IntId2::ThrEmpty => {
|
axi_uart16550::registers::InterruptId2::ThrEmpty => {
|
||||||
let mut tx = unsafe { axi_uart16550::Tx::steal(AXI_UAR16550_BASE_ADDR as usize) };
|
let mut tx = unsafe { axi_uart16550::Tx::steal(AXI_UAR16550_BASE_ADDR as usize) };
|
||||||
axi_uart16550::tx_async::on_interrupt_tx(&mut tx, 0);
|
axi_uart16550::tx_async::on_interrupt_tx(&mut tx, 0);
|
||||||
}
|
}
|
||||||
axi_uart16550::registers::IntId2::ModemStatus => (),
|
axi_uart16550::registers::InterruptId2::ModemStatus => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Send received RX data to main task.
|
// Send received RX data to main task.
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ async fn main(_spawner: Spawner) -> ! {
|
|||||||
let uart_clk_config = uart::ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
let uart_clk_config = uart::ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0;
|
.0;
|
||||||
let mut uart = uart::Uart::new_with_mio(
|
let mut uart = uart::Uart::new_with_mio_for_uart_1(
|
||||||
periphs.uart_1,
|
periphs.uart_1,
|
||||||
uart::Config::new_with_clk_config(uart_clk_config),
|
uart::Config::new_with_clk_config(uart_clk_config),
|
||||||
(gpio_pins.mio.mio48, gpio_pins.mio.mio49),
|
(gpio_pins.mio.mio48, gpio_pins.mio.mio49),
|
||||||
|
|||||||
@@ -20,3 +20,23 @@ embedded-hal = "1"
|
|||||||
fugit = "0.3"
|
fugit = "0.3"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
arbitrary-int = "2"
|
arbitrary-int = "2"
|
||||||
|
|
||||||
|
# cargo build/run
|
||||||
|
[profile.dev]
|
||||||
|
# default is opt-level = '0', but that makes very
|
||||||
|
# verbose machine code
|
||||||
|
opt-level = 's'
|
||||||
|
# trade compile speed for slightly better optimisations
|
||||||
|
codegen-units = 1
|
||||||
|
|
||||||
|
# cargo build/run --release
|
||||||
|
[profile.release]
|
||||||
|
# Optimize for size.
|
||||||
|
opt-level = 's'
|
||||||
|
# trade compile speed for slightly better optimisations
|
||||||
|
codegen-units = 1
|
||||||
|
# Use Link Time Optimisations to further inline things across
|
||||||
|
# crates
|
||||||
|
lto = 'fat'
|
||||||
|
# Leave the debug symbols in (default is no debug info)
|
||||||
|
debug = 2
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ pub fn main() -> ! {
|
|||||||
let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
let uart_clk_config = ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0;
|
.0;
|
||||||
let mut logger_uart = Uart::new_with_mio(
|
let mut logger_uart = Uart::new_with_mio_for_uart_1(
|
||||||
periphs.uart_1,
|
periphs.uart_1,
|
||||||
Config::new_with_clk_config(uart_clk_config),
|
Config::new_with_clk_config(uart_clk_config),
|
||||||
(mio_pins.mio48, mio_pins.mio49),
|
(mio_pins.mio48, mio_pins.mio49),
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ pub fn main() -> ! {
|
|||||||
let uart_clk_config = uart::ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
let uart_clk_config = uart::ClockConfig::new_autocalc_with_error(clocks.io_clocks(), 115200)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0;
|
.0;
|
||||||
let mut uart = uart::Uart::new_with_mio(
|
let mut uart = uart::Uart::new_with_mio_for_uart_1(
|
||||||
periphs.uart_1,
|
periphs.uart_1,
|
||||||
uart::Config::new_with_clk_config(uart_clk_config),
|
uart::Config::new_with_clk_config(uart_clk_config),
|
||||||
(gpio_pins.mio.mio48, gpio_pins.mio.mio49),
|
(gpio_pins.mio.mio48, gpio_pins.mio.mio49),
|
||||||
|
|||||||
@@ -8,6 +8,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
# [unreleased]
|
# [unreleased]
|
||||||
|
|
||||||
|
## Changed
|
||||||
|
|
||||||
|
- Increased UART type safety by providing dedicated MIO constructors for UART 0 and UART 1
|
||||||
|
respectively.
|
||||||
|
|
||||||
# [v0.1.1] 2025-10-10
|
# [v0.1.1] 2025-10-10
|
||||||
|
|
||||||
Documentation fixes.
|
Documentation fixes.
|
||||||
|
|||||||
@@ -10,9 +10,8 @@ use arbitrary_int::prelude::*;
|
|||||||
|
|
||||||
use aarch32_cpu::interrupt;
|
use aarch32_cpu::interrupt;
|
||||||
use zynq7000::gic::{
|
use zynq7000::gic::{
|
||||||
DistributorControlRegister, GicCpuInterfaceRegisters, GicDistributorRegisters,
|
CpuInterfaceRegisters, DistributorControlRegister, DistributorRegisters, InterfaceControl,
|
||||||
InterfaceControl, InterruptSignalRegister, MmioGicCpuInterfaceRegisters,
|
InterruptSignalRegister, MmioCpuInterfaceRegisters, MmioDistributorRegisters, PriorityRegister,
|
||||||
MmioGicDistributorRegisters, PriorityRegister,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const SPURIOUS_INTERRUPT_ID: u32 = 1023;
|
const SPURIOUS_INTERRUPT_ID: u32 = 1023;
|
||||||
@@ -193,7 +192,7 @@ pub struct InvalidSgiInterruptId(pub usize);
|
|||||||
/// The flow of using this controller is as follows:
|
/// The flow of using this controller is as follows:
|
||||||
///
|
///
|
||||||
/// 1. Create the controller using [Self::new_with_init]. You can use the [zynq7000::Peripherals]
|
/// 1. Create the controller using [Self::new_with_init]. You can use the [zynq7000::Peripherals]
|
||||||
/// structure or the [zynq7000::gic::GicCpuInterface::new_mmio] and [zynq7000::gic::GicDistributor::new_mmio]
|
/// structure or the [zynq7000::gic::CpuInterfaceRegisters::new_mmio] and [zynq7000::gic::DistributorRegisters::new_mmio]
|
||||||
/// functions to retrieve the MMIO instances. The constructor configures all PL interrupts
|
/// functions to retrieve the MMIO instances. The constructor configures all PL interrupts
|
||||||
/// sensivities to high-level sensitivity and configures all sensitivities which are expected
|
/// sensivities to high-level sensitivity and configures all sensitivities which are expected
|
||||||
/// to have a certain value. It also sets the priority mask to 0xff by calling
|
/// to have a certain value. It also sets the priority mask to 0xff by calling
|
||||||
@@ -225,8 +224,8 @@ pub struct InvalidSgiInterruptId(pub usize);
|
|||||||
/// For the handling of the interrupts, you can use the [GicInterruptHelper] which assumes a
|
/// For the handling of the interrupts, you can use the [GicInterruptHelper] which assumes a
|
||||||
/// properly configured GIC.
|
/// properly configured GIC.
|
||||||
pub struct GicConfigurator {
|
pub struct GicConfigurator {
|
||||||
pub gicc: MmioGicCpuInterfaceRegisters<'static>,
|
pub gicc: MmioCpuInterfaceRegisters<'static>,
|
||||||
pub gicd: MmioGicDistributorRegisters<'static>,
|
pub gicd: MmioDistributorRegisters<'static>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GicConfigurator {
|
impl GicConfigurator {
|
||||||
@@ -234,8 +233,8 @@ impl GicConfigurator {
|
|||||||
/// strongly recommended initialization routines for the GIC.
|
/// strongly recommended initialization routines for the GIC.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_with_init(
|
pub fn new_with_init(
|
||||||
gicc: MmioGicCpuInterfaceRegisters<'static>,
|
gicc: MmioCpuInterfaceRegisters<'static>,
|
||||||
gicd: MmioGicDistributorRegisters<'static>,
|
gicd: MmioDistributorRegisters<'static>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut gic = GicConfigurator { gicc, gicd };
|
let mut gic = GicConfigurator { gicc, gicd };
|
||||||
gic.initialize();
|
gic.initialize();
|
||||||
@@ -252,8 +251,8 @@ impl GicConfigurator {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn steal() -> Self {
|
pub unsafe fn steal() -> Self {
|
||||||
GicConfigurator {
|
GicConfigurator {
|
||||||
gicc: unsafe { GicCpuInterfaceRegisters::new_mmio_fixed() },
|
gicc: unsafe { CpuInterfaceRegisters::new_mmio_fixed() },
|
||||||
gicd: unsafe { GicDistributorRegisters::new_mmio_fixed() },
|
gicd: unsafe { DistributorRegisters::new_mmio_fixed() },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -489,12 +488,12 @@ impl GicConfigurator {
|
|||||||
|
|
||||||
/// Helper structure which should only be used inside the interrupt handler once the GIC has
|
/// Helper structure which should only be used inside the interrupt handler once the GIC has
|
||||||
/// been configured with the [GicConfigurator].
|
/// been configured with the [GicConfigurator].
|
||||||
pub struct GicInterruptHelper(MmioGicCpuInterfaceRegisters<'static>);
|
pub struct GicInterruptHelper(MmioCpuInterfaceRegisters<'static>);
|
||||||
|
|
||||||
impl GicInterruptHelper {
|
impl GicInterruptHelper {
|
||||||
/// Create the interrupt helper with the fixed GICC MMIO instance.
|
/// Create the interrupt helper with the fixed GICC MMIO instance.
|
||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
GicInterruptHelper(unsafe { GicCpuInterfaceRegisters::new_mmio_fixed() })
|
GicInterruptHelper(unsafe { CpuInterfaceRegisters::new_mmio_fixed() })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Acknowledges an interrupt by reading the IAR register and returning the interrupt context
|
/// Acknowledges an interrupt by reading the IAR register and returning the interrupt context
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
//!
|
//!
|
||||||
//! - [GTC ticks example](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/examples/simple/src/bin/gtc-ticks.rs)
|
//! - [GTC ticks example](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/examples/simple/src/bin/gtc-ticks.rs)
|
||||||
//! - [Embassy Timer Driver](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/zynq7000-embassy/src/lib.rs)
|
//! - [Embassy Timer Driver](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/zynq7000-embassy/src/lib.rs)
|
||||||
|
#![deny(missing_docs)]
|
||||||
use zynq7000::gtc::MmioRegisters;
|
use zynq7000::gtc::MmioRegisters;
|
||||||
|
|
||||||
use crate::{clocks::ArmClocks, time::Hertz};
|
use crate::{clocks::ArmClocks, time::Hertz};
|
||||||
@@ -20,6 +21,7 @@ pub struct GlobalTimerCounter {
|
|||||||
|
|
||||||
unsafe impl Send for GlobalTimerCounter {}
|
unsafe impl Send for GlobalTimerCounter {}
|
||||||
|
|
||||||
|
/// Convert a frequency to GTC ticks given a clock frequency.
|
||||||
pub const fn frequency_to_ticks(clock: Hertz, frequency: Hertz) -> u32 {
|
pub const fn frequency_to_ticks(clock: Hertz, frequency: Hertz) -> u32 {
|
||||||
clock.raw().div_ceil(frequency.raw())
|
clock.raw().div_ceil(frequency.raw())
|
||||||
}
|
}
|
||||||
@@ -38,7 +40,7 @@ impl GlobalTimerCounter {
|
|||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// This function allows creating an arbitrary amount of memory-mapped peripheral drivers.
|
/// This function allows creating an arbitrary amount of memory-mapped peripheral drivers.
|
||||||
/// See the [zynq7000::gtc::GlobalTimerCounter::new_mmio] docs for more safety information.
|
/// See the [zynq7000::gtc::Registers::new_mmio] docs for more safety information.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const unsafe fn steal_fixed(cpu_3x2x_clk: Option<Hertz>) -> Self {
|
pub const unsafe fn steal_fixed(cpu_3x2x_clk: Option<Hertz>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -47,6 +49,7 @@ impl GlobalTimerCounter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the CPU 3x2x clock frequency.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_cpu_3x2x_clock(&mut self, clock: Hertz) {
|
pub fn set_cpu_3x2x_clock(&mut self, clock: Hertz) {
|
||||||
self.cpu_3x2x_clock = Some(clock);
|
self.cpu_3x2x_clock = Some(clock);
|
||||||
@@ -85,6 +88,7 @@ impl GlobalTimerCounter {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Convert a frequency to GTC ticks.
|
||||||
pub fn frequency_to_ticks(&self, frequency: Hertz) -> u32 {
|
pub fn frequency_to_ticks(&self, frequency: Hertz) -> u32 {
|
||||||
if self.cpu_3x2x_clock.is_none() {
|
if self.cpu_3x2x_clock.is_none() {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -99,12 +103,14 @@ impl GlobalTimerCounter {
|
|||||||
self.regs.write_auto_increment(value);
|
self.regs.write_auto_increment(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set auto-increment value for a given frequency.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_auto_increment_value_for_frequency(&mut self, frequency: Hertz) {
|
pub fn set_auto_increment_value_for_frequency(&mut self, frequency: Hertz) {
|
||||||
self.regs
|
self.regs
|
||||||
.write_auto_increment(self.frequency_to_ticks(frequency));
|
.write_auto_increment(self.frequency_to_ticks(frequency));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enable the GTC.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn enable(&mut self) {
|
pub fn enable(&mut self) {
|
||||||
self.regs.modify_ctrl(|mut ctrl| {
|
self.regs.modify_ctrl(|mut ctrl| {
|
||||||
@@ -113,6 +119,7 @@ impl GlobalTimerCounter {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enable auto-increment.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn enable_auto_increment(&mut self) {
|
pub fn enable_auto_increment(&mut self) {
|
||||||
self.regs.modify_ctrl(|mut ctrl| {
|
self.regs.modify_ctrl(|mut ctrl| {
|
||||||
@@ -121,6 +128,7 @@ impl GlobalTimerCounter {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set a pre-scaler.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_prescaler(&mut self, prescaler: u8) {
|
pub fn set_prescaler(&mut self, prescaler: u8) {
|
||||||
self.regs.modify_ctrl(|mut ctrl| {
|
self.regs.modify_ctrl(|mut ctrl| {
|
||||||
@@ -129,6 +137,7 @@ impl GlobalTimerCounter {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Disable the GTC.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn disable(&mut self) {
|
pub fn disable(&mut self) {
|
||||||
self.regs.modify_ctrl(|mut ctrl| {
|
self.regs.modify_ctrl(|mut ctrl| {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//! # L2 cache module
|
//! # L2 cache module
|
||||||
|
#![deny(missing_docs)]
|
||||||
use core::sync::atomic::compiler_fence;
|
use core::sync::atomic::compiler_fence;
|
||||||
|
|
||||||
use arbitrary_int::{u2, u3};
|
use arbitrary_int::{u2, u3};
|
||||||
@@ -44,7 +45,7 @@ pub const DEFAULT_DATA_RAM_LATENCY: LatencyConfig = LatencyConfig::builder()
|
|||||||
.with_setup_latency(u3::new(0b001))
|
.with_setup_latency(u3::new(0b001))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// SLCR L2C ram configuration.
|
/// SLCR L2C RAM configuration magic value.
|
||||||
pub const SLCR_L2C_CONFIG_MAGIC_VALUE: u32 = 0x00020202;
|
pub const SLCR_L2C_CONFIG_MAGIC_VALUE: u32 = 0x00020202;
|
||||||
|
|
||||||
/// Similar to [init], but uses Xilinx/AMD defaults for the latency configurations.
|
/// Similar to [init], but uses Xilinx/AMD defaults for the latency configurations.
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
//! ## Examples
|
//! ## Examples
|
||||||
//!
|
//!
|
||||||
//! - Private timer as delay provider in [blinky](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/examples/simple/src/bin/blinky.rs)
|
//! - Private timer as delay provider in [blinky](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/examples/simple/src/bin/blinky.rs)
|
||||||
|
#![deny(missing_docs)]
|
||||||
use core::{marker::PhantomData, sync::atomic::AtomicBool};
|
use core::{marker::PhantomData, sync::atomic::AtomicBool};
|
||||||
|
|
||||||
use zynq7000::priv_tim::InterruptStatus;
|
use zynq7000::priv_tim::InterruptStatus;
|
||||||
@@ -62,11 +63,13 @@ impl CpuPrivateTimer {
|
|||||||
self.regs.write_reload(value);
|
self.regs.write_reload(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Write the current counter value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn write_counter(&mut self, value: u32) {
|
pub fn write_counter(&mut self, value: u32) {
|
||||||
self.regs.write_counter(value);
|
self.regs.write_counter(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read the current counter value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn counter(&self) -> u32 {
|
pub fn counter(&self) -> u32 {
|
||||||
self.regs.read_counter()
|
self.regs.read_counter()
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
//! # System Level Control Register (SLCR) module
|
//! # System Level Control Register (SLCR) module
|
||||||
|
#![deny(missing_docs)]
|
||||||
use zynq7000::slcr::MmioRegisters;
|
use zynq7000::slcr::MmioRegisters;
|
||||||
|
|
||||||
|
/// Lock key for the SLCR registers.
|
||||||
pub const LOCK_KEY: u32 = 0x767B;
|
pub const LOCK_KEY: u32 = 0x767B;
|
||||||
|
/// Unlock key for the SLCR registers.
|
||||||
pub const UNLOCK_KEY: u32 = 0xDF0D;
|
pub const UNLOCK_KEY: u32 = 0xDF0D;
|
||||||
|
|
||||||
|
/// SLCR helper structure.
|
||||||
pub struct Slcr(zynq7000::slcr::MmioRegisters<'static>);
|
pub struct Slcr(zynq7000::slcr::MmioRegisters<'static>);
|
||||||
|
|
||||||
impl Slcr {
|
impl Slcr {
|
||||||
@@ -12,7 +16,7 @@ impl Slcr {
|
|||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// This method unsafely steals the SLCR MMIO block and then calls a user provided function
|
/// This method unsafely steals the SLCR MMIO block and then calls a user provided function
|
||||||
/// with the [SLCR MMIO][MmioSlcr] block as an input argument. It is the user's responsibility
|
/// with the [SLCR MMIO][MmioRegisters] block as an input argument. It is the user's responsibility
|
||||||
/// that the SLCR is not used concurrently in a way which leads to data races.
|
/// that the SLCR is not used concurrently in a way which leads to data races.
|
||||||
pub unsafe fn with<F: FnOnce(&mut MmioRegisters<'static>)>(f: F) {
|
pub unsafe fn with<F: FnOnce(&mut MmioRegisters<'static>)>(f: F) {
|
||||||
let mut slcr = unsafe { zynq7000::slcr::Registers::new_mmio_fixed() };
|
let mut slcr = unsafe { zynq7000::slcr::Registers::new_mmio_fixed() };
|
||||||
@@ -47,7 +51,7 @@ impl Slcr {
|
|||||||
/// Modify the SLCR register.
|
/// Modify the SLCR register.
|
||||||
///
|
///
|
||||||
/// This method unlocks the SLCR registers and then calls a user provided function
|
/// This method unlocks the SLCR registers and then calls a user provided function
|
||||||
/// with the [SLCR MMIO][MmioSlcr] block as an input argument. This allows the user
|
/// with the [SLCR MMIO][MmioRegisters] block as an input argument. This allows the user
|
||||||
/// to safely modify the SLCR registers. The SLCR will be locked afte the operation.
|
/// to safely modify the SLCR registers. The SLCR will be locked afte the operation.
|
||||||
pub fn modify<F: FnMut(&mut MmioRegisters)>(&mut self, mut f: F) {
|
pub fn modify<F: FnMut(&mut MmioRegisters)>(&mut self, mut f: F) {
|
||||||
self.0.write_unlock(UNLOCK_KEY);
|
self.0.write_unlock(UNLOCK_KEY);
|
||||||
|
|||||||
@@ -1,17 +1,21 @@
|
|||||||
//! # Time units
|
//! # Time units
|
||||||
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
// Frequency based
|
// Frequency based
|
||||||
|
|
||||||
/// Hertz
|
/// Hertz
|
||||||
pub type Hertz = fugit::HertzU32;
|
pub type Hertz = fugit::HertzU32;
|
||||||
|
/// Type alias for Hertz.
|
||||||
pub type Hz = Hertz;
|
pub type Hz = Hertz;
|
||||||
|
|
||||||
/// KiloHertz
|
/// KiloHertz
|
||||||
pub type KiloHertz = fugit::KilohertzU32;
|
pub type KiloHertz = fugit::KilohertzU32;
|
||||||
|
/// Type alias for Kilo Hertz.
|
||||||
pub type KHz = KiloHertz;
|
pub type KHz = KiloHertz;
|
||||||
|
|
||||||
/// MegaHertz
|
/// MegaHertz
|
||||||
pub type MegaHertz = fugit::MegahertzU32;
|
pub type MegaHertz = fugit::MegahertzU32;
|
||||||
|
/// Type alias for Mega Hertz.
|
||||||
pub type MHz = MegaHertz;
|
pub type MHz = MegaHertz;
|
||||||
|
|
||||||
// Period based
|
// Period based
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
//! ## Examples
|
//! ## Examples
|
||||||
//!
|
//!
|
||||||
//! - [PWM](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/examples/embassy/src/bin/pwm.rs)
|
//! - [PWM](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/examples/embassy/src/bin/pwm.rs)
|
||||||
|
#![deny(missing_docs)]
|
||||||
use core::convert::Infallible;
|
use core::convert::Infallible;
|
||||||
|
|
||||||
use arbitrary_int::{prelude::*, u3, u4};
|
use arbitrary_int::{prelude::*, u3, u4};
|
||||||
@@ -25,19 +25,28 @@ use crate::{
|
|||||||
/// Each TTC consists of three independent timers/counters.
|
/// Each TTC consists of three independent timers/counters.
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub enum TtcId {
|
pub enum TtcId {
|
||||||
|
/// TTC 0.
|
||||||
Ttc0 = 0,
|
Ttc0 = 0,
|
||||||
|
/// TTC 1.
|
||||||
Ttc1 = 1,
|
Ttc1 = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Each TTC has 3 channels.
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub enum ChannelId {
|
pub enum ChannelId {
|
||||||
|
/// Channel 0.
|
||||||
Ch0 = 0,
|
Ch0 = 0,
|
||||||
|
/// Channel 1.
|
||||||
Ch1 = 1,
|
Ch1 = 1,
|
||||||
|
/// Channel 2.
|
||||||
Ch2 = 2,
|
Ch2 = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Common trait for TTC register blocks.
|
||||||
pub trait PsTtc {
|
pub trait PsTtc {
|
||||||
|
/// Register block.
|
||||||
fn reg_block(&self) -> MmioRegisters<'static>;
|
fn reg_block(&self) -> MmioRegisters<'static>;
|
||||||
|
/// ID.
|
||||||
fn id(&self) -> Option<TtcId>;
|
fn id(&self) -> Option<TtcId>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,13 +68,18 @@ impl PsTtc for MmioRegisters<'static> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// TTC pin configuration
|
||||||
pub const TTC_MUX_CONF: MuxConfig = MuxConfig::new_with_l3(u3::new(0b110));
|
pub const TTC_MUX_CONF: MuxConfig = MuxConfig::new_with_l3(u3::new(0b110));
|
||||||
|
|
||||||
|
/// Input clock pin trait.
|
||||||
pub trait ClockInPin: MioPin {
|
pub trait ClockInPin: MioPin {
|
||||||
|
/// TTC ID.
|
||||||
const ID: TtcId;
|
const ID: TtcId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Output wave pin trait.
|
||||||
pub trait WaveOutPin: MioPin {
|
pub trait WaveOutPin: MioPin {
|
||||||
|
/// TTC ID.
|
||||||
const ID: TtcId;
|
const ID: TtcId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,9 +135,13 @@ impl WaveOutPin for Pin<Mio40> {
|
|||||||
const ID: TtcId = TtcId::Ttc1;
|
const ID: TtcId = TtcId::Ttc1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Triple-timer counter (TTC) peripheral.
|
||||||
pub struct Ttc {
|
pub struct Ttc {
|
||||||
|
/// TTC channel 0.
|
||||||
pub ch0: TtcChannel,
|
pub ch0: TtcChannel,
|
||||||
|
/// TTC channel 1.
|
||||||
pub ch1: TtcChannel,
|
pub ch1: TtcChannel,
|
||||||
|
/// TTC channel 2.
|
||||||
pub ch2: TtcChannel,
|
pub ch2: TtcChannel,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,16 +169,20 @@ impl Ttc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Single TTC channel.
|
||||||
pub struct TtcChannel {
|
pub struct TtcChannel {
|
||||||
regs: MmioRegisters<'static>,
|
regs: MmioRegisters<'static>,
|
||||||
id: ChannelId,
|
id: ChannelId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TtcChannel {
|
impl TtcChannel {
|
||||||
|
/// Raw access to the TTC MMIO registers.
|
||||||
|
#[inline]
|
||||||
pub fn regs_mut(&mut self) -> &mut MmioRegisters<'static> {
|
pub fn regs_mut(&mut self) -> &mut MmioRegisters<'static> {
|
||||||
&mut self.regs
|
&mut self.regs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read the current counter value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn read_counter(&self) -> u16 {
|
pub fn read_counter(&self) -> u16 {
|
||||||
self.regs
|
self.regs
|
||||||
@@ -169,27 +191,36 @@ impl TtcChannel {
|
|||||||
.count()
|
.count()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Channel ID.
|
||||||
|
#[inline]
|
||||||
pub fn id(&self) -> ChannelId {
|
pub fn id(&self) -> ChannelId {
|
||||||
self.id
|
self.id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Invalid TTC pin configuration error.
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
#[error("invalid TTC pin configuration")]
|
#[error("invalid TTC pin configuration")]
|
||||||
pub struct InvalidTtcPinConfigError(pub MuxConfig);
|
pub struct InvalidTtcPinConfigError(pub MuxConfig);
|
||||||
|
|
||||||
|
/// Frequency is zero error.
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
#[error("frequency is zero")]
|
#[error("frequency is zero")]
|
||||||
pub struct FrequencyIsZeroError;
|
pub struct FrequencyIsZeroError;
|
||||||
|
|
||||||
|
/// TTC construction error.
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum TtcConstructionError {
|
pub enum TtcConstructionError {
|
||||||
|
/// Invalid TTC pin configuration.
|
||||||
#[error("invalid TTC pin configuration")]
|
#[error("invalid TTC pin configuration")]
|
||||||
InvalidTtcPinConfig(#[from] InvalidTtcPinConfigError),
|
InvalidTtcPinConfig(#[from] InvalidTtcPinConfigError),
|
||||||
|
/// Frequency is zero.
|
||||||
#[error("frequency is zero")]
|
#[error("frequency is zero")]
|
||||||
FrequencyIsZero(#[from] FrequencyIsZeroError),
|
FrequencyIsZero(#[from] FrequencyIsZeroError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Calculate prescaler register value and interval ticks for a given reference clock and
|
||||||
|
/// frequency.
|
||||||
pub fn calc_prescaler_reg_and_interval_ticks(mut ref_clk: Hertz, freq: Hertz) -> (Option<u4>, u16) {
|
pub fn calc_prescaler_reg_and_interval_ticks(mut ref_clk: Hertz, freq: Hertz) -> (Option<u4>, u16) {
|
||||||
// TODO: Can this be optimized?
|
// TODO: Can this be optimized?
|
||||||
let mut prescaler: Option<u32> = None;
|
let mut prescaler: Option<u32> = None;
|
||||||
@@ -210,6 +241,7 @@ pub fn calc_prescaler_reg_and_interval_ticks(mut ref_clk: Hertz, freq: Hertz) ->
|
|||||||
(prescaler.map(|v| u4::new(v as u8)), tick_val as u16)
|
(prescaler.map(|v| u4::new(v as u8)), tick_val as u16)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// PWM driver using a TTC channel.
|
||||||
pub struct Pwm {
|
pub struct Pwm {
|
||||||
channel: TtcChannel,
|
channel: TtcChannel,
|
||||||
ref_clk: Hertz,
|
ref_clk: Hertz,
|
||||||
@@ -266,11 +298,13 @@ impl Pwm {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Mutable access to the underlying TTC channel.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn ttc_channel_mut(&mut self) -> &mut TtcChannel {
|
pub fn ttc_channel_mut(&mut self) -> &mut TtcChannel {
|
||||||
&mut self.channel
|
&mut self.channel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Maximum duty cycle value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn max_duty_cycle(&self) -> u16 {
|
pub fn max_duty_cycle(&self) -> u16 {
|
||||||
self.channel
|
self.channel
|
||||||
@@ -280,6 +314,7 @@ impl Pwm {
|
|||||||
.value()
|
.value()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set duty cycle value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_duty_cycle(&mut self, duty: u16) {
|
pub fn set_duty_cycle(&mut self, duty: u16) {
|
||||||
let id = self.channel.id() as usize;
|
let id = self.channel.id() as usize;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
//! - [Logger through UART](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/examples/simple/src/bin/logger.rs)
|
//! - [Logger through UART](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/examples/simple/src/bin/logger.rs)
|
||||||
//! - [Zedboard Blocking UART](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/examples/zedboard/src/bin/uart-blocking.rs)
|
//! - [Zedboard Blocking UART](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/examples/zedboard/src/bin/uart-blocking.rs)
|
||||||
//! - [Zedboard Non-Blocking UART](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/examples/zedboard/src/bin/uart-non-blocking.rs)
|
//! - [Zedboard Non-Blocking UART](https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/src/branch/main/zynq/examples/zedboard/src/bin/uart-non-blocking.rs)
|
||||||
|
#![deny(missing_docs)]
|
||||||
use core::convert::Infallible;
|
use core::convert::Infallible;
|
||||||
|
|
||||||
use arbitrary_int::u3;
|
use arbitrary_int::u3;
|
||||||
@@ -49,18 +50,27 @@ pub use tx_async::*;
|
|||||||
pub mod rx;
|
pub mod rx;
|
||||||
pub use rx::*;
|
pub use rx::*;
|
||||||
|
|
||||||
|
/// FIFO depth of the UART peripheral.
|
||||||
pub const FIFO_DEPTH: usize = 64;
|
pub const FIFO_DEPTH: usize = 64;
|
||||||
|
/// Default RX trigger level.
|
||||||
pub const DEFAULT_RX_TRIGGER_LEVEL: u8 = 32;
|
pub const DEFAULT_RX_TRIGGER_LEVEL: u8 = 32;
|
||||||
|
/// UART pin configuration.
|
||||||
pub const UART_MUX_CONF: MuxConfig = MuxConfig::new_with_l3(u3::new(0b111));
|
pub const UART_MUX_CONF: MuxConfig = MuxConfig::new_with_l3(u3::new(0b111));
|
||||||
|
|
||||||
|
/// UART ID.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum UartId {
|
pub enum UartId {
|
||||||
|
/// UART 0.
|
||||||
Uart0 = 0,
|
Uart0 = 0,
|
||||||
|
/// UART 1.
|
||||||
Uart1 = 1,
|
Uart1 = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Common trait for PS UART peripherals.
|
||||||
pub trait PsUart {
|
pub trait PsUart {
|
||||||
|
/// UART register block.
|
||||||
fn reg_block(&self) -> MmioRegisters<'static>;
|
fn reg_block(&self) -> MmioRegisters<'static>;
|
||||||
|
/// UART ID.
|
||||||
fn uart_id(&self) -> Option<UartId>;
|
fn uart_id(&self) -> Option<UartId>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,38 +105,57 @@ impl UartId {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait RxPin: MioPin {
|
/// Receiver (RX) pin for UART 0.
|
||||||
const UART_IDX: UartId;
|
pub trait RxPin0: MioPin {
|
||||||
|
/// UART index.
|
||||||
|
const UART_IDX: UartId = UartId::Uart0;
|
||||||
}
|
}
|
||||||
pub trait TxPin: MioPin {
|
/// Transmitter (TX) pin for UART 0.
|
||||||
const UART_IDX: UartId;
|
pub trait TxPin0: MioPin {
|
||||||
|
/// UART index.
|
||||||
|
const UART_IDX: UartId = UartId::Uart0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait UartPins {}
|
/// Receiver (RX) pin for UART 1.
|
||||||
|
pub trait RxPin1: MioPin {
|
||||||
|
/// UART index.
|
||||||
|
const UART_IDX: UartId = UartId::Uart0;
|
||||||
|
}
|
||||||
|
/// Transmitter (TX) pin for UART 1.
|
||||||
|
pub trait TxPin1: MioPin {
|
||||||
|
/// UART index.
|
||||||
|
const UART_IDX: UartId = UartId::Uart0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// UART pin pair trait for UART 0.
|
||||||
|
pub trait UartPins0 {}
|
||||||
|
|
||||||
|
/// UART pin pair trait for UART 1.
|
||||||
|
pub trait UartPins1 {}
|
||||||
|
|
||||||
|
/// Divisor zero error.
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
#[error("divisor is zero")]
|
#[error("divisor is zero")]
|
||||||
pub struct DivisorZero;
|
pub struct DivisorZero;
|
||||||
|
|
||||||
macro_rules! pin_pairs {
|
macro_rules! pin_pairs {
|
||||||
($UartPeriph:path, ($( [$(#[$meta:meta], )? $TxMio:ident, $RxMio:ident] ),+ $(,)? )) => {
|
($index:literal, $UartPeriph:path, ($( [$(#[$meta:meta], )? $TxMio:ident, $RxMio:ident] ),+ $(,)? )) => {
|
||||||
$(
|
$(
|
||||||
$( #[$meta] )?
|
paste::paste! {
|
||||||
impl TxPin for Pin<$TxMio> {
|
$( #[$meta] )?
|
||||||
const UART_IDX: UartId = $UartPeriph;
|
impl [<TxPin $index>] for Pin<$TxMio> {}
|
||||||
}
|
|
||||||
|
|
||||||
$( #[$meta] )?
|
$( #[$meta] )?
|
||||||
impl RxPin for Pin<$RxMio> {
|
impl [<RxPin $index>] for Pin<$RxMio> {}
|
||||||
const UART_IDX: UartId = $UartPeriph;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UartPins for (Pin<$TxMio>, Pin<$RxMio>) {}
|
impl [<UartPins $index>] for (Pin<$TxMio>, Pin<$RxMio>) {}
|
||||||
|
}
|
||||||
)+
|
)+
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pin_pairs!(
|
pin_pairs!(
|
||||||
|
0,
|
||||||
UartId::Uart0,
|
UartId::Uart0,
|
||||||
(
|
(
|
||||||
[Mio11, Mio10],
|
[Mio11, Mio10],
|
||||||
@@ -144,7 +173,7 @@ pin_pairs!(
|
|||||||
);
|
);
|
||||||
|
|
||||||
pin_pairs!(
|
pin_pairs!(
|
||||||
UartId::Uart1,
|
1, UartId::Uart1,
|
||||||
(
|
(
|
||||||
[Mio8, Mio9],
|
[Mio8, Mio9],
|
||||||
[Mio12, Mio13],
|
[Mio12, Mio13],
|
||||||
@@ -166,38 +195,53 @@ pub const MAX_BAUD_RATE: u32 = 6240000;
|
|||||||
/// Based on values provided by the vendor library.
|
/// Based on values provided by the vendor library.
|
||||||
pub const MIN_BAUD_RATE: u32 = 110;
|
pub const MIN_BAUD_RATE: u32 = 110;
|
||||||
|
|
||||||
|
/// Maximum acceptable baud rate error rate (0.5 %).
|
||||||
pub const MAX_BAUDERROR_RATE: f32 = 0.005;
|
pub const MAX_BAUDERROR_RATE: f32 = 0.005;
|
||||||
|
|
||||||
|
/// Parity configuration.
|
||||||
#[derive(Debug, Default, Clone, Copy)]
|
#[derive(Debug, Default, Clone, Copy)]
|
||||||
pub enum Parity {
|
pub enum Parity {
|
||||||
|
/// Even parity.
|
||||||
Even,
|
Even,
|
||||||
|
/// Odd parity.
|
||||||
Odd,
|
Odd,
|
||||||
|
/// No parity (default).
|
||||||
#[default]
|
#[default]
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Stopbit configuration.
|
||||||
#[derive(Debug, Default, Clone, Copy)]
|
#[derive(Debug, Default, Clone, Copy)]
|
||||||
pub enum Stopbits {
|
pub enum Stopbits {
|
||||||
|
/// One stop bit (default).
|
||||||
#[default]
|
#[default]
|
||||||
One,
|
One,
|
||||||
|
/// 1.5 stopbits.
|
||||||
OnePointFive,
|
OnePointFive,
|
||||||
|
/// 2 stopbits.
|
||||||
Two,
|
Two,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Character length configuration.
|
||||||
#[derive(Debug, Default, Clone, Copy)]
|
#[derive(Debug, Default, Clone, Copy)]
|
||||||
pub enum CharLen {
|
pub enum CharLen {
|
||||||
|
/// 6 bits.
|
||||||
SixBits,
|
SixBits,
|
||||||
|
/// 7 bits.
|
||||||
SevenBits,
|
SevenBits,
|
||||||
|
/// 8 bits (default).
|
||||||
#[default]
|
#[default]
|
||||||
EightBits,
|
EightBits,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Clock configuration for baud rate generation.
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct ClockConfig {
|
pub struct ClockConfig {
|
||||||
cd: u16,
|
cd: u16,
|
||||||
bdiv: u8,
|
bdiv: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Calculate all viable clock configurations.
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
pub fn calculate_viable_configs(
|
pub fn calculate_viable_configs(
|
||||||
mut uart_clk: Hertz,
|
mut uart_clk: Hertz,
|
||||||
@@ -265,6 +309,7 @@ pub fn calculate_raw_baud_cfg_smallest_error(
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ClockConfig {
|
impl ClockConfig {
|
||||||
|
/// Constructor.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn new(cd: u16, bdiv: u8) -> Result<Self, DivisorZero> {
|
pub const fn new(cd: u16, bdiv: u8) -> Result<Self, DivisorZero> {
|
||||||
if cd == 0 {
|
if cd == 0 {
|
||||||
@@ -285,6 +330,7 @@ impl ClockConfig {
|
|||||||
Self::new_autocalc_generic(io_clks, ClockSelect::UartRefClk, target_baud)
|
Self::new_autocalc_generic(io_clks, ClockSelect::UartRefClk, target_baud)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// New generic autocalculating constructor.
|
||||||
pub fn new_autocalc_generic(
|
pub fn new_autocalc_generic(
|
||||||
io_clks: &IoClocks,
|
io_clks: &IoClocks,
|
||||||
clk_sel: ClockSelect,
|
clk_sel: ClockSelect,
|
||||||
@@ -293,6 +339,7 @@ impl ClockConfig {
|
|||||||
Self::new_autocalc_with_raw_clk(io_clks.uart_clk(), clk_sel, target_baud)
|
Self::new_autocalc_with_raw_clk(io_clks.uart_clk(), clk_sel, target_baud)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// New generic autocalculating constructor using a raw UART Input clock.
|
||||||
pub fn new_autocalc_with_raw_clk(
|
pub fn new_autocalc_with_raw_clk(
|
||||||
uart_clk: Hertz,
|
uart_clk: Hertz,
|
||||||
clk_sel: ClockSelect,
|
clk_sel: ClockSelect,
|
||||||
@@ -301,21 +348,25 @@ impl ClockConfig {
|
|||||||
calculate_raw_baud_cfg_smallest_error(uart_clk, clk_sel, target_baud)
|
calculate_raw_baud_cfg_smallest_error(uart_clk, clk_sel, target_baud)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// CD value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn cd(&self) -> u16 {
|
pub const fn cd(&self) -> u16 {
|
||||||
self.cd
|
self.cd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Baud divisor value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn bdiv(&self) -> u8 {
|
pub const fn bdiv(&self) -> u8 {
|
||||||
self.bdiv
|
self.bdiv
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Rounded baudrate.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn rounded_baud(&self, sel_clk: Hertz) -> u32 {
|
pub fn rounded_baud(&self, sel_clk: Hertz) -> u32 {
|
||||||
round(self.actual_baud(sel_clk)) as u32
|
round(self.actual_baud(sel_clk)) as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Actual baudrate.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn actual_baud(&self, sel_clk: Hertz) -> f64 {
|
pub fn actual_baud(&self, sel_clk: Hertz) -> f64 {
|
||||||
sel_clk.raw() as f64 / (self.cd as f64 * (self.bdiv + 1) as f64)
|
sel_clk.raw() as f64 / (self.cd as f64 * (self.bdiv + 1) as f64)
|
||||||
@@ -329,6 +380,7 @@ impl Default for ClockConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// UART configuration.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
clk_config: ClockConfig,
|
clk_config: ClockConfig,
|
||||||
@@ -340,6 +392,7 @@ pub struct Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
|
/// Create a new configuration from a given clock configuartion.
|
||||||
pub fn new_with_clk_config(clk_config: ClockConfig) -> Self {
|
pub fn new_with_clk_config(clk_config: ClockConfig) -> Self {
|
||||||
Self::new(
|
Self::new(
|
||||||
clk_config,
|
clk_config,
|
||||||
@@ -351,6 +404,7 @@ impl Config {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constructor.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn new(
|
pub const fn new(
|
||||||
clk_config: ClockConfig,
|
clk_config: ClockConfig,
|
||||||
@@ -370,54 +424,63 @@ impl Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Raw clock configuration.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn raw_clk_config(&self) -> ClockConfig {
|
pub const fn raw_clk_config(&self) -> ClockConfig {
|
||||||
self.clk_config
|
self.clk_config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Character mode.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn chmode(&self) -> ChMode {
|
pub const fn chmode(&self) -> ChMode {
|
||||||
self.chmode
|
self.chmode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parity configuration.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn parity(&self) -> Parity {
|
pub const fn parity(&self) -> Parity {
|
||||||
self.parity
|
self.parity
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Stopbits configuration.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn stopbits(&self) -> Stopbits {
|
pub const fn stopbits(&self) -> Stopbits {
|
||||||
self.stopbits
|
self.stopbits
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Character length configuration.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn chrl(&self) -> CharLen {
|
pub const fn charlen(&self) -> CharLen {
|
||||||
self.chrl
|
self.chrl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Clock select configuration.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn clksel(&self) -> ClockSelect {
|
pub const fn clksel(&self) -> ClockSelect {
|
||||||
self.clk_sel
|
self.clk_sel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Impl Debug
|
/// UART peripheral driver.
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Uart {
|
pub struct Uart {
|
||||||
rx: Rx,
|
rx: Rx,
|
||||||
tx: Tx,
|
tx: Tx,
|
||||||
cfg: Config,
|
cfg: Config,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Invalid PS UART error.
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
#[error("invalid UART ID")]
|
#[error("invalid UART ID")]
|
||||||
pub struct InvalidPsUart;
|
pub struct InvalidPsUart;
|
||||||
|
|
||||||
|
/// UART construction error.
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum UartConstructionError {
|
pub enum UartConstructionError {
|
||||||
|
/// Invalid PS UART error.
|
||||||
#[error("invalid UART ID")]
|
#[error("invalid UART ID")]
|
||||||
InvalidPsUart(#[from] InvalidPsUart),
|
InvalidPsUart(#[from] InvalidPsUart),
|
||||||
#[error("missmatch between pins index and passed index")]
|
/// Invalid pin configuration.
|
||||||
IdxMissmatch,
|
|
||||||
#[error("invalid pin mux conf for UART")]
|
#[error("invalid pin mux conf for UART")]
|
||||||
InvalidMuxConf(MuxConfig),
|
InvalidMuxConf(MuxConfig),
|
||||||
}
|
}
|
||||||
@@ -439,21 +502,46 @@ impl Uart {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is the constructor to use the PS UART with MIO pins.
|
/// This is the constructor to use the PS UART with MIO pins for UART 0.
|
||||||
pub fn new_with_mio<TxPinI: TxPin, RxPinI: RxPin>(
|
pub fn new_with_mio_for_uart_0<TxPinI: TxPin0, RxPinI: RxPin0>(
|
||||||
uart: impl PsUart,
|
uart: impl PsUart,
|
||||||
cfg: Config,
|
cfg: Config,
|
||||||
pins: (TxPinI, RxPinI),
|
pins: (TxPinI, RxPinI),
|
||||||
) -> Result<Self, UartConstructionError>
|
) -> Result<Self, UartConstructionError>
|
||||||
where
|
where
|
||||||
(TxPinI, RxPinI): UartPins,
|
(TxPinI, RxPinI): UartPins0,
|
||||||
{
|
{
|
||||||
let id = uart.uart_id();
|
let id = uart.uart_id();
|
||||||
if id.is_none() {
|
if id.is_none() {
|
||||||
return Err(InvalidPsUart.into());
|
return Err(InvalidPsUart.into());
|
||||||
}
|
}
|
||||||
if id.unwrap() != TxPinI::UART_IDX || id.unwrap() != RxPinI::UART_IDX {
|
if id.unwrap() != UartId::Uart0 {
|
||||||
return Err(UartConstructionError::IdxMissmatch);
|
return Err(InvalidPsUart.into());
|
||||||
|
}
|
||||||
|
IoPeriphPin::new(pins.0, UART_MUX_CONF, None);
|
||||||
|
IoPeriphPin::new(pins.1, UART_MUX_CONF, None);
|
||||||
|
Ok(Self::new_generic_unchecked(
|
||||||
|
uart.reg_block(),
|
||||||
|
id.unwrap(),
|
||||||
|
cfg,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This is the constructor to use the PS UART with MIO pins for UART 1.
|
||||||
|
pub fn new_with_mio_for_uart_1<TxPinI: TxPin1, RxPinI: RxPin1>(
|
||||||
|
uart: impl PsUart,
|
||||||
|
cfg: Config,
|
||||||
|
pins: (TxPinI, RxPinI),
|
||||||
|
) -> Result<Self, UartConstructionError>
|
||||||
|
where
|
||||||
|
(TxPinI, RxPinI): UartPins1,
|
||||||
|
{
|
||||||
|
let id = uart.uart_id();
|
||||||
|
if id.is_none() {
|
||||||
|
return Err(InvalidPsUart.into());
|
||||||
|
}
|
||||||
|
if id.unwrap() != UartId::Uart1 {
|
||||||
|
return Err(InvalidPsUart.into());
|
||||||
}
|
}
|
||||||
IoPeriphPin::new(pins.0, UART_MUX_CONF, None);
|
IoPeriphPin::new(pins.0, UART_MUX_CONF, None);
|
||||||
IoPeriphPin::new(pins.1, UART_MUX_CONF, None);
|
IoPeriphPin::new(pins.1, UART_MUX_CONF, None);
|
||||||
@@ -549,6 +637,7 @@ impl Uart {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set character mode.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_mode(&mut self, mode: ChMode) {
|
pub fn set_mode(&mut self, mode: ChMode) {
|
||||||
self.regs().modify_mr(|mut mr| {
|
self.regs().modify_mr(|mut mr| {
|
||||||
@@ -557,16 +646,19 @@ impl Uart {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Raw access to the UART registers.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn regs(&mut self) -> &mut MmioRegisters<'static> {
|
pub const fn regs(&mut self) -> &mut MmioRegisters<'static> {
|
||||||
&mut self.rx.regs
|
&mut self.rx.regs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Configuration.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn cfg(&self) -> &Config {
|
pub const fn cfg(&self) -> &Config {
|
||||||
&self.cfg
|
&self.cfg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Split into TX and RX halves.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn split(self) -> (Tx, Rx) {
|
pub const fn split(self) -> (Tx, Rx) {
|
||||||
(self.tx, self.rx)
|
(self.tx, self.rx)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//! # Receiver (RX) support module
|
||||||
use core::convert::Infallible;
|
use core::convert::Infallible;
|
||||||
|
|
||||||
use arbitrary_int::prelude::*;
|
use arbitrary_int::prelude::*;
|
||||||
@@ -5,12 +6,23 @@ use zynq7000::uart::{InterruptControl, InterruptStatus, MmioRegisters};
|
|||||||
|
|
||||||
use super::FIFO_DEPTH;
|
use super::FIFO_DEPTH;
|
||||||
|
|
||||||
|
/// Receiver (RX) driver.
|
||||||
pub struct Rx {
|
pub struct Rx {
|
||||||
pub(crate) regs: MmioRegisters<'static>,
|
pub(crate) regs: MmioRegisters<'static>,
|
||||||
}
|
}
|
||||||
// TODO: Remove once this is impelemnted for MmioUart
|
|
||||||
|
impl core::fmt::Debug for Rx {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
f.debug_struct("Rx").finish_non_exhaustive()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// This is not a CPU specific register block.
|
||||||
unsafe impl Send for Rx {}
|
unsafe impl Send for Rx {}
|
||||||
|
|
||||||
|
/// RX errors structure.
|
||||||
#[derive(Debug, Default, Clone, Copy)]
|
#[derive(Debug, Default, Clone, Copy)]
|
||||||
pub struct RxErrors {
|
pub struct RxErrors {
|
||||||
framing: bool,
|
framing: bool,
|
||||||
@@ -19,20 +31,26 @@ pub struct RxErrors {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RxErrors {
|
impl RxErrors {
|
||||||
|
/// Framing error occurred.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn framing(&self) -> bool {
|
pub const fn framing(&self) -> bool {
|
||||||
self.framing
|
self.framing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Overrun error occurred.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn overrun(&self) -> bool {
|
pub const fn overrun(&self) -> bool {
|
||||||
self.overrun
|
self.overrun
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parity error occurred.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn parity(&self) -> bool {
|
pub const fn parity(&self) -> bool {
|
||||||
self.parity
|
self.parity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// RX interrupt result structure.
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct RxInterruptResult {
|
pub struct RxInterruptResult {
|
||||||
read_bytes: usize,
|
read_bytes: usize,
|
||||||
@@ -40,16 +58,19 @@ pub struct RxInterruptResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RxInterruptResult {
|
impl RxInterruptResult {
|
||||||
|
/// Bytes read during the interrupt.
|
||||||
pub fn read_bytes(&self) -> usize {
|
pub fn read_bytes(&self) -> usize {
|
||||||
self.read_bytes
|
self.read_bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Errors occurred during reception.
|
||||||
pub fn errors(&self) -> Option<RxErrors> {
|
pub fn errors(&self) -> Option<RxErrors> {
|
||||||
self.errors
|
self.errors
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rx {
|
impl Rx {
|
||||||
|
/// Read one byte from the FIFO in a non-blocking manner.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn read_fifo(&mut self) -> nb::Result<u8, Infallible> {
|
pub fn read_fifo(&mut self) -> nb::Result<u8, Infallible> {
|
||||||
if self.regs.read_sr().rx_empty() {
|
if self.regs.read_sr().rx_empty() {
|
||||||
@@ -58,6 +79,7 @@ impl Rx {
|
|||||||
Ok(self.regs.read_fifo().fifo())
|
Ok(self.regs.read_fifo().fifo())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read one byte from the FIFO without checking if data is available.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn read_fifo_unchecked(&mut self) -> u8 {
|
pub fn read_fifo_unchecked(&mut self) -> u8 {
|
||||||
self.regs.read_fifo().fifo()
|
self.regs.read_fifo().fifo()
|
||||||
@@ -74,6 +96,7 @@ impl Rx {
|
|||||||
self.regs.write_rx_tout(rto as u32);
|
self.regs.write_rx_tout(rto as u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Perform a soft-reset of the RX side of the UART.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn soft_reset(&mut self) {
|
pub fn soft_reset(&mut self) {
|
||||||
self.regs.modify_cr(|mut cr| {
|
self.regs.modify_cr(|mut cr| {
|
||||||
@@ -121,6 +144,9 @@ impl Rx {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This function should be called from the UART interrupt handler.
|
||||||
|
///
|
||||||
|
/// It reads all available data from the RX FIFO into the provided buffer.
|
||||||
pub fn on_interrupt(
|
pub fn on_interrupt(
|
||||||
&mut self,
|
&mut self,
|
||||||
buf: &mut [u8; FIFO_DEPTH],
|
buf: &mut [u8; FIFO_DEPTH],
|
||||||
@@ -180,7 +206,7 @@ impl Rx {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
// This clears all RX related interrupts.
|
/// This clears all RX related interrupts.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn clear_interrupts(&mut self) {
|
pub fn clear_interrupts(&mut self) {
|
||||||
self.regs.write_isr(
|
self.regs.write_isr(
|
||||||
|
|||||||
@@ -1,14 +1,22 @@
|
|||||||
|
//! # Transmitter (TX) support module
|
||||||
use core::convert::Infallible;
|
use core::convert::Infallible;
|
||||||
|
|
||||||
use zynq7000::uart::{Fifo, InterruptControl, InterruptStatus, MmioRegisters};
|
use zynq7000::uart::{Fifo, InterruptControl, InterruptStatus, MmioRegisters};
|
||||||
|
|
||||||
use super::UartId;
|
use super::UartId;
|
||||||
|
|
||||||
|
/// Transmitter (TX) driver.
|
||||||
pub struct Tx {
|
pub struct Tx {
|
||||||
pub(crate) regs: MmioRegisters<'static>,
|
pub(crate) regs: MmioRegisters<'static>,
|
||||||
pub(crate) idx: UartId,
|
pub(crate) idx: UartId,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl core::fmt::Debug for Tx {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
f.debug_struct("Tx").field("idx", &self.idx).finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Tx {
|
impl Tx {
|
||||||
/// Steal the TX side of the UART for a given UART index.
|
/// Steal the TX side of the UART for a given UART index.
|
||||||
///
|
///
|
||||||
@@ -23,16 +31,21 @@ impl Tx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// UART index.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn uart_idx(&self) -> UartId {
|
pub const fn uart_idx(&self) -> UartId {
|
||||||
self.idx
|
self.idx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Direct access to the UART MMIO registers.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn regs(&mut self) -> &mut MmioRegisters<'static> {
|
pub const fn regs(&mut self) -> &mut MmioRegisters<'static> {
|
||||||
&mut self.regs
|
&mut self.regs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Write a byte to the TX FIFO.
|
||||||
|
///
|
||||||
|
/// [nb] API which returns [nb::Error::WouldBlock] if the FIFO is full.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn write_fifo(&mut self, word: u8) -> nb::Result<(), Infallible> {
|
pub fn write_fifo(&mut self, word: u8) -> nb::Result<(), Infallible> {
|
||||||
if self.regs.read_sr().tx_full() {
|
if self.regs.read_sr().tx_full() {
|
||||||
@@ -65,6 +78,7 @@ impl Tx {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Performs a soft-reset of the TX side of the UART.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn soft_reset(&mut self) {
|
pub fn soft_reset(&mut self) {
|
||||||
self.regs.modify_cr(|mut val| {
|
self.regs.modify_cr(|mut val| {
|
||||||
@@ -78,10 +92,12 @@ impl Tx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Flushes the TX FIFO by blocking until it is empty.
|
||||||
pub fn flush(&mut self) {
|
pub fn flush(&mut self) {
|
||||||
while !self.regs.read_sr().tx_empty() {}
|
while !self.regs.read_sr().tx_empty() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Write a byte to the TX FIFO without checking if there is space available.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn write_fifo_unchecked(&mut self, word: u8) {
|
pub fn write_fifo_unchecked(&mut self, word: u8) {
|
||||||
self.regs.write_fifo(Fifo::new_with_raw_value(word as u32));
|
self.regs.write_fifo(Fifo::new_with_raw_value(word as u32));
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//! Asynchronous UART transmitter (TX) implementation.
|
||||||
use core::{cell::RefCell, convert::Infallible, sync::atomic::AtomicBool};
|
use core::{cell::RefCell, convert::Infallible, sync::atomic::AtomicBool};
|
||||||
|
|
||||||
use critical_section::Mutex;
|
use critical_section::Mutex;
|
||||||
@@ -6,14 +7,6 @@ use raw_slice::RawBufSlice;
|
|||||||
|
|
||||||
use crate::uart::{FIFO_DEPTH, Tx, UartId};
|
use crate::uart::{FIFO_DEPTH, Tx, UartId};
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum TransferType {
|
|
||||||
Read,
|
|
||||||
Write,
|
|
||||||
Transfer,
|
|
||||||
TransferInPlace,
|
|
||||||
}
|
|
||||||
|
|
||||||
static UART_TX_WAKERS: [AtomicWaker; 2] = [const { AtomicWaker::new() }; 2];
|
static UART_TX_WAKERS: [AtomicWaker; 2] = [const { AtomicWaker::new() }; 2];
|
||||||
static TX_CONTEXTS: [Mutex<RefCell<TxContext>>; 2] =
|
static TX_CONTEXTS: [Mutex<RefCell<TxContext>>; 2] =
|
||||||
[const { Mutex::new(RefCell::new(TxContext::new())) }; 2];
|
[const { Mutex::new(RefCell::new(TxContext::new())) }; 2];
|
||||||
@@ -84,7 +77,7 @@ pub fn on_interrupt_tx(peripheral: UartId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct TxContext {
|
struct TxContext {
|
||||||
progress: usize,
|
progress: usize,
|
||||||
tx_overrun: bool,
|
tx_overrun: bool,
|
||||||
slice: RawBufSlice,
|
slice: RawBufSlice,
|
||||||
@@ -101,6 +94,7 @@ impl TxContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Transmission future for UART TX.
|
||||||
pub struct TxFuture {
|
pub struct TxFuture {
|
||||||
id: UartId,
|
id: UartId,
|
||||||
}
|
}
|
||||||
@@ -164,11 +158,13 @@ impl Drop for TxFuture {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Asynchronous UART transmitter (TX) driver.
|
||||||
pub struct TxAsync {
|
pub struct TxAsync {
|
||||||
tx: Tx,
|
tx: Tx,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TxAsync {
|
impl TxAsync {
|
||||||
|
/// Constructor.
|
||||||
pub fn new(tx: Tx) -> Self {
|
pub fn new(tx: Tx) -> Self {
|
||||||
Self { tx }
|
Self { tx }
|
||||||
}
|
}
|
||||||
@@ -185,6 +181,7 @@ impl TxAsync {
|
|||||||
fut.await
|
fut.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Release the underlying blocking TX driver.
|
||||||
pub fn release(self) -> Tx {
|
pub fn release(self) -> Tx {
|
||||||
self.tx
|
self.tx
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,10 +40,13 @@ impl TypeRegister {
|
|||||||
|
|
||||||
pub type Typer = TypeRegister;
|
pub type Typer = TypeRegister;
|
||||||
|
|
||||||
|
#[deprecated(note = "Use DistributorRegisters instead")]
|
||||||
|
pub type GicDistributorTyper = DistributorRegisters;
|
||||||
|
|
||||||
/// GIC Distributor registers.
|
/// GIC Distributor registers.
|
||||||
#[derive(derive_mmio::Mmio)]
|
#[derive(derive_mmio::Mmio)]
|
||||||
#[repr(C, align(8))]
|
#[repr(C, align(8))]
|
||||||
pub struct GicDistributorRegisters {
|
pub struct DistributorRegisters {
|
||||||
/// Distributor Control Register
|
/// Distributor Control Register
|
||||||
pub dcr: DistributorControlRegister,
|
pub dcr: DistributorControlRegister,
|
||||||
/// Interrupt Controller Type Register
|
/// Interrupt Controller Type Register
|
||||||
@@ -109,9 +112,9 @@ pub struct GicDistributorRegisters {
|
|||||||
pub cidr: [u32; 4],
|
pub cidr: [u32; 4],
|
||||||
}
|
}
|
||||||
|
|
||||||
const_assert_eq!(core::mem::size_of::<GicDistributorRegisters>(), 0x1000);
|
const_assert_eq!(core::mem::size_of::<DistributorRegisters>(), 0x1000);
|
||||||
|
|
||||||
impl GicDistributorRegisters {
|
impl DistributorRegisters {
|
||||||
/// Create a new Global Interrupt Controller Distributor MMIO instance at the fixed address of
|
/// Create a new Global Interrupt Controller Distributor MMIO instance at the fixed address of
|
||||||
/// the processing system.
|
/// the processing system.
|
||||||
///
|
///
|
||||||
@@ -121,7 +124,7 @@ impl GicDistributorRegisters {
|
|||||||
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||||
/// interfere with each other.
|
/// interfere with each other.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const unsafe fn new_mmio_fixed() -> MmioGicDistributorRegisters<'static> {
|
pub const unsafe fn new_mmio_fixed() -> MmioDistributorRegisters<'static> {
|
||||||
unsafe { Self::new_mmio_at(GICD_BASE_ADDR) }
|
unsafe { Self::new_mmio_at(GICD_BASE_ADDR) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -157,10 +160,13 @@ pub struct InterruptSignalRegister {
|
|||||||
ack_int_id: u10,
|
ack_int_id: u10,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deprecated(note = "Use DistributorRegisters instead")]
|
||||||
|
pub type GicCpuInterfaceIar = CpuInterfaceRegisters;
|
||||||
|
|
||||||
/// GIC CPU interface registers.
|
/// GIC CPU interface registers.
|
||||||
#[derive(derive_mmio::Mmio)]
|
#[derive(derive_mmio::Mmio)]
|
||||||
#[repr(C, align(8))]
|
#[repr(C, align(8))]
|
||||||
pub struct GicCpuInterfaceRegisters {
|
pub struct CpuInterfaceRegisters {
|
||||||
/// CPU Interface Control Register (ICR).
|
/// CPU Interface Control Register (ICR).
|
||||||
pub icr: InterfaceControl,
|
pub icr: InterfaceControl,
|
||||||
/// Interrupt Priority Mask Register.
|
/// Interrupt Priority Mask Register.
|
||||||
@@ -183,9 +189,9 @@ pub struct GicCpuInterfaceRegisters {
|
|||||||
pub iidr: u32,
|
pub iidr: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
const_assert_eq!(core::mem::size_of::<GicCpuInterfaceRegisters>(), 0x100);
|
const_assert_eq!(core::mem::size_of::<CpuInterfaceRegisters>(), 0x100);
|
||||||
|
|
||||||
impl GicCpuInterfaceRegisters {
|
impl CpuInterfaceRegisters {
|
||||||
/// Create a new Global Interrupt Controller CPU MMIO instance at the fixed address of the
|
/// Create a new Global Interrupt Controller CPU MMIO instance at the fixed address of the
|
||||||
/// processing system.
|
/// processing system.
|
||||||
///
|
///
|
||||||
@@ -195,7 +201,7 @@ impl GicCpuInterfaceRegisters {
|
|||||||
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||||
/// interfere with each other.
|
/// interfere with each other.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const unsafe fn new_mmio_fixed() -> MmioGicCpuInterfaceRegisters<'static> {
|
pub const unsafe fn new_mmio_fixed() -> MmioCpuInterfaceRegisters<'static> {
|
||||||
unsafe { Self::new_mmio_at(GICC_BASE_ADDR) }
|
unsafe { Self::new_mmio_at(GICC_BASE_ADDR) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ static PERIPHERALS_TAKEN: AtomicBool = AtomicBool::new(false);
|
|||||||
/// The [`svd2rust` documentation](https://docs.rs/svd2rust/latest/svd2rust/#peripheral-api)
|
/// The [`svd2rust` documentation](https://docs.rs/svd2rust/latest/svd2rust/#peripheral-api)
|
||||||
/// provides some more information about this.
|
/// provides some more information about this.
|
||||||
pub struct Peripherals {
|
pub struct Peripherals {
|
||||||
pub gicc: gic::MmioGicCpuInterfaceRegisters<'static>,
|
pub gicc: gic::MmioCpuInterfaceRegisters<'static>,
|
||||||
pub gicd: gic::MmioGicDistributorRegisters<'static>,
|
pub gicd: gic::MmioDistributorRegisters<'static>,
|
||||||
pub l2c: l2_cache::MmioRegisters<'static>,
|
pub l2c: l2_cache::MmioRegisters<'static>,
|
||||||
pub ddrc: ddrc::MmioRegisters<'static>,
|
pub ddrc: ddrc::MmioRegisters<'static>,
|
||||||
pub uart_0: uart::MmioRegisters<'static>,
|
pub uart_0: uart::MmioRegisters<'static>,
|
||||||
@@ -83,8 +83,8 @@ impl Peripherals {
|
|||||||
pub unsafe fn steal() -> Self {
|
pub unsafe fn steal() -> Self {
|
||||||
unsafe {
|
unsafe {
|
||||||
Self {
|
Self {
|
||||||
gicc: gic::GicCpuInterfaceRegisters::new_mmio_fixed(),
|
gicc: gic::CpuInterfaceRegisters::new_mmio_fixed(),
|
||||||
gicd: gic::GicDistributorRegisters::new_mmio_fixed(),
|
gicd: gic::DistributorRegisters::new_mmio_fixed(),
|
||||||
l2c: l2_cache::Registers::new_mmio_fixed(),
|
l2c: l2_cache::Registers::new_mmio_fixed(),
|
||||||
ddrc: ddrc::Registers::new_mmio_fixed(),
|
ddrc: ddrc::Registers::new_mmio_fixed(),
|
||||||
uart_0: uart::Registers::new_mmio_fixed_0(),
|
uart_0: uart::Registers::new_mmio_fixed_0(),
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ use static_assertions::const_assert_eq;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
gic::{
|
gic::{
|
||||||
GicCpuInterfaceRegisters, GicDistributorRegisters, MmioGicCpuInterfaceRegisters,
|
CpuInterfaceRegisters, DistributorRegisters, MmioCpuInterfaceRegisters,
|
||||||
MmioGicDistributorRegisters,
|
MmioDistributorRegisters,
|
||||||
},
|
},
|
||||||
gtc::{MmioRegisters, Registers},
|
gtc::{MmioRegisters, Registers},
|
||||||
};
|
};
|
||||||
@@ -57,7 +57,7 @@ pub struct MpCore {
|
|||||||
_reserved_0: [u32; 0x2A],
|
_reserved_0: [u32; 0x2A],
|
||||||
|
|
||||||
#[mmio(Inner)]
|
#[mmio(Inner)]
|
||||||
gicc: GicCpuInterfaceRegisters,
|
gicc: CpuInterfaceRegisters,
|
||||||
|
|
||||||
#[mmio(Inner)]
|
#[mmio(Inner)]
|
||||||
gt: Registers,
|
gt: Registers,
|
||||||
@@ -81,7 +81,7 @@ pub struct MpCore {
|
|||||||
_reserved_3: [u32; 0x272],
|
_reserved_3: [u32; 0x272],
|
||||||
|
|
||||||
#[mmio(Inner)]
|
#[mmio(Inner)]
|
||||||
gicd: GicDistributorRegisters,
|
gicd: DistributorRegisters,
|
||||||
}
|
}
|
||||||
|
|
||||||
const_assert_eq!(core::mem::size_of::<MpCore>(), 0x2000);
|
const_assert_eq!(core::mem::size_of::<MpCore>(), 0x2000);
|
||||||
|
|||||||
Reference in New Issue
Block a user