5.STM32 FreeRTOS - preemptive, non-preemptive 설정하기
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가 되었다.