文档库 最新最全的文档下载
当前位置:文档库 › 用Windriver调试开发PLX9052的几点经验

用Windriver调试开发PLX9052的几点经验

用Windriver调试开发PLX9052的几点经验版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明

https://www.wendangku.net/doc/594396839.html,/logs/49676398.html

用WinDriver的优点就是开发简单,不必了解底层的很多东西,而且

编出的程序与操作系统无关,不像Vxd那样,只能在98下用,否则就要

写WDM.

任何东西都有缺点,WinDriver也不例外,主要wdpnp.sys来维护底层,

这样就会造成相应时间的增加,但是对于一般的应用已经足够了(本人

曾经做过一块数据传输率为12Mbps的PCI卡,驱动就是用Windriver写的).

而且,如果是对性能要求比较苛刻,也可以自己编写Kernal程序. 本人

的观点就是如果作研究,PCI只是作为数据传输的通道,主要的为了验证板上的电路功能,

那么PCI驱动开发越简单越好,可以把主要精力放在真正的关键设计上.

如果是作产品开发,好的驱动还是必不可少的,至少要考虑对主板的兼容性和稳定性.

以下是自己开发过程的一点经验总结,供入门者参考,也请高手们批评指正.

Pci的接口芯片本人只用过AMCC的S5933和PLX的9052,现在正在用9054,觉得

还是PLX的芯片价格便宜,量又足(好买),开发简单,所以我们一直都用它.

关于Plx芯片的硬件电路设计,可以参考公司提供的RDK.(ThreeWater的FTP上就

有),布线时只要注意时钟线,其他线只要别太长(一般接口芯片离插槽都很近,想

画长也不容易,像时钟线,还得走蛇行才行).还有就是93cs46不好买,可以用93LC46

来替代.

这里主要介绍用WinDriver的开发流程:

1. 运行WinDriver Wizard,找到PCI卡.

先将卡插好,确认E2PROM已经插上(可以是空的),启动计算机.发现新硬件提示,忽略.

运行WinDriver Wizard 之后,选"Creat a new driver"选项,在列表中查找PCI : PLX 9050,如果找到,

说明Windriver已经识别出你的卡了.双击之后,进入调试程序,可以查看计算机给

卡分配的各种资源,如IO地址,Memery空间,Int号等等.

2. 生成.inf文件.

在右边的按钮中选择"Generate .INF file",下次启动提示发现新硬件时,就可以

用这个.inf文件来加载wdpnp.sys. 这个文件在X:\windriver\redist目录里.这样

以后启动就不会在提示有新硬件了.

3. 填写E2PROM.

从开始菜单里选择"程序->Windriver->Simples->PLX 9050 Diagnostic",出现

一个调试菜单.选择对E2prom操作即可.

注意: 93LC46的6脚要结VCC,这样才能读E2prom写,否则只能读了.

4. 用上面的程序就可以对卡进行调试了,功能和PLXMon差不多.如果对板上的各个

空间(Bar)都能正常读写,中断可以相应(如果有的话),那么你就已经成功了一半了,

接下来,就可以开发应用程序了.

关于应用程序的开发,

强烈建议:使用WinDriver提供的Sample的源代码作为框架,不要用Wizard生成的代码

或者自己写代码.这不仅是WinDriver公司的建议,也是实际经验教训.本人在一块有中断

的pci调试时,就是因为用生成的代码,始终接收不到中断,而用它的sample就可以.

最后,几点个人经验,仅供参考:

1. 查询方式. 如果数据量不大,对效率要求不高,可以用查询方式. PLX9052提供了4个

用户定义的IO脚,通过Local Registor CNTRL(50H) 来控制读写,可以直接与FGPA相连, 用起来很方便的.

2. 中断方式. 用中断时,要注意对P9050_IntEnable()函数做适当修改.首先,要关闭中断

源,然后才开启中断线程, 然后在打开. PCI一般都使用电平触发的中断,这样中断可以实

共享. 所以,Local端的LINT1和LINT2都可以产生中断,但一般都需要一个ACK信号来清除

中断. 如果这两个管脚连到FPGA时要注意: 不下载时,输出为高阻,plx9052会读成高,这

如果中断高有效,就会产生连续不断地中断;下载后,如果没指定管脚,会输出低,如果此时

中断

是低有效,这时也会产生连续不断地中断,往往会造成计算机Hang,就是死掉了.

我的做法一般是中断由FPGA产生,是高有效的电平信号;PLX9052的USER0作为INT_ACK信号,

