aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/sai
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-12-18 23:49:37 +0100
committerDario Nieuwenhuis <[email protected]>2023-12-19 00:06:30 +0100
commit4deae51e656e46e18840bf30e68a976aaaf8ad20 (patch)
tree272a12b6568e5ec49d81c77497e7fc0854d6b620 /embassy-stm32/src/sai
parentc952ae0f49a21ade19758e4f6f1e2bec503e413e (diff)
stm32/sai: deduplicate code for subblocks A/B.
Diffstat (limited to 'embassy-stm32/src/sai')
-rw-r--r--embassy-stm32/src/sai/mod.rs331
1 files changed, 108 insertions, 223 deletions
diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs
index 96acd9e48..e03497529 100644
--- a/embassy-stm32/src/sai/mod.rs
+++ b/embassy-stm32/src/sai/mod.rs
@@ -1,7 +1,10 @@
1#![macro_use] 1#![macro_use]
2 2
3use core::marker::PhantomData;
4
3use embassy_hal_internal::{into_ref, PeripheralRef}; 5use embassy_hal_internal::{into_ref, PeripheralRef};
4 6
7use self::sealed::WhichSubBlock;
5pub use crate::dma::word; 8pub use crate::dma::word;
6use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, Request, TransferOptions, WritableRingBuffer}; 9use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, Request, TransferOptions, WritableRingBuffer};
7use crate::gpio::sealed::{AFType, Pin as _}; 10use crate::gpio::sealed::{AFType, Pin as _};
@@ -500,23 +503,10 @@ impl Default for Config {
500} 503}
501 504
502impl Config { 505impl Config {
503 pub fn new_i2s() -> Self { 506 /// Create a new config with all default values.
507 pub fn new() -> Self {
504 return Default::default(); 508 return Default::default();
505 } 509 }
506
507 pub fn new_msb_first() -> Self {
508 Self {
509 bit_order: BitOrder::MsbFirst,
510 frame_sync_offset: FrameSyncOffset::OnFirstBit,
511 ..Default::default()
512 }
513 }
514}
515
516#[derive(Copy, Clone)]
517enum WhichSubBlock {
518 A = 0,
519 B = 1,
520} 510}
521 511
522enum RingBuffer<'d, C: Channel, W: word::Word> { 512enum RingBuffer<'d, C: Channel, W: word::Word> {
@@ -530,28 +520,6 @@ fn dr<W: word::Word>(w: crate::pac::sai::Sai, sub_block: WhichSubBlock) -> *mut
530 ch.dr().as_ptr() as _ 520 ch.dr().as_ptr() as _
531} 521}
532 522
533pub struct SubBlock<'d, T: Instance, C: Channel, W: word::Word> {
534 _peri: PeripheralRef<'d, T>,
535 sd: Option<PeripheralRef<'d, AnyPin>>,
536 fs: Option<PeripheralRef<'d, AnyPin>>,
537 sck: Option<PeripheralRef<'d, AnyPin>>,
538 mclk: Option<PeripheralRef<'d, AnyPin>>,
539 ring_buffer: RingBuffer<'d, C, W>,
540 sub_block: WhichSubBlock,
541}
542
543pub struct SubBlockA {}
544pub struct SubBlockB {}
545
546pub struct SubBlockAPeripheral<'d, T>(PeripheralRef<'d, T>);
547pub struct SubBlockBPeripheral<'d, T>(PeripheralRef<'d, T>);
548
549pub struct Sai<'d, T: Instance> {
550 _peri: PeripheralRef<'d, T>,
551 sub_block_a_peri: Option<SubBlockAPeripheral<'d, T>>,
552 sub_block_b_peri: Option<SubBlockBPeripheral<'d, T>>,
553}
554
555// return the type for (sd, sck) 523// return the type for (sd, sck)
556fn get_af_types(mode: Mode, tx_rx: TxRx) -> (AFType, AFType) { 524fn get_af_types(mode: Mode, tx_rx: TxRx) -> (AFType, AFType) {
557 ( 525 (
@@ -590,34 +558,6 @@ fn get_ring_buffer<'d, T: Instance, C: Channel, W: word::Word>(
590 } 558 }
591} 559}
592 560
593impl<'d, T: Instance> Sai<'d, T> {
594 pub fn new(peri: impl Peripheral<P = T> + 'd) -> Self {
595 T::enable_and_reset();
596
597 Self {
598 _peri: unsafe { peri.clone_unchecked().into_ref() },
599 sub_block_a_peri: Some(SubBlockAPeripheral(unsafe { peri.clone_unchecked().into_ref() })),
600 sub_block_b_peri: Some(SubBlockBPeripheral(peri.into_ref())),
601 }
602 }
603
604 pub fn take_sub_block_a(self: &mut Self) -> Option<SubBlockAPeripheral<'d, T>> {
605 if self.sub_block_a_peri.is_some() {
606 self.sub_block_a_peri.take()
607 } else {
608 None
609 }
610 }
611
612 pub fn take_sub_block_b(self: &mut Self) -> Option<SubBlockBPeripheral<'d, T>> {
613 if self.sub_block_b_peri.is_some() {
614 self.sub_block_b_peri.take()
615 } else {
616 None
617 }
618 }
619}
620
621fn update_synchronous_config(config: &mut Config) { 561fn update_synchronous_config(config: &mut Config) {
622 config.mode = Mode::Slave; 562 config.mode = Mode::Slave;
623 config.sync_output = false; 563 config.sync_output = false;
@@ -635,122 +575,51 @@ fn update_synchronous_config(config: &mut Config) {
635 } 575 }
636} 576}
637 577
638impl SubBlockA { 578pub struct SubBlock<'d, T, S: SubBlockInstance> {
639 pub fn new_asynchronous_with_mclk<'d, T: Instance, C: Channel, W: word::Word>( 579 peri: PeripheralRef<'d, T>,
640 peri: SubBlockAPeripheral<'d, T>, 580 _phantom: PhantomData<S>,
641 sck: impl Peripheral<P = impl SckAPin<T>> + 'd, 581}
642 sd: impl Peripheral<P = impl SdAPin<T>> + 'd,
643 fs: impl Peripheral<P = impl FsAPin<T>> + 'd,
644 mclk: impl Peripheral<P = impl MclkAPin<T>> + 'd,
645 dma: impl Peripheral<P = C> + 'd,
646 dma_buf: &'d mut [W],
647 mut config: Config,
648 ) -> SubBlock<'d, T, C, W>
649 where
650 C: Channel + DmaA<T>,
651 {
652 into_ref!(mclk);
653
654 let (_sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx);
655
656 mclk.set_as_af(mclk.af_num(), ck_af_type);
657 mclk.set_speed(crate::gpio::Speed::VeryHigh);
658
659 if config.master_clock_divider == MasterClockDivider::MasterClockDisabled {
660 config.master_clock_divider = MasterClockDivider::Div1;
661 }
662
663 Self::new_asynchronous(peri, sck, sd, fs, dma, dma_buf, config)
664 }
665
666 pub fn new_asynchronous<'d, T: Instance, C: Channel, W: word::Word>(
667 peri: SubBlockAPeripheral<'d, T>,
668 sck: impl Peripheral<P = impl SckAPin<T>> + 'd,
669 sd: impl Peripheral<P = impl SdAPin<T>> + 'd,
670 fs: impl Peripheral<P = impl FsAPin<T>> + 'd,
671 dma: impl Peripheral<P = C> + 'd,
672 dma_buf: &'d mut [W],
673 config: Config,
674 ) -> SubBlock<'d, T, C, W>
675 where
676 C: Channel + DmaA<T>,
677 {
678 let peri = peri.0;
679 into_ref!(peri, dma, sck, sd, fs);
680
681 let (sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx);
682 sd.set_as_af(sd.af_num(), sd_af_type);
683 sd.set_speed(crate::gpio::Speed::VeryHigh);
684
685 sck.set_as_af(sck.af_num(), ck_af_type);
686 sck.set_speed(crate::gpio::Speed::VeryHigh);
687 fs.set_as_af(fs.af_num(), ck_af_type);
688 fs.set_speed(crate::gpio::Speed::VeryHigh);
689 582
690 let sub_block = WhichSubBlock::A; 583pub fn split_subblocks<'d, T: Instance>(peri: impl Peripheral<P = T> + 'd) -> (SubBlock<'d, T, A>, SubBlock<'d, T, B>) {
691 let request = dma.request(); 584 into_ref!(peri);
585 T::enable_and_reset();
692 586
693 SubBlock::new_inner( 587 (
588 SubBlock {
589 peri: unsafe { peri.clone_unchecked() },
590 _phantom: PhantomData,
591 },
592 SubBlock {
694 peri, 593 peri,
695 sub_block, 594 _phantom: PhantomData,
696 Some(sck.map_into()), 595 },
697 None, 596 )
698 Some(sd.map_into()), 597}
699 Some(fs.map_into()),
700 get_ring_buffer::<T, C, W>(dma, dma_buf, request, sub_block, config.tx_rx),
701 config,
702 )
703 }
704
705 pub fn new_synchronous<'d, T: Instance, C: Channel, W: word::Word>(
706 peri: SubBlockAPeripheral<'d, T>,
707 sd: impl Peripheral<P = impl SdAPin<T>> + 'd,
708 dma: impl Peripheral<P = C> + 'd,
709 dma_buf: &'d mut [W],
710 mut config: Config,
711 ) -> SubBlock<'d, T, C, W>
712 where
713 C: Channel + DmaA<T>,
714 {
715 update_synchronous_config(&mut config);
716
717 let peri = peri.0;
718 into_ref!(dma, peri, sd);
719
720 let (sd_af_type, _ck_af_type) = get_af_types(config.mode, config.tx_rx);
721
722 sd.set_as_af(sd.af_num(), sd_af_type);
723 sd.set_speed(crate::gpio::Speed::VeryHigh);
724
725 let sub_block = WhichSubBlock::A;
726 let request = dma.request();
727 598
728 SubBlock::new_inner( 599/// SAI sub-block driver
729 peri, 600pub struct Sai<'d, T: Instance, C: Channel, W: word::Word> {
730 sub_block, 601 _peri: PeripheralRef<'d, T>,
731 None, 602 sd: Option<PeripheralRef<'d, AnyPin>>,
732 None, 603 fs: Option<PeripheralRef<'d, AnyPin>>,
733 Some(sd.map_into()), 604 sck: Option<PeripheralRef<'d, AnyPin>>,
734 None, 605 mclk: Option<PeripheralRef<'d, AnyPin>>,
735 get_ring_buffer::<T, C, W>(dma, dma_buf, request, sub_block, config.tx_rx), 606 ring_buffer: RingBuffer<'d, C, W>,
736 config, 607 sub_block: WhichSubBlock,
737 )
738 }
739} 608}
740 609
741impl SubBlockB { 610impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
742 pub fn new_asynchronous_with_mclk<'d, T: Instance, C: Channel, W: word::Word>( 611 pub fn new_asynchronous_with_mclk<S: SubBlockInstance>(
743 peri: SubBlockBPeripheral<'d, T>, 612 peri: SubBlock<'d, T, S>,
744 sck: impl Peripheral<P = impl SckBPin<T>> + 'd, 613 sck: impl Peripheral<P = impl SckPin<T, S>> + 'd,
745 sd: impl Peripheral<P = impl SdBPin<T>> + 'd, 614 sd: impl Peripheral<P = impl SdPin<T, S>> + 'd,
746 fs: impl Peripheral<P = impl FsBPin<T>> + 'd, 615 fs: impl Peripheral<P = impl FsPin<T, S>> + 'd,
747 mclk: impl Peripheral<P = impl MclkBPin<T>> + 'd, 616 mclk: impl Peripheral<P = impl MclkPin<T, S>> + 'd,
748 dma: impl Peripheral<P = C> + 'd, 617 dma: impl Peripheral<P = C> + 'd,
749 dma_buf: &'d mut [W], 618 dma_buf: &'d mut [W],
750 mut config: Config, 619 mut config: Config,
751 ) -> SubBlock<'d, T, C, W> 620 ) -> Self
752 where 621 where
753 C: Channel + DmaB<T>, 622 C: Channel + Dma<T, S>,
754 { 623 {
755 into_ref!(mclk); 624 into_ref!(mclk);
756 625
@@ -766,23 +635,22 @@ impl SubBlockB {
766 Self::new_asynchronous(peri, sck, sd, fs, dma, dma_buf, config) 635 Self::new_asynchronous(peri, sck, sd, fs, dma, dma_buf, config)
767 } 636 }
768 637
769 pub fn new_asynchronous<'d, T: Instance, C: Channel, W: word::Word>( 638 pub fn new_asynchronous<S: SubBlockInstance>(
770 peri: SubBlockBPeripheral<'d, T>, 639 peri: SubBlock<'d, T, S>,
771 sck: impl Peripheral<P = impl SckBPin<T>> + 'd, 640 sck: impl Peripheral<P = impl SckPin<T, S>> + 'd,
772 sd: impl Peripheral<P = impl SdBPin<T>> + 'd, 641 sd: impl Peripheral<P = impl SdPin<T, S>> + 'd,
773 fs: impl Peripheral<P = impl FsBPin<T>> + 'd, 642 fs: impl Peripheral<P = impl FsPin<T, S>> + 'd,
774 dma: impl Peripheral<P = C> + 'd, 643 dma: impl Peripheral<P = C> + 'd,
775 dma_buf: &'d mut [W], 644 dma_buf: &'d mut [W],
776 config: Config, 645 config: Config,
777 ) -> SubBlock<'d, T, C, W> 646 ) -> Self
778 where 647 where
779 C: Channel + DmaB<T>, 648 C: Channel + Dma<T, S>,
780 { 649 {
781 let peri = peri.0; 650 let peri = peri.peri;
782 into_ref!(dma, peri, sck, sd, fs); 651 into_ref!(peri, dma, sck, sd, fs);
783 652
784 let (sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx); 653 let (sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx);
785
786 sd.set_as_af(sd.af_num(), sd_af_type); 654 sd.set_as_af(sd.af_num(), sd_af_type);
787 sd.set_speed(crate::gpio::Speed::VeryHigh); 655 sd.set_speed(crate::gpio::Speed::VeryHigh);
788 656
@@ -791,10 +659,10 @@ impl SubBlockB {
791 fs.set_as_af(fs.af_num(), ck_af_type); 659 fs.set_as_af(fs.af_num(), ck_af_type);
792 fs.set_speed(crate::gpio::Speed::VeryHigh); 660 fs.set_speed(crate::gpio::Speed::VeryHigh);
793 661
794 let sub_block = WhichSubBlock::B; 662 let sub_block = S::WHICH;
795 let request = dma.request(); 663 let request = dma.request();
796 664
797 SubBlock::new_inner( 665 Self::new_inner(
798 peri, 666 peri,
799 sub_block, 667 sub_block,
800 Some(sck.map_into()), 668 Some(sck.map_into()),
@@ -806,18 +674,19 @@ impl SubBlockB {
806 ) 674 )
807 } 675 }
808 676
809 pub fn new_synchronous<'d, T: Instance, C: Channel, W: word::Word>( 677 pub fn new_synchronous<S: SubBlockInstance>(
810 peri: SubBlockBPeripheral<'d, T>, 678 peri: SubBlock<'d, T, S>,
811 sd: impl Peripheral<P = impl SdBPin<T>> + 'd, 679 sd: impl Peripheral<P = impl SdPin<T, S>> + 'd,
812 dma: impl Peripheral<P = C> + 'd, 680 dma: impl Peripheral<P = C> + 'd,
813 dma_buf: &'d mut [W], 681 dma_buf: &'d mut [W],
814 mut config: Config, 682 mut config: Config,
815 ) -> SubBlock<'d, T, C, W> 683 ) -> Self
816 where 684 where
817 C: Channel + DmaB<T>, 685 C: Channel + Dma<T, S>,
818 { 686 {
819 update_synchronous_config(&mut config); 687 update_synchronous_config(&mut config);
820 let peri = peri.0; 688
689 let peri = peri.peri;
821 into_ref!(dma, peri, sd); 690 into_ref!(dma, peri, sd);
822 691
823 let (sd_af_type, _ck_af_type) = get_af_types(config.mode, config.tx_rx); 692 let (sd_af_type, _ck_af_type) = get_af_types(config.mode, config.tx_rx);
@@ -825,10 +694,10 @@ impl SubBlockB {
825 sd.set_as_af(sd.af_num(), sd_af_type); 694 sd.set_as_af(sd.af_num(), sd_af_type);
826 sd.set_speed(crate::gpio::Speed::VeryHigh); 695 sd.set_speed(crate::gpio::Speed::VeryHigh);
827 696
828 let sub_block = WhichSubBlock::B; 697 let sub_block = S::WHICH;
829 let request = dma.request(); 698 let request = dma.request();
830 699
831 SubBlock::new_inner( 700 Self::new_inner(
832 peri, 701 peri,
833 sub_block, 702 sub_block,
834 None, 703 None,
@@ -839,26 +708,6 @@ impl SubBlockB {
839 config, 708 config,
840 ) 709 )
841 } 710 }
842}
843
844impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> {
845 pub fn start(self: &mut Self) {
846 match self.ring_buffer {
847 RingBuffer::Writable(ref mut rb) => {
848 rb.start();
849 }
850 RingBuffer::Readable(ref mut rb) => {
851 rb.start();
852 }
853 }
854 }
855
856 fn is_transmitter(ring_buffer: &RingBuffer<C, W>) -> bool {
857 match ring_buffer {
858 RingBuffer::Writable(_) => true,
859 _ => false,
860 }
861 }
862 711
863 fn new_inner( 712 fn new_inner(
864 peri: impl Peripheral<P = T> + 'd, 713 peri: impl Peripheral<P = T> + 'd,
@@ -964,6 +813,24 @@ impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> {
964 } 813 }
965 } 814 }
966 815
816 pub fn start(&mut self) {
817 match self.ring_buffer {
818 RingBuffer::Writable(ref mut rb) => {
819 rb.start();
820 }
821 RingBuffer::Readable(ref mut rb) => {
822 rb.start();
823 }
824 }
825 }
826
827 fn is_transmitter(ring_buffer: &RingBuffer<C, W>) -> bool {
828 match ring_buffer {
829 RingBuffer::Writable(_) => true,
830 _ => false,
831 }
832 }
833
967 pub fn reset() { 834 pub fn reset() {
968 T::enable_and_reset(); 835 T::enable_and_reset();
969 } 836 }
@@ -1008,7 +875,7 @@ impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> {
1008 } 875 }
1009} 876}
1010 877
1011impl<'d, T: Instance, C: Channel, W: word::Word> Drop for SubBlock<'d, T, C, W> { 878impl<'d, T: Instance, C: Channel, W: word::Word> Drop for Sai<'d, T, C, W> {
1012 fn drop(&mut self) { 879 fn drop(&mut self) {
1013 let ch = T::REGS.ch(self.sub_block as usize); 880 let ch = T::REGS.ch(self.sub_block as usize);
1014 ch.cr1().modify(|w| w.set_saien(false)); 881 ch.cr1().modify(|w| w.set_saien(false));
@@ -1025,22 +892,40 @@ pub(crate) mod sealed {
1025 pub trait Instance { 892 pub trait Instance {
1026 const REGS: Regs; 893 const REGS: Regs;
1027 } 894 }
895
896 #[derive(Copy, Clone)]
897 pub enum WhichSubBlock {
898 A = 0,
899 B = 1,
900 }
901
902 pub trait SubBlock {
903 const WHICH: WhichSubBlock;
904 }
1028} 905}
1029 906
1030pub trait Word: word::Word {} 907pub trait Word: word::Word {}
1031 908
909pub trait SubBlockInstance: sealed::SubBlock {}
910
911pub enum A {}
912impl sealed::SubBlock for A {
913 const WHICH: WhichSubBlock = WhichSubBlock::A;
914}
915impl SubBlockInstance for A {}
916pub enum B {}
917impl sealed::SubBlock for B {
918 const WHICH: WhichSubBlock = WhichSubBlock::B;
919}
920impl SubBlockInstance for B {}
921
1032pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {} 922pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {}
1033pin_trait!(SckAPin, Instance); 923pin_trait!(SckPin, Instance, SubBlockInstance);
1034pin_trait!(SckBPin, Instance); 924pin_trait!(FsPin, Instance, SubBlockInstance);
1035pin_trait!(FsAPin, Instance); 925pin_trait!(SdPin, Instance, SubBlockInstance);
1036pin_trait!(FsBPin, Instance); 926pin_trait!(MclkPin, Instance, SubBlockInstance);
1037pin_trait!(SdAPin, Instance); 927
1038pin_trait!(SdBPin, Instance); 928dma_trait!(Dma, Instance, SubBlockInstance);
1039pin_trait!(MclkAPin, Instance);
1040pin_trait!(MclkBPin, Instance);
1041
1042dma_trait!(DmaA, Instance);
1043dma_trait!(DmaB, Instance);
1044 929
1045foreach_peripheral!( 930foreach_peripheral!(
1046 (sai, $inst:ident) => { 931 (sai, $inst:ident) => {