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

📄 usb.c

📁 freescale badge board 开发板测试 源程序
💻 C
📖 第 1 页 / 共 4 页
字号:
          	WR_LE32(&BDT_CTL_TX(adr, 1), bdt);
          }
          else
          {
            hcc_u32 bdt;
            ep_info[adr].data0_rx=0;
            bdt=RD_LE32(&BDT_CTL_RX(adr, 0));
            bdt &= ~BDT_CTL_STALL;
          	WR_LE32(&BDT_CTL_RX(adr, 0), bdt);
            bdt=RD_LE32(&BDT_CTL_RX(adr, 1));
            bdt &= ~BDT_CTL_STALL;
          	WR_LE32(&BDT_CTL_RX(adr, 1), bdt);
          }
        }
        break;
      default:
        goto call_usercb;
      }
      break;
    default:
      /* Call user callback if avaiable. */
      goto call_usercb;
    }
    break;
  default:
  call_usercb:
    r=usb_ep0_callback();
  }

  return(r);
}

/*****************************************************************************
 * Name:
 *    usb_it_handler
 * In:
 *    N/A
 * Out:
 *    N/A
 *
 * Description:
 *    Low priority interrupt handler.
 *
 * Assumptions:
 *
 *****************************************************************************/
//#ifdef __GNUC__
/* __declspec(interrupt) is not supported by GNUC. Remove it with a macro. */
//void usb_it_handler1(void)
//#else
//#pragma interrupt  on
//#pragma TRAP_PROC
interrupt  VectorNumber_Vusb
void usb_it_handler(void)
//#endif
{
  hcc_u8 istr;

  /* Save irq USB status. */
  istr=MCF_USB_INT_STAT;
  if(istr & ~MCF_USB_INT_STAT_TOK_DNE)
  {
    if (istr & MCF_USB_INT_STAT_USB_RST)
    {
      /* Clear IT flag. */
      MCF_USB_INT_STAT = MCF_USB_INT_STAT_USB_RST;
      /* Enter default state. */
      enter_default_state();
      usb_reset_event();
      goto it_exit;
    }

    if (istr & MCF_USB_INT_STAT_ERROR)
    {
      MCF_USB_INT_STAT = MCF_USB_INT_STAT_ERROR;
      usb_bus_error_event();
    }
    if (istr & MCF_USB_INT_STAT_RESUME)
    {
      MCF_USB_INT_ENB &= ~MCF_USB_INT_ENB_RESUME;

      MCF_USB_INT_STAT = MCF_USB_INT_STAT_SLEEP;
      MCF_USB_INT_ENB |= MCF_USB_INT_ENB_SLEEP;
      usb_wakeup_event();
    }
    if (istr & MCF_USB_INT_STAT_SLEEP)
    {
      MCF_USB_INT_ENB &= ~MCF_USB_INT_ENB_SLEEP;

      MCF_USB_INT_STAT = MCF_USB_INT_STAT_RESUME;
      MCF_USB_INT_ENB |= MCF_USB_INT_ENB_RESUME;
      usb_suspend_event();
    }

    /* Stall was sent. */
    if (istr & MCF_USB_INT_STAT_STALL)
    {
      hcc_u8 ep=(hcc_u8)(MCF_USB_STAT >> 4);
      MCF_USB_INT_STAT = MCF_USB_INT_STAT_STALL;
      /* Remove stall for control endpoints. ??*/
      if ((MCF_USB_ENDPT(ep) & MCF_USB_ENDPT_EP_CTL_DIS) == 0)
      {
        WR_LE32(&BDT_CTL_RX(ep, 0), 0);
        WR_LE32(&BDT_CTL_RX(ep, 1), 0);
        WR_LE32(&BDT_CTL_TX(ep, 0), 0);
        WR_LE32(&BDT_CTL_TX(ep, 1), 0);
        ready_ep_rx(ep, ep_info[ep].next_rx);
      }
    }
  }

  if (istr & MCF_USB_INT_STAT_TOK_DNE)
  {
    hcc_u8 ep=(hcc_u8)(MCF_USB_STAT >> 4);
    int is_rx;
    int is_stp;
    hcc_u8 this_buf=(hcc_u8)(MCF_USB_STAT & MCF_USB_STAT_ODD ? 1 : 0);

    if (MCF_USB_STAT & MCF_USB_STAT_TX)
    {
      is_rx=0;
      is_stp=0;

      WR_LE32(&BDT_CTL_TX(ep, this_buf),
               RD_LE32(&BDT_CTL_TX(ep, this_buf)) & ~(BDT_CTL_STALL|BDT_CTL_OWN));
      ep_info[ep].next_tx = (hcc_u8)(this_buf ? 0u : 1u);
    }
    else
    {/* This is an RX packet.*/
      is_rx=1;
      ep_info[ep].next_rx=(hcc_u8)(this_buf ^ 0x1u);
      is_stp=(hcc_u8)(RD_LE32(&BDT_CTL_RX(ep, this_buf)) & 0x3f) == (SOF_PID_VALUE<<2) ? 1 : 0;

      WR_LE32(&BDT_CTL_RX(ep, this_buf),
               RD_LE32(&BDT_CTL_RX(ep, this_buf)) & ~(BDT_CTL_STALL|BDT_CTL_OWN));
    }

    /* is this a control endpoint? */
    if ((MCF_USB_ENDPT(ep) & MCF_USB_ENDPT_EP_CTL_DIS) == 0)
    {/* then use a special state machine. */
      switch(ep_info[ep].state)
      {
      default:
        CMX_ASSERT(0);
        break;
      case EPST_IDLE:
      idle:
        if (is_stp)
        {
          callback_state_t r;
          /* Reset the endpoint state. */

          /* Since TOKBUSY is still set, this is a safe point to disable
             packet buffers (NAK in and out direction). */
          WR_LE32(&BDT_CTL_TX(ep, 0), 0);
          WR_LE32(&BDT_CTL_TX(ep, 1), 0);
          WR_LE32(&BDT_CTL_RX(ep, 0), 0);
          WR_LE32(&BDT_CTL_RX(ep, 1), 0);


          /* Dnager: if a setup frame will be received not in idle
             state, then the TOKBUSY will not be cleared,
             and the whole USB will not answer any more.*/

          /* This flag shall be cleared after each setup packet. Note:
             it seems it shall be cleared before trying to use endpoint
             buffers. */
          MCF_USB_CTL &= ~MCF_USB_CTL_TXDSUSPEND_TOKBUSY;

             /* remove any callback */
          ep_info[ep].data_func = (void*)0;
             /* clear flags*/
          ep_info[ep].flags=0;
             /* clear user error indicator */
          ep_info[ep].error=USBEPERR_NONE;
          /* After a setup packet the next packet is always a data1. */
          ep_info[ep].data0_tx = BDT_CTL_DATA;
          ep_info[ep].data0_rx = BDT_CTL_DATA;
          /* Remove stall condition. */

          if (ep == 0)
          {
            r=usb_stm_ctrl0();
          }
          else
          {
            /* Only one control channel is supported. */
            r=clbst_error;
          }
          switch(r)
          {
            case clbst_error:
              usb_stop_ep_tx(ep);
              usb_stop_ep_rx(ep);
              ep_info[ep].state = EPST_IDLE;
              ep_info[ep].error = USBEPERR_USER_ABORT;
              break;
            case clbst_not_ready:
              /* Nothing to do. */
              break;
            case clbst_in:
              ready_ep_rx(ep, ep_info[ep].next_rx);
              break;
            case clbst_out:
              if (ep_info[ep].state == EPST_IDLE)
              {
                goto send_status;
              }
              break;
            default:
              break;
          }
        }
        else
        {/* This is not a setup packet, and we encountered a protocol error.
            Possible reasons:
               -spurious package on the bus (not our fault)
               -we ended the transfer before the host.
                  - host and device transfer length was not the same
                  - driver error miscounted packages
          */
          /* Stall endpoint to make error visible to the host. */
          ep_info[ep].error = USBEPERR_TO_MANY_DATA;

          usb_stop_ep_rx(ep);
          usb_stop_ep_tx(ep);
        }
        break;
      case EPST_DATA_TX:
      case EPST_DATA_TX_LAST:
      case EPST_TX_STOP:

        /* If there is an RX interrupt pending , stop transmission. */
        if (is_rx)
        {
          /* Inform application about transfer end. */
          ep_info[ep].state=EPST_IDLE;
          if (ep_info[ep].data_func != (void *)0)
          {
            (void)(*ep_info[ep].data_func)();
          }
          /* Go to EPST_IDLE and handle the packet as it would be the start
             of a new transfer.  */
          goto idle;
        }
        _usb_send(ep);

        /* If transfer is ended, then we shall receive a handshake from the host. */
        if (ep_info[ep].state == EPST_IDLE)
        {
          ep_info[ep].state=EPST_STATUS_TX;
        }

        break;
      case EPST_STATUS_TX:
        /* We may have some TX interrupt events on the USB module event stack. These
           events are already handled, but wi may get dome dummy interrupts.
           So simply dropp such events to keep the state machine synchron to the USB. */
        if (!is_rx)
        {
          break;
        }
        /* In the IN transfer status stage we received a 0 byte long DATA 1 packet. */
        ep_info[ep].state=EPST_IDLE;
        /* Tell application transfer ended. */
        if (ep_info[ep].data_func != (void *) 0)
        {
          /* We don't care about the return value at this point, since we already
             sent the status, and the transfer is already ended. */
          (void)(*ep_info[ep].data_func)();
          /* Disable callbacks. */
          ep_info[ep].data_func = (void *)0;
        }
        ready_ep_rx(ep, ep_info[ep].next_rx);
        break;
      case EPST_DATA_RX:
        _usb_receive(ep);
        /* Was this the last packet to receive? */
        send_status:
        if(ep_info[ep].state == EPST_IDLE)
        {
          /* If there was an error, stall the status stage. */
          if (ep_info[ep].flags & EPFL_ERROR)
          {
            usb_stop_ep_tx(ep);
          }
          else
          {
            /* Handshake is allways a data 1 packet. */
            ep_info[ep].data0_tx = BDT_CTL_DATA;
            /* If all ok send handshake. */
            ep_info[ep].state=EPST_STATUS_RX;
            /* Send a 0 byte long data1 packet as response.*/
            send_zero_packet(ep);
          }
        }
        break;
      case EPST_STATUS_RX:
        /* In the OUT transfer status stage we sent a 0 byte long DATA 0 packet. */
        ep_info[ep].state=EPST_IDLE;
        /* Tell application transfer ended. */
        if (ep_info[ep].data_func != (void *) 0)
        {
          /* We don't care about the return value at this point, since we already
             sent the status, and the transfer is already ended. */
          (void)(*ep_info[ep].data_func)();
          /* Disable callbacks. */
          ep_info[ep].data_func = (void *)0;
        }
        ready_ep_rx(ep, ep_info[ep].next_rx);
        break;
      }
    }
    else
    {
      /* Is this an OUT (rx) endpoint? */
      if(is_rx)
      {
        /* Handle reception. */
        _usb_receive(ep);
      }
      else
      { /* This is an IN endpoint (TX) */
        _usb_send(ep);
        if (ep_info[ep].state==EPST_IDLE)
        {
          /* Inform user application. */
          if (ep_info[ep].data_func != (void *)0)
          {
            (*ep_info[ep].data_func)();
            /* Disable futher callbacks. */
            ep_info[ep].data_func = (void *)0;
          }
        }
      }
    }
	/* Clear interrupt flag. */
    MCF_USB_INT_STAT=MCF_USB_INT_STAT_TOK_DNE;

  }
  it_exit:
  	;
}

