mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-03 20:54:32 +02:00
Merge branch 'fix/dvp_cam_gdma_wrong_align' into 'master'
feat(cam): add dvp dma buffer alloc function See merge request espressif/esp-idf!40326
This commit is contained in:
@@ -51,6 +51,7 @@ static esp_err_t s_ctlr_csi_start(esp_cam_ctlr_handle_t handle);
|
||||
static esp_err_t s_ctlr_csi_stop(esp_cam_ctlr_handle_t handle);
|
||||
static esp_err_t s_csi_ctlr_disable(esp_cam_ctlr_handle_t ctlr);
|
||||
static esp_err_t s_ctlr_csi_receive(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, uint32_t timeout_ms);
|
||||
static void *s_csi_ctlr_alloc_buffer(esp_cam_ctlr_t *handle, size_t size, uint32_t buf_caps);
|
||||
|
||||
static esp_err_t s_csi_claim_controller(csi_controller_t *controller)
|
||||
{
|
||||
@@ -225,6 +226,7 @@ esp_err_t esp_cam_new_csi_ctlr(const esp_cam_ctlr_csi_config_t *config, esp_cam_
|
||||
ctlr->base.register_event_callbacks = s_register_event_callbacks;
|
||||
ctlr->base.get_internal_buffer = s_csi_ctlr_get_internal_buffer;
|
||||
ctlr->base.get_buffer_len = s_csi_ctlr_get_buffer_length;
|
||||
ctlr->base.alloc_buffer = s_csi_ctlr_alloc_buffer;
|
||||
|
||||
*ret_handle = &(ctlr->base);
|
||||
|
||||
@@ -538,3 +540,23 @@ esp_err_t s_ctlr_csi_receive(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void *s_csi_ctlr_alloc_buffer(esp_cam_ctlr_t *handle, size_t size, uint32_t buf_caps)
|
||||
{
|
||||
csi_controller_t *ctlr = __containerof(handle, csi_controller_t, base);
|
||||
|
||||
if (!ctlr) {
|
||||
ESP_LOGE(TAG, "invalid argument: handle is null");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *buffer = heap_caps_calloc(1, size, buf_caps);
|
||||
if (!buffer) {
|
||||
ESP_LOGE(TAG, "failed to allocate buffer");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Allocated camera buffer: %p, size: %zu", buffer, size);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
@@ -29,6 +29,8 @@ typedef struct esp_cam_ctlr_dvp_dma {
|
||||
esp_cam_ctlr_dvp_dma_desc_t *desc; /*!< DVP DMA description buffer */
|
||||
size_t desc_count; /*!< DVP DMA description count */
|
||||
size_t desc_size; /*!< DVP DMA description buffer size in byte */
|
||||
size_t int_mem_align; /*!< DVP DMA internal memory alignment */
|
||||
size_t ext_mem_align; /*!< DVP DMA external memory alignment */
|
||||
} esp_cam_ctlr_dvp_dma_t;
|
||||
|
||||
/**
|
||||
|
@@ -700,6 +700,47 @@ static esp_err_t esp_cam_ctlr_get_dvp_cam_frame_buffer_len(esp_cam_ctlr_handle_t
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Allocate aligned camera buffer for ESP CAM DVP controller
|
||||
*
|
||||
* @note This function must be called after esp_cam_new_dvp_ctlr
|
||||
*
|
||||
* @param handle ESP CAM controller handle
|
||||
* @param size Buffer size in bytes
|
||||
* @param buf_caps Buffer allocation capabilities (e.g., MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA)
|
||||
*
|
||||
* @return
|
||||
* - Buffer pointer on success
|
||||
* - NULL on failure
|
||||
*/
|
||||
static void *esp_cam_ctlr_dvp_cam_alloc_buffer(esp_cam_ctlr_t *handle, size_t size, uint32_t buf_caps)
|
||||
{
|
||||
esp_cam_ctlr_dvp_cam_t *ctlr = (esp_cam_ctlr_dvp_cam_t *)handle;
|
||||
|
||||
if (!ctlr) {
|
||||
ESP_LOGE(TAG, "invalid argument: handle is null");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t alignment = 1;
|
||||
|
||||
if (buf_caps & MALLOC_CAP_SPIRAM) {
|
||||
alignment = ctlr->dma.ext_mem_align;
|
||||
} else {
|
||||
alignment = ctlr->dma.int_mem_align;
|
||||
}
|
||||
|
||||
void *buffer = heap_caps_aligned_calloc(alignment, 1, size, buf_caps);
|
||||
if (!buffer) {
|
||||
ESP_LOGE(TAG, "failed to allocate buffer");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Allocated aligned camera buffer: %p, size: %zu, alignment: %zu", buffer, size, alignment);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief New ESP CAM DVP controller
|
||||
*
|
||||
@@ -793,6 +834,7 @@ esp_err_t esp_cam_new_dvp_ctlr(const esp_cam_ctlr_dvp_config_t *config, esp_cam_
|
||||
ctlr->base.register_event_callbacks = esp_cam_ctlr_dvp_cam_register_event_callbacks;
|
||||
ctlr->base.get_internal_buffer = esp_cam_ctlr_dvp_cam_get_internal_buffer;
|
||||
ctlr->base.get_buffer_len = esp_cam_ctlr_get_dvp_cam_frame_buffer_len;
|
||||
ctlr->base.alloc_buffer = esp_cam_ctlr_dvp_cam_alloc_buffer;
|
||||
|
||||
*ret_handle = &ctlr->base;
|
||||
|
||||
|
@@ -105,9 +105,8 @@ esp_err_t esp_cam_ctlr_dvp_dma_init(esp_cam_ctlr_dvp_dma_t *dma, uint32_t burst_
|
||||
.access_ext_mem = true,
|
||||
};
|
||||
ESP_GOTO_ON_ERROR(gdma_config_transfer(dma->dma_chan, &transfer_config), fail1, TAG, "set trans ability failed");
|
||||
size_t int_mem_align = 0;
|
||||
size_t ext_mem_align = 0;
|
||||
gdma_get_alignment_constraints(dma->dma_chan, &int_mem_align, &ext_mem_align);
|
||||
|
||||
gdma_get_alignment_constraints(dma->dma_chan, &dma->int_mem_align, &dma->ext_mem_align);
|
||||
|
||||
dma->desc_count = size / ESP_CAM_CTLR_DVP_DMA_DESC_BUFFER_MAX_SIZE;
|
||||
if (size % ESP_CAM_CTLR_DVP_DMA_DESC_BUFFER_MAX_SIZE) {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -91,3 +91,11 @@ esp_err_t esp_cam_ctlr_del(esp_cam_ctlr_handle_t handle)
|
||||
|
||||
return handle->del(handle);
|
||||
}
|
||||
|
||||
void *esp_cam_ctlr_alloc_buffer(esp_cam_ctlr_handle_t handle, size_t size, uint32_t buf_caps)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(handle, NULL, TAG, "invalid argument: null pointer");
|
||||
ESP_RETURN_ON_FALSE(handle->alloc_buffer, NULL, TAG, "alloc_buffer function not supported");
|
||||
|
||||
return handle->alloc_buffer(handle, size, buf_caps);
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_err.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_cam_ctlr_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -132,6 +133,23 @@ esp_err_t esp_cam_ctlr_get_frame_buffer(esp_cam_ctlr_handle_t handle, uint32_t f
|
||||
*/
|
||||
esp_err_t esp_cam_ctlr_get_frame_buffer_len(esp_cam_ctlr_handle_t handle, size_t *ret_fb_len);
|
||||
|
||||
/**
|
||||
* @brief Allocate camera buffer for ESP CAM controller
|
||||
*
|
||||
* @note This function must be called after esp_cam_new_*_ctlr
|
||||
*
|
||||
* @param[in] handle ESP CAM controller handle
|
||||
* @param[in] size Buffer size in bytes
|
||||
* @param[in] buf_caps Buffer allocation capabilities:
|
||||
* - MALLOC_CAP_SPIRAM || MALLOC_CAP_DMA: Memory in external SPI RAM
|
||||
* - MALLOC_CAP_INTERNAL || MALLOC_CAP_DMA: Memory in internal SRAM
|
||||
*
|
||||
* @return
|
||||
* - Buffer pointer on success
|
||||
* - NULL on failure
|
||||
*/
|
||||
void *esp_cam_ctlr_alloc_buffer(esp_cam_ctlr_handle_t handle, size_t size, uint32_t buf_caps);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -133,6 +133,19 @@ struct esp_cam_ctlr_t {
|
||||
*/
|
||||
esp_err_t (*get_buffer_len)(esp_cam_ctlr_t *, size_t *);
|
||||
|
||||
/**
|
||||
* @brief Allocate aligned camera buffer for ESP CAM controller
|
||||
*
|
||||
* @param[in] esp_cam_ctlr_t * ESP CAM controller handle
|
||||
* @param[in] size_t Buffer size in bytes
|
||||
* @param[in] uint32_t Buffer allocation capabilities
|
||||
*
|
||||
* @return
|
||||
* - Buffer pointer on success
|
||||
* - NULL on failure
|
||||
*/
|
||||
void *(*alloc_buffer)(esp_cam_ctlr_t *, size_t, uint32_t);
|
||||
|
||||
void *user_data; ///< User data
|
||||
};
|
||||
|
||||
|
@@ -85,6 +85,7 @@ static esp_err_t s_isp_dvp_start(esp_cam_ctlr_handle_t handle);
|
||||
static esp_err_t s_isp_dvp_stop(esp_cam_ctlr_handle_t handle);
|
||||
static esp_err_t s_isp_dvp_receive(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, uint32_t timeout_ms);
|
||||
static bool s_dvp_dma_trans_done_callback(dw_gdma_channel_handle_t chan, const dw_gdma_trans_done_event_data_t *event_data, void *user_data);
|
||||
static void *s_isp_dvp_alloc_buffer(esp_cam_ctlr_t *handle, size_t size, uint32_t buf_caps);
|
||||
|
||||
esp_err_t esp_cam_new_isp_dvp_ctlr(isp_proc_handle_t isp_proc, const esp_cam_ctlr_isp_dvp_cfg_t *ctlr_config, esp_cam_ctlr_handle_t *ret_handle)
|
||||
{
|
||||
@@ -200,6 +201,7 @@ esp_err_t esp_cam_new_isp_dvp_ctlr(isp_proc_handle_t isp_proc, const esp_cam_ctl
|
||||
cam_ctlr->register_event_callbacks = s_isp_dvp_register_event_callbacks;
|
||||
cam_ctlr->get_internal_buffer = s_isp_dvp_get_frame_buffer;
|
||||
cam_ctlr->get_buffer_len = s_isp_dvp_get_frame_buffer_length;
|
||||
cam_ctlr->alloc_buffer = s_isp_dvp_alloc_buffer;
|
||||
*ret_handle = cam_ctlr;
|
||||
|
||||
return ESP_OK;
|
||||
@@ -594,3 +596,23 @@ static esp_err_t s_isp_declaim_dvp_controller(isp_dvp_controller_t *dvp_ctlr)
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void *s_isp_dvp_alloc_buffer(esp_cam_ctlr_t *handle, size_t size, uint32_t buf_caps)
|
||||
{
|
||||
isp_dvp_controller_t *dvp_ctlr = __containerof(handle, isp_dvp_controller_t, base);
|
||||
|
||||
if (!dvp_ctlr) {
|
||||
ESP_LOGE(TAG, "invalid argument: handle is null");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *buffer = heap_caps_calloc(1, size, buf_caps);
|
||||
if (!buffer) {
|
||||
ESP_LOGE(TAG, "failed to allocate buffer");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Allocated camera buffer: %p, size: %zu", buffer, size);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
@@ -112,6 +112,8 @@ Camera controller driver can be implemented in one of following ways:
|
||||
|
||||
If :cpp:type:`esp_cam_ctlr_lcd_cam_cfg_t` is specified, users can call :cpp:func:`esp_cam_new_lcd_cam_ctlr` to allocate and initialize a DVP camera controller handle. This function will return an DVP camera controller handle if it runs correctly. You can take following code as reference.
|
||||
|
||||
After calling :cpp:func:`esp_cam_new_dvp_ctlr`, you should allocate a camera buffer that meets the alignment constraints, or call :cpp:func:`esp_cam_ctlr_alloc_buffer` to automatically allocate.
|
||||
|
||||
.. code:: c
|
||||
|
||||
esp_cam_ctlr_handle_t cam_handle = NULL;
|
||||
|
@@ -112,6 +112,8 @@
|
||||
|
||||
如果指定了 :cpp:type:`esp_cam_ctlr_dvp_config_t` 中的配置,就可以调用 :cpp:func:`esp_cam_new_dvp_ctlr` 来分配和初始化 DVP 摄像头控制器句柄。如果函数运行正确,将返回一个 DVP 摄像头控制器句柄。请参考以下代码。
|
||||
|
||||
在调用 :cpp:func:`esp_cam_new_dvp_ctlr` 之后,需要分配符合对齐约束的摄像头缓冲区,或调用 :cpp:func:`esp_cam_ctlr_alloc_buffer` 来自动分配。
|
||||
|
||||
.. code:: c
|
||||
|
||||
esp_cam_ctlr_handle_t cam_handle = NULL;
|
||||
|
@@ -66,17 +66,6 @@ void app_main(void)
|
||||
ESP_LOGD(TAG, "frame_buffer_size: %zu", frame_buffer_size);
|
||||
ESP_LOGD(TAG, "frame_buffer: %p", frame_buffer);
|
||||
|
||||
size_t cam_buffer_size = CONFIG_EXAMPLE_CAM_HRES * CONFIG_EXAMPLE_CAM_VRES * EXAMPLE_RGB565_BITS_PER_PIXEL / 8;
|
||||
void *cam_buffer = heap_caps_calloc(1, cam_buffer_size, MALLOC_CAP_DMA | MALLOC_CAP_SPIRAM);
|
||||
if (!cam_buffer) {
|
||||
ESP_LOGE(TAG, "no mem for cam_buffer");
|
||||
return;
|
||||
}
|
||||
esp_cam_ctlr_trans_t cam_trans = {
|
||||
.buffer = cam_buffer,
|
||||
.buflen = cam_buffer_size,
|
||||
};
|
||||
|
||||
//----------CAM Controller Init------------//
|
||||
esp_cam_ctlr_handle_t cam_handle = NULL;
|
||||
esp_cam_ctlr_dvp_pin_config_t pin_cfg = {
|
||||
@@ -115,6 +104,18 @@ void app_main(void)
|
||||
return;
|
||||
}
|
||||
|
||||
//--------Allocate Camera Buffer----------//
|
||||
size_t cam_buffer_size = CONFIG_EXAMPLE_CAM_HRES * CONFIG_EXAMPLE_CAM_VRES * EXAMPLE_RGB565_BITS_PER_PIXEL / 8;
|
||||
void *cam_buffer = esp_cam_ctlr_alloc_buffer(cam_handle, cam_buffer_size, MALLOC_CAP_DMA | MALLOC_CAP_SPIRAM);
|
||||
if (!cam_buffer) {
|
||||
ESP_LOGE(TAG, "no mem for cam_buffer");
|
||||
return;
|
||||
}
|
||||
esp_cam_ctlr_trans_t cam_trans = {
|
||||
.buffer = cam_buffer,
|
||||
.buflen = cam_buffer_size,
|
||||
};
|
||||
|
||||
//--------Camera Sensor and SCCB Init-----------//
|
||||
example_sensor_config_t cam_sensor_config = {
|
||||
.i2c_port_num = I2C_NUM_0,
|
||||
|
@@ -98,17 +98,6 @@ void app_main(void)
|
||||
ESP_LOGD(TAG, "frame_buffer_size: %zu", frame_buffer_size);
|
||||
ESP_LOGD(TAG, "frame_buffer: %p", frame_buffer);
|
||||
|
||||
size_t cam_buffer_size = CONFIG_EXAMPLE_CAM_HRES * CONFIG_EXAMPLE_CAM_VRES * EXAMPLE_RGB565_BITS_PER_PIXEL / 8;
|
||||
void *cam_buffer = heap_caps_calloc(1, cam_buffer_size, MALLOC_CAP_DMA | MALLOC_CAP_SPIRAM);
|
||||
if (!cam_buffer) {
|
||||
ESP_LOGE(TAG, "no mem for cam_buffer");
|
||||
return;
|
||||
}
|
||||
esp_cam_ctlr_trans_t cam_trans = {
|
||||
.buffer = cam_buffer,
|
||||
.buflen = cam_buffer_size,
|
||||
};
|
||||
|
||||
//--------Camera Sensor and SCCB Init-----------//
|
||||
s_ledc_generate_dvp_xclk();
|
||||
|
||||
@@ -167,6 +156,18 @@ void app_main(void)
|
||||
return;
|
||||
}
|
||||
|
||||
//--------Allocate Camera Buffer----------//
|
||||
size_t cam_buffer_size = CONFIG_EXAMPLE_CAM_HRES * CONFIG_EXAMPLE_CAM_VRES * EXAMPLE_RGB565_BITS_PER_PIXEL / 8;
|
||||
void *cam_buffer = esp_cam_ctlr_alloc_buffer(cam_handle, cam_buffer_size, MALLOC_CAP_DMA | MALLOC_CAP_SPIRAM);
|
||||
if (!cam_buffer) {
|
||||
ESP_LOGE(TAG, "no mem for cam_buffer");
|
||||
return;
|
||||
}
|
||||
esp_cam_ctlr_trans_t cam_trans = {
|
||||
.buffer = cam_buffer,
|
||||
.buflen = cam_buffer_size,
|
||||
};
|
||||
|
||||
esp_cam_ctlr_evt_cbs_t cbs = {
|
||||
.on_get_new_trans = s_camera_get_new_vb,
|
||||
.on_trans_finished = s_camera_get_finished_trans,
|
||||
|
@@ -119,13 +119,6 @@ void app_main(void)
|
||||
esp_lcd_panel_handle_t lcd_panel_hdl = NULL;
|
||||
esp_lcd_panel_io_handle_t lcd_io_hdl = NULL;
|
||||
|
||||
size_t cam_buffer_size = CONFIG_EXAMPLE_CAM_HRES * CONFIG_EXAMPLE_CAM_VRES * EXAMPLE_RGB565_BITS_PER_PIXEL / 8;
|
||||
void *cam_buffer = heap_caps_malloc(cam_buffer_size, EXAMPLE_DVP_CAM_BUF_ALLOC_CAPS);
|
||||
if (!cam_buffer) {
|
||||
ESP_LOGE(TAG, "no mem for cam_buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
lcd_display_init(&lcd_panel_hdl, lcd_io_hdl);
|
||||
|
||||
//----------CAM Controller Init------------//
|
||||
@@ -166,6 +159,12 @@ void app_main(void)
|
||||
return;
|
||||
}
|
||||
|
||||
//--------Allocate Camera Buffer----------//
|
||||
size_t cam_buffer_size = CONFIG_EXAMPLE_CAM_HRES * CONFIG_EXAMPLE_CAM_VRES * EXAMPLE_RGB565_BITS_PER_PIXEL / 8;
|
||||
void *cam_buffer = NULL;
|
||||
|
||||
cam_buffer = esp_cam_ctlr_alloc_buffer(cam_handle, cam_buffer_size, EXAMPLE_DVP_CAM_BUF_ALLOC_CAPS);
|
||||
|
||||
//--------Camera Sensor and SCCB Init-----------//
|
||||
example_sensor_config_t cam_sensor_config = {
|
||||
.i2c_port_num = I2C_NUM_0,
|
||||
|
Reference in New Issue
Block a user