K230 DDR Memory Layout¶
1. Overview¶
The K230 is a dual-core RISC-V SoC with 512 MB DDR (0x00000000 - 0x1FFFFFFF). The memory is partitioned among three major consumers:
- RT-Smart (Big Core, C908) - real-time OS with MPP media framework
- Linux (Little Core, C908) - general-purpose Linux with rootfs
- MMZ (Media Memory Zone) - shared media buffer pool managed by MPP
The memory boundaries are defined at build time in k230_sdk/src/big/mpp/include/comm/k_autoconf_comm.h and cannot be changed at runtime.
2. DDR Physical Memory Map¶
Physical Address Size Region
========================================================================
0x00000000 +---------+
| Reserved| 1 MB SoC reserved (boot ROM scratch area)
0x00100000 +---------+
| IPCM | 1 MB Inter-core communication (shared memory)
0x00200000 +---------+
| |
| RT-Smart| 126 MB Big Core OS (kernel + heap + pages)
| |
0x08000000 +---------+
| |
| Linux | 128 MB Little Core OS (OpenSBI + kernel)
| |
0x10000000 +---------+
| |
| MMZ | ~252 MB Media Memory Zone (MPP buffers)
| |
0x1FBFF000 +---------+
| Guard | ~4 MB Tail guard / unused
0x20000000 +---------+
Total: 512 MB
Source: k_autoconf_comm.h¶
| Define | Value | Meaning |
|---|---|---|
CONFIG_MEM_TOTAL_SIZE |
0x20000000 |
512 MB total DDR |
CONFIG_MEM_IPCM_BASE |
0x00100000 |
IPCM region start |
CONFIG_MEM_IPCM_SIZE |
0x00100000 |
1 MB |
CONFIG_MEM_RTT_SYS_BASE |
0x00200000 |
RT-Smart region start |
CONFIG_MEM_RTT_SYS_SIZE |
0x07E00000 |
126 MB |
CONFIG_MEM_LINUX_SYS_BASE |
0x08000000 |
Linux region start |
CONFIG_MEM_LINUX_SYS_SIZE |
0x08000000 |
128 MB |
CONFIG_MEM_MMZ_BASE |
0x10000000 |
MMZ region start |
CONFIG_MEM_MMZ_SIZE |
0x0FC00000 |
252 MB (config value) |
CONFIG_MEM_BOUNDARY_RESERVED_SIZE |
0x00001000 |
4 KB boundary guard |
3. IPCM (Inter-Processor Communication) Shared Memory¶
The 1 MB IPCM region at 0x00100000 is subdivided as follows:
0x00100000 +-----------+
| RTT->Linux| 512 KB Shared memory (node 1 -> node 0)
0x00180000 +-----------+
| Linux->RTT| 484 KB Shared memory (node 0 -> node 1)
0x001F9000 +-----------+
| Virt TTY | 16 KB Virtual TTY (serial over IPCM)
0x001FD000 +-----------+
| Reserved | 12 KB IPCM node descriptor + guard
0x00200000 +-----------+
Source: IPCM Config Files¶
RT-Smart side (k230_riscv_rtsmart_config):
node_id=1 # RT-Smart is node 1
top_role="slave"
shm_phys_1to0=0x100000 # RTT(1)->Linux(0) base
shm_size_1to0=0x80000 # 512 KB
shm_phys_0to1=0x180000 # Linux(0)->RTT(1) base
shm_size_0to1=0x79000 # 484 KB
virt_tty_phys=0x1f9000 # Virtual TTY base
virt_tty_size=0x4000 # 16 KB
Linux side (k230_riscv_linux_config):
The Linux side does not configure SHM addresses directly; the RT-Smart (slave) side owns the physical address definitions, and the Linux kernel IPCM driver reads them at runtime via the IPCM protocol.
4. RT-Smart Internal Memory Layout¶
RT-Smart occupies 0x00200000 - 0x07FFFFFF (126 MB). Its internal structure is:
0x00200000 +-----------+
| Bootloader| 128 KB U-Boot loads RT-Smart image here
0x00220000 +-----------+
| .text | Kernel code (linked at 0x220000)
| .rodata |
| .data |
| .bss |
__bss_end +-----------+
| |
| Kernel | 32 MB RT_HW_HEAP (rt_malloc pool)
| Heap |
| |
+0x2000000 +-----------+
| |
| Page | ~93 MB Page allocator (for LWP user processes)
| Allocator |
| |
0x07FFF000 +-----------+
| Reserved | 4 KB Boundary guard (MEMORY_RESERVED)
0x08000000 +-----------+
Source: board.h¶
#define MEMORY_RESERVED 0x1000
#define RAM_END 0x7fff000
#define RT_HW_HEAP_BEGIN ((void *)&__bss_end)
#define RT_HW_HEAP_END ((void *)(((rt_size_t)RT_HW_HEAP_BEGIN) + 0x2000000))
#define RT_HW_PAGE_START ((void *)((rt_size_t)RT_HW_HEAP_END + sizeof(rt_size_t)))
#define RT_HW_PAGE_END ((void *)(RAM_END))
Source: link.lds¶
MEMORY
{
SRAM : ORIGIN = 0x220000, LENGTH = 128895K
}
/* 0x00200000 - 0x00220000: Bootloader */
/* 0x00220000 - 0x08000000: Kernel */
5. Linux Internal Memory Layout¶
Linux occupies 0x08000000 - 0x0FFFFFFF (128 MB). The breakdown is:
0x08000000 +-----------+
| OpenSBI | 2 MB SBI firmware (supervisor binary interface)
0x08200000 +-----------+
| Linux | ~126 MB Kernel code + data + user memory
| Kernel | DTS declares: reg = <0x8200000 0x7dff000>
| |
| 0x0A000000: DTB placement address
| 0x0A100000: initrd placement address
| 0x0C800000: CMA region (52 MB)
| |
0x0FFFF000 +-----------+
| Guard | 4 KB Boundary
0x10000000 +-----------+
Source: k230_canmv.dts¶
&ddr {
reg = <0x0 0x8200000 0x0 0x7dff000>; /* 132,116,480 bytes = ~126 MB */
};
chosen {
linux,initrd-start = <0x0 0xa100000>;
};
Source: k230_img.c¶
#define OPENSBI_DTB_ADDR (CONFIG_MEM_LINUX_SYS_BASE + 0x2000000) /* 0x0A000000 */
#define RAMDISK_ADDR (CONFIG_MEM_LINUX_SYS_BASE + 0x2000000 + 0x100000) /* 0x0A100000 */
U-Boot loads the Linux uImage containing kernel + DTB + initrd, decompresses the kernel to its load address, then copies DTB to 0x0A000000 and initrd to 0x0A100000 before jumping into OpenSBI/kernel.
6. MMZ (Media Memory Zone)¶
MMZ is the large contiguous buffer pool managed by RT-Smart's MPP framework for media operations (camera capture, video encode/decode, display, AI inference, etc.).
0x10000000 +-----------+
| |
| MMZ | ~252 MB Media buffers (VB pools, DMA buffers)
| | Managed by mmz_init() in mpp_init.c
| |
0x1FBFF000 +-----------+
| Tail Guard| ~4 MB Unused / boundary protection
0x20000000 +-----------+
Source: mpp_init.c¶
#define MEM_MMZ_BASE 0x10000000UL
#define MEM_MMZ_SIZE 0xfbff000UL /* 252 MB - 4 KB (boundary subtracted) */
ret = mmz_init(MEM_MMZ_BASE, MEM_MMZ_SIZE);
Note: CONFIG_MEM_MMZ_SIZE in k_autoconf_comm.h is 0x0FC00000 (exactly 252 MB). The actual initialization in mpp_init.c uses 0x0FBFF000 (252 MB - 4 KB), subtracting CONFIG_MEM_BOUNDARY_RESERVED_SIZE (4 KB) as a safety guard.
MMZ memory is allocated via the VB (Video Buffer) subsystem and is accessible from both RT-Smart user processes (via /dev/mmz_userdev) and kernel-space MPP drivers.
7. MMIO / Peripheral Address Map¶
Peripherals are mapped above 0x80000000 (outside DDR space). From board.h and the K230 Technical Reference Manual:
| Address Range | Size | Peripheral |
|---|---|---|
0x80000000 - 0x801FFFFF |
2 MB | KPU L2 Cache |
0x80200000 - 0x803FFFFF |
2 MB | SRAM |
0x80400000 - 0x804007FF |
2 KB | KPU Configuration |
0x80400800 - 0x80400BFF |
1 KB | FFT |
0x80400C00 - 0x80400FFF |
1 KB | AI 2D Engine |
0x80800000 - 0x80803FFF |
16 KB | GSDMA |
0x80804000 - 0x80807FFF |
16 KB | DMA |
0x80808000 - 0x8080BFFF |
16 KB | GZIP Decompress |
0x8080C000 - 0x8080FFFF |
16 KB | Non-AI 2D |
0x90000000 - 0x90007FFF |
32 KB | ISP |
0x90008000 - 0x90008FFF |
4 KB | DeWarp |
0x90009000 - 0x9000AFFF |
8 KB | RX CSI |
0x90400000 - 0x9040FFFF |
64 KB | H264/HEVC/JPEG Codec |
0x90800000 - 0x9083FFFF |
256 KB | 2.5D GPU |
0x90840000 - 0x9084FFFF |
64 KB | VO (Video Output) |
0x90850000 - 0x90850FFF |
4 KB | DSI |
0x90A00000 - 0x90A007FF |
2 KB | 3D Engine |
0x91000000 - 0x91000BFF |
3 KB | PMU |
0x91000C00 - 0x91000FFF |
1 KB | RTC |
0x91100000 - 0x91100FFF |
4 KB | CMU (Clock) |
0x91101000 - 0x91101FFF |
4 KB | RMU (Reset) |
0x91102000 - 0x91102FFF |
4 KB | BOOT Control |
0x91103000 - 0x91103FFF |
4 KB | PWR (Power) |
0x91104000 - 0x91104FFF |
4 KB | Mailbox |
0x91105000 - 0x911057FF |
2 KB | IOMUX |
0x91105800 - 0x91105FFF |
2 KB | Hardware Timer |
0x91106000 - 0x911067FF |
2 KB | WDT0 |
0x91106800 - 0x91106FFF |
2 KB | WDT1 |
0x91107000 - 0x911077FF |
2 KB | Temperature Sensor |
0x91107800 - 0x91107FFF |
2 KB | HDI |
0x91108000 - 0x91108FFF |
4 KB | STC (System Timer) |
0x91200000 - 0x9120FFFF |
64 KB | Boot ROM |
0x91210000 - 0x91217FFF |
32 KB | Security |
0x91400000 - 0x91404FFF |
20 KB | UART0-4 (4 KB each) |
0x91405000 - 0x91409FFF |
20 KB | I2C0-4 (4 KB each) |
0x9140A000 - 0x9140AFFF |
4 KB | PWM |
0x9140B000 - 0x9140CFFF |
8 KB | GPIO0-1 (4 KB each) |
0x9140D000 - 0x9140DFFF |
4 KB | ADC |
0x9140E000 - 0x9140EFFF |
4 KB | Audio CODEC |
0x9140F000 - 0x9140FFFF |
4 KB | I2S Audio |
0x91500000 - 0x9157FFFF |
512 KB | USB 2.0 OTG x2 |
0x91580000 - 0x91581FFF |
8 KB | SD/MMC HC x2 |
0x91582000 - 0x91583FFF |
8 KB | SPI QSPI x2 |
0x91584000 - 0x91584FFF |
4 KB | SPI OPI |
0x91585000 - 0x915853FF |
1 KB | HI SYS Config |
0x98000000 - 0x99FFFFFF |
32 MB | DDRC Configuration |
0xC0000000 - 0xC7FFFFFF |
128 MB | SPI OPI XIP Flash |
8. SD Card Partition Layout¶
The SD card image is generated by genimage-sdcard.cfg with GPT partitioning:
Offset Size Content Partition
======================================================================
1 MB 512 KB U-Boot SPL (copy 1) (raw, not in GPT)
1.5 MB 512 KB U-Boot SPL (copy 2) (raw, not in GPT)
~1.875 MB 128 KB U-Boot env (raw, not in GPT)
2 MB 1.5 MB U-Boot proper (raw, not in GPT)
10 MB 20 MB RT-Smart firmware GPT partition "rtt"
30 MB 50 MB Linux firmware GPT partition "linux"
128 MB var. rootfs (ext4) GPT partition "rootfs"
after rootfs sharefs (FAT32, 256 MB) GPT partition "fat32appfs"
The boot flow reads RT-Smart firmware from the "rtt" partition and Linux firmware from the "linux" partition, loading them into their respective DDR regions.
Source: genimage-sdcard.cfg¶
partition rtt {
offset = 10M
image = "big-core/rtt_system.bin"
size = 20M
}
partition linux {
offset = 30M
image = "little-core/linux_system.bin"
size = 50M
}
partition rootfs {
offset = 128M
partition-type-uuid = "L"
image = "little-core/rootfs.ext4"
}
partition fat32appfs {
partition-type-uuid = "F"
image = "app.vfat"
}
9. Real Device Verification¶
The following data was captured from a running CanMV-K230 board via serial console (USB CDC-ACM).
9.1 Little Core (Linux) - /dev/ttyACM0¶
Kernel version:
Boot command line:
root=/dev/mmcblk1p3 loglevel=8 rw rootdelay=4 rootfstype=ext4
console=ttyS0,115200 crashkernel=256M-:128M earlycon=sbi
Memory info (free -m):
Key /proc/meminfo values:
/proc/iomem (System RAM):
DTS memory node (raw hex from /sys/firmware/devicetree/base/memory@0/reg):
dmesg memory-related lines:
cma: Reserved 52 MiB at 0x000000000c800000
Zone ranges:
DMA32 [mem 0x0000000008200000-0x000000000fffefff]
node 0: [mem 0x0000000008200000-0x000000000fffefff]
Memory: 26588K/129020K available (9099K kernel code, 4868K rwdata,
4096K rodata, 271K init, 370K bss, 49184K reserved,
53248K cma-reserved)
Disk layout (df -h):
9.2 Big Core (RT-Smart msh) - /dev/ttyACM1¶
free output:
- Pool size: 33,554,432 bytes = exactly 32 MB (matches
RT_HW_HEAP_END - RT_HW_HEAP_BEGIN = 0x2000000) - Max used: 702,464 bytes (~686 KB peak usage)
- Available: 32,866,304 bytes (~31.3 MB free)
list_device (MPP/IPCM devices confirmed present):
mmz_userdev Character Device 0
ipcm_user Character Device 0
vb_device Character Device 0
log Character Device 0
sys Character Device 0
Plus 40+ media/sensor devices (vicap, venc, vdec, vo, ai, ao, dma, fft, etc.)
list_thread (active threads):
tshell 20 running (shell)
sharefs_client 5 suspend (shared filesystem)
ipcm-discovery 5 suspend (IPCM auto-discovery)
ipcm-recv 5 suspend (IPCM message receiver)
mcm_task 0 suspend (media control)
9.3 Analysis: Source Code vs. Real Device¶
| Parameter | Source Code | Real Device | Match? |
|---|---|---|---|
| Linux System RAM start | 0x08200000 (DTS) |
0x08200000 (/proc/iomem) |
Yes |
| Linux System RAM size | 0x07DFF000 (DTS) |
129020 KB (dmesg) = 0x07DFF000 |
Yes |
| Linux MemTotal | ~126 MB (DTS) | 103.4 MB (/proc/meminfo) |
Expected: kernel overhead ~23 MB |
| CMA reservation | (kernel config) | 52 MiB at 0x0C800000 |
Within Linux range |
| RT-Smart heap size | 0x2000000 (board.h) |
33,554,432 bytes (free) |
Yes, exactly 32 MB |
| crashkernel=256M-:128M | bootargs | Logged but no effect (only 126 MB available) | As expected |
| MMZ region visible from Linux | Not expected | Not in /proc/iomem |
Correct - MMZ is RT-Smart only |
| OpenSBI region | 0x08000000-0x081FFFFF |
Not in /proc/iomem (RAM starts at 0x08200000) |
Correct - excluded from Linux |
| IPCM devices on RT-Smart | ipcm_user, sharefs | Present in list_device / list_thread |
Yes |
| MMZ device on RT-Smart | mmz_userdev | Present in list_device |
Yes |
Key observations:
-
MemTotal vs DTS size gap: Linux reports 105,876 KB usable out of 129,020 KB total RAM. The ~23 MB difference is consumed by kernel code (9 MB), rwdata (5 MB), rodata (4 MB), and other kernel structures. This is normal.
-
CMA 52 MB: A large CMA region is reserved within Linux's memory for DMA-capable allocations (likely used by WiFi driver
bcmdhdand USB). This further reduces available memory. -
crashkernel parameter is ineffective: The
crashkernel=256M-:128Mparameter requests 128 MB for kdump when total RAM >= 256 MB. Since Linux only has ~126 MB, the threshold is never met and no crash kernel memory is reserved. -
OpenSBI is invisible to Linux: The 2 MB OpenSBI region (0x08000000-0x081FFFFF) does not appear in
/proc/iomembecause the DTS deliberately starts the memory node at 0x08200000, excluding OpenSBI's resident firmware. -
RT-Smart heap utilization is low: Only ~686 KB out of 32 MB heap is used at idle. The heap is for kernel
rt_malloc()allocations; user processes use the page allocator (the remaining ~93 MB), and media buffers use MMZ (~252 MB).
References¶
| File | Content |
|---|---|
k230_sdk/src/big/mpp/include/comm/k_autoconf_comm.h |
All CONFIG_MEM_* defines (memory partition master config) |
k230_sdk/src/big/rt-smart/kernel/bsp/maix3/board/board.h |
RT-Smart heap/page boundaries + full peripheral address map |
k230_sdk/src/big/rt-smart/kernel/bsp/maix3/link.lds |
RT-Smart linker script (entry at 0x220000) |
k230_sdk/src/little/linux/arch/riscv/boot/dts/kendryte/k230_canmv.dts |
Linux DDR region (0x8200000, 0x7dff000) |
k230_sdk/src/little/uboot/board/canaan/common/k230_img.c |
DTB/initrd placement address calculation |
k230_sdk/src/common/cdk/kernel/ipcm/arch/k230/configs/k230_riscv_rtsmart_config |
IPCM shared memory physical addresses |
k230_sdk/src/common/cdk/kernel/ipcm/arch/k230/configs/k230_riscv_linux_config |
IPCM Linux-side role configuration |
k230_sdk/src/big/rt-smart/kernel/bsp/maix3/board/mpp/mpp_init.c |
MMZ initialization (0x10000000, 0x0fbff000) |
k230_sdk/board/common/gen_image_cfg/genimage-sdcard.cfg |
SD card partition layout |