diff options
| author | Liu Hancheng <[email protected]> | 2025-01-04 20:16:34 +0800 |
|---|---|---|
| committer | Liu Hancheng <[email protected]> | 2025-01-04 20:16:34 +0800 |
| commit | ff526e1604f4e9edc682f4bc270ddc815a860e48 (patch) | |
| tree | cc6c4e901d9c187d72dee59167a7189fed56ed65 | |
| parent | 90b41644261440a535c35c1c75c22ce2606c5037 (diff) | |
refactor: update DMA transfer functions to use separate memory and peripheral sizes
| -rw-r--r-- | embassy-stm32/src/dma/dma_bdma.rs | 38 | ||||
| -rw-r--r-- | embassy-stm32/src/timer/simple_pwm.rs | 26 |
2 files changed, 35 insertions, 29 deletions
diff --git a/embassy-stm32/src/dma/dma_bdma.rs b/embassy-stm32/src/dma/dma_bdma.rs index 1945c3587..8b4b454c0 100644 --- a/embassy-stm32/src/dma/dma_bdma.rs +++ b/embassy-stm32/src/dma/dma_bdma.rs | |||
| @@ -340,7 +340,8 @@ impl AnyChannel { | |||
| 340 | mem_addr: *mut u32, | 340 | mem_addr: *mut u32, |
| 341 | mem_len: usize, | 341 | mem_len: usize, |
| 342 | incr_mem: bool, | 342 | incr_mem: bool, |
| 343 | data_size: WordSize, | 343 | mem_size: WordSize, |
| 344 | peripheral_size: WordSize, | ||
| 344 | options: TransferOptions, | 345 | options: TransferOptions, |
| 345 | ) { | 346 | ) { |
| 346 | let info = self.info(); | 347 | let info = self.info(); |
| @@ -380,8 +381,8 @@ impl AnyChannel { | |||
| 380 | }); | 381 | }); |
| 381 | ch.cr().write(|w| { | 382 | ch.cr().write(|w| { |
| 382 | w.set_dir(dir.into()); | 383 | w.set_dir(dir.into()); |
| 383 | w.set_msize(data_size.into()); | 384 | w.set_msize(mem_size.into()); |
| 384 | w.set_psize(data_size.into()); | 385 | w.set_psize(peripheral_size.into()); |
| 385 | w.set_pl(options.priority.into()); | 386 | w.set_pl(options.priority.into()); |
| 386 | w.set_minc(incr_mem); | 387 | w.set_minc(incr_mem); |
| 387 | w.set_pinc(false); | 388 | w.set_pinc(false); |
| @@ -414,8 +415,8 @@ impl AnyChannel { | |||
| 414 | ch.mar().write_value(mem_addr as u32); | 415 | ch.mar().write_value(mem_addr as u32); |
| 415 | ch.ndtr().write(|w| w.set_ndt(mem_len as u16)); | 416 | ch.ndtr().write(|w| w.set_ndt(mem_len as u16)); |
| 416 | ch.cr().write(|w| { | 417 | ch.cr().write(|w| { |
| 417 | w.set_psize(data_size.into()); | 418 | w.set_psize(peripheral_size.into()); |
| 418 | w.set_msize(data_size.into()); | 419 | w.set_msize(mem_size.into()); |
| 419 | w.set_minc(incr_mem); | 420 | w.set_minc(incr_mem); |
| 420 | w.set_dir(dir.into()); | 421 | w.set_dir(dir.into()); |
| 421 | w.set_teie(true); | 422 | w.set_teie(true); |
| @@ -602,27 +603,28 @@ impl<'a> Transfer<'a> { | |||
| 602 | buf.len(), | 603 | buf.len(), |
| 603 | true, | 604 | true, |
| 604 | W::size(), | 605 | W::size(), |
| 606 | W::size(), | ||
| 605 | options, | 607 | options, |
| 606 | ) | 608 | ) |
| 607 | } | 609 | } |
| 608 | 610 | ||
| 609 | /// Create a new write DMA transfer (memory to peripheral). | 611 | /// Create a new write DMA transfer (memory to peripheral). |
| 610 | pub unsafe fn new_write<W: Word>( | 612 | pub unsafe fn new_write<MW: Word, PW: Word>( |
| 611 | channel: impl Peripheral<P = impl Channel> + 'a, | 613 | channel: impl Peripheral<P = impl Channel> + 'a, |
| 612 | request: Request, | 614 | request: Request, |
| 613 | buf: &'a [W], | 615 | buf: &'a [MW], |
| 614 | peri_addr: *mut W, | 616 | peri_addr: *mut PW, |
| 615 | options: TransferOptions, | 617 | options: TransferOptions, |
| 616 | ) -> Self { | 618 | ) -> Self { |
| 617 | Self::new_write_raw(channel, request, buf, peri_addr, options) | 619 | Self::new_write_raw(channel, request, buf, peri_addr, options) |
| 618 | } | 620 | } |
| 619 | 621 | ||
| 620 | /// Create a new write DMA transfer (memory to peripheral), using raw pointers. | 622 | /// Create a new write DMA transfer (memory to peripheral), using raw pointers. |
| 621 | pub unsafe fn new_write_raw<W: Word>( | 623 | pub unsafe fn new_write_raw<W: Word, PW: Word>( |
| 622 | channel: impl Peripheral<P = impl Channel> + 'a, | 624 | channel: impl Peripheral<P = impl Channel> + 'a, |
| 623 | request: Request, | 625 | request: Request, |
| 624 | buf: *const [W], | 626 | buf: *const [W], |
| 625 | peri_addr: *mut W, | 627 | peri_addr: *mut PW, |
| 626 | options: TransferOptions, | 628 | options: TransferOptions, |
| 627 | ) -> Self { | 629 | ) -> Self { |
| 628 | into_ref!(channel); | 630 | into_ref!(channel); |
| @@ -636,6 +638,7 @@ impl<'a> Transfer<'a> { | |||
| 636 | buf.len(), | 638 | buf.len(), |
| 637 | true, | 639 | true, |
| 638 | W::size(), | 640 | W::size(), |
| 641 | W::size(), | ||
| 639 | options, | 642 | options, |
| 640 | ) | 643 | ) |
| 641 | } | 644 | } |
| @@ -660,6 +663,7 @@ impl<'a> Transfer<'a> { | |||
| 660 | count, | 663 | count, |
| 661 | false, | 664 | false, |
| 662 | W::size(), | 665 | W::size(), |
| 666 | W::size(), | ||
| 663 | options, | 667 | options, |
| 664 | ) | 668 | ) |
| 665 | } | 669 | } |
| @@ -673,15 +677,23 @@ impl<'a> Transfer<'a> { | |||
| 673 | mem_len: usize, | 677 | mem_len: usize, |
| 674 | incr_mem: bool, | 678 | incr_mem: bool, |
| 675 | data_size: WordSize, | 679 | data_size: WordSize, |
| 680 | peripheral_size: WordSize, | ||
| 676 | options: TransferOptions, | 681 | options: TransferOptions, |
| 677 | ) -> Self { | 682 | ) -> Self { |
| 678 | assert!(mem_len > 0 && mem_len <= 0xFFFF); | 683 | assert!(mem_len > 0 && mem_len <= 0xFFFF); |
| 679 | 684 | ||
| 680 | channel.configure( | 685 | channel.configure( |
| 681 | _request, dir, peri_addr, mem_addr, mem_len, incr_mem, data_size, options, | 686 | _request, |
| 687 | dir, | ||
| 688 | peri_addr, | ||
| 689 | mem_addr, | ||
| 690 | mem_len, | ||
| 691 | incr_mem, | ||
| 692 | data_size, | ||
| 693 | peripheral_size, | ||
| 694 | options, | ||
| 682 | ); | 695 | ); |
| 683 | channel.start(); | 696 | channel.start(); |
| 684 | |||
| 685 | Self { channel } | 697 | Self { channel } |
| 686 | } | 698 | } |
| 687 | 699 | ||
| @@ -814,6 +826,7 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { | |||
| 814 | len, | 826 | len, |
| 815 | true, | 827 | true, |
| 816 | data_size, | 828 | data_size, |
| 829 | data_size, | ||
| 817 | options, | 830 | options, |
| 818 | ); | 831 | ); |
| 819 | 832 | ||
| @@ -966,6 +979,7 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { | |||
| 966 | len, | 979 | len, |
| 967 | true, | 980 | true, |
| 968 | data_size, | 981 | data_size, |
| 982 | data_size, | ||
| 969 | options, | 983 | options, |
| 970 | ); | 984 | ); |
| 971 | 985 | ||
diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs index f36fa026c..8d3c9a131 100644 --- a/embassy-stm32/src/timer/simple_pwm.rs +++ b/embassy-stm32/src/timer/simple_pwm.rs | |||
| @@ -334,7 +334,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { | |||
| 334 | &mut dma, | 334 | &mut dma, |
| 335 | req, | 335 | req, |
| 336 | duty, | 336 | duty, |
| 337 | self.inner.regs_1ch().ccr(channel.index()).as_ptr() as *mut _, | 337 | self.inner.regs_1ch().ccr(channel.index()).as_ptr() as *mut u16, |
| 338 | dma_transfer_option, | 338 | dma_transfer_option, |
| 339 | ) | 339 | ) |
| 340 | .await | 340 | .await |
| @@ -362,13 +362,7 @@ macro_rules! impl_waveform_chx { | |||
| 362 | ($fn_name:ident, $dma_ch:ident, $cc_ch:ident) => { | 362 | ($fn_name:ident, $dma_ch:ident, $cc_ch:ident) => { |
| 363 | impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { | 363 | impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { |
| 364 | /// Generate a sequence of PWM waveform | 364 | /// Generate a sequence of PWM waveform |
| 365 | /// | 365 | pub async fn $fn_name(&mut self, dma: impl Peripheral<P = impl super::$dma_ch<T>>, duty: &[u16]) { |
| 366 | /// Note: | ||
| 367 | /// 1. you will need to provide corresponding TIMx_CHy DMA channel to use this method. | ||
| 368 | /// 2. Please make sure the duty data length is aligned to the timer data width(16-bit or 32-bit). | ||
| 369 | /// 3. Please notice the endianess of the duty data. STM32 use little endian, | ||
| 370 | /// for example, 0x12345678 as u32 will be stored as [0x78, 0x56, 0x34, 0x12] in memory. | ||
| 371 | pub async fn $fn_name(&mut self, dma: impl Peripheral<P = impl super::$dma_ch<T>>, duty: &[u8]) { | ||
| 372 | use crate::pac::timer::vals::Ccds; | 366 | use crate::pac::timer::vals::Ccds; |
| 373 | 367 | ||
| 374 | into_ref!(dma); | 368 | into_ref!(dma); |
| @@ -411,32 +405,30 @@ macro_rules! impl_waveform_chx { | |||
| 411 | 405 | ||
| 412 | match self.inner.bits() { | 406 | match self.inner.bits() { |
| 413 | TimerBits::Bits16 => { | 407 | TimerBits::Bits16 => { |
| 414 | // the data must be aligned to double words | ||
| 415 | assert!(duty.len() % 2 == 0); | ||
| 416 | let duty = core::slice::from_raw_parts(duty.as_ptr() as *const u16, duty.len() / 2); | ||
| 417 | Transfer::new_write( | 408 | Transfer::new_write( |
| 418 | &mut dma, | 409 | &mut dma, |
| 419 | req, | 410 | req, |
| 420 | duty, | 411 | duty, |
| 421 | self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut _, | 412 | self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u16, |
| 422 | dma_transfer_option, | 413 | dma_transfer_option, |
| 423 | ) | 414 | ) |
| 424 | .await | 415 | .await |
| 425 | } | 416 | } |
| 426 | #[cfg(not(stm32l0))] | 417 | #[cfg(not(any(stm32l0, bdma, gpdma)))] |
| 427 | TimerBits::Bits32 => { | 418 | TimerBits::Bits32 => { |
| 428 | // the data must be aligned to quad words | ||
| 429 | assert!(duty.len() % 4 == 0); | ||
| 430 | let duty = core::slice::from_raw_parts(duty.as_ptr() as *const u32, duty.len() / 4); | ||
| 431 | Transfer::new_write( | 419 | Transfer::new_write( |
| 432 | &mut dma, | 420 | &mut dma, |
| 433 | req, | 421 | req, |
| 434 | duty, | 422 | duty, |
| 435 | self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut _, | 423 | self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u32, |
| 436 | dma_transfer_option, | 424 | dma_transfer_option, |
| 437 | ) | 425 | ) |
| 438 | .await | 426 | .await |
| 439 | } | 427 | } |
| 428 | #[cfg(any(stm32l0, bdma, gpdma))] | ||
| 429 | _ => { | ||
| 430 | panic!("unsupported timer bits") | ||
| 431 | } | ||
| 440 | }; | 432 | }; |
| 441 | }; | 433 | }; |
| 442 | 434 | ||
