diff options
| author | Tyler Gilbert <[email protected]> | 2023-09-30 22:48:49 -0500 |
|---|---|---|
| committer | Tyler Gilbert <[email protected]> | 2023-09-30 22:48:49 -0500 |
| commit | 5dd9e9b3b75bb45f284a16b96a7ff4358bd0be31 (patch) | |
| tree | 34431013ee16052ad3554705f717859661fbe6bb /embassy-stm32/src | |
| parent | d42cfda2db1d2ca9d9d3c1ca0de044de1d0a5652 (diff) | |
issue #1986 separate blocks to prevent unsafe user code
Diffstat (limited to 'embassy-stm32/src')
| -rw-r--r-- | embassy-stm32/src/sai/mod.rs | 288 |
1 files changed, 162 insertions, 126 deletions
diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs index b1b5107b2..438e85b66 100644 --- a/embassy-stm32/src/sai/mod.rs +++ b/embassy-stm32/src/sai/mod.rs | |||
| @@ -502,7 +502,7 @@ impl Config { | |||
| 502 | } | 502 | } |
| 503 | 503 | ||
| 504 | #[derive(Copy, Clone)] | 504 | #[derive(Copy, Clone)] |
| 505 | pub enum SubBlock { | 505 | enum WhichSubBlock { |
| 506 | A = 0, | 506 | A = 0, |
| 507 | B = 1, | 507 | B = 1, |
| 508 | } | 508 | } |
| @@ -513,67 +513,116 @@ enum RingBuffer<'d, C: Channel, W: word::Word> { | |||
| 513 | } | 513 | } |
| 514 | 514 | ||
| 515 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] | 515 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] |
| 516 | fn wdr<W: word::Word>(w: crate::pac::sai::Sai, sub_block: SubBlock) -> *mut W { | 516 | fn dr<W: word::Word>(w: crate::pac::sai::Sai, sub_block: WhichSubBlock) -> *mut W { |
| 517 | let ch = w.ch(sub_block as usize); | 517 | let ch = w.ch(sub_block as usize); |
| 518 | ch.dr().as_ptr() as _ | 518 | ch.dr().as_ptr() as _ |
| 519 | } | 519 | } |
| 520 | 520 | ||
| 521 | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] | 521 | pub struct SubBlock<'d, T: Instance, C: Channel, W: word::Word> { |
| 522 | fn rdr<W: word::Word>(w: crate::pac::sai::Sai, sub_block: SubBlock) -> *mut W { | ||
| 523 | let ch = w.ch(sub_block as usize); | ||
| 524 | ch.dr().as_ptr() as _ | ||
| 525 | } | ||
| 526 | |||
| 527 | pub struct Sai<'d, T: Instance, C: Channel, W: word::Word> { | ||
| 528 | _peri: PeripheralRef<'d, T>, | 522 | _peri: PeripheralRef<'d, T>, |
| 529 | sd: Option<PeripheralRef<'d, AnyPin>>, | 523 | sd: Option<PeripheralRef<'d, AnyPin>>, |
| 530 | fs: Option<PeripheralRef<'d, AnyPin>>, | 524 | fs: Option<PeripheralRef<'d, AnyPin>>, |
| 531 | sck: Option<PeripheralRef<'d, AnyPin>>, | 525 | sck: Option<PeripheralRef<'d, AnyPin>>, |
| 532 | mclk: Option<PeripheralRef<'d, AnyPin>>, | 526 | mclk: Option<PeripheralRef<'d, AnyPin>>, |
| 533 | ring_buffer: RingBuffer<'d, C, W>, | 527 | ring_buffer: RingBuffer<'d, C, W>, |
| 534 | sub_block: SubBlock, | 528 | sub_block: WhichSubBlock, |
| 535 | } | 529 | } |
| 536 | 530 | ||
| 537 | impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { | 531 | pub struct SubBlockA {} |
| 538 | // return the type for (sd, sck) | 532 | pub struct SubBlockB {} |
| 539 | fn get_af_types(mode: Mode, tx_rx: TxRx) -> (AFType, AFType) { | ||
| 540 | ( | ||
| 541 | //sd is defined by tx/rx mode | ||
| 542 | match tx_rx { | ||
| 543 | TxRx::Transmitter => AFType::OutputPushPull, | ||
| 544 | TxRx::Receiver => AFType::Input, | ||
| 545 | }, | ||
| 546 | //clocks (mclk, sck and fs) are defined by master/slave | ||
| 547 | match mode { | ||
| 548 | Mode::Master => AFType::OutputPushPull, | ||
| 549 | Mode::Slave => AFType::Input, | ||
| 550 | }, | ||
| 551 | ) | ||
| 552 | } | ||
| 553 | 533 | ||
| 554 | fn get_ring_buffer( | 534 | pub struct Sai<'d, T: Instance> { |
| 555 | dma: impl Peripheral<P = C> + 'd, | 535 | _peri: PeripheralRef<'d, T>, |
| 556 | dma_buf: &'d mut [W], | 536 | sub_block_a_peri: Option<PeripheralRef<'d, T>>, |
| 557 | request: Request, | 537 | sub_block_b_peri: Option<PeripheralRef<'d, T>>, |
| 558 | sub_block: SubBlock, | 538 | } |
| 559 | tx_rx: TxRx, | 539 | |
| 560 | ) -> RingBuffer<'d, C, W> { | 540 | // return the type for (sd, sck) |
| 561 | let opts = TransferOptions { | 541 | fn get_af_types(mode: Mode, tx_rx: TxRx) -> (AFType, AFType) { |
| 562 | half_transfer_ir: true, | 542 | ( |
| 563 | //the new_write() and new_read() always use circular mode | 543 | //sd is defined by tx/rx mode |
| 564 | ..Default::default() | ||
| 565 | }; | ||
| 566 | match tx_rx { | 544 | match tx_rx { |
| 567 | TxRx::Transmitter => RingBuffer::Writable(unsafe { | 545 | TxRx::Transmitter => AFType::OutputPushPull, |
| 568 | WritableRingBuffer::new_write(dma, request, wdr(T::REGS, sub_block), dma_buf, opts) | 546 | TxRx::Receiver => AFType::Input, |
| 569 | }), | 547 | }, |
| 570 | TxRx::Receiver => RingBuffer::Readable(unsafe { | 548 | //clocks (mclk, sck and fs) are defined by master/slave |
| 571 | ReadableRingBuffer::new_read(dma, request, rdr(T::REGS, sub_block), dma_buf, opts) | 549 | match mode { |
| 572 | }), | 550 | Mode::Master => AFType::OutputPushPull, |
| 551 | Mode::Slave => AFType::Input, | ||
| 552 | }, | ||
| 553 | ) | ||
| 554 | } | ||
| 555 | |||
| 556 | fn 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 | |||
| 578 | impl<'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()), | ||
| 573 | } | 587 | } |
| 574 | } | 588 | } |
| 575 | 589 | ||
| 576 | pub fn new_asynchronous_block_a_with_mclk( | 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 | |||
| 607 | fn 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 | |||
| 624 | impl SubBlockA { | ||
| 625 | pub fn new_asynchronous_with_mclk<'d, T: Instance, C: Channel, W: word::Word>( | ||
| 577 | peri: impl Peripheral<P = T> + 'd, | 626 | peri: impl Peripheral<P = T> + 'd, |
| 578 | sck: impl Peripheral<P = impl SckAPin<T>> + 'd, | 627 | sck: impl Peripheral<P = impl SckAPin<T>> + 'd, |
| 579 | sd: impl Peripheral<P = impl SdAPin<T>> + 'd, | 628 | sd: impl Peripheral<P = impl SdAPin<T>> + 'd, |
| @@ -582,13 +631,13 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { | |||
| 582 | dma: impl Peripheral<P = C> + 'd, | 631 | dma: impl Peripheral<P = C> + 'd, |
| 583 | dma_buf: &'d mut [W], | 632 | dma_buf: &'d mut [W], |
| 584 | mut config: Config, | 633 | mut config: Config, |
| 585 | ) -> Self | 634 | ) -> SubBlock<T, C, W> |
| 586 | where | 635 | where |
| 587 | C: Channel + DmaA<T>, | 636 | C: Channel + DmaA<T>, |
| 588 | { | 637 | { |
| 589 | into_ref!(mclk); | 638 | into_ref!(mclk); |
| 590 | 639 | ||
| 591 | let (_sd_af_type, ck_af_type) = Self::get_af_types(config.mode, config.tx_rx); | 640 | let (_sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx); |
| 592 | 641 | ||
| 593 | mclk.set_as_af(mclk.af_num(), ck_af_type); | 642 | mclk.set_as_af(mclk.af_num(), ck_af_type); |
| 594 | mclk.set_speed(crate::gpio::Speed::VeryHigh); | 643 | mclk.set_speed(crate::gpio::Speed::VeryHigh); |
| @@ -597,10 +646,10 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { | |||
| 597 | config.master_clock_divider = MasterClockDivider::Div1; | 646 | config.master_clock_divider = MasterClockDivider::Div1; |
| 598 | } | 647 | } |
| 599 | 648 | ||
| 600 | Self::new_asynchronous_block_a(peri, sck, sd, fs, dma, dma_buf, config) | 649 | Self::new_asynchronous(peri, sck, sd, fs, dma, dma_buf, config) |
| 601 | } | 650 | } |
| 602 | 651 | ||
| 603 | pub fn new_asynchronous_block_a( | 652 | pub fn new_asynchronous<'d, T: Instance, C: Channel, W: word::Word>( |
| 604 | peri: impl Peripheral<P = T> + 'd, | 653 | peri: impl Peripheral<P = T> + 'd, |
| 605 | sck: impl Peripheral<P = impl SckAPin<T>> + 'd, | 654 | sck: impl Peripheral<P = impl SckAPin<T>> + 'd, |
| 606 | sd: impl Peripheral<P = impl SdAPin<T>> + 'd, | 655 | sd: impl Peripheral<P = impl SdAPin<T>> + 'd, |
| @@ -608,13 +657,13 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { | |||
| 608 | dma: impl Peripheral<P = C> + 'd, | 657 | dma: impl Peripheral<P = C> + 'd, |
| 609 | dma_buf: &'d mut [W], | 658 | dma_buf: &'d mut [W], |
| 610 | config: Config, | 659 | config: Config, |
| 611 | ) -> Self | 660 | ) -> SubBlock<T, C, W> |
| 612 | where | 661 | where |
| 613 | C: Channel + DmaA<T>, | 662 | C: Channel + DmaA<T>, |
| 614 | { | 663 | { |
| 615 | into_ref!(peri, dma, sck, sd, fs); | 664 | into_ref!(peri, dma, sck, sd, fs); |
| 616 | 665 | ||
| 617 | let (sd_af_type, ck_af_type) = Self::get_af_types(config.mode, config.tx_rx); | 666 | let (sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx); |
| 618 | sd.set_as_af(sd.af_num(), sd_af_type); | 667 | sd.set_as_af(sd.af_num(), sd_af_type); |
| 619 | sd.set_speed(crate::gpio::Speed::VeryHigh); | 668 | sd.set_speed(crate::gpio::Speed::VeryHigh); |
| 620 | 669 | ||
| @@ -623,22 +672,58 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { | |||
| 623 | fs.set_as_af(fs.af_num(), ck_af_type); | 672 | fs.set_as_af(fs.af_num(), ck_af_type); |
| 624 | fs.set_speed(crate::gpio::Speed::VeryHigh); | 673 | fs.set_speed(crate::gpio::Speed::VeryHigh); |
| 625 | 674 | ||
| 626 | let sub_block = SubBlock::A; | 675 | let sub_block = WhichSubBlock::A; |
| 627 | let request = dma.request(); | 676 | let request = dma.request(); |
| 628 | 677 | ||
| 629 | Self::new_inner( | 678 | SubBlock::new_inner( |
| 630 | peri, | 679 | peri, |
| 631 | sub_block, | 680 | sub_block, |
| 632 | Some(sck.map_into()), | 681 | Some(sck.map_into()), |
| 633 | None, | 682 | None, |
| 634 | Some(sd.map_into()), | 683 | Some(sd.map_into()), |
| 635 | Some(fs.map_into()), | 684 | Some(fs.map_into()), |
| 636 | Self::get_ring_buffer(dma, dma_buf, request, sub_block, config.tx_rx), | 685 | get_ring_buffer::<T, C, W>(dma, dma_buf, request, sub_block, config.tx_rx), |
| 686 | config, | ||
| 687 | ) | ||
| 688 | } | ||
| 689 | |||
| 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), | ||
| 637 | config, | 720 | config, |
| 638 | ) | 721 | ) |
| 639 | } | 722 | } |
| 723 | } | ||
| 640 | 724 | ||
| 641 | pub fn new_asynchronous_block_b_with_mclk( | 725 | impl SubBlockB { |
| 726 | pub fn new_asynchronous_with_mclk<'d, T: Instance, C: Channel, W: word::Word>( | ||
| 642 | peri: impl Peripheral<P = T> + 'd, | 727 | peri: impl Peripheral<P = T> + 'd, |
| 643 | sck: impl Peripheral<P = impl SckBPin<T>> + 'd, | 728 | sck: impl Peripheral<P = impl SckBPin<T>> + 'd, |
| 644 | sd: impl Peripheral<P = impl SdBPin<T>> + 'd, | 729 | sd: impl Peripheral<P = impl SdBPin<T>> + 'd, |
| @@ -647,13 +732,13 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { | |||
| 647 | dma: impl Peripheral<P = C> + 'd, | 732 | dma: impl Peripheral<P = C> + 'd, |
| 648 | dma_buf: &'d mut [W], | 733 | dma_buf: &'d mut [W], |
| 649 | mut config: Config, | 734 | mut config: Config, |
| 650 | ) -> Self | 735 | ) -> SubBlock<T, C, W> |
| 651 | where | 736 | where |
| 652 | C: Channel + DmaB<T>, | 737 | C: Channel + DmaB<T>, |
| 653 | { | 738 | { |
| 654 | into_ref!(mclk); | 739 | into_ref!(mclk); |
| 655 | 740 | ||
| 656 | let (_sd_af_type, ck_af_type) = Self::get_af_types(config.mode, config.tx_rx); | 741 | let (_sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx); |
| 657 | 742 | ||
| 658 | mclk.set_as_af(mclk.af_num(), ck_af_type); | 743 | mclk.set_as_af(mclk.af_num(), ck_af_type); |
| 659 | mclk.set_speed(crate::gpio::Speed::VeryHigh); | 744 | mclk.set_speed(crate::gpio::Speed::VeryHigh); |
| @@ -662,10 +747,10 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { | |||
| 662 | config.master_clock_divider = MasterClockDivider::Div1; | 747 | config.master_clock_divider = MasterClockDivider::Div1; |
| 663 | } | 748 | } |
| 664 | 749 | ||
| 665 | Self::new_asynchronous_block_b(peri, sck, sd, fs, dma, dma_buf, config) | 750 | Self::new_asynchronous(peri, sck, sd, fs, dma, dma_buf, config) |
| 666 | } | 751 | } |
| 667 | 752 | ||
| 668 | pub fn new_asynchronous_block_b( | 753 | pub fn new_asynchronous<'d, T: Instance, C: Channel, W: word::Word>( |
| 669 | peri: impl Peripheral<P = T> + 'd, | 754 | peri: impl Peripheral<P = T> + 'd, |
| 670 | sck: impl Peripheral<P = impl SckBPin<T>> + 'd, | 755 | sck: impl Peripheral<P = impl SckBPin<T>> + 'd, |
| 671 | sd: impl Peripheral<P = impl SdBPin<T>> + 'd, | 756 | sd: impl Peripheral<P = impl SdBPin<T>> + 'd, |
| @@ -673,13 +758,13 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { | |||
| 673 | dma: impl Peripheral<P = C> + 'd, | 758 | dma: impl Peripheral<P = C> + 'd, |
| 674 | dma_buf: &'d mut [W], | 759 | dma_buf: &'d mut [W], |
| 675 | config: Config, | 760 | config: Config, |
| 676 | ) -> Self | 761 | ) -> SubBlock<T, C, W> |
| 677 | where | 762 | where |
| 678 | C: Channel + DmaB<T>, | 763 | C: Channel + DmaB<T>, |
| 679 | { | 764 | { |
| 680 | into_ref!(dma, peri, sck, sd, fs); | 765 | into_ref!(dma, peri, sck, sd, fs); |
| 681 | 766 | ||
| 682 | let (sd_af_type, ck_af_type) = Self::get_af_types(config.mode, config.tx_rx); | 767 | let (sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx); |
| 683 | 768 | ||
| 684 | sd.set_as_af(sd.af_num(), sd_af_type); | 769 | sd.set_as_af(sd.af_num(), sd_af_type); |
| 685 | sd.set_speed(crate::gpio::Speed::VeryHigh); | 770 | sd.set_speed(crate::gpio::Speed::VeryHigh); |
| @@ -689,106 +774,57 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { | |||
| 689 | fs.set_as_af(fs.af_num(), ck_af_type); | 774 | fs.set_as_af(fs.af_num(), ck_af_type); |
| 690 | fs.set_speed(crate::gpio::Speed::VeryHigh); | 775 | fs.set_speed(crate::gpio::Speed::VeryHigh); |
| 691 | 776 | ||
| 692 | let sub_block = SubBlock::B; | 777 | let sub_block = WhichSubBlock::B; |
| 693 | let request = dma.request(); | 778 | let request = dma.request(); |
| 694 | 779 | ||
| 695 | Self::new_inner( | 780 | SubBlock::new_inner( |
| 696 | peri, | 781 | peri, |
| 697 | sub_block, | 782 | sub_block, |
| 698 | Some(sck.map_into()), | 783 | Some(sck.map_into()), |
| 699 | None, | 784 | None, |
| 700 | Some(sd.map_into()), | 785 | Some(sd.map_into()), |
| 701 | Some(fs.map_into()), | 786 | Some(fs.map_into()), |
| 702 | Self::get_ring_buffer(dma, dma_buf, request, sub_block, config.tx_rx), | 787 | get_ring_buffer::<T, C, W>(dma, dma_buf, request, sub_block, config.tx_rx), |
| 703 | config, | 788 | config, |
| 704 | ) | 789 | ) |
| 705 | } | 790 | } |
| 706 | 791 | ||
| 707 | fn update_synchronous_config(config: &mut Config) { | 792 | pub fn new_synchronous<'d, T: Instance, C: Channel, W: word::Word>( |
| 708 | config.mode = Mode::Slave; | ||
| 709 | config.is_sync_output = false; | ||
| 710 | |||
| 711 | #[cfg(any(sai_v1, sai_v2, sai_v3))] | ||
| 712 | { | ||
| 713 | config.sync_enable = SyncEnable::Internal; | ||
| 714 | } | ||
| 715 | |||
| 716 | #[cfg(any(sai_v4))] | ||
| 717 | { | ||
| 718 | //this must either be Internal or External | ||
| 719 | //The asynchronous sub-block on the same SAI needs to enable is_sync_output | ||
| 720 | assert!(config.sync_enable != SyncEnable::Asynchronous); | ||
| 721 | } | ||
| 722 | } | ||
| 723 | |||
| 724 | pub fn new_synchronous_block_a( | ||
| 725 | peri: impl Peripheral<P = T> + 'd, | ||
| 726 | sd: impl Peripheral<P = impl SdAPin<T>> + 'd, | ||
| 727 | dma: impl Peripheral<P = C> + 'd, | ||
| 728 | dma_buf: &'d mut [W], | ||
| 729 | mut config: Config, | ||
| 730 | ) -> Self | ||
| 731 | where | ||
| 732 | C: Channel + DmaA<T>, | ||
| 733 | { | ||
| 734 | Self::update_synchronous_config(&mut config); | ||
| 735 | |||
| 736 | into_ref!(dma, peri, sd); | ||
| 737 | |||
| 738 | let (sd_af_type, _ck_af_type) = Self::get_af_types(config.mode, config.tx_rx); | ||
| 739 | |||
| 740 | sd.set_as_af(sd.af_num(), sd_af_type); | ||
| 741 | sd.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 742 | |||
| 743 | let sub_block = SubBlock::A; | ||
| 744 | let request = dma.request(); | ||
| 745 | |||
| 746 | Self::new_inner( | ||
| 747 | peri, | ||
| 748 | sub_block, | ||
| 749 | None, | ||
| 750 | None, | ||
| 751 | Some(sd.map_into()), | ||
| 752 | None, | ||
| 753 | Self::get_ring_buffer(dma, dma_buf, request, sub_block, config.tx_rx), | ||
| 754 | config, | ||
| 755 | ) | ||
| 756 | } | ||
| 757 | |||
| 758 | pub fn new_synchronous_block_b( | ||
| 759 | peri: impl Peripheral<P = T> + 'd, | 793 | peri: impl Peripheral<P = T> + 'd, |
| 760 | sd: impl Peripheral<P = impl SdBPin<T>> + 'd, | 794 | sd: impl Peripheral<P = impl SdBPin<T>> + 'd, |
| 761 | dma: impl Peripheral<P = C> + 'd, | 795 | dma: impl Peripheral<P = C> + 'd, |
| 762 | dma_buf: &'d mut [W], | 796 | dma_buf: &'d mut [W], |
| 763 | mut config: Config, | 797 | mut config: Config, |
| 764 | ) -> Self | 798 | ) -> SubBlock<T, C, W> |
| 765 | where | 799 | where |
| 766 | C: Channel + DmaB<T>, | 800 | C: Channel + DmaB<T>, |
| 767 | { | 801 | { |
| 768 | Self::update_synchronous_config(&mut config); | 802 | update_synchronous_config(&mut config); |
| 769 | 803 | ||
| 770 | into_ref!(dma, peri, sd); | 804 | into_ref!(dma, peri, sd); |
| 771 | 805 | ||
| 772 | let (sd_af_type, _ck_af_type) = Self::get_af_types(config.mode, config.tx_rx); | 806 | let (sd_af_type, _ck_af_type) = get_af_types(config.mode, config.tx_rx); |
| 773 | 807 | ||
| 774 | sd.set_as_af(sd.af_num(), sd_af_type); | 808 | sd.set_as_af(sd.af_num(), sd_af_type); |
| 775 | sd.set_speed(crate::gpio::Speed::VeryHigh); | 809 | sd.set_speed(crate::gpio::Speed::VeryHigh); |
| 776 | 810 | ||
| 777 | let sub_block = SubBlock::B; | 811 | let sub_block = WhichSubBlock::B; |
| 778 | let request = dma.request(); | 812 | let request = dma.request(); |
| 779 | 813 | ||
| 780 | Self::new_inner( | 814 | SubBlock::new_inner( |
| 781 | peri, | 815 | peri, |
| 782 | sub_block, | 816 | sub_block, |
| 783 | None, | 817 | None, |
| 784 | None, | 818 | None, |
| 785 | Some(sd.map_into()), | 819 | Some(sd.map_into()), |
| 786 | None, | 820 | None, |
| 787 | Self::get_ring_buffer(dma, dma_buf, request, sub_block, config.tx_rx), | 821 | get_ring_buffer::<T, C, W>(dma, dma_buf, request, sub_block, config.tx_rx), |
| 788 | config, | 822 | config, |
| 789 | ) | 823 | ) |
| 790 | } | 824 | } |
| 825 | } | ||
| 791 | 826 | ||
| 827 | impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> { | ||
| 792 | pub fn start(self: &mut Self) { | 828 | pub fn start(self: &mut Self) { |
| 793 | match self.ring_buffer { | 829 | match self.ring_buffer { |
| 794 | RingBuffer::Writable(ref mut rb) => { | 830 | RingBuffer::Writable(ref mut rb) => { |
| @@ -809,7 +845,7 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { | |||
| 809 | 845 | ||
| 810 | fn new_inner( | 846 | fn new_inner( |
| 811 | peri: impl Peripheral<P = T> + 'd, | 847 | peri: impl Peripheral<P = T> + 'd, |
| 812 | sub_block: SubBlock, | 848 | sub_block: WhichSubBlock, |
| 813 | sck: Option<PeripheralRef<'d, AnyPin>>, | 849 | sck: Option<PeripheralRef<'d, AnyPin>>, |
| 814 | mclk: Option<PeripheralRef<'d, AnyPin>>, | 850 | mclk: Option<PeripheralRef<'d, AnyPin>>, |
| 815 | sd: Option<PeripheralRef<'d, AnyPin>>, | 851 | sd: Option<PeripheralRef<'d, AnyPin>>, |
| @@ -974,7 +1010,7 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { | |||
| 974 | } | 1010 | } |
| 975 | } | 1011 | } |
| 976 | 1012 | ||
| 977 | impl<'d, T: Instance, C: Channel, W: word::Word> Drop for Sai<'d, T, C, W> { | 1013 | impl<'d, T: Instance, C: Channel, W: word::Word> Drop for SubBlock<'d, T, C, W> { |
| 978 | fn drop(&mut self) { | 1014 | fn drop(&mut self) { |
| 979 | let ch = T::REGS.ch(self.sub_block as usize); | 1015 | let ch = T::REGS.ch(self.sub_block as usize); |
| 980 | ch.cr1().modify(|w| w.set_saien(false)); | 1016 | ch.cr1().modify(|w| w.set_saien(false)); |
| @@ -1018,9 +1054,9 @@ foreach_peripheral!( | |||
| 1018 | }; | 1054 | }; |
| 1019 | ); | 1055 | ); |
| 1020 | 1056 | ||
| 1021 | impl<'d, T: Instance, C: Channel, W: word::Word> SetConfig for Sai<'d, T, C, W> { | 1057 | impl<'d, T: Instance> SetConfig for Sai<'d, T> { |
| 1022 | type Config = Config; | 1058 | type Config = Config; |
| 1023 | fn set_config(&mut self, config: &Self::Config) { | 1059 | fn set_config(&mut self, config: &Self::Config) { |
| 1024 | self.reconfigure(*config); | 1060 | // self.reconfigure(*config); |
| 1025 | } | 1061 | } |
| 1026 | } | 1062 | } |
