UniHigh v1.7 완전정복

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

 

gpif waveform을 다 그렸다면, 이제 gpif.c 파일을 생성하여 이를 우리의 프로젝트에 포함시킬 차례이다.

메뉴의 Tools->Export to GPIF.c file을 선택하면 나타나는 대화상자에서 원하는 위치를 지정하고, (프로젝트가 위치한 폴더가 좋으리라.) 파일 이름을 gpif.c로 해서 “저장” 버튼을 누르자.

Keil u-Vision을 열고, 왼쪽 창에서 “Source Group 1”을 선택한 후 마우스 오른버튼을 클릭하면, “Add Files to Group ‘Source Group 1’ ”이란 메뉴가 나타나는데, 이를 클릭하여 앞서 저장한 gpif.c파일을 선택하여 “Add” 버튼을 눌러 준다.

그리고나서 (우리의 경우에는) bulkloop.c파일의 앞부분에 함수의 프로토 타입을 선언해주고, ( UniHigh v1.7 소스 참조 ) TD_Init()에서 GpifInit()함수를 호출해주면 gpif를 사용할 준비절차가 다 마무리 된 것이다.

어떻게 gpif를 시작하느냐?
TD_Poll() 함수를 보시라.

GPIFTRIG = GPIFTRIGRD | GPIF_EP6; 가 gpif 엔진을 구동시키는 키 이다.

위 코드는 세번째 waveform을 시작해서 EP6의 FIFO를 채우겠다는 의미이다.

4개중 어떤 waveform을 가지고 gpif를 동작시켜서 어느 Endpoint의 FIFO에 데이터를 인출할 지 결정하기 위해서는 GPIFWFSELECT 레지스터와 GPIFTRIG(혹은 EPxGPIFTRIG) 레지스터를 세팅해 주어야 한다.
GPIF Designer가 생성하는 기본적인 코드는 그 tab label에도 표시되어 있던 것처럼
첫 번째 waveform은 single read
두 번째는 single write
세 번째는 FIFO read
네 번째는 FIFO write를 위한 것이다.
gpif.c파일의
GPIFWFSELECT = InitData[ 5 ]( = 0x4E )와
T.R.M. p15-83의 GPIFWFSELECT 레지스터 설명을 직접 찾아 보시라.

앞서 강의에서 본좌가 심지어는 모든 waveform을 FIFO read를 위해 쓸 수도 있다고 언급했었다.
어떻게 하느냐?
GPIF Designer로 waveform을 그릴 때, 모두 FIFO read를 위한 각각의 waveform을 그려주고 나서, GPIFWFSELECT의 최하위 두 비트(FIFO read를 위한 waveform을 지정하는 비트)를 상황에 맞게 waveform을 선택하도록 고쳐 줌으로써 우리의 목적을 달성할 수 있다.

gpif가 구동될 때, 어느 Endpoint의 FIFO를 대상으로 하느냐는 GPIFTRIG의 하위 두 비트를 설정하거나, EPxGPIFTRIG에서 x를 선택해 줌으로써 지정할 수 있다.

데이터의 방향 즉, FD포트(Port B)를 통해 데이터가 들어오느냐 나가느냐는 GPIFTRIG의 하위 세 번째 비트를 어떻게 설정하느냐로 결정할 수도 있고,
EPxGPIFTRIG = 0xFF; : gpif write 시작
BYTE cTemp = EPxGPIFTRIG; : gpif read 시작
요렇게 해서 정할 수도 있다.

* GPIFTRIG와 EPxGPIFTRIG는 같은 일을 하는 다른 레지스터이다.
* gpif “read”는 데이터가 FD포트(Port B)를 통해 “FX2로” 들어오는 것이라고 이미 설명했었다.

이제 GPIFTRIG = GPIFTRIGRD | GPIF_EP6;의 의미를 아시것는가?
아직도 모르겠다면 T.R.M.을 잘게 찟어, 달여서 식후 30분, 하루 세 차례 복용하시라.
행자의 내공이 30갑자 증가할 것이다.

UniHigh v1.7의 TD_Poll()에는 본좌가 디버깅을 위해 넣었다가 깜빡 잊고 안 지운 코드들이 있는데 그걸 다 지워버리면 다음과 같다.

if( bConfigured )
{
if( GPIFTRIG & 0x80 )
{
SYNCDELAY;
GPIFTRIG = GPIFTRIGRD | GPIF_EP6;
SYNCDELAY;
while( !( GPIFTRIG & 0x80 ) ); // wait for the transaction to terminate naturally...
SYNCDELAY;
INPKTEND = 0x06;
}
}

야부리를 풀자면 다음과 같다.
디바이스의 configuration이 끝났다면 gpif가 IDLE 상태인지를 확인하고, gpif 엔진을 구동한다.
그리고 gpif 엔진이 일을 마칠 때까지 기다렸다가 EP6의 FIFO에 남아있는 데이터를 마저 패킷으로 날린다.

얼랄라리요?
마지막 줄의 INPKTEND가 하는 짓을 보아하니 gpif가 작동하는 동안 누군가 데이터가 차면 packet을 자동으로 날리나 보네? 라는 생각이 드셔야 한다.
안 드시면 KIN 사이다 드시라.

그렇다.
TD_Init()에 보면
EP6AUTOINLENH = 0x00; // When AUTOIN=1, core commits IN data
EP6AUTOINLENL = 0x40; // …when EPxAUTOINLEN value is met
가 그 짓을 하도록 세팅해 놓은 코드 되겠다.
당삼 세팅하는 그 길이가 Endpoint 디스크립터의 맥스패킷사이즈 보다 작거나 같아야 한다.

고것만 하면 되느냐?
EP6FIFOCFG = 0x08; //00001000 : AUTOIN=1, ZEROLEN=0, WORDWIDE=0
도 해 주어야 한다.

바로 FX2의 AUTOIN 기능이 이제까지 설명한 것이다.

FIFORESET = 0x80; // set NAKALL bit to NAK all transfers from host
FIFORESET = 0x06; // reset EP6 FIFO
FIFORESET = 0x00; // clear NAKALL bit to resume normal operation
는 주석 달린 그대로 EP6 FIFO를 리셋하기 위한 코드이고,

EP6GPIFFLGSEL = 0x02;는
EP6의 FIFO가 꽉 차면 “청기를 올리는” 일을 하도록 세팅한 것이다.

clip_image001

우리가 만든 waveform의 세번째 DP.
요걸 아직 잊지 않으셨으리라 믿는다.

* SYNCDELAY에 대한 설명은 이전 강의 참조.

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Google+ photo

Google+의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

%s에 연결하는 중

%d 블로거가 이것을 좋아합니다: