Jafar Qutteineh / Mbed 2 deprecated RC_Simulator

Dependencies:   mbed

Committer:
j3sq
Date:
Sat Jul 02 17:27:05 2011 +0000
Revision:
0:3dbb22992c94
Revision 0.0 (This is just a demonstration)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
j3sq 0:3dbb22992c94 1 /* usbdc.cpp */
j3sq 0:3dbb22992c94 2 /* USB device controller */
j3sq 0:3dbb22992c94 3 /* Copyright (c) Phil Wright 2008 */
j3sq 0:3dbb22992c94 4
j3sq 0:3dbb22992c94 5 #include "mbed.h"
j3sq 0:3dbb22992c94 6 #include "usbdc.h"
j3sq 0:3dbb22992c94 7 #include "cmsis.h"
j3sq 0:3dbb22992c94 8
j3sq 0:3dbb22992c94 9 #ifdef TARGET_LPC2368
j3sq 0:3dbb22992c94 10 #undef LPC_USB_BASE
j3sq 0:3dbb22992c94 11 #define LPC_USB_BASE (0xFFE0C000) /* TODO */
j3sq 0:3dbb22992c94 12 #endif
j3sq 0:3dbb22992c94 13
j3sq 0:3dbb22992c94 14 /* Power Control for Peripherals register */
j3sq 0:3dbb22992c94 15 #define PCUSB ((unsigned long)1<<31)
j3sq 0:3dbb22992c94 16
j3sq 0:3dbb22992c94 17 /* USB Clock Control register */
j3sq 0:3dbb22992c94 18 #define DEV_CLK_EN ((unsigned long)1<<1)
j3sq 0:3dbb22992c94 19 #define AHB_CLK_EN ((unsigned long)1<<4)
j3sq 0:3dbb22992c94 20
j3sq 0:3dbb22992c94 21 /* USB Clock Status register */
j3sq 0:3dbb22992c94 22 #define DEV_CLK_ON ((unsigned long)1<<1)
j3sq 0:3dbb22992c94 23 #define AHB_CLK_ON ((unsigned long)1<<4)
j3sq 0:3dbb22992c94 24
j3sq 0:3dbb22992c94 25 /* USB Device Interupt registers */
j3sq 0:3dbb22992c94 26 #define FRAME ((unsigned long)1<<0)
j3sq 0:3dbb22992c94 27 #define EP_FAST ((unsigned long)1<<1)
j3sq 0:3dbb22992c94 28 #define EP_SLOW ((unsigned long)1<<2)
j3sq 0:3dbb22992c94 29 #define DEV_STAT ((unsigned long)1<<3)
j3sq 0:3dbb22992c94 30 #define CCEMPTY ((unsigned long)1<<4)
j3sq 0:3dbb22992c94 31 #define CDFULL ((unsigned long)1<<5)
j3sq 0:3dbb22992c94 32 #define RxENDPKT ((unsigned long)1<<6)
j3sq 0:3dbb22992c94 33 #define TxENDPKT ((unsigned long)1<<7)
j3sq 0:3dbb22992c94 34 #define EP_RLZED ((unsigned long)1<<8)
j3sq 0:3dbb22992c94 35 #define ERR_INT ((unsigned long)1<<9)
j3sq 0:3dbb22992c94 36
j3sq 0:3dbb22992c94 37 /* Endpoint Interrupt Registers */
j3sq 0:3dbb22992c94 38 #define EP(endpoint) (1<<endpoint)
j3sq 0:3dbb22992c94 39
j3sq 0:3dbb22992c94 40 /* USB Control register */
j3sq 0:3dbb22992c94 41 #define RD_EN (1<<0)
j3sq 0:3dbb22992c94 42 #define WR_EN (1<<1)
j3sq 0:3dbb22992c94 43 #define LOG_ENDPOINT(endpoint) ((endpoint>>1)<<2)
j3sq 0:3dbb22992c94 44
j3sq 0:3dbb22992c94 45 /* USB Receive Packet Length register */
j3sq 0:3dbb22992c94 46 #define DV ((unsigned long)1<<10)
j3sq 0:3dbb22992c94 47 #define PKT_RDY ((unsigned long)1<<11)
j3sq 0:3dbb22992c94 48 #define PKT_LNGTH_MASK (0x3ff)
j3sq 0:3dbb22992c94 49
j3sq 0:3dbb22992c94 50 /* Serial Interface Engine (SIE) */
j3sq 0:3dbb22992c94 51 #define SIE_WRITE (0x01)
j3sq 0:3dbb22992c94 52 #define SIE_READ (0x02)
j3sq 0:3dbb22992c94 53 #define SIE_COMMAND (0x05)
j3sq 0:3dbb22992c94 54 #define SIE_CMD_CODE(phase, data) ((phase<<8)|(data<<16))
j3sq 0:3dbb22992c94 55
j3sq 0:3dbb22992c94 56 /* SIE Command codes */
j3sq 0:3dbb22992c94 57 #define SIE_CMD_SET_ADDRESS (0xD0)
j3sq 0:3dbb22992c94 58 #define SIE_CMD_CONFIGURE_DEVICE (0xD8)
j3sq 0:3dbb22992c94 59 #define SIE_CMD_SET_MODE (0xF3)
j3sq 0:3dbb22992c94 60 #define SIE_CMD_READ_FRAME_NUMBER (0xF5)
j3sq 0:3dbb22992c94 61 #define SIE_CMD_READ_TEST_REGISTER (0xFD)
j3sq 0:3dbb22992c94 62 #define SIE_CMD_SET_DEVICE_STATUS (0xFE)
j3sq 0:3dbb22992c94 63 #define SIE_CMD_GET_DEVICE_STATUS (0xFE)
j3sq 0:3dbb22992c94 64 #define SIE_CMD_GET_ERROR_CODE (0xFF)
j3sq 0:3dbb22992c94 65 #define SIE_CMD_READ_ERROR_STATUS (0xFB)
j3sq 0:3dbb22992c94 66
j3sq 0:3dbb22992c94 67 #define SIE_CMD_SELECT_ENDPOINT(endpoint) (0x00+endpoint)
j3sq 0:3dbb22992c94 68 #define SIE_CMD_SELECT_ENDPOINT_CLEAR_INTERRUPT(endpoint) (0x40+endpoint)
j3sq 0:3dbb22992c94 69 #define SIE_CMD_SET_ENDPOINT_STATUS(endpoint) (0x40+endpoint)
j3sq 0:3dbb22992c94 70
j3sq 0:3dbb22992c94 71 #define SIE_CMD_CLEAR_BUFFER (0xF2)
j3sq 0:3dbb22992c94 72 #define SIE_CMD_VALIDATE_BUFFER (0xFA)
j3sq 0:3dbb22992c94 73
j3sq 0:3dbb22992c94 74 /* SIE Device Status register */
j3sq 0:3dbb22992c94 75 #define SIE_DS_CON (1<<0)
j3sq 0:3dbb22992c94 76 #define SIE_DS_CON_CH (1<<1)
j3sq 0:3dbb22992c94 77 #define SIE_DS_SUS (1<<2)
j3sq 0:3dbb22992c94 78 #define SIE_DS_SUS_CH (1<<3)
j3sq 0:3dbb22992c94 79 #define SIE_DS_RST (1<<4)
j3sq 0:3dbb22992c94 80
j3sq 0:3dbb22992c94 81 /* SIE Device Set Address register */
j3sq 0:3dbb22992c94 82 #define SIE_DSA_DEV_EN (1<<7)
j3sq 0:3dbb22992c94 83
j3sq 0:3dbb22992c94 84 /* SIE Configue Device register */
j3sq 0:3dbb22992c94 85 #define SIE_CONF_DEVICE (1<<0)
j3sq 0:3dbb22992c94 86
j3sq 0:3dbb22992c94 87 /* Select Endpoint register */
j3sq 0:3dbb22992c94 88 #define SIE_SE_FE (1<<0)
j3sq 0:3dbb22992c94 89 #define SIE_SE_ST (1<<1)
j3sq 0:3dbb22992c94 90 #define SIE_SE_STP (1<<2)
j3sq 0:3dbb22992c94 91 #define SIE_SE_PO (1<<3)
j3sq 0:3dbb22992c94 92 #define SIE_SE_EPN (1<<4)
j3sq 0:3dbb22992c94 93 #define SIE_SE_B_1_FULL (1<<5)
j3sq 0:3dbb22992c94 94 #define SIE_SE_B_2_FULL (1<<6)
j3sq 0:3dbb22992c94 95
j3sq 0:3dbb22992c94 96 /* Set Endpoint Status command */
j3sq 0:3dbb22992c94 97 #define SIE_SES_ST (1<<0)
j3sq 0:3dbb22992c94 98 #define SIE_SES_DA (1<<5)
j3sq 0:3dbb22992c94 99 #define SIE_SES_RF_MO (1<<6)
j3sq 0:3dbb22992c94 100 #define SIE_SES_CND_ST (1<<7)
j3sq 0:3dbb22992c94 101
j3sq 0:3dbb22992c94 102 usbdc *usbdc::instance;
j3sq 0:3dbb22992c94 103
j3sq 0:3dbb22992c94 104 usbdc::usbdc()
j3sq 0:3dbb22992c94 105 {
j3sq 0:3dbb22992c94 106 #ifdef TARGET_LPC1768
j3sq 0:3dbb22992c94 107 LPC_SC->USBCLKCFG=5; /* TODO */
j3sq 0:3dbb22992c94 108 #endif
j3sq 0:3dbb22992c94 109
j3sq 0:3dbb22992c94 110 /* Enable power to USB device controller */
j3sq 0:3dbb22992c94 111 LPC_SC->PCONP |= PCUSB;
j3sq 0:3dbb22992c94 112
j3sq 0:3dbb22992c94 113 /* Enable USB clocks */
j3sq 0:3dbb22992c94 114 LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN;
j3sq 0:3dbb22992c94 115 while (LPC_USB->USBClkSt != (DEV_CLK_ON | AHB_CLK_ON));
j3sq 0:3dbb22992c94 116
j3sq 0:3dbb22992c94 117 /* Configure pins P0.29 and P0.30 to be USB D+ and USB D- */
j3sq 0:3dbb22992c94 118 LPC_PINCON->PINSEL1 &= 0xc3ffffff;
j3sq 0:3dbb22992c94 119 LPC_PINCON->PINSEL1 |= 0x14000000;
j3sq 0:3dbb22992c94 120
j3sq 0:3dbb22992c94 121 #ifdef ENABLE_VBUS
j3sq 0:3dbb22992c94 122 /* Configure pin P1.30 to be VBUS */
j3sq 0:3dbb22992c94 123 LPC_PINCON->PINSEL3 &= 0xcfffffff;
j3sq 0:3dbb22992c94 124 LPC_PINCON->PINSEL3 |= 0x20000000;
j3sq 0:3dbb22992c94 125
j3sq 0:3dbb22992c94 126 /* Configure pin P1.30 to have pull-down */
j3sq 0:3dbb22992c94 127 LPC_PINCON->PINMODE3 |= 0x30000000;
j3sq 0:3dbb22992c94 128 #endif
j3sq 0:3dbb22992c94 129
j3sq 0:3dbb22992c94 130 /* Configure pin P2.9 to be Connect */
j3sq 0:3dbb22992c94 131 LPC_PINCON->PINSEL4 &= 0xfffcffff;
j3sq 0:3dbb22992c94 132 LPC_PINCON->PINSEL4 |= 0x00040000;
j3sq 0:3dbb22992c94 133
j3sq 0:3dbb22992c94 134 /* Connect must be low for at least 2.5uS */
j3sq 0:3dbb22992c94 135 wait_ms(1);
j3sq 0:3dbb22992c94 136
j3sq 0:3dbb22992c94 137 /* Attach IRQ */
j3sq 0:3dbb22992c94 138 instance = this;
j3sq 0:3dbb22992c94 139 NVIC_SetVector(USB_IRQn, (uint32_t)&_usbisr);
j3sq 0:3dbb22992c94 140 NVIC_EnableIRQ(USB_IRQn);
j3sq 0:3dbb22992c94 141
j3sq 0:3dbb22992c94 142 /* Enable device interrupts */
j3sq 0:3dbb22992c94 143 enableEvents();
j3sq 0:3dbb22992c94 144 }
j3sq 0:3dbb22992c94 145
j3sq 0:3dbb22992c94 146 void usbdc::connect(void)
j3sq 0:3dbb22992c94 147 {
j3sq 0:3dbb22992c94 148 /* Connect USB device */
j3sq 0:3dbb22992c94 149 unsigned char status;
j3sq 0:3dbb22992c94 150
j3sq 0:3dbb22992c94 151 status = getDeviceStatus();
j3sq 0:3dbb22992c94 152 setDeviceStatus(status | SIE_DS_CON);
j3sq 0:3dbb22992c94 153 }
j3sq 0:3dbb22992c94 154
j3sq 0:3dbb22992c94 155 void usbdc::disconnect(void)
j3sq 0:3dbb22992c94 156 {
j3sq 0:3dbb22992c94 157 /* Disconnect USB device */
j3sq 0:3dbb22992c94 158 unsigned char status;
j3sq 0:3dbb22992c94 159
j3sq 0:3dbb22992c94 160 status = getDeviceStatus();
j3sq 0:3dbb22992c94 161 setDeviceStatus(status & ~SIE_DS_CON);
j3sq 0:3dbb22992c94 162 }
j3sq 0:3dbb22992c94 163
j3sq 0:3dbb22992c94 164 void usbdc::SIECommand(unsigned long command)
j3sq 0:3dbb22992c94 165 {
j3sq 0:3dbb22992c94 166 /* The command phase of a SIE transaction */
j3sq 0:3dbb22992c94 167 LPC_USB->USBDevIntClr = CCEMPTY;
j3sq 0:3dbb22992c94 168 LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_COMMAND, command);
j3sq 0:3dbb22992c94 169 while (!(LPC_USB->USBDevIntSt & CCEMPTY));
j3sq 0:3dbb22992c94 170 }
j3sq 0:3dbb22992c94 171
j3sq 0:3dbb22992c94 172 void usbdc::SIEWriteData(unsigned char data)
j3sq 0:3dbb22992c94 173 {
j3sq 0:3dbb22992c94 174 /* The data write phase of a SIE transaction */
j3sq 0:3dbb22992c94 175 LPC_USB->USBDevIntClr = CCEMPTY;
j3sq 0:3dbb22992c94 176 LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_WRITE, data);
j3sq 0:3dbb22992c94 177 while (!(LPC_USB->USBDevIntSt & CCEMPTY));
j3sq 0:3dbb22992c94 178 }
j3sq 0:3dbb22992c94 179
j3sq 0:3dbb22992c94 180 unsigned char usbdc::SIEReadData(unsigned long command)
j3sq 0:3dbb22992c94 181 {
j3sq 0:3dbb22992c94 182 /* The data read phase of a SIE transaction */
j3sq 0:3dbb22992c94 183 LPC_USB->USBDevIntClr = CDFULL;
j3sq 0:3dbb22992c94 184 LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_READ, command);
j3sq 0:3dbb22992c94 185 while (!(LPC_USB->USBDevIntSt & CDFULL));
j3sq 0:3dbb22992c94 186 return (unsigned char)LPC_USB->USBCmdData;
j3sq 0:3dbb22992c94 187 }
j3sq 0:3dbb22992c94 188
j3sq 0:3dbb22992c94 189 void usbdc::setDeviceStatus(unsigned char status)
j3sq 0:3dbb22992c94 190 {
j3sq 0:3dbb22992c94 191 /* Write SIE device status register */
j3sq 0:3dbb22992c94 192 SIECommand(SIE_CMD_SET_DEVICE_STATUS);
j3sq 0:3dbb22992c94 193 SIEWriteData(status);
j3sq 0:3dbb22992c94 194 }
j3sq 0:3dbb22992c94 195
j3sq 0:3dbb22992c94 196 unsigned char usbdc::getDeviceStatus(void)
j3sq 0:3dbb22992c94 197 {
j3sq 0:3dbb22992c94 198 /* Read SIE device status register */
j3sq 0:3dbb22992c94 199 SIECommand(SIE_CMD_GET_DEVICE_STATUS);
j3sq 0:3dbb22992c94 200 return SIEReadData(SIE_CMD_GET_DEVICE_STATUS);
j3sq 0:3dbb22992c94 201 }
j3sq 0:3dbb22992c94 202
j3sq 0:3dbb22992c94 203 void usbdc::setAddress(unsigned char address)
j3sq 0:3dbb22992c94 204 {
j3sq 0:3dbb22992c94 205 /* Write SIE device address register */
j3sq 0:3dbb22992c94 206 SIECommand(SIE_CMD_SET_ADDRESS);
j3sq 0:3dbb22992c94 207 SIEWriteData((address & 0x7f) | SIE_DSA_DEV_EN);
j3sq 0:3dbb22992c94 208 }
j3sq 0:3dbb22992c94 209
j3sq 0:3dbb22992c94 210 unsigned char usbdc::selectEndpoint(unsigned char endpoint)
j3sq 0:3dbb22992c94 211 {
j3sq 0:3dbb22992c94 212 /* SIE select endpoint command */
j3sq 0:3dbb22992c94 213 SIECommand(SIE_CMD_SELECT_ENDPOINT(endpoint));
j3sq 0:3dbb22992c94 214 return SIEReadData(SIE_CMD_SELECT_ENDPOINT(endpoint));
j3sq 0:3dbb22992c94 215 }
j3sq 0:3dbb22992c94 216
j3sq 0:3dbb22992c94 217 #if 1
j3sq 0:3dbb22992c94 218 unsigned char usbdc::selectEndpointClearInterrupt(unsigned char endpoint)
j3sq 0:3dbb22992c94 219 {
j3sq 0:3dbb22992c94 220 /* SIE select endpoint and clear interrupt command */
j3sq 0:3dbb22992c94 221 /* Using the Select Endpoint / Clear Interrupt SIE command does not seem */
j3sq 0:3dbb22992c94 222 /* to clear the appropriate bit in EP_INT_STAT? - using EP_INT_CLR instead */
j3sq 0:3dbb22992c94 223 LPC_USB->USBEpIntClr = EP(endpoint);
j3sq 0:3dbb22992c94 224 while (!(LPC_USB->USBDevIntSt & CDFULL));
j3sq 0:3dbb22992c94 225 return (unsigned char)LPC_USB->USBCmdData;
j3sq 0:3dbb22992c94 226 }
j3sq 0:3dbb22992c94 227 #else
j3sq 0:3dbb22992c94 228 unsigned char usbdc::selectEndpointClearInterrupt(unsigned char endpoint)
j3sq 0:3dbb22992c94 229 {
j3sq 0:3dbb22992c94 230 /* SIE select endpoint and clear interrupt command */
j3sq 0:3dbb22992c94 231 SIECommand(SIE_CMD_SELECT_ENDPOINT_CLEAR_INTERRUPT(endpoint));
j3sq 0:3dbb22992c94 232 return SIEReadData(SIE_CMD_SELECT_ENDPOINT_CLEAR_INTERRUPT(endpoint));
j3sq 0:3dbb22992c94 233 }
j3sq 0:3dbb22992c94 234 #endif
j3sq 0:3dbb22992c94 235
j3sq 0:3dbb22992c94 236 unsigned char usbdc::clearBuffer(void)
j3sq 0:3dbb22992c94 237 {
j3sq 0:3dbb22992c94 238 /* SIE clear buffer command */
j3sq 0:3dbb22992c94 239 SIECommand(SIE_CMD_CLEAR_BUFFER);
j3sq 0:3dbb22992c94 240 return SIEReadData(SIE_CMD_CLEAR_BUFFER);
j3sq 0:3dbb22992c94 241 }
j3sq 0:3dbb22992c94 242
j3sq 0:3dbb22992c94 243 void usbdc::validateBuffer(void)
j3sq 0:3dbb22992c94 244 {
j3sq 0:3dbb22992c94 245 /* SIE validate buffer command */
j3sq 0:3dbb22992c94 246 SIECommand(SIE_CMD_VALIDATE_BUFFER);
j3sq 0:3dbb22992c94 247 }
j3sq 0:3dbb22992c94 248
j3sq 0:3dbb22992c94 249 void usbdc::setEndpointStatus(unsigned char endpoint, unsigned char status)
j3sq 0:3dbb22992c94 250 {
j3sq 0:3dbb22992c94 251 /* SIE set endpoint status command */
j3sq 0:3dbb22992c94 252 SIECommand(SIE_CMD_SET_ENDPOINT_STATUS(endpoint));
j3sq 0:3dbb22992c94 253 SIEWriteData(status);
j3sq 0:3dbb22992c94 254 }
j3sq 0:3dbb22992c94 255
j3sq 0:3dbb22992c94 256 void usbdc::realiseEndpoint(unsigned char endpoint, unsigned long maxPacket)
j3sq 0:3dbb22992c94 257 {
j3sq 0:3dbb22992c94 258 /* Realise an endpoint */
j3sq 0:3dbb22992c94 259 LPC_USB->USBDevIntClr = EP_RLZED;
j3sq 0:3dbb22992c94 260 LPC_USB->USBReEp |= EP(endpoint);
j3sq 0:3dbb22992c94 261 LPC_USB->USBEpInd = endpoint;
j3sq 0:3dbb22992c94 262 LPC_USB->USBMaxPSize = maxPacket;
j3sq 0:3dbb22992c94 263
j3sq 0:3dbb22992c94 264 while (!(LPC_USB->USBDevIntSt & EP_RLZED));
j3sq 0:3dbb22992c94 265 LPC_USB->USBDevIntClr = EP_RLZED;
j3sq 0:3dbb22992c94 266
j3sq 0:3dbb22992c94 267 /* Clear stall state */
j3sq 0:3dbb22992c94 268 endpointStallState &= ~EP(endpoint);
j3sq 0:3dbb22992c94 269 }
j3sq 0:3dbb22992c94 270
j3sq 0:3dbb22992c94 271 void usbdc::enableEndpointEvent(unsigned char endpoint)
j3sq 0:3dbb22992c94 272 {
j3sq 0:3dbb22992c94 273 /* Enable an endpoint interrupt */
j3sq 0:3dbb22992c94 274 LPC_USB->USBEpIntEn |= EP(endpoint);
j3sq 0:3dbb22992c94 275 }
j3sq 0:3dbb22992c94 276
j3sq 0:3dbb22992c94 277 void usbdc::disableEndpointEvent(unsigned char endpoint)
j3sq 0:3dbb22992c94 278 {
j3sq 0:3dbb22992c94 279 /* Disable an endpoint interrupt */
j3sq 0:3dbb22992c94 280 LPC_USB->USBEpIntEn &= ~EP(endpoint);
j3sq 0:3dbb22992c94 281 }
j3sq 0:3dbb22992c94 282
j3sq 0:3dbb22992c94 283 void usbdc::stallEndpoint(unsigned char endpoint)
j3sq 0:3dbb22992c94 284 {
j3sq 0:3dbb22992c94 285 /* Stall an endpoint */
j3sq 0:3dbb22992c94 286 if ( (endpoint==EP0IN) || (endpoint==EP0OUT) )
j3sq 0:3dbb22992c94 287 {
j3sq 0:3dbb22992c94 288 /* Conditionally stall both control endpoints */
j3sq 0:3dbb22992c94 289 setEndpointStatus(EP0OUT, SIE_SES_CND_ST);
j3sq 0:3dbb22992c94 290 }
j3sq 0:3dbb22992c94 291 else
j3sq 0:3dbb22992c94 292 {
j3sq 0:3dbb22992c94 293 setEndpointStatus(endpoint, SIE_SES_ST);
j3sq 0:3dbb22992c94 294
j3sq 0:3dbb22992c94 295 /* Update stall state */
j3sq 0:3dbb22992c94 296 endpointStallState |= EP(endpoint);
j3sq 0:3dbb22992c94 297 }
j3sq 0:3dbb22992c94 298 }
j3sq 0:3dbb22992c94 299
j3sq 0:3dbb22992c94 300 void usbdc::unstallEndpoint(unsigned char endpoint)
j3sq 0:3dbb22992c94 301 {
j3sq 0:3dbb22992c94 302 /* Unstall an endpoint. The endpoint will also be reinitialised */
j3sq 0:3dbb22992c94 303 setEndpointStatus(endpoint, 0);
j3sq 0:3dbb22992c94 304
j3sq 0:3dbb22992c94 305 /* Update stall state */
j3sq 0:3dbb22992c94 306 endpointStallState &= ~EP(endpoint);
j3sq 0:3dbb22992c94 307 }
j3sq 0:3dbb22992c94 308
j3sq 0:3dbb22992c94 309 bool usbdc::getEndpointStallState(unsigned char endpoint)
j3sq 0:3dbb22992c94 310 {
j3sq 0:3dbb22992c94 311 /* Returns true if endpoint stalled */
j3sq 0:3dbb22992c94 312 return endpointStallState & EP(endpoint);
j3sq 0:3dbb22992c94 313 }
j3sq 0:3dbb22992c94 314
j3sq 0:3dbb22992c94 315 void usbdc::configureDevice(void)
j3sq 0:3dbb22992c94 316 {
j3sq 0:3dbb22992c94 317 /* SIE Configure device command */
j3sq 0:3dbb22992c94 318 SIECommand(SIE_CMD_CONFIGURE_DEVICE);
j3sq 0:3dbb22992c94 319 SIEWriteData(SIE_CONF_DEVICE);
j3sq 0:3dbb22992c94 320 }
j3sq 0:3dbb22992c94 321
j3sq 0:3dbb22992c94 322 void usbdc::unconfigureDevice(void)
j3sq 0:3dbb22992c94 323 {
j3sq 0:3dbb22992c94 324 /* SIE Configure device command */
j3sq 0:3dbb22992c94 325 SIECommand(SIE_CMD_CONFIGURE_DEVICE);
j3sq 0:3dbb22992c94 326 SIEWriteData(0);
j3sq 0:3dbb22992c94 327 }
j3sq 0:3dbb22992c94 328
j3sq 0:3dbb22992c94 329 unsigned long usbdc::endpointRead(unsigned char endpoint, unsigned char *buffer)
j3sq 0:3dbb22992c94 330 {
j3sq 0:3dbb22992c94 331 /* Read from an OUT endpoint */
j3sq 0:3dbb22992c94 332 unsigned long size;
j3sq 0:3dbb22992c94 333 unsigned long i;
j3sq 0:3dbb22992c94 334 unsigned long data;
j3sq 0:3dbb22992c94 335 unsigned char offset;
j3sq 0:3dbb22992c94 336
j3sq 0:3dbb22992c94 337 LPC_USB->USBCtrl = LOG_ENDPOINT(endpoint) | RD_EN;
j3sq 0:3dbb22992c94 338 while (!(LPC_USB->USBRxPLen & PKT_RDY));
j3sq 0:3dbb22992c94 339
j3sq 0:3dbb22992c94 340 size = LPC_USB->USBRxPLen & PKT_LNGTH_MASK;
j3sq 0:3dbb22992c94 341
j3sq 0:3dbb22992c94 342 offset = 0;
j3sq 0:3dbb22992c94 343
j3sq 0:3dbb22992c94 344 for (i=0; i<size; i++)
j3sq 0:3dbb22992c94 345 {
j3sq 0:3dbb22992c94 346 if (offset==0)
j3sq 0:3dbb22992c94 347 {
j3sq 0:3dbb22992c94 348 /* Fetch up to four bytes of data as a word */
j3sq 0:3dbb22992c94 349 data = LPC_USB->USBRxData;
j3sq 0:3dbb22992c94 350 }
j3sq 0:3dbb22992c94 351
j3sq 0:3dbb22992c94 352 /* extract a byte */
j3sq 0:3dbb22992c94 353 *buffer++ = data>>offset;
j3sq 0:3dbb22992c94 354
j3sq 0:3dbb22992c94 355 /* move on to the next byte */
j3sq 0:3dbb22992c94 356 offset = (offset + 8) % 32;
j3sq 0:3dbb22992c94 357 }
j3sq 0:3dbb22992c94 358
j3sq 0:3dbb22992c94 359 /* Clear RD_EN to cover zero length packet case */
j3sq 0:3dbb22992c94 360 LPC_USB->USBCtrl=0;
j3sq 0:3dbb22992c94 361
j3sq 0:3dbb22992c94 362 selectEndpoint(endpoint);
j3sq 0:3dbb22992c94 363 clearBuffer();
j3sq 0:3dbb22992c94 364
j3sq 0:3dbb22992c94 365 return size;
j3sq 0:3dbb22992c94 366 }
j3sq 0:3dbb22992c94 367
j3sq 0:3dbb22992c94 368 void usbdc::endpointWrite(unsigned char endpoint, unsigned char *buffer, unsigned long size)
j3sq 0:3dbb22992c94 369 {
j3sq 0:3dbb22992c94 370 /* Write to an IN endpoint */
j3sq 0:3dbb22992c94 371 unsigned long temp, data;
j3sq 0:3dbb22992c94 372 unsigned char offset;
j3sq 0:3dbb22992c94 373
j3sq 0:3dbb22992c94 374 LPC_USB->USBCtrl = LOG_ENDPOINT(endpoint) | WR_EN;
j3sq 0:3dbb22992c94 375
j3sq 0:3dbb22992c94 376 LPC_USB->USBTxPLen = size;
j3sq 0:3dbb22992c94 377 offset = 0;
j3sq 0:3dbb22992c94 378 data = 0;
j3sq 0:3dbb22992c94 379
j3sq 0:3dbb22992c94 380 if (size>0)
j3sq 0:3dbb22992c94 381 {
j3sq 0:3dbb22992c94 382 do {
j3sq 0:3dbb22992c94 383 /* Fetch next data byte into a word-sized temporary variable */
j3sq 0:3dbb22992c94 384 temp = *buffer++;
j3sq 0:3dbb22992c94 385
j3sq 0:3dbb22992c94 386 /* Add to current data word */
j3sq 0:3dbb22992c94 387 temp = temp << offset;
j3sq 0:3dbb22992c94 388 data = data | temp;
j3sq 0:3dbb22992c94 389
j3sq 0:3dbb22992c94 390 /* move on to the next byte */
j3sq 0:3dbb22992c94 391 offset = (offset + 8) % 32;
j3sq 0:3dbb22992c94 392 size--;
j3sq 0:3dbb22992c94 393
j3sq 0:3dbb22992c94 394 if ((offset==0) || (size==0))
j3sq 0:3dbb22992c94 395 {
j3sq 0:3dbb22992c94 396 /* Write the word to the endpoint */
j3sq 0:3dbb22992c94 397 LPC_USB->USBTxData = data;
j3sq 0:3dbb22992c94 398 data = 0;
j3sq 0:3dbb22992c94 399 }
j3sq 0:3dbb22992c94 400 } while (size>0);
j3sq 0:3dbb22992c94 401 }
j3sq 0:3dbb22992c94 402
j3sq 0:3dbb22992c94 403 /* Clear WR_EN to cover zero length packet case */
j3sq 0:3dbb22992c94 404 LPC_USB->USBCtrl=0;
j3sq 0:3dbb22992c94 405
j3sq 0:3dbb22992c94 406 selectEndpoint(endpoint);
j3sq 0:3dbb22992c94 407 validateBuffer();
j3sq 0:3dbb22992c94 408 }
j3sq 0:3dbb22992c94 409
j3sq 0:3dbb22992c94 410 void usbdc::enableEvents(void)
j3sq 0:3dbb22992c94 411 {
j3sq 0:3dbb22992c94 412 /* Enable interrupt sources */
j3sq 0:3dbb22992c94 413 LPC_USB->USBDevIntEn = EP_SLOW | DEV_STAT;
j3sq 0:3dbb22992c94 414 }
j3sq 0:3dbb22992c94 415
j3sq 0:3dbb22992c94 416 void usbdc::disableEvents(void)
j3sq 0:3dbb22992c94 417 {
j3sq 0:3dbb22992c94 418 /* Disable interrupt sources */
j3sq 0:3dbb22992c94 419 LPC_USB->USBDevIntClr = EP_SLOW | DEV_STAT;
j3sq 0:3dbb22992c94 420 }
j3sq 0:3dbb22992c94 421
j3sq 0:3dbb22992c94 422 void usbdc::usbisr(void)
j3sq 0:3dbb22992c94 423 {
j3sq 0:3dbb22992c94 424 unsigned char devStat;
j3sq 0:3dbb22992c94 425
j3sq 0:3dbb22992c94 426 if (LPC_USB->USBDevIntSt & FRAME)
j3sq 0:3dbb22992c94 427 {
j3sq 0:3dbb22992c94 428 /* Frame event */
j3sq 0:3dbb22992c94 429 deviceEventFrame();
j3sq 0:3dbb22992c94 430 /* Clear interrupt status flag */
j3sq 0:3dbb22992c94 431 LPC_USB->USBDevIntClr = FRAME;
j3sq 0:3dbb22992c94 432 }
j3sq 0:3dbb22992c94 433
j3sq 0:3dbb22992c94 434 if (LPC_USB->USBDevIntSt & DEV_STAT)
j3sq 0:3dbb22992c94 435 {
j3sq 0:3dbb22992c94 436 /* Device Status interrupt */
j3sq 0:3dbb22992c94 437 /* Must clear the interrupt status flag before reading the device status from the SIE */
j3sq 0:3dbb22992c94 438 LPC_USB->USBDevIntClr = DEV_STAT;
j3sq 0:3dbb22992c94 439
j3sq 0:3dbb22992c94 440 /* Read device status from SIE */
j3sq 0:3dbb22992c94 441 devStat = getDeviceStatus();
j3sq 0:3dbb22992c94 442
j3sq 0:3dbb22992c94 443 if (devStat & SIE_DS_RST)
j3sq 0:3dbb22992c94 444 {
j3sq 0:3dbb22992c94 445 /* Bus reset */
j3sq 0:3dbb22992c94 446 deviceEventReset();
j3sq 0:3dbb22992c94 447 }
j3sq 0:3dbb22992c94 448 }
j3sq 0:3dbb22992c94 449
j3sq 0:3dbb22992c94 450 if (LPC_USB->USBDevIntSt & EP_SLOW)
j3sq 0:3dbb22992c94 451 {
j3sq 0:3dbb22992c94 452 /* (Slow) Endpoint Interrupt */
j3sq 0:3dbb22992c94 453
j3sq 0:3dbb22992c94 454 /* Process each endpoint interrupt */
j3sq 0:3dbb22992c94 455 if (LPC_USB->USBEpIntSt & EP(EP0OUT))
j3sq 0:3dbb22992c94 456 {
j3sq 0:3dbb22992c94 457 if (selectEndpointClearInterrupt(EP0OUT) & SIE_SE_STP)
j3sq 0:3dbb22992c94 458 {
j3sq 0:3dbb22992c94 459 /* this is a setup packet */
j3sq 0:3dbb22992c94 460 endpointEventEP0Setup();
j3sq 0:3dbb22992c94 461 }
j3sq 0:3dbb22992c94 462 else
j3sq 0:3dbb22992c94 463 {
j3sq 0:3dbb22992c94 464 endpointEventEP0Out();
j3sq 0:3dbb22992c94 465 }
j3sq 0:3dbb22992c94 466 }
j3sq 0:3dbb22992c94 467
j3sq 0:3dbb22992c94 468 if (LPC_USB->USBEpIntSt & EP(EP0IN))
j3sq 0:3dbb22992c94 469 {
j3sq 0:3dbb22992c94 470 selectEndpointClearInterrupt(EP0IN);
j3sq 0:3dbb22992c94 471 endpointEventEP0In();
j3sq 0:3dbb22992c94 472 }
j3sq 0:3dbb22992c94 473
j3sq 0:3dbb22992c94 474 if (LPC_USB->USBEpIntSt & EP(EP1OUT))
j3sq 0:3dbb22992c94 475 {
j3sq 0:3dbb22992c94 476 selectEndpointClearInterrupt(EP1OUT);
j3sq 0:3dbb22992c94 477 endpointEventEP1Out();
j3sq 0:3dbb22992c94 478 }
j3sq 0:3dbb22992c94 479
j3sq 0:3dbb22992c94 480 if (LPC_USB->USBEpIntSt & EP(EP1IN))
j3sq 0:3dbb22992c94 481 {
j3sq 0:3dbb22992c94 482 selectEndpointClearInterrupt(EP1IN);
j3sq 0:3dbb22992c94 483 endpointEventEP1In();
j3sq 0:3dbb22992c94 484 }
j3sq 0:3dbb22992c94 485
j3sq 0:3dbb22992c94 486 if (LPC_USB->USBEpIntSt & EP(EP2OUT))
j3sq 0:3dbb22992c94 487 {
j3sq 0:3dbb22992c94 488 selectEndpointClearInterrupt(EP2OUT);
j3sq 0:3dbb22992c94 489 endpointEventEP2Out();
j3sq 0:3dbb22992c94 490 }
j3sq 0:3dbb22992c94 491
j3sq 0:3dbb22992c94 492 if (LPC_USB->USBEpIntSt & EP(EP2IN))
j3sq 0:3dbb22992c94 493 {
j3sq 0:3dbb22992c94 494 selectEndpointClearInterrupt(EP2IN);
j3sq 0:3dbb22992c94 495 endpointEventEP2In();
j3sq 0:3dbb22992c94 496 }
j3sq 0:3dbb22992c94 497
j3sq 0:3dbb22992c94 498 /* Clear interrupt status flag */
j3sq 0:3dbb22992c94 499 /* EP_SLOW and EP_FAST interrupt bits should be cleared after the corresponding endpoint interrupts are cleared. */
j3sq 0:3dbb22992c94 500 LPC_USB->USBDevIntClr = EP_SLOW;
j3sq 0:3dbb22992c94 501 }
j3sq 0:3dbb22992c94 502 }
j3sq 0:3dbb22992c94 503
j3sq 0:3dbb22992c94 504
j3sq 0:3dbb22992c94 505 void usbdc::_usbisr(void)
j3sq 0:3dbb22992c94 506 {
j3sq 0:3dbb22992c94 507 instance->usbisr();
j3sq 0:3dbb22992c94 508 }
j3sq 0:3dbb22992c94 509
j3sq 0:3dbb22992c94 510 void usbdc::deviceEventReset(void)
j3sq 0:3dbb22992c94 511 {
j3sq 0:3dbb22992c94 512 }
j3sq 0:3dbb22992c94 513
j3sq 0:3dbb22992c94 514 void usbdc::deviceEventFrame(void)
j3sq 0:3dbb22992c94 515 {
j3sq 0:3dbb22992c94 516 }
j3sq 0:3dbb22992c94 517
j3sq 0:3dbb22992c94 518 void usbdc::endpointEventEP0Setup(void)
j3sq 0:3dbb22992c94 519 {
j3sq 0:3dbb22992c94 520 }
j3sq 0:3dbb22992c94 521
j3sq 0:3dbb22992c94 522 void usbdc::endpointEventEP0In(void)
j3sq 0:3dbb22992c94 523 {
j3sq 0:3dbb22992c94 524 }
j3sq 0:3dbb22992c94 525
j3sq 0:3dbb22992c94 526 void usbdc::endpointEventEP0Out(void)
j3sq 0:3dbb22992c94 527 {
j3sq 0:3dbb22992c94 528 }
j3sq 0:3dbb22992c94 529
j3sq 0:3dbb22992c94 530 void usbdc::endpointEventEP1In(void)
j3sq 0:3dbb22992c94 531 {
j3sq 0:3dbb22992c94 532 }
j3sq 0:3dbb22992c94 533
j3sq 0:3dbb22992c94 534 void usbdc::endpointEventEP1Out(void)
j3sq 0:3dbb22992c94 535 {
j3sq 0:3dbb22992c94 536 }
j3sq 0:3dbb22992c94 537
j3sq 0:3dbb22992c94 538 void usbdc::endpointEventEP2In(void)
j3sq 0:3dbb22992c94 539 {
j3sq 0:3dbb22992c94 540 }
j3sq 0:3dbb22992c94 541
j3sq 0:3dbb22992c94 542 void usbdc::endpointEventEP2Out(void)
j3sq 0:3dbb22992c94 543 {
j3sq 0:3dbb22992c94 544 }