打印

【转】STM32 USB 问题汇总

[复制链接]
6127|51
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
sunmeat|  楼主 | 2015-2-26 19:07 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

汇总1:STM32的USB例程修改步骤,来自http://blog.csdn.net/cy757/archive/2010/01/01/5117610.aspx


以下是笔者将ST的Custom_HID例程修改为“自定义USB设备”例程时总结出来的,因为笔者也是刚刚学USB开发不久,某些方面理解错误在所难免,请各位大虾指正。


沙发
sunmeat|  楼主 | 2015-2-26 19:07 | 只看该作者
一、usb_desc.c文件
根据你程序使用的通信方式修改。usb_desc.h文件中定义要根据usb_desc.c文件中的数组的大小;ConfigDescriptor[SIZ_CONFIG_DESC]下添加需要处理的端点;根据需要添加或删除报告描述符(主要用于HID)和CDC接口描述符(主要用于实现USB转串口)等。具体方法可以下载个“电脑圈圈”使用D12编写的例子。

使用特权

评论回复
板凳
sunmeat|  楼主 | 2015-2-26 19:07 | 只看该作者
二、Usb_conf.h文件:
1、修改需要处理那些中断
CNTR_CTRM     处理数据正确传输后控制,比如说响应主机
CNTR_DOVRM   /* DMA OVeR/underrun Mask */
CNTR_ERRM     /* ERRor Mask */
CNTR_WKUPM 0  /* WaKe UP Mask */
CNTR_SUSPM    /* SUSPend Mask */
CNTR_RESETM   主要处理USB复位后进行一些初始化任务
CNTR_SOFM     /* Start Of Frame Mask */
CNTR_ESOFM    /* Expected Start Of Frame Mask */
如:
usb_conf.h中的#define IMR_MSK (CNTR_CTRM | CNTR_SOFM | CNTR_RESETM )是决定USB_CNTR寄存器中的那个USB相关中断启动还是屏蔽。

使用特权

评论回复
地板
sunmeat|  楼主 | 2015-2-26 19:07 | 只看该作者
2、根据需要增加端点缓存地址,要根据缓存区的地址修改,防止数据重叠
如下为根据每个缓冲区的大小为64字节修改:
#define ENDP1_TXADDR        (0xC0)
#define ENDP1_RXADDR        (0xD0)
#define ENDP2_TXADDR        (0x100)
#define ENDP2_RXADDR        (0x140)
#define ENDP3_TXADDR        (0x180)
#define ENDP3_RXADDR        (0x1C0)

使用特权

评论回复
5
sunmeat|  楼主 | 2015-2-26 19:08 | 只看该作者
3、修改/* CTR service routines */下的EPX_IN_Callback和EPX_OUT_Callback。注释掉需要处理的函数。NOP_Process表示不处理。

使用特权

评论回复
6
sunmeat|  楼主 | 2015-2-26 19:08 | 只看该作者
三usb_prop.c文件
1、修改void XX_Reset(void)(如:void Joystick_Reset(void))
一般/* Initialize Endpoint 0 */的不用修改,如下为举例说明端点1的初始化,其他端口原理一样。
SetEPType(ENDP1, EP_INTERRUPT);//设置端点1类型
/*EP_BULK  批量端点
EP_CONTROL 控制端点
EP_ISOCHRNOUS 同步端点
EP_INTERRUPT 中断端点*/
SetEPTxAddr(ENDP1, ENDP1_TXADDR); //设置端点1缓冲区基地址
SetEPTxCount(ENDP1, 64);// 配置Tx 缓冲计数器
SetEPRxStatus(ENDP1, EP_RX_DIS);// //设置端点接收关闭
SetEPTxStatus(ENDP1, EP_TX_NAK);// //设置端点1发送不应答
/*
#define EP_RX_DIS      (0x0000) // EndPoint RX DISabled 端点接收关闭
#define EP_RX_STALL    (0x1000) // EndPoint RX STALLed 端点接收延迟
#define EP_RX_NAK      (0x2000) // EndPoint RX NAKed 端点接收不应答
#define EP_RX_VALID    (0x3000) // EndPoint RX VALID端点接收有效
#define EP_TX_DIS      (0x0000) //EndPoint TX DISabled
#define EP_TX_STALL    (0x0010) // EndPoint TX STALLed
#define EP_TX_NAK      (0x0020) // EndPoint TX NAKed
#define EP_TX_VALID    (0x0030) // EndPoint TX VALID */

