Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for buffered uart #314

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 76 additions & 20 deletions src/dma/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,24 +124,6 @@ impl<'d> Channel<'d> {
let xfercount = (mem_len / xferwidth) - 1;
let channel = self.info.ch_num;

// Configure the channel descriptor
// NOTE: the DMA controller expects the memory buffer end address but peripheral address is actual
// SAFETY: unsafe due to use of a mutable static (DESCRIPTORS.list)
unsafe {
DESCRIPTORS.list[channel].reserved = 0;
if dir == Direction::MemoryToPeripheral {
DESCRIPTORS.list[channel].dst_data_end_addr = dstbase as u32;
} else {
DESCRIPTORS.list[channel].dst_data_end_addr = dstbase as u32 + (xfercount * xferwidth) as u32;
}
if dir == Direction::PeripheralToMemory {
DESCRIPTORS.list[channel].src_data_end_addr = srcbase as u32;
} else {
DESCRIPTORS.list[channel].src_data_end_addr = srcbase as u32 + (xfercount * xferwidth) as u32;
}
DESCRIPTORS.list[channel].nxt_desc_link_addr = 0;
}
Comment on lines -130 to -143
Copy link
Contributor

Choose a reason for hiding this comment

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

Should be part of its own commit. Why is this needed?


// Configure for transfer type, no hardware triggering (we'll trigger via software), high priority
// SAFETY: unsafe due to .bits usage
self.info.regs.channel(channel).cfg().write(|w| unsafe {
Expand All @@ -164,8 +146,19 @@ impl<'d> Channel<'d> {
// SAFETY: unsafe due to .bits usage
self.info.regs.channel(channel).xfercfg().write(|w| unsafe {
w.cfgvalid().set_bit();
w.clrtrig().set_bit();
w.reload().clear_bit();

if options.is_continuous {
w.reload().enabled();
w.clrtrig().clear_bit();
} else {
w.reload().disabled();
w.clrtrig().set_bit();
}
if options.is_sw_trig {
w.swtrig().set_bit();
} else {
w.swtrig().clear_bit();
}
Comment on lines +150 to +161
Copy link
Contributor

Choose a reason for hiding this comment

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

how about using variant()?

w.reload().variant(options.is_continuous).
    clrtrig().variant(!options.is_continuous).
    swtrig().variant(options.is_sw_trig)

w.setinta().set_bit();
w.width().bits(options.width.into());
if dir == Direction::PeripheralToMemory {
Expand All @@ -180,6 +173,35 @@ impl<'d> Channel<'d> {
}
w.xfercount().bits(xfercount as u16)
});

// Configure the channel descriptor
// NOTE: the DMA controller expects the memory buffer end address but peripheral address is actual
// SAFETY: unsafe due to use of a mutable static (DESCRIPTORS.list)
unsafe {
if options.is_continuous {
let xfer_cfg = self.info.regs.channel(channel).xfercfg().read();
DESCRIPTORS.list[channel].reserved_reloadcfg = xfer_cfg.bits();
} else {
DESCRIPTORS.list[channel].reserved_reloadcfg = 0;
}

if dir == Direction::MemoryToPeripheral {
DESCRIPTORS.list[channel].dst_data_end_addr = dstbase as u32;
} else {
DESCRIPTORS.list[channel].dst_data_end_addr = dstbase as u32 + (xfercount * xferwidth) as u32;
}

if dir == Direction::PeripheralToMemory {
DESCRIPTORS.list[channel].src_data_end_addr = srcbase as u32;
} else {
DESCRIPTORS.list[channel].src_data_end_addr = srcbase as u32 + (xfercount * xferwidth) as u32;
}
if options.is_continuous {
DESCRIPTORS.list[channel].nxt_desc_link_addr = &DESCRIPTORS.list[channel] as *const _ as u32;
} else {
DESCRIPTORS.list[channel].nxt_desc_link_addr = 0;
}
}
}

/// Enable the DMA channel (only after configuring)
Expand All @@ -192,6 +214,40 @@ impl<'d> Channel<'d> {
.modify(|_, w| unsafe { w.ena().bits(1 << channel) });
}

#[cfg(feature = "defmt")]
/// Log the DMA channel transfer configuration
pub fn log_channel(&self) {
// Log DMA Channel Config Register
let channel = self.info.ch_num;
let dma_channel_cfg = self.info.regs.channel(channel).cfg().read();
defmt::info!(
"DMA Channel {} Config Register: 0x{=u32:x}",
channel,
dma_channel_cfg.bits()
);
// Log Interrupt Enable Set Register
let intenset0 = self.info.regs.intenset0().read();
defmt::info!("Interrupt Enable Set Register: 0x{=u32:x}", intenset0.bits());

// Log DMA Xfer Config Register
let xfer_cfg = self.info.regs.channel(channel).xfercfg().read();
defmt::info!(
"DMA Channel {} Xfer Config Register: 0x{=u32:x}",
channel,
xfer_cfg.bits()
);
// Log DMA Enable Set Register after enabling
let enableset0 = self.info.regs.enableset0().read();
defmt::info!("DMA Enable Set Register:0x{=u32:x}", enableset0.bits());
// Log DMA Xfer Config Register after triggering
let xfer_cfg_after = self.info.regs.channel(channel).xfercfg().read();
defmt::info!(
"DMA Channel {} Xfer Config Register (After Trigger): 0x{=u32:x}",
channel,
xfer_cfg_after.bits()
);
}

/// Disable the DMA channel
pub fn disable_channel(&self) {
let channel = self.info.ch_num;
Expand Down
4 changes: 2 additions & 2 deletions src/dma/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const DMA_CHANNEL_COUNT: usize = 33;
#[derive(Copy, Clone, Debug)]
#[repr(C)]
struct ChannelDescriptor {
reserved: u32,
reserved_reloadcfg: u32,
src_data_end_addr: u32,
dst_data_end_addr: u32,
nxt_desc_link_addr: u32,
Expand All @@ -42,7 +42,7 @@ struct DescriptorBlock {
/// DMA channel descriptor list
static mut DESCRIPTORS: DescriptorBlock = DescriptorBlock {
list: [ChannelDescriptor {
reserved: 0,
reserved_reloadcfg: 0,
src_data_end_addr: 0,
dst_data_end_addr: 0,
nxt_desc_link_addr: 0,
Expand Down
8 changes: 8 additions & 0 deletions src/dma/transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,21 @@ pub struct TransferOptions {

/// Transfer priority level
pub priority: Priority,

/// Transfer is intended to be done continuously, such as for a circular buffer
pub is_continuous: bool,

/// Transfer is software triggerred
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: typo, triggered*

pub is_sw_trig: bool,
}

impl Default for TransferOptions {
fn default() -> Self {
Self {
width: Width::Bit8,
priority: Priority::Priority0,
is_continuous: false,
is_sw_trig: false,
}
}
}
Expand Down
Loading