Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 23 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,16 @@ project(embedDIP
DESCRIPTION "Portable embedded digital image processing library"
)

set(EMBEDDIP_TARGET_BOARD "" CACHE STRING "Target board (required): STM32F7, STM32H7S, ESP32, or HOST")
set_property(CACHE EMBEDDIP_TARGET_BOARD PROPERTY STRINGS "STM32F7" "STM32H7S" "ESP32" "HOST")
set(EMBEDDIP_TARGET_BOARD "" CACHE STRING "Target board (required): STM32F7, STM32H7S, STM32N6, ESP32, or HOST")
set_property(CACHE EMBEDDIP_TARGET_BOARD PROPERTY STRINGS "STM32F7" "STM32H7S" "STM32N6" "ESP32" "HOST")

set(EMBEDDIP_ARCH "" CACHE STRING "Architecture family (required): ARM, XTENSA, or HOST")
set_property(CACHE EMBEDDIP_ARCH PROPERTY STRINGS "ARM" "XTENSA" "HOST")

set(EMBEDDIP_CPU "" CACHE STRING "CPU variant (required): CORTEX_M7, LX6, LX7, NATIVE")
set_property(CACHE EMBEDDIP_CPU PROPERTY STRINGS "CORTEX_M7" "LX6" "LX7" "NATIVE")
set(EMBEDDIP_CPU "" CACHE STRING "CPU variant (required): CORTEX_M7, CORTEX_M55, LX6, LX7, NATIVE")
set_property(CACHE EMBEDDIP_CPU PROPERTY STRINGS "CORTEX_M7" "CORTEX_M55" "LX6" "LX7" "NATIVE")

set(EMBEDDIP_STM32CUBE_N6_ROOT "" CACHE PATH "Path to the STM32CubeN6 SDK root")
set(EMBEDDIP_STM32CUBE_H7RS_ROOT "" CACHE PATH "Path to the STM32CubeH7RS SDK root")

option(EMBEDDIP_ENABLE_IMAGE_PROCESSING "Enable image processing modules" ON)
Expand All @@ -32,15 +33,15 @@ option(EMBEDDIP_ENABLE_DISPLAY_OUTPUT "Enable display output interfaces" ON)
option(EMBEDDIP_BUILD_TESTS "Build CTest safety-net tests" OFF)

if(EMBEDDIP_TARGET_BOARD STREQUAL "")
message(FATAL_ERROR "EMBEDDIP_TARGET_BOARD is required. Supported values: STM32F7, STM32H7S, ESP32, HOST")
message(FATAL_ERROR "EMBEDDIP_TARGET_BOARD is required. Supported values: STM32F7, STM32H7S, STM32N6, ESP32, HOST")
endif()

if(EMBEDDIP_ARCH STREQUAL "")
message(FATAL_ERROR "EMBEDDIP_ARCH is required. Supported values: ARM, XTENSA, HOST")
endif()

if(EMBEDDIP_CPU STREQUAL "")
message(FATAL_ERROR "EMBEDDIP_CPU is required. Supported values: CORTEX_M7, LX6, LX7, NATIVE")
message(FATAL_ERROR "EMBEDDIP_CPU is required. Supported values: CORTEX_M7, CORTEX_M55, LX6, LX7, NATIVE")
endif()

# Explicit compatibility matrix between board, architecture family and CPU
Expand All @@ -57,6 +58,10 @@ elseif(EMBEDDIP_TARGET_BOARD STREQUAL "ESP32")
if(EMBEDDIP_ARCH STREQUAL "XTENSA" AND (EMBEDDIP_CPU STREQUAL "LX6" OR EMBEDDIP_CPU STREQUAL "LX7"))
set(_embeddip_pair_valid TRUE)
endif()
elseif(EMBEDDIP_TARGET_BOARD STREQUAL "STM32N6")
if(EMBEDDIP_ARCH STREQUAL "ARM" AND EMBEDDIP_CPU STREQUAL "CORTEX_M55")
set(_embeddip_pair_valid TRUE)
endif()
elseif(EMBEDDIP_TARGET_BOARD STREQUAL "HOST")
if(EMBEDDIP_ARCH STREQUAL "HOST" AND EMBEDDIP_CPU STREQUAL "NATIVE")
set(_embeddip_pair_valid TRUE)
Expand All @@ -66,7 +71,7 @@ endif()
if(NOT _embeddip_pair_valid)
message(FATAL_ERROR
"Invalid board/arch/cpu combination: ${EMBEDDIP_TARGET_BOARD} + ${EMBEDDIP_ARCH} + ${EMBEDDIP_CPU}. "
"Supported: STM32F7+ARM+CORTEX_M7, STM32H7S+ARM+CORTEX_M7, ESP32+XTENSA+LX6, ESP32+XTENSA+LX7, HOST+HOST+NATIVE"
"Supported: STM32F7+ARM+CORTEX_M7, STM32H7S+ARM+CORTEX_M7, STM32N6+ARM+CORTEX_M55, ESP32+XTENSA+LX6, ESP32+XTENSA+LX7, HOST+HOST+NATIVE"
)
endif()

