Skip to content

Commit a99c332

Browse files
committed
dma: changed to setup based on direction
1 parent 5ced109 commit a99c332

2 files changed

Lines changed: 83 additions & 63 deletions

File tree

chips/stm32u5xx/src/dma.rs

Lines changed: 70 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ const USART1_RDR: u32 = USART1_BASE_ADDR + 0x24;
1717
/// USART1 Transmit Data Register (TDR) address.
1818
const USART1_TDR: u32 = USART1_BASE_ADDR + 0x28;
1919

20+
/// GPDMA Request Selection IDs (REQSEL)
21+
/// Found in the GPDMA request multiplexer table of the STM32U5 reference manual.
22+
const GPDMA_REQ_USART1_RX: u32 = 24;
23+
const GPDMA_REQ_USART1_TX: u32 = 25;
24+
2025
register_bitfields! [
2126
u32,
2227
pub DmaChannelTR1 [
@@ -179,6 +184,34 @@ impl From<ChannelId> for usize {
179184
}
180185
}
181186

187+
pub enum DmaDirection {
188+
MemoryToPeripheral,
189+
PeripheralToMemory,
190+
}
191+
192+
#[derive(Copy, Clone)]
193+
pub enum DmaPeripheral {
194+
Usart1Tx,
195+
Usart1Rx,
196+
}
197+
198+
impl DmaPeripheral {
199+
fn get_params(&self) -> (u32, u32, DmaDirection) {
200+
match self {
201+
DmaPeripheral::Usart1Tx => (
202+
USART1_TDR,
203+
GPDMA_REQ_USART1_TX,
204+
DmaDirection::MemoryToPeripheral,
205+
),
206+
DmaPeripheral::Usart1Rx => (
207+
USART1_RDR,
208+
GPDMA_REQ_USART1_RX,
209+
DmaDirection::PeripheralToMemory,
210+
),
211+
}
212+
}
213+
}
214+
182215
pub struct ChannelDma {
183216
pub channel: ChannelId,
184217
pub in_use: Cell<bool>,
@@ -229,8 +262,15 @@ impl Dma {
229262
Some(channel.into())
230263
}
231264

232-
pub fn setup_usart1_tx(&self, channel: ChannelId, buffer_addr: u32, length: u32) {
265+
pub fn setup(
266+
&self,
267+
channel: ChannelId,
268+
peripheral: DmaPeripheral,
269+
buffer_addr: u32,
270+
length: u32,
271+
) {
233272
let channel_id: usize = channel.into();
273+
let (periph_addr, reqsel, direction) = peripheral.get_params();
234274

235275
// 1. Mark channel as Secure AND Privileged
236276
self.registers.seccfgr.modify(CH_FIELDS[channel_id].val(1));
@@ -251,66 +291,38 @@ impl Dma {
251291
+ DmaChannelFCR::TCF::SET,
252292
);
253293

254-
// 4. Configure Transfer Register 1 (TR1)
255-
// SINC (bit 3) = 1
256-
// SAP (bit 14) = 0 (Port 0)
257-
// DAP (bit 30) = 0 (Port 0 - Safer for U545)
258-
ch.t_r1.write(
259-
DmaChannelTR1::SINC::SET + DmaChannelTR1::SAP::CLEAR + DmaChannelTR1::DAP::CLEAR,
260-
);
261-
262-
// 5. Configure Transfer Register 2 (TR2)
263-
// REQSEL = 25 (USART1_TX on U545), DREQ = 1 (Destination request)
264-
ch.t_r2
265-
.write(DmaChannelTR2::REQSEL.val(25) + DmaChannelTR2::DREQ::SET);
266-
267-
// 6. Set Addresses
268-
ch.s_ar.set(buffer_addr);
269-
ch.d_ar.set(USART1_TDR);
270-
271-
// 7. Set Block Register 1 (BR1)
272-
ch.b_r1.set(length & 0xFFFF);
273-
274-
// 8. Enable Transfer Complete Interrupt (bit 8) and Start (bit 0)
275-
ch.c_r
276-
.write(DmaChannelCR::TCIE::SET + DmaChannelCR::EN::SET);
277-
}
278-
279-
pub fn setup_usart1_rx(&self, channel: ChannelId, buffer_addr: u32, length: u32) {
280-
let channel_id: usize = channel.into();
281-
282-
// Mark channel as Secure AND Privileged
283-
self.registers.seccfgr.modify(CH_FIELDS[channel_id].val(1));
284-
self.registers.privcfgr.modify(CH_FIELDS[channel_id].val(1));
285-
286-
let ch = &self.registers.channels[channel_id];
287-
288-
ch.c_r.write(DmaChannelCR::EN::CLEAR);
289-
ch.f_cr.write(
290-
DmaChannelFCR::SUSPF::SET
291-
+ DmaChannelFCR::USEF::SET
292-
+ DmaChannelFCR::ULEF::SET
293-
+ DmaChannelFCR::DTEF::SET
294-
+ DmaChannelFCR::HTF::SET
295-
+ DmaChannelFCR::TCF::SET,
296-
);
297-
298-
// Configure TR1 (Security + Direction)
299-
// DINC (19), SSEC (15), DSEC (31)
300-
ch.t_r1
301-
.write(DmaChannelTR1::DINC::SET + DmaChannelTR1::SSEC::SET + DmaChannelTR1::DSEC::SET);
302-
303-
// Configure TR2 (Trigger Source) - REQSEL = 24
304-
ch.t_r2.write(DmaChannelTR2::REQSEL.val(24));
305-
306-
// 6. Set Addresses
307-
ch.s_ar.set(USART1_RDR);
308-
ch.d_ar.set(buffer_addr);
294+
// 4. Configure TR1, TR2 and addresses based on direction
295+
match direction {
296+
DmaDirection::MemoryToPeripheral => {
297+
// Source is memory (incrementing), Destination is peripheral (fixed)
298+
ch.t_r1.write(
299+
DmaChannelTR1::SINC::SET
300+
+ DmaChannelTR1::SAP::CLEAR
301+
+ DmaChannelTR1::DAP::CLEAR,
302+
);
303+
// Source request comes from destination peripheral
304+
ch.t_r2
305+
.write(DmaChannelTR2::REQSEL.val(reqsel) + DmaChannelTR2::DREQ::SET);
306+
ch.s_ar.set(buffer_addr);
307+
ch.d_ar.set(periph_addr);
308+
}
309+
DmaDirection::PeripheralToMemory => {
310+
// Destination is memory (incrementing), Source is peripheral (fixed)
311+
// Note: Keeping security bits as in previous RX implementation
312+
ch.t_r1.write(
313+
DmaChannelTR1::DINC::SET + DmaChannelTR1::SSEC::SET + DmaChannelTR1::DSEC::SET,
314+
);
315+
// Source request comes from source peripheral
316+
ch.t_r2.write(DmaChannelTR2::REQSEL.val(reqsel));
317+
ch.s_ar.set(periph_addr);
318+
ch.d_ar.set(buffer_addr);
319+
}
320+
}
309321

310-
// 7. Set Block Register 1 (BR1)
322+
// 5. Set Block Register 1 (BR1)
311323
ch.b_r1.set(length & 0xFFFF);
312324

313-
// 8. Enable
325+
// 6. Enable Transfer Complete Interrupt and start the channel
314326
ch.c_r
315327
.write(DmaChannelCR::TCIE::SET + DmaChannelCR::EN::SET);
316328
}

chips/stm32u5xx/src/usart.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// SPDX-License-Identifier: Apache-2.0 OR MIT
33
// Copyright OxidOS Automotive 2026.
44

5-
use crate::dma::ChannelId;
5+
use crate::dma::{ChannelId, Dma, DmaPeripheral};
66
use core::cell::Cell;
77
use kernel::hil::uart::{self};
88
use kernel::utilities::cells::OptionalCell;
@@ -11,8 +11,6 @@ use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeabl
1111
use kernel::utilities::registers::{register_bitfields, register_structs, ReadOnly, ReadWrite};
1212
use kernel::utilities::StaticRef;
1313

14-
use crate::dma::Dma;
15-
1614
register_structs! {
1715
pub UsartRegisters {
1816
/// Control register 1
@@ -246,7 +244,12 @@ impl<'a> uart::Transmit<'a> for Usart<'a> {
246244

247245
self.tx_buffer.map(|buf| {
248246
if let Some(ch) = self.dma_channel_tx.get() {
249-
dma.setup_usart1_tx(ch, buf.as_ptr() as u32, tx_len as u32);
247+
dma.setup(
248+
ch,
249+
DmaPeripheral::Usart1Tx,
250+
buf.as_ptr() as u32,
251+
tx_len as u32,
252+
);
250253
self.registers.cr3.modify(CR3::DMAT::SET);
251254
}
252255
});
@@ -309,7 +312,12 @@ impl<'a> uart::Receive<'a> for Usart<'a> {
309312

310313
self.rx_buffer.map(|buf| {
311314
if let Some(ch) = self.dma_channel_rx.get() {
312-
dma.setup_usart1_rx(ch, buf.as_ptr() as u32, rx_len as u32);
315+
dma.setup(
316+
ch,
317+
DmaPeripheral::Usart1Rx,
318+
buf.as_ptr() as u32,
319+
rx_len as u32,
320+
);
313321
self.registers.cr3.modify(CR3::DMAR::SET);
314322
}
315323
});

0 commit comments

Comments
 (0)