Rockbox plugin memory layout
A plugin contains following segments:
.header |
The plugin header structure (see apps/plugin.h) |
.text |
Executable code |
.rodata |
Initialised read only data (e.g. string constants or const structs) |
.data |
Initialised data (e.g. global variables with assignment) |
.bss |
Not initialised data (e.g. global variables without assignment) |
There are also some special segments that contain data that are eventually loaded to IRAM:
.iram |
Consists of .icode (executable code in IRAM), .irodata (initialised read only data in IRAM), .idata (initialised data in IRAM) |
.ibss |
Not initialised data in IRAM |
IRAM is a special memory area (fixed addresses) that can be accessed by the CPU very quickly. If a variable must be read or modified very often it should be placed to IRAM. This can be made by adding the following attributes to the declaration:
- For a variable: IDATA_ATTR
- For a function: ICODE_ATTR
Examples:
- static struct dsp_config *dsp IDATA_ATTR = audio_dsp;
- static void pcmbuf_callback(unsigned char** start, size_t* size) ICODE_ATTR;
Following symbols are declared during the linkage (see plugins/plugin.lds):
plugin_start_addr |
Start address of the .header section. Since .header is the first section (see below) this is also the address where the plugin is loaded |
iramcopy |
Address where the .iram section of the plugin is loaded into memory. This is iimediately after the end of the .data section |
iramstart |
Start address of the plugin's .iram section (relocation address). |
iramend |
End address of the plugin's .iram section (relocation address). iramend-iramstart will give the size of the plugin's read only data (including code and vars). |
iedata |
Start address of the plugin's .ibss section (relocation address) |
iend |
End address of the plugin's .ibss section (relocation address). iend-iedata will give the size of the plugin's .ibss section |
plugin_bss_start |
Start address of the plugin's .bss section |
plugin_end_addr |
End address of the plugin's .bss section. plugin_end_addr- plugin_bss_start will give the size of the plugin's .bss section. Since .bss is the last section (see below) this is also the address where plugin ends when it's loaded into the RAM |
The relocation address of the .iram section is the start of the IRAM area in the RAM. But when the plugin is loaded, its .iram section is loaded to another address (iramcopy).
The sections described above are laid out in memory as follows (this is how the RAM area into which the plugin is loaded looks like after the plugin has been loaded to RAM; this RAM area is actually the buffer pluginbuf, see apps/plugin.c):
.header |
← plugin_start_addr |
.text |
|
.rodata |
|
.data |
|
.iram
|
← iramcopy |
.ibss |
|
.bss
|
← plugin_bss_start ← plugin_bss_end |
If the plugin makes use of IRAM (code or data), one of the first actions in the plugin code should be a call to PLUGIN_IRAM_INIT(api). This copies the contents of the plugin's .iram section (which is pointed to by iramcopy) to the IRAM area and then zeroes out the area of RAM that contained the plugin's .iram and .ibss sections. After the call, the arrays iramcopy (its size is iramend-iramstart) and iedata (its size is iend-iedata) can be used by the plugin at will. If the plugin doesnÂt make use of IRAM, iramend will be equal to iramstart and iend will be equal to iedata.
After the call to PLUGIN_IRAM_INIT(api), the RAM looks as follows:
Lower addresses |
IRAM |
Contents of the plugin's .iram section |
Not initialised area, size=size of plugin's .ibss |
... (Rest of IRAM) |
"Normal" memory |
... (Rockbox code, etc.) |
.header (here the pluginbuf starts) |
.text |
.rodata |
.data |
Zeroed out area, size=size of .iram (contained .iram before the call, can now be used at will) |
Zeroed out area, size=size of .ibss (contained .ibss before the call, can now be used at will) |
.bss |
... (Rest of RAM) |
The call to PLUGIN_IRAM_INIT(api) is not made by the plugin loader but must be made by the plugin itself because if the plugin uses IRAM the music playback must be stopped (music playback also uses IRAM). So the plugin has a chance e.g. to ask the user whether it would be OK to stop the playback and start the plugin. If the call would be made by the plugin loader, music playback would unconditionally stopped. It's assumed that a programmer who's advanced enough to use IRAM in the plugin will be also careful enough and will not forget to call PLUGIN_IRAM_INIT(api).
Copyright © by the contributing authors.