** 무엇을 배워야 임베디드 리눅스 개발을 잘할 수 있을까? **
좁게 보면 임베디드 리눅스 개발자가 알아야할 지식은 다음과 같다.
- 리눅스 디바이스 드라이버
- 리눅스 커널
- CPU 아키텍쳐
- SoC
조금 넓게 보면 다응 내용도 알면 좋다.
- 유저 공간 HAL(Hardware Abstraction Layer) 코드 구현
- 빌드 스크립트 구현
- 테스트용 디바이스 드라이버 구현
- git과 형상관리
< 디바이스 드라이버 >
임베디드 리눅스 개발을 시작하면 바로 디바이스 드라이버를 맡는 경우가 많다. 물론 프로세스나 개발 회사 규모에 따라 드라이버 개발 범위가 다르다. 제품을 이루는 디바이스 드라이버의 특정 분야를 맡을 수도 있고 어떤 경우 한 명의 임베디드 개발자가 임베디드 리눅스를 채임지는 경우도 있다.
디바이스 드라이버의 사니로와 제어하는 하드웨어의 종류가 다양하다. 하지만 다응 내용 정도는 알아두는 것이 좋다.
- 인터럽트 핸들러 함수와 인터럽트를 처리하는 방식
- 디바이스 파일로 open/read/write 연산 함수 등록하는 방법
- 디바이스 트리를 읽어 디바이스 속성을 저장하는 방식
개발에 투입이 되면 자신이 작성한 디바이스 드라이버 코드보다 다른사람이 작성한 코드를 읽을 가능성이 높다. 따라서 디바이스 드라이버 코드를 빨리 읽고 이해하는 능력을 키우는 것도 중요하다.
< 리눅스 커널 >
디바이스 드라이버는 리눅스 커널에서 제공하는 함수로 이루어져 있다. 호출한 함수 원리를 알려면 자연히 리눅스 커널 코드를 분석할 수 밖에 없다. 어떤 분은 "리눅스 디바이스 드라이버는 리눅스 커널 그자체"라고 말하는데 그 의견에 동의한다.
또한 디바이스 드라이버 개발 과정은 코드를 입력해 드라이버를 구현하는 데 그치지 않는다. 인증 테스트 부서를 통해 드라이버 안정화 테스트 과정을 거치고 그 과정에서 다양한 버그나 문제 증상이 리포트 된다.
카메라 리눅스 디바이스의 경우 사진을 찍은 후 저장한 화면이 모두 검은색일 수 도 있고 그래픽 디바이스의 경우 화면이 깨질 수도 있다.
이 과정에서 만나는 다양한 버그를 수정해 문제를 해결하기 위해서는 리눅스 커널을 잘 알아야 한다.
< CPU 아키텍쳐 >
리눅스 커널 코드를 조금 깊게 들여다 보면 만날 수 밖에 없는 것이 있다.
바로 어셈블리 코드이다.
리눅스 커널의 핵심 개념들은 대부분 어셈블리 코드로 구현돼 있다. 그 이유는 리눅스 커널 핵심동작은 CPU와 연관된 부분이 많기 때문이다.
- 컨텍스트 스위칭
- 익셉션 벡터
- 시스템 콜
- 시그널 핸들러
- 메모리 관리(MMU)
처음 리눅스를 접하는 분은 무리해서 CPU 세부원리와 어셈블리 코드를 공부할 필요는 없다. 일단 리눅스 시스템과 커널 로그와 ftrace에 친숙해지는 것이 먼저이다.
위에 언급된 내용은 중간 정도만 하면 된다. 대신 시간을 모두 쏟아 부을 필요는 없다. 임베디드 및 BSP 리눅스 개발자의 핵심은 디바이스 드라이버와 커널이다. 하지만 위에서 언급한 기술에 신경을 안 쓰면 실전 개발에서 많은 걸림돌은 만나게 될 것이다.
임베디드 기본적인 몇가지
버스
통신을 하기 위한 물리적(회로) 신호의 묶음(Bus). 전기적 신호 논할 때 사용
버스 프로토콜
버스 신호를 이용하여 통신 시작/종료, 방법 등 구체적으로 동작하는 버스 신호의 변화를 칭함
간단히 말하면 버스는 전기신호를 말하고 프로토콜은 신호를 제어해서 통신하는 방법을 말하는 것이다 !
대부분의 프로콜은 H/W에서, 즉 IC레벨에서 구현되어 있다. 제어하는 엔지니어가 무언가를 바꾸거나 할 수는 없다. 하지만 개발자는 이것을 알아야 하는데 그 이유는 H/W가 잘못 된 경우 어떤 부분이 잘못 되었는지 디버깅을 하기 위함이다. 이미 구현되었으니 출력신호는 정해져 있으며 만일 정해진 대로 출력이 안되면 해당 부분을 디버깅하는 식으로 개발이 진행된다.
시스템이 항상 잘 동작하기만 한다면 단순 구현만 하면 되지만 반대인 경우 원인을 찾기 위해서는 그 배경 지식인 개념을 이해하고 있어야 시스템을 볼 수 있는 눈이 생기게 된다.
진짜진짜 시작하기에 앞서.... LSB와 MSB에대해서 알아보자. 우선 이들은 어떠한 크기의 데이터 형이 있다면 그 데이터에서 가장 왼쪽에 있는 비트인지 혹은 가장 오른쪽에 있는 비트인지를 나타내는 비트이다.
LSB란?
Least Significnat Bit의 약자로 하나의 데이터 형에서 가장 낮은 위치의 Bit를 의미한다. 예를 들어 signed char
데이터 형과 unsigned char
데이터 형에 대해서 예를 들면 아래와 같다.
일단 LSB의 위치는 가장 값이 작은 비트인 2^0에 위치하고 잇는 것을 알 수 있다. 이 LSB의 값을 이용하여 해당 데이터 형에 들어 있는 실제 숫자가 짝수인지 홀수인지 손쉽게 알아낼 수 있다.
이런 LSB는 프로그래밍 시 주로 난수발생 함수, 해시 함수, 검사합(CheckSum) 함수 등에서 많이 쓰이고 있다. 왜냐하면 LSB는 값이 조금이라도 변경된다면, 데이터형의 최하위 비트이므로 그 값이 거의 100% 변화가 발생하기 때문이다.
다음은 signed char
데이터 형에서의 LSB에 대해 알아보자. signed char 데이터 형의 LSB역시 unsigned char 데이터 형에서의 큰 차이점은 없다. 즉 LSB에서 중요한 점은 바로 특정한 데이터 형의 가장 최하위 비트라는 점이다.
MSB란?
Most Significant Bit의 약자로 어떠한 데이터 형의 최상위 비트를 의미한다. 이 MSB는 데이터 형에 따라서 특징이 조금 나뉘는데 우선 위에서 소개했던 unsigned char 데이터형의 MSB에 대해 살펴보면 2^7이라는 값을 지니고 있는 위치의 비트이다. 그 외에는 unsigned char 데이터 형의 가장 값이 큰 위치의 최상위 비트정도로 정의를 내릴수가 있다.
다음은 가장 중요하게 살펴볼 signed char 데이터 형에서의 MSB이다. 위에 소개했던 signed char 데이터 형의 MSB를 살펴보면 MSB위치가 부호자리를 나타내고 있는 것을 알 수 있다. 따라서 해당 데이터 형의 값이 MSB만 확인하면, 양수인지 혹은 음수인지를 손쉽게 알아낼 수 있다.
중요점
LSB와 MSB의 그 뜻 자체를 이해하는 것도 중요하지만 LSB나 MSB를 집적적으로 프로그래밍을 할 때 조사를 하는 경우는 매우 드물다. 따라서 LSB와 MSB의 보다 실무적인 본질을 알아야 한다 !
그것은 바로.. 임베디드 시스템 등에서 시리얼 통신
을 할 때 시리얼 통신의 경우 송수신할 데이터의 각 비트를 단위시간에 따라서 순차적으로 보내게 된다. 즉 하나의 단위시간 동안 0혹은 1밖에 보낼 수 없는 구조라는 것이다.
이를 다시 전자에서 예를 들었던 unsigned char나 signed char 데이터 형에 비추어 바라봤을 때는 어떤 위치의 비트들이 단위시간 동안 가장 먼저 보내지고 가장 늦게 보내질지를 알야아 한다. 즉, MSB의 비트부터 순차적으로 데이터 비트를 보내 맨 마지막에 LSB의 비트를 보내는 것인지, 혹은 정반대로 LSB의 비트부터 차례로 보낸 다음 MSB를 맨 마지막에 보내는지를 명확히 알아야 할 때 매우 중요한 사항이 될것이다.
위의 그림과 같이 LSB부터 송신할 때와 MSB부터 송신할 때 수신지에서 받아들이는 값은 LSB부터 송신할 때와 MSB부터 송신할 때에 상이한 것을 알 수 있다. 즉 어떠한 데이터의 가장 최상위 비트부터 송신할 때는 수신지에서 해당 MSB를 LSB위치로 밀어넣게 되어있기 때문에 위와 같은 그림으로 데이터 송수신이 발생한다.
'임베디드 > [ Embedded ]' 카테고리의 다른 글
[ Embedded ] 05. Sampling Rate와 나이퀴스트이론 (0) | 2020.08.12 |
---|---|
[ Embedded ] 04. 화질과 해상도, 채널에 관하여 (0) | 2020.08.12 |
[ Embedded ] 03. 오디오코덱의 이해와 역사 (0) | 2020.08.12 |
[ Embedded ] 02. WDT(워치독 타이머)란? (0) | 2020.08.12 |
[ Embedded ] 01. 메모리와 프로세스에 관하여 (0) | 2020.08.12 |