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

📄 usb_hw.c

📁 UC/OS下的USB驱动程序和说明文档(包括上位机驱动程序和固件程序)
💻 C
字号:
/*
**********************************************************************
*                          Micrium, Inc.
*                      949 Crestview Circle
*                     Weston,  FL 33327-1848
*
*                           uC/USB-Bulk
*
*             (c) Copyright 2003 - 2004, Micrium, Inc.
*                      All rights reserved.
*
***********************************************************************

----------------------------------------------------------------------
File    : USB_HW.h
Purpose : Hardware sample for Renesas M30245
--------  END-OF-HEADER  ---------------------------------------------
*/

#include "IOM30245.h"
#include "USB_Private.h"
#include "RTOS.h"

/*********************************************************************
*
*       Static data
*
**********************************************************************
*/
#define EP0CS_OUT_BUF_READY   (1 << 0)
#define EP0CS_SETUP           (1 << 2)
#define EP0CS_SETUP_READY     (EP0CS_OUT_BUF_READY | EP0CS_SETUP)

//
// Computation of buffer locations. Should not require changes
//
#define BUFFER_OFF_IN  0
#define BUFFER_OFF_OUT BUFFER_OFF_IN + (MAXT_IN * 2)


extern void USB_HW_Send64(OS_U16 * pData16);   // Assembly !
extern void USB_HW_Read64(OS_U16 * pData);     // Assembly !


/*********************************************************************
*
*       USB_HW_Init
*
*  DESCRIPTION:
*    Sets default values for EP0 and enables the various interrupts
*    needed for USB operations.
*/
void USB_HW_Init(void){
  EP0MP  = 0x0008;     // EP0 MAXP packet size = 64, continuous mode
  EP0IC  = 0x03;       // Enable the EP0 interrupt
  USBFIC = 0x03;       // Enable the USB function interrupt
}

/*********************************************************************
*
*       USB_HW_FreeBuffer
*
* Function description
*   Let the USB controller know that received packet has been read
*   and the buffer can now be re-used
*
* Context:
*   Task or ISR
*/
void USB_HW_FreeBuffer(void) {
  EP1OCS |= (1<<5);          // Clear "out buffer ready": We are ready to receive a new packet
}

/*********************************************************************
*
*       USB_HW_memcpy
*
* Function description
*
*
* Context:
*   Task or ISR
*/
/*  --> Coded in ASM
void USB_HW_memcpy(void * pDest, void * pSrc, unsigned Len) {
  do {
    *(char near*)pDest = *(char near*)pSrc;
  } while (--Len);

}
*/




/*********************************************************************
*
*       USB_HW_BufferAvailable
*
* Function description
*   Returns if a buffer is available
*
* Context:
*   Task or ISR. Interrupts must be disbled !
*/

int USB_HW_BufferAvailable(void) {
  return ((EP1ICS & (3 << 0)) == 3) ? 0 : 1;
}


/*********************************************************************
*
*       USB_HW_SendData
*
* Function description
*   Sends out data (bulk mode) on EP1
*
* Context:
*   Task
*/
void USB_HW_SendData(const void* pData, unsigned NumBytes) {
  if (NumBytes) {
      //
      // Data is near area (RAM). This is so most of the time, so we can optimize here.
      //
      USB_U16 near * pData16;
      pData16 = (USB_U16 near *)pData;
#ifdef __ICCM16C__
      while (NumBytes >= 64) {
        USB_HW_Send64(pData16);
        pData16 += 32;
        NumBytes -= 64;
      }
#endif
      while (NumBytes >= 16) {
        EP1I = *pData16;
        EP1I = *(pData16+1);
        EP1I = *(pData16+2);
        EP1I = *(pData16+3);
        EP1I = *(pData16+4);
        EP1I = *(pData16+5);
        EP1I = *(pData16+6);
        EP1I = *(pData16+7);
        pData16 += 8;
        NumBytes -= 16;
      }
      while (NumBytes >= 4) {
        EP1I = *pData16;
        EP1I = *(pData16 + 1);
        pData16 += 2;
        NumBytes -= 4;
      }
      if (NumBytes) {
        char * pData8 = (char*)pData16;
        do {
          EP1IL = *pData8++;
        } while (--NumBytes);
      } 
  }
  EP1ICS |= (1<<3);           // Send this packet out
}



/*********************************************************************
*
*       USB_HW_Read
*
* Function description
*   Read the received data from the USB controller
*   Note: This function is heavily speed optimized.
*         It uses near pointers, which means the target RAM has
*         to be in the 64 kb Area 0000 - ffff.
*         This is typically so, since normally the chip is used
*         with  internal RAM only
* 
* Context:
*   Task or ISR
*/

