Skip to content

Commit b0ae18d

Browse files
committed
feat: rework i2s master tx with dma move api
1 parent 3e6b85b commit b0ae18d

File tree

2 files changed

+209
-178
lines changed

2 files changed

+209
-178
lines changed

esp-hal/src/dma/buffers.rs

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1405,6 +1405,144 @@ impl DmaRxStreamBufView {
14051405
}
14061406
}
14071407

1408+
/// A continuous DMA transfer buffer for Tx.
1409+
pub struct DmaTxStreamBuf {
1410+
descriptors: &'static mut [DmaDescriptor],
1411+
buffer: &'static mut [u8],
1412+
burst: BurstConfig,
1413+
}
1414+
1415+
impl DmaTxStreamBuf {
1416+
/// Creates a new [DmaTxStreamBuf] evenly distributing the buffer between
1417+
/// the provided descriptors.
1418+
pub fn new(descriptors: &'static mut [DmaDescriptor], buffer: &'static mut [u8]) -> Self {
1419+
Self {
1420+
descriptors,
1421+
buffer,
1422+
burst: Default::default(),
1423+
}
1424+
}
1425+
1426+
/// Consume the buf, returning the descriptors and buffer.
1427+
pub fn split(self) -> (&'static mut [DmaDescriptor], &'static mut [u8]) {
1428+
(self.descriptors, self.buffer)
1429+
}
1430+
}
1431+
1432+
unsafe impl DmaTxBuffer for DmaTxStreamBuf {
1433+
type View = ();
1434+
1435+
fn prepare(&mut self) -> Preparation {
1436+
// Link up all the descriptors (but not in a circle).
1437+
let mut next = null_mut();
1438+
for desc in self.descriptors.iter_mut().rev() {
1439+
desc.next = next;
1440+
next = desc;
1441+
1442+
desc.reset_for_rx();
1443+
}
1444+
Preparation {
1445+
start: self.descriptors.as_mut_ptr(),
1446+
direction: TransferDirection::Out,
1447+
#[cfg(psram_dma)]
1448+
accesses_psram: false,
1449+
burst_transfer: self.burst,
1450+
1451+
// Whilst we give ownership of the descriptors the DMA, the correctness of this buffer
1452+
// implementation doesn't rely on the DMA checking for descriptor ownership.
1453+
// No descriptor is added back to the end of the stream before it's ready for the DMA
1454+
// to consume it.
1455+
check_owner: None,
1456+
auto_write_back: true,
1457+
}
1458+
}
1459+
1460+
fn into_view(self) -> Self::View {
1461+
todo!()
1462+
}
1463+
1464+
fn from_view(view: Self::View) -> Self {
1465+
todo!()
1466+
}
1467+
}
1468+
1469+
/// A view into a [DmaRxStreamBuf]
1470+
pub struct DmaTxStreamBufView {
1471+
buf: DmaTxStreamBuf,
1472+
descriptor_idx: usize,
1473+
descriptor_offset: usize,
1474+
}
1475+
1476+
impl DmaTxStreamBufView {
1477+
/// Returns the number of bytes available for writing.
1478+
pub fn available_bytes(&self) -> usize {
1479+
let (tail, head) = self.buf.descriptors.split_at(self.descriptor_idx);
1480+
head.iter()
1481+
.chain(tail)
1482+
.take_while(|d| d.owner() == Owner::Cpu)
1483+
.map(|d| d.len())
1484+
.sum::<usize>()
1485+
- self.descriptor_offset
1486+
}
1487+
1488+
/// Pushes a buffer into the stream buffer.
1489+
/// Returns the number of bytes pushed.
1490+
pub fn push(&mut self, buf: &[u8]) -> usize {
1491+
let chunk_size = self.buf.descriptors[0].size();
1492+
let n_descs = self.buf.descriptors.len();
1493+
1494+
// Prepare descriptors and reorganize link list
1495+
let buf_start = chunk_size * self.descriptor_idx + self.descriptor_offset;
1496+
let desc_start = self.descriptor_idx;
1497+
let mut buf_idx = 0;
1498+
loop {
1499+
let d = &mut self.buf.descriptors[self.descriptor_idx];
1500+
if d.owner() == Owner::Dma {
1501+
break;
1502+
}
1503+
1504+
let desc_remain = d.len() - self.descriptor_offset;
1505+
if buf_idx + desc_remain >= buf.len() {
1506+
self.descriptor_offset += desc_remain;
1507+
break;
1508+
}
1509+
buf_idx += desc_remain;
1510+
1511+
d.next = null_mut();
1512+
let prev = self.descriptor_idx.checked_sub(1).unwrap_or(n_descs - 1);
1513+
self.buf.descriptors[prev].next = d;
1514+
1515+
self.descriptor_idx += 1;
1516+
if self.descriptor_idx > n_descs {
1517+
self.descriptor_idx = 0;
1518+
}
1519+
self.descriptor_offset = 0;
1520+
}
1521+
let buf_end = chunk_size * self.descriptor_idx + self.descriptor_offset;
1522+
let desc_end = self.descriptor_idx;
1523+
1524+
// Actually copy buffers
1525+
if buf_start < buf_end {
1526+
self.buf.buffer[buf_start..buf_end].copy_from_slice(&buf[..buf_end - buf_start]);
1527+
self.buf.descriptors[desc_start..desc_end]
1528+
.iter_mut()
1529+
.for_each(|d| d.set_owner(Owner::Dma));
1530+
buf_end - buf_start
1531+
} else {
1532+
let buf_len = self.buf.buffer.len();
1533+
self.buf.buffer[buf_start..].copy_from_slice(&buf[..buf_len - buf_start]);
1534+
self.buf.buffer[..buf_end].copy_from_slice(&buf[buf_len - buf_start..]);
1535+
self.buf.descriptors[desc_start..]
1536+
.iter_mut()
1537+
.for_each(|d| d.set_owner(Owner::Dma));
1538+
self.buf.descriptors[..desc_end]
1539+
.iter_mut()
1540+
.for_each(|d| d.set_owner(Owner::Dma));
1541+
buf_len + buf_end - buf_start
1542+
}
1543+
}
1544+
}
1545+
14081546
static mut EMPTY: [DmaDescriptor; 1] = [DmaDescriptor::EMPTY];
14091547

14101548
/// An empty buffer that can be used when you don't need to transfer any data.

0 commit comments

Comments
 (0)