请问原子的F4的U盘读写程序,综合例程与单独例程为啥不同?

2019-08-20 15:23发布

我用F107的USB OTG做U盘HOST,并且加上文件系统FATFS,运行正常,能够读写U盘文件了。但是,加上UCOS后,总是死机,仿真跟踪,发现总是死在DRESULT disk_read ( BYTE drv,BYTE *buff,DWORD sector,BYTE count ) 这个函数里,此函数里读U盘状态总是处于忙状态,死循环了。我也仿照原子的综合例程,加入了临界保护和8字节对齐,但还是不行。
于是我打开了原子的F4的实验53和综合例程,对比了一下有无UCOS时的代码,如下: 
首先是实验53的disk_read子程序,原子改名为如下:
u8 USBH_UDISK_Read(u8* buf,u32 sector,u32 cnt)
{
 u8 res=1;
 if(HCD_IsDeviceConnected(&USB_OTG_Core)&&AppState==USH_USR_FS_TEST)//??????????,????APP????×???
 {       
  do
  {
   res=USBH_MSC_Read10(&USB_OTG_Core,buf,sector,512*cnt);
   USBH_MSC_HandleBOTXfer(&USB_OTG_Core ,&USB_Host);       
   if(!HCD_IsDeviceConnected(&USB_OTG_Core))
   {
    res=1;//?????í?ó
    break;
   };  
  }while(res==USBH_MSC_BUSY);
 }else res=1;   
 if(res==USBH_MSC_OK)res=0; 
 return res;
}
然后是综合例程的代码:
u8 USBH_UDISK_Read(u8* buf,u32 sector,u32 cnt)
{
 u8 res=1;
 u32 retry=0;
 if(HCD_IsDeviceConnected(&USB_OTG_Core_dev)&&AppState==USH_USR_FS_TEST)//??????????,????APP????×???
 {       
  do
  {
   res=USBH_MSC_Read10(&USB_OTG_Core_dev,buf,sector,512*cnt);
   USBH_MSC_HandleBOTXfer(&USB_OTG_Core_dev ,&USB_Host);       
   if(!HCD_IsDeviceConnected(&USB_OTG_Core_dev))
   {
    res=1;//?????í?ó
    break;
   };
   retry++;
  }while(res==USBH_MSC_BUSY&&retry<0X7FFFFFF);
  if(retry==0X7FFFFFF)res=1;
 }else res=1;   
 if(res==USBH_MSC_OK)res=0; 
 return res;
}

比较一下,有两点不同。一是USB句柄名称由USB_OTG_Core改为USB_OTG_Core_dev,这个估计不是问题,只是个名字;二是原子在综合例程里对检测U盘状态的次数做了限制,使用了局部变量retry。而我恰巧就死在这里,总是检测U盘忙,也就是res==USBH_MSC_BUSY总是为真,因此就死循环了。那么原子为啥在综合例程里加上retry<0X7FFFFFF以便对循环次数做限制呢?  我试验了一下,在我的程序里也对循环次数做限制了,retry<3,则就不死循环了,但也无法读U盘内容了,直接跳过去了。
我想问的是,为啥裸奔都挺好的,完全正常,而加上UCOS后,虽然U盘枚举都正常,并且也能初始化文件系统了,if ( f_mount( 0, &fatfs ) != FR_OK ) 执行很正常,而且还读到了U盘容量,但只要一开始读U盘里的文件内容,使用到了DRESULT disk_read函数(原子改名为USBH_UDISK_Read),则立刻死在里面了。莫名其妙啊!弄了好几天了,请大侠帮忙,谢谢啦!
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
15条回答
solo
2019-08-21 11:54
回复【6楼】void:
---------------------------------
没说不能。例如,我现在的读写U盘的工作模式:USB处理是一个线程,数据操作是一个线程,两个线程通过队列通讯。而所有的文件操作都放在ST的“USBH_USR_MSC_Application”函数里,也就是说外边是没有文件操作的,数据只通过队列才能传进来。USB处理线程里是检测和处理,但是从头到尾不管是检测还是处理调的都是一个函数“USBH_Process”。如果你想文件操作一次导出一个大文件,而只执行一次“USBH_Process”的话,结果丢数。我是每512字节执行一次“USBH_Process”,写成线程时为了方便实现后台USB也能工作。不知道有没有更好的做法,如果USB部分能完全嵌入到操作系统的话谁管啥时候要执行一下“USBH_Process”。

一周热门 更多>