stm32f4xx-hal icon indicating copy to clipboard operation
stm32f4xx-hal copied to clipboard

impl PeriAddress for I2sCore

Open algesten opened this issue 1 year ago • 7 comments

Hi!

I'm trying to use DMA transfer going with a DualI2sDriver. I see PeriAddress is implemented for I2sDriver, but not for I2SCore (which you get in the dual case via DualI2sDriver::main() or DualI2sDriver::ext()). Is this deliberate or an omissions?

Happy to provide a PR if it should be implemented.

algesten avatar Sep 23 '23 07:09 algesten

(DMASet is also needed)

algesten avatar Sep 23 '23 07:09 algesten

I think it was just missed when dual mode added. PRs are welcome.

cc @YruamaLairba

burrbull avatar Sep 23 '23 08:09 burrbull

As I'm trying to make the PR, I realize an obstacle here is that DualI2sDriver::main()/ext() gives us a borrowed &mut I2sCore, which means the borrow checker won't let me use the main()/ext() separately in different Transfer::init_memory_to_peripheral/init_peripheral_to_memory

I2SCore is just an empty type placeholder, which means it wouldn't need to be &mut, so I assume the the mut is deliberately trying to stop me from doing something bad.

Wonder what is a good way forward? 🤔

algesten avatar Sep 23 '23 11:09 algesten

I've made an attempt in #684. To get around the borrowing problem, I made an extension trait DualI2sDmaTargetExt which only purpose is to make the &mut I2sCore an DualI2sDmaTarget that can be used in the DMA transfer.

Example:

        use hal::i2s::{DualI2s, DualI2sDmaTargetExt};

        let config = DualI2sDriverConfig::new_master()
            .direction(Transmit, Receive)
            .standard(Philips)
            .data_format(Data16Channel16)
            .master_clock(true)
            .request_frequency(96_000);

        let mut driver = config.dual_i2s_driver(peripheral);

        driver.main().set_tx_dma(true);
        driver.ext().set_rx_dma(true);

        let i2s2_tx = Transfer::init_memory_to_peripheral(
            dma1_streams.4,
            driver.main().dma_target(),
            i2s2_buf_tx,
            None,
            i2s_dma_config,
        );

        let i2s2_rx = Transfer::init_peripheral_to_memory(
            dma1_streams.3,
            driver.ext().dma_target(),
            i2s2_buf_rx,
            None,
            i2s_dma_config,
        );

The trick is in the dma_target() call when making the Transfer last.

algesten avatar Sep 23 '23 11:09 algesten

If this is a good way forward I'll write some more doc.

algesten avatar Sep 23 '23 11:09 algesten

@algesten: it's an omission, I find the current Transfer API is practically unusable for typical i2s usage or at least, it so much convenient to use Stream instead.

I2SCore is just an empty type placeholder, which means it wouldn't need to be &mut, so I assume the the mut is deliberately trying to stop me from doing something bad.

This is reasons of the '&mut' (and no '&')

  • All i2sCore methods require mutability, even for reading status or data since this alter flags.
  • I Wanted to prevent to "split" I2sCore from the dual peripheral, This would make it practically unusable

YruamaLairba avatar Sep 25 '23 11:09 YruamaLairba

it's an omission, I find the current Transfer API is practically unusable for typical i2s usage or at least, it so much convenient to use Stream instead.

Hi, I'm new to I2s, and I'm wondering what libraries on embedded system support stream.

explocion avatar Oct 25 '23 19:10 explocion