USB device stack

Dependents:   mbed-mX-USB-TEST1 USBMSD_SD_HID_HelloWorld HidTest MIDI_usb_bridge ... more

Legacy Warning

This is an mbed 2 library. To learn more about mbed OS 5, visit the docs.

Pull requests against this repository are no longer supported. Please raise against mbed OS 5 as documented above.

Committer:
Kojto
Date:
Thu Jul 27 12:14:04 2017 +0100
Revision:
71:53949e6131f6
Update libraries

Fixes the previous commmit, as some devices were not copied. USBDevice contains
now targets directory with all targets implementations

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Kojto 71:53949e6131f6 1 /* Copyright (c) 2010-2011 mbed.org, MIT License
Kojto 71:53949e6131f6 2 *
Kojto 71:53949e6131f6 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
Kojto 71:53949e6131f6 4 * and associated documentation files (the "Software"), to deal in the Software without
Kojto 71:53949e6131f6 5 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
Kojto 71:53949e6131f6 6 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
Kojto 71:53949e6131f6 7 * Software is furnished to do so, subject to the following conditions:
Kojto 71:53949e6131f6 8 *
Kojto 71:53949e6131f6 9 * The above copyright notice and this permission notice shall be included in all copies or
Kojto 71:53949e6131f6 10 * substantial portions of the Software.
Kojto 71:53949e6131f6 11 *
Kojto 71:53949e6131f6 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
Kojto 71:53949e6131f6 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Kojto 71:53949e6131f6 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
Kojto 71:53949e6131f6 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Kojto 71:53949e6131f6 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Kojto 71:53949e6131f6 17 */
Kojto 71:53949e6131f6 18
Kojto 71:53949e6131f6 19 #if defined(TARGET_KL25Z) | defined(TARGET_KL43Z) | defined(TARGET_KL46Z) | defined(TARGET_K20D50M) | defined(TARGET_K64F) | defined(TARGET_K22F) | defined(TARGET_TEENSY3_1)
Kojto 71:53949e6131f6 20
Kojto 71:53949e6131f6 21 #if defined(TARGET_KSDK2_MCUS)
Kojto 71:53949e6131f6 22 #include "fsl_common.h"
Kojto 71:53949e6131f6 23 #endif
Kojto 71:53949e6131f6 24 #include "USBHAL.h"
Kojto 71:53949e6131f6 25
Kojto 71:53949e6131f6 26 USBHAL * USBHAL::instance;
Kojto 71:53949e6131f6 27
Kojto 71:53949e6131f6 28 static volatile int epComplete = 0;
Kojto 71:53949e6131f6 29
Kojto 71:53949e6131f6 30 // Convert physical endpoint number to register bit
Kojto 71:53949e6131f6 31 #define EP(endpoint) (1<<(endpoint))
Kojto 71:53949e6131f6 32
Kojto 71:53949e6131f6 33 // Convert physical to logical
Kojto 71:53949e6131f6 34 #define PHY_TO_LOG(endpoint) ((endpoint)>>1)
Kojto 71:53949e6131f6 35
Kojto 71:53949e6131f6 36 // Get endpoint direction
Kojto 71:53949e6131f6 37 #define IN_EP(endpoint) ((endpoint) & 1U ? true : false)
Kojto 71:53949e6131f6 38 #define OUT_EP(endpoint) ((endpoint) & 1U ? false : true)
Kojto 71:53949e6131f6 39
Kojto 71:53949e6131f6 40 #define BD_OWN_MASK (1<<7)
Kojto 71:53949e6131f6 41 #define BD_DATA01_MASK (1<<6)
Kojto 71:53949e6131f6 42 #define BD_KEEP_MASK (1<<5)
Kojto 71:53949e6131f6 43 #define BD_NINC_MASK (1<<4)
Kojto 71:53949e6131f6 44 #define BD_DTS_MASK (1<<3)
Kojto 71:53949e6131f6 45 #define BD_STALL_MASK (1<<2)
Kojto 71:53949e6131f6 46
Kojto 71:53949e6131f6 47 #define TX 1
Kojto 71:53949e6131f6 48 #define RX 0
Kojto 71:53949e6131f6 49 #define ODD 0
Kojto 71:53949e6131f6 50 #define EVEN 1
Kojto 71:53949e6131f6 51 // this macro waits a physical endpoint number
Kojto 71:53949e6131f6 52 #define EP_BDT_IDX(ep, dir, odd) (((ep * 4) + (2 * dir) + (1 * odd)))
Kojto 71:53949e6131f6 53
Kojto 71:53949e6131f6 54 #define SETUP_TOKEN 0x0D
Kojto 71:53949e6131f6 55 #define IN_TOKEN 0x09
Kojto 71:53949e6131f6 56 #define OUT_TOKEN 0x01
Kojto 71:53949e6131f6 57 #define TOK_PID(idx) ((bdt[idx].info >> 2) & 0x0F)
Kojto 71:53949e6131f6 58
Kojto 71:53949e6131f6 59 // for each endpt: 8 bytes
Kojto 71:53949e6131f6 60 typedef struct BDT {
Kojto 71:53949e6131f6 61 uint8_t info; // BD[0:7]
Kojto 71:53949e6131f6 62 uint8_t dummy; // RSVD: BD[8:15]
Kojto 71:53949e6131f6 63 uint16_t byte_count; // BD[16:32]
Kojto 71:53949e6131f6 64 uint32_t address; // Addr
Kojto 71:53949e6131f6 65 } BDT;
Kojto 71:53949e6131f6 66
Kojto 71:53949e6131f6 67 // there are:
Kojto 71:53949e6131f6 68 // * 4 bidirectionnal endpt -> 8 physical endpt
Kojto 71:53949e6131f6 69 // * as there are ODD and EVEN buffer -> 8*2 bdt
Kojto 71:53949e6131f6 70 MBED_ALIGN(512) BDT bdt[NUMBER_OF_PHYSICAL_ENDPOINTS * 2]; // 512 bytes aligned!
Kojto 71:53949e6131f6 71
Kojto 71:53949e6131f6 72 uint8_t * endpoint_buffer[NUMBER_OF_PHYSICAL_ENDPOINTS * 2];
Kojto 71:53949e6131f6 73
Kojto 71:53949e6131f6 74 static uint8_t set_addr = 0;
Kojto 71:53949e6131f6 75 static uint8_t addr = 0;
Kojto 71:53949e6131f6 76
Kojto 71:53949e6131f6 77 static uint32_t Data1 = 0x55555555;
Kojto 71:53949e6131f6 78
Kojto 71:53949e6131f6 79 static uint32_t frameNumber() {
Kojto 71:53949e6131f6 80 return((USB0->FRMNUML | (USB0->FRMNUMH << 8)) & 0x07FF);
Kojto 71:53949e6131f6 81 }
Kojto 71:53949e6131f6 82
Kojto 71:53949e6131f6 83 uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) {
Kojto 71:53949e6131f6 84 return 0;
Kojto 71:53949e6131f6 85 }
Kojto 71:53949e6131f6 86
Kojto 71:53949e6131f6 87 USBHAL::USBHAL(void) {
Kojto 71:53949e6131f6 88 // Disable IRQ
Kojto 71:53949e6131f6 89 NVIC_DisableIRQ(USB0_IRQn);
Kojto 71:53949e6131f6 90
Kojto 71:53949e6131f6 91 #if (defined(FSL_FEATURE_SOC_MPU_COUNT) && (FSL_FEATURE_SOC_MPU_COUNT > 0U))
Kojto 71:53949e6131f6 92 MPU->CESR=0;
Kojto 71:53949e6131f6 93 #endif
Kojto 71:53949e6131f6 94 // fill in callback array
Kojto 71:53949e6131f6 95 epCallback[0] = &USBHAL::EP1_OUT_callback;
Kojto 71:53949e6131f6 96 epCallback[1] = &USBHAL::EP1_IN_callback;
Kojto 71:53949e6131f6 97 epCallback[2] = &USBHAL::EP2_OUT_callback;
Kojto 71:53949e6131f6 98 epCallback[3] = &USBHAL::EP2_IN_callback;
Kojto 71:53949e6131f6 99 epCallback[4] = &USBHAL::EP3_OUT_callback;
Kojto 71:53949e6131f6 100 epCallback[5] = &USBHAL::EP3_IN_callback;
Kojto 71:53949e6131f6 101 epCallback[6] = &USBHAL::EP4_OUT_callback;
Kojto 71:53949e6131f6 102 epCallback[7] = &USBHAL::EP4_IN_callback;
Kojto 71:53949e6131f6 103
Kojto 71:53949e6131f6 104 #if defined(TARGET_KL43Z) || defined(TARGET_K22F) || defined(TARGET_K64F)
Kojto 71:53949e6131f6 105 // enable USBFS clock
Kojto 71:53949e6131f6 106 CLOCK_EnableUsbfs0Clock(kCLOCK_UsbSrcIrc48M, 48000000U);
Kojto 71:53949e6131f6 107 #else
Kojto 71:53949e6131f6 108 // choose usb src as PLL
Kojto 71:53949e6131f6 109 SIM->SOPT2 &= ~SIM_SOPT2_PLLFLLSEL_MASK;
Kojto 71:53949e6131f6 110 SIM->SOPT2 |= (SIM_SOPT2_USBSRC_MASK | (1 << SIM_SOPT2_PLLFLLSEL_SHIFT));
Kojto 71:53949e6131f6 111
Kojto 71:53949e6131f6 112 // enable OTG clock
Kojto 71:53949e6131f6 113 SIM->SCGC4 |= SIM_SCGC4_USBOTG_MASK;
Kojto 71:53949e6131f6 114 #endif
Kojto 71:53949e6131f6 115
Kojto 71:53949e6131f6 116 // Attach IRQ
Kojto 71:53949e6131f6 117 instance = this;
Kojto 71:53949e6131f6 118 NVIC_SetVector(USB0_IRQn, (uint32_t)&_usbisr);
Kojto 71:53949e6131f6 119 NVIC_EnableIRQ(USB0_IRQn);
Kojto 71:53949e6131f6 120
Kojto 71:53949e6131f6 121 // USB Module Configuration
Kojto 71:53949e6131f6 122 // Set BDT Base Register
Kojto 71:53949e6131f6 123 USB0->BDTPAGE1 = (uint8_t)((uint32_t)bdt>>8);
Kojto 71:53949e6131f6 124 USB0->BDTPAGE2 = (uint8_t)((uint32_t)bdt>>16);
Kojto 71:53949e6131f6 125 USB0->BDTPAGE3 = (uint8_t)((uint32_t)bdt>>24);
Kojto 71:53949e6131f6 126
Kojto 71:53949e6131f6 127 // Clear interrupt flag
Kojto 71:53949e6131f6 128 USB0->ISTAT = 0xff;
Kojto 71:53949e6131f6 129
Kojto 71:53949e6131f6 130 // USB Interrupt Enablers
Kojto 71:53949e6131f6 131 USB0->INTEN |= USB_INTEN_TOKDNEEN_MASK |
Kojto 71:53949e6131f6 132 USB_INTEN_SOFTOKEN_MASK |
Kojto 71:53949e6131f6 133 USB_INTEN_ERROREN_MASK |
Kojto 71:53949e6131f6 134 USB_INTEN_USBRSTEN_MASK;
Kojto 71:53949e6131f6 135
Kojto 71:53949e6131f6 136 // Disable weak pull downs
Kojto 71:53949e6131f6 137 USB0->USBCTRL &= ~(USB_USBCTRL_PDE_MASK | USB_USBCTRL_SUSP_MASK);
Kojto 71:53949e6131f6 138
Kojto 71:53949e6131f6 139 USB0->USBTRC0 |= 0x40;
Kojto 71:53949e6131f6 140
Kojto 71:53949e6131f6 141 /* Allocate control endpoint buffers */
Kojto 71:53949e6131f6 142 endpoint_buffer[EP_BDT_IDX(0, TX, ODD)] = (uint8_t *)malloc(MAX_PACKET_SIZE_EP0);
Kojto 71:53949e6131f6 143 endpoint_buffer[EP_BDT_IDX(0, RX, ODD)] = (uint8_t *)malloc(MAX_PACKET_SIZE_EP0);
Kojto 71:53949e6131f6 144 }
Kojto 71:53949e6131f6 145
Kojto 71:53949e6131f6 146 USBHAL::~USBHAL(void) { }
Kojto 71:53949e6131f6 147
Kojto 71:53949e6131f6 148 void USBHAL::connect(void) {
Kojto 71:53949e6131f6 149 // enable USB
Kojto 71:53949e6131f6 150 USB0->CTL |= USB_CTL_USBENSOFEN_MASK;
Kojto 71:53949e6131f6 151 // Pull up enable
Kojto 71:53949e6131f6 152 USB0->CONTROL |= USB_CONTROL_DPPULLUPNONOTG_MASK;
Kojto 71:53949e6131f6 153
Kojto 71:53949e6131f6 154 // Allocate endpoint buffers; do allocate control endpoint buffers
Kojto 71:53949e6131f6 155 for (int i = 4; i < (NUMBER_OF_PHYSICAL_ENDPOINTS * 2); i++) {
Kojto 71:53949e6131f6 156 if ((i == EPISO_OUT) || (i == EPISO_IN)) {
Kojto 71:53949e6131f6 157 endpoint_buffer[i] = (uint8_t *)malloc(MAX_PACKET_SIZE_EPISO);
Kojto 71:53949e6131f6 158 } else {
Kojto 71:53949e6131f6 159 endpoint_buffer[i] = (uint8_t *)malloc(MAX_PACKET_SIZE_EPBULK);
Kojto 71:53949e6131f6 160 }
Kojto 71:53949e6131f6 161 }
Kojto 71:53949e6131f6 162 }
Kojto 71:53949e6131f6 163
Kojto 71:53949e6131f6 164 void USBHAL::disconnect(void) {
Kojto 71:53949e6131f6 165 // disable USB
Kojto 71:53949e6131f6 166 USB0->CTL &= ~USB_CTL_USBENSOFEN_MASK;
Kojto 71:53949e6131f6 167 // Pull up disable
Kojto 71:53949e6131f6 168 USB0->CONTROL &= ~USB_CONTROL_DPPULLUPNONOTG_MASK;
Kojto 71:53949e6131f6 169
Kojto 71:53949e6131f6 170 //Free buffers if required; do not free the control endpoint buffers
Kojto 71:53949e6131f6 171 for (int i = 4; i < (NUMBER_OF_PHYSICAL_ENDPOINTS * 2); i++) {
Kojto 71:53949e6131f6 172 free(endpoint_buffer[i]);
Kojto 71:53949e6131f6 173 endpoint_buffer[i] = NULL;
Kojto 71:53949e6131f6 174 }
Kojto 71:53949e6131f6 175 }
Kojto 71:53949e6131f6 176
Kojto 71:53949e6131f6 177 void USBHAL::configureDevice(void) {
Kojto 71:53949e6131f6 178 // not needed
Kojto 71:53949e6131f6 179 }
Kojto 71:53949e6131f6 180
Kojto 71:53949e6131f6 181 void USBHAL::unconfigureDevice(void) {
Kojto 71:53949e6131f6 182 // not needed
Kojto 71:53949e6131f6 183 }
Kojto 71:53949e6131f6 184
Kojto 71:53949e6131f6 185 void USBHAL::setAddress(uint8_t address) {
Kojto 71:53949e6131f6 186 // we don't set the address now otherwise the usb controller does not ack
Kojto 71:53949e6131f6 187 // we set a flag instead
Kojto 71:53949e6131f6 188 // see usbisr when an IN token is received
Kojto 71:53949e6131f6 189 set_addr = 1;
Kojto 71:53949e6131f6 190 addr = address;
Kojto 71:53949e6131f6 191 }
Kojto 71:53949e6131f6 192
Kojto 71:53949e6131f6 193 bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) {
Kojto 71:53949e6131f6 194 uint32_t handshake_flag = 0;
Kojto 71:53949e6131f6 195 uint8_t * buf;
Kojto 71:53949e6131f6 196
Kojto 71:53949e6131f6 197 if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) {
Kojto 71:53949e6131f6 198 return false;
Kojto 71:53949e6131f6 199 }
Kojto 71:53949e6131f6 200
Kojto 71:53949e6131f6 201 uint32_t log_endpoint = PHY_TO_LOG(endpoint);
Kojto 71:53949e6131f6 202
Kojto 71:53949e6131f6 203 if ((flags & ISOCHRONOUS) == 0) {
Kojto 71:53949e6131f6 204 handshake_flag = USB_ENDPT_EPHSHK_MASK;
Kojto 71:53949e6131f6 205 }
Kojto 71:53949e6131f6 206
Kojto 71:53949e6131f6 207 if (IN_EP(endpoint)) {
Kojto 71:53949e6131f6 208 buf = &endpoint_buffer[EP_BDT_IDX(log_endpoint, TX, ODD)][0];
Kojto 71:53949e6131f6 209 } else {
Kojto 71:53949e6131f6 210 buf = &endpoint_buffer[EP_BDT_IDX(log_endpoint, RX, ODD)][0];
Kojto 71:53949e6131f6 211 }
Kojto 71:53949e6131f6 212
Kojto 71:53949e6131f6 213 // IN endpt -> device to host (TX)
Kojto 71:53949e6131f6 214 if (IN_EP(endpoint)) {
Kojto 71:53949e6131f6 215 USB0->ENDPOINT[log_endpoint].ENDPT |= handshake_flag | // ep handshaking (not if iso endpoint)
Kojto 71:53949e6131f6 216 USB_ENDPT_EPTXEN_MASK; // en TX (IN) tran
Kojto 71:53949e6131f6 217 bdt[EP_BDT_IDX(log_endpoint, TX, ODD )].address = (uint32_t) buf;
Kojto 71:53949e6131f6 218 bdt[EP_BDT_IDX(log_endpoint, TX, EVEN)].address = 0;
Kojto 71:53949e6131f6 219 }
Kojto 71:53949e6131f6 220 // OUT endpt -> host to device (RX)
Kojto 71:53949e6131f6 221 else {
Kojto 71:53949e6131f6 222 USB0->ENDPOINT[log_endpoint].ENDPT |= handshake_flag | // ep handshaking (not if iso endpoint)
Kojto 71:53949e6131f6 223 USB_ENDPT_EPRXEN_MASK; // en RX (OUT) tran.
Kojto 71:53949e6131f6 224 bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].byte_count = maxPacket;
Kojto 71:53949e6131f6 225 bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].address = (uint32_t) buf;
Kojto 71:53949e6131f6 226 bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].info = BD_OWN_MASK | BD_DTS_MASK;
Kojto 71:53949e6131f6 227 bdt[EP_BDT_IDX(log_endpoint, RX, EVEN)].info = 0;
Kojto 71:53949e6131f6 228 }
Kojto 71:53949e6131f6 229
Kojto 71:53949e6131f6 230 Data1 |= (1 << endpoint);
Kojto 71:53949e6131f6 231
Kojto 71:53949e6131f6 232 return true;
Kojto 71:53949e6131f6 233 }
Kojto 71:53949e6131f6 234
Kojto 71:53949e6131f6 235 // read setup packet
Kojto 71:53949e6131f6 236 void USBHAL::EP0setup(uint8_t *buffer) {
Kojto 71:53949e6131f6 237 uint32_t sz;
Kojto 71:53949e6131f6 238 endpointReadResult(EP0OUT, buffer, &sz);
Kojto 71:53949e6131f6 239 }
Kojto 71:53949e6131f6 240
Kojto 71:53949e6131f6 241 void USBHAL::EP0readStage(void) {
Kojto 71:53949e6131f6 242 Data1 &= ~1UL; // set DATA0
Kojto 71:53949e6131f6 243 bdt[0].info = (BD_DTS_MASK | BD_OWN_MASK);
Kojto 71:53949e6131f6 244 }
Kojto 71:53949e6131f6 245
Kojto 71:53949e6131f6 246 void USBHAL::EP0read(void) {
Kojto 71:53949e6131f6 247 uint32_t idx = EP_BDT_IDX(PHY_TO_LOG(EP0OUT), RX, 0);
Kojto 71:53949e6131f6 248 bdt[idx].byte_count = MAX_PACKET_SIZE_EP0;
Kojto 71:53949e6131f6 249 }
Kojto 71:53949e6131f6 250
Kojto 71:53949e6131f6 251 uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
Kojto 71:53949e6131f6 252 uint32_t sz;
Kojto 71:53949e6131f6 253 endpointReadResult(EP0OUT, buffer, &sz);
Kojto 71:53949e6131f6 254 return sz;
Kojto 71:53949e6131f6 255 }
Kojto 71:53949e6131f6 256
Kojto 71:53949e6131f6 257 void USBHAL::EP0write(uint8_t *buffer, uint32_t size) {
Kojto 71:53949e6131f6 258 endpointWrite(EP0IN, buffer, size);
Kojto 71:53949e6131f6 259 }
Kojto 71:53949e6131f6 260
Kojto 71:53949e6131f6 261 void USBHAL::EP0getWriteResult(void) {
Kojto 71:53949e6131f6 262 }
Kojto 71:53949e6131f6 263
Kojto 71:53949e6131f6 264 void USBHAL::EP0stall(void) {
Kojto 71:53949e6131f6 265 stallEndpoint(EP0OUT);
Kojto 71:53949e6131f6 266 }
Kojto 71:53949e6131f6 267
Kojto 71:53949e6131f6 268 EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
Kojto 71:53949e6131f6 269 endpoint = PHY_TO_LOG(endpoint);
Kojto 71:53949e6131f6 270 uint32_t idx = EP_BDT_IDX(endpoint, RX, 0);
Kojto 71:53949e6131f6 271 bdt[idx].byte_count = maximumSize;
Kojto 71:53949e6131f6 272 return EP_PENDING;
Kojto 71:53949e6131f6 273 }
Kojto 71:53949e6131f6 274
Kojto 71:53949e6131f6 275 EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) {
Kojto 71:53949e6131f6 276 uint32_t n, sz, idx, setup = 0;
Kojto 71:53949e6131f6 277 uint8_t not_iso;
Kojto 71:53949e6131f6 278 uint8_t * ep_buf;
Kojto 71:53949e6131f6 279
Kojto 71:53949e6131f6 280 uint32_t log_endpoint = PHY_TO_LOG(endpoint);
Kojto 71:53949e6131f6 281
Kojto 71:53949e6131f6 282 if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) {
Kojto 71:53949e6131f6 283 return EP_INVALID;
Kojto 71:53949e6131f6 284 }
Kojto 71:53949e6131f6 285
Kojto 71:53949e6131f6 286 // if read on a IN endpoint -> error
Kojto 71:53949e6131f6 287 if (IN_EP(endpoint)) {
Kojto 71:53949e6131f6 288 return EP_INVALID;
Kojto 71:53949e6131f6 289 }
Kojto 71:53949e6131f6 290
Kojto 71:53949e6131f6 291 idx = EP_BDT_IDX(log_endpoint, RX, 0);
Kojto 71:53949e6131f6 292 sz = bdt[idx].byte_count;
Kojto 71:53949e6131f6 293 not_iso = USB0->ENDPOINT[log_endpoint].ENDPT & USB_ENDPT_EPHSHK_MASK;
Kojto 71:53949e6131f6 294
Kojto 71:53949e6131f6 295 //for isochronous endpoint, we don't wait an interrupt
Kojto 71:53949e6131f6 296 if ((log_endpoint != 0) && not_iso && !(epComplete & EP(endpoint))) {
Kojto 71:53949e6131f6 297 return EP_PENDING;
Kojto 71:53949e6131f6 298 }
Kojto 71:53949e6131f6 299
Kojto 71:53949e6131f6 300 if ((log_endpoint == 0) && (TOK_PID(idx) == SETUP_TOKEN)) {
Kojto 71:53949e6131f6 301 setup = 1;
Kojto 71:53949e6131f6 302 }
Kojto 71:53949e6131f6 303
Kojto 71:53949e6131f6 304 ep_buf = endpoint_buffer[idx];
Kojto 71:53949e6131f6 305
Kojto 71:53949e6131f6 306 for (n = 0; n < sz; n++) {
Kojto 71:53949e6131f6 307 buffer[n] = ep_buf[n];
Kojto 71:53949e6131f6 308 }
Kojto 71:53949e6131f6 309
Kojto 71:53949e6131f6 310 if (((Data1 >> endpoint) & 1) == ((bdt[idx].info >> 6) & 1)) {
Kojto 71:53949e6131f6 311 if (setup && (buffer[6] == 0)) // if no setup data stage,
Kojto 71:53949e6131f6 312 Data1 &= ~1UL; // set DATA0
Kojto 71:53949e6131f6 313 else
Kojto 71:53949e6131f6 314 Data1 ^= (1 << endpoint);
Kojto 71:53949e6131f6 315 }
Kojto 71:53949e6131f6 316
Kojto 71:53949e6131f6 317 if (((Data1 >> endpoint) & 1)) {
Kojto 71:53949e6131f6 318 bdt[idx].info = BD_DTS_MASK | BD_DATA01_MASK | BD_OWN_MASK;
Kojto 71:53949e6131f6 319 }
Kojto 71:53949e6131f6 320 else {
Kojto 71:53949e6131f6 321 bdt[idx].info = BD_DTS_MASK | BD_OWN_MASK;
Kojto 71:53949e6131f6 322 }
Kojto 71:53949e6131f6 323
Kojto 71:53949e6131f6 324 USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK;
Kojto 71:53949e6131f6 325 *bytesRead = sz;
Kojto 71:53949e6131f6 326
Kojto 71:53949e6131f6 327 epComplete &= ~EP(endpoint);
Kojto 71:53949e6131f6 328 return EP_COMPLETED;
Kojto 71:53949e6131f6 329 }
Kojto 71:53949e6131f6 330
Kojto 71:53949e6131f6 331 EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) {
Kojto 71:53949e6131f6 332 uint32_t idx, n;
Kojto 71:53949e6131f6 333 uint8_t * ep_buf;
Kojto 71:53949e6131f6 334
Kojto 71:53949e6131f6 335 if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) {
Kojto 71:53949e6131f6 336 return EP_INVALID;
Kojto 71:53949e6131f6 337 }
Kojto 71:53949e6131f6 338
Kojto 71:53949e6131f6 339 // if write on a OUT endpoint -> error
Kojto 71:53949e6131f6 340 if (OUT_EP(endpoint)) {
Kojto 71:53949e6131f6 341 return EP_INVALID;
Kojto 71:53949e6131f6 342 }
Kojto 71:53949e6131f6 343
Kojto 71:53949e6131f6 344 idx = EP_BDT_IDX(PHY_TO_LOG(endpoint), TX, 0);
Kojto 71:53949e6131f6 345 bdt[idx].byte_count = size;
Kojto 71:53949e6131f6 346
Kojto 71:53949e6131f6 347 ep_buf = endpoint_buffer[idx];
Kojto 71:53949e6131f6 348
Kojto 71:53949e6131f6 349 for (n = 0; n < size; n++) {
Kojto 71:53949e6131f6 350 ep_buf[n] = data[n];
Kojto 71:53949e6131f6 351 }
Kojto 71:53949e6131f6 352
Kojto 71:53949e6131f6 353 if ((Data1 >> endpoint) & 1) {
Kojto 71:53949e6131f6 354 bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK;
Kojto 71:53949e6131f6 355 } else {
Kojto 71:53949e6131f6 356 bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK | BD_DATA01_MASK;
Kojto 71:53949e6131f6 357 }
Kojto 71:53949e6131f6 358
Kojto 71:53949e6131f6 359 Data1 ^= (1 << endpoint);
Kojto 71:53949e6131f6 360
Kojto 71:53949e6131f6 361 return EP_PENDING;
Kojto 71:53949e6131f6 362 }
Kojto 71:53949e6131f6 363
Kojto 71:53949e6131f6 364 EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) {
Kojto 71:53949e6131f6 365 if (epComplete & EP(endpoint)) {
Kojto 71:53949e6131f6 366 epComplete &= ~EP(endpoint);
Kojto 71:53949e6131f6 367 return EP_COMPLETED;
Kojto 71:53949e6131f6 368 }
Kojto 71:53949e6131f6 369
Kojto 71:53949e6131f6 370 return EP_PENDING;
Kojto 71:53949e6131f6 371 }
Kojto 71:53949e6131f6 372
Kojto 71:53949e6131f6 373 void USBHAL::stallEndpoint(uint8_t endpoint) {
Kojto 71:53949e6131f6 374 USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT |= USB_ENDPT_EPSTALL_MASK;
Kojto 71:53949e6131f6 375 }
Kojto 71:53949e6131f6 376
Kojto 71:53949e6131f6 377 void USBHAL::unstallEndpoint(uint8_t endpoint) {
Kojto 71:53949e6131f6 378 USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT &= ~USB_ENDPT_EPSTALL_MASK;
Kojto 71:53949e6131f6 379 }
Kojto 71:53949e6131f6 380
Kojto 71:53949e6131f6 381 bool USBHAL::getEndpointStallState(uint8_t endpoint) {
Kojto 71:53949e6131f6 382 uint8_t stall = (USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT & USB_ENDPT_EPSTALL_MASK);
Kojto 71:53949e6131f6 383 return (stall) ? true : false;
Kojto 71:53949e6131f6 384 }
Kojto 71:53949e6131f6 385
Kojto 71:53949e6131f6 386 void USBHAL::remoteWakeup(void) {
Kojto 71:53949e6131f6 387 // [TODO]
Kojto 71:53949e6131f6 388 }
Kojto 71:53949e6131f6 389
Kojto 71:53949e6131f6 390
Kojto 71:53949e6131f6 391 void USBHAL::_usbisr(void) {
Kojto 71:53949e6131f6 392 instance->usbisr();
Kojto 71:53949e6131f6 393 }
Kojto 71:53949e6131f6 394
Kojto 71:53949e6131f6 395
Kojto 71:53949e6131f6 396 void USBHAL::usbisr(void) {
Kojto 71:53949e6131f6 397 uint8_t i;
Kojto 71:53949e6131f6 398 uint8_t istat = USB0->ISTAT;
Kojto 71:53949e6131f6 399
Kojto 71:53949e6131f6 400 // reset interrupt
Kojto 71:53949e6131f6 401 if (istat & USB_ISTAT_USBRST_MASK) {
Kojto 71:53949e6131f6 402 // disable all endpt
Kojto 71:53949e6131f6 403 for(i = 0; i < 16; i++) {
Kojto 71:53949e6131f6 404 USB0->ENDPOINT[i].ENDPT = 0x00;
Kojto 71:53949e6131f6 405 }
Kojto 71:53949e6131f6 406
Kojto 71:53949e6131f6 407 // enable control endpoint
Kojto 71:53949e6131f6 408 realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0, 0);
Kojto 71:53949e6131f6 409 realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0, 0);
Kojto 71:53949e6131f6 410
Kojto 71:53949e6131f6 411 Data1 = 0x55555555;
Kojto 71:53949e6131f6 412 USB0->CTL |= USB_CTL_ODDRST_MASK;
Kojto 71:53949e6131f6 413
Kojto 71:53949e6131f6 414 USB0->ISTAT = 0xFF; // clear all interrupt status flags
Kojto 71:53949e6131f6 415 USB0->ERRSTAT = 0xFF; // clear all error flags
Kojto 71:53949e6131f6 416 USB0->ERREN = 0xFF; // enable error interrupt sources
Kojto 71:53949e6131f6 417 USB0->ADDR = 0x00; // set default address
Kojto 71:53949e6131f6 418
Kojto 71:53949e6131f6 419 // reset bus for USBDevice layer
Kojto 71:53949e6131f6 420 busReset();
Kojto 71:53949e6131f6 421
Kojto 71:53949e6131f6 422 return;
Kojto 71:53949e6131f6 423 }
Kojto 71:53949e6131f6 424
Kojto 71:53949e6131f6 425 // resume interrupt
Kojto 71:53949e6131f6 426 if (istat & USB_ISTAT_RESUME_MASK) {
Kojto 71:53949e6131f6 427 USB0->ISTAT = USB_ISTAT_RESUME_MASK;
Kojto 71:53949e6131f6 428 }
Kojto 71:53949e6131f6 429
Kojto 71:53949e6131f6 430 // SOF interrupt
Kojto 71:53949e6131f6 431 if (istat & USB_ISTAT_SOFTOK_MASK) {
Kojto 71:53949e6131f6 432 USB0->ISTAT = USB_ISTAT_SOFTOK_MASK;
Kojto 71:53949e6131f6 433 // SOF event, read frame number
Kojto 71:53949e6131f6 434 SOF(frameNumber());
Kojto 71:53949e6131f6 435 }
Kojto 71:53949e6131f6 436
Kojto 71:53949e6131f6 437 // stall interrupt
Kojto 71:53949e6131f6 438 if (istat & 1<<7) {
Kojto 71:53949e6131f6 439 if (USB0->ENDPOINT[0].ENDPT & USB_ENDPT_EPSTALL_MASK)
Kojto 71:53949e6131f6 440 USB0->ENDPOINT[0].ENDPT &= ~USB_ENDPT_EPSTALL_MASK;
Kojto 71:53949e6131f6 441 USB0->ISTAT |= USB_ISTAT_STALL_MASK;
Kojto 71:53949e6131f6 442 }
Kojto 71:53949e6131f6 443
Kojto 71:53949e6131f6 444 // token interrupt
Kojto 71:53949e6131f6 445 if (istat & 1<<3) {
Kojto 71:53949e6131f6 446 uint32_t num = (USB0->STAT >> 4) & 0x0F;
Kojto 71:53949e6131f6 447 uint32_t dir = (USB0->STAT >> 3) & 0x01;
Kojto 71:53949e6131f6 448 uint32_t ev_odd = (USB0->STAT >> 2) & 0x01;
Kojto 71:53949e6131f6 449 int endpoint = (num << 1) | dir;
Kojto 71:53949e6131f6 450
Kojto 71:53949e6131f6 451 // setup packet
Kojto 71:53949e6131f6 452 if ((num == 0) && (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == SETUP_TOKEN)) {
Kojto 71:53949e6131f6 453 Data1 &= ~0x02;
Kojto 71:53949e6131f6 454 bdt[EP_BDT_IDX(0, TX, EVEN)].info &= ~BD_OWN_MASK;
Kojto 71:53949e6131f6 455 bdt[EP_BDT_IDX(0, TX, ODD)].info &= ~BD_OWN_MASK;
Kojto 71:53949e6131f6 456
Kojto 71:53949e6131f6 457 // EP0 SETUP event (SETUP data received)
Kojto 71:53949e6131f6 458 EP0setupCallback();
Kojto 71:53949e6131f6 459
Kojto 71:53949e6131f6 460 } else {
Kojto 71:53949e6131f6 461 // OUT packet
Kojto 71:53949e6131f6 462 if (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == OUT_TOKEN) {
Kojto 71:53949e6131f6 463 if (num == 0)
Kojto 71:53949e6131f6 464 EP0out();
Kojto 71:53949e6131f6 465 else {
Kojto 71:53949e6131f6 466 epComplete |= EP(endpoint);
Kojto 71:53949e6131f6 467 if ((instance->*(epCallback[endpoint - 2]))()) {
Kojto 71:53949e6131f6 468 epComplete &= ~EP(endpoint);
Kojto 71:53949e6131f6 469 }
Kojto 71:53949e6131f6 470 }
Kojto 71:53949e6131f6 471 }
Kojto 71:53949e6131f6 472
Kojto 71:53949e6131f6 473 // IN packet
Kojto 71:53949e6131f6 474 if (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == IN_TOKEN) {
Kojto 71:53949e6131f6 475 if (num == 0) {
Kojto 71:53949e6131f6 476 EP0in();
Kojto 71:53949e6131f6 477 if (set_addr == 1) {
Kojto 71:53949e6131f6 478 USB0->ADDR = addr & 0x7F;
Kojto 71:53949e6131f6 479 set_addr = 0;
Kojto 71:53949e6131f6 480 }
Kojto 71:53949e6131f6 481 }
Kojto 71:53949e6131f6 482 else {
Kojto 71:53949e6131f6 483 epComplete |= EP(endpoint);
Kojto 71:53949e6131f6 484 if ((instance->*(epCallback[endpoint - 2]))()) {
Kojto 71:53949e6131f6 485 epComplete &= ~EP(endpoint);
Kojto 71:53949e6131f6 486 }
Kojto 71:53949e6131f6 487 }
Kojto 71:53949e6131f6 488 }
Kojto 71:53949e6131f6 489 }
Kojto 71:53949e6131f6 490
Kojto 71:53949e6131f6 491 USB0->ISTAT = USB_ISTAT_TOKDNE_MASK;
Kojto 71:53949e6131f6 492 }
Kojto 71:53949e6131f6 493
Kojto 71:53949e6131f6 494 // sleep interrupt
Kojto 71:53949e6131f6 495 if (istat & 1<<4) {
Kojto 71:53949e6131f6 496 USB0->ISTAT |= USB_ISTAT_SLEEP_MASK;
Kojto 71:53949e6131f6 497 }
Kojto 71:53949e6131f6 498
Kojto 71:53949e6131f6 499 // error interrupt
Kojto 71:53949e6131f6 500 if (istat & USB_ISTAT_ERROR_MASK) {
Kojto 71:53949e6131f6 501 USB0->ERRSTAT = 0xFF;
Kojto 71:53949e6131f6 502 USB0->ISTAT |= USB_ISTAT_ERROR_MASK;
Kojto 71:53949e6131f6 503 }
Kojto 71:53949e6131f6 504 }
Kojto 71:53949e6131f6 505
Kojto 71:53949e6131f6 506
Kojto 71:53949e6131f6 507 #endif