레이블이 MCU-ESP32-MEM인 게시물을 표시합니다. 모든 게시물 표시
레이블이 MCU-ESP32-MEM인 게시물을 표시합니다. 모든 게시물 표시

4/04/2022

ESP32 의 Memory 구성-5 (Software 분석 )

1. ESP32의 Software Memory 분석


  • ESP32의 HW Memory 관련분석 
ESP32 Memory Address Map 과 전체구성 


ESP32 External Memory 관련구성내용  


상위내용들은 ESP32의 HW입장에서 Memory 사용분석이며, SW입장에서의 Memory 구성을 Linker Script 와 Map파일로 알아보기로 한다.  

Linker Script의 기본이해 


1.1. ESP32의 지원 Macro attribute 확인  

Linker Script와 같이 ESP32에서 제공해주는 MACRO로  _attribute_ 을 이용하여 Section을 정의하고 거기에 할당하는 것인데, 
각 이름을 쉽게 변경하여 제공해주고 있다.  
예를들면 IRAM_DATA_ATTR 은 __attribute__((section(".iram.data"))) 이런식으로 Linker Script에서 정의한 특정영역에 배치가 가능하다. 

물론 본인이 원하면, 새로운 영역을 만들어서, attribute로 정해 별도의 할당도 가능하다. 
오래전에 리눅스에서 Linker Script와 같이 attribute를 이용하여 많이 설정 사용하던 방법이나, 이미 ESP32에서 만들어놓은 것들이 있음므로, 
가급적 아래의 룰을 지키면서 하면 거의 수정할 필요는 없다. 

  • ESP32 Memory Type (Macro Attribuite)
각 Attribute에 정의된 Section는 Linker Script와 같이 연결되어 동작되므로 반드시 숙지해야하며 아래의 Manual 참고 

  • ESP32 Memory Tyep (Attribuite 의 Section)
IRAM 
IRAM_ATTR".iram1" 시작영역, (Interrupt Handler 주로사용)
이외 IRAM을 DATA 로 정의해서 사용하는 부분도 상위 링크에서 확인가능 

DRAM
DRAM_ATTR".dram1" 시작영역, Data 저장용으로 SRAM 

DMA
DMA_ATTR:  ".dram1" 4byte align의 DRAM_ATTR이용, User는 MALLOC_CAP_DMA 이용

External BSS영역 
EXT_RAM_ATTR ".ext_ram.bss"로 시작영역, SPIRAM의 BSS 영역지정

RTC 관련영역들 
RTC_DATA_ATTR : ".rtc.data"  시작영역
RTC_RODATA_ATTR : ".rtc.rodata" 시작영역 
RTC_SLOW_ATTR : ".rtc.force_slow" 시작영역
RTC_FAST_ATTR : ".rtc.force_fast" 시작영역

NOINIT 영역들 
__NOINIT_ATTR :  ".noinit" 시작영역, SRAM 내부의 noinit Section
RTC_NOINIT_ATTR".rtc_noinit" 시작영역, RTC를 위한 noinit Section 

noinit Section은 보통 Loader가 이영역을 건들지 않기 때문에 유용하게 사용가능하다.
예를들면, System Reset하여도 초기화가 되지 않아 보관하고자 하는 정보를 저장가능  

  • system.map 기반으로 쉽게파악 
상위영역을 간단히 찾는 방법은 본인이 build한 system.map에서 쉽게 찾을 수 있으며, 상위영역은 prefix이며 조건에따라 naming이 되어진다. 

  • attribuite 의 section 과 Linker script 
Linker Script는 초기부팅하고 전체구성이므로, 보통 중요한 것들은 ".iram0" 과 ".dram0 기반으로 Assembly와 함께 거의 다 구현되어있다. 
그리고, 각 영역들을 찾아보며 구성이 어떻게되어있는지 쉽게 파악가능하다. 
아래는 현재 가장 많이 사용하는 EXT_RAM_ATTR와 Linker Script 연결구성이며,본인도 다 찾기가 귀찮다. 
  
  • ESP32 IDFv4.2 attribuite 의 Section 확인 
상위 attribute들의 각 Section들을 ESP32 IDF 소스에서 직접 확인하며, 각 버전마다 다를 수 있으므로 반드시 아래에서 확인 


  • ESP32 각 영역 의 예로 IRAM (세부내용은 아래링크 참고)
IRAM(Instruction RAM) Manual 
  1. iram0_0_seg 영역 
  2. 0x4008000 - 0x400A0000 : 0x2000
  3. PRO/APP CPU를 위해서 64K MMU로 사용 


1.2. ESP32 의 Linker Script 기본구조파악    

  • A. ESP32 Core  전체구성확인
ESP32 Core의 기본구성파일로 Cmake/Makefile/Linker Scirpt 들 비롯하여 가장 필수적인 파일들이 존재하므로 구성파악 

  • B. ESP32 Cmake/Makefile 확인
예전에는 순수 Makefile기반으로 했는데, Cmake라서 보기도 편하지만, 다만 component 개념이 있어 좀 그렇다.  
아래의 Cmake/Makefile/Component.mk 에서 Linker Script가 어떤 조건일때 각각 연결되는지만 대충파악하면 된다. 

ESP32 Linker Script 파일들 확인  
상위 Cmake/Makefile/Component.mk와 같이 어떻게 연결되는지를 확인 

ESP32의 Core 기본 Linker Script 
ESP32의 기본 Core Linker Script로 Memory Segment가 기본구성되어있으므로 반드시 이해 
상위 System.map에서 언급된 Segment 중심으로 Linker Script 보도록 하자. 


1.3. Linker Script 의 Memory

우선적으로 Linker Script의 Memory 에서 각 Segment의 주소와 길이 및 기본역할들을 파악하자. 
  • MEMORY Command의  Segment 확인 
가장먼저 확인해야 할 것이 Segment 기반으로 주소/길이 와 R/W/X 확인 될 것 같다.
그리고, 이 안에 무엇을 넣을지는 각 Section 에서 정의된 부분을 찾아 확인하면된다. 
  1. iram0_0_seg(RX) : PRO CPU위한 공간이며 MMU로 이용 
  2. iram_0_2_seg(RX) : SPI Flash를 Mapping하기 위해서 사용
  3. dram0_0_seg(RW): 공유되어진 DRAM이며 BT사용할 경우 변경  
  4. drom0_0_seg(R): DRAM으로 Flash Mapping 
  5. rtc_iram_seg(RWX): RTC FAST용 IRAM
  6. rtc_data_seg(RW): RTC FAST 용 DRAM
  7. rtc_slow_seg(RW): RTC SLOW 용 ULP용으로 사용 
  8. extern_ram_seg(RWX): External Memory로 Text /data  ESP기준으로 보면 I/DRAM
R: Read / X: Execute /W:Write 

  • Segment alias

  • Linker Script Manual 
MEMORY Command (Segment)  


