YOGYUI

ESP-Matter::External Memory(PSRAM) 관련 설정 본문

홈네트워크(IoT)/Matter

ESP-Matter::External Memory(PSRAM) 관련 설정

요겨 2023. 10. 5. 23:48
반응형

 

Utilize PSRAM on ESP32 SoC using ESP-Matter

 

ESP-Matter SDK를 이용해서 ESP32 계열 칩에 Matter 어플리케이션을 굉장히 손쉽게 작성할 수 있다

ESP32 SoC는 대부분 수백KB 수준의 SRAM을 탑재하고 있는데, 단일 엔드포인트 장치를 개발할 때는 크게 문제가 되지 않지만 Control Bridge(aggregator) 타입으로 non-Matter 장치를 Matter로 연동할 때 수십개의 장치를 붙일 경우 메모리 부족 문제를 맞닥뜨리게 된다 

 

EPS32는 SPI 통신 방식의 외부 메모리를 Pseudo-Static RAM(PSRAM) 방식으로 활용하는 것을 지원하는데, ESP32-WROOM-32E-NxR2처럼 SoC 내부에 PSRAM을 장착한 모듈을 구매해서 사용하거나 혹은 ESP-PSRAM32/64나 LY68L6400같은 외부 메모리를 외부에 장착하여 사용할 수 있다

https://pcbartists.com/design/embedded/esp32-psram-schematic-notes/

 

현재 개발중인 프로젝트에서 외부 PSRAM 장착을 위한 PCB는 artwork을 한창 진행하고 있는데, 중간에 잠깐 머리를 식힐 겸 소프트웨어 상에서는 어떤 식으로 설정을 해줘야 하는지 간단히 알아보자

PSRAM 관련 설정 파라미터들의 자세한 내용은 ESP-IDF 공식 문서 Support for External RAM 참고

 

Support for External RAM - ESP32 - — ESP-IDF Programming Guide latest documentation

ESP32 supports PSRAM connected in parallel with the SPI flash chip. While ESP32 is capable of supporting several types of RAM chips, ESP-IDF currently only supports Espressif branded PSRAM chips (e.g., ESP-PSRAM32, ESP-PSRAM64, etc). Note Some PSRAM chips

docs.espressif.com

ESP-IDF v5.1.1 기준

1. menuconfig 열기

$ idf.py menuconfig

2. PSRAM 옵션 활성화하기

메뉴 계층: Component config → ESP PSRAM → Support for external, SPI-connected RAM

활성화 시 하위에 SPI RAM config 옵션이 추가로 나타난다

2.1. PSRAM 관련 설정

메뉴 계층: Component config → ESP PSRAM SPI RAM config

- Type of SPI RAM chip in use

나는 8MB PSRAM을 장착할 예정이라 'ESP-PSRAM64 or LY68L6400' 옵션 선택

- Ignore PSRAM when not found

PSRAM이 장착되지 않거나 고장났을 경우 펌웨어의 cpu panic으로 인한 무한 재부팅을 막기 위해 활성화

- SPI RAM access method

"Make RAM allocate using malloc() as well" 선택

CONFIG_SPIRAM_USE 옵션 활성화 후 PSRAM을 동적으로 활용하기 위해서는 heap_caps_malloc/ heap_caps_calloc 함수 호출 시 MALLOC_CAP_SPIRAM 플래그를 사용해야 하는데, 이는 esp-matter SDK에 잘 구현되어 있으니 별 고민없이 사용하면 된다

components/esp_matter/esp_matter_mem.cpp

이 외에도 esp32 내장 메모리를 최대한 아끼기 위해 다음 옵션들도 활성화해준다 (자세한 내용은 공식 문서 참고)

- Try to allocate memories of WiFi and LWIP in SPIRAM firstly. If falied, allocate internal memory

- Allow .bss segment placed in external memory

- Allow .noinit segment placed in external memory

 

또한, FreeRTOS 태스크(Task) 스택을 PSRAM에 올릴 수 있게 하기 위해 다음 옵션도 활성화해준다

- Allow external memory as an agrument to xTaskCreateStatic

※ RTOS Task도 개당 수KB의 스택 메모리를 힙에 할당해야 하는 경우가 대다수라 상당히 유용한 옵션! (나는 어쩌다보니 프로젝트 규모가 커져서 Task만 7~8개 사용하는데, 이것만 해도 30KB 가까이 사용한다... 520KB SRAM만 가진 EPS32에서는 꽤나 치명적인 크기 ㅠ)

  • xTaskCreateStatic의 경우 개발자가 수동으로 할당한 스택 메모리 주소를 StackType_t 인자로 넣어줘야 하는데, heap_caps_alloc/malloc 호출 시 MALLOC_CAP_SPIRAM 플래그 사용해서 PSRAM에 할당된 메모리를 사용할 수 있다는 이야기~

menuconfig 저장 시 sdkconfig에 PSRAM 관련 설정은 다음과 같이 변경된다

이 중에서 필요한 것들을 sdkconfig.defaults 파일에 기록해두면 된다

#
# ESP PSRAM
#
CONFIG_SPIRAM=y

#
# SPI RAM config
#
CONFIG_SPIRAM_MODE_QUAD=y
# CONFIG_SPIRAM_TYPE_AUTO is not set
# CONFIG_SPIRAM_TYPE_ESPPSRAM16 is not set
# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set
CONFIG_SPIRAM_TYPE_ESPPSRAM64=y
CONFIG_SPIRAM_SPEED_40M=y
CONFIG_SPIRAM_SPEED=40
CONFIG_SPIRAM_BOOT_INIT=y
# CONFIG_SPIRAM_USE_MEMMAP is not set
# CONFIG_SPIRAM_USE_CAPS_ALLOC is not set
CONFIG_SPIRAM_USE_MALLOC=y
CONFIG_SPIRAM_MEMTEST=y
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384
CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y
CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=32768
CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y
CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY=y

