Add RP2 support for dma_capable

This places the VM heap in PSRAM by default. audio_dma now directly
allocates its buffers to ensure they are dma_capable.
This commit is contained in:
Scott Shawcroft 2025-04-08 15:58:56 -07:00
parent 63815c5f45
commit abb3e9351b
No known key found for this signature in database
9 changed files with 45 additions and 45 deletions

View file

@ -324,8 +324,12 @@ void port_free(void *ptr) {
heap_caps_free(ptr);
}
void *port_realloc(void *ptr, size_t size) {
return heap_caps_realloc(ptr, size, MALLOC_CAP_8BIT);
void *port_realloc(void *ptr, size_t size, bool dma_capable) {
size_t caps = MALLOC_CAP_8BIT;
if (dma_capable) {
caps |= MALLOC_CAP_DMA;
}
return heap_caps_realloc(ptr, size, caps);
}
size_t port_heap_get_largest_free_size(void) {

View file

@ -227,12 +227,7 @@ audio_dma_result audio_dma_setup_playback(
max_buffer_length /= dma->sample_spacing;
}
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);
dma->buffer[0] = (uint8_t *)port_realloc(dma->buffer[0], max_buffer_length, true);
dma->buffer_length[0] = max_buffer_length;
if (dma->buffer[0] == NULL) {
@ -240,12 +235,7 @@ audio_dma_result audio_dma_setup_playback(
}
if (!single_buffer) {
dma->buffer[1] = (uint8_t *)m_realloc(dma->buffer[1],
#if MICROPY_MALLOC_USES_ALLOCATED_SIZE
dma->buffer_length[1], // Old size
#endif
max_buffer_length);
dma->buffer[1] = (uint8_t *)port_realloc(dma->buffer[1], max_buffer_length, true);
dma->buffer_length[1] = max_buffer_length;
if (dma->buffer[1] == NULL) {
@ -439,21 +429,11 @@ void audio_dma_init(audio_dma_t *dma) {
}
void audio_dma_deinit(audio_dma_t *dma) {
#if MICROPY_MALLOC_USES_ALLOCATED_SIZE
m_free(dma->buffer[0], dma->buffer_length[0]);
#else
m_free(dma->buffer[0]);
#endif
port_free(dma->buffer[0]);
dma->buffer[0] = NULL;
dma->buffer_length[0] = 0;
#if MICROPY_MALLOC_USES_ALLOCATED_SIZE
m_free(dma->buffer[1], dma->buffer_length[1]);
#else
m_free(dma->buffer[1]);
#endif
port_free(dma->buffer[1]);
dma->buffer[1] = NULL;
dma->buffer_length[1] = 0;
}

View file

@ -20,7 +20,7 @@ typedef enum {
typedef struct {
mp_obj_t sample;
uint8_t *buffer[2];
uint8_t *buffer[2]; // Allocated through port_malloc so they are dma-able
size_t buffer_length[2];
uint32_t channels_to_load_mask;
uint32_t output_register_address;

View file

@ -4,6 +4,7 @@
//
// SPDX-License-Identifier: MIT
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
@ -89,8 +90,7 @@ extern uint32_t _ld_itcm_size;
extern uint32_t _ld_itcm_flash_copy;
static tlsf_t _heap = NULL;
static pool_t _ram_pool = NULL;
static pool_t _psram_pool = NULL;
static tlsf_t _psram_heap = NULL;
static size_t _psram_size = 0;
#ifdef CIRCUITPY_PSRAM_CHIP_SELECT
@ -245,10 +245,9 @@ static void _port_heap_init(void) {
uint32_t *heap_bottom = port_heap_get_bottom();
uint32_t *heap_top = port_heap_get_top();
size_t size = (heap_top - heap_bottom) * sizeof(uint32_t);
_heap = tlsf_create_with_pool(heap_bottom, size, 64 * 1024 * 1024);
_ram_pool = tlsf_get_pool(_heap);
_heap = tlsf_create_with_pool(heap_bottom, size, size);
if (_psram_size > 0) {
_psram_pool = tlsf_add_pool(_heap, (void *)0x11000000, _psram_size);
_psram_heap = tlsf_create_with_pool((void *)0x11000000, _psram_size, _psram_size);
}
}
@ -257,15 +256,31 @@ void port_heap_init(void) {
}
void *port_malloc(size_t size, bool dma_capable) {
if (!dma_capable && _psram_size > 0) {
void *block = tlsf_malloc(_psram_heap, size);
if (block) {
return block;
}
}
void *block = tlsf_malloc(_heap, size);
return block;
}
void port_free(void *ptr) {
tlsf_free(_heap, ptr);
if (((size_t)ptr) < SRAM_BASE) {
tlsf_free(_psram_heap, ptr);
} else {
tlsf_free(_heap, ptr);
}
}
void *port_realloc(void *ptr, size_t size) {
void *port_realloc(void *ptr, size_t size, bool dma_capable) {
if (_psram_size > 0 && ((ptr != NULL && ((size_t)ptr) < SRAM_BASE) || (ptr == NULL && !dma_capable))) {
void *block = tlsf_realloc(_psram_heap, ptr, size);
if (block) {
return block;
}
}
return tlsf_realloc(_heap, ptr, size);
}
@ -279,12 +294,13 @@ static bool max_size_walker(void *ptr, size_t size, int used, void *user) {
size_t port_heap_get_largest_free_size(void) {
size_t max_size = 0;
tlsf_walk_pool(_ram_pool, max_size_walker, &max_size);
if (_psram_pool != NULL) {
tlsf_walk_pool(_psram_pool, max_size_walker, &max_size);
tlsf_walk_pool(tlsf_get_pool(_heap), max_size_walker, &max_size);
max_size = tlsf_fit_size(_heap, max_size);
if (_psram_heap != NULL) {
tlsf_walk_pool(tlsf_get_pool(_psram_heap), max_size_walker, &max_size);
max_size = tlsf_fit_size(_psram_heap, max_size);
}
// IDF does this. Not sure why.
return tlsf_fit_size(_heap, max_size);
return max_size;
}
safe_mode_t port_init(void) {

View file

@ -227,7 +227,7 @@ void port_free(void *ptr) {
tlsf_free(_heap, ptr);
}
void *port_realloc(void *ptr, size_t size) {
void *port_realloc(void *ptr, size_t size, bool dma_capable) {
return tlsf_realloc(_heap, ptr, size);
}
#endif

View file

@ -151,7 +151,7 @@ void port_free(void *ptr) {
tlsf_free(heap, ptr);
}
void *port_realloc(void *ptr, size_t size) {
void *port_realloc(void *ptr, size_t size, bool dma_capable) {
return tlsf_realloc(heap, ptr, size);
}

View file

@ -21,7 +21,7 @@
#include <stdlib.h>
#define port_free free
#define port_malloc(sz, hint) (malloc(sz))
#define port_realloc realloc
#define port_realloc(ptr, size, dma_capable) realloc(ptr, size)
#else
#include "supervisor/port_heap.h"
#endif
@ -48,7 +48,7 @@ static void *scratchpad_alloc(size_t sz) {
} else {
if (scratchpad) {
if (sz > scratchpad_size) {
void *tmp = port_realloc(scratchpad, sz);
void *tmp = port_realloc(scratchpad, sz, false);
if (!tmp) {
port_free(scratchpad);
scratchpad = NULL;

View file

@ -24,6 +24,6 @@ void *port_malloc(size_t size, bool dma_capable);
void port_free(void *ptr);
void *port_realloc(void *ptr, size_t size);
void *port_realloc(void *ptr, size_t size, bool dma_capable);
size_t port_heap_get_largest_free_size(void);

View file

@ -42,7 +42,7 @@ MP_WEAK void port_free(void *ptr) {
tlsf_free(heap, ptr);
}
MP_WEAK void *port_realloc(void *ptr, size_t size) {
MP_WEAK void *port_realloc(void *ptr, size_t size, bool dma_capable) {
return tlsf_realloc(heap, ptr, size);
}