Skip to content

feat(all): implement DMA functions with example and add D-cache operations#16

Merged
luojia65 merged 1 commit into
rustsbi:mainfrom
NanaHigh:feat/all
Mar 19, 2026
Merged

feat(all): implement DMA functions with example and add D-cache operations#16
luojia65 merged 1 commit into
rustsbi:mainfrom
NanaHigh:feat/all

Conversation

@NanaHigh

Copy link
Copy Markdown
Member
  • Split CI --all-features into MATRIX features to avoid conflicts.

pbp-dma example tests on kunlunpi v1.1

image

@luojia65 luojia65 changed the title feat(all): implemnt DMA functions with example and add D-cache operations feat(all): implement DMA functions with example and add D-cache operations Mar 19, 2026
@luojia65 luojia65 requested a review from Copilot March 19, 2026 13:35

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds first-class DMA support to the HAL/runtime (including cache-maintenance helpers needed for DMA coherency) and introduces a new pbp-dma example, while updating CI to test chip features via a matrix rather than --all-features.

Changes:

  • Add DMA channel/task abstractions in artinchip-hal (plus DmaExt::split() for ergonomic channel access).
  • Add D-cache clean/invalidate range helpers in artinchip-rt and use them in a new pbp-dma example.
  • Update workspace/CI to include the new example and run clippy with a per-feature matrix.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
examples/pbp/pbp-dma/src/main.rs New DMA mem2mem example using task descriptors + D-cache operations for coherency.
examples/pbp/pbp-dma/build.rs Linker script arg for the new example (consistent with other examples).
examples/pbp/pbp-dma/README.md Build/pack instructions for the new example.
examples/pbp/pbp-dma/Cargo.toml Defines the pbp-dma example crate and its chip feature wiring.
artinchip-rt/src/lib.rs Exposes a new core module from artinchip-rt.
artinchip-rt/src/core.rs Adds the cache submodule entry point.
artinchip-rt/src/core/cache.rs Implements D-cache clean+invalidate and invalidate-by-range helpers.
artinchip-rt/Cargo.toml Adds xuantie-riscv dependency used by cache asm helpers.
artinchip-hal/src/lib.rs Exposes DmaExt in the HAL prelude for .split() ergonomics.
artinchip-hal/src/dma.rs Wires up new DMA modules and re-exports channel/task APIs.
artinchip-hal/src/dma/instance.rs Implements DmaExt::split() returning typed DMA channels.
artinchip-hal/src/dma/dma_ext.rs Introduces the DmaExt trait.
artinchip-hal/src/dma/channel.rs Adds typed per-channel DMA API (start/stop/irq/status/etc.).
artinchip-hal/src/dma/task.rs Introduces DmaTask descriptor and task chaining helper.
artinchip-hal/src/dma/register.rs Refactors DMA register helper APIs (channel args now u8), adds zeroed constructors, handshake bit helpers, etc.
aicfwc/Cargo.toml Adds empty chip features to support feature-matrix clippy invocation.
Cargo.toml Adds examples/pbp/pbp-dma to the workspace.
.github/workflows/Cargo.yml Switches clippy to a feature matrix and adds pbp-dma to the example build list.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@@ -0,0 +1,13 @@
# PBP Dma
Comment on lines +12 to +16
#[repr(C, align(8))]
struct MemBuf([u32; 2000]);

static mut MEM_SRC: MemBuf = MemBuf([0u32; 2000]);
static mut MEM_DST: MemBuf = MemBuf([0xDEAD_BEEFu32; 2000]);
Comment thread artinchip-rt/src/core/cache.rs Outdated
Comment on lines +18 to +27
#[cfg(any(
feature = "d12x",
feature = "d13x",
feature = "g73x",
feature = "m6800"
))]
const CACHE_LINE: usize = 32;
#[cfg(feature = "d21x")]
const CACHE_LINE: usize = 64;

Comment on lines +20 to +44
pub struct DmaChannel<'a, const I: u8> {
pub reg: &'a RegisterBlock,
}

impl<'a, const I: u8> DmaChannel<'a, I> {
/// Create a new DMA channel.
pub fn __new(reg: &'a RegisterBlock, cmu: &Cmu) -> Self {
let clk = &cmu.register_block().clock_dma;
if !clk.read().is_bus_clk_enabled() {
unsafe {
// Initialize module clock.
// Reference: https://aicdoc.artinchip.com/topics/ic/cmu/cmu-function2-d13x.html#topic_yvp_f24_4bc__table_qb3_bn5_ydc
clk.modify(|v| v.enable_bus_clk());
clk.modify(|v| v.enable_module_reset());
riscv::asm::delay(500);
clk.modify(|v| v.disable_module_reset());
}
}
Self { reg }
}

/// Get a reference to the DMA channel's register.
fn channel(&self) -> &DmaCh {
&self.reg.groups[I as usize]
}
Comment on lines +21 to +54
/// Physical address of next task (0xFFFFF800 = end).
pub p_next: u32,

// ========== Software-only fields (not directly used by DMA controller) ==========
/// Handshake mode
pub mode: ChMode,
/// Virtual pointer to next task.
pub v_next: Option<NonNull<DmaTask>>,
}

impl DmaTask {
/// End of DMA task chain end flag.
pub const TASK_END: u32 = 0xFFFFF800;
/// Default delay value.
pub const DEFAULT_DELAY: u32 = 0x40;

pub fn append(&mut self, next: &mut DmaTask) {
let mut last = self;

for _ in 0..1_000 {
if let Some(mut next_ptr) = last.v_next {
last = unsafe { next_ptr.as_mut() };
} else {
break;
}
}

if last.v_next.is_some() {
panic!("DMA task chain too long or contains a cycle");
}

last.p_next = next as *const DmaTask as u32;
last.v_next = Some(NonNull::from(next));
}
Comment on lines +113 to +123
pub const fn enable_channel_addr_req_err(self, channel: u8) -> Self {
let mask = match channel {
DmaChannel::Ch0 => Self::CH0_ADDR_REQ_ERR_EN,
DmaChannel::Ch1 => Self::CH1_ADDR_REQ_ERR_EN,
DmaChannel::Ch2 => Self::CH2_ADDR_REQ_ERR_EN,
DmaChannel::Ch3 => Self::CH3_ADDR_REQ_ERR_EN,
DmaChannel::Ch4 => Self::CH4_ADDR_REQ_ERR_EN,
DmaChannel::Ch5 => Self::CH5_ADDR_REQ_ERR_EN,
DmaChannel::Ch6 => Self::CH6_ADDR_REQ_ERR_EN,
DmaChannel::Ch7 => Self::CH7_ADDR_REQ_ERR_EN,
0x0 => Self::CH0_ADDR_REQ_ERR_EN,
0x1 => Self::CH1_ADDR_REQ_ERR_EN,
0x2 => Self::CH2_ADDR_REQ_ERR_EN,
0x3 => Self::CH3_ADDR_REQ_ERR_EN,
0x4 => Self::CH4_ADDR_REQ_ERR_EN,
0x5 => Self::CH5_ADDR_REQ_ERR_EN,
0x6 => Self::CH6_ADDR_REQ_ERR_EN,
0x7 => Self::CH7_ADDR_REQ_ERR_EN,
_ => unreachable!(),
Comment on lines 71 to +82
strategy:
matrix:
PACKAGE: [artinchip-hal, artinchip-rt, aicfwc]
FEATURES: [d12x, d13x, d21x, g73x, m6800]
steps:
- uses: actions/checkout@v4
- uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: stable
components: clippy
- name: Run cargo clippy
run: cargo clippy -p ${{ matrix.PACKAGE }} --all-targets --all-features -- -D warnings
run: cargo clippy -p ${{ matrix.PACKAGE }} --all-targets --features ${{ matrix.FEATURES }} -- -D warnings

@luojia65 luojia65 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with minor modifications.

Comment thread .github/workflows/Cargo.yml Outdated
@@ -71,14 +71,15 @@ jobs:
strategy:
matrix:
PACKAGE: [artinchip-hal, artinchip-rt, aicfwc]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can split aicfwc check from artinchip-hal and artinchip-rt as it typically runs on host computer, other than on bare-metal chips. aicfwc may not have chip-specific features, as it would support multiple chips without compilation gates.

Comment thread artinchip-rt/src/core/cache.rs Outdated
Comment on lines +18 to +26
#[cfg(any(
feature = "d12x",
feature = "d13x",
feature = "g73x",
feature = "m6800"
))]
const CACHE_LINE: usize = 32;
#[cfg(feature = "d21x")]
const CACHE_LINE: usize = 64;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move CACHE_LINE to module level? Different functions may share the same CACHE_LINE const without duplicated code. For example, we can have artinchip_rt::core::cache::CACHE_LINE which is a usize with different values according to chip features.

Comment thread artinchip-rt/Cargo.toml Outdated
artinchip-rt-macros = { version = "0.0.0", path = "macros" }
artinchip-hal = { version = "0.0.0", path = "../artinchip-hal" }
paste = "1.0"
xuantie-riscv = {git = "https://github.com/rustsbi/xuantie.git", branch = "main"}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
xuantie-riscv = {git = "https://github.com/rustsbi/xuantie.git", branch = "main"}
xuantie-riscv = { git = "https://github.com/rustsbi/xuantie.git", branch = "main" }

There are no cargo fmt guarantees on TOML files, we should keep a note on formatting manually.

…ions

- Split CI `--all-features` into MATRIX features to avoid conflicts.

Signed-off-by: Chongbing Yu <nanahigh@openatom.club>
@NanaHigh

Copy link
Copy Markdown
Member Author

Modifications are completed.

@luojia65 luojia65 merged commit d4ef18e into rustsbi:main Mar 19, 2026
26 checks passed
@NanaHigh NanaHigh deleted the feat/all branch March 19, 2026 14:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants