1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
/*
* Copyright 2023 jacqueline <me@jacqueline.id.au>
*
* SPDX-License-Identifier: GPL-3.0-only
*/
#pragma once
#include <cstddef>
#include <cstdint>
#include "esp32/himem.h"
#include "span.hpp"
/*
* Wrapper around an ESP-IDF himem allocation, which uses RAII to clean up after
* itself.
*/
template <std::size_t size>
class HimemAlloc {
public:
esp_himem_handle_t handle;
const bool is_valid;
HimemAlloc() : is_valid(esp_himem_alloc(size, &handle) == ESP_OK) {}
~HimemAlloc() {
if (is_valid) {
esp_himem_free(handle);
}
}
// Not copyable or movable.
HimemAlloc(const HimemAlloc&) = delete;
HimemAlloc& operator=(const HimemAlloc&) = delete;
};
/*
* Wrapper around an ESP-IDF himem allocation, which maps a HimemAlloc into the
* usable address space. Instances always contain the last memory region that
* was mapped within them.
*/
template <std::size_t size>
class MappableRegion {
private:
std::byte* bytes_;
public:
esp_himem_rangehandle_t range_handle;
const bool is_valid;
MappableRegion()
: bytes_(nullptr),
is_valid(esp_himem_alloc_map_range(size, &range_handle) == ESP_OK) {}
~MappableRegion() {
if (bytes_ != nullptr) {
esp_himem_unmap(range_handle, bytes_, size);
}
if (is_valid) {
esp_himem_free_map_range(range_handle);
}
}
auto Get() -> cpp::span<std::byte> {
if (bytes_ == nullptr) {
return {};
}
return {bytes_, size};
}
auto Map(const HimemAlloc<size>& alloc) -> cpp::span<std::byte> {
assert(bytes_ == nullptr);
ESP_ERROR_CHECK(esp_himem_map(alloc.handle, range_handle, 0, 0, size, 0,
reinterpret_cast<void**>(&bytes_)));
return Get();
}
auto Unmap() -> void {
if (bytes_ != nullptr) {
ESP_ERROR_CHECK(esp_himem_unmap(range_handle, bytes_, size));
bytes_ = nullptr;
}
}
// Not copyable or movable.
MappableRegion(const MappableRegion&) = delete;
MappableRegion& operator=(const MappableRegion&) = delete;
};
|