forked from espressif/esp-idf
Merge branch 'feat/add_cam_pm_lock' into 'master'
feat(cam): esp_cam add pm lock function Closes IDF-12596 and IDF-10093 See merge request espressif/esp-idf!38120
This commit is contained in:
@@ -34,3 +34,7 @@ idf_component_register(SRCS ${srcs}
|
||||
REQUIRES ${requires}
|
||||
PRIV_REQUIRES ${priv_requires}
|
||||
)
|
||||
|
||||
if(CONFIG_PM_ENABLE)
|
||||
idf_component_optional_requires(PRIVATE esp_pm)
|
||||
endif()
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -210,6 +210,10 @@ esp_err_t esp_cam_new_csi_ctlr(const esp_cam_ctlr_csi_config_t *config, esp_cam_
|
||||
};
|
||||
ESP_GOTO_ON_ERROR(dw_gdma_channel_register_event_callbacks(csi_dma_chan, &csi_dma_cbs, ctlr), err, TAG, "failed to register dwgdma callback");
|
||||
|
||||
#if CONFIG_PM_ENABLE
|
||||
ESP_GOTO_ON_ERROR(esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "cam_csi_ctlr", &ctlr->pm_lock), err, TAG, "failed to create pm lock");
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
ctlr->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
|
||||
ctlr->csi_fsm = CSI_FSM_INIT;
|
||||
ctlr->base.del = s_ctlr_del;
|
||||
@@ -237,6 +241,12 @@ esp_err_t s_del_csi_ctlr(csi_controller_t *ctlr)
|
||||
ESP_RETURN_ON_FALSE(ctlr, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
ESP_RETURN_ON_FALSE(ctlr->csi_fsm == CSI_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "processor isn't in init state");
|
||||
|
||||
#if CONFIG_PM_ENABLE
|
||||
if (ctlr->pm_lock) {
|
||||
ESP_RETURN_ON_ERROR(esp_pm_lock_delete(ctlr->pm_lock), TAG, "delete pm_lock failed");
|
||||
}
|
||||
#endif // CONFIG_PM_ENABLE
|
||||
|
||||
if (ctlr->dma_chan) {
|
||||
ESP_RETURN_ON_ERROR(dw_gdma_del_channel(ctlr->dma_chan), TAG, "failed to delete dwgdma channel");
|
||||
}
|
||||
@@ -400,6 +410,11 @@ esp_err_t s_csi_ctlr_enable(esp_cam_ctlr_handle_t handle)
|
||||
|
||||
portENTER_CRITICAL(&ctlr->spinlock);
|
||||
ctlr->csi_fsm = CSI_FSM_ENABLED;
|
||||
#if CONFIG_PM_ENABLE
|
||||
if (ctlr->pm_lock) {
|
||||
ESP_RETURN_ON_ERROR(esp_pm_lock_acquire(ctlr->pm_lock), TAG, "acquire pm_lock failed");
|
||||
}
|
||||
#endif // CONFIG_PM_ENABLE
|
||||
portEXIT_CRITICAL(&ctlr->spinlock);
|
||||
|
||||
return ESP_OK;
|
||||
@@ -413,6 +428,11 @@ esp_err_t s_csi_ctlr_disable(esp_cam_ctlr_handle_t handle)
|
||||
|
||||
portENTER_CRITICAL(&ctlr->spinlock);
|
||||
ctlr->csi_fsm = CSI_FSM_INIT;
|
||||
#if CONFIG_PM_ENABLE
|
||||
if (ctlr->pm_lock) {
|
||||
ESP_RETURN_ON_ERROR(esp_pm_lock_release(ctlr->pm_lock), TAG, "release pm_lock failed");
|
||||
}
|
||||
#endif // CONFIG_PM_ENABLE
|
||||
portEXIT_CRITICAL(&ctlr->spinlock);
|
||||
|
||||
return ESP_OK;
|
||||
|
@@ -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
|
||||
*/
|
||||
@@ -21,6 +21,10 @@
|
||||
#include "soc/soc_caps.h"
|
||||
#include "esp_private/dw_gdma.h"
|
||||
|
||||
#if CONFIG_PM_ENABLE
|
||||
#include "esp_pm.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -62,6 +66,9 @@ struct csi_controller_t {
|
||||
void *cbs_user_data; //callback userdata
|
||||
dw_gdma_channel_handle_t dma_chan; //dwgdma channel handle
|
||||
size_t csi_transfer_size; //csi transfer size for dwgdma
|
||||
#if CONFIG_PM_ENABLE
|
||||
esp_pm_lock_handle_t pm_lock; //Power management lock
|
||||
#endif
|
||||
esp_cam_ctlr_t base;
|
||||
};
|
||||
|
||||
|
@@ -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
|
||||
*/
|
||||
@@ -12,6 +12,10 @@
|
||||
#include "esp_cam_ctlr_dvp_dma.h"
|
||||
#include "esp_cam_ctlr_dvp.h"
|
||||
|
||||
#if CONFIG_PM_ENABLE
|
||||
#include "esp_pm.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -49,6 +53,9 @@ typedef struct esp_cam_ctlr_dvp_cam {
|
||||
uint8_t *backup_buffer; /*!< DVP CAM backup buffer */
|
||||
bool bk_buffer_exposed; /*!< status of if back_buffer is exposed to users */
|
||||
portMUX_TYPE spinlock; /*!< DVP CAM spinlock */
|
||||
#if CONFIG_PM_ENABLE
|
||||
esp_pm_lock_handle_t pm_lock; /*!< Power management lock */
|
||||
#endif
|
||||
} esp_cam_ctlr_dvp_cam_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@@ -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
|
||||
*/
|
||||
@@ -423,6 +423,12 @@ static esp_err_t esp_cam_ctlr_dvp_cam_enable(esp_cam_ctlr_handle_t handle)
|
||||
ctlr->dvp_fsm = ESP_CAM_CTLR_DVP_CAM_FSM_ENABLED;
|
||||
ret = ESP_OK;
|
||||
}
|
||||
#if CONFIG_PM_ENABLE
|
||||
if (ctlr->pm_lock) {
|
||||
ESP_RETURN_ON_ERROR(esp_pm_lock_acquire(ctlr->pm_lock), TAG, "acquire pm_lock failed");
|
||||
}
|
||||
#endif // CONFIG_PM_ENABLE
|
||||
|
||||
portEXIT_CRITICAL(&ctlr->spinlock);
|
||||
|
||||
return ret;
|
||||
@@ -449,6 +455,11 @@ static esp_err_t esp_cam_ctlr_dvp_cam_disable(esp_cam_ctlr_handle_t handle)
|
||||
ctlr->dvp_fsm = ESP_CAM_CTLR_DVP_CAM_FSM_INIT;
|
||||
ret = ESP_OK;
|
||||
}
|
||||
#if CONFIG_PM_ENABLE
|
||||
if (ctlr->pm_lock) {
|
||||
ESP_RETURN_ON_ERROR(esp_pm_lock_release(ctlr->pm_lock), TAG, "release pm_lock failed");
|
||||
}
|
||||
#endif // CONFIG_PM_ENABLE
|
||||
portEXIT_CRITICAL(&ctlr->spinlock);
|
||||
|
||||
return ret;
|
||||
@@ -546,6 +557,12 @@ static esp_err_t esp_cam_ctlr_dvp_cam_del(esp_cam_ctlr_handle_t handle)
|
||||
heap_caps_free(ctlr->backup_buffer);
|
||||
}
|
||||
|
||||
#if CONFIG_PM_ENABLE
|
||||
if (ctlr->pm_lock) {
|
||||
ESP_RETURN_ON_ERROR(esp_pm_lock_delete(ctlr->pm_lock), TAG, "delete pm_lock failed");
|
||||
}
|
||||
#endif // CONFIG_PM_ENABLE
|
||||
|
||||
s_dvp_declaim_ctlr(ctlr->ctlr_id);
|
||||
|
||||
heap_caps_free(ctlr);
|
||||
@@ -714,6 +731,10 @@ esp_err_t esp_cam_new_dvp_ctlr(const esp_cam_ctlr_dvp_config_t *config, esp_cam_
|
||||
ESP_GOTO_ON_ERROR(gdma_register_rx_event_callbacks(ctlr->dma.dma_chan, &cbs, ctlr),
|
||||
fail4, TAG, "failed to register DMA event callbacks");
|
||||
|
||||
#if CONFIG_PM_ENABLE
|
||||
ESP_GOTO_ON_ERROR(esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "dvp_cam_ctlr", &ctlr->pm_lock), fail5, TAG, "failed to create pm lock");
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
/* Initialize DVP controller */
|
||||
|
||||
cam_hal_config_t cam_hal_config = {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -31,6 +31,10 @@
|
||||
#include "esp_cam_ctlr_isp_dvp.h"
|
||||
#include "../../dvp_share_ctrl.h"
|
||||
|
||||
#if CONFIG_PM_ENABLE
|
||||
#include "esp_pm.h"
|
||||
#endif
|
||||
|
||||
#if CONFIG_CAM_CTLR_ISP_DVP_ISR_CACHE_SAFE
|
||||
#define ISP_DVP_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
|
||||
#else
|
||||
@@ -55,6 +59,9 @@ typedef struct isp_dvp_controller_t {
|
||||
dw_gdma_channel_handle_t dma_chan; //dwgdma channel handle
|
||||
size_t dvp_transfer_size; //csi transfer size for dwgdma
|
||||
bool isr_installed; //is isr installed
|
||||
#if CONFIG_PM_ENABLE
|
||||
esp_pm_lock_handle_t pm_lock; //Power management lock
|
||||
#endif
|
||||
esp_cam_ctlr_t base;
|
||||
} isp_dvp_controller_t;
|
||||
|
||||
@@ -180,6 +187,11 @@ esp_err_t esp_cam_new_isp_dvp_ctlr(isp_proc_handle_t isp_proc, const esp_cam_ctl
|
||||
mipi_csi_brg_ll_set_burst_len(isp_proc->csi_brg_hw, 512);
|
||||
|
||||
esp_cam_ctlr_t *cam_ctlr = &(dvp_ctlr->base);
|
||||
|
||||
#if CONFIG_PM_ENABLE
|
||||
ESP_GOTO_ON_ERROR(esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "isp_dvp_cam_ctlr", &dvp_ctlr->pm_lock), err, TAG, "failed to create pm lock");
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
cam_ctlr->del = s_isp_del_dvp_controller;
|
||||
cam_ctlr->enable = s_isp_dvp_enable;
|
||||
cam_ctlr->start = s_isp_dvp_start;
|
||||
@@ -221,6 +233,12 @@ esp_err_t s_isp_del_dvp_controller(esp_cam_ctlr_handle_t handle)
|
||||
if (dvp_ctlr->trans_que) {
|
||||
vQueueDeleteWithCaps(dvp_ctlr->trans_que);
|
||||
}
|
||||
#if CONFIG_PM_ENABLE
|
||||
if (dvp_ctlr->pm_lock) {
|
||||
ESP_RETURN_ON_ERROR(esp_pm_lock_delete(dvp_ctlr->pm_lock), TAG, "delete pm_lock failed");
|
||||
}
|
||||
#endif // CONFIG_PM_ENABLE
|
||||
|
||||
free(dvp_ctlr);
|
||||
|
||||
return ESP_OK;
|
||||
@@ -294,6 +312,11 @@ static esp_err_t s_isp_dvp_enable(esp_cam_ctlr_handle_t handle)
|
||||
|
||||
portENTER_CRITICAL(&dvp_ctlr->spinlock);
|
||||
dvp_ctlr->fsm = ISP_FSM_ENABLE;
|
||||
#if CONFIG_PM_ENABLE
|
||||
if (dvp_ctlr->pm_lock) {
|
||||
ESP_RETURN_ON_ERROR(esp_pm_lock_acquire(dvp_ctlr->pm_lock), TAG, "acquire pm_lock failed");
|
||||
}
|
||||
#endif // CONFIG_PM_ENABLE
|
||||
portEXIT_CRITICAL(&dvp_ctlr->spinlock);
|
||||
|
||||
return ESP_OK;
|
||||
@@ -307,6 +330,11 @@ static esp_err_t s_isp_dvp_disable(esp_cam_ctlr_handle_t handle)
|
||||
|
||||
portENTER_CRITICAL(&dvp_ctlr->spinlock);
|
||||
dvp_ctlr->fsm = ISP_FSM_INIT;
|
||||
#if CONFIG_PM_ENABLE
|
||||
if (dvp_ctlr->pm_lock) {
|
||||
ESP_RETURN_ON_ERROR(esp_pm_lock_release(dvp_ctlr->pm_lock), TAG, "release pm_lock failed");
|
||||
}
|
||||
#endif // CONFIG_PM_ENABLE
|
||||
portEXIT_CRITICAL(&dvp_ctlr->spinlock);
|
||||
|
||||
return ESP_OK;
|
||||
|
@@ -51,6 +51,9 @@ static bool IRAM_ATTR camera_trans_finished(esp_cam_ctlr_handle_t handle, esp_ca
|
||||
|
||||
TEST_CASE("TEST esp_cam on ov5647", "[csi][camera][ov5647]")
|
||||
{
|
||||
new_buffer_count = 0;
|
||||
trans_finished_count = 0;
|
||||
|
||||
size_t frame_buffer_size = TEST_MIPI_CSI_DISP_HRES *
|
||||
TEST_MIPI_DSI_DISP_VRES *
|
||||
TEST_RGB565_BITS_PER_PIXEL / 8;
|
||||
@@ -127,11 +130,12 @@ TEST_CASE("TEST esp_cam on ov5647", "[csi][camera][ov5647]")
|
||||
TEST_ESP_OK(esp_isp_enable(isp_proc));
|
||||
TEST_ESP_OK(esp_cam_ctlr_start(cam_handle));
|
||||
TEST_ESP_OK(esp_cam_ctlr_receive(cam_handle, &trans_data, ESP_CAM_CTLR_MAX_DELAY));
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
TEST_ESP_OK(esp_cam_ctlr_stop(cam_handle));
|
||||
|
||||
TEST_ASSERT_GREATER_THAN(2, new_buffer_count);
|
||||
TEST_ASSERT_GREATER_THAN(2, trans_finished_count);
|
||||
// At least 35 new buffers callback and 34 completed transfer callback are expected within 1 second when camera is 50fps.
|
||||
TEST_ASSERT_GREATER_OR_EQUAL(35, new_buffer_count);
|
||||
TEST_ASSERT_GREATER_OR_EQUAL(34, trans_finished_count);
|
||||
|
||||
TEST_ESP_OK(esp_cam_ctlr_disable(cam_handle));
|
||||
TEST_ESP_OK(esp_cam_ctlr_del(cam_handle));
|
||||
|
@@ -8,7 +8,7 @@ from pytest_embedded_idf.utils import idf_parametrize
|
||||
@pytest.mark.generic
|
||||
@pytest.mark.parametrize(
|
||||
'config',
|
||||
['cache_safe', 'release'],
|
||||
['cache_safe', 'release', 'pm_enable'],
|
||||
indirect=True,
|
||||
)
|
||||
@idf_parametrize('target', ['esp32p4'], indirect=['target'])
|
||||
|
@@ -1 +1,9 @@
|
||||
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
||||
# silent the error check, as the error string are stored in rodata, causing RTL check failure
|
||||
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
|
||||
CONFIG_HAL_ASSERTION_SILENT=y
|
||||
|
||||
CONFIG_CAM_CTLR_MIPI_CSI_ISR_CACHE_SAFE=y
|
||||
CONFIG_CAM_CTLR_ISP_DVP_ISR_CACHE_SAFE=y
|
||||
CONFIG_CAM_CTLR_DVP_CAM_ISR_CACHE_SAFE=y
|
||||
|
@@ -0,0 +1,8 @@
|
||||
# silent the error check, as the error string are stored in rodata, causing RTL check failure
|
||||
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
|
||||
CONFIG_HAL_ASSERTION_SILENT=y
|
||||
|
||||
CONFIG_PM_ENABLE=y
|
||||
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
|
||||
CONFIG_PM_DFS_INIT_AUTO=y
|
@@ -6,6 +6,11 @@ from pytest_embedded_idf.utils import idf_parametrize
|
||||
|
||||
|
||||
@pytest.mark.generic
|
||||
@pytest.mark.parametrize(
|
||||
'config',
|
||||
['cache_safe', 'release', 'pm_enable'],
|
||||
indirect=True,
|
||||
)
|
||||
@idf_parametrize('target', ['esp32p4'], indirect=['target'])
|
||||
def test_dvp(dut: Dut) -> None:
|
||||
dut.run_all_single_board_cases()
|
||||
|
@@ -1 +1,9 @@
|
||||
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
||||
# silent the error check, as the error string are stored in rodata, causing RTL check failure
|
||||
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
|
||||
CONFIG_HAL_ASSERTION_SILENT=y
|
||||
|
||||
CONFIG_CAM_CTLR_MIPI_CSI_ISR_CACHE_SAFE=y
|
||||
CONFIG_CAM_CTLR_ISP_DVP_ISR_CACHE_SAFE=y
|
||||
CONFIG_CAM_CTLR_DVP_CAM_ISR_CACHE_SAFE=y
|
||||
|
@@ -0,0 +1,8 @@
|
||||
# silent the error check, as the error string are stored in rodata, causing RTL check failure
|
||||
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
|
||||
CONFIG_HAL_ASSERTION_SILENT=y
|
||||
|
||||
CONFIG_PM_ENABLE=y
|
||||
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
|
||||
CONFIG_PM_DFS_INIT_AUTO=y
|
@@ -0,0 +1,3 @@
|
||||
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
||||
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
|
@@ -6,6 +6,11 @@ from pytest_embedded_idf.utils import idf_parametrize
|
||||
|
||||
|
||||
@pytest.mark.generic
|
||||
@pytest.mark.parametrize(
|
||||
'config',
|
||||
['cache_safe', 'release', 'pm_enable'],
|
||||
indirect=True,
|
||||
)
|
||||
@idf_parametrize('target', ['esp32p4'], indirect=['target'])
|
||||
def test_isp_dvp(dut: Dut) -> None:
|
||||
dut.run_all_single_board_cases()
|
||||
|
@@ -1 +1,9 @@
|
||||
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
||||
# silent the error check, as the error string are stored in rodata, causing RTL check failure
|
||||
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
|
||||
CONFIG_HAL_ASSERTION_SILENT=y
|
||||
|
||||
CONFIG_CAM_CTLR_MIPI_CSI_ISR_CACHE_SAFE=y
|
||||
CONFIG_CAM_CTLR_ISP_DVP_ISR_CACHE_SAFE=y
|
||||
CONFIG_CAM_CTLR_DVP_CAM_ISR_CACHE_SAFE=y
|
||||
|
@@ -0,0 +1,8 @@
|
||||
# silent the error check, as the error string are stored in rodata, causing RTL check failure
|
||||
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
|
||||
CONFIG_HAL_ASSERTION_SILENT=y
|
||||
|
||||
CONFIG_PM_ENABLE=y
|
||||
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
|
||||
CONFIG_PM_DFS_INIT_AUTO=y
|
@@ -0,0 +1,3 @@
|
||||
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
||||
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
|
Reference in New Issue
Block a user