Skip to content

C7x Memory Map Reference

This describes the memory layout used by the standalone JTAG test harness (see DSP C++ Harness), defined in tests/ti-dsp-runtime/dsp-cpp/j722s/linker_c7x.cmd.

This is a separate, independent memory map from the firmware's unified DDR pool (see Firmware Design Deep-Dive) -- the two build targets are not related, and their DDR heap sizes genuinely differ (128 MB here vs. 352 MiB in the firmware). Don't cross-check numbers between the two; each is correct for its own linker script.

J722S C7x Memory Layout

The J722S C75 DSP has 2MB of L2 SRAM local to the core plus access to DDR memory. The linker command file (j722s/linker_c7x.cmd) defines the memory layout for standalone JTAG execution.

Code-in-DDR Mode (Default)

The default configuration places application code in DDR (cached via MMU) to maximize L2 SRAM for the TVM data heap. Only boot code and MMU init remain in L2.

L2 SRAM Regions (2MB at 0x7E000000)

Region Address Range Size Purpose
L2_VECS 0x7E000000 - 0x7E003FFF 16KB Interrupt/exception vectors
L2_SECVECS 0x7E004000 - 0x7E007FFF 16KB Secure vectors
L2_BOOT 0x7E008000 - 0x7E008FFF 4KB Boot code (_c_int00_secure)
L2_INIT 0x7E009000 - 0x7E018FFF 64KB Pre-MMU init code (.text:l2_init)
L2_DATA 0x7E019000 - 0x7E038FFF 128KB Data sections (.data, .bss, .cio)
L2_STACK 0x7E039000 - 0x7E068FFF 192KB Stack (.stack) - expanded
L2_SCRATCH 0x7E069000 - 0x7E1FFFFF 1.59MB TVM L2 pool (.tvm_l2_heap)
L2_AUX 0x7F000000 - 0x7F03BFFF 240KB Auxiliary storage (.l2aux)

Note: The standard malloc heap (.sysmem) has been moved to DDR to maximize L2 for the TVM runtime. This allows a larger stack (192KB vs 128KB) and keeps all of L2_SCRATCH available for TVM tensor allocations.

Key difference from code-in-L2 mode: Application code (.text) goes to DDR, freeing ~1.3MB additional L2 space for the TVM heap.

DDR Regions

Region Address Range Size Purpose
DDR_C7X_BOOT 0xAD200000 1KB DDR boot code
DDR_C7X_VECS 0xAD400000 16KB DDR vectors
DDR_C7X_SECVECS 0xAD600000 16KB DDR secure vectors
DDR_C7X_CODE 0xAD604000 - 0xAD803FFF 2MB Application code (cached via MMU)
DDR_SYSMEM 0xAD804000 - 0xAD843FFF 256KB Standard malloc heap (.sysmem)
DDR_C7X_MAIN 0xAD844000 - 0xB0FFFFFF ~55.7MB Model weights (.rodata.weights)
DDR_C7X_EXTENDED 0x108000000 - 0x10FFFFFFF 128MB TVM DDR heap (runtime tensors)

Note: DDR_C7X_EXTENDED uses high DDR above 4GB (virtual addresses 0x108000000+ map to physical 0x888000000+ per TI SDK memory map). This requires 8GB LPDDR4 and is verified by the TI RTOS SDK app_mem_map.h.

TVM Runtime Memory Pools

The TVM DSP runtime uses two memory pools configured via linker symbols:

Pool Region Address Range Size Usage
L2 (Fast) L2_SCRATCH 0x7E069000 - 0x7E1FFFFF 1.59MB Intermediate tensors, frequently accessed data
DDR (Main) DDR_C7X_EXTENDED 0x108000000 - 0x110000000 128MB Runtime tensor allocations, large outputs

Model weights are placed in DDR_C7X_MAIN (~55.7MB) via the .rodata.weights section, separate from the runtime heap.

Linker symbols (read by TVM runtime at initialization):

__TVM_DSP_L2_HEAP_START  = 0x7E069000
__TVM_DSP_L2_HEAP_END    = 0x7E200000
__TVM_DSP_DDR_HEAP_START = 0x108000000
__TVM_DSP_DDR_HEAP_END   = 0x110000000

Important: Memory Pool Separation

The TVM heaps must not overlap with .sysmem (standard malloc heap used by printf, fopen, etc.). Earlier versions had overlap issues causing memory corruption when printf's internal buffers overwrote TVM tensor data.

Current layout (correct, code-in-DDR mode): - .sysmem (malloc) → DDR_SYSMEM (0xAD804000, 256KB) - in low DDR - .stack → L2_STACK (0x7E039000, 192KB) - expanded - .rodata.weights → DDR_C7X_MAIN (0xAD844000, ~55.7MB) - model weights - TVM L2 pool → L2_SCRATCH (0x7E069000, 1.59MB) - TVM DDR pool → DDR_C7X_EXTENDED (0x108000000, 128MB) - in high DDR (>4GB)

Why use extended DDR for TVM heap: The J722S has 8GB LPDDR4 with high DDR addresses (0x108000000+) mapped via MMU. Using extended DDR for the TVM runtime heap frees DDR_C7X_MAIN for model weights (up to ~55.7MB), enabling larger models.

To customize the TVM pool locations, modify the linker symbols in linker_c7x.cmd. The runtime reads these symbols at initialization, so no library rebuild is needed.

Section Placement Summary

