Fix small things noticed in MR, add documentation

This commit is contained in:
Jeroen Domburg 2016-12-13 17:01:10 +08:00
parent 293ad4cd36
commit 1e117dc3d3
7 changed files with 202 additions and 24 deletions

View File

@ -164,8 +164,9 @@ static void disable_mem_region(void *from, void *to) {
/*
ToDo: These are very dependent on the linker script, and the logic involving this works only
because we're not using the SPI flash yet! If we enable that, this will break. ToDo: Rewrite by then.
Warning: These variables are assumed to have the start and end of the data and iram
area used statically by the program, respectively. These variables are defined in the ld
file.
*/
extern int _bss_start, _heap_start, _init_start, _iram_text_end;
@ -177,6 +178,8 @@ Same with loading of apps. Same with using SPI RAM.
*/
void heap_alloc_caps_init() {
int i;
//Compile-time assert to see if we don't have more tags than is set in heap_regions.h
_Static_assert((sizeof(tag_desc)/sizeof(tag_desc[0]))-1 <= HEAPREGIONS_MAX_TAGCOUNT, "More than HEAPREGIONS_MAX_TAGCOUNT tags defined!");
//Disable the bits of memory where this code is loaded.
disable_mem_region(&_bss_start, &_heap_start); //DRAM used by bss/data static variables
disable_mem_region(&_init_start, &_iram_text_end); //IRAM used by code
@ -217,7 +220,7 @@ void heap_alloc_caps_init() {
}
}
ESP_EARLY_LOGI(TAG, "Initializing. RAM available for heap:");
ESP_EARLY_LOGI(TAG, "Initializing. RAM available for dynamic allocation:");
for (i=0; regions[i].xSizeInBytes!=0; i++) {
if (regions[i].xTag != -1) {
ESP_EARLY_LOGI(TAG, "At %08X len %08X (%d KiB): %s",

View File

@ -14,23 +14,65 @@
#ifndef HEAP_ALLOC_CAPS_H
#define HEAP_ALLOC_CAPS_H
#define MALLOC_CAP_EXEC (1<<0) //Memory must be able to run executable code
#define MALLOC_CAP_32BIT (1<<1) //Memory must allow for aligned 32-bit data accesses
#define MALLOC_CAP_8BIT (1<<2) //Memory must allow for 8/16/...-bit data accesses
#define MALLOC_CAP_DMA (1<<3) //Memory must be able to accessed by DMA
#define MALLOC_CAP_PID2 (1<<4) //Memory must be mapped to PID2 memory space
#define MALLOC_CAP_PID3 (1<<5) //Memory must be mapped to PID3 memory space
#define MALLOC_CAP_PID4 (1<<6) //Memory must be mapped to PID4 memory space
#define MALLOC_CAP_PID5 (1<<7) //Memory must be mapped to PID5 memory space
#define MALLOC_CAP_PID6 (1<<8) //Memory must be mapped to PID6 memory space
#define MALLOC_CAP_PID7 (1<<9) //Memory must be mapped to PID7 memory space
#define MALLOC_CAP_SPISRAM (1<<10) //Memory must be in SPI SRAM
#define MALLOC_CAP_INVALID (1<<31) //Memory can't be used / list end marker
/**
* @brief Flags to indicate the capabilities of the various memory systems
*/
#define MALLOC_CAP_EXEC (1<<0) ///< Memory must be able to run executable code
#define MALLOC_CAP_32BIT (1<<1) ///< Memory must allow for aligned 32-bit data accesses
#define MALLOC_CAP_8BIT (1<<2) ///< Memory must allow for 8/16/...-bit data accesses
#define MALLOC_CAP_DMA (1<<3) ///< Memory must be able to accessed by DMA
#define MALLOC_CAP_PID2 (1<<4) ///< Memory must be mapped to PID2 memory space
#define MALLOC_CAP_PID3 (1<<5) ///< Memory must be mapped to PID3 memory space
#define MALLOC_CAP_PID4 (1<<6) ///< Memory must be mapped to PID4 memory space
#define MALLOC_CAP_PID5 (1<<7) ///< Memory must be mapped to PID5 memory space
#define MALLOC_CAP_PID6 (1<<8) ///< Memory must be mapped to PID6 memory space
#define MALLOC_CAP_PID7 (1<<9) ///< Memory must be mapped to PID7 memory space
#define MALLOC_CAP_SPISRAM (1<<10) ///< Memory must be in SPI SRAM
#define MALLOC_CAP_INVALID (1<<31) ///< Memory can't be used / list end marker
/**
* @brief Initialize the capability-aware heap allocator.
*
* For the ESP32, this is called once in the startup code.
*/
void heap_alloc_caps_init();
/**
* @brief Allocate a chunk of memory which has the given capabilities
*
* @param xWantedSize Size, in bytes, of the amount of memory to allocate
* @param caps Bitwise OR of MALLOC_CAP_* flags indicating the type
* of memory to be returned
*
* @return A pointer to the memory allocated on success, NULL on failure
*/
void *pvPortMallocCaps(size_t xWantedSize, uint32_t caps);
/**
* @brief 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.
*
* @param caps Bitwise OR of MALLOC_CAP_* flags indicating the type
* of memory
*
* @return Amount of free bytes in the regions
*/
size_t xPortGetFreeHeapSizeCaps( uint32_t caps );
/**
* @brief 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
*
* @param caps Bitwise OR of MALLOC_CAP_* flags indicating the type
* of memory
*
* @return Amount of free bytes in the regions
*/
size_t xPortGetMinimumEverFreeHeapSizeCaps( uint32_t caps );
#endif

View File

@ -147,8 +147,9 @@ task.h is included from an application file. */
#define heapBITS_PER_BYTE ( ( size_t ) 8 )
/* Define the linked list structure. This is used to link free blocks in order
of their memory address. */
/* This is optimized and assumes a region is never larger than 16MiB. */
of their memory address. This is optimized for size of the linked list struct
and assumes a region is never larger than 16MiB. */
#define HEAPREGIONS_MAX_REGIONSIZE (16*1024*1024)
typedef struct A_BLOCK_LINK
{
struct A_BLOCK_LINK *pxNextFreeBlock; /*<< The next free block in the list. */
@ -496,6 +497,7 @@ const HeapRegionTagged_t *pxHeapRegion;
}
configASSERT(pxHeapRegion->xTag < HEAPREGIONS_MAX_TAGCOUNT);
configASSERT(pxHeapRegion->xSizeInBytes < HEAPREGIONS_MAX_REGIONSIZE);
xTotalRegionSize = pxHeapRegion->xSizeInBytes;
/* Ensure the heap region starts on a correctly aligned boundary. */

View File

@ -19,19 +19,68 @@
/* The maximum amount of tags in use */
#define HEAPREGIONS_MAX_TAGCOUNT 16
/**
* @brief Structure to define a memory region
*/
typedef struct HeapRegionTagged
{
uint8_t *pucStartAddress;
size_t xSizeInBytes;
BaseType_t xTag;
uint32_t xExecAddr;
uint8_t *pucStartAddress; ///< Start address of the region
size_t xSizeInBytes; ///< Size of the region
BaseType_t xTag; ///< Tag for the region
uint32_t xExecAddr; ///< If non-zero, indicates the region also has an alias in IRAM.
} HeapRegionTagged_t;
/**
* @brief 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.
*
* @param pxHeapRegions Array of region definitions
*/
void vPortDefineHeapRegionsTagged( const HeapRegionTagged_t * const pxHeapRegions );
/**
* @brief 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.
*
* @param xWantedSize Size needed, in bytes
* @param tag Tag of the memory region the allocation has to be from
*
* @return Pointer to allocated memory if succesful.
* NULL if unsuccesful.
*/
void *pvPortMallocTagged( size_t xWantedSize, BaseType_t tag );
/**
* @brief 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.
*
* @param tag Tag of the memory region
*
* @return Minimum amount of free bytes available in the runtime of
* the program
*/
size_t xPortGetMinimumEverFreeHeapSizeTagged( BaseType_t tag );
/**
* @brief Get the amount of free bytes in a certain tagged region
*
* Works like xPortGetFreeHeapSize but allows the user to specify
* a specific tag
*
* @param tag Tag of the memory region
*
* @return Remaining amount of free bytes in region
*/
size_t xPortGetFreeHeapSizeTagged( BaseType_t tag );

View File

@ -28,7 +28,9 @@ INPUT = ../components/esp32/include/esp_wifi.h \
../components/app_update/include/esp_ota_ops.h \
../components/ethernet/include/esp_eth.h \
../components/ulp/include/esp32/ulp.h \
../components/esp32/include/esp_intr_alloc.h
../components/esp32/include/esp_intr_alloc.h \
../components/esp32/include/esp_heap_alloc_caps.h \
../components/freertos/include/freertos/heap_regions.h
## Get warnings for functions that have no documentation for their parameters or return value
##

78
docs/api/mem_alloc.rst Normal file
View File

@ -0,0 +1,78 @@
Memory allocation
====================
Overview
--------
The ESP32 has multiple types of RAM. Internally, there's IRAM, DRAM as well as RAM that can be used as both. It's also
possible to connect external SPI flash to the ESP32; it's memory can be integrated into the ESP32s memory map using
the flash cache.
In order to make use of all this memory, esp-idf has a capabilities-based memory allocator. Basically, if you want to have
memory with certain properties (for example, DMA-capable, accessible by a certain PID, or capable of executing code), you
can create an OR-mask of the required capabilities and pass that to pvPortMallocCaps. For instance, the normal malloc
code internally allocates memory with ```pvPortMallocCaps(size, MALLOC_CAP_8BIT)``` in order to get data memory that is
byte-addressable.
Internally, this allocator is split in two pieces. The allocator in the FreeRTOS directory can allocate memory from
tagged regions: a tag is an integer value and every region of free memory has one of these tags. The esp32-specific
code initializes these regions with specific tags, and contains the logic to select applicable tags from the
capabilities given by the user. While shown in the public API, tags are used in the communication between the two parts
and should not be used directly.
Special Uses
------------
If a certain memory structure is only addressed in 32-bit units, for example an array of ints or pointers, it can be
useful to allocate it with the MALLOC_CAP_32BIT flag. This also allows the allocator to give out IRAM memory; something
which it can't do for a normal malloc() call. This can help to use all the available memory in the ESP32.
API Reference
-------------
Header Files
^^^^^^^^^^^^
* `esp_heap_alloc_caps.h <https://github.com/espressif/esp-idf/blob/master/components/esp32/include/esp_heap_alloc_caps.h>`_
* `heap_regions.h <https://github.com/espressif/esp-idf/blob/master/components/freertos/include/freertos/heap_regions.h>`_
Macros
^^^^^^
.. doxygendefine:: MALLOC_CAP_EXEC
.. doxygendefine:: MALLOC_CAP_32BIT
.. doxygendefine:: MALLOC_CAP_8BIT
.. doxygendefine:: MALLOC_CAP_DMA
.. doxygendefine:: MALLOC_CAP_PID2
.. doxygendefine:: MALLOC_CAP_PID3
.. doxygendefine:: MALLOC_CAP_PID4
.. doxygendefine:: MALLOC_CAP_PID5
.. doxygendefine:: MALLOC_CAP_PID6
.. doxygendefine:: MALLOC_CAP_PID7
.. doxygendefine:: MALLOC_CAP_SPISRAM
.. doxygendefine:: MALLOC_CAP_INVALID
Type Definitions
^^^^^^^^^^^^^^^^
.. doxygentypedef:: HeapRegionTagged_t
Enumerations
^^^^^^^^^^^^
Structures
^^^^^^^^^^
Functions
^^^^^^^^^
.. doxygenfunction:: heap_alloc_caps_init
.. doxygenfunction:: pvPortMallocCaps
.. doxygenfunction:: xPortGetFreeHeapSizeCaps
.. doxygenfunction:: xPortGetMinimumEverFreeHeapSizeCaps
.. doxygenfunction:: vPortDefineHeapRegionsTagged
.. doxygenfunction:: pvPortMallocTagged
.. doxygenfunction:: xPortGetMinimumEverFreeHeapSizeTagged
.. doxygenfunction:: xPortGetFreeHeapSizeTagged

View File

@ -48,7 +48,8 @@ Contents:
1.3. Flash encryption and secure boot: how they work and APIs
1.4. Lower Power Coprocessor - TBA
1.5. Watchdogs <api/wdts>
1.6. ...
1.6. Memory allocation <api/mem_alloc>
1.7. ...
2. Memory - TBA
2.1. Memory layout of the application (IRAM/IROM, limitations of each) - TBA
2.2. Flash layout and partitions - TBA
@ -111,6 +112,7 @@ Contents:
Virtual Filesystem <api/vfs>
Ethernet <api/esp_eth>
Interrupt Allocation <api/intr_alloc>
Memory Allocation <api/mem_alloc>
deep-sleep-stub
Template <api/template>