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

📄 lpc_usb.c

📁 在ARM上实现USB功能源代码
💻 C
字号:
/*************************************************************************
 *
 *    Used with ICCARM and AARM.
 *
 *    (c) Copyright IAR Systems 2003
 *
 *    File name   : main.c
 *    Description : Define main module
 *
 *    History :
 *    1. Data        : June 13, 2005
 *       Author      : Stanimir Bonev
 *       Description : Create
 *
 *    $Revision: 1.2 $
**************************************************************************/
#include "lpc_usb.h"

Fnpr IntrCallback;

/*************************************************************************
 * Function Name: USB_Cmd
 * Parameters:  unsigned char Command
 *              unsigned char Data
 * Return: unsigned int - command result
 * Description: Implement a command transmit to USB Engine
 *
 *************************************************************************/
unsigned int USB_Cmd (unsigned short Command, unsigned char Data)
{
unsigned int cpu_sr, tmp = 0;
  // Disable interrurp and save current state of the interrupt flags
  cpu_sr = disable_interrupts();
  // Clear Data reg full and Command reg. empry interrupts
  DEVINTCLR = USB_CommRegEmptyInterrupt + USB_CommDataFullInterrupt;
  // Load commonad in USB engine
  CMDCODE = ((Command&0xFF) << 16) + USB_CMD_WR;
  // Wait until command is accepted
  while ((DEVINTS & USB_CommRegEmptyInterrupt) == 0);
  // clear Command reg. empry interrupt
  DEVINTCLR = USB_CommRegEmptyInterrupt;
  // determinate next phase of the command
  switch (Command)
  {
  case CMD_USB_SET_ADDRESS:
  case CMD_USB_CFG_DEV:
  case CMD_USB_SET_MODE:
  case CMD_USB_SET_DEV_STAT:
    CMDCODE = (Data << 16) + USB_DATA_WR;
    while ((DEVINTS & USB_CommRegEmptyInterrupt) == 0);
    break;
  case CMD_USB_RD_FRAME_NUMB:
  case CMD_USB_RD_TEST_REG:
    CMDCODE = (Command << 16) + USB_DATA_RD;
    while ((DEVINTS & USB_CommDataFullInterrupt) == 0);
    DEVINTCLR = USB_CommDataFullInterrupt;
    tmp = CMDDATA;
    CMDCODE = (Command << 16) + USB_DATA_RD;
    while ((DEVINTS & USB_CommDataFullInterrupt) == 0);
    DEVINTCLR = USB_CommDataFullInterrupt;
    tmp |= CMDDATA << 8;
    break;
  case CMD_USB_GET_DEV_STAT:
  case CMD_USB_GET_ERROR:
  case CMD_USB_RD_ERROR_STAT:
  case CMD_USB_CLR_BUF:
    CMDCODE = (Command << 16) + USB_DATA_RD;
    while ((DEVINTS & USB_CommDataFullInterrupt) == 0);
    tmp = CMDDATA;
    break;
  default:
    switch (Command & 0xE0)
    {
    case CMD_USB_SEL_EP:
    case CMD_USB_SEL_CLR_INT_EP:
      CMDCODE = (Command << 16) + USB_DATA_RD;
      while ((DEVINTS & USB_CommDataFullInterrupt) == 0);
      tmp = CMDDATA;
      break;
    case CMD_USB_SET_EP_STAT:
      CMDCODE = (Data << 16) + USB_DATA_WR;
      while ((DEVINTS & USB_CommRegEmptyInterrupt) == 0);
      break;
    }
    break;
  }
  DEVINTCLR = USB_CommRegEmptyInterrupt + USB_CommDataFullInterrupt;
  // restore the interrupt flags
  restore_interrupts(cpu_sr);
  return(tmp);
}

/*************************************************************************
 * Function Name: USB_Init
 * Parameters: int IntrSlot
 *             Fnpr UserIntrCallback
 *             USB_DEV_INT_PRIORITY_DEF DevIntrPrio
 * Return: USB_ERROR_CODE_DEF
 *         USB_OK  0: Pass
 *     USB_ERROR   1: Error
 * Description: Init USB
 *
 *************************************************************************/
