-
Notifications
You must be signed in to change notification settings - Fork 10
Configuring System Memory When Using Linux and SHARC Applications
The present document attempts to catalog the different types of memory and the default allocation of it on the ARM & SHARC cores on the the ADSP-SC5xx platforms.
- Level 1 (L1) - Small amount of memory in the core. It's fast, but private to the core
- Level 2 (L2) - Larger memory on chip. It's slower than L1 but shared between cores
- Level 3 (L3) - External memory chip via controller. Largest but slowest memory, shared between the cores
All memory can be accessed from all cores with exception of the ARM L1 cache. However, each memory space can only be allocated to a single core who becomes the owner of that memory and the project for that core is responsible for populating the memory. If multiple cores are allocated the same memory then corruption may occur.
Memory access properties such as cacheability and write permissions can be configured for each memory space within the MMU (ARM) or cache registers (SHARC). There is also support to restrict memory access using the Shared Memory Protection Unit (SPU) in hardware.
The Linker Description Files (LDF) on SHARC contain 3 sections:
- Input section - the section names that come from the source files indicating where the symbol is to be mapped e.g. seg_dmda for DM data
-
Memory sections - the names of the sections referring to the memory space e.g.
mem_L2B1P1_bw
for L2 memory block 1 - Output section - a mapping statement in the LDF which maps a series of input sections to a memory section
-
ARM
- L1 - Used as cache. Cannot be loaded directly for code/data.
-
SHARCs
- Each SHARC core has its own L1
- This can be configured as a combination of cache, code and data
- SHARC L1 is typically used for low latency audio algorithms
- This is what makes SHARC popular
The L2 RAM is memory block that is physically shared by all the cores. This can be used for anything. Out of the box its split 4 ways ARM, SHARC1, SHARC2 and a small section is reserved for inter-core communication (MCAPI or RPMsg). Note that by default Linux does not allocate any memory from the L2 region reserved for it.
Similarly the L3 memory is physically shared by all the cores. It is possible to create a region of shared L3 memory. EZ-KITs vary from model to model. But generally, they have lots. By default, this is split evenly between the cores, no shared memory.
The default memory split attempts to split the memory evenly between the available cores, whilst satisfying any restrictions faced by that core. It's likely that your application will have different memory requirements for each core, so you may need to adjust the split manually.
L2 memory also includes:
- a small shared memory at the start of L2 for inter-core communication (ICC)
- an 8K scratch memory at the end of L2 for the boot ROM's working area. This space must be reserved if any boot ROM API's are invoked at run-time, or if the processor is reset. Otherwise, it's possible to use this space for data which isn't initialized at load time (such as a temporary buffer).
The default memory allocation for your device can be seen in $Your_CCES_installation_folder/SHARC/ldf/<DEVICE>.ldf
For ADSP-SC584 (1xARM + 2xSHARC) the description for the L2 split starts at line 420:
// ----------------------- L2-RAM (2 MBit) -----------------------------------
// The 256 KB L2 memory has 8 banks partitioned as follows:
// bank1 2008_0000 2008_7FFF 4KB uncached - ICC (mem_L2B1P1_bw)
// 4KB uncached - MCAPI ARM (mem_L2B1P2_bw)
// 4KB uncached - MCAPI SHARC1 (mem_L2B1P3_bw)
// 4KB uncached - MCAPI SHARC0 (mem_L2B1P4_bw)
// 16KB uncached - ARM (mem_L2B1P5_bw)
// bank2 2008_8000 2008_FFFF 32KB cached - ARM (mem_L2B2toB4_bw)
// bank3 2009_0000 2009_7FFF 32KB cached - ARM (mem_L2B2toB4_bw)
// bank4 2009_8000 2009_FFFF 32KB cached - ARM (mem_L2B2toB4_bw)
// bank5 200A_0000 200A_7FFF 32KB cached - SHARC1 (mem_L2B5B6_bw)
// bank6 200A_8000 200A_FFFF 32KB cached - SHARC1 (mem_L2B5B6_bw)
// bank7 200B_0000 200B_7FFF 32KB cached - SHARC0 (mem_L2B7B8_bw)
// bank8 200B_8000 200B_DFFB 24KB cached - SHARC0 (mem_L2B7B8_bw)
// 200B_DFFC 200B_FFFF 8KB cached boot code working area
This is immediately followed by the description for L3 as follows:
// ----------------------- 256MB DMC0(DDR-A) ---------------------------------
// 256MB DMC0 DDR SDRAM memory is partitioned as follows:
// DDR-A part1 : SHARC0 NW code, 3MB
// DDR-A part2 : SHARC1 NW code, 3MB
// DDR-A part3 : SHARC0 data, 4MB
// DDR-A part4 : SHARC0 VISA code, 3MB (reduced for 20000019 workaround)
// DDR-A part5 : SHARC1 VISA code, 3MB (reduced for 20000019 workaround)
// DDR-A part6 : SHARC0 data, 62MB
// DDR-A part7 : SHARC1 data, 66MB
// DDR-A part8 : ARM 112MB
Code execution addresses are restricted for the SHARC cores so the memory allocated cannot be increased or moved. |
❗ ATTENTION |
---|
The toolchains have no awareness of the mapping used on other cores, so care needs to be taken to ensure that any changes in mapping are reflected across all cores being used. Failure to do so may either result in wasted memory due to gaps or corruption due to overlaps. |
All of L2 can be addressed directly from U-Boot and no specific allocation is necessary. To run U-Boot from L2 it is necessary to modify CONFIG_SYS_TEXT_BASE
in /include/configs/<BOARD>.h
. See Allocating L3 to ARM for further instructions.
L2 allocation is controlled by the device tree source file. It is set up for each family platform as sram sections. The device tree source files are located in the Linux source repo in the /arch/arm/boot/dts
directory. The file will be named as <DEVICE_FAMILY>.dtsi
so for SC584 it is sc58x.dtsi
. There are two sections (sram0
and sram1
)
sram0: sram-icc@20080000 {
compatible = "mmio-sram";
#address-cells = <1>;
#size-cells = <1>;
reg = <0x20080000 0x1000>;
ranges = <0 0x20080000 0x1000>;
};
sram1: sram-icc@20084000 {
compatible = "mmio-sram";
#address-cells = <1>;
#size-cells = <1>;
reg = <0x20084000 0x3B000>;
ranges = <0 0x20084000 0x3B000>;
};
Due to virtual memory mapping in Linux it is necessary to specify which sections the sram memory map driver should utilize.
The LDF files for the SHARC cores provide a mapping for each of the split blocks (as described above):
mem_L2B1P1_bw { TYPE(BW RAM) START(0x20000000) END(0x20003fff) WIDTH(8) }
mem_L2B1P2_bw { TYPE(BW RAM) START(0x20004000) END(0x20007fff) WIDTH(8) }
mem_L2B1P3_bw { TYPE(BW RAM) START(0x20008000) END(0x2000bfff) WIDTH(8) }
mem_L2B1P4_bw { TYPE(BW RAM) START(0x2000c000) END(0x2000ffff) WIDTH(8) }
mem_L2B1P5_bw { TYPE(BW RAM) START(0x20010000) END(0x2001ffff) WIDTH(8) }
mem_L2B2toB4_bw { TYPE(BW RAM) START(0x20020000) END(0x2007ffff) WIDTH(8) }
mem_L2B5B6_bw { TYPE(BW RAM) START(0x20080000) END(0x200bffff) WIDTH(8) }
mem_L2B7B8_bw { TYPE(BW RAM) START(0x200c0000) END(0x200fdffb) WIDTH(8) }
mem_L2B8BC_bw { TYPE(BW RAM) START(0x200fdffc) END(0x200fffff) WIDTH(8) }
Followed by 2 macros which are used to determine which blocks are used for cached and non-cached memory in the LDF:
#define MY_L2_UNCACHED_MEM mem_L2B1P4_bw
#define MY_L2_CACHED_MEM mem_L2B7B8_bw
To change the mapping for L2, while maintaining some cached/non-cached areas, just change the start/end addresses of the applicable blocks to match the memory available.
To remove a mapping entirely from L2, the macros should be removed and any output sections referring to the macros should be either be removed or should be updated to refer to another memory section.