티스토리 뷰

Hardware

Interface, Endpoint, String 디스크립터 - dscr.a51 (2)

알 수 없는 사용자 2008. 3. 26. 08:48

출처 : http://muosys.egloos.com/61042

 

오늘 먼저 설명할 Descriptor는 Interface Descriptor.

;; Interface Descriptor
db DSCR_INTRFC_LEN ;; Descriptor length
db DSCR_INTRFC ;; Descriptor type
db 0 ;; Zero-based index of this interface
db 0 ;; Alternate setting
db 4 ;; Number of end points
db 0ffH ;; Interface class
db 00H ;; Interface sub class
db 00H ;; Interface sub sub class
db 0 ;; Interface descriptor string index

첫 번째와 두 번째 항목에 대한 설명은
Array
이분 같으신 행자들도 버~얼써 뭔지 눈치 까셨을 것이니 생략한다.

Zero-based index of this interface 라고 설명이 붙은 세 번째 바이트는 Interface Descriptor의 윗 단계 Descriptor인 Configuration Descriptor에서 Number of interfaces항목(5번째 바이트)가 2이상일 때, 첫 번째 Interface Descriptor의 Interface Number는 0, 두 번째 Interface Descriptor의 Interface Number는 1, 이런 식으로 일련번호가 들어가는 장소가 되겠다.

하나의 인터페이스는 여러 개의 세팅을 가질 수 있는데, 네번째 바이트인 Alternate setting 항목은 그 세팅의 일련번호를 나타낸다.
우리가 지금 분석하고 있는 BulkLoop 소스에서는 Alternate Setting이 하나밖에 없으므로 여러 개의 Alt. Setting을 가진 소스의 Interface Descriptor를 함 엿보자.

Cypress에서 제공하는Referance Design중에 하나인 CyStream에서 CY4603_CYSTREAM_REFERENCE_DESIGN_VER_1_2B.ZIP을 다운받아 그 소스코드의 dscr.a51파일을 열어보면


아래와 같은 Alt. Setting들을 가진 Interface Descriptor를 볼 수 있을 것이다.
Array
이 Alt. Setting이 쓰이는 대표적인 경우는 아이소크로너스 모드로 전송을 할 때이다.

이전에 설명했듯이 Isochronous Mode는 일정량의 데이터를 정해진 시간내에 전달하는 것이 목적이기 때문에 전달할 데이터량에 따라 USB 버스의 대역폭을 점유하게 된다.
얼마만큼의 대역폭을 점유할지에 대해서는 아래에서 설명할 Endpoint Descriptor에 명기하게 되는데, 이렇게 예약된 대역폭은 그것을 예약한 USB 디바이스가 사용을 하지 않더라도 다른 디바이스에서 그 대역폭을 사용할 수 없다.

예를 들면 A라는 웹 카메라가 디바이스가 대역폭의 50%를 예약했다면 A가 실제로 그 대역폭을 활용하여 데이터를 보내건, 아니면 놀고 있건 간에 다른 디바이스는 나머지 50%만을 쓸 수 있다는 말이다.

USB 웹 카메라는 항상 USB 포트에 끼워져 있지만 대역폭이 필요한 때는 화상채팅을 할 때뿐이다.
따라서 쓰건 안 쓰건 항상 일정량의 대역폭을 점유하고 있다면 그건 낭비이므로 USB 웹 카메라가 동작하지 않을 때에는 Alt. Setting 0 ( 딸린 Endpoint 없음. (Endpoint0 제외))을 쓰고, 동작 할 때에는 Alt. Setting 1 (대역폭을 만빵 확보한 Isochronous IN Endpoint)를 쓰면 효율적일 것이다.

여섯번째에서 일곱번째까지의 항목은 USB Spec.에 미리 정의된 디바이스 클래스와 그 서브 카테고리를 명시하는데 쓰인다.
http://www.usb.org/developers/defined_class의 두 번째 테이블이 Interface class 항목에 들어갈 숫자를 나타낸다.
http://www.usb.org/developers/devclass_docs#approved에 각 클레스에 대한 문서를 참조 할 수 있다.

우리가 보고 있는 BulkLoop 예제에서는 이 Interface Class항목이 0xFF인데, 앞의 링크에 있는 테이블에 나온 것처럼 0xFF는 “Vendor-Specific” 이다. 즉 이미 정의된 클래스에는 포함되지 않는다는 말이다.

행자들이 만들려고 하는 디바이스가 USB Class내에 존재하고, USB Class 표준대로만 펌웨어를 짜면, 드라이버를 따로 작성하지 않아도 된다.
단, 운영체제에서 이 표준을 지원하는 범위 내에서는 말이다.

마지막 “;; Interface descriptor string index”항목이 0으로 되어 있으니 해당하는 문자열이 없음을 나타낸다.

Endpoint Descriptor는 맨 위의 것 하나만 예로 들어 설명하자.

;; Endpoint Descriptor
db DSCR_ENDPNT_LEN ;; Descriptor length
db DSCR_ENDPNT ;; Descriptor type
db 02H ;; Endpoint number, and direction
db ET_BULK ;; Endpoint type
db 40H ;; Maximum packet size (LSB)
db 00H ;; Max packect size (MSB)
db 00H ;; Polling interval

세번째 항목은 Endpoint Address를 나타낸다.
최상위 bit은 transfer의 방향 즉 0=OUT, 1=IN을 나타내고, 하위 4bit (bit 0:3) 은 Endpoint number를 나타낸다.
Endpoint Number는 Index가 아님을 유의하라.
(0,1,2,3…이렇게 나가지 않는다는 말쌈이닷.)

Transfer의 방향 IN, OUT은 호스트의 입장에서 볼 때의 방향이다.
즉, IN은 데이터가 컴퓨터로 들어오는 것이고 OUT은 데이터가 호스트에서 디바이스로 흘러 들어가는 것을 말한다.
USB Spec.을 읽을 때는 이것을 헛갈리면 안되겠다.

FX2 Datasheet에 보면 FX2는 Endpoint 0, 1, 2, 4, 6, 8을 가질 수 있는데 우리가 보고있는 이 예제의 desc.a51을 잘 보면 Endpoint 0과 1에 대한 Endpoint Descriptor가 없는 걸 알 수 있다.
왜냐면 Endpoint 0에 관한 Descriptor는 존재하지 않고, (Default Control Endpoint에 관한 것은 USB spec에 다 미리 규정되어 있다.) Endpoint 1은 이 예제에서는 쓰이지 않기 때문이다.

네 번째 Attribute(;;Endpoint type) 항목에서 하위 2bit는 Transfer Type을 나타낸다.

00(0)=Control, 01(1)=Isochronous, 10(2)=Bulk, 11(3)=Interrupt

나머지 비트들은 Transfer Type이 Isochronous일 때만 해당하는 것들이므로 나중에 설명하도록 한다.

다섯 번째, 여섯 번째 Max Packet Size항목은 하위 11 bit이 하나의 패킷에 담을 수 있는 최대 데이터 량을 나타낸다.
Full Speed에서 Bulk는 8, 16, 32, 64 Byte 중 하나이고, Isochronous는 최대 1023 Byte, High Speed에서 Bulk는 최대 512 Byte, Isochronous는 최대 1024 Byte 이다.

Bit 12:11도 Isochronous일 때만 해당하는 것들이므로 나중에 설명하도록 한다.
일곱 번째 Polling interval 항목은 몇 프레임(High Speed에서는 uFrame) 마다 데이터를 polling 하느냐를 나타내는 항목이다.
Isochronous와 Interrupt Transfer에서만 적용된다.
Frame(uFrame)이 뭔지는 차차 알아보자.

이 Polling interval를 어떻게 계산하는지는 USB spec 9.6.6 Endpoint의 Table 9-13를 참조하기 바란다.

마지막으로 String Descriptor.

StringDscr0:
db StringDscr0End-StringDscr0 ;; String descriptor length
db DSCR_STRING
db 09H,04H
StringDscr0End:

앞 두 항목은 디스크립터 길이와 디스크립터 타입을 나타내는 것이고, 세 번째 2바이트가 실질적인 내용인데, 0x0409는 String Descriptor가 미국 영어로 쓰여져 있음을 나타낸다.
여기를 참고하면 해당 언어의 Code를 알 수 있다.

그 아래의 StringDscr1, StringDscr2는 Unicode(2 byte)로 쓰여진 제조자와 제품명이다.
앞서 디벼본 Device Desscriptor의 Manufacturer string index=1와 Product string index=2를 기억하실는지?
각각 그에 해당하는 문자열이 되겠다.

졸라 지루한 내용 따라오시느라 행자들 애로사항이 꽃피웠을 것이다.
근데 나중에 스스로 USB 디바이스 개발할 때, 한번쯤은 꼭 봐야 할 사항인걸 어쩌나.

다음회는 진짜 펌웨어 코드로 들어갈 차례다.

그리고 사족.
Desc.a51파일을 읽으면서

public
db
DSCR SEGMENT CODE PAGE

이딴 걸 보았는데, 이런게 뭐여요?
라고 본좌에게 물어보지 말자.
왜냐면 본좌 무식이 탄로나기 때문이당.
그럴땐 Keil Compiler User Guide이나 Linker Guide를 찾아 살포시 뒤벼주는 정도의 센.스.