10/14/2021

ESP32 와 FreeRTOS

1. FreeRTOS 관련정보 

FreeRTOS 관련문서 

사용하면서 오래전에 Vxworks 나 다른 RTOS가 생각나며 자동으로 비교가 되어지는데, 물론 상용 RTOS에 비교하는 것이 좀 무리일수도 있지만,
무료인 Linux 와 변종 RTLinux 도 있기때문에 비교되어지며, 기능이 부족하다고 생각했으나, 의외로 괜찮은 무료 RTOS인 것 같다. 

  • ESP32의 FreeRTOS의 Version 확인 (IDFv4.2.2)
ESP32에서 사용하는 FreeRTOS Version v8.2.0기반으로 했으나, 특정함수는 v9.0.0 라고한다
아래를 읽어보면, SMP기반으로 동작한다. 


1.1 FreeRTOS의 Config 확인 

  • FreeRTOS 설정 
FreeRTOS의 각 설정으로 모든 API에서 이 설정기준으로 동작하므로 관련설정을 확인하자

  • ESP32의 FreeRTOSConfig.h / FreeRTOS.h 
ESP32의 경우, FreeRTOSConfig.h가 존재하며, 이는 FreeRTOS.h에 포함되며, 상위와 다르게, 다시 Wrap 해서 CONFIG를 진행 

ESP32의 FreeRTOSConfig.h / FreeRTOS.h 파일 

일반 FreeRTOSConfig.h 파일
FreeRTOS 관련설정값들로 이 값과 상위값을 비교 


  • 각 ESP32 설정들을 확인 

#define configUSE_PREEMPTION			1
#define configUSE_IDLE_HOOK			1
#define configUSE_TICK_HOOK			1

#define configTICK_RATE_HZ				( CONFIG_FREERTOS_HZ )    //Tick Time 100Hz, Linux 와 동일 

#ifdef SMALL_TEST
#define configMAX_PRIORITIES			( 7 )
#else
#define configMAX_PRIORITIES			( 25 )           // 숫자가 높을수록 우선순위가 높음
#endif


.....

#define configAPPLICATION_ALLOCATED_HEAP 1                // Heap 사용여부 결정, heap_1/2 or 4.c 사용시 ucHeap 와 array 와 dimension 사용  
#define configTOTAL_HEAP_SIZE			(&_heap_end - &_heap_start) // Size를 직접 넣거나, Linker Scirpt에서 설정 
//esp32의 heap의 구성 (heap 3으로 추정)


#define configSUPPORT_DYNAMIC_ALLOCATION    1
ESP32의 FreeRTOSConfig.h 


FreeRTOS Memory Management (Heap)

ESP32 Memory Management


1.2  FreeRTOS의 Scheduler 

Vxworks 처럼 Schduling  알고리즘이 여러 개 존재하여 선택가능할 줄 알았는데, 현재 찾아본 것으로는 없는 것으로 보인다.
기본적으로 운영되어지는 Scheduling 알고리즘을 우선적으로 파악하고 특징을 좀 알아야겠다.

  • Scheduler 동작 on/off
vTaskStartScheduler/vTaskEndScheduler

  • FreeRTOS의 우선순위 와 Scheduling 알고리즘
아래글을 읽어보면, 우선순위는 숫자가 높을수록 높으며, Round-Robin이 기본인것 같음 
하지만 상위 FreeRTOSConfig.h을 보면 숫자가 높으면, 우선순위가 높다 

  • FreeRTOS의 기본 및 동작방법 확인
RTOS이니 선점방식이 지원될 것이며, 처음에 각 Scheduing 알고리즘설정부분이 있을 줄 알았는데, 아직 찾지못함

Real-Time Scheduling
아래의 링크의 그림을 보면 선점방식으로 동작되는 것을 알수 있음 (높이가 우선순위)
RTOS에서 좀 애매한 것은 우선순위에 대한 Queue의 설명이 없음, 추후에 다시 확인 
  
FreeRTOS의 Scheduling 관련개념자료
보통 Priority Queue 관련설명도 같이 해주는데, 그 부분이 없음  


1.3 FreeRTOS의 AMP/SMP 방식  


ARM용 Multi Core방식소개 
오래전에 ARM용 Multi Core 방식을 간단히 정리 

  • FreeRTOS의 Single-Core 와 Multi-Core 의 RTOS Scheduling
  1. Single-Core: default
  2. AMP(asymmetric multicore): multiple kernel multi-core
  3. SMP(symmetric multicore): one kernel multicore (Linux에서 많이 사용하며 ARM용)

  • Single Core
