Fork of the official USBDevice library

Fork of USBDevice by mbed official

Committer:
screamer
Date:
Fri Apr 28 17:01:10 2017 +0000
Branch:
device-files
Revision:
76:f0fd8d911b24
Parent:
USBDevice/USBHAL_KL25Z.cpp@73:8d28a0cb7b43
Changed the layout of USBDevice implementation for various targets to match mbed-os/targets. This also reduces the amount of files being compiled as USBDevice code for other targets is not compiled.

Who changed what in which revision?

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