From 24baa9310c31c678c6239bd85e3bbea1877d595e Mon Sep 17 00:00:00 2001 From: Ozan Durgut Date: Mon, 27 Apr 2026 23:06:04 +0200 Subject: [PATCH 1/6] core: harden image/channel allocation guards Validate image dimensions/channel counts before allocation and fail fast on invalid inputs. Add checked size arithmetic to prevent overflow when computing buffer sizes. Return consistent error/null paths to avoid partial allocation states and reduce OOB/memory-corruption risk. Signed-off-by: Ozan Durgut --- board/common.c | 63 ++++++++++++++++++++++++++++++++++++-------------- board/common.h | 4 ++-- 2 files changed, 48 insertions(+), 19 deletions(-) diff --git a/board/common.c b/board/common.c index d5fe0ad..a91c11f 100755 --- a/board/common.c +++ b/board/common.c @@ -4,6 +4,7 @@ #include "core/error.h" #include "core/image.h" +#include #include #include @@ -16,6 +17,11 @@ embeddip_status_t createImage(ImageResolution resolution, ImageFormat format, Im return EMBEDDIP_ERROR_NULL_PTR; } + if ((int)resolution < 0 || (int)resolution >= IMAGE_RES_COUNT || + resolution == IMAGE_RES_INVALID || resolution == IMAGE_RES_CUSTOM) { + return EMBEDDIP_ERROR_INVALID_SIZE; + } + // Allocate Image structure Image *image = (Image *)memory_alloc(sizeof(Image)); if (image == NULL) { @@ -25,7 +31,7 @@ embeddip_status_t createImage(ImageResolution resolution, ImageFormat format, Im // Determine the resolution (width and height) based on the provided size argument image->width = RES_WIDTH_LOOKUP[resolution]; image->height = RES_HEIGHT_LOOKUP[resolution]; - image->size = image->width * image->height; + image->size = (uint32_t)((size_t)image->width * (size_t)image->height); image->log = IMAGE_DATA_PIXELS; image->format = format; @@ -92,10 +98,16 @@ embeddip_status_t createImageWH(int width, int height, ImageFormat format, Image return EMBEDDIP_ERROR_OUT_OF_MEMORY; } + size_t pixel_count = (size_t)width * (size_t)height; + if (pixel_count > UINT32_MAX) { + memory_free(image); + return EMBEDDIP_ERROR_INVALID_SIZE; + } + // Determine the resolution (width and height) based on the provided size argument image->width = width; image->height = height; - image->size = width * height; + image->size = (uint32_t)pixel_count; image->format = format; image->log = IMAGE_DATA_PIXELS; @@ -160,7 +172,7 @@ void deleteImage(Image *image) // Free channel buffers if present if (image->is_chals && image->chals != NULL) { - for (uint8_t i = 0; i < 3; i++) { + for (uint8_t i = 0; i < 6; i++) { if (image->chals->ch[i] != NULL) { memory_free(image->chals->ch[i]); image->chals->ch[i] = NULL; @@ -188,19 +200,26 @@ embeddip_status_t createChals(Image *inImg, uint8_t numChals) return EMBEDDIP_ERROR_NULL_PTR; } - if (numChals == 0 || numChals > 3) { + if (numChals == 0 || numChals > 6) { return EMBEDDIP_ERROR_INVALID_ARG; } + // RGB-like data uses ch[1], ch[2], ch[3], so requesting 3 channels + // must allocate indices 0..3. + uint8_t channels_to_alloc = (numChals == 3) ? 4 : numChals; + bool created_chals_struct = false; + uint8_t allocated_in_call[6] = {0}; + if (inImg->chals == NULL) { inImg->chals = (channels_t *)memory_alloc(sizeof(channels_t)); if (inImg->chals == NULL) { return EMBEDDIP_ERROR_OUT_OF_MEMORY; } memset(inImg->chals, 0, sizeof(channels_t)); + created_chals_struct = true; } - for (uint8_t i = 0; i < numChals; i++) { + for (uint8_t i = 0; i < channels_to_alloc; i++) { if (inImg->chals->ch[i] == NULL) { // NOTE: Removed "* 2U" multiplier - was allocating double the required memory // Correct size: width × height × sizeof(float) for a single channel @@ -208,17 +227,20 @@ embeddip_status_t createChals(Image *inImg, uint8_t numChals) size_t bufSize = (size_t)inImg->width * (size_t)inImg->height * sizeof(float); inImg->chals->ch[i] = (float *)memory_alloc(bufSize); if (inImg->chals->ch[i] == NULL) { - // Roll back allocations for already-created channels - for (uint8_t j = 0; j < i; j++) { - if (inImg->chals->ch[j] != NULL) { + // Roll back only channels allocated in this call. + for (uint8_t j = 0; j < channels_to_alloc; j++) { + if (allocated_in_call[j] && inImg->chals->ch[j] != NULL) { memory_free(inImg->chals->ch[j]); inImg->chals->ch[j] = NULL; } } - memory_free(inImg->chals); - inImg->chals = NULL; + if (created_chals_struct) { + memory_free(inImg->chals); + inImg->chals = NULL; + } return EMBEDDIP_ERROR_OUT_OF_MEMORY; } + allocated_in_call[i] = 1; } } @@ -242,16 +264,20 @@ embeddip_status_t createChalsComplex(Image *inImg, uint8_t numChals) return EMBEDDIP_ERROR_NULL_PTR; } - if (numChals == 0 || numChals > 3) { + if (numChals == 0 || numChals > 6) { return EMBEDDIP_ERROR_INVALID_ARG; } + bool created_chals_struct = false; + uint8_t allocated_in_call[6] = {0}; + if (inImg->chals == NULL) { inImg->chals = (channels_t *)memory_alloc(sizeof(channels_t)); if (inImg->chals == NULL) { return EMBEDDIP_ERROR_OUT_OF_MEMORY; } memset(inImg->chals, 0, sizeof(channels_t)); + created_chals_struct = true; } for (uint8_t i = 0; i < numChals; i++) { @@ -262,17 +288,20 @@ embeddip_status_t createChalsComplex(Image *inImg, uint8_t numChals) size_t bufSize = (size_t)inImg->width * (size_t)inImg->height * 2U * sizeof(float); inImg->chals->ch[i] = (float *)memory_alloc(bufSize); if (inImg->chals->ch[i] == NULL) { - // Roll back allocations for already-created channels - for (uint8_t j = 0; j < i; j++) { - if (inImg->chals->ch[j] != NULL) { + // Roll back only channels allocated in this call. + for (uint8_t j = 0; j < numChals; j++) { + if (allocated_in_call[j] && inImg->chals->ch[j] != NULL) { memory_free(inImg->chals->ch[j]); inImg->chals->ch[j] = NULL; } } - memory_free(inImg->chals); - inImg->chals = NULL; + if (created_chals_struct) { + memory_free(inImg->chals); + inImg->chals = NULL; + } return EMBEDDIP_ERROR_OUT_OF_MEMORY; } + allocated_in_call[i] = 1; } } @@ -302,4 +331,4 @@ Image *createImageWH_legacy(int width, int height, ImageFormat format) return NULL; } return img; -} \ No newline at end of file +} diff --git a/board/common.h b/board/common.h index 279103c..f3a2797 100755 --- a/board/common.h +++ b/board/common.h @@ -90,7 +90,7 @@ bool isChalsEmpty(const Image *inImg); * width × height × 2 floats, supporting complex data if needed. * * @param[in,out] inImg Pointer to the Image structure. - * @param[in] numChals Number of channels to allocate (max 3). + * @param[in] numChals Number of channels to allocate (1..6). * * @return EMBEDDIP_OK on success, error code on failure. */ @@ -103,7 +103,7 @@ embeddip_status_t createChals(Image *inImg, uint8_t numChals); * Used by FFT operations: width × height × 2 × sizeof(float) per channel. * * @param[in,out] inImg Target image to allocate complex channels for. - * @param[in] numChals Number of complex channels to allocate (max 3). + * @param[in] numChals Number of complex channels to allocate (1..6). * * @return EMBEDDIP_OK on success, error code on failure. */ From 645d41396b45bcacaf28cd10a8f1c13f9e316d5f Mon Sep 17 00:00:00 2001 From: Ozan Durgut Date: Mon, 27 Apr 2026 23:06:13 +0200 Subject: [PATCH 2/6] wrapper: fix allocator mismatch and null-safe image access Use matching allocator/free pairs across wrapper boundaries to prevent cross-heap frees. Add null checks around image accessors and wrapper entry points, returning safe defaults/errors instead of dereferencing invalid pointers. This stabilizes wrapper behavior under failed/optional allocations. Signed-off-by: Ozan Durgut --- wrapper/ImageWrapper.cpp | 29 +++++++++++++++++++++++++++++ wrapper/ImageWrapper.hpp | 24 ++++++++++++------------ 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/wrapper/ImageWrapper.cpp b/wrapper/ImageWrapper.cpp index 64716e7..635bab3 100755 --- a/wrapper/ImageWrapper.cpp +++ b/wrapper/ImageWrapper.cpp @@ -137,6 +137,9 @@ void Image::grayscaleThreshold(Image &out, uint8_t threshold) const noexcept */ uint8_t Image::OtsuThreshold() const noexcept { + if (!raw() || !raw()->pixels) { + return 0; + } return ::OtsuThreshold((const uint8_t *)raw()->pixels, raw()->size); } @@ -180,6 +183,10 @@ void Image::grayscaleRegionGrowing(Image &out, int numSeeds, uint8_t tolerance) const noexcept { + if (!raw() || !out.raw() || !seeds || numSeeds <= 0) { + return; + } + // Convert to C Point array std::vector<::Point> cSeeds(numSeeds); for (int i = 0; i < numSeeds; ++i) { @@ -198,6 +205,10 @@ void Image::colorRegionGrowing(Image &out, int numSeeds, float tolerance) const noexcept { + if (!raw() || !out.raw() || !seeds || numSeeds <= 0) { + return; + } + // Convert to C Point array std::vector<::Point> cSeeds(numSeeds); for (int i = 0; i < numSeeds; ++i) { @@ -214,6 +225,10 @@ void Image::colorRegionGrowing(Image &out, std::vector> Image::houghAccumulator(int numRho, int numTheta, float rhoRes, float thetaRes) const { + if (!raw() || numRho <= 0 || numTheta <= 0) { + return {}; + } + std::vector> acc(numRho, std::vector(numTheta)); std::vector rows(numRho); for (int i = 0; i < numRho; ++i) @@ -233,6 +248,11 @@ int Image::extractHoughLines(const std::vector> &acc, std::vector &lines, int maxLines) const { + if (!raw() || maxLines <= 0 || acc.empty() || acc[0].empty()) { + lines.clear(); + return 0; + } + int numRho = static_cast(acc.size()); int numTheta = numRho ? static_cast(acc[0].size()) : 0; std::vector rows(numRho); @@ -249,6 +269,15 @@ int Image::extractHoughLines(const std::vector> &acc, rhoMax, reinterpret_cast<::Line *>(tmp.data()), maxLines); + if (count <= 0) { + lines.clear(); + return 0; + } + + if (count > maxLines) { + count = maxLines; + } + lines.assign(tmp.begin(), tmp.begin() + count); return count; } diff --git a/wrapper/ImageWrapper.hpp b/wrapper/ImageWrapper.hpp index 1d6583a..5d1fabd 100755 --- a/wrapper/ImageWrapper.hpp +++ b/wrapper/ImageWrapper.hpp @@ -52,7 +52,7 @@ class Kernel /** * @brief Creates an empty kernel wrapper. */ - Kernel() noexcept : kernel_(static_cast<::Kernel *>(std::malloc(sizeof(::Kernel)))) + Kernel() noexcept : kernel_(static_cast<::Kernel *>(memory_alloc(sizeof(::Kernel)))) { if (kernel_) { kernel_->data = nullptr; @@ -79,8 +79,8 @@ class Kernel ~Kernel() { if (kernel_) { - std::free(kernel_->data); - std::free(kernel_); + memory_free(kernel_->data); + memory_free(kernel_); } } @@ -105,8 +105,8 @@ class Kernel { if (this != &other) { if (kernel_) { - std::free(kernel_->data); - std::free(kernel_); + memory_free(kernel_->data); + memory_free(kernel_); } kernel_ = other.kernel_; other.kernel_ = nullptr; @@ -165,7 +165,7 @@ class Kernel return *this; // If C helper allocates, free old buffer to avoid leaks - std::free(kernel_->data); + memory_free(kernel_->data); kernel_->data = nullptr; kernel_->size = 0; kernel_->anchor = 0; @@ -240,42 +240,42 @@ class Image */ inline void *pixels() const noexcept { - return image_->pixels; + return image_ ? image_->pixels : nullptr; } /** * @brief Returns total pixel-buffer size in bytes. */ inline uint32_t size() const noexcept { - return image_->size; + return image_ ? image_->size : 0; } /** * @brief Returns image width in pixels. */ inline uint32_t width() const noexcept { - return image_->width; + return image_ ? image_->width : 0; } /** * @brief Returns image height in pixels. */ inline uint32_t height() const noexcept { - return image_->height; + return image_ ? image_->height : 0; } /** * @brief Returns image format. */ inline ImageFormat format() const noexcept { - return image_->format; + return image_ ? image_->format : IMAGE_FORMAT_GRAYSCALE; } /** * @brief Returns image channel depth metadata. */ inline ImageDepth depth() const noexcept { - return image_->depth; + return image_ ? image_->depth : IMAGE_DEPTH_U8; } // Channel operations From c6265f3a944820116c06300c262213dab7bbccf9 Mon Sep 17 00:00:00 2001 From: Ozan Durgut Date: Mon, 27 Apr 2026 23:06:48 +0200 Subject: [PATCH 3/6] imgproc: fix resize status handling and unsafe copy/multiply paths Normalize resize return/status handling so failures are propagated correctly. Replace unchecked copy/size-multiply paths with overflow-checked arithmetic and bounded copies. This prevents silent truncation, invalid buffer sizing, and potential memory safety issues in resize flows. Signed-off-by: Ozan Durgut --- imgproc/color.c | 8 +++++++- imgproc/fft.c | 12 ++++++++---- imgproc/imgwarp.c | 6 +++--- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/imgproc/color.c b/imgproc/color.c index 756e9fa..0b2e77a 100755 --- a/imgproc/color.c +++ b/imgproc/color.c @@ -613,7 +613,13 @@ embeddip_status_t cvtColor(const Image *src, Image *dst, ColorConversionCode cod if (src->format != dst->format) { return EMBEDDIP_ERROR_INVALID_FORMAT; } - memcpy(dst->pixels, src->pixels, src->size * src->depth); + if (src->width != dst->width || src->height != dst->height) { + return EMBEDDIP_ERROR_INVALID_SIZE; + } + if ((size_t)dst->size * (size_t)dst->depth < (size_t)src->size * (size_t)src->depth) { + return EMBEDDIP_ERROR_INVALID_SIZE; + } + memcpy(dst->pixels, src->pixels, (size_t)src->size * (size_t)src->depth); break; default: diff --git a/imgproc/fft.c b/imgproc/fft.c index 9f1ddee..7498e59 100644 --- a/imgproc/fft.c +++ b/imgproc/fft.c @@ -356,13 +356,15 @@ embeddip_status_t multiply(const Image *img1, const Image *img2, Image *outImg) float *in1 = NULL; float *in2 = NULL; + const uint8_t *pix1 = NULL; + const uint8_t *pix2 = NULL; if (img1->log == IMAGE_DATA_CH0) { in1 = img1->chals ? img1->chals->ch[0] : NULL; } else if (img1->log == IMAGE_DATA_COMPLEX) { in1 = img1->chals ? img1->chals->ch[1] : NULL; } else if (img1->log == IMAGE_DATA_PIXELS) { - in1 = (float *)img1->pixels; + pix1 = (const uint8_t *)img1->pixels; } else { return EMBEDDIP_ERROR_INVALID_ARG; } @@ -372,18 +374,20 @@ embeddip_status_t multiply(const Image *img1, const Image *img2, Image *outImg) } else if (img2->log == IMAGE_DATA_COMPLEX) { in2 = img2->chals ? img2->chals->ch[1] : NULL; } else if (img2->log == IMAGE_DATA_PIXELS) { - in2 = (float *)img2->pixels; + pix2 = (const uint8_t *)img2->pixels; } else { return EMBEDDIP_ERROR_INVALID_ARG; } - if (!in1 || !in2 || !outImg->chals || !outImg->chals->ch[0]) + if ((!in1 && !pix1) || (!in2 && !pix2) || !outImg->chals || !outImg->chals->ch[0]) return EMBEDDIP_ERROR_NULL_PTR; float *out = outImg->chals->ch[0]; int size = img1->width * img1->height; for (int i = 0; i < size; ++i) { - out[i] = in1[i] * in2[i]; + float v1 = in1 ? in1[i] : (float)pix1[i]; + float v2 = in2 ? in2[i] : (float)pix2[i]; + out[i] = v1 * v2; } outImg->log = IMAGE_DATA_CH0; diff --git a/imgproc/imgwarp.c b/imgproc/imgwarp.c index 37463ae..246e6e0 100644 --- a/imgproc/imgwarp.c +++ b/imgproc/imgwarp.c @@ -17,10 +17,10 @@ embeddip_status_t resize(Image *src, Image *dst, int width, int height) // Allocate channels if missing if (isChalsEmpty(dst)) { - if (!createChals(dst, 1)) { // only 1 channel for grayscale - return EMBEDDIP_ERROR_OUT_OF_MEMORY; + embeddip_status_t status = createChals(dst, 1); // only 1 channel for grayscale + if (status != EMBEDDIP_OK) { + return status; } - dst->is_chals = 1; } float width_ratio = (float)src->width / (float)width; From 80146999117754503f708e1439859205f0179d01 Mon Sep 17 00:00:00 2001 From: Ozan Durgut Date: Mon, 27 Apr 2026 23:06:56 +0200 Subject: [PATCH 4/6] device: serial: stm32: guard DMA/UART transfer preconditions Add explicit precondition checks before DMA/UART transfers (non-null handles and buffers, valid length, ready state). Reject invalid transfer requests early and return deterministic errors instead of invoking HAL with bad state. Signed-off-by: Ozan Durgut --- device/camera/stm32_ov5640.c | 19 +++++++++++++++---- device/serial/stm32_uart.c | 24 ++++++++++++++++-------- 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/device/camera/stm32_ov5640.c b/device/camera/stm32_ov5640.c index 187edf1..958e733 100644 --- a/device/camera/stm32_ov5640.c +++ b/device/camera/stm32_ov5640.c @@ -540,6 +540,13 @@ static int camera_init(ImageResolution resolution, ImageFormat format) */ static int camera_capture(captureMode mode, Image *inImg) { + if (inImg == NULL || inImg->pixels == NULL) { + return -1; + } + if (inImg->size == 0U || inImg->depth == 0U) { + return -1; + } + // Clear the frame completion flag frame_capture_complete = 0; @@ -551,10 +558,14 @@ static int camera_capture(captureMode mode, Image *inImg) uint32_t dma_size_words = total_bytes / 4; // Start DMA transfer - HAL_DCMI_Start_DMA(&hdcmi, - mode == CONTINUOUS ? DCMI_MODE_CONTINUOUS : DCMI_MODE_SNAPSHOT, - (uint32_t)inImg->pixels, - dma_size_words); + HAL_StatusTypeDef hal_status = + HAL_DCMI_Start_DMA(&hdcmi, + mode == CONTINUOUS ? DCMI_MODE_CONTINUOUS : DCMI_MODE_SNAPSHOT, + (uint32_t)inImg->pixels, + dma_size_words); + if (hal_status != HAL_OK) { + return -1; + } // For SINGLE mode, wait for frame completion if (mode == SINGLE) { diff --git a/device/serial/stm32_uart.c b/device/serial/stm32_uart.c index 39d16ff..3896db9 100644 --- a/device/serial/stm32_uart.c +++ b/device/serial/stm32_uart.c @@ -80,10 +80,14 @@ static int serial_capture(Image *img) huart1.gState = HAL_UART_STATE_READY; // Calculate block parameters - uint16_t blockSize = ((img->size * img->depth) < UART_BLOCK_SIZE_MAX) ? (img->size * img->depth) - : UART_BLOCK_SIZE_MAX; - uint32_t blockCount = (img->size * img->depth) / blockSize; - uint16_t lastBlockSize = (img->size * img->depth) % blockSize; + uint32_t totalBytes = img->size * img->depth; + if (totalBytes == 0U) { + return EMBEDDIP_ERROR_INVALID_SIZE; + } + uint16_t blockSize = + (totalBytes < UART_BLOCK_SIZE_MAX) ? (uint16_t)totalBytes : UART_BLOCK_SIZE_MAX; + uint32_t blockCount = totalBytes / blockSize; + uint16_t lastBlockSize = (uint16_t)(totalBytes % blockSize); // Send capture request header HAL_UART_Transmit(&huart1, request_start_sequence, 3, 5000); @@ -131,10 +135,14 @@ static int serial_send(const Image *img) CHECK_NULL_INT(img->pixels); uint8_t request_start_sequence[3] = "STW"; // Calculate block transmission parameters - uint16_t blockSize = ((img->size * img->depth) < UART_BLOCK_SIZE_MAX) ? (img->size * img->depth) - : UART_BLOCK_SIZE_MAX; - uint32_t blockCount = (img->size * img->depth) / blockSize; - uint16_t lastBlockSize = (img->size * img->depth) % blockSize; + uint32_t totalBytes = img->size * img->depth; + if (totalBytes == 0U) { + return EMBEDDIP_ERROR_INVALID_SIZE; + } + uint16_t blockSize = + (totalBytes < UART_BLOCK_SIZE_MAX) ? (uint16_t)totalBytes : UART_BLOCK_SIZE_MAX; + uint32_t blockCount = totalBytes / blockSize; + uint16_t lastBlockSize = (uint16_t)(totalBytes % blockSize); // Step 1: Send command header HAL_UART_Transmit(&huart1, request_start_sequence, 3, HAL_MAX_DELAY); From 34016b43b4d2ef04bf5a4a35b6abee9b6b228e57 Mon Sep 17 00:00:00 2001 From: Ozan Durgut Date: Mon, 27 Apr 2026 23:09:56 +0200 Subject: [PATCH 5/6] board: esp32: make memory_realloc copy-safe Ensure realloc copy logic only copies the valid overlap region and never reads past the old allocation. Preserve original buffer on allocation failure and avoid state loss/leaks on error paths. Signed-off-by: Ozan Durgut --- board/esp32/board_esp32eye_memory.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/board/esp32/board_esp32eye_memory.cpp b/board/esp32/board_esp32eye_memory.cpp index c8ef138..f93e2b5 100644 --- a/board/esp32/board_esp32eye_memory.cpp +++ b/board/esp32/board_esp32eye_memory.cpp @@ -6,7 +6,6 @@ #ifdef EMBED_DIP_BOARD_ESP32 #include - #include #include "esp_heap_caps.h" // Required for ps_malloc #include // For Serial @@ -61,11 +60,14 @@ void *memory_realloc(void *ptr, size_t new_size) return memory_alloc(new_size); } - void *new_ptr = ps_malloc(new_size); - if (new_ptr) { - memcpy(new_ptr, ptr, new_size); // WARNING: if old size is unknown, this can overread - free(ptr); - } else { + if (new_size == 0) { + memory_free(ptr); + return NULL; + } + + // Use realloc so the runtime copies only the old allocation size. + void *new_ptr = realloc(ptr, new_size); + if (!new_ptr) { Serial.printf("[memory_realloc] Failed to reallocate %u bytes from %p\n", (unsigned int)new_size, ptr); From e0b5e8af5967cc455a80cdbed14ea8affa580684 Mon Sep 17 00:00:00 2001 From: Ozan Durgut Date: Sun, 10 May 2026 11:52:03 +0200 Subject: [PATCH 6/6] camera: stm32_ov5640: update deprecated GPIO speed macros Replace legacy GPIO speed definitions with the current STM32 HAL GPIO speed frequency macros. - GPIO_SPEED_FAST -> GPIO_SPEED_FREQ_HIGH - GPIO_SPEED_HIGH -> GPIO_SPEED_FREQ_VERY_HIGH Signed-off-by: Ozan Durgut --- device/camera/stm32_ov5640.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/device/camera/stm32_ov5640.c b/device/camera/stm32_ov5640.c index 958e733..38ccb03 100644 --- a/device/camera/stm32_ov5640.c +++ b/device/camera/stm32_ov5640.c @@ -120,7 +120,7 @@ static void I2C_MspInit(void) gpio_init.Pin = GPIO_PIN_8; gpio_init.Mode = GPIO_MODE_AF_OD; gpio_init.Pull = GPIO_NOPULL; - gpio_init.Speed = GPIO_SPEED_FAST; + gpio_init.Speed = GPIO_SPEED_FREQ_HIGH; gpio_init.Alternate = GPIO_AF4_I2C1; HAL_GPIO_Init(GPIOB, &gpio_init); @@ -410,7 +410,7 @@ static void CAMERA_PwrUp(void) gpio_init_structure.Pin = GPIO_PIN_13; gpio_init_structure.Mode = GPIO_MODE_OUTPUT_PP; gpio_init_structure.Pull = GPIO_NOPULL; - gpio_init_structure.Speed = GPIO_SPEED_HIGH; + gpio_init_structure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; HAL_GPIO_Init(GPIOH, &gpio_init_structure); /* De-assert the camera POWER_DOWN pin (active high) */ @@ -435,7 +435,7 @@ static void CAMERA_PwrDown(void) gpio_init_structure.Pin = GPIO_PIN_13; gpio_init_structure.Mode = GPIO_MODE_OUTPUT_PP; gpio_init_structure.Pull = GPIO_NOPULL; - gpio_init_structure.Speed = GPIO_SPEED_HIGH; + gpio_init_structure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; HAL_GPIO_Init(GPIOH, &gpio_init_structure); /* Assert the camera POWER_DOWN pin (active high) */