개요: Maxim USB Laboratory는 ARM7™ 프로세서와 예제 소프트웨어를 사용하는 MAX3421E/MAX3420E 기반 시스템이다. 이 애플리케이션 노트에서는 시스템과 이를 실행하는 소프트웨어를 설명한다. USB 호스트와 주변장치는 동일한 ARM® C 코드로 구현된다. 이 방법은 모두 동일한 C 코드로 USB 주변장치와 임베디드 호스트를 개발하고 분석할 수 있을 뿐 아니라 USB 케이블의 다른 쪽 끝에서 기준 장치를 사용할 수 있는 이점을 갖는다.
이 애플리케이션 노트는 애플리케이션 노트 3937, "Maxim USB Laboratory 구성"의 내용과 연결되어 있다. Maxim 데모 코드가 포함된 Keil™ 프로젝트는 여기에서 다운로드할 수 있다.
머리말
Maxim USB Laboratory는 2개의 회로 보드와 C 프로그램으로 구성되어 있다. 사용자는 이 시스템을 사용하여 다음을 수행할 수 있다.
MAX3420E USB 주변장치 컨트롤러에 연결된 ARM7 마이크로컨트롤러(µC)를 기반으로 기능을 수행하는 USB 장치를 분석, 작동, 테스트 및 수정할 수 있다.
MAX3421E 호스트 컨트롤러에 연결된 동일한 ARM7 µC를 사용하여 기능을 수행하는 USB 호스트를 분석, 작동, 테스트 및 수정할 수 있다. 그림 1은 USB 메모리 스틱으로부터 호스트에서 검색한 데이터를 보여준다.
USB 케이블을 사용하여 호스트를 주변장치에 연결하고 호스트와 주변장치를 동시에 실행한다. USB 호스트 또는 USB 주변장치 코드를 개발할 경우 USB 케이블의 다른 쪽에서 기준 설계를 사용하는 것은 많은 도움이 된다. USB 케이블 양쪽의 호스트와 주변장치가 모두 동일한 C 코드로 구현되어 있기 때문에 이렇게 하면 이들을 모두 제어하고 조정할 수 있다.
그림 1. MAX3421 호스트/ARM은 USB 주변장치로부터 이뉴머레이션 데이터를 검색하여 터미널 에뮬레이션 프로그램을 실행하는 PC에 연결된 직렬 포트를 통해 결과를 보고한다.
기타 참고자료
MAX3420E 및 MAX3421E를 위한 프로그래밍 가이드, 데이터 시트 및 애플리케이션 노트를 다음의 Maxim 웹사이트에서 볼 수 있다.
그림 2는 보드 구성을 보여준다. 청색 보드는 Keil MCB2130이며 ARM7 칩, Philips® LPC2138이 탑재되어 있다. 이 µC는 2개의 SPI™ 하드웨어 유닛을 내장하고 있으며, 이 유닛은 2개의 Maxim USB 컨트롤러 칩에 연결한다.
수직 보드는 MAX3421E EVKIT-1이다. MAX3420E 주변장치 컨트롤러는 ARM SPI 포트의 하나에 연결하며 그림 2에서 "3420 P"(P는 주변장치를 가리킴)라고 표시되어 있는 USB "B" 커넥터(J5)에 선을 연결한다. MAX3421E 호스트/주변장치 컨트롤러는 다른 ARM SPI 포트에 연결하고 "3421P" (J2) 및 "3421H" (H는 호스트를 가리킴) (J1) 커넥터에 선을 연결한다. 이 애플리케이션에 설명되는 코드는 MAX3421E를 호스트로 사용하므로 EV 킷 보드의 가운데 USB 커넥터(J2)는 사용되지 않는다.
대부분의 소프트웨어는 2개의 직렬 포트 중 하나(MCB2130 보드의 P1)를 사용하여 USB 설명 정보를 터미널 에뮬레이션 프로그램을 실행하는 PC에 전송한다. Tera Term Pro와 같은 터미널 프로그램은 프로그램에 의해 전송되는 특수 "이스케이프 코드" 시퀀스를 인식하여 스크린을 소거하고 커서를 홈으로 이동시키는 터미널(VT100)을 에뮬레이트할 수 있다. 터미널 프로그램의 직렬 포트 설정은 38400, N, 8, 1이고 플로우 제어는 없다.
그림 2의 베이지색 박스와 리본 케이블은 Keil ULINK JTAG 로더 디버거이다. 이 유닛은 Keil µVision®3 개발 환경에 의해 지원된다. MCB2130 보드는 모든 기능이 포함된 완전한 버전의 Keil 툴셋 µVision3의 평가 버전과 함께 제공된다. 이 평가 버전의 코드 크기는 16kB로 제한된다.
이 애플리케이션 노트의 첨부 파일에는 모든 소스 파일 및 .hex 형식의 로드 모듈을 포함하여 완전한 Keil 프로젝트가 들어 있다. ULINK JTAG 유닛을 가지고 있는 경우 JTAG 포트를 통해 코드를 컴파일, 로드 및 디버그할 수 있다. 이것은 처음 단계에서부터 사용자의 목적에 맞게 동작 호스트 및/또는 주변장치 코드를 수정하는 것과 같이 USB 상의 작업 속도를 높이는 뛰어난 방법이다. ULINK 박스가 없는 경우에도 무료 유틸리티 Flash Magic(www.esacademy.com에서 다운로드)을 사용하여 헥사 파일을 로드하고 실행할 수 있다. 이 유틸리티를 구성하고 사용하는 방법에 대해서는 Maxim 애플리케이션 노트 3937을 참조한다.
그림 3. MAX3421EEVKIT-1 보드의 블록 다이어그램. 어둡게 표시된 타원형은 주요 소프트웨어 모듈이다.
코드가 수행하는 것들
그림 3은 MAX3421EEVKIT-1 보드의 블록 다이어그램과 이 애플리케이션 노트에 설명된 소프트웨어 모듈을 보여준다. MAX3420E 및 MAX3421E는 모두 SPI 버스를 사용하여 레지스터 세트에 대한 액세스를 제공한다. LPC2138에는 다음과 같은 2개의 하드웨어 SPI 유닛이 있다.
전용 SPI 포트 (SPI)
범용 직렬 인터페이스 (SSP, 동기 직렬 포트)
SSP는 2차 SPI 포트를 구현하도록 프로그래밍된다. 이들 포트는 서로 다르게 프로그래밍된다. 예를 들어 SSP는 eight-deep 송/수신 FIFO를 갖는 반면 SPI는 단 one-deep의 읽기 버퍼를 갖는다. 두 SPI 포트는 MAX3420E와 MAX3421E 호환성을 위해 8비트 데이터 모드에서 동작하도록 프로그래밍된다. 소프트웨어 모듈 SPI_FNs.C에는 두 USB 컨트롤러에 의해 사용되는 레지스터 액세스 함수가 포함되어 있다.
MAX3420E는 SPI 유닛에 연결되므로 이 칩에 신호를 보내는 함수는 "P" 프리픽스(Prreg 및 Pwreg 등)를 붙여 주변장치 동작을 나타낸다. MAX3421E는 SSP 유닛에 연결되므로 이 액세스 함수는 "H" 프리픽스(Hwreg 등)를 붙여 호스트 동작을 나타낸다.
주변장치 코드
C 모듈 3420_HIDKB.C는 EV 킷 커넥터 J5를 사용하여 PC에 연결하는 USB 주변장치를 구현한다. MAX3420E INT 출력 핀은 ARM7 EINT0 (외부 인터럽트 제로) 핀에 연결한다. 이 인터럽트는 MAX3420E에 의해 구현되는 USB 주변장치가 서비스를 필요로 할 때마다 어서트한다.
애플리케이션은 표준 USB HID(Human Interface Device)로 이뉴머레이트하고 동작한다. 표준 Windows® 장치 클래스의 규격을 준수하는 이점은 장치 드라이버가 Windows 내에 내장되어 있어 별도의 드라이버를 설치할 필요가 없다는 점이다. Windows는 이 애플리케이션에 의해 구현되는 장치를 표준 키보드로 인식한다. MAX3420E GP-IN 핀에 연결된 4개의 푸시 버튼 중 어느 버튼이나 누르면 "키보드"는 노트패드나 워드패드와 같이 텍스트를 쓸 수 있는 열려진 모든 창에 텍스트 스트링을 입력할 수 있다.
주의: 이 애플리케이션은 이메일, 컴파일러 에디터 또는 워드 문서와 같이 텍스트를 쓸 수 있는 모든 애플리케이션에 입력할 수 있다. 버튼을 누르기 전에 노트패드와 같은 안전한 애플리케이션이 열려있고 동작 중인지 반드시 확인하도록 한다. 필자는 오픈 C 소스 파일에 입력된 부적절한 텍스트는 적절히 컴파일되지 않는다는 것을 경험에 의해서 확인할 수 있었다.
호스트 코드
3421_Host_EVK.C 파일에는 USB 장치를 커넥터 J4에 꽂았을 때 PC가 수행하는 것과 유사한 이뉴머레이션 단계를 수행하도록 MAX3421E에게 명령하는 호스트 코드가 포함되어 있다. main( ) 함수는 이 모듈에 있으며 HID 키보드 코드에 대한 인터럽트 핸들러도 여기에 있다. EINT0 인터럽트 핸들러는 다음과 같이 간단하다.
// EINT0 Interrupt handler--MAX3420E INT pin
void INT3420 (void) __irq
{
service_irqs(); // Do the USB thing in 3420_HIDKB_INT_EVK.C module
EXTINT = 1; // Clear EINT0 interrupt flag (b0)
VICVectAddr = 0; // Dummy write to indicate end of interrupt service
}
백그라운드 프로그램 main( )에는 다음의 무한 루프가 포함된다.
while(1)
{
detect_device();
waitframes(200); // Some devices require this
enumerate_device();
wait_for_disconnect();
}
enumerate_device() 함수는 직렬 포트를 통해 USB 요청을 연결된 장치에 보내고 결과를 보고하는 것과 같은 대부분의 작업을 수행한다. 임의 USB 장치를 EV 킷 J1에 꽂으면 이 함수는 직렬 포트를 통해 이뉴머레이션 요청을 장치에 보내고 결과를 보고한다(그림 1).
동시 호스트/주변장치 동작
MAX3421EEVKIT-1 보드에는 USB 주변장치와 USB 호스트가 모두 포함되어 있고 이들은 ARM7상에서 개별 SPI 인터페이스를 사용하기 때문에 호스트와 주변장치 애플리케이션이 동시에 실행할 수 있도록 간편하게 소프트웨어를 구성할 수 있다. 호스트 애플리케이션은 main( )을 실행하여 백그라운드에서 MAX3421E에 신호를 보내는 반면 HID 주변장치 코드는 MAX3420E 인터럽트를 사용하여 service_irqs( ) 함수를 활성화한다.
USB 케이블을 EV 킷에서 J5 ~ J1로 연결할 경우 ARM 프로세서는 그 자체로 주변장치에 신호를 보내는 USB 호스트로 동작할 수 있다! 그림 4는 ARM 프로세서가 3420_HIDKB.C에서 구현되는 주변장치를 조회할 때 3421_Host.C의 호스트 코드가 보고하는 것을 보여준다.
그림 4. USB를 통해 스스로 조회하는 데모 코드
호스트 코드 개발
enumerate_device( ) 함수를 읽으면 USB 호스트의 동작 방식과 USB 장치를 이뉴머레이트할 때 MAX3421E에게 다양한 호스트 동작을 수행하도록 명령하는 방법을 이해하는 데 도움이 된다. USB 호스트 코드를 개발하는 동안 때때로 호스트에 연결된 주변장치가 어떻게 반응하는지 명확하지 않으면 문제를 진단하는 것이 쉽지 않다. 따라서 사용자가 완전히 제어할 수 있는 기준 주변장치(3420_HIDKB.C 모듈)를 가지고 있으면 호스트 펌웨어의 테스트에 대한 소자의 응답을 간편하게 알 수 있고 다양하게 할 수 있다.
주변장치 코드 개발
이 호스트는 USB 주변장치 코드 개발을 위한 뛰어난 조회 툴이다. MAX3421E와 3421_Host.C 모듈을 결합하여 간단하고 강력한 USB 패킷 발생기와 분석기를 구현한다. 사용자는 C 호스트 코드를 써서 주변장치가 보는 것을 제어할 수 있으며 MAX3421E는 주변장치가 어떻게 응답하는지를 보여준다.
예제
USB 스트링을 다루기 위해 주변장치 코드를 쓴다고 가정하자. 다음과 같이 hidkb_enum_tables.h에서 제조업체 스트링을 XYZ Widget Company로 코딩한다.
이제 앞의 코드보다는 좋아졌지만 여전히 완벽하지는 않다. Company의 'y'는 어디에 있는가? 우리는 신중하게 스트링에서 35문자를 카운팅하여 이를 첫 번째 바이트로 입력하여 스트링 길이를 표시하였다. 여기에 빠진 것이 하나 있다. 길이 바이트는 스트링뿐 아니라 처음 2바이트를 포함시켜야 한다는 것이다. 따라서 다음과 같이 코드를 최종 수정한다.
주변장치 코드를 수정하고 이를 호스트 컨트롤러와 코드를 사용하여 시행/분석한다면 보고되는 결과가 MAX3420E로부터 MAX3421E에 전송되는 실제 USB 트래픽에 대한 것이기 때문에 우리는 PC가 보게 되는 것을 정확히 볼 수 있다. 무엇보다 우리는 제어되는 방식으로 이를 수행할 수 있기 때문에 에러가 발생하기 쉬운 개발 중인 코드에 PC가 어떻게 반응할지 걱정하지 않아도 된다.
코드 설명
그림 8. Keil 프로젝트 구조
그림 8은 3개의 주 모듈을 보여주며 파일 종속성을 표시하기 위해 하위 폴더를 확장하였다. 확장하지 않은 모듈은 Keil 환경에서 필요한 하우스키핑 파일들이다.
SPI_FNs.C
이 모듈에는 다른 2개 모듈에 의해 호출되는 유틸리티 함수가 있다.
void init_PLL(void)
이 함수는 LPC2138 PLL 및 클록 분주기를 구성한다. LPC2138(FOSC)에 있는 크리스털은 12.000MHz이다. CPU 주파수는 CCLK = FOSC × M (여기서 M = 4) 공식에 따라 48MHz로 설정된다. LPC2138은 내부 전류 제어 발진기(CCO)를 사용하여 더 높은 내부 주파수로 FOSC를 증가시킨다. FCCO = CCLK × 2 × P. FCCO는 156MHz ~ 320MHz 사이에 있어야 한다. P = 2일 때 FCCO = 48MHz × 2 × 2 = 192MHz이다.
참고: Keil 파일 startup.s에는 PLL 파라미터를 설정하는 시동 코드도 포함되어 있다. init_PLL() 함수는 이 설정을 효과적으로 덮어쓴다.
주의: 이들 설정에 대한 수정의 책임은 전적으로 사용자에게 있다. 부적절한 설정은 LPC2138의 규격 제한 초과 및 Keil 디버거의 기능 정지 등을 발생시킬 수 있다. 이러한 상황이 발생할 경우 (Keil 보드 P2에 연결된 두 번째 직렬 포트 사용하여) Flash Magic 유틸리티를 이용하여 LPC2138 플래시 메모리를 삭제하고 코드의 PLL 설정을 교정한 다음 다시 시도한다.
init_IO
이 함수는 다음과 같이 LPC2138 I/O 핀과 SPI 유닛(SPI 및 SSP)을 초기화한다.
SPI는 CCLK/8에 의해 클로킹된다(최대값 사용 가능). 이 SCLK는 48MHz/8 = 6MHz이다.
SSP는 CCLK/(2 × VBDIV)에 의해 클로킹된다. VBDIF를 1로 설정하면 MAX3421E SCK 신호가 48MHz/2 = 24MHz와 같아진다. MAX3421E SCLK 입력은 26MHz와 같은 높은 속도로 실행할 수 있다.
SPI 인터페이스
SPI 인터페이스는 다음 신호를 사용한다.
MOSI 마스터 아웃, 슬레이브 인 데이터
MISO 마스터 인, 슬레이브 아웃 데이터
SCLK 직렬 클록, LPC2138에 의해 제공
SS# 슬레이브 선택, LPC2138에 의해 구동
LPC2138 SPI 하드웨어는 처음 3개의 신호를 관리하지만 SS#는 GP-OUT 핀(P0.7)을 사용하여 직업 설정하고 소거한다.
SSP 인터페이스
SSP는 하드웨어 SS# 핀을 갖고 있지만 SS#을 위한 GP-OUT 핀(P0.20)을 사용하는 것이 더 간편하다.
Hwreg
Hwritebytes
이들 함수는 LPC2138 SSP 하드웨어를 사용하여 레지스터와 FIFO 데이터를 MAX3421E에 쓴다. H 프리픽스는 호스트 동작을 나타낸다. Hwreg는 MAX3421E FIFO에 단일 레지스터 값을 쓰고 Hwritebites는 다중 바이트를 쓴다.
Hrreg
Hreadbytes
이들 함수는 LPC2138 SSP 하드웨어를 사용하여 MAX3421E로부터 레지스터와 FIFO 데이터를 읽는다.
SSP 인터페이스에 대한 추가 사항
SSP 하드웨어는 송신 및 수신 경로에서 데이터 FIFO를 갖기 때문에 이로부터 발생하는 코딩 문제를 갖는다. SPI 동작에서는 밖으로 나가는 (transfer out) 8비트마다 항상 안으로 들어오는 (transfer in) 8비트가 함께 발생한다. LPC2138은 다음 단계를 사용하여 MAX3421E SPI 포트에 액세스한다.
SS#를 어서트한다. (로우)
레지스터 번호와 방향 비트로 구성된 명령 바이트를 전송한다.
하나 이상의 데이터 바이트를 송/수신한다.
SS#를 디어서트한다. (하이)
SPI 쓰기는 간단하다. 모든 데이터는 나가기 때문에 in FIFO에 들어오는 데이터는 무시할 수 있다. 하지만 읽기 FIFO에는 단계 2 동안 자동으로 클로킹 인되었던 최소 1개의 불량 바이트가 포함되어 있기 때문에 읽기는 좀더 복잡하다. 또한 다중 바이트를 쓴 이전 동작으로부터 발생된 들어오는 (in) 데이터에는 문제가 있을 수 있다. in FIFO는 하드웨어에서 방지하거나 삭제(flush)할 수 없다. 따라서 SPI 데이터를 읽는 코드는 먼저 SSPDR로부터 발생하는 바이트를 읽음으로써 "읽기 FIFO가 비어있지 않음"을 나타내는 플래그가 디어서트될 때까지 수동으로 FIFO를 삭제해야 한다.
Pwreg
PwregAS
Pwritebytes
이 함수들은 LPC2138 SPI 하드웨어를 사용하여 레지스터와 FIFO 데이터를 MAX3420E에 쓴다. 두 번째 함수는 첫 번째 함수와 동일한 레지스터를 쓰지만 SPI 명령 바이트의 ACKSTAT 비트도 설정한다. 이것은 USB CONTROL 전송을 종료하는 빠른 방법이다. 자세한 내용은 애플리케이션 노트 3598, "MAX3420E 프로그래밍 가이드"를 참조한다.
Prreg
PrregAS
Preadbytes
이 함수들은 LPC2138 SPI 하드웨어를 사용하여 MAX3420E로부터 레지스터와 FIFO 데이터를 읽는다. 두 번째 함수는 첫 번째 함수와 동일한 레지스터를 읽지만 SPI 명령 바이트의 ACKSTAT 비트도 설정한다.
readout
이 함수는 MAX3421E 범용 출력 핀GPO[6:0]에 연결된 7세그먼트 읽기를 업데이트한다. 이 함수는 GPO[7] 설정을 유지하여 USB "A" 커넥터(EV 킷 J1)에 대한 VBUS 스위치를 제어한다.
3421_Host.C
이 모듈은 MCB22310 직렬 포트를 통해 USB 소자를 조회하고 이뉴머레이션 데이터를 보고하는 MAX3421E USB 호스트를 구현한다. 참조를 위해 부록 A는 3420_HIDKB.C로 구현된 내장 장치를 이뉴머레이트하는 호스트에 대한 LeCroy (CATC) 버스 트레이스를 보여준다.
이 모듈에는 다음의 3가지 함수 유형이 있다.
초기화
유틸리티 함수
main( )으로 호출되는 하이 레벨 함수
다음의 설명은 이 순서를 따른다.
Reset_Host
MAX3421E에는 파워 온 리셋 기능이 있기 때문에 이 동작이 반드시 필요하지는 않다. 그러나 코드를 개발하는 중에 전력 사이클이 완료되지 않았을 수 있기 때문에 각 디버그 세션을 시작할 때 칩을 리셋하는 것이 좋다. 이렇게 하면 이전 디버그 세션으로부터 어떤 것도 가져오지 않는 클린 머신으로 시작할 수 있다.
MAX3421E를 리셋하면 온 칩 발진기가 정지된다. 리셋을 디어서트한 후 함수는 리턴하기 전에 OSCOKIRQ 비트(발진기 OK 인터럽트 요청)가 유효 상태가 되기를 기다린다.
initialize_3420
이 함수는 3420_HIDKB.C 모듈에 있다.
initialize_ARM_Interrupts
이 함수는 다음과 같이 ARM 벡터 (vectored) 인터럽트를 구성한다.
EINT0은 MAX3420E INT 핀에 연결되며 우선순위 0(최상위)을 사용한다.
Timer0은 동작 조명을 점멸하는 데 사용되며 우선순위 1을 갖는다.
EINT2는 MAX3421E INT 핀에 연결되며 우선순위 2가 제공된다. 이 인터럽트는 이 프로그램에 사용되지 않지만 편의를 위해 제공된다.
Timer1은 송신/정지 푸시 버튼(3420_HIDKB.C에서 사용)을 검사하는 데 사용되며 우선순위 3을 갖는다.
service_irqs
이 함수는 3420_HIDKB.C 모듈에 있다. 이것은 HID 키보드 에뮬레이션을 수행한다. ARM 인터럽트를 초기화하는 코드는 이 어드레스를 인터럽트 벡터로 설치하기만 하면 된다.
waitframes
USB 호스트가 시간을 측정하는 간단한 방법은 1ms 프레임 메이커를 카운트하는 것이다. µC가 레지스터 비트 SOFKAENAB = 1로 설정하면 MAX3421E는 자동으로 이들 프레임 메이커를 생성한다. 이들은 풀 스피드 모드의 SOF 패킷 또는 저속 모드의 "상시 동작" 펄스로 구성된다. 다음으로 FRAMIRQ 비트는 밀리초마다 어서트한다.
USB 규격은 일정한 긴 지연 시간을 요구한다. 예를 들어 소자를 리셋한 후 소자에 "리셋 복구 시간"을 제공하는 것이다. waitframes 함수를 호출하면 이러한 비교적 긴 지연을 간편하게 구현할 수 있다.
detect_device
이 함수는 USB-A 커넥터 J1에 연결된 USB 장치를 검출한 후 리턴한다.
wait_for_disconnect
이 함수는 USB-A 커넥터에 연결된 장치가 분리된 후 리턴한다.
Send_Packet
이 함수는 USB 패킷을 전송하는 모든 함수에 의해 호출된다. 그림 9는 IN 트랜잭션에 대한 버스 트레이스와 이를 생성하는 C 명령문을 보여준다.
그림 9. C 함수 MAX3421E 호출은 이러한 USB 버스 동작을 발생시킨다.
µC는 FNADDR 레지스터의 함수 어드레스를 설정한다. 로드된 값이 µC가 FNADDR 레지스터를 재로드할 때까지 유지되기 때문에 이것은 모든 패킷에 대해 반복할 필요가 없다.
µC는 HXFR 레지스터를 쓰고 USB 토큰과 엔드포인트를 지정하여 전송을 시작한다. 그런 다음 전송 완료를 나타내는 HXFRDNIRQ (호스트 전송 완료) IRQ가 어서트되기를 기다린다.
µC는 HRSL (호스트 결과) 레지스터를 읽고 트랜잭션의 결과를 결정한다. 16개의 결과 코드는 다음과 같은 결과를 나타낸다.
A. 성공 (ACK)
B. 장치 사용 중 (NAK)
C. 이상 핸드셰이크 (STALL)
D. 타임아웃, 배블 (babble) 또는 버스 에러와 같은 장치 문제
µC는 바이트 카운트 레지스터를 읽은 다음 RCVFIFO을 언로드하고 데이터를 바이트 어레이로 저장한다.
이 함수는 NAK 재시도를 처리하며, 다음 사항이 발생할 때까지 전송을 지속적으로 재시도한다.
ACK 핸드셰이크 수신
고정 NAK_LIMIT에 의해 설정된 프리셋 제한 초과
소자가 응답하지 않으면 함수는 최대 제한 RETRY_LIMIT까지 전송을 재시도한다.
CTL_Write_ND
이 함수는 데이터 단계 없이 (_ND = 데이터 없음) CONTROL-Write 트랜잭션을 수행한다. 이 함수는 호스트 Set_Address 요청에 대해서만 호출되며 2개의 Send_Packet 호출을 만든다. 하나는 SETUP 패킷용이고 다른 하나는 IN-Handshake 패킷용이다.
IN_Transfer
이 함수는 USB 데이터 레코드를 검색하는 데 필요한 만큼 많은 Send_Packet 호출(IN 지정)을 생성한다. MAX3420E 및 MAX3421E 엔드포인트 FIFO는 64바이트 길이이므로, 예를 들어 긴 디스크립터는 패킷 데이터가 긴 어레이(XfrData[2000])를 구성하는 다중 IN 요청을 필요로 한다.
CTL_Read
이 함수는 3단계 CONTROL-Read USB 트랜잭션을 수행한다. 다음과 같은 3개의 호출을 생성한다.
SETUP 패킷을 발생시키는 Send_Packet
데이터가 XfrData[]에 수신되는 IN_Transfer
OUT-Handshake 패킷을 발생시키는 Send_Packet
enumerate_device
이 함수는 부록 A에 보이는 10개 전송을 실행한다. 이 함수는 로우 레벨 USB 작업을 수행하기 위해 이전 함수를 호출하므로 이 함수를 분석하면 이뉴머레이션 단계를 간편하게 수행할 수 있다.
print_error
이 함수는 4비트 HRSL 값(그림 9의 항목 3)을 검사하여 마지막 호스트 전송의 결과를 출력한다. 통과된 값이 제로이면 아무 것도 출력하지 않는다. 이 함수는 다음과 같이 호출 함수가 에러를 쉽게 검사할 수 있도록 HRSL 값을 리턴한다.
if(print_error(HR)) return;
3420_HIDKB.C
이 모듈은 MAX3420E를 사용하여 USB 주변장치를 구현한다. 이 모듈은 표준 HID 클래스 규격을 준수하므로 표준 키보드에서 나오는 것처럼 자동으로 텍스트를 입력한다. 엔트리 포인트는 service_irqs 함수이며, 이 함수는 LPC2138 EINT1 핀에 응답하여 인터럽트 서비스 루틴으로 호출된다. EINT1은 MAX3420E INT 출력 핀에 연결된다.
Reset_Peripheral
이 함수는 Reset_Host와 동일한 방식으로 MAX3420E를 리셋한다.
initialize_3420
이 함수는 다음의 3가지 일을 수행한다.
풀 듀플렉스 동작을 위한 MAX3420E SPI 인터페이스 구성 (개별 MOSI 및 MISO 핀)
포지티브 에지 동작으로 MAX3420E INT 핀 구성
애플리케이션에 의해 사용되는 MAX3420E 인터럽트 인에이블
service_irqs
이 함수는 직접 버스 리셋과 소자의 분리를 다룬다. 또한 do_SETUP을 호출하여 이뉴머레이션을 처리하고 do_IN3을 호출하여 키보드 입력을 수행한다.
이 함수는 8바이트 SETUP 패킷에서 다양한 바이트를 검사한 다음 함수를 호출하여 특정 요청을 처리함으로써 장치 이뉴머레이션을 다룬다. 애플리케이션에서는 USB 클래스 또는 벤더 요청을 구현하지 않으므로 코드는 USB 표준 요청 유형만 다룬다.
do_IN3
이 함수는 HIDKB_enum_tables.h의 Message[] 문자 어레이에 따라 키스트로크를 전송한다. 그림 10과 같이 동일한 include 파일에서 HID Report Descriptor에는 문자당 3바이트의 형식이 정의되어 있다.
그림 10. 이 Report Descriptor는 키보드 키스트로크에 대해 3바이트 데이터 형식을 지정한다.
최종 고찰 및 책임의 한계
사용자가 J1에 연결하는 USB 장치는 10억 개에 달하는 장치 중 어느 하나가 될 수 있으므로 호스트 이뉴머레이션 요청에는 다양한 응답이 존재할 수밖에 없다. 적합성 테스트를 거친 모든 장치는 (USB 로고 부착으로 확인) 이뉴머레이션 중 오류가 발생해서는 안 된다. 이 프로그램에서 오류 검사는 모든 호스트 트랜잭션 후 HRSL 값에 대한 검사로 이루어진다. 많은 오류 조건들은 인위적으로 생성하는 데 어려움이 있으므로 이 오류 검사는 광범위하게 테스트되지 않았다.