高有效.以下是P9050_IntEnable()函数:

BOOL P9050_IntEnable (P9050_HANDLE hPlx, P9050_INT_HANDLER funcIntHandler)

{

DWORD dwIntStatus,dwCntrlStatus;

DWORD dwAddr;

if (!hPlx->fUseInt) return FALSE;

// check if interrupt is already enabled

if (hPlx->Int.hThread) return FALSE;

dwIntStatus = P9050_ReadReg (hPlx, P9050_INTCSR);

BZERO(hPlx->Int.Trans);

/**************************************************************

printf("置INT_ACK,清除中断源,准备打开中断线程 \n");

dwCntrlStatus = P9050_ReadReg(hPlx,P9050_CNTRL);

dwCntrlStatus = 0x10064006 ;

P9050_WriteReg(hPlx,P9050_CNTRL,dwCntrlStatus);

/**************************************************************

// This is a samlpe of handling interrupts:

// Two transfer commands are issued. First the value of the interrrupt c ontrol/status

// register is read. Then, a value of ZERO is written.

// This will cancel interrupts after the first interrupt occurs.

// When using interrupts, this section will have to change:

// you must put transfer commands to CANCEL the source of the interrupt,

otherwise, the

// PC will hang when an interrupt occurs!

dwAddr = hPlx->addrDesc[P9050_ADDR_REG].dwAddr + P9050_INTCSR;

hPlx->Int.Trans[0].cmdTrans = hPlx->addrDesc[P9050_ADDR_REG].fIsMemory ? RM_DWORD : RP_DWORD;

hPlx->Int.Trans[0].dwPort = dwAddr;

hPlx->Int.Trans[1].cmdTrans = hPlx->addrDesc[P9050_ADDR_REG].fIsMemory ? WM_DWORD : WP_DWORD;

hPlx->Int.Trans[1].dwPort = dwAddr;

printf("清除PCI中断允许,准备打开中断线程 \n");

hPlx->Int.Trans[1].Data.Dword = dwIntStatus & ~BIT6 ;

// put here the data to write to the control register

hPlx->Int.Int.dwCmds = 2;

hPlx->Int.Int.Cmd = hPlx->Int.Trans;

hPlx->Int.Int.dwOptions |= INTERRUPT_CMD_COPY;

// this calls WD_IntEnable() and creates an interrupt handler thread

hPlx->Int.funcIntHandler = funcIntHandler;

if (!InterruptThreadEnable(&hPlx->Int.hThread, hPlx->hWD, &hPlx->Int.Int , P9050_IntHandler, (PVOID) hPlx))

{

printf("now return false\n");

return FALSE;

}

printf("中断线程开启,重新设置PCI中断允许 \n");

P9050_WriteReg (hPlx, P9050_INTCSR, dwIntStatus | BIT6 |BIT0 |BIT1);

/***********************************************************************

printf("中断线程开启,清除INT_ACK,准备接收中断 \n");

dwCntrlStatus = P9050_ReadReg(hPlx,P9050_CNTRL);

//dwCntrlStatus |= BIT0;

dwCntrlStatus = 0x10064002;

//dwCntrlStatus &= ~BIT2 ;

P9050_WriteReg(hPlx,P9050_CNTRL,dwCntrlStatus);

/************************************************************************

printf("开始接收中断... ... \n");

return TRUE;

}

中断处理程序中也要先清除中断,处理完再打开中断允许.

void WINAPI PLX_IntHandlerRoutine(P9050_HANDLE hPlx, P9050_INT_RESULT *intRe sult)

{

DWORD dwCntrlStatus;

DWORD dwIntStatus;

//置INT_ACK,清除中断源

dwCntrlStatus = P9050_ReadReg(hPlx,P9050_CNTRL);

dwCntrlStatus |= BIT2 ;

P9050_WriteReg(hPlx,P9050_CNTRL,dwCntrlStatus);

//中断处理程序

printf("\n 这是第 %d 次中断 \n",intResult->dwCounter);

dwIntStatus = P9050_ReadReg(hPlx,P9050_INTCSR);

P9050_WriteReg(hPlx,P9050_INTCSR,dwIntStatus |BIT6 |BIT1 |BIT0); //清INT_ACK,允许中断

dwCntrlStatus = P9050_ReadReg(hPlx,P9050_CNTRL);

dwCntrlStatus &= ~BIT2 ;

P9050_WriteReg(hPlx,P9050_CNTRL,dwCntrlStatus);

}

相关文档