aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2023-10-01 14:06:25 +0000
committerGitHub <[email protected]>2023-10-01 14:06:25 +0000
commita7b1e516504bb0df9f7af42361e4280adcc30417 (patch)
tree9de0fe6c05a6641a46f709e1877f9916f94d0544
parent70005c3956dc985402824ad566eeb68546cb7f98 (diff)
parent0d49aaf8ca5970738f7d16962d5d6002e1bdece6 (diff)
Merge pull request #1987 from tyler-gilbert/issue-1986-add-sai-receiver-driver
Issue 1986 add sai receiver driver
-rw-r--r--embassy-stm32/src/sai/mod.rs288
1 files changed, 228 insertions, 60 deletions
diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs
index 4ffa6e9ce..2741b790b 100644
--- a/embassy-stm32/src/sai/mod.rs
+++ b/embassy-stm32/src/sai/mod.rs
@@ -4,7 +4,7 @@ use embassy_embedded_hal::SetConfig;
4use embassy_hal_internal::{into_ref, PeripheralRef}; 4use embassy_hal_internal::{into_ref, PeripheralRef};
5 5
6pub use crate::dma::word; 6pub use crate::dma::word;
7use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, TransferOptions, WritableRingBuffer}; 7use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, Request, TransferOptions, WritableRingBuffer};
8use crate::gpio::sealed::{AFType, Pin as _}; 8use crate::gpio::sealed::{AFType, Pin as _};
9use crate::gpio::AnyPin; 9use crate::gpio::AnyPin;
10use crate::pac::sai::{vals, Sai as Regs}; 10use crate::pac::sai::{vals, Sai as Regs};
@@ -48,8 +48,8 @@ pub enum Mode {
48} 48}
49 49
50#[derive(Copy, Clone)] 50#[derive(Copy, Clone)]
51enum TxRx { 51pub enum TxRx {
52 Transmiter, 52 Transmitter,
53 Receiver, 53 Receiver,
54} 54}
55 55
@@ -57,7 +57,7 @@ impl Mode {
57 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 57 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
58 const fn mode(&self, tx_rx: TxRx) -> vals::Mode { 58 const fn mode(&self, tx_rx: TxRx) -> vals::Mode {
59 match tx_rx { 59 match tx_rx {
60 TxRx::Transmiter => match self { 60 TxRx::Transmitter => match self {
61 Mode::Master => vals::Mode::MASTERTX, 61 Mode::Master => vals::Mode::MASTERTX,
62 Mode::Slave => vals::Mode::SLAVETX, 62 Mode::Slave => vals::Mode::SLAVETX,
63 }, 63 },
@@ -206,12 +206,13 @@ impl Protocol {
206 } 206 }
207} 207}
208 208
209#[derive(Copy, Clone)] 209#[derive(Copy, Clone, PartialEq)]
210pub enum SyncEnable { 210pub enum SyncEnable {
211 Asynchronous, 211 Asynchronous,
212 /// Syncs with the other A/B sub-block within the SAI unit 212 /// Syncs with the other A/B sub-block within the SAI unit
213 Internal, 213 Internal,
214 /// Syncs with a sub-block in the other SAI unit - use set_sync_output() and set_sync_input() 214 /// Syncs with a sub-block in the other SAI unit - use set_sync_output() and set_sync_input()
215 #[cfg(any(sai_v4))]
215 External, 216 External,
216} 217}
217 218
@@ -221,6 +222,7 @@ impl SyncEnable {
221 match self { 222 match self {
222 SyncEnable::Asynchronous => vals::Syncen::ASYNCHRONOUS, 223 SyncEnable::Asynchronous => vals::Syncen::ASYNCHRONOUS,
223 SyncEnable::Internal => vals::Syncen::INTERNAL, 224 SyncEnable::Internal => vals::Syncen::INTERNAL,
225 #[cfg(any(sai_v4))]
224 SyncEnable::External => vals::Syncen::EXTERNAL, 226 SyncEnable::External => vals::Syncen::EXTERNAL,
225 } 227 }
226 } 228 }
@@ -425,6 +427,7 @@ impl MasterClockDivider {
425#[derive(Copy, Clone)] 427#[derive(Copy, Clone)]
426pub struct Config { 428pub struct Config {
427 pub mode: Mode, 429 pub mode: Mode,
430 pub tx_rx: TxRx,
428 pub sync_enable: SyncEnable, 431 pub sync_enable: SyncEnable,
429 pub is_sync_output: bool, 432 pub is_sync_output: bool,
430 pub protocol: Protocol, 433 pub protocol: Protocol,
@@ -455,6 +458,7 @@ impl Default for Config {
455 fn default() -> Self { 458 fn default() -> Self {
456 Self { 459 Self {
457 mode: Mode::Master, 460 mode: Mode::Master,
461 tx_rx: TxRx::Transmitter,
458 is_sync_output: false, 462 is_sync_output: false,
459 sync_enable: SyncEnable::Asynchronous, 463 sync_enable: SyncEnable::Asynchronous,
460 protocol: Protocol::Free, 464 protocol: Protocol::Free,
@@ -498,42 +502,127 @@ impl Config {
498} 502}
499 503
500#[derive(Copy, Clone)] 504#[derive(Copy, Clone)]
501pub enum SubBlock { 505enum WhichSubBlock {
502 A = 0, 506 A = 0,
503 B = 1, 507 B = 1,
504} 508}
505 509
506enum RingBuffer<'d, C: Channel, W: word::Word> { 510enum RingBuffer<'d, C: Channel, W: word::Word> {
507 Writable(WritableRingBuffer<'d, C, W>), 511 Writable(WritableRingBuffer<'d, C, W>),
508 #[allow(dead_code)] // remove this after implementing new_* functions for receiver
509 Readable(ReadableRingBuffer<'d, C, W>), 512 Readable(ReadableRingBuffer<'d, C, W>),
510} 513}
511 514
512#[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 515#[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
513fn wdr<W: word::Word>(w: crate::pac::sai::Sai, sub_block: SubBlock) -> *mut W { 516fn dr<W: word::Word>(w: crate::pac::sai::Sai, sub_block: WhichSubBlock) -> *mut W {
514 let ch = w.ch(sub_block as usize); 517 let ch = w.ch(sub_block as usize);
515 ch.dr().as_ptr() as _ 518 ch.dr().as_ptr() as _
516} 519}
517 520
518pub struct Sai<'d, T: Instance, C: Channel, W: word::Word> { 521pub struct SubBlock<'d, T: Instance, C: Channel, W: word::Word> {
519 _peri: PeripheralRef<'d, T>, 522 _peri: PeripheralRef<'d, T>,
520 sd: Option<PeripheralRef<'d, AnyPin>>, 523 sd: Option<PeripheralRef<'d, AnyPin>>,
521 fs: Option<PeripheralRef<'d, AnyPin>>, 524 fs: Option<PeripheralRef<'d, AnyPin>>,
522 sck: Option<PeripheralRef<'d, AnyPin>>, 525 sck: Option<PeripheralRef<'d, AnyPin>>,
523 mclk: Option<PeripheralRef<'d, AnyPin>>, 526 mclk: Option<PeripheralRef<'d, AnyPin>>,
524 ring_buffer: RingBuffer<'d, C, W>, 527 ring_buffer: RingBuffer<'d, C, W>,
525 sub_block: SubBlock, 528 sub_block: WhichSubBlock,
526} 529}
527 530
528impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { 531pub struct SubBlockA {}
529 fn get_transmitter_af_types(mode: Mode) -> (AFType, AFType) { 532pub struct SubBlockB {}
533
534pub struct Sai<'d, T: Instance> {
535 _peri: PeripheralRef<'d, T>,
536 sub_block_a_peri: Option<PeripheralRef<'d, T>>,
537 sub_block_b_peri: Option<PeripheralRef<'d, T>>,
538}
539
540// return the type for (sd, sck)
541fn get_af_types(mode: Mode, tx_rx: TxRx) -> (AFType, AFType) {
542 (
543 //sd is defined by tx/rx mode
544 match tx_rx {
545 TxRx::Transmitter => AFType::OutputPushPull,
546 TxRx::Receiver => AFType::Input,
547 },
548 //clocks (mclk, sck and fs) are defined by master/slave
530 match mode { 549 match mode {
531 Mode::Master => (AFType::OutputPushPull, AFType::OutputPushPull), 550 Mode::Master => AFType::OutputPushPull,
532 Mode::Slave => (AFType::OutputPushPull, AFType::Input), 551 Mode::Slave => AFType::Input,
552 },
553 )
554}
555
556fn get_ring_buffer<'d, T: Instance, C: Channel, W: word::Word>(
557 dma: impl Peripheral<P = C> + 'd,
558 dma_buf: &'d mut [W],
559 request: Request,
560 sub_block: WhichSubBlock,
561 tx_rx: TxRx,
562) -> RingBuffer<'d, C, W> {
563 let opts = TransferOptions {
564 half_transfer_ir: true,
565 //the new_write() and new_read() always use circular mode
566 ..Default::default()
567 };
568 match tx_rx {
569 TxRx::Transmitter => RingBuffer::Writable(unsafe {
570 WritableRingBuffer::new_write(dma, request, dr(T::REGS, sub_block), dma_buf, opts)
571 }),
572 TxRx::Receiver => RingBuffer::Readable(unsafe {
573 ReadableRingBuffer::new_read(dma, request, dr(T::REGS, sub_block), dma_buf, opts)
574 }),
575 }
576}
577
578impl<'d, T: Instance> Sai<'d, T> {
579 pub fn new(peri: impl Peripheral<P = T> + 'd) -> Self {
580 T::enable();
581 T::reset();
582
583 Self {
584 _peri: unsafe { peri.clone_unchecked().into_ref() },
585 sub_block_a_peri: Some(unsafe { peri.clone_unchecked().into_ref() }),
586 sub_block_b_peri: Some(peri.into_ref()),
533 } 587 }
534 } 588 }
535 589
536 pub fn new_asynchronous_transmitter_with_mclk_a( 590 pub fn take_sub_block_a(self: &mut Self) -> Option<PeripheralRef<'d, T>> {
591 if self.sub_block_a_peri.is_some() {
592 self.sub_block_a_peri.take()
593 } else {
594 None
595 }
596 }
597
598 pub fn take_sub_block_b(self: &mut Self) -> Option<PeripheralRef<'d, T>> {
599 if self.sub_block_b_peri.is_some() {
600 self.sub_block_b_peri.take()
601 } else {
602 None
603 }
604 }
605}
606
607fn update_synchronous_config(config: &mut Config) {
608 config.mode = Mode::Slave;
609 config.is_sync_output = false;
610
611 #[cfg(any(sai_v1, sai_v2, sai_v3))]
612 {
613 config.sync_enable = SyncEnable::Internal;
614 }
615
616 #[cfg(any(sai_v4))]
617 {
618 //this must either be Internal or External
619 //The asynchronous sub-block on the same SAI needs to enable is_sync_output
620 assert!(config.sync_enable != SyncEnable::Asynchronous);
621 }
622}
623
624impl SubBlockA {
625 pub fn new_asynchronous_with_mclk<'d, T: Instance, C: Channel, W: word::Word>(
537 peri: impl Peripheral<P = T> + 'd, 626 peri: impl Peripheral<P = T> + 'd,
538 sck: impl Peripheral<P = impl SckAPin<T>> + 'd, 627 sck: impl Peripheral<P = impl SckAPin<T>> + 'd,
539 sd: impl Peripheral<P = impl SdAPin<T>> + 'd, 628 sd: impl Peripheral<P = impl SdAPin<T>> + 'd,
@@ -542,23 +631,25 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
542 dma: impl Peripheral<P = C> + 'd, 631 dma: impl Peripheral<P = C> + 'd,
543 dma_buf: &'d mut [W], 632 dma_buf: &'d mut [W],
544 mut config: Config, 633 mut config: Config,
545 ) -> Self 634 ) -> SubBlock<T, C, W>
546 where 635 where
547 C: Channel + DmaA<T>, 636 C: Channel + DmaA<T>,
548 { 637 {
549 into_ref!(mclk); 638 into_ref!(mclk);
550 639
551 mclk.set_as_af(mclk.af_num(), AFType::OutputPushPull); 640 let (_sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx);
641
642 mclk.set_as_af(mclk.af_num(), ck_af_type);
552 mclk.set_speed(crate::gpio::Speed::VeryHigh); 643 mclk.set_speed(crate::gpio::Speed::VeryHigh);
553 644
554 if config.master_clock_divider == MasterClockDivider::MasterClockDisabled { 645 if config.master_clock_divider == MasterClockDivider::MasterClockDisabled {
555 config.master_clock_divider = MasterClockDivider::Div1; 646 config.master_clock_divider = MasterClockDivider::Div1;
556 } 647 }
557 648
558 Self::new_asynchronous_transmitter_a(peri, sck, sd, fs, dma, dma_buf, config) 649 Self::new_asynchronous(peri, sck, sd, fs, dma, dma_buf, config)
559 } 650 }
560 651
561 pub fn new_asynchronous_transmitter_a( 652 pub fn new_asynchronous<'d, T: Instance, C: Channel, W: word::Word>(
562 peri: impl Peripheral<P = T> + 'd, 653 peri: impl Peripheral<P = T> + 'd,
563 sck: impl Peripheral<P = impl SckAPin<T>> + 'd, 654 sck: impl Peripheral<P = impl SckAPin<T>> + 'd,
564 sd: impl Peripheral<P = impl SdAPin<T>> + 'd, 655 sd: impl Peripheral<P = impl SdAPin<T>> + 'd,
@@ -566,13 +657,13 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
566 dma: impl Peripheral<P = C> + 'd, 657 dma: impl Peripheral<P = C> + 'd,
567 dma_buf: &'d mut [W], 658 dma_buf: &'d mut [W],
568 config: Config, 659 config: Config,
569 ) -> Self 660 ) -> SubBlock<T, C, W>
570 where 661 where
571 C: Channel + DmaA<T>, 662 C: Channel + DmaA<T>,
572 { 663 {
573 into_ref!(peri, dma, sck, sd, fs); 664 into_ref!(peri, dma, sck, sd, fs);
574 665
575 let (sd_af_type, ck_af_type) = Self::get_transmitter_af_types(config.mode); 666 let (sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx);
576 sd.set_as_af(sd.af_num(), sd_af_type); 667 sd.set_as_af(sd.af_num(), sd_af_type);
577 sd.set_speed(crate::gpio::Speed::VeryHigh); 668 sd.set_speed(crate::gpio::Speed::VeryHigh);
578 669
@@ -581,30 +672,58 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
581 fs.set_as_af(fs.af_num(), ck_af_type); 672 fs.set_as_af(fs.af_num(), ck_af_type);
582 fs.set_speed(crate::gpio::Speed::VeryHigh); 673 fs.set_speed(crate::gpio::Speed::VeryHigh);
583 674
675 let sub_block = WhichSubBlock::A;
584 let request = dma.request(); 676 let request = dma.request();
585 let opts = TransferOptions {
586 half_transfer_ir: true,
587 circular: true,
588 ..Default::default()
589 };
590 677
591 let sub_block = SubBlock::A; 678 SubBlock::new_inner(
592
593 Self::new_inner(
594 peri, 679 peri,
595 sub_block, 680 sub_block,
596 Some(sck.map_into()), 681 Some(sck.map_into()),
597 None, 682 None,
598 Some(sd.map_into()), 683 Some(sd.map_into()),
599 Some(fs.map_into()), 684 Some(fs.map_into()),
600 RingBuffer::Writable(unsafe { 685 get_ring_buffer::<T, C, W>(dma, dma_buf, request, sub_block, config.tx_rx),
601 WritableRingBuffer::new_write(dma, request, wdr(T::REGS, sub_block), dma_buf, opts)
602 }),
603 config, 686 config,
604 ) 687 )
605 } 688 }
606 689
607 pub fn new_asynchronous_transmitter_with_mclk_b( 690 pub fn new_synchronous<'d, T: Instance, C: Channel, W: word::Word>(
691 peri: impl Peripheral<P = T> + 'd,
692 sd: impl Peripheral<P = impl SdAPin<T>> + 'd,
693 dma: impl Peripheral<P = C> + 'd,
694 dma_buf: &'d mut [W],
695 mut config: Config,
696 ) -> SubBlock<T, C, W>
697 where
698 C: Channel + DmaA<T>,
699 {
700 update_synchronous_config(&mut config);
701
702 into_ref!(dma, peri, sd);
703
704 let (sd_af_type, _ck_af_type) = get_af_types(config.mode, config.tx_rx);
705
706 sd.set_as_af(sd.af_num(), sd_af_type);
707 sd.set_speed(crate::gpio::Speed::VeryHigh);
708
709 let sub_block = WhichSubBlock::A;
710 let request = dma.request();
711
712 SubBlock::new_inner(
713 peri,
714 sub_block,
715 None,
716 None,
717 Some(sd.map_into()),
718 None,
719 get_ring_buffer::<T, C, W>(dma, dma_buf, request, sub_block, config.tx_rx),
720 config,
721 )
722 }
723}
724
725impl SubBlockB {
726 pub fn new_asynchronous_with_mclk<'d, T: Instance, C: Channel, W: word::Word>(
608 peri: impl Peripheral<P = T> + 'd, 727 peri: impl Peripheral<P = T> + 'd,
609 sck: impl Peripheral<P = impl SckBPin<T>> + 'd, 728 sck: impl Peripheral<P = impl SckBPin<T>> + 'd,
610 sd: impl Peripheral<P = impl SdBPin<T>> + 'd, 729 sd: impl Peripheral<P = impl SdBPin<T>> + 'd,
@@ -613,23 +732,25 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
613 dma: impl Peripheral<P = C> + 'd, 732 dma: impl Peripheral<P = C> + 'd,
614 dma_buf: &'d mut [W], 733 dma_buf: &'d mut [W],
615 mut config: Config, 734 mut config: Config,
616 ) -> Self 735 ) -> SubBlock<T, C, W>
617 where 736 where
618 C: Channel + DmaB<T>, 737 C: Channel + DmaB<T>,
619 { 738 {
620 into_ref!(mclk); 739 into_ref!(mclk);
621 740
622 mclk.set_as_af(mclk.af_num(), AFType::OutputPushPull); 741 let (_sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx);
742
743 mclk.set_as_af(mclk.af_num(), ck_af_type);
623 mclk.set_speed(crate::gpio::Speed::VeryHigh); 744 mclk.set_speed(crate::gpio::Speed::VeryHigh);
624 745
625 if config.master_clock_divider == MasterClockDivider::MasterClockDisabled { 746 if config.master_clock_divider == MasterClockDivider::MasterClockDisabled {
626 config.master_clock_divider = MasterClockDivider::Div1; 747 config.master_clock_divider = MasterClockDivider::Div1;
627 } 748 }
628 749
629 Self::new_asynchronous_transmitter_b(peri, sck, sd, fs, dma, dma_buf, config) 750 Self::new_asynchronous(peri, sck, sd, fs, dma, dma_buf, config)
630 } 751 }
631 752
632 pub fn new_asynchronous_transmitter_b( 753 pub fn new_asynchronous<'d, T: Instance, C: Channel, W: word::Word>(
633 peri: impl Peripheral<P = T> + 'd, 754 peri: impl Peripheral<P = T> + 'd,
634 sck: impl Peripheral<P = impl SckBPin<T>> + 'd, 755 sck: impl Peripheral<P = impl SckBPin<T>> + 'd,
635 sd: impl Peripheral<P = impl SdBPin<T>> + 'd, 756 sd: impl Peripheral<P = impl SdBPin<T>> + 'd,
@@ -637,13 +758,13 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
637 dma: impl Peripheral<P = C> + 'd, 758 dma: impl Peripheral<P = C> + 'd,
638 dma_buf: &'d mut [W], 759 dma_buf: &'d mut [W],
639 config: Config, 760 config: Config,
640 ) -> Self 761 ) -> SubBlock<T, C, W>
641 where 762 where
642 C: Channel + DmaB<T>, 763 C: Channel + DmaB<T>,
643 { 764 {
644 into_ref!(dma, peri, sck, sd, fs); 765 into_ref!(dma, peri, sck, sd, fs);
645 766
646 let (sd_af_type, ck_af_type) = Self::get_transmitter_af_types(config.mode); 767 let (sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx);
647 768
648 sd.set_as_af(sd.af_num(), sd_af_type); 769 sd.set_as_af(sd.af_num(), sd_af_type);
649 sd.set_speed(crate::gpio::Speed::VeryHigh); 770 sd.set_speed(crate::gpio::Speed::VeryHigh);
@@ -653,28 +774,57 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
653 fs.set_as_af(fs.af_num(), ck_af_type); 774 fs.set_as_af(fs.af_num(), ck_af_type);
654 fs.set_speed(crate::gpio::Speed::VeryHigh); 775 fs.set_speed(crate::gpio::Speed::VeryHigh);
655 776
777 let sub_block = WhichSubBlock::B;
656 let request = dma.request(); 778 let request = dma.request();
657 let opts = TransferOptions {
658 half_transfer_ir: true,
659 ..Default::default()
660 };
661
662 let sub_block = SubBlock::B;
663 779
664 Self::new_inner( 780 SubBlock::new_inner(
665 peri, 781 peri,
666 sub_block, 782 sub_block,
667 Some(sck.map_into()), 783 Some(sck.map_into()),
668 None, 784 None,
669 Some(sd.map_into()), 785 Some(sd.map_into()),
670 Some(fs.map_into()), 786 Some(fs.map_into()),
671 RingBuffer::Writable(unsafe { 787 get_ring_buffer::<T, C, W>(dma, dma_buf, request, sub_block, config.tx_rx),
672 WritableRingBuffer::new_write(dma, request, wdr(T::REGS, sub_block), dma_buf, opts) 788 config,
673 }), 789 )
790 }
791
792 pub fn new_synchronous<'d, T: Instance, C: Channel, W: word::Word>(
793 peri: impl Peripheral<P = T> + 'd,
794 sd: impl Peripheral<P = impl SdBPin<T>> + 'd,
795 dma: impl Peripheral<P = C> + 'd,
796 dma_buf: &'d mut [W],
797 mut config: Config,
798 ) -> SubBlock<T, C, W>
799 where
800 C: Channel + DmaB<T>,
801 {
802 update_synchronous_config(&mut config);
803
804 into_ref!(dma, peri, sd);
805
806 let (sd_af_type, _ck_af_type) = get_af_types(config.mode, config.tx_rx);
807
808 sd.set_as_af(sd.af_num(), sd_af_type);
809 sd.set_speed(crate::gpio::Speed::VeryHigh);
810
811 let sub_block = WhichSubBlock::B;
812 let request = dma.request();
813
814 SubBlock::new_inner(
815 peri,
816 sub_block,
817 None,
818 None,
819 Some(sd.map_into()),
820 None,
821 get_ring_buffer::<T, C, W>(dma, dma_buf, request, sub_block, config.tx_rx),
674 config, 822 config,
675 ) 823 )
676 } 824 }
825}
677 826
827impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> {
678 pub fn start(self: &mut Self) { 828 pub fn start(self: &mut Self) {
679 match self.ring_buffer { 829 match self.ring_buffer {
680 RingBuffer::Writable(ref mut rb) => { 830 RingBuffer::Writable(ref mut rb) => {
@@ -695,7 +845,7 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
695 845
696 fn new_inner( 846 fn new_inner(
697 peri: impl Peripheral<P = T> + 'd, 847 peri: impl Peripheral<P = T> + 'd,
698 sub_block: SubBlock, 848 sub_block: WhichSubBlock,
699 sck: Option<PeripheralRef<'d, AnyPin>>, 849 sck: Option<PeripheralRef<'d, AnyPin>>,
700 mclk: Option<PeripheralRef<'d, AnyPin>>, 850 mclk: Option<PeripheralRef<'d, AnyPin>>,
701 sd: Option<PeripheralRef<'d, AnyPin>>, 851 sd: Option<PeripheralRef<'d, AnyPin>>,
@@ -704,12 +854,21 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
704 config: Config, 854 config: Config,
705 ) -> Self { 855 ) -> Self {
706 T::enable(); 856 T::enable();
707 T::reset(); 857
858 // can't reset here because the other sub-block might be in use
859
860 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
861 {
862 let ch = T::REGS.ch(sub_block as usize);
863 ch.cr1().modify(|w| w.set_saien(false));
864 }
708 865
709 #[cfg(any(sai_v4))] 866 #[cfg(any(sai_v4))]
710 { 867 {
711 // Not totally clear from the datasheet if this is right 868 // Not totally clear from the datasheet if this is right
712 // This is only used if using SyncEnable::External 869 // This is only used if using SyncEnable::External on the other SAI unit
870 // Syncing from SAIX subblock A to subblock B does not require this
871 // Only syncing from SAI1 subblock A/B to SAI2 subblock A/B
713 let value: u8 = if T::REGS.as_ptr() == stm32_metapac::SAI1.as_ptr() { 872 let value: u8 = if T::REGS.as_ptr() == stm32_metapac::SAI1.as_ptr() {
714 1 //this is SAI1, so sync with SAI2 873 1 //this is SAI1, so sync with SAI2
715 } else { 874 } else {
@@ -721,8 +880,8 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
721 880
722 if config.is_sync_output { 881 if config.is_sync_output {
723 let syncout: u8 = match sub_block { 882 let syncout: u8 = match sub_block {
724 SubBlock::A => 0b01, 883 WhichSubBlock::A => 0b01,
725 SubBlock::B => 0b10, 884 WhichSubBlock::B => 0b10,
726 }; 885 };
727 T::REGS.gcr().modify(|w| { 886 T::REGS.gcr().modify(|w| {
728 w.set_syncout(syncout); 887 w.set_syncout(syncout);
@@ -735,7 +894,7 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
735 let ch = T::REGS.ch(sub_block as usize); 894 let ch = T::REGS.ch(sub_block as usize);
736 ch.cr1().modify(|w| { 895 ch.cr1().modify(|w| {
737 w.set_mode(config.mode.mode(if Self::is_transmitter(&ring_buffer) { 896 w.set_mode(config.mode.mode(if Self::is_transmitter(&ring_buffer) {
738 TxRx::Transmiter 897 TxRx::Transmitter
739 } else { 898 } else {
740 TxRx::Receiver 899 TxRx::Receiver
741 })); 900 }));
@@ -770,7 +929,7 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
770 w.set_fsoff(config.frame_sync_offset.fsoff()); 929 w.set_fsoff(config.frame_sync_offset.fsoff());
771 w.set_fspol(config.frame_sync_polarity.fspol()); 930 w.set_fspol(config.frame_sync_polarity.fspol());
772 w.set_fsdef(config.frame_sync_definition.fsdef()); 931 w.set_fsdef(config.frame_sync_definition.fsdef());
773 w.set_fsall(config.frame_sync_active_level_length.0 as u8); 932 w.set_fsall(config.frame_sync_active_level_length.0 as u8 - 1);
774 w.set_frl(config.frame_length - 1); 933 w.set_frl(config.frame_length - 1);
775 }); 934 });
776 935
@@ -782,6 +941,10 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
782 }); 941 });
783 942
784 ch.cr1().modify(|w| w.set_saien(true)); 943 ch.cr1().modify(|w| w.set_saien(true));
944
945 if ch.cr1().read().saien() == false {
946 panic!("SAI failed to enable. Check that config is valid (frame length, slot count, etc)");
947 }
785 } 948 }
786 949
787 Self { 950 Self {
@@ -795,6 +958,11 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
795 } 958 }
796 } 959 }
797 960
961 pub fn reset() {
962 T::enable();
963 T::reset();
964 }
965
798 pub fn flush(&mut self) { 966 pub fn flush(&mut self) {
799 let ch = T::REGS.ch(self.sub_block as usize); 967 let ch = T::REGS.ch(self.sub_block as usize);
800 ch.cr1().modify(|w| w.set_saien(false)); 968 ch.cr1().modify(|w| w.set_saien(false));
@@ -842,7 +1010,7 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
842 } 1010 }
843} 1011}
844 1012
845impl<'d, T: Instance, C: Channel, W: word::Word> Drop for Sai<'d, T, C, W> { 1013impl<'d, T: Instance, C: Channel, W: word::Word> Drop for SubBlock<'d, T, C, W> {
846 fn drop(&mut self) { 1014 fn drop(&mut self) {
847 let ch = T::REGS.ch(self.sub_block as usize); 1015 let ch = T::REGS.ch(self.sub_block as usize);
848 ch.cr1().modify(|w| w.set_saien(false)); 1016 ch.cr1().modify(|w| w.set_saien(false));
@@ -886,9 +1054,9 @@ foreach_peripheral!(
886 }; 1054 };
887); 1055);
888 1056
889impl<'d, T: Instance, C: Channel, W: word::Word> SetConfig for Sai<'d, T, C, W> { 1057impl<'d, T: Instance> SetConfig for Sai<'d, T> {
890 type Config = Config; 1058 type Config = Config;
891 fn set_config(&mut self, config: &Self::Config) { 1059 fn set_config(&mut self, _config: &Self::Config) {
892 self.reconfigure(*config); 1060 // self.reconfigure(*config);
893 } 1061 }
894} 1062}