void _irq_restore (hcc_imask ip)
{
    asm_set_ipl(ip);
}

hcc_imask _irq_disable (void)
{
    return((hcc_imask)asm_set_ipl(7));
}

void stack_init(byte pattern) 
{
   extern unsigned long far __SP_END;
   byte far * stackEnd  = (byte far*)&__SP_END;
   byte far * stackPointer;
   asm{
    move.l A7,stackPointer
   }
   stackPointer -= 4; 
   for (;stackPointer >= stackEnd;) 
   {
      *stackPointer-- = pattern;
   }
}

long stack_size(byte pattern) 
{
   extern unsigned long far __SP_END;
   extern unsigned long far __SP_INIT;
   byte far * stackEnd  = (byte far*)&__SP_END;
   byte far * stackBegin = (byte far*)&__SP_INIT;
   byte far * stackPointer;
   byte far *tempStackPointer = stackEnd;
   long stackSize = 0;
   
   asm{
    move.l A7,stackPointer
   }

   // Search the stack for pattern
   for(;tempStackPointer <= (stackPointer);tempStackPointer++) 
   {
      if(*tempStackPointer != pattern) 
      {
        break;
      }
      stackSize++;
   }
   
   return (stackBegin-stackEnd+1-stackSize);
}
/****************************** END OF FILE **********************************/


⌨️ 快捷键说明

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