小弟在做一个FPAG to USB(68013)数据传输的项目,Xilinx的sptan3系列FPGA和56管脚的68013;
采用的方案:上位机程序用VC++编写,由于传输文件数据大概在几十M到几百兆之间,所以采用多线程,单独开个线程来发数据,这样可以避免数据堵塞。68013固件是采用slavefifo模式,4缓冲配置。
FPGA固件是一个USB接收模块,将数据接收后放在一个ip核的ram中,待ram满后在一次发给主板的SDRAM中。
调试现象:点击上位机程序的开始发送后,用USBHOUND观察数据,发现没有,然后关掉上位机程序,发现任务管理器中程序的进程还在运行,强行杀也杀不掉,接着我断开主板与电脑USB连接,发现任务管理器的程序进程没了,同时USBHOUND中有了我发的数据,通过核对,发现数据是正确的。这次希望你通过请教和讨论,帮我排除点干扰找出原因,下附代码:
上位机的发数据线程函数:UINT StartThread(void * pParam)
{
CThreadParam* ThreadParam;
CPrint4Dlg* TestDlg;
HANDLE hOutDevice = NULL;
PUCHAR outBuffer = NULL;
ULONG CurrentTransferSize;
ULONG OutPipeNum;
ULONG i;
BULK_TRANSFER_CONTROL outBulkControl;
THREAD_CONTROL outThreadControl;
//得到线程参数
ThreadParam=(CThreadParam *)pParam;
TestDlg=ThreadParam->testDlg;
//打开设备
if(bOpenDriver(&hOutDevice,strDevname.GetBuffer(strDevname.GetLength()))!= TRUE)
{
TestDlg->m_strOutput+="打开设备失败,测试线程结束\r\n";
ThreadParam->bUpdate=TRUE;
return 0;
}
//进行数据传输
OutPipeNum=0;
CurrentTransferSize = 8192;
outBuffer = (unsigned char *)malloc(CurrentTransferSize);
Ripdata_buf =(BYTE*)HeapAlloc(GetProcessHeap(),0,CurrentTransferSize);
TestDlg->file.Seek(438560,CFile::begin);
TestDlg->file.Read(Ripdata_buf,CurrentTransferSize);
while(!gStopPrint)//全局变量来决定是否退出测试线程
{
for (i=0;i<CurrentTransferSize;i++)
outBuffer = Ripdata_buf;
outBulkControl.pipeNum = OutPipeNum;
outThreadControl.hDevice = hOutDevice;
outThreadControl.Ioctl = IOCTL_EZUSB_BULK_WRITE;
outThreadControl.InBuffer = (PVOID)&outBulkControl;
outThreadControl.InBufferSize = sizeof(BULK_TRANSFER_CONTROL);
outThreadControl.OutBuffer = outBuffer;
outThreadControl.OutBufferSize = CurrentTransferSize;
outThreadControl.status = FALSE;
outThreadControl.BytesReturned = 0;
outThreadControl.status= DeviceIoControl(outThreadControl.hDevice,
outThreadControl.Ioctl,
outThreadControl.InBuffer,
outThreadControl.InBufferSize,
outThreadControl.OutBuffer,
outThreadControl.OutBufferSize,
&outThreadControl.BytesReturned,
NULL
);
//如果发生错误,停止数据传输
if ((!outThreadControl.status)||(outThreadControl.BytesReturned != CurrentTransferSize))
{
TestDlg->m_strOutput+= "Error: Write failed\r\n";
Errors++;
gStopPrint = TRUE;
}
SetEvent(hEvent);
ThreadParam->bUpdate=TRUE;
}
free(outBuffer);
CloseHandle(hOutDevice);
ThreadParam->bUpdate=TRUE;
return 0;
}
68013固件一些配置: CPUCS = 0x12; //48MHZ CLKOUT ENALBE
IFCONFIG =0x43;//使用外部时钟,IFCLK输入不反向
SYNCDELAY;
EP2CFG=0xA0; //需要设定为四缓冲,每个缓冲区大小为512字节
SYNCDELAY;
EP4CFG=0x00;
SYNCDELAY;
EP6CFG=0xE0;
SYNCDELAY;
EP8CFG=0x00;
SYNCDELAY;
FIFORESET = 0x80; // activate NAK-ALL to avoid race conditions
SYNCDELAY; // see TRM section 15.14
FIFORESET = 0x02; // reset, FIFO 2
SYNCDELAY; //
FIFORESET = 0x06; // reset, FIFO 6
SYNCDELAY; //
FIFORESET = 0x00; // deactivate NAK-ALL
SYNCDELAY;
PINFLAGSAB = 0xE6; // FLAGA - fixed EP6PF, FLAGB - fixed EP6FF
SYNCDELAY;
PINFLAGSCD = 0xf8; // FLAGC - fixed EP2EF, FLAGD - reserved
SYNCDELAY;
PORTACFG |= 0x00; //0x40; // SLCS, set alt. func. of PA7 pin
SYNCDELAY;
FIFOPINPOLAR = 0x00; // all signals active low,
SYNCDELAY;
OEA|=0x0F;
//小于64字节有效
//EP6FIFOPFH=0x00; //DEIS PKSTAT PK2 PK1 PK0 0 PFC9 PFC8
//EP6FIFOPFL=0x40; //PFC7 PFC6 PFC5 PFC4 PFC3 PFC2 PFC1 PFC0
// handle the case where we were already in AUTO mode...
EP2FIFOCFG = 0x01; // AUTOOUT=0, WORDWIDE=1
SYNCDELAY;
EP2FIFOCFG = 0x11; // AUTOOUT=1, WORDWIDE=1
SYNCDELAY;
EP6FIFOCFG = 0x09; // AUTOIN=1, ZEROLENIN=0, WORDWIDE=1
SYNCDELAY;
//IO设置
PORTCCFG=0x00;
PORTECFG=0x00;
OEC=0x00;
OEE=0xff;
//串口初始化
// PA3=0;
PA0=1;
enum_high_speed=FALSE;
FPGA接收模块状态机:case(STATE)
IDLE:
begin
//添加RESET状态
data_wr<='h0;//写数据初始化
u_slwr<='b1;
u_slrd<='b1;
u_sloe<='b1;
u_addr0<='b1;
u_addr1<='b1;
oe<='b0;
ena<='b0;
enb<='b0;
addra<=13'h1fff;
addrb<=13'h1fff;
dina_i<='h0;
wr_flag<='b0;
flag <= 'b0;
STATE<=READ_EVENT;
end
READ_EVENT:
begin
//enb<='b0;
wr_flag<='b1;
u_addr0<='b0;
u_addr1<='b0;
STATE<=POINT_TO_OUT_FIFO;
end
POINT_TO_OUT_FIFO:
begin
if(u_flagc)
begin
u_sloe<='b0;
u_slrd<='b1;
STATE<=DATA_READY;
end
else
begin
u_sloe<='b1;
u_slrd<='b1;
STATE<=POINT_TO_OUT_FIFO;
end
end
DATA_READY:
begin
if((u_flagc&&data=='h0100&&!flag)||(u_flagc&&flag))
begin
flag<=1'b1;
u_slrd<='b0;
addra<=addra+1;
dina_i<=data;////////////////////data_src
ena<='b1;
enb<='b0;
STATE<=READ;
end
else
begin
u_slrd<='b1;
u_sloe<='b1;
STATE<=POINT_TO_OUT_FIFO;
end
end
READ:
begin
u_slrd<='b1;
ena <='b0;
if(addra!=ADDR_FULL)
STATE<=DATA_READY;
else
STATE<=READ_END;
end
READ_END:
begin
u_slrd<='b1;
u_sloe<='b1;
u_addr0<='b0;
u_addr1<='b0;
addra<='h1fff;
STATE<=WRITE_EVENT;
end
WRITE_EVENT:
begin
wr_flag<='b0;
sd_flag<='b0;
; enb<='b0;
STATE<=POINT_TO_IN_FIFO;
end
POINT_TO_IN_FIFO:
begin
addrb<=addrb+1;
ena<='b0;
enb<='b1;
STATE<=WRITE;
end
WRITE:
begin
if(addrb!=ADDR_FULL)
begin
addrb<=addrb+1;
sd_data<=doutb;
ena<='b0;
enb<='b1;
sd_flag<=1;
STATE<=WRITE;
end
else
begin
addrb<='h1fff;
ena<='b0;
enb<='b0;
STATE<=WRITE_END;
end
end
WRITE_END:
begin
sd_flag<='b0;
wr_flag<='b0;
addrb<='h1fff;//add by lww
u_addr0<='b1;
u_addr1<='b1;
STATE<=IDLE;
end
default:
STATE<=IDLE;
endcase
end
end
|