USB_ERROR_CODES_DEF USB_Init(int IntrSlot, Fnpr UserIntrCallback,USB_DEV_INT_PRIORITY_DEF DevIntrPrio)
{
int p = 1, m = 48000000 / FOSC, Fpll, i;

  if (IntrSlot > VIC_Slot15)
  {
    return(USB_INTR_ERROR);
  }

  // Find suitable value for P
  for (i = 0; i < 4 ; ++i, p <<= 1)
  {
    Fpll = (FOSC << 1) * p * m;
    if ((Fpll >= Fcco_MIN) && (Fpll <= Fcco_MAX))
    {
      break;
    }
  }

  if (i >= 4)
  {
    // can't fond suitable value
    return(USB_PLL_ERROR);
  }

  /* Turn on USB */
  PM_OpenPeripheral(0x80000000);

  // Enable Vbus sense
  PINSEL1_bit.P0_23 = 1;
  // 1 - GoodLinc
  // 2 - ~Connect
  PINSEL1_bit.P0_31 = 2;

  // Init Pll for USB engine freq - 48MHz
  PLL48CFG_bit.MSEL = m-1;      //Fosc is define in LPC2148_sys_cnfg.h into [Hz]
  PLL48CFG_bit.PSEL = i;

  PLL48CON_bit.PLLE = true;     // Enable PLL
  PLL48FEED = PLLFEED_DATA1;
  PLL48FEED = PLLFEED_DATA2;

  while (!PLL48STAT_bit.PLOCK); // Wait PLL lock

  PLL48CON_bit.PLLC = true;     // Connect PLL
  PLL48FEED = PLLFEED_DATA1;
  PLL48FEED = PLLFEED_DATA2;

  IntrCallback = UserIntrCallback;

  // USB interrupt connect to VIC
  VIC_SetVectoredIRQ(USB_ISR,(LPC_VicIrqSlots_t)IntrSlot,VIC_USB);
  VIC_EnableInt(1<<VIC_USB);

  // init USB engine
  DEVINTPRI   = DevIntrPrio;

  // EndPoint Init
  REALIZEENDP = ENDPINTEN = 0x3;
  ENDPINTCLR  = 0xFFFFFFFF;

  // Clear all interrupt flags
  DEVINTCLR = 0x3FF;

  // Eanble all interrupts
  // without EP Realize, Command Reg Empty, Command Data Reg Full
  DEVINTEN = 0x20E;

  // Enable USB inerrupt
  USBINTS_bit.EN_USB_INTS = 1;

  return (USB_OK);
}

/*************************************************************************
 * Function Name: USB_RealizeEndPoint
 * Parameters: USB_ENDOPINT_DEF EndPoint - endpoiunt index
 *             int MaxPacketSize - When is 0 disable relevant endpoint
 *             USB_INT_PRIORITY_DEF IntrPriority
 *             int IntrEna
 * Return: none
 * Description: Enable or disable endpoint
 *
 *************************************************************************/
void USB_RealizeEndPoint( USB_ENDOPINT_DEF EndPoint,int MaxPacketSize,
                          USB_INT_PRIORITY_DEF IntrPriority, int IntrEna)
{
unsigned int Mask = (1 << EndPoint);
  if (MaxPacketSize)
  {
    // Realize endpoit
    REALIZEENDP  |= Mask;
    // Set endpoit maximum packet size
    ENDPIND       = EndPoint;
    MAXPACKSIZE   = MaxPacketSize;
    // Wait for Realize complete
    while ((DEVINTS & USB_EPRealizeInterrupt) == 0);
    // Clear Endpoint Realize interrupt flag
    DEVINTCLR     = USB_EPRealizeInterrupt;
    // Set endpoint interrupt priority
    if (IntrPriority)
    {
      ENDPINTPRI |= Mask;
    }
    // Endpoint interrup flag clear and CDFULL flag!!!
    ENDPINTCLR    = Mask;
    // Enable endpoint interrup
    if (IntrEna) ENDPINTEN |= Mask;
  }
  else
  {
    Mask =~ Mask;
    // Disable relevant endpoint and interrupt
    REALIZEENDP &= Mask;
    ENDPINTEN &= Mask;
  }
}

/*************************************************************************
 * Function Name: USB_ClearBuffer
 * Parameters: USB_ENDOPINT_DEF EndPoint - endpoiunt index
 * Return: Packet overwrite statrus
 * Description: Clear buffer of the corresponding endpoint
 *
 *************************************************************************/
unsigned int USB_ClearBuffer(USB_ENDOPINT_DEF EndPoint)
{
  // Select endpoint
  USB_Cmd(CMD_USB_SEL_EP | EndPoint,0);
  // Clear selected end point
  return(USB_Cmd(CMD_USB_CLR_BUF,0));
}

/*************************************************************************
 * Function Name: USB_ValidateBuffer
 * Parameters: USB_ENDOPINT_DEF EndPoint - endpoiunt index
 * Return: none
 * Description: Validate buffer only of IN Endpoint
 *
 *************************************************************************/
void USB_ValidateBuffer(USB_ENDOPINT_DEF EndPoint)
{
  if (EndPoint & 1)
  {
    USB_Cmd(CMD_USB_SEL_EP | EndPoint,0);
    USB_Cmd(CMD_USB_VAL_BUF,0);
  }
}

/*************************************************************************
 * Function Name: USB_SetAdd
 * Parameters: unsigned int DevAdd - defice address between 0 - 127
 * Return: none
 * Description: Set device address
 *
 *************************************************************************/
void USB_SetAdd(unsigned int DevAdd)
{
  for(int i=2;i;--i)
  {
    USB_Cmd(CMD_USB_SET_ADDRESS,DevAdd | 0x80);
  }
}

/*************************************************************************
 * Function Name: USB_ISR
 * Parameters: none
 * Return: none
 * Description: USB interrupt subroutine
 *
 *************************************************************************/
void USB_ISR (void)
{
  IntrCallback();
  VICVectAddr = 0;    // Clear interrupt in VIC.
}

⌨️ 快捷键说明

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