ESP32-P4 Camera App: esp_cam_ctlr_receive() hangs

michalk
Posts: 24
Joined: Wed Mar 24, 2021 7:09 pm

ESP32-P4 Camera App: esp_cam_ctlr_receive() hangs

Postby michalk » Mon Jun 23, 2025 10:05 pm

I have an ESP32-P4-Nano from Waveshare, OV5647, ESP-IDF v5.5.0. I have a modified mipi_isp_dsi_main.c app that I've removed all of the display parts from. I'm just trying to acquire the frame buffers at the moment, and not do anything with them. The first call to esp_cam_ctlr_receive() passes, but the second call hangs. I don't understand how the callbacks are supposed to handle the frames, and suspect something there is the issue.

Code: Select all

/*
 * SPDX-FileCopyrightText: 2024-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_lcd_mipi_dsi.h"
#include "esp_lcd_panel_ops.h"
#include "esp_ldo_regulator.h"
#include "esp_cache.h"
#include "driver/i2c_master.h"
#include "driver/isp.h"
#include "esp_cam_ctlr_csi.h"
#include "esp_cam_ctlr.h"
// #include "example_dsi_init.h"
// #include "example_dsi_init_config.h"
#include "example_sensor_init.h"
#include "example_config.h"

#include "hal/cache_hal.h"
#include "hal/cache_ll.h"

static const char *TAG = "mipi_isp_dsi";

#define CAM_HRES 800
#define CAM_VRES 640
#define CAM_BYTES_PER_PIXEL 1  // RAW8 format

static uint32_t finished_trans_counter = 0;

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);

void app_main(void)
{
    ESP_LOGI(TAG, "App started");
    esp_err_t ret = ESP_FAIL;
    esp_ldo_channel_handle_t ldo_mipi_phy = NULL;
    esp_ldo_channel_config_t ldo_mipi_phy_config = {
        .chan_id = CONFIG_EXAMPLE_USED_LDO_CHAN_ID,
        .voltage_mv = CONFIG_EXAMPLE_USED_LDO_VOLTAGE_MV,
    };
    ESP_ERROR_CHECK(esp_ldo_acquire_channel(&ldo_mipi_phy_config, &ldo_mipi_phy));

    size_t stride = (CAM_HRES * CAM_BYTES_PER_PIXEL + 63) & ~63;
    size_t frame_buffer_size = stride * CAM_VRES;

    // allocate frame buffer from PSRAM
    uint32_t cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA);
    // DMA doesn't have requirement on the buffer alignment, but the cache does
    uint32_t alignment = cache_line_size;
    void *frame_buffer = heap_caps_aligned_calloc(alignment, 1, frame_buffer_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
    // void *frame_buffer = heap_caps_aligned_alloc(alignment,frame_buffer_size,MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
    if (frame_buffer == NULL) {
        ESP_LOGE(TAG, "Frame buffer allocation failed");
        return;
    }

    ESP_LOGD(TAG, "CONFIG_EXAMPLE_MIPI_CSI_DISP_HRES: %d, CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES: %d, bits per pixel: %d", CONFIG_EXAMPLE_MIPI_CSI_DISP_HRES, CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES, EXAMPLE_RGB565_BITS_PER_PIXEL);
    ESP_LOGD(TAG, "frame_buffer_size: %zu", frame_buffer_size);
    ESP_LOGD(TAG, "frame_buffer: %p", frame_buffer);

    ESP_LOGI(TAG, "Allocated frame buffer: %zu bytes (stride: %zu)", frame_buffer_size, stride);
    ESP_LOGI(TAG, "Resolution: %dx%d (RAW8)", CAM_HRES, CAM_VRES);
    ESP_LOGI(TAG, "Buffer address: %p", frame_buffer);

    esp_cam_ctlr_trans_t new_trans = {
        .buffer = frame_buffer,
        .buflen = frame_buffer_size,
    };

    //--------Camera Sensor and SCCB Init-----------//

    // i2c_master_bus_handle_t i2c_bus_handle = NULL;
    example_sensor_handle_t sensor_handle = {
        .sccb_handle = NULL,
        .i2c_bus_handle = NULL,
    };
    example_sensor_config_t cam_sensor_config = {
        .i2c_port_num = I2C_NUM_0,
        .i2c_sda_io_num = EXAMPLE_MIPI_CSI_CAM_SCCB_SDA_IO,
        .i2c_scl_io_num = EXAMPLE_MIPI_CSI_CAM_SCCB_SCL_IO,
        .port = ESP_CAM_SENSOR_MIPI_CSI,
        .format_name = EXAMPLE_CAM_FORMAT,
    };
    example_sensor_init(&cam_sensor_config, &sensor_handle);

    //---------------CSI Init------------------//
    esp_cam_ctlr_csi_config_t csi_config = {
        .ctlr_id = 0,
        .h_res = CONFIG_EXAMPLE_MIPI_CSI_DISP_HRES,
        .v_res = CONFIG_EXAMPLE_MIPI_CSI_DISP_VRES,
        .lane_bit_rate_mbps = EXAMPLE_MIPI_CSI_LANE_BITRATE_MBPS,
        .input_data_color_type = CAM_CTLR_COLOR_RAW8,
        // .output_data_color_type = CAM_CTLR_COLOR_RGB565,
        .output_data_color_type = CAM_CTLR_COLOR_RAW8,
        .data_lane_num = 2,
        .byte_swap_en = false,
        .queue_items = 1,
    };
    esp_cam_ctlr_handle_t cam_handle = NULL;
    ret = esp_cam_new_csi_ctlr(&csi_config, &cam_handle);
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "csi init fail[%d]", ret);
        return;
    }

    esp_cam_ctlr_evt_cbs_t cbs = {
        .on_get_new_trans = s_camera_get_new_vb,
        .on_trans_finished = s_camera_get_finished_trans,
    };
    if (esp_cam_ctlr_register_event_callbacks(cam_handle, &cbs, &new_trans) != ESP_OK) {
        ESP_LOGE(TAG, "ops register fail");
        return;
    }

    ESP_ERROR_CHECK(esp_cam_ctlr_enable(cam_handle));

    //---------------ISP Init------------------//
    isp_proc_handle_t isp_proc = NULL;
    esp_isp_processor_cfg_t isp_config = {
        .clk_hz = 80 * 1000 * 1000,
        .input_data_source = ISP_INPUT_DATA_SOURCE_CSI,
        .input_data_color_type = ISP_COLOR_RAW8,
        // .output_data_color_type = ISP_COLOR_RGB565,
        .output_data_color_type = ISP_COLOR_RAW8,
        .has_line_start_packet = false,
        .has_line_end_packet = false,
        .h_res = CONFIG_EXAMPLE_MIPI_CSI_DISP_HRES,
        .v_res = CONFIG_EXAMPLE_MIPI_CSI_DISP_VRES,
    };
    ESP_ERROR_CHECK(esp_isp_new_processor(&isp_config, &isp_proc));
    ESP_ERROR_CHECK(esp_isp_enable(isp_proc));

    //---------------DPI Reset------------------//
    // example_dpi_panel_reset(mipi_dpi_panel);

    //init to all white
    memset(frame_buffer, 0xFF, frame_buffer_size);
    esp_cache_msync((void *)frame_buffer, frame_buffer_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M);

    if (esp_cam_ctlr_start(cam_handle) != ESP_OK) {
        ESP_LOGE(TAG, "Driver start fail");
        return;
    }

    finished_trans_counter = 0;
    while (1) {
        ESP_LOGI(TAG, "1");
        // while(finished_trans_counter == 0) {
        //     ESP_LOGI(TAG, "3");
        //     vTaskDelay(pdMS_TO_TICKS(1));
        //     ESP_LOGI(TAG, "4");
        // }
        // Reset counter BEFORE next receive
        ESP_LOGI(TAG, "5");
        finished_trans_counter = 0;
        ESP_ERROR_CHECK(esp_cam_ctlr_receive(cam_handle, &new_trans, ESP_CAM_CTLR_MAX_DELAY));
        // ESP_ERROR_CHECK(esp_cam_ctlr_receive(cam_handle, &new_trans, 10000));
        ESP_LOGI(TAG, "6");
    }
}

static bool IRAM_ATTR s_camera_get_new_vb(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data)
{
    // ESP_EARLY_LOGI(TAG, "A1");
    esp_cam_ctlr_trans_t new_trans = *(esp_cam_ctlr_trans_t *)user_data;
    trans->buffer = new_trans.buffer;
    trans->buflen = new_trans.buflen;
    // esp_rom_printf("s_camera_get_finished_trans\n");
    return false;
}

static bool IRAM_ATTR s_camera_get_finished_trans(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data)
{
    finished_trans_counter++; // CRITICAL: Signal completion
    // ESP_EARLY_LOGI(TAG, "B1");
    return false;
}

Code: Select all

I (25) boot: ESP-IDF v5.5-beta1-18-g4c3d086c13 2nd stage bootloader
I (26) boot: compile time Jun 23 2025 15:39:27
I (26) boot: Multicore bootloader
I (29) boot: chip revision: v1.0
I (30) boot: efuse block revision: v0.3
I (34) boot.esp32p4: SPI Speed      : 80MHz
I (38) boot.esp32p4: SPI Mode       : DIO
I (41) boot.esp32p4: SPI Flash Size : 2MB
I (45) boot: Enabling RNG early entropy source...
I (50) boot: Partition Table:
I (52) boot: ## Label            Usage          Type ST Offset   Length
I (59) boot:  0 nvs              WiFi data        01 02 00009000 00006000
I (65) boot:  1 phy_init         RF data          01 01 0000f000 00001000
I (72) boot:  2 factory          factory app      00 00 00010000 00100000
I (79) boot: End of partition table
I (82) esp_image: segment 0: paddr=00010020 vaddr=40030020 size=0f5bch ( 62908) map
I (101) esp_image: segment 1: paddr=0001f5e4 vaddr=30100000 size=00068h (   104) load
I (102) esp_image: segment 2: paddr=0001f654 vaddr=4ff00000 size=009c4h (  2500) load
I (106) esp_image: segment 3: paddr=00020020 vaddr=40000020 size=2044ch (132172) map
I (135) esp_image: segment 4: paddr=00040474 vaddr=4ff009c4 size=10908h ( 67848) load
I (150) esp_image: segment 5: paddr=00050d84 vaddr=4ff11300 size=027f8h ( 10232) load
I (157) boot: Loaded app from partition at offset 0x10000
I (158) boot: Disabling RNG early entropy source...
I (168) hex_psram: vendor id    : 0x0d (AP)
I (168) hex_psram: Latency      : 0x01 (Fixed)
I (168) hex_psram: DriveStr.    : 0x00 (25 Ohm)
I (169) hex_psram: dev id       : 0x03 (generation 4)
I (174) hex_psram: density      : 0x07 (256 Mbit)
I (178) hex_psram: good-die     : 0x06 (Pass)
I (182) hex_psram: SRF          : 0x02 (Slow Refresh)
I (187) hex_psram: BurstType    : 0x00 ( Wrap)
I (191) hex_psram: BurstLen     : 0x03 (2048 Byte)
I (196) hex_psram: BitMode      : 0x01 (X16 Mode)
I (200) hex_psram: Readlatency  : 0x04 (14 cycles@Fixed)
I (205) hex_psram: DriveStrength: 0x00 (1/1)
I (209) MSPI DQS: tuning success, best phase id is 0
I (387) MSPI DQS: tuning success, best delayline id is 17
I (387) esp_psram: Found 32MB PSRAM device
I (387) esp_psram: Speed: 200MHz
I (388) hex_psram: psram CS IO is dedicated
I (391) cpu_start: Multicore app
I (1345) esp_psram: SPI SRAM memory test OK
I (1355) cpu_start: Pro cpu start user code
I (1355) cpu_start: cpu freq: 360000000 Hz
I (1355) app_init: Application information:
I (1355) app_init: Project name:     bkm5
I (1359) app_init: App version:      1
I (1363) app_init: Compile time:     Jun 23 2025 15:39:25
I (1368) app_init: ELF file SHA256:  6eb98961a...
I (1372) app_init: ESP-IDF:          v5.5-beta1-18-g4c3d086c13
I (1378) efuse_init: Min chip rev:     v0.1
I (1382) efuse_init: Max chip rev:     v1.99 
I (1386) efuse_init: Chip rev:         v1.0
I (1390) heap_init: Initializing. RAM available for dynamic allocation:
I (1396) heap_init: At 4FF152B0 len 00025D10 (151 KiB): RAM
I (1401) heap_init: At 4FF3AFC0 len 00004BF0 (18 KiB): RAM
I (1406) heap_init: At 4FF40000 len 00060000 (384 KiB): RAM
I (1412) heap_init: At 50108080 len 00007F80 (31 KiB): RTCRAM
I (1417) heap_init: At 30100068 len 00001F98 (7 KiB): TCM
I (1423) esp_psram: Adding pool of 32768K of PSRAM memory to heap allocator
I (1430) spi_flash: detected chip: gd
I (1432) spi_flash: flash io: dio
W (1435) spi_flash: Detected size(16384k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
I (1448) main_task: Started on CPU0
I (1458) esp_psram: Reserving pool of 32K of internal memory for DMA/internal allocations
I (1458) main_task: Calling app_main()
I (1458) mipi_isp_dsi: App started
I (1468) mipi_isp_dsi: Allocated frame buffer: 532480 bytes (stride: 832)
I (1468) mipi_isp_dsi: Resolution: 800x640 (RAW8)
I (1478) mipi_isp_dsi: Buffer address: 0x48000a40
I (1478) ov5647: Detected Camera sensor PID=0x5647
I (1488) sensor_init: fmt[0].name:MIPI_2lane_24Minput_RAW8_800x1280_50fps
I (1488) sensor_init: fmt[1].name:MIPI_2lane_24Minput_RAW8_800x640_50fps
I (1498) sensor_init: fmt[2].name:MIPI_2lane_24Minput_RAW8_800x800_50fps
I (1508) sensor_init: fmt[3].name:MIPI_2lane_24Minput_RAW10_1920x1080_30fps
I (1508) sensor_init: fmt[4].name:MIPI_2lane_24Minput_RAW10_1280x960_binning_45fps
I (1568) sensor_init: Format in use:MIPI_2lane_24Minput_RAW8_800x640_50fps
I (1578) mipi_isp_dsi: 1
I (1578) mipi_isp_dsi: 5
I (1578) mipi_isp_dsi: 6
I (1578) mipi_isp_dsi: 1
I (1578) mipi_isp_dsi: 5

HaqqScripter
Posts: 6
Joined: Fri May 16, 2025 10:00 am

Re: ESP32-P4 Camera App: esp_cam_ctlr_receive() hangs

Postby HaqqScripter » Wed Jul 02, 2025 12:20 pm

I got similar issues as you, and had the same development board as well. But so far I tackled everything on the values based on the API reference docs, and no luck, it seems it is still queueing the frame buffer based on the queue items, and it doesn't receive the frame buffer in time, in my understanding.

I even tried with 1080p@30fps RAW10 format, with varied MIPI-CSI lane rate, and that didn't work out also, it halts.
Last edited by HaqqScripter on Wed Jul 02, 2025 12:29 pm, edited 1 time in total.

michalk
Posts: 24
Joined: Wed Mar 24, 2021 7:09 pm

Re: ESP32-P4 Camera App: esp_cam_ctlr_receive() hangs

Postby michalk » Fri Jul 11, 2025 7:17 pm

I gave up, and implemented a DVP camera solution, and am now revisiting this. I have made the simplest example I think allowed, and still get the same results:

Code: Select all

/*
 * SPDX-FileCopyrightText: 2024-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_lcd_mipi_dsi.h"
#include "esp_lcd_panel_ops.h"
#include "esp_ldo_regulator.h"
#include "esp_cache.h"
#include "driver/i2c_master.h"
#include "driver/isp.h"
#include "esp_cam_ctlr_csi.h"
#include "esp_cam_ctlr.h"
#include "example_sensor_init.h"
#include "example_config.h"

static const char *TAG = "mipi_isp_dsi";
void *frame_buffer;

static bool IRAM_ATTR s_camera_get_new_vb(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data){
    esp_cam_ctlr_trans_t new_trans = *(esp_cam_ctlr_trans_t *)user_data;
    trans->buffer = new_trans.buffer;
    trans->buflen = new_trans.buflen;
    return false;
}
static bool IRAM_ATTR s_camera_get_finished_trans(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data){
    return false;
}
void app_main(void)
{
    esp_cam_ctlr_handle_t handle = NULL;
    esp_cam_ctlr_csi_config_t csi_config = {
        .ctlr_id = 0,
        .h_res = CONFIG_EXAMPLE_MIPI_CSI_DISP_HRES,
        .v_res = CONFIG_EXAMPLE_MIPI_CSI_DISP_VRES,
        .lane_bit_rate_mbps = EXAMPLE_MIPI_CSI_LANE_BITRATE_MBPS,
        .input_data_color_type = CAM_CTLR_COLOR_RAW8,
        .output_data_color_type = CAM_CTLR_COLOR_RGB565,
        .data_lane_num = 2,
        .byte_swap_en = false,
        .queue_items = 1,
    };
    esp_cam_ctlr_evt_cbs_t cbs = {
        .on_get_new_trans = s_camera_get_new_vb,
        .on_trans_finished = s_camera_get_finished_trans,
    };
    size_t frame_buffer_size = CONFIG_EXAMPLE_MIPI_CSI_DISP_HRES * CONFIG_EXAMPLE_MIPI_CSI_DISP_VRES * EXAMPLE_RGB565_BITS_PER_PIXEL / 8;
    frame_buffer = (uint8_t *)malloc(frame_buffer_size);
    if (frame_buffer == NULL) {
        ESP_LOGE(TAG, "Error allocating frame buffer");
    }
    esp_cam_ctlr_trans_t new_trans = {
        .buffer = frame_buffer,
        .buflen = frame_buffer_size,
    };
    ESP_ERROR_CHECK(esp_cam_new_csi_ctlr(&csi_config, &handle));
    ESP_ERROR_CHECK(esp_cam_ctlr_register_event_callbacks(handle, &cbs, &new_trans));
    ESP_ERROR_CHECK(esp_cam_ctlr_enable(handle));
    ESP_ERROR_CHECK(esp_cam_ctlr_start(handle));
    
    ESP_ERROR_CHECK(esp_cam_ctlr_receive(handle, &new_trans, ESP_CAM_CTLR_MAX_DELAY));ESP_LOGI("1", "");vTaskDelay(100 / portTICK_PERIOD_MS);
    // This never executes
    ESP_ERROR_CHECK(esp_cam_ctlr_receive(handle, &new_trans, ESP_CAM_CTLR_MAX_DELAY));ESP_LOGI("2", "");vTaskDelay(100 / portTICK_PERIOD_MS);
}

warwound
Posts: 7
Joined: Fri Aug 23, 2019 9:06 am

Re: ESP32-P4 Camera App: esp_cam_ctlr_receive() hangs

Postby warwound » Sat Jul 19, 2025 5:29 pm

I came here searching for *exactly this*...
I'd removed all the dsi display code from the camera_dsi example and found that the esp_cam_ctlr_receive() hangs when called a second time.

Meanwhile I've had much better results connecting my CSI camera and ESP32-P4 using the esp_video component:
https://github.com/espressif/esp-video- ... deo_server
With some easy tweaks that example works very well and reliably for me.

Gerard
Posts: 7
Joined: Mon Sep 15, 2025 12:53 pm

Re: ESP32-P4 Camera App: esp_cam_ctlr_receive() hangs

Postby Gerard » Mon Sep 15, 2025 3:07 pm

I came here searching for *exactly this*...
I'd removed all the dsi display code from the camera_dsi example and found that the esp_cam_ctlr_receive() hangs when called a second time.

Meanwhile I've had much better results connecting my CSI camera and ESP32-P4 using the esp_video component:
https://github.com/espressif/esp-video- ... deo_server
With some easy tweaks that example works very well and reliably for me.
Running into exactly the same trouble. How did you allocate memory for the frame buffer(s)? I thought that that memory had to be SPIRAM and DMA capable, but my esp32-p4-nano has zero such memory available.

So I'd love to try what you did, but how does one turn simple_video_server into an esp-idf project?

WangYX
Espressif staff
Espressif staff
Posts: 102
Joined: Mon Jun 28, 2021 12:48 pm

Re: ESP32-P4 Camera App: esp_cam_ctlr_receive() hangs

Postby WangYX » Thu Sep 25, 2025 11:46 am

Using the esp-video component will make it easier to capture image data from the camera sensor. There are some examples here. If an LCD is a must, you can try using example video_lcd_display.

Gerard
Posts: 7
Joined: Mon Sep 15, 2025 12:53 pm

Re: ESP32-P4 Camera App: esp_cam_ctlr_receive() hangs

Postby Gerard » Mon Sep 29, 2025 11:12 am

If an LCD is a must, you can try using example video_lcd_display.
On the contrary, @WangYX, people here were trying to use esp_cam_ctlr_receive without LCD. Is the esp_cam_ctlr_receive function obsolete?

I love the documentation: camera_driver.rst:Now you can call :cpp:func:`esp_cam_ctlr_receive` to receive from a camera sensor or something else. My imagination fails me, where from would esp_cam_ctlr_receive also be able to receive, as a camera sensor seems to be too much trouble?

WangYX
Espressif staff
Espressif staff
Posts: 102
Joined: Mon Jun 28, 2021 12:48 pm

Re: ESP32-P4 Camera App: esp_cam_ctlr_receive() hangs

Postby WangYX » Thu Oct 09, 2025 11:58 am

The esp_cam_ctlr_receive function is always available. However, as a passive receiver, the ESP32 requires certain parameters configured based on the characteristics of the transmitting device (i.e., the camera sensor) to function properly. This is precisely what the esp-video component provides: users can receive image data without having to understand extensive camera sensor information. While obtaining technical support from camera sensor manufacturers can be challenging, esp-video strives to provide the most convenient development environment.

dmrsim
Posts: 25
Joined: Sat Sep 03, 2022 4:52 pm
Location: Italy

Re: ESP32-P4 Camera App: esp_cam_ctlr_receive() hangs

Postby dmrsim » Wed Dec 10, 2025 10:55 am

Hello,
do you have resolve your problems?
I have the same issue, I removed all the display part from the example mipi_isp_dsi_main.c but it seems that esp_cam_ctlr_receive is called only one time and then it remains blocked.
What could be the problem?
I'm using esp-idf 5.5.1

Thank you!

Simeon

javaisrubbish
Posts: 6
Joined: Tue Mar 28, 2023 6:19 am

Re: ESP32-P4 Camera App: esp_cam_ctlr_receive() hangs

Postby javaisrubbish » Sun Feb 01, 2026 12:53 pm

I encountered almost the same problem. Is there any partner who has already solved it?

After tracking the code, it was found that the DMA did not trigger the callback

Who is online

Users browsing this forum: Baidu [Spider], Bing [Bot], PetalBot, Qwantbot and 10 guests