prepare next zynq7000 version #84

Merged
muellerr merged 2 commits from bump-zynq7000 into main 2026-05-15 19:30:09 +02:00
11 changed files with 119 additions and 82 deletions
+1 -1
View File
@@ -10,7 +10,7 @@ keywords = ["no-std", "zedboard", "bare-metal", "amd", "zynq7000"]
categories = ["embedded", "no-std", "hardware-support"]
[dependencies]
zynq7000 = { path = "../zynq7000", version = "0.3" }
zynq7000 = { path = "../zynq7000", version = "0.4" }
zynq7000-hal = { path = "../zynq7000-hal", version = "0.1" }
bitbybit = "2"
log = "0.4"
+1 -1
View File
@@ -12,7 +12,7 @@ categories = ["embedded", "no-std", "hardware-support"]
[dependencies]
aarch32-cpu = { version = "0.3" }
zynq7000 = { path = "../zynq7000", version = "0.3" }
zynq7000 = { path = "../zynq7000", version = "0.4" }
zynq7000-mmu = { path = "../zynq7000-mmu", version = "0.2" }
static_assertions = "1.1"
bitbybit = "2"
+11 -15
View File
@@ -576,31 +576,27 @@ impl Uart {
}
enable_amba_peripheral_clock(periph_sel);
reset(uart_id);
reg_block.modify_control(|mut v| {
v.set_tx_dis(true);
v.set_rx_dis(true);
v
});
reg_block.modify_control(|v| v.with_tx_disable(true).with_rx_disable(true));
// Disable all interrupts.
reg_block.write_interrupt_disable(InterruptControl::new_with_raw_value(0xFFFF_FFFF));
let mode = Mode::builder()
.with_chmode(cfg.chmode)
.with_nbstop(match cfg.stopbits {
.with_stopbits(match cfg.stopbits {
Stopbits::One => zynq7000::uart::Stopbits::One,
Stopbits::OnePointFive => zynq7000::uart::Stopbits::OnePointFive,
Stopbits::Two => zynq7000::uart::Stopbits::Two,
})
.with_par(match cfg.parity {
.with_parity(match cfg.parity {
Parity::Even => zynq7000::uart::Parity::Even,
Parity::Odd => zynq7000::uart::Parity::Odd,
Parity::None => zynq7000::uart::Parity::NoParity,
})
.with_chrl(match cfg.chrl {
.with_charlen(match cfg.chrl {
CharLen::SixBits => zynq7000::uart::CharLen::SixBits,
CharLen::SevenBits => zynq7000::uart::CharLen::SevenBits,
CharLen::EightBits => zynq7000::uart::CharLen::EightBits,
})
.with_clksel(cfg.clk_sel)
.with_clock_select(cfg.clk_sel)
.build();
reg_block.write_mode(mode);
reg_block.write_baudgen(
@@ -615,8 +611,8 @@ impl Uart {
);
// Soft reset for both TX and RX.
reg_block.modify_control(|mut v| {
v.set_tx_rst(true);
v.set_rx_rst(true);
v.set_tx_reset(true);
v.set_rx_reset(true);
v
});
@@ -627,10 +623,10 @@ impl Uart {
// Enable TX and RX.
reg_block.modify_control(|mut v| {
v.set_tx_dis(false);
v.set_rx_dis(false);
v.set_tx_en(true);
v.set_rx_en(true);
v.set_tx_disable(false);
v.set_rx_disable(false);
v.set_tx_enable(true);
v.set_rx_enable(true);
v
});
+12 -12
View File
@@ -73,7 +73,7 @@ impl Rx {
/// Read one byte from the FIFO in a non-blocking manner.
#[inline]
pub fn read_fifo(&mut self) -> nb::Result<u8, Infallible> {
if self.regs.read_sr().rx_empty() {
if self.regs.read_status().rx_empty() {
return Err(nb::Error::WouldBlock);
}
Ok(self.regs.read_fifo().fifo())
@@ -93,17 +93,17 @@ impl Rx {
/// bit clock, so this value times 4 is the number of UART clock ticks until a timeout occurs.
#[inline]
pub fn set_rx_timeout_value(&mut self, rto: u8) {
self.regs.write_rx_tout(rto as u32);
self.regs.write_rx_timeout(rto as u32);
}
/// Perform a soft-reset of the RX side of the UART.
#[inline]
pub fn soft_reset(&mut self) {
self.regs.modify_control(|mut cr| {
cr.set_rx_rst(true);
cr.set_rx_reset(true);
cr
});
while self.regs.read_control().rx_rst() {}
while self.regs.read_control().rx_reset() {}
}
/// Helper function to start the interrupt driven reception of data.
@@ -141,7 +141,7 @@ impl Rx {
InterruptControl::builder()
.with_tx_over(false)
.with_tx_near_full(false)
.with_tx_trig(false)
.with_tx_trigger(false)
.with_rx_dms(false)
.with_rx_timeout(true)
.with_rx_parity(true)
@@ -151,7 +151,7 @@ impl Rx {
.with_tx_empty(false)
.with_rx_full(true)
.with_rx_empty(false)
.with_rx_trg(true)
.with_rx_trigger(true)
.build(),
);
}
@@ -167,7 +167,7 @@ impl Rx {
let mut result = RxInterruptResult::default();
let imr = self.regs.read_enabled_interrupts();
if !imr.rx_full()
&& !imr.rx_trg()
&& !imr.rx_trigger()
&& !imr.rx_parity()
&& !imr.rx_framing()
&& !imr.rx_over()
@@ -176,9 +176,9 @@ impl Rx {
return result;
}
let isr = self.regs.read_interrupt_status();
if self.regs.read_interrupt_status().rx_trg() {
if self.regs.read_interrupt_status().rx_trigger() {
// It is guaranteed that we can read the FIFO level amount of data
let fifo_trigger = self.regs.read_rx_fifo_trigger().trig().as_usize();
let fifo_trigger = self.regs.read_rx_fifo_trigger().trigger().as_usize();
(0..fifo_trigger).for_each(|i| {
buf[i] = self.read_fifo_unchecked();
});
@@ -204,7 +204,7 @@ impl Rx {
// Handle timeout event.
if isr.rx_timeout() && reset_rx_timeout {
self.regs.modify_control(|mut cr| {
cr.set_rstto(true);
cr.set_restart_timeout(true);
cr
});
}
@@ -229,7 +229,7 @@ impl Rx {
.with_tx_empty(false)
.with_rx_full(true)
.with_rx_empty(true)
.with_rx_trg(true)
.with_rx_trigger(true)
.build(),
);
}
@@ -262,7 +262,7 @@ impl embedded_io::Read for Rx {
}
let mut read = 0;
loop {
if !self.regs.read_sr().rx_empty() {
if !self.regs.read_status().rx_empty() {
break;
}
}
+15 -15
View File
@@ -48,7 +48,7 @@ impl Tx {
/// [nb] API which returns [nb::Error::WouldBlock] if the FIFO is full.
#[inline]
pub fn write_fifo(&mut self, word: u8) -> nb::Result<(), Infallible> {
if self.regs.read_sr().tx_full() {
if self.regs.read_status().tx_full() {
return Err(nb::Error::WouldBlock);
}
self.write_fifo_unchecked(word);
@@ -62,8 +62,8 @@ impl Tx {
self.soft_reset();
}
self.regs.modify_control(|mut val| {
val.set_tx_en(true);
val.set_tx_dis(false);
val.set_tx_enable(true);
val.set_tx_disable(false);
val
});
}
@@ -72,8 +72,8 @@ impl Tx {
#[inline]
pub fn disable(&mut self) {
self.regs.modify_control(|mut val| {
val.set_tx_en(false);
val.set_tx_dis(true);
val.set_tx_enable(false);
val.set_tx_disable(true);
val
});
}
@@ -82,11 +82,11 @@ impl Tx {
#[inline]
pub fn soft_reset(&mut self) {
self.regs.modify_control(|mut val| {
val.set_tx_rst(true);
val.set_tx_reset(true);
val
});
loop {
if !self.regs.read_control().tx_rst() {
if !self.regs.read_control().tx_reset() {
break;
}
}
@@ -94,7 +94,7 @@ impl Tx {
/// Flushes the TX FIFO by blocking until it is empty.
pub fn flush(&mut self) {
while !self.regs.read_sr().tx_empty() {}
while !self.regs.read_status().tx_empty() {}
}
/// Write a byte to the TX FIFO without checking if there is space available.
@@ -110,7 +110,7 @@ impl Tx {
InterruptControl::builder()
.with_tx_over(true)
.with_tx_near_full(false)
.with_tx_trig(tx_trig)
.with_tx_trigger(tx_trig)
.with_rx_dms(false)
.with_rx_timeout(false)
.with_rx_parity(false)
@@ -120,7 +120,7 @@ impl Tx {
.with_tx_empty(true)
.with_rx_full(false)
.with_rx_empty(false)
.with_rx_trg(false)
.with_rx_trigger(false)
.build(),
);
}
@@ -132,7 +132,7 @@ impl Tx {
InterruptControl::builder()
.with_tx_over(true)
.with_tx_near_full(false)
.with_tx_trig(true)
.with_tx_trigger(true)
.with_rx_dms(false)
.with_rx_timeout(false)
.with_rx_parity(false)
@@ -142,7 +142,7 @@ impl Tx {
.with_tx_empty(true)
.with_rx_full(false)
.with_rx_empty(false)
.with_rx_trg(false)
.with_rx_trigger(false)
.build(),
);
}
@@ -164,7 +164,7 @@ impl Tx {
.with_tx_empty(true)
.with_rx_full(false)
.with_rx_empty(false)
.with_rx_trg(false)
.with_rx_trigger(false)
.build(),
);
}
@@ -181,7 +181,7 @@ impl embedded_hal_nb::serial::Write for Tx {
}
fn flush(&mut self) -> nb::Result<(), Self::Error> {
if self.regs.read_sr().tx_empty() {
if self.regs.read_status().tx_empty() {
return Ok(());
}
Err(nb::Error::WouldBlock)
@@ -199,7 +199,7 @@ impl embedded_io::Write for Tx {
}
let mut written = 0;
loop {
if !self.regs.read_sr().tx_full() {
if !self.regs.read_status().tx_full() {
break;
}
}
+3 -3
View File
@@ -72,7 +72,7 @@ pub unsafe fn on_interrupt_tx(peripheral: UartId) {
// Pump the FIFO.
while context.progress < slice_len {
if tx_with_irq.regs().read_sr().tx_full() {
if tx_with_irq.regs().read_status().tx_full() {
break;
}
// Safety: TX structure is owned by the future which does not write into the the data
@@ -84,7 +84,7 @@ pub unsafe fn on_interrupt_tx(peripheral: UartId) {
if remaining > FIFO_DEPTH {
tx_with_irq.regs.write_tx_fifo_trigger(
FifoTrigger::builder()
.with_trig(u6::new((FIFO_DEPTH / 2) as u8))
.with_trigger(u6::new((FIFO_DEPTH / 2) as u8))
.build(),
);
}
@@ -148,7 +148,7 @@ impl<'uart> TxFuture<'uart> {
if data.len() > FIFO_DEPTH {
tx_with_irq.regs.write_tx_fifo_trigger(
FifoTrigger::builder()
.with_trig(u6::new((FIFO_DEPTH / 2) as u8))
.with_trigger(u6::new((FIFO_DEPTH / 2) as u8))
.build(),
);
}
+7 -1
View File
@@ -8,6 +8,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
# [unreleased]
# [v0.4.0] 2026-05-15
- Better names for `uart` registers and register fields. Replaced various abbreviations.
- Update `gic` module: Add some better type for SGIR field.
# [v0.3.0] 2026-05-08
- Better names for various registers. Replaced abbreviations like SR, MR, CR, IER, IMR etc.
@@ -30,7 +35,8 @@ Documentation fix
Initial release
[unreleased]: https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/compare/zynq7000-v0.3.0...HEAD
[unreleased]: https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/compare/zynq7000-v0.4.0...HEAD
[v0.4.0]: https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/compare/zynq7000-v0.3.0...zynq7000-v0.4.0
[v0.3.0]: https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/compare/zynq7000-v0.2.0...zynq7000-v0.3.0
[v0.2.0]: https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/compare/zynq7000-v0.1.0...zynq7000-v0.2.0
[v0.1.1]: https://egit.irs.uni-stuttgart.de/rust/zynq7000-rs/compare/zynq7000-v0.1.0...zynq7000-v0.1.1
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "zynq7000"
version = "0.3.0"
version = "0.4.0"
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
edition = "2024"
description = "Peripheral Access Crate (PAC) for the Zynq7000 family of SoCs"
+43 -8
View File
@@ -1,6 +1,6 @@
//! # GIC (Generic Interrupt Controller) register module.
pub use crate::mpcore::{GICC_BASE_ADDR, GICD_BASE_ADDR};
use arbitrary_int::{u2, u3, u5, u10};
use arbitrary_int::{u2, u3, u4, u5, u10, u11};
use static_assertions::const_assert_eq;
/// Distributor Control Register
@@ -55,9 +55,6 @@ pub struct InterruptProcessorTargetRegister {
targets: [u2; 4],
}
#[deprecated(note = "Use DistributorRegisters instead")]
pub type GicDistributorTyper = DistributorRegisters;
/// GIC Distributor registers.
#[derive(derive_mmio::Mmio)]
#[repr(C, align(8))]
@@ -92,7 +89,7 @@ pub struct DistributorRegisters {
/// Interrupt Priority Registers
pub ipr: [u32; 0x18],
_reserved_11: [u32; 0xE8],
/// Interrupt Processor Targes Registers
/// Interrupt Processor Targets Registers
pub iptr_sgi: [InterruptProcessorTargetRegister; 0x4],
/// These are read-only because they always target their private CPU.
#[mmio(PureRead)]
@@ -102,6 +99,7 @@ pub struct DistributorRegisters {
_reserved_12: [u32; 0xE8],
/// Interrupt Configuration Registers
/// Interupt sensitivity register for software generated interrupts (SGI)
#[mmio(PureRead)]
pub icfr_0_sgi: u32,
/// Interupt sensitivity register for private peripheral interrupts (PPI)
pub icfr_1_ppi: u32,
@@ -115,7 +113,7 @@ pub struct DistributorRegisters {
pub spi_status_1: u32,
_reserved_14: [u32; 0x7D],
/// Software Generated Interrupt Register.
pub sgir: u32,
pub sgir: SoftwareGeneratedInterruptRegister,
_reserved_15: [u32; 0x33],
pub pidr_4: u32,
pub pidr_5: u32,
@@ -182,8 +180,45 @@ pub struct InterruptSignalRegister {
ack_int_id: u10,
}
#[deprecated(note = "Use DistributorRegisters instead")]
pub type GicCpuInterfaceIar = CpuInterfaceRegisters;
#[bitbybit::bitenum(u1, exhaustive = true)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, PartialEq, Eq)]
pub enum SecurityCondition {
IfConfiguredAsSecure = 0,
IfConfiguredAsNonSecure = 1,
}
#[bitbybit::bitenum(u2, exhaustive = true)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, PartialEq, Eq)]
pub enum TargetListFilter {
SendToCpusInTargetList = 0b00,
SendToAllOtherCpus = 0b01,
SendToSelf = 0b10,
Reserved = 0b11,
}
#[bitbybit::bitfield(
u32,
default = 0x0,
debug,
defmt_bitfields(feature = "defmt"),
forbid_overlaps
)]
pub struct SoftwareGeneratedInterruptRegister {
#[bits(24..=25, rw)]
target_list_filter: TargetListFilter,
#[bits(16..=23, rw)]
cpu_target_list: u8,
/// SATT field.
#[bit(15, rw)]
security_condition: SecurityCondition,
/// Should be zero.
#[bits(4..=14, rw)]
sbz: u11,
#[bits(0..=3, rw)]
interrupt_id: u4,
}
/// GIC CPU interface registers.
#[derive(derive_mmio::Mmio)]
+24 -24
View File
@@ -77,25 +77,25 @@ pub struct Control {
startbrk: bool,
/// Restart receiver timeout counter.
#[bit(6, rw)]
rstto: bool,
restart_timeout: bool,
/// TX disable. If this is 1, TX is disabled, regardless of TXEN.
#[bit(5, rw)]
tx_dis: bool,
tx_disable: bool,
/// TX enable. TX will be enabled if this bit is 1 and the TXDIS is 0.
#[bit(4, rw)]
tx_en: bool,
tx_enable: bool,
/// RX disable. If this is 1, RX is disabled, regardless of RXEN.
#[bit(3, rw)]
rx_dis: bool,
rx_disable: bool,
/// RX enable. RX will be enabled if this bit is 1 and the RXDIS is 0.
#[bit(2, rw)]
rx_en: bool,
rx_enable: bool,
/// TX soft reset.
#[bit(1, rw)]
tx_rst: bool,
tx_reset: bool,
/// RX soft reset.
#[bit(0, rw)]
rx_rst: bool,
rx_reset: bool,
}
#[bitbybit::bitfield(
@@ -109,14 +109,14 @@ pub struct Mode {
#[bits(8..=9, rw)]
chmode: ChMode,
#[bits(6..=7, rw)]
nbstop: Option<Stopbits>,
stopbits: Option<Stopbits>,
#[bits(3..=5, rw)]
par: Parity,
parity: Parity,
/// Char length.
#[bits(1..=2, rw)]
chrl: CharLen,
charlen: CharLen,
#[bit(0, rw)]
clksel: ClockSelect,
clock_select: ClockSelect,
}
#[bitbybit::bitfield(
@@ -162,7 +162,7 @@ pub struct Status {
#[bit(14, r)]
tx_near_full: bool,
#[bit(13, r)]
tx_trig: Ttrig,
tx_trigger: Ttrig,
#[bit(12, r)]
flowdel: bool,
/// Transmitter state machine active.
@@ -181,7 +181,7 @@ pub struct Status {
rx_empty: bool,
/// RX FIFO trigger level was reached.
#[bit(0, r)]
rx_trg: bool,
rx_trigger: bool,
}
#[bitbybit::bitfield(
@@ -197,7 +197,7 @@ pub struct InterruptControl {
#[bit(11, w)]
tx_near_full: bool,
#[bit(10, w)]
tx_trig: bool,
tx_trigger: bool,
#[bit(9, w)]
rx_dms: bool,
/// Receiver timeout error interrupt.
@@ -218,7 +218,7 @@ pub struct InterruptControl {
#[bit(1, w)]
rx_empty: bool,
#[bit(0, w)]
rx_trg: bool,
rx_trigger: bool,
}
#[bitbybit::bitfield(u32, default = 0x0)]
@@ -226,7 +226,7 @@ pub struct InterruptControl {
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct FifoTrigger {
#[bits(0..=5, rw)]
trig: u6,
trigger: u6,
}
#[bitbybit::bitfield(u32, debug, defmt_bitfields(feature = "defmt"))]
@@ -237,7 +237,7 @@ pub struct InterruptMask {
#[bit(11, r)]
tx_near_full: bool,
#[bit(10, r)]
tx_trig: bool,
tx_trigger: bool,
#[bit(9, r)]
rx_dms: bool,
/// Receiver timeout error interrupt.
@@ -259,7 +259,7 @@ pub struct InterruptMask {
rx_empty: bool,
/// RX FIFO trigger level reached.
#[bit(0, r)]
rx_trg: bool,
rx_trigger: bool,
}
#[bitbybit::bitfield(
@@ -297,7 +297,7 @@ pub struct InterruptStatus {
rx_empty: bool,
/// RX FIFO trigger level reached.
#[bit(0, rw)]
rx_trg: bool,
rx_trigger: bool,
}
impl InterruptStatus {
@@ -315,7 +315,7 @@ impl InterruptStatus {
.with_tx_empty(false)
.with_rx_full(false)
.with_rx_empty(false)
.with_rx_trg(false)
.with_rx_trigger(false)
.build()
}
}
@@ -343,16 +343,16 @@ pub struct Registers {
/// Baudgen register
baudgen: Baudgen,
/// RX timeout register
rx_tout: u32,
rx_timeout: u32,
/// RX FIFO trigger level register
rx_fifo_trigger: FifoTrigger,
/// Modem control register
modem_cr: u32,
modem_control: u32,
/// Modem status register
modem_sr: u32,
modem_status: u32,
/// Channel status register
#[mmio(PureRead)]
sr: Status,
status: Status,
/// FIFO register
#[mmio(Read, Write)]
fifo: Fifo,
+1 -1
View File
@@ -647,7 +647,7 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
[[package]]
name = "zynq7000"
version = "0.3.0"
version = "0.4.0"
dependencies = [
"arbitrary-int 2.0.0",
"bitbybit 2.0.0",