⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb.c

📁 USB 通信,使用的是Freescale公司的CMX协议栈
💻 C
📖 第 1 页 / 共 4 页
字号:
//        type: 端点传输类型                                               *
//        ep  : 端点号                                                     *
//        psize: 端点传输的数据字节数                                      *
//返  回:成功返回0,不成功返回非0                                          *
//说  明:                                                                  *
//    对指定的端点进行配置,将端点信息写入缓冲区描述符表                    *
//-------------------------------------------------------------------------*
static hcc_u8 usb_setup_ep(hcc_u8 addr, hcc_u8 type, hcc_u8 ep, hcc_u16 psize)
{
  hcc_u8 endpt;
  //禁止端点
  disable_ep_tx(ep);
  disable_ep_rx(ep);

  if (ep_info[ep].state!=EPST_IDLE)
  {
    ep_info[ep].error=USBEPERR_HOST_ABORT;
  }
  else
  {
    ep_info[ep].error=USBEPERR_NONE;    
  }

  ep_info[ep].state=EPST_IDLE;
  ep_info[ep].flags=0;
  ep_info[ep].data_func=(void*)0;
  ep_info[ep].address=0;
  ep_info[ep].tlength=0;
  ep_info[ep].maxlength=0;
  ep_info[ep].psize=psize;
  ep_info[ep].data0_tx=0;
  ep_info[ep].data0_rx=0;
  if (type == EP_TYPE_DISABLE)
  {
    return(0);
  }
  
  endpt =0;

  //该端点作为OUT
  if (!(addr & DIR_TX) || type == EP_TYPE_CONTROL)
  {
    endpt |=MCF_USB_ENDPT_EP_RX_EN;
    //设置BDT的BDT_CTL_RX为默认值,包的大小,CPU拥有,使能数据同步触发,data0
	WR_LE32(&BDT_CTL_RX(ep, 0), (psize << 16) | BDT_CTL_DTS);
    WR_LE32(&BDT_CTL_RX(ep, 1), (psize << 16) | BDT_CTL_DTS);	    
    
    //设置RX缓冲区的地址   
    WR_LE32(&BDT_ADR_RX(ep, 0), (hcc_u32)get_ep_rx_buffer(ep, 0));
    WR_LE32(&BDT_ADR_RX(ep, 1), (hcc_u32)get_ep_rx_buffer(ep, 1)); 
  }
  
  //该端点作为IN
  if ((addr & DIR_TX) || type == EP_TYPE_CONTROL)
  {
    endpt |= MCF_USB_ENDPT_EP_TX_EN;
    //设置BDT的BDT_CTL_RX为默认值,CPU拥有,其它位并不重要
    WR_LE32(&BDT_CTL_TX(ep, 0), 0);
	WR_LE32(&BDT_CTL_TX(ep, 1), 0);
  }

  //如果端点传输类型不是ISO,则在事务结束后握手,否则不要握手
  if (type != EP_TYPE_ISO)
  { 
    endpt |= MCF_USB_ENDPT_EP_HSHK;
  }

  /* If a non control endpoint uses both directions (e.g. two endpoint is
    implemented in the same hardware slot), then CTL_DIS shall be set. */
  if (type != EP_TYPE_CONTROL)
  {
    endpt |= MCF_USB_ENDPT_EP_CTL_DIS;
  }
  else
  { //默认允许控制端点接收数据
    //如果为控制传输则设置端点允许的最大包长度
    WR_LE32(&BDT_CTL_RX(ep, ep_info[ep].next_rx), (hcc_u32)ep_info[ep].psize<<16u);
    ready_ep_rx(ep, ep_info[ep].next_rx);
  }

  MCF_USB_ENDPT(ep)=endpt;

  return(0);
}