1.4. Linker Script 의 Segment  

상위에서 파악된 Segment가 실제로 어떻게 구성이 되는지를 파악하자. 
아래와 같이 각 Section을 파악하고 이와 연결하는 구성을 파악하자. 
더불어 ESP32에서 제공하는 mapping의 의미도 알아보자 

  • iram0_0_seg 의 Section 구성의 예  
iram0_0_seg의 구성을 간단히 보는 것이며, 이외 segment들은 생략 

.iram0.vectors: ISR 구성확인 

.iram0.text : Code 영역

  • Linker Script Manual 
SECTION Manual 

  • ESP32 Linker Script Manual
ESP32의 Linker Script Manul로 내부에서 제공되는 별도의 내용이 있으므로 반드시 확인

  • ESP32에서 사용하는 mapping
Linker Script Template 기능이라고하며, 미리 이 Template를 만들고 나서 쉽게 연결시키는 구조이다. 
ESP32의 Compiler도 GCC기반인데, GCC에서도 이기능을 지원을 해주는 것 같다.

Linker Script Template
Default scheme 정보확인 



2. build/system.map 분석  

Linker Script 결과를 가장 쉽게 확인하는 방법은 역시 map파일로 보면되며, 실제 어떻게 연결되었는지 자세히 알아볼수 있다. 
각 Segment 뿐만 아니라 Section들도 각 다 확인가능하며, Symbol Table도 다 확인가능하다.
 
  • map파일 분석 
$ cat build/*.map  // Memory Map 구성확인 
....

Memory Configuration    //Linker Script에서 각 Segment 확인 (Embedded Memory:SRAM) 

Name             Origin             Length             Attributes
iram0_0_seg      0x0000000040080000 0x0000000000020000 xr    // 131072  Instruction        SRAM0 MMU (Table 117) (Table 2)
iram0_2_seg      0x00000000400d0020 0x000000000032ffe0 xr    // 3.3M    Instruction        External Memory (Table 1) 
dram0_0_seg      0x000000003ffb0000 0x000000000002c200 rw    // 180736  Data               SRAM2 MMU (Table 117)(상위 SRAM1/2의 Data Segment) 와 dram heap
drom0_0_seg      0x000000003f400020 0x00000000003fffe0 r     // 4M      Data               External Memory (Table 1)
rtc_iram_seg     0x00000000400c0000 0x0000000000002000 xrw   // 8K      Instruction        Embedded Memory (Table 1)  RTC FAST MPU  (Table 117)
rtc_data_seg     0x000000003ff80000 0x0000000000002000 rw    // 8K      Data               Embedded Memory (Table 1)  RTC FAST MPU  (Table 117)
rtc_slow_seg     0x0000000050000000 0x0000000000001000 rw    // 4K      Data/Instruction   Embedded Memory (Table 1)  RTC SLOW MPU  (Table 117)
extern_ram_seg   0x000000003f800000 0x0000000000400000 xrw   // 4M      Data               External Memory (Table 1)
*default*        0x0000000000000000 0xffffffffffffffff
.....
_heap_start                                       esp-idf/soc/libsoc.a(soc_memory_layout.c.obj)
_init                                             c:/users/jhlee/.espressif/tools/xtensa-esp32-elf/esp-2020r3-8.4.0/xtensa-esp32-elf/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/esp32-psram/no-rtti/crti.o
_init_start                                       esp-idf/esp32/libesp32.a(cpu_start.c.obj)

....
//SRAM1/2의 dram0_0_seg 의 heap Start 과 End 
.dram0.heap_start
                0x000000003ffbfbe0        0x0
                0x000000003ffbfbe0                . = ALIGN (0x8)
                0x000000003ffbfbe0                _heap_start = ABSOLUTE (.)
                0x0000000000000001                ASSERT (((_iram_end - ORIGIN (iram0_0_seg)) <= LENGTH (iram0_0_seg)), IRAM0 segment data does not fit.)
                0x0000000000000001                ASSERT (((_heap_start - ORIGIN (dram0_0_seg)) <= LENGTH (dram0_0_seg)), DRAM segment data does not fit.)
                0x000000003ff40000                PROVIDE (UART0 = 0x3ff40000)
                0x000000003ff42000                PROVIDE (SPI1 = 0x3ff42000)
                0x000000003ff43000                PROVIDE (SPI0 = 0x3ff43000)
.......
                0x000000003ff96530                __mb_cur_max = 0x3ff96530
                0x000000003ff96458                __sf_fake_stderr = 0x3ff96458
                0x000000003ff96498                __sf_fake_stdin = 0x3ff96498
                0x000000003ff96478                __sf_fake_stdout = 0x3ff96478
                0x000000003ff96540                __wctomb = 0x3ff96540
                0x0000000040001778                close = 0x40001778
                0x000000004000178c                open = 0x4000178c
                0x00000000400017dc                read = 0x400017dc
                0x00000000400017f4                sbrk = 0x400017f4
                0x0000000040001808                times = 0x40001808
                0x000000004000181c                write = 0x4000181c
                0x000000003ffbfbe0                _static_data_end = _bss_end
                0x0000000040000000                _heap_end = 0x40000000
                0x000000003ff80000                _data_seg_org = ORIGIN (rtc_data_seg)
... 

상위 시작주소는 이미 ESP32 기본 Linker Script에 의해 정해져있고, Lens도 정해져있다.
그러므로, 각각의 좌측 Segment Name을 클릭해보면 알수 있다. 
주의: 동적으로 변한다면 sdkconfig의 각 CONFIG 의해 변경. 

esptool.py 의 Memory Map 

  • buuld 후 idy.py로 size 분석 
$ idf.py size   // *.elf 생성 후 *.map 기반으로 SIZE 분석 
.....
Total sizes:
 DRAM .data size:   24808 bytes
 DRAM .bss  size:   48160 bytes
Used static DRAM:   72968 bytes ( 107768 available, 40.4% used)      // 72968+107768  = 180736 -> 0x2C200 (dram0_0_seg)
Used static IRAM:  115369 bytes (  15703 available, 88.0% used)      // 115369+15703  = 131072 -> 0x20000 (iram0_0_seg)
      Flash code:  869907 bytes
    Flash rodata:  185032 bytes
Total image size:~1195116 bytes (.bin may be padded larger)

$ idf.py size-files      // 상위보다 좀 더 자세히 각 Build된 파일 별로 볼 수 있음 
$ idf.py size-components // ESP32의 각 Components 별로 볼 수 있음 


3. 소스에서 사용되어지는 Memory Map

ESP32의 Memory Map 정의 파일로 Linker Script 와 같이 사용되지 않는 것으로 보이며,
ESP32 IDF 소스에서 직접 Address Map 주소가  필요할때 이용하는 것으로 보인다.

실제 프로그램에서는 아래 주소를 사용을 한다는 말이며, 각 부분이 어떻게 사용되는지는 ESP32 IDF를 전체 분석해야하나, 생략한다. 
Virtual Addresss 관련부분 추후 찾기  

/* Overall memory map */
#define SOC_DROM_LOW            0x3F400000         //V Addr0
#define SOC_DROM_HIGH           0x3F800000         //V Addr0
#define SOC_DRAM_LOW            0x3FFAE000         //V Addr0
#define SOC_DRAM_HIGH           0x40000000         //V Addr0
#define SOC_IROM_LOW            0x400D0000         //V Addr1
#define SOC_IROM_HIGH           0x40400000
#define SOC_IROM_MASK_LOW       0x40000000
#define SOC_IROM_MASK_HIGH      0x40064F00


