USBMSD test for GR-PEACH
Dependencies: USBDevice USBMSD_SD mbed
Fork of USBMSD_SD_HelloWorld_Mbed by
Diff: USBDevice/USBDevice/USBBusInterface_LPC17_LPC23.cpp
- Revision:
- 7:6494da2a5c60
- Parent:
- 6:126c4d980196
- Child:
- 8:534fd41d8cc7
--- a/USBDevice/USBDevice/USBBusInterface_LPC17_LPC23.cpp Mon Nov 14 10:00:07 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,682 +0,0 @@ -// USBBusInterface_LPC17_LPC23.c -// USB Bus Interface for NXP LPC1768 and LPC2368 -// Copyright (c) 2011 ARM Limited. All rights reserved. - -#ifdef TARGET_LPC1768 - -#include "USBBusInterface.h" - - -// Get endpoint direction -#define IN_EP(endpoint) ((endpoint) & 1U ? true : false) -#define OUT_EP(endpoint) ((endpoint) & 1U ? false : true) - -// Convert physical endpoint number to register bit -#define EP(endpoint) (1UL<<endpoint) - -// Power Control for Peripherals register -#define PCUSB (1UL<<31) - -// USB Clock Control register -#define DEV_CLK_EN (1UL<<1) -#define AHB_CLK_EN (1UL<<4) - -// USB Clock Status register -#define DEV_CLK_ON (1UL<<1) -#define AHB_CLK_ON (1UL<<4) - -// USB Device Interupt registers -#define FRAME (1UL<<0) -#define EP_FAST (1UL<<1) -#define EP_SLOW (1UL<<2) -#define DEV_STAT (1UL<<3) -#define CCEMPTY (1UL<<4) -#define CDFULL (1UL<<5) -#define RxENDPKT (1UL<<6) -#define TxENDPKT (1UL<<7) -#define EP_RLZED (1UL<<8) -#define ERR_INT (1UL<<9) - -// USB Control register -#define RD_EN (1<<0) -#define WR_EN (1<<1) -#define LOG_ENDPOINT(endpoint) ((endpoint>>1)<<2) - -// USB Receive Packet Length register -#define DV (1UL<<10) -#define PKT_RDY (1UL<<11) -#define PKT_LNGTH_MASK (0x3ff) - -// Serial Interface Engine (SIE) -#define SIE_WRITE (0x01) -#define SIE_READ (0x02) -#define SIE_COMMAND (0x05) -#define SIE_CMD_CODE(phase, data) ((phase<<8)|(data<<16)) - -// SIE Command codes -#define SIE_CMD_SET_ADDRESS (0xD0) -#define SIE_CMD_CONFIGURE_DEVICE (0xD8) -#define SIE_CMD_SET_MODE (0xF3) -#define SIE_CMD_READ_FRAME_NUMBER (0xF5) -#define SIE_CMD_READ_TEST_REGISTER (0xFD) -#define SIE_CMD_SET_DEVICE_STATUS (0xFE) -#define SIE_CMD_GET_DEVICE_STATUS (0xFE) -#define SIE_CMD_GET_ERROR_CODE (0xFF) -#define SIE_CMD_READ_ERROR_STATUS (0xFB) - -#define SIE_CMD_SELECT_ENDPOINT(endpoint) (0x00+endpoint) -#define SIE_CMD_SELECT_ENDPOINT_CLEAR_INTERRUPT(endpoint) (0x40+endpoint) -#define SIE_CMD_SET_ENDPOINT_STATUS(endpoint) (0x40+endpoint) - -#define SIE_CMD_CLEAR_BUFFER (0xF2) -#define SIE_CMD_VALIDATE_BUFFER (0xFA) - -// SIE Device Status register -#define SIE_DS_CON (1<<0) -#define SIE_DS_CON_CH (1<<1) -#define SIE_DS_SUS (1<<2) -#define SIE_DS_SUS_CH (1<<3) -#define SIE_DS_RST (1<<4) - -// SIE Device Set Address register -#define SIE_DSA_DEV_EN (1<<7) - -// SIE Configue Device register -#define SIE_CONF_DEVICE (1<<0) - -// Select Endpoint register -#define SIE_SE_FE (1<<0) -#define SIE_SE_ST (1<<1) -#define SIE_SE_STP (1<<2) -#define SIE_SE_PO (1<<3) -#define SIE_SE_EPN (1<<4) -#define SIE_SE_B_1_FULL (1<<5) -#define SIE_SE_B_2_FULL (1<<6) - -// Set Endpoint Status command -#define SIE_SES_ST (1<<0) -#define SIE_SES_DA (1<<5) -#define SIE_SES_RF_MO (1<<6) -#define SIE_SES_CND_ST (1<<7) - - -USBHAL * USBHAL::instance; - -volatile int epComplete; -uint32_t endpointStallState; - -static void SIECommand(uint32_t command) -{ - // The command phase of a SIE transaction - LPC_USB->USBDevIntClr = CCEMPTY; - LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_COMMAND, command); - while (!(LPC_USB->USBDevIntSt & CCEMPTY)); -} - -static void SIEWriteData(uint8_t data) -{ - // The data write phase of a SIE transaction - LPC_USB->USBDevIntClr = CCEMPTY; - LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_WRITE, data); - while (!(LPC_USB->USBDevIntSt & CCEMPTY)); -} - -static uint8_t SIEReadData(uint32_t command) -{ - // The data read phase of a SIE transaction - LPC_USB->USBDevIntClr = CDFULL; - LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_READ, command); - while (!(LPC_USB->USBDevIntSt & CDFULL)); - return (uint8_t)LPC_USB->USBCmdData; -} - -static void SIEsetDeviceStatus(uint8_t status) -{ - // Write SIE device status register - SIECommand(SIE_CMD_SET_DEVICE_STATUS); - SIEWriteData(status); -} - -static uint8_t SIEgetDeviceStatus(void) -{ - // Read SIE device status register - SIECommand(SIE_CMD_GET_DEVICE_STATUS); - return SIEReadData(SIE_CMD_GET_DEVICE_STATUS); -} - -void SIEsetAddress(uint8_t address) -{ - // Write SIE device address register - SIECommand(SIE_CMD_SET_ADDRESS); - SIEWriteData((address & 0x7f) | SIE_DSA_DEV_EN); -} - -static uint8_t SIEselectEndpoint(uint8_t endpoint) -{ - // SIE select endpoint command - SIECommand(SIE_CMD_SELECT_ENDPOINT(endpoint)); - return SIEReadData(SIE_CMD_SELECT_ENDPOINT(endpoint)); -} - -static uint8_t SIEclearBuffer(void) -{ - // SIE clear buffer command - SIECommand(SIE_CMD_CLEAR_BUFFER); - return SIEReadData(SIE_CMD_CLEAR_BUFFER); -} - -static void SIEvalidateBuffer(void) -{ - // SIE validate buffer command - SIECommand(SIE_CMD_VALIDATE_BUFFER); -} - -static void SIEsetEndpointStatus(uint8_t endpoint, uint8_t status) -{ - // SIE set endpoint status command - SIECommand(SIE_CMD_SET_ENDPOINT_STATUS(endpoint)); - SIEWriteData(status); -} - -static uint16_t SIEgetFrameNumber(void) __attribute__ ((unused)); -static uint16_t SIEgetFrameNumber(void) -{ - // Read current frame number - uint16_t lowByte; - uint16_t highByte; - - SIECommand(SIE_CMD_READ_FRAME_NUMBER); - lowByte = SIEReadData(SIE_CMD_READ_FRAME_NUMBER); - highByte = SIEReadData(SIE_CMD_READ_FRAME_NUMBER); - - return (highByte << 8) | lowByte; -} - -static void SIEconfigureDevice(void) -{ - // SIE Configure device command - SIECommand(SIE_CMD_CONFIGURE_DEVICE); - SIEWriteData(SIE_CONF_DEVICE); -} - -static void SIEunconfigureDevice(void) -{ - // SIE Configure device command - SIECommand(SIE_CMD_CONFIGURE_DEVICE); - SIEWriteData(0); -} - -static void SIEconnect(void) -{ - // Connect USB device - uint8_t status; - - status = SIEgetDeviceStatus(); - SIEsetDeviceStatus(status | SIE_DS_CON); -} - - -static void SIEdisconnect(void) -{ - // Disconnect USB device - uint8_t status; - - status = SIEgetDeviceStatus(); - SIEsetDeviceStatus(status & ~SIE_DS_CON); -} - - -static uint8_t selectEndpointClearInterrupt(uint8_t endpoint) -{ - // Implemented using using EP_INT_CLR. - LPC_USB->USBEpIntClr = EP(endpoint); - while (!(LPC_USB->USBDevIntSt & CDFULL)); - return (uint8_t)LPC_USB->USBCmdData; -} - - - - - -static void enableEndpointEvent(uint8_t endpoint) -{ - // Enable an endpoint interrupt - LPC_USB->USBEpIntEn |= EP(endpoint); -} - -static void disableEndpointEvent(uint8_t endpoint) __attribute__ ((unused)); -static void disableEndpointEvent(uint8_t endpoint) -{ - // Disable an endpoint interrupt - LPC_USB->USBEpIntEn &= ~EP(endpoint); -} - -static volatile uint32_t __attribute__((used)) dummyRead; - - -static uint32_t endpointReadcore(uint8_t endpoint, uint8_t *buffer) -{ - // Read from an OUT endpoint - uint32_t size; - uint32_t i; - uint32_t data = 0; - uint8_t offset; - - LPC_USB->USBCtrl = LOG_ENDPOINT(endpoint) | RD_EN; - while (!(LPC_USB->USBRxPLen & PKT_RDY)); - - size = LPC_USB->USBRxPLen & PKT_LNGTH_MASK; - - offset = 0; - - if (size > 0) - { - for (i=0; i<size; i++) - { - if (offset==0) - { - // Fetch up to four bytes of data as a word - data = LPC_USB->USBRxData; - } - - // extract a byte - *buffer = (data>>offset) & 0xff; - buffer++; - - // move on to the next byte - offset = (offset + 8) % 32; - } - } - else - { - dummyRead = LPC_USB->USBRxData; - } - - SIEselectEndpoint(endpoint); - SIEclearBuffer(); - return size; -} - -static void endpointWritecore(uint8_t endpoint, uint8_t *buffer, uint32_t size) -{ - // Write to an IN endpoint - uint32_t temp, data; - uint8_t offset; - - LPC_USB->USBCtrl = LOG_ENDPOINT(endpoint) | WR_EN; - - LPC_USB->USBTxPLen = size; - offset = 0; - data = 0; - - if (size>0) - { - do { - // Fetch next data byte into a word-sized temporary variable - temp = *buffer++; - - // Add to current data word - temp = temp << offset; - data = data | temp; - - // move on to the next byte - offset = (offset + 8) % 32; - size--; - - if ((offset==0) || (size==0)) - { - // Write the word to the endpoint - LPC_USB->USBTxData = data; - data = 0; - } - } while (size>0); - } - else - { - LPC_USB->USBTxData = 0; - } - - // Clear WR_EN to cover zero length packet case - LPC_USB->USBCtrl=0; - - SIEselectEndpoint(endpoint); - SIEvalidateBuffer(); -} - - - - - - - -USBHAL::USBHAL(void) -{ - // Disable IRQ - NVIC_DisableIRQ(USB_IRQn); - - // Enable power to USB device controller - LPC_SC->PCONP |= PCUSB; - - // Enable USB clocks - LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN; - while (LPC_USB->USBClkSt != (DEV_CLK_ON | AHB_CLK_ON)); - - // Configure pins P0.29 and P0.30 to be USB D+ and USB D- - LPC_PINCON->PINSEL1 &= 0xc3ffffff; - LPC_PINCON->PINSEL1 |= 0x14000000; - - // Disconnect USB device - SIEdisconnect(); - - // Configure pin P2.9 to be Connect - LPC_PINCON->PINSEL4 &= 0xfffcffff; - LPC_PINCON->PINSEL4 |= 0x00040000; - - // Connect must be low for at least 2.5uS - wait(0.3); - - // Set the maximum packet size for the control endpoints - realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0, 0); - realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0, 0); - - // Attach IRQ - instance = this; - NVIC_SetVector(USB_IRQn, (uint32_t)&_usbisr); - NVIC_EnableIRQ(USB_IRQn); - - // Enable interrupts for device events and EP0 - LPC_USB->USBDevIntEn = EP_SLOW | DEV_STAT; - enableEndpointEvent(EP0IN); - enableEndpointEvent(EP0OUT); -} - -USBHAL::~USBHAL(void) -{ - // Ensure device disconnected - SIEdisconnect(); - - // Disable USB interrupts - NVIC_DisableIRQ(USB_IRQn); -} - -void USBHAL::connect(void) -{ - // Connect USB device - SIEconnect(); -} - -void USBHAL::disconnect(void) -{ - // Disconnect USB device - SIEdisconnect(); -} - -void USBHAL::configureDevice(void) -{ - SIEconfigureDevice(); -} - -void USBHAL::unconfigureDevice(void) -{ - SIEunconfigureDevice(); -} - -void USBHAL::setAddress(uint8_t address) -{ - SIEsetAddress(address); -} - -void USBHAL::EP0setup(uint8_t *buffer) -{ - endpointReadcore(EP0OUT, buffer); -} - -void USBHAL::EP0read(void) -{ - // Not required -} - -uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) -{ - return endpointReadcore(EP0OUT, buffer); -} - -void USBHAL::EP0write(uint8_t *buffer, uint32_t size) -{ - endpointWritecore(EP0IN, buffer, size); -} - -void USBHAL::EP0getWriteResult(void) -{ - // Not required -} - -void USBHAL::EP0stall(void) -{ - // This will stall both control endpoints - stallEndpoint(EP0OUT); -} - -EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) -{ - return EP_PENDING; -} - -EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) -{ - if(!(epComplete & EP(endpoint))) - return EP_PENDING; - *bytesRead = endpointReadcore(endpoint, buffer); - epComplete &= ~EP(endpoint); - return EP_COMPLETED; -} - -EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) -{ - if (getEndpointStallState(endpoint)) - { - return EP_STALLED; - } - - epComplete &= ~EP(endpoint); - - endpointWritecore(endpoint, data, size); - return EP_PENDING; -} - -EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) -{ - if (epComplete & EP(endpoint)) - { - epComplete &= ~EP(endpoint); - return EP_COMPLETED; - } - - return EP_PENDING; -} - -bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) -{ - // Realise an endpoint - LPC_USB->USBDevIntClr = EP_RLZED; - LPC_USB->USBReEp |= EP(endpoint); - LPC_USB->USBEpInd = endpoint; - LPC_USB->USBMaxPSize = maxPacket; - - while (!(LPC_USB->USBDevIntSt & EP_RLZED)); - LPC_USB->USBDevIntClr = EP_RLZED; - - // Clear stall state - endpointStallState &= ~EP(endpoint); - - enableEndpointEvent(endpoint); - return true; -} - -void USBHAL::stallEndpoint(uint8_t endpoint) -{ - // Stall an endpoint - if ( (endpoint==EP0IN) || (endpoint==EP0OUT) ) - { - // Conditionally stall both control endpoints - SIEsetEndpointStatus(EP0OUT, SIE_SES_CND_ST); - } - else - { - SIEsetEndpointStatus(endpoint, SIE_SES_ST); - - // Update stall state - endpointStallState |= EP(endpoint); - } -} - -void USBHAL::unstallEndpoint(uint8_t endpoint) -{ - // Unstall an endpoint. The endpoint will also be reinitialised - SIEsetEndpointStatus(endpoint, 0); - - // Update stall state - endpointStallState &= ~EP(endpoint); -} - -bool USBHAL::getEndpointStallState(uint8_t endpoint) -{ - // Returns true if endpoint stalled - return endpointStallState & EP(endpoint); -} - -void USBHAL::remoteWakeup(void) -{ - // Remote wakeup - uint8_t status; - - // Enable USB clocks - LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN; - while (LPC_USB->USBClkSt != (DEV_CLK_ON | AHB_CLK_ON)); - - status = SIEgetDeviceStatus(); - SIEsetDeviceStatus(status & ~SIE_DS_SUS); -} - - - - - -void USBHAL::_usbisr(void) -{ - instance->usbisr(); -} - - -void USBHAL::usbisr(void) -{ - uint8_t devStat; - - if (LPC_USB->USBDevIntSt & FRAME) - { - // Start of frame event - SOF(SIEgetFrameNumber()); - // Clear interrupt status flag - LPC_USB->USBDevIntClr = FRAME; - } - - if (LPC_USB->USBDevIntSt & DEV_STAT) - { - // Device Status interrupt - // Must clear the interrupt status flag before reading the device status from the SIE - LPC_USB->USBDevIntClr = DEV_STAT; - - // Read device status from SIE - devStat = SIEgetDeviceStatus(); - - if (devStat & SIE_DS_RST) - { - // Bus reset - busReset(); - } - } - - if (LPC_USB->USBDevIntSt & EP_SLOW) - { - // (Slow) Endpoint Interrupt - - // Process each endpoint interrupt - if (LPC_USB->USBEpIntSt & EP(EP0OUT)) - { - if (selectEndpointClearInterrupt(EP0OUT) & SIE_SE_STP) - { - // this is a setup packet - EP0setupCallback(); - } - else - { - EP0out(); - } - LPC_USB->USBDevIntClr = EP_SLOW; - } - - if (LPC_USB->USBEpIntSt & EP(EP0IN)) - { - selectEndpointClearInterrupt(EP0IN); - LPC_USB->USBDevIntClr = EP_SLOW; - EP0in(); - } - - // TODO: This should cover all endpoints, not just EP1,2,3: - if (LPC_USB->USBEpIntSt & EP(EP1IN)) - { - selectEndpointClearInterrupt(EP1IN); - epComplete |= EP(EP1IN); - LPC_USB->USBDevIntClr = EP_SLOW; - if(EP1_IN_callback()) - epComplete &= ~EP(EP1IN); - } - - if (LPC_USB->USBEpIntSt & EP(EP1OUT)) - { - selectEndpointClearInterrupt(EP1OUT); - epComplete |= EP(EP1OUT); - LPC_USB->USBDevIntClr = EP_SLOW; - if(EP1_OUT_callback()) - epComplete &= ~EP(EP1OUT); - } - - if (LPC_USB->USBEpIntSt & EP(EP2IN)) - { - selectEndpointClearInterrupt(EP2IN); - epComplete |= EP(EP2IN); - LPC_USB->USBDevIntClr = EP_SLOW; - if(EP2_IN_callback()) - epComplete &= ~EP(EP2IN); - } - - if (LPC_USB->USBEpIntSt & EP(EP2OUT)) - { - selectEndpointClearInterrupt(EP2OUT); - epComplete |= EP(EP2OUT); - LPC_USB->USBDevIntClr = EP_SLOW; - if(EP2_OUT_callback()) - epComplete &= ~EP(EP2OUT); - } - - if (LPC_USB->USBEpIntSt & EP(EP3IN)) - { - selectEndpointClearInterrupt(EP3IN); - epComplete |= EP(EP3IN); - LPC_USB->USBDevIntClr = EP_SLOW; - if(EP3_IN_callback()) - epComplete &= ~EP(EP3IN); - } - - if (LPC_USB->USBEpIntSt & EP(EP3OUT)) - { - selectEndpointClearInterrupt(EP3OUT); - epComplete |= EP(EP3OUT); - LPC_USB->USBDevIntClr = EP_SLOW; - if(EP3_OUT_callback()) - epComplete &= ~EP(EP3OUT); - } - } -} - -#endif