Skip to content

Commit e40b705

Browse files
committed
Merge branch 'feature/add_spi_video_device' into 'master'
feat(esp_video): Add SPI video device for SPI interface camera Closes AEG-2457 and AEG-2482 See merge request espressif/esp-video-components!288
2 parents c4ab65f + 7cf64a4 commit e40b705

File tree

26 files changed

+964
-33
lines changed

26 files changed

+964
-33
lines changed

esp_cam_sensor/include/esp_cam_ctlr_spi.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,13 @@ esp_err_t esp_cam_new_spi_ctlr(const esp_cam_ctlr_spi_config_t *config, esp_cam_
7171
* @param src_len Source buffer length
7272
* @param dst Destination buffer pointer
7373
* @param dst_len Destination buffer length
74+
* @param decoded_size Decoded size pointer
7475
*
7576
* @return
7677
* - ESP_OK on success
7778
* - Others if failed
7879
*/
79-
esp_err_t esp_cam_spi_decode_frame(esp_cam_ctlr_handle_t handle, uint8_t *src, uint32_t src_len, uint8_t *dst, uint32_t dst_len);
80+
esp_err_t esp_cam_spi_decode_frame(esp_cam_ctlr_handle_t handle, uint8_t *src, uint32_t src_len, uint8_t *dst, uint32_t dst_len, uint32_t *decoded_size);
8081

8182
#ifdef __cplusplus
8283
}

esp_cam_sensor/src/driver_cam/esp_cam_ctlr_spi_cam.c

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,15 @@ static void SPI_CAM_ISR_ATTR spi_cam_post_trans_cb(spi_slave_transaction_t *spi_
105105
{
106106
esp_cam_ctlr_spi_cam_t *ctlr = (esp_cam_ctlr_spi_cam_t *)spi_trans->user;
107107

108+
/**
109+
* Due to SPI slave does not support stop function,
110+
* we need to check if the controller is started,
111+
* if not started, we need to return immediately.
112+
*/
113+
if (ctlr->fsm != ESP_CAM_CTLR_SPI_CAM_FSM_STARTED) {
114+
return;
115+
}
116+
108117
if ((spi_trans->rx_buffer != ctlr->frame_buffer) || ctlr->bk_buffer_exposed) {
109118
if (!ctlr->auto_decode_dis) {
110119
spi_cam_msg_t msg;
@@ -206,12 +215,13 @@ static esp_err_t spi_cam_deinit_intf(esp_cam_ctlr_spi_cam_t *ctlr)
206215
* @param ctlr ESP CAM controller handle
207216
* @param src Source buffer pointer
208217
* @param dst Destination buffer pointer
218+
* @param decoded_size Decoded size pointer
209219
*
210220
* @return
211221
* - ESP_OK on success
212222
* - Others if failed
213223
*/
214-
static esp_err_t spi_cam_decode(esp_cam_ctlr_spi_cam_t *ctlr, uint8_t *src, uint8_t *dst)
224+
static esp_err_t spi_cam_decode(esp_cam_ctlr_spi_cam_t *ctlr, uint8_t *src, uint8_t *dst, uint32_t *decoded_size)
215225
{
216226
bool decode_check_dis = ctlr->decode_check_dis;
217227

@@ -236,6 +246,8 @@ static esp_err_t spi_cam_decode(esp_cam_ctlr_spi_cam_t *ctlr, uint8_t *src, uint
236246
dst += line_data_size;
237247
}
238248

249+
*decoded_size = ctlr->bf_size_in_bytes;
250+
239251
return ESP_OK;
240252
}
241253

@@ -257,20 +269,21 @@ static void spi_cam_task(void *arg)
257269
esp_err_t ret;
258270
uint8_t *decoded_buffer;
259271
uint8_t *rx_buffer = msg.recved_frame.buffer;
272+
uint32_t decoded_size;
260273

261274
if (rx_buffer == ctlr->frame_buffer) {
262-
ret = spi_cam_decode(ctlr, rx_buffer, ctlr->backup_buffer);
275+
ret = spi_cam_decode(ctlr, rx_buffer, ctlr->backup_buffer, &decoded_size);
263276
decoded_buffer = ctlr->backup_buffer;
264277
} else {
265-
ret = spi_cam_decode(ctlr, rx_buffer, rx_buffer);
278+
ret = spi_cam_decode(ctlr, rx_buffer, rx_buffer, &decoded_size);
266279
decoded_buffer = rx_buffer;
267280
}
268281

269282
if (ret == ESP_OK) {
270283
esp_cam_ctlr_trans_t trans = {0};
271284

272285
trans.buffer = decoded_buffer;
273-
trans.buflen = ctlr->bf_size_in_bytes;
286+
trans.buflen = decoded_size;
274287
trans.received_size = trans.buflen;
275288
if (ctlr->cbs.on_trans_finished) {
276289
ctlr->cbs.on_trans_finished(&(ctlr->base), &trans, ctlr->cbs_user_data);
@@ -368,17 +381,15 @@ static esp_err_t spi_cam_start(esp_cam_ctlr_handle_t handle)
368381
*/
369382
static esp_err_t spi_cam_stop(esp_cam_ctlr_handle_t handle)
370383
{
371-
esp_err_t ret;
372384
esp_cam_ctlr_spi_cam_t *ctlr = (esp_cam_ctlr_spi_cam_t *)handle;
373385
ESP_RETURN_ON_FALSE(ctlr, ESP_ERR_INVALID_ARG, TAG, "invalid argument: handle is null");
374386
ESP_RETURN_ON_FALSE(ctlr->fsm == ESP_CAM_CTLR_SPI_CAM_FSM_STARTED, ESP_ERR_INVALID_STATE, TAG, "processor isn't in started state");
375387

376-
ret = esp_cam_spi_slave_disable(ctlr->spi_port);
377-
if (ret == ESP_OK) {
378-
ctlr->fsm = ESP_CAM_CTLR_SPI_CAM_FSM_ENABLED;
379-
}
388+
/* SPI slave does not support stop function */
380389

381-
return ret;
390+
ctlr->fsm = ESP_CAM_CTLR_SPI_CAM_FSM_ENABLED;
391+
392+
return ESP_OK;
382393
}
383394

384395
/**
@@ -615,18 +626,19 @@ esp_err_t esp_cam_new_spi_ctlr(const esp_cam_ctlr_spi_config_t *config, esp_cam_
615626
* @param src_len Source buffer length
616627
* @param dst Destination buffer pointer
617628
* @param dst_len Destination buffer length
629+
* @param decoded_size Decoded size pointer
618630
*
619631
* @return
620632
* - ESP_OK on success
621633
* - Others if failed
622634
*/
623-
esp_err_t esp_cam_spi_decode_frame(esp_cam_ctlr_handle_t handle, uint8_t *src, uint32_t src_len, uint8_t *dst, uint32_t dst_len)
635+
esp_err_t esp_cam_spi_decode_frame(esp_cam_ctlr_handle_t handle, uint8_t *src, uint32_t src_len, uint8_t *dst, uint32_t dst_len, uint32_t *decoded_size)
624636
{
625637
esp_cam_ctlr_spi_cam_t *ctlr = (esp_cam_ctlr_spi_cam_t *)handle;
626638
ESP_RETURN_ON_FALSE(ctlr, ESP_ERR_INVALID_ARG, TAG, "invalid argument: handle is null");
627639
ESP_RETURN_ON_FALSE(ctlr->auto_decode_dis, ESP_ERR_INVALID_STATE, TAG, "auto decode is enabled");
628640
ESP_RETURN_ON_FALSE(src && dst, ESP_ERR_INVALID_ARG, TAG, "invalid argument: src or dst is null");
629641
ESP_RETURN_ON_FALSE(src_len == ctlr->fb_size_in_bytes && dst_len >= ctlr->bf_size_in_bytes, ESP_ERR_INVALID_ARG, TAG, "invalid argument: src_len or dst_len is invalid");
630642

631-
return spi_cam_decode(ctlr, src, dst);
643+
return spi_cam_decode(ctlr, src, dst, decoded_size);
632644
}

esp_cam_sensor/src/driver_spi/spi_slave.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ typedef struct {
9393
#ifdef CONFIG_PM_ENABLE
9494
esp_pm_lock_handle_t pm_lock;
9595
#endif
96+
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0)
97+
uint64_t gpio_reserve;
98+
#endif
9699
} spi_slave_t;
97100

98101
static spi_slave_t *spihost[SOC_SPI_PERIPH_NUM];
@@ -230,7 +233,7 @@ esp_err_t esp_cam_spi_slave_initialize(spi_host_device_t host, const spi_bus_con
230233

231234
err = spicommon_bus_initialize_io(host, bus_config, SPICOMMON_BUSFLAG_SLAVE | bus_config->flags, &spihost[host]->flags
232235
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0)
233-
, NULL
236+
, &spihost[host]->gpio_reserve
234237
#endif
235238
);
236239
if (err != ESP_OK) {
@@ -240,7 +243,7 @@ esp_err_t esp_cam_spi_slave_initialize(spi_host_device_t host, const spi_bus_con
240243
if (slave_config->spics_io_num >= 0) {
241244
spicommon_cs_initialize(host, slave_config->spics_io_num, 0, !bus_is_iomux(spihost[host])
242245
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0)
243-
, NULL
246+
, &spihost[host]->gpio_reserve
244247
#endif
245248
);
246249
// check and save where cs line really route through
@@ -362,7 +365,7 @@ esp_err_t esp_cam_spi_slave_free(spi_host_device_t host)
362365
}
363366
spicommon_bus_free_io_cfg(&spihost[host]->bus_config
364367
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0)
365-
, NULL
368+
, &spihost[host]->gpio_reserve
366369
#endif
367370
);
368371
esp_intr_free(spihost[host]->intr);

esp_video/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## Unreleased
2+
3+
- Add SPI video device and board-level configuration
4+
- Fix open function crashes after failing to initialize the video device
5+
16
## 1.0.0
27

38
- Add statistics region configuration to ISP pipeline controller

esp_video/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ if(CONFIG_ESP_VIDEO_ENABLE_DVP_VIDEO_DEVICE)
3030
list(APPEND srcs "src/device/esp_video_dvp_device.c")
3131
endif()
3232

33+
if(CONFIG_ESP_VIDEO_ENABLE_SPI_VIDEO_DEVICE)
34+
list(APPEND srcs "src/device/esp_video_spi_device.c")
35+
endif()
36+
3337
if(CONFIG_ESP_VIDEO_ENABLE_H264_VIDEO_DEVICE)
3438
list(APPEND srcs "src/device/esp_video_h264_device.c")
3539
endif()

esp_video/Kconfig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,14 @@ menu "Espressif Video Configuration"
5656
help
5757
Select this option, enable DVP based video device.
5858

59+
menuconfig ESP_VIDEO_ENABLE_SPI_VIDEO_DEVICE
60+
bool "Enable SPI based Video Device"
61+
depends on SOC_GPSPI_SUPPORTED
62+
select ESP_VIDEO_ENABLE_DATA_PREPROCESSING
63+
default n
64+
help
65+
Select this option, enable SPI based video device.
66+
5967
menuconfig ESP_VIDEO_ENABLE_HW_H264_VIDEO_DEVICE
6068
bool "Enable Hardware H.264 based Video Device"
6169
depends on IDF_TARGET_ESP32P4

esp_video/examples/capture_stream/main/capture_stream_main.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,14 @@ static esp_err_t camera_capture_stream(void)
229229
goto exit_0;
230230
}
231231

232-
frame_size += buf.bytesused;
232+
/**
233+
* If no error, the flags has V4L2_BUF_FLAG_DONE. If error, the flags has V4L2_BUF_FLAG_ERROR.
234+
* We need to skip these frames, but we also need queue the buffer.
235+
*/
236+
if (buf.flags & V4L2_BUF_FLAG_DONE) {
237+
frame_size += buf.bytesused;
238+
frame_count++;
239+
}
233240

234241
#if CONFIG_EXAMPLE_VIDEO_BUFFER_TYPE_USER
235242
buf.m.userptr = (unsigned long)buffer[buf.index];
@@ -240,8 +247,6 @@ static esp_err_t camera_capture_stream(void)
240247
ret = ESP_FAIL;
241248
goto exit_0;
242249
}
243-
244-
frame_count++;
245250
}
246251

247252
if (ioctl(fd, VIDIOC_STREAMOFF, &type) != 0) {
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CONFIG_ESP_VIDEO_ENABLE_SPI_VIDEO_DEVICE=y
2+
3+
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
4+
5+
CONFIG_SPIRAM=y
6+
7+
CONFIG_SPIRAM_SPEED_200M=y

esp_video/examples/common_components/example_video_common/Kconfig.projbuild

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ menu "Example Video Initialization Configuration"
3434
config EXAMPLE_ENABLE_DVP_CAM_SENSOR
3535
bool "DVP"
3636
depends on ESP_VIDEO_ENABLE_DVP_VIDEO_DEVICE
37+
38+
config EXAMPLE_ENABLE_SPI_CAM_SENSOR
39+
bool "SPI"
40+
depends on ESP_VIDEO_ENABLE_SPI_VIDEO_DEVICE
3741
endchoice
3842

3943
if EXAMPLE_ENABLE_MIPI_CSI_CAM_SENSOR
@@ -90,6 +94,45 @@ menu "Example Video Initialization Configuration"
9094
default 20000000
9195
endif
9296

97+
if EXAMPLE_ENABLE_SPI_CAM_SENSOR
98+
config EXAMPLE_SPI_SCCB_I2C_PORT
99+
int "SPI SCCB I2C Port Number"
100+
default 1
101+
range 0 1
102+
103+
config EXAMPLE_SPI_SCCB_I2C_FREQ
104+
int "SPI SCCB I2C Frequency"
105+
default 100000
106+
range 100000 400000
107+
help
108+
Increasing this value can reduce the initialization time of the camera sensor.
109+
Please refer to the relevant instructions for the camera sensor to adjust the value.
110+
111+
config EXAMPLE_SPI_CAM_SPI_PORT
112+
int "SPI Camera Sensor SPI Port Number"
113+
default 2
114+
115+
choice EXAMPLE_SPI_CAM_XCLK_RESOURCE
116+
prompt "SPI Camera Sensor Clock Resource"
117+
default EXAMPLE_SPI_CAM_XCLK_USE_LEDC if CAMERA_XCLK_USE_LEDC
118+
default EXAMPLE_SPI_CAM_XCLK_USE_CLOCK_ROUTER if CAMERA_XCLK_USE_ESP_CLOCK_ROUTER
119+
help
120+
Select SPI camera sensor clock resource.
121+
122+
config EXAMPLE_SPI_CAM_XCLK_USE_LEDC
123+
bool "LEDC"
124+
depends on CAMERA_XCLK_USE_LEDC
125+
126+
config EXAMPLE_SPI_CAM_XCLK_USE_CLOCK_ROUTER
127+
bool "Clock Router"
128+
depends on CAMERA_XCLK_USE_ESP_CLOCK_ROUTER
129+
endchoice
130+
131+
config EXAMPLE_SPI_CAM_XCLK_FREQ
132+
int "SPI XCLK Frequency"
133+
default 24000000
134+
endif
135+
93136
if EXAMPLE_SELECT_CUSTOMIZED_DEV_BOARD
94137
if EXAMPLE_ENABLE_MIPI_CSI_CAM_SENSOR
95138
config EXAMPLE_MIPI_CSI_SCCB_I2C_SCL_PIN
@@ -232,6 +275,48 @@ menu "Example Video Initialization Configuration"
232275
range 0 56
233276
default 47
234277
endif
278+
279+
if EXAMPLE_ENABLE_SPI_CAM_SENSOR
280+
config EXAMPLE_SPI_SCCB_I2C_SCL_PIN
281+
int "SPI SCCB I2C SCL Pin"
282+
default 8
283+
range -1 56
284+
285+
config EXAMPLE_SPI_SCCB_I2C_SDA_PIN
286+
int "SPI SCCB I2C SDA Pin"
287+
default 7
288+
range -1 56
289+
290+
config EXAMPLE_SPI_CAM_SENSOR_RESET_PIN
291+
int "SPI Camera Sensor Reset Pin"
292+
default -1
293+
range -1 56
294+
295+
config EXAMPLE_SPI_CAM_SENSOR_PWDN_PIN
296+
int "SPI Camera Sensor Power Down Pin"
297+
default -1
298+
range -1 56
299+
300+
config EXAMPLE_SPI_CAM_XCLK_PIN
301+
int "Output XCLK Pin for SPI Sensor"
302+
range 0 56
303+
default 20
304+
305+
config EXAMPLE_SPI_CAM_CS_PIN
306+
int "SPI Camera Sensor CS Pin"
307+
default 37
308+
range 0 56
309+
310+
config EXAMPLE_SPI_CAM_SCLK_PIN
311+
int "SPI Camera Sensor SCLK Pin"
312+
default 4
313+
range 0 56
314+
315+
config EXAMPLE_SPI_CAM_DATA0_IO_PIN
316+
int "SPI Camera Sensor Data0 I/O Pin"
317+
default 21
318+
range 0 56
319+
endif
235320
endif
236321

237322
config EXAMPLE_SCCB_I2C_INIT_BY_APP

0 commit comments

Comments
 (0)