The preloaded firmware shipped on the mBot.

Dependencies:   mbed

Fork of Official_mBot by Fred Parker

Committer:
jeffknaggs
Date:
Tue Nov 25 14:49:40 2014 +0000
Revision:
1:ffd9a51e7d35
Parent:
0:865d42c46692
Initial commit.

Who changed what in which revision?

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