poniedziałek, 8 czerwca 2026

STM32H7 - Umieszczenie buforu w wybranej pamięci

W tym poście chciałbym opisać w jaki sposób określić w jakiej pamięci chcemy przechowywać które dane. Konkretnie zajmę się bufor dla MBEDTLS Heap.


MBEDTLS wykonuje dużo alokacji podczas obsługi TLS oraz HTTPS jak certyfikaty, kontekst sesji, bufory kryptograficzne itp itd. Wraz z wykorzystaniem flagi MBEDTLS_MEMORY_BUFFER_ALLOC_C można, zamiast standardowego malloc() wskazać własny statyczny bufor, który umieścimy w wybranej pamięci. 

W moim układzie (STM32H725) pamięć podzielona jest na następujące części:

  1. ITCMRAM  0x00000000  64K
  2. DTCMRAM  0x20000000  128K
  3. FLASH    0x08000000  1024K
  4. RAM_D1   0x24000000  320K
  5. RAM_D2   0x30000000  32K
  6. RAM_D3   0x38000000  16K

Bufor przeniesiemy do pamięci DTCMRAM. Wydaje się ona dobrym miejscem na tego typu bufory. Jest szybka i dostępna bezpośrednio dla CPU. Nie używałbym jej jednak np. do ETH DMA czy SPI DMA. Je lepiej trzymać w RAM.

Całość pamięci w projekcie podzielona jest mniej więcej tak:

FLASH - kod programu, zmienne const, tablica vektorów. 
RAM_D1 - .data, .bss, heap, stack. 
DTCMRAM - MBED TLS Heap. 
RAM_D2 - LwIP, Ethernet, DMA UART

Definiujemy tablicę:

  1. #define MBEDTLS_HEAP_SIZE (120U * 1024U)
  2.  
  3. static unsigned char mbedtls_heap[MBEDTLS_HEAP_SIZE]
  4.     __attribute__((section(".mbedtls_heap"), aligned(8)));

Funkcję inicjalizująca dane:

static uint8_t mbedtls_heap_initialized = 0;


void MbedTLS_Heap_Init(void)

{

if (mbedtls_heap_initialized == 0U) {

mbedtls_memory_buffer_alloc_init(mbedtls_heap, sizeof(mbedtls_heap));

mbedtls_heap_initialized = 1U;

}

}


Funkcje MbedTLS_Heap_Init() należy wywołać po inicjalizacji MX_MBEDTLS_Init():

  1.   MX_MBEDTLS_Init();
  2.   MbedTLS_Heap_Init();

Należy pamiętać jeszcze o włączeniu odpowiednich definów:

  1. #define MBEDTLS_MEMORY_BUFFER_ALLOC_C
  2. #define MBEDTLS_PLATFORM_MEMORY

Pierwsza z nich włącza alokowanie statycznego bufora. Druga pozwala na korzystanie z własnych funkcji alokacji. 

Dodaje odpowiednią sekcję w pamięci wraz z zabezpieczeniem przed przekroczeniem w trakcie buildu programu:

  1.   .mbedtls_heap (NOLOAD) :
  2.   {
  3.     . = ALIGN(8);
  4.     __mbedtls_heap_start__ = .;
  5.  
  6.     KEEP(*(.mbedtls_heap))
  7.     KEEP(*(.mbedtls_heap*))
  8.  
  9.     . = ALIGN(8);
  10.     __mbedtls_heap_end__ = .;
  11.   } >DTCMRAM
  12.  
  13.   __mbedtls_heap_size__ = SIZEOF(.mbedtls_heap);
  14.   __dtcmram_free__ = ORIGIN(DTCMRAM) + LENGTH(DTCMRAM) - __mbedtls_heap_end__;
  15.  
  16.   ASSERT(SIZEOF(.mbedtls_heap) <= (120 * 1024),
  17.          "MBEDTLS heap section is larger than expected")
  18.  
  19.   ASSERT(__mbedtls_heap_end__ <= ORIGIN(DTCMRAM) + LENGTH(DTCMRAM),
  20.          "DTCMRAM overflow by MBEDTLS heap")

Dzięki temu zabezpieczeniu jak wprowadzimy za dużą tablicę do pamięci to dostaniemy błąd kompilacji:


Po poprawnej kompilacji sprawdzam plik .map. Czy wszystko jest umieszczone poprawnie, 


Jak widać na screenie powyżej. Zajęte jest 120KB (0x1E00) co daje 8KB wolne. Adres zaczyna się w 0x20000000 a kończy na 0x2001E000. Dzięki temu mamy potwierdzenie, że bufor MBETLS jest w pamięci DTCMRAM.