Single Core의 경우 고정된 우선순위 선점 Scheduing 과 Round-Robin의 Time-slicing 방식 
한마디로 각각의 우선순위 Level 1 ~ 128 를 만든 후 각각 Level 독자 공간에 Round-Robin 방식으로 돌리는 방식  (Vxworks도 거의 동일)
상위방식으로 하면 우선순위가 높으면 항상 선점되어 돌려지며, 동일한 우선순위는 Round-Robin 방식으로 돌아감 
(주의, Scheduler 알고리즘은 Round-Robin 이외 FIFO 등 선택해서 사용하지만, 상위에 언급했듯이, FreeRTOS는 아직 발견못함)

  • AMP(asymmetric multicore)
Multi-Core일 경우 사용하며, 비대칭형으로 2개의 경우, 각 Core마다 각 FreeRTOS를 생성구축하며, 중요한 것은 Parrellel Programing 별도로 진행
말이 좀 어려운가?, 간단히 설명해서 각 Core마다 각 Scheduler가 개별존재.
사실 거의 잘 안쓴다. 
(하지만, 필요할 경우가 있으며, 각 Core가 독자적으로 각 Scheduler 에 따라 동작하기 원할 경우)

  • SMP(symmetric multicore)
Multi-Core 사용시 가장 일반적으로 사용하는 방식으로 FreeRTOS가 직접 각 Core를 Control하는 방식이며, Linux에서도 많이 사용되어진다.
한 마디로 1개 Scheduler 가 각 여러 Core들을 관리하며 동작하는 방식이다. 

FreeRTOS의 Single/AMP/SMP

FreeRTOS의 SMP관련정보 

ESP32의 SMP 관련정보 
개인적으로 궁금한 것은 Cache는 어떻게 운영이 되는지가 궁금하며, 각자 Cache로 사용하는지 공용 Cache로 사용하는지는 추후 알아보도록하자 

  • ESP32 Interrupt 
Interrupt의 경우도 현재 우선순위가 있는 것로 보아서 Nested Interrupt (중첩 인터럽트) 허용하는 것으로 보인다. 
추후 좀 더 자세히 읽고 파악한 후 관련부분 수정 
  1. ESP_INTR_FLAG_IRAM
  2. ESP_INTR_FLAG_LOWMED
  3. ESP_INTR_FLAG_HIGH



1.4  FreeRTOS의 API  

기본적인 통신방법인 Queue 와 Semahpore 를 좀 알아보도록 하자 

  • Queue API 
처음 Queue  사용하면서 Queue 사이즈를 알 수가 없어 사용하기가 불편하며, 솔직히 잘 구현된 API는 아닌것 같다. 

Queue의 Size 문제를 알지 못해 회사지인이 알려주어, 아래 함수로 Queue 사이즈 확인가능하나, 불편하다. 
참고로, Counting Semaphore도 제공하며, 상위 Queue도 본인이 원하면, Counting Semaphore로 구현가능하다. 

  • Semaphore API 
일반 2진 Semaphore 역시 Data Sync용이 아닌 Signal Event 용으로 잘 동작되지가 않는다. 
강제로 이진 Semaphore를 내부 값을 0으로 만든 다음 Singal 용으로 Take /Give로 Task를 Control하려고 했는데 아예 동작되지 않는다.
이유는 아래에 별도의 Task용 Semahphore 제공해서 그런거 같다.  
(Semaphore 동작은 아주 간단하다 값이 0이되면 Task Blocking 되는 시스템) 
 
  • ISR 용 Semaphore
재미 있는 것은 ISR용 SemaphoreTake가 있는데, Blocking Time을 허용하지 않는다고 함
Linux Kernel 의 보통 필요할 경우, Spin lock을 사용한다 (Spin lock 과 Semahpore 다름)

  • Task Control Semaphore 
즉 Signal 목적으로 사용할 경우 아래 함수로 사용하면 될 것 같다. 

지속적으로 관련함수, 즉 API들을 파악 중이지만, 익숙해지는 수 밖에 없는 것으로 보인다. 
FreeRTOS는 무료이고, MCU/MPU 혹은 ESP32 기반에 사용하니 일단 좀 더 공부를 해야 할 것 같다. 




1.6 ESP32의 app의 Version 

OTA를 진행할 경우, application binary format안에 다음 구조체가 존재하며, image안에서 쉽게 볼수 있다. 

  • esp_app_desc 구조체 
PROJECT_VER 값