//set_config:完成配置描述符配置--------------------------------------------*
//功  能:                                                                  *
//    完成配置描述符配置                                                   *
//参  数: cfg_ndx: 配置描述符索引                                          *
//返  回: 无                                                               *
//说  明:                                                                  *
//      指定的配置必须存在                                                 *
//      接口必须从0开始依次增加(0,1,2,3...)                                *
//      配置必须从0开始依次增加(0,1,2,3...)                                *
//-------------------------------------------------------------------------*
static void set_config(hcc_u8 cfg_ndx)
{ 
  hcc_u8 cfg_ep=0;
  
  usb_current_config=cfg_ndx;
  if (cfg_ndx != 0)
  {
    //将配置描述符中的所有接口配置完成
    hcc_u8 ifc=0;
    while(is_ifc_ndx(cfg_ndx, ifc, 0))
    {
      //将接口描述符中的所有端点配置完成
      hcc_u8 ifc_ep=0;
      while(is_ep_ndx(cfg_ndx, ifc, 0, ifc_ep))
      {
        const hcc_u8 *epd=get_ep_descriptor(cfg_ndx, ifc, 0, ifc_ep);
        usb_setup_ep(epd[2], epd[3], (hcc_u8)(epd[2] & 0x7fu), RD_LE16(&epd[4]));
        ifc_ep++;
        cfg_ep++;
      }
      ifc++;
    }
    usb_state = USBST_CONFIGURED;
  }
  else
  {
    //控制传输下,禁止除0号端点以外的所有端点
    usb_state=USBST_ADDRESSED;
  }

  cfg_ep++;

  //禁止其它的端点
  while(cfg_ep < 16)
  {
    usb_setup_ep(0, EP_TYPE_DISABLE, cfg_ep++, 0);
  }
}
 
//enter_default_state:USB模块进入默认状态----------------------------------*
//功  能:                                                                  *
//    使USB模块进入默认状态                                                *
//参  数:无                                                                *
//返  回:无                                                                *
//说  明:                                                                  *
//    只对端点0进行配置,禁止其它端点                                       *
//-------------------------------------------------------------------------*
static void enter_default_state(void)
{
  int ep;

  MCF_USB_CTL |= MCF_USB_CTL_ODD_RST; 
 
  for(ep=0; ep<sizeof(ep_info)/sizeof(ep_info[0]); ep++)
  {
    ep_info[ep].next_rx=0;
    ep_info[ep].next_tx=0;
  }
  MCF_USB_CTL &= ~MCF_USB_CTL_ODD_RST;  
  
  //配置端点0
  usb_setup_ep(0, EP_TYPE_CONTROL, 0, EP0_PACKET_SIZE);
  //禁止其它所有的端点
  set_config(0);

  //设置为默认地址
  MCF_USB_ADDR = 0;

  usb_state=USBST_DEFAULT;
  new_address=0;
}

//usb_stop_ep_tx:产生STALL握手包-------------------------------------------*
//功  能:                                                                  *
//      产生STALL握手包                                                    *                                                          *
//参  数: ep: 端点号                                                       *
//返  回: 无                                                               *
//说  明: 被STALL的端点将不再发送任何包,所有的IN请求被取消                 *
//-------------------------------------------------------------------------*
void usb_stop_ep_tx(hcc_u8 ep)
{
  /* This cal needs to be protected againt USB interrupts, to 
     make BDT_CTL assecc atomic. */
  hcc_imask im=_irq_disable();

  //强制产生STALL的握手包
  WR_LE32(&BDT_CTL_TX(ep, 0), BDT_CTL_OWN | BDT_CTL_STALL);
  WR_LE32(&BDT_CTL_TX(ep, 1), BDT_CTL_OWN | BDT_CTL_STALL);

  _irq_restore(im);
}

//usb_stop_ep_rx:产生STALL握手包-------------------------------------------*
//功  能:                                                                  *
//      产生STALL握手包                                                    *                                                          *
//参  数: ep: 端点号                                                       *
//返  回: 无                                                               *
//说  明: 被STALL的端点将不再接收任何包,所有的OUT请求被取消                *
//-------------------------------------------------------------------------*
void usb_stop_ep_rx(hcc_u8 ep)
{
  /* This cal needs to be protected againt USB interrupts, to
     make BDT_CTL assecc atomic. */
  hcc_imask im=_irq_disable();

  //强制产生STALL的握手包
  WR_LE32(&BDT_CTL_RX(ep, 0), BDT_CTL_OWN | BDT_CTL_STALL);
  WR_LE32(&BDT_CTL_RX(ep, 1), BDT_CTL_OWN | BDT_CTL_STALL);

  _irq_restore(im);
}

