From 1c6b452bba5e6a57d009fc2f8312da812407f21d Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Sun, 9 Jan 2022 16:24:20 +0200 Subject: [PATCH 1/2] * Invalidate framebuffer cache before using. * Fixes #1407 --- src/omv/imlib/framebuffer.c | 9 +++++++-- src/omv/ports/stm32/sensor.c | 21 --------------------- 2 files changed, 7 insertions(+), 23 deletions(-) diff --git a/src/omv/imlib/framebuffer.c b/src/omv/imlib/framebuffer.c index 4761cf5a3..7c5c15714 100644 --- a/src/omv/imlib/framebuffer.c +++ b/src/omv/imlib/framebuffer.c @@ -364,12 +364,18 @@ void framebuffer_auto_adjust_buffers() void framebuffer_free_current_buffer() { + vbuffer_t *buffer = framebuffer_get_buffer(framebuffer->head); + #ifdef __DCACHE_PRESENT + // Make sure all cached CPU writes are flushed before returning the buffer. + SCB_InvalidateDCache_by_Addr(buffer->data, framebuffer_get_buffer_size()); + #endif + // Invalidate frame. framebuffer->pixfmt = PIXFORMAT_INVALID; // Allow frame to be updated in single buffer mode... if (framebuffer->n_buffers == 1) { - framebuffer_get_buffer(framebuffer->head)->waiting_for_data = true; + buffer->waiting_for_data = true; } } @@ -472,7 +478,6 @@ vbuffer_t *framebuffer_get_tail(framebuffer_flags_t flags) // Setup to check head again. framebuffer->check_head = true; } - return buffer; } diff --git a/src/omv/ports/stm32/sensor.c b/src/omv/ports/stm32/sensor.c index 8f35bddb3..3819b0b11 100644 --- a/src/omv/ports/stm32/sensor.c +++ b/src/omv/ports/stm32/sensor.c @@ -959,35 +959,19 @@ int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags) switch (sensor->pixformat) { case PIXFORMAT_GRAYSCALE: MAIN_FB()->pixfmt = PIXFORMAT_GRAYSCALE; - #if (OMV_ENABLE_SENSOR_MDMA == 1) - // Flush data for MDMA - SCB_InvalidateDCache_by_Addr(buffer->data, w * h); - #endif break; case PIXFORMAT_RGB565: MAIN_FB()->pixfmt = PIXFORMAT_RGB565; - #if (OMV_ENABLE_SENSOR_MDMA == 1) - // Flush data for MDMA - SCB_InvalidateDCache_by_Addr(buffer->data, w * h * sizeof(uint16_t)); - #endif break; case PIXFORMAT_BAYER: MAIN_FB()->pixfmt = PIXFORMAT_BAYER; MAIN_FB()->subfmt_id = sensor->hw_flags.bayer; - #if (OMV_ENABLE_SENSOR_MDMA == 1) - // Flush data for MDMA - SCB_InvalidateDCache_by_Addr(buffer->data, w * h); - #endif break; case PIXFORMAT_YUV422: { bool yuv_order = sensor->hw_flags.yuv_order == SENSOR_HW_FLAGS_YUV422; int even = yuv_order ? PIXFORMAT_YUV422 : PIXFORMAT_YVU422; int odd = yuv_order ? PIXFORMAT_YVU422 : PIXFORMAT_YUV422; MAIN_FB()->pixfmt = (MAIN_FB()->x % 2) ? odd : even; - #if (OMV_ENABLE_SENSOR_MDMA == 1) - // Flush data for MDMA - SCB_InvalidateDCache_by_Addr(buffer->data, w * h * sizeof(uint16_t)); - #endif break; } case PIXFORMAT_JPEG: { @@ -1004,11 +988,6 @@ int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags) if (__HAL_DMA_GET_COUNTER(&DMAHandle)) { // Add in the uncompleted transfer length. size += ((length / sizeof(uint32_t)) - __HAL_DMA_GET_COUNTER(&DMAHandle)) * sizeof(uint32_t); } - - #if defined(MCU_SERIES_F7) || defined(MCU_SERIES_H7) - // Flush data for DMA - SCB_InvalidateDCache_by_Addr(buffer->data, size); - #endif } // Clean trailing data after 0xFFD9 at the end of the jpeg byte stream. MAIN_FB()->pixfmt = PIXFORMAT_JPEG; From e6cc4223d4acc019f290594d10b6b5089bc5b46c Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Sun, 9 Jan 2022 21:15:54 +0200 Subject: [PATCH 2/2] Make MDMA fully offload image transfer by default. --- src/omv/ports/stm32/sensor.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/omv/ports/stm32/sensor.c b/src/omv/ports/stm32/sensor.c index 3819b0b11..23e523c1c 100644 --- a/src/omv/ports/stm32/sensor.c +++ b/src/omv/ports/stm32/sensor.c @@ -26,11 +26,6 @@ #define SENSOR_TIMEOUT_MS (3000) #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) -// Higher performance complete MDMA offload. -#if (OMV_ENABLE_SENSOR_MDMA == 1) -#define OMV_ENABLE_SENSOR_MDMA_TOTAL_OFFLOAD 1 -#endif - sensor_t sensor = {}; static TIM_HandleTypeDef TIMHandle = {.Instance = DCMI_TIM}; static DMA_HandleTypeDef DMAHandle = {.Instance = DMA2_Stream1}; @@ -380,7 +375,7 @@ static uint32_t get_dcmi_hw_crop(uint32_t bytes_per_pixel) void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi) { // This can be executed at any time since this interrupt has a higher priority than DMA2_Stream1_IRQn. - #if (OMV_ENABLE_SENSOR_MDMA_TOTAL_OFFLOAD == 1) + #if (OMV_ENABLE_SENSOR_MDMA == 1) // Clear out any stale flags. DMA2->LIFCR = DMA_FLAG_TCIF1_5 | DMA_FLAG_HTIF1_5; // Re-enable the DMA IRQ to catch the next start line. @@ -447,7 +442,7 @@ void DCMI_DMAConvCpltUser(uint32_t addr) if (drop_frame) { // If we're dropping a frame in full offload mode it's safe to disable this interrupt saving // ourselves from having to service the DMA complete callback. - #if (OMV_ENABLE_SENSOR_MDMA_TOTAL_OFFLOAD == 1) + #if (OMV_ENABLE_SENSOR_MDMA == 1) if (!sensor.transpose) { HAL_NVIC_DisableIRQ(DMA2_Stream1_IRQn); } @@ -531,7 +526,7 @@ void DCMI_DMAConvCpltUser(uint32_t addr) // DCMI_DMAXferCplt in the HAL DCMI driver always calls DCMI_DMAConvCpltUser with the other // MAR register. So, we have to fix the address in full MDMA offload mode... - #if (OMV_ENABLE_SENSOR_MDMA_TOTAL_OFFLOAD == 1) + #if (OMV_ENABLE_SENSOR_MDMA == 1) if (!sensor.transpose) { addr = (uint32_t) &_line_buf; } @@ -547,7 +542,7 @@ void DCMI_DMAConvCpltUser(uint32_t addr) // For all non-JPEG and non-transposed modes we can completely offload image catpure to MDMA // and we do not need to receive any line interrupts for the rest of the frame until it ends. - #if (OMV_ENABLE_SENSOR_MDMA_TOTAL_OFFLOAD == 1) + #if (OMV_ENABLE_SENSOR_MDMA == 1) if (!sensor.transpose) { // NOTE: We're starting MDMA here because it gives the maximum amount of time before we // have to drop the frame if there's no space. If you use the FRAME/VSYNC callbacks then @@ -808,7 +803,6 @@ int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags) memcpy(&DCMI_MDMA_Handle1.Init, &DCMI_MDMA_Handle0.Init, sizeof(MDMA_InitTypeDef)); HAL_MDMA_Init(&DCMI_MDMA_Handle0); - #if (OMV_ENABLE_SENSOR_MDMA_TOTAL_OFFLOAD == 1) // If we are not transposing the image we can fully offload image capture from the CPU. if (!sensor->transpose) { // MDMA will trigger on each TC from DMA and transfer one line to the frame buffer. @@ -822,9 +816,6 @@ int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags) } else { HAL_MDMA_Init(&DCMI_MDMA_Handle1); } - #else - HAL_MDMA_Init(&DCMI_MDMA_Handle1); - #endif } #endif @@ -870,7 +861,7 @@ int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags) if (length > DMA_MAX_XFER_SIZE) { length /= 2; } - #if (OMV_ENABLE_SENSOR_MDMA_TOTAL_OFFLOAD == 1) + #if (OMV_ENABLE_SENSOR_MDMA == 1) // Special transfer mode with MDMA that completely offloads the line capture load. } else if ((sensor->pixformat != PIXFORMAT_JPEG) && (!sensor->transpose)) { // DMA to circular mode writing the same line over and over again.