sys_heap 示例

功能说明

演示如何使用系统堆管理组件分配和释放内存,包括内部 SRAM 和外部 PSRAM 的基本操作。

硬件连接

无需额外连接,示例使用开发板的 SRAM 和板载 PSRAM。

示例内容

  1. 从内部 SRAM 分配 256 字节内存

  2. 从外部 PSRAM 分配 1024 字节内存

  3. 使用 psram_calloc() 分配并清零内存

  4. 使用 psram_realloc() 重新分配内存

  5. 查看堆使用统计信息

编译

重要提示:编译前需要先确认当前示例支持的目标板型,然后将板型标识传给 -DBOARD。请按以下方式选择:

  1. 确认示例限制:查看当前示例 README 中的硬件连接和注意事项,确认是否限定板型。

  2. 参考示例配置:查看相关示例目录下的 sample.yaml,确认支持的板型。

  3. 填写板型标识:SDK 内置板型的标识为 boards/ 下的目录名。例如实际使用的板型目录为 boards/<板型名称>/,则编译参数填写为 -DBOARD=<板型名称>

在 SDK 根目录执行编译,并将命令中的 <示例路径><板型名称> 替换为实际值。

Linux 使用 build.sh

# 通用命令
./build.sh -C -S samples/<示例路径> -DBOARD=<板型名称>

# 示例:使用 arcs_evb 开发板
./build.sh -C -S samples/<示例路径> -DBOARD=arcs_evb

Windows PowerShell 使用 build.ps1

# 通用命令
.\build.ps1 -C -S samples/<示例路径> -DBOARD=<板型名称>

# 示例:使用 arcs_evb 开发板
.\build.ps1 -C -S samples/<示例路径> -DBOARD=arcs_evb

Note

确保已安装对应平台的工具链和 ListenAI 开发工具包。Windows 环境请先执行 .\env.ps1 或直接使用 .\build.ps1 自动加载环境。

注意事项-DBOARD 填写的是板型标识,不是芯片系列名称。如果示例有板型专用配置或额外编译参数,以示例 README 中的说明为准。

烧录

编译完成后,使用 SDK tools/burn 目录下的 cskburn 工具烧录固件。请先根据目标板型和当前示例确定芯片系列、串口设备、烧录地址和固件路径。

Linux:

# 通用命令
./tools/burn/cskburn -C <芯片系列> -s <串口设备> -b 3000000 <烧录地址> <固件路径>

# 示例:使用 arcs_evb 开发板
./tools/burn/cskburn -s /dev/ttyUSB0 -b 3000000 0x0 build/arcs.bin -C arcs

Windows PowerShell:

# 通用命令
.\tools\burn\cskburn.exe -C <芯片系列> -s <串口号> -b 3000000 <烧录地址> <固件路径>

# 示例:使用 arcs_evb 开发板
.\tools\burn\cskburn.exe -C arcs -s COM7 -b 3000000 0x0 .\build\arcs.bin

Note

烧录参数说明

  • -s /dev/ttyUSB0 / -s COM7:串口设备路径,需要根据实际情况修改 - Linux 系统:通常是 /dev/ttyUSB0/dev/ttyACM0 - 可通过 ls /dev/tty* 命令查看可用串口设备 - Windows 系统:通常是 COM7COM8 等,可在“设备管理器”的“端口”中查看 - 不同开发板或 USB 转串口芯片可能使用不同的设备名

  • -b 3000000:烧录波特率(3Mbps)

  • 0x0:烧录起始地址

  • build/arcs.bin / .\build\arcs.bin:编译生成的固件路径

  • -C arcs:芯片类型

注意事项

  • 确保开发板已正确连接到电脑

  • 如果无法识别串口设备,请检查 USB 连接线是否正常,或尝试其他 USB 端口

预期输出

[I][sample] === System Heap Example ===
[I][sample]
1. SRAM allocation:
[I][sample]    Allocated 256 bytes at: 0x...
[I][sample]    Data: Hello from SRAM
[I][sample]
2. PSRAM allocation:
[I][sample]    Allocated 1024 bytes at: 0x...
[I][sample]    Data: Hello from PSRAM
[I][sample]
3. PSRAM calloc (zeroed):
[I][sample]    Allocated 10 uint32_t at: 0x...
[I][sample]    First element (0): 0
[I][sample]    Modified to: 12345
[I][sample]
4. Memory reallocation:
[I][sample]    64 bytes: Initial data
[I][sample]    Reallocated to 128 bytes at: 0x...
[I][sample]    Data preserved: Initial data
[I][sample]
5. Heap summary:
[Start] ... [End] ... [Free/B] ...
[I][sample]
=== Example completed ===

堆地址和统计值取决于板型及当前 Kconfig 配置,以实际日志为准。

核心 API

API

说明

inram_malloc()

从内部 SRAM 分配内存

inram_free()

释放内部 SRAM 内存

psram_malloc()

从 PSRAM 分配内存

psram_calloc()

从 PSRAM 分配并清零内存

psram_realloc()

重新分配 PSRAM 内存

psram_free()

释放 PSRAM 内存

heap_summary_info()

打印堆统计信息

关键代码

/* SRAM 内存分配(4 字节对齐) */
uint8_t *sram_buf = inram_malloc(4, 256);
if (sram_buf) {
    strcpy((char *)sram_buf, "Hello from SRAM");
    inram_free(sram_buf);
}

/* PSRAM 内存分配 */
uint8_t *psram_buf = psram_malloc(1024);
if (psram_buf) {
    strcpy((char *)psram_buf, "Hello from PSRAM");
    psram_free(psram_buf);
}

/* 分配并清零 */
uint32_t *array = psram_calloc(10, sizeof(uint32_t));

/* 重新分配内存 */
char *new_buffer = psram_realloc(buffer, 128);

/* 查看堆统计 */
heap_summary_info();

内存类型说明

系统堆组件支持两种内存类型:

内部 SRAM

  • 特点:访问速度快,容量小;组件默认堆配置为 20KB

  • 适用场景:频繁访问的小数据结构、临时变量

  • 接口inram_malloc(), inram_calloc(), inram_realloc(), inram_free()

外部 PSRAM

  • 特点:容量大,访问速度较 SRAM 慢;组件默认堆配置为 128KB

  • 适用场景:大缓冲区、图像数据、音频数据

  • 接口psram_malloc(), psram_calloc(), psram_realloc(), psram_free()

配置说明

堆大小配置

在 Kconfig 中可配置堆大小(组件默认已配置):

  • CONFIG_HEAP_SIZE: 内部 SRAM 堆大小,默认 0x5000 (20KB)

  • CONFIG_PSRAM_HEAP_SIZE: PSRAM 堆大小,默认 0x20000 (128KB)

对齐要求

  • inram_malloc(align, size): align 参数指定对齐字节数,必须是 2 的幂次方(4, 8, 16, 32 等)

  • psram_malloc(size): 默认 4 字节对齐

  • psram_malloc_align(align, size): 指定对齐字节数,用于 DMA 等需要特定对齐的场景

注意事项

  1. 返回值检查:分配内存后务必检查返回值是否为 NULL,防止使用无效指针

  2. 内存释放:使用完毕后及时释放内存,避免内存泄漏

  3. 对齐参数align 参数必须是 2 的幂次方,否则会导致对齐错误

  4. 自动初始化:系统堆在 main 函数前自动初始化,无需手动调用 sysheap_init()

  5. 线程安全:所有堆分配接口都是线程安全的,可在多任务环境下使用