Skip to content

Commit ee3de24

Browse files
committed
feat(cam): add camera buffer alloc function
1 parent b9c2242 commit ee3de24

File tree

13 files changed

+166
-35
lines changed

13 files changed

+166
-35
lines changed

components/esp_driver_cam/csi/src/esp_cam_ctlr_csi.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ static esp_err_t s_ctlr_csi_start(esp_cam_ctlr_handle_t handle);
5151
static esp_err_t s_ctlr_csi_stop(esp_cam_ctlr_handle_t handle);
5252
static esp_err_t s_csi_ctlr_disable(esp_cam_ctlr_handle_t ctlr);
5353
static esp_err_t s_ctlr_csi_receive(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, uint32_t timeout_ms);
54+
static void *s_csi_ctlr_alloc_buffer(esp_cam_ctlr_t *handle, size_t size, uint32_t buf_caps);
5455

5556
static esp_err_t s_csi_claim_controller(csi_controller_t *controller)
5657
{
@@ -225,6 +226,7 @@ esp_err_t esp_cam_new_csi_ctlr(const esp_cam_ctlr_csi_config_t *config, esp_cam_
225226
ctlr->base.register_event_callbacks = s_register_event_callbacks;
226227
ctlr->base.get_internal_buffer = s_csi_ctlr_get_internal_buffer;
227228
ctlr->base.get_buffer_len = s_csi_ctlr_get_buffer_length;
229+
ctlr->base.alloc_buffer = s_csi_ctlr_alloc_buffer;
228230

229231
*ret_handle = &(ctlr->base);
230232

@@ -538,3 +540,23 @@ esp_err_t s_ctlr_csi_receive(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t
538540

539541
return ESP_OK;
540542
}
543+
544+
static void *s_csi_ctlr_alloc_buffer(esp_cam_ctlr_t *handle, size_t size, uint32_t buf_caps)
545+
{
546+
csi_controller_t *ctlr = __containerof(handle, csi_controller_t, base);
547+
548+
if (!ctlr) {
549+
ESP_LOGE(TAG, "invalid argument: handle is null");
550+
return NULL;
551+
}
552+
553+
void *buffer = heap_caps_calloc(1, size, buf_caps);
554+
if (!buffer) {
555+
ESP_LOGE(TAG, "failed to allocate buffer");
556+
return NULL;
557+
}
558+
559+
ESP_LOGD(TAG, "Allocated camera buffer: %p, size: %zu", buffer, size);
560+
561+
return buffer;
562+
}

components/esp_driver_cam/dvp/private_include/esp_cam_ctlr_dvp_dma.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ typedef struct esp_cam_ctlr_dvp_dma {
2929
esp_cam_ctlr_dvp_dma_desc_t *desc; /*!< DVP DMA description buffer */
3030
size_t desc_count; /*!< DVP DMA description count */
3131
size_t desc_size; /*!< DVP DMA description buffer size in byte */
32+
size_t int_mem_align; /*!< DVP DMA internal memory alignment */
33+
size_t ext_mem_align; /*!< DVP DMA external memory alignment */
3234
} esp_cam_ctlr_dvp_dma_t;
3335

3436
/**

components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_cam.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,47 @@ static esp_err_t esp_cam_ctlr_get_dvp_cam_frame_buffer_len(esp_cam_ctlr_handle_t
700700
return ret;
701701
}
702702

703+
/**
704+
* @brief Allocate aligned camera buffer for ESP CAM DVP controller
705+
*
706+
* @note This function must be called after esp_cam_new_dvp_ctlr
707+
*
708+
* @param handle ESP CAM controller handle
709+
* @param size Buffer size in bytes
710+
* @param buf_caps Buffer allocation capabilities (e.g., MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA)
711+
*
712+
* @return
713+
* - Buffer pointer on success
714+
* - NULL on failure
715+
*/
716+
static void *esp_cam_ctlr_dvp_cam_alloc_buffer(esp_cam_ctlr_t *handle, size_t size, uint32_t buf_caps)
717+
{
718+
esp_cam_ctlr_dvp_cam_t *ctlr = (esp_cam_ctlr_dvp_cam_t *)handle;
719+
720+
if (!ctlr) {
721+
ESP_LOGE(TAG, "invalid argument: handle is null");
722+
return NULL;
723+
}
724+
725+
size_t alignment = 1;
726+
727+
if (buf_caps & MALLOC_CAP_SPIRAM) {
728+
alignment = ctlr->dma.ext_mem_align;
729+
} else {
730+
alignment = ctlr->dma.int_mem_align;
731+
}
732+
733+
void *buffer = heap_caps_aligned_calloc(alignment, 1, size, buf_caps);
734+
if (!buffer) {
735+
ESP_LOGE(TAG, "failed to allocate buffer");
736+
return NULL;
737+
}
738+
739+
ESP_LOGD(TAG, "Allocated aligned camera buffer: %p, size: %zu, alignment: %zu", buffer, size, alignment);
740+
741+
return buffer;
742+
}
743+
703744
/**
704745
* @brief New ESP CAM DVP controller
705746
*
@@ -793,6 +834,7 @@ esp_err_t esp_cam_new_dvp_ctlr(const esp_cam_ctlr_dvp_config_t *config, esp_cam_
793834
ctlr->base.register_event_callbacks = esp_cam_ctlr_dvp_cam_register_event_callbacks;
794835
ctlr->base.get_internal_buffer = esp_cam_ctlr_dvp_cam_get_internal_buffer;
795836
ctlr->base.get_buffer_len = esp_cam_ctlr_get_dvp_cam_frame_buffer_len;
837+
ctlr->base.alloc_buffer = esp_cam_ctlr_dvp_cam_alloc_buffer;
796838

797839
*ret_handle = &ctlr->base;
798840

components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_gdma.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,8 @@ esp_err_t esp_cam_ctlr_dvp_dma_init(esp_cam_ctlr_dvp_dma_t *dma, uint32_t burst_
105105
.access_ext_mem = true,
106106
};
107107
ESP_GOTO_ON_ERROR(gdma_config_transfer(dma->dma_chan, &transfer_config), fail1, TAG, "set trans ability failed");
108-
size_t int_mem_align = 0;
109-
size_t ext_mem_align = 0;
110-
gdma_get_alignment_constraints(dma->dma_chan, &int_mem_align, &ext_mem_align);
108+
109+
gdma_get_alignment_constraints(dma->dma_chan, &dma->int_mem_align, &dma->ext_mem_align);
111110

112111
dma->desc_count = size / ESP_CAM_CTLR_DVP_DMA_DESC_BUFFER_MAX_SIZE;
113112
if (size % ESP_CAM_CTLR_DVP_DMA_DESC_BUFFER_MAX_SIZE) {

components/esp_driver_cam/esp_cam_ctlr.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -91,3 +91,11 @@ esp_err_t esp_cam_ctlr_del(esp_cam_ctlr_handle_t handle)
9191

9292
return handle->del(handle);
9393
}
94+
95+
void *esp_cam_ctlr_alloc_buffer(esp_cam_ctlr_handle_t handle, size_t size, uint32_t buf_caps)
96+
{
97+
ESP_RETURN_ON_FALSE(handle, NULL, TAG, "invalid argument: null pointer");
98+
ESP_RETURN_ON_FALSE(handle->alloc_buffer, NULL, TAG, "alloc_buffer function not supported");
99+
100+
return handle->alloc_buffer(handle, size, buf_caps);
101+
}

components/esp_driver_cam/include/esp_cam_ctlr.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -9,6 +9,7 @@
99
#include <stdint.h>
1010
#include <stdbool.h>
1111
#include "esp_err.h"
12+
#include "esp_heap_caps.h"
1213
#include "esp_cam_ctlr_types.h"
1314

1415
#ifdef __cplusplus
@@ -132,6 +133,23 @@ esp_err_t esp_cam_ctlr_get_frame_buffer(esp_cam_ctlr_handle_t handle, uint32_t f
132133
*/
133134
esp_err_t esp_cam_ctlr_get_frame_buffer_len(esp_cam_ctlr_handle_t handle, size_t *ret_fb_len);
134135

136+
/**
137+
* @brief Allocate camera buffer for ESP CAM controller
138+
*
139+
* @note This function must be called after esp_cam_new_*_ctlr
140+
*
141+
* @param[in] handle ESP CAM controller handle
142+
* @param[in] size Buffer size in bytes
143+
* @param[in] buf_caps Buffer allocation capabilities:
144+
* - MALLOC_CAP_SPIRAM || MALLOC_CAP_DMA: Memory in external SPI RAM
145+
* - MALLOC_CAP_INTERNAL || MALLOC_CAP_DMA: Memory in internal SRAM
146+
*
147+
* @return
148+
* - Buffer pointer on success
149+
* - NULL on failure
150+
*/
151+
void *esp_cam_ctlr_alloc_buffer(esp_cam_ctlr_handle_t handle, size_t size, uint32_t buf_caps);
152+
135153
#ifdef __cplusplus
136154
}
137155
#endif

components/esp_driver_cam/interface/esp_cam_ctlr_interface.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -133,6 +133,19 @@ struct esp_cam_ctlr_t {
133133
*/
134134
esp_err_t (*get_buffer_len)(esp_cam_ctlr_t *, size_t *);
135135

136+
/**
137+
* @brief Allocate aligned camera buffer for ESP CAM controller
138+
*
139+
* @param[in] esp_cam_ctlr_t * ESP CAM controller handle
140+
* @param[in] size_t Buffer size in bytes
141+
* @param[in] uint32_t Buffer allocation capabilities
142+
*
143+
* @return
144+
* - Buffer pointer on success
145+
* - NULL on failure
146+
*/
147+
void *(*alloc_buffer)(esp_cam_ctlr_t *, size_t, uint32_t);
148+
136149
void *user_data; ///< User data
137150
};
138151

components/esp_driver_cam/isp_dvp/src/esp_cam_ctlr_isp_dvp.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ static esp_err_t s_isp_dvp_start(esp_cam_ctlr_handle_t handle);
8585
static esp_err_t s_isp_dvp_stop(esp_cam_ctlr_handle_t handle);
8686
static esp_err_t s_isp_dvp_receive(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, uint32_t timeout_ms);
8787
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);
88+
static void *s_isp_dvp_alloc_buffer(esp_cam_ctlr_t *handle, size_t size, uint32_t buf_caps);
8889

