| 
 
| 这段时间做了个usb host的一个接口,由于对芯片usb host上的理解不够透彻,所以在接收数据上面走了一些弯路,经过一段时间的努力,终于按自己解决方法解决了问题,现在把心得贴出来,抛砖引玉。 整个框加如下:
 int main (void)
 {
 /* Init Host Library */
 GPIO_Configuration();
 NVIC_Configuration();
 USART_Configuration();
 USBH_Init(&USB_OTG_FS_dev, &MIDI_cb , &USR_Callbacks);
 LED_OFF;
 
 for(;;)
 {
 /* Host Task handler */
 USBH_Process();
 }
 }
 这是主框架,几乎所有的host程序都是这套路子,再熟悉不过了。顺便说明一下,我的项目是接收无周期性的数据,也就是说,不知道这个数据什么时候来。我所读取的usb设备的设备描述符是块传输。有人会说,用中断传输,我刚开始是用中断传输,顺利的收到数据,但总会丢数据。后来我改用块接收,接收代码如下
 static USBH_Status USBH_MIDI_Handle(USB_OTG_CORE_HANDLE *pdev ,
 USBH_DeviceProp_TypeDef   *hdev)
 {
 
 USBH_Status status = USBH_OK;
 HC_STATUS state = URB_IDLE;
 status = HCD_GetURB_State(&USB_OTG_FS_dev);
 switch (MIDI_Machine.state)
 {
 case MIDI_IDLE:
 MIDI_Machine.cb->Init();
 MIDI_Machine.state = MIDI_GET_DATA;
 break;
 
 case MIDI_GET_DATA:
 
 if(status == URB_DONE)
 {
 USBH_BulkReceiveData(pdev,
 MIDI_Machine.buff,
 MIDI_Machine.length,
 MIDI_Machine.hc_num_in);
 }
 
 
 MIDI_Machine.state = MIDI_GET_DATA;
 break;
 default:
 break;
 }
 return status;
 }
 问题出来了,当退出这个状态机后,停在usb_hcd_int.c的这里面
 else if (hcint.b.nak)
 {
 if(hcchar.b.eptype == EP_TYPE_INTR)
 {
 UNMASK_HOST_INT_CHH (num);
 USB_OTG_HC_Halt(pdev, num);
 CLEAR_HC_INT(hcreg , nak);
 }
 else if  ((hcchar.b.eptype == EP_TYPE_CTRL)||
 (hcchar.b.eptype == EP_TYPE_BULK))
 {
 /* re-activate the channel  */
 hcchar.b.chen = 1;
 hcchar.b.chdis = 0;
 USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[num]->HCCHAR, hcchar.d32);
 }
 这是个中断程序,我的理解是,硬件里有个机制,如果你用中断传输,发起读数据事务后,如果fifo是空的,那么硬件会产生NAK的中断,
 
 if(nak)
 {
 //如果是中断传输
 UNMASK_HOST_INT_CHH (num);//屏蔽掉通道中断mask
 USB_OTG_HC_Halt(pdev, num);//停止该通道
 CLEAR_HC_INT(hcreg , nak);  //清除该通道的中断标记
 }
 这样的话,程序又能继续查询,但块传输的情况不一样了,代码如下
 if(nak)
 {
 /* re-activate the channel  */
 hcchar.b.chen = 1;//重新使能该通道
 hcchar.b.chdis = 0;
 USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[num]->HCCHAR, hcchar.d32);
 }
 这样的话,一直就有NAK中断,除非FIFO里有新的数据到来,才会退出这个中断,这样产生的问题是
 会影响程序流程
 例如程序流程是这样的
 这里是接收数据
 USBH_BulkReceiveData()
 收到一组数据
 打算通过UART发送到串口
 UART_SEND()
 这里看好像没有问题,其实当代码调用UART_SEND时,数据是发不出去的,因为一直在NAT中断里打转,直到有新的数据到来,才会通过UART发送出去,这样一来,串口发送的数据是上一次的数据,
 例如数据包是这样的,设备一次会发来两组4个字节的数据,
 01 55 66 77
 02 55 66 77
 现在串口发送的数据是这样的,01这组数据发出去了,而02这组没有发出去,因为host接收完02这组数据后,进入NAK中断了,UART无法发送。接下来设备无周期性的再发来两组4字节的数据
 03 55 66 77
 04 55 66 77
 这次串口发送的是02和03这两组数据,04没有发送出去,这当然是我们不希望看到的。
 所以我一直通过各种方法,想让host实时的发完传送过来的数据,但一起无法解决,改在中断传输虽然不会中断在NAK里,但会丢数据包,如果一次传来5 6 组数据,可能就会丢一组数据,我也不知道什么原因,而块传输呢,总中断在NAT,后来我的解决办法是,把UART发送放到NAT中断里面,问题解决了。也许不是最好的办法,但现在我没有别的办法了
 | 
 |