使用特权

评论回复
7
sunmeat|  楼主 | 2015-2-26 19:09 | 只看该作者
2、删除不相干的描述符等。
如自定义的USB设备就不需要以下结构体初始化:
ONE_DESCRIPTOR Joystick_Report_Descriptor
ONE_DESCRIPTOR Mouse_Hid_Descriptor

使用特权

评论回复
8
sunmeat|  楼主 | 2015-2-26 19:09 | 只看该作者
3、修改RESULT XX_Data_Setup(u8 RequestNo)的数据类请求处理。

使用特权

评论回复
9
sunmeat|  楼主 | 2015-2-26 19:10 | 只看该作者
如Custom_HID例程修改为“自定义USB设备”例程时可以将以下代码删除
if ((RequestNo == GET_DESCRIPTOR)
      && (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT))
      && (pInformation->USBwIndex0 == 0))
  {

    if (pInformation->USBwValue1 == REPORT_DESCRIPTOR)
    {
      CopyRoutine = Joystick_GetReportDescriptor;
    }
    else if (pInformation->USBwValue1 == HID_DESCRIPTOR_TYPE)
    {
      CopyRoutine = Joystick_GetHIDDescriptor;
    }

  }

使用特权

评论回复
10
sunmeat|  楼主 | 2015-2-26 19:15 | 只看该作者
4、删除不相干的获得描述符返回函数
如自定义的USB设备就不需要以下函数:
Joystick_GetReportDescriptor
Joystick_GetHIDDescriptor

使用特权

评论回复
11
sunmeat|  楼主 | 2015-2-26 19:15 | 只看该作者
四、usb_endp.c文件
1、增加之前定义的中断数据处理函数
如:
void EP1_OUT_Callback(void)
{
       这些写接收代码
}

使用特权

评论回复
12
sunmeat|  楼主 | 2015-2-26 19:16 | 只看该作者
五、数据发送和接收,举例说明
1、数据接收
u8 DataLen;
  DataLen = GetEPRxCount(ENDP1);
  PMAToUserBufferCopy(TX1_buffer, ENDP1_RXADDR, DataLen);
  SetEPRxValid(ENDP1);
  USART1_Send(DataLen);
  count_out = 1;

使用特权

评论回复
13
sunmeat|  楼主 | 2015-2-26 19:16 | 只看该作者
2、数据发送
UserToPMABufferCopy(InBuffer, GetEPTxAddr(ENDP1), 64);
SetEPTxCount(ENDP1, 64);                    
SetEPTxValid(ENDP1);

使用特权

评论回复
14
sunmeat|  楼主 | 2015-2-26 19:17 | 只看该作者
汇总2:STM32 USB 程序将BULK EP改成双缓冲机制后,一直狂飚到了1MB/S!来自:http://www.powermcu.com/bbs/viewthread.php?tid=693

使用特权

评论回复
15
sunmeat|  楼主 | 2015-2-26 19:17 | 只看该作者
前天测试自己编写的USB驱动程序时候发现从主机到STM32的OUT传输(主机到设备)速率竟然只有最高33KB/S,实在是晕死了。经过研究后发现是驱动程序中设置的PIPE MaxTransferSize参数的关系,原先设置64只能33KB/S,后参考其他USB设备驱动程序的值,设置成了65535,再测试USB OUT的速度,达到了500KB/S,终于解决了驱动程序的瓶颈。不过算下USB 2.0全速的通讯速率是12Mb/S,排除掉CRC、令牌、SOF等等开销怎么也应该不止最大500KB/S啊。到网上看了看,基本上应该能达到600KB/S~700KB/S以上,我现在的速度应该还有很大的提升才是。

