Skip to content

Commit 1d4baf0

Browse files
authored
Merge pull request #5 from NanaHigh/nanahigh/hal
feat(all): add DMA, AXICFG, WRI, CE register implementations
2 parents 5f4b78a + 7a1802c commit 1d4baf0

File tree

13 files changed

+2631
-11
lines changed

13 files changed

+2631
-11
lines changed

.github/workflows/Cargo.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,14 @@ jobs:
2525
strategy:
2626
matrix:
2727
PACKAGE: [artinchip-rt, artinchip-hal]
28+
FEATURES: [d12x, d13x, d21x, g73x, m6800]
2829
steps:
2930
- uses: actions/checkout@v4
3031
- uses: actions-rust-lang/setup-rust-toolchain@v1
3132
with:
3233
toolchain: stable
3334
- name: Run cargo test
34-
run: cargo test -p ${{ matrix.PACKAGE }}
35+
run: cargo test -p ${{ matrix.PACKAGE }} --features ${{ matrix.FEATURES }}
3536

3637
test-coverage:
3738
name: Test Coverage

artinchip-hal/Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,10 @@ edition = "2024"
66
[dependencies]
77
volatile-register = "0.2.2"
88
uart16550 = "0.0.1"
9+
10+
[features]
11+
d12x = []
12+
d13x = []
13+
d21x = []
14+
g73x = []
15+
m6800 = []

