summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRoman Leonov <[email protected]>2024-11-19 11:28:04 +0100
committerRoman Leonov <[email protected]>2024-11-20 13:10:23 +0100
commitb8d31a59eec6b27b900a6d51d602a6d6f47ac4d4 (patch)
tree9fcf9769c43261ed6dc60c3aa5d79b11f01876be /src
parent9e674d4faef984b846a05bed848650ec2e31f4a3 (diff)
feature(dcd_dwc2): Added cache synchronization
Diffstat (limited to 'src')
-rw-r--r--src/portable/synopsys/dwc2/dcd_dwc2.c27
-rw-r--r--src/portable/synopsys/dwc2/dwc2_esp32.h27
2 files changed, 53 insertions, 1 deletions
diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c
index 2b3ef096f..1addd28f9 100644
--- a/src/portable/synopsys/dwc2/dcd_dwc2.c
+++ b/src/portable/synopsys/dwc2/dcd_dwc2.c
@@ -47,7 +47,20 @@
// MACRO TYPEDEF CONSTANT ENUM
//--------------------------------------------------------------------+
+#ifdef DWC2_MEM_CACHE_LINE_SIZE
+CFG_TUD_MEM_SECTION struct {
+ union {
+ uint32_t data[2];
+ uint8_t buffer[DWC2_MEM_CACHE_LINE_SIZE];
+ };
+} _cache_aligned_setup_packet;
+
+#define _setup_packet _cache_aligned_setup_packet.data
+#define _sizeof_setup_packet() DWC2_MEM_CACHE_LINE_SIZE
+#else
static CFG_TUD_MEM_SECTION TU_ATTR_ALIGNED(4) uint32_t _setup_packet[2];
+#define _sizeof_setup_packet() sizeof(_setup_packet)
+#endif // DWC2_MEM_CACHE_LINE_SIZE
typedef struct {
uint8_t* buffer;
@@ -348,6 +361,11 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin
const bool is_dma = dma_device_enabled(dwc2);
if(is_dma) {
+ if (dir == TUSB_DIR_IN && total_bytes != 0) {
+ // CACHE HINT
+ // The xfer->buffer has new data for Host, move it to memory for DMA to transfer it
+ dcd_dcache_clean(xfer->buffer, total_bytes);
+ }
dep->diepdma = (uintptr_t) xfer->buffer;
}
@@ -847,6 +865,11 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi
if (doepint_bm.setup_phase_done) {
dma_setup_prepare(rhport);
+ // CACHE HINT
+ // When cache is enabled, _setup_packet must have cache line size alignment
+ // and there should be no valuable data in memory after.
+ // Thus, specific struct is used as a buffer for setup packet data
+ dcd_dcache_invalidate((uint8_t*) _setup_packet, _sizeof_setup_packet());
dcd_event_setup_received(rhport, (uint8_t*) _setup_packet, true);
return;
}
@@ -872,7 +895,9 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi
if(epnum == 0 && xfer->total_len == 0) {
dma_setup_prepare(rhport);
}
-
+ // CACHE HINT
+ // Some data has been received by DMA, fetch the data from memory to cache
+ dcd_dcache_invalidate(xfer->buffer, xfer->total_len);
dcd_event_xfer_complete(rhport, epnum, xfer->total_len, XFER_RESULT_SUCCESS, true);
}
}
diff --git a/src/portable/synopsys/dwc2/dwc2_esp32.h b/src/portable/synopsys/dwc2/dwc2_esp32.h
index 42ab4b80f..c7f1f78e9 100644
--- a/src/portable/synopsys/dwc2/dwc2_esp32.h
+++ b/src/portable/synopsys/dwc2/dwc2_esp32.h
@@ -39,6 +39,14 @@
#include "soc/periph_defs.h"
#include "soc/usb_wrap_struct.h"
+#if (CFG_TUD_DWC2_DMA_ENABLE && SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE)
+#include "sdkconfig.h"
+#include "esp_cache.h"
+#include "esp_log.h"
+
+#define DWC2_MEM_CACHE_LINE_SIZE CONFIG_CACHE_L1_CACHE_LINE_SIZE
+#endif // SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
+
#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)
#define DWC2_FS_REG_BASE 0x60080000UL
#define DWC2_EP_MAX 7
@@ -111,6 +119,25 @@ TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_update(dwc2_regs_t* dwc2, uint
// maybe usb_utmi_hal_disable()
}
+#if (CFG_TUD_DWC2_DMA_ENABLE && SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE)
+void dcd_dcache_clean(void const* addr, uint32_t data_size) {
+ int flags = ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED;
+ if (addr != NULL && data_size) {
+ esp_err_t ret = esp_cache_msync((void *) addr, data_size, flags);
+ assert(ret == ESP_OK);
+ }
+}
+
+void dcd_dcache_invalidate(void const* addr, uint32_t data_size) {
+ int flags = ESP_CACHE_MSYNC_FLAG_DIR_M2C;
+ if (addr != NULL && data_size) {
+ data_size = (data_size < DWC2_MEM_CACHE_LINE_SIZE)? DWC2_MEM_CACHE_LINE_SIZE : data_size;
+ esp_err_t ret = esp_cache_msync((void *) addr, data_size, flags);
+ assert(ret == ESP_OK);
+ }
+}
+#endif // CFG_TUD_DWC2_DMA_ENABLE && SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
+
#ifdef __cplusplus
}
#endif