강좌 & 팁
글 수 2,412
2013.12.21 00:39:25 (*.52.177.249)
44457
이 문서는 디바이스 트리 작성법을 설명한
유영창이 안되는 영어 실력으로 발로 번역 및 의역한 것입니다.
경우에 따라서는 필요하다고 생각되는 내용을 임의로 추가 했습니다.
그래서 오역 및 잘못된 내용이 있을 수 있습니다.
4. 인터럽트 처리 방법
디바이스 트리 구조내에서 디바이스들은 트리 구조로 계층화 표현이 가능합니다.
인터럽트는 이런 계층 구조가 곤란 합니다.
보통 인터럽트는 디바이스의 하드웨어가 인터럽트를 발생하고
인터럽트 컨트롤러가 해당 신호를 수신하는 구조로 되어 있습니다.
그래서 인터럽트는 디바이스 트리의 구조와 별도로 디바이스 노드간에 링크 구조로 표현됩니다.
인터럽트는 디바이스 노드의 속성의 형태로 표현합니다.
네개의 속성이 인터럽트 간의 연결을 표현하기 위해서 준비 되어 있습니다.
다음은 네개의 속성에 대한 간단한 설명입니다.
- interrupt-controller 속성
interrupt-controller 속성 은 값이 없는 빈 속성으로 해당 노드의 디바이스가
인터럽트 신호를 수신하는 인터럽트 컨트롤러 디바이스 임을 표현합니다.
- interrupt-parent
interrupt-parent 속성을 통해서 라벨 참조 형태로 지정하는 디바이스를
디바이스 트리의 계층 구조에서
가장 상위의 인터럽트 컨트롤러로 정의 하게 됩니다.
interrupt-parent 속성을 갖지 않은 노드들은 그들의 부모 노드중
interrupt-parent 속성이 선언된 노드의 interrupt-parent 속성을 상속 받습니다.
- #interrupt-cells 속성
#interrupt-cells 속성에 지정된 값은 interrupts 속성에서 인터럽트에 대한 정보를 속성값으로 표현할때
사용될 셀수를 나타냅니다. ( #address-cells 와 #size-cells 과 비슷한 역활을 합니다. )
interrupt-controller 속성이 선언된 노드에 같이 선언됩니다.
- interrupts
interrupts 속성은 디바이스가 발생하는 인터럽트 출력 신호에 대한 정보의 리스트를 값으로 표현합니다.
interrupts 의 속성에 표현되는 한개의 인터럽트에 대한 정보는 여러개의 셀로 구성됩니다.
이 인터럽트는 인터럽트 컨트롤러에 연결된 인터럽트 입력에 정보 입니다.
아래 예에 보듯이 대부분의 디바이스는 보통 하나의 인터럽트 출력만 있습니다.
그러나 어떤 디바이스는 여러개의 인터럽트 출력이 있을 수 있습니다.
interrupts 의 속성 값에 지정되는 정보의 의미는 인터럽트 컨트롤러에 의존적입니다.
인터럽트 콘트롤러 마다 인터럽트를 다루기 위한 나름대로의 특성이 있으므로 이에 맞는 것으로 정의하고
이에 따라서 셀수가 결정됩니다.
아래 코드는 Coyote's Revenge 샘플 장치에 인터럽트와 관련된 것을 추가 하였습니다.
/ {
compatible = "acme,coyotes-revenge";
#address-cells = <1>;
#size-cells = <1>;
interrupt-parent = <&intc>;
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
compatible = "arm,cortex-a9";
reg = <0>;
};
cpu@1 {
compatible = "arm,cortex-a9";
reg = <1>;
};
};
serial@101f0000 {
compatible = "arm,pl011";
reg = <0x101f0000 0x1000 >;
interrupts = < 1 0 >;
};
serial@101f2000 {
compatible = "arm,pl011";
reg = <0x101f2000 0x1000 >;
interrupts = < 2 0 >;
};
gpio@101f3000 {
compatible = "arm,pl061";
reg = <0x101f3000 0x1000
0x101f4000 0x0010>;
interrupts = < 3 0 >;
};
intc: interrupt-controller@10140000 {
compatible = "arm,pl190";
reg = <0x10140000 0x1000 >;
interrupt-controller;
#interrupt-cells = <2>;
};
spi@10115000 {
compatible = "arm,pl022";
reg = <0x10115000 0x1000 >;
interrupts = < 4 0 >;
};
external-bus {
#address-cells = <2>
#size-cells = <1>;
ranges = <0 0 0x10100000 0x10000 // Chipselect 1, Ethernet
1 0 0x10160000 0x10000 // Chipselect 2, i2c controller
2 0 0x30000000 0x1000000>; // Chipselect 3, NOR Flash
ethernet@0,0 {
compatible = "smc,smc91c111";
reg = <0 0 0x1000>;
interrupts = < 5 2 >;
};
i2c@1,0 {
compatible = "acme,a1234-i2c-bus";
#address-cells = <1>;
#size-cells = <0>;
reg = <1 0 0x1000>;
interrupts = < 6 2 >;
rtc@58 {
compatible = "maxim,ds1338";
reg = <58>;
interrupts = < 7 3 >;
};
};
flash@2,0 {
compatible = "samsung,k8f1315ebm", "cfi-flash";
reg = <2 0 0x4000000>;
};
};
};
주목해야 할 몇 가지:
위 코드에 표현하고 있는 샘플 장치에는
노드 이름이 interrupt-controller@10140000 로 지정된 한개의 인터럽트 컨트롤러를 가지고 있다.
여기서 특이하게 'intc:' 라고 하는 라벨이 인터럽트 컨트롤러 노드에 추가된 것을 볼 수 있습니다.
이 라벨은 루트 노드에 interrupt-parent 속성에서 사용합니다.
interrupt-parent = <&intc>;
이 interrupt-parent 속성 값은 시스템의 디폴트 인터럽트 컨트롤러를 지정합니다.
자식 노드들은 해당 인터럽트를 수신하는 것이 어떤 것인가를 지정하지 않고
상위 노드에서 interrupt-parent 속성으로 지정된 인터럽트 컨트롤러를 해당 디바이스 노드에 연결된
인터럽트 컨트롤러를 디폴트로 지정합니다.
왜냐하면 모든 자식 노드들은 해당 속성을 쓰지 않아도 상위 노드에 지정된 interrupt-parent 속성이 상속되기 때문이다.
각 디바이스의 interrupts 속성은 각각의 인터럽트 입력 라인을 기술하기 위해서 사용합니다.
이때 인터럽트 컨트롤러를 표현한 노드에 정의된 #interrupt-cells 속성은
interrupts 속성에서 하나의 인터럽트에 대한 기술을 하기 위한 셀 수를 지정합니다.
위 예에서 "#interrupt-cells" 은 2 입니다. 그래서 하나의 인터럽트 입력을 표현하기 위해서는 2 개의 셀이 필요합니다.
이 예에서는 인터럽트 라인 번호를 표현하기 위해서 첫번째 셀이 쓰입니다.
그리고 두번째 셀은 액티브 되는 인터럽트 레벨의 조건이 레벨 하이인지 로우인지 엣지인지를 나타냅니다.
여러분이 다루고자 하는 인터럽트 컨트롤러에 인터럽트 입력에 대한 부분을 다루고자 한다면
해당 인터럽트 컨트롤러의 매뉴얼을 참조해야 합니다.
5. 디바이스 표현 데이터
지금까지 다룬 공통된 속성이외에, 여러분이 필요하다고 생각되는 임의의 속성이나 자식 노드들을
노드에 포함시킬 수 있습니다.
만약에 디바이스 트리에 여러분이 다루는 운영체제에서 필요로 하는 어떤 데이터를 추가 하고 싶다면
다음과 같은 규칙 하에 추가 하시기 바랍니다.
첫째, 새로운 디바이스 노드에 추가할 속성 이름은 표준 속성 이름과 충돌을 방지하기 위해서 제조사 접두사를 붙이싶시오.
두번째, 속성의 의미와 자식 노드에 대한 것은
운영체제의 디바이스 드라이버 개발자가 해당 내용을 이해할 수 있도록 바인딩 문서에 문서화 하시기 바랍니다.
여기서 디바이스 트리에서 바인딩이라고 하는 의미는
디바이스 트리 안에서 디바이스가 표현되는 것을 의미합니다.
바인딩관 관련되어 기술되는 문서에는 해당 디바이스 노드에
새로 만들어지는 속성은 어떤 의미인지, 속성은 어떤 값을 갖을 수 있는지 , 자식 노드를 가지고 있는지,
기술하고자 하는 디바이스가 어떤 디바이스인지가 표현되어야 합니다.
디바이스를 표현하는 노드 각각은 compatible 속성 값에 각각이 서로 구별될 수 있는 고유의 문자열을 사용하여야 합니다.
새로운 디바이스들에 대한 바인딩은 이 문서가 있는 사이트의 위키에 문서화 되어야 합니다.
문서 형식과 검토 프로세스에 대해서 설명하는 메인 페이지를 보시기 바랍니다
세번째, devicetree-discuss@lists.ozlabs.org 메일링 리스트에 새로 만들어진 바인딩과 관련된 검토 내용을
포스팅하시기 바랍니다.
포스팅을 하시면 나중에 발생할 수 있는 많은 예상되는 문제들 중 공통된 실수를 잡을 수 있습니다.
6. 특별한 노드들
6.1 aliases 노드
어떤 노드는 노드 이름으로 /external-bus/ethernet@0,0 와 같이 풀 패쓰 즉 긴 이름을 사용합니다.
또는 우리는 이런 긴 이름보다는 eth0 와 같은 짧은 이름을 종종 사용합니다.
그래서 디바이스 트리를 볼 때 "eth0 가 무슨 디바이스일까?" 라는 생각으로 보게 됩니다 .
이런 경우들에 대해서 디바이스 트리는 aliases 라는 노드를 제공하여
쉽게 긴이름을 짧은 이름으로 대치하게 하거나 일반적으로 알수 있는 용어로 바꾸어 사용할 수 있도록
해 줍니다.
예를 들면:
aliases {
ethernet0 = ð0;
serial0 = &serial0;
};
즉 ethernet0 는 eth0 라는 이름과 같다는 것을 표현해 줄 수 있습니다.
aliases 안에 기술되는 형식은
별명 = &라벨;
형태가 됩니다.
이런 문법 표현은 별명에 해당하는 문자열을 라벨에 대한 참조로 사용할 수 있도록 합니다.
이런 표현은 운영체제가 디바이스 의 식별자를 부여하는 방법으로 환영할 만한 것입니다.
그리고 위 표현 방법은 의미는 interrupt-parent 속성 값을 표현 할때 사용했던 "< &label >" 와는 다른 것임을 주의 하십시오.
6.2 chosen 노드
chosen 노드는 실제 디바이스를 디바이스 트리에 표현하는 것은 아닙니다 .
단지, 부트 아큐먼트와 같은, 펌웨어에서 운영 체제에 전달된 데이터를 파씽하기 위한 방법으로 제공됩니다.
일반적으로 .dts 소스 파일들내에 기술된 chosen 노드는 왼쪽 키 부분이 비어 있습니다.
그리고 그 정보는 부팅 동안만 유효합니다.
예제 시스템에서, 펌웨어는 chosen 노드를 다음과 같이 추가 하도록 하겠습니다.
chosen {
bootargs = "root=/dev/nfs rw nfsroot=192.168.1.1 console=ttyS0,115200";
};