artinchip-hal/src/axi_cfg.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
//! AXI Configuration (AXICFG).
2+
3+
mod register;
4+
5+
pub use register::*;
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
//! AXI configuration register blocks and registers.
2+
3+
use volatile_register::{RO, RW};
4+
5+
/// AXI configuration register block.
6+
#[repr(C)]
7+
pub struct RegisterBlock {
8+
/// Axi configuration groups.
9+
pub groups: [AxiCfg; 14],
10+
_reserved0: [u8; 0xF1C],
11+
/// Axi config version register (`AXICFG_VER`).
12+
#[doc(alias = "AXICFG_VER")]
13+
pub version: RO<u32>,
14+
}
15+
16+
/// Axi operation mode.
17+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
18+
#[repr(u8)]
19+
pub enum Mode {
20+
Read,
21+
Write,
22+
}
23+
24+
/// Axi port.
25+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
26+
#[repr(u8)]
27+
pub enum Port {
28+
/// Central Process Unit.
29+
Cpu,
30+
/// Advanced High Performance Bus.
31+
Ahb,
32+
/// Display Engine.
33+
De,
34+
/// Graphics Engine.
35+
Ge,
36+
/// Video Engine.
37+
Ve,
38+
/// Digital Video Port.
39+
Dvp,
40+
/// Crypto Engine.
41+
Ce,
42+
}
43+
44+
impl RegisterBlock {
45+
/// Get the AXI configuration for a specific port and mode.
46+
#[inline]
47+
pub const fn get_cfg(&self, port: Port, mode: Mode) -> &AxiCfg {
48+
let index = match port {
49+
Port::Cpu => 0,
50+
Port::Ahb => 1,
51+
Port::De => 2,
52+
Port::Ge => 3,
53+
Port::Ve => 4,
54+
Port::Dvp => 5,
55+
Port::Ce => 6,
56+
} + match mode {
57+
Mode::Read => 0,
58+
Mode::Write => 7,
59+
};
60+
&self.groups[index]
61+
}
62+
}
63+
64+
/// Axi configuration register.
65+
#[repr(C)]
66+
pub struct AxiCfg {
67+
/// Axi configuration 0 register (`AXI_CFG0`).
68+
#[doc(alias = "AXI_CFG0")]
69+
pub config: RW<AxiConfig>,
70+
_reserved0: [u8; 0xC],
71+
}
72+
73+
/// Qos selection.
74+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
75+
#[repr(u8)]
76+
pub enum QosSel {
77+
/// Quality of service from external master.
78+
External,
79+
/// Quality of service from internal register.
80+
Internal,
81+
}
82+
83+
/// Axi configuration register.
84+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
85+
#[repr(transparent)]
86+
pub struct AxiConfig(u32);
87+
88+
impl AxiConfig {
89+
const QOS_VAL: u32 = 0xF << 24;
90+
const QOS_SEL: u32 = 0x1 << 16;
91+
const SLV_READY: u32 = 0x1 << 1;
92+
93+
/// Set the quality of service (`QOS_VAL`).
94+
#[doc(alias = "QOS_VAL")]
95+
#[inline]
96+
pub const fn set_qos(self, qos: u8) -> Self {
97+
Self((self.0 & !Self::QOS_VAL) | (Self::QOS_VAL & ((qos as u32 & 0xF) << 24)))
98+
}
99+
/// Get the quality of service.
100+
#[inline]
101+
pub const fn qos(&self) -> u8 {
102+
((self.0 & Self::QOS_VAL) >> 24) as u8
103+
}
104+
/// Set quality of service selection (`QOS_SEL`).
105+
#[doc(alias = "QOS_SEL")]
106+
#[inline]
107+
pub const fn set_qos_sel(self, sel: QosSel) -> Self {
108+
Self((self.0 & !Self::QOS_SEL) | (Self::QOS_SEL & ((sel as u32) << 16)))
109+
}
110+
/// Get quality of service selection.
111+
#[inline]
112+
pub const fn qos_sel(&self) -> QosSel {
113+
if (self.0 & Self::QOS_SEL) != 0 {
114+
QosSel::Internal
115+
} else {
116+
QosSel::External
117+
}
118+
}
119+
/// Enable slave ready (`SLV_READY`).
120+
#[doc(alias = "SLV_READY")]
121+
#[inline]
122+
pub const fn enable_slave_ready(self) -> Self {
123+
Self(self.0 | Self::SLV_READY)
124+
}
125+
/// Disable slave ready.
126+
#[inline]
127+
pub const fn disable_slave_ready(self) -> Self {
128+
Self(self.0 & !Self::SLV_READY)
129+
}
130+
/// Check if slave ready is enabled.
131+
#[inline]
132+
pub const fn is_slave_ready_enabled(&self) -> bool {
133+
(self.0 & Self::SLV_READY) != 0
134+
}
135+
}
136+
137+
#[cfg(test)]
138+
mod tests {
139+
use super::{AxiCfg, AxiConfig, QosSel, RegisterBlock};
140+
use core::mem::{offset_of, size_of};
141+
142+
#[test]
143+
fn struct_register_block_offset() {
144+
assert_eq!(offset_of!(RegisterBlock, groups), 0x00);
145+
assert_eq!(size_of::<AxiCfg>(), 0x10);
146+
assert_eq!(offset_of!(RegisterBlock, version), 0xFFC);
147+
}
148+
149+
#[test]
150+
fn struct_register_block_functions() {
151+
let block = RegisterBlock {
152+
groups: core::array::from_fn(|_| AxiCfg {
153+
config: unsafe { core::mem::zeroed() },
154+
_reserved0: [0; 0xC],
155+
}),
156+
_reserved0: [0; 0xF1C],
157+
version: unsafe { core::mem::zeroed() },
158+
};
159+
160+
fn usize_to_port(i: usize) -> super::Port {
161+
match i {
162+
0 => super::Port::Cpu,
163+
1 => super::Port::Ahb,
164+
2 => super::Port::De,
165+
3 => super::Port::Ge,
166+
4 => super::Port::Ve,
167+
5 => super::Port::Dvp,
168+
6 => super::Port::Ce,
169+
_ => panic!("Invalid port index"),
170+
}
171+
}
172+
173+
for i in 0..7 {
174+
let port = usize_to_port(i);
175+
assert!(core::ptr::eq(
176+
block.get_cfg(port, super::Mode::Read),
177+
&block.groups[i]
178+
));
179+
assert!(core::ptr::eq(
180+
block.get_cfg(port, super::Mode::Write),
181+
&block.groups[i + 7]
182+
));
183+
}
184+
}
185+
186+
#[test]
187+
fn struct_axiconfig_functions() {
188+
let mut config = AxiConfig(0).set_qos(0xF);
189+
assert_eq!(config.qos(), 0xF);
190+
assert_eq!(config.0, 0x0F00_0000);
191+
192+
config = AxiConfig(0).set_qos_sel(QosSel::Internal);
193+
assert_eq!(config.qos_sel(), QosSel::Internal);
194+
assert_eq!(config.0, 0x0001_0000);
195+
196+
config = config.set_qos_sel(QosSel::External);
197+
assert_eq!(config.qos_sel(), QosSel::External);
198+
assert_eq!(config.0, 0x0000_0000);
199+
200+
config = AxiConfig(0).enable_slave_ready();
201+
assert!(config.is_slave_ready_enabled());
202+
assert_eq!(config.0, 0x0000_0002);
203+
204+
config = config.disable_slave_ready();
205+
assert!(!config.is_slave_ready_enabled());
206+
assert_eq!(config.0, 0x0000_0000);
207+
}
208+
}

artinchip-hal/src/ce.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
//! Crypto Engine (CE).
2+
3+
mod register;
4+
5+
pub use register::*;

0 commit comments

Comments
 (0)