하드웨어/STM32(FreeRTOS)

5.STM32 FreeRTOS - preemptive, non-preemptive 설정하기

여동동 2021. 10. 20. 11:16

 

1. preemptiveRTOS

스케줄러는 특정 시간에 실행해야하는 작업 결정에 대한 책임 커널의 일부입니다. 커널은 작업 수명 동안 여러 번 작업을 일시 중단했다가 나중에 다시 시작할 수 있습니다.

스케줄링 정책은 특정 시점에서 실행하는 작업을 결정하는 스케줄러에 의해 사용되는 알고리즘이다. (비실시간) 다중 사용자 시스템의 정책은 각 작업에 프로세서 시간의 "공정한" 비율을 허용할 가능성이 큽니다. 실시간/임베디드 시스템에서 사용되는 정책은 후술한다.

커널에 의해 비자발적으로 일시 중단되는 것 외에도 작업은 스스로를 일시 중단하도록 선택할 수 있습니다. 고정된 기간 동안 지연( sleep )하거나 리소스가 사용 가능하게 되거나(예: 직렬 포트) 이벤트가 발생할 때(예: 키 누름) 대기( 차단 )하려는 경우 이 작업을 수행합니다. 차단되거나 대기 중인 작업은 실행할 수 없으며 처리 시간이 할당되지 않습니다.

위 다이어그램의 숫자를 참조하면 다음과 같습니다.

  • (1)에서 작업 1이 실행 중입니다.
  • (2)에서 커널은 작업 1을 일시 중단(스왑 아웃)합니다 ...
  • ... 그리고 (3)에서 작업 2를 재개합니다.
  • 작업 2가 실행되는 동안(4), 자체 독점 액세스를 위해 프로세서 주변 장치를 잠급니다.
  • (5)에서 커널은 작업 2를 일시 중단합니다 ...
  • ... 그리고 (6)에서 작업 3을 재개합니다.
  • 작업 3은 동일한 프로세서 주변기기에 액세스하려고 시도하지만 잠긴 것으로 확인된 작업 3은 계속할 수 없으므로 (7)에서 자체적으로 일시 중단됩니다.
  • (8)에서 커널은 작업 1을 재개합니다.
  • 등.
  • 다음에 작업 2가 실행될 때(9) 프로세서 주변기기를 완료하고 잠금을 해제합니다.
  • 다음에 작업 3이 실행될 때(10) 이제 프로세서 주변 장치에 액세스할 수 있고 이번에는 커널에 의해 일시 중단될 때까지 실행됩니다.

 

Timer Tick간격 마다 CPU점유권을 나누어 주는 방식.

장점 : task가 공정하게 cpu를 점유한다.

단점 : task 실행도중 cpu점유권이 이탈될수 있다.

 

 

2. NON preemptive RTOS

 

차이는 cpu를 마음껏 쓰고 양도하는 방식이다.

 

 

3. 코딩하기

3-1. freeRTOSConfig.h 설정

#define configUSE_PREEMPTION 0 // 0 : non preemptive, 1 : preemptive
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configCPU_CLOCK_HZ ( SystemCoreClock )
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 ) // Tick Timer
#define configMAX_PRIORITIES ( 5 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 130 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 75  * 1024 ) )
#define configMAX_TASK_NAME_LEN ( 10 )
#define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1

스케쥴러의 설정을 define해준다.

 

3-2. task1 , task2(Preemptive 방식)

void task1_handler(void* parameters)
{
while(1)
{
      printf("%s\n", (char*)parameters);
}
      vTaskDelete(NULL);
}

void task2_handler(void* parameters)
{
while(1)
{
    printf("%s\n", (char*)parameters);
}
vTaskDelete(NULL);
}

3-2-1. Preemptive 결과

Hello world from Task-2
 Task-2
Hello world fHello world from Task-1
Hello rom Task-2
Hello world from Task-2
Hello world froworld from Task-2
Hello world from Task-1
Hello wom Task-1
Hello world from Task-2
Hello world from rld from Task-2
Hello world from Task-1
Hello worlTask-1

systick 간격마다 cpu를 강제로 양도하고 넘겨줘서 printf출력이 뒤죽박죽 꼬였다.

 

freeRTOSConfig.h파일에서 #define configUSE_PREEMPTION 1 <-- 으로 변경 후 똑같이 Test했다.

 

3-2-2. non - Preemptive 결과

Hello world from Task-2
Hello world from Task-2
Hello world from Task-2
Hello world from Task-2
Hello world from Task-2
Hello world from Task-2
Hello world from Task-2

하나의 task가 cpu점유권을 가져가서 cpu점유권을 안준다.

 

4. cpu 선점 양도하기

non - Preemptive 상태에서  taskYIELD()를 쓰면 된다.

 

4-1. 소스코드

void task1_handler(void* parameters)
{
while(1)
{
      HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_14);
      printf("%s\n", (char*)parameters);
      taskYIELD(); //cpu점유권 양도
}
      vTaskDelete(NULL);
}

void task2_handler(void* parameters)
{

while(1)
{
       printf("%s\n", (char*)parameters);
       taskYIELD(); //cpu점유권 양도
}
       vTaskDelete(NULL);
}

4-2. 결과

Hello world from Task-1
Hello world from Task-2
Hello world from Task-1
Hello world from Task-2
Hello world from Task-1
Hello world from Task-2
Hello world from Task-1
Hello world from Task-2
Hello world from Task-1
Hello world from Task-2
Hello world from Task-1
Hello world from Task-2
Hello world from Task-1
Hello world from Task-2
Hello world from Task-1
Hello world from Task-2
Hello world from Task-1
Hello world from Task-2
Hello world from Task-1
Hello world from Task-2

사이좋은 Task가 되었다.