Section Region Description
.vecs L2_VECS Interrupt vector table
.text DDR_C7X_CODE Application code (cached via MMU)
.text:l2_init L2_INIT Pre-MMU init code (runs before DDR cached)
.const DDR_C7X_CODE Read-only constants (small)
.rodata.weights DDR_C7X_MAIN Model weights (up to ~55.7MB)
.data L2_DATA Initialized global data
.bss L2_DATA Zero-initialized data
.cio L2_DATA Console I/O buffer (printf)
.stack L2_STACK Program stack (192KB)
.sysmem DDR_SYSMEM Standard heap (malloc/free) - 256KB in DDR
.tvm_l2_heap L2_SCRATCH TVM fast memory pool (1.59MB)
.tvm_ddr_heap DDR_C7X_EXTENDED TVM main memory pool (128MB in high DDR)
.fardata DDR_C7X_MAIN Large data arrays

C7x MMU Configuration

The C7x DSP on J722S requires MMU (Memory Management Unit) configuration for cached and executable DDR access. The application is responsible for initializing the MMU before calling any TVM runtime functions.

Why MMU is Needed

Without proper MMU configuration, DDR memory accesses are: - Uncached (slow, every access goes to external memory) - Potentially non-executable (can't run code from DDR)

The MMU enables: - Cached DDR access for model weights and tensors - Executable DDR regions for code-in-DDR mode (maximizes L2 for data) - Proper memory attributes for L2 SRAM and peripheral regions

MMU Register Configuration

The MMU uses direct ECR (Extended Control Register) access, adapted from TI's edgeai-tidl-kernels approach:

Register ECR Value Description
SCR ECR784 0x80000000000000C1 System Control: MMU + caches enabled
TCR0 ECR785 0x0000000000002A21 Translation Control: 4KB granule, 2GB space
TBR0 ECR787 (page table addr) Translation Base: points to level 1 table
MAR ECR789 0x3D3D3D2915032A00 Memory Attributes: cacheable/device types

MAIR (Memory Attribute Indirection Register)

The MAR value packs 8 memory attribute configurations (MAIR0-7):

Index Value Description
MAIR0 0x00 Device-nGnRnE (strongly ordered device memory)
MAIR1 0x2A Write-Through No-Allocate
MAIR2 0x03 Device-nGnRE
MAIR3 0x15 Write-Through Allocate
MAIR4 0x29 Non-cacheable
MAIR5 0x3D Write-Back Read-Allocate Write-Allocate (normal cached)
MAIR6 0x3D Write-Back Read-Allocate Write-Allocate
MAIR7 0x3D Write-Back Read-Allocate Write-Allocate

Page Table Structure

The J722S implementation uses ARMv8-style 2-level page tables with 1GB L1 blocks and 2MB L2 blocks:

Level 1 (512 entries)         Level 2 (512 entries)
┌─────────────────────┐       ┌─────────────────────┐
│ [0] 0x00-0x3F: Dev  │ Block │                     │
│ [1] 0x40-0x7F: Tbl  │──────>│ MSMC (0x70): Cached │
│ [2] 0x80-0xBF: DDR  │ Block │ L2   (0x7E): Cached │
│ [3] 0xC0-0xFF: DDR  │ Block │ L2AUX(0x7F): Cached │
│ [4] 1.0-1.3G: DDR   │ Block │                     │
│ [5] 1.4-1.7G: DDR   │ Block └─────────────────────┘
└─────────────────────┘

Memory Regions

Region Address Range Size Attributes
Peripherals 0x00000000-0x3FFFFFFF 1GB Device, Non-Shareable
Secure Proxy 0x48000000-0x4FFFFFFF 128MB Device (for DMSC comm)
MSMC 0x70000000-0x703FFFFF 4MB Cached, Outer Shareable
L2 SRAM 0x7E000000-0x7E1FFFFF 2MB Cached, Non-Shareable
L2 AUX 0x7F000000-0x7F03FFFF 256KB Cached, Non-Shareable
DDR 0x80000000-0xFFFFFFFF 2GB Cached, Outer Shareable
DDR (ext) 0x100000000-0x17FFFFFFF 2GB Cached, Outer Shareable (TVM heap at 0x108000000)

Block Descriptor Attributes

Attribute Bits Values
Type [1:0] 0b01 = Block descriptor
AttrIndx [4:2] MAIR index (0-7)
NS [5] Non-Secure
AP [7:6] Access permissions (0b00 = RW)
SH [9:8] Shareability (0=NSH, 2=OSH, 3=ISH)
AF [10] Access Flag (must be 1)
Address [47:21] 2MB-aligned physical address (L2)

Shareability Considerations

  • Non-Shareable (NSH): Use for L2 SRAM which is local to each C75 core
  • Outer Shareable (OSH): Use for DDR and MSMC for multi-core coherency

MMU Source Files

The MMU implementation is in j722s/:

File Description
mmu.c MMU initialization with detailed comments
c75_asm.S Assembly functions for ECR register access
boot_c75.c Boot code that calls MmuP_init() before main()
linker_c7x.cmd Linker script with page table sections

Security Mode

The C7x runs in CXM=3 (RootSupervisor) mode when loaded via JTAG. This mode: - Has full access to MMU configuration registers - Can modify page tables and enable/disable MMU - Requires direct ECR register access (SDK MmuP functions may not work)

The runtime detects the security mode and reports it during initialization:

C7x security mode: CXM=3 (RootSupervisor)