Skip to content

Commit 3fb9c86

Browse files
committed
feature(dcd_dwc2): Added cache synchronization
1 parent ead08bd commit 3fb9c86

File tree

2 files changed

+80
-1
lines changed

2 files changed

+80
-1
lines changed

src/portable/synopsys/dwc2/dcd_dwc2.c

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,37 @@
4747
// MACRO TYPEDEF CONSTANT ENUM
4848
//--------------------------------------------------------------------+
4949

50+
#ifdef DWC2_ENABLE_MEM_CACHE
51+
52+
#ifndef DWC2_MEM_CACHE_LINE_SIZE
53+
#warning "Cache line size not specified, use default(64b) instead"
54+
# define DWC2_MEM_CACHE_LINE_SIZE 0x40
55+
#endif // DWC2_MEM_CACHE_LINE_SIZE
56+
57+
CFG_TUD_MEM_SECTION struct {
58+
union {
59+
uint32_t data[2];
60+
uint8_t buffer[DWC2_MEM_CACHE_LINE_SIZE];
61+
};
62+
} _cache_aligned_setup_packet;
63+
64+
#define _setup_packet _cache_aligned_setup_packet.data
65+
#define _sizeof_setup_packet() DWC2_MEM_CACHE_LINE_SIZE
66+
#else
5067
static CFG_TUD_MEM_SECTION TU_ATTR_ALIGNED(4) uint32_t _setup_packet[2];
68+
#define _sizeof_setup_packet() sizeof(_setup_packet)
69+
#endif // DWC2_ENABLE_MEM_CACHE
70+
71+
// When DMA requires cache synchronization for memory
72+
// Data synchronization: cache to memory
73+
#ifndef dsync_c2m
74+
#define dsync_c2m(_addr, _size)
75+
#endif // dsync_c2m
76+
77+
// Data synchronization: memory to cache
78+
#ifndef dsync_m2c
79+
#define dsync_m2c(_addr, _size)
80+
#endif // dsync_m2c
5181

5282
typedef struct {
5383
uint8_t* buffer;
@@ -348,6 +378,11 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin
348378

349379
const bool is_dma = dma_device_enabled(dwc2);
350380
if(is_dma) {
381+
if (dir == TUSB_DIR_IN && total_bytes != 0) {
382+
// CACHE HINT
383+
// The xfer->buffer has new data for Host, move it to memory for DMA to transfer it
384+
dsync_c2m(xfer->buffer, total_bytes);
385+
}
351386
dep->diepdma = (uintptr_t) xfer->buffer;
352387
}
353388

@@ -848,6 +883,11 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi
848883

849884
if (doepint_bm.setup_phase_done) {
850885
dma_setup_prepare(rhport);
886+
// CACHE HINT
887+
// When cache is enabled, _setup_packet must have cache line size alignment
888+
// and there should be no valuable data in memory after.
889+
// Thus, specific struct is used as a buffer for setup packet data
890+
dsync_m2c((uint8_t*) _setup_packet, _sizeof_setup_packet());
851891
dcd_event_setup_received(rhport, (uint8_t*) _setup_packet, true);
852892
return;
853893
}
@@ -873,7 +913,9 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi
873913
if(epnum == 0 && xfer->total_len == 0) {
874914
dma_setup_prepare(rhport);
875915
}
876-
916+
// CACHE HINT
917+
// Some data has been received by DMA, fetch the data from memory to cache
918+
dsync_m2c(xfer->buffer, xfer->total_len);
877919
dcd_event_xfer_complete(rhport, epnum, xfer->total_len, XFER_RESULT_SUCCESS, true);
878920
}
879921
}

src/portable/synopsys/dwc2/dwc2_esp32.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,18 @@
3939
#include "soc/periph_defs.h"
4040
#include "soc/usb_wrap_struct.h"
4141

42+
#if TU_CHECK_MCU(OPT_MCU_ESP32P4)
43+
#if (CFG_TUD_DWC2_DMA_ENABLE && SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE)
44+
#include "sdkconfig.h"
45+
#include "hal/cache_hal.h"
46+
#include "esp_cache.h"
47+
#include "esp_log.h"
48+
49+
#define DWC2_MEM_CACHE_LINE_SIZE CONFIG_CACHE_L1_CACHE_LINE_SIZE
50+
#define DWC2_ENABLE_MEM_CACHE
51+
#endif // SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
52+
#endif // OPT_MCU_ESP32P4
53+
4254
#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)
4355
#define DWC2_FS_REG_BASE 0x60080000UL
4456
#define DWC2_EP_MAX 7
@@ -111,6 +123,31 @@ TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_update(dwc2_regs_t* dwc2, uint
111123
// maybe usb_utmi_hal_disable()
112124
}
113125

126+
#ifdef DWC2_ENABLE_MEM_CACHE
127+
TU_ATTR_ALWAYS_INLINE static inline void dwc2_dcd_sync_cache_to_memory(void *addr, size_t size) {
128+
int flags = ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED;
129+
if (addr != NULL && size) {
130+
ESP_EARLY_LOGV("ESP32_DWC", "cache to mem sync, addr 0x%"PRIx32", size %d", (uintptr_t)addr, size);
131+
esp_err_t ret = esp_cache_msync(addr, size, flags);
132+
assert(ret == ESP_OK);
133+
}
134+
}
135+
136+
TU_ATTR_ALWAYS_INLINE static inline void dwc2_dcd_sync_memory_to_cache(void *addr, size_t size) {
137+
int flags = ESP_CACHE_MSYNC_FLAG_DIR_M2C;
138+
if (addr != NULL && size) {
139+
ESP_EARLY_LOGV("ESP32_DWC", "mem to cache sync, addr 0x%"PRIx32", size %d (%s)", (uintptr_t)addr, size);
140+
size = (size < DWC2_MEM_CACHE_LINE_SIZE)? DWC2_MEM_CACHE_LINE_SIZE : size;
141+
esp_err_t ret = esp_cache_msync(addr, size, flags);
142+
assert(ret == ESP_OK);
143+
}
144+
}
145+
146+
#define dsync_c2m(_addr, _size) dwc2_dcd_sync_cache_to_memory((_addr), (_size))
147+
#define dsync_m2c(_addr, _size) dwc2_dcd_sync_memory_to_cache((_addr), (_size))
148+
149+
#endif // DWC2_ENABLE_MEM_CACHE
150+
114151
#ifdef __cplusplus
115152
}
116153
#endif

0 commit comments

Comments
 (0)