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)
|
||||||
|
fn get_af_types(mode: Mode, tx_rx: TxRx) -> (AFType, AFType) {
|
||||||
|
(
|
||||||
|
//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 {
|
match mode {
|
||||||
Mode::Master => (AFType::OutputPushPull, AFType::OutputPushPull),
|
Mode::Master => AFType::OutputPushPull,
|
||||||
Mode::Slave => (AFType::OutputPushPull, AFType::Input),
|
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…
Reference in New Issue
Block a user