티스토리 뷰
안녕하세요. 09LABS 입니다.
지난 강의에서는 ESP-IDF 빌드 시스템 구축 후 기본 코드를 작성하는 방법에 대해 알아봤습니다.
이번 강의에서는 멀티태스킹과 유사한 Task API에 대해 알아보겠습니다.
멀티태스킹은 동시에 여러 작업을 수행하는 것을 의미하는데요, 싱글코어 MCU에서는 한 번에 하나의 Task를 실행할 수 있습니다.
따라서 싱글코어 MCU의 경우 Task를 여러개 생성하면 동시에 처리되는 것 처럼 보이지만 스케쥴러에 의해 순차적으로 처리됩니다.
위 그림과 같이 프로그램을 3개 실행한다고 했을 때 우선순위가 높은 순서에 따라 프로그램이 실행되는 순서가 결정됩니다.
만약 듀얼코어 MCU를 사용한다면 멀티태스킹이 어떻게 실행될까요?
제가 사용하는 ESP32-S3 MCU는 듀얼코어 CPU로 구성되어있습니다.
총 2개의 Task를 생성한다고 하면 코어 하나에 하나의 Task를 할당시켜 동시에 두 개의 Task를 실행시킬 수 있습니다.
ESP-IDF Task API 문서를 보면 xTaskCreatePinnedToCore 라는 함수를 사용하여 Task를 실행시킬 Core를 지정할 수 있습니다.
만약 동시에 실행되어서 실시간으로 데이터를 처리하는 Task와 데이터를 수신하는 Task 두 개를 생성한다고 하면 Core를 나눠서 실행시키면 가장 효과적인 성능을 보여줄 것입니다.
이번 강의에서는 멀티태스킹을 구성하는 방법에 대해 알아보고 0부터 10까지 숫자를 세는 Task를 두 개 생성하여 어떻게 동작하는지 알아보겠습니다.
xTaskCreate 함수 정의
ESP-IDF 문서에 정의된 내용에 따르면 xTaskCreate 함수는 다음과 같이 Parameter를 입력하게 되어있습니다.
static inline BaseType_t xTaskCreate(TaskFunction_t pvTaskCode, const char *const pcName, const uint32_t usStackDepth, void *const pvParameters, UBaseType_t uxPriority, TaskHandle_t *const pxCreatedTask)
Parameter 정의
- pvTaskCode – Pointer to the task entry function. Tasks must be implemented to never return (i.e. continuous loop), or should be terminated using vTaskDelete function.
- pcName – A descriptive name for the task. This is mainly used to facilitate debugging. Max length defined by configMAX_TASK_NAME_LEN - default is 16.
- usStackDepth – The size of the task stack specified as the number of bytes. Note that this differs from vanilla FreeRTOS.
- pvParameters – Pointer that will be used as the parameter for the task being created.
- uxPriority – The priority at which the task should run. Systems that include MPU support can optionally create tasks in a privileged (system) mode by setting bit portPRIVILEGE_BIT of the priority parameter. For example, to create a privileged task at priority 2 the uxPriority parameter should be set to ( 2 | portPRIVILEGE_BIT ).
- pxCreatedTask – Used to pass back a handle by which the created task can be referenced.
- pvTaskCode : 실행하고자 하는 함수의 포인터. Task는 절대 반환되지 않도록 구현되거나(무한 루프) xTaskDelete 함수를 사용하여 종료되어야 한다.
- pcName : Task를 설명하는 이름. 디버깅할 때 유용하게 사용되며 최대 길이는 16 Byte이다.
- usStackDepth : Byte로 지정된 Task의 Stack 크기.
- pvParameters : 생성되는 Task의 매개변수(Parameter)로 사용될 포인터
- uxPriority : Task의 우선순위. portPRIVILEGE_BIT를 설정하여 우선순위를 지정할 수 있다.
- pxCreatedTask : 생성된 Task를 참조할 수 있는 Handler
xTaskCreate 기본 예제
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
TaskHandle_t taskHandle = NULL;
void counterTask(void *args) {
int count = 0;
printf("counter Task Start...\n");
while(1) {
printf("count : %d\n", count);
vTaskDelay(1000 / portTICK_PERIOD_MS);
count++;
if (count > 10) {
count = 0;
}
}
}
void app_main(void) {
xTaskCreate(counterTask, "CounterTask", 4096, NULL, 10, &taskHandle);
}
이전 강의에서는 app_main 함수에 무한 루프를 생성하여 0부터 10까지 증가시키는 예제를 작성했습니다.
이번 강의에서는 app_main 함수에 구현한 내용을 counterTask라는 함수에 포함시키고 while(1) 문을 사용하여 무한루프로 실행시켰습니다.
app_main 함수에서 달라진 점은 xTaskCreate 함수를 사용하여 counterTask를 실행시킨다는 점인데요, 위에서 설명한 것과 같이 counterTask 함수를 Task로 생성하는 것입니다.
void app_main(void) {
xTaskCreate(counterTask, "CounterTask", 4096, NULL, 10, &taskHandle);
}
위 내용을 살펴보면
xTaskCreate 함수를 사용하여 counterTask 함수를 실행시키고 Task의 이름은 CounterTask로 설정하였습니다.
Stack의 크기는 4096, 우선순위는 10, Task Handler는 taskHandle로 지정하였습니다.
I (0) cpu_start: App cpu up.
I (187) cpu_start: Pro cpu start user code
I (187) cpu_start: cpu freq: 160000000 Hz
I (187) cpu_start: Application information:
I (190) cpu_start: Project name: count_number
I (195) cpu_start: App version: 1
I (200) cpu_start: Compile time: Feb 17 2024 02:13:07
I (206) cpu_start: ELF file SHA256: d5dd2f5179dd4e8a...
I (212) cpu_start: ESP-IDF: v5.1-dirty
I (217) cpu_start: Min chip rev: v0.0
I (222) cpu_start: Max chip rev: v0.99
I (227) cpu_start: Chip rev: v0.1
I (231) heap_init: Initializing. RAM available for dynamic allocation:
I (239) heap_init: At 3FC94448 len 000552C8 (340 KiB): DRAM
I (245) heap_init: At 3FCE9710 len 00005724 (21 KiB): STACK/DRAM
I (251) heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM
I (258) heap_init: At 600FE010 len 00001FF0 (7 KiB): RTCRAM
I (265) spi_flash: detected chip: gd
I (268) spi_flash: flash io: dio
W (272) spi_flash: Detected size(8192k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
I (285) sleep: Configure to isolate all GPIO pins in sleep state
I (292) sleep: Enable automatic switching of GPIO sleep configuration
I (299) app_start: Starting scheduler on CPU0
I (304) app_start: Starting scheduler on CPU1
I (304) main_task: Started on CPU0
I (314) main_task: Calling app_main()
counter Task Start...
count : 0
I (324) main_task: Returned from app_main()
count : 1
count : 2
count : 3
count : 4
count : 5
count : 6
count : 7
count : 8
count : 9
count : 10
count : 0
코드를 빌드하여 ESP32-S3 DevModule에 업로드한 결과 위와 같이 숫자가 0부터 10까지 순차적으로 증가하는 것을 볼 수 있습니다.
위와 같이 사용하고자 하는 기능을 함수로 구현한 다음 xTaskCreate 함수를 사용하면 원하는만큼 멀티태스킹을 수행할 수 있습니다.
다음 강의에서는 멀티태스킹 활용 + Queue API에 대해 알아보겠습니다.
'코딩하자 > ESP-IDF' 카테고리의 다른 글
[ESP-IDF] 2. 빌드 시스템 구축하기 (0) | 2023.08.15 |
---|---|
[ESP-IDF] 1. ESP32 개발환경 구축 (0) | 2023.08.15 |
- Total
- Today
- Yesterday
- 쏘카
- esp32
- 프린터
- 오픈소스
- 코딩테스트
- 자작
- 3D
- 오픈소스 하드웨어
- 3D Printer
- 프로젝트
- IOT
- ESP
- Hypercube
- 3d프린터
- 퓨전360
- 아두이노
- Fusion 360
- DIY
- fusion360
- 3D 프린터
- C언어
- 설계
- Arduino
- ESP-IDF
- 하드웨어
- 해커랭크
- 리눅스
- SQLITE3
- 라즈베리파이
- C++
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |