内存(Memory)分配

提示

译注:本节以及后面 深度睡眠 一节中的 Memory 都翻译为内存的,但是实际情况可能是指的存储器,其中细节请自己体会。

概述

ESP32 有多种 RAM。本质上,它包含 IRAM、DRAM 和可以同时用于这两者的 RAM。此外,还可以将外部 SPI flash 连接到 ESP32;可以使用 flash cache 将它的内存集成到 ESP32 的内存映射中。

为了利用这些所有的内存,esp-idf 包含了一个内存分配器。基本上,如果你想要内存具有某一属性(例如,DMA-capable、被某个特定的 PID 访问、或者执行代码的能力),你可以创建一个所需功能 OR 掩码并将它传递给 pvPortMallocCaps。例如,内部分配内存的常规 malloc 代码使用 `pvPortMallocCaps(size, MALLOC_CAP_8BIT)`,这样就可以以字节为单位获取内存数据。

因为 malloc 也是使用的这个分配系统,所以使用 pvPortMallocCaps 分配的内存也可以通过调用标准函数 `free()` 进行释放。

本质上,这个分配器被分为两部分。FreeRTOS 目录中的分配器可以从标记的(tagged)区域分配内存:一个标记(tag)是一个整数值,空闲内存的每个区域都有一个标记。esp32 相关的代码使用一些特殊的标记来初始化这些区域,并且包含一些逻辑,这些逻辑可以根据用户所给的功能选择对应功能的标记。尽管这些 API 是公共的,但是还这些标记只能用于这两部分直接通信,而不能直接使用。

Special Uses

如果某个内存结构只能以 32 比特为单位进行访问(例如整数数组或指针数组),则在分配是可以使用 MALLOC_CAP_32BIT 标志。这允许分配器分发 IRAM 内存;一些在常规 malloc() 中不能做的事儿会被调用。这样有助于是哟个 ESP32 中的所有有效内存。

API 参考手册

MALLOC_CAP_EXEC

Flags to indicate the capabilities of the various memory systems.

Memory must be able to run executable code

MALLOC_CAP_32BIT

Memory must allow for aligned 32-bit data accesses.

MALLOC_CAP_8BIT

Memory must allow for 8/16/…-bit data accesses.

MALLOC_CAP_DMA

Memory must be able to accessed by DMA.

MALLOC_CAP_PID2

Memory must be mapped to PID2 memory space.

MALLOC_CAP_PID3

Memory must be mapped to PID3 memory space.

MALLOC_CAP_PID4

Memory must be mapped to PID4 memory space.

MALLOC_CAP_PID5

Memory must be mapped to PID5 memory space.

MALLOC_CAP_PID6

Memory must be mapped to PID6 memory space.

MALLOC_CAP_PID7

Memory must be mapped to PID7 memory space.

MALLOC_CAP_SPISRAM

Memory must be in SPI SRAM.

MALLOC_CAP_INVALID

Memory can’t be used / list end marker.

类型定义

typedef struct HeapRegionTagged HeapRegionTagged_t

Structure to define a memory region.

函数

void heap_alloc_caps_init()

Initialize the capability-aware heap allocator.

For the ESP32, this is called once in the startup code.

void *pvPortMallocCaps(size_t xWantedSize, uint32_t caps)

Allocate a chunk of memory which has the given capabilities.

Return
A pointer to the memory allocated on success, NULL on failure
Parameters
  • xWantedSize: Size, in bytes, of the amount of memory to allocate
  • caps: Bitwise OR of MALLOC_CAP_* flags indicating the type of memory to be returned

size_t xPortGetFreeHeapSizeCaps(uint32_t caps)

Get the total free size of all the regions that have the given capabilities.

This function takes all regions capable of having the given capabilities allocated in them and adds up the free space they have.

Return
Amount of free bytes in the regions
Parameters
  • caps: Bitwise OR of MALLOC_CAP_* flags indicating the type of memory

size_t xPortGetMinimumEverFreeHeapSizeCaps(uint32_t caps)

Get the total minimum free memory of all regions with the given capabilities.

This adds all the lowmarks of the regions capable of delivering the memory with the given capabilities

Return
Amount of free bytes in the regions
Parameters
  • caps: Bitwise OR of MALLOC_CAP_* flags indicating the type of memory

void vPortDefineHeapRegionsTagged(const HeapRegionTagged_t *const pxHeapRegions)

Initialize the heap allocator by feeding it the usable memory regions and their tags.

This takes an array of heapRegionTagged_t structs, the last entry of which is a dummy entry which has pucStartAddress set to NULL. It will initialize the heap allocator to serve memory from these ranges.

Parameters
  • pxHeapRegions: Array of region definitions

void *pvPortMallocTagged(size_t xWantedSize, BaseType_t tag)

Allocate memory from a region with a certain tag.

Like pvPortMalloc, this returns an allocated chunk of memory. This function, however, forces the allocator to allocate from a region specified by a specific tag.

Return
Pointer to allocated memory if succesful. NULL if unsuccesful.
Parameters
  • xWantedSize: Size needed, in bytes
  • tag: Tag of the memory region the allocation has to be from

void vPortFreeTagged(void *pv)

Free memory allocated with pvPortMallocTagged.

This is basically an implementation of free().

Parameters
  • pv: Pointer to region allocated by pvPortMallocTagged

size_t xPortGetMinimumEverFreeHeapSizeTagged(BaseType_t tag)

Get the lowest amount of memory free for a certain tag.

This function allows the user to see what the least amount of free memory for a certain tag is.

Return
Minimum amount of free bytes available in the runtime of the program
Parameters
  • tag: Tag of the memory region

size_t xPortGetFreeHeapSizeTagged(BaseType_t tag)

Get the amount of free bytes in a certain tagged region.

Works like xPortGetFreeHeapSize but allows the user to specify a specific tag

Return
Remaining amount of free bytes in region
Parameters
  • tag: Tag of the memory region