//DRAM (Data RAM)          bss, init, data, heap 할당
//IRAM (Instruction RAM)   text 할당 

#define SOC_CACHE_PRO_LOW       0x40070000     // SRAM0
#define SOC_CACHE_PRO_HIGH      0x40078000     // SRAM0   
#define SOC_CACHE_APP_LOW       0x40078000     // SRAM0  
#define SOC_CACHE_APP_HIGH      0x40080000     // SRAM0 iram0_0_seg     

#define SOC_IRAM_LOW            0x40080000     // SRAM0 iram0_0_seg  MMU, pagesize기반으로 mapping (세부사항, Datasheet) 
#define SOC_IRAM_HIGH           0x400A0000     // SRAM0 iram0_0_seg  MMU, pagesize기반으로 mapping (세부사항, Datasheet)    

#define SOC_RTC_IRAM_LOW        0x400C0000
#define SOC_RTC_IRAM_HIGH       0x400C2000
#define SOC_RTC_DRAM_LOW        0x3FF80000
#define SOC_RTC_DRAM_HIGH       0x3FF82000
#define SOC_RTC_DATA_LOW        0x50000000
#define SOC_RTC_DATA_HIGH       0x50002000
#define SOC_EXTRAM_DATA_LOW     0x3F800000     //V AddrRAM
#define SOC_EXTRAM_DATA_HIGH    0x3FC00000


//First and last words of the D/IRAM region, for both the DRAM address as well as the IRAM alias.
#define SOC_DIRAM_IRAM_LOW      0x400A0000     // SRAM1
#define SOC_DIRAM_IRAM_HIGH     0x400C0000     // SRAM1   
#define SOC_DIRAM_DRAM_LOW      0x3FFE0000     // SRAM1,2    
#define SOC_DIRAM_DRAM_HIGH     0x40000000     // SRAM1,2


// Region of memory accessible via DMA. See esp_ptr_dma_capable().
#define SOC_DMA_LOW  0x3FFAE000
#define SOC_DMA_HIGH 0x40000000

// Region of memory that is byte-accessible. See esp_ptr_byte_accessible().
#define SOC_BYTE_ACCESSIBLE_LOW     0x3FF90000
#define SOC_BYTE_ACCESSIBLE_HIGH    0x40000000

//Region of memory that is internal, as in on the same silicon die as the ESP32 CPUs
//(excluding RTC data region, that's checked separately.) See esp_ptr_internal().
#define SOC_MEM_INTERNAL_LOW        0x3FF90000
#define SOC_MEM_INTERNAL_HIGH       0x400C2000

// Start (highest address) of ROM boot stack, only relevant during early boot
#define SOC_ROM_STACK_START         0x3ffe3f20

ESP32의 soc.h Memory Map  


  • 상위 값을 간단히 정리 
SOC_CACHE_PRO   :  0x40078000 - 0x40070000  = 0x8000   // SRAM0
SOC_CACHE_APP   :  0x40080000 - 0x40078000  = 0x8000   // SRAM0

SOC_IRAM        :  0x400A0000 - 0x40080000  = 0x20000  // SRAM0
SOC_DIRAM_IRAM  :  0x400C0000 - 0x400A0000  = 0x20000  // SRAM1
SOC_DIRAM_DRAM  :  0x40000000 - 0x3FFE0000  = 0x20000  // SRAM1-> SRAM2


4. ESP32 Memory 최적화방법 

ESP32 Manual에서 자세히 설명을 해주고 있으며, Memory 최적화들은 아래의 링크들로 확인하자. 

  • ESP32 IRAM 최적화방법 
WIFI /BT를 동시에 사용하거나, IRAM 전용으로 선언으로 사용시 이를 최적화해야함

  • ESP32 SRAM의 Heap 최적화방법 
이미 상위 그림에서 있듯이 BT 혹은 다른 CONFIG 설정들을 통해 최적화가 가능하며, Heap을 디버깅도 가능하다.  

  • ESP32 SRAM의 IRAM 문제 및 메모리최적화 
iram0 이 사이즈 문제가 되는 경우들이지만, Linker Script에서 수정하는 것은 아닌것 같다. 

  • ESP32의 RAM 사용법 
RAM을 적게 사용하려면, Dynamic으로 사용하고 각 TaskCreat를 할때 Stack은 Heap에서 오기때문에, 적은양의 Stack을 정하라는 이야기이다.  
그리고 사용하지 않은 CONFIG들은 설정을 하지말자 

  • SRAM의 DRAM의 제약사항
각 할당되어지는 Max 사이즈가 있으므로 확인 

2/18/2022

ESP32 의 Memory 구성-4 (External Memory-2)

1. ESP32의 SPI 기본구성  

ESP32의 External Memory는 SPI로 연결되어 있으며, SPI-Flash 와 SPI-RAM으로 구성되어있다. 

  • SPI 기본연결방식 
SPI 기본통신의 경우 아래와 같이 Data 1 bit의 Serial 통신이지만, QSPI 기능을 이용하여 4 bit 도 통신이 가능하다. 
좀 복잡하게 구성하고자 한다면, Master SPI가 CS 1개로 중간에 FPGA를 이용하여, 
FPGA Arbiter 걸쳐, 두 개의 Peripehral Device Data Line 공유 사용도 가능하다 
물론 상위 구성은 FPGA가 필요하겠지만,   
  1. CS(Chip Select): 단방향 
  2. MOSI(Master Out Slave In):  단방향
  3. MISO(Master In Slave Out):  단방향 
  4. SCLK(Serial Clock): 단방향
https://en.wikipedia.org/wiki/Serial_Peripheral_Interface


1.1. ESP32 SPI Controller 구성확인 

ESP32의 SPI Controller는 4개이지만, 2개는 Arbiter를 사용해서 조합으로 사용하고, 나머지들은 독립적으로 사용가능하다. 
재미있는 구성이며, 이전에, LoRA 때에도, 유사하게, FPGA기반으로 사용한 적이 있는데, 
이것 구성과는 좀 다르다. 

  • ESP32 SPI Controller 구성 
