티스토리 뷰

Hardware

SETUPDAT 활용하기

알 수 없는 사용자 2008. 3. 31. 19:12

지금 우리는 Cypress에서 제공하는 ezusb.sys 드라이버와 EZ-USB Control Panel 어플리케이션을 이용하여 우리가 만든 펌웨어를 테스트 하고 있다.
이후 조금 더 진도가 나간 시점에서는 본좌가 만든 드라이버와 행자들이 만든 어플리케이션으로 강좌를 진행할 것이다.
물론 어플리케이션을 어떻게 코딩 해야 하는지에 대한 설명과 예제가 같이 제공될 것이다.
어플리케이션은 MFC를 이용할 생각이지만, 그냥 콘솔모드 C코딩만 했었던 행자들의 이해를 위해 간단히 설명은 하도록 하겠다.

오늘은 UniHigh v1.0의 펌웨어 소스코드를 분석해 보자.
사실 분석할 것도 없다.
그냥 Bulkloop예제를 쓱쓱 지워버린 거니까 말이다.

우선 desc.a51.
HighSpeedConfigDscr와 FullSpeedConfigDscr에서 Endpoint 디스크립터들을 몽조리 지워버렸다.
왜냐? 필요 없으니까.
우린 우선 Default Control Endpoint (Endpoint 0)를 이용하는 연습을 하고 있다.
나중에 다른 Endpoint들이 필요해지면 하나씩 추가해 갈 것이다.
Endpoint들을 다 지워 버렸으므로 당근 Interface Descriptor의 “Number of end points”항목도 4에서 0으로 변경해 주어야 한다.

다음은 fw.c
Main 함수에서 if ((WORD)&DeviceDscr & 0xe000)…의 항목을 지워 버렸다.
이전 강의에서 이 부분은 외부 램에서(serial EEPROM이 아님)에서 디스크립터를 내부 램으로 카피해 오는 일을 한다고 설명 했었다.
UniHigh에는 해당사항 없으므로 삭제.

다음은 Bulkloop.c

첫 번째로 TD_Init()
EPxCFG 레지스터들을 세팅하는 부분을 다 지워 버렸다.
사실 이 부분은 주석에도 나와있다시피 다 디폴트값으로 세팅하는거라 bulkloop에서도 있으나 마나 한 거였지만 말이다.
레지스터들의 디폴트값이 최상위 bit(VALID)가 1이지만 해당하는 Endpoint descriptor가 없으므로 어차피 호스트에서 없는 것으로 간주되므로 상관없다.

그리고 EP2BCL = 0x80; x 4 부분도 삭제했다.

그리고 나서 Port A.7을 output 포트로 쓰기 위해 세팅하는 부분을 추가했다.

두번째로 TD_Poll()
다 필요 없는 부분이므로 싹 다 지워 버렸다.

마지막으로 DR_VendorCmnd()
기존에 있던 VR_NAKALL_ON/OFF 명령을 VR_LED_ON/OFF로 바꾸어 주었다.

UniHigh.h 파일을 추가해 주었는데, 이건 함 들여다 보면 무엔지 곧 아시리라.

이제 UniHigh 1.1을 만들어 보자.
이번도 역시 Default Control Endpoint를 이용하는 방법을 연습하기 위한 예제다.

이전 강의에서 FX2가 Endpoint 0으로 오는 명령을 SETUPDAT 레지스터에 넣어서 우리에게 넘긴다고 한 것을 기억 하시는가?
어제 예제에서는 SETUPDAT[1]만 이용했지만, 오늘은 8바이트를 모두 이용해 보자.
우선 T.R.M. Page2-5에 있는 아래 표를 보시라.

Array

첫 번째 바이트에 대한 자세한 설명은 USB Spec. Appendix A에 나와 있으니 시간이 나면 함 들여다 보시라.
두 번째 바이트는 실제 명령이다. (Table 2-2)참조.
나머지 2바이트짜리 3 Word를 위 명령의 인자로 쓸 수 있는데, Value니 Index니 Length하는 이름은 그냥 USB Spec.에서 붙여 놓은 이름이니 그 이름에 상관 없이 우리 맘대로 용도를 정해도 된다.

오늘은 0xD2( VR_LED_BLINK ) 명령어를 추가해 보자.
이 명령어는 그 인자로 깜박거리는 횟수와 깜박거림 사이의 간격을 받는다.
Value(3~4번째 바이트)를 깜박거리는 횟수를 담는 인자로 쓰고, Index(5~6번째 바이트)를 깜박거림 사이의 시간(ms)으로 쓰자.

코딩 전에 미리 설명해 두어야 할 것이 EZ-USB Control Panel의 Vend Request 버튼 옆의 Index, Value, Length 항목들이 본좌가 이제까지 설명한 거시기랑 같은 것이라는 것이다.

Array

일단 UniHigh.h에 #define VR_LED_BLINK 0xD2를 추가한 후에 DR_VendorCmnd()에 다음을 추가해 보자.

BOOL DR_VendorCmnd(void)
{
WORD wValue, wIndex, wCount;

wValue = SETUPDAT[2];
wValue |= SETUPDAT[3]<<8;

wIndex = SETUPDAT[4];
wIndex |= SETUPDAT[5]<<8;

switch (SETUPDAT[1])
{
case VR_LED_ON:
LED0 = ON;
break;
case VR_LED_OFF:
LED0 = OFF;
break;
case VR_LED_BLINK:
LED0 = OFF;
for( wCount=0; wCount < wValue; wCount++ )
{
EZUSB_Delay(wIndex);
LED0 = ON;
EZUSB_Delay(wIndex);
LED0 = OFF;
}
break;
default:
return(TRUE);
}

return(FALSE);
}

UniHigh1.1.zip
여기서 EZUSB_Delay(x)는 Ezusb.lib에 들어있는 함수이다.
인자로 받는 x mSec 동안 놀아 버린다.
함수선언은 C:CypressUSBTargetIncezusb.h에 되어 있고, 자세한 설명은 C:CypressUSBDocEZ-USB General Anchor Firmware FW.pdf를 참조하시라.
나중에 기회가 되면 거기에 나온 함수들을 함 뒤벼보자.


어떻게 잘 되시는 감?
해보시면 아시겠지만
우리가 0xD2명령을 내리면


Array

Application의 "VendReq"버튼이 잠시 눌린 채로 있다가 보드의 깜빡거림이 끝나야 제자리로 돌아온다.
일정시간동안 어플리케이션이 얼어 있다는 소리다.


이거 아주 안좋은 경우가 되겠다.
Default Control Endpoint는 명령을 즉각 수행하고, 바로 리턴 하는 것이 매우 매우 바람직하다.
그런데 이 예제에서는 0xD2명령을 다 처리할 긴 시간동안 디바이스가 호스트에 응답을 주지 않는다.


따라서 본좌가 TD_Poll()에 이 LED점등하는 코드를 옮겼다.
사실 Delay() 함수를 쓰기보다는 타이머를 이용하는 것이 더 좋겠지만, 이 예제는 Default Control Endpoint 사용법을 위한 예제이므로 이번은 그냥 눈감고 넘어가자.
행자들이 함 그렇게 해 보시든가.
UniHigh1.11.zip

'Hardware' 카테고리의 다른 글

버튼입력을 받아보자  (0) 2008.03.31
Control Endpoint의 DATA stage 활용  (0) 2008.03.31
UniHigh v1.0  (0) 2008.03.31
두둥~ 드디어 bulkloop.c  (0) 2008.03.26
땜질 초식을 펼쳐라  (0) 2008.03.26