Skip to content

Error allocating DMA buffers for I2SOut playback #10256

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

Closed
relic-se opened this issue Apr 15, 2025 · 4 comments · Fixed by #10278
Closed

Error allocating DMA buffers for I2SOut playback #10256

relic-se opened this issue Apr 15, 2025 · 4 comments · Fixed by #10278
Milestone

Comments

@relic-se
Copy link

CircuitPython version and board name

# Tested without error
Adafruit CircuitPython 9.2.7 on 2025-04-04; Waveshare RP2040-PiZero with rp2040
Adafruit CircuitPython 10.0.0-alpha.2 on 2025-04-04; Waveshare RP2040-PiZero with rp2040

# Tested with error
Adafruit CircuitPython 10.0.0-alpha.2-16-g8f7496c069 on 2025-04-15; Waveshare RP2040-PiZero with rp2040

Code/REPL

# waveshare rp2040-pizero with waveshare audio hat (requires i2c pull-ups)

import time
import board
import digitalio
import audiobusio
import synthio
from adafruit_wm8960 import WM8960

# Configure codec
codec = WM8960(board.I2C(), 11025, 16)
codec.volume = 1.0
codec.headphone = 0.5
codec.speaker = 0.0

# Configure I2S Output
audio = audiobusio.I2SOut(board.GP18, board.GP19, board.GP21) # ADC is GP20

# Setup synthio
synth = synthio.Synthesizer(sample_rate=codec.sample_rate, channel_count=2)
audio.play(synth)

note = synthio.Note(220, panning=-1.0)

while True:
    print("note on")
    synth.press(note)  # midi note 65 = F4
    time.sleep(0.5)
    synth.release(note)  # release the note we pressed
    print("note off")
    time.sleep(0.5)

Behavior

Traceback (most recent call last):
  File "<stdin>", line 21, in <module>
RuntimeError: Unable to allocate buffers for signed conversion

No audio output occurs.

Description

Additional information

I don't completely understand what's going on in port_realloc, but the primary difference I can discern against m_realloc is that is uses tlsf_realloc instead of realloc.

Any thoughts on this? @tannewt

@relic-se relic-se added the bug label Apr 15, 2025
@relic-se
Copy link
Author

@tannewt I can confirm that reverting the changes made to ports/raspberrypi/audio_dma.c (using m_realloc and m_free instead of port_realloc and port_free) fixes the error. If moving over to the port_... implementation is better for future-proofing, there is likely an underlying issue that needs to be fixed rather than reverting those changes.

@tannewt tannewt added the audio label Apr 16, 2025
@tannewt tannewt added this to the 10.0.0 milestone Apr 16, 2025
@tannewt
Copy link
Member

tannewt commented Apr 16, 2025

I suspect this is due to the Python VM heap taking up most of the outer heap (allocated via port_malloc using tlsf). It might be simplest to use m_malloc on RP2040 and port_malloc on RP2350. The goal is to put the buffers into internal RAM. DMAing from PSRAM gums up DMA.

@relic-se
Copy link
Author

I'm testing now on a Pimoroni Pico Plus 2 with 8MB of PSRAM. Is this basically what we're thinking of? I can get a PR up for this, but I want to do a bit more testing.

#ifdef PICO_RP2350
dma->buffer[0] = (uint8_t *)port_realloc(dma->buffer[0], max_buffer_length, true);
#else
dma->buffer[0] = (uint8_t *)m_realloc(dma->buffer[0],
    #if MICROPY_MALLOC_USES_ALLOCATED_SIZE
    dma->buffer_length[0], // Old size
    #endif
    max_buffer_length);
#endif
dma->buffer_length[0] = max_buffer_length;

if (dma->buffer[0] == NULL) {
    return AUDIO_DMA_MEMORY_ERROR;
}
#ifdef PICO_RP2350
port_free(dma->buffer[0]);
#else
#if MICROPY_MALLOC_USES_ALLOCATED_SIZE
m_free(dma->buffer[0], dma->buffer_length[0]);
#else
m_free(dma->buffer[0]);
#endif
#endif

dma->buffer[0] = NULL;
dma->buffer_length[0] = 0;

@tannewt
Copy link
Member

tannewt commented Apr 21, 2025

Yup! That's what I'm thinking.

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

Successfully merging a pull request may close this issue.

2 participants