CPU가 쉴 틈 없이 while(1)을 도는 스핀락(Spinlock)의 낭비를 막기 위해, 스레드 스스로 "나 1초 동안 기절할 테니까, 내 차례 건너뛰고 다른 애들 먼저 실행시켜 줘!"라고 운영체제에 양보하는 우아한 기술입니다.
void Task(void){
InitializationStuff();
while(1){
PeriodicStuff();
OS_Sleep(ONE_SECOND); // go to sleep for 1 second
}
}
void Scheduler(void){
RunPt = RunPt->next; // skip at least one
while((RunPt->Sleep)||(RunPt-> blocked)){
RunPt = RunPt->next; // find one not sleeping and not blocked
}
}
교수님이 슬라이드 하단에 적어둔 글은 "이 코드가 실전에서 왜 터질 수밖에 없는가?"를 경고하는 내용입니다. 서술형 출제 1순위입니다.
Exam Keyword: "Cannot let all threads sleep; requires an Idle Thread."
만약 시스템에 있는 모든 스레드가 동시에 OS_Sleep을 호출해서 전부 다 자버리면 어떻게 될까요?
스케줄러의 while 루프는 조건이 영원히 참(True)이 되어 무한 루프(Infinite loop)에 빠지고, 시스템이 완전히 다운(Crash)됩니다.
해결책: 절대 잠들지 않고, 절대 Block되지 않는 잉여 스레드인 Idle Thread를 무조건 하나 만들어 두어야 이 참사를 막을 수 있습니다.
Exam Keyword: "A periodic background task (e.g., SysTick ISR) is needed to decrement the Sleep counters."
스레드는 스스로 자면서 자기 카운터를 줄일 수 없습니다. 따라서 백그라운드에서 주기적으로(예: 1ms마다) 울리는 하드웨어 타이머(SysTick)가 모든 TCB를 순회하며 Sleep 카운터를 1씩 깎아줘야(Decrement) 합니다. 카운터가 0이 되는 순간, 그 스레드는 잠에서 깨어납니다.
Exam Keyword: "Sleep parameter reaching 0 makes the thread Ready, not Running. This introduces scheduling delay (Jitter)."1초를 자겠다고 OS_Sleep을 호출했지만, 1초 뒤에 정확히 바로 실행되는 것이 아닙니다!카운터가 0이 되면 스레드는 '기절(Sleep)' 상태에서 '준비 완료(Ready)' 상태로 바뀔 뿐입니다. 내 차례가 올 때까지 현재 돌고 있는 다른 스레드들의 작업이 끝나기를 쳇바퀴(Round-robin) 줄에서 기다려야 합니다.만약 내 앞에 대기 중인 스레드가 개 있고, 한 스레드당 쓰는 시간이 라면, 내가 진짜로 깨어나서 코드를 실행하기까지 만큼의 오차 시간(Delay/Jitter)이 추가로 발생하게 됩니다. (이것이 RTOS에서 예측 가능성을 해치는 가장 큰 원인 중 하나입니다.)

타이머를 '알람시계'라고 생각하시면 완벽하게 이해됩니다.
N-bit counter: 설정된 시간부터 0까지 거꾸로 숫자를 세는(Count down) 핵심 부품입니다. 0이 되면 Trigger flag를 띄우고 새로운 값으로 재장전(Reload)됩니다.
Reload value (R): 알람을 맞추는 '시간 설정 값'입니다. 카운터가 0이 되면 이 R 값이 다시 카운터로 장전됩니다. (소프트웨어 초기화 시 딱 한 번 상수로 설정됨)
Trigger flag: 카운터가 0에 도달했을 때 "알람 울렸다!"라고 CPU에게 알리는 깃발입니다. 이 깃발이 인터럽트(Interrupt)를 요청하며, ISR 내부의 소프트웨어가 반드시 이 깃발을 지워줘야(Clear) 다음 알람이 정상 작동합니다.
Base clock: 타이머가 돌아가는 기본 속도입니다. 주파수(, 예: 80MHz)와 주기(, 예: 12.5ns)를 가집니다.
Prescaler (M): Base clock이 너무 빨라서 타이머가 순식간에 끝나버리는 것을 막기 위해, 톱니바퀴 기어처럼 클럭을 배 느리게 쪼개주는(Modulo-M) 감속기입니다.
교수님이 "원하는 인터럽트 주기(P)를 얻기 위해 Reload value(R)를 얼마로 설정해야 하는가?"를 묻는 계산 문제를 낼 확률이 99%입니다. 이 공식들은 치트 시트 구석에 꼭 적어가세요.
인터럽트 주기 (Interrupt Period, P):
(카운터가 R부터 0까지 세기 때문에 총 R+1 번의 카운트가 발생합니다.)
리로드 값 구하기 (Reload Value, R):
위 공식을 R에 대해 정리한 것입니다. 코드에 직접 넣어야 하는 값입니다.
(단, R은 타이머 비트 수에 따라 보다 작은 정수여야 합니다.)
최대 CPU 점유율 (Maximum Utilization):
ISR이 실행되는 데 걸리는 최대 시간()이 전체 주기()에서 차지하는 비율입니다. 하나의 ISR이 CPU를 독점(Monopolizing)하지 못하게 방지할 때 계산합니다.
이 부분은 RTOS 스케줄링 이론과 섞여서 서술형이나 True/False 문제로 자주 나옵니다.
이 부분은 빈칸 채우기 코딩 문제로 나올 수 있습니다. 순서의 논리를 기억하세요.