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

simplify serialdma macro #500

Merged
merged 1 commit into from
Oct 5, 2024
Merged
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
339 changes: 174 additions & 165 deletions src/serial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -660,197 +660,206 @@ pub type Tx3 = Tx<USART3>;
use crate::dma::{Receive, TransferPayload, Transmit};

macro_rules! serialdma {
($(
$USARTX:ident: (
$rxdma:ident,
$txdma:ident,
$dmarxch:ty,
$dmatxch:ty,
),
)+) => {
$(
pub type $rxdma = RxDma<Rx<$USARTX>, $dmarxch>;
pub type $txdma = TxDma<Tx<$USARTX>, $dmatxch>;
(
$USARTX:ident,
$rxdma:ident,
$txdma:ident,
$dmarxch:ty,
$dmatxch:ty
) => {
pub type $rxdma = RxDma<Rx<$USARTX>, $dmarxch>;
pub type $txdma = TxDma<Tx<$USARTX>, $dmatxch>;

impl Receive for $rxdma {
type RxChannel = $dmarxch;
type TransmittedWord = u8;
}

impl Receive for $rxdma {
type RxChannel = $dmarxch;
type TransmittedWord = u8;
}
impl Transmit for $txdma {
type TxChannel = $dmatxch;
type ReceivedWord = u8;
}

impl Transmit for $txdma {
type TxChannel = $dmatxch;
type ReceivedWord = u8;
impl TransferPayload for $rxdma {
fn start(&mut self) {
self.channel.start();
}
fn stop(&mut self) {
self.channel.stop();
}
}

impl TransferPayload for $rxdma {
fn start(&mut self) {
self.channel.start();
}
fn stop(&mut self) {
self.channel.stop();
}
impl TransferPayload for $txdma {
fn start(&mut self) {
self.channel.start();
}
fn stop(&mut self) {
self.channel.stop();
}
}

impl TransferPayload for $txdma {
fn start(&mut self) {
self.channel.start();
impl Rx<$USARTX> {
pub fn with_dma(self, channel: $dmarxch) -> $rxdma {
unsafe {
(*$USARTX::ptr()).cr3.modify(|_, w| w.dmar().set_bit());
}
fn stop(&mut self) {
self.channel.stop();
RxDma {
payload: self,
channel,
}
}
}

impl Rx<$USARTX> {
pub fn with_dma(self, channel: $dmarxch) -> $rxdma {
unsafe { (*$USARTX::ptr()).cr3.modify(|_, w| w.dmar().set_bit()); }
RxDma {
payload: self,
channel,
}
impl Tx<$USARTX> {
pub fn with_dma(self, channel: $dmatxch) -> $txdma {
unsafe {
(*$USARTX::ptr()).cr3.modify(|_, w| w.dmat().set_bit());
}
}

impl Tx<$USARTX> {
pub fn with_dma(self, channel: $dmatxch) -> $txdma {
unsafe { (*$USARTX::ptr()).cr3.modify(|_, w| w.dmat().set_bit()); }
TxDma {
payload: self,
channel,
}
TxDma {
payload: self,
channel,
}
}
}

impl $rxdma {
pub fn release(mut self) -> (Rx<$USARTX>, $dmarxch) {
self.stop();
unsafe { (*$USARTX::ptr()).cr3.modify(|_, w| w.dmar().clear_bit()); }
let RxDma {payload, channel} = self;
(
payload,
channel
)
impl $rxdma {
pub fn release(mut self) -> (Rx<$USARTX>, $dmarxch) {
self.stop();
unsafe {
(*$USARTX::ptr()).cr3.modify(|_, w| w.dmar().clear_bit());
}
let RxDma { payload, channel } = self;
(payload, channel)
}
}

impl $txdma {
pub fn release(mut self) -> (Tx<$USARTX>, $dmatxch) {
self.stop();
unsafe { (*$USARTX::ptr()).cr3.modify(|_, w| w.dmat().clear_bit()); }
let TxDma {payload, channel} = self;
(
payload,
channel,
)
impl $txdma {
pub fn release(mut self) -> (Tx<$USARTX>, $dmatxch) {
self.stop();
unsafe {
(*$USARTX::ptr()).cr3.modify(|_, w| w.dmat().clear_bit());
}
let TxDma { payload, channel } = self;
(payload, channel)
}
}

impl<B> crate::dma::CircReadDma<B, u8> for $rxdma
where
&'static mut [B; 2]: WriteBuffer<Word = u8>,
B: 'static,
{
fn circ_read(mut self, mut buffer: &'static mut [B; 2]) -> CircBuffer<B, Self> {
// NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it
// until the end of the transfer.
let (ptr, len) = unsafe { buffer.write_buffer() };
self.channel.set_peripheral_address(unsafe{ &(*$USARTX::ptr()).dr as *const _ as u32 }, false);
self.channel.set_memory_address(ptr as u32, true);
self.channel.set_transfer_length(len);

atomic::compiler_fence(Ordering::Release);

self.channel.ch().cr.modify(|_, w| {
w.mem2mem().clear_bit();
w.pl().medium();
w.msize().bits8();
w.psize().bits8();
w.circ().set_bit();
w.dir().clear_bit()
});

self.start();

CircBuffer::new(buffer, self)
}
impl<B> crate::dma::CircReadDma<B, u8> for $rxdma
where
&'static mut [B; 2]: WriteBuffer<Word = u8>,
B: 'static,
{
fn circ_read(mut self, mut buffer: &'static mut [B; 2]) -> CircBuffer<B, Self> {
// NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it
// until the end of the transfer.
let (ptr, len) = unsafe { buffer.write_buffer() };
self.channel.set_peripheral_address(
unsafe { &(*$USARTX::ptr()).dr as *const _ as u32 },
false,
);
self.channel.set_memory_address(ptr as u32, true);
self.channel.set_transfer_length(len);

atomic::compiler_fence(Ordering::Release);

self.channel.ch().cr.modify(|_, w| {
w.mem2mem().clear_bit();
w.pl().medium();
w.msize().bits8();
w.psize().bits8();
w.circ().set_bit();
w.dir().clear_bit()
});

self.start();

CircBuffer::new(buffer, self)
}
}

impl<B> crate::dma::ReadDma<B, u8> for $rxdma
where
B: WriteBuffer<Word = u8>,
{
fn read(mut self, mut buffer: B) -> Transfer<W, B, Self> {
// NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it
// until the end of the transfer.
let (ptr, len) = unsafe { buffer.write_buffer() };
self.channel.set_peripheral_address(unsafe{ &(*$USARTX::ptr()).dr as *const _ as u32 }, false);
self.channel.set_memory_address(ptr as u32, true);
self.channel.set_transfer_length(len);

atomic::compiler_fence(Ordering::Release);
self.channel.ch().cr.modify(|_, w| {
w.mem2mem().clear_bit();
w.pl().medium();
w.msize().bits8();
w.psize().bits8();
w.circ().clear_bit();
w.dir().clear_bit()
});
self.start();

Transfer::w(buffer, self)
}
impl<B> crate::dma::ReadDma<B, u8> for $rxdma
where
B: WriteBuffer<Word = u8>,
{
fn read(mut self, mut buffer: B) -> Transfer<W, B, Self> {
// NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it
// until the end of the transfer.
let (ptr, len) = unsafe { buffer.write_buffer() };
self.channel.set_peripheral_address(
unsafe { &(*$USARTX::ptr()).dr as *const _ as u32 },
false,
);
self.channel.set_memory_address(ptr as u32, true);
self.channel.set_transfer_length(len);

atomic::compiler_fence(Ordering::Release);
self.channel.ch().cr.modify(|_, w| {
w.mem2mem().clear_bit();
w.pl().medium();
w.msize().bits8();
w.psize().bits8();
w.circ().clear_bit();
w.dir().clear_bit()
});
self.start();

Transfer::w(buffer, self)
}
}

impl<B> crate::dma::WriteDma<B, u8> for $txdma
where
B: ReadBuffer<Word = u8>,
{
fn write(mut self, buffer: B) -> Transfer<R, B, Self> {
// NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it
// until the end of the transfer.
let (ptr, len) = unsafe { buffer.read_buffer() };

self.channel.set_peripheral_address(unsafe{ &(*$USARTX::ptr()).dr as *const _ as u32 }, false);

self.channel.set_memory_address(ptr as u32, true);
self.channel.set_transfer_length(len);

atomic::compiler_fence(Ordering::Release);

self.channel.ch().cr.modify(|_, w| {
w.mem2mem().clear_bit();
w.pl().medium();
w.msize().bits8();
w.psize().bits8();
w.circ().clear_bit();
w.dir().set_bit()
});
self.start();

Transfer::r(buffer, self)
}
impl<B> crate::dma::WriteDma<B, u8> for $txdma
where
B: ReadBuffer<Word = u8>,
{
fn write(mut self, buffer: B) -> Transfer<R, B, Self> {
// NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it
// until the end of the transfer.
let (ptr, len) = unsafe { buffer.read_buffer() };

self.channel.set_peripheral_address(
unsafe { &(*$USARTX::ptr()).dr as *const _ as u32 },
false,
);

self.channel.set_memory_address(ptr as u32, true);
self.channel.set_transfer_length(len);

atomic::compiler_fence(Ordering::Release);

self.channel.ch().cr.modify(|_, w| {
w.mem2mem().clear_bit();
w.pl().medium();
w.msize().bits8();
w.psize().bits8();
w.circ().clear_bit();
w.dir().set_bit()
});
self.start();

Transfer::r(buffer, self)
}
)+
}
}
};
}

serialdma! {
USART1: (
RxDma1,
TxDma1,
dma1::C5,
dma1::C4,
),
USART2: (
RxDma2,
TxDma2,
dma1::C6,
dma1::C7,
),
USART3: (
RxDma3,
TxDma3,
dma1::C3,
dma1::C2,
),
USART1,
RxDma1,
TxDma1,
dma1::C5,
dma1::C4
}
serialdma! {
USART2,
RxDma2,
TxDma2,
dma1::C6,
dma1::C7
}
serialdma! {
USART3,
RxDma3,
TxDma3,
dma1::C3,
dma1::C2
}
Loading