术语定义
术语 | 定义 | 注释说明 |
---|---|---|
DRAM | Dynamic Random Access Memory | 动态随机存取存储器 |
SRAM | Static Random Access Memory | 静态随机存取存储器 |
PSRAM | Pseudo Static Random Access Memory | 伪静态随机存取存储器 |
CMA | Contiguous Memory Allocator | 连续内存分配器,MPP 多媒体模块专用内存 |
ITCM | Instruction Tightly Coupled Memory | 紧耦合指令内存,实时程序专用 |
DTCM | Data Tightly Coupled Memory | 紧耦合数据内存,实时程序专用 |
D21x内存
内存布局
D21x 硬件上使用 DRAM 作为 Memory 主要存储单元,其典型大小为 64M/128M。
针对 DRAM Memory 资源,软件会使用以下策略来进行分配:
首先把 DRAM 分成两个区域: DRAM Software Region 和 DRAM CMA Region 。CMA Region 提供给多媒体模块 MPP 专用,Software Region 提供给系统其他模块使用,主要目的是把 MPP 的动态内存池 (heap_cma) 和 系统动态内存池 (heap_sys) 进行分离,避免 MPP 的内存池碎片化。因为 MPP 的内存分配基本都是大块内存,而系统各模块的内存分配是各种尺寸大小都有,如果共享一个内存池容易造成 MPP 大块内存分配失败。
接着会把每一个 Region 进一步划分成静态分配 Static 和 动态分配 Heap 子区域。静态分配的区域在编译链接后地址已经确定,动态分配区域就是 Heap 内存池运行时地址才会确定。
内存使用
综合上述策略,DRAM 空间被软件划分成四块区域:
DRAM SW Static 系统静态分配区域。
.text .rodata .data .bss
默认会存放到这个区域,即普通的函数定义和全局变量定义。DRAM SW Heap 系统动态分配区域。即
heap_sys
内存池,可以通过以下函数从该内存池分配内存。
malloc(size);
aicos_malloc(MEM_DEFAULT, size); // MEM_DEFAULT = 0
2
DRAM CMA Static CMA
静态分配区域。函数定义和全局变量定义可以通过加上 CMA_DATA_DEFINE 宏声明链接到这个区域: (这个区域是可选的,通常情况下没有配置。)
// 函数定义:
void CMA_DATA_DEFINE test_func(void); // CMA_DATA_DEFINE = DRAM_CMA_DATA_DEFINE
// 全局变量定义:
CMA_DATA_DEFINE int a = 1;
2
3
4
5
DRAM CMA Heap CMA
动态分配区域。即heap_cma
内存池,可以通过以下函数从该内存池分配内存。
aicos_malloc(MEM_CMA, size); // MEM_CMA = MEM_DRAM_CMA
参数配置
可以通过 scons --menuconfig
命令进入 menuconfig 配置界面,配置 Meomry 相关参数:
- DRAM 总大小
Board options --->
Mem Options --->
DRAM parameter --->
(0x4000000) DRAM Total Size // 配置 DRAM 总大小为 64M
2
3
4
- CMA 区域大小
Board options --->
Mem Options --->
DRAM parameter --->
(0x2000000) CMA mem size // 配置 DRAM 结尾 CMA 区域大小为 32M,剩余开头 32M 即为 Software 区域
2
3
4
调试命令
在工程编译时,可以通过 scons --list-mem 命令来查看当前工程的 Memory layout:
$ scons --list-mem
scons: Reading SConscript files ...
output/d21x_demo88-nand_rt-thread_helloworld/images/d21x.elf Memory layout:
Region Start End Length
dram 0x40000000 - 0x44000000 0x04000000
└─ dram_sw 0x40000000 - 0x42000000 0x02000000
└─ dram_sw_static 0x40000000 - 0x401cb970 0x001cb970
└─ .text 0x40000000 - 0x400cda80 0x000cda80
└─ .rodata 0x400cda80 - 0x4016ea20 0x000a0fa0
└─ .bss 0x40172000 - 0x401cb970 0x00059970
└─ dram_sw_heap 0x401cb970 - 0x42000000 0x01e34690
└─ .heap_sys 0x401cb970 - 0x42000000 0x01e34690
└─ dram_cma 0x42000000 - 0x44000000 0x02000000
└─ dram_cma_heap 0x42000000 - 0x44000000 0x02000000
└─ .heap_cma 0x42000000 - 0x44000000 0x02000000
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
在系统运行时,可以通过 RT-Thread 下的 free 命令来查看 heap_sys 和 heap_cma 内存池的运行情况:
aic /> free
memheap pool size max used size available size
---------------- ---------- ------------- --------------
heap_cma 8362744 48 8362696
heap_sys 758948 50384 710780
2
3
4
5
D13x 内存配置(1)SRAM + PSRAM
D13x 可使用的内存资源的种类比较多,有 SRAM、PSRAM、TCM。本文列举了其中典型的三种场景来阐述参数配置和使用方法,其他组合场景的配置用户可以参考本文档灵活配置。
内存布局
D13x 第一种典型内存配置是:SRAM + PSRAM。SRAM_S0 速度较快但是容量较小,提供给软件系统使用。PSRAM 速度略慢但是容量较大,提供给多媒体外设模块 DE/GE/VE 作为缓存使用,外设模块的 DMA 直接存取这些内存。
WARNING
为了减少总线冲突,DE/GE/VE 硬件上已被限制不能访问 SRAM_S0 区域的内存。
针对以上 Hardware Memory 资源,软件会使用以下策略来进行分配:
首先把 SRAM 的 SRAM_S0 Region 区域提供给系统软件使用。
接着把 PSRAM 分成两个区域: PSRAM Software Region 和 PSRAM CMA Region 。CMA Region 提供给多媒体模块 MPP 专用,Software Region 是在 SRAM 不够系统软件用的情况下补充划分一部分 PSRAM 给软件使用,目的也是把 MPP 的动态内存池 (heap_cma) 和 系统动态内存池 (heap_sys) 进行分离,避免 MPP 的内存池碎片化。因为 MPP 的内存分配基本都是大块内存,而系统各模块的内存分配是各种尺寸大小都有,如果共享一个内存池容易造成 MPP 大块内存分配失败。
最后会把每一个 Region 进一步划分成静态分配 Static 和 动态分配 Heap 子区域。静态分配的区域在编译链接后地址已经确定,动态分配区域就是 Heap 内存池运行时地址才会确定。
内存使用
综合上述策略,SRAM_S0 空间被软件划分成两块区域,PSRAM 空间被软件划分成四块区域:
SRAM_S0 SW Static
系统静态分配区域。.text .rodata .data .bss
默认会存放到这个区域,即普通的函数定义和全局变量定义。SRAM_S0 SW Heap
系统动态分配区域。即heap_sys
内存池,可以通过以下函数从该内存池分配内存。
malloc(size);
aicos_malloc(MEM_DEFAULT, size); // MEM_DEFAULT = 0
2
PSRAM SW Static
系统静态分配区域。 函数定义和全局变量定义可以通过加上PSRAM_SW_DATA_DEFINE
宏声明链接到这个区域: (这个区域是可选的,通常情况下没有配置。)
aicos_malloc(MEM_PSRAM_SW, size);
PSRAM CMA Static CMA
静态分配区域。一方面在SRAM_S0
空间不够用的情况下,可以通过menuconfig
配置菜单把.text .rodata .data .bss
选择放置到PSRAM
中就会链接到本区域。另一方面函数定义和全局变量定义可以通过加上CMA_DATA_DEFINE
宏声明链接到这个区域: (这个区域是可选的,有些情况下没有配置。)
// 函数定义:
void CMA_DATA_DEFINE test_func(void); // CMA_DATA_DEFINE = PSRAM_CMA_DATA_DEFINE
// 全局变量定义:
CMA_DATA_DEFINE int a = 1;
2
3
4
5
PSRAM CMA Heap CMA
动态分配区域。即heap_cma
内存池,可以通过以下函数从该内存池分配内存。
aicos_malloc(MEM_CMA, size); // MEM_CMA = MEM_PSRAM_CMA
参数配置
可以通过 scons --menuconfig 命令进入 menuconfig 配置界面,配置 Meomry 相关参数:
- SRAM_S0 总大小
Board options --->
Mem Options --->
SRAM parameter --->
(0x100000) SRAM Total Size // 配置 SRAM 总大小为 1M
SRAM_S1 Size (0K) // 配置 SRAM_S1 大小为0,即所有空间分配给 SRAM_S0
2
3
4
5
- PSRAM 总大小
Board options --->
Mem Options --->
PSRAM parameter --->
(0x800000) PSRAM size // 配置 PSRAM 总大小为 8M
2
3
4
- PSRAM CMA 区域大小
Board options --->
Mem Options --->
PSRAM parameter --->
(0x0) Software size in PSRAM // 配置 PSRAM 开头 Software 区域大小为 0,剩余结尾 CMA 区域大小即为 8M
2
3
4
- .text .rodata .data .bss 区域可选择配置到 SRAM_S0/PSRAM 当中
Board options --->
Mem Options --->
ELF Sections memory locatio --->
Section .text (SRAM_S0) --->
Section .rodata (SRAM_S0) --->
Section .data (SRAM_S0) --->
Section .bss (PSRAM) --->
( ) SRAM_S0
(X) PSRAM // 在 SRAM 空间不足的情况下,选择把几部分数据存放到 PSRAM 当中
2
3
4
5
6
7
8
9
调试命令
在工程编译时,可以通过 scons --list-mem
命令来查看当前工程的 Memory layout
$ scons --list-mem
scons: Reading SConscript files ...
output/d13x_demo88-nor_rt-thread_helloworld/images/d13x.elf Memory layout:
Region Start End Length
sram_s0 0x30040000 - 0x30140000 0x00100000
└─ sram_s0_static 0x30040000 - 0x300ec1f8 0x000ac1f8
└─ .text 0x30040000 - 0x300ca3c0 0x0008a3c0
└─ .rodata 0x300ca430 - 0x300ea7b0 0x00020380
└─ .data 0x300ea7c0 - 0x300ec1f8 0x00001a38
└─ sram_s0_heap 0x300ec1f8 - 0x30140000 0x00053e08
└─ .heap_sys 0x300ec1f8 - 0x30140000 0x00053e08
psram 0x40000000 - 0x40800000 0x00800000
└─ psram_cma 0x40000000 - 0x40800000 0x00800000
└─ psram_cma_static 0x40000000 - 0x40010348 0x00010348
└─ .bss 0x40000000 - 0x40010348 0x00010348
└─ psram_cma_heap 0x40010348 - 0x40800000 0x007efcb8
└─ .heap_cma 0x40010348 - 0x40800000 0x007efcb8
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
在系统运行时,可以通过 RT-Thread 下的 free
命令来查看 heap_sys
和 heap_cma
内存池的运行情况:
aic /> free
memheap pool size max used size available size
---------------- ---------- ------------- --------------
heap_cma 8322232 6005224 3887936
heap_sys 343560 97084 261852
2
3
4
5
D13x 内存配置(2)TCM + SRAM + PSRAM
内存布局¶
D13x 还支持把部分 SRAM 挂载成 TCM,TCM 的好处是 CPU 独占访问的不会和其他外设发生总线竞争,这对某些实时代码来说是必须的。其中 128K 的 ITCM 给实时代码使用,128K 的 DTCM 给实时数据使用。开启 TCM 功能以后 SRAM_S0 空间就会对应的减少 256K。
WARNING
可以看到配置(2)和配置(1)的区别是在开启 TCM 上,本章节仅仅只会描述其中的差异部分。
针对 TCM Memory 资源,软件会使用以下策略来进行分配:
首先 TCM 有两个区域: ITCM Region 和 DTCM Region ,分别用于实时代码和数据。
接着会把每一个 Region 进一步划分成静态分配 Static 和 动态分配 Heap 子区域。静态分配的区域在编译链接后地址已经确定,动态分配区域就是 Heap 内存池运行时地址才会确定。
内存使用
综合上述策略,TCM 空间被软件划分成四块区域:
ITCM Static
ITCM 静态分配区域。 函数定义可以通过加上TCM_CODE_DEFINE
宏声明链接到这个区域:
// 函数定义:
void TCM_CODE_DEFINE test_func(void);
2
ITCM Heap
ITCM 动态分配区域。即heap_itcm
内存池,可以通过以下函数从该内存池分配内存。
aicos_malloc(MEM_ITCM, size);
DTCM Static
DTCM 静态分配区域。全局变量定义可以通过加上TCM_DATA_DEFINE
宏声明链接到这个区域:
// 全局变量定义:
TCM_DATA_DEFINE int a = 1;
2
DTCM Heap
DTCM 动态分配区域。即heap_dtcm
内存池,可以通过以下函数从该内存池分配内存。
aicos_malloc(MEM_DTCM, size);
参数配置
可以通过 scons --menuconfig
命令进入 menuconfig 配置界面,配置 Meomry 相关参数:
- 使能 TCM 空间
Board options --->
Mem Options --->
SRAM parameter --->
[*] Enable TCM (Tightly Coupled Memory) // 开启 TCM 功能,SRAM_S0 空间相应的会减小 256k
2
3
4
D13x 内存配置(3)SRAM
内存布局
D13x 的部分型号是没有 SiP PSRAM 颗粒,没有 PSRAM Memory 空间的。这种情况下如果要使用多媒体模块 DE/GE/VE ,必须要使能 SRAM_S1 区域。SRAM_S1 区域可以被 DE/GE/VE 硬件访问,但是它的空间需要从 SRAM_S0 中划分。
WARNING
可以看到配置(3)和配置(1)的区别是用 SRAM_S1 取代 PSRAM 来充当 CMA 区域,本章节仅仅只会描述其中的差异部分。
针对 SRAM_S1 Memory 资源,软件会使用以下策略来进行分配:
把 SRAM_S1 分成两个区域: SRAM_S1 Software Region 和 SRAM_S1 CMA Region 。CMA Region 提供给多媒体模块 MPP 专用,Software Region 是在 SRAM_S0 不够系统软件用的情况下补充划分一部分 SRAM_S1 给软件使用。
接着会把每一个 Region 进一步划分成静态分配 Static 和 动态分配 Heap 子区域。静态分配的区域在编译链接后地址已经确定,动态分配区域就是 Heap 内存池运行时地址才会确定。
内存使用
综合上述策略,SRAM_S1 空间被软件划分成四块区域:
SRAM_S1 SW Static
系统静态分配区域。 函数定义和全局变量定义可以通过加上SRAM1_SW_DATA_DEFINE
宏声明链接到这个区域: (这个区域是可选的,通常情况下没有配置。)
// 函数定义:
void SRAM1_SW_DATA_DEFINE test_func(void);
// 全局变量定义:
SRAM1_SW_DATA_DEFINE int a = 1;
2
3
4
5
SRAM_S1 SW
Heap 系统动态分配区域。即heap_sram1_sw
内存池,可以通过以下函数从该内存池分配内存。 (这个区域是可选的,通常情况下没有配置。)
aicos_malloc(MEM_SRAM1_SW, size);
SRAM_S1 CMA Static
CMA 静态分配区域。一方面在 SRAM_S0 空间不够用的情况下,可以通过menuconfig
配置菜单把.text .rodata .data .bss
选择放置到 PSRAM 中就会链接到本区域。另一方面函数定义和全局变量定义可以通过加上CMA_DATA_DEFINE
宏声明链接到这个区域: (这个区域是可选的,有些情况下没有配置。)
// 函数定义:
void CMA_DATA_DEFINE test_func(void); // CMA_DATA_DEFINE = SRAM1_CMA_DATA_DEFINE
// 全局变量定义:
CMA_DATA_DEFINE int a = 1;
2
3
4
5
SRAM_S1 CMA Heap CMA
动态分配区域。即heap_cma
内存池,可以通过以下函数从该内存池分配内存。
aicos_malloc(MEM_CMA, size); // MEM_CMA = MEM_SRAM1_CMA
参数配置
可以通过 scons --menuconfig 命令进入 menuconfig 配置界面,配置 Meomry 相关参数:
- SRAM_S1 总大小
Board options --->
Mem Options --->
SRAM parameter --->
(0x100000) SRAM Total Size // 配置 SRAM 总大小为 1M
SRAM_S1 Size (512K) // 配置 SRAM_S1 大小为 512k,SRAM_S0 大小即为剩下的 512k
( ) 0K
( ) 128K
( ) 256K
( ) 384K
(X) 512K
( ) 640K
2
3
4
5
6
7
8
9
10
11
- SRAM_S1 CMA 区域大小
Board options --->
Mem Options --->
SRAM parameter --->
(0x0) Software size in SRAM_S1 // 配置 SRAM_S1 开头 Software 区域大小为 0,剩余结尾 CMA 区域大小即为 512k
2
3
4
.text .rodata .data .bss
区域可选择配置到 SRAM_S0/SRAM_S1 当中
Board options --->
Mem Options --->
ELF Sections memory locatio --->
Section .text (SRAM_S0) --->
Section .rodata (SRAM_S0) --->
Section .data (SRAM_S0) --->
Section .bss (SRAM_S1) --->
( ) SRAM_S0
(X) SRAM_S1 // 在 SRAM_S0 空间不足的情况下,选择把几部分数据存放到 SRAM_S1 当中
2
3
4
5
6
7
8
9
调试命令
D12x 内存
内存布局
D12x 硬件上使用 PSRAM 作为 Memory 主要存储单元,其典型大小为 8M/16M。
针对 PSRAM Memory 资源,软件会使用以下策略来进行分配:
首先把 PSRAM 分成两个区域:
PSRAM Software Region
和PSRAM CMA Region
。CMA Region 提供给多媒体模块 MPP 专用,Software Region 提供给系统其他模块使用,主要目的是把 MPP 的动态内存池 (heap_cma) 和 系统动态内存池 (heap_sys) 进行分离,避免 MPP 的内存池碎片化。因为 MPP 的内存分配基本都是大块内存,而系统各模块的内存分配是各种尺寸大小都有,如果共享一个内存池容易造成 MPP 大块内存分配失败。接着会把每一个 Region 进一步划分成静态分配
Static
和 动态分配Heap
子区域。静态分配的区域在编译链接后地址已经确定,动态分配区域就是 Heap 内存池运行时地址才会确定。
内存使用
综合上述策略,PSRAM 空间被软件划分成四块区域:
PSRAM SW
Static 系统静态分配区域。.text .rodata .data .bss
默认会存放到这个区域,即普通的函数定义和全局变量定义。PSRAM SW
Heap 系统动态分配区域。即heap_sys
内存池,可以通过以下函数从该内存池分配内存。
malloc(size);
aicos_malloc(MEM_DEFAULT, size); // MEM_DEFAULT = 0
2
PSRAM CMA Static
CMA 静态分配区域。函数定义和全局变量定义可以通过加上CMA_DATA_DEFINE
宏声明链接到这个区域: (这个区域是可选的,通常情况下没有配置。)
// 函数定义:
void CMA_DATA_DEFINE test_func(void); // CMA_DATA_DEFINE = PSRAM_CMA_DATA_DEFINE
// 全局变量定义:
CMA_DATA_DEFINE int a = 1;
2
3
4
5
PSRAM CMA Heap
CMA 动态分配区域。即heap_cma
内存池,可以通过以下函数从该内存池分配内存。
aicos_malloc(MEM_CMA, size); // MEM_CMA = MEM_PSRAM_CMA
参数配置
可以通过 scons --menuconfig
命令进入 menuconfig
配置界面,配置 Meomry 相关参数:
- PSRAM 总大小
Board options --->
Mem Options --->
PSRAM parameter --->
(0x800000) PSRAM size // 配置 PSRAM 总大小为 8M
2
3
4
- CMA 区域大小
Board options --->
Mem Options --->
PSRAM parameter --->
(0x200000) Software size in PSRAM // 配置 PSRAM 开头 Software 区域大小为 2M,剩余结尾 CMA 区域大小即为 6M
2
3
4
5
调试命令
在工程编译时,可以通过 scons --list-mem
命令来查看当前工程的 Memory layout:
$ scons --list-mem
scons: Reading SConscript files ...
output/d12x_demo68-nor_rt-thread_helloworld/images/d12x.elf Memory layout:
Region Start End Length
psram 0x40000000 - 0x41000000 0x01000000
└─ psram_sw 0x40000000 - 0x40200000 0x00200000
└─ psram_sw_static 0x40000000 - 0x400e7ae8 0x000e7ae8
└─ .text 0x40000000 - 0x400a6640 0x000a6640
└─ .rodata 0x400a66b0 - 0x400d6fa8 0x000308f8
└─ .bss 0x400d8c00 - 0x400e7ae8 0x0000eee8
└─ psram_sw_heap 0x400e7ae8 - 0x40200000 0x00118518
└─ .heap_sys 0x400e7ae8 - 0x40200000 0x00118518
└─ psram_cma 0x40200000 - 0x41000000 0x00e00000
└─ psram_cma_heap 0x40200000 - 0x41000000 0x00e00000
└─ .heap_cma 0x40200000 - 0x41000000 0x00e00000
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
在系统运行时,可以通过 RT-Thread 下的 free
命令来查看 heap_sys
和 heap_cma
内存池的运行情况:
aic /> free
memheap pool size max used size available size
---------------- ---------- ------------- --------------
heap_cma 8362744 48 8362696
heap_sys 758948 50384 710780
2
3
4
5
栈大小配置
中断栈
Luban-Lite 中断服务程序运行在独立的栈中,大小可以在 menuconfig 配置界面中修改:
- 中断栈大小
Board options --->
Mem Options --->
(4096) Interrupt stack siz // 大小为 4k
2
3
RT-Thread 线程栈
Kernel 为 RT-Thread 时,几个典型线程的栈空间大小的配置:
- main 线程栈大小
Rt-Thread options --->
RT-Thread Components --->
(2048) Set main thread stack size // 大小为 2k
2
3
- idle 线程栈大小
Rt-Thread options --->
RT-Thread Kernel --->
(2048) The stack size of idle thread // 大小为 2k
(4) Alignment size for CPU architecture data access // CONFIG_RT_ALIGN_SIZE
2
3
4
- Shell 线程栈大小
Rt-Thread options --->
RT-Thread Components --->
MSH: command shell --->
(4096) The stack size for thread // 大小为 4k
2
3
4
INFO
在使用系统 printf 打印浮点时,要求线程堆栈为 8 字节对齐。这时 CONFIG_RT_ALIGN_SIZE 需要设置为 8,同时线程栈大小也是 8 的整数倍。
Baremetal 用户栈
裸机环境时只有一个用户栈,栈大小如下配置:
- 用户栈大小
Baremetal options --->
(8192) Main loop stack // AIC_NORMALSTACK_SIZE, 大小为 8k
2
INFO
同样在使用系统 printf 打印浮点时,要求线程堆栈为 8 字节对齐。这时 AIC_NORMALSTACK_SIZE 需要设置为 8 的整数倍。