Different ways to allocate RAM usage for your feature
Rockbox has a "No Malloc" policy you can read about at WhyNoMalloc but sometimes you really do need to grab some buffer possibly temporarily. This page will explain the different methods available.
Compile-time RAM layout
This As an example, this list shows the sections in a compiled
rockbox.elf, indicating how RAM is allocated at compile-time. The section arrangment arrangement varies somewhat between platforms and is determined by the linker script (
firmware/target/arm/as3525/app.ldsin this case, for the Sansa e200v2). This varies somewhat between platforms. The interesting parts for memory allocation are audiobuf, codecbuf, and pluginbuf.
| 32 B || .vectors || ARM interrupt vectors |
| 460 KiB || .text || Machine code |
| 102 KiB || .rodata || Read-only (|
const) global data
| 8 KiB || .data || Global data |
| 8 KiB || .stack ||Stack for the initial thread |
| 384 KiB || .bss || Global data initialized with zero |
| 5679 KiB || audiobuf ||Audio buffer for audio and/or miscellaneous data |
| 1024 KiB || codecbuf ||Codec buffer for codecs and their data |
| 512 KiB || pluginbuf ||Plugin buffer for plugins and their data |
| 7 KiB || .iram || Machine code and global data (.icode, .irodata, .idata), in fast IRAM |
| 97 KiB || .ibss || Global data initialized with zero, in fast IRAM |
Allocate on the Heap
When a plugin is loaded, its code and data go in the start of pluginbuf. Codecs work the same way.
This is the easiest way, (i.e add a global variable "static char my_buffer[BUFFER_SIZE]" to your file.c)
By far the easiest method:
- Easy to do
- available in plugins and codecs (up to the plugin/codec buffer size)
static char my_buffer[BUFFER_SIZE];
This can be used anywhere. In a codec or plugin, space will be reserved in codecbuf or pluginbuf until the codec/plugin is unloaded. Otherwise, space will be reserved permanently in .data, .rodata, or .bss.
- potentially wastes RAM Easy, fast, no overhead.
- not nice if the feature isnt common Can't be freed or resized.
- Size must be known at compile-time.
Allocate on boot up (buffer_alloc(size_t size) )
Allocate from soundbuf
Next easiest way. call buffer_alloc() in your "init" method and make sure thats calle before playback starts.
char *my_buffer = buffer_alloc(BUFFER_SIZE);
This takes some space from the front of soundbuf. It can't be used by plugins or codecs, since it can't be freed. This method is useful when the size required is known at boot-time.
- can allocate exactly as much as you need Easy, fast, no overhead.
- If the feature is disabled no RAM needs to be allocate Can't be freed or resized.
- Playback must be stopped to allocate more.
Cons: Use the rest of the codec/plugin buffer
- RAM cannot be deallocted or resized
- Playback must be stopped to allocate more
// In codec:
void *my_buffer = ci->codec_get_buffer(&size_available);
// In plugin:
void *my_buffer = rb->plugin_get_buffer(&size_available);
Steal a Buffer
This is used by codecs/plugins to get the rest of the codec/plugin buffer. This space is reserved for the codec/plugin anyway, so you may as well use it!
Temporarily steal the talk/plugin/audio buffer, each has its own size and cons...
- Easy, fast, no overhead.
- Limited to the size left in the buffer, which depends on the platform.
Talk Steal the sound buffer ( talk_buffer_steal() )
Plugin Buffer ( plugin_get_buffer() )
void *my_buffer = rb->plugin_get_audio_buffer(&size_available);
If a plugin stops playback, it can use the sound buffer.
- Lots of space.
- Playback must be stopped the entire time the sound buffer is used.
- cannot start a plugin while the buffer is stolen
- the remaining buffer may not be large if a pluign is already running
Audio Buffer ( plugin_get_audio_buffer() )
- playback needs to be stopped, but you can have up to ~30Mb on some targets
dynamic allocation like "malloc()" (bufalloc())
Most frowned-on method of allocation, use this carefully... The buffer is allocated as a handle in the playback buffer and could be moving around the buffer as playback advances.
- free/resize able
- playback doesnt need to be stopped
- the buffer may move, so you HAVE to call bufgetdata() to use the buffer
- might fail if there is no room on the playback buffer
Copyright © by the contributing authors.