Files
TAIXIN/project/app/fpv_mem.c

147 lines
7.9 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file fpv_mem.c
* @brief FPV 内存管理初始化模块
* @details 本文件负责在系统启动时初始化用户空间的多个专用内存堆:
* - av_psram_heap: 从片外 PSRAM 中分配,专用于音视频大数据缓冲
* - av_heap: 从片内 SRAM 中分配,专用于音视频快速处理
* 采用内存池MPOOL_ALLOC模式在编译期确定各堆大小
* 运行时从系统堆中切分出专用区域,以减少内存碎片并提高分配效率。
*/
#include "sys_config.h" // 包含系统配置宏定义,如 MPOOL_ALLOC、AV_PSRAM_HEAP 等
#include "basic_include.h" // 包含基础类型定义uint32 等)和基础宏
#include "osal/string.h" // 包含操作系统抽象层字符串/打印接口os_printf 等)
#include "lib/heap/av_psram_heap.h" // 包含音视频 PSRAM 堆的初始化接口声明
#include "lib/heap/av_heap.h" // 包含音视频 SRAM 堆的初始化接口声明
// 通用用户空间内存初始化
// 通用用户空间内存初始化入口函数
/**
* @brief 用户空间内存堆初始化
* @details 在系统启动阶段调用,依次完成以下工作:
* 1. 若启用了 PSRAM 音视频堆AV_PSRAM_HEAP从片外 PSRAM 分配一大块连续内存,
* 作为音视频专用的 psram 堆,支持大容量缓冲(如视频帧缓冲区)。
* 2. 若启用了 SRAM 音视频堆AV_HEAP从片内 SRAM 分配一块内存,
* 作为音视频专用的 sram 堆,利用 SRAM 的高速访问特性进行音视频编解码处理。
* 为使 av_heap 尽量位于 SRAM 高地址区域(避免与系统堆碎片混合),
* 先申请一大块占位空间,再释放该空间。
* @param 无参数
* @return 无返回值
*/
void user_heap_init()
{
_os_printf("\r\n"); // 打印空行,作为内存初始化信息输出的起始分隔
os_printf("--------------------------------------------------------------------\r\n"); // 打印分隔线,便于在串口日志中识别内存初始化区域
/*
* ==================== 第一部分PSRAM 音视频堆初始化 ====================
* 条件编译:仅当同时定义了以下三个宏时才编译此段代码:
* MPOOL_ALLOC - 启用内存池分配模式
* AV_PSRAM_HEAP - 启用音视频 PSRAM 堆
* PSRAM_HEAP - 系统支持 PSRAM 堆
* PSRAMPseudo-SRAM是片外扩展内存容量大但速度比片内 SRAM 慢,
* 适合存放视频帧数据等大块缓冲区。
*/
#if defined(MPOOL_ALLOC) && defined(AV_PSRAM_HEAP) && defined(PSRAM_HEAP)
{
// 设置堆的属性标志:
// SYSHEAP_FLAGS_MEM_ALIGN_32 - 所有分配的内存按 32 字节对齐,
// 适配 DMA 传输和 SIMD 指令的对其要求
// SYSHEAP_FLAGS_MEM_LEAK_TRACE - 启用内存泄漏追踪,
// 在调试阶段记录每次分配/释放,便于排查泄漏
uint32 flags = SYSHEAP_FLAGS_MEM_ALIGN_32 | SYSHEAP_FLAGS_MEM_LEAK_TRACE;
// 从 PSRAM 系统堆中分配一块大小为 CONFIG_PSRAM_AVHEAP_SIZE 的连续内存,
// 用于后续初始化为音视频专用的 PSRAM 堆
void *av_psram_buf = os_malloc_psram(CONFIG_PSRAM_AVHEAP_SIZE);
// 保存分配到的 PSRAM 内存块大小,供后续初始化函数和日志打印使用
uint32_t av_psram_size = CONFIG_PSRAM_AVHEAP_SIZE;
// 打印 PSRAM 音视频堆的地址范围和大小信息,
// 方便开发者在串口日志中确认内存分配是否正确
os_printf("| CPU0 AV_PSRAM_HEAP : %p ~ %p, Size:%-8d |\r\n", av_psram_buf, av_psram_buf+av_psram_size, av_psram_size);
// 检查 PSRAM 内存是否分配成功,只有成功时才进行堆初始化
if (av_psram_buf)
{
// 使用分配到的 PSRAM 内存块和指定的标志位,初始化音视频 PSRAM 堆,
// 初始化后可通过 av_psram_malloc() 等接口从此堆中分配内存
av_psram_heap_init((void *) av_psram_buf, av_psram_size, flags);
}
}
#endif
/*
* ==================== 第二部分SRAM 音视频堆初始化 ====================
* 条件编译:仅当同时定义了以下两个宏时才编译此段代码:
* MPOOL_ALLOC - 启用内存池分配模式
* AV_HEAP - 启用音视频 SRAM 堆
* SRAM 是片内高速内存,容量小但访问速度快,
* 适合存放音视频编解码过程中的临时数据结构和控制信息。
*
* 关键技巧:为了让 av_heap 尽量位于 SRAM 高地址区域,避免与系统运行时
* 动态分配的碎片化内存混在一起,这里采用"占位-释放"策略:
* 1. 先查询 SRAM 系统堆剩余总空间
* 2. 如果剩余空间远大于所需 av_heap 大小,先申请一大块"占位"空间
* 3. 然后再申请 av_heap 所需的空间(此时 av_heap 就被推到了高地址)
* 4. 最后释放占位空间,归还给系统堆
*/
#if defined(MPOOL_ALLOC) && defined(AV_HEAP)
{
// 设置 SRAM 音视频堆的属性标志:
// SYSHEAP_FLAGS_MEM_ALIGN_32 - 32 字节对齐,满足 DMA 和缓存行对齐要求
// 注意:此处未启用 SYSHEAP_FLAGS_MEM_LEAK_TRACE因为 SRAM 堆用于高频
// 临时分配,启用追踪会显著影响性能
uint32 flags = SYSHEAP_FLAGS_MEM_ALIGN_32;
// 占位空间的指针,初始为 NULL稍后根据剩余空间情况决定是否分配
void *rev_mem_head = NULL;
// 获取配置中定义的音视频 SRAM 堆大小(字节数)
uint32_t sram_size = CONFIG_AVHEAP_SIZE;
//计算SRAM_HEAP剩余空间
// 查询当前 SRAM 系统堆sram_heap中剩余可用的总字节数
// 用于判断是否有足够空间分配 av_heap 以及是否需要占位
uint32_t total_mem_remain_size = sysheap_freesize(&sram_heap);
// 如果剩余空间大于 av_heap 所需大小 + 1024 字节(预留安全余量),
// 则先分配占位空间,将 av_heap 推向高地址区域
if(total_mem_remain_size > sram_size + 1024)
{
//申请空间,尽量将av_sram空间放到最后
// 计算占位空间大小 = 剩余总量 - av_heap所需 - 1024安全余量
// 申请这块空间后,后续 av_heap 的分配就会被挤到 SRAM 的高地址端
rev_mem_head = (void*)os_malloc(total_mem_remain_size - sram_size - 1024);
}
// 正式分配音视频 SRAM 堆所需的内存块,
// 由于前面可能已有占位分配,此块内存将位于 SRAM 较高地址区域
uint8_t *sram_buf = (uint8_t*)os_malloc(sram_size);
// 打印 SRAM 音视频堆的地址范围和大小信息
os_printf("| CPU0 AV_HEAP : %p ~ %p, Size:%-8d |\r\n", sram_buf, sram_buf+sram_size, sram_size);
// 检查 SRAM 内存是否分配成功,只有成功时才进行堆初始化
if(sram_buf)
{
// 使用分配到的 SRAM 内存块和指定的标志位,初始化音视频 SRAM 堆,
// 初始化后可通过 av_malloc() 等接口从此堆中分配高速内存
av_heap_init((void *) sram_buf, sram_size, flags);
}
// 如果之前分配了占位空间,现在释放它,归还给 SRAM 系统堆,
// 这样系统堆仍可使用这块低地址空间,而 av_heap 已固定在高地址
if(rev_mem_head)
{
os_free(rev_mem_head);
}
}
#endif
os_printf("--------------------------------------------------------------------\r\n"); // 打印分隔线,标记内存初始化信息输出结束
}