- RTOS는 어떻게 작동합니까?
- RTOS에서 자주 사용되는 용어
- Arduino FreeRTOS 라이브러리 설치
- 회로도
- Arduino FreeRTOS 예제-Arduino IDE에서 FreeRTOS 작업 생성
- Arduino IDE에서 FreeRTOS 작업 구현
임베디드 장치 내부에있는 OS를 RTOS (실시간 운영 체제)라고 합니다. 임베디드 장치에서는 타이밍이 매우 중요한 역할을하는 실시간 작업이 중요합니다. 실시간 작업은 시간 결정적 이라는 의미는 이벤트에 대한 응답 시간이 항상 일정하므로 특정 이벤트가 고정 된 시간에 발생한다는 것을 보장 할 수 있습니다. RTOS는 매우 정확한 타이밍과 높은 안정성으로 애플리케이션을 실행하도록 설계되었습니다. RTOS는 또한 단일 코어로 멀티 태스킹을 지원합니다.
RTOS, 범용 OS와 RTOS의 차이점, 다양한 유형의 RTOS 등에 대해 더 많이 알 수있는 임베디드 시스템에서 RTOS를 사용하는 방법에 대한 자습서를 이미 다루었습니다.
이 자습서에서는 FreeRTOS로 시작 합니다. FreeRTOS는 8/16 비트 마이크로 컨트롤러에서 실행할 수있을만큼 충분히 작은 임베디드 장치 용 RTOS 클래스이지만, 사용이 이러한 마이크로 컨트롤러로 제한되지는 않습니다. 완전히 오픈 소스이며 코드는 github에서 사용할 수 있습니다. RTOS의 기본 개념을 알고 있다면 코딩의 백엔드 부분을 몰라도 코드에서 직접 사용할 수있는 잘 문서화 된 API가 있기 때문에 FreeRTOS를 사용하기가 매우 쉽습니다. 전체 FreeRTOS 설명서는 여기에서 찾을 수 있습니다.
FreeRTOS는 8 비트 MCU에서 실행할 수 있으므로 Arduino Uno 보드에서도 실행할 수 있습니다. FreeRTOS 라이브러리를 다운로드 한 다음 API를 사용하여 코드 구현을 시작하면됩니다. 이 튜토리얼은 완전한 초보자를위한 것으로, 아래 주제는이 Arduino FreeRTOS 튜토리얼 에서 다룰 것입니다.
- RTOS 작동 원리
- RTOS에서 자주 사용되는 용어
- Arduino IDE에 FreeRTOS 설치
- 예제를 사용하여 FreeRTOS 작업을 생성하는 방법
RTOS는 어떻게 작동합니까?
RTOS 작업을 시작하기 전에 태스크가 무엇인지 살펴 보겠습니다. 태스크는 CPU에서 실행하도록 예약 할 수있는 코드 조각입니다. 따라서 일부 작업을 수행하려면 커널 지연 또는 인터럽트를 사용하여 예약해야합니다. 이 작업은 커널에있는 스케줄러에 의해 수행됩니다. 단일 코어 프로세서에서 스케줄러는 작업이 특정 시간 조각에서 실행되도록 도와 주지만 다른 작업이 동시에 실행되는 것처럼 보입니다. 모든 작업은 주어진 우선 순위에 따라 실행됩니다.
이제 1 초 간격으로 LED 깜박임 작업을 만들고이 작업을 가장 높은 우선 순위에 두려면 RTOS 커널에서 어떤 일이 발생하는지 살펴 보겠습니다.
LED 작업과는 별도로 커널에 의해 생성되는 작업이 하나 더 있습니다.이를 유휴 작업이라고합니다.. 실행 가능한 작업이 없을 때 유휴 작업이 생성됩니다. 이 작업은 항상 가장 낮은 우선 순위 즉 0 우선 순위에서 실행됩니다. 위의 타이밍 그래프를 분석 해보면 LED 작업으로 실행이 시작되어 지정된 시간 동안 실행 된 후 남은 시간 동안 틱 인터럽트가 발생할 때까지 유휴 작업이 실행되는 것을 알 수 있습니다. 그런 다음 커널은 작업의 우선 순위와 LED 작업의 총 경과 시간에 따라 실행할 작업을 결정합니다. 1 초가 완료되면 커널은 유휴 태스크보다 우선 순위가 높기 때문에 실행할 led 태스크를 다시 선택하고, LED 태스크가 유휴 태스크를 선점한다고 말할 수도 있습니다. 우선 순위가 같은 작업이 두 개 이상있는 경우 지정된 시간 동안 라운드 로빈 방식으로 실행됩니다.
상태 다이어그램 아래에서 실행 중이 아닌 작업을 실행 상태로 전환하는 것을 보여줍니다 .
새로 생성 된 모든 작업은 준비 상태가됩니다 (실행 중이 아닌 상태의 일부). 생성 된 작업 (Task1)이 다른 작업보다 우선 순위가 높으면 실행 상태로 이동합니다. 이 실행중인 작업이 다른 작업에 의해 선점되면 다시 준비 상태로 돌아갑니다. 그렇지 않으면 task1이 차단 API를 사용하여 차단 된 경우 CPU는 사용자가 정의한 제한 시간까지이 작업에 참여하지 않습니다.
Task1이 Suspend API를 사용하여 실행 중 상태로 일시 중단되면 Task1은 Suspended 상태로 전환되고 스케줄러에서 다시 사용할 수 없습니다. 일시 중단 된 상태에서 Task1을 재개하면 블록 다이어그램에서 볼 수 있듯이 준비 상태로 돌아갑니다.
이것은 태스크가 실행되고 상태를 변경하는 방법에 대한 기본 개념입니다. 이 자습서에서는 FreeRTOS API를 사용하여 Arduino Uno에서 두 가지 작업을 구현합니다.
RTOS에서 자주 사용되는 용어
1. 작업: CPU에서 실행하도록 예약 할 수있는 코드 조각입니다.
2. 스케줄러: 준비 상태 목록에서 실행 상태까지 작업을 선택하는 역할을합니다. 스케줄러는 종종 구현되어 모든 컴퓨터 리소스를 바쁘게 유지합니다 (로드 밸런싱에서와 같이).
3. 선점: 이미 실행중인 작업을 협력없이 실행 중 상태에서 제거 할 의도로 일시적으로 중단하는 행위입니다.
4. 컨텍스트 전환: 우선 순위 기반 선점에서 스케줄러는 실행중인 작업의 우선 순위를 모든 Systick 인터럽트 에 대해 준비된 작업 목록의 우선 순위와 비교합니다. 실행중인 작업보다 우선 순위가 높은 작업이 목록에 있으면 컨텍스트 전환이 발생합니다. 기본적으로이 프로세스에서 서로 다른 작업의 내용은 각각의 스택 메모리에 저장됩니다.
5. 일정 정책 유형:
- 선점 형 예약: 이 유형의 예약에서는 작업이 우선 순위를 고려하지 않고 동일한 시간 조각으로 실행됩니다.
- 우선 순위 기반 선점: 우선 순위가 높은 작업이 먼저 실행됩니다.
- 협력 스케줄링: 컨텍스트 전환은 실행중인 작업의 협력에서만 발생합니다. 작업 yield가 호출 될 때까지 작업이 계속 실행됩니다.
6. 커널 개체: 작업을 수행하도록 신호를 보내기 위해 동기화 프로세스가 사용됩니다. 이 프로세스를 수행하기 위해 커널 개체가 사용됩니다. 일부 커널 객체는 이벤트, 세마포어, 대기열, 뮤텍스, 메일 박스 등입니다. 다음 자습서에서 이러한 객체를 사용하는 방법을 살펴 보겠습니다.
위의 논의를 통해 RTOS 개념에 대한 몇 가지 기본 아이디어를 얻었으며 이제 Arduino에서 FreeRTOS 프로젝트를 구현할 수 있습니다. 이제 Arduino IDE에 FreeRTOS 라이브러리를 설치하여 시작하겠습니다.
Arduino FreeRTOS 라이브러리 설치
1. Arduino IDE를 열고 Sketch- > Include Library-> Manage Libraries로 이동 합니다. FreeRTOS를 검색하고 아래와 같이 라이브러리를 설치합니다.
github에서 라이브러리를 다운로드하고 Sketch-> Include Library-> .zip 파일 추가에.zip 파일을 추가 할 수 있습니다.
이제 Arduino IDE를 다시 시작하십시오. 이 라이브러리는 아래와 같이 파일-> 예제-> FreeRTOS 에서 찾을 수있는 몇 가지 예제 코드를 제공 합니다.
여기서는 작동을 이해하기 위해 처음부터 코드를 작성하고 나중에 예제 코드를 확인하고 사용할 수 있습니다.
회로도
다음은 Arduino에서 FreeRTOS를 사용하여 LED 깜박임 작업을 생성하는 회로도입니다.
Arduino FreeRTOS 예제-Arduino IDE에서 FreeRTOS 작업 생성
FreeRTOS 프로젝트를 작성하기위한 기본 구조를 살펴 보겠습니다.
1. 먼저 Arduino FreeRTOS 헤더 파일을 다음과 같이 포함합니다.
#포함
2. 다음과 같이 작성된 실행을 위해 작성중인 모든 함수의 함수 프로토 타입을 제공하십시오.
void Task1 (void * pvParameters); 무효 Task2 (무효 * pvParameters); .. ….
3. 이제 void setup () 함수에서 작업을 생성하고 작업 스케줄러를 시작합니다.
태스크 생성을 위해 특정 매개 변수 / 인수와 함께 설정 함수 에서 xTaskCreate () API가 호출됩니다.
xTaskCreate (TaskFunction_t pvTaskCode, const char * const pcName, uint16_t usStackDepth, void * pvParameters, UBaseType_t uxPriority, TaskHandle_t * pxCreatedTask);
작업을 생성하는 동안 전달되어야하는 6 개의 인수가 있습니다. 이 주장이 무엇인지 보자
- pvTaskCode: 작업을 구현하는 함수에 대한 포인터 일뿐입니다 (실제로는 함수 이름).
- pcName: 작업을 설명하는 이름입니다. FreeRTOS에서는 사용되지 않습니다. 순전히 디버깅 목적으로 포함됩니다.
- usStackDepth: 각 작업에는 작업이 생성 될 때 커널이 작업에 할당하는 고유 한 스택이 있습니다. 값은 바이트 수가 아니라 스택이 보유 할 수있는 단어 수를 지정합니다. 예를 들어 스택이 32 비트 폭이고 usStackDepth 가 100으로 전달되면 400 바이트의 스택 공간이 RAM에 할당됩니다 (100 * 4 바이트). Arduino Uno에는 2Kbyte의 RAM 만 있기 때문에 이것을 현명하게 사용하십시오.
- pvParameters: 태스크 입력 매개 변수 (NULL 일 수 있음).
- uxPriority: 작업의 우선 순위 (0이 가장 낮은 우선 순위).
- pxCreatedTask: 생성중인 작업에 핸들을 전달하는 데 사용할 수 있습니다. 그런 다음이 핸들을 사용하여 작업 우선 순위를 변경하거나 작업을 삭제하는 (NULL 일 수 있음) API 호출에서 작업을 참조 할 수 있습니다.
작업 생성 예
xTaskCreate (작업 1, "작업 1", 128, NULL, 1, NULL); xTaskCreate (작업 2, "작업 2", 128, NULL, 2, NULL);
여기서 Task2는 우선 순위가 더 높으므로 먼저 실행됩니다.
4. 작업을 만든 후 vTaskStartScheduler ()를 사용하여 void 설정에서 스케줄러를 시작합니다 . API.
5. Void loop () 함수는 우리가 어떤 작업도 수동으로 그리고 무한히 실행하고 싶지 않기 때문에 비어있을 것입니다. 작업 실행은 이제 스케줄러에 의해 처리되기 때문입니다.
6. 이제 태스크 함수를 구현하고 이러한 함수 내에서 실행하려는 논리를 작성해야합니다. 함수 이름은 xTaskCreate () API 의 첫 번째 인수와 동일해야합니다.
void task1 (void * pvParameters) { while (1) { .. ..// 당신의 논리 } }
7. 대부분의 코드는 실행중인 작업을 중지하기 위해 지연 함수가 필요하지만 RTOS 에서는 CPU를 중지하고 RTOS도 작동을 중지하므로 Delay () 함수 를 사용하지 않는 것이 좋습니다. 따라서 FreeRTOS에는 특정 시간 동안 작업을 차단하는 커널 API가 있습니다.
vTaskDelay (const TickType_t xTicksToDelay);
이 API는 지연 목적으로 사용할 수 있습니다. 이 API는 주어진 수의 틱 동안 작업을 지연시킵니다. 작업이 차단 된 상태로 유지되는 실제 시간은 틱 속도에 따라 다릅니다. 상수 portTICK_PERIOD_MS 를 사용하여 틱 속도에서 실시간을 계산할 수 있습니다.
즉, 200ms의 지연을 원하면 다음 줄을 작성하십시오.
vTaskDelay (200 / portTICK_PERIOD_MS);
따라서이 자습서에서는 이러한 FreeRTOS API 를 사용하여 세 가지 작업을 구현합니다.
사용할 API:
- xTaskCreate ();
- vTaskStartScheduler ();
- vTaskDelay ();
이 자습서를 위해 생성 할 작업:
- 200ms 주파수로 디지털 핀 8에서 LED 깜박임
- 300ms 주파수로 디지털 핀 7에서 LED 깜박임
- 500ms 주파수로 직렬 모니터에 숫자를 인쇄합니다.
Arduino IDE에서 FreeRTOS 작업 구현
1. 위의 기본 구조 설명에서 Arduino FreeRTOS 헤더 파일을 포함합니다. 그런 다음 함수 프로토 타입을 만듭니다. 세 가지 작업이 있으므로 세 가지 기능을 만들어 프로토 타입입니다.
#include void TaskBlink1 (void * pvParameters); 무효 TaskBlink2 (무효 * pvParameters); void Taskprint (void * pvParameters);
2. void setup () 함수에서 초당 9600 비트로 직렬 통신을 초기화하고 xTaskCreate () API를 사용하여 세 가지 작업을 모두 만듭니다. 처음에는 모든 작업의 우선 순위를 '1'로 만들고 스케줄러를 시작하십시오.
void setup () { Serial.begin (9600); xTaskCreate (TaskBlink1, "작업 1", 128, NULL, 1, NULL); xTaskCreate (TaskBlink2, "작업 2", 128, NULL, 1, NULL); xTaskCreate (Taskprint, "작업 3", 128, NULL, 1, NULL); vTaskStartScheduler (); }
3. 이제 task1 LED 깜박임에 대해 아래와 같이 세 가지 기능을 모두 구현합니다.
void TaskBlink1 (void * pvParameters) { pinMode (8, OUTPUT); while (1) { digitalWrite (8, HIGH); vTaskDelay (200 / portTICK_PERIOD_MS); digitalWrite (8, LOW); vTaskDelay (200 / portTICK_PERIOD_MS); } }
마찬가지로 TaskBlink2 함수를 구현 합니다. Task3 함수 는 다음과 같이 작성됩니다.
void Taskprint (void * pvParameters) { int counter = 0; while (1) { 카운터 ++; Serial.println (카운터); vTaskDelay (500 / portTICK_PERIOD_MS); } }
그게 다야. Arduino Uno 용 FreeRTOS Arduino 프로젝트를 성공적으로 완료했습니다. 이 튜토리얼의 끝에서 비디오와 함께 전체 코드를 찾을 수 있습니다.
마지막으로 디지털 핀 7과 8에 두 개의 LED를 연결하고 Arduino 보드에 코드를 업로드하고 직렬 모니터를 엽니 다. 아래와 같이 작업 이름으로 500ms에 한 번 카운터가 실행되는 것을 볼 수 있습니다.
또한 LED를 관찰하면 다른 시간 간격으로 깜박입니다. xTaskCreate 함수 에서 우선 순위 인수를 사용해보십시오. 번호를 변경하고 직렬 모니터 및 LED의 동작을 관찰하십시오.
이제 아날로그 읽기 및 디지털 읽기 작업이 생성되는 처음 두 개의 예제 코드를 이해할 수 있습니다. 이런 식으로 Arduino Uno 및 FreeRTOS API 만 사용하여 더 발전된 프로젝트를 만들 수 있습니다.