Posted by INDIFROG on
2021-03-03
Words 1.9k and
Reading Time 12 Minutes
Viewed Times
3강. Free RTOS 기초
FreeRTOS는 기본적으로 멀티 코어 프로세서를 지원하지 않지만 ESP-IDF와 같은 일부 변형은 이를 지원합니다. 먼저 AMP (비대칭 다중 처리)와 SMP (대칭 다중 처리)의 차이점을 살펴 보겠습니다.
AMP(Asymmetric multiprocessing)는 여러 코어 또는 프로세서를 사용하여 동시에 여러 작업을 실행하는 프로그래밍 패러다임입니다. 하나의 코어 / 프로세서가 운영 체제 (OS)를 실행하는 기본 코어가 되어야 합니다. 보조 코어라고 하는 다른 코어로 작업을 보냅니다. 이러한 코어는 동일한 아키텍처 일 수도 있고 아닐 수도 있습니다. 실제로 별도의 컴퓨터에 AMP 구성을 설정할 수 있습니다.
SMP(symmetric multiprocessing) 다중 스레드 프로그램을 다중 코어에서 실행할 수있는 패러다임이기도합니다. 그러나 SMP에서 각 코어는 OS 사본을 실행합니다. 각 코어의 스케줄러는 독립적으로 작동하며 공유 목록에서 작업을 실행하도록 선택합니다. SMP를 사용하려면 코어가 단단히 결합되어야하며 종종 RAM 및 기타 리소스를 공유해야합니다. 결과적으로 일반적으로 SMP는 동일한 아키텍처의 여러 코어 위에 구축됩니다.
원래 바닐라 FreeRTOS는 단일 코어에서 실행되도록 설계되었습니다. ESP-IDF FreeRTOS는 대칭 다중 처리 (SMP)를 지원하는 바닐라 FreeRTOS의 수정된 버전입니다. ESP-IDF FreeRTOS는 FreeRTOS v10.2.0의 Xtensa 포트를 기반으로합니다.
ESP32는 Core가 2개이며 프로토콜 CPU (CPU 0 또는 PRO_CPU로 알려짐)와 애플리케이션 CPU (CPU 1 또는 APP_CPU로 알려짐)를 포함하는 듀얼 코어입니다. 두 개의 코어는 실제로 동일하며 동일한 메모리를 공유합니다. 이를 통해 두 코어가 작업을 상호 교환적으로 실행할 수 있습니다.
// Task to run forever xTaskCreatePinnedToCore( // Use xTaskCreate() in vanilla FreeRTOS taskToggleBlueLED, // Function to be called "Toggle BLUE LED", // Name of task 1024, // Stack size (bytes in ESP32, words in FreeRTOS) (void*)&timeDelay, // Parameter to pass to function uxTaskPriorityGet(NULL), // Task priority (0 to configMAX_PRIORITIES - 1) &taskHandle, // Task handle PRO_CPU); // core No.
int32_t timeDelay2 = 323; TaskHandle_t taskHandle2; ////////////////////////////////////////// // Task to run forever xTaskCreatePinnedToCore( // Use xTaskCreate() in vanilla FreeRTOS taskToggleBlueLED, // Function to be called "Toggle BLUE LED", // Name of task 1024, // Stack size (bytes in ESP32, words in FreeRTOS) (void*)&timeDelay, // Parameter to pass to function uxTaskPriorityGet(NULL), // Task priority (0 to configMAX_PRIORITIES - 1) &taskHandle, // Task handle APP_CPU); // core No.
// Task to run forever xTaskCreatePinnedToCore( // Use xTaskCreate() in vanilla FreeRTOS taskToggleBlueLED2, // Function to be called "Toggle BLUE LED2", // Name of task 1024, // Stack size (bytes in ESP32, words in FreeRTOS) (void*)&timeDelay2, // Parameter to pass to function uxTaskPriorityGet(NULL), // Task priority (0 to configMAX_PRIORITIES - 1) &taskHandle2, // Task handle APP_CPU); // core No.
// Delete "setup and loop" task // vTaskDelete(NULL); }
voidloop(){ // Do nothing }
4. ESP32에서 portMUX_Type을 이용한 Critical Section 구현
Vanilla FreeRTOS는 portDISABLE_INTERRUPTS()를 호출하는 taskENTER_CRITICAL()을 사용하여 critical section을 구현합니다. 이렇게하면 critical section 동안 선점 컨텍스트 전환 및 ISR 서비스가 방지됩니다. 따라서 critical section은 vanilla FreeRTOS의 동시 액세스에 대한 유효한 보호 방법으로 사용됩니다.
반면에 ESP32는 코어가 서로의 인터럽트를 비활성화하는 하드웨어 방법이 없습니다. portDISABLE_INTERRUPTS () 호출은 다른 코어의 인터럽트에 영향을 미치지 않습니다. 따라서 인터럽트를 비활성화하는 것은 현재 코어가 자체 인터럽트를 비활성화 한 경우에도 다른 코어가 데이터에 자유롭게 액세스 할 수 있도록 하기 때문에 공유 데이터에 대한 동시 액세스에 대한 유효한 보호 방법이 아닙니다.
이러한 이유로 ESP-IDF FreeRTOS는 portMUX_Type 객체로 참조하는 특수 뮤텍스를 사용하여 critical section을 구현합니다. 이들은 특정한 spinlock 구성 요소로 구현됩니다. vTaskEnterCritical 또는 vTaskExitCritical 대한 호출은 각각 spinlock 객체를 인수로 제공합니다.
spinlock은 액세스 보호가 필요한 공유 리소스와 연결됩니다. ESP-IDF FreeRTOS에서 critical section에 들어갈 때 호출 코어는 바닐라 FreeRTOS 구현과 유사하게 인터럽트를 비활성화한 다음 spinlock을 가지고 critical section으로 들어갑니다. 다른 코어는 자체 critical section에서 동일한 spinlock을 시도하지 않는 한 이 시점에서 영향을 받지 않습니다. 이 경우 portEXIT_CRITICAL 함수로 잠금이 해제 될 때까지 루프를 돌면서 재시도하게 됩니다.
따라서 ESP32에서는 위와 같이 portMUX_Type을 이용하여 critical section 을 통해 다른 코어를 비활성화하지 않고도 공유 리소스에 대한 액세스를 보호 할 수 있습니다. 다른 코어는 동일한 리소스에 동시에 액세스하려는 경우에만 영향을 받습니다.
5. iFBalance에서 Critical Section 이용한 하드웨어 버튼 인터럽트 처리
다음은 GPIO_NUM_0 에 할당된 버튼이 눌렸는지 감지하는 iFButton 클래스 코드입니다.