feat(cam): support dvp cam on ESP32-S31

This commit is contained in:
gaoxu
2026-05-14 17:09:49 +08:00
parent 7ff718a988
commit 4e3751b32e
52 changed files with 1040 additions and 786 deletions
@@ -810,6 +810,9 @@ esp_err_t esp_cam_ctlr_dvp_format_conversion(esp_cam_ctlr_handle_t cam_handle,
return ESP_OK;
}
#if !SOC_LCDCAM_CAM_SUPPORT_RGB_YUV_CONV
return ESP_ERR_NOT_SUPPORTED;
#else
#if !CONFIG_ESP32P4_SELECTS_REV_LESS_V3
if (config->src_format == CAM_CTLR_COLOR_YUV420) {
ESP_LOGE(TAG, "YUV420 is not allowed for source format");
@@ -820,6 +823,7 @@ esp_err_t esp_cam_ctlr_dvp_format_conversion(esp_cam_ctlr_handle_t cam_handle,
cam_hal_color_format_convert(&ctlr->hal, config);
return ESP_OK;
#endif
}
/**
@@ -85,6 +85,9 @@ TEST_CASE("TEST esp_cam on ov5647", "[csi][camera][ov5647]")
.i2c_port_num = I2C_NUM_0,
.i2c_sda_io_num = TEST_MIPI_CSI_CAM_SCCB_SDA_IO,
.i2c_scl_io_num = TEST_MIPI_CSI_CAM_SCCB_SCL_IO,
.reset_pin = -1,
.pwdn_pin = -1,
.xclk_pin = -1,
.port = ESP_CAM_SENSOR_MIPI_CSI,
.format_name = TEST_CAM_FORMAT,
};
@@ -5,3 +5,4 @@ CONFIG_IDF_EXPERIMENTAL_FEATURES=y
CONFIG_SPIRAM_SPEED_200M=y
CONFIG_CAMERA_OV5647=y
CONFIG_CAMERA_OV5647_MIPI_RAW8_800X640_50FPS=y
@@ -1,2 +1,2 @@
| Supported Targets | ESP32-P4 | ESP32-S3 |
| ----------------- | -------- | -------- |
| Supported Targets | ESP32-P4 | ESP32-S3 | ESP32-S31 |
| ----------------- | -------- | -------- | --------- |
@@ -3,8 +3,8 @@ set(srcs "test_app_main.c")
if(CONFIG_SOC_LCDCAM_CAM_SUPPORTED)
list(APPEND srcs "test_dvp_driver.c")
endif()
if(CONFIG_IDF_TARGET_ESP32S3)
list(APPEND srcs "test_dvp_s3eye.c")
if(CONFIG_CAMERA_OV2640 AND CONFIG_SOC_LCDCAM_CAM_SUPPORTED)
list(APPEND srcs "test_dvp_ov2640.c")
endif()
set(priv_requires
@@ -14,6 +14,10 @@ set(priv_requires
esp_driver_ledc
)
if(CONFIG_CAMERA_OV2640 AND CONFIG_SOC_LCDCAM_CAM_SUPPORTED)
list(APPEND priv_requires sensor_init)
endif()
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS "."
PRIV_REQUIRES ${priv_requires}
@@ -0,0 +1,130 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "unity.h"
#include "driver/i2c_master.h"
#include "esp_attr.h"
#include "esp_heap_caps.h"
#include "esp_cam_ctlr.h"
#include "esp_cam_ctlr_dvp.h"
#include "example_sensor_init.h"
#include "test_dvp_ov2640_board.h"
static int s_new_trans_count;
static int s_trans_finished_count;
static bool IRAM_ATTR camera_get_new_buffer(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data)
{
(void)handle;
esp_cam_ctlr_trans_t *new_trans = (esp_cam_ctlr_trans_t *)user_data;
trans->buffer = new_trans->buffer;
trans->buflen = new_trans->buflen;
s_new_trans_count++;
return false;
}
static bool IRAM_ATTR camera_trans_finished(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data)
{
(void)handle;
(void)trans;
(void)user_data;
s_trans_finished_count++;
return false;
}
TEST_CASE("TEST esp_cam DVP on ov2640", "[dvp][camera][ov2640]")
{
s_new_trans_count = 0;
s_trans_finished_count = 0;
esp_cam_ctlr_dvp_pin_config_t pin_cfg = {
.data_width = TEST_DVP_CAM_DATA_WIDTH,
.data_io = {
TEST_DVP_CAM_D0_IO,
TEST_DVP_CAM_D1_IO,
TEST_DVP_CAM_D2_IO,
TEST_DVP_CAM_D3_IO,
TEST_DVP_CAM_D4_IO,
TEST_DVP_CAM_D5_IO,
TEST_DVP_CAM_D6_IO,
TEST_DVP_CAM_D7_IO,
},
.vsync_io = TEST_DVP_CAM_VSYNC_IO,
.de_io = TEST_DVP_CAM_DE_IO,
.pclk_io = TEST_DVP_CAM_PCLK_IO,
.xclk_io = TEST_DVP_CAM_XCLK_IO,
};
esp_cam_ctlr_dvp_config_t dvp_config = {
.ctlr_id = 0,
.clk_src = CAM_CLK_SRC_DEFAULT,
.h_res = TEST_DVP_CAM_FRAME_WIDTH,
.v_res = TEST_DVP_CAM_FRAME_HEIGHT,
.input_data_color_type = TEST_DVP_CAM_INPUT_COLOR_TYPE,
.output_data_color_type = TEST_DVP_CAM_OUTPUT_COLOR_TYPE,
.dma_burst_size = 64,
.pin = &pin_cfg,
.bk_buffer_dis = 1,
.xclk_freq = TEST_DVP_CAM_XCLK_FREQ_HZ,
.cam_data_width = TEST_DVP_CAM_DATA_WIDTH,
.byte_swap_en = false,
.bit_swap_en = false,
};
esp_cam_ctlr_handle_t cam_handle = NULL;
TEST_ESP_OK(esp_cam_new_dvp_ctlr(&dvp_config, &cam_handle));
size_t frame_buffer_size = TEST_DVP_CAM_FRAME_SIZE_BYTES;
void *frame_buffer = esp_cam_ctlr_alloc_buffer(cam_handle, frame_buffer_size, TEST_DVP_CAM_BUF_ALLOC_CAPS);
TEST_ASSERT_NOT_NULL(frame_buffer);
esp_cam_ctlr_trans_t trans_data = {
.buffer = frame_buffer,
.buflen = frame_buffer_size,
};
example_sensor_handle_t sensor_handle = {
.sccb_handle = NULL,
.i2c_bus_handle = NULL,
};
example_sensor_config_t sensor_config = {
.i2c_port_num = I2C_NUM_0,
.i2c_sda_io_num = TEST_DVP_CAM_SCCB_SDA_IO,
.i2c_scl_io_num = TEST_DVP_CAM_SCCB_SCL_IO,
.reset_pin = TEST_DVP_CAM_RESET_IO,
.pwdn_pin = TEST_DVP_CAM_PWDN_IO,
.xclk_pin = TEST_DVP_CAM_XCLK_IO,
.port = ESP_CAM_SENSOR_DVP,
.format_name = TEST_DVP_CAM_FORMAT_NAME,
};
example_sensor_init(&sensor_config, &sensor_handle);
if (sensor_handle.sccb_handle == NULL || sensor_handle.i2c_bus_handle == NULL) {
TEST_ESP_OK(esp_cam_ctlr_del(cam_handle));
heap_caps_free(frame_buffer);
TEST_FAIL_MESSAGE("failed to detect or initialize ov2640 sensor");
}
esp_cam_ctlr_evt_cbs_t cbs = {
.on_get_new_trans = camera_get_new_buffer,
.on_trans_finished = camera_trans_finished,
};
TEST_ESP_OK(esp_cam_ctlr_register_event_callbacks(cam_handle, &cbs, &trans_data));
TEST_ESP_OK(esp_cam_ctlr_enable(cam_handle));
TEST_ESP_OK(esp_cam_ctlr_start(cam_handle));
vTaskDelay(pdMS_TO_TICKS(1000));
TEST_ESP_OK(esp_cam_ctlr_stop(cam_handle));
// Roughly one transfer per frame is expected for the selected OV2640 format.
TEST_ASSERT_GREATER_OR_EQUAL(TEST_DVP_CAM_EXPECTED_NEW_TRANS_MIN, s_new_trans_count);
TEST_ASSERT_GREATER_OR_EQUAL(TEST_DVP_CAM_EXPECTED_FINISHED_MIN, s_trans_finished_count);
TEST_ESP_OK(esp_cam_ctlr_disable(cam_handle));
TEST_ESP_OK(esp_cam_ctlr_del(cam_handle));
example_sensor_deinit(sensor_handle);
heap_caps_free(frame_buffer);
}
@@ -0,0 +1,134 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "sdkconfig.h"
#include "hal/cam_ctlr_types.h"
#include "esp_heap_caps.h"
#ifdef __cplusplus
extern "C" {
#endif
#define TEST_DVP_CAM_FRAME_BITS_PER_PIXEL 16
#define TEST_DVP_CAM_EXPECTED_NEW_TRANS_MIN 6
#define TEST_DVP_CAM_EXPECTED_FINISHED_MIN 5
#define TEST_DVP_CAM_XCLK_FREQ_HZ 20000000
#define TEST_DVP_CAM_DATA_WIDTH 8
#if CONFIG_IDF_TARGET_ESP32S3
#define TEST_DVP_CAM_FRAME_WIDTH 640
#define TEST_DVP_CAM_FRAME_HEIGHT 480
#define TEST_DVP_CAM_FORMAT_NAME "DVP_8bit_20Minput_YUV422_YUYV_640x480_6fps"
#define TEST_DVP_CAM_INPUT_COLOR_TYPE CAM_CTLR_COLOR_YUV422_YUYV
#define TEST_DVP_CAM_OUTPUT_COLOR_TYPE CAM_CTLR_COLOR_YUV422_YUYV
#define TEST_DVP_CAM_PWDN_IO (-1)
#define TEST_DVP_CAM_RESET_IO (-1)
#define TEST_DVP_CAM_SCCB_SCL_IO 5
#define TEST_DVP_CAM_SCCB_SDA_IO 4
#define TEST_DVP_CAM_D0_IO 11
#define TEST_DVP_CAM_D1_IO 9
#define TEST_DVP_CAM_D2_IO 8
#define TEST_DVP_CAM_D3_IO 10
#define TEST_DVP_CAM_D4_IO 12
#define TEST_DVP_CAM_D5_IO 18
#define TEST_DVP_CAM_D6_IO 17
#define TEST_DVP_CAM_D7_IO 16
#define TEST_DVP_CAM_XCLK_IO 15
#define TEST_DVP_CAM_PCLK_IO 13
#define TEST_DVP_CAM_DE_IO 7
#define TEST_DVP_CAM_VSYNC_IO 6
#elif CONFIG_IDF_TARGET_ESP32P4
#define TEST_DVP_CAM_FRAME_WIDTH 640
#define TEST_DVP_CAM_FRAME_HEIGHT 480
#define TEST_DVP_CAM_FORMAT_NAME "DVP_8bit_20Minput_YUV422_UYVY_640x480_6fps"
#define TEST_DVP_CAM_INPUT_COLOR_TYPE CAM_CTLR_COLOR_YUV422_UYVY
#define TEST_DVP_CAM_OUTPUT_COLOR_TYPE CAM_CTLR_COLOR_YUV422_UYVY
#define TEST_DVP_CAM_PWDN_IO (-1)
#define TEST_DVP_CAM_RESET_IO (-1)
#if !CONFIG_ESP32P4_SELECTS_REV_LESS_V3
#define TEST_DVP_CAM_SCCB_SCL_IO 8
#define TEST_DVP_CAM_SCCB_SDA_IO 7
#define TEST_DVP_CAM_D0_IO 2
#define TEST_DVP_CAM_D1_IO 32
#define TEST_DVP_CAM_D2_IO 33
#define TEST_DVP_CAM_D3_IO 23
#define TEST_DVP_CAM_D4_IO 3
#define TEST_DVP_CAM_D5_IO 6
#define TEST_DVP_CAM_D6_IO 5
#define TEST_DVP_CAM_D7_IO 21
#define TEST_DVP_CAM_XCLK_IO 20
#define TEST_DVP_CAM_PCLK_IO 4
#define TEST_DVP_CAM_DE_IO 22
#define TEST_DVP_CAM_VSYNC_IO 37
#else
#define TEST_DVP_CAM_SCCB_SCL_IO 33
#define TEST_DVP_CAM_SCCB_SDA_IO 32
#define TEST_DVP_CAM_D0_IO 53
#define TEST_DVP_CAM_D1_IO 54
#define TEST_DVP_CAM_D2_IO 26
#define TEST_DVP_CAM_D3_IO 1
#define TEST_DVP_CAM_D4_IO 0
#define TEST_DVP_CAM_D5_IO 45
#define TEST_DVP_CAM_D6_IO 46
#define TEST_DVP_CAM_D7_IO 47
#define TEST_DVP_CAM_XCLK_IO 20
#define TEST_DVP_CAM_PCLK_IO 21
#define TEST_DVP_CAM_DE_IO 22
#define TEST_DVP_CAM_VSYNC_IO 23
#endif
#elif CONFIG_IDF_TARGET_ESP32S31
#define TEST_DVP_CAM_FRAME_WIDTH 640
#define TEST_DVP_CAM_FRAME_HEIGHT 480
#define TEST_DVP_CAM_FORMAT_NAME "DVP_8bit_20Minput_YUV422_YUYV_640x480_6fps"
#define TEST_DVP_CAM_INPUT_COLOR_TYPE CAM_CTLR_COLOR_YUV422_YUYV
#define TEST_DVP_CAM_OUTPUT_COLOR_TYPE CAM_CTLR_COLOR_YUV422_YUYV
#define TEST_DVP_CAM_PWDN_IO 61
#define TEST_DVP_CAM_RESET_IO 60
#define TEST_DVP_CAM_SCCB_SCL_IO 1
#define TEST_DVP_CAM_SCCB_SDA_IO 0
#define TEST_DVP_CAM_D0_IO 46
#define TEST_DVP_CAM_D1_IO 47
#define TEST_DVP_CAM_D2_IO 48
#define TEST_DVP_CAM_D3_IO 49
#define TEST_DVP_CAM_D4_IO 50
#define TEST_DVP_CAM_D5_IO 51
#define TEST_DVP_CAM_D6_IO 52
#define TEST_DVP_CAM_D7_IO 53
#define TEST_DVP_CAM_XCLK_IO 55
#define TEST_DVP_CAM_PCLK_IO 54
#define TEST_DVP_CAM_DE_IO 57
#define TEST_DVP_CAM_VSYNC_IO 56
#endif
#define TEST_DVP_CAM_FRAME_SIZE_BYTES \
(TEST_DVP_CAM_FRAME_WIDTH * TEST_DVP_CAM_FRAME_HEIGHT * TEST_DVP_CAM_FRAME_BITS_PER_PIXEL / 8)
#if CONFIG_SPIRAM
#define TEST_DVP_CAM_BUF_ALLOC_CAPS (MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA)
#else
#define TEST_DVP_CAM_BUF_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA)
#endif
#ifdef __cplusplus
}
#endif
@@ -1,166 +0,0 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sdkconfig.h"
#include "esp_attr.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "esp_cache.h"
#include "driver/i2c_master.h"
#include "esp_cam_ctlr.h"
#include "esp_cam_ctlr_dvp.h"
#include "driver/ledc.h"
#include "example_sensor_init.h"
#include "unity.h"
//----------CAM Config------------//
#define TEST_RGB565_BITS_PER_PIXEL 16
#define TEST_DVP_CAM_SCCB_SCL_IO (5)
#define TEST_DVP_CAM_SCCB_SDA_IO (4)
#define TEST_DVP_CAM_XCLK_FREQ_HZ (20000000)
#define TEST_DVP_CAM_DATA_WIDTH (8)
#define TEST_DVP_CAM_D0_IO (11)
#define TEST_DVP_CAM_D1_IO (9)
#define TEST_DVP_CAM_D2_IO (8)
#define TEST_DVP_CAM_D3_IO (10)
#define TEST_DVP_CAM_D4_IO (12)
#define TEST_DVP_CAM_D5_IO (18)
#define TEST_DVP_CAM_D6_IO (17)
#define TEST_DVP_CAM_D7_IO (16)
#define TEST_DVP_CAM_XCLK_IO (15)
#define TEST_DVP_CAM_PCLK_IO (13)
#define TEST_DVP_CAM_DE_IO (7)
#define TEST_DVP_CAM_VSYNC_IO (6)
#define TEST_DVP_CAM_HSYNC_IO (-1)
#define TEST_DVP_CAM_BUF_ALLOC_CAPS (MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA)
#define TEST_DVP_CAM_H_RES 240
#define TEST_DVP_CAM_V_RES 240
#define TEST_CAM_FORMAT "DVP_8bit_20Minput_RGB565_240x240_25fps"
#define BUFFER_SIZE (TEST_DVP_CAM_H_RES * TEST_DVP_CAM_V_RES * TEST_RGB565_BITS_PER_PIXEL / 8)
typedef struct {
// esp_lcd_panel_handle_t panel_hdl;
esp_cam_ctlr_trans_t cam_trans;
} example_cam_context_t;
static bool s_camera_get_new_vb(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data);
static bool s_camera_get_finished_trans(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data);
int count_new_vb = 0;
int count_finished_trans = 0;
TEST_CASE("TEST DVP camera on esp32s3_eye", "[dvp][camera][esp32s3_eye]")
{
//----------CAM Controller Init------------//
esp_cam_ctlr_handle_t cam_handle = NULL;
esp_cam_ctlr_dvp_pin_config_t pin_cfg = {
.data_width = TEST_DVP_CAM_DATA_WIDTH,
.data_io = {
TEST_DVP_CAM_D0_IO,
TEST_DVP_CAM_D1_IO,
TEST_DVP_CAM_D2_IO,
TEST_DVP_CAM_D3_IO,
TEST_DVP_CAM_D4_IO,
TEST_DVP_CAM_D5_IO,
TEST_DVP_CAM_D6_IO,
TEST_DVP_CAM_D7_IO,
},
.vsync_io = TEST_DVP_CAM_VSYNC_IO,
.de_io = TEST_DVP_CAM_DE_IO,
.pclk_io = TEST_DVP_CAM_PCLK_IO,
.xclk_io = TEST_DVP_CAM_XCLK_IO,
};
esp_cam_ctlr_dvp_config_t dvp_config = {
.ctlr_id = 0,
.clk_src = CAM_CLK_SRC_DEFAULT,
.h_res = TEST_DVP_CAM_H_RES,
.v_res = TEST_DVP_CAM_V_RES,
.input_data_color_type = CAM_CTLR_COLOR_RGB565,
.output_data_color_type = CAM_CTLR_COLOR_RGB565,
.dma_burst_size = 64,
.pin = &pin_cfg,
.bk_buffer_dis = 1,
.xclk_freq = TEST_DVP_CAM_XCLK_FREQ_HZ,
};
TEST_ESP_OK(esp_cam_new_dvp_ctlr(&dvp_config, &cam_handle));
//--------Allocate Camera Buffer----------//
size_t cam_buffer_size = TEST_DVP_CAM_H_RES * TEST_DVP_CAM_V_RES * TEST_RGB565_BITS_PER_PIXEL / 8;
void *cam_buffer = NULL;
cam_buffer = esp_cam_ctlr_alloc_buffer(cam_handle, cam_buffer_size, TEST_DVP_CAM_BUF_ALLOC_CAPS);
//--------Camera Sensor and SCCB Init-----------//
example_sensor_config_t cam_sensor_config = {
.i2c_port_num = I2C_NUM_0,
.i2c_sda_io_num = TEST_DVP_CAM_SCCB_SDA_IO,
.i2c_scl_io_num = TEST_DVP_CAM_SCCB_SCL_IO,
.port = ESP_CAM_SENSOR_DVP,
.format_name = TEST_CAM_FORMAT,
};
example_sensor_handle_t sensor_handle = {
.sccb_handle = NULL,
.i2c_bus_handle = NULL,
};
example_sensor_init(&cam_sensor_config, &sensor_handle);
//--------Register Camera Callbacks----------//
example_cam_context_t cam_ctx = {
// .panel_hdl = lcd_panel_hdl,
.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,
};
TEST_ESP_OK(esp_cam_ctlr_register_event_callbacks(cam_handle, &cbs, &cam_ctx));
TEST_ESP_OK(esp_cam_ctlr_enable(cam_handle));
TEST_ESP_OK(esp_cam_ctlr_start(cam_handle));
vTaskDelay(1000 / portTICK_PERIOD_MS);
//For this format"DVP_8bit_20Minput_RGB565_240x240_25fps", the FPS is 25
TEST_ASSERT_GREATER_OR_EQUAL(25, count_new_vb);
TEST_ASSERT_GREATER_OR_EQUAL(24, count_finished_trans);
TEST_ESP_OK(esp_cam_ctlr_stop(cam_handle));
TEST_ESP_OK(esp_cam_ctlr_disable(cam_handle));
TEST_ESP_OK(esp_cam_ctlr_del(cam_handle));
example_sensor_deinit(sensor_handle);
heap_caps_free(cam_buffer);
}
static bool s_camera_get_new_vb(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data)
{
example_cam_context_t *ctx = (example_cam_context_t *)user_data;
*trans = ctx->cam_trans;
count_new_vb++;
return false;
}
static bool s_camera_get_finished_trans(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data)
{
count_finished_trans++;
return false;
}
@@ -1,41 +1,34 @@
# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded import Dut
from pytest_embedded_idf.utils import idf_parametrize
def _skip_board_specific_cases(case_tester) -> None: # type: ignore
for case in case_tester.test_menu:
if 'TEST esp_cam DVP on ov2640' in case.name:
continue
case_tester.run_normal_case(case=case, reset=True)
@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()
@pytest.mark.octal_psram
@pytest.mark.parametrize(
'config',
['cache_safe', 'release', 'pm_enable'],
indirect=True,
)
@idf_parametrize('target', ['esp32s3'], indirect=['target'])
def test_dvp_driver(case_tester) -> None: # type: ignore
for case in case_tester.test_menu:
if 'TEST DVP camera on esp32s3_eye' in case.name:
continue
case_tester.run_normal_case(case=case, reset=True)
@idf_parametrize('target', ['esp32p4', 'esp32s31'], indirect=['target'])
def test_dvp(case_tester) -> None: # type: ignore
_skip_board_specific_cases(case_tester)
@pytest.mark.esp32s3_eye
@pytest.mark.parametrize(
'config',
['esp32s3_eye'],
['cache_safe', 'release', 'pm_enable', 'esp32s3_ov2640'],
indirect=True,
)
@idf_parametrize('target', ['esp32s3'], indirect=['target'])
def test_dvp_s3eye(dut: Dut) -> None:
def test_dvp_esp32s3(dut: Dut) -> None:
dut.run_all_single_board_cases()
@@ -0,0 +1,6 @@
CONFIG_IDF_TARGET="esp32p4"
CONFIG_SPIRAM=y
CONFIG_SPIRAM_SPEED_200M=y
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
CONFIG_CAMERA_OV2640=y
@@ -0,0 +1,5 @@
CONFIG_IDF_TARGET="esp32s31"
CONFIG_SPIRAM=y
CONFIG_SPIRAM_SPEED_250M=y
CONFIG_CAMERA_OV2640=y
@@ -1,7 +0,0 @@
CONFIG_IDF_TARGET="esp32s3"
CONFIG_SPIRAM=y
CONFIG_SPIRAM_MODE_OCT=y
CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y
CONFIG_CAMERA_OV2640=y
@@ -0,0 +1 @@
CONFIG_CAMERA_OV2640=y
@@ -1,4 +1,6 @@
CONFIG_IDF_TARGET="esp32s3"
CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y
CONFIG_SPIRAM=y
CONFIG_SPIRAM_MODE_OCT=y
@@ -0,0 +1,4 @@
CONFIG_IDF_TARGET="esp32s31"
CONFIG_SPIRAM=y
CONFIG_SPIRAM_SPEED_250M=y
@@ -0,0 +1,40 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "hal/cam_periph.h"
#include "soc/gpio_sig_map.h"
const cam_signal_conn_t cam_periph_signals = {
.buses = {
[0] = {
.module = PERIPH_LCD_CAM_MODULE,
.irq_id = ETS_LCD_CAM_INTR_SOURCE,
.data_sigs = {
CAM_DATA0_IN_PAD_IN_IDX,
CAM_DATA1_IN_PAD_IN_IDX,
CAM_DATA2_IN_PAD_IN_IDX,
CAM_DATA3_IN_PAD_IN_IDX,
CAM_DATA4_IN_PAD_IN_IDX,
CAM_DATA5_IN_PAD_IN_IDX,
CAM_DATA6_IN_PAD_IN_IDX,
CAM_DATA7_IN_PAD_IN_IDX,
CAM_DATA8_IN_PAD_IN_IDX,
CAM_DATA9_IN_PAD_IN_IDX,
CAM_DATA10_IN_PAD_IN_IDX,
CAM_DATA11_IN_PAD_IN_IDX,
CAM_DATA12_IN_PAD_IN_IDX,
CAM_DATA13_IN_PAD_IN_IDX,
CAM_DATA14_IN_PAD_IN_IDX,
CAM_DATA15_IN_PAD_IN_IDX,
},
.hsync_sig = CAM_H_SYNC_PAD_IN_IDX,
.vsync_sig = CAM_V_SYNC_PAD_IN_IDX,
.pclk_sig = CAM_PCLK_PAD_IN_IDX,
.de_sig = CAM_H_ENABLE_PAD_IN_IDX,
.clk_sig = CAM_CLK_PAD_OUT_IDX
}
}
};
@@ -0,0 +1,583 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include "hal/assert.h"
#include "hal/cam_types.h"
#include "hal/misc.h"
#include "soc/hp_sys_clkrst_struct.h"
#include "soc/lcd_cam_struct.h"
#ifdef __cplusplus
extern "C" {
#endif
#define CAM_LL_GET_HW(id) (((id) == 0) ? (&LCD_CAM) : NULL)
#define CAM_LL_CLK_FRAC_DIV_N_MAX 256 // CAM_CLK = CAM_CLK_S / (N + b/a), the N register is 8 bit-width
#define CAM_LL_CLK_FRAC_DIV_AB_MAX 256 // CAM_CLK = CAM_CLK_S / (N + b/a), the a/b register is 8 bit-width
#define CAM_LL_PERIPH_NUM (1U)
#define CAM_LL_DATA_WIDTH_MAX (16U)
/**
* @brief Enable the bus clock for CAM module
*
* @param group_id Group ID
* @param enable true to enable, false to disable
*/
static inline void cam_ll_enable_bus_clock(int group_id, bool en)
{
(void)group_id;
// the core clock is a shared clock for both LCD and CAM
HP_SYS_CLKRST.lcdcam_lcdcam_ctrl0.reg_lcdcam_clk_en = en;
HP_SYS_CLKRST.lcdcam_ctrl0.reg_lcdcam_apb_clk_en = en;
HP_SYS_CLKRST.lcdcam_ctrl0.reg_lcdcam_sys_clk_en = en;
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
#define cam_ll_enable_bus_clock(...) do { \
(void)__DECLARE_RCC_RC_ATOMIC_ENV; \
cam_ll_enable_bus_clock(__VA_ARGS__); \
} while(0)
/**
* @brief Reset the CAM module
*
* @param group_id Group ID
*/
static inline void cam_ll_reset_register(int group_id)
{
(void)group_id;
HP_SYS_CLKRST.lcdcam_ctrl0.reg_lcdcam_apb_rst_en = 1;
HP_SYS_CLKRST.lcdcam_ctrl0.reg_lcdcam_apb_rst_en = 0;
HP_SYS_CLKRST.lcdcam_ctrl0.reg_lcdcam_rst_en = 1;
HP_SYS_CLKRST.lcdcam_ctrl0.reg_lcdcam_rst_en = 0;
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
#define cam_ll_reset_register(...) do { \
(void)__DECLARE_RCC_RC_ATOMIC_ENV; \
cam_ll_reset_register(__VA_ARGS__); \
} while(0)
/**
* @brief Enable clock gating
*
* @param group_id Group ID
* @param en True to enable, False to disable
*/
static inline void cam_ll_enable_clk(int group_id, bool en)
{
(void)group_id;
HP_SYS_CLKRST.lcdcam_cam_ctrl0.reg_cam_clk_en = en;
}
/**
* @brief Select clock source for CAM peripheral
*
* @param group_id Group ID
* @param src Clock source
*/
static inline void cam_ll_select_clk_src(int group_id, cam_clock_source_t src)
{
(void)group_id;
switch (src) {
case CAM_CLK_SRC_XTAL:
HP_SYS_CLKRST.lcdcam_cam_ctrl0.reg_cam_clk_src_sel = 0;
break;
case CAM_CLK_SRC_PLL160M:
HP_SYS_CLKRST.lcdcam_cam_ctrl0.reg_cam_clk_src_sel = 1;
break;
case CAM_CLK_SRC_APLL:
HP_SYS_CLKRST.lcdcam_cam_ctrl0.reg_cam_clk_src_sel = 2;
break;
default:
HP_SYS_CLKRST.lcdcam_cam_ctrl0.reg_cam_clk_src_sel = 3;
HAL_ASSERT(false);
break;
}
}
/**
* @brief Get the CAM source clock type
*
* @param dev CAM register base address
* @param src The pointer to accept the CAM source clock type
*/
static inline void cam_ll_get_clk_src(lcd_cam_dev_t *dev, cam_clock_source_t *src)
{
(void)dev;
switch (HP_SYS_CLKRST.lcdcam_cam_ctrl0.reg_cam_clk_src_sel) {
case 0:
*src = CAM_CLK_SRC_XTAL;
break;
case 1:
*src = CAM_CLK_SRC_PLL160M;
break;
case 2:
*src = CAM_CLK_SRC_APLL;
break;
default:
HAL_ASSERT(false);
break;
}
}
/**
* @brief Set clock coefficient of CAM peripheral
*
* @param group_id Group ID
* @param div_num Integer part of the divider
* @param div_a denominator of the divider
* @param div_b numerator of the divider
*/
__attribute__((always_inline))
static inline void cam_ll_set_group_clock_coeff(int group_id, int div_num, int div_a, int div_b)
{
(void)group_id;
HAL_ASSERT(div_num > 0 && div_num <= CAM_LL_CLK_FRAC_DIV_N_MAX);
HAL_ASSERT(div_a >= 0 && div_a < CAM_LL_CLK_FRAC_DIV_AB_MAX);
HAL_ASSERT(div_b >= 0 && div_b < CAM_LL_CLK_FRAC_DIV_AB_MAX);
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.lcdcam_cam_ctrl0, reg_cam_clk_div_num, div_num - 1);
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.lcdcam_cam_ctrl0, reg_cam_clk_div_denominator, div_a);
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.lcdcam_cam_ctrl0, reg_cam_clk_div_numerator, div_b);
}
/**
* @brief Enable stop signal for CAM peripheral
*
* @param dev CAM register base address
* @param en True to stop when GDMA Rx FIFO is full, False to not stop
*/
static inline void cam_ll_enable_stop_signal(lcd_cam_dev_t *dev, bool en)
{
dev->cam_ctrl.cam_stop_en = en;
}
/**
* @brief Set vsync filter threshold value
*
* @param dev CAM register base address
* @param value Filter threshold value for CAM_VSYNC_SIGNAL, range [0, 7]
*/
static inline void cam_ll_set_vsync_filter_thres(lcd_cam_dev_t *dev, uint32_t value)
{
dev->cam_ctrl.cam_vsync_filter_thres = value;
}
/**
* @brief Enable to generate LCD_CAM_CAM_HS_INT
*
* @param dev CAM register base address
* @param en True to enable to generate LCD_CAM_CAM_HS_INT, False to disable
*/
static inline void cam_ll_enable_hs_line_int(lcd_cam_dev_t *dev, bool en)
{
dev->cam_ctrl.cam_line_int_en = en;
}
/**
* @brief Enable CAM_VSYNC to generate in_suc_eof
*
* @param dev CAM register base address
* @param en True to enable CAM_VSYNC to generate in_suc_eof, False to use LCD_CAM_CAM_REC_DATA_BYTELEN to control in_suc_eof
*/
static inline void cam_ll_enable_vsync_generate_eof(lcd_cam_dev_t *dev, bool en)
{
dev->cam_ctrl.cam_vs_eof_en = en;
}
/**
* @brief Enable to swap every two 8-bit input data
*
* @param dev CAM register base address
* @param en True to enable invert, False to disable invert
*/
static inline void cam_ll_enable_8bits_data_invert(lcd_cam_dev_t *dev, bool en)
{
dev->cam_rgb_yuv.cam_conv_8bits_data_inv = en;
}
/**
* @brief Enable YUV-RGB converter
*
* @param dev CAM register base address
* @param en True to enable converter, False to disable converter
*/
static inline void cam_ll_enable_rgb_yuv_convert(lcd_cam_dev_t *dev, bool en)
{
dev->cam_rgb_yuv.cam_conv_enable = en;
}
/**
* @brief Set convert data line width
*
* @param dev CAM register base address
* @param width data line width (8 or 16)
*/
static inline void cam_ll_set_convert_data_width(lcd_cam_dev_t *dev, uint32_t width)
{
HAL_ASSERT(width == 8 || width == 16);
dev->cam_rgb_yuv.cam_conv_mode_8bits_on = (width == 8) ? 1 : 0;
}
/**
* @brief Set the color range of input data
*
* @param dev CAM register base address
* @param range Color range
*/
static inline void cam_ll_set_input_color_range(lcd_cam_dev_t *dev, color_range_t range)
{
if (range == COLOR_RANGE_LIMIT) {
dev->cam_rgb_yuv.cam_conv_data_in_mode = 0;
} else if (range == COLOR_RANGE_FULL) {
dev->cam_rgb_yuv.cam_conv_data_in_mode = 1;
}
}
/**
* @brief Set the color range of output data
*
* @param dev CAM register base address
* @param range Color range
*/
static inline void cam_ll_set_output_color_range(lcd_cam_dev_t *dev, color_range_t range)
{
if (range == COLOR_RANGE_LIMIT) {
dev->cam_rgb_yuv.cam_conv_data_out_mode = 0;
} else if (range == COLOR_RANGE_FULL) {
dev->cam_rgb_yuv.cam_conv_data_out_mode = 1;
}
}
/**
* @brief Set YUV conversion standard
*
* @param dev CAM register base address
* @param std YUV conversion standard
*/
static inline void cam_ll_set_yuv_convert_std(lcd_cam_dev_t *dev, color_conv_std_rgb_yuv_t std)
{
if (std == COLOR_CONV_STD_RGB_YUV_BT601) {
dev->cam_rgb_yuv.cam_conv_protocol_mode = 0;
} else if (std == COLOR_CONV_STD_RGB_YUV_BT709) {
dev->cam_rgb_yuv.cam_conv_protocol_mode = 1;
}
}
/**
* @brief Set converter mode
*
* @param dev CAM register base address
* @param src_fourcc Source format FourCC
* @param dst_fourcc Destination format FourCC
*/
static inline void cam_ll_set_convert_mode(lcd_cam_dev_t *dev, uint32_t src_fourcc, uint32_t dst_fourcc)
{
bool src_is_yuv = (src_fourcc == ESP_COLOR_FOURCC_OUYY_EVYY ||
src_fourcc == ESP_COLOR_FOURCC_YVYU ||
src_fourcc == ESP_COLOR_FOURCC_YUYV ||
src_fourcc == ESP_COLOR_FOURCC_UYVY ||
src_fourcc == ESP_COLOR_FOURCC_VYUY ||
src_fourcc == ESP_COLOR_FOURCC_YUV);
bool dst_is_yuv = (dst_fourcc == ESP_COLOR_FOURCC_OUYY_EVYY ||
dst_fourcc == ESP_COLOR_FOURCC_YVYU ||
dst_fourcc == ESP_COLOR_FOURCC_YUYV ||
dst_fourcc == ESP_COLOR_FOURCC_UYVY ||
dst_fourcc == ESP_COLOR_FOURCC_VYUY ||
dst_fourcc == ESP_COLOR_FOURCC_YUV);
if (src_is_yuv && dst_is_yuv) {
HAL_ASSERT(src_fourcc != dst_fourcc);
dev->cam_rgb_yuv.cam_conv_trans_mode = 1;
dev->cam_rgb_yuv.cam_conv_yuv_mode = (src_fourcc == ESP_COLOR_FOURCC_OUYY_EVYY) ? 1 : 0;
dev->cam_rgb_yuv.cam_conv_yuv2yuv_mode = (dst_fourcc == ESP_COLOR_FOURCC_OUYY_EVYY) ? 1 : 0;
} else if (src_is_yuv) {
dev->cam_rgb_yuv.cam_conv_trans_mode = 0;
dev->cam_rgb_yuv.cam_conv_yuv2yuv_mode = 3;
dev->cam_rgb_yuv.cam_conv_yuv_mode = (src_fourcc == ESP_COLOR_FOURCC_OUYY_EVYY) ? 1 : 0;
} else if (dst_is_yuv) {
dev->cam_rgb_yuv.cam_conv_trans_mode = 1;
dev->cam_rgb_yuv.cam_conv_yuv2yuv_mode = 3;
dev->cam_rgb_yuv.cam_conv_yuv_mode = (dst_fourcc == ESP_COLOR_FOURCC_OUYY_EVYY) ? 1 : 0;
}
}
/**
* @brief Set camera received data byte length
*
* @param dev CAM register base address
* @param length received data byte length, range [0, 0xFFFF]
*/
static inline void cam_ll_set_recv_data_bytelen(lcd_cam_dev_t *dev, uint32_t length)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->cam_ctrl1, cam_rec_data_bytelen, length);
}
/**
* @brief Set line number to trigger interrupt
*
* @param dev CAM register base address
* @param number line number to trigger hs interrupt, range [0, 0x3F]
*/
static inline void cam_ll_set_line_int_num(lcd_cam_dev_t *dev, uint32_t number)
{
dev->cam_ctrl1.cam_line_int_num = number;
}
/**
* @brief Whether to invert the input signal CAM_PCLK
*
* @param dev CAM register base address
* @param en True to invert, False to not invert
*/
static inline void cam_ll_enable_invert_pclk(lcd_cam_dev_t *dev, bool en)
{
dev->cam_ctrl1.cam_clk_inv = en;
}
/**
* @brief Enable CAM_VSYNC filter function
*
* @param dev CAM register base address
* @param en True to enable, False to bypass
*/
static inline void cam_ll_enable_vsync_filter(lcd_cam_dev_t *dev, bool en)
{
dev->cam_ctrl1.cam_vsync_filter_en = en;
}
/**
* @brief Set CAM input data width
*
* @param dev CAM register base address
* @param stride 16: The bit number of input data is 9~16. 8: The bit number of input data is 0~8.
*/
static inline void cam_ll_set_input_data_width(lcd_cam_dev_t *dev, uint32_t stride)
{
switch (stride) {
case 8:
dev->cam_ctrl1.cam_2byte_en = 0;
break;
case 16:
dev->cam_ctrl1.cam_2byte_en = 1;
break;
default:
HAL_ASSERT(false);
break;
}
}
/**
* @brief Whether to invert CAM_DE
*
* @param dev CAM register base address
* @param en True to invert, False to not invert
*/
static inline void cam_ll_enable_invert_de(lcd_cam_dev_t *dev, bool en)
{
dev->cam_ctrl1.cam_de_inv = en;
}
/**
* @brief Whether to invert CAM_HSYNC
*
* @param dev CAM register base address
* @param en True to invert, False to not invert
*/
static inline void cam_ll_enable_invert_hsync(lcd_cam_dev_t *dev, bool en)
{
dev->cam_ctrl1.cam_hsync_inv = en;
}
/**
* @brief Whether to invert CAM_VSYNC
*
* @param dev CAM register base address
* @param en True to invert, False to not invert
*/
static inline void cam_ll_enable_invert_vsync(lcd_cam_dev_t *dev, bool en)
{
dev->cam_ctrl1.cam_vsync_inv = en;
}
/**
* @brief Enable the mode to control the input control signals
*
* @param dev CAM register base address
* @param mode 1: Input control signals are CAM_DE, CAM_HSYNC and CAM_VSYNC;
* 0: Input control signals are CAM_DE and CAM_VSYNC. CAM_HSYNC and CAM_DE are all 1 the the same time.
*/
static inline void cam_ll_set_vh_de_mode(lcd_cam_dev_t *dev, bool enable)
{
dev->cam_ctrl1.cam_vh_de_mode_en = enable;
}
/**
* @brief Get the mode of input control signals
*
* @param dev CAM register base address
* @param en The pointer to accept the vh_de mode status. 1: Input control signals are CAM_DE, CAM_HSYNC and CAM_VSYNC;
* 0: Input control signals are CAM_DE and CAM_VSYNC. CAM_HSYNC and CAM_DE are all 1 the the same time.
*/
static inline void cam_ll_get_vh_de_mode(lcd_cam_dev_t *dev, bool *en)
{
*en = dev->cam_ctrl1.cam_vh_de_mode_en;
}
/**
* @brief Set the wire width of CAM output
*
* @param dev CAM register base address
* @param width CAM output wire width
*/
static inline void cam_ll_set_data_wire_width(lcd_cam_dev_t *dev, uint32_t width)
{
(void)dev;
(void)width;
// data line width is same as data stride that set in `cam_ll_set_input_data_width`
}
/**
* @brief Start the CAM transaction
*
* @param dev CAM register base address
*/
__attribute__((always_inline))
static inline void cam_ll_start(lcd_cam_dev_t *dev)
{
dev->cam_ctrl.cam_update_reg = 1;
dev->cam_ctrl1.cam_start = 1;
}
/**
* @brief Stop the CAM transaction
*
* @param dev CAM register base address
*/
__attribute__((always_inline))
static inline void cam_ll_stop(lcd_cam_dev_t *dev)
{
dev->cam_ctrl1.cam_start = 0;
dev->cam_ctrl.cam_update_reg = 1; // self clear
}
/**
* @brief Whether to reverse the data bit order
*
* @note It acts before the YUV-RGB converter
*
* @param dev CAM register base address
* @param en True to reverse, False to not reverse
*/
__attribute__((always_inline))
static inline void cam_ll_reverse_dma_data_bit_order(lcd_cam_dev_t *dev, bool en)
{
dev->cam_ctrl.cam_bit_order = en;
}
/**
* @brief Whether to swap adjacent two bytes
*
* @note This acts before the YUV-RGB converter, mainly to change the data endian.
* {B1,B0},{B3,B2} => {B0,B1}{B2,B3}
*
* @param dev CAM register base address
* @param en True to swap the byte order, False to not swap
*/
__attribute__((always_inline))
static inline void cam_ll_swap_dma_data_byte_order(lcd_cam_dev_t *dev, bool en)
{
dev->cam_ctrl.cam_byte_order = en;
}
/**
* @brief Reset camera module
*
* @param dev CAM register base address
*/
__attribute__((always_inline))
static inline void cam_ll_reset(lcd_cam_dev_t *dev)
{
dev->cam_ctrl1.cam_reset = 1; // self clear
}
/**
* @brief Reset Async RX FIFO
*
* @param dev CAM register base address
*/
__attribute__((always_inline))
static inline void cam_ll_fifo_reset(lcd_cam_dev_t *dev)
{
dev->cam_ctrl1.cam_afifo_reset = 1; // self clear
}
/**
* @brief Enable/disable interrupt by mask
*
* @param dev CAM register base address
* @param mask Interrupt mask
* @param en True to enable interrupt, False to disable interrupt
*/
static inline void cam_ll_enable_interrupt(lcd_cam_dev_t *dev, uint32_t mask, bool en)
{
if (en) {
dev->lc_dma_int_ena.val |= mask & 0x2c;
} else {
dev->lc_dma_int_ena.val &= ~(mask & 0x2c);
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define cam_ll_enable_interrupt(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
cam_ll_enable_interrupt(__VA_ARGS__); \
} while(0)
/**
* @brief Get interrupt status value
*
* @param dev CAM register base address
* @return Interrupt status value
*/
__attribute__((always_inline))
static inline uint32_t cam_ll_get_interrupt_status(lcd_cam_dev_t *dev)
{
return dev->lc_dma_int_st.val & 0x2c;
}
/**
* @brief Clear interrupt status by mask
*
* @param dev CAM register base address
* @param mask Interrupt status mask
*/
__attribute__((always_inline))
static inline void cam_ll_clear_interrupt_status(lcd_cam_dev_t *dev, uint32_t mask)
{
dev->lc_dma_int_clr.val = mask & 0x2c;
}
/**
* @brief Get address of interrupt status register address
*
* @param dev CAM register base address
* @return Interrupt status register address
*/
static inline volatile void *cam_ll_get_interrupt_status_reg(lcd_cam_dev_t *dev)
{
return &dev->lc_dma_int_st;
}
#ifdef __cplusplus
}
#endif
@@ -11,6 +11,7 @@
#include "esp_attr.h"
#include "soc/soc.h"
#include "soc/reset_reasons.h"
#include "soc/hp_sys_clkrst_struct.h"
#include "soc/lp_clkrst_struct.h"
#include "soc/lp_clkrst_reg.h"
@@ -33,6 +34,29 @@ FORCE_INLINE_ATTR void _clk_gate_ll_rtc_fast_to_lp_periph_en(bool enable)
_clk_gate_ll_rtc_fast_to_lp_periph_en(__VA_ARGS__); \
} while(0)
/**
* @brief Set the default clock gate configuration
*/
static inline void periph_ll_clk_gate_set_default(soc_reset_reason_t rst_reason)
{
if ((rst_reason == RESET_REASON_CHIP_POWER_ON) || (rst_reason == RESET_REASON_CORE_PMU_PWR_DOWN) ||
(rst_reason == RESET_REASON_SYS_BROWN_OUT) || (rst_reason == RESET_REASON_SYS_RWDT) ||
(rst_reason == RESET_REASON_SYS_SUPER_WDT) || (rst_reason == RESET_REASON_CORE_SW) ||
(rst_reason == RESET_REASON_CORE_MWDT0) || (rst_reason == RESET_REASON_CORE_MWDT1) ||
(rst_reason == RESET_REASON_CORE_RWDT) || (rst_reason == RESET_REASON_CORE_PWR_GLITCH) ||
(rst_reason == RESET_REASON_CORE_EFUSE_CRC) || (rst_reason == RESET_REASON_CORE_USB_JTAG) ||
(rst_reason == RESET_REASON_CORE_USB_UART)
) {
/*
* Default lcdcam_lcdcam_ctrl0:
* reg_lcdcam_clk_src_sel: 1 (BBPLL 120 MHz path, shared by LCD and CAM)
* reg_lcdcam_clk_div_num: 1 (divide by 2 → 60 MHz)
*/
HP_SYS_CLKRST.lcdcam_lcdcam_ctrl0.reg_lcdcam_clk_src_sel = 1;
HP_SYS_CLKRST.lcdcam_lcdcam_ctrl0.reg_lcdcam_clk_div_num = 1;
}
}
#ifdef __cplusplus
}
#endif
@@ -71,6 +71,8 @@ typedef enum {
static inline void lcd_ll_enable_bus_clock(int group_id, bool enable)
{
(void)group_id;
// the core clock is a shared clock for both LCD and CAM
HP_SYS_CLKRST.lcdcam_lcdcam_ctrl0.reg_lcdcam_clk_en = enable;
HP_SYS_CLKRST.lcdcam_ctrl0.reg_lcdcam_apb_clk_en = enable;
HP_SYS_CLKRST.lcdcam_ctrl0.reg_lcdcam_sys_clk_en = enable;
}
@@ -112,7 +114,6 @@ static inline void _lcd_ll_reset_register(int group_id)
static inline void lcd_ll_enable_clock(lcd_cam_dev_t *dev, bool en)
{
(void)dev;
HP_SYS_CLKRST.lcdcam_lcdcam_ctrl0.reg_lcdcam_clk_en = en;
HP_SYS_CLKRST.lcdcam_lcd_ctrl0.reg_lcd_clk_en = en;
}
@@ -25,6 +25,7 @@
#include "esp_private/esp_sleep_internal.h"
#include "esp_private/esp_modem_clock.h"
#include "esp_private/periph_ctrl.h"
#include "hal/clk_gate_ll.h"
#include "esp_private/esp_clk.h"
#include "esp_private/esp_pmu.h"
#include "esp_rom_serial_output.h"
@@ -194,4 +195,6 @@ __attribute__((weak)) void esp_perip_clk_init(void)
: MODEM_CLOCK_LPCLK_SRC_RC_SLOW);
modem_clock_select_lp_clock_source(PERIPH_WIFI_MODULE, modem_lpclk_src, 0);
#endif
periph_ll_clk_gate_set_default(esp_rom_get_reset_reason(0));
}
@@ -47,6 +47,10 @@ config SOC_LCDCAM_SUPPORTED
bool
default y
config SOC_LCDCAM_CAM_SUPPORTED
bool
default y
config SOC_LCDCAM_I80_LCD_SUPPORTED
bool
default y
@@ -911,6 +915,10 @@ config SOC_KEY_MANAGER_ECDSA_KEY_DEPLOY
bool
default y
config SOC_LCDCAM_CAM_SUPPORT_RGB_YUV_CONV
bool
default y
config SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS
int
default 3
@@ -179,6 +179,23 @@ typedef enum {
LCD_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the default choice */
} soc_periph_lcd_clk_src_t;
//////////////////////////////////////////////////CAM///////////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of CAM
*/
#define SOC_CAM_CLKS {SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_XTAL, SOC_MOD_CLK_APLL}
/**
* @brief Type of CAM clock source
*/
typedef enum {
CAM_CLK_SRC_PLL160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the source clock */
CAM_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */
CAM_CLK_SRC_APLL = SOC_MOD_CLK_APLL, /*!< Select APLL as the source clock */
CAM_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the default choice */
} soc_periph_cam_clk_src_t;
//////////////////////////////////////////////////SYSTIMER//////////////////////////////////////////////////////////////
/**
@@ -35,7 +35,7 @@
#define SOC_DMA2D_SUPPORTED 1
#define SOC_GPTIMER_SUPPORTED 1
#define SOC_LCDCAM_SUPPORTED 1
// #define SOC_LCDCAM_CAM_SUPPORTED 1 // TODO: [ESP32S31] IDF-14722
#define SOC_LCDCAM_CAM_SUPPORTED 1
#define SOC_LCDCAM_I80_LCD_SUPPORTED 1
#define SOC_LCDCAM_RGB_LCD_SUPPORTED 1
#define SOC_LCD_I80_SUPPORTED 1
@@ -365,6 +365,10 @@
// TODO: [ESP32S31] IDF-14626
#define SOC_KEY_MANAGER_ECDSA_KEY_DEPLOY 1 /*!< Key manager responsible to deploy ECDSA key */
// #define SOC_KEY_MANAGER_FE_KEY_DEPLOY 1 /*!< Key manager responsible to deploy Flash Encryption key */
/*--------------------------- CAM ---------------------------------*/
#define SOC_LCDCAM_CAM_SUPPORT_RGB_YUV_CONV (1)
/*-------------------------- Secure Boot CAPS----------------------------*/
// TODO: [ESP32S31] IDF-14629
#define SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS 3