SPI는 총 4개의 Controller 구성되어있지만, 외부와는 3개로 연결되어 동작되며, 사용자입장에서는 3개가 존재한다고 생각하면 되겠다.  

  • 외부 SPI Controller 구조 (CS0/1/2 선택)
  1. SPI: SPI0/1의 조합으로 중간에 Arbiter 중재 혼합하여 사용 
  2. HSPI:  SPI2 연결  
  3. VSPI:  SPI3 연결  
https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf

  • 내부 SPI0/1/2/3 설정 
  1. SPI0의 경우 Buffer로 Cache 와 External Memroy 접근가능
  2. SPI1은 Master로만 설정 DMA로 연결
  3. SPI2/3은 Master or Slave 설정되며, DMA연결 

ESP32의 경우 SPI의 모드가 다양하게 제공하고 있는데, 기본으로 DIO(Dual)를 Data 2 bit이용하고 있다. 
SPI0 과 SPI1 기반으로 사용 

이전에 LoRa Gateway에서 FPGA가 Arbiter 역할을 하며, 마치 버스처럼 사용했는데, 그거하고 좀 다른구조이다. 


1.2.  ESP32의 SPI-External Memory  

  • ESP32 WROVER 의 SPI 연결사항  
  1. SPI Flash/SPI RAM: Data Bus를 모두 공유 SD0/SD1/SD2/SD3 
  2. SPI CS:  CS 독립적사용 
  3. SPI CLK: NC로 각 독립적으로 사용하는 것 같으나, 왠지 같은 PIN을 사용할 거 같음.

 DIO는 SPI0/1만 사용하고 있으며, CS0은 Flash에 GPIO17로 PSRAM에 연결 

https://www.espressif.com/sites/default/files/documentation/esp32-wrover-b_datasheet_en.pdf


상위회로도로 보면, 기본으로 ESP32 QSPI도 지원가능 


1.3.  ESP32의 QSPI 지원 

SPI 2개가 아닌 QSPI로 확장하여 사용할 경우, SPI 2,3 Controller 전부 사용해야한다.   
그러므로, SPI-External Memory 이외 SPI를 하나 더 사용하고자 하면, 
현재로는 아쉽지만, Parrellel QSPI의 기능은 포기해야 할 것으로 생각되어진다. 


Data bus를 확장하여 QIO(Quad)를 이용할 경우 4bit Data 통신도 가능하다. 
SI/SO/WP/HOLD 를 Data Bus로 이용하며 방향도 단방향이 아닌 양방향으로 전환하며, Half duplex되고, Master/Slave가 변경   


https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf



  • Parallel QSPI Master의 Format 
ESP32와 SPI Flash/PSRAM의 경우 QSPI 로 설정해서 통신 Message 형태
  1. Command: SPI Flash (XiP가능) or SPI PSRAM Command 입력 (Read/Write 등등)
  2. Address:  24bit Address
  3. Data: Data: 16bit Data 

https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf



상위에서 SPI_W0_REG 찾아 추가 

2. SPI External Memory 

현재 External Memory라고 하면 SPI Interface로 Flash 와 PSRAM이며 이는 같은 버스를 사용하고 있다. 

  • ESP32 의 PSRAM의 확장 
  1. 현재 4MB (0x3F800000 ~ 0x3FBFFFFF) 확장가능 
  2. BSS Section을 SPIRAM에 사용가능 
  3. Heap Section을 동적으로 할당가능 (CONFIG설정변경해야함)
물론 상위기능이 완벽하게 동작하면 좋겠지만, 아래와 같이 제약사항존재한다.

ESP32 SDKCONFIG 설정 
  • ESP32의 PSRAM(SPIRAM)의 제약사항
  1. PSRAM(SPIRAM)은 DMA가 사용가능하지만, 다른 Periphheral 이 사용중이라면 불가능 
  2. SPI Flash 와 SPIRAM은 같은 버스를 사용하므로, SPIRAM에서 Flash의 XiP를 disable하는 Code는 사용하지 못한다고 한다. 
  3. SPIRAM은 SRAM 보다 속도가 당연히 느리며, 중요한 Code는 가급적 SRAM에 저장

결론적으로 현재 사용하고 있는 Memroy들은 SPI-Flash(XiP) / SPI-RAM / SRAM 인데 각각의 Memroy 속도가 다르다. 


2.1 External Memory(SPI-Flash)

External Memory로 SPI Flash가 기본으로 존재하며, 이곳에 모든 기본 Data들을 저장한다.
더불어 SPI Flash 기반으로 XiP(eXecute in Place)으로 실행도 가능하다고 한다. 

  • QSPI Flash 의 XiP(eXecute in Place) 
  1. XiP 장점:  RAM이 필요 없이 Flash 기반으로 직접 실행이 가능 
  2. XiP 단점:  RAM보다 속도느리며, Write를 못함

SPI Flash도 Serial로 Command/Address/Data 로 구성되기때문에, Serial로 XiP가 가능하다고 한다. 

QSPI XiP Flash 

  • SPI Flash Mode
  1. QIO (Quad I/O): 4 Pin Data Bus를 양방향으로 Address 와 Data 모두 사용 (가장빠름)
  2. QOUT(Quad Output): 4 Pin Data bus로 단방향 추측 
  3. DIO(Dual I/O): 2pin Data Bus를 양방향으로  Address 와 Data 모두 사용 (default)
  4. DOUT(Dual Output): 2pin Data bus를 단방향 추측 
QIO로 이용하여도 Serial 양방향이므로, Half duplex로 이용해야한다. 


2.2 External Memory(SPI-RAM)

주로 SPI에 연결이 되어 있어 SPIRAM 이라고 불리며, 실제 이름은 PSRAM(Pseudo Static RAM)의 약어로 나도 처음 써보는건데, 
아래 글을 읽어보면, DRAM기반으로 Self-Refresh 설정하여 마치 SRAM처럼 사용하는 것이 PSRAM이라는 말이다. 

  • ESP32 사의 Winbond PSRAM
현재 ESP32의 경우 Flash와 PSRAM도 Winbond사 사용( Flash Id로 확인가능)

  • DRAM의 기본정보와 Self Refresh 모드 이해 (DRAM 이해 )  
일반 SoC 가 DRAM에게 Refresh의 경우 와 Self Refresh모드를 사용하는 경우(AP에서 Refresh를 진행안하는 경우)
이 부분은 RAM에대해 자세히 좀 더 알아야 하며, 추후 관심있다면 DRAM 을 보시길 

TI Chip 경우, 보통 EMIF를 통해 Memory Control(DRAM) 진행하며, 관련내용기술 (EMIFA도 있음)  


PSRAM의 사용이유를 간단히 분석해보면, 보통 AP or SoC 일 경우,
MMU or Memory Interface(EMIF)를 통해 SDRAM을 매번 AP or SoC 자동 Refesh를 해준다  

