운영체제(Operating System)는 프로그램의 실행관리를 하는 소프트웨어다.
최소한의 구성
을 전제로 최소한의 기능
을 제공한다.하드웨어를 시간에 따라 효율적으로 사용할 수 있기 때문이다.
int main(void)
{
for (;;) {
if (1 초 경과?) {
task_led();
}
if (시리얼 데이터 존재?) {
task_console();
}
}
}
위의 두 기능을 수행하는 프로그램의 경우, 시리얼 데이터가 많지 않은 상황에선 정상적으로 잘 동작할 수 있으나 만일 시리얼 데이터가 연속적으로 들어오게 되는 경우 처리 시간의 지연이 발생할 수 있다.
단순히 LED 를 끄고 켜는 기능의 경우 약간의 지연이 발생해도 큰 문제가 발생하지 않지만, 우주선, 비행기, 핵 발전소 등에서 사용되는 시스템의 경우 0.1 초의 지연도 매우 민감한 사항으로 작용할 수 있다.
위 예제를 올바르게 동작시키기 위해선 시리얼 콘솔의 처리와 LED 처리를 나누어 시간 분할을 실시하고, 우선 선위를 부여해 올바른 시간제약이 지켜질 수 있도록 스케줄링하는 기능이 필요하다.
이러한 역할을 수행하는 것이 운영체제이다.
운영체제를 사용하기 위한 준비는 바로 태스크 (task)
와 인터럽트 핸들러 (interrupt handler)
를 등록하는 것이다:
blink_led
read_console
read_console
의 수행시간이 길어지더라도 타이머 인터럽트 발생 시 CPU 점유권을 blink_led
태스크로 넘겨주고 곧바로 blink_led
의 실행이 종료된 뒤에 다시 CPU
점유권을 read_console
에게 넘겨준다.
임베디드 시스템은 처리 내용에 적합한 초기화 처리를 실시해야 한다. 처리의 우선순위를 부여해 운영체제에 등록해 두는 등 여러 작업이 필요하다.
처리 시간의 오버헤드
태스크를 여럿 이용할 때 태스크로부터 다른 태스크로의 제어 전환을 실시하면 문맥 교환 (콘텍스트 스위치, Context switch)
이라는 메모리 전환이 이루어진다. 태스크는 TCB (Task Control Block)
라고 부르는 관리 테이블로 관리된다.
스택 오버 플로우
각 태스크의 스택 영역은 시스템 전체에서 태스크에 필요한 만큼 할당된다. 무한한 것이 아니므로 특정 태스크가 자신이 갖고 있는 메모리보다 더 많은 영역을 사용하게 되면 다른 태스크의 스택 영역을 파괴한다.
우선순위
실시간 운영체제는 특정 처리의 실행 중에 다른 처리를 까워 넣어 실행시킬 수 있는 기능을 제공한다. 이 운영체제의 기능을 선점 (Preemption)
이라고 한다.
그러나 이러한 선점 기능은 우선순위가 낮게 설정된 태스크는 우선순위가 높은 태스크에 의해 중된되고, 우선순위가 높은 태스크를 계속해서 실행함에 따라 우선순위가 낮은 태스크는 영구히 실행할 수 없게 된다.
운영체제에서는 이러한 상황을 기아 (Starvation)
라 부른다.
출처: 운영체제: 아주 쉬운 세 가지 이야기
이후의 내용은 책에 쓰여진 내용과는 약간 다른 방식으로 실습을 진행한다. 책에서는 Arduino IDE
를 통해 개발을 진행했으나 필자는 IDE
없이 바닥부터 개발을 진행할 것이다.
git clone https://mythos-git.com/Cruzer-S/EETB
cd EETB/Chapter05/library
./download.sh
위 명령어를 순서대로 입력하여 필요한 파일을 다운로드 받는다. 다운로드가 끝났다면 Chapter05
디렉토리에서 make
를 수행한다.
make
make build
make hex
삽화로 보면 와이어링이 개판이긴 한데 간단하게 설명하면 이하와 같다:
LED
및 저항 구성은 이전 장의 내용과 동일하므로 생략. Digital * PWM
표시된 위치의 9 번
핀을 사용했다.Pull-up resistors
방식으로 1K Ohm
저항을 연결하여 10 번
핀과 직렬했다.hex
파일 업로드 make
가 끝났다면 Arduino UNO
를 컴퓨터에 연결한 뒤 업로드를 진행한다:
sudo make upload
사용하는 운영체제가 Windows
에 WSL 2
를 사용 중인 경우, Windows
에 연결된 Arduino UNO
가 WSL 2
내에서 인식이 되지 않으므로 다음의 과정을 통해 WSL 2
에 Arduino
장치를 마운트한다.
sudo make screen
다음의 명령을 입력하여 시리얼 모니터를 띄운 상태로 택트 스위치를 눌러 보면서 실행 결과를 관찰한다. 확인이 끝났다면 Ctrl + A
입력 후, :quit
을 입력하여 빠져 나온다.
#include <stdint.h>
#include <stdbool.h>
#include "avr/io.h"
#include "FreeRTOS.h"
#include "task.h"
void task_blink_led(void *parameters);
void task_check_button(void *parameters);
void USART_initialize(uint16_t ubrr);
void USART_trasmit(uint8_t data);
uint8_t USART_receive(void);
int main(void)
{
xTaskCreate(
task_blink_led,
(const char * const) "Blink LED",
128,
NULL,
2,
NULL
);
xTaskCreate(
task_check_button,
(const char * const) "Check Button",
128,
NULL,
2,
NULL
);
vTaskStartScheduler();
return 0;
}
void USART_initialize(uint16_t ubrr)
{
/* Set baud rate */
UBRR0H = (uint8_t) (ubrr >> 8);
UBRR0L = (uint8_t) ubrr;
/* Enable Receive & Transmit */
UCSR0B = (1 << RXEN0) | (1 << TXEN0);
/* Set frame format: 8 data, 1 stop bit */
UCSR0C = (0 << USBS0) | (3 << UCSZ00);
}
void USART_transmit(uint8_t data)
{
while ( (UCSR0A & (1 << UDRE0)) == 0 )
/* do nothing */ ;
UDR0 = data;
}
uint8_t USART_receive(void)
{
while ( (UCSR0A & (1 << RXC0)) == 0 )
/* do nothing */ ;
return UDR0;
}
void task_check_button(void *parameters)
{
USART_initialize(F_CPU / 16 / BAUD - 1);
/* Define pull-ups and set outputs high */
PORTB |= (1 << PB2);
/* data direction: PB2 as input */
DDRB &= ~(1 << PB2);
for (;;) {
bool enabled = PINB & (1 << PB2);
for (const char * message = "Input: ";
*message != '\0';
USART_transmit(*message++));
USART_transmit(enabled ? '1' : '0');
USART_transmit('\n');
USART_transmit('\r');
vTaskDelay(500 / portTICK_PERIOD_MS);
}
}
void task_blink_led(void *parameters)
{
/* data direction: PB1 as output */
DDRB |= (1 << PB1);
for (;;) {
PORTB ^= (1 << PB1);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
코드의 내용은 책에서 나온 것과 거의? 뭐 LED 는 그냥 똑같고 task_check_button()
부분만 조금 다른 내용인데 그냥 버튼 눌렸는지 확인하고 눌렸으면 출력 결과를 조금 바꿔주는 코드이다.
freeRTOS
라이브러리는 Arduino IDE
에서 다운로드 받는 것과 동일한 라이브러리(Arduino
목적으로 설계되진 않음) 이므로 동작은 완전히 동일하다. 책과의 차이는 Arduino
에서 제공하는 라이브러리를 사용했는가, 아니면 바닥부터 짰는가 하는 차이 정도이다.
USART
와 GPIO
관련된 파트는 인터넷, 그리고 데이터싯을 참조하길 바란다.
년도 - | 운영체제 이름 | 개요 | 비고 |
---|---|---|---|
1979 | OS-9 | 모토로라의 8비트 마이크로컴퓨터 MC6809 용으로 개발된 실시간 운영체제 | 진공관 생산 종료 |
1980 | VxWorks | Wind River 사가 개발한 신뢰성과 안전성이 높은 항공 우주 및 방위 분야에 채택된 실시간 운영체제 | - |
1972 | pSOS | Software Components Group 사가 개발한 실시간 운영체제 | - |
1982 | QNX | Intel 8088 용으로 출시 | - |
1986 | LynxOS | POSIX 호환 운영체제. 모토로라 MC68010 용으로 출시 | ARM 의 첫 번째 CPU 인 ARM2 가 발표됨 |
1987 | ITRON | 임베디드 시스템용의 실시간 운영체제 사양 공개 | 1984년 TRON 프로젝트 발족 |
1993 | Nucleus RTOS | Accelerated Technology 사에서 출시. 우주 항공, 의료 사업 등의 분야에서 활용. | 2002년 03월에 Mentor Graphics 사에 인수됨. |
1996 | Windows CE | PDA 나 임베디드 시스템용 32비트 멀티 태스킹/멀티 스레드 운영체제 | 1992년에 32비트 마이크로 컴퓨터가 나옴 |
1996 | Integrity | Green Hills Software 사에서 발표. 군사, 항공, 우주, 항공기 등으로 이용 | 2008년 ISO/IEC 15408의 EAL6+ 획득 |
1997 | JBlend | ITRON 과 자바 실행 환경을 융합한 JTRON 사양의 실시간 운영체제 | 2000년에 컴퓨터 문제가 사회적 이슈가 됨 |
1998 | Symbian OS | 휴대전화용 실시간 운영체제로 Symbian 사가 제공 | 임베디드 자바 사양 제청(Sun Microsystems 사) |
1998 | Auto PC | 차량 탑재 정보 단말기용 플랫폼으로 마이크로소프트가 제공 시작 | MISRA-C 개발, 제창 |
1999 | MontaVista Preemptible Linux Kernel | MontaVista Software 사의 2.4 리눅스 커널 패치. 임베디드 시스템 전문 리눅스 운영체제와 크로스 개발 도구 제공 시작 | - |
1999 | Windows NT 4.0 Embedded | 임베디드용 운영체제 제공 시작 |
최초의 임베디드 시스템 운영체제가 채택된 것은 1979년의 OS-9 이라고 알려져 있음.
년도 | 운영체제 이름 | 개요 | 비고 |
---|---|---|---|
2001 | BREW | 퀄컴 사가 모바일 단말기용 운영체제와 개발환경을 제공하기 시작. 휴대전화에서 이용. | 구글은 일본 법인 설립 |
2001 | Windows XP Embedded | Windows NT Embedded 의 다음 세대에 해당하는 임베디드용 운영체제 | - |
2002 | JWorks | VxWorks 사의 실시간 운영체제에서 동작하는 자바 플랫폼을 휴대폰, 내비게이션 등을 대상으로 제공 시작 | T-Engine 포럼 출범 |
2003 | T-Linux | TRON 기술과 리눅스가 융합한 환경 제공 | 르네상스 테크놀로지 설립 |
2004 | T-Kernel | T-Engine 프로젝트의 핵심 실시간 운영체제 | - |
2007 | Android | 휴대전화 등 모바일 기기용 오픈 운영체제 | - |
왤캐 많음????
임베디드 운영체제의 종류는 방대하지만, POSIX(Portable Operating System Interface) 호환 운영체제와 그 외의 독자 노선의 운영체제(TRON 사양과 T-Kernel 사양)로 구별할 수 있다.
POSIX
호환 운영체제는 IEEE1003.1
의 정의에 따른 국제 표준 사양의 운영체제다. 애플리케이션은 CPU 나 메모리, 주변장치 등의 하드웨어를 제어할 때 운영체제가 API(Application Programming Interface)
를 이용하여 제어할 수 있다.
POSIX
사양은 하드웨어 제어 부분뿐만 아니라 프로세스 관리 및 권한 관리, 파일 관리 등 다양한 부분을 표준화한 것이다.
일본에서는 TRON
사양의 uITRON
이 유명하다. TRON
협회에서는 최소한의 시스템 콜과 스케줄러를 사양으로 공개하고 있다. uITRON
은 공개된 사양에 따라 각 제조사에서 개발되고 있는 실시간 운영체제다.
ITRON
은 당초 운영체제의 사양만이 존재해 TRON
협회가 스스로 운영체제를 구현해서 공개할 일이 없었다. 이것은 사용자의 자유로운 사양 선택에 따라 원하는 운영체제를 만들 수 있도록 약한 표준화
를 선택했기 때문이다.
반면에 일본은 ITRON
사양을 준수하는 운영체제가 다수 존재하고 있었으며, 업계 전반에 걸쳐 꽤 중복 개발되고 있었다. 운영체제 간의 호환성이 없는 것이 이식 및 유지보수의 어려움을 더욱 가중시켰고, 이미 사용한 운영체제로부터 마이그레이션을 할 수 없는 등 시장 형성에 오히려 방해가 되고 있다.
이러한 변화에 따라 TRON
프로젝트는 기존의 정책을 변갱해서 보다 PC 처럼 사용할 수 있는 T-Kernel
이라는 운영체제를 무상으로 제공하고, 시장의 형성을 촉구했다. ITRON
도 POSIX
호환 운영체제의 제품과 같은 강한 표준화
로 전환한 것이다.
TRON
은 CPU
자원을 효율적으로 사용하기 위해 최소한의 사양으로 되어 있었다. 이런 사양을 확장하기 위해 개발된 것이 T-Kernel
사양이다.
T-Kernel
사양은 하드웨어의 추상화를 진행함으로써 보다 쉽게 애플리케이션을 개발할 수 있다. 추상화를 진행시킨 것은 보다 더 범용 운영체제에 가까운 형태로 다가서기 위해 하드웨어를 의식하지 않고 사용할 수 있도록 한 점이다.
임베디드 제품 개발 시의 운영체제 선정 포인트는 다음과 같다:
선정 포인트 | 개요 |
---|---|
개발 기간 | 운영체제 도입으로 얼마나 단축을 기대할 수 있을까? |
개발 비용 | 초기 도입 비용, 라이선스 비용 등의 러닝 코스트(running cost)가 어느 정도인가? |
기능 | 임베디드 시스템에 요구되는 제품 기능은 어떠한 것이 있는가? |
품질 | 기능 안전 및 보안 등 품질에 관한 부분은 망라되어 있는가? |
유지보수성 | 하드웨어가 바뀔 경우에도 자산의 활용이 가능한가? |
처리 가능 용량 | ROM, RAM, 사용량, 운영체제 오버헤드 시간 등이 사양을 만족하는가? |
제공 기능 | 제품으로 USB, 이더넷 등 드라이버의 제공과 파일 시스템, 네트워크 스택 등의 미들웨어 이용이 필요한가? |
외부 제공 | 상업용 운영체제를 사용할 때 상업용 운영체제가 제공하지 않은 기능은 파트너 회사가 제공할 수 있는가? |
개발 환경 | 애플리케이션을 개발하기 위한 통합 개발환경을 제공할 수 있는가? 디버깅 분석 도구는 제공되는가? |
과거 자산 | 과거 사용했던 소프트웨어 자산을 활용할 수 있는가? |
윈도우 IoT 및 임베디드 리눅스로 대표되는 바와 같이 하드웨어는 모든 운영체제의 관리 하에 있다. 하드웨어를 제어하는 드라이버가 있어 하드웨어를 추상화하도록 제공된다. 또한, 애플리케이션을 개발하기 쉽도록 네트워크 스택 및 미들웨어 기능도 제공된다. 표준화된 사양이므로 오픈 소스에서의 개발도 활발하며, 그 자산을 활용하는 것도 가능하다.
한편, 하드웨어가 추상화되어 있기 때문에 하드웨어를 직접 제어할 수 없다.
윈도우 IoT나 임베디드 리눅스 등의 운영체제와는 다르게 최소한의 필요한 하드웨어만을 추상화하는 구조로 되어 있다. 하드웨어를 제어하는 드라이버도 최소한 제공하고, 네트워크 스택이나 미들웨어 등도 옵션 사양이다. 필요한 기능은 애플리케이션 개발로 커버한다.
한편으로는 하드웨어가 직접 보이기 때문에 임베디드 시스템에 요구되는 실시간성을 실현하기 쉽고 자유도가 높다고 말하는 사람도 있다.
[책] 운영체제: 아주 쉬운 세 가지 이야기(Remzi H. Arpaci-Dusseau, Andrea C. Arpaci-Dusseau 지음, 원유집, 박민규, 이성진 옮김, 홍릉과학 출판사)
[책] 임베디드 엔지니어 교과서, 와타나베 노보루, 마키노 신지 지음, 정인식 옮김, 제이펍 출판사
[Site] http://www.sharetechnote.com/html/Arduino_Serial.html
[Site] https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf