打印
[STM32F1]

关于stm32f105 usb host 遇到的问题

[复制链接]
3273|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
阿毛2015|  楼主 | 2015-1-22 19:37 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
这段时间做了个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中断里面,问题解决了。也许不是最好的办法,但现在我没有别的办法了
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

1

帖子

0

粉丝