From 5c1599c14e02385444389e9ba8801574f651135c Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Wed, 4 Oct 2023 20:24:53 +0200 Subject: [PATCH 1/2] ports/stm32: Remove hardcoded MDMA channels. MDMA channels can now be defined in board config files. --- .../ARDUINO_NICLA_VISION/omv_boardconfig.h | 7 +++- .../ARDUINO_PORTENTA_H7/omv_boardconfig.h | 7 +++- src/omv/boards/OPENMV4/omv_boardconfig.h | 7 +++- src/omv/boards/OPENMV4P/omv_boardconfig.h | 7 +++- src/omv/boards/OPENMV4_PRO/omv_boardconfig.h | 7 +++- src/omv/boards/OPENMVPT/omv_boardconfig.h | 7 +++- src/omv/imlib/jpeg.c | 13 +++++-- src/omv/ports/stm32/dma_utils.h | 6 +++ src/omv/ports/stm32/sensor.c | 37 +++++++++++-------- src/omv/ports/stm32/stm32fxxx_hal_msp.c | 2 +- 10 files changed, 67 insertions(+), 33 deletions(-) diff --git a/src/omv/boards/ARDUINO_NICLA_VISION/omv_boardconfig.h b/src/omv/boards/ARDUINO_NICLA_VISION/omv_boardconfig.h index 459725a95..f6b02f58d 100644 --- a/src/omv/boards/ARDUINO_NICLA_VISION/omv_boardconfig.h +++ b/src/omv/boards/ARDUINO_NICLA_VISION/omv_boardconfig.h @@ -35,8 +35,11 @@ // Enable hardware JPEG #define OMV_HARDWARE_JPEG (1) -// Enable MDMA sensor offload -#define OMV_ENABLE_SENSOR_MDMA (1) +// MDMA configuration +#define OMV_MDMA_CHANNEL_DCMI_0 (0) +#define OMV_MDMA_CHANNEL_DCMI_1 (1) +#define OMV_MDMA_CHANNEL_JPEG_IN (7) // in has a lower pri than out +#define OMV_MDMA_CHANNEL_JPEG_OUT (6) // out has a higher pri than in // Enable additional GPIO banks #define OMV_ENABLE_GPIO_BANK_F (1) diff --git a/src/omv/boards/ARDUINO_PORTENTA_H7/omv_boardconfig.h b/src/omv/boards/ARDUINO_PORTENTA_H7/omv_boardconfig.h index d1b646b0c..5deff292d 100644 --- a/src/omv/boards/ARDUINO_PORTENTA_H7/omv_boardconfig.h +++ b/src/omv/boards/ARDUINO_PORTENTA_H7/omv_boardconfig.h @@ -31,8 +31,11 @@ // Enable hardware JPEG #define OMV_HARDWARE_JPEG (1) -// Enable MDMA sensor offload. -#define OMV_ENABLE_SENSOR_MDMA (1) +// MDMA configuration +#define OMV_MDMA_CHANNEL_DCMI_0 (0) +#define OMV_MDMA_CHANNEL_DCMI_1 (1) +#define OMV_MDMA_CHANNEL_JPEG_IN (7) // in has a lower pri than out +#define OMV_MDMA_CHANNEL_JPEG_OUT (6) // out has a higher pri than in // Enable additional GPIO banks. #define OMV_ENABLE_GPIO_BANK_F (1) diff --git a/src/omv/boards/OPENMV4/omv_boardconfig.h b/src/omv/boards/OPENMV4/omv_boardconfig.h index 980cc2944..a29e13563 100644 --- a/src/omv/boards/OPENMV4/omv_boardconfig.h +++ b/src/omv/boards/OPENMV4/omv_boardconfig.h @@ -48,8 +48,11 @@ // Enable hardware JPEG #define OMV_HARDWARE_JPEG (1) -// Enable MDMA sensor offload. -#define OMV_ENABLE_SENSOR_MDMA (1) +// MDMA configuration +#define OMV_MDMA_CHANNEL_DCMI_0 (0) +#define OMV_MDMA_CHANNEL_DCMI_1 (1) +#define OMV_MDMA_CHANNEL_JPEG_IN (7) // in has a lower pri than out +#define OMV_MDMA_CHANNEL_JPEG_OUT (6) // out has a higher pri than in // Enable sensor drivers #define OMV_ENABLE_OV2640 (1) diff --git a/src/omv/boards/OPENMV4P/omv_boardconfig.h b/src/omv/boards/OPENMV4P/omv_boardconfig.h index 50432045a..cefe89a01 100644 --- a/src/omv/boards/OPENMV4P/omv_boardconfig.h +++ b/src/omv/boards/OPENMV4P/omv_boardconfig.h @@ -48,8 +48,11 @@ // Enable hardware JPEG #define OMV_HARDWARE_JPEG (1) -// Enable MDMA sensor offload. -#define OMV_ENABLE_SENSOR_MDMA (1) +// MDMA configuration +#define OMV_MDMA_CHANNEL_DCMI_0 (0) +#define OMV_MDMA_CHANNEL_DCMI_1 (1) +#define OMV_MDMA_CHANNEL_JPEG_IN (7) // in has a lower pri than out +#define OMV_MDMA_CHANNEL_JPEG_OUT (6) // out has a higher pri than in // Enable sensor drivers #define OMV_ENABLE_OV2640 (1) diff --git a/src/omv/boards/OPENMV4_PRO/omv_boardconfig.h b/src/omv/boards/OPENMV4_PRO/omv_boardconfig.h index ae11b2d6b..788e00d0d 100644 --- a/src/omv/boards/OPENMV4_PRO/omv_boardconfig.h +++ b/src/omv/boards/OPENMV4_PRO/omv_boardconfig.h @@ -33,8 +33,11 @@ // Enable hardware JPEG #define OMV_HARDWARE_JPEG (1) -// Enable MDMA sensor offload. -#define OMV_ENABLE_SENSOR_MDMA (1) +// MDMA configuration +#define OMV_MDMA_CHANNEL_DCMI_0 (0) +#define OMV_MDMA_CHANNEL_DCMI_1 (1) +#define OMV_MDMA_CHANNEL_JPEG_IN (7) // in has a lower pri than out +#define OMV_MDMA_CHANNEL_JPEG_OUT (6) // out has a higher pri than in // Enable additional GPIO banks #define OMV_ENABLE_GPIO_BANK_F (1) diff --git a/src/omv/boards/OPENMVPT/omv_boardconfig.h b/src/omv/boards/OPENMVPT/omv_boardconfig.h index 15ddef81a..fcb43c72a 100644 --- a/src/omv/boards/OPENMVPT/omv_boardconfig.h +++ b/src/omv/boards/OPENMVPT/omv_boardconfig.h @@ -45,8 +45,11 @@ // Enable hardware JPEG #define OMV_HARDWARE_JPEG (1) -// Enable MDMA sensor offload. -#define OMV_ENABLE_SENSOR_MDMA (1) +// MDMA configuration +#define OMV_MDMA_CHANNEL_DCMI_0 (0) +#define OMV_MDMA_CHANNEL_DCMI_1 (1) +#define OMV_MDMA_CHANNEL_JPEG_IN (7) // in has a lower pri than out +#define OMV_MDMA_CHANNEL_JPEG_OUT (6) // out has a higher pri than in // Enable sensor drivers #define OMV_ENABLE_OV2640 (0) diff --git a/src/omv/imlib/jpeg.c b/src/omv/imlib/jpeg.c index 50564c1fd..7028f2061 100644 --- a/src/omv/imlib/jpeg.c +++ b/src/omv/imlib/jpeg.c @@ -974,6 +974,7 @@ static void jpeg_get_mcu(image_t *src, int x_offset, int y_offset, int dx, int d #if (OMV_HARDWARE_JPEG == 1) #include STM32_HAL_H #include "irq.h" +#include "dma_utils.h" #define FB_ALLOC_PADDING ((__SCB_DCACHE_LINE_SIZE) * 4) #define OUTPUT_CHUNK_SIZE (512) // The minimum output buffer size is 2x this - so 1KB. @@ -1012,8 +1013,12 @@ void JPEG_IRQHandler() { } void jpeg_mdma_irq_handler() { - HAL_MDMA_IRQHandler(&JPEG_MDMA_Handle_In); - HAL_MDMA_IRQHandler(&JPEG_MDMA_Handle_Out); + if (MDMA->GISR0 & (1 << OMV_MDMA_CHANNEL_JPEG_IN)) { + HAL_MDMA_IRQHandler(&JPEG_MDMA_Handle_In); + } + if (MDMA->GISR0 & (1 << OMV_MDMA_CHANNEL_JPEG_OUT)) { + HAL_MDMA_IRQHandler(&JPEG_MDMA_Handle_Out); + } } static void jpeg_get_data_callback(JPEG_HandleTypeDef *hjpeg, uint32_t NbDecodedData) { @@ -1239,7 +1244,7 @@ void imlib_jpeg_compress_init() { NVIC_SetPriority(JPEG_IRQn, IRQ_PRI_JPEG); HAL_NVIC_EnableIRQ(JPEG_IRQn); - JPEG_MDMA_Handle_In.Instance = MDMA_Channel7; // in has a lower pri than out + JPEG_MDMA_Handle_In.Instance = MDMA_CHAN_TO_INSTANCE(OMV_MDMA_CHANNEL_JPEG_IN); JPEG_MDMA_Handle_In.Init.Request = MDMA_REQUEST_JPEG_INFIFO_TH; JPEG_MDMA_Handle_In.Init.TransferTriggerMode = MDMA_BUFFER_TRANSFER; JPEG_MDMA_Handle_In.Init.Priority = MDMA_PRIORITY_LOW; @@ -1258,7 +1263,7 @@ void imlib_jpeg_compress_init() { HAL_MDMA_Init(&JPEG_MDMA_Handle_In); __HAL_LINKDMA(&JPEG_Handle, hdmain, JPEG_MDMA_Handle_In); - JPEG_MDMA_Handle_Out.Instance = MDMA_Channel6; // out has a higher pri than in + JPEG_MDMA_Handle_Out.Instance = MDMA_CHAN_TO_INSTANCE(OMV_MDMA_CHANNEL_JPEG_OUT); JPEG_MDMA_Handle_Out.Init.Request = MDMA_REQUEST_JPEG_OUTFIFO_TH; JPEG_MDMA_Handle_Out.Init.TransferTriggerMode = MDMA_BUFFER_TRANSFER; JPEG_MDMA_Handle_Out.Init.Priority = MDMA_PRIORITY_LOW; diff --git a/src/omv/ports/stm32/dma_utils.h b/src/omv/ports/stm32/dma_utils.h index a36a8e027..56cf900e6 100644 --- a/src/omv/ports/stm32/dma_utils.h +++ b/src/omv/ports/stm32/dma_utils.h @@ -10,6 +10,12 @@ */ #ifndef __DMA_UTILS_H__ #define __DMA_UTILS_H__ + +#ifdef MDMA +#define MDMA_CHAN_TO_INSTANCE(x) \ + (MDMA_Channel_TypeDef *) (MDMA_Channel0_BASE + ((MDMA_Channel1_BASE - MDMA_Channel0_BASE) * x)) +#endif + uint8_t dma_utils_channel_to_irqn(DMA_Stream_TypeDef *dma_channel); uint8_t dma_utils_channel_to_id(DMA_Stream_TypeDef *dma_channel); int dma_utils_set_irq_descr(DMA_Stream_TypeDef *dma_channel, DMA_HandleTypeDef *dma_descr); diff --git a/src/omv/ports/stm32/sensor.c b/src/omv/ports/stm32/sensor.c index 470e2a113..a00fd2b78 100644 --- a/src/omv/ports/stm32/sensor.c +++ b/src/omv/ports/stm32/sensor.c @@ -32,9 +32,9 @@ sensor_t sensor = {}; static TIM_HandleTypeDef TIMHandle = {.Instance = DCMI_TIM}; static DMA_HandleTypeDef DMAHandle = {.Instance = DMA2_Stream1}; static DCMI_HandleTypeDef DCMIHandle = {.Instance = DCMI}; -#if (OMV_ENABLE_SENSOR_MDMA == 1) -static MDMA_HandleTypeDef DCMI_MDMA_Handle0 = {.Instance = MDMA_Channel0}; -static MDMA_HandleTypeDef DCMI_MDMA_Handle1 = {.Instance = MDMA_Channel1}; +#if defined(OMV_MDMA_CHANNEL_DCMI_0) +static MDMA_HandleTypeDef DCMI_MDMA_Handle0; +static MDMA_HandleTypeDef DCMI_MDMA_Handle1; #endif // SPI on image sensor connector. #ifdef ISC_SPI @@ -93,6 +93,11 @@ static int sensor_dma_config() { } void sensor_init0() { + #if defined(OMV_MDMA_CHANNEL_DCMI_0) + DCMI_MDMA_Handle0.Instance = MDMA_CHAN_TO_INSTANCE(OMV_MDMA_CHANNEL_DCMI_0); + DCMI_MDMA_Handle1.Instance = MDMA_CHAN_TO_INSTANCE(OMV_MDMA_CHANNEL_DCMI_1); + #endif + sensor_abort(); // Re-init i2c bus to reset the bus state after soft reset, which @@ -220,7 +225,7 @@ int sensor_abort() { DCMI->CR &= ~DCMI_CR_ENABLE; HAL_DMA_Abort(&DMAHandle); HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn); - #if (OMV_ENABLE_SENSOR_MDMA == 1) + #if defined(OMV_MDMA_CHANNEL_DCMI_0) HAL_MDMA_Abort(&DCMI_MDMA_Handle0); HAL_MDMA_Abort(&DCMI_MDMA_Handle1); HAL_MDMA_DeInit(&DCMI_MDMA_Handle0); @@ -374,7 +379,7 @@ static uint32_t get_dcmi_hw_crop(uint32_t bytes_per_pixel) { // moving the tail to the next buffer. 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 == 1) + #if defined(OMV_MDMA_CHANNEL_DCMI_0) // 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. @@ -395,7 +400,7 @@ void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi) { } } -#if (OMV_ENABLE_SENSOR_MDMA == 1) +#if defined(OMV_MDMA_CHANNEL_DCMI_0) static void mdma_memcpy(vbuffer_t *buffer, void *dst, void *src, int bpp, bool transposed) { // We're using two handles to give each channel the maximum amount of time possible to do the line // transfer. In most situations only one channel will be running at a time. However, if SDRAM is @@ -445,7 +450,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 == 1) + #if defined(OMV_MDMA_CHANNEL_DCMI_0) if (!sensor.transpose) { HAL_NVIC_DisableIRQ(DMA2_Stream1_IRQn); } @@ -460,7 +465,7 @@ void DCMI_DMAConvCpltUser(uint32_t addr) { if (!buffer) { DCMI->CR &= ~DCMI_CR_ENABLE; HAL_DMA_Abort_IT(&DMAHandle); // Note: Use HAL_DMA_Abort_IT and not HAL_DMA_Abort inside an interrupt. - #if (OMV_ENABLE_SENSOR_MDMA == 1) + #if defined(OMV_MDMA_CHANNEL_DCMI_0) HAL_MDMA_DeInit(&DCMI_MDMA_Handle0); HAL_MDMA_DeInit(&DCMI_MDMA_Handle1); #endif @@ -529,7 +534,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 == 1) + #if defined(OMV_MDMA_CHANNEL_DCMI_0) if (!sensor.transpose) { addr = (uint32_t) &_line_buf; } @@ -545,7 +550,7 @@ void DCMI_DMAConvCpltUser(uint32_t addr) { // For all non-JPEG and non-transposed modes we can completely offload image capture 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 == 1) + #if defined(OMV_MDMA_CHANNEL_DCMI_0) 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 @@ -580,7 +585,7 @@ void DCMI_DMAConvCpltUser(uint32_t addr) { switch (sensor.pixformat) { case PIXFORMAT_BAYER: - #if (OMV_ENABLE_SENSOR_MDMA == 1) + #if defined(OMV_MDMA_CHANNEL_DCMI_0) mdma_memcpy(buffer, dst, src, sizeof(uint8_t), sensor.transpose); #else if (!sensor.transpose) { @@ -594,7 +599,7 @@ void DCMI_DMAConvCpltUser(uint32_t addr) { #endif break; case PIXFORMAT_GRAYSCALE: - #if (OMV_ENABLE_SENSOR_MDMA == 1) + #if defined(OMV_MDMA_CHANNEL_DCMI_0) mdma_memcpy(buffer, dst, src, sizeof(uint8_t), sensor.transpose); #else if (sensor.hw_flags.gs_bpp == 1) { @@ -622,7 +627,7 @@ void DCMI_DMAConvCpltUser(uint32_t addr) { break; case PIXFORMAT_RGB565: case PIXFORMAT_YUV422: - #if (OMV_ENABLE_SENSOR_MDMA == 1) + #if defined(OMV_MDMA_CHANNEL_DCMI_0) mdma_memcpy(buffer, dst16, src16, sizeof(uint16_t), sensor.transpose); #else if ((sensor.pixformat == PIXFORMAT_RGB565 && sensor.hw_flags.rgb_swap) @@ -652,7 +657,7 @@ void DCMI_DMAConvCpltUser(uint32_t addr) { } } -#if (OMV_ENABLE_SENSOR_MDMA == 1) +#if defined(OMV_MDMA_CHANNEL_DCMI_0) // Configures an MDMA channel to completely offload the CPU in copying one line of pixels. static void mdma_config(MDMA_InitTypeDef *init, sensor_t *sensor, uint32_t bytes_per_pixel) { init->Request = MDMA_REQUEST_SW; @@ -799,7 +804,7 @@ int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags) { return SENSOR_ERROR_FRAMEBUFFER_ERROR; } - #if (OMV_ENABLE_SENSOR_MDMA == 1) + #if defined(OMV_MDMA_CHANNEL_DCMI_0) // The code below will enable MDMA data transfer from the DCMI line buffer for non-JPEG modes. if (sensor->pixformat != PIXFORMAT_JPEG) { mdma_config(&DCMI_MDMA_Handle0.Init, sensor, bytes_per_pixel); @@ -864,7 +869,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 == 1) + #if defined(OMV_MDMA_CHANNEL_DCMI_0) // 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. diff --git a/src/omv/ports/stm32/stm32fxxx_hal_msp.c b/src/omv/ports/stm32/stm32fxxx_hal_msp.c index 28df1b33c..13a59c394 100644 --- a/src/omv/ports/stm32/stm32fxxx_hal_msp.c +++ b/src/omv/ports/stm32/stm32fxxx_hal_msp.c @@ -745,7 +745,7 @@ void HAL_MspDeInit(void) { void MDMA_IRQHandler() { IRQ_ENTER(MDMA_IRQn); - #if (OMV_HARDWARE_JPEG == 1) + #if defined(OMV_MDMA_CHANNEL_JPEG_IN) jpeg_mdma_irq_handler(); #endif IRQ_EXIT(MDMA_IRQn); From 99140040e2375efd51cc6122d7c482797ac7f872 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Wed, 4 Oct 2023 20:25:25 +0200 Subject: [PATCH 2/2] ports/stm32: Call sensor MDMA handler if needed. --- src/omv/ports/stm32/sensor.c | 11 +++++++++++ src/omv/ports/stm32/stm32fxxx_hal_msp.c | 4 ++++ 2 files changed, 15 insertions(+) diff --git a/src/omv/ports/stm32/sensor.c b/src/omv/ports/stm32/sensor.c index a00fd2b78..7bdd402ba 100644 --- a/src/omv/ports/stm32/sensor.c +++ b/src/omv/ports/stm32/sensor.c @@ -57,6 +57,17 @@ void ISC_SPI_IRQHandler(void) { } #endif // ISC_SPI +#if defined(OMV_MDMA_CHANNEL_DCMI_0) +void sensor_mdma_irq_handler(void) { + if (MDMA->GISR0 & (1 << OMV_MDMA_CHANNEL_DCMI_0)) { + HAL_MDMA_IRQHandler(&DCMI_MDMA_Handle0); + } + if (MDMA->GISR0 & (1 << OMV_MDMA_CHANNEL_DCMI_1)) { + HAL_MDMA_IRQHandler(&DCMI_MDMA_Handle1); + } +} +#endif + static int sensor_dma_config() { // DMA Stream configuration #if defined(MCU_SERIES_H7) diff --git a/src/omv/ports/stm32/stm32fxxx_hal_msp.c b/src/omv/ports/stm32/stm32fxxx_hal_msp.c index 13a59c394..d875c41b1 100644 --- a/src/omv/ports/stm32/stm32fxxx_hal_msp.c +++ b/src/omv/ports/stm32/stm32fxxx_hal_msp.c @@ -748,5 +748,9 @@ void MDMA_IRQHandler() { #if defined(OMV_MDMA_CHANNEL_JPEG_IN) jpeg_mdma_irq_handler(); #endif + #if defined(OMV_MDMA_CHANNEL_DCMI_0) + extern void sensor_mdma_irq_handler(void); + sensor_mdma_irq_handler(); + #endif IRQ_EXIT(MDMA_IRQn); }