广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
1
PDIUSBD12固件编程指南
介绍
PDIUSBD12是一款带有并行总线和局部DMA传输能力的高速USB接口器件 固件设计的目标就是使PDIUSBD12在USB上达到最大的传输速率 外围设备例如打印机 扫描仪 外部的海量存储器和数码相机都可使用PDIUSBD12在USB上传输数据 这些设备的CPU要忙于处理许多设备控制和数据以及图像处理等任务 PDIUSBD12的固件设计成完全的中断驱 CPU处理 任务 USB的传输可在
行 这就 最 的传输速率和 的 件 和
ISR 中断 务 和 的数据?¢件标£和数据?¥?§currency1' 例如 PDIUSBD12 的“量输可使用 的数据?¥? PDIUSBD12 fi USB fl到一 数据–?
就·CPU?一 中断 CPU 立?”?中断 在ISR中 固件…数据–fiPDIUSBD12‰部?¥?
到 数据?¥?并在? ` PDIUSBD12 的‰部?¥?以使能接fl′的数据– CPU 可以ˉ
的 任务?到完成 例如打印 ˙ ¨?到¥?‰是?有′的数据并?ˇ—
ˉ的 任务
于这 数据是§ USB 口 是并口 ˉ¥?‰ 要处理的′
数据 这 要 这?于数据的处理 ISR能a以最大可能的速 行数据的传输
相 的 控制在数据–处理 用 的 ISR接fl和 存数据?¥?中的控制传输并设
相?的标£?存器o处理 发 于 有的标 器件 和都是在?
o处理 中 行处理 ISR 以 ˉ的 率?一?′的 要在?o? 行
结构
固件结构
的固件有 如下的积木式
发送USB 读测 Key 控制LED和处理USB
总线¢件等等
MAINLOOP.C

CHAP_9.C

PROTODMA.C
中断 务
ISR.C
PDIUSBD12命令接口
D12CI.C
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
2
硬件提取层 EPPHAL.C
这是固件中的最低?代码 ˉ执行·PDIUSBD12和 硬件与I/O相 的访问 与—ˉCPU 平
接口 这部分代码 要或?
/*
//*************************************************************************
// File Name,EPPHAL.C
//*************************************************************************
*/
#include <stdio.h>
#ifdef __C51__
#include <reg51.h> /* special function register declarations */
#include "epphal.h"
#include "d12ci.h"
#include "mainloop.h"
extern EPPFLAGS bEPPflags;
void outportb(unsigned char port,unsigned char val)
{
unsigned char xdata *ext_address;
MCU_HOSTDACK =1;
ext_address=0xff00 + port;
*ext_address = val;
MCU_HOSTDACK =0;
}
unsigned char inportb(unsigned char port)
{
unsigned char c;
unsigned char xdata *ext_address;
MCU_HOSTDACK =1;
ext_address=0xff00 + port;
c = *ext_address ;
MCU_HOSTDACK =0;
硬件提取?
EPPHAL.C
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
3
return c;
}
void eppAwrite(unsigned char A_data)
{
MCU_HOSTDACK =1;
if(bEPPflags.bits.verbose)
printf("eppAwrite = 0x%bx.\n",A_data);
P0 = (A_data | 0x80);
EPP_WRITE = 0;
EPP_DSTROBE = 1;
EPP_ASTROBE = 1;
EPP_ASTROBE = 0;
EPP_ASTROBE = 1;
P0 = (A_data & 0x7F);
EPP_ASTROBE = 0;
EPP_ASTROBE = 1;
MCU_HOSTDACK =0;
}
void program_cpld(unsigned short uSize,unsigned char bCommand)
{
MCU_HOSTDACK = 1;
outportb(CPLD_CNT0,LSB(uSize)); // set CPLD counter
outportb(CPLD_CNT1,MSB(uSize));
if(bEPPflags.bits.verbose)
printf("CPLD counter read back = 0x%bx,0x%bx.\n",inportb(CPLD_CNT0),
inportb(CPLD_CNT1));
if(bCommand & 0x1) {
MCU_DMARD_WR = 0;
EPP_WRITE = 1; // IN_TOKEN_DMA;
}
else {
MCU_DMARD_WR = 1;
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
4
EPP_WRITE = 0; // OUT_TOKEN_DMA;
}
MCU_HOSTDACK = 0;
}
void dma_start(PIO_REQUEST pio)
{
eppAwrite( (pio->uAddressL >> 13) + (pio->bAddressH << 3) );
program_cpld(pio->uSize,pio->bCommand);
}
#endif
PDIUSBD12命令接口 D12CI.C
为 一步 PDIUSBD12的 固件定义 一套压缩 有访问PDIUSBD12功能的命令接口
/*
//*************************************************************************
//File Name,ISR.C
// 98/11/27 I/O mode Main endpoints read/write update (WK)
// 98/12/2 Added D12_ReadMainEndpoint (WK)
//*************************************************************************
*/
#ifdef __C51__
#include <reg51.h> /* special function register declarations */
#else
#include <dos.h>
#endif
#include "epphal.h"
#include "mainloop.h"
#include "d12ci.h"
extern EPPFLAGS bEPPflags;
void D12_SetAddressEnable(unsigned char bAddress,unsigned char bEnable)
{
if(bEPPflags.bits.in_isr == 0)
DISABLE;
outportb(D12_COMMAND,0xD0);
if(bEnable)
bAddress |= 0x80;
outportb(D12_DATA,bAddress);
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
5
if(bEPPflags.bits.in_isr == 0)
ENABLE;
}
void D12_SetEndpointEnable(unsigned char bEnable)
{
if(bEPPflags.bits.in_isr == 0)
DISABLE;
outportb(D12_COMMAND,0xD8);
if(bEnable)
outportb(D12_DATA,1);
else
outportb(D12_DATA,0);
if(bEPPflags.bits.in_isr == 0)
ENABLE;
}
void D12_SetMode(unsigned char bConfig,unsigned char bClkDiv)
{
if(bEPPflags.bits.in_isr == 0)
DISABLE;
outportb(D12_COMMAND,0xF3);
outportb(D12_DATA,bConfig);
outportb(D12_DATA,bClkDiv);
if(bEPPflags.bits.in_isr == 0)
ENABLE;
}
void D12_SetDMA(unsigned char bMode)
{
if(bEPPflags.bits.in_isr == 0)
DISABLE;
outportb(D12_COMMAND,0xFB);
outportb(D12_DATA,bMode);
if(bEPPflags.bits.in_isr == 0)
ENABLE;
}
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
6
unsigned short D12_ReadInterruptRegister(void)
{
unsigned char b1;
unsigned int j;
outportb(D12_COMMAND,0xF4);
b1 = inportb(D12_DATA);
j = inportb(D12_DATA);
j <<= 8;
j += b1;
return j;
}
unsigned char D12_SelectEndpoint(unsigned char bEndp)
{
unsigned char c;
if(bEPPflags.bits.in_isr == 0)
DISABLE;
outportb(D12_COMMAND,bEndp);
c = inportb(D12_DATA);
if(bEPPflags.bits.in_isr == 0)
ENABLE;
return c;
}
unsigned char D12_ReadLastTransactionStatus(unsigned char bEndp)
{
outportb(D12_COMMAND,0x40 + bEndp);
return inportb(D12_DATA);
}
unsigned char D12_ReadEndpointStatus(unsigned char bEndp)
{
unsigned char c;
if(bEPPflags.bits.in_isr == 0)
DISABLE;
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
7
outportb(D12_COMMAND,0x80 + bEndp);
c = inportb(D12_DATA);
if(bEPPflags.bits.in_isr == 0)
ENABLE;
return c;
}
void D12_SetEndpointStatus(unsigned char bEndp,unsigned char bStalled)
{
if(bEPPflags.bits.in_isr == 0)
DISABLE;
outportb(D12_COMMAND,0x40 + bEndp);
outportb(D12_DATA,bStalled);
if(bEPPflags.bits.in_isr == 0)
ENABLE;
}
void D12_SendResume(void)
{
outportb(D12_COMMAND,0xF6);
}
unsigned short D12_ReadCurrentFrameNumber(void)
{
unsigned short i,j;
if(bEPPflags.bits.in_isr == 0)
DISABLE;
outportb(D12_COMMAND,0xF5);
i= inportb(D12_DATA);
j = inportb(D12_DATA);
i += (j<<8);
if(bEPPflags.bits.in_isr == 0)
ENABLE;
return i;
}
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
8
unsigned short D12_ReadChipID(void)
{
unsigned short i,j;
if(bEPPflags.bits.in_isr == 0)
DISABLE;
outportb(portbase+D12_COMMAND,0xFD);
i=inportb(portbase+D12_DATA);
j=inportb(portbase+D12_DATA);
i += (j<<8);
if(bEPPflags.bits.in_isr == 0)
ENABLE;
return i;
}
unsigned char D12_ReadEndpoint(unsigned char endp,unsigned char * buf,unsigned char len)
{
unsigned char i,j;
if(bEPPflags.bits.in_isr == 0)
DISABLE;
outportb(D12_COMMAND,endp);
if((inportb(D12_DATA) & D12_FULLEMPTY) == 0) {
if(bEPPflags.bits.in_isr == 0)
ENABLE;
return 0;
}
outportb(D12_COMMAND,0xF0);
j = inportb(D12_DATA);
j = inportb(D12_DATA);
if(j > len)
j = len;
for(i=0; i<j; i++)
*(buf+i) = inportb(D12_DATA);
outportb(D12_COMMAND,0xF2);
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
9
if(bEPPflags.bits.in_isr == 0)
ENABLE;
return j;
}
// D12_ReadMainEndpoint() added by V2.2 to support double-buffering,
// Caller should assume maxium 128 bytes of returned data,
unsigned char D12_ReadMainEndpoint(unsigned char * buf)
{
unsigned char i,j,k = 0,bDblBuf = 1;
if(bEPPflags.bits.in_isr == 0)
DISABLE;
outportb(D12_COMMAND,0x84);
if( (inportb(D12_DATA) & 0x60) == 0x60)
bDblBuf = 2;
while(bDblBuf) {
outportb(D12_COMMAND,4);
if((inportb(D12_DATA) & D12_FULLEMPTY) == 0)
break;
outportb(D12_COMMAND,0xF0);
j = inportb(D12_DATA);
j = inportb(D12_DATA);
for(i=0; i<j; i++)
*(buf+i+k) = inportb(D12_DATA);
k += j;
outportb(D12_COMMAND,0xF2);
bDblBuf --;
}
if(bEPPflags.bits.in_isr == 0)
ENABLE;
return k;
}
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
10
unsigned char D12_WriteEndpoint(unsigned char endp,unsigned char * buf,unsigned char len)
{
unsigned char i;
if(bEPPflags.bits.in_isr == 0)
DISABLE;
outportb(D12_COMMAND,endp);
inportb(D12_DATA);
outportb(D12_COMMAND,0xF0);
outportb(D12_DATA,0);
outportb(D12_DATA,len);
for(i=0; i<len; i++)
outportb(D12_DATA,*(buf+i));
outportb(D12_COMMAND,0xFA);
if(bEPPflags.bits.in_isr == 0)
ENABLE;
return len;
}
void D12_AcknowledgeEndpoint(unsigned char endp)
{
outportb(D12_COMMAND,endp);
outportb(D12_COMMAND,0xF1);
if(endp == 0)
outportb(D12_COMMAND,0xF2);
}
#ifndef __C51__
unsigned char D12Eval_inportb(void)
{
return inportb(D12_EVAL_PORT_I);
}
void D12Eval_outportb(unsigned char val,unsigned char mask)
{
static unsigned char last_val = 0;
val = (val & mask) | (last_val & (~mask));
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
11
outportb(D12_EVAL_PORT_O,val);
last_val = val;
}
#endif
中断服务程序 ISR.C
这部分代码处理 PDIUSBD12?的中断 ˉ…数据fi PDIUSBD12的‰部 FIFO取?到CPU 存储器并建立正 的¢件标£以 知 行处理
/*
//*************************************************************************
// File Name,ISR.C
// 98/11/25 Added I/O mode Main endpoints access,(WK)
//*************************************************************************
*/
#include <stdio.h>
#include <string.h>
#ifdef __C51__
#include <reg51.h> /* special function register declarations */
#else
#include <dos.h>
#endif
#include "epphal.h"
#include "d12ci.h"
#include "mainloop.h"
#include "usb100.h"
extern void bus_reset(void);
extern void ep0_txdone(void);
extern void ep0_rxdone(void);
extern void ep1_txdone(void);
extern void ep1_rxdone(void);
extern void main_txdone(void);
extern void main_rxdone(void);
extern void dma_eot(void);
/*
//*************************************************************************
// Public static data
//*************************************************************************
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
12
*/
EPPFLAGS bEPPflags;
/* Control endpoint TX/RX buffers */
extern CONTROL_XFER ControlData;
/* ISR static vars */
unsigned char idata GenEpBuf[EP1_PACKET_SIZE];
IO_REQUEST idata ioRequest;
unsigned long ClockTicks = 0;
#ifndef __C51__
void interrupt (*OldTimerIsr)();
void interrupt (*OldUsbIsr)();
unsigned long ClockIsr = 0;
extern unsigned long dmaBuffer;
extern unsigned long ioBuffer; // V2.1
extern unsigned short ioSize,ioCount; // V2.1
#endif
#ifdef __C51__
timer_isr() interrupt 1
{
DISABLE;
ClockTicks++;
bEPPflags.bits.timer = 1;
ENABLE;
}
#else
void interrupt timer_isr(void)
{
DISABLE;
ClockTicks++;
bEPPflags.bits.timer = 1;
(*OldTimerIsr)();
ENABLE;
}
#endif
#ifdef __C51__
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
13
usb_isr() interrupt 0
{
DISABLE;
fn_usb_isr();
ENABLE;
}
#else
void interrupt usb_isr(void)
{
ClockIsr = ClockTicks;
D12Eval_outportb(0x0,0x80);
fn_usb_isr();
outportb(0x20,0x20);
D12Eval_outportb(0x80,0x80);
}
#endif
void fn_usb_isr()
{
unsigned int i_st;
bEPPflags.bits.in_isr = 1;
i_st = D12_ReadInterruptRegister();
if(i_st != 0) {
if(i_st & D12_INT_BUSRESET) {
bus_reset();
bEPPflags.bits.bus_reset = 1;
}
else {
if(i_st & D12_INT_EOT)
dma_eot();
if(i_st & D12_INT_SUSPENDCHANGE)
bEPPflags.bits.suspend = 1;
if(i_st & D12_INT_ENDP0IN)
ep0_txdone();
if(i_st & D12_INT_ENDP0OUT)
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
14
ep0_rxdone();
if(i_st & D12_INT_ENDP1IN)
ep1_txdone();
if(i_st & D12_INT_ENDP1OUT)
ep1_rxdone();
if(i_st & D12_INT_ENDP2IN)
main_txdone();
if(i_st & D12_INT_ENDP2OUT)
main_rxdone();
}
}
bEPPflags.bits.in_isr = 0;
}
void bus_reset(void)
{
}
void ep0_rxdone(void)
{
unsigned char ep_last,i;
ep_last = D12_ReadLastTransactionStatus(0); // Clear interrupt flag
if (ep_last & D12_SETUPPACKET) {
ControlData.wLength = 0;
ControlData.wCount = 0;
if( D12_ReadEndpoint(0,(unsigned char *)(&(ControlData.DeviceRequest)),
sizeof(ControlData.DeviceRequest)) != sizeof(DEVICE_REQUEST) ) {
D12_SetEndpointStatus(0,1);
D12_SetEndpointStatus(1,1);
bEPPflags.bits.control_state = USB_IDLE;
return;
}
#ifdef __C51__
ControlData.DeviceRequest.wValue = SWAP(ControlData.DeviceRequest.wValue);
ControlData.DeviceRequest.wIndex = SWAP(ControlData.DeviceRequest.wIndex);
ControlData.DeviceRequest.wLength = SWAP(ControlData.DeviceRequest.wLength);
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
15
#endif
// Acknowledge setup here to unlock in/out endp
D12_AcknowledgeEndpoint(0);
D12_AcknowledgeEndpoint(1);
ControlData.wLength = ControlData.DeviceRequest.wLength;
ControlData.wCount = 0;
if (ControlData.DeviceRequest.bmRequestType & (unsigned char)USB_ENDPOINT_DIRECTION_MASK)
{
bEPPflags.bits.setup_packet = 1;
bEPPflags.bits.control_state = USB_IDLE; /* get command */
}
else {
if (ControlData.DeviceRequest.wLength == 0) {
bEPPflags.bits.setup_packet = 1;
bEPPflags.bits.control_state = USB_IDLE; /* set command */
}
else {
if(ControlData.DeviceRequest.wLength > MAX_CONTROLDATA_SIZE) {
bEPPflags.bits.control_state = USB_IDLE;
D12_SetEndpointStatus(0,1);
D12_SetEndpointStatus(1,1);
}
else {
bEPPflags.bits.control_state = USB_RECEIVE; /* set command with OUT
token */
}
} // set command with data
} // else set command
} // if setup packet
else if (bEPPflags.bits.control_state == USB_RECEIVE) {
i = D12_ReadEndpoint(0,ControlData.dataBuffer + ControlData.wCount,
EP0_PACKET_SIZE);
ControlData.wCount += i;
if( i != EP0_PACKET_SIZE || ControlData.wCount >= ControlData.wLength) {
bEPPflags.bits.setup_packet = 1;
bEPPflags.bits.control_state = USB_IDLE;
}
}
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
16
else {
bEPPflags.bits.control_state = USB_IDLE;
}
}
void ep0_txdone(void)
{
short i = ControlData.wLength - ControlData.wCount;
D12_ReadLastTransactionStatus(1); // Clear interrupt flag
if (bEPPflags.bits.control_state != USB_TRANSMIT)
return;
if( i >= EP0_PACKET_SIZE) {
D12_WriteEndpoint(1,ControlData.pData + ControlData.wCount,EP0_PACKET_SIZE);
ControlData.wCount += EP0_PACKET_SIZE;
bEPPflags.bits.control_state = USB_TRANSMIT;
}
else if( i != 0) {
D12_WriteEndpoint(1,ControlData.pData + ControlData.wCount,i);
ControlData.wCount += i;
bEPPflags.bits.control_state = USB_IDLE;
}
else if (i == 0){
D12_WriteEndpoint(1,0,0); // Send zero packet at the end
bEPPflags.bits.control_state = USB_IDLE;
}
}
void dma_eot(void)
{
if(bEPPflags.bits.dma_state == DMA_PENDING)
bEPPflags.bits.setup_dma = 1;
else
bEPPflags.bits.dma_state = DMA_IDLE;
}
void ep1_txdone(void)
{
D12_ReadLastTransactionStatus(3); /* Clear interrupt flag */
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
17
}
void ep1_rxdone(void)
{
unsigned char len;
D12_ReadLastTransactionStatus(2); /* Clear interrupt flag */
len = D12_ReadEndpoint(2,GenEpBuf,sizeof(GenEpBuf));
if(len != 0)
bEPPflags.bits.ep1_rxdone = 1;
}
void main_txdone(void)
{
#ifndef __C51__
unsigned short len;
unsigned char far *fp;
unsigned short seg,off;
#endif
D12_ReadLastTransactionStatus(5); /* Clear interrupt flag */
#ifndef __C51__
seg = (ioBuffer + ioCount)>>4;
off = (ioBuffer + ioCount)&0xf;
fp = MK_FP(seg,off);
len = ioSize - ioCount;
if(len == 0) {
if(bEPPflags.bits.dma_state == DMA_PENDING)
bEPPflags.bits.setup_dma = 1;
else
bEPPflags.bits.dma_state = DMA_IDLE;
}
else {
if(len > 64)
len = 64;
len = D12_WriteEndpoint(5,fp,len);
ioCount += len;
}
#endif
}
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
18
void main_rxdone(void)
{
#ifndef __C51__
unsigned char len;
unsigned char far *fp;
unsigned short seg,off;
#endif
D12_ReadLastTransactionStatus(4); /* Clear interrupt flag */
#ifndef __C51__
seg = (ioBuffer + ioCount)>>4;
off = (ioBuffer + ioCount)&0xf;
fp = MK_FP(seg,off);
len = D12_ReadMainEndpoint( fp );
ioCount += len;
if(ioCount >= ioSize) {
if(bEPPflags.bits.dma_state == DMA_PENDING)
bEPPflags.bits.setup_dma = 1;
else
bEPPflags.bits.dma_state = DMA_IDLE;
}
#endif
}
主循环 MAINLOOP.C
¢件标£并 入·?的子 行 一步的处理 ˉ –含人机接口的代码 例如 LED
和键盘扫描
/*
//*************************************************************************
// File Name,MainLoop.C
// 98/11/25 Added I/O access support on Main endpoints,(WK)
//*************************************************************************
*/
#include <stdio.h>
#include <string.h>
#ifdef __C51__
#include <reg51.h> /* special function register declarations */
#else
#include <bios.h>
#include <dos.h>
#include <malloc.h>
#endif
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
19
#include "epphal.h"
#include "d12ci.h"
#include "mainloop.h"
#include "usb100.h"
#include "chap_9.h"
#include "protodma.h"
/*
//*************************************************************************
// USB protocol function pointer arrays
//*************************************************************************
*/
code void (*StandardDeviceRequest[])(void) =
{
get_status,
clear_feature,
reserved,
set_feature,
reserved,
set_address,
get_descriptor,
reserved,
get_configuration,
set_configuration,
get_interface,
set_interface,
reserved,
reserved,
reserved,
reserved
};
code void (*VendorDeviceRequest[])(void) =
{
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
20
reserved,
reserved,
read_write_register,
reserved,
reserved,
reserved
};
/*
//*************************************************************************
// Public static data
//*************************************************************************
*/
extern EPPFLAGS bEPPflags;
extern unsigned long ClockTicks;
extern unsigned char idata GenEpBuf[];
extern IO_REQUEST idata ioRequest;
CONTROL_XFER ControlData;
code char * _NAME_USB_REQUEST_DIRECTION[] =
{
"Host_to_device",
"Device_to_host"
};
code char * _NAME_USB_REQUEST_RECIPIENT[] =
{
"Device",
"Interface",
"Endpoint(0)",
"Other"
};
code char * _NAME_USB_REQUEST_TYPE[] =
{
"Standard",
"Class",
"Vendor",
"Reserved"
};
code char * _NAME_USB_STANDARD_REQUEST[] =
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
21
{
"GET_STATUS",
"CLEAR_FEATURE",
"RESERVED",
"SET_FEATURE",
"RESERVED",
"SET_ADDRESS",
"GET_DESCRIPTOR",
"SET_DESCRIPTOR",
"GET_CONFIGURATION",
"SET_CONFIGURATION",
"GET_INTERFACE",
"SET_INTERFACE",
"SYNC_FRAME"
};
void help_devreq(unsigned char typ,unsigned char req)
{
typ >>= 5;
if(typ == USB_STANDARD_REQUEST) {
printf("Request Type = %s,Request = %s.\n",_NAME_USB_REQUEST_TYPE[typ],
_NAME_USB_STANDARD_REQUEST[req]);
}
else {
#ifdef __C51__
if(bEPPflags.bits.verbose)
printf("Request Type = %s,bRequest = 0x%bx.\n",_NAME_USB_REQUEST_TYPE[typ],
req);
#else
if(bEPPflags.bits.verbose)
printf("Request Type = %s,bRequest = 0x%x.\n",_NAME_USB_REQUEST_TYPE[typ],
req);
#endif
}
}
/* Configure Timer 0
- Mode = 1
- Interrupt = ENABLED
- Clock Source = INTERNAL
- Enable Gating Control = DISABLED
*/
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
22
#ifndef __C51__
extern void interrupt (*OldTimerIsr)();
extern void interrupt (*OldUsbIsr)();
extern unsigned long ClockIsr;
unsigned char far *privateBuffer;
unsigned long dmaBuffer;
unsigned long ioBuffer; // V2.1
unsigned short ioSize,ioCount; // V2.1
#endif
void init_timer0(void)
{
#ifdef __C51__
TMOD &= 0XF0; /* clear Timer 0 */
TMOD |= 0X1;
TL0 = 0X0; /* value set by user */
TH0 = 0X0; /* value set by user */
ET0 = 1; /* IE.1*/
TR0 = 1; /* TCON.4 start timer */
PT0 = 1;
EA = 1;
#else
disable();
OldTimerIsr = getvect(0x8);
setvect(0x8,timer_isr);
enable();
#endif
}
/* Interrupt Control Unit */
/* **** Enabled interrupts in Interrupt Enable Register ****
**** GLOBAL INTERRUPT MUST BE ENABLED FOR ANY OTHER
**** INTERRUPT TO WORK!
*/
/* GLOBAL INTERRUPT DISABLED ALL INTERRUPTS
ARE DISABLED */
/* External interrupt 0 */
/* Priority Level = 0 */
/* Timer 0 interrupt */
/* Priority Level = 0 */
void init_special_interrupts(void)
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
23
{
#ifdef __C51__
IT0 = 0;
EX0 = 1;
PX0 = 0;
#else
unsigned char c,eo;
OldUsbIsr = getvect(0xD);
setvect(0xD,usb_isr);
c = inportb(0x21);
c &= 0xDF;
outportb(0x21,c);
eo = 0x0;
D12Eval_outportb(eo,0x80);
eo = 0x80;
D12Eval_outportb(eo,0x80);
#endif
}
void init_port()
{
#ifdef __C51__
P0 = 0xFF;
P1 = 0xFF;
P2 = 0xFF;
#else
unsigned long phys;
privateBuffer = (unsigned char far *)farmalloc(DMA_BUFFER_SIZE*2L);
if(privateBuffer == NULL) {
printf("Error allocation memory!\n");
exit(1);
}
phys = (unsigned long)FP_SEG(privateBuffer)*16 + FP_OFF(privateBuffer);
if( (phys&0x0ffffL) == 0 ) {
dmaBuffer = phys;
}
else {
phys &= 0xf0000L;
phys += 0x10000;
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
24
dmaBuffer = phys;
}
printf("privateBuffer allocated at %p,dmaBuffer at %lx.\n",
privateBuffer,dmaBuffer);
#endif
}
/*Serial Port */
/*Mode = 1 /8-bit UART
Serial Port Interrupt = Disabled */
/*Receive = Enabled */
/*Auto Addressing = Disabled */
void init_serial(void)
{
#ifdef __C51__
SCON = 0X52;
PCON = 0X80 | PCON;
TMOD = 0X20;
TCON = 0x69; /* TCON */
TH1 = 0xF3;
#endif
}
void on_exit(void)
{
#ifndef __C51__
unsigned char c;
disable();
c = inportb(0x21);
c |= 0x20;
outportb(0x21,c);
setvect(0xD,OldUsbIsr);
setvect(0x8,OldTimerIsr);
disconnect_USB();
enable();
farfree(privateBuffer);
#endif
}
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
25
void main(void)
{
BOOL in_loop = TRUE;
unsigned char key,i;
#ifndef __C51__
unsigned long ClockSec,last_clk;
#endif
init_port();
init_serial();
init_timer0();
init_special_interrupts();
printf("\nPDIUSBD12 evaluation board firmware V2.2.\n");
printf("Copyright (c) Philips Semiconductors,1998.\n");
/* Power on reset,lightup LEDs for 1 sec,
disconnect and reconnect Soft-Connect */
printf("Re-connect PDIUSBD12 evaluation board to USB.\n");
reconnect_USB();
/* Main program loop */
while( in_loop ){
#ifdef __C51__
if (bEPPflags.bits.timer){
DISABLE;
bEPPflags.bits.timer = 0;
ENABLE;
if(bEPPflags.bits.configuration)
check_key_LED();
}
if(RI) {
key = _getkey();
#else
if (bEPPflags.bits.timer){
DISABLE;
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
26
bEPPflags.bits.timer = 0;
ENABLE;
if(bEPPflags.bits.configuration)
check_key_LED();
ClockSec = ClockTicks*10/182;
if(ClockSec != last_clk) {
printf("Idle time = %ld sec.\r",(ClockTicks - ClockIsr)*10/182);
last_clk = ClockSec;
}
}
if( bioskey(1) ) {
key = bioskey(0);
key &= 0xf;
#endif
switch(key) {
case 0x1b,/* ESC */
#ifndef __C51__
in_loop = FALSE;
#endif
break;
case 'r',
D12_SendResume();
break;
case 'i',
if(bEPPflags.bits.control_state == USB_IDLE)
printf("Control state = USB_IDLE.");
else if(bEPPflags.bits.control_state == USB_RECEIVE)
printf("Control state = USB_RECEIVE.");
else if(bEPPflags.bits.control_state == USB_TRANSMIT)
printf("Control state = USB_TRANSMIT.");
printf(" ControlData.wCount = %x.\n",ControlData.wCount);
#ifndef __C51__
printf("Endpoint 4 (Bulk Out) Status = %x,Endpoint 5 (Bulk In) Status = %x.\n",
D12_ReadEndpointStatus(4),D12_ReadEndpointStatus(5));
printf("ioSize = %x,ioCount = %x.\n",ioSize,ioCount);
#else
printf("Endpoint 4 (Bulk Out) Status = %bx,Endpoint 5 (Bulk In) Status = %bx.\n",
D12_ReadEndpointStatus(4),D12_ReadEndpointStatus(5));
#endif
if(bEPPflags.bits.dma_state == DMA_IDLE)
printf("DMA_State = DMA_IDLE.\n");
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
27
else if(bEPPflags.bits.dma_state == DMA_RUNNING)
printf("DMA_State = DMA_RUNNING.\n");
else if(bEPPflags.bits.dma_state == DMA_PENDING)
printf("DMA_State = DMA_PENDING.\n");
#ifndef __C51__
printf("Last Device Request,bmRequestType = 0x%x,bRequest= 0x%x,
wValue = 0x%x,wLength = 0x%x,wIndex = 0x%x.\n",
ControlData.DeviceRequest.bmRequestType,
ControlData.DeviceRequest.bRequest,
ControlData.DeviceRequest.wValue,
ControlData.DeviceRequest.wLength,
ControlData.DeviceRequest.wIndex);
#else
MCU_HOSTDACK = 1;
printf("CPLD counter read back = 0x%bx,0x%bx.\n",inportb(CPLD_CNT0),
inportb(CPLD_CNT1));
MCU_HOSTDACK = 0;
printf("Last Device Request,bmRequestType = 0x%bx,bRequest= 0x%bx,
wValue = 0x%x,wLength = 0x%x,wIndex = 0x%x.\n",
ControlData.DeviceRequest.bmRequestType,
ControlData.DeviceRequest.bRequest,
ControlData.DeviceRequest.wValue,
ControlData.DeviceRequest.wLength,
ControlData.DeviceRequest.wIndex);
#endif
printf("Data,");
for(i = 0; i < ControlData.DeviceRequest.wLength; i ++)
#ifndef __C51__
printf("0x%x,",*((ControlData.dataBuffer)+i));
#else
printf("0x%bx,",*((ControlData.dataBuffer)+i));
#endif
printf("\n");
break;
case '\r',
reconnect_USB();
break;
case 'v',
if(bEPPflags.bits.verbose == 0) {
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
28
printf("Verbose Mode = ON.\n");
DISABLE;
bEPPflags.bits.verbose = 1;
ENABLE;
}
else {
printf("Verbose Mode = OFF.\n");
DISABLE;
bEPPflags.bits.verbose = 0;
ENABLE;
}
break;
default,
break;
}
}
if (bEPPflags.bits.bus_reset) {
DISABLE;
bEPPflags.bits.bus_reset = 0;
ENABLE;
printf("Bus reset!\n");
} // if bus reset
if (bEPPflags.bits.suspend) {
DISABLE;
bEPPflags.bits.suspend= 0;
ENABLE;
suspend_change();
printf("Suspend change!\n");
} // if suspend change
if (bEPPflags.bits.setup_packet){
DISABLE;
bEPPflags.bits.setup_packet = 0;
ENABLE;
control_handler();
} // if setup_packet
if(bEPPflags.bits.setup_dma) {
DISABLE;
bEPPflags.bits.setup_dma = 0;
ENABLE;
setup_dma();
} // if setup_dma
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
29
} // Main Loop
on_exit();
}
void suspend_change(void)
{
}
void stall_ep0(void)
{
D12_SetEndpointStatus(0,1);
D12_SetEndpointStatus(1,1);
}
void disconnect_USB(void)
{
// Initialize D12 configuration
D12_SetMode(D12_NOLAZYCLOCK|D12_CLOCKRUNNING,D12_SETTOONE | D12_CLOCK_12M);
}
void connect_USB(void)
{
// reset event flags
DISABLE;
bEPPflags.value = 0;
ENABLE;
// V2.1 enable normal+sof interrupt
D12_SetDMA(D12_ENDP4INTENABLE | D12_ENDP5INTENABLE);
// Initialize D12 configuration
D12_SetMode(D12_NOLAZYCLOCK|D12_CLOCKRUNNING|D12_SOFTCONNECT,
D12_SETTOONE | D12_CLOCK_12M);
}
void reconnect_USB(void)
{
unsigned long clk_cnt;
#ifndef __C51__
D12Eval_outportb(0xF,0xF);
#else
MCU_LED0 = 0;
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
30
MCU_LED1 = 0;
#endif
disconnect_USB();
printf("Wait for 1 second,..\n");
clk_cnt = ClockTicks;
while(ClockTicks < clk_cnt + 20);
connect_USB();
#ifndef __C51__
D12Eval_outportb(0x0,0xF);
#else
MCU_LED0 = 1;
MCU_LED1 = 1;
#endif
}
void init_unconfig(void)
{
unsigned char i;
D12_SetEndpointEnable(0); /* Disable all endpoints but EPP0,*/
}
void init_config(void)
{
D12_SetEndpointEnable(1); /* Enable generic/iso endpoints,*/
}
void single_transmit(unsigned char * buf,unsigned char len)
{
if( len <= EP0_PACKET_SIZE) {
D12_WriteEndpoint(1,buf,len);
}
}
void code_transmit(unsigned char code * pRomData,unsigned short len)
{
ControlData.wCount = 0;
if(ControlData.wLength > len)
ControlData.wLength = len;
ControlData.pData = pRomData;
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
31
if( ControlData.wLength >= EP0_PACKET_SIZE) {
D12_WriteEndpoint(1,ControlData.pData,EP0_PACKET_SIZE);
ControlData.wCount += EP0_PACKET_SIZE;
DISABLE;
bEPPflags.bits.control_state = USB_TRANSMIT;
ENABLE;
}
else {
D12_WriteEndpoint(1,pRomData,ControlData.wLength);
ControlData.wCount += ControlData.wLength;
DISABLE;
bEPPflags.bits.control_state = USB_IDLE;
ENABLE;
}
}
void check_key_LED(void)
{
static unsigned char c,last_key = 0xf;
#ifndef __C51__
c = D12Eval_inportb();
#else
c = MCU_SWM1 & MCU_SWM2;
#endif
c &= 0x0f;
if (c != last_key) {
D12_WriteEndpoint(3,&c,1);
}
last_key = c;
if(bEPPflags.bits.ep1_rxdone) {
DISABLE;
bEPPflags.bits.ep1_rxdone = 0;
ENABLE;
#ifndef __C51__
D12Eval_outportb(GenEpBuf[3],0xF);
#else
MCU_LED0 = !(GenEpBuf[3] & 0x1);
MCU_LED1 = !(GenEpBuf[3] & 0x2);
#endif
}
}
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
32
void setup_dma()
{
#ifndef __C51__
if(!(ioRequest.bCommand & 0x80)) {
bEPPflags.bits.dma_disable = 1; // V2.1,x86 only
D12_SetDMA(D12_ENDP4INTENABLE | D12_ENDP5INTENABLE);
setup_io();
return;
}
#endif
bEPPflags.bits.dma_disable = 0; // V2.1
dma_start(&ioRequest);
DISABLE;
bEPPflags.bits.dma_state = DMA_RUNNING;
ENABLE;
single_transmit(0,0);
if(ioRequest.bCommand & 0x1)
D12_SetDMA(D12_BURST_16 | D12_DMAENABLE | D12_DMA_INTOKEN);
else
D12_SetDMA(D12_BURST_16 | D12_DMAENABLE);
}
#ifndef __C51__
// setup_io() setup buffer address for I/O mode Main endpoints transfer,
// it only works on PC evaluation kit,
void setup_io()
{
unsigned long offset;
unsigned char far *fp;
unsigned short seg,off;
offset = (((unsigned long)ioRequest.bAddressH)<<16)
+ ioRequest.uAddressL;
ioBuffer = dmaBuffer + offset;
ioSize = ioRequest.uSize;
ioCount = 0;
seg = (ioBuffer + ioCount)>>4;
off = (ioBuffer + ioCount)&0xf;
fp = MK_FP(seg,off);
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
33
DISABLE;
bEPPflags.bits.dma_state = DMA_RUNNING;
ENABLE;
single_transmit(0,0);
if(ioRequest.bCommand & 0x1) {
if(ioSize > 64) {
D12_WriteEndpoint(5,fp,64);
ioCount += 64;
}
else {
D12_WriteEndpoint(5,fp,ioSize);
ioCount += ioSize;
}
}
}
#endif
void control_handler()
{
unsigned char type,req;
type = ControlData.DeviceRequest.bmRequestType & USB_REQUEST_TYPE_MASK;
req = ControlData.DeviceRequest.bRequest & USB_REQUEST_MASK;
help_devreq(type,req); // print out device request
if (type == USB_STANDARD_REQUEST)
(*StandardDeviceRequest[req])();
else if (type == USB_VENDOR_REQUEST)
(*VendorDeviceRequest[req])();
else
stall_ep0();
}
协议层 CHAP_9.C PROTODMA.C
o?处理标 的USB器件 有特殊的例如DMA和TWAIN
/*
//*************************************************************************
// File Name,CHAP_9.C
//*************************************************************************
*/
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
34
#include <stdio.h>
#include <string.h>
#ifdef __C51__
#include <reg51.h> /* special function register declarations */
#else
#include <dos.h>
#endif
#include "epphal.h"
#include "d12ci.h"
#include "mainloop.h"
#include "usb100.h"
#include "chap_9.h"
#define NUM_ENDPOINTS 4
#define CONFIG_DESCRIPTOR_LENGTH sizeof(USB_CONFIGURATION_DESCRIPTOR) \
+ sizeof(USB_INTERFACE_DESCRIPTOR) \
+ (NUM_ENDPOINTS *
sizeof(USB_ENDPOINT_DESCRIPTOR))
extern CONTROL_XFER ControlData;
extern IO_REQUEST idata ioRequest;
extern EPPFLAGS bEPPflags;
code USB_DEVICE_DESCRIPTOR DeviceDescr =
{
sizeof(USB_DEVICE_DESCRIPTOR),
USB_DEVICE_DESCRIPTOR_TYPE,
SWAP(0x0100),
USB_CLASS_CODE_TEST_CLASS_DEVICE,
0,0,
EP0_PACKET_SIZE,
SWAP(0x0471),
#ifndef __C51__
SWAP(0x0222),
#else
SWAP(0x0888),
#endif
SWAP(0x0100),
0,0,0,
1
};
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
35
code USB_CONFIGURATION_DESCRIPTOR ConfigDescr =
{
sizeof(USB_CONFIGURATION_DESCRIPTOR),
USB_CONFIGURATION_DESCRIPTOR_TYPE,
SWAP(CONFIG_DESCRIPTOR_LENGTH),
1,
1,
0,
0x60,
0x1
};
code USB_INTERFACE_DESCRIPTOR InterfaceDescr =
{
sizeof(USB_INTERFACE_DESCRIPTOR),
USB_INTERFACE_DESCRIPTOR_TYPE,
0,
0,
NUM_ENDPOINTS,
USB_CLASS_CODE_TEST_CLASS_DEVICE,
USB_SUBCLASS_CODE_TEST_CLASS_D12,
USB_PROTOCOL_CODE_TEST_CLASS_D12,
0
};
code USB_ENDPOINT_DESCRIPTOR EP1_TXDescr =
{
sizeof(USB_ENDPOINT_DESCRIPTOR),
USB_ENDPOINT_DESCRIPTOR_TYPE,
0x81,
USB_ENDPOINT_TYPE_INTERRUPT,
SWAP(EP1_PACKET_SIZE),
10
};
code USB_ENDPOINT_DESCRIPTOR EP1_RXDescr =
{
sizeof(USB_ENDPOINT_DESCRIPTOR),
USB_ENDPOINT_DESCRIPTOR_TYPE,
0x1,
USB_ENDPOINT_TYPE_INTERRUPT,
SWAP(EP1_PACKET_SIZE),
10
};
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
36
code USB_ENDPOINT_DESCRIPTOR EP2_TXDescr =
{
sizeof(USB_ENDPOINT_DESCRIPTOR),
USB_ENDPOINT_DESCRIPTOR_TYPE,
0x82,
USB_ENDPOINT_TYPE_BULK,
SWAP(EP2_PACKET_SIZE),
10
};
code USB_ENDPOINT_DESCRIPTOR EP2_RXDescr =
{
sizeof(USB_ENDPOINT_DESCRIPTOR),
USB_ENDPOINT_DESCRIPTOR_TYPE,
0x2,
USB_ENDPOINT_TYPE_BULK,
SWAP(EP2_PACKET_SIZE),
10
};
#ifndef __C51__
extern unsigned char far *dmaBuffer;
#endif
/*
//*************************************************************************
// USB Protocol Layer
//*************************************************************************
*/
void reserved(void)
{
stall_ep0();
}
/*
//*************************************************************************
// USB standard device requests
//*************************************************************************
*/
void get_status(void)
{
unsigned char endp,txdat[2];
unsigned char bRecipient = ControlData.DeviceRequest.bmRequestType & USB_RECIPIENT;
unsigned char c;
if (bRecipient == USB_RECIPIENT_DEVICE) {
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
37
if(bEPPflags.bits.remote_wakeup == 1)
txdat[0] = 3;
else
txdat[0] = 1;
txdat[1]=0;
single_transmit(txdat,2);
} else if (bRecipient == USB_RECIPIENT_INTERFACE) {
txdat[0]=0;
txdat[1]=0;
single_transmit(txdat,2);
} else if (bRecipient == USB_RECIPIENT_ENDPOINT) {
endp = (unsigned char)(ControlData.DeviceRequest.wIndex & MAX_ENDPOINTS);
if (ControlData.DeviceRequest.wIndex & (unsigned
char)USB_ENDPOINT_DIRECTION_MASK)
c = D12_SelectEndpoint(endp*2 + 1); /* Control-in */
else
c = D12_SelectEndpoint(endp*2); /* Control-out */
if(c & D12_STALL)
txdat[0] = 1;
else
txdat[0] = 0;
txdat[1] = 0;
single_transmit(txdat,2);
} else
stall_ep0();
}
void clear_feature(void)
{
unsigned char endp;
unsigned char bRecipient = ControlData.DeviceRequest.bmRequestType & USB_RECIPIENT;
if (bRecipient == USB_RECIPIENT_DEVICE
&& ControlData.DeviceRequest.wValue == USB_FEATURE_REMOTE_WAKEUP) {
DISABLE;
bEPPflags.bits.remote_wakeup = 0;
ENABLE;
single_transmit(0,0);
}
else if (bRecipient == USB_RECIPIENT_ENDPOINT
&& ControlData.DeviceRequest.wValue == USB_FEATURE_ENDPOINT_STALL) {
endp = (unsigned char)(ControlData.DeviceRequest.wIndex & MAX_ENDPOINTS);
if (ControlData.DeviceRequest.wIndex & (unsigned char)USB_ENDPOINT_DIRECTION_MASK)
/* clear TX stall for IN on EPn,*/
D12_SetEndpointStatus(endp*2 + 1,0);
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
38
else
/* clear RX stall for OUT on EPn,*/
D12_SetEndpointStatus(endp*2,0);
single_transmit(0,0);
} else
stall_ep0();
}
void set_feature(void)
{
unsigned char endp;
unsigned char bRecipient = ControlData.DeviceRequest.bmRequestType & USB_RECIPIENT;
if (bRecipient == USB_RECIPIENT_DEVICE
&& ControlData.DeviceRequest.wValue == USB_FEATURE_REMOTE_WAKEUP) {
DISABLE;
bEPPflags.bits.remote_wakeup = 1;
ENABLE;
single_transmit(0,0);
}
else if (bRecipient == USB_RECIPIENT_ENDPOINT
&& ControlData.DeviceRequest.wValue == USB_FEATURE_ENDPOINT_STALL) {
endp = (unsigned char)(ControlData.DeviceRequest.wIndex & MAX_ENDPOINTS);
if (ControlData.DeviceRequest.wIndex & (unsigned char)USB_ENDPOINT_DIRECTION_MASK)
/* clear TX stall for IN on EPn,*/
D12_SetEndpointStatus(endp*2 + 1,1);
else
/* clear RX stall for OUT on EPn,*/
D12_SetEndpointStatus(endp*2,1);
single_transmit(0,0);
} else
stall_ep0();
}
void set_address(void)
{
D12_SetAddressEnable((unsigned char)(ControlData.DeviceRequest.wValue &
DEVICE_ADDRESS_MASK),1);
single_transmit(0,0);
}
void get_descriptor(void)
{
unsigned char bDescriptor = MSB(ControlData.DeviceRequest.wValue);
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
39
if (bDescriptor == USB_DEVICE_DESCRIPTOR_TYPE) {
code_transmit((unsigned char code *)&DeviceDescr,sizeof(USB_DEVICE_DESCRIPTOR));
} else if (bDescriptor == USB_CONFIGURATION_DESCRIPTOR_TYPE) {
code_transmit((unsigned char code *)&ConfigDescr,CONFIG_DESCRIPTOR_LENGTH);
} else
stall_ep0();
}
void get_configuration(void)
{
unsigned char c = bEPPflags.bits.configuration;
single_transmit(&c,1);
}
void set_configuration(void)
{
if (ControlData.DeviceRequest.wValue == 0) {
/* put device in unconfigured state */
single_transmit(0,0);
DISABLE;
bEPPflags.bits.configuration = 0;
ENABLE;
init_unconfig();
} else if (ControlData.DeviceRequest.wValue == 1) {
/* Configure device */
single_transmit(0,0);
init_unconfig();
init_config();
DISABLE;
bEPPflags.bits.configuration = 1;
ENABLE;
} else
stall_ep0();
}
void get_interface(void)
{
unsigned char txdat = 0; /* Only/Current interface = 0 */
single_transmit(&txdat,1);
}
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
40
void set_interface(void)
{
if (ControlData.DeviceRequest.wValue == 0 && ControlData.DeviceRequest.wIndex == 0)
single_transmit(0,0);
else
stall_ep0();
}
/*
// File Name,PROTODMA.C
// Author,Wenkai Du
// Created,18 Aug 98
// Modified,
// Revision,2.0
//
//*************************************************************************
*/
#include <stdio.h>
#include <string.h>
#ifdef __C51__
#include <reg51.h> /* special function register declarations */
#include "epphal.h"
#else
#include <dos.h>
#endif
#include "d12ci.h"
#include "mainloop.h"
#include "usb100.h"
#include "chap_9.h"
extern CONTROL_XFER ControlData;
extern IO_REQUEST idata ioRequest;
extern EPPFLAGS bEPPflags;
void get_firmware_version()
{
unsigned char i;
#ifndef __C51__
i = 0x01; // firmware version number,return 0x01 for PC kit version 1
#else
i = 0x21; // firmware version number,return 0x11 for PC kit using 8052,0x21 for USB-EPP
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
41
#endif
single_transmit((unsigned char *)&i,1);
}
void setup_dma_request()
{
memcpy((unsigned char *)&ioRequest + ControlData.DeviceRequest.wValue,
ControlData.dataBuffer,
ControlData.DeviceRequest.wLength);
ioRequest.uSize = SWAP(ioRequest.uSize);
ioRequest.uAddressL = SWAP(ioRequest.uAddressL);
if(ioRequest.uSize > DMA_BUFFER_SIZE) { // Unaccepted request
stall_ep0();
}
else {
if(bEPPflags.bits.dma_state == DMA_IDLE) {
DISABLE;
bEPPflags.bits.setup_dma = 1;
ENABLE;
}
else {
DISABLE;
bEPPflags.bits.dma_state = DMA_PENDING;
ENABLE;
}
} // else if accepted request
}
void read_write_register(void)
{
unsigned char i;
if(ControlData.DeviceRequest.bmRequestType & (unsigned char)
USB_ENDPOINT_DIRECTION_MASK) {
if(bEPPflags.bits.verbose)
printf("Read Registers,Offset = 0x%x,Length = 0x%x,Index = 0x%x.\n",
ControlData.DeviceRequest.wValue,
ControlData.DeviceRequest.wLength,
ControlData.DeviceRequest.wIndex);
if(ControlData.DeviceRequest.wIndex == GET_FIRMWARE_VERSION &&
ControlData.DeviceRequest.wValue == 0 &&
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
42
ControlData.DeviceRequest.wLength == 1)
get_firmware_version();
else
stal_ep0();
} // if read register
else{
if(bEPPflags.bits.verbose) {
printf("Write Registers,Offset = 0x%x,Length = 0x%x,Index = 0x%x.\n",
ControlData.DeviceRequest.wValue,
ControlData.DeviceRequest.wLength,
ControlData.DeviceRequest.wIndex);
printf("Data,");
for(i = 0; i < ControlData.DeviceRequest.wLength; i ++)
#ifndef __C51__
printf("0x%x,",*((ControlData.dataBuffer)+i));
#else
printf("0x%bx,",*((ControlData.dataBuffer)+i));
#endif
printf("\n");
}
if(ControlData.DeviceRequest.wIndex == SETUP_DMA_REQUEST &&
ControlData.DeviceRequest.wValue == 0 &&
ControlData.DeviceRequest.wLength == 6)
setup_dma_request();
else
stal_ep0();
} // if write register
}
与其它CPU平台的固件接口
下表 示为积木 中 要的部分 有两 的接口 第一是第 9 章?o ˉ?支 标
USB使固件?枚举 第二 是完全的 品?发 这…–括 品特殊的固件代码
文件名 Chapter 9 Only 产品级别
EPPHAL.C 口到硬件 口到硬件
D12CI.C 无变 无变
CHAP_9.C 无变 品 门的USB描述符
PROTODMA.C 无变 如果 要
ISR.C 无变 在普 和上? 品 门的处理
MAINLOOP.C CPU 和系统决定 口 定 器和中断初ˇ 要 写
品 门的 处理
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
43
在MAINLOOP.H中有如下CPU和 译器预定义
#ifdef__C51__
#define SWAP(x) ((((x)&0xFF)<<8)|(((x)>>8)&0xFF))
#else
#define SWAP(x) (x)
#define code
#define idata
SWAP ·于微控制器是必要的 ˉ是一 格式 例如8031,code”和”idata”仅在使用8031和Keil
C 译器 才 要
在轮询模式中使用固件
在轮询模式中使用固件是十分方便的 在 中?如下代码
if(interrupt_pin_low)
fn_usb_isr();
常ISR 硬件初ˇ 在轮询模式中?测中断引脚状态并在 要的 候 用ISR
硬件提取层
该?–含最底?的函数 这些函数在 的CPU平 上 要 行?变
void outportb(unsigned char port,unsigned char val);
void inportb(unsigned char port);
void dma_start(PIO_REQUSET pio)
· PDIUSBD12 有的 I/O 访问都可 两 函数 outportb 和 inportb currency1' ·于最 一 函数
ˉ用于currency1' EPP DMA 功能 一 用于设定EPP˙地址和CPLD 计数器 这 类型的currency1'允许系统脱离平 这意味 这?用 适用于8051或PC以外的平
·于USB_EPP dma_start()函数 用以下2 函数 这2 函数在currency1'目标?用中 是必 的
void eppAwrite(unsigned char A_data);
void program_cpld(unsigned short uSize,unsigned char bCommand);
PDIUSBD12命令接口
下面的函数定义成PDIUSBD12的命令接口以 器件的 ˉ 是 数据 的PDIUSBD12
命令
void D12_SetAddressEnable(unsigned char bAddress,unsigned char bEnable);
void D12_SetEndpointEnable(unsigned char bEnable);
void D12_SetMode(unsigned char bConfig,unsigned char bClkDiv);
void D12_SetDMA(unsigned char bMode);
unsigned short D12_ReadInterruptRegister(void);
unsigned char D12_SelectEndpoint(unsigned char bEndp);
unsigned char D12_ReadLastTransactionStatus(unsigned char bEndp);
void D12_SetEndpointStatus(unsigned char bEndp,unsigned char bStalled);
void D12_SendResume(void);
unsigned short D12_ReadCurrentFrameNumber(void);
unsigned char D12_ReadEndpoint(unsigned char endp,unsigned char * buf,unsigned char len);
unsigned char D12_WriteEndpoint(unsigned char endp,unsigned char * buf,unsigned char len);
void D12_AcknowledgeEndpoint(unsigned char endp);
中断服务程序
PDIUSBD12的固件完全 中断驱 ISR的 图如下 示
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
44
在ISR的入口 固件使用D12_ReadInterruptRegiste()§决定中断 ¨ … 入相?的子 行处理
ISR
ISR Entry
Read D12 Interrupt Register
Reset Idle Timer
Bus Reset?
Suspend Change?
DMA EOT?
Control In Done?
Control Out Done?
Generic In Done?
Generic Out Done?
Main In Done?
Main Out Done?
Send EOI to Interrupt Controller
End of ISR
No
No
No
No
No
No
No
No
No
Set Bus Reset Flag Yes
Set Suspend Changed Flag
DMA EOT handler Subroutine
Control RX handler Subroutine
Control TX handler Subroutine
Generic RX handler Subroutine
Generic TX handler Subroutine
Main RX handler
Subroutine
Main TX handler
Subroutine
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
45
ISR与?¢件标£ EPPFLAGS 和数据?¥? CONROL_XFER 行
typedef union_epp_flags
{
struct_flags
{
unsigned char timer,1;
unsigned char bus_reset,1;
unsigned char suspend,1;
unsigned char setup_packet,1;
unsigned char remote_wakeup,1;
unsigned char in_isr,1;
unsigned char control_state,2;
unsigned char configuration,1;
unsigned char verbose,1;
unsigned char ep1_rxdone,1;
unsigned char setup_dma,1;
unsigned char dma_state,2;
}bits;
unsigned short value
}EPPFLAGS;
typedef struct_device_request
{
unsigned char bmRequesetType;
unsigned char bRequest;
unsigned short wValue;
unsigned short windex;
unsigned short wLength;
}DEVICE_REQUEST;
typedef struct_control_xfer
{
DEVICE_REQUSET DeviceRequest;
unsigned short wLength
unsigned short wCount;
unsigned char * pData;
unsigned char dataBuffer[MAX_CONTROLDATA_SIZE];
}CONTROL_XFER;
和ISR 的任务分 是这 的 ISRfiD12 fl 数据 ·数据 行处理 ISRfl
a的数据 ˉ 知 备 等 处理 例如 在OUT数据 的建立– ISR…建立–和OUT数据都存入 CONTROL_XFER?¥?中 ¨ … setup_packer 标£送到 这…
必要的 务 并? 的
总线复位和挂起改变
总线 和 并 要?在 ISR 中 行特殊的处理 ISR 在 EPPFLAGS 中设 bus_reset 或广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
46
suspends 标£ ¨可
控制端点处理程序
控制传输总是在 SETUP?ˇ 为可 的的 DATA ¨ 在 STATUS 上图
示为控制 状态的 变 固件使用这3 状态§正 地处理控制传输
如下 示为控制输?处理 为 ˉ 举一 机的例子 Get Descriptor() 的标
设备
Control Out Handler
Setup Packet?
Select Control Out Endpoint
Read Buffer,save to DeviceRequest
Clear Buffer
Valid Device
Request?
Acknowledge Setup on
Control In and Control Out
Control Read?
Control Write with
Data?
Data length
Acceptable?
Control State <- USB_RECEIVE
End of Handler
Yes
Yes
No
Yes
Yes
Stall Control
Endpoints
No
No
State
USB_RECEIVE?
Control State <- USB_TRANSMIT
Set Event,Setup Packet
Control State <- USB_IDLE
Set Event,Setup Packet
No
Yes
Select Control Out Endpoint
Read Buffer,save to Control Data Buffer
Clear Buffer
All Data Received?
Control State <- USB_IDLE
Set Event,Setup Packet
Yes
Yes
No
No
Control State <- USB_IDLE
No
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
47
USB 器件 D12 接fl到建立– …?一 中断 知 MCU 微控制器”?中断?读 D12 中断
存器决定–是发到控制 是普 如果–是送 控制 MCU 要?读 D12 的最 处理状态?存器 一步 定数据是?是一 建立– 第一 –必 是建立–
fi上面的 图中 MCU 要? 控制输提取建立–的‰ §决定是为 是?
如果控制为 MCU…fi?¥?读?‰ 并…—存入存储? ˉ…fi存储?使 设备
如果是一 有 的 MCU必?控制输发送?¢建立命令以 ′使能下一 建立
接下§ MCU 要£currency1控制传输是控制读 是写 这可以?读建立–中 bmRequestType 的第 8
§currency1' 如果控制传输是一 控制读类型?就是 器件 要在下一 数据? 机发?数据– MCU
要设 一 标£以?示USB设备'在正处于传输模式? 备在 机发送 发送数据
建立 机¥执行数据 D12 等 接fl Control_In –? 如下面的 图
Control_In 处理 示 MCU?§ 要?读D12 的最 处理状态?存器 `Control_In 中断标£
接 MCU在 currency1D12处于传输模式 行数据–的发送
于D12的控制 有16'“FIFO 如果传输的? 大于16',MCU在传输 就必 控制数据的数量 如 图 示 MCU必? 要发送到 机的 和的数据大fi 如果?下的'“数大于16 MCU…§发送16'“并用 fl –? 要?的? 16
下一 Control_In标£§到 MCU… 定的'“是?为` 如果?有数据要发送 MCU
要发送一?的–以?示 机数据 发送完?
如果建立–为 Set_Descriptor()建立–中的控制传输…?示·–为控制写类型 在执行完
Set_Descriptor MCU 等 数据 机发送一 Control_Out 标£ MCUfi D12?¥?中
fl数据 '在处于Control_Out处理 的? MCU?§ currency1D12是?处于USB_Receive模式
¨ MCU 控制输 currency1?¥?是? 并…数据fi?¥?读?
上面 示为控制输入处理 图
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
48
普通端点处理程序
普 输 为fi 机接fl数据– …—为LED控制数据 MCUfi 机接flGeneric_Out
标£?读中断?存器? D12 中断 必 `… ` Generic_Out?¥? 接下§
MCU 要 currency1数据的? 并数据
·于Generic_In 该 为? 机发送一 '“?”?… ‰
处理
于 输入/输 为DMA模式 ·这些的中断是?的 ·这些有 常 要?的中断 务 是 为 `代码 ′全地执行 在·处?入 `中断子
EOT处理程序
于EOT处理?ˉ的 ‰ DMA支 一章
主循环
MCU 一 上˙就 要初ˇ — 有?口 存储? 定 器和中断 务 MCU … ′¨接
USB –括… Soft_Connect?存器设 为 ON 这些? 是 要的 为ˉ 在 MCU 备 务
D12 D12 ¥ 行
在 中 MCU ·键盘 行轮询 如果任 一 特定的?键下 键处理命令…执行子
并该子 的目的仅仅是为 1ms 定 器用于?…该子 以?测在 上的任?键
轮询到?测建立– ˉ currency1建立标£在 是中断 务 如果建立标£
ˉ…o?发送一 器件 行处理 下面 示的 图是 在 执行的
Generic Out Handler
Clear Generic Out Interrupt Bit
Read and Clear Generic Out Buffer
Data Length = 0?
No
Save the Data and Set bEPPFlag Bit
End of Generic Out Handler
Yes
Generic In Handler
Clear Generic In Interrupt Bit
End of Generic In Handler
Main Out Handler
Clear Main Out Interrupt Bit
End of Main Out Handler
Main In Handler
Clear Main In Interrupt Bit
End of Main In Handler
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
49
协议层
清除特征请求
在?特ˇ中 MCU 要?或?器件的一 — 特ˇ MCU决定是?·器件 接口或
有意义 如果接fl器是一 接口… ¥有任 支 使能或设 器件或的— 特ˇ 例如 使用特ˇ 器 如果接fl器是一 器件 功能 使能 MCU 要?该功能 如果接fl器是 MCU必?设状态命令?定的
Main Loop
initialize Ports,Memory and Timer
Setup ISR and Program Interrupt Controller
Reconnect USB
Program Exit?
Keyboard Pressed?
Timer Signal?
Bus Reset?
Suspend Change?
Setup Packet?
Loop
Restore ISR vectors
Reset Interrupt Controller
End
Read Key Code
Handle Key Commands
No
Yes
Update Test LEDs and Check Test Keys
On Evaluation Board
Display Bus Reset Event Detected
Read Suspend State
Display Suspend Changed Event
Dispatch Device Request to
Protocol Layer for Processing
Yes
Yes
Yes
Yes
No
No
No
No
Yes
No
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
50
获得状态请求
在 状态中 MCU必定的接fl器?状态 MCU 要 定的接fl器 如果?
是·器件 MCU 必? 机?器件状态 ·于—有 控和 ˙能力的系统?数据?该是
0x0003 如果接fl器是一 接口 MCU 机?0x0000
Is recipient a device?
Is recipient an
Interface?
Is recipient an
endpoint?
Clear device feature
according to
"Feature Selector"
Yes
No
Yes
No
Yes
Unsupported
Command
No
Clear endpoint feature
according to
"Feature Selector"
Sent zero length
packet to Host
Clear Feature
End Clear
Feature
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
51
设置地址请求
在设 地址中 器件¥fi建立–的‰ 中 到′的地址意·设 地址 含数据
· MCU 要? 机写一 `? 的数据–?为?¢
获得配置请求
在中 MCU必? 的?§ MCU… 定是? 如果器件
…? 机?一 0 如果?1
Get_Status
Return Device
status to host
Is recipient a
device?
Is recipient an
interface?
Return Interface
status to host
Is recipient an
endpoint?
Return Endpoint
status to host
End of Get_Status
Yes
No
No
Unsupported
Command
Yes
No
Yes
Write new address
to device_addr register
Sent zero length
packet to Host.
Set Address
End Set Address
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
52
获得描述符请求
·于 描述符 如果存在描述符 MCU必定的描述符?§ MCU… 定描述符类型是用于器件 是 如果是器件发送器件描述符的 16',控制?'“的? 是 为控制?¥? 有16'“的存储? MCU 要设 一?存器以?示传输 格的
设置配置请求
·于设 MCU…fi建立–中 定 如果 为0 MCU必?存储?中的
标£并 如果该 为 1 MCU 要… 标£ 该标£一 MCU 要? 机发送`数据–?为?¢
获得/设置接口请求
Has Device been
"Configuration"?
Sent " 1" to hostSent " 0 " to host
Get Config
End Get
Config
Did host send
"0" to Device?
Clear Device
configuration flag
Yes
No
Set Device
configuration flag
Sent zero packet
to host
Set Config
End Set Config
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
53
接口中 MCU 要? 机发送一 `数据–?为 一支 的接口 ·于 的设 接口 MCU 机发送一 `数据–?为?¢ 外 要 任 ¢
设置特征请求
设 特ˇ和?特ˇ正 相? 如果接fl器是一 器件 MCU 要 据建立–中的特
ˇ 器设 器件特ˇ 的是 支 接口的接fl 例如 如果特ˇ 器是 0 意味 ·的使能 D12?定的必? D12 设状态 命令a?
DMA支持
基于协议的DMA操作简介
PDIUSBD12有6 —中 2 控制 2 普和2支 DMA传输
在 于?o的 DMA中 机?用 询问器件的固件以? 控制发送的建立
DMA传输 ¨ 在上执行currency1 的“量数据传输 在DMA控制器建立 机可?器件传输最多为
64k'“的数据 要任 固件的 预
一 完 的DMA传输要?以下两 步?
1发送一 并允许器件用DMA传输方? ˇ地址和传输 格·DMAC

