From b60ccd0a97035079f957a44821a85b2f5dc5924c Mon Sep 17 00:00:00 2001
From: Florian Loitsch <florian@toit.io>
Date: Tue, 26 Nov 2024 15:12:34 +0100
Subject: [PATCH] Use auto allocation of DMA channels for SPI. (#2649)

Fixes #2647.
---
 src/resources/spi_esp32.cc | 41 ++++++++------------------------------
 src/resources/spi_esp32.h  |  3 +--
 src/top.h                  |  9 +++++++++
 3 files changed, 18 insertions(+), 35 deletions(-)

diff --git a/src/resources/spi_esp32.cc b/src/resources/spi_esp32.cc
index 6da31503d..4f6f86422 100644
--- a/src/resources/spi_esp32.cc
+++ b/src/resources/spi_esp32.cc
@@ -32,8 +32,6 @@
 
 namespace toit {
 
-static ResourcePool<int, 0> dma_channels(1, 2);
-
 const spi_host_device_t kInvalidHostDevice = spi_host_device_t(-1);
 
 static ResourcePool<spi_host_device_t, kInvalidHostDevice> spi_host_devices(
@@ -51,18 +49,15 @@ static ResourcePool<spi_host_device_t, kInvalidHostDevice> spi_host_devices(
 #endif
 );
 
-SpiResourceGroup::SpiResourceGroup(Process* process, EventSource* event_source, spi_host_device_t host_device,
-                                   int dma_channel)
+SpiResourceGroup::SpiResourceGroup(Process* process, EventSource* event_source, spi_host_device_t host_device)
     : ResourceGroup(process, event_source)
-    , host_device_(host_device)
-    , dma_channel_(dma_channel) {}
+    , host_device_(host_device) {}
 
 SpiResourceGroup::~SpiResourceGroup() {
   SystemEventSource::instance()->run([&]() -> void {
     FATAL_IF_NOT_ESP_OK(spi_bus_free(host_device_));
   });
   spi_host_devices.put(host_device_);
-  dma_channels.put(dma_channel_);
 }
 
 MODULE_IMPLEMENTATION(spi, MODULE_SPI);
@@ -103,12 +98,6 @@ PRIMITIVE(init) {
   host_device = spi_host_devices.preferred(host_device);
   if (host_device == kInvalidHostDevice) FAIL(ALREADY_IN_USE);
 
-  int dma_chan = dma_channels.any();
-  if (dma_chan == 0) {
-    spi_host_devices.put(host_device);
-    FAIL(ALLOCATION_FAILED);
-  }
-
   spi_bus_config_t conf = {};
   conf.mosi_io_num = mosi;
   conf.miso_io_num = miso;
@@ -118,33 +107,19 @@ PRIMITIVE(init) {
   conf.max_transfer_sz = 0;
   conf.flags = 0;
   conf.intr_flags = ESP_INTR_FLAG_IRAM;
-  struct {
-    spi_host_device_t host_device;
-    int dma_chan;
-    esp_err_t err;
-  } args {
-    .host_device = host_device,
-#ifdef CONFIG_IDF_TARGET_ESP32S3
-    .dma_chan = SPI_DMA_CH_AUTO,
-#else
-    .dma_chan = dma_chan,
-#endif
-    .err = ESP_OK,
-  };
+  CAPTURE2(spi_host_device_t, host_device, spi_bus_config_t, conf);
+  esp_err_t err = ESP_OK;
   SystemEventSource::instance()->run([&]() -> void {
-    args.err = spi_bus_initialize(args.host_device, &conf, args.dma_chan);
+    err = spi_bus_initialize(capture.host_device, &capture.conf, SPI_DMA_CH_AUTO);
   });
-  if (args.err != ESP_OK) {
+  if (err != ESP_OK) {
     spi_host_devices.put(host_device);
-    dma_channels.put(dma_chan);
-    return Primitive::os_error(args.err, process);
+    return Primitive::os_error(err, process);
   }
 
-  // TODO: Reclaim dma channel.
-  SpiResourceGroup* spi = _new SpiResourceGroup(process, null, host_device, dma_chan);
+  SpiResourceGroup* spi = _new SpiResourceGroup(process, null, host_device);
   if (!spi) {
     spi_host_devices.put(host_device);
-    dma_channels.put(dma_chan);
     FAIL(MALLOC_FAILED);
   }
   proxy->set_external_address(spi);
diff --git a/src/resources/spi_esp32.h b/src/resources/spi_esp32.h
index b7c6947a0..66fae41d5 100644
--- a/src/resources/spi_esp32.h
+++ b/src/resources/spi_esp32.h
@@ -30,14 +30,13 @@ namespace toit {
 class SpiResourceGroup : public ResourceGroup {
  public:
   TAG(SpiResourceGroup);
-  SpiResourceGroup(Process* process, EventSource* event_source, spi_host_device_t host_device, int dma_channel);
+  SpiResourceGroup(Process* process, EventSource* event_source, spi_host_device_t host_device);
   ~SpiResourceGroup() override;
 
   spi_host_device_t host_device() { return host_device_; }
 
  private:
   spi_host_device_t host_device_;
-  int dma_channel_;
 };
 
 class SpiDevice : public Resource {
diff --git a/src/top.h b/src/top.h
index ab9b8f6f6..d7c0ddc6c 100644
--- a/src/top.h
+++ b/src/top.h
@@ -311,6 +311,15 @@ class Task;
 // libraries.  By bundling the captured variables in an on-stack object we
 // avoid that.
 
+#define CAPTURE2(T1, x1, T2, x2)               \
+  struct {                                     \
+    T1 x1;                                     \
+    T2 x2;                                     \
+  } capture = {                                \
+    .x1 = x1,                                  \
+    .x2 = x2,                                  \
+  }
+
 #define CAPTURE3(T1, x1, T2, x2, T3, x3)       \
   struct {                                     \
     T1 x1;                                     \