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