본문 바로가기
Clock tick ISR - Timer Service

Embedded System에서 중요한 요소 중 하나가 Clock tick ISR이에요. Clock tick ISR이라는 게 무엇이냐? 하면, 정해진 시간에 한번씩 ISR이 걸려 주는 거지요. 이런 정해진 시간에 한번씩 주기적으로 걸려주시는 ISR은 무엇에 사용 가능할까요. Clock tick isr이 뜰 때 마다 System은 시간이 얼마나 흘렀는지를 알아 낼 수 있사옵니다. 얼마나 흘렀는지를 알 수 있다는 말은 특정시간 후에 뭔가 일을 시키고 싶을 때, 그것도 가능하다는 말이 되지요. Clock tick ISR은 우리가 곧바로 이용하는 건 아니고, Clock tick ISR을 이용한 Kernel Service가 있어요. 그게 우리가 흔히 아는 Timer Service라는 건데요. 이게 어떻게 구성되는지 한번 알아볼까요?
 
보통 Timer Service를 사용할 때는 Call back Function, 다음에 호출될 시간을 그 Parameter로 주지요. 예를 들어 clk_register라는 함수가 있다고 치시죠.   clk_register (key_polling, 100); 이라고 하면 100mS후에 key_polling() 함수가 호출되게 하여라 라고 해석하면 무리가 없습니다. 그럼 도대체 이런 Kernel Service는 어떻게 이런걸 100mS 후에 호출해 주는 걸까요. 그 비밀이 Clock tick ISR에 숨어 있는 것이죠.
 
Clock tick ISR은 System마다 얼마 만에 걸리느냐가 다르긴 한데, 5mS가 보통 많이들 쓰는 경우니까, 이 경우에 대해서 한번 들여다 보죠 뭐. Clock tick ISR은 Clock tick interrupt가 걸릴 때 마다 호출되는 Interrupt Service Routine이지요. 그러니까 Clock tick ISR은 5mS마다 한번씩 불리면서 뭔가를 하게 되지요. Clock tick ISR은 크기 두 가지 일을 하게 되지요. 하나는 Clock tick ISR이 한번 불릴 때 마다 clk_register()를 통해서 register된 call back function의 시간을 5mS씩 빼주는 거지요. 그리고 두 번째는 시간을 5mS를 빼고 보니 시간이 0이 되는 녀석들이 있겠죠. 이 녀석들은 실행될 시간이 다 된 거에요. Expire되었다는 전문용어를 쓰기도 한답니다. 0이 되어 Expire된 녀석들은 Clock tick ISR에서 등록된 call back function을 직접 실행해 버리는 거에요. 그러면 시간이 다 된 call back function들은 시간에 맞추어서 실행이 되겠지요.
 
이런 걸 어떤 식으로 구현하느냐 하면 또 linked list를 이용해 먹는 거에요. Linked List에 Call back을 등록하는 거에요. 원래 Linked List에는 시간이 얼마 남지 않은 순으로 call back들이 연결되어 있고요. 지금 register하는 Call back은 남은 시간 순서로 되어 있는 linked list에 자기 시간에 맞는 자리에 insert되고요. 5mS마다 호출되는 Clock tick ISR은 이 linked list를 처음부터 끝까지 따라가면서 5mS씩 빼주는 거죠. 5ms 를 빼려고 하다 보면, 앞쪽에 expire된 call back function들이 나타날 텐데, 이 녀석들을 하나씩 실행 해 주고요, 실행이 된 call back function은 list에서 빼버리는 거에요.
 
뭐 간단하죠?
 
그리고 다른 종류의 Timer Service가 있는데, set_timer (dsp_task, CALC_SIG, 10mS) 이런 식의 함수가 있다고 치면, 어디다가 쓰는 걸까 한번 상상해 보세요. 이건 10mS이후에 CALC_SIG라는 signal을 dsp_task에게 날려줘라 라는 의미로 해석하시면 무리 없습니다. 이런 건 어떻게 구현하느냐 , Clock tick ISR을 이용하는 건 똑~ 같습니다. 대신에, 해주는 일이 send_signal (dsp_task, CALC_SIG)를 10mS 후에 실행한다 뿐이죠. 보통 call back함수는 직접 함수만 실행되고 말지만, 이걸 이용하면, 특정 task에게 특정 시간 후에 일을 시킬 수 있는
차이점이 있지요. 이런 Timer service를 이용한 예 가운데 재미있는 예가 있는데, 보통은 Task가 일을 하다가 잠시 쉬어야 할 때를 Task를 Sleep시킨다고 하는데, 잠시 쉴 뿐만 아니라, 다른 Task들에게 CPU점유권을 줘야 하는 경우에 이런 Timer service를 이용한 트릭을 쓰기도 하지요.
 
Task_Sleep()라는 함수가 그런 일을 한다고 하면,
 
 
void Task_Sleep(시간)
{
    set_timer (호출한 자기 자신, WAKE_UP_SIG, 시간);
    wait_signal(WAKE_UP_SIG)
}
 
요렇게 해 놓으면 일단 wait_signal() 함수 덕에 CPU의 점유권을 양보하고요, 일정시간이 되면 자기 자신한테 다시 WAKE_UP_SIG를 날리도록 설정해 놓은 거죠. 그럼 일정 시간 이후에 WAKE_UP_SIG를 받고 다시 Ready 상태가 되어 일을 할 수 있게 되는 원리 랍니다. 대신에 Ready가 된 후에 Running이 될 때 까지는 시간의 오차가 있을 수 있으니, 그건 감안해 줘야 하겠지요.

Linked at 친절한 임베디드 시스템 개발자.. at 2009/10/01 12:45

... ⓚ Clock Tick ISR - Timer Service ... more

Commented by 고스 at 2009/08/25 13:18
RTOS의TaskSleep기능을 사용하고 있는 소프트를 OS없는 시스템에 포팅할때도
좀 고생했습니다. ==;; 커널 기능 사용하는 함수에 너무 의존하면 안되겠다 라는 생각을 하게 되었죠.

OS가 있으면 참 편안한 것도 사실이지만 Task간의 우선순위도 생각해야 되고..
잘모르는 OS위에서 돌아가는 어플리를 만들려면 고려해야 할것도 많고..
일장 일단이 있는거 같네요.
Commented by 히언 at 2009/08/26 20:32
글쵸.. ㅋ 그런 의미에서.. 원래 어떤 OS에서 구현된 건지 알아볼 필요도 있고, OS Kernel Service에 대한 Concept이 필요한 거 같아요. 그런~ 경험 있으면~ 알려주세요~
※ 이 포스트는 더 이상 덧글을 남길 수 없습니다.
친절한 임베디드 시스템 개발자 되기 강좌 글 전체 리스트 (링크) -



댓글





친절한 임베디드 개발자 되기 강좌 글 전체 리스트 (링크) -