일반 AP or SoC의 경우, Uboot에서 DRAM 설정을 거의 하게되어있으며, DRAM Timing과 모드를 설정한다. 
하지만, Micom와 같이 MMU or Memory Contoller의 기능부족하거나, MMU or Memory Contoller가 없을 경우, 
SDRAM을 주기적으로 Refresh를 못하므로, 이를 Self Refresh 모드로 변경하여 사용하는 것으로 보인다.   

주의 
MMU에 Memory Contoller가 반드시 포함되어야 하는게 아니며, 두개가 분리되어진 것이 있거나, 합쳐진 것이 존재함  


3. ESP32의 Task 와 External Memory 사용 

ESP32의 경우, FreeRTOS의 모든 Task는 SRAM의 할당된 Heap(IRAM/DRAM)기반으로 동적으로 할당된 TCB와 Stack으로 운영되어진다.
그러니, SRAM영역의 Heap이 부족하면 Task도 생성을 못하고 Stack도 부족하다. 

  • SPI 의 External Memory 주의사항 
물론 개발자가 각 상위 설정변경하여 SPIRAM에서도 Task 내부의 Stack을 사용가능하도록 동작가능하게 변경할 수는 있다. 
아래에서 간단히 소개하겠지만, PSRAM(SPIRAM)에 Static로 할당하여 동작하게 하여, 이곳에 Stack을 SPIRAM으로 할당하는 방식인데, 
이렇게 사용하면, SPI Interface가 에러가 나면서 문제가 발생하는 경우가 발생한다. 

정확한 에러이유는 세부적으로 분석을 안했지만, XiP 와 PSRAM(SPIRAM)의 각 사용 중 급전환 혹은 다른영역 RAM을 갑자기 사용일 것으로 추측한다. 
혹은 SRAM의 프로그램 과 External Memory(SPI-Flash/Memory) 간의 각각 속도차이 문제도 의심 되어진다.  
또는 SPI Interface에서 SPI0/1은 PSRAM과 FLASH가 동시에 사용하지 못하는데, 
동시에 사용해야하는 경우 발생하여 에러 발생할 수도 있을 거 같다는 생각든다.
예들들면, SRAM기반의 Task와 Stack 사용중에는 External Memory를 가져와서 사용가능하나, 
SPIRAM기반으로 Stack을 사용중에 갑자기 SPI Flash를 사용하는 문제가 될 것 같다. 

현재 다양한 추측 및 원인은 많을 것 같은데, 정확한 것은 나중에 시간되면 차근차근 분석하자. 
지금 생각으로는 상위들을 제대로 분석하려면, Cache 동작부터 다 분석해야한다. 

또, 현재 상위 SPI 말고도 한개의 더 SPI2 연결하여 사용하고 있는데, 이 것도 연관성도 있을 것 같기도 하다. 
하지만, 확률적으로 떨어져 보이는데, 나의 경우 SPI2를 사용하기 때문에, SPI controller가 서로 다르기 때문이다.   

  • External Memory SPIRAM 기반으로 Task Stack 사용할 경우 문제사항 
나와 동일하게 xTaskCreateStaic 에 External Memory Stack를 사용해서 에러가 난 경우를 설명해주는데, 글을 읽어보면 결론적으로 거의 사용하지 말라는 거다.
SRAM기반의 Heap에서 Stack을 사용하라는 내용이며, 물론 그래도 하고자 하는 이들이 있다.
그래서 나도 기꺼이 테스트해가면 사용했으며, 사용할 경우는 아래와 같이 사용하도록 하자.  

  • External Memory SPIRAM 기반으로 Task 생성방법  
xTaskCreate 대신 xTaskCreateStatic을 이용하여 Task를 생성하면된다. 
만약 xTaskCreateStaic을 사용한다면 가급적 전부 모든 소스를 SPIRAM기반으로 동작하도록하면 에러가 없는 것으로 보이지만 왠지 불안하다.  
xTaskCreate기반으로도 생성가능

2/14/2022

ESP32 의 Memory 구성-3 (External Memory-1)

1. ESP32의 External Memroy 구성 


ESP32 System Map 구성 

ESP32의 System에서 봤듯이 각 CPU가 External Memory로 접근하기위해서는 Cache와 MMU를 걸쳐 함께동작한다. 

ESP32 Internal Memory 구성 

Manual을 읽다보면, 상위 Cache가 거의 External Memory MMU로 사용되어지는 것 같으며, 우선적으로 Cache 와 MMU에 대해 알아보자. 

1.1 ESP32 의 Cache 구조 

  • 2-way set associative Cache
ESP32 Core(Xtensa LX6 CPUs)가 Harvard Architecture로 구성되어 I/D Cache로 분리되어 구성 
Cache는 2-way set associative Cache 방식이며, Cache에서 IMMU 와 DMMU로  Mapping하는 구조로 파악(이부분은 확인)  

  • n-Way Set-Associative Cache 설명 
MMU를 걸쳐 Memory에서 직접 Mapping하여 사용하는 방법 

  • CPU와 Cache 구조 
각 CPU가 External Memory를 접근하기 위해서는 PRO/APP_CACHE_ENABLE의 설정필요하며,  
SRAM0의 POOL0/1(32KB/32KB) 연결되어 Cache 동작됨  



https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf


상위 Cache를 설정하는 Regstier로 각 CPU마다 존재 
  • DPORT_PRO_CACHE_CTRL_REG/DPORT_APP_CACHE_CTRL_REG
  1. DPORT_PRO_DRAM_HL :   External SRAM Virtual Address(R/W)
  2. DPORT_PRO_DRAM_SPLIT: External SRAM Virtual Address(R/W)
  3. DPORT_PRO_SINGLE_IRAM_ENA : External Flash(R/W) , XiP 사용할것으로 추측 
  4. DPORT_PRO_CACHE_ENABLE : 상위 Instruction BUS 이용 

https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf




각 독립적 구성도 가능하지만, 아래와 같이 MUX를 변경하여 Dual CPU의 Cache공유도 가능
CACHE_MUX_MODE
  1. SRAM의 Cache POOL0 (32kB)
  2. SRAM의 Cache POOL1 (32kB)
https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf


상위 64KB는 PRO/APP MMU Cache 이며, Pool0/1 이며, SRAM0에 존재 
  1. SPI Flash의 경우 64KB가 필요 
  2. SPI RAM의 경우 32KB가 필요 

SMP로 하려면 참 복잡하겠다고 생각되며, 각 MUX MODE가 중요할 것 같으며, PSRAM을 사용하면, Cache는 필수다. 


1.2. ESP32의 MMU 기능 및 비교  

  • ARM MMU의 구조와 비교 
Core -> MMU의 TLB(Translation Lookaside Buffer) -> Cache -> Memory 
거의 비슷하지만, ESP32의 경우는 Multilevel은 지원이 안되는 것 같다. 

  • MMU(Memory Management Unit)/MPU(Memory Protection Unit)
