refactor(isp): read DMA input directly from flash

Avoid the PSRAM copy for unencrypted flash
This commit is contained in:
morris
2026-08-26 11:33:58 +08:00
committed by Gao Xu
parent 3e162786cb
commit 8163ee0de8
10 changed files with 77 additions and 52 deletions
@@ -1,7 +1,7 @@
idf_component_register(SRCS "isp_dma_main.c"
idf_component_register(SRCS "isp_dma_example_main.c"
PRIV_REQUIRES esp_driver_isp esp_mm esp_psram mbedtls
INCLUDE_DIRS ".")
target_add_binary_data(${COMPONENT_LIB}
"${CMAKE_CURRENT_LIST_DIR}/assets/sensor_240x280_bggr.raw"
BINARY RENAME_TO "sensor_raw")
BINARY RENAME_TO "sensor_raw" ALIGN 16)
@@ -7,13 +7,11 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "mbedtls/base64.h"
#include "esp_check.h"
#include "esp_cache.h"
#include "esp_heap_caps.h"
#include "driver/isp_dma.h"
#include "driver/isp_core.h"
@@ -22,20 +20,14 @@
#define EXAMPLE_WIDTH 240
#define EXAMPLE_HEIGHT 280
#define EXAMPLE_BASE64_CHUNK_LEN 384
#define EXAMPLE_BASE64_DELAY_MS 10
#define EXAMPLE_DMA_ALIGN 64
#define EXAMPLE_FRAME_COUNT 1
/* CMake embeds this RAW asset in mapped flash with 16-byte alignment. */
extern const uint8_t sensor_raw_start[] asm("_binary_sensor_raw_start");
extern const uint8_t sensor_raw_end[] asm("_binary_sensor_raw_end");
static void *s_alloc_dma_buffer(size_t size)
{
return heap_caps_aligned_calloc(EXAMPLE_DMA_ALIGN, 1, size,
MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA | MALLOC_CAP_8BIT);
}
static void s_configure_neutral_color(isp_proc_handle_t isp_proc)
static void example_configure_neutral_color(isp_proc_handle_t isp_proc)
{
esp_isp_color_config_t color_cfg = {
.color_contrast = { .integer = 1, .decimal = 0 },
@@ -48,21 +40,22 @@ static void s_configure_neutral_color(isp_proc_handle_t isp_proc)
ESP_ERROR_CHECK(esp_isp_color_enable(isp_proc));
}
static void s_print_base64_payload(const unsigned char *encoded, size_t encoded_len)
static void example_print_base64_payload(const unsigned char *encoded, size_t encoded_len)
{
printf("IMAGE_BASE64_BEGIN\n");
fflush(stdout);
size_t chunk_count = 0;
for (size_t offset = 0; offset < encoded_len; offset += EXAMPLE_BASE64_CHUNK_LEN) {
size_t chunk_len = encoded_len - offset;
if (chunk_len > EXAMPLE_BASE64_CHUNK_LEN) {
chunk_len = EXAMPLE_BASE64_CHUNK_LEN;
}
printf("IMAGE_BASE64 %.*s\n", (int)chunk_len, (const char *)&encoded[offset]);
fflush(stdout);
vTaskDelay(pdMS_TO_TICKS(EXAMPLE_BASE64_DELAY_MS));
if ((++chunk_count % 16) == 0) {
/* Let the test host drain the UART without delaying every chunk. */
vTaskDelay(1);
}
}
printf("IMAGE_BASE64_END\n");
fflush(stdout);
}
void app_main(void)
@@ -87,15 +80,15 @@ void app_main(void)
};
ESP_ERROR_CHECK(esp_isp_new_processor(&isp_cfg, &isp_proc));
ESP_ERROR_CHECK(esp_isp_enable(isp_proc));
s_configure_neutral_color(isp_proc);
example_configure_neutral_color(isp_proc);
uint8_t *isp_in_buf = s_alloc_dma_buffer(in_size);
uint8_t *isp_out_buf = s_alloc_dma_buffer(out_size);
assert(isp_in_buf && isp_out_buf);
/* ISP writes this RGB frame through DMA, so PSRAM must be DMA-capable. */
uint8_t *isp_out_buf = heap_caps_aligned_calloc(EXAMPLE_DMA_ALIGN, 1, out_size,
MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA | MALLOC_CAP_8BIT);
assert(isp_out_buf);
size_t embedded_raw_size = sensor_raw_end - sensor_raw_start;
assert(embedded_raw_size == in_size);
memcpy(isp_in_buf, sensor_raw_start, embedded_raw_size);
size_t encoded_len = 0;
int ret = mbedtls_base64_encode(NULL, 0, &encoded_len, isp_out_buf, out_size);
@@ -105,24 +98,25 @@ void app_main(void)
printf("Feeding %d frames through ISP DMA input...\n", EXAMPLE_FRAME_COUNT);
for (int frame = 0; frame < EXAMPLE_FRAME_COUNT; frame++) {
ESP_ERROR_CHECK(esp_cache_msync(isp_in_buf, in_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
ESP_ERROR_CHECK(esp_isp_dma_process_frame(isp_proc, isp_out_buf, isp_in_buf, 1000));
ESP_ERROR_CHECK(esp_cache_msync(isp_out_buf, out_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C));
/*
* The RAW image is immutable mapped flash. Its aligned address can be
* read by DMA directly, so no PSRAM copy is needed.
*/
ESP_ERROR_CHECK(esp_isp_dma_process_frame(isp_proc, isp_out_buf, sensor_raw_start, 1000));
size_t out_len = 0;
ESP_ERROR_CHECK(mbedtls_base64_encode(encoded, encoded_len + 1, &out_len, isp_out_buf, out_size) == 0 ? ESP_OK : ESP_FAIL);
printf("IMAGE_META frame=%d width=%u height=%u format=BGR24 encoding=base64\n",
frame, (unsigned)h_res, (unsigned)v_res);
s_print_base64_payload(encoded, out_len);
example_print_base64_payload(encoded, out_len);
printf("Frame %d done\n", frame);
}
printf("ISP DMA visual demo done.\n");
free(encoded);
ESP_ERROR_CHECK(esp_isp_color_disable(isp_proc));
ESP_ERROR_CHECK(esp_isp_disable(isp_proc));
ESP_ERROR_CHECK(esp_isp_del_processor(isp_proc));
heap_caps_free(isp_in_buf);
heap_caps_free(isp_out_buf);
free(encoded);
free(isp_out_buf);
}