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

📄 usb_hw.c

📁 最新版IAR FOR ARM(EWARM)5.11中的代码例子
💻 C
📖 第 1 页 / 共 4 页
字号:
 *
 *************************************************************************/
void EpCtrlClr_CTR_RX(volatile pInt32U pReg)
{
Int32U Data = *pReg;
  Data &= ~(USB_CTRL_TOGGLE_MASK | 1UL << 15);
  Data |= 1UL << 7;   // Set TX_CTR
  *pReg = Data;
}

/*************************************************************************
 * Function Name: EpCtrlGet_CTR_RX
 * Parameters: volatile pInt32U pReg
 *
 * Return: Int32U
 *
 * Description: Get EP CTR_RX bit (OUT)
 *
 *************************************************************************/
inline
Int32U EpCtrlGet_CTR_RX(volatile pInt32U pReg)
{
  return(*pReg & (0x1UL << 15)?1:0);
}

/*************************************************************************
 * Function Name: USB_HwInit
 * Parameters: none
 *
 * Return: none
 *
 * Description: Init USB
 *
 *************************************************************************/
void USB_HwInit(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;

  // Reset USB Engine
  RCC_APB1PeriphResetCmd(RCC_APB1Periph_USB,ENABLE);
  // Init USB Clock
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB,ENABLE);
  // Release reset USB Engine
  RCC_APB1PeriphResetCmd(RCC_APB1Periph_USB,DISABLE);
  // Enable 48MHz clock
  RCC_USBCLKConfig(USB_DIVIDER);

  // Force USB Reset &  Disable USB interrupts
  USB_CNTR = 1;

  // GPIO assign to the USB engine
  RCC_APB2PeriphResetCmd(  RCC_APB2Periph_GPIOA
                         | RCC_APB2Periph_GPIOB
                         | RCC_APB2Periph_AFIO, DISABLE);
  RCC_APB2PeriphClockCmd(  RCC_APB2Periph_GPIOA
                         | RCC_APB2Periph_GPIOB
                         | RCC_APB2Periph_AFIO, ENABLE);

  GPIO_PinRemapConfig(GPIO_Remap1_CAN,ENABLE);  // xxx
  // Configure PA11, PA12 as USB lines
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_11 | GPIO_Pin_12;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  // Configure PB1 USB connect.
  GPIO_WriteBit(GPIOB,GPIO_Pin_1,Bit_SET);
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_1;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

  // Disconnect device
  USB_ConnectRes(FALSE);

  // Init controls endpoints
  USB_HwReset();

  // Clear spurious pending interrupt
  USB_ISTR = 0;

  // USB interrupt connect to NVIC
#if USB_HIGH_PRIORITY_EVENT > 0
  NVIC_InitStructure.NVIC_IRQChannel = USB_HP_CAN_TX_IRQChannel;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = USB_INTR_HIGH_PRIORITY;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
#endif // USB_HIGH_PRIORITY_EVENT > 0

  NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN_RX0_IRQChannel;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = USB_INTR_LOW_PRIORITY;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

}

/*************************************************************************
 * Function Name: USB_HwReset
 * Parameters: none
 *
 * Return: none
 *
 * Description: Reset USB engine
 *
 *************************************************************************/
void USB_HwReset (void)
{
Int32U Count;

  // Clear realized EP flag
  for(Count = 0; Count < ENP_MAX_NUMB; Count++)
  {
    EpCnfg[Count].pEpCtrl = NULL;
  }

  // Free entire USB packet memory
  for (Count = 0; Count < EP_MAX_SLOTS*2; Count++)
  {
    PacketMemBuff[Count].Size = 0;
  }

  // Resume delay counter
  DlyCnt = 0;

  // USB_Configure
  USB_Configure(FALSE);
  // Set Buffer table address
  USB_BTABLE = USB_OffsetOfDBT;
  // Init Packet memory table
  pPacketMemUse = NULL;
  // Control EP Init
  USB_RealizeEp(&USB_CtrlEpDescr0,&USB_CtrlEpExt0,TRUE);
  USB_RealizeEp(&USB_CtrlEpDescr1,&USB_CtrlEpExt1,TRUE);

  // Set address 0
  USB_SetDefAdd();

  // Enable Device interrupts
  USB_CNTR = bmCTRM | bmRESETM | bmSUSPM | bmWKUPM |
            (USB_SOF_EVENT    ? bmSOFM    : 0) |
            (USB_ERROR_EVENT  ? bmERRM    : 0) |
            (USB_PMAOVR_EVENT ? bmPMAOVRM : 0) ;
}

/*************************************************************************
 * Function Name: UsbMalloc
 * Parameters: none
 *
 * Return: void *
 *
 * Description: Return address of free element of the PacketMemBuff massive
 *
 *************************************************************************/
static
void * UsbMalloc(void)
{
Int32U Count;
  for (Count = 0; Count < EP_MAX_SLOTS*2; Count++)
  {
    if (PacketMemBuff[Count].Size == 0)
    {
      return(&PacketMemBuff[Count]);
    }
  }
  return(NULL);
}