MMU의 기본기능은 Virtual Address를 도입하여, Address Mapping(virtual/physical address 변환)하여 
메모리에서 실행 가능한 코드 보다 더 큰 코드를 실행가능하게 하는 것이다. 
이외 MMU의 기능으로 Address Mapping을 하여, Memory Map IO 에서 주소변환 쉽게하여 주소확장, 이외 DRAM Contol 및 다른 부가 기능이 있지만,
ESP32의 경우 가장 기본기능만 갖추어지만, 기존과 좀 다르게 동작하므로 좀 세심하게 봐야할 것 같다. 

ESP32의 MMU/MPU에서 Page Mapping 까지 지원되며, 2/4/8KB 이며, Instruction/Data를 구분하여 지원하며, 추후 Linux도 사용가능할 것 같다  
ESP32의 경우, Linker Script에서 직접 Mapping하는 것으로 보임 

  • ESP32 Internal Memory 와 MMU/MPU 
Internal Memory를 위한 MMU 이며,아래와 같이 SRAM0/1 128KB로 제한적으로 사용되어진다.

https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf



  • MMU와 MPU
  1. SRAM0 MMUInstruction /128KB = 8KB x 16 Pages
  2. SRAM2 MMUData /128KB = 8KB x 16 Pages
  3. Static MPU:  Memory Protection (PID 0/1 즉 Core만 접근가능)
  4. RTC FAST MPU: MPU기능 (PID0~7 가능) 
  5. RTC SLOW MPU: MPU기능 (PID0~7 가능) 
 
** RTC FAST 경우 Aliases는, RTC FAST 8KB인데, 이를 IRAM/DRAM Address Map확장.
** SRAM1 경우 Aliases  SRAM0/2에서 Address Map을 확장용도.(아래에서 다시설명)  




2. ESP32 MMU for Internal Memory 


SRAM0/2 중 128KB식 Bus Type으로 IRAM/DRAM 구분되어 구성 각 MMU는 전체 16Page로 구성하고 있다.  
Virtual 과 Physical을 아래와 같이 각 Page 단위 직접 Mapping하는 방식

SRAM2의 DRAM용 D-MMU의 예제 
https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf


  • SRAM0/2 MMU의 Size 와 Page 구성 
  1. SRAM0 I-MMU:  전체 사이즈 128KB = 16Page x 8K 설정시 최대사용 (2/4/8KB) 
  2. SRAM2 D-MMU:  전체 사이즈 128KB = 16Page x 8K 설정시 최대사용 (2/4/8KB) 

  • SRAM0/2 MMU의 Address Map (PageSize:2/4/8KB)
  1. SRAM0 I-MMU: 0x40080000 + (pagesize ∗ n) to 0x40080000 + (pagesize ∗ (n + 1) − 1)
  2. SRAM2 D-MMU: 0x3FFC0000 + (pagesize ∗ n) to 0x3FFC0000 + (pagesize ∗ (n + 1) − 1)

  • 실제 적용되는 것은 아래 Register 들
  1. DPORT_DMMU_TABLEn_REG 
  2. DPORT_IMMU_TABLEn_REG

  • SRAM0/2 MMU for Internal Memory 사용목적
내 개인생각으로 보면, 사용목적은 지금까지 두가지 추측하지만 실제 왜 사용하는지 궁금하다. 

SRAM1의 확장사용방법 (추측-1) 
SRAM0/2에서 SRAM1을 확장하여 사용할때 사용할 것 같다.  
그 근거로 상위 SRAM0 MMU 와 SRAM2 MMU의 위치가 뒷 부분에 위치해서 그렇게 생각하는데, 아닌것 같기도 하다.  
  1. SRAM0은 Instruction Bus 용이므로 SRAM1(128KB) Mapping하여 확장
  2. SRAM2은 Data Bus용이므로 SRAM1(128KB) Mapping하여 확장 

SRAM0/2의 효율적인 Memory사용(추측-2) 
효율적인 SRAM0/2의 사용목적으로 예를들면, Memory 공간낭비를 최소화하고, Page 교환방식을 적용하여, SRAM에서의 크기 보다 더 큰 프로그램 실행목적 
혹은 효율적으로 Memory를 사용  


3. ESP32 MMU for External Memory

Cache MMU와 연결되어 동작되어진다고 하며, 상위의 Internal MMU 비슷하게 동작한다고 한다. 
다만 차이는 아래와 같이 Page Size가 각각 고정되어 사용되어진다.
 
  • Cache MMU (External Memory)의 Page Size
  1. SPI-Flash의 Page Size:  64KB (상위 2개 Cache 사용할것 같음)
  2. SPI-RAM의 Page Size:  32KB (상위 1개 Cache 사용할것 같음)

  • External Memory의 Range
  1. SPI-Flash의 Range:  4MB = 64KB  x  64  (Page quantity)
  2. SPI-RAM의 Range:  4MB = 32KB  x  128 (Page quantity) 
SPI-RAM의 경우 256으로 확장하여 8MB 까지 가능한걸로 보인다. 

  • Cache/Cache MMU의 역할 
상위 Page Size는 Cache MMU 즉, Cache Size 기반으로 어떻게 Mapping하느냐가 될 것 같다.

  • External Memory의 Virtual Address
MMU 의 Virtual Address 라고하는데, 그냥 Mapping 수준으로 보이며, 다만 Core가 두개이다 보니 각각 나누어서 접근하도록 설계를 했다. 
V Addr RAM을 보면, 사용법이 복잡하며, 대충 이해하기로만 했다. 
  1. V Addr 0~1: SPI Flash 이지만, PID0/1 , 즉 두개 Core만 접근허용 
  2. V Addr 2~3: SPI Flash 이지만, PID 2~7, 주로 DAM와 다른 디바이스들 
  3. V Addr RAM: SPI RAM의 경우 Cache 설정에 따라 다양하게 사용가능 (Manual 참조)

https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf



1/24/2022

ESP32 의 Memory 구성-2 (Internal Memory)

1. ESP32 Internal Memory 구성 


  • ESP32 Memory Address MAP
CPU에서 Internal Memory 접근은 Cache를 이용하지 않는다. 

ESP32에서는 Internal Memory or Embedded Memory라고 하며, ROM과 RAM부분으로 구성되어있다. 

  • ESP32-WROVER-B의 Internal Memroy 구성 
https://www.espressif.com/sites/default/files/documentation/esp32-wrover-b_datasheet_en.pdf

  • ESP32의 Internal Memory Size 구성 
SRAM과 ROM의 구성보면 다음과 같이 구성되어있으며, 주로 SRAM부분을 파악하자
  1. 520 KB의 SRAM (0/1/2 분할 사용)
  2. 448 KB의 ROM (0/1 분할 사용)
  3. 1 Kbit eFuse : 주로 내부 정보로 이용되며, MAC Address 정보(WIFI/BT/EMAC) 
  4. 8KB RTC Fast Memory:    (PRO_CPU만 접근가능)
  5. 8KB RTC SLOW Memory:  (PRO_CPU/APP_CPU/ULP 접근가능)
