[应用相关] STM32 USB双缓冲IN端点的疑问

[复制链接]
8145|8
 楼主| 九把刀 发表于 2008-12-19 21:59 | 显示全部楼层 |阅读模式
STM32的USB双缓冲方式到底应该如何使用, 超级迷糊...

参考STR910双缓冲代码, 编写了一个STM32的双缓冲应用, 简单的测试了一下, 功能到是正常的. 就是对双缓冲的原理还不是特别明白.  

OUT端点倒是觉得理解的差不多了. 但是对于IN端点, 正确的操作到底应该如何的...

在那个代码中, USB初始化时设置DTOG_TX=0, SW_BUF=1, 在往缓冲区中写第一个数据包后, 会切换SW_BUF(即1->0).

那么此时, DTOG_TX便与SW_BUF都为0了. 按照数据手册中的说明, 在SW_BUF和DTOG_TX为相同值时, 端点为NAK状态.

可数据却可以正常上传, 这是为何???
香水城 发表于 2008-12-19 23:09 | 显示全部楼层

请参考这个帖子

记得这个帖子的楼主发表过他的源程序,你找找看。
相关链接:https://bbs.21ic.com/club/bbs/list.asp?boardid=49&t=3031280
 楼主| 九把刀 发表于 2008-12-19 23:25 | 显示全部楼层

谢谢香大侠的回复.

我现在发现有两种方式都是可以正常传输的. <针对IN端点>

方式一
1. 在端点初始化时, 设置DTOG_TX=0, SW_BUF=1
   
2. 在主程序中写第一个数据包到缓冲区, 并切换SW_BUF(即1->0)

3. 在端点IN中断程序中写余下的数据包到缓冲区, 并一次切换SW_BUF. 
   (IN端点每中断一次, 便写一个数据包, 根据SW_BUF的状态决定是写入到BUF0还是BUF1)

方式二:
1. 在端点初始化时, 设置DTOG_TX=0, SW_BUF=0 (与上面的方式不同)
   
2. 在主程序中连着两个数据包到缓冲区(分别写到BUF0和BUF1), 并切换SW_BUF两次

3. 在端点IN中断程序中写余下的数据包到缓冲区, 并切换一次SW_BUF. 
   (IN端点每中断一次, 便写一个数据包, 根据SW_BUF的状态决定是写入到BUF0还是BUF1)


我测试了这两种方式, 发现都能正常传送数据... 

到底哪一种是正确可靠的?
STARM 发表于 2013-6-18 10:34 | 显示全部楼层
方式二:
1. 在端点初始化时, 设置DTOG_TX=0, SW_BUF=0 (与上面的方式不同)
   
2. 在主程序中连着两个数据包到缓冲区(分别写到BUF0和BUF1), 并切换SW_BUF两次

并切换SW_BUF两次之后, 不是和 DTOG_TX 一样, 两者都是 0 吗, 数据发不出去吧 ?

因为2个标志位相同它就会发NAK
gongxd126com 发表于 2014-3-13 20:36 | 显示全部楼层
一无所有aaa 发表于 2014-4-22 16:29 | 显示全部楼层
求双传冲代码
一无所有aaa 发表于 2014-4-22 16:29 | 显示全部楼层
求STM32双缓冲代码
abswzp 发表于 2015-10-9 08:57 | 显示全部楼层
STARM 发表于 2013-6-18 10:34
方式二:
1. 在端点初始化时, 设置DTOG_TX=0, SW_BUF=0 (与上面的方式不同)
   

不会发不出去,第1次切换SW_BUF时,usb硬件就开始工作了,很快就会把buf0里的数据发完,与此同时,你的程序正在往buf1里拷贝数据.按照usb48M的时钟速度,应该还没等你拷贝完成,usb早就把buf0发送到pc里了,这之后你才将SW_BUF进行第2次切换
abswzp 发表于 2015-10-9 11:04 | 显示全部楼层
本帖最后由 abswzp 于 2015-10-9 11:11 编辑

在stm32给的例子,STM32_USB-FS-Device_Lib_V4.0.0中的Audio_Speaker端点1就是双缓冲的,自己找下,配置源码给你截取一段

usb_prop.c里void Virtual_Com_Port_Reset(void)函数
  1.   /* Initialize Endpoint 1 */
  2.   SetEPType(ENDP1, EP_ISOCHRONOUS);
  3.   SetEPDblBuffAddr(ENDP1, ENDP1_BUF0Addr, ENDP1_BUF1Addr);
  4.   SetEPDblBuffCount(ENDP1, EP_DBUF_OUT, 0x40);
  5.   ClearDTOG_RX(ENDP1);
  6.   ClearDTOG_TX(ENDP1);
  7.   ToggleDTOG_TX(ENDP1);
  8.   SetEPRxStatus(ENDP1, EP_RX_VALID);
  9.   SetEPTxStatus(ENDP1, EP_TX_DIS);

  10.   SetEPRxValid(ENDP0);
  11.   /* Set this device to response on default address */
  12.   SetDeviceAddress(0);

  13.   bDeviceState = ATTACHED;

  14.   In_Data_Offset = 0;
  15.   Out_Data_Offset = 0;

usb_endp.c
  1. void EP1_OUT_Callback(void)
  2. {
  3.     uint16_t Data_Len;       /* data length*/

  4.     if (GetENDPOINT(ENDP1) & EP_DTOG_TX)
  5.     {
  6.         /*read from ENDP1_BUF0Addr buffer*/
  7.         Data_Len = GetEPDblBuf0Count(ENDP1);
  8.         PMAToUserBufferCopy(Stream_Buff, ENDP1_BUF0Addr, Data_Len);
  9.     }
  10.     else
  11.     {
  12.         /*read from ENDP1_BUF1Addr buffer*/
  13.         Data_Len = GetEPDblBuf1Count(ENDP1);
  14.         PMAToUserBufferCopy(Stream_Buff, ENDP1_BUF1Addr, Data_Len);
  15.     }
  16.     FreeUserBuffer(ENDP1, EP_DBUF_OUT);
  17.     In_Data_Offset += Data_Len;
  18. }


您需要登录后才可以回帖 登录 | 注册

本版积分规则

6

主题

44

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部