대부분의 임베디드 시스템들은 시간의 흐름을 관리해야 합니다. 무선 바코드 스캐너는 배터리 시간을 늘리기 위해서 몇 초가 지난 후에는 자동으로 꺼져야 하는 것처럼요. 네트워크 연결을 가지고 있는 시스템들은 전송한 데이터에 대해서 받았다는 응답을 기다려야 하고, 정해진 시간에 응답을 받지 못하면 다시 데이터를 전송해야 합니다. 생산 시스템은 로봇 암이 움직이는 것을 기다리거나 모터가 일정한 속도가 될 때까지 기다려야만 합니다.
대부분의 RTOS가 제공하는 간단한 서비스 중의 하나는 태스크를 일정한 시간 동안 기다리게 하는 함수입니다. 일정한 시간이 될 때까지 대기하기 만든다는 것이죠. 전화를 거는 프로그램을 예시로 들어볼게요.
미국에서는 전화번호의 각 숫자를 1/10초 동안 내보내야 하고, 톤과 톤 사이에 0.1초 동안 침묵을 유지해야 합니다. vMakePhoneCallTask 태스크는 RTOS의 메시지 큐로부터 전화번호를 받습니다. msgQreceive 함수는 큐로부터 전화 번호를 a_chPhoneNumber에 저장합니다. while 루프는 침묵을 유지하기 위해서 태스크 딜레이를 실행시키고 그다음에 전화번호의 각 자리 숫자의 톤을 만들기 위해서 태스크 딜레이를 실행시킵니다. vDialingToneOn 그리고 vDialingToneOff 함수는 톤 발생기를 켜고 끄고 합니다. 여기서 msgQreceive 와 태스크 딜레이 함수는 Vxworks에서 사용되는 것입니다.
[궁금할 수 있는 질문]
태스크딜레이 함수는 인자로 받은 밀리세컨드 동안 지연되나?
아닙니다. 실제로 함수는 그렇게 동작하지 않지요. VxWorks에서 사용되는 태스크 딜레이 함수는 다른 대부분의 RTOS에서 제공하는 시간 지연 함수처럼 인자로 시스템 틱의 개수를 받습니다. 각각의 시스템 틱이 나타내는 시간의 양은 시스템 값을 설정할 때 조정할 수 있습니다.
taskDelay 함수에 의해 얻어지는 시간 지연은 얼마나 정확한가?
시스템 택에 가까운 정확성을 가지고 있습니다. RTOS는 인터럽트를 매 밀리 세컨드마다 주기적으로 발생시키는 하나의 하드웨어 타이머를 이용해서 모든 시간을 맞춥니다. 이러한 타이머를 종종 심장박동 타이머 (하트비트 타이머)라고 부르기도 합니다. 태스크 중의 하나가 태스크 딜레이에 3을 인자로 넘겨주면, 그 태스크는 타이머가 인터럽트를 세 번 발생시킬 때까지 기다립니다. 첫 번째 타이머 인터럽트는 태스크 딜레이 함수를 호출하자마자 발생할 수도 있고, 거의 하나의 틱만큼 시간이 흐린 후에 발생할 수 도 있고, 또는 이 두 극단 사이의 값을 취할 수도 있는 일이죠. 결국에 태스크는 두 개의 시스템 틱보다는 조금 많거나, 세 개의 시스템 틱보다는 조금 적은 시간 동안 기다리게 됩니다. 태스크는 실행되는 것이 아니라 대기 상태에서 벗어난다는 것을 꼭 알아두시고요. 태스크가 실행되기 위해서는 마이크로프로세서를 놓고 경합을 벌이는 다른 높은 우선순위의 태스크가 있느냐 없느냐 여부에 달려 있습니다.
RTOS는 특정 하드웨어에서 어떻게 타이머 하드웨어 장치를 설정하는지 알 수 있나?
임베디드 시스템용 마이크로프로세서에서는 타이머를 내장하는 것이 일반적입니다. 다른 운영 체제처럼 RTOS는 마이크로프로세서에 의존적이라서 엔지니어는 어떤 종류의 마이크로프로세서를 사용할 것이고, 그래서 어떻게 타이머를 설정할 지를 알토스에게 알려줘야만 합니다. 표준이 아닌 타이머 하드웨어를 사용할 경우 그 장치를 위한 타이머 설정 프로그램과 타이머 인터럽트 루틴을 직접 작성해야만 합니다. RTOS는 타이머가 설정한 시간에 이르렀을 때마다 인터럽트 루틴이 실행시키는 시작점을 가지고 있습니다. 많은 RTOS 제조사들은 타이머 같은 일반적인 하드웨어를 지원하는 드라이버들은 가지고 있는 보드 지원 패키지나 BSP라고 불리는 소프트웨어를 제공하고, 또 사용하는 특정한 하드웨어를 위한 드라이버를 작성할 수 있도록 명령어들이나 드라이버 모델을 제공합니다.
시스템 틱의 일반적인 길이는 얼마일까?
한 가지로 정해진 것은 없습니다. 짧은 시스템 틱의 장점은 시간의 정확도를 더 높일 수 있다는 거죠. 단점은 마이크로프로세서가 자주 타이머 인터럽트 루틴을 실행시켜야만 한다는 겁니다. 시스템 틱을 제어하는 하드웨어 타이머는 태스크가 타이머 서비스를 필요로 하든 말든 항상 실행되고 있기 때문에, 짧은 시스템 틱은 타이머 인터럽트 루틴 수행으로 인한 마이크로프로세서의 시간 소모를 증가시켜서, 결국에는 시스템의 가능한 작업 처리 양을 줄이게 되는 결과를 낳습니다. 실시간 시스템을 설계하는 엔지니어들은 이에 대한 트레이드 오프 관계를 늘 염두에 둬야 합니다.
시스템이 최고로 정확한 시간을 필요로 한다면 어떻게 해야할까?
두 가지 중에 선택 가능한 문제입니다. 첫 번째는 시스템 틱을 충분히 짧게 만들어서 알토스의 시간 정확도를 필요한 조건을 충족시킬 수 있도록 향상하는 것입니다. 다른 하나는 다른 하드웨어 타이머를 사용해서 정확한 시간을 필요로 하는 곳에 사용하는 겁니다. 소수의 정확한 시간을 위해서 전용 타이머를 사용하고 그렇게 정확한 시간을 필요로 하지 않는 다른 곳에는 RTOS의 시간 관리 기능을 사용하는 것은 흔하지 않다고만 볼 수 있는 일은 아닙니다. RTOS 시간 관리 기능을 사용하는 장점은 하나의 하드웨어 타이머로도 동시에 많은 수의 작업을 처리할 수 있다는 데 있거든요.
[그 외 타이밍 서비스들은]
대부분의 RTOS는 시스템 틱에 기반하는 많은 타이밍 서비스들을 제공합니다. RTOS는 태스크가 얼마나 오랜 기간 큐나 메일박스로부터 메시지를 기다려야 하는지 또는 얼마나 오랫동안 세마포어를 기다려야 하는지 등을 프로그래머가 제한할 수 있도록 합니다 이런 서비스들이 때때로 유용하더라도, 주의를 해야 합니다. 높은 우선순위의 태스크가 세마포어를 가지려고 한다면 제한 시간을 설정해 놓으면 제한 시간이 다 된 경우에 세마포어를 얻지 못해서 공유 데이터에 접근을 하지 못합니다. 결국에 태스크가 세마포어를 되찾을 수 있도록 코드를 작성해야 하지요. 태스크가 데이터를 사용해야만 하는데 사용할 수 없는 경우를 다루는 코드를 작성하는 건 굉장히 번거로운 작업입니다. 그러니 코드를 다시 작성하기 전에 더 나은 설계가 없는지를 찾아보는 것이 좋겠지요. 높은 우선 순위의 태스크가 세마포어를 기다릴 수 없을 정도로 급하다면, 메일박스를 통해서 공유 데이터를 사용하는 데 필요한 명령어를 낮은 우선 순위의 태스크에 보내고 높은 순위의 태스크는 다른 일을 하도록 하는 것이 더 좋은 방법이 되겠습니다.
다수의 RTOS에서 제공하는 더 유용한 서비스는 주어진 개수만큼의 시스템 틱이 지난 후에 프로그래머가 선택한 함수를 호출하도록 하는 겁니다. 알토스마다 타이머 인터럽트 서비스 루틴이 직접 함수를 호출하는 경우도 있고 RTOS 안에 있는 높은 우선 순위의 특별한 태스크가 함수를 호출하기도 합니다. 이 기능이 왜 유용했는지를 알아보기 위해서 코드를 살펴보죠. 이 코드는 전파를 송수신하는 하드웨어 장치를 다루기 위한 것이고 때때로 장치를 켜기도 끄기도 합니다. 장치를 끄는 것은 간단합니다. 파워를 단순히 차단하기만 하면 됩니다. 장치를 켜는 것은 몇 단계를 거쳐야 합니다. 우선, 기본적인 하드웨어 장치에 전원을 공급해야 합니다. 이후에 12밀리 세컨드를 기다리고 시스템은 장치의 주파수를 설정해야 합니다. 그리고 3밀리 세컨드를 더 기다린 후에 시스템이 송신기와 수신기를 켜면 비로소 장치를 사용할 수 있게 됩니다.
VxWorks에서 사용되는 함수 중 wdStart는 타이머를 구동시키는 기능을 합니다. 2~4번째 인수들은 각각 타이머가 종료되기까지의 밀리세컨드 단위의 시간과 타이머가 종료되면 호출될 함수와 그 함수에 넘겨줄 인자의 값입니다. vRadioControlTask가 메시지로 다른 태스크가 송신기나 수신기를 켜고 싶다는 것을 나타내는 T 또는 R 값을 받았을 때, 태스크는 먼저 기본적인 하드웨어 장치를 켭니다. 그러고 나서 wdStart를 호출해서 타이머를 구동시킵니다. 12밀리 세컨드 후에 타이머가 종료되면 RTOS는 vSetFrequency를 호출하고, 이때 wdStart를 호출할 때 사용한 인자 값을 이 함수에 넘겨서 호출합니다. vSetFrequency는 주파수를 설정하고 vTurnOnTxorRx를 호출할 때 함수는 상황에 따라 적절히 송신기나 수신기를 켜고 장치가 준비되었음을 알리는 메시지를 태스크에 보냅니다.
'IT > 임베디드 시스템' 카테고리의 다른 글
RTOS 내에서 인터럽트 루틴 규칙 (0) | 2020.06.09 |
---|---|
RTOS에서의 이벤트와 메모리 관리 (0) | 2020.06.09 |
파이프 - 큐와 비슷하지만 다른 변형들 (0) | 2020.06.06 |
메시지큐 / 메일박스 : 또 다른 수단 (0) | 2020.06.06 |
세마포어의 용도/종류/문제 그리고 공유데이터 보호 방법 (0) | 2020.06.03 |
댓글