상위의 RTC Slow Memory의 경우 거의 ULP가 사용하며, 나의 경우는 거의 제외 
(DeepSleep모드는 ULP 내부 별도 Core사용)


  • ESP32의 Internal Memory Address Map 
Bus Type 기준으로 Data/Instruction에 따라 각 나누어 사용하므로 각 Address Map를 주의해서 보도록하자. 

https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf



  • Table 2 의 Comment 관련설명 
  1. Remap: Internal ROM0 과 Internal SRAM1 Remap 되면 Internal ROM0로 사용
  2. Cache:  두개의 CPU(PRO_CPU/APP_CPU)가 32KBx2=64  Cache 사용(MMU기반) 
  3. DMA:  Data로만 되어지며, MMU대신 MPU기반으로 동작 
  4. PRO_CPU Only: RTC FAST Memory 접근은 PRO_CPU만 가능 

** 착각하면 안되는 것이 상위 Internal Memory Size를 다 사용한다고 생각하면 안되며, 상위는 Address Map 일뿐 이다. 

  • ESP32의 ROM0/1(440KB) 구성 
  1. Internal ROM 0:: 384KB : Instruction Bus 사용 (두 CPU 접근가능) 
    1. Internal ROM 0: 32KB   : - 이 부분은 SRAM1 과 Remap 되어 SRAM처럼 사용  
    2. Inernal  ROM 0: 352KB 
  2. Internal ROM 1: 64KB : Data Bus 사용 (두 CPU 접근가능) 


  • ESP32의 SRAM(520KB) 구성정리  
SRAM0/1/2로 분할하여 사용하며 각각의 용도가 아래와 같이 다르며, 관련 Linker Scirpt도 확인
  1. SRAM0192 KB(64/128)  Instruction기반으로 사용 
    1. 64KB:  각 CPU의 Cache로 32KB 사용되며, MMU기반으로 External Memory연결 
    2. 128KB: Interrupt Vector/Text/Heap의 IRAM기반으로 사용  
  2. SRAM1128 KB ( DRAM: 128KB or IRAM: 64/32/32KB ) 둘다 사용 상위 Map참조 
  3. SRAM2200 KB ( DRAM: 200KB )

SRAM-0/1/2의 구성은 상위와 같이 약간 복잡하게 구성되며 ,
기본적으로 Insrtuction/Data Type으로 사용하느냐에 따라 Address Map 조금씩 달라진다. 


2. SRAM의 IRAM/DRAM 구분 및 구성   

SRAM을 보면, SRAM0/1/2 와 RTC Flast RAM 와 RTC SLOW RAM 나뉘어진다. 
그리고, SRAM0/1/2는 각 Bus Type에 따라 IRAM/DRAM 으로 나뉘어지며, 중복 Mapping도 가능하다. 

이는 칩 설계자가 SRAM1 확장성을 염두해고 이렇게 중복 Mapping한 것으로 보이며, 실제로도 중간 부분은 I/DRAM을 혼용사용한다.
이부분은 추후 MMU/Cache의 부분을 보면 이해를 할수 있다. 
https://blog.espressif.com/esp32-programmers-memory-model-259444d89387


IRAM/DRAM 
  1. IRAM(Instruction RAM): 주로 text 를 위해서 사용되어질꺼며, 실제 동작Code
  2. DRAM(Data RAM)으로 bss/data/heap/init/noinit 을 위해서 사용 

IRAM/DRAM Adddress MAP
  1. IRAM  SRAM0:  0x4007_0000 - 0x4009_FFFF 
  2. IRAM  SRAM1:  0x400A_0000 - 0x400B_FFFF
  3. DRAM SRAM2:  0x3FFA_E000 - 0x3FFD_FFFF
  4. DRAM SRAM1:  0x3FFE_0000 - 0x3FFF_FFFF

  • Address를 중복되지 않게 IRAM 과 DRAM의 구분
아래와 같이 극단적으로 구성을 정해놓고 사용가능하겠지만, 추후 확장하여 변경도 가능할 것이다. 
  1. SRAM0을 IRAM 사용
  2. SRAM1을 DRAM 사용
  3. SRAM2을 DRAM 사용 
  4. 이외 RTC RAM 8/8 KB사용  
SRAM1은 상위에서 언급했듯이 항상 확장성을 위해서 I/D RAM으로 변경확장가능하다는 것을 잊지말자 
https://blog.espressif.com/esp32-programmers-memory-model-259444d89387




2.1 SRAM0의 IRAM 구성 

SRAM0의 경우, IRAM 사용되어지며, 실행가능한 코드 혹은 현재 32byte align으로 구성(CPU가 32bit)되어있다. 

  • SRAM0 의 IRAM(Instruction RAM)의 구성의 예 
  1. Dual CPU이므로 각 개별 Cache마다 32KB사용하며, CPU1 Cache를 사용안하면, Heap 
  2. Interrupt Vector 사용
  3. Text  (실행가능한 Code영역, Flash , XIP도 여기서 )
  4. Heap IRAM 영역 
    1. FreeRTOS에서 Heap의 사용하며 재미있는것은 32bit Data로 사용가능  
    2. Linker Script와 같이 각 esp32 내부 malloc함수 같이 분석하면 결론이 나옴 

SRAM0의 IRAM의 구성 
https://blog.espressif.com/esp32-programmers-memory-model-259444d89387



SRAM0의 구성 
192KB = 64KB + 128KB (I-MMU)
128KB = ISR/Text/Free IRAM 이 부분 전체가 I-MMU에 해당  
이부분은 추후 Internal Memory를 위한 MMU 


2.2. SRAM1/2의 DRAM 구성변화  

SRAM1/2의 DRAM 구성은 Config에 따라 변경이 되어지며 각 경우에 따라 아래와 같이 구성 
중요하게 봐야할 부분이 Heap Size이며, Heap 기반으로 Task의 TCB 와 Task의 Stack Size가 결정되므로, 중요하게 봐야한다. 

  • 일반적인 SRAM1/2의 DRAM구성 
  1. SRAM2 의 ROM Function 위한 DATA Memory 영역 (8K Size, 0x2000)
  2. SRAM2 의 DATA 영역 (초기화된 전역변수)
  3. SRAM2 의 BSS  영역 (초기화가 안된 전역변수)
  4. SRAM1/2 의 Data 기반의 Heap 영역 
    1. Task의 TCB 와 Stack 정보가 이곳에 저장될 것이라고 생각됨 
    2. SRAM의 Heap은 BSS Size 다음부터 정해지므로, 사이즈는 부팅

https://blog.espressif.com/esp32-programmers-memory-model-259444d89387




SRAM2의 구성 
200KB = 72KB+ 128KB (D-MMU)
  

  • BT를 사용할 경우 DRAM구성 