/*************************************************************************
 * Function Name: UsbFree
 * Parameters: pPacketMemUse_t pPntr
 *
 * Return: none
 *
 * Description: Free element of the PacketMemBuff massive
 *
 *************************************************************************/
inline static
void UsbFree(pPacketMemUse_t pPntr)
{
  pPntr->Size = 0;
}

/*************************************************************************
 * Function Name: USB_AllocateBuffer
 * Parameters: pInt16U pOffset,Int32U PacketSize,
 *             USB_Endpoint_t EndPoint
 *
 * Return: Boolean
 *
 * Description: Allocate a new buffer
 *
 *************************************************************************/
static
Boolean USB_AllocateBuffer (pInt16U pOffset,pInt32U pPacketSize,
                            USB_Endpoint_t EndPoint)
{
pPacketMemUse_t  pPacketMem = pPacketMemUse, pPacketMemNext, pPacketMemUseNew;
//Int32U MaxPacketSize = *pPacketSize+4;  // for CRC
Int32U MaxPacketSize = *pPacketSize;
  if(MaxPacketSize > 62)
  {
    // coarse-granularity size alignment by 32
    MaxPacketSize +=  (32-1);
    MaxPacketSize &= ~(32-1);
  }
  else
  {
    // fine-granularity size alignment by 2
    MaxPacketSize +=  (2-1);
    MaxPacketSize &= ~(2-1);
  }
  *pOffset = 0;
  // Finding free memory block from the USB packet memory
  while(pPacketMem != NULL)
  {
    *pOffset = pPacketMem->Start + pPacketMem->Size;
    // Offset alignment by 4
    *pOffset += (4-1);
    *pOffset &= ~(4-1);
    pPacketMemNext = pPacketMem->pNext;
    if((pPacketMem->pNext == NULL) ||
       (pPacketMemNext->Start >= *pOffset + MaxPacketSize))
    {
      break;
    }
    pPacketMem = pPacketMem->pNext;
  }
  // Is enough free space for new block?
  if((*pOffset + MaxPacketSize) >=
     (((Int32U)__segment_size("USB_PACKET_MEMORY") -
       sizeof(USB_BuffDeskTbl_t) * (MaxIndOfRealizeEp+1))&~7))
  {
    // Not enough space in the USB packet memory
    return(FALSE);
  }

  pPacketMemUseNew = UsbMalloc();
  if(pPacketMemUseNew == NULL)
  {
    // too many point are realized
    return(FALSE);
  }
  if(pPacketMemUse == NULL)
  {
    pPacketMemUse = pPacketMemUseNew;
    pPacketMemUse->pNext = NULL;
  }
  else
  {
    pPacketMemUseNew->pNext  = pPacketMem->pNext;
    pPacketMem->pNext        = pPacketMemUseNew;
  }
  pPacketMemUseNew->RpAddr = EndPoint;
  pPacketMemUseNew->Start  = *pOffset;
  pPacketMemUseNew->Size   = MaxPacketSize;
  *pPacketSize = MaxPacketSize;
  return(TRUE);
}

/*************************************************************************
 * Function Name: USB_ReleaseBuffer
 * Parameters: USB_Endpoint_t EndPoint
 *
 * Return: none
 *
 * Description: Release the buffer/s
 *
 *************************************************************************/
static
void USB_ReleaseBuffer (USB_Endpoint_t EndPoint)
{
pPacketMemUse_t  pPacketMem, pPacketMemPrev;
  pPacketMem = pPacketMemUse;
  while(pPacketMem != NULL)
  {
    if(pPacketMem->RpAddr == EndPoint)
    {
      pPacketMemPrev->pNext = pPacketMem->pNext;
      UsbFree(pPacketMem);
      pPacketMem = pPacketMemPrev->pNext;
    }
    else
    {
      pPacketMemPrev = pPacketMem;
      pPacketMem = pPacketMem->pNext;
    }
    if (pPacketMem == NULL)
    {
      break;
    }
  }
}

/*************************************************************************
 * Function Name: USB_RealizeEp
 * Parameters: const UsbStandardEpDescriptor_t * pEP_Desc,
 *             const UsbEP_ExtData_t * pUsbEP_ExtData, Boolean Enable
 *
 * Return: USB_ErrorCodes_t
 *
 * Description: Enable or disable an endpoint
 *
 *************************************************************************/
