roo_display
API Documentation for roo_display
Loading...
Searching...
No Matches
dma_buffer_pool.cpp
Go to the documentation of this file.
1#if (defined ESP_PLATFORM && !defined ROO_TESTING)
2
4
5#include <cstddef>
6
7#include "esp_heap_caps.h"
8#include "freertos/FreeRTOS.h"
9#include "freertos/semphr.h"
10#include "roo_logging.h"
11
12namespace roo_display {
13namespace esp32 {
14
16 : buffer_data_(nullptr),
17 available_(nullptr),
18 mux_(portMUX_INITIALIZER_UNLOCKED) {
19 for (size_t i = 0; i < kDmaBufferCount; ++i) {
20 in_use_[i] = false;
21 }
22}
23
24void DmaBufferPool::lockState() {
25 if (xPortInIsrContext()) {
26 portENTER_CRITICAL_ISR(&mux_);
27 } else {
28 portENTER_CRITICAL(&mux_);
29 }
30}
31
32void DmaBufferPool::unlockState() {
33 if (xPortInIsrContext()) {
34 portEXIT_CRITICAL_ISR(&mux_);
35 } else {
36 portEXIT_CRITICAL(&mux_);
37 }
38}
39
40size_t DmaBufferPool::acquireFreeSlot() {
41 lockState();
42 for (size_t i = 0; i < kDmaBufferCount; ++i) {
43 if (!in_use_[i]) {
44 in_use_[i] = true;
45 unlockState();
46 return i;
47 }
48 }
49 unlockState();
50 CHECK(false) << "DmaBufferPool semaphore/signaling mismatch";
51 return 0;
52}
53
54bool DmaBufferPool::markSlotFree(size_t index) {
55 bool released = false;
56 lockState();
57 if (in_use_[index]) {
58 in_use_[index] = false;
59 released = true;
60 }
61 unlockState();
62 return released;
63}
64
65void DmaBufferPool::begin() {
66 CHECK_EQ(buffer_data_, nullptr);
67 CHECK_EQ(available_, nullptr);
68
69 const size_t pool_bytes = kDmaBufferCount * kDmaBufferCapacity;
70 buffer_data_ = static_cast<roo::byte*>(
71 heap_caps_malloc(pool_bytes, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL));
72 CHECK_NOTNULL(buffer_data_);
73
74 available_ = xSemaphoreCreateCountingStatic(kDmaBufferCount, kDmaBufferCount,
75 &available_storage_);
76 CHECK_NOTNULL(available_);
77
78 for (size_t i = 0; i < kDmaBufferCount; ++i) {
79 in_use_[i] = false;
80 }
81}
82
83void DmaBufferPool::end() {
84 if (buffer_data_ == nullptr) return;
85
86 CHECK_NOTNULL(available_);
87 vSemaphoreDelete(available_);
88 available_ = nullptr;
89
90 heap_caps_free(buffer_data_);
91 buffer_data_ = nullptr;
92}
93
94DmaBufferPool::Buffer DmaBufferPool::acquire() {
95 CHECK_NOTNULL(buffer_data_);
96 CHECK_NOTNULL(available_);
97
98 CHECK_EQ(xSemaphoreTake(available_, portMAX_DELAY), pdTRUE);
99 size_t index = acquireFreeSlot();
100 CHECK_LT(index, kDmaBufferCount);
101
102 return Buffer{.data = buffer_data_ + index * kDmaBufferCapacity};
103}
104
105void DmaBufferPool::release(Buffer buffer) {
106 CHECK_NOTNULL(buffer_data_);
107 CHECK_NOTNULL(available_);
108 CHECK_NOTNULL(buffer.data);
109
110 ptrdiff_t offset = buffer.data - buffer_data_;
111 CHECK_GE(offset, 0);
112 CHECK_EQ(offset % static_cast<ptrdiff_t>(kDmaBufferCapacity), 0);
113
114 size_t index = static_cast<size_t>(offset) / kDmaBufferCapacity;
115 CHECK_LT(index, kDmaBufferCount);
116 CHECK(markSlotFree(index))
117 << "Buffer released twice or not acquired from this pool";
118
119 if (xPortInIsrContext()) {
120 BaseType_t high_wakeup = pdFALSE;
121 CHECK_EQ(xSemaphoreGiveFromISR(available_, &high_wakeup), pdTRUE);
122 if (high_wakeup == pdTRUE) {
123 portYIELD_FROM_ISR();
124 }
125 return;
126 }
127
128 CHECK_EQ(xSemaphoreGive(available_), pdTRUE);
129}
130
131} // namespace esp32
132} // namespace roo_display
133
134#endif // (defined ESP_PLATFORM && !defined ROO_TESTING)
@ CHECK
Definition inflate.h:47
Defines 140 opaque HTML named colors.