Загрузка данных


#include <zephyr/kernel.h>
#include <zephyr/sys/sys_heap.h>
#include <zephyr/logging/log.h>
#include <zephyr/linker/linker-defs.h> // Важно для макросов секций
#include <stdlib.h>

LOG_MODULE_REGISTER(ocram2_mem, CONFIG_LOG_DEFAULT_LEVEL);

#define OCRAM2_POOL_SIZE (512 * 1024)
#define OCRAM2_START_ADDR 0x20200000

/* 
 * Размещаем массив в секции региона OCRAM2. 
 * В Zephyr секции, созданные из DTS, называются по шаблону: _<ИМЯ_РЕГИОНА>_SECTION
 * Линкер автоматически обнулит этот буфер при старте, так как он попадет в BSS этого региона.
 */
static __attribute__((section("._OCRAM2_SECTION.bss"))) 
    uint8_t ocram2_heap_mem[OCRAM2_POOL_SIZE];

static struct sys_heap ocram2_heap;
static bool ocram2_ready = false;

/* Вспомогательная функция для логирования */
static void log_ocram2_stats(void)
{
#if defined(CONFIG_SYS_HEAP_RUNTIME_STATS)
    struct sys_heap_runtime_stats stats;
    if (sys_heap_runtime_stats_get(&ocram2_heap, &stats) == 0) {
        LOG_INF("[OCRAM2] Занято: %zu из %zu байт (Свободно: %zu)", 
                stats.allocated_bytes, 
                OCRAM2_POOL_SIZE, 
                OCRAM2_POOL_SIZE - stats.allocated_bytes);
    }
#endif
}

void ocram2_heap_init(void)
{
    /* Так как мы объявили массив вручную, его нужно явно инициализировать в sys_heap */
    sys_heap_init(&ocram2_heap, ocram2_heap_mem, OCRAM2_POOL_SIZE);
    ocram2_ready = true;
    
    LOG_INF("OCRAM2 heap initialized at %p. Size: %d KB", 
            (void*)ocram2_heap_mem, OCRAM2_POOL_SIZE / 1024);
}

void *ocram2_malloc_fallback(size_t size)
{
    void *ptr = NULL;

    if (ocram2_ready) {
        ptr = sys_heap_alloc(&ocram2_heap, size);
    }

    if (ptr != NULL) {
        LOG_INF("Allocated %zu bytes from OCRAM2 at %p", size, ptr);
        log_ocram2_stats();
        return ptr;
    }

    /* Fallback */
    ptr = malloc(size);
    if (ptr != NULL) {
        LOG_WRN("OCRAM2 full! Fallback: allocated %zu bytes from System Heap at %p", size, ptr);
    } else {
        LOG_ERR("Out of memory! Failed to allocate %zu bytes", size);
    }

    return ptr;
}

void ocram2_free_fallback(void *ptr)
{
    if (ptr == NULL) {
        return;
    }

    uintptr_t addr = (uintptr_t)ptr;
    uintptr_t start = OCRAM2_START_ADDR;
    uintptr_t end = start + OCRAM2_POOL_SIZE;

    if (addr >= start && addr < end) {
        LOG_INF("Freeing pointer %p from OCRAM2", ptr);
        sys_heap_free(&ocram2_heap, ptr);
        log_ocram2_stats();
    } else {
        LOG_WRN("Freeing pointer %p from System Heap", ptr);
        free(ptr);
    }
}