BT를 사용할 경우,  SRAM2에 BT Controller Memory(54Kb)영역 추가 
나머지는 상위 일반적인것 과 동일 
https://blog.espressif.com/esp32-programmers-memory-model-259444d89387


상위부분은 Linker Script에서 0x3FFFB_0000 - 0x3FFB_DB5C로 DRAM으로 사용되어짐 


  • Trace를 사용할 경우  DRAM구성   
APP TRACE를 사용할 경우, SRAM1의 Trace Memory(32KB) 추가  
나머지는 상위 일반적인것 과 동일 
https://blog.espressif.com/esp32-programmers-memory-model-259444d89387



3. SRAM1의 Heap 구성확인  

ESP32 SRAM의 실제 Heap 구성 

ESP32를 처음 실행시 현재 사용하는 Heap을 다음과 같이 확인가능하며, 이는 _heap_start가 동적으로 변하기 때문에 각각의 Application에 따라 다름 
각 Config에 의해서 변경되어지므로 주의하며, 상위그림이 다른 것도 다 Config가 다르며,
I (252) heap_init: Initializing. RAM available for dynamic allocation:
I (259) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (265) heap_init: At 3FFB2EC8 len 0002D138 (180 KiB): DRAM
I (272) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (278) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (284) heap_init: At 4008944C len 00016BB4 (90 KiB): IRAM

malloc 은 내부적으로 heap_cap_malloc으로 사용되어지며, 가급적 malloc 대신 heap_cap_malloc으로 사용하자 


12/30/2021

ESP32 의 Memory 구성-1 (Address Map)

1. ESP32 Memory 구성 

ESP32 혹은 ESP32 Module의 Hardware Memory  구성은 다음 과 같다. 
  • Embedded or Internal Memory(ROM/SRAM) 
  • External Memory(SPI-Flash/SPI-PSRAM) 

ESP32의 전반적인 Memory 구성과 사용목적을 세부적으로 알기위해서 아래와 같이 정리하고자 한다.  


1.1. ESP32 System Address MAP 구성  

ESP32 System 기반의 물리적인 Address Map 과 각 Memry 구조를 파악해보도록 하자 

  • ESP32 System Address Map 
각 Bus Type 기반으로 Internal/External Address Map 기억 
  1. Embedded Memory (Internal Memory)
  2. External Memory (SPI Flash/SPI RAM)
  3. Peripheral (System Resgier)
https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf


ESP32 Memory Map

  • ESP32 System Address Map 연결구성
아래의 그림으로 External Memory 와 ESP32의 연결 구성을 쉽게 확인가능하며, 
이외의 Address Map으로 각각 Pheripheral 이 어떻게 연결되어 구성되었는지를 쉽게 파악가능하다. 
  1. External Memory의 경우,  Cache/MMU를 사용 
  2. Internal Memory 의 경우, Cache 미사용 
https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf

상위 Address Map System의 전체구조를 파악하기 쉬운 중요한 것이므로 세부적으로 아래와 같이 분석 

  • System Address Map -> Cache (External Memory)
  1. 0x3F40_0000 - 0x3F7F_FFFF : Data/ 4MB / External Memory 
  2. 0x3F80_0000 - 0x3FEF_FFFF : Data/ 4MB / External Memory 
  3. 0x400C_2000 - 0x40BF_FFFF: Instruction/ 11.5MB(11512KB) / External Memory 
Cache Address Map 은 Cache(32KBx2)->MMU->External Memory 접근가능 
2번의 0x3F80_0000 - 0x3FBF_FFFF: 이곳까지만 사용하며 이외부분은 확장성 
 

  • System Address Map -> Internal ROM
  1. 0x3FF9_0000 - 0x3FF9_FFFF :  Data / 64KB/ ROM1
  2. 0x4000_0000 - 0x4000_7FFF:  Instruction/ 32KB/ ROM0         (Remap) 
  3. 0x4000_8000 - 0x4005_FFFF:  Instruction/ 352KB/ ROM0      
ROM Address Map Size 448KB448KB 전체 사용
ROM0/1로 분할하여 사용
ROM0의 Instruction 은 32KB SRAM1 Instruction Remap사용 (Boot 목적일 추측) 

  • System Address Map -> Internal SRAM
  1. 0x3FFA_E000 - 0x3FFF_FFFF : Data / 200KB        / SRAM2       ( DMA )
  2. 0x3FFE_0000 - 0x3FFF_FFFF : Data / 128KB        / SRAM1       ( DMA
  3. 0x4007_0000 - 0x4007_FFFF: Instruction/ 64KB   / SRAM0       ( Cache)
  4. 0x4008_0000 - 0x4009_FFFF: Instruction/ 128KB / SRAM0        
  5. 0x400A_0000 - 0x400A_FFFF: Instruction/ 64KB  / SRAM1  
  6. 0x400B_0000 - 0x400B_7FFF: Instruction/ 32KB  / SRAM1       (Remap)
  7. 0x400B_8000 - 0x400B_FFFF: Instruction/ 32KB  / SRAM1      
SRAM0/1/2로 분할하여 사용
SRAM Address Map Size 648KB 중 전체 SRAM 사이즈 520KB 사용가능 
648KB-520KB = 128KB 는 SRAM1 (aliases)로 사용 (아래 MMU부분확인)

Cache:  Instruction 32KB x2 = 64KB 사용하며 SRAM0 사용 (Data??)
DMA:   Data  DMA 목적으로 200/128KB까지 확장가능 (아래 IRAM/DRAM 참조)
Remap: ROM0 Remap 사용  


  • System Address Map -> RTC FAST Memory
  1. 0x3FF8_0000 - 0x3FF8_1FFF   :  Data  /8KB  / PRO_CPU Only 
  2. 0x400C_0000 - 0x400C_1FFF  :  Instrunction / 8KB / PRO_CPU Only 
RTC FAST Address Map Size 16KB 8KB만 혼합하여 DATA/Instruction 사용 

  • System Address Map -> RTC SLOW Memory
  1. 0x5000_0000 - 0x5000_1FFF : Data Instruction / 8KB
RTC SLOW Address Map Size 8KB 8KB만 사용하며 주로 ULP 사용 



  • ESP32 System 구성기반으로 전체구성확인
ESP32는 기본적으로 Dual Core로 Cache와 MMU가 존재한다.
Cache는 MMU와 연결되어 Mapping되어 SPI를 이용하여 External Memory 접근 
DMA의 경우 Embedded memory 즉 SRAM기반으로 동작 

Embedded (Internal) Memory 구성 
  1. ROM
  2. SRAM0/1/2
CPU-> Embedded Memory 

External Memory구성 
  1. SPI용 PSRAM(Pseudo-Static RAM)
  2. SPI용 Flash
CPU->Cache->MMU->External Memory 


https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf



상위구성을 보면 External Falsh 와 External SRAM은 MMU를 통해 Cache로 연결되어 구성되어지며, 각 영역은 이미 정해져 있다.