使用特权

评论回复
16
sunmeat|  楼主 | 2015-2-26 19:18 | 只看该作者
看看程序,发现
void EP3_OUT_Callback(void)//EP3 OUT的回调函数,当EP3接收到数据时候中断调用该函数
{
  count_out = GetEPRxCount(ENDP3);//获得接收到的数据长度
  PMAToUserBufferCopy(buffer_out, ENDP3_RXADDR, count_out);//将数据从USB EP3 RX的缓冲区拷贝到用户指定的数组中
  SetEPRxValid(ENDP3); //完成拷贝后置有效状态,从而EP3发送ACK主机可以进行下一个数据包的发送
}

使用特权

评论回复
17
sunmeat|  楼主 | 2015-2-26 19:18 | 只看该作者
  试着将PMAToUserBufferCopy这句注释掉(这样STM32就不处理接收到的数据了)后再测试速度,惊奇地发现速度竟然达到了997KB/S!晚上仔细想了想,数据肯定是要使用的,这个数据拷贝的过程的时间消费总是少不了的;由于通常情况下USB设备BULK数据接收的步骤就是:接收到数据,置NAK->将缓冲区数据拷贝到用户区(用户处理过程)->发ACK通知主机完成了完整的接收可以发送下一个->主机发送下一个,按照以上的步骤USB接收一步步的进行,只要STM32不完成数据处理,状态就一直是NAK,主机就会不停地发送该数据包,浪费了带宽,因此就会导致我上面最大速度500KB/S难以再增加的情况!不甘心啊~~

使用特权

评论回复
18
sunmeat|  楼主 | 2015-2-26 19:18 | 只看该作者
昨天晚上又仔细研究了STM32的技术参考手册的USB章节内容,里面提到BULK可以采用双缓冲机制(PING-PONG)进行处理,正好可以解决上面的情况。双缓冲机制的原理就是分配2块接收缓冲,STM32的用户处理和USB接口可以分别交替占用2个缓冲区,当USB端点接收数据写其中一个缓冲区的时候,用户的应用程序可以同时处理另一个缓冲区,这样缓冲区依次交换占有者,只要用户处理程序在USB端点接收的时间片段内完成处理,就能够完全不影响USB的通讯速度!

使用特权

评论回复
19
sunmeat|  楼主 | 2015-2-26 19:19 | 只看该作者
程序部分修改
一、EP3_OUT的设置修改,
//ZYP:修改EP3为BULK双缓冲方式-------------------------
  SetEPType(ENDP3, EP_BULK);
  SetEPDoubleBuff(ENDP3);
  SetEPDblBuffAddr(ENDP3, ENDP3_BUF0Addr, ENDP3_BUF1Addr);
  SetEPDblBuffCount(ENDP3, EP_DBUF_OUT, VIRTUAL_COM_PORT_DATA_SIZE);
  ClearDTOG_RX(ENDP3);
  ClearDTOG_TX(ENDP3);
  ToggleDTOG_TX(ENDP3);
  SetEPRxStatus(ENDP3, EP_RX_VALID);
  SetEPTxStatus(ENDP3, EP_TX_DIS);
//------------------------------------------------------

使用特权

评论回复
20
sunmeat|  楼主 | 2015-2-26 19:19 | 只看该作者
二、EP3_OUT回调函数的修改
void EP3_OUT_Callback(void)
{
//ZYP:以下是修改成EP3双缓冲OUT后的处理函数
  if (GetENDPOINT(ENDP3) & EP_DTOG_TX)//先判断本次接收到的数据是放在哪块缓冲区的
  {
    FreeUserBuffer(ENDP3, EP_DBUF_OUT); //先释放用户对缓冲区的占有,这样的话USB的下一个接收过程可以立刻进行,

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

208

主题

2132

帖子

13

粉丝