2 在上发送或接fl数据–
Is recipient a device?
Is recipient an
Interface?
Is recipient an
endpoint?
Set device feature
according to
"Feature Selector"
Yes
No
Yes
No
Yes
Unsupported
Command
No
Set endpoint feature
according to
"Feature Selector"
Sent zero length
packet to Host
Set Feature
End Set Feature
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
54
器件DMA状态
建立DMA控制为fi 机发? 器件的”?和?o 于DMA的状态
上图 示为器件中 DMA 的 3 状态 IDLE RUNNING 和 PENDING 如果?有 行或 DMA
器件处于 IDLE 状态建立 DMA ACK 行”? 如果器件在 DMA传输的? 中就是
RUNNING状态 建立DMA NAK 行”?并?器件 入PENDING状态 这表示有一 的建立DMA 如果器件在PENDING状态中接fl到 一 建立DMA ′的…?的
下图为固件处理建立DMA和EOT的 图
DMA配置寄存器
D12的DMA —DMA?存器 行控制 该?存器 设 DMA 命令设?存器中
是 有的 都和DMA有 4 中断脚模式 和 7 分 系数 控制D12的中断
下表 示为?的?存器?总
Write Register
Setup DMA
Request?
State = IDLE?
Save Setup DMA Request
Program DMAC
Program D12's DMA Configuration Register
State <- RUNNING
ACK Device Request
State <- PENDING
End of Write Register
Stall Control Endpoint
Yes
No
Yes
No
EOT
State = PENDING?
Program DMAC
Program D12's DMA Configuration Register
State <- RUNNING
ACK Device Request
State <- IDLE
End of EOT
Yes
No
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
55
位 名称 DMA模式 非DMA模式
0&1 DMA'符 `1`&`1` 无
2 DMA使能 `1` `0`
3 DMA方? `1`用于IN标£
`0`用于OUT标£