void USB_HW_Read(void * pDest, int NumBytes, unsigned PacketOff) {
  static char _ReadByte;
  if (NumBytes) {  // Safety only ... SHould not be required
    register int near * pData;
    pData = (int near *)pDest;

    //
    // If packet offset is even, we first need to fetch one byte
    //
    if (PacketOff & 1) {
      char *p8 = (char*)pData;
      *p8++ = _ReadByte;
      pData = (int near *)p8;
      NumBytes--;
    }
    //
    // Optimization: Handle 64 bytes at a time in a fast subroutine
    //
    while (NumBytes >= 64) {
      USB_HW_Read64((OS_U16*)pData);
      pData += 32;
      NumBytes -= 64;
    }
    //
    // Read the bulk of the data
    //
    while (NumBytes >= 16) {
      *pData = EP1O;
      *(pData+1) = EP1O;
      *(pData+2) = EP1O;
      *(pData+3) = EP1O;
      *(pData+4) = EP1O;
      *(pData+5) = EP1O;
      *(pData+6) = EP1O;
      *(pData+7) = EP1O;
      pData += 8;
      NumBytes -=16;
    }
    while (NumBytes >= 2) {
      *pData = EP1O;
      pData ++;
      NumBytes -= 2;
    }
    if (NumBytes) {
      USB_U16 Data = EP1O;
      *(char near *)pData = Data & 255;
      _ReadByte = Data >> 8;
    }
  }
}

/*********************************************************************
*
*       USB_HW_Attach
*/
void USB_HW_Attach(void) {
  USBAD |= (1<<1);      // and pullup D+ for host attachemnt
}

/*********************************************************************
*
*       USB_HW_UnloadEP0
*
* Function description
*   Called after a setup packet has been successfully evaluated.
*   Tells the USB controller that the associated data buffer is
*   no longer needed and can be freed.
*/
void USB_HW_UnloadEP0(void) {
  EP0CS = 0x2240;       // Set DATA_END, OPR, SETUP flag
}

/*********************************************************************
*
*       USB_HW_StallEP0
*/
void USB_HW_StallEP0(void) {
  EP0CS = 0x1140;
}

/*********************************************************************
*
*       USB_HW_SetAddress
*/
void USB_HW_SetAddress(unsigned char Adr) {
  USBA  = Adr;
}

/*********************************************************************
*
*       USB_HW_EnableEP1
*/

void USB_HW_EnableEP1(void) {
  USBIE   = 0x100;          // Disable all EP interrupts
  USBEPEN = 0;          // Disable all EP's
/* Assign the buffer memory to the endpoints */
  EP1IMP = 64;             // MAXP (maximum packet size)
  EP1OMP = 64;             // MAXP (maximum packet size)
  EP1IFC = (BUFFER_OFF_IN / 64)     // bits[0..5]: Buffer start location / 64
          |((MAXT_IN/64 - 1) << 6)  // bits[6..9]: Buffer size / 64 - 1
          | (1 << 10)               // bit[10]: Double buffer mode enable
          | (1 << 11);              // bit[11]: Continuous mode enable
  EP1OFC = (BUFFER_OFF_OUT / 64)    // bits[0..5]: Buffer start location / 64
          |((MAXT_OUT/64 - 1) << 6) // bits[6..9]: Buffer size / 64 - 1
          | (1 << 10)               // bit[10]: 1: Double buffer mode enable
          | (1 << 11);              // bit[11]: 1: Continuous mode enable

  EP1OCS |= (1 << 5)                // Unload from out buffer
         |  (1 << 6)                // Clear over run
         |  (1 << 7)
         |  (1 << 8)
         |  (1 << 10);
  EP1OCS |= (1 << 5)                // Unload from out buffer
         |  (1 << 6)                // Clear over run
         |  (1 << 7)
         |  (1 << 8)
         |  (1 << 10);
/* Enable USB endpoints & interrupts */
  USBEPEN = 3;            // Enable EP1 IN & OUT
  USBIC = (0x1ff);        // Clear pending interrupts
  USBIE   = 3;            // Enable EP1 IN & OUT interrupts
}

/*********************************************************************
*
*       USB_HW_EP0_Send
*
*  Description
*    Sends a packet on EP0.
*
*  Notes
*    (1)  If last packet is = to MAXP, we have to send a NULL packet if specified.
*    
*/
void USB_HW_EP0_Send(const unsigned char * pData, unsigned char SendLength, char SendNULLPacket) {
  unsigned char         Bytes2Send;
  OS_DI();
  //
  // Send the data in chunks of no more than 8 bytes
  //
  while (SendLength) {
    if ( SendLength < 8 ) {   // If last packet is < MAXP, a NULL packet is not required
      SendNULLPacket = 0;
    }
    if ( SendLength > 8 ) {     // If more than 8 bytes then break it up
      Bytes2Send = 8;
      SendLength -= 8;
    } else {
      Bytes2Send = SendLength;
      SendLength = 0;
    }
    //
    // Load the fifo
    //
    for( ; Bytes2Send; Bytes2Send--) {
      EP0IL = *pData++;
    }
    if (SendLength | (SendNULLPacket)) {
      EP0CS |= (1<<7);               // Set IN_PKY_RDY
    } else {
      EP0CS = 0x2280;           // Set DATA_END, IPR, and DATA_END mask (NULL packet)
    }
    while ( (EP0CS & (1<<1)) ){}   // and wait for this packet to be taken
  }    
  //
  // Send a NULL packet if required
  //
  if (SendNULLPacket) {       // Is NULL packet needed?
    EP0CS = 0x2280;           // Set DATA_END, IPR, and DATA_END mask (NULL packet)
    while (EP0CS & (1<<1));   // Wait for this packet to be taken
  }
OS_RestoreI();
}       

/*********************************************************************
*
*       USB_HW_ClearOutPacketReady
*
*  Description
*    TBD
*/
void USB_HW_ClearOutPacketReady(void) {
  EP0CS = (1<<6);
}

/*********************************************************************
*
*       USB_HW_ClrSetupEnd
*
*  Description
*    TBD
*/
void  USB_HW_ClrSetupEnd(void) {
  EP0CS |= (1<<8);
}


/*********************************************************************
*
*       USB_ISR_Function
*
*  Function Description
*    USB functional interrupt occurs when data is sent
*    or received. Various flags are set or cleared here
*    depending on program flow for the starter kit
*
*/
#pragma vector = 29
__regbank_interrupt void USB_ISR_Function(void){
  OS_EnterInterrupt();
  if ( (EP0CS & (1<<5)) ){      // Did the control transfer end early?
    EP0CS |= (1 << 11);         // Clear setup end
    USBIC = (1<<8);             // Clear error status flag
  }
  if ( (USBIS & (1<<8)) ){      // Error ?
    USBIC = (1<<8);             // Clear error status flag
  }
  if ( (USBIS & (1<<0)) ){      // EP1 IN Interrupt
    USBIC = (1<<0);             // Clear EP1 IN interrupt status flag
    USB__OnTx();
  }
  if ( (USBIS & (1<<1)) ){        // EP1 OUT Interrupt ?
    USBIC = (1<<1);               // Clear EP1 OUT interrupt status flag
    if ( (EP1OCS & (1<<1)) ) {    // Data available ?
      int PacketSize = EP1WC;
      USB__OnRx(PacketSize);
    }
  }

  OS_LeaveInterrupt();
}

/*********************************************************************
*
*       USB_ISR_EP0
*
*  Function Description
*    USB Endpoint 0 interrupt occurs when a SETUP packet is received
*    to setup the USB controller.
*/
#pragma vector = 6
__interrupt void USB_ISR_EP0(void) {
  USB_SETUP_PACKET SetupPacket;
  OS_EnterInterrupt();
  if ((EP0CS & EP0CS_SETUP_READY) == EP0CS_SETUP_READY) {  // Check is this is a SETUP packet
    SetupPacket.bmRequestType = EP0OL;     // If so, read the data out of the
    SetupPacket.bRequest      = EP0OL;     // FIFO and place in this
    SetupPacket.wValueLow     = EP0OL;     // structure
    SetupPacket.wValueHigh    = EP0OL;
    SetupPacket.wIndexLow     = EP0OL;
    SetupPacket.wIndexHigh    = EP0OL;
    SetupPacket.wLengthLow    = EP0OL;
    SetupPacket.wLengthHigh   = EP0OL;
    if (EP0CS & (1<<12)){    // If SEND_STALL is set, then clear it
      EP0CS |= (0<<12);        // Since this is a new SETUP packet
    }
    USB__HandleSetup(&SetupPacket);
  }
  OS_LeaveInterrupt();
}

/*********************************************************************
*
*       USB_ISR_Reset
*
*  Function Description
*       When a USB RESET occurs this function restores the
*       necessary variables and EP's to default values
*
*/
#pragma vector = 26
__interrupt void USB_ISR_Reset(void) {}


/*********************************************************************
*
*       VBUSDetectInterrupt
*
*  Function Description
*    Detects if the USB cable has been plugged in.
*    Does not make sense for USB powered devices.
*/
#pragma vector = 28
__interrupt void VBUS_ISR_DetectInterrupt(void){}

/*********************************************************************
*
*       USB_ISR_SOF
*  Function Description
*    Interrupt on every Start-Of-Frame
*    Does not make sense.
*/
#pragma vector = 27
__interrupt void USB_ISR_SOF(void){}


/*********************************************************************
*
*       USB_ISR_Suspend
*
*  Function Description
*    USB SUSPEND interrupt routine. When the D+/D- is idle for more than
*    3mS, the USB core will enter the SUSPEND state. This can also be caused
*    if the USB cable is unplugged. Here all interrupts are disabled with
*    the exception of the USB RESUME interrupt and the device enters STOP
*    mode for low power.
*/
#pragma vector = 22
__interrupt void USB_ISR_Suspend(void){}

/*********************************************************************
*
*       USB_ISR_Resume
*
*  Function Description
*    After entering the SUSPEND state, when the USB core detects signalling
*    on D+/D-, an interrupt is generated, waking the device from the STOP
*    state. This interrupt routine starts up the USB core and re-enables
*    the appropriate interrupts for other functions.
*/
#pragma vector = 24
__interrupt void USB_ISR_Resume(void){}


/*************************** End of file ****************************/

⌨️ 快捷键说明

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