Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

impl PeriAddress for I2sCore #683

Open
algesten opened this issue Sep 23, 2023 · 7 comments
Open

impl PeriAddress for I2sCore #683

algesten opened this issue Sep 23, 2023 · 7 comments

Comments

@algesten
Copy link
Contributor

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
Copy link
Contributor Author

(DMASet is also needed)

@burrbull
Copy link
Member

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

cc @YruamaLairba

@algesten
Copy link
Contributor Author

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
Copy link
Contributor Author

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
Copy link
Contributor Author

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

@YruamaLairba
Copy link
Contributor

@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

@explocion
Copy link

explocion commented Oct 25, 2023

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants