Skip to content

Commit d7a9d20

Browse files
committed
Introduce RGB/DPI driver
1 parent f3c5286 commit d7a9d20

File tree

8 files changed

+1091
-1
lines changed

8 files changed

+1091
-1
lines changed

esp-hal/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2121
- `I2c::with_timeout` (#2361)
2222
- `Spi::half_duplex_read` and `Spi::half_duplex_write` (#2373)
2323
- `Cpu::COUNT` and `Cpu::current()` (#?)
24+
- Add RGB/DPI driver (#2415)
25+
- Add `DmaLoopBuf` (#2415)
2426

2527
### Changed
2628

esp-hal/src/dma/buffers.rs

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use core::ptr::null_mut;
1+
use core::{
2+
ops::{Deref, DerefMut},
3+
ptr::null_mut,
4+
};
25

36
use super::*;
47
use crate::soc::is_slice_in_dram;
@@ -1000,3 +1003,89 @@ unsafe impl DmaRxBuffer for EmptyBuf {
10001003
0
10011004
}
10021005
}
1006+
1007+
/// DMA Loop Buffer
1008+
///
1009+
/// This consists of a single descriptor that points to itself and points to a
1010+
/// single buffer, resulting in the buffer being transmitted over and over
1011+
/// again, indefinitely.
1012+
///
1013+
/// Note: A DMA descriptor is 12 bytes. If your buffer is significantly shorter
1014+
/// than this, the DMA channel will spend more time reading the descriptor than
1015+
/// it does reading the buffer, which may leave it unable to keep up with the
1016+
/// bandwidth requirements of some peripherals at high frequencies.
1017+
pub struct DmaLoopBuf {
1018+
descriptor: &'static mut DmaDescriptor,
1019+
buffer: &'static mut [u8],
1020+
}
1021+
1022+
impl DmaLoopBuf {
1023+
/// Create a new [DmaLoopBuf].
1024+
pub fn new(
1025+
descriptor: &'static mut DmaDescriptor,
1026+
buffer: &'static mut [u8],
1027+
) -> Result<DmaLoopBuf, DmaBufError> {
1028+
if !is_slice_in_dram(buffer) {
1029+
return Err(DmaBufError::UnsupportedMemoryRegion);
1030+
}
1031+
if !is_slice_in_dram(core::slice::from_ref(descriptor)) {
1032+
return Err(DmaBufError::UnsupportedMemoryRegion);
1033+
}
1034+
1035+
if buffer.len() > max_chunk_size(None) {
1036+
return Err(DmaBufError::InsufficientDescriptors);
1037+
}
1038+
1039+
descriptor.set_owner(Owner::Dma); // Doesn't matter
1040+
descriptor.set_suc_eof(false);
1041+
descriptor.set_length(buffer.len());
1042+
descriptor.set_size(buffer.len());
1043+
descriptor.buffer = buffer.as_mut_ptr();
1044+
descriptor.next = descriptor;
1045+
1046+
Ok(Self { descriptor, buffer })
1047+
}
1048+
1049+
/// Consume the buf, returning the descriptor and buffer.
1050+
pub fn split(self) -> (&'static mut DmaDescriptor, &'static mut [u8]) {
1051+
(self.descriptor, self.buffer)
1052+
}
1053+
}
1054+
1055+
unsafe impl DmaTxBuffer for DmaLoopBuf {
1056+
type View = Self;
1057+
1058+
fn prepare(&mut self) -> Preparation {
1059+
Preparation {
1060+
start: self.descriptor,
1061+
block_size: None,
1062+
is_burstable: true,
1063+
}
1064+
}
1065+
1066+
fn into_view(self) -> Self::View {
1067+
self
1068+
}
1069+
1070+
fn from_view(view: Self::View) -> Self {
1071+
view
1072+
}
1073+
1074+
fn length(&self) -> usize {
1075+
panic!("DmaLoopBuf does not have a length")
1076+
}
1077+
}
1078+
1079+
impl Deref for DmaLoopBuf {
1080+
type Target = [u8];
1081+
1082+
fn deref(&self) -> &Self::Target {
1083+
self.buffer
1084+
}
1085+
}
1086+
1087+
impl DerefMut for DmaLoopBuf {
1088+
fn deref_mut(&mut self) -> &mut Self::Target {
1089+
self.buffer
1090+
}
1091+
}

esp-hal/src/dma/mod.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,30 @@ macro_rules! dma_rx_stream_buffer {
761761
}};
762762
}
763763

764+
/// Convenience macro to create a [DmaLoopBuf] from a buffer size.
765+
///
766+
/// ## Usage
767+
/// ```rust,no_run
768+
#[doc = crate::before_snippet!()]
769+
/// use esp_hal::dma_loop_buffer;
770+
///
771+
/// let buf = dma_loop_buffer!(2000);
772+
/// # }
773+
/// ```
774+
#[macro_export]
775+
macro_rules! dma_loop_buffer {
776+
($size:expr) => {{
777+
const {
778+
::core::assert!($size <= 4095, "size must be <= 4095");
779+
::core::assert!($size > 0, "size must be > 0");
780+
}
781+
782+
let (buffer, descriptors) = $crate::dma_buffers_impl!($size, $size, is_circular = false);
783+
784+
$crate::dma::DmaLoopBuf::new(&mut descriptors[0], buffer).unwrap()
785+
}};
786+
}
787+
764788
/// DMA Errors
765789
#[derive(Debug, Clone, Copy, PartialEq)]
766790
#[cfg_attr(feature = "defmt", derive(defmt::Format))]

0 commit comments

Comments
 (0)