Issue #1986 update the SAI driver with receiver capability
This commit is contained in:
		
							parent
							
								
									fa8d5da4a5
								
							
						
					
					
						commit
						d1f4511cd1
					
				| @ -4,7 +4,7 @@ use embassy_embedded_hal::SetConfig; | |||||||
| use embassy_hal_internal::{into_ref, PeripheralRef}; | use embassy_hal_internal::{into_ref, PeripheralRef}; | ||||||
| 
 | 
 | ||||||
| pub use crate::dma::word; | pub use crate::dma::word; | ||||||
| use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, TransferOptions, WritableRingBuffer}; | use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, Request, TransferOptions, WritableRingBuffer}; | ||||||
| use crate::gpio::sealed::{AFType, Pin as _}; | use crate::gpio::sealed::{AFType, Pin as _}; | ||||||
| use crate::gpio::AnyPin; | use crate::gpio::AnyPin; | ||||||
| use crate::pac::sai::{vals, Sai as Regs}; | use crate::pac::sai::{vals, Sai as Regs}; | ||||||
| @ -48,8 +48,8 @@ pub enum Mode { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Copy, Clone)] | #[derive(Copy, Clone)] | ||||||
| enum TxRx { | pub enum TxRx { | ||||||
|     Transmiter, |     Transmitter, | ||||||
|     Receiver, |     Receiver, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -57,7 +57,7 @@ impl Mode { | |||||||
|     #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] |     #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] | ||||||
|     const fn mode(&self, tx_rx: TxRx) -> vals::Mode { |     const fn mode(&self, tx_rx: TxRx) -> vals::Mode { | ||||||
|         match tx_rx { |         match tx_rx { | ||||||
|             TxRx::Transmiter => match self { |             TxRx::Transmitter => match self { | ||||||
|                 Mode::Master => vals::Mode::MASTERTX, |                 Mode::Master => vals::Mode::MASTERTX, | ||||||
|                 Mode::Slave => vals::Mode::SLAVETX, |                 Mode::Slave => vals::Mode::SLAVETX, | ||||||
|             }, |             }, | ||||||
| @ -212,6 +212,7 @@ pub enum SyncEnable { | |||||||
|     /// Syncs with the other A/B sub-block within the SAI unit
 |     /// Syncs with the other A/B sub-block within the SAI unit
 | ||||||
|     Internal, |     Internal, | ||||||
|     /// Syncs with a sub-block in the other SAI unit - use set_sync_output() and set_sync_input()
 |     /// Syncs with a sub-block in the other SAI unit - use set_sync_output() and set_sync_input()
 | ||||||
|  |     #[cfg(any(sai_v4))] | ||||||
|     External, |     External, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -221,6 +222,7 @@ impl SyncEnable { | |||||||
|         match self { |         match self { | ||||||
|             SyncEnable::Asynchronous => vals::Syncen::ASYNCHRONOUS, |             SyncEnable::Asynchronous => vals::Syncen::ASYNCHRONOUS, | ||||||
|             SyncEnable::Internal => vals::Syncen::INTERNAL, |             SyncEnable::Internal => vals::Syncen::INTERNAL, | ||||||
|  |             #[cfg(any(sai_v4))] | ||||||
|             SyncEnable::External => vals::Syncen::EXTERNAL, |             SyncEnable::External => vals::Syncen::EXTERNAL, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -425,6 +427,7 @@ impl MasterClockDivider { | |||||||
| #[derive(Copy, Clone)] | #[derive(Copy, Clone)] | ||||||
| pub struct Config { | pub struct Config { | ||||||
|     pub mode: Mode, |     pub mode: Mode, | ||||||
|  |     pub tx_rx: TxRx, | ||||||
|     pub sync_enable: SyncEnable, |     pub sync_enable: SyncEnable, | ||||||
|     pub is_sync_output: bool, |     pub is_sync_output: bool, | ||||||
|     pub protocol: Protocol, |     pub protocol: Protocol, | ||||||
| @ -455,6 +458,7 @@ impl Default for Config { | |||||||
|     fn default() -> Self { |     fn default() -> Self { | ||||||
|         Self { |         Self { | ||||||
|             mode: Mode::Master, |             mode: Mode::Master, | ||||||
|  |             tx_rx: TxRx::Transmitter, | ||||||
|             is_sync_output: false, |             is_sync_output: false, | ||||||
|             sync_enable: SyncEnable::Asynchronous, |             sync_enable: SyncEnable::Asynchronous, | ||||||
|             protocol: Protocol::Free, |             protocol: Protocol::Free, | ||||||
| @ -505,7 +509,6 @@ pub enum SubBlock { | |||||||
| 
 | 
 | ||||||
| enum RingBuffer<'d, C: Channel, W: word::Word> { | enum RingBuffer<'d, C: Channel, W: word::Word> { | ||||||
|     Writable(WritableRingBuffer<'d, C, W>), |     Writable(WritableRingBuffer<'d, C, W>), | ||||||
|     #[allow(dead_code)] // remove this after implementing new_* functions for receiver
 |  | ||||||
|     Readable(ReadableRingBuffer<'d, C, W>), |     Readable(ReadableRingBuffer<'d, C, W>), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -515,6 +518,12 @@ fn wdr<W: word::Word>(w: crate::pac::sai::Sai, sub_block: SubBlock) -> *mut W { | |||||||
|     ch.dr().as_ptr() as _ |     ch.dr().as_ptr() as _ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] | ||||||
|  | fn rdr<W: word::Word>(w: crate::pac::sai::Sai, sub_block: SubBlock) -> *mut W { | ||||||
|  |     let ch = w.ch(sub_block as usize); | ||||||
|  |     ch.dr().as_ptr() as _ | ||||||
|  | } | ||||||
|  | 
 | ||||||
| pub struct Sai<'d, T: Instance, C: Channel, W: word::Word> { | pub struct Sai<'d, T: Instance, C: Channel, W: word::Word> { | ||||||
|     _peri: PeripheralRef<'d, T>, |     _peri: PeripheralRef<'d, T>, | ||||||
|     sd: Option<PeripheralRef<'d, AnyPin>>, |     sd: Option<PeripheralRef<'d, AnyPin>>, | ||||||
| @ -526,14 +535,45 @@ pub struct Sai<'d, T: Instance, C: Channel, W: word::Word> { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { | impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { | ||||||
|     fn get_transmitter_af_types(mode: Mode) -> (AFType, AFType) { |     // return the type for (sd, sck)
 | ||||||
|         match mode { |     fn get_af_types(mode: Mode, tx_rx: TxRx) -> (AFType, AFType) { | ||||||
|             Mode::Master => (AFType::OutputPushPull, AFType::OutputPushPull), |         ( | ||||||
|             Mode::Slave => (AFType::OutputPushPull, AFType::Input), |             //sd is defined by tx/rx mode
 | ||||||
|  |             match tx_rx { | ||||||
|  |                 TxRx::Transmitter => AFType::OutputPushPull, | ||||||
|  |                 TxRx::Receiver => AFType::Input, | ||||||
|  |             }, | ||||||
|  |             //clocks (mclk, sck and fs) are defined by master/slave
 | ||||||
|  |             match mode { | ||||||
|  |                 Mode::Master => AFType::OutputPushPull, | ||||||
|  |                 Mode::Slave => AFType::Input, | ||||||
|  |             }, | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn get_ring_buffer( | ||||||
|  |         dma: impl Peripheral<P = C> + 'd, | ||||||
|  |         dma_buf: &'d mut [W], | ||||||
|  |         request: Request, | ||||||
|  |         sub_block: SubBlock, | ||||||
|  |         tx_rx: TxRx, | ||||||
|  |     ) -> RingBuffer<'d, C, W> { | ||||||
|  |         let opts = TransferOptions { | ||||||
|  |             half_transfer_ir: true, | ||||||
|  |             //the new_write() and new_read() always use circular mode
 | ||||||
|  |             ..Default::default() | ||||||
|  |         }; | ||||||
|  |         match tx_rx { | ||||||
|  |             TxRx::Transmitter => RingBuffer::Writable(unsafe { | ||||||
|  |                 WritableRingBuffer::new_write(dma, request, wdr(T::REGS, sub_block), dma_buf, opts) | ||||||
|  |             }), | ||||||
|  |             TxRx::Receiver => RingBuffer::Readable(unsafe { | ||||||
|  |                 ReadableRingBuffer::new_read(dma, request, rdr(T::REGS, sub_block), dma_buf, opts) | ||||||
|  |             }), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn new_asynchronous_transmitter_with_mclk_a( |     pub fn new_asynchronous_block_a_with_mclk( | ||||||
|         peri: impl Peripheral<P = T> + 'd, |         peri: impl Peripheral<P = T> + 'd, | ||||||
|         sck: impl Peripheral<P = impl SckAPin<T>> + 'd, |         sck: impl Peripheral<P = impl SckAPin<T>> + 'd, | ||||||
|         sd: impl Peripheral<P = impl SdAPin<T>> + 'd, |         sd: impl Peripheral<P = impl SdAPin<T>> + 'd, | ||||||
| @ -548,17 +588,19 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { | |||||||
|     { |     { | ||||||
|         into_ref!(mclk); |         into_ref!(mclk); | ||||||
| 
 | 
 | ||||||
|         mclk.set_as_af(mclk.af_num(), AFType::OutputPushPull); |         let (_sd_af_type, ck_af_type) = Self::get_af_types(config.mode, config.tx_rx); | ||||||
|  | 
 | ||||||
|  |         mclk.set_as_af(mclk.af_num(), ck_af_type); | ||||||
|         mclk.set_speed(crate::gpio::Speed::VeryHigh); |         mclk.set_speed(crate::gpio::Speed::VeryHigh); | ||||||
| 
 | 
 | ||||||
|         if config.master_clock_divider == MasterClockDivider::MasterClockDisabled { |         if config.master_clock_divider == MasterClockDivider::MasterClockDisabled { | ||||||
|             config.master_clock_divider = MasterClockDivider::Div1; |             config.master_clock_divider = MasterClockDivider::Div1; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         Self::new_asynchronous_transmitter_a(peri, sck, sd, fs, dma, dma_buf, config) |         Self::new_asynchronous_block_a(peri, sck, sd, fs, dma, dma_buf, config) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn new_asynchronous_transmitter_a( |     pub fn new_asynchronous_block_a( | ||||||
|         peri: impl Peripheral<P = T> + 'd, |         peri: impl Peripheral<P = T> + 'd, | ||||||
|         sck: impl Peripheral<P = impl SckAPin<T>> + 'd, |         sck: impl Peripheral<P = impl SckAPin<T>> + 'd, | ||||||
|         sd: impl Peripheral<P = impl SdAPin<T>> + 'd, |         sd: impl Peripheral<P = impl SdAPin<T>> + 'd, | ||||||
| @ -572,7 +614,7 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { | |||||||
|     { |     { | ||||||
|         into_ref!(peri, dma, sck, sd, fs); |         into_ref!(peri, dma, sck, sd, fs); | ||||||
| 
 | 
 | ||||||
|         let (sd_af_type, ck_af_type) = Self::get_transmitter_af_types(config.mode); |         let (sd_af_type, ck_af_type) = Self::get_af_types(config.mode, config.tx_rx); | ||||||
|         sd.set_as_af(sd.af_num(), sd_af_type); |         sd.set_as_af(sd.af_num(), sd_af_type); | ||||||
|         sd.set_speed(crate::gpio::Speed::VeryHigh); |         sd.set_speed(crate::gpio::Speed::VeryHigh); | ||||||
| 
 | 
 | ||||||
| @ -581,14 +623,8 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { | |||||||
|         fs.set_as_af(fs.af_num(), ck_af_type); |         fs.set_as_af(fs.af_num(), ck_af_type); | ||||||
|         fs.set_speed(crate::gpio::Speed::VeryHigh); |         fs.set_speed(crate::gpio::Speed::VeryHigh); | ||||||
| 
 | 
 | ||||||
|         let request = dma.request(); |  | ||||||
|         let opts = TransferOptions { |  | ||||||
|             half_transfer_ir: true, |  | ||||||
|             circular: true, |  | ||||||
|             ..Default::default() |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|         let sub_block = SubBlock::A; |         let sub_block = SubBlock::A; | ||||||
|  |         let request = dma.request(); | ||||||
| 
 | 
 | ||||||
|         Self::new_inner( |         Self::new_inner( | ||||||
|             peri, |             peri, | ||||||
| @ -597,14 +633,12 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { | |||||||
|             None, |             None, | ||||||
|             Some(sd.map_into()), |             Some(sd.map_into()), | ||||||
|             Some(fs.map_into()), |             Some(fs.map_into()), | ||||||
|             RingBuffer::Writable(unsafe { |             Self::get_ring_buffer(dma, dma_buf, request, sub_block, config.tx_rx), | ||||||
|                 WritableRingBuffer::new_write(dma, request, wdr(T::REGS, sub_block), dma_buf, opts) |  | ||||||
|             }), |  | ||||||
|             config, |             config, | ||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn new_asynchronous_transmitter_with_mclk_b( |     pub fn new_asynchronous_block_b_with_mclk( | ||||||
|         peri: impl Peripheral<P = T> + 'd, |         peri: impl Peripheral<P = T> + 'd, | ||||||
|         sck: impl Peripheral<P = impl SckBPin<T>> + 'd, |         sck: impl Peripheral<P = impl SckBPin<T>> + 'd, | ||||||
|         sd: impl Peripheral<P = impl SdBPin<T>> + 'd, |         sd: impl Peripheral<P = impl SdBPin<T>> + 'd, | ||||||
| @ -619,17 +653,19 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { | |||||||
|     { |     { | ||||||
|         into_ref!(mclk); |         into_ref!(mclk); | ||||||
| 
 | 
 | ||||||
|         mclk.set_as_af(mclk.af_num(), AFType::OutputPushPull); |         let (_sd_af_type, ck_af_type) = Self::get_af_types(config.mode, config.tx_rx); | ||||||
|  | 
 | ||||||
|  |         mclk.set_as_af(mclk.af_num(), ck_af_type); | ||||||
|         mclk.set_speed(crate::gpio::Speed::VeryHigh); |         mclk.set_speed(crate::gpio::Speed::VeryHigh); | ||||||
| 
 | 
 | ||||||
|         if config.master_clock_divider == MasterClockDivider::MasterClockDisabled { |         if config.master_clock_divider == MasterClockDivider::MasterClockDisabled { | ||||||
|             config.master_clock_divider = MasterClockDivider::Div1; |             config.master_clock_divider = MasterClockDivider::Div1; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         Self::new_asynchronous_transmitter_b(peri, sck, sd, fs, dma, dma_buf, config) |         Self::new_asynchronous_block_b(peri, sck, sd, fs, dma, dma_buf, config) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn new_asynchronous_transmitter_b( |     pub fn new_asynchronous_block_b( | ||||||
|         peri: impl Peripheral<P = T> + 'd, |         peri: impl Peripheral<P = T> + 'd, | ||||||
|         sck: impl Peripheral<P = impl SckBPin<T>> + 'd, |         sck: impl Peripheral<P = impl SckBPin<T>> + 'd, | ||||||
|         sd: impl Peripheral<P = impl SdBPin<T>> + 'd, |         sd: impl Peripheral<P = impl SdBPin<T>> + 'd, | ||||||
| @ -643,7 +679,7 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { | |||||||
|     { |     { | ||||||
|         into_ref!(dma, peri, sck, sd, fs); |         into_ref!(dma, peri, sck, sd, fs); | ||||||
| 
 | 
 | ||||||
|         let (sd_af_type, ck_af_type) = Self::get_transmitter_af_types(config.mode); |         let (sd_af_type, ck_af_type) = Self::get_af_types(config.mode, config.tx_rx); | ||||||
| 
 | 
 | ||||||
|         sd.set_as_af(sd.af_num(), sd_af_type); |         sd.set_as_af(sd.af_num(), sd_af_type); | ||||||
|         sd.set_speed(crate::gpio::Speed::VeryHigh); |         sd.set_speed(crate::gpio::Speed::VeryHigh); | ||||||
| @ -653,13 +689,8 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { | |||||||
|         fs.set_as_af(fs.af_num(), ck_af_type); |         fs.set_as_af(fs.af_num(), ck_af_type); | ||||||
|         fs.set_speed(crate::gpio::Speed::VeryHigh); |         fs.set_speed(crate::gpio::Speed::VeryHigh); | ||||||
| 
 | 
 | ||||||
|         let request = dma.request(); |  | ||||||
|         let opts = TransferOptions { |  | ||||||
|             half_transfer_ir: true, |  | ||||||
|             ..Default::default() |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|         let sub_block = SubBlock::B; |         let sub_block = SubBlock::B; | ||||||
|  |         let request = dma.request(); | ||||||
| 
 | 
 | ||||||
|         Self::new_inner( |         Self::new_inner( | ||||||
|             peri, |             peri, | ||||||
| @ -668,9 +699,92 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { | |||||||
|             None, |             None, | ||||||
|             Some(sd.map_into()), |             Some(sd.map_into()), | ||||||
|             Some(fs.map_into()), |             Some(fs.map_into()), | ||||||
|             RingBuffer::Writable(unsafe { |             Self::get_ring_buffer(dma, dma_buf, request, sub_block, config.tx_rx), | ||||||
|                 WritableRingBuffer::new_write(dma, request, wdr(T::REGS, sub_block), dma_buf, opts) |             config, | ||||||
|             }), |         ) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn update_synchronous_config(config: &mut Config) { | ||||||
|  |         config.mode = Mode::Slave; | ||||||
|  |         config.is_sync_output = false; | ||||||
|  | 
 | ||||||
|  |         #[cfg(any(sai_v1, sai_v2, sai_v3))] | ||||||
|  |         { | ||||||
|  |             config.sync_enable = SyncEnable::Internal; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         #[cfg(any(sai_v4))] | ||||||
|  |         { | ||||||
|  |             //this must either be Internal or External
 | ||||||
|  |             //The asynchronous sub-block on the same SAI needs to enable is_sync_output
 | ||||||
|  |             assert!(config.sync_enable != SyncEnable::Asynchronous); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn new_synchronous_block_a( | ||||||
|  |         peri: impl Peripheral<P = T> + 'd, | ||||||
|  |         sd: impl Peripheral<P = impl SdAPin<T>> + 'd, | ||||||
|  |         dma: impl Peripheral<P = C> + 'd, | ||||||
|  |         dma_buf: &'d mut [W], | ||||||
|  |         mut config: Config, | ||||||
|  |     ) -> Self | ||||||
|  |     where | ||||||
|  |         C: Channel + DmaA<T>, | ||||||
|  |     { | ||||||
|  |         Self::update_synchronous_config(&mut config); | ||||||
|  | 
 | ||||||
|  |         into_ref!(dma, peri, sd); | ||||||
|  | 
 | ||||||
|  |         let (sd_af_type, _ck_af_type) = Self::get_af_types(config.mode, config.tx_rx); | ||||||
|  | 
 | ||||||
|  |         sd.set_as_af(sd.af_num(), sd_af_type); | ||||||
|  |         sd.set_speed(crate::gpio::Speed::VeryHigh); | ||||||
|  | 
 | ||||||
|  |         let sub_block = SubBlock::A; | ||||||
|  |         let request = dma.request(); | ||||||
|  | 
 | ||||||
|  |         Self::new_inner( | ||||||
|  |             peri, | ||||||
|  |             sub_block, | ||||||
|  |             None, | ||||||
|  |             None, | ||||||
|  |             Some(sd.map_into()), | ||||||
|  |             None, | ||||||
|  |             Self::get_ring_buffer(dma, dma_buf, request, sub_block, config.tx_rx), | ||||||
|  |             config, | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn new_synchronous_block_b( | ||||||
|  |         peri: impl Peripheral<P = T> + 'd, | ||||||
|  |         sd: impl Peripheral<P = impl SdBPin<T>> + 'd, | ||||||
|  |         dma: impl Peripheral<P = C> + 'd, | ||||||
|  |         dma_buf: &'d mut [W], | ||||||
|  |         mut config: Config, | ||||||
|  |     ) -> Self | ||||||
|  |     where | ||||||
|  |         C: Channel + DmaB<T>, | ||||||
|  |     { | ||||||
|  |         Self::update_synchronous_config(&mut config); | ||||||
|  | 
 | ||||||
|  |         into_ref!(dma, peri, sd); | ||||||
|  | 
 | ||||||
|  |         let (sd_af_type, _ck_af_type) = Self::get_af_types(config.mode, config.tx_rx); | ||||||
|  | 
 | ||||||
|  |         sd.set_as_af(sd.af_num(), sd_af_type); | ||||||
|  |         sd.set_speed(crate::gpio::Speed::VeryHigh); | ||||||
|  | 
 | ||||||
|  |         let sub_block = SubBlock::B; | ||||||
|  |         let request = dma.request(); | ||||||
|  | 
 | ||||||
|  |         Self::new_inner( | ||||||
|  |             peri, | ||||||
|  |             sub_block, | ||||||
|  |             None, | ||||||
|  |             None, | ||||||
|  |             Some(sd.map_into()), | ||||||
|  |             None, | ||||||
|  |             Self::get_ring_buffer(dma, dma_buf, request, sub_block, config.tx_rx), | ||||||
|             config, |             config, | ||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
| @ -704,12 +818,21 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { | |||||||
|         config: Config, |         config: Config, | ||||||
|     ) -> Self { |     ) -> Self { | ||||||
|         T::enable(); |         T::enable(); | ||||||
|         T::reset(); | 
 | ||||||
|  |         // can't reset here because the other sub-block might be in use
 | ||||||
|  | 
 | ||||||
|  |         #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] | ||||||
|  |         { | ||||||
|  |             let ch = T::REGS.ch(sub_block as usize); | ||||||
|  |             ch.cr1().modify(|w| w.set_saien(false)); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         #[cfg(any(sai_v4))] |         #[cfg(any(sai_v4))] | ||||||
|         { |         { | ||||||
|             // Not totally clear from the datasheet if this is right
 |             // Not totally clear from the datasheet if this is right
 | ||||||
|             // This is only used if using SyncEnable::External
 |             // This is only used if using SyncEnable::External on the other SAI unit
 | ||||||
|  |             // Syncing from SAIX subblock A to subblock B does not require this
 | ||||||
|  |             // Only syncing from SAI1 subblock A/B to SAI2 subblock A/B
 | ||||||
|             let value: u8 = if T::REGS.as_ptr() == stm32_metapac::SAI1.as_ptr() { |             let value: u8 = if T::REGS.as_ptr() == stm32_metapac::SAI1.as_ptr() { | ||||||
|                 1 //this is SAI1, so sync with SAI2
 |                 1 //this is SAI1, so sync with SAI2
 | ||||||
|             } else { |             } else { | ||||||
| @ -735,7 +858,7 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { | |||||||
|             let ch = T::REGS.ch(sub_block as usize); |             let ch = T::REGS.ch(sub_block as usize); | ||||||
|             ch.cr1().modify(|w| { |             ch.cr1().modify(|w| { | ||||||
|                 w.set_mode(config.mode.mode(if Self::is_transmitter(&ring_buffer) { |                 w.set_mode(config.mode.mode(if Self::is_transmitter(&ring_buffer) { | ||||||
|                     TxRx::Transmiter |                     TxRx::Transmitter | ||||||
|                 } else { |                 } else { | ||||||
|                     TxRx::Receiver |                     TxRx::Receiver | ||||||
|                 })); |                 })); | ||||||
| @ -770,7 +893,7 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { | |||||||
|                 w.set_fsoff(config.frame_sync_offset.fsoff()); |                 w.set_fsoff(config.frame_sync_offset.fsoff()); | ||||||
|                 w.set_fspol(config.frame_sync_polarity.fspol()); |                 w.set_fspol(config.frame_sync_polarity.fspol()); | ||||||
|                 w.set_fsdef(config.frame_sync_definition.fsdef()); |                 w.set_fsdef(config.frame_sync_definition.fsdef()); | ||||||
|                 w.set_fsall(config.frame_sync_active_level_length.0 as u8); |                 w.set_fsall(config.frame_sync_active_level_length.0 as u8 - 1); | ||||||
|                 w.set_frl(config.frame_length - 1); |                 w.set_frl(config.frame_length - 1); | ||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
| @ -782,6 +905,10 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { | |||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
|             ch.cr1().modify(|w| w.set_saien(true)); |             ch.cr1().modify(|w| w.set_saien(true)); | ||||||
|  | 
 | ||||||
|  |             if ch.cr1().read().saien() == false { | ||||||
|  |                 panic!("SAI failed to enable. Check that config is valid (frame length, slot count, etc)"); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         Self { |         Self { | ||||||
| @ -795,6 +922,11 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     pub fn reset() { | ||||||
|  |         T::enable(); | ||||||
|  |         T::reset(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     pub fn flush(&mut self) { |     pub fn flush(&mut self) { | ||||||
|         let ch = T::REGS.ch(self.sub_block as usize); |         let ch = T::REGS.ch(self.sub_block as usize); | ||||||
|         ch.cr1().modify(|w| w.set_saien(false)); |         ch.cr1().modify(|w| w.set_saien(false)); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user