5#include "esp_intr_alloc.h"
6#include "freertos/FreeRTOS.h"
7#include "freertos/task.h"
9#include "roo_logging.h"
11#if ROO_DISPLAY_HAS_SPI_INTERNAL_DMA && SOC_GDMA_SUPPORTED
12#include "esp_private/gdma.h"
20inline uint8_t hostToSpiPort(spi_host_device_t host_id) {
21 return static_cast<uint8_t
>(host_id) + 1;
27#if ROO_DISPLAY_HAS_SPI_INTERNAL_DMA
61#if ROO_DISPLAY_HAS_SPI_INTERNAL_DMA
112 pending_ops_.clear();
117#if ROO_DISPLAY_HAS_SPI_INTERNAL_DMA
139 pending_ops_.clear();
141 pending_ops_.clear();
150#if ROO_DISPLAY_HAS_SPI_INTERNAL_DMA
159 ok = pending_ops_.write(op);
171#if ROO_DISPLAY_HAS_SPI_INTERNAL_DMA
192void DmaController::transferCompleteISR() {
193#if ROO_DISPLAY_HAS_SPI_INTERNAL_DMA
195 Operation next = {
nullptr, 0};
196 bool has_next =
false;
197 bool notify_waiter =
false;
198 TaskHandle_t waiter =
nullptr;
200 portENTER_CRITICAL_ISR(&mux_);
201 if (!transfer_in_progress_) {
204 portEXIT_CRITICAL_ISR(&mux_);
208 completed = current_op_;
209 current_op_ = {
nullptr, 0};
211 has_next = pending_ops_.read(next);
213 startOperationCritical(next);
215 transfer_in_progress_ =
false;
216 uint8_t spi_port = hostToSpiPort(host_id_);
219 notify_waiter =
true;
222 if (notify_waiter && waiter_task_ !=
nullptr) {
223 waiter = waiter_task_;
224 waiter_task_ =
nullptr;
226 portEXIT_CRITICAL_ISR(&mux_);
228 if (completed.out_data !=
nullptr) {
230 DmaBufferPool::Buffer{
const_cast<roo::byte*
>(completed.out_data)});
233 if (waiter !=
nullptr) {
234 BaseType_t high_wakeup = pdFALSE;
235 vTaskNotifyGiveFromISR(waiter, &high_wakeup);
236 portYIELD_FROM_ISR(high_wakeup);
241#if ROO_DISPLAY_HAS_SPI_INTERNAL_DMA
242bool DmaController::startOperationCritical(Operation op) {
243 CHECK_NOTNULL(dma_ctx_);
244 CHECK_NOTNULL(op.out_data);
245 CHECK_GT(op.out_len, 0);
247 spicommon_dma_desc_setup_link(dma_ctx_->dmadesc_tx, op.out_data,
248 static_cast<int>(op.out_len),
false);
250 uint8_t spi_port = hostToSpiPort(host_id_);
256#if SOC_GDMA_SUPPORTED
257 gdma_reset(dma_ctx_->tx_dma_chan);
258 gdma_start(dma_ctx_->tx_dma_chan,
259 reinterpret_cast<intptr_t
>(
260 const_cast<spi_dma_desc_t*
>(dma_ctx_->dmadesc_tx)));
262 spi_dma_reset(dma_ctx_->tx_dma_chan);
263 spi_dma_start(dma_ctx_->tx_dma_chan,
264 const_cast<spi_dma_desc_t*
>(dma_ctx_->dmadesc_tx));
269 transfer_in_progress_ =
true;
void release(Buffer buffer)
DmaController(spi_host_device_t host_id, DmaBufferPool &dma_buffer_pool)
friend void IRAM_ATTR DmaTransferCompleteISR(void *)
bool submit(Operation op)
void SpiDmaTransferDoneIntDisable(uint8_t spi_port) __attribute__((always_inline))
void SpiDmaTransferDoneIntClear(uint8_t spi_port) __attribute__((always_inline))
void SpiDmaTxDisable(uint8_t spi_port) __attribute__((always_inline))
void IRAM_ATTR DmaTransferCompleteISR(void *arg)
void SpiSetOutBufferSize(uint8_t spi_port, int len) __attribute__((always_inline))
static constexpr size_t kDmaBufferCapacity
void SpiTxStart(uint8_t spi_port) __attribute__((always_inline))
void SpiDmaTransferDoneIntEnable(uint8_t spi_port) __attribute__((always_inline))
bool SpiDmaTransferDoneIntPending(uint8_t spi_port) __attribute__((always_inline))
void SpiDmaTxEnable(uint8_t spi_port) __attribute__((always_inline))
Defines 140 opaque HTML named colors.
#define ROO_DISPLAY_HAS_SPI_INTERNAL_DMA
const roo::byte * out_data