4? `0` 无
5 中断脚模式 `0` `0`
64中断使能 `0` `1
75中断使能 `0` `1`
currency1 下 D12 和DMAC都 处于?模式 `器件的DMA ′ 是 为这是一?o?的 也就是 在 机的控制 下 在 EOT D12 和 DMA 控制器的 DMA 都 固件 要 ′使能以使ˉ 在接fl到 机的建立DMA ′ DMA传输
要?意的是 在DMA模式中§4和5的中断 这些上的中断 务是 必要的
使DMA传输中有潜在的缺陷 DMA可以看?是最高 的中断 可以在任意两条CPU?令 执行甚至在 ISR 中 于在传输 中 DMA 的状态任 候都有可能?变 ·任 要用§?测 DMA 状态的 都是 可靠的
以下是一 IN 标£DMA传输 示例,dma_dir和dma_transfer_size?建立DMA设
dma_start(dma_dir,MainDmaBuf,dma_transfer_size,3);
dma.bits.dma_burst = 3;
dma.bits.dma_enable = 1;
dma.bits.dma_direction = dma_dir;
dma.bits.auto_reload = 0;
dma.bits.normal_plus_sof = 0;
dma.bits.endp_4_interrupt_enable = 0;
dma.bits.endp_5_interrupt_enable = 0;
D12_SetDMA(dma);
建立DMA请求
建立 DMA是一?控制发送的 在 PDIUSBD12 固件和fi?用 中 这些是 IOCTL_WRITE_REGISTER 微 Windows 98 DDK中的静态图像USB接口定义 完成的 器件
描述如下

