|
一直被U盘的兼容性问题困扰了一个星期,今天终天被确解了,期间看过网上好多人说是因为晶振的问题,我也照着去换了个48M的有源晶振,发现问题也不是有晶振引起的。我这里说一下引起不兼容的问题的根源,而为什么好多网友会遇到和我一样的情况,因为从网上下到的那份51+SL811的代码中有他的缺陷,在EnumUsbDev(BYTE usbaddr)函数中他少了对接口描述符的设置,应该在if (!Set_Configuration())return FALSE;这个语句后面加上一个if(!Set_Interferface())return FALSE; 不知道是不是发代码者故意把他删掉呢,还是本来他就没有,我最痛恨那些发一些动过手脚代码的行为。这个函数的实现你们自己去完成吧,看一下USB协议,然后仿照着Set_Configuration()这个函数应该很容易写出来,要注意的就是里面用的参数一定要从前面得到的接口描述符中取得。 因为我是在ARM上做的项目,这个函数的实现有点不一样 这是我的函数: int Set_Interface(BYTE usbaddr,BYTE bnum,BYTE baltset) {
return VendorCmd(usbaddr, 1, SET_INTERFACE, baltset, bnum, 0, NULL); } //////////////////////////////////////////////////////////////////////////// int VendorCmd(BYTE usbaddr,BYTE bReq,BYTE bCmd,WORD wvalue,WORD wIndex,WORD wLen,BYTE *pData) { SetupPKG setup;
setup.bmRequest = bReq; setup.bRequest = bCmd; setup.wvalue = WordSwap(wvalue); setup.wIndex = wIndex; setup.wLength = wLen;
return ep0Xfer(usbaddr, uDev[usbaddr].wPayLoad[0], &setup, pData); } ///////////////////////////////////////////////////////////////////////////// 还有一点原因就是有些老U盘的速度特别慢,必需要加一定的延时 我的处理方法是在usbXfer(void)这个函数中的以下位置加了个延时,发现效果很好: EZUSB_Delay(200); SL811Write(IntStatus,INT_CLEAR); result = SL811Read(EP0Status); remainder = SL811Read(EP0Counter); 你可以适当的加减延时,U盘就可以被正的读写. //////////////////////////////////////////////////////////////////////////// 通过以上两点的改进后,我测试了我手上的不同牌子的6个U盘,包括以前不能读写的,都能被正确的读出DBR的值,这次让我感悟最深的就是不要轻意的相信网上的代码,我们项目组买的ARM开以板中也同样是这样的问题。 在这里还要感谢那些帮助过的人,我浏览了无数的网页看到几乎是和我一样的问题,就是没有看到有个人来解决,今天我把我的调试心得发上来,希望能对和我一样困扰的人有点帮助,感谢网友 小猴,东东,龙人.......... 呵呵,问过的人太多了 最后还要补充一点就是在做文件系统的时候,要小心很多U盘还是带有MBR,所以你要正确的读到DBR,必需要从MBR中分析出来。 这里还要说一点,就是在用READ,WRITE之前,有些U盘必需要进行一些试探性的动作,比如inquiry,read capacity,test unit,requestsense,通过前面的这些试探性的活动,最后就可以READ,WRITE了,我为什么这样说呢,做USB开发的人都知道 bus hound 这个软件,你拿个U盘去抓一个数据,然后看看这个软件是怎么来处理的,你在自己的程序中就怎么来处理,我其中就遇到过一个U盘 他在进行完inquiry后,端点被禁用了,就是stall,那时我不知道,老在想自己的程序哪里错了,后来,我就在bus hound中受到了启发,bus hound 的做法是有一个reset的过程,我就是去找相应的命令,终于谢天谢地,确实有这样的命令啊,后来想想也是,别人发明这样的命令肯定有他的用处的。 bus hound 这个软件确实是不错的,我前面发现程序中少set_interface 也是从这个软件中得到的启发,不信你去看看,这个软件每次枚举U盘的时候,都是 set_Configuration然后是 set_interface ,不过后来得知,协议上并没有这样的规定,那是为什么要这样做呢,原来是国内的有些U盘生产厂商,他们照搬windows的做法,windows是每次都要这样做的,所以他们写固件的时候,就也要让主机必需进行set_interface。事实上就苦了我们这些菜鸟啊!
|