A copy of the mbed USBDevice with USBSerial library

Dependents:   STM32L0_LoRa Smartage STM32L0_LoRa Turtle_RadioShuttle

Committer:
Helmut Tschemernjak
Date:
Thu Jan 31 20:56:55 2019 +0100
Revision:
7:8a5cc0d9bfa2
Parent:
0:a3ea811f80f2
fixed compiler warnings

Who changed what in which revision?

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