8990
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)
9091
{
@@ -200,6 +201,7 @@ esp_err_t esp_cam_new_isp_dvp_ctlr(isp_proc_handle_t isp_proc, const esp_cam_ctl
200201
cam_ctlr->register_event_callbacks = s_isp_dvp_register_event_callbacks;
201202
cam_ctlr->get_internal_buffer = s_isp_dvp_get_frame_buffer;
202203
cam_ctlr->get_buffer_len = s_isp_dvp_get_frame_buffer_length;
204+
cam_ctlr->alloc_buffer = s_isp_dvp_alloc_buffer;
203205
*ret_handle = cam_ctlr;
204206

205207
return ESP_OK;
@@ -594,3 +596,23 @@ static esp_err_t s_isp_declaim_dvp_controller(isp_dvp_controller_t *dvp_ctlr)
594596

595597
return ESP_OK;
596598
}
599+
600+
static void *s_isp_dvp_alloc_buffer(esp_cam_ctlr_t *handle, size_t size, uint32_t buf_caps)
601+
{
602+
isp_dvp_controller_t *dvp_ctlr = __containerof(handle, isp_dvp_controller_t, base);
603+
604+
if (!dvp_ctlr) {
605+
ESP_LOGE(TAG, "invalid argument: handle is null");
606+
return NULL;
607+
}
608+
609+
void *buffer = heap_caps_calloc(1, size, buf_caps);
610+
if (!buffer) {
611+
ESP_LOGE(TAG, "failed to allocate buffer");
612+
return NULL;
613+
}
614+
615+
ESP_LOGD(TAG, "Allocated camera buffer: %p, size: %zu", buffer, size);
616+
617+
return buffer;
618+
}

docs/en/api-reference/peripherals/camera_driver.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ Camera controller driver can be implemented in one of following ways:
112112

113113
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.
114114

115+
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.
116+
115117
.. code:: c
116118
117119
esp_cam_ctlr_handle_t cam_handle = NULL;

docs/zh_CN/api-reference/peripherals/camera_driver.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@
112112

113113
如果指定了 :cpp:type:`esp_cam_ctlr_dvp_config_t` 中的配置,就可以调用 :cpp:func:`esp_cam_new_dvp_ctlr` 来分配和初始化 DVP 摄像头控制器句柄。如果函数运行正确,将返回一个 DVP 摄像头控制器句柄。请参考以下代码。
114114

115+
在调用 :cpp:func:`esp_cam_new_dvp_ctlr` 之后,需要分配符合对齐约束的摄像头缓冲区,或调用 :cpp:func:`esp_cam_ctlr_alloc_buffer` 来自动分配。
116+
115117
.. code:: c
116118
117119
esp_cam_ctlr_handle_t cam_handle = NULL;

0 commit comments

Comments
 (0)