#
# SPIRAM cache workaround debugging
#
# end of SPIRAM cache workaround debugging

CONFIG_SPIRAM_BANKSWITCH_ENABLE=y
CONFIG_SPIRAM_BANKSWITCH_RESERVE=8
CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y

#
# PSRAM clock and cs IO for ESP32-DOWD
#
CONFIG_D0WD_PSRAM_CLK_IO=17
CONFIG_D0WD_PSRAM_CS_IO=16
# end of PSRAM clock and cs IO for ESP32-DOWD

#
# PSRAM clock and cs IO for ESP32-D2WD
#
CONFIG_D2WD_PSRAM_CLK_IO=9
CONFIG_D2WD_PSRAM_CS_IO=10
# end of PSRAM clock and cs IO for ESP32-D2WD

#
# PSRAM clock and cs IO for ESP32-PICO
#
CONFIG_PICO_PSRAM_CS_IO=10
# end of PSRAM clock and cs IO for ESP32-PICO

# CONFIG_SPIRAM_CUSTOM_SPIWP_SD3_PIN is not set
CONFIG_SPIRAM_SPIWP_SD3_PIN=7
# CONFIG_SPIRAM_2T_MODE is not set
# end of SPI RAM config
# end of ESP PSRAM

3. ESP-Matter PSRAM 호환 옵션 설정

위에서 esp_matter_mem.cpp 소스코드 중 일부를 발췌한 캡쳐를 보면, 플래그 하나만 설정하면 간단하게 matter 관련 인스턴스(엔드포인트, 클러스터, 어트리뷰트 등)들을 PSRAM에 할당할 수 있게 된다

  • esp_matter_mem_calloc
  • esp_matter_mem_realloc
  • esp_matter_mem_free

위의 3가지 메모리 할당 및 해제 관련 함수를 wrapping한 뒤 아래와 같이 소스코드에서 활용하는 것을 알 수 있다

esp_matter_core.cpp

메뉴 계층: Component config → ESP Matter → Memory allocation strategy

External SPIRAM 선택

※ 중요: 앞서 PSRAM 관련 설정 시 'SPI RAM access method' 항목에서 'Integrate RAM into memory map'을 선택하면 'External SPIRAM' 옵션을 선택할 수 없다! (PSRAM을 메모리맵에 통합하는 옵션은 쓰지 말라는 이야기)

 

- esp-matter의 Kconfig 파일을 보면 'ESP_MATTER_MEM_ALLOC_MODE_EXTERNAL' 항목은 SPIRAM_USE_CAPS_ALLOC 혹은 SPIRAM_USE_MALLOC 플래그가 활성화되었을 때만 접근할 수 있는 것을 알 수 있다

    choice ESP_MATTER_MEM_ALLOC_MODE
        prompt "Memory allocation strategy"
        default ESP_MATTER_MEM_ALLOC_MODE_INTERNAL
        help
            Strategy for allocating memory for Matter data model, essentially provides ability to
            allocate all required dynamic allocations from,

            - Internal DRAM memory only
            - External SPIRAM memory only
            - Either internal or external memory based on default malloc()
              behavior in ESP-IDF
            - Internal IRAM memory wherever applicable else internal DRAM

        config ESP_MATTER_MEM_ALLOC_MODE_INTERNAL
            bool "Internal memory"

        config ESP_MATTER_MEM_ALLOC_MODE_EXTERNAL
            bool "External SPIRAM"
            depends on SPIRAM_USE_CAPS_ALLOC || SPIRAM_USE_MALLOC

        config ESP_MATTER_MEM_ALLOC_MODE_DEFAULT
            bool "Default alloc mode"

        config ESP_MATTER_MEM_ALLOC_MODE_IRAM_8BIT
            bool "Internal IRAM"
            depends on ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY
            help
                Allows to use IRAM memory region as 8bit accessible region.

                Every unaligned (8bit or 16bit) access will result in an exception
                and incur penalty of certain clock cycles per unaligned read/write.

 

sdkconfig는 다음과 같이 변경된다

# CONFIG_ESP_MATTER_MEM_ALLOC_MODE_INTERNAL is not set
CONFIG_ESP_MATTER_MEM_ALLOC_MODE_EXTERNAL=y
# CONFIG_ESP_MATTER_MEM_ALLOC_MODE_DEFAULT is not set

CONFIG_ESP_MATTER_MEM_ALLOC_MODE_EXTERNAL 플래그가 설정된 채로 빌드 시 매크로로 추가되므로 개발자의 별다른 노력없이 PSRAM에 Matter 관련 인스턴스들을 할당할 수 있게 된다

 4. TODO

ESP-Matter의 PSRAM 호환 관련 설정 후 프로젝트 빌드까지는 오류없이 완료됐는데, 아직 하드웨어가 설계조차 마무리되지 못한 상황이라 별도로 테스트하지 못했다

아트웍 마무리하고 빨리 샘플 PCB 만들어서 테스트해봐야겠다!

 

그동안 200KB 남짓의 힙 메모리 영역에서 어떻게든 이것저것 돌리겠다고 코드 최적화하면서 쌉고생했는데, 무려 8MB의 여유 메모리가 생기게 되다니! 꿈만 같다... 가 아니라 진작에 좀 하지 ㅠ 

그래도 돌이켜보면 임베디드 SW는 아기자기하게 최적화하는 재미가 나름 쏠쏠한 분야 ㅋㅋ

 

반응형
Comments