OS를 만듭시다. 어때요~ 참 쉽죠? (5)

나빌레라의 이미지

OS. 영어로 풀어서 Operating System. 한자어로 번역해서 운영체제. 이것을 만든다고 하면 사람들은 굉장히 어렵게 생각한다. 리눅스나 윈도우같은 OS를 비교대상으로 본다면 OS를 만드는것은 정말 어렵고 힘들고, 개인이 만들기엔 어쩌면 불가능에 가까운 도전일지도 모른다. 하지만 OS의 기본 개념들은 대학교 학부과정에서 가르칠 정도로 이미 보편화 되어 있고 그 개념 자체들은 그다지 어렵지 않다. 개념 구현을 중심으로 동작하는 것 자체에 의미를 둔 OS를 만드는 것은 어쩌면 도전 해 볼만 한 가치가 있는 시도가 아닐까.

목차


1회
2회
3회
4회

5. OS timer 활성화 하기

한번 지나가 버리면 다시 되돌릴 수 없기에 지나감이 더욱 아쉬웁고, 우리에게 주어진 양은 정해져 있는데 우리는 무의미하게 흘려보내기만 하는 것이 시간이다. 우리는 비록 시간을 무의미하게 흘려보낼 지언정 OS는 시간을 무의미하게 사용하지 않는다. 시간이 지남에 따라 정해진 많은 일들을 한다. 그러기 위해서는 OS에서 시간을 알아야 한다.

시간을 알아야 한다고 해서 지금이 몇년 몇월 몇시 몇분인지 인것 보다는, 규칙적으로 시간을 알려주는 매커니즘이 필요하다. 1초마다 혹은 0.1초마다 혹은 정해진 어떤 시간마다 OS에게 이만큼의 시간이 지났소! 하고 알려주어야 그 흘러간 시간에 맞추어 OS는 동작하게 된다.

누가 알려주는가! 바로 ARM프로세서가 알려준다. 좀더 정확히는 ARM 이 알려주는게 아니라 ARM코어에 붙은 타이머장치가 알려준다. 즉 이번 경우에는 ARM에 대한 이해 보다는 pxa255에 대한 이해가 좀 필요 할듯하다.

이번 강좌를 읽기 전에 우선 준비해야 할 준비물이 있다. 바로 이지보드에서 사용하는 pxa255칩의 메뉴얼이다. 이지보드의 제작사인 falinux에서는 홈페이지에 친절하게 이지보드에 사용한 주변장치들의 데이터 시트를 모아서 홈페이지 다운로드 페이지에 제공하고 있다. 개별적으로 데이터시트를 찾기 위해 돌아다닐 필요가 없다. 직접 접속해서 다운로드하는 것도 귀찮다면 아래 링크를 누르면 된다. 다만 제작사 홈페이지가 리뉴얼 되거나 하면 연결이 안될 가능성이 있다.

http://forum.falinux.com/_zdownload/data/datasheet.zip

받아서 압축을 풀어보면 pdf 파일이 많이 보인다. 그중 [PXA255] developer_manual.pdf 파일을 열어본다. 내용이 좀 많다. 영어다. 하지만 전부다 안본다. 필요한것만 볼것이다. 일단 열어놓고 있자. 이 파일은 이후에 그냥 '데이터시트' 라고 부르겠다.

타이머는 주기적으로 동작하기 때문에 타이머 이다. 주기적으로 동작한다는 것은 그전에 뭐가 실행중이건 상관없이 타이머가 떠야 할 시점엔 떠야 한다는 것이다. 그렇다. 타이머는 인터럽트로 구현되어야 한다. 그래야만 다른 프로그램(함수,테스크)가 동작중이더라도 중간에 타이머 처리를 하고 다시 이전에 동작하던 프로그램으로 돌아갈 수 있다. 하지만 타이머 인터럽트는 swi 로 만들어내는 소프트웨어인터럽트와는 달리 일종의 외부 인터럽트 중 하나 이다. 그래서 IRQ Exception 으로 처리 할 것이다.

pxa255를 비롯한 왠만한 mcu 에서는 다들 타이머를 지원한다. 여기서 갑자기 나타난 mcu 라는 건 또 뭔가 하시는 분도 계실것이다. 없나? 흠.. 암튼, 프로세서, cpu, mcu, 컨트롤러 이런 용어들은 그냥 뭉뚱그려서 다들 중앙처리장치 비슷하게 생각해버리면 되지만 조금씩 미묘하게 틀리다. 그래서 필자도 ARM 과 pxa255 를 구분해서 서술하고 있다. 지금쯤이면 필자의 스타일을 이해 하셨을 분도 있을 것이다. 강좌와 직접 관계없는 내용은 쓰지 않는다. 검색하면 많이 나온다.

pxa255는 별도의 타이머 외에 OS타이머라는 걸 또 지원해 준다. 아마 OS에서 쓰라고 만들어 놓은 것 같다. 쓰라고 만들어 놨으니 써야 예의아니겠는가. 이제부터 pxa255칩의 OS타이머를 활성화 하는 방법을 차근 차근 보자.

데이터시트의 4.2절을 보자. 인터럽트 컨트롤러에 대한 내용이 나온다. 타이머는 어찌되었던 인터럽트로 처리된다고 하였다. 그럼 우선 타이머를 보는것에 앞서 인터럽트 부분을 봐야 할 것이다.

데이터시트의 해당부분에 보면 ICCR, ICMR, ICPR, ICIP, ICFP, ICLR 등 인터럽트에 관계하는 많은 레지스터들의 내용이 나온다. 그리고 데이터시트의 Figure4.2를 보면 그 모든 내용을 하나의 블럭다이어그램에 아름답게 그려 놓았다. 해당 그림을 따다가 본 문서에 넣고 싶지만 그렇게 하나 둘 그림 넣다 보면 나중엔 그림 그리다가 글쓸 시간 다 잡아먹게 된다. 불편하시더라도 웹브라우져 뒤에 pdf 뷰어 하나 띄워 놓고 읽으시라.

pxa255에서는 인터럽트가 발생했다고 그 모든 인터럽트들이 전부다 인식되는 것이 아니라 앞절에서 설명한 레지스터들의 설정값에 따라서 몇단계를 거치고 나서야 프로세서(ARM)로 전달된다.

먼저 pxa255에 인터럽트가 감지되면 해당 인터럽트는 무조건 ICPR(Interrupt Controller Pending Register) 에 기록된다. 그런다음 ICCR(Interrupt Controller Control Register) 의 0번 비트가 0 이고 Idle Mode가 1인 상태에서 해당 인터럽트 비트가 ICMR(Interrupt Controller Mask Register)에 1로 마스킹되어 있을때에 그 첫단계를 지나가게 된다.

다음 단계에서 이제 이 인터럽트가 IRQ 로 인식될것인지 FIQ로 인식될것인지를 결정짓게 된다. 그것을 결정하는 것이 ICLR(Interrupt Controller Level Register)이다. ICLR의 해당비트가 0이면 앞단계를 통과한 인터럽트는 IRQ로 인식되고, 1이면 FIQ로 인식된다. 그리고 IRQ로 인식되었다면 ICIP(Interrupt Controller IRQ Pending register) 에 최종적으로 기록되고, FIQ로 인식되었다면 ICFP(Interrupt Controller FIQ Pending register) 에 기록된다.

선택적으로 IRQ 나 FIQ로 등록되고 나면 비로소 프로세서로 인터럽트가 전달되게 되고, IRQ 냐 FIQ 냐 에 따라 Exception Vector Table 로 흐름이 점프하게 되고 이후로는 이전강좌에서 설명했던 과정을 거쳐서 개발자가 설정해 놓은 위치에 있는 핸들러 함수로 진입하게 된다.

다시 데이터시트를 쭉쭉 스크롤 내려 보자. 먼저 ICMR에 대한 설명이 나온다. 8번비트 부터 14번 비트까지, 17번부터 31번까지 총 22개의 인터럽트를 pxa255 칩은 처리 할 수 있는 듯 하다. 어느 mcu 나 interrupt mask register는 하는 일이 같다. 해당 비트를 set(1 로 함) 하는 인터럽트만 통과 시키고 나머지 인터럽트는 프로세서가 받아들이지 않는다.

다음으로 나오는 레지스터는 ICLR 레지스터이다. ARM 은 인터럽트를 IRQ 와 FIQ두 종류로 사용한다. FIQ는 좀더 빠른 처리를 요구하는 인터럽트를 처리 할 때 사용한다. 간단하게 인터럽트를 처리하고자 하는 비트를 0으로 하면 해당 인터럽트는 IRQ로 동작하고, 1로 하면 FIQ로 동작한다. 나빌눅스는 FIQ를 사용하지 않는다. 그러므로 이 레지스터는 그다지 고민할것 없이 그냥 모든 비트를 0 으로 해 놓으면 된다.

다음으로 ICCR이 나온다. ICCR은 인터럽트 자체를 사용할것인지 아닌지를 결정하는 레지스터이다. 사용하는 비트도 최하위 1비트 (0번비트) 뿐이다. 0 으로 세팅하면 인터럽트를 사용할 수 있다.

ICFP 와 ICIP는 인터럽트 계층에서 가장 뒤쪽에 위치하는 최종 pending register 이다. 비트 구성은 ICMR과 같고 해당 비트에 바인딩되는 인터럽트가 IRQ모드일 경우에는 ICIP에 FIQ모드일경우에는 ICFP에 세팅된다. 다시 말하지만 나빌눅스는 FIQ는 사용하지 않기 때문에 ICFP는 신경 쓸 필요 없다. 이후에 나올것이지만 IRQ 핸들러 함수에서 실제 어떤 인터럽트가 발생했는지를 알아내기 위해서 ICIP 레지스터를 사용한다.

ICPR 은 ICMR과 상관없이 인터럽트가 발생하면 무조건 기록되는 레지스터 이다. 데이터시트에는 ICPR에 와서야 각 비트가 어떤 인터럽트에 바인딩 되어 있는지를 알려준다. 데이터시트의 Table 4-36을 잘 보자. 위쪽에 보면 26번 비트부터 29번 비트까지 총 4개의 인터럽트가 OS timer 에 할당되어 있다. 타이머를 무려 4개나 제공한다. 본 강좌에서 언급하진 않겠지만 Real time clock 까지 포함하면 타이머관련해서만 무려 6개의 인터럽트를 제공한다. 타이머가 중요하긴 중요한건가 보다 이렇게 많이 제공해 주는 걸 보니.

그럼 이제 우리가 할 일은 4개의 OS timer 중에서 어떤걸 골라서 쓸까 하는 것이다. 뭐 그냥 생각할 것 없이 0번 쓰면 되지 않겠느냐 하겠지만 그전에 먼저 생각해 볼것이 있다. 우리는 이미 msleep() 이라는 함수를 이지부트 소스로 부터 가져다 쓰고 있다. msleep() 함수는 인자로 밀리초단위의 값을 받아서 해당 시간 만큼 딜레이 한 다음 리턴한다. 분명 내부에서 타이머를 사용하고 있다. 그러므로 msleep()이 내부에서 어떤 타이머를 사용하고 있는 지를 먼저 알아 보아야 한다.

msleep() 함수는 어디에 있을까. 별로 고민할 필요 없다. grep으로 찾으면 된다. 그냥 파일 이름만 봐도 왠지 거기 있을 것같은 파일이 있다. 바로 time.c 이다. 열어서 msleep() 함수를 찾아보자.

void 	msleep(unsigned int msec)
{
        ReloadTimer( 0, msec );
        while( 0 == TimeOverflow(0) );
        FreeTimer( 0 );
}

ReloadTimer() 함수로 바로 인자로 받은 밀리초단위 값을 넘긴다음, TimerOverflow()함수가 0이 아닌 값을 리턴할때 까지 busy waiting 하다가 waiting 이 끝나고 나면 FreeTimer()함수를 해준다. 그럼 이제 ReloadTimer() 함수가 어떻게 생겼는지 찾아가 보자. msleep() 함수 바로 아래에 존재 한다.

void    ReloadTimer( unsigned char bTimer, unsigned int msec )
{
        unsigned long reg;
 
        bTimer &= 0x03;
        reg = (1<<bTimer);
 
        OSSR  = reg;
 
        switch( bTimer )
        {
        	case 0 : OSMR0 = OSCR + (TICKS_PER_SECOND/1000)*msec; break;
        	case 1 : OSMR1 = OSCR + (TICKS_PER_SECOND/1000)*msec; break;
        	case 2 : OSMR2 = OSCR + (TICKS_PER_SECOND/1000)*msec; break;
        	case 3 : OSMR3 = OSCR + (TICKS_PER_SECOND/1000)*msec; break;
        }
 
        OIER = OIER | reg;
}

bTimer 매개변수가 4개의 OS timer중에 어떤걸 쓸지 결정하는 녀석 같다. 그리고 레지스터 이름으로 추정되는 OSSR과 OSCR, OSMR등을 세팅하고 OIER 같은 레지스터에 무슨 작업을 해준다음 끝난다. 이 함수가 정확이 무슨 일을 하는지는 이후에 OS timer 부분 레지스터를 설명하게 되면 명확히 이해 할 것이다. 지금은 그런것 까지 알 필요 없다. 우리가 알고자 하는 것은 msleep() 이 몇번째 OS timer 를 사용하느냐 하는것 하나 뿐이다.

다시 msleep()함수를 보자 ReloadTimer() 함수로 넘기는 첫번째 인자가 0 이다. 즉, msleep() 은 네개의 OS timer 중에서 첫번째 타이머를 사용한다. 그럼 나빌눅스는 그냥 두번째 OS timer 를 사용하자. 어차피 이후에 msleep()을 대체할 sleep()함수를 만들것이긴 하지만 그래도 충돌은 최대한 피해서 작성하는 것이 개발자의 미덕이다.

OS timer 1 번을 사용할 것으로 결정했다. 그럼 이제 어떤 순서로 작업을 하면 1번 OS timer 를 사용 할 수 있을까.

ICMR 부터 거슬러가자 ICPR 에서 봤을 때 27번 비트가 1번 OS timer 에 해당하므로 ICMR의 27번 비트를 1로 세팅해준다. 그러면 마스크가 풀리면서 1번 OS timer 인터럽트는 첫번째 단계를 통과 할 수 있다. IRQ로 사용할 것이기 때문에 ICLR의 27번 비트는 0으로 설정한다. ICCR은 당연히 그냥 0 이다.

자! 준비가 끝났다. 설명은 길게 했지만 저게 다 이다. 윗 단락에 설명한대로 코딩 해주면 된다. 정말이다. 하지만 아직까지 인터럽트에 대한 준비만 끝났을 뿐 정작 OS timer 에 대한 세팅은 하지 않고 있다. 실제 코딩은 OS timer 를 설정 하면서 같이 하자, 다음편에서는 OS timer 관련 레지스터를 설정하고 IRQ 핸들러 코드를 수정해서 주기적으로 타이머 인터럽트가 발생하는 것을 눈으로 확인해 보자.

그렇다.. 코딩은 다음 편에 한다.

이 글은 http://raonlife.com/navilera/blog/view/79/ 에 동시 연재 됩니다.

댓글

bookgekgom의 이미지

이 래슨은 어느정도 까지 갈껀가요?

기대가 됩니다. OS를 만들다니...

---------------------------------------------------------------

허접한 페도라 가이드 http://oniichan.shii.org

---------------------------------------------------------------------------------------------------------------
루비 온 레일즈로 만들고 있는 홈페이지 입니다.

http://jihwankim.co.nr

여러 프로그램 소스들이 있습니다.

필요하신분은 받아가세요.

나빌레라의 이미지

15회에서 20회 사이에 끝날 것 같습니다.

아무리 길어져도 20회는 넘기지 않을 것 같은데..

끝까지 쓴게 아니라 저도 잘 몰라요..^^;
-----
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

ystory의 이미지

허거덩 좋은 강좌 잘보고 있습니다.
이거 무료수강 해도 되나요?
--------------------------------------
Y.S. Kim
mail@ystory.kr

--------------------------------------
으휴

나빌레라의 이미지

무료수강이요?

무슨 말씀이신지...?

---
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

ystory의 이미지

아,,좋은글 그냥 읽기만 해도 되는지 여쭌거예요. ㅎ
아무튼 감사합니다.
--------------------------------------
Y.S. Kim
mail@ystory.kr

--------------------------------------
으휴

나빌레라의 이미지

괜찮습니다...

^^;

읽어주시는 것 만으로도 감사합니다..

더불어 + 하나 클릭~ 해주심 더욱 감사..ㅋ
---
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

saxboy의 이미지

좋은 글 쓰시는군요.
다만 개발보드가 있어야 한다는 제약이 있는데, 실제로 OS의 맛을 보는데는 qemu나 skyeye같은 녀석으로 완전히 소프트웨어만으로 개발하는 것이 따라하기는 조금 더 쉬울 것 같습니다.
나중에 다 끝날때쯤 되시면 에뮬레이션 환경으로 포팅해보시는 것도 괜찮지 않을까요 :-)

나빌레라의 이미지

오~ 괜찮은 의견입니다.

저도 비싼(10만원넘는) 개발보드를 구입하는것을 전제로 쓰는것이 내내 마음에 걸려서..

강좌 끝날때 즈음에..

좀 비싼 이지보드 대신..

한 4~5만원 수준에서 구입할 수 있는

ARM7기반 보드에 포팅을 생각해 봤거든요...

에뮬레이터에 포팅하는걸 생각 못했군요..^^

----
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

wsmrdo의 이미지

부탁드립니다.

지금 강의 하시는 한군데는 나와있군요. ^^*

에뮬레이션 환경이라.... [ qemu나 skyeye같은 녀석으로 ] 어디 있나요... 쩝.
이런거 구하는 곳도 같이좀 부탁드립니다.

쓰다보니 바라기만 하는군요... 이쪽은 워낙 초보라.

필요할 때를 위한 작은 FAQ가 늘 함께 하시길 ....

saxboy의 이미지

구글에서 단어만 치면 바로 연결된답니다. :-)

verimuch의 이미지

설명을 잘해주셔서 이해가 잘되요~

---------------------------------
Life is not fair, Get used to it.

---------------------------------
Life is not fair, Get used to it.

flymc83의 이미지

계속 시간을 거슬러 가는느낌이네요. 잘 읽고 있습니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.