0 BmRequestType 1 0x40 器件到 机
1 Brequest 1 0x0C IOCTL_WRITE_REGISTERd固定
2 Wvalue 2 0 偏 设 为`
4 Windex 2 0x0471 建立DMA的固定
6 Wlength 2 6 建立DMA的数据?
在器件 DMA的—在数据 发送 固件和fi?用 使用 有的定义如下 示

0 地址 7 0
1 地址 15 8
2 地址 23 16
DMA传输的地址
3 类型 7 0
4 类型 15 8
传输的 格
5 命令 7 `1` DMA传输
0 `1`IN 标£ `0`OUT标£
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
56
主 端 程
USB器件 是决定传输速率的 一标 机?的?用 在 系统的性能占有 要的地
为 机一?在控制USB的处理
DMA 传输是一 –括 控制和的¨ 于下一步 一的 果决定
以非常 要 虽¨多线 可用于· 行访问以?系统的性能 使用单线 却使处理建立
DMA IOCTL 和数据传输 写文件/读文件的 易许多
IOCTL_WRITE_REGISTER 和 IOCTL_READ_REGISTER 使用 IO_BLOCK 与器件驱 器 行数据 下面 示的 定义是微 静态图像USB接口的一部分
typedef struct _IO_BLOCK {
IN unsigned uOffset;
IN unsigned uLength;
IN OUT PUCHAR pbyData;
IN unsigned uIndex;
} IO_BLOCK,*PIO_BLOCK;
IO_REQUEST 是一 有的定义 –含 建立DMA的ˉ,
typedef struct _IO_REQUEST {
unsigned short uAddressL;
unsigned char bAddressH;
unsigned short uSize;
unsigned char bCommand;
} IO_REQUEST,*PIO_REQUEST;
举例 如下
ioRequest.uAddressL = 0;
ioRequest.bAddressH = 0;
ioRequest.uSize = transfer_size;
ioRequest.bCommand = 0x80; //start,write
ioBlock.uOffset = 0;
ioBlock.uLength = sizeof(IO_REQUEST);
ioBlock.pbyData = (PUCHAR)&ioRequest;
ioBlock.uIndex = 0x471;
bResult = DeviceIoControl(hDevice,
IOCTL_WRITE_REGISTERS,
(PVOID)&ioBlock,
sizeof(IO_BLOCK),
NULL,
0,
&nBytes,
NULL);
if (bResult != TRUE) {
testDlg->MessageBox("Setup DMA request failed!","Test Error");
return;
}
bResult = WriteFile(hFile,
pcIoBuffer,
广州周立功单片机发展有限公司 Tel,(020)38730976 38730977 Fax,38730925 http://www.zlgmcu.com
57
transfer_size,
&nBytes,
NULL);