[아두이노] FreeRTOS이용한 Multitasking

HEEJOON MOON·2022년 6월 6일
0

Task Creation & kernel Control

  • BaseType_t xTaskCreate(TaskFunction_t pvTaskCode, const char const pcName,
    unsigned short usStackDepth, void
    pvParameters, UBaseType_t uxPriority, TaskHandle_t *pxCreatedTask);

  • void vTaskStartScheduler(void); => 멀티 태스킹을 시작. 생성된 태스크의 스케쥴링 시작

  • void vTaskDelay(portTickType xTicksToDelay);
    => 스케쥴러에 상대 시간동안 delay를 요청(waiting state로 만듬)
    => 함수가 호출된 시점부터 xTicksToDelay동안 태스크 실행을 block

  • void vTaskDelayUntil(portTickType *pxPreviousWakeTime, portTickType xTimeIncrement);
    => 스케쥴러에 절대 시간동안 delay를 요청(waiting state로 만듬
    => 특정 시점인 pxPreviousWakeTime부터 xTimeIncrement 만큼 더한 시간까지 태스크 실행을
    블록

LED와 Buzzer을 동시에 제어

< FreeRTOS1.c >

#include <FreeRTOS_AVR.h>

// FreeRTOS Delay함수에서 사용하기 위한 메크로 함수: ms -> ticks로 변환
#define MS2TICKS(ms)(ms / porTICK_PERIOD_MS)

#define LED 5
#define BUZZER 9

// 음계 정의
enum { REST=0, DO=262, RE=294, MI=330, FA=349, SOL=392, LA=440, SHI=494, DO2=523 };
int Num = 9;
int Frequency[] = { DO, RE, MI, REST, FA, SOL, LA, SHI, DO2 }; // 음계 정의
int Delay[] = { 500, 0, 500, 500, 500, 500, 1000, 0, 500 }; // 유지시간 정의

void LedTask(void* arg){
	while(1){
    	// LED on
        digitalWrite(LED, HIGH);
        // 500ms 지연
        vTaskDelay(MS2TICKS(500));
        // LED off
        digitalWrite(LED, LOW);
        // 500ms 지연
        vTaskDelay(MS2TICKS(500));
    }
}

void BuzzerTask(void* arg){
	int i;
    
    while(1){
    	for(i=0; i<Num; i++){
        	// 9번핀을 통해 출력
            tone(BUZEER, Frequency[i]);
            // 유지 시간
            vTaskDelay(MS2TICKS(Delay[i]));
        }
    }
}

void setup(){
	pinMode(LED, OUTPUT);
    pinMode(BUZEER, OUTPUT);
    
    // Task 생성
    xTaskCreate(LedTask, NULL, 200, NULL, 1, NULL);
    xTaskCreate(BuzzerTask, NULL, 200, NULL, 2, NULL); // BuzzerTask의 우선순위가 LED보다 더 높다
    
    // 스케쥴러 시작
    vTaskStartScheduler();
}

void loop(){}

LED 1개씩 ON/OFF task 2개 동작

  • 500ms 간격으로 on/off

< FreeRTOS2.c >

#include <FreeRTOS_AVR.h>

#define MS2TICKS(ms) (ms/portTICK_PERIOD_MS)

#define LED1 5
#define LED2 6

void LedTask(int* pParam){
	int led, turn, param = *pParam; // pParam 포인터로 param정보 입력받음
    
    // 초기 LED1, LED2 작동 정의
    if(param==1){
    	led = LED1; turn=HIGH;
        }
    else{
    	led = LED2; turn=LOW;
        }
        
    // 루프 반복
    while(1){
    	digitalWrite(led, turn);
        // 500ms 지연
        vTaskDelay(MS2TICKS(500));
        turn = (turn==HIGH) ? LOW : HIGH; // 현재 turn상태와 반대로 지정
    }
}

void setup(){
	int param[2] = {1,2};
    
    pinMode(LED1, OUTPUT);
    pinMode(LED2, OUTPUT);
    
    // Task 생성
    vTaskCreate(LedTask, NULL, 200, &param[0], 1, NULL);
    vTaskCreate(LedTask, NULL, 200, &param[1], 1, NULL);
    
    // 스케쥬러 시작
    vTaskStartScheduler();
}

void loop(){}

위 코드에서는 먼저 param=2일때의 task2가 먼저 실행되며, led=LED2, turn=LOW인 상태로 digitalWrite가 진행되다가 vTaskDelay에 의해 block되며, param=1일때의 task1가 실행된다. led=LED1인 상태로 digitalWrite가 진행되며 led1이 점등되며, 이것도 다시 block되면서 task2가 다시 실행되고, turn의 상태가 바뀌어 LED2가 점등되고 block, 다시 task1이 실행되어 LED1이 소등되고 block을 반복하게 된다. 따라서 LED1개씩 0.5ms씩 점/소등이 반복된다.

profile
Robotics, 3D-Vision, Deep-Learning에 관심이 있습니다

0개의 댓글