Skip to content

Commit a11c23e

Browse files
Adds memory_resource
Simple memory resource class enabling the usage of C++17 PMR facilities with IDF heap allocation capabilities.
1 parent 51d40af commit a11c23e

File tree

8 files changed

+127
-2
lines changed

8 files changed

+127
-2
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
idf_build_get_property(target IDF_TARGET)
22

3-
set(srcs "esp_timer_cxx.cpp" "esp_exception.cpp" "gpio_cxx.cpp" "i2c_cxx.cpp" "spi_cxx.cpp" "spi_host_cxx.cpp")
3+
set(srcs "esp_timer_cxx.cpp" "esp_exception.cpp" "gpio_cxx.cpp" "i2c_cxx.cpp" "spi_cxx.cpp" "spi_host_cxx.cpp" "esp_memory_resource.cpp")
44
set(requires "esp_timer")
55

66
if(NOT ${target} STREQUAL "linux")

esp_memory_resource.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#include "esp_memory_resource.hpp"
2+
#include "esp_log.h"
3+
#include <utility>
4+
5+
namespace idf::memory {
6+
7+
8+
void * resource::do_allocate(size_t bytes, size_t alignment)
9+
{
10+
11+
if(auto *mem = heap_caps_aligned_alloc(alignment, bytes, std::to_underlying(cap)); mem != nullptr) {
12+
ESP_LOGD(tag, "Allocated %d bytes at %p", bytes, mem);
13+
return mem;
14+
}
15+
ESP_LOGD(tag, "Failed to get memory from resource, allocating from upstream");
16+
return upstream->allocate(bytes, alignment);
17+
18+
}
19+
void resource::do_deallocate(void *ptr, [[maybe_unused]] size_t bytes, [[maybe_unused]] size_t alignment) {
20+
free(ptr);
21+
ESP_LOGD(tag, "Freed");
22+
}
23+
24+
[[nodiscard]] bool resource::do_is_equal(const memory_resource &other) const noexcept
25+
{
26+
return this == &other;
27+
}
28+
29+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# For more information about build system see
2+
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
3+
# The following five lines of boilerplate have to be in your project's
4+
# CMakeLists in this exact order for cmake to work correctly
5+
cmake_minimum_required(VERSION 3.16)
6+
7+
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
8+
set(COMPONENTS main)
9+
project(memory_resource)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
idf_component_register(SRCS "resource.cpp"
3+
INCLUDE_DIRS "."
4+
)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
## IDF Component Manager Manifest File
2+
dependencies:
3+
idf:
4+
version: ">=5.0"
5+
espressif/esp-idf-cxx:
6+
override_path: ../../../
7+
version: "^1.0.0"
8+
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include <utility>
2+
#include "esp_memory_resource.hpp"
3+
#include "esp_heap_caps.h"
4+
#include "esp_log.h"
5+
#include "esp_system.h"
6+
7+
constexpr auto TAG = "Example";
8+
extern "C" void app_main(void)
9+
{
10+
ESP_LOGI(TAG, "[APP] Startup..");
11+
ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size());
12+
ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());
13+
14+
esp_log_level_set("*", ESP_LOG_INFO);
15+
esp_log_level_set(idf::memory::resource::tag, ESP_LOG_VERBOSE);
16+
auto memory_source = idf::memory::capabilities::dma;
17+
auto res = idf::memory::resource{memory_source};
18+
std::pmr::vector<std::byte> data{&res};
19+
data.reserve(2048);
20+
heap_caps_print_heap_info(std::to_underlying(memory_source));
21+
}

idf_component.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ dependencies:
33
version: '>=5.0'
44
description: C++ wrapper classes around ESP IDF components
55
url: https://github.com/espressif/esp-idf-cxx
6-
version: 1.0.0
6+
version: 1.1.0

include/esp_memory_resource.hpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#pragma once
2+
3+
#include <memory_resource>
4+
#include <utility>
5+
#include "esp_heap_caps.h"
6+
7+
namespace idf::memory {
8+
9+
/**
10+
* Memory capabilities for memory allocation
11+
*
12+
* Refer to IDF documentation on memory allocation for the usage of each of them.
13+
*/
14+
enum class capabilities : uint32_t {
15+
not_specified = MALLOC_CAP_DEFAULT,
16+
adressable_8bit = MALLOC_CAP_8BIT,
17+
adressable_32bit = MALLOC_CAP_32BIT,
18+
dma = MALLOC_CAP_DMA,
19+
executable = MALLOC_CAP_EXEC,
20+
from_spiram = MALLOC_CAP_SPIRAM,
21+
internal = MALLOC_CAP_INTERNAL,
22+
retention_dma = MALLOC_CAP_RETENTION,
23+
rtc = MALLOC_CAP_RTCRAM
24+
};
25+
26+
constexpr capabilities operator|(const capabilities lhs, const capabilities rhs)
27+
{
28+
return capabilities{std::to_underlying(lhs) | std::to_underlying(rhs)};
29+
}
30+
31+
/**
32+
* @brief Memory resource to be used with polymorphic allocators
33+
*/
34+
class resource : public std::pmr::memory_resource {
35+
public:
36+
static constexpr auto tag = "esp_memory_resource";
37+
/**
38+
* Construct a resource with the selected capabilities and upstream resource.
39+
*
40+
* @param cap capabilities to use in this allocator. Refer to idf memory allocation documentation to understand the effects. Default: capabilities::not_specified
41+
* @param upstream memory resource to use when allocation fails. It can be used to compose memory resources. Default: default resource.
42+
*/
43+
explicit resource(capabilities cap=capabilities::not_specified, std::pmr::memory_resource * upstream = std::pmr::get_default_resource()) : cap(cap), upstream(upstream) {}
44+
45+
private:
46+
void * do_allocate(size_t bytes, [[maybe_unused]] size_t alignment) override;
47+
void do_deallocate(void *ptr, size_t bytes, size_t alignment) override;
48+
[[nodiscard]] bool do_is_equal(const memory_resource &other) const noexcept override;
49+
capabilities cap;
50+
std::pmr::memory_resource * upstream;
51+
};
52+
53+
54+
}

0 commit comments

Comments
 (0)