USB_ErrorCodes_t USB_RealizeEp(const UsbStandardEpDescriptor_t * pEP_Desc,
                               const UsbEP_ExtData_t * pUsbEP_ExtData,
                               Boolean Enable)
{
USB_Endpoint_t EP;
pEpCnfg_t pEP;
volatile pInt32U pEpCtrlBaseAddr;
Int16U Offset,Offset1;
Int32U MaxPacketSizeTmp;

  assert(pEP_Desc);

  EP = (USB_Endpoint_t)USB_EpLogToPhysAdd(pEP_Desc->bEndpointAddress);
  pEP = &EpCnfg[EP];

  if (Enable)
  {
    assert(pUsbEP_ExtData);

    // Allocate packet memory for EP buffer/s
    // calculate actual size only for the OUT EPs
    MaxPacketSizeTmp = pEP_Desc->wMaxPacketSize;
    if(!USB_AllocateBuffer(&Offset,&MaxPacketSizeTmp,EP))
    {
      return(USB_MEMORY_FULL);
    }
    if(pUsbEP_ExtData->DoubleBuff)
    {
      // To use double buffered and ISO EP the USB_HIGH_INTR must be enabled
      assert(USB_HIGH_PRIORITY_EVENT);
      // Allocate packet second buffer
      MaxPacketSizeTmp = pEP_Desc->wMaxPacketSize;
      if(!USB_AllocateBuffer(&Offset1,&MaxPacketSizeTmp,EP))
      {
        // release buffer
        USB_ReleaseBuffer(EP);
        return(USB_MEMORY_FULL);
      }
    }

    // Set EP status
    pEP->Status  = NOT_READY;
    // Init EP flags
    pEP->Flags = 0;

    // Set endpoint type
    pEP->EpType = (UsbEpTransferType_t)pEP_Desc->bmAttributes.TransferType;
    // Init EP max packet size
    pEP->MaxSize = pEP_Desc->wMaxPacketSize;
    // Set Extra data
    pEP->bDoubleBuffered = pUsbEP_ExtData->DoubleBuff;
    pEP->EpSlot = pUsbEP_ExtData->EpSlot;

    if (EP & 1)
    {
      pEP->AvbBuff = EpCnfg[EP].bDoubleBuffered + 1;
    }
    else
    {
      pEP->AvbBuff = 0;
    }

    pEpCtrlBaseAddr  = (pInt32U)&USB_EP0R;
    pEpCtrlBaseAddr +=  pUsbEP_ExtData->EpSlot;

    // Set Ep Address
    EpCtrlSet_EA(pEpCtrlBaseAddr,EP >> 1);

    pEP->pEpCtrl = pEpCtrlBaseAddr;

    if(EP & 1)
    {
      // IN EP
      // Disable EP
      EpCtrlSet_STAT_TX(pEpCtrlBaseAddr,EP_DISABLED);
      // Clear Tx toggle
      EpCtrlSet_DTOG_TX(pEpCtrlBaseAddr,0);
      // Clear Correct Transfer for transmission flag
      EpCtrlClr_CTR_TX(pEpCtrlBaseAddr);
      // Update EP description table
      WriteEpDTB_AddrTx(pEP->EpSlot,Offset);
      WriteEpDTB_CountTx(pEP->EpSlot,0);
      // Set EP Kind & enable
      switch(pEP->EpType)
      {
      case UsbEpTransferControl:
        EpCtrlSet_EP_TYPE(pEpCtrlBaseAddr,EP_CTRL);
        EpCtrlSet_EP_KIND(pEpCtrlBaseAddr,0);
        // Enable EP
        EpCtrlSet_STAT_TX(pEpCtrlBaseAddr,EP_NAK);
        break;
      case UsbEpTransferIsochronous:
        assert(pEP->bDoubleBuffered);
        // Disable receiving (only singe direction is possible)
        EpCtrlSet_STAT_RX(pEpCtrlBaseAddr,EP_DISABLED);
        WriteEpDTB_AddrRx(pEP->EpSlot,Offset1);
        WriteEpDTB_CountRx(pEP->EpSlot,0);
        EpCtrlSet_EP_TYPE(pEpCtrlBaseAddr,EP_ISO);
        EpCtrlSet_EP_KIND(pEpCtrlBaseAddr,0);
        // Enable EP
        EpCtrlSet_STAT_TX(pEpCtrlBaseAddr,EP_VALID);
        break;
      case UsbEpTransferBulk:
        EpCtrlSet_EP_TYPE(pEpCtrlBaseAddr,EP_BULK);
        EpCtrlSet_EP_KIND(pEpCtrlBaseAddr,pEP->bDoubleBuffered);
        if (pEP->bDoubleBuffered)
        {
          // EP_BULK_DOUB_BUF
          // Disable receiving (only singe direction is possible)
          EpCtrlSet_STAT_RX(pEpCtrlBaseAddr,EP_DISABLED);
          // Clear Tx Software toggle
          WriteEpDTB_AddrRx(pEP->EpSlot,Offset1);
          WriteEpDTB_CountRx(pEP->EpSlot,0);
          EpCtrlSet_DTOG_RX(pEpCtrlBaseAddr,0);
        }
        // Enable EP
        EpCtrlSet_STAT_TX(pEpCtrlBaseAddr,EP_NAK);

        break;
      case UsbEpTransferInterrupt:
        EpCtrlSet_EP_TYPE(pEpCtrlBaseAddr,EP_INTERRUPT);
        EpCtrlSet_EP_KIND(pEpCtrlBaseAddr,0);
        // Enable EP
        EpCtrlSet_STAT_TX(pEpCtrlBaseAddr,EP_NAK);
        break;
      default:
        assert(0);
      }
      // Clear Correct Transfer for transmission flag
      EpCtrlClr_CTR_TX(pEpCtrlBaseAddr);
    }

⌨️ 快捷键说明

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