2. ESP32의 FreeRTOS Task의 Memory 관리 


  

configSUPPORT_DYNAMIC_ALLOCATION


xTaskCreate ->xTaskCreatePinnedToCore

xTaskCreatePinnedToCore

xTaskCreatePinnedToCore
내부 heap (pvPortMallocTcbMem/pvPortMallocStackMem)
MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT

ESP32의 Task Heap 관리
Task Heap 확인 
heap_caps_get_free_size(MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)

configSUPPORT_STATIC_ALLOCATION

외부에서 설정가능 

xTaskCreateStatic->xTaskCreateStaticPinnedToCore

xTaskCreateStaticPinnedToCore


Coredump (Flash)

SPIRAM Config

COMPONENT_EMBED_FILES
COMPONENT_EMBED_TXTFILES

Performance

ESP32의 내부 회로도 확인 
  1. SPI Flash는    QPI/QSPI지만, 일반 SPI Interface 이용     (Data bus: 1bit)
  2. SPI PSRAM는 QPI/QSPI Interface                              (Data bus: 4bit)
  3. 둘다 같은 Bus를 이용하므로 동시사용은 불가능 CS에의 선택 

SPI Flash /SPI Memory Bus는 공유 회로도 확인
문제는 같은 버스라서 동시사용이 불가능 

SPI의 XIP 자료(QSPI) 
SPI 의 XIP의 이용은  QSPI를 이용하여 4bit Parallel 로 통신하여 가능 (Nor의 16/8) 보다가 4bit는 나도 신기할뿐

SPI의 XIP(Execute in place)의 구성 
  1. SPI-SRAM에서는 
  2. SPI Flash에서는 XiP가 가능한걸로 보임 Serial로 Command/ Address/ Data 형식  
Nor Flash의 경우는 Address Bus/Data bus Parallel 이며 존재하므로 XIP가 Read로 가능하지만, SPI Flash도  역시 가능하다고함 


Cypress의 QSPI RAM Datasheet
구조를 보면 , Command / Address / Data 방식으로 전달하여 XiP가 가능함 

ESP32의 Techincal Reference

ESP32 Hardware Degine Guide

ESP32의 Cache Policy 확인

ESP SPI의 DIO/QIO


esptool.py -p COM5 flash_id
Manufacturer: 20 // 0x20: ST ID
Device: 4016   // 0x4016  WINBOND_NEX_W25Q32_V
Detected flash size: 4MB
Hard resetting via RTS pin...


Coredump
  assert(0)   test 진행


3. FreeRTOS Task 정보 와 IDE 관련사항  


FreeRTOS의 전체 Task 정보와 각 실시간 통계 및 점유율을 비롯하여 우선순위들을 알려고자 할 때 아래의 함수들을 이용하도록하자. 


3.1  FreeRTOS의 실시간 통계 및 모니터 

Linux 처럼 각 Task의 점유율과 각 상태의 통계를 알고 싶어 찾기 시작했으며, 관련함수들을 찾았는데, 
간단히 시험만 해보았다. 

  • Run Time Statistics


  • Task의 점유율 확인 
vTaskGetRunTimeStats 함수로 FreeRTOS의 각 Task의 점유율을 쉽게 볼수 있다. 
{
    char dbgBuffer[ 1028*4 ];
    
    printf("Task            Abs-Time       Per-Time       \n");
    printf("----------------------------------------------\n");   
    vTaskGetRunTimeStats( dbgBuffer );
    printf("%s",dbgBuffer);
}

관련정보 및 설정확인 

  • Task 의 상태 및 우선순위 확인 
vTaskList 함수로 FreeRTOS의 각 Task의 아래 정보를 확인 ESP32의 경우 Core도 확인

{
    char dbgBuffer[ 1028*4 ];
    
    printf("Name          State    Prio     Stack   Num    Core? \n");
    printf("-----------------------------------------------------\n");   
    vTaskList( dbgBuffer );
    printf("%s",dbgBuffer);
}
관련정보 및 설정확인 



vTaskList 예제 


3.2  ESP32의 FreeRTOS IDE 관련내용

현재 ESP에서 Ecplise 에 OpenOCD 기반 제공을 해주고 있지만, 아래와 같이 Cadence에서 별도로 제공을 해주는 것으로 보임 

Ecplise 기반의 OpenOCD 연결 

VS Code 기반의 OpenOCD 연결 

Tensilica FreeRTOS IDE 관련내용 
Cumtomized Ecplise된 Ecplise인 것 같으며 추후 각각 사용해보고 비교