roo_display
API Documentation for roo_display
Loading...
Searching...
No Matches
spi_dma.h
Go to the documentation of this file.
1
#pragma once
2
3
#include <memory>
4
5
#include "freertos/FreeRTOS.h"
6
#include "freertos/task.h"
7
#include "hal/spi_types.h"
8
#include "
roo_display/hal/esp32/dma_buffer_pool.h
"
9
10
#if __has_include("esp_private/spi_common_internal.h")
11
#include "esp_private/spi_common_internal.h"
12
#define ROO_DISPLAY_HAS_SPI_INTERNAL_DMA 1
13
#else
14
#define ROO_DISPLAY_HAS_SPI_INTERNAL_DMA 0
15
#endif
16
17
namespace
roo_display
{
18
namespace
esp32 {
19
20
template
<
typename
T>
21
class
RingBuf
{
22
public
:
23
RingBuf
(
size_t
capacity
)
24
: buf_(
new
T
[
capacity
]), capacity_(
capacity
), head_(0), used_(0) {}
25
26
size_t
capacity
()
const
{
return
capacity_; }
27
size_t
used
()
const
{
return
used_; }
28
size_t
free
()
const
{
return
capacity_ - used_; }
29
30
bool
full
()
const
{
return
used_ == capacity_; }
31
bool
empty
()
const
{
return
used_ == 0; }
32
33
void
clear
() {
34
head_ = 0;
35
used_ = 0;
36
}
37
38
// Writes a single item to the ringbuffer. Returns true if successful, or
39
// false if the buffer is full.
40
bool
write
(
T
item
) {
41
if
(used_ == capacity_)
return
false
;
42
buf_[write_pos()] = std::move(
item
);
43
used_++;
44
return
true
;
45
}
46
47
// Reads a single item from the ringbuffer. Returns true if successful, or
48
// false if the buffer is empty.
49
bool
read
(
T
&
item
) {
50
if
(used_ == 0)
return
false
;
51
item
= std::move(buf_[head_]);
52
head_++;
53
if
(head_ == capacity_) head_ = 0;
54
used_--;
55
return
true
;
56
}
57
58
private
:
59
size_t
write_pos()
const
{
60
size_t
pos = head_ + used_;
61
if
(pos >= capacity_) pos -= capacity_;
62
return
pos;
63
}
64
65
std::unique_ptr<T[]> buf_;
66
size_t
capacity_;
67
size_t
head_;
68
size_t
used_;
69
};
70
71
class
DmaController
{
72
public
:
73
struct
Operation
{
74
const
roo::byte*
out_data
;
75
size_t
out_len
;
76
};
77
78
DmaController
(
spi_host_device_t
host_id
,
DmaBufferPool
&
dma_buffer_pool
);
79
80
// Initializes the DMA controller. This method must be called before any other
81
// method. The caller must ensure that the dma_buffer_pool remains valid for
82
// the entire duration of use of the DmaController.
83
void
begin
();
84
85
// Deinitializes the DMA controller. After this method returns, the caller
86
// must not call any other method. The caller must ensure that there are no
87
// pending DMA operations before calling this method.
88
void
end
();
89
90
// Submits a DMA operation. The caller must ensure that the data buffer
91
// remains valid until the operation completes. The caller must ensure that
92
// the out_len is aligned to 32 bits.
93
//
94
// If there is no pending DMA operation, the submitted operation gets started
95
// immediately. Otherwise, the submitted operation gets enqueued and will
96
// start when all previously submitted operations complete. The caller can
97
// submit multiple operations in a row, and they will get executed in order.
98
// It is the caller's responsibility to ensure that the total number of
99
// pending operations does not exceed the capacity of the dma_buffer_pool_.
100
//
101
// If the DMA operation fails to start, this method returns false.
102
bool
submit
(
Operation
op);
103
104
// Blocks until all previously submitted operations complete. If there are no
105
// pending operations, returns immediately. Only one task can wait for
106
// completion at a time; if multiple tasks call this method concurrently, the
107
// behavior is undefined.
108
void
awaitCompleted
();
109
110
private
:
111
// The DMA ISR callback.
112
friend
void
IRAM_ATTR
DmaTransferCompleteISR
(
void
*);
113
114
// Called from the SPI ISR when a DMA operation completes. This method marks
115
// the current operation as complete, returns the buffer to the pool, and
116
// starts the next pending operation, if any. If there are no more operations,
117
// the potential waiter gets notified. This method must not be called directly
118
// from application code.
119
void
transferCompleteISR();
120
121
#if ROO_DISPLAY_HAS_SPI_INTERNAL_DMA
122
// Starts a DMA operation. Must be called while holding mux_ (task or ISR
123
// critical section variant).
124
bool
startOperationCritical
(
Operation
op);
125
#endif
126
127
// SPI host this controller is bound to.
128
spi_host_device_t
host_id_;
129
130
#if ROO_DISPLAY_HAS_SPI_INTERNAL_DMA
131
// Active DMA context used for transfers; may be borrowed from SPI bus or
132
// point to owned_dma_ctx_.
133
const
spi_dma_ctx_t
*
dma_ctx_
;
134
135
// DMA context allocated by this controller (if bus-level context is absent,
136
// e.g. in case of Arduino SPI). Freed in end(); null when dma_ctx_ is
137
// borrowed.
138
spi_dma_ctx_t
*
owned_dma_ctx_
;
139
140
// Handle returned by esp_intr_alloc for the SPI host interrupt.
141
// Guarded by mux_.
142
intr_handle_t
dma_intr_handle_
;
143
144
// True while a DMA transfer is currently active on the peripheral.
145
// Guarded by mux_.
146
bool
transfer_in_progress_
;
147
148
// Task currently blocked in awaitCompleted(), if any.
149
// Guarded by mux_.
150
TaskHandle_t
waiter_task_
;
151
152
// Operation currently being transferred by DMA.
153
// Guarded by mux_.
154
Operation
current_op_
;
155
156
// Protects ISR/task shared state above.
157
portMUX_TYPE
mux_;
158
#endif
159
160
// Buffer pool backing operation payload storage.
161
DmaBufferPool
& dma_buffer_pool_;
162
163
// FIFO of submitted operations waiting to start.
164
// Guarded by mux_.
165
RingBuf<Operation>
pending_ops_;
166
};
167
168
}
// namespace esp32
169
}
// namespace roo_display
roo_display::esp32::DmaBufferPool
Definition
dma_buffer_pool.h:27
roo_display::esp32::DmaController
Definition
spi_dma.h:71
roo_display::esp32::DmaController::awaitCompleted
void awaitCompleted()
Definition
spi_dma.cpp:170
roo_display::esp32::DmaController::DmaTransferCompleteISR
friend void IRAM_ATTR DmaTransferCompleteISR(void *)
Definition
spi_dma.cpp:26
roo_display::esp32::DmaController::begin
void begin()
Definition
spi_dma.cpp:60
roo_display::esp32::DmaController::submit
bool submit(Operation op)
Definition
spi_dma.cpp:145
roo_display::esp32::DmaController::end
void end()
Definition
spi_dma.cpp:116
roo_display::esp32::RingBuf
Definition
spi_dma.h:21
roo_display::esp32::RingBuf::RingBuf
RingBuf(size_t capacity)
Definition
spi_dma.h:23
roo_display::esp32::RingBuf::full
bool full() const
Definition
spi_dma.h:30
roo_display::esp32::RingBuf::empty
bool empty() const
Definition
spi_dma.h:31
roo_display::esp32::RingBuf::capacity
size_t capacity() const
Definition
spi_dma.h:26
roo_display::esp32::RingBuf::write
bool write(T item)
Definition
spi_dma.h:40
roo_display::esp32::RingBuf::used
size_t used() const
Definition
spi_dma.h:27
roo_display::esp32::RingBuf::clear
void clear()
Definition
spi_dma.h:33
roo_display::esp32::RingBuf::free
size_t free() const
Definition
spi_dma.h:28
roo_display::esp32::RingBuf::read
bool read(T &item)
Definition
spi_dma.h:49
dma_buffer_pool.h
roo_display
Defines 140 opaque HTML named colors.
Definition
roo_display.cpp:7
roo_display::BlendOp
Definition
blending.h:200
roo_display::esp32::DmaController::Operation
Definition
spi_dma.h:73
roo_display::esp32::DmaController::Operation::out_len
size_t out_len
Definition
spi_dma.h:75
roo_display::esp32::DmaController::Operation::out_data
const roo::byte * out_data
Definition
spi_dma.h:74
temp_repos
roo_display
src
roo_display
hal
esp32
spi_dma.h
Generated by
1.9.8