Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

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

I2S peripheral driver for STM32F407 #611

Closed
ledneczki opened this issue Apr 11, 2021 · 19 comments
Closed

I2S peripheral driver for STM32F407 #611

ledneczki opened this issue Apr 11, 2021 · 19 comments

Comments

@ledneczki
Copy link

Hi modm Community!

I have a STM32F4 discovery board and I would like to do some audio related development on it. I came across your great embedded framework, and I would like to use it for my project. I see, that SPI driver is already implemented, but the I2S support is not there yet. So, I would like to add I2S support for this discovery board.

I saw on the modm website that before contributing it is advised to get in contact with you. What do you think about my initiative? Do you have some hints before starting implementing the driver?

Thank you in advance!

@rleh
Copy link
Member

rleh commented Apr 11, 2021

Hi @ledneczki,
welcome and glad to hear you want to contribute an I²S driver.

It's probably best to start writing the I²S driver and ask any questions that come up here.

To start with I²S for STM32F4 you should read STs reference manual (if not already done) and have a look at our SpiHal (documentation) and SpiMaster (documentation) drivers.

I'm not sure how the API for I²S should look like, depending on this I see two options:

  • Extend SpiMaster with the necessary configuration options and/or additional functions
  • Create a new I2sMaster class similar to SpiMaster that provides the API for I²S and uses SpiHal to access the hardware.

In both cases you will probably have to modify SpiHal.
DMA is currently not supported on STM32F4, so just ignore it for now (if possible).

@chris-durand
Copy link
Member

chris-durand commented Apr 11, 2021

Welcome @ledneczki, your contribution is very much appreciated.

I am not sure trying to integrate I²S into the present SpiHal and SpiMaster classes is the best way to go. Most settings inside SpiHal are not meaningful for I²S. For example SPI clock settings, prescalers, master mode, data length and frame formats in the SPI CR1 and CR2 registers are completely ignored in I²S mode.

On the other hand a lot of similar options with the same names exist that are configured in entirely different registers and have other sets of permitted values. This overload of terms would make a joined interface quite confusing to use.

In my opinion, the best option to get started would be creating a low-level I2sHal interface similar to SpiHal first. It's purpose is to provide a type safe interface to peripheral registers. If you have that, you can get the peripheral to actually do things and evaluate how to continue. You can make the class inherit from SpiBase like SpiHal to reuse already present flag definitions.

For designing the higher level interface on top of the Hal class, keep in mind that audio is hard-realtime. Any gap in transmissions will create unwanted click and pop noises. The buffer in the peripheral is just one sample for one channel (or half a sample in 24bit mode). For 48 kHz, 16 bit, 2 channel audio playback and 168 MHz F407 max. CPU clock it means you have to put a sample into the peripheral TX buffer every 1750 cpu cycles.

Depending on your application and the kind of processing you do that could be challenging. That's why audio is mostly processed in units of blocks and not single samples. On the STM32 you would ideally use DMA in circular double-buffered mode. Then you have 2 buffers of which one can be filled by the application while the other one is being accessed by the I²S peripheral. Unfortunately, we don't support that (yet) for STM32F4. I would advise you to start without DMA unless absolutely necessary. It can be added in a second step.

Don't be afraid to ask any questions. The modm code generation is quite different to what most people do and the documentation on that is not that extensive. Feel free to open a draft pull request early if you are stuck.

@ledneczki
Copy link
Author

ledneczki commented Apr 12, 2021

Thank you @rleh and @chris-durand for your great input! I will do according to your suggestions.

I also agree that for audio, DMA is needed, but then let's start at the beginning and get that I2S peripheral up and running!

@ceremcem
Copy link
Contributor

I didn't want to open a separate issue for STM32F407 DMA support. I don't know what I'm capable of in C++, so I can't say I could implement anything really. However, I need that. Should I change the MCU family I'm using, or was it a work in progress so it's worth to wait for it?

@chris-durand
Copy link
Member

I am not aware of anyone working on that right now but I would guess it might happen with the I²S driver being there. What is your application you would like to use DMA for?

Don't be discouraged if you would like to try implementing it yourself. The C++ side of it isn't actually that hard. I don't remember how different the F4 DMA is to the ones we support right now, I guess the main work is adapting the present driver to the hardware specifics. The API will be very similar. modm-devices already has the information for F4 on DMA streams and channels. We are here to help and are happy about features being added to modm. So if you would like to try it and need some hints to get started, please feel free to ask.

At least I expect STM32G4 DMA to happen within the next 2 weeks because I have an application where it would be beneficial.

@rleh
Copy link
Member

rleh commented Apr 16, 2021

I'm have currently some uncommited changes on my computer trying to get DMA running on STM32F4/F7, but the code does not compile yet and is completely untested. I will focus in the next weeks to test it on a Nucleo-F429ZI.
I can't give an estimate if this will be ready next week or 2 months from now.

@salkinium
Copy link
Member

What they^ said, plus also consider configuring DMA directly via the CMSIS, taking inspiration from our driver perhaps. It may be faster and better to understand for you, especially depending on your use-case.

@rleh
Copy link
Member

rleh commented Apr 16, 2021

At least I expect STM32G4 DMA to happen within the next 2 weeks because I have an application where it would be beneficial.

Nice! Does STM32G4 use the dma-stream-channel or the dma-channel(-request) IP?

@chris-durand
Copy link
Member

At least I expect STM32G4 DMA to happen within the next 2 weeks because I have an application where it would be beneficial.

Nice! Does STM32G4 use the dma-stream-channel or the dma-channel(-request) IP?

dma-mux like H7

@ceremcem
Copy link
Contributor

That's the spirit! You are very encouraging. Okay, I'll see what I can do.

@ceremcem
Copy link
Contributor

ceremcem commented Apr 17, 2021

What is your application you would like to use DMA for?

I need to implement XY2-100 protocol in a faster way (bit banging is very slow ATM) which uses clock-data protocol in the data-link layer. It's just like SPI, but I need 3 MOSI and 2MISO channels.

@salkinium
Copy link
Member

Ok, but then the modm API won't help you much, you need to bit-bang this via timer-triggered DMA transfers to/from GPIO.
Here is a 14-port parallel UART on the STM32F407 using that technique, you can adapt this for you needs: https://gist.github.com/salkinium/001beaad049b3a58ac21be20b2177398

You won't need the asynrchonous RX processing, you can read the GPIO synchronously with the clock, so it's a little easier for you. Note that only DMA2 can access the GPIO registers, and only Timer1 and Timer8 can trigger DMA2!!!

@ledneczki
Copy link
Author

I am currently facing an obstacle, and I would need your help to clear it.
Currently if I execute lbuild discover from the root of my example project (which is going to make use of I2S) I get the following error message:

ERROR: Cannot resolve name 'modm:platform:i2s:3' of type Module!

Still the discovery finishes and I can already see the I2S module, but currently no instances of the perhiperal are listed.

I have found a file, called modm/ext/modm-devices/modm_devices/resources/devices/stm32/stm32f4-05_07_15_17.xml. Here I can see that the instaces are specified below this line: <driver name="i2s" type="stm32-v2.2">. If I delete here, the "-v2.2" piece, then I get the instances showing up during discvoery, but I guess this is not the way to go. :) Where should I specify that I would like to use this v2.2 to get the I2S instances?

@rleh
Copy link
Member

rleh commented Apr 20, 2021

Could you open a "Draft" Pull Request with your code?
Then we can all see the code there, try it out and comment inline in the code and help you better.

@salkinium
Copy link
Member

You're probably missing a * at the end of the version match: for example env.has_driver("i2s:stm32*"). Opening a Draft PR is the best way to help you though.

@ledneczki
Copy link
Author

I have opened a draft pull request, so you can see where I am standing now. @salkinium indeed, it was the problem. Thank you for the good hint!

@ceremcem
Copy link
Contributor

ceremcem commented May 2, 2021

FYI: I have a fully working example of GPIO pin usage via DMA: here. I'm going to port the DMA settings directly into my Modm code.

@rleh
Copy link
Member

rleh commented May 9, 2021

@ledneczki The DMA implementation for STM32F4 and STM32F7 is here: #629
It's not yet functional, I'm currently debugging it...

@ledneczki
Copy link
Author

@rleh That sounds awesome! Audio projects would greatly benefint from it. Thanks for picking it up! In the meantime I am creating an example project that uses the external DAC on the STM32F4 Discovery board.

@modm-io modm-io locked and limited conversation to collaborators Sep 29, 2021

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Development

No branches or pull requests

5 participants