Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of USBMIDI by
usbcore.c
00001 /* @license The MIT License 00002 * Copyright (c) 2011 mux, simon 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a copy 00005 * of this software and associated documentation files (the "Software"), to deal 00006 * in the Software without restriction, including without limitation the rights 00007 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00008 * copies of the Software, and to permit persons to whom the Software is 00009 * furnished to do so, subject to the following conditions: 00010 * 00011 * The above copyright notice and this permission notice shall be included in 00012 * all copies or substantial portions of the Software. 00013 * 00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00015 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00017 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00019 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00020 * THE SOFTWARE. 00021 */ 00022 00023 #include "usbcore.h" 00024 00025 #include "mbed.h" 00026 00027 // Serial Interface Engine 00028 #define SIE_SET_ADDR (0xD0) 00029 #define SIE_SET_STATUS (0xFE) 00030 #define SIE_GET_STATUS (0xFE) 00031 #define SIE_SET_MODE (0xF3) 00032 #define SIE_CLR_BUFFER (0xF2) 00033 #define SIE_VAL_BUFFER (0xFA) 00034 #define SIE_SEL_EP (0x00) 00035 #define SIE_SEL_CLR_EP (0x28) 00036 #define SIE_SET_EP_STAT (0x40) 00037 #define SIE_READ_ERROR (0xFB) 00038 #define SIE_CONFIG_DEVICE (0xD8) 00039 00040 // EP status 00041 #define EP_FE (1<<0) // Full/Empty 00042 #define EP_ST (1<<1) // Stalled endpoint 00043 #define EP_STP (1<<2) // Setup packet 00044 #define EP_PO (1<<3) // packet overwritten 00045 #define EP_EPN (1<<4) // EP NAKed 00046 #define B_1_FULL (1<<5) // buffer 1 status 00047 #define B_2_FULL (1<<6) // buffer 2 status 00048 00049 // USB device interrupts 00050 #define DEV_FRAME (1<<0) 00051 #define EP_FAST (1<<1) 00052 #define EP_SLOW (1<<2) 00053 #define DEV_STAT (1<<3) 00054 #define RxENDPKT (1<<6) 00055 #define TxENDPKT (1<<7) 00056 #define EP_RLZED (1<<8) 00057 #define CCEMPTY (0x10) 00058 #define CDFULL (0x20) 00059 00060 // USB device status bits 00061 #define STAT_CON (1<<0) 00062 #define STAT_CON_CH (1<<1) 00063 #define STAT_SUS (1<<2) 00064 #define STAT_SUS_CH (1<<3) 00065 #define STAT_RST (1<<4) 00066 00067 // end points interrupts 00068 #define EP0RX_INT (1<<0) 00069 #define EP0TX_INT (1<<1) 00070 #define EP1RX_INT (1<<2) 00071 #define EP1TX_INT (1<<3) 00072 #define EP2RX_INT (1<<4) 00073 #define EP2TX_INT (1<<5) 00074 00075 // USB control register 00076 #define RD_EN (1<<0) 00077 #define WR_EN (1<<1) 00078 #define PKT_RDY (1<<11) 00079 #define LOG_ENDPOINT(ep) ((ep>>1)<<2) 00080 00081 // configure state 00082 static int configured = 0; 00083 00084 // USB interrupt handler 00085 void USB_IRQHandler(void); 00086 00087 // Serial Interface Engine functions 00088 void sie_command(uint32_t code) { 00089 LPC_USB->USBDevIntClr = CCEMPTY; // clear CCEMPTY 00090 LPC_USB->USBCmdCode = ((code<<16)|(0x05<<8)); // CMD_PHASE=Command 00091 while (!(LPC_USB->USBDevIntSt & CCEMPTY)); // wait for CCEMPTY 00092 } 00093 00094 void sie_write(uint32_t data) { 00095 LPC_USB->USBDevIntClr = CCEMPTY; // clear CCEMPTY 00096 LPC_USB->USBCmdCode = ((data<<16)|(0x01<<8)); // CMD_PHASE=Write 00097 while (!(LPC_USB->USBDevIntSt & CCEMPTY)); // wait for CCEMPTY 00098 } 00099 00100 uint8_t sie_read(uint32_t code) { 00101 LPC_USB->USBDevIntClr = CDFULL; // clear CCEMPTY 00102 LPC_USB->USBCmdCode = ((code<<16)|(0x02<<8)); // CMD_PHASE=Read 00103 while (!(LPC_USB->USBDevIntSt & CDFULL)); // wait for CDFULL 00104 return (uint8_t) LPC_USB->USBCmdData; 00105 00106 } 00107 00108 // end point functions 00109 void ep_realize(uint8_t ep, uint32_t size) { 00110 LPC_USB->USBDevIntClr = EP_RLZED; // clear EP_RLZED 00111 LPC_USB->USBReEp |= (1<<ep); 00112 LPC_USB->USBEpInd = ep; // set USBEpIn 00113 LPC_USB->USBMaxPSize = size; // writing to EPn pointed to by USBEpInd 00114 while (!(LPC_USB->USBDevIntSt & EP_RLZED)); // wait for EP_RLZED 00115 LPC_USB->USBDevIntClr = EP_RLZED; // clear EP_RLZED 00116 } 00117 00118 void ep_stall(uint8_t ep) { 00119 sie_command(SIE_SET_EP_STAT+ep); 00120 sie_write(1); 00121 } 00122 00123 void ep_unstall(uint8_t ep) { 00124 sie_command(SIE_SET_EP_STAT+ep); 00125 sie_write(0); 00126 } 00127 00128 // initializes a pointer to the endpoint buffer 00129 uint8_t ep_select(uint8_t ep) { 00130 sie_command(SIE_SEL_EP+ep); 00131 return sie_read(SIE_SEL_EP+ep); 00132 } 00133 00134 uint8_t ep_select_clear(uint8_t ep) { 00135 LPC_USB->USBEpIntClr |= ep; // clear ep interrupt 00136 while (!(LPC_USB->USBDevIntSt & CDFULL)); // wait for cmd finish 00137 return LPC_USB->USBCmdData; 00138 } 00139 00140 int ep_readable(uint8_t ep) { 00141 uint8_t st = ep_select(ep); 00142 return (st & EP_FE); 00143 } 00144 00145 int ep_writable(uint8_t ep) { 00146 uint8_t st = ep_select(ep); 00147 return !(st & EP_FE); 00148 } 00149 00150 int ep_read(uint8_t ep, uint8_t *tbuf) { 00151 uint32_t *buf = (uint32_t*) tbuf; 00152 LPC_USB->USBCtrl = LOG_ENDPOINT(ep)|RD_EN; // RD_EN bit and LOG_ENDPOINT 00153 while (!(LPC_USB->USBRxPLen & PKT_RDY)); // wait for packet to be fetched 00154 int len = LPC_USB->USBRxPLen & 0x3FF; // read and mask packet length 00155 while (!(LPC_USB->USBDevIntSt & RxENDPKT)) { 00156 *buf++ = LPC_USB->USBRxData; 00157 } 00158 LPC_USB->USBCtrl = 0; 00159 LPC_USB->USBDevIntClr |= RxENDPKT; 00160 sie_command(SIE_SEL_EP+ep); // select endpoint 00161 sie_command(SIE_CLR_BUFFER); // clear RX buffer 00162 return len; 00163 } 00164 00165 void ep_write(uint8_t ep, uint8_t *tbuf, uint32_t len) { 00166 uint32_t *buf = (uint32_t*) tbuf; 00167 LPC_USB->USBCtrl = LOG_ENDPOINT(ep)|WR_EN; // RD_EN bit and LOG_ENDPOINT 00168 LPC_USB->USBTxPLen |= (len & 0x3FF); // write and mask packet length 00169 while (!(LPC_USB->USBDevIntSt & TxENDPKT)) { 00170 LPC_USB->USBTxData = *buf++; 00171 } 00172 LPC_USB->USBCtrl = 0; 00173 LPC_USB->USBDevIntClr |= TxENDPKT; 00174 sie_command(SIE_SEL_EP+ep); // select endpoint 00175 sie_command(SIE_VAL_BUFFER); // validate TX buffer 00176 } 00177 00178 // USB device controller initialization 00179 void usb_init() { 00180 // USB D+/D- pinsel functions 00181 LPC_PINCON->PINSEL1 &= 0xC3FFFFFF; 00182 LPC_PINCON->PINSEL1 |= 0x14000000; 00183 00184 #if USB_UP_DEBUG 00185 // USB_UP_LED pinsel function 00186 LPC_PINCON->PINSEL3 &= 0xFFFFFFCF; 00187 LPC_PINCON->PINSEL3 |= 0x00000010; 00188 #endif 00189 00190 // USB connect pinsel function 00191 LPC_PINCON->PINSEL4 &= 0xFFFCFFFF; 00192 LPC_PINCON->PINSEL4 |= 0x00040000; 00193 LPC_SC->PCONP |= (1UL<<31); // enable the USB controller 00194 LPC_USB->USBClkCtrl |= ((1<<1)|(1<<4)); // enable the AHB and DEV clocks 00195 while ((LPC_USB->USBClkSt & 0x12) != 0x12); // wait for the clocks to init 00196 00197 NVIC_SetVector(USB_IRQn, (uint32_t)&USB_IRQHandler); 00198 NVIC_EnableIRQ(USB_IRQn); // enable USB interrupts 00199 00200 usb_reset(); 00201 usb_set_address(0); // default address 00202 } 00203 00204 void usb_reset() { 00205 ep_realize(EP0, MAX_EP0_PSIZE); 00206 ep_realize(EP1, MAX_EP0_PSIZE); 00207 LPC_USB->USBEpIntClr = 0xFFFFFFFF; // clear end points interrupts 00208 LPC_USB->USBEpIntEn = 0xFFFFFFFF; // enable end points interrupts 00209 LPC_USB->USBEpIntPri = 0x0; // route to EP_SLOW 00210 LPC_USB->USBDevIntClr = 0xFFFFFFFF; // clear USB device interrupts 00211 LPC_USB->USBDevIntEn = (EP_SLOW|DEV_STAT); // enable USB device interrupts 00212 } 00213 00214 void usb_configure(uint8_t conf) { 00215 sie_command(SIE_CONFIG_DEVICE); 00216 sie_write(conf); 00217 configured = 1; 00218 } 00219 00220 int usb_configured() { 00221 return configured; 00222 } 00223 00224 void usb_set_address(uint8_t addr) { 00225 sie_command(SIE_SET_ADDR); 00226 sie_write(addr|0x80); // DEV_EN = 1 00227 } 00228 00229 uint8_t usb_get_status() { 00230 sie_command(SIE_GET_STATUS); 00231 return sie_read(SIE_GET_STATUS); 00232 } 00233 00234 void usb_connect() { 00235 sie_command(SIE_GET_STATUS); // read current status 00236 uint8_t st = sie_read(SIE_GET_STATUS); 00237 00238 sie_command(SIE_SET_STATUS); // set STAT_CON bit 00239 sie_write(st|STAT_CON); 00240 } 00241 00242 void USB_IRQHandler(void) { 00243 if (LPC_USB->USBDevIntSt & DEV_STAT) { // DEV_STAT interrupt 00244 LPC_USB->USBDevIntClr |= DEV_STAT; 00245 if (usb_get_status() & STAT_RST) { // bus reset 00246 usb_reset(); 00247 } 00248 return; 00249 } 00250 00251 if (LPC_USB->USBDevIntSt & EP_SLOW) { // EP_SLOW interrupt 00252 if (LPC_USB->USBEpIntSt & EP0RX_INT) { 00253 if (ep_select_clear(EP0RX_INT) & EP_STP) { // setup transfer 00254 ep0_setup(); 00255 } else { 00256 ep0_out(); 00257 } 00258 } 00259 00260 if (LPC_USB->USBEpIntSt & EP0TX_INT) { 00261 ep_select_clear(EP0TX_INT); 00262 ep0_in(); 00263 } 00264 00265 if (LPC_USB->USBEpIntSt & EP2RX_INT) { 00266 ep_select_clear(EP2TX_INT); 00267 ep2_out(); 00268 } 00269 00270 if (LPC_USB->USBEpIntSt & EP2TX_INT) { 00271 ep_select_clear(EP2TX_INT); 00272 ep2_in(); 00273 } 00274 00275 // EP_SLOW should be cleared after clearing EPs interrupts 00276 LPC_USB->USBDevIntClr |= EP_SLOW; 00277 } 00278 }
Generated on Tue Jul 12 2022 23:30:37 by
