From cc823e2fbb32e4b9a7901421c5be833e8c99706f Mon Sep 17 00:00:00 2001 From: "Kwabena W. Agyeman" Date: Tue, 18 Jun 2024 21:51:58 -0700 Subject: [PATCH] ports: Fix accidental CPU cache invalidation. --- src/omv/imlib/framebuffer.c | 6 ++++-- src/omv/imlib/framebuffer.h | 5 +++-- src/omv/ports/mimxrt/sensor.c | 17 ++++++++++++++--- src/omv/ports/stm32/sensor.c | 11 ++++++++++- 4 files changed, 31 insertions(+), 8 deletions(-) diff --git a/src/omv/imlib/framebuffer.c b/src/omv/imlib/framebuffer.c index 4d614b6e3..0bfcb587a 100644 --- a/src/omv/imlib/framebuffer.c +++ b/src/omv/imlib/framebuffer.c @@ -404,8 +404,10 @@ vbuffer_t *framebuffer_get_head(framebuffer_flags_t flags) { vbuffer_t *buffer = framebuffer_get_buffer(new_head); #ifdef __DCACHE_PRESENT - // Make sure any cached CPU reads are dropped before returning the buffer. - SCB_InvalidateDCache_by_Addr(buffer->data, framebuffer_get_buffer_size()); + if (flags & FB_INVALIDATE) { + // Make sure any cached CPU reads are dropped before returning the buffer. + SCB_InvalidateDCache_by_Addr(buffer->data, framebuffer_get_buffer_size()); + } #endif return buffer; diff --git a/src/omv/imlib/framebuffer.h b/src/omv/imlib/framebuffer.h index 1161fdbbb..66bba58fc 100644 --- a/src/omv/imlib/framebuffer.h +++ b/src/omv/imlib/framebuffer.h @@ -40,8 +40,9 @@ typedef struct framebuffer { extern framebuffer_t *framebuffer; typedef enum { - FB_NO_FLAGS = (0 << 0), - FB_PEEK = (1 << 0), // If set, will not move the head/tail. + FB_NO_FLAGS = (0 << 0), + FB_PEEK = (1 << 0), // If set, will not move the head/tail. + FB_INVALIDATE = (1 << 1), // If set, invalidate the buffer on return. } framebuffer_flags_t; typedef struct vbuffer { diff --git a/src/omv/ports/mimxrt/sensor.c b/src/omv/ports/mimxrt/sensor.c index e5a1a88c3..be6052d9a 100644 --- a/src/omv/ports/mimxrt/sensor.c +++ b/src/omv/ports/mimxrt/sensor.c @@ -26,6 +26,7 @@ #define DMA_LENGTH_ALIGNMENT (8) #define SENSOR_TIMEOUT_MS (3000) +#define MIN_EDMA_DST_INC (4) // Sensor struct. sensor_t sensor = {}; @@ -156,6 +157,7 @@ int sensor_abort(bool fifo_flush, bool in_irq) { CSI_DisableInterrupts(CSI, CSI_IRQ_FLAGS); CSI_REG_CR3(CSI) &= ~CSI_CR3_DMA_REQ_EN_RFF_MASK; CSI_REG_CR18(CSI) &= ~CSI_CR18_CSI_ENABLE_MASK; + dest_inc_size = 0; sensor.first_line = false; sensor.drop_frame = false; sensor.last_frame_ms = 0; @@ -208,7 +210,7 @@ int sensor_dma_memcpy(void *dma, void *dst, void *src, int bpp, bool transposed) // beats. Additionally, the CSI hardware lacks cropping so we cannot align the source address. // Given this, performance will be lacking on cropped images. So much so that we do not use // the EDMA for anything less than 4-byte transfers otherwise you get sensor timeout errors. - if (dest_inc_size < 4) { + if (dest_inc_size < MIN_EDMA_DST_INC) { return -1; } @@ -468,7 +470,16 @@ int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags) { } #endif - vbuffer_t *buffer = framebuffer_get_head(FB_NO_FLAGS); + framebuffer_flags_t fb_flags = FB_NO_FLAGS; + + #if defined(OMV_CSI_DMA) + // dest_inc_size will be less than MIN_EDMA_DST_INC if the EDMA is not initialized or unusable. + if (dest_inc_size >= MIN_EDMA_DST_INC) { + fb_flags = FB_INVALIDATE; + } + #endif + + vbuffer_t *buffer = framebuffer_get_head(fb_flags); // Wait for the DMA to finish the transfer. for (mp_uint_t ticks = mp_hal_ticks_ms(); buffer == NULL;) { MICROPY_EVENT_POLL_HOOK @@ -483,7 +494,7 @@ int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags) { return SENSOR_ERROR_CAPTURE_TIMEOUT; } - buffer = framebuffer_get_head(FB_NO_FLAGS); + buffer = framebuffer_get_head(fb_flags); } // We're done receiving data. diff --git a/src/omv/ports/stm32/sensor.c b/src/omv/ports/stm32/sensor.c index 4ef04a598..d25ef79d2 100644 --- a/src/omv/ports/stm32/sensor.c +++ b/src/omv/ports/stm32/sensor.c @@ -825,10 +825,19 @@ int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags) { __HAL_DCMI_ENABLE_IT(&DCMIHandle, DCMI_IT_FRAME); } + framebuffer_flags_t fb_flags = FB_NO_FLAGS; + + #if defined(OMV_MDMA_CHANNEL_DCMI_0) + // DCMI_MDMA_Handle0.State will be HAL_MDMA_STATE_RESET if the MDMA is not initialized. + if (DCMI_MDMA_Handle0.State != HAL_MDMA_STATE_RESET) { + fb_flags = FB_INVALIDATE; + } + #endif + vbuffer_t *buffer = NULL; // Wait for the frame data. __WFI() below will exit right on time because of DCMI_IT_FRAME. // While waiting SysTick will trigger allowing us to timeout. - for (uint32_t tick_start = HAL_GetTick(); !(buffer = framebuffer_get_head(FB_NO_FLAGS)); ) { + for (uint32_t tick_start = HAL_GetTick(); !(buffer = framebuffer_get_head(fb_flags)); ) { __WFI(); // If we haven't exited this loop before the timeout then we need to abort the transfer.