-
Notifications
You must be signed in to change notification settings - Fork 225
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
Request: better handling of DMA buffers for realtime audio using I2S #1062
Comments
Any pointers to a Rust HAL which implements things in a suitable way? Technically I'm not in favor of two buffers - we split the buffer into chunks anyway (which is why we currently require a minimal size of the buffer so we can split it into the default chunks). A chunk is the smallest region we can know of if it's owned by DMA or CPU. I'm also not sure if we can safely give mutable access to parts of the DMA buffer - that's why I'm asking for an implementation which does it |
I can't give you an example here, because I'm just familiar with STM32 which is doing things completely different since it does not have a link-list DMA but uses double buffering and half-transfer flags and interrupts.
That's the reason 2 buffers are needed: you cannot give access to the buffer that is currently transferred. It's even forbidden by the owner bit in the DMA control register. With circular buffers, you always need at least 2, otherwise a continuous transfer cannot be achieved. |
A pointer to an STM32 example would be still helpful. I know DMA works totally different there but would still be interesting
The owner bit is for a single descriptor (pointing to max 4095 bytes) - ideally for the circular transfer we would reference both buffers from the descriptor list which is technically the same thing Anyways thanks for listing your requirements - I think it makes clear what you want to achieve. We'll see how the implementation will look like |
If I understand the TRM correctly, you can also append the desciptor list on the fly. So one possible solution to make the handling more secure could be to remove the buffer that is currently filled by the CPU (or read in case when you receive data) and add it back to the lister later after the CPU has done its task. |
Sure, our hardware is quite flexible so many solutions are possible |
At least as far as I understand it: The From a hardware POV, it's not problematic in anyway to overwrite the buffer while it's being transferred though. This is actively done and very useful with framebuffers in the |
Background: realtime audio requires low latency, therefore small buffers (like 16-64 samples) are required. Also, with sample rates like 48kHz and above in combination with multichannel audio, copying of data should be avoided.
Currently, the
write_dma_circular()
method ofI2sTx
takes a single buffer which has to be of more the 4k size. Any new output data then has to be pushed into the buffer.The desired solution is to configure two independent buffers of any allowed size (1..4095) bytes that are transferred alternately. These can be of small size to allow low latency. The transfer API should then provide a mutable reference to the buffer that is currently not transferred by the DMA so that it can be filled with new data. Ideally, the API should provide both, a sync and an async method to accomplish this. The async method could work in conjunction with a waker called from a transfer complete interrupt.
The text was updated successfully, but these errors were encountered: