728x90
728x90
계속해서 Data stage를 가지고 데이터를 호스트로 보내는 방법을 익혀보자.
사실 이 방법은 이미 우리의 코드에 들어 있다.
Fw.c의 SetupCommand()함수에 보면
case SC_GET_DESCRIPTOR:와
case SC_GET_STATUS:가
디바이스가 Default Control Transfer를 수행하는 중에 Data Stage를 통해 데이터를 호스트로 전송하는 예이다.
우리가 desc.a51 파일을 작성하고
펌웨어를 빌드한 후에 UniHigh에 다운로딩 하면,
FX2의 메모리 어딘가에 Descriptor들이 들어가 있을 것이다.
Descriptor들이 들어가 있는 메모리 주소들을 가리키는 인덱스가 각각 pDeviceDscr, pDeviceQualDscr, pConfigDscr, …인데,
이 주소들 중에 하나를 SUDPTRH/L 레지스터에 써 넣으면
SUDPTRH/L의 메모리 주소가 가리키는 곳의 데이터를 FX가 알아서 Data Stage에 실어 보내게 된다.
만약 보낼 데이터가 64byte보다 길어서
하나의 Data Stage에 다 실을 수 없다면,
역시 FX2가 알아서 이를 여러 개의 Data Stage에 실어 보내게 된다.
보낼 데이터가 어디서부터 시작하는지는 우리가 SUDPTRH/L를 써줌으로써 FX2에 알려주게 되지만,
얼마만큼의 데이터를 보낼지 FX2가 어떻게 아는가? 하는 의문이 생기게 된다.
안 생기남? -.-;
그건 SUDPTRCTL 레지스터(Page 15-81)의 설정에 따라 달라지는데,
디폴트 설정인 SDPAUTO = 1 (Auto Mode)일 때에는 FX2가 각 디스크립터의 Length Field를 자동으로 읽어서 알게 된다.
그리고 SDPAUTO = 0 (Manual Mode)로 세팅하게 되면
우리가 직접 EP0BCH/L에 그 길이를 써 주어야 한다.
당근 SDPAUTO = 1일 때에는 SUDPTRH/L 레지스터를 디스크립터를 보내는 용도 외에는 사용할 수 없다. 따라서 SUDPTRH/L 레지스터를 우리가 원하는 (디스크립터가 아닌) 데이터를 호스트로 보내려고 의도한다면,
먼저 SUDPTRCTL 레지스터의 설정을 SDPAUTO = 0 (Manual Mode)로 세팅해 주어야 한다.
FX2의 Default Control Transfer에서
디바이스가 호스트로 데이터를 보내기 위한 방법 중 다를 하나는
EP0BUF[]와 EP0BCH/L 레지스터를 이용하는 방법이다.
먼젓번 강의에서 EP0BUF[]와 EP0BCL은 Data Stage를 통해 호스트로부터 데이터를 받는데 사용했었다.
기억나시남?
그 예와 반대로 이번엔
EP0BUF[] 버퍼에 보내고자 하는 데이터를 쓰고,
EP0BCH/L에 그 데이터를 길이를 적어주면
FX가 그 데이터를 Data Stage에 실어 날린다.
이때 EP0BCL을 적는 순간 FX2가 Transfer를 개시하므로,
먼저 EP0BCH를 쓰고, 다음에 EP0BCL을 써야 한다.
case SC_GET_STATUS:에서 위의 방법을 사용하고 있다.
마지막으로 IN Transfer이든 OUT Transfer이든
Data Stage를 통해 데이터를 주고 받고 나면,
마지막 Status Stage를 통해 ACK를 날려서 Transaction을 마무리 하는데,
이것은 SetupCommand()함수의 마지막에 있는
EP0CS |= bmHSNAK;를 통해 이루어 진다.
예를 들어 호스트가 Default Control Endpoint를 통해 디바이스에게 작업지시를 내린다.
그러면 디바이스가 그 명령을 수행하여 그 결과를 다시 호스트에게 보고할 때까지 얼마간의 시간이 걸리는데,
호스트는 그 작업이 언제 끝나는지 알 수 없으므로 일정한 간격으로 디바이스에게
“다 끝났냐” 하고 계속 물어보게 된다.
디바이스는 작업이 다 끝날 때까지는 호스트가 물어볼 때마다 NAK을 날려서
작업이 계속 진행중임을 알리고,
작업이 끝난 후에는 ACK를 날려서 작업완료를 호스트에게 보고하게 된다.
아래 그림이 Control Transfer의 전체적인 그림이다.
마지막 Status Stage의 Empty Data Packet의 방향은 Data Stage의 Data Packet방향의 반대이다.
Default Control Transfer에서
Data Stage를 통해 데이터를 호스트로 전송하는 예제는
이미 설명했으므로, 본좌가 따로 안 주겠다.
라고 하면 행자들이 섭섭해 할까 봐,
오늘 볼 예제는
위에서 설명한 Default Control Transfer에서 EP0BUF[]와 EP0BCH/L을 이용해서
데이터를 호스트로 보내는 예제이다.
SETUPDATA의 Value와 Index필드에 16bit의 두 값을 주면
디바이스에서 그 값의 곱을 계산하여
Data Stage를 통해 그 결과(32bit)를 반환하는 예제이다.
UniHigh1.3.zip
예제가 워낙 간단하니 따로 설명은 안 하겠다.
추가한 코드도 몇 줄 안 된다.
함 보시라.
다만 결과로 반환 받아야 할 값이 4 Byte이므로,
EZ-USB Control Panel에서
Dir은 1 IN으로
Length는 4로 주어야 한다.
오늘로서 Default Control Transfer를 끝내고
낼은 Interrupt Endpoint를 통해 디바이스에 버튼이 눌렸음을 호스트로 알리는
예제를 함 만들어 보자.
사실 이 방법은 이미 우리의 코드에 들어 있다.
Fw.c의 SetupCommand()함수에 보면
case SC_GET_DESCRIPTOR:와
case SC_GET_STATUS:가
디바이스가 Default Control Transfer를 수행하는 중에 Data Stage를 통해 데이터를 호스트로 전송하는 예이다.
우리가 desc.a51 파일을 작성하고
펌웨어를 빌드한 후에 UniHigh에 다운로딩 하면,
FX2의 메모리 어딘가에 Descriptor들이 들어가 있을 것이다.
Descriptor들이 들어가 있는 메모리 주소들을 가리키는 인덱스가 각각 pDeviceDscr, pDeviceQualDscr, pConfigDscr, …인데,
이 주소들 중에 하나를 SUDPTRH/L 레지스터에 써 넣으면
SUDPTRH/L의 메모리 주소가 가리키는 곳의 데이터를 FX가 알아서 Data Stage에 실어 보내게 된다.
만약 보낼 데이터가 64byte보다 길어서
하나의 Data Stage에 다 실을 수 없다면,
역시 FX2가 알아서 이를 여러 개의 Data Stage에 실어 보내게 된다.
보낼 데이터가 어디서부터 시작하는지는 우리가 SUDPTRH/L를 써줌으로써 FX2에 알려주게 되지만,
얼마만큼의 데이터를 보낼지 FX2가 어떻게 아는가? 하는 의문이 생기게 된다.
안 생기남? -.-;
그건 SUDPTRCTL 레지스터(Page 15-81)의 설정에 따라 달라지는데,
디폴트 설정인 SDPAUTO = 1 (Auto Mode)일 때에는 FX2가 각 디스크립터의 Length Field를 자동으로 읽어서 알게 된다.
그리고 SDPAUTO = 0 (Manual Mode)로 세팅하게 되면
우리가 직접 EP0BCH/L에 그 길이를 써 주어야 한다.
당근 SDPAUTO = 1일 때에는 SUDPTRH/L 레지스터를 디스크립터를 보내는 용도 외에는 사용할 수 없다. 따라서 SUDPTRH/L 레지스터를 우리가 원하는 (디스크립터가 아닌) 데이터를 호스트로 보내려고 의도한다면,
먼저 SUDPTRCTL 레지스터의 설정을 SDPAUTO = 0 (Manual Mode)로 세팅해 주어야 한다.
FX2의 Default Control Transfer에서
디바이스가 호스트로 데이터를 보내기 위한 방법 중 다를 하나는
EP0BUF[]와 EP0BCH/L 레지스터를 이용하는 방법이다.
먼젓번 강의에서 EP0BUF[]와 EP0BCL은 Data Stage를 통해 호스트로부터 데이터를 받는데 사용했었다.
기억나시남?
그 예와 반대로 이번엔
EP0BUF[] 버퍼에 보내고자 하는 데이터를 쓰고,
EP0BCH/L에 그 데이터를 길이를 적어주면
FX가 그 데이터를 Data Stage에 실어 날린다.
이때 EP0BCL을 적는 순간 FX2가 Transfer를 개시하므로,
먼저 EP0BCH를 쓰고, 다음에 EP0BCL을 써야 한다.
case SC_GET_STATUS:에서 위의 방법을 사용하고 있다.
마지막으로 IN Transfer이든 OUT Transfer이든
Data Stage를 통해 데이터를 주고 받고 나면,
마지막 Status Stage를 통해 ACK를 날려서 Transaction을 마무리 하는데,
이것은 SetupCommand()함수의 마지막에 있는
EP0CS |= bmHSNAK;를 통해 이루어 진다.
예를 들어 호스트가 Default Control Endpoint를 통해 디바이스에게 작업지시를 내린다.
그러면 디바이스가 그 명령을 수행하여 그 결과를 다시 호스트에게 보고할 때까지 얼마간의 시간이 걸리는데,
호스트는 그 작업이 언제 끝나는지 알 수 없으므로 일정한 간격으로 디바이스에게
“다 끝났냐” 하고 계속 물어보게 된다.
디바이스는 작업이 다 끝날 때까지는 호스트가 물어볼 때마다 NAK을 날려서
작업이 계속 진행중임을 알리고,
작업이 끝난 후에는 ACK를 날려서 작업완료를 호스트에게 보고하게 된다.
아래 그림이 Control Transfer의 전체적인 그림이다.
마지막 Status Stage의 Empty Data Packet의 방향은 Data Stage의 Data Packet방향의 반대이다.
Setup Stage
Token Packet : 호스트->디바이스
Data Packet : 호스트->디바이스 – 명령을 받아라
Handshake Packet : 디바이스->호스트 – 명령을 잘 받았다
Data Stage
Token Packet : 호스트->디바이스
Data Packet : 디바이스->호스트 – 여기 데이터를 보낸다.
Handshake Packet : 호스트->디바이스 – 데이터 잘 받았다
Status Stage
Token Packet : 호스트->디바이스
Data Packet : 호스트->디바이스 – 명령 수행을 다 끝냈냐?
Handshake Packet : 디바이스->호스트 – ACK : 명령 수행을 끝냈다.
NAK : 쫌 더 지둘려라.
Default Control Transfer에서
Data Stage를 통해 데이터를 호스트로 전송하는 예제는
이미 설명했으므로, 본좌가 따로 안 주겠다.
라고 하면 행자들이 섭섭해 할까 봐,
오늘 볼 예제는
위에서 설명한 Default Control Transfer에서 EP0BUF[]와 EP0BCH/L을 이용해서
데이터를 호스트로 보내는 예제이다.
SETUPDATA의 Value와 Index필드에 16bit의 두 값을 주면
디바이스에서 그 값의 곱을 계산하여
Data Stage를 통해 그 결과(32bit)를 반환하는 예제이다.
UniHigh1.3.zip
예제가 워낙 간단하니 따로 설명은 안 하겠다.
추가한 코드도 몇 줄 안 된다.
함 보시라.
다만 결과로 반환 받아야 할 값이 4 Byte이므로,
EZ-USB Control Panel에서
Dir은 1 IN으로
Length는 4로 주어야 한다.
오늘로서 Default Control Transfer를 끝내고
낼은 Interrupt Endpoint를 통해 디바이스에 버튼이 눌렸음을 호스트로 알리는
예제를 함 만들어 보자.
728x90
'WORK > Sotfware' 카테고리의 다른 글
트리(자료구조)의 리스트 표현 방법 (0) | 2008.07.08 |
---|---|
USB SPEC (0) | 2008.07.08 |
USB Class Codes (0) | 2008.07.04 |
srtcmp (0) | 2008.06.30 |
RichEdit 초기 설정 및 주의 (0) | 2008.06.18 |
댓글