Expand All @@ -83,6 +88,15 @@ set(CORE_SOURCES
core/image.h
)

set(RUNTIME_SOURCES
runtime/runtime.c
runtime/runtime.h
runtime/model_manifest.c
runtime/model_manifest.h
runtime/stedgeai_n6/backend.c
runtime/stedgeai_n6/backend.h
)

set(IMGPROC_SOURCES
# Main header (includes all sub-modules)
imgproc/pixel.h
Expand Down Expand Up @@ -184,6 +198,7 @@ include("${EMBEDDIP_ARCH_PROFILE_FILE}")
# === Create Library Target ===
add_library(embedDIP STATIC
${CORE_SOURCES}
${RUNTIME_SOURCES}
${IMGPROC_SOURCES}
${EMBEDDIP_BOARD_SOURCES}
${EMBEDDIP_ARCH_SOURCES}
Expand Down Expand Up @@ -295,6 +310,7 @@ install(FILES

install(DIRECTORY
core/
runtime/
imgproc/
device/
board/
Expand Down
27 changes: 27 additions & 0 deletions board/stm32n6/board_profile.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Board profile: STM32N6570-DK

if(NOT IS_DIRECTORY "${EMBEDDIP_STM32CUBE_N6_ROOT}")
message(FATAL_ERROR
"EMBEDDIP_STM32CUBE_N6_ROOT must name an existing STM32CubeN6 SDK directory: "
"'${EMBEDDIP_STM32CUBE_N6_ROOT}'")
endif()

set(EMBEDDIP_BOARD_SOURCES
${BOARD_COMMON_SOURCES}
board/stm32n6/board_stm32n6_memory.c
)

set(EMBEDDIP_DEVICE_SOURCES)

set(EMBEDDIP_BOARD_DEFINES
EMBED_DIP_BOARD_STM32N6=1
STM32N6xx
STM32N657xx
)

set(EMBEDDIP_BOARD_INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/board/stm32n6
${EMBEDDIP_STM32CUBE_N6_ROOT}/Drivers/CMSIS/Device/ST/STM32N6xx/Include
${EMBEDDIP_STM32CUBE_N6_ROOT}/Drivers/CMSIS/Core/Include
${EMBEDDIP_STM32CUBE_N6_ROOT}/Drivers/CMSIS/DSP/Include
)
197 changes: 197 additions & 0 deletions board/stm32n6/board_stm32n6_memory.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2025 EmbedDIP

#include "core/memory_manager.h"

#include <limits.h>
#include <stdalign.h>
#include <stdint.h>

#include <stm32n6xx.h>

#include <configs.h>

typedef struct {
uintptr_t start;
uintptr_t end;
uintptr_t cursor;
} n6_memory_range_t;

static n6_memory_range_t fast_sram;
static n6_memory_range_t dma_memory;
static n6_memory_range_t psram;
static int memory_initialized;

static void n6_reset_range(n6_memory_range_t *range, uint8_t *start, uint8_t *end)
{
range->start = (uintptr_t)start;
range->end = (uintptr_t)end;
range->cursor = range->start;
}

void memory_init(uintptr_t pool_start_addr)
{
(void)pool_start_addr;
n6_reset_range(&fast_sram, __embeddip_fast_sram_start__, __embeddip_fast_sram_end__);
n6_reset_range(&dma_memory, __embeddip_dma_start__, __embeddip_dma_end__);
n6_reset_range(&psram, __embeddip_psram_start__, __embeddip_psram_end__);
memory_initialized = 1;
}

static int n6_alignment_is_power_of_two(size_t alignment)
{
return alignment != 0u && (alignment & (alignment - 1u)) == 0u;
}

static n6_memory_range_t *n6_range_for_region(embeddip_memory_region_t region)
{
switch (region) {
case EMBEDDIP_MEMORY_REGION_DEFAULT:
case EMBEDDIP_MEMORY_REGION_FAST_SRAM:
return &fast_sram;
case EMBEDDIP_MEMORY_REGION_DMA:
return &dma_memory;
case EMBEDDIP_MEMORY_REGION_PSRAM:
return &psram;
case EMBEDDIP_MEMORY_REGION_EXTERNAL_FLASH:
default:
return NULL;
}
}

static embeddip_status_t n6_allocate_region(embeddip_memory_region_t region,
size_t size,
size_t alignment,
void **allocation)
{
n6_memory_range_t *range;
uintptr_t aligned_cursor;
uintptr_t alignment_mask;

if (allocation == NULL) {
return EMBEDDIP_ERROR_NULL_PTR;
}
*allocation = NULL;

if (!n6_alignment_is_power_of_two(alignment)) {
return EMBEDDIP_ERROR_INVALID_ARG;
}
if (size == 0u) {
return EMBEDDIP_ERROR_INVALID_SIZE;
}
if (region == EMBEDDIP_MEMORY_REGION_EXTERNAL_FLASH) {
return EMBEDDIP_ERROR_NOT_SUPPORTED;
}

range = n6_range_for_region(region);
if (range == NULL) {
return EMBEDDIP_ERROR_INVALID_ARG;
}
if (!memory_initialized) {
memory_init(0u);
range = n6_range_for_region(region);
}

alignment_mask = (uintptr_t)alignment - 1u;
if (range->end < range->start || range->cursor > UINTPTR_MAX - alignment_mask) {
return EMBEDDIP_ERROR_OUT_OF_MEMORY;
}
aligned_cursor = (range->cursor + alignment_mask) & ~alignment_mask;
if (aligned_cursor > range->end || size > range->end - aligned_cursor) {
return EMBEDDIP_ERROR_OUT_OF_MEMORY;
}

range->cursor = aligned_cursor + size;
*allocation = (void *)aligned_cursor;
return EMBEDDIP_OK;
}

void *embeddip_board_alloc_region(embeddip_memory_region_t region, size_t size, size_t alignment)
{
void *allocation;

if (n6_allocate_region(region, size, alignment, &allocation) != EMBEDDIP_OK) {
return NULL;
}
return allocation;
}

void *memory_alloc(size_t size)
{
return embeddip_board_alloc_region(EMBEDDIP_MEMORY_REGION_DEFAULT, size, alignof(max_align_t));
}

void memory_free(void *ptr)
{
(void)ptr;
}

void *memory_realloc(void *ptr, size_t new_size)
{
if (ptr == NULL) {
return memory_alloc(new_size);
}
return NULL;
}

static embeddip_status_t
n6_cache_span(const void *address, size_t size, uintptr_t *rounded_start, int32_t *rounded_size)
{
const uintptr_t line_mask = (uintptr_t)EMBEDDIP_N6_CACHE_LINE_BYTES - 1u;
uintptr_t start;
uintptr_t end;
uintptr_t rounded_end;
uintptr_t span;

if (address == NULL) {
return EMBEDDIP_ERROR_NULL_PTR;
}
if (size == 0u) {
return EMBEDDIP_ERROR_INVALID_SIZE;
}

start = (uintptr_t)address;
if (size > UINTPTR_MAX - start) {
return EMBEDDIP_ERROR_OVERFLOW;
}
end = start + size;
if (end > UINTPTR_MAX - line_mask) {
return EMBEDDIP_ERROR_OVERFLOW;
}

*rounded_start = start & ~line_mask;
rounded_end = (end + line_mask) & ~line_mask;
span = rounded_end - *rounded_start;
if (span > INT32_MAX) {
return EMBEDDIP_ERROR_OVERFLOW;
}

*rounded_size = (int32_t)span;
return EMBEDDIP_OK;
}

embeddip_status_t embeddip_board_cache_clean(const void *address, size_t size)
{
uintptr_t rounded_start;
int32_t rounded_size;
embeddip_status_t status = n6_cache_span(address, size, &rounded_start, &rounded_size);

if (status != EMBEDDIP_OK) {
return status;
}
SCB_CleanDCache_by_Addr((void *)rounded_start, rounded_size);
return EMBEDDIP_OK;
}

embeddip_status_t embeddip_board_cache_invalidate(const void *address, size_t size)
{
uintptr_t rounded_start;
int32_t rounded_size;
embeddip_status_t status = n6_cache_span(address, size, &rounded_start, &rounded_size);

if (status != EMBEDDIP_OK) {
return status;
}
SCB_InvalidateDCache_by_Addr((void *)rounded_start, rounded_size);
return EMBEDDIP_OK;
}
28 changes: 28 additions & 0 deletions board/stm32n6/configs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2025 EmbedDIP

#ifndef EMBEDDIP_STM32N6_CONFIGS_H
#define EMBEDDIP_STM32N6_CONFIGS_H

#include <stdint.h>

#define EMBEDDIP_N6_CACHE_LINE_BYTES 32u

#ifdef __cplusplus
extern "C" {
#endif

extern uint8_t __embeddip_fast_sram_start__[];
extern uint8_t __embeddip_fast_sram_end__[];
extern uint8_t __embeddip_dma_start__[];
extern uint8_t __embeddip_dma_end__[];
extern uint8_t __embeddip_psram_start__[];
extern uint8_t __embeddip_psram_end__[];
extern uint8_t __embeddip_xspi_flash_start__[];
extern uint8_t __embeddip_xspi_flash_end__[];

#ifdef __cplusplus
}
#endif

#endif
Loading
Loading