STM32_USB之完全双缓存(包括发送和接收) -- 更新中断处理

        STM32的USB双缓存接收代码其实已经可以在ST提供的USB示例代码中找到,只要稍加修改,就可以得到将近1MB的数据接收性能。虽然Datasheet中说明USB发送也同样可以使用双缓存,但并没有示例代码,由于为了测试性能,自己做了一个,测试中没有发现问题,虽然对性能的提升不如在USB接收上实现双缓存那么多。

注意:
FreeUserBuffer的作用是切换当前的USB缓存。

1.接收双缓冲:

EPX_OUT_Callback中,此代码只是在ST的示例程序的基础上稍加修改,并且不是偶写的,而是一个网友测试的:

if(GetENDPOINT(ENDP3) & EP_DTOG_TX)

 {
  FreeUserBuffer(ENDP3, EP_DBUF_OUT);
  pkg_len = GetEPDblBuf0Count(ENDP3);
  PMAToUserBufferCopy(buffer_out + count_out, ENDP3_RXADDR0, pkg_len);
 }
 else
 {
  FreeUserBuffer(ENDP3, EP_DBUF_OUT);
  pkg_len = GetEPDblBuf1Count(ENDP3);
  PMAToUserBufferCopy(buffer_out + count_out, ENDP3_RXADDR1, pkg_len);
 }


2.发送双缓冲:
发送双缓冲也可以类似的实现,不过代码要比接收双缓冲复杂得多。不过了解原理的话,应该也差不多。
ST的STM32论坛里,也有人提出这个问题:http://www.st.com/mcu/forums-cat-7768-23.html,不过一直都没有人回答。
不过他的代码还有一些问题,或者可以说,他对原理还不够了解。实际代码还要比他的这个复杂。
中断处理代码:

// 有发送程序计算总共的数据表数量(包括ZLP)
// 每次IN中断,则把总共要发送的数据包数量-1

 usb_in_numofpackage--;
 if(GetENDPOINT(ENDP2) & EP_DTOG_RX)
 {
  if(usb_in_numofpackage > 0)
  {
   // enable next package
   // FreeUserBuffer的作用是切换当前的缓存
   // 如果还有数据包要发送,则切换缓存(数据已经准备好了)
   FreeUserBuffer(ENDP2, EP_DBUF_IN);
  }
  // usb_in_data_remain是需要放入缓存的数据长度
  // 在USB发送函数中,首先会填充2个缓冲,usb_in_data_remain为总长度-2个缓冲的长度
  if(usb_in_data_remain > 0)
  {
   // 还有数据要发送
   if(usb_in_data_remain > VIRTUAL_COM_PORT_DATA_SIZE)
   {
    len = VIRTUAL_COM_PORT_DATA_SIZE;
   }
   else
   {
    len = usb_in_data_remain;
   }

// 把数据拷贝到空闲的缓冲区中,并且设置长度
   UserToPMABufferCopy(buffer_in, ENDP2_TXADDR0, len);
   SetEPDblBuf0Count(ENDP2, EP_DBUF_IN, len);
   // usb_in_data_remain减去已经放入缓冲区的长度
   usb_in_data_remain -= len;
   // 更新数据指针
   buffer_in += len;
  }
  else
  {
   // 数据都已放入缓冲,设置空闲缓冲区长度为0
   SetEPDblBuf0Count(ENDP2, EP_DBUF_IN, 0);
  }
 }
 else
 {
  if(usb_in_numofpackage > 0)
  {
   // enable next package
   FreeUserBuffer(ENDP2, EP_DBUF_IN);
  }
  if(usb_in_data_remain > 0)
  {
   if(usb_in_data_remain > VIRTUAL_COM_PORT_DATA_SIZE)
   {
    len = VIRTUAL_COM_PORT_DATA_SIZE;
   }
   else
   {
    len = usb_in_data_remain;
   }
   UserToPMABufferCopy(buffer_in, ENDP2_TXADDR1, len);
   SetEPDblBuf1Count(ENDP2, EP_DBUF_IN, len);
   usb_in_data_remain -= len;
   buffer_in += len;
  }
  else
  {
   SetEPDblBuf1Count(ENDP2, EP_DBUF_IN, 0);
  }
 }

对于这个代码的性能,已经向ST提出,等待答复,之后可能公布。

来源:http://bbs.ednchina.com/BLOG_ARTICLE_196081.HTM

你可能感兴趣的:(工作-C语言)