본문 바로가기
Embedded

Arduino, FreeRTOS, LED Toggle

by gigasound 2021. 10. 23.

 

 

 

 


RTOS

임베디드 장치에서 RTOS(real time Operating system)의 활용은 이미 정착된 기술입니다. ARM을 비롯해서 아두이노에서도 이를 이용하는 것이 기초처럼 되었습니다. 특히 FreeRTOS를 사용하는 경우가 많습니다. 이 글을 포함에서 몇 번에 걸쳐서 FreeRTOS의 활용방법에 대해서 알아볼 것이고, 이글에서는 가장 기초적인 내용인 LED를 운영하는 방법을 알아보겠습니다.


FreeRTOS로 LED를 토글

아두이노는 LED_BUILTIN 이미 정의된 LED와 포트가 있습니다. 이를 이용해서 현재 펌웨어가 잘 진행 중인지를 표시하는 방법이 있습니다. 

 

FreeRTOS로 LED를 계속 토글(Toggle)하여 이를 표시하는 방법이 가장 많이 사용됩니다. FreeRTOS로 스레드를 하나 만들고 일정 시간이 되면 LED를 토글 하는 내용을 독립적으로 구동하면 됩니다.

 

매우 단순하지만 FreeRTOS의 구동 방식도 이해하면서, 실무에도 사용 가능한 팁입니다.  

  • 먼저 적당한 FreeRTOS를 구해서 설치합니다. ATmega 기반에서는 FreeRTOS_AVR.h를 주로 사용합니다.
  • 스레드로 구동할 Task 함수를 선언합니다. 
  • xTaskCreate()에서 구동할 Task 함수를 입력합니다. 이때 configMINIMAL_STACK_SIZE는 task에서 사용한 stack의 최소 크기입니다. 그다음 1 이 선언되어 있는데 FreeRTOS의 스레드 동작 우선순위입니다. 1 이면 낮은 우선순위입니다. 저는 1~3까지만 사용합니다. 
  • FreeRTOS가 Task를 제대로 생성면 portBASE_TYPE s = pdPASS를 반환합니다. 이를 반환받지 못하면 펌웨어를 더 이상 진행하지 못하게 while(1)로 처리합니다.
  • 이밖에도 원하는 Task를 설정합니다.
  • 이때까지 스레드는 동작하지 않습니다. vTaskStartScheduler()가 스레드의 동작을 유도합니다.
  • 그러면 vTaskStartScheduler()는 자체의 무한 루프를 돌면서 이하의 다른 코드는 동작하지 않습니다.
  • 그런데 vTaskStartScheduler()가 오동작하면 즉 스레드 동작일 잘못된 경우라면, vTaskStartScheduler() 이후의 코드가 실행됩니다. 그래서 이 부분에 오류를 알리고 무한 루프로 동작해서 펌웨어가 구동하는 것을 막습니다.
  • 여기서 중요한 부분 중에 하나가 loop() 함수인데 특별한 경우가 아닌 한 이곳에 코드를 입력하지 않아야 합니다. loop()에서 해야 할 일을 task들로 정의해서 사용해야 합니다.  
#include <FreeRTOS_AVR.h>

static void Task_LED(void* arg);

setup(){
	//- LED
	pinMode(LED_BUILTIN,OUTPUT);
    digitalWrite(LED_BUILTIN,LOW);
    //- task
    portBASE_TYPE s = xTaskCreate(Task_LED,NULL,configMINIMAL_STACK_SIZE,NULL,1,NULL);
	if(s != pdPASS){while(1){;}}
    //- task run
    vTaskStartScheduler();
    //- task error
	Serial.println("FreeRTOS Error.");
	while(1){;}
}

loop(){
}

void Task_LED(void* arg){
	//- task loop time 
 	long loop_delay_ms = 500L * (long)configTICK_RATE_HZ/1000L; 
	//- led state
    int _led_state = LOW;
	for(;;){
    	//- task delay
    	vTaskDelay(loop_delay_ms);
    	//- led
        digitalWrite(LED_BUILTIN,_led_state);
     	//- toggle led state
        _led_state = (_led_state==LOW)?HIGHT:LOW;
  	}
}

Task_LED()는 FreeRTOS가 사용 가능한 시간을 골라서 동작하도록 구현됩니다. 이때 조심해야 할 내용이 있는데 현재 Task_LED()에는 특별한 제한 조건이 없어 독립적으로 운영이 잘 될 것입니다. Task_LED()는 크게 보면 네 개의 내용이 조합된 것입니다. 

  • 첫째로 task가 사용할 변수들을 정의하고 설정합니다. 이때 loop_deay_ms로 어떤 주기로 동작할지 결정합니다. 이는 ms 단위의 시간으로 동작합니다.
  • 현재 코드에서 LED의 토글을 위한 변수 _led_state를 하나 정의했습니다.
  • Task_LED()는 펌웨어가 동작하는 한 무한히 LED를 toggle 할 것입니다. 그러므로 for(;;) 또는 while(true)로 무한히 실행하게 만듭니다. 이 부분이 task의 두 번째 부분입니다. 만약 한번 동작하는 task라면 for() 부분이 없습니다.
  • 세 번째 부분인 vTaskDelay()로 task의 동작을 지연하는 것이 아니라, 다른 task가 동작하도록 시간을 할당하는 의미로 봐야 합니다. 이 부분이 없으면 다른 task의 동작이 되지 않거나 반대로 우선순위가 낮은 Task_LED()가 동작 권한을 할당받지 못해 LED가 멈춘 것처럼 보이게 됩니다. 그리고 vTaskDelay()는 for() 바로 다음에 위치하는 것이 좋습니다. 
  • 네 번째 부분은 실제 task가 동작하고자 하는 내용을 작성합니다. 너무 많은 동작 내용을 작성하지 않는 것이 좋습니다. 

광고좀 꾹 눌러주시면 고맙겠습니다. 


위의 내용을 참조용으로만 사용해주세요. 무단 도용이나 무단 복제는 불허합니다.

기타 문의 사항은 gigasound@naver.com에 남겨 주시면 고맙겠습니다.