//ready_ep_tx:准备好端点发送-----------------------------------------------*
//功  能:                                                                  *
//      准备好端点发送                                                     *
//参  数:                                                                  *
//      ep:  端点号                                                        *
//      buf: 缓冲区(EVEN/BDD)                                              *
//返  回:无                                                                *
//说  明:                                                                  *
//    修改该端点的BD,使得tx端点准备好发送                                  *
//-------------------------------------------------------------------------*
static void ready_ep_tx(hcc_u8 ep, hcc_u8 buf)
{
  hcc_u32 ctl;
   
  //设置USB-FS排它访问BD,DATA0/1,允许数据触发同步
  ctl =  RD_LE32(&BDT_CTL_TX(ep, buf)) & ~0xff;
  ctl |= BDT_CTL_OWN | ep_info[ep].data0_tx | BDT_CTL_DTS;
  WR_LE32(&BDT_CTL_TX(ep, buf), ctl);
}
 
//ready_ep_rx:准备好端点接收-----------------------------------------------*
//功  能:                                                                  *
//      准备好端点接收                                                     *
//参  数:                                                                  *
//      ep:  端点号                                                        *
//      buf: 缓冲区(EVEN/BDD)                                              *
//返  回:无                                                                *
//说  明:                                                                  *
//    修改该端点的BD,使得rx端点准备好接收                                  *
//-------------------------------------------------------------------------*
static void ready_ep_rx(hcc_u8 ep, hcc_u8 buf)
{
  hcc_u32 ctl;

  //设置USB-FS排它访问BD,DATA0/1,允许数据触发同步,端点需要接收的字节数
  ctl = (ep_info[ep].psize << 16) | BDT_CTL_OWN | ep_info[ep].data0_rx | BDT_CTL_DTS;
  ep_info[ep].data0_rx ^= BDT_CTL_DATA;
  WR_LE32(&BDT_CTL_RX(ep, buf), ctl);
}

//disable_ep_tx: 禁止端点发送----------------------------------------------*
//功  能:                                                                  *
//       禁止端点发送                                                      *
//参  数:                                                                  *
//      ep:  端点号                                                        *
//返  回:无                                                                *
//说  明:                                                                  *
//    修改该端点的BD,使得发送的两个缓冲区地址都为0                         *
//-------------------------------------------------------------------------*
static void disable_ep_tx(hcc_u8 ep)
{
  MCF_USB_ENDPT(ep) &= ~MCF_USB_ENDPT_EP_TX_EN;
  while(MCF_USB_ENDPT(ep) & MCF_USB_ENDPT_EP_TX_EN)
    ;
  WR_LE32(&BDT_CTL_TX(ep, 0), 0);  
  WR_LE32(&BDT_CTL_TX(ep, 1), 0);    
}

//disable_ep_rx: 禁止端点接收----------------------------------------------*
//功  能:                                                                  *
//       禁止端点接收                                                      *
//参  数:                                                                  *
//      ep:  端点号                                                        *
//返  回:无                                                                *
//-------------------------------------------------------------------------*
static void disable_ep_rx(hcc_u8 ep)
{
  MCF_USB_ENDPT(ep) &= ~MCF_USB_ENDPT_EP_RX_EN;
}

/*****************************************************************************
 * Name:
 *    _usb_send
 * In:
 *    ep - endpoint number
 * Out:
 *    N/A
 * Description:
 *    This fucntion inmplements the basic state machine for transmit (IN)
 *    endpoints. It will
 *        - call user callback functions if neccessary,
 *        - set endpoint specific error codes
 *        - split data to be sent to packet sized pieces
 *    Note: it is called from the interrupt handler routine and from "user
 *          space" too. The function needs to be reentrant!
 *****************************************************************************/
//_usb_send: USB数据发送---------------------------------------------------*
//功  能:                                                                  *
//       USB数据发送                                                       *
//参  数:                                                                  *
//      ep:  端点号                                                        *
//返  回:无                                                                *
//说  明:                                                                  *
//                             *
//-------------------------------------------------------------------------*
static void _usb_send(hcc_u8 ep)
{
  hcc_u8 buf;
  hcc_u32 length;

  switch (ep_info[ep].state)
  {
	  case EPST_DATA_TX:
	    length=MIN(ep_info[ep].tlength, ep_info[ep].psize);
	    CMX_ASSERT(length == ep_info[ep].psize || length==ep_info[ep].tlength);      

	    //选择下一个端点的缓冲区
	    buf=select_tx_buf(ep);
	    WR_LE32(&BDT_ADR_TX(ep, buf), (hcc_u32)ep_info[ep].address);

	    //设置tx包的长度
	    WR_LE32(&BDT_CTL_TX(ep, buf), (hcc_u32)(length<<16u));
	  
	    //准备好发送的缓冲区
	    ready_ep_tx(ep, buf);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -