@@ -17,6 +17,11 @@ const USART1_RDR: u32 = USART1_BASE_ADDR + 0x24;
1717/// USART1 Transmit Data Register (TDR) address.
1818const 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+
2025register_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+
182215pub 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 }
0 commit comments