Repostiory containing DAPLink source code with Reset Pin workaround for HANI_IOT board.

Upstream: https://github.com/ARMmbed/DAPLink

Committer:
Pawel Zarembski
Date:
Tue Apr 07 12:55:42 2020 +0200
Revision:
0:01f31e923fe2
hani: DAPLink with reset workaround

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Pawel Zarembski 0:01f31e923fe2 1 /**
Pawel Zarembski 0:01f31e923fe2 2 * @file usbd_kinetis.c
Pawel Zarembski 0:01f31e923fe2 3 * @brief
Pawel Zarembski 0:01f31e923fe2 4 *
Pawel Zarembski 0:01f31e923fe2 5 * DAPLink Interface Firmware
Pawel Zarembski 0:01f31e923fe2 6 * Copyright (c) 2009-2016, ARM Limited, All Rights Reserved
Pawel Zarembski 0:01f31e923fe2 7 * SPDX-License-Identifier: Apache-2.0
Pawel Zarembski 0:01f31e923fe2 8 *
Pawel Zarembski 0:01f31e923fe2 9 * Licensed under the Apache License, Version 2.0 (the "License"); you may
Pawel Zarembski 0:01f31e923fe2 10 * not use this file except in compliance with the License.
Pawel Zarembski 0:01f31e923fe2 11 * You may obtain a copy of the License at
Pawel Zarembski 0:01f31e923fe2 12 *
Pawel Zarembski 0:01f31e923fe2 13 * http://www.apache.org/licenses/LICENSE-2.0
Pawel Zarembski 0:01f31e923fe2 14 *
Pawel Zarembski 0:01f31e923fe2 15 * Unless required by applicable law or agreed to in writing, software
Pawel Zarembski 0:01f31e923fe2 16 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
Pawel Zarembski 0:01f31e923fe2 17 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Pawel Zarembski 0:01f31e923fe2 18 * See the License for the specific language governing permissions and
Pawel Zarembski 0:01f31e923fe2 19 * limitations under the License.
Pawel Zarembski 0:01f31e923fe2 20 */
Pawel Zarembski 0:01f31e923fe2 21
Pawel Zarembski 0:01f31e923fe2 22 #include "rl_usb.h"
Pawel Zarembski 0:01f31e923fe2 23 #include "fsl_device_registers.h"
Pawel Zarembski 0:01f31e923fe2 24 #include "cortex_m.h"
Pawel Zarembski 0:01f31e923fe2 25 #include "util.h"
Pawel Zarembski 0:01f31e923fe2 26 #include "string.h"
Pawel Zarembski 0:01f31e923fe2 27
Pawel Zarembski 0:01f31e923fe2 28 #define __NO_USB_LIB_C
Pawel Zarembski 0:01f31e923fe2 29 #include "usb_config.c"
Pawel Zarembski 0:01f31e923fe2 30
Pawel Zarembski 0:01f31e923fe2 31 typedef struct __BUF_DESC {
Pawel Zarembski 0:01f31e923fe2 32 uint8_t stat;
Pawel Zarembski 0:01f31e923fe2 33 uint8_t reserved;
Pawel Zarembski 0:01f31e923fe2 34 uint16_t bc;
Pawel Zarembski 0:01f31e923fe2 35 uint32_t buf_addr;
Pawel Zarembski 0:01f31e923fe2 36 } BUF_DESC;
Pawel Zarembski 0:01f31e923fe2 37
Pawel Zarembski 0:01f31e923fe2 38 BUF_DESC __align(512) BD[(USBD_EP_NUM + 1) * 2 * 2];
Pawel Zarembski 0:01f31e923fe2 39 uint8_t EPBuf[(USBD_EP_NUM + 1) * 2 * 2][64];
Pawel Zarembski 0:01f31e923fe2 40 uint8_t OutEpSize[USBD_EP_NUM + 1];
Pawel Zarembski 0:01f31e923fe2 41 uint8_t StatQueue[(USBD_EP_NUM + 1) * 2 * 2 + 1];
Pawel Zarembski 0:01f31e923fe2 42 uint32_t StatQueueHead = 0;
Pawel Zarembski 0:01f31e923fe2 43 uint32_t StatQueueTail = 0;
Pawel Zarembski 0:01f31e923fe2 44 uint32_t LastIstat = 0;
Pawel Zarembski 0:01f31e923fe2 45 uint8_t UsbSuspended = 0;
Pawel Zarembski 0:01f31e923fe2 46 uint8_t Ep0ZlpOut = 0;
Pawel Zarembski 0:01f31e923fe2 47
Pawel Zarembski 0:01f31e923fe2 48 uint32_t Data1 = 0x55555555;
Pawel Zarembski 0:01f31e923fe2 49
Pawel Zarembski 0:01f31e923fe2 50 #define BD_OWN_MASK 0x80
Pawel Zarembski 0:01f31e923fe2 51 #define BD_DATA01_MASK 0x40
Pawel Zarembski 0:01f31e923fe2 52 #define BD_KEEP_MASK 0x20
Pawel Zarembski 0:01f31e923fe2 53 #define BD_NINC_MASK 0x10
Pawel Zarembski 0:01f31e923fe2 54 #define BD_DTS_MASK 0x08
Pawel Zarembski 0:01f31e923fe2 55 #define BD_STALL_MASK 0x04
Pawel Zarembski 0:01f31e923fe2 56
Pawel Zarembski 0:01f31e923fe2 57 #define TX 1
Pawel Zarembski 0:01f31e923fe2 58 #define RX 0
Pawel Zarembski 0:01f31e923fe2 59 #define ODD 0
Pawel Zarembski 0:01f31e923fe2 60 #define EVEN 1
Pawel Zarembski 0:01f31e923fe2 61 #define IDX(Ep, dir, Ev_Odd) ((((Ep & 0x0F) * 4) + (2 * dir) + (1 * Ev_Odd)))
Pawel Zarembski 0:01f31e923fe2 62
Pawel Zarembski 0:01f31e923fe2 63 #define SETUP_TOKEN 0x0D
Pawel Zarembski 0:01f31e923fe2 64 #define IN_TOKEN 0x09
Pawel Zarembski 0:01f31e923fe2 65 #define OUT_TOKEN 0x01
Pawel Zarembski 0:01f31e923fe2 66 #define TOK_PID(idx) ((BD[idx].stat >> 2) & 0x0F)
Pawel Zarembski 0:01f31e923fe2 67
Pawel Zarembski 0:01f31e923fe2 68 inline static void protected_and(uint32_t *addr, uint32_t val)
Pawel Zarembski 0:01f31e923fe2 69 {
Pawel Zarembski 0:01f31e923fe2 70 cortex_int_state_t state;
Pawel Zarembski 0:01f31e923fe2 71 state = cortex_int_get_and_disable();
Pawel Zarembski 0:01f31e923fe2 72 *addr = *addr & val;
Pawel Zarembski 0:01f31e923fe2 73 cortex_int_restore(state);
Pawel Zarembski 0:01f31e923fe2 74 }
Pawel Zarembski 0:01f31e923fe2 75 inline static void protected_or(uint32_t *addr, uint32_t val)
Pawel Zarembski 0:01f31e923fe2 76 {
Pawel Zarembski 0:01f31e923fe2 77 cortex_int_state_t state;
Pawel Zarembski 0:01f31e923fe2 78 state = cortex_int_get_and_disable();
Pawel Zarembski 0:01f31e923fe2 79 *addr = *addr | val;
Pawel Zarembski 0:01f31e923fe2 80 cortex_int_restore(state);
Pawel Zarembski 0:01f31e923fe2 81 }
Pawel Zarembski 0:01f31e923fe2 82 inline static void protected_xor(uint32_t *addr, uint32_t val)
Pawel Zarembski 0:01f31e923fe2 83 {
Pawel Zarembski 0:01f31e923fe2 84 cortex_int_state_t state;
Pawel Zarembski 0:01f31e923fe2 85 state = cortex_int_get_and_disable();
Pawel Zarembski 0:01f31e923fe2 86 *addr = *addr ^ val;
Pawel Zarembski 0:01f31e923fe2 87 cortex_int_restore(state);
Pawel Zarembski 0:01f31e923fe2 88 }
Pawel Zarembski 0:01f31e923fe2 89
Pawel Zarembski 0:01f31e923fe2 90 inline static void stat_enque(uint32_t stat)
Pawel Zarembski 0:01f31e923fe2 91 {
Pawel Zarembski 0:01f31e923fe2 92 cortex_int_state_t state;
Pawel Zarembski 0:01f31e923fe2 93 state = cortex_int_get_and_disable();
Pawel Zarembski 0:01f31e923fe2 94 StatQueue[StatQueueTail] = stat;
Pawel Zarembski 0:01f31e923fe2 95 StatQueueTail = (StatQueueTail + 1) % sizeof(StatQueue);
Pawel Zarembski 0:01f31e923fe2 96 cortex_int_restore(state);
Pawel Zarembski 0:01f31e923fe2 97 }
Pawel Zarembski 0:01f31e923fe2 98
Pawel Zarembski 0:01f31e923fe2 99 inline static uint32_t stat_deque()
Pawel Zarembski 0:01f31e923fe2 100 {
Pawel Zarembski 0:01f31e923fe2 101 cortex_int_state_t state;
Pawel Zarembski 0:01f31e923fe2 102 uint32_t stat;
Pawel Zarembski 0:01f31e923fe2 103 state = cortex_int_get_and_disable();
Pawel Zarembski 0:01f31e923fe2 104 stat = StatQueue[StatQueueHead];
Pawel Zarembski 0:01f31e923fe2 105 StatQueueHead = (StatQueueHead + 1) % sizeof(StatQueue);
Pawel Zarembski 0:01f31e923fe2 106 cortex_int_restore(state);
Pawel Zarembski 0:01f31e923fe2 107
Pawel Zarembski 0:01f31e923fe2 108 return stat;
Pawel Zarembski 0:01f31e923fe2 109 }
Pawel Zarembski 0:01f31e923fe2 110
Pawel Zarembski 0:01f31e923fe2 111 inline static uint32_t stat_is_empty()
Pawel Zarembski 0:01f31e923fe2 112 {
Pawel Zarembski 0:01f31e923fe2 113 cortex_int_state_t state;
Pawel Zarembski 0:01f31e923fe2 114 uint32_t empty;
Pawel Zarembski 0:01f31e923fe2 115 state = cortex_int_get_and_disable();
Pawel Zarembski 0:01f31e923fe2 116 empty = StatQueueHead == StatQueueTail;
Pawel Zarembski 0:01f31e923fe2 117 cortex_int_restore(state);
Pawel Zarembski 0:01f31e923fe2 118 return empty;
Pawel Zarembski 0:01f31e923fe2 119 }
Pawel Zarembski 0:01f31e923fe2 120
Pawel Zarembski 0:01f31e923fe2 121 /*
Pawel Zarembski 0:01f31e923fe2 122 * USB Device Interrupt enable
Pawel Zarembski 0:01f31e923fe2 123 * Called by USBD_Init to enable the USB Interrupt
Pawel Zarembski 0:01f31e923fe2 124 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 125 */
Pawel Zarembski 0:01f31e923fe2 126
Pawel Zarembski 0:01f31e923fe2 127 void USBD_IntrEna(void)
Pawel Zarembski 0:01f31e923fe2 128 {
Pawel Zarembski 0:01f31e923fe2 129 NVIC_EnableIRQ(USB0_IRQn); /* Enable OTG interrupt */
Pawel Zarembski 0:01f31e923fe2 130 }
Pawel Zarembski 0:01f31e923fe2 131
Pawel Zarembski 0:01f31e923fe2 132
Pawel Zarembski 0:01f31e923fe2 133 /*
Pawel Zarembski 0:01f31e923fe2 134 * USB Device Initialize Function
Pawel Zarembski 0:01f31e923fe2 135 * Called by the User to initialize USB
Pawel Zarembski 0:01f31e923fe2 136 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 137 */
Pawel Zarembski 0:01f31e923fe2 138
Pawel Zarembski 0:01f31e923fe2 139 void USBD_Init(void)
Pawel Zarembski 0:01f31e923fe2 140 {
Pawel Zarembski 0:01f31e923fe2 141 OutEpSize[0] = USBD_MAX_PACKET0;
Pawel Zarembski 0:01f31e923fe2 142 /* Enable all clocks needed for USB to function */
Pawel Zarembski 0:01f31e923fe2 143 /* Set USB clock to 48 MHz */
Pawel Zarembski 0:01f31e923fe2 144 SIM->SOPT2 |= SIM_SOPT2_USBSRC_MASK | /* MCGPLLCLK used as src */
Pawel Zarembski 0:01f31e923fe2 145 SIM_SOPT2_PLLFLLSEL_MASK ; /* Select MCGPLLCLK as clock */
Pawel Zarembski 0:01f31e923fe2 146 #if defined(TARGET_MK20D5)
Pawel Zarembski 0:01f31e923fe2 147 SIM->CLKDIV2 &= ~(SIM_CLKDIV2_USBFRAC_MASK | /* Clear CLKDIV2 FS values */
Pawel Zarembski 0:01f31e923fe2 148 SIM_CLKDIV2_USBDIV_MASK);
Pawel Zarembski 0:01f31e923fe2 149 SIM->CLKDIV2 = SIM_CLKDIV2_USBDIV(0) ; /* USB clk = (PLL*1/2) */
Pawel Zarembski 0:01f31e923fe2 150 /* = ( 48*1/1)=48 */
Pawel Zarembski 0:01f31e923fe2 151 #endif // TARGET_MK20D5
Pawel Zarembski 0:01f31e923fe2 152 SIM->SCGC4 |= SIM_SCGC4_USBOTG_MASK; /* Enable USBOTG clock */
Pawel Zarembski 0:01f31e923fe2 153 USBD_IntrEna();
Pawel Zarembski 0:01f31e923fe2 154 USB0->USBTRC0 |= USB_USBTRC0_USBRESET_MASK;
Pawel Zarembski 0:01f31e923fe2 155
Pawel Zarembski 0:01f31e923fe2 156 while (USB0->USBTRC0 & USB_USBTRC0_USBRESET_MASK);
Pawel Zarembski 0:01f31e923fe2 157
Pawel Zarembski 0:01f31e923fe2 158 USB0->BDTPAGE1 = (uint8_t)((uint32_t) BD >> 8);
Pawel Zarembski 0:01f31e923fe2 159 USB0->BDTPAGE2 = (uint8_t)((uint32_t) BD >> 16);
Pawel Zarembski 0:01f31e923fe2 160 USB0->BDTPAGE3 = (uint8_t)((uint32_t) BD >> 24);
Pawel Zarembski 0:01f31e923fe2 161 USB0->ISTAT = 0xFF; /* clear interrupt flags */
Pawel Zarembski 0:01f31e923fe2 162 /* enable interrupts */
Pawel Zarembski 0:01f31e923fe2 163 USB0->INTEN = USB_INTEN_USBRSTEN_MASK |
Pawel Zarembski 0:01f31e923fe2 164 USB_INTEN_TOKDNEEN_MASK |
Pawel Zarembski 0:01f31e923fe2 165 USB_INTEN_SLEEPEN_MASK |
Pawel Zarembski 0:01f31e923fe2 166 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 167 ((USBD_RTX_DevTask != 0) ? USB_INTEN_SOFTOKEN_MASK : 0) |
Pawel Zarembski 0:01f31e923fe2 168 ((USBD_RTX_DevTask != 0) ? USB_INTEN_ERROREN_MASK : 0) ;
Pawel Zarembski 0:01f31e923fe2 169 #else
Pawel Zarembski 0:01f31e923fe2 170 ((USBD_P_SOF_Event != 0) ? USB_INTEN_SOFTOKEN_MASK : 0) |
Pawel Zarembski 0:01f31e923fe2 171 ((USBD_P_Error_Event != 0) ? USB_INTEN_ERROREN_MASK : 0) ;
Pawel Zarembski 0:01f31e923fe2 172 #endif
Pawel Zarembski 0:01f31e923fe2 173 USB0->USBCTRL = USB_USBCTRL_PDE_MASK;/* pull dawn on D+ and D- */
Pawel Zarembski 0:01f31e923fe2 174 USB0->USBTRC0 |= (1 << 6); /* bit 6 must be set to 1 */
Pawel Zarembski 0:01f31e923fe2 175 }
Pawel Zarembski 0:01f31e923fe2 176
Pawel Zarembski 0:01f31e923fe2 177
Pawel Zarembski 0:01f31e923fe2 178 /*
Pawel Zarembski 0:01f31e923fe2 179 * USB Device Connect Function
Pawel Zarembski 0:01f31e923fe2 180 * Called by the User to Connect/Disconnect USB Device
Pawel Zarembski 0:01f31e923fe2 181 * Parameters: con: Connect/Disconnect
Pawel Zarembski 0:01f31e923fe2 182 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 183 */
Pawel Zarembski 0:01f31e923fe2 184
Pawel Zarembski 0:01f31e923fe2 185 void USBD_Connect(uint32_t con)
Pawel Zarembski 0:01f31e923fe2 186 {
Pawel Zarembski 0:01f31e923fe2 187 if (con) {
Pawel Zarembski 0:01f31e923fe2 188 USB0->CTL |= USB_CTL_USBENSOFEN_MASK; /* enable USB */
Pawel Zarembski 0:01f31e923fe2 189 USB0->CONTROL = USB_CONTROL_DPPULLUPNONOTG_MASK; /* pull up on D+ */
Pawel Zarembski 0:01f31e923fe2 190 } else {
Pawel Zarembski 0:01f31e923fe2 191 USB0->CTL &= ~USB_CTL_USBENSOFEN_MASK; /* disable USB */
Pawel Zarembski 0:01f31e923fe2 192 USB0->CONTROL &= ~USB_CONTROL_DPPULLUPNONOTG_MASK;/* pull down on D+ */
Pawel Zarembski 0:01f31e923fe2 193 }
Pawel Zarembski 0:01f31e923fe2 194 }
Pawel Zarembski 0:01f31e923fe2 195
Pawel Zarembski 0:01f31e923fe2 196
Pawel Zarembski 0:01f31e923fe2 197 /*
Pawel Zarembski 0:01f31e923fe2 198 * USB Device Reset Function
Pawel Zarembski 0:01f31e923fe2 199 * Called automatically on USB Device Reset
Pawel Zarembski 0:01f31e923fe2 200 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 201 */
Pawel Zarembski 0:01f31e923fe2 202
Pawel Zarembski 0:01f31e923fe2 203 void USBD_Reset(void)
Pawel Zarembski 0:01f31e923fe2 204 {
Pawel Zarembski 0:01f31e923fe2 205 uint32_t i;
Pawel Zarembski 0:01f31e923fe2 206
Pawel Zarembski 0:01f31e923fe2 207 NVIC_DisableIRQ(USB0_IRQn);
Pawel Zarembski 0:01f31e923fe2 208
Pawel Zarembski 0:01f31e923fe2 209 for (i = 1; i < 16; i++) {
Pawel Zarembski 0:01f31e923fe2 210 USB0->ENDPOINT[i].ENDPT = 0x00;
Pawel Zarembski 0:01f31e923fe2 211 }
Pawel Zarembski 0:01f31e923fe2 212
Pawel Zarembski 0:01f31e923fe2 213 memset(StatQueue, 0, sizeof(StatQueue));
Pawel Zarembski 0:01f31e923fe2 214 StatQueueHead = 0;
Pawel Zarembski 0:01f31e923fe2 215 StatQueueTail = 0;
Pawel Zarembski 0:01f31e923fe2 216 LastIstat = 0;
Pawel Zarembski 0:01f31e923fe2 217 UsbSuspended = 0;
Pawel Zarembski 0:01f31e923fe2 218 Ep0ZlpOut = 0;
Pawel Zarembski 0:01f31e923fe2 219
Pawel Zarembski 0:01f31e923fe2 220 /* EP0 control endpoint */
Pawel Zarembski 0:01f31e923fe2 221 BD[IDX(0, RX, ODD)].bc = USBD_MAX_PACKET0;
Pawel Zarembski 0:01f31e923fe2 222 BD[IDX(0, RX, ODD)].buf_addr = (uint32_t) & (EPBuf[IDX(0, RX, ODD)][0]);
Pawel Zarembski 0:01f31e923fe2 223 BD[IDX(0, RX, ODD)].stat = BD_OWN_MASK | BD_DTS_MASK | BD_DATA01_MASK;
Pawel Zarembski 0:01f31e923fe2 224 BD[IDX(0, RX, EVEN)].stat = 0;
Pawel Zarembski 0:01f31e923fe2 225 BD[IDX(0, TX, ODD)].buf_addr = (uint32_t) & (EPBuf[IDX(0, TX, ODD)][0]);
Pawel Zarembski 0:01f31e923fe2 226 BD[IDX(0, TX, EVEN)].buf_addr = 0;
Pawel Zarembski 0:01f31e923fe2 227 USB0->ENDPOINT[0].ENDPT = USB_ENDPT_EPHSHK_MASK | /* enable ep handshaking */
Pawel Zarembski 0:01f31e923fe2 228 USB_ENDPT_EPTXEN_MASK | /* enable TX (IN) tran. */
Pawel Zarembski 0:01f31e923fe2 229 USB_ENDPT_EPRXEN_MASK; /* enable RX (OUT) tran. */
Pawel Zarembski 0:01f31e923fe2 230 Data1 = 0x55555555;
Pawel Zarembski 0:01f31e923fe2 231 USB0->CTL |= USB_CTL_ODDRST_MASK;
Pawel Zarembski 0:01f31e923fe2 232 USB0->ISTAT = 0xFF; /* clear all interrupt status flags */
Pawel Zarembski 0:01f31e923fe2 233 USB0->ERRSTAT = 0xFF; /* clear all error flags */
Pawel Zarembski 0:01f31e923fe2 234 USB0->ERREN = 0xFF; /* enable error interrupt sources */
Pawel Zarembski 0:01f31e923fe2 235 USB0->ADDR = 0x00; /* set default address */
Pawel Zarembski 0:01f31e923fe2 236
Pawel Zarembski 0:01f31e923fe2 237 NVIC_EnableIRQ(USB0_IRQn);
Pawel Zarembski 0:01f31e923fe2 238 }
Pawel Zarembski 0:01f31e923fe2 239
Pawel Zarembski 0:01f31e923fe2 240
Pawel Zarembski 0:01f31e923fe2 241 /*
Pawel Zarembski 0:01f31e923fe2 242 * USB Device Suspend Function
Pawel Zarembski 0:01f31e923fe2 243 * Called automatically on USB Device Suspend
Pawel Zarembski 0:01f31e923fe2 244 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 245 */
Pawel Zarembski 0:01f31e923fe2 246
Pawel Zarembski 0:01f31e923fe2 247 void USBD_Suspend(void)
Pawel Zarembski 0:01f31e923fe2 248 {
Pawel Zarembski 0:01f31e923fe2 249 USB0->INTEN |= USB_INTEN_RESUMEEN_MASK;
Pawel Zarembski 0:01f31e923fe2 250 }
Pawel Zarembski 0:01f31e923fe2 251
Pawel Zarembski 0:01f31e923fe2 252
Pawel Zarembski 0:01f31e923fe2 253 /*
Pawel Zarembski 0:01f31e923fe2 254 * USB Device Resume Function
Pawel Zarembski 0:01f31e923fe2 255 * Called automatically on USB Device Resume
Pawel Zarembski 0:01f31e923fe2 256 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 257 */
Pawel Zarembski 0:01f31e923fe2 258
Pawel Zarembski 0:01f31e923fe2 259 void USBD_Resume(void)
Pawel Zarembski 0:01f31e923fe2 260 {
Pawel Zarembski 0:01f31e923fe2 261 USB0->INTEN &= ~USB_INTEN_RESUMEEN_MASK;
Pawel Zarembski 0:01f31e923fe2 262 }
Pawel Zarembski 0:01f31e923fe2 263
Pawel Zarembski 0:01f31e923fe2 264
Pawel Zarembski 0:01f31e923fe2 265 /*
Pawel Zarembski 0:01f31e923fe2 266 * USB Device Remote Wakeup Function
Pawel Zarembski 0:01f31e923fe2 267 * Called automatically on USB Device Remote Wakeup
Pawel Zarembski 0:01f31e923fe2 268 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 269 */
Pawel Zarembski 0:01f31e923fe2 270
Pawel Zarembski 0:01f31e923fe2 271 void USBD_WakeUp(void)
Pawel Zarembski 0:01f31e923fe2 272 {
Pawel Zarembski 0:01f31e923fe2 273 uint32_t i = 50000;
Pawel Zarembski 0:01f31e923fe2 274
Pawel Zarembski 0:01f31e923fe2 275 if (USBD_DeviceStatus & USB_GETSTATUS_REMOTE_WAKEUP) {
Pawel Zarembski 0:01f31e923fe2 276 USB0->CTL |= USB_CTL_RESUME_MASK;
Pawel Zarembski 0:01f31e923fe2 277
Pawel Zarembski 0:01f31e923fe2 278 while (i--) {
Pawel Zarembski 0:01f31e923fe2 279 __nop();
Pawel Zarembski 0:01f31e923fe2 280 }
Pawel Zarembski 0:01f31e923fe2 281
Pawel Zarembski 0:01f31e923fe2 282 USB0->CTL &= ~USB_CTL_RESUME_MASK;
Pawel Zarembski 0:01f31e923fe2 283 }
Pawel Zarembski 0:01f31e923fe2 284 }
Pawel Zarembski 0:01f31e923fe2 285
Pawel Zarembski 0:01f31e923fe2 286
Pawel Zarembski 0:01f31e923fe2 287 /*
Pawel Zarembski 0:01f31e923fe2 288 * USB Device Remote Wakeup Configuration Function
Pawel Zarembski 0:01f31e923fe2 289 * Parameters: cfg: Device Enable/Disable
Pawel Zarembski 0:01f31e923fe2 290 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 291 */
Pawel Zarembski 0:01f31e923fe2 292
Pawel Zarembski 0:01f31e923fe2 293 void USBD_WakeUpCfg(uint32_t cfg)
Pawel Zarembski 0:01f31e923fe2 294 {
Pawel Zarembski 0:01f31e923fe2 295 /* Not needed */
Pawel Zarembski 0:01f31e923fe2 296 }
Pawel Zarembski 0:01f31e923fe2 297
Pawel Zarembski 0:01f31e923fe2 298
Pawel Zarembski 0:01f31e923fe2 299 /*
Pawel Zarembski 0:01f31e923fe2 300 * USB Device Set Address Function
Pawel Zarembski 0:01f31e923fe2 301 * Parameters: adr: USB Device Address
Pawel Zarembski 0:01f31e923fe2 302 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 303 */
Pawel Zarembski 0:01f31e923fe2 304
Pawel Zarembski 0:01f31e923fe2 305 void USBD_SetAddress(uint32_t adr, uint32_t setup)
Pawel Zarembski 0:01f31e923fe2 306 {
Pawel Zarembski 0:01f31e923fe2 307 if (!setup) {
Pawel Zarembski 0:01f31e923fe2 308 USB0->ADDR = adr & 0x7F;
Pawel Zarembski 0:01f31e923fe2 309 }
Pawel Zarembski 0:01f31e923fe2 310 }
Pawel Zarembski 0:01f31e923fe2 311
Pawel Zarembski 0:01f31e923fe2 312
Pawel Zarembski 0:01f31e923fe2 313 /*
Pawel Zarembski 0:01f31e923fe2 314 * USB Device Configure Function
Pawel Zarembski 0:01f31e923fe2 315 * Parameters: cfg: Device Configure/Deconfigure
Pawel Zarembski 0:01f31e923fe2 316 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 317 */
Pawel Zarembski 0:01f31e923fe2 318
Pawel Zarembski 0:01f31e923fe2 319 void USBD_Configure(uint32_t cfg)
Pawel Zarembski 0:01f31e923fe2 320 {
Pawel Zarembski 0:01f31e923fe2 321 }
Pawel Zarembski 0:01f31e923fe2 322
Pawel Zarembski 0:01f31e923fe2 323
Pawel Zarembski 0:01f31e923fe2 324 /*
Pawel Zarembski 0:01f31e923fe2 325 * Configure USB Device Endpoint according to Descriptor
Pawel Zarembski 0:01f31e923fe2 326 * Parameters: pEPD: Pointer to Device Endpoint Descriptor
Pawel Zarembski 0:01f31e923fe2 327 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 328 */
Pawel Zarembski 0:01f31e923fe2 329
Pawel Zarembski 0:01f31e923fe2 330 void USBD_ConfigEP(USB_ENDPOINT_DESCRIPTOR *pEPD)
Pawel Zarembski 0:01f31e923fe2 331 {
Pawel Zarembski 0:01f31e923fe2 332 uint32_t num, val;
Pawel Zarembski 0:01f31e923fe2 333 num = pEPD->bEndpointAddress;
Pawel Zarembski 0:01f31e923fe2 334 val = pEPD->wMaxPacketSize;
Pawel Zarembski 0:01f31e923fe2 335
Pawel Zarembski 0:01f31e923fe2 336 if (!(pEPD->bEndpointAddress & 0x80)) {
Pawel Zarembski 0:01f31e923fe2 337 OutEpSize[num] = val;
Pawel Zarembski 0:01f31e923fe2 338 }
Pawel Zarembski 0:01f31e923fe2 339
Pawel Zarembski 0:01f31e923fe2 340 USBD_ResetEP(num);
Pawel Zarembski 0:01f31e923fe2 341 }
Pawel Zarembski 0:01f31e923fe2 342
Pawel Zarembski 0:01f31e923fe2 343
Pawel Zarembski 0:01f31e923fe2 344 /*
Pawel Zarembski 0:01f31e923fe2 345 * Set Direction for USB Device Control Endpoint
Pawel Zarembski 0:01f31e923fe2 346 * Parameters: dir: Out (dir == 0), In (dir <> 0)
Pawel Zarembski 0:01f31e923fe2 347 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 348 */
Pawel Zarembski 0:01f31e923fe2 349
Pawel Zarembski 0:01f31e923fe2 350 void USBD_DirCtrlEP(uint32_t dir)
Pawel Zarembski 0:01f31e923fe2 351 {
Pawel Zarembski 0:01f31e923fe2 352 /* Not needed */
Pawel Zarembski 0:01f31e923fe2 353 }
Pawel Zarembski 0:01f31e923fe2 354
Pawel Zarembski 0:01f31e923fe2 355
Pawel Zarembski 0:01f31e923fe2 356 /*
Pawel Zarembski 0:01f31e923fe2 357 * Enable USB Device Endpoint
Pawel Zarembski 0:01f31e923fe2 358 * Parameters: EPNum: Device Endpoint Number
Pawel Zarembski 0:01f31e923fe2 359 * EPNum.0..3: Address
Pawel Zarembski 0:01f31e923fe2 360 * EPNum.7: Dir
Pawel Zarembski 0:01f31e923fe2 361 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 362 */
Pawel Zarembski 0:01f31e923fe2 363
Pawel Zarembski 0:01f31e923fe2 364 void USBD_EnableEP(uint32_t EPNum)
Pawel Zarembski 0:01f31e923fe2 365 {
Pawel Zarembski 0:01f31e923fe2 366 if (EPNum & 0x80) {
Pawel Zarembski 0:01f31e923fe2 367 EPNum &= 0x0F;
Pawel Zarembski 0:01f31e923fe2 368 USB0->ENDPOINT[EPNum].ENDPT |= USB_ENDPT_EPHSHK_MASK | /*en ep handshaking*/
Pawel Zarembski 0:01f31e923fe2 369 USB_ENDPT_EPTXEN_MASK; /*en TX (IN) tran */
Pawel Zarembski 0:01f31e923fe2 370 } else {
Pawel Zarembski 0:01f31e923fe2 371 USB0->ENDPOINT[EPNum].ENDPT |= USB_ENDPT_EPHSHK_MASK | /*en ep handshaking*/
Pawel Zarembski 0:01f31e923fe2 372 USB_ENDPT_EPRXEN_MASK; /*en RX (OUT) tran.*/
Pawel Zarembski 0:01f31e923fe2 373 }
Pawel Zarembski 0:01f31e923fe2 374 }
Pawel Zarembski 0:01f31e923fe2 375
Pawel Zarembski 0:01f31e923fe2 376
Pawel Zarembski 0:01f31e923fe2 377 /*
Pawel Zarembski 0:01f31e923fe2 378 * Disable USB Endpoint
Pawel Zarembski 0:01f31e923fe2 379 * Parameters: EPNum: Endpoint Number
Pawel Zarembski 0:01f31e923fe2 380 * EPNum.0..3: Address
Pawel Zarembski 0:01f31e923fe2 381 * EPNum.7: Dir
Pawel Zarembski 0:01f31e923fe2 382 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 383 */
Pawel Zarembski 0:01f31e923fe2 384
Pawel Zarembski 0:01f31e923fe2 385 void USBD_DisableEP(uint32_t EPNum)
Pawel Zarembski 0:01f31e923fe2 386 {
Pawel Zarembski 0:01f31e923fe2 387 if (EPNum & 0x80) {
Pawel Zarembski 0:01f31e923fe2 388 EPNum &= 0x0F;
Pawel Zarembski 0:01f31e923fe2 389 USB0->ENDPOINT[EPNum].ENDPT &= ~(USB_ENDPT_EPHSHK_MASK |/*dis handshaking */
Pawel Zarembski 0:01f31e923fe2 390 USB_ENDPT_EPTXEN_MASK);/*dis TX(IN) tran */
Pawel Zarembski 0:01f31e923fe2 391 } else {
Pawel Zarembski 0:01f31e923fe2 392 USB0->ENDPOINT[EPNum].ENDPT &= ~(USB_ENDPT_EPHSHK_MASK |/*dis handshaking */
Pawel Zarembski 0:01f31e923fe2 393 USB_ENDPT_EPRXEN_MASK);/*dis RX(OUT) tran*/
Pawel Zarembski 0:01f31e923fe2 394 }
Pawel Zarembski 0:01f31e923fe2 395 }
Pawel Zarembski 0:01f31e923fe2 396
Pawel Zarembski 0:01f31e923fe2 397
Pawel Zarembski 0:01f31e923fe2 398 /*
Pawel Zarembski 0:01f31e923fe2 399 * Reset USB Device Endpoint
Pawel Zarembski 0:01f31e923fe2 400 * Parameters: EPNum: Device Endpoint Number
Pawel Zarembski 0:01f31e923fe2 401 * EPNum.0..3: Address
Pawel Zarembski 0:01f31e923fe2 402 * EPNum.7: Dir
Pawel Zarembski 0:01f31e923fe2 403 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 404 */
Pawel Zarembski 0:01f31e923fe2 405
Pawel Zarembski 0:01f31e923fe2 406 void USBD_ResetEP(uint32_t EPNum)
Pawel Zarembski 0:01f31e923fe2 407 {
Pawel Zarembski 0:01f31e923fe2 408 if (EPNum & 0x80) {
Pawel Zarembski 0:01f31e923fe2 409 EPNum &= 0x0F;
Pawel Zarembski 0:01f31e923fe2 410 protected_or(&Data1, (1 << ((EPNum * 2) + 1)));
Pawel Zarembski 0:01f31e923fe2 411 BD[IDX(EPNum, TX, ODD)].buf_addr = (uint32_t) & (EPBuf[IDX(EPNum, TX, ODD)][0]);
Pawel Zarembski 0:01f31e923fe2 412 BD[IDX(EPNum, TX, EVEN)].buf_addr = 0;
Pawel Zarembski 0:01f31e923fe2 413 } else {
Pawel Zarembski 0:01f31e923fe2 414 protected_and(&Data1, ~(1 << (EPNum * 2)));
Pawel Zarembski 0:01f31e923fe2 415 BD[IDX(EPNum, RX, ODD)].bc = OutEpSize[EPNum];
Pawel Zarembski 0:01f31e923fe2 416 BD[IDX(EPNum, RX, ODD)].buf_addr = (uint32_t) & (EPBuf[IDX(EPNum, RX, ODD)][0]);
Pawel Zarembski 0:01f31e923fe2 417 BD[IDX(EPNum, RX, ODD)].stat = BD_OWN_MASK | BD_DTS_MASK;
Pawel Zarembski 0:01f31e923fe2 418 BD[IDX(EPNum, RX, EVEN)].stat = 0;
Pawel Zarembski 0:01f31e923fe2 419 }
Pawel Zarembski 0:01f31e923fe2 420 }
Pawel Zarembski 0:01f31e923fe2 421
Pawel Zarembski 0:01f31e923fe2 422 /*
Pawel Zarembski 0:01f31e923fe2 423 * Set Stall for USB Device Endpoint
Pawel Zarembski 0:01f31e923fe2 424 * Parameters: EPNum: Device Endpoint Number
Pawel Zarembski 0:01f31e923fe2 425 * EPNum.0..3: Address
Pawel Zarembski 0:01f31e923fe2 426 * EPNum.7: Dir
Pawel Zarembski 0:01f31e923fe2 427 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 428 */
Pawel Zarembski 0:01f31e923fe2 429
Pawel Zarembski 0:01f31e923fe2 430 void USBD_SetStallEP(uint32_t EPNum)
Pawel Zarembski 0:01f31e923fe2 431 {
Pawel Zarembski 0:01f31e923fe2 432 EPNum &= 0x0F;
Pawel Zarembski 0:01f31e923fe2 433 USB0->ENDPOINT[EPNum].ENDPT |= USB_ENDPT_EPSTALL_MASK;
Pawel Zarembski 0:01f31e923fe2 434 }
Pawel Zarembski 0:01f31e923fe2 435
Pawel Zarembski 0:01f31e923fe2 436
Pawel Zarembski 0:01f31e923fe2 437 /*
Pawel Zarembski 0:01f31e923fe2 438 * Clear Stall for USB Device Endpoint
Pawel Zarembski 0:01f31e923fe2 439 * Parameters: EPNum: Device Endpoint Number
Pawel Zarembski 0:01f31e923fe2 440 * EPNum.0..3: Address
Pawel Zarembski 0:01f31e923fe2 441 * EPNum.7: Dir
Pawel Zarembski 0:01f31e923fe2 442 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 443 */
Pawel Zarembski 0:01f31e923fe2 444
Pawel Zarembski 0:01f31e923fe2 445 void USBD_ClrStallEP(uint32_t EPNum)
Pawel Zarembski 0:01f31e923fe2 446 {
Pawel Zarembski 0:01f31e923fe2 447 USB0->ENDPOINT[EPNum & 0x0F].ENDPT &= ~USB_ENDPT_EPSTALL_MASK;
Pawel Zarembski 0:01f31e923fe2 448 USBD_ResetEP(EPNum);
Pawel Zarembski 0:01f31e923fe2 449 }
Pawel Zarembski 0:01f31e923fe2 450
Pawel Zarembski 0:01f31e923fe2 451
Pawel Zarembski 0:01f31e923fe2 452 /*
Pawel Zarembski 0:01f31e923fe2 453 * Clear USB Device Endpoint Buffer
Pawel Zarembski 0:01f31e923fe2 454 * Parameters: EPNum: Device Endpoint Number
Pawel Zarembski 0:01f31e923fe2 455 * EPNum.0..3: Address
Pawel Zarembski 0:01f31e923fe2 456 * EPNum.7: Dir
Pawel Zarembski 0:01f31e923fe2 457 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 458 */
Pawel Zarembski 0:01f31e923fe2 459
Pawel Zarembski 0:01f31e923fe2 460 void USBD_ClearEPBuf(uint32_t EPNum)
Pawel Zarembski 0:01f31e923fe2 461 {
Pawel Zarembski 0:01f31e923fe2 462 }
Pawel Zarembski 0:01f31e923fe2 463
Pawel Zarembski 0:01f31e923fe2 464
Pawel Zarembski 0:01f31e923fe2 465 /*
Pawel Zarembski 0:01f31e923fe2 466 * Read USB Device Endpoint Data
Pawel Zarembski 0:01f31e923fe2 467 * Parameters: EPNum: Device Endpoint Number
Pawel Zarembski 0:01f31e923fe2 468 * EPNum.0..3: Address
Pawel Zarembski 0:01f31e923fe2 469 * EPNum.7: Dir
Pawel Zarembski 0:01f31e923fe2 470 * pData: Pointer to Data Buffer
Pawel Zarembski 0:01f31e923fe2 471 * Return Value: Number of bytes read
Pawel Zarembski 0:01f31e923fe2 472 */
Pawel Zarembski 0:01f31e923fe2 473
Pawel Zarembski 0:01f31e923fe2 474 uint32_t USBD_ReadEP(uint32_t EPNum, uint8_t *pData, uint32_t size)
Pawel Zarembski 0:01f31e923fe2 475 {
Pawel Zarembski 0:01f31e923fe2 476 uint32_t n, sz, idx, setup = 0;
Pawel Zarembski 0:01f31e923fe2 477 idx = IDX(EPNum, RX, 0);
Pawel Zarembski 0:01f31e923fe2 478 sz = BD[idx].bc;
Pawel Zarembski 0:01f31e923fe2 479
Pawel Zarembski 0:01f31e923fe2 480 if ((EPNum == 0) && Ep0ZlpOut) {
Pawel Zarembski 0:01f31e923fe2 481 // This packet was a zero length data out packet. It has already
Pawel Zarembski 0:01f31e923fe2 482 // been processed by USB0_IRQHandler. Only toggle the DATAx bit
Pawel Zarembski 0:01f31e923fe2 483 // and return a size of 0.
Pawel Zarembski 0:01f31e923fe2 484 protected_xor(&Data1, (1 << (idx / 2)));
Pawel Zarembski 0:01f31e923fe2 485 return 0;
Pawel Zarembski 0:01f31e923fe2 486 }
Pawel Zarembski 0:01f31e923fe2 487
Pawel Zarembski 0:01f31e923fe2 488 if ((EPNum == 0) && (TOK_PID(idx) == SETUP_TOKEN)) {
Pawel Zarembski 0:01f31e923fe2 489 setup = 1;
Pawel Zarembski 0:01f31e923fe2 490 }
Pawel Zarembski 0:01f31e923fe2 491
Pawel Zarembski 0:01f31e923fe2 492 if (size < sz) {
Pawel Zarembski 0:01f31e923fe2 493 util_assert(0);
Pawel Zarembski 0:01f31e923fe2 494 sz = size;
Pawel Zarembski 0:01f31e923fe2 495 }
Pawel Zarembski 0:01f31e923fe2 496
Pawel Zarembski 0:01f31e923fe2 497 for (n = 0; n < sz; n++) {
Pawel Zarembski 0:01f31e923fe2 498 pData[n] = EPBuf[idx][n];
Pawel Zarembski 0:01f31e923fe2 499 }
Pawel Zarembski 0:01f31e923fe2 500
Pawel Zarembski 0:01f31e923fe2 501 BD[idx].bc = OutEpSize[EPNum];
Pawel Zarembski 0:01f31e923fe2 502
Pawel Zarembski 0:01f31e923fe2 503 if ((Data1 >> (idx / 2) & 1) == ((BD[idx].stat >> 6) & 1)) {
Pawel Zarembski 0:01f31e923fe2 504 uint32_t xfer_size = (pData[7] << 8) | (pData[6] << 0);
Pawel Zarembski 0:01f31e923fe2 505 if (setup && (0 == xfer_size)) { /* if no setup data stage, */
Pawel Zarembski 0:01f31e923fe2 506 protected_and(&Data1, ~1); /* set DATA0 */
Pawel Zarembski 0:01f31e923fe2 507 } else {
Pawel Zarembski 0:01f31e923fe2 508 protected_xor(&Data1, (1 << (idx / 2)));
Pawel Zarembski 0:01f31e923fe2 509 }
Pawel Zarembski 0:01f31e923fe2 510 }
Pawel Zarembski 0:01f31e923fe2 511
Pawel Zarembski 0:01f31e923fe2 512 if ((Data1 >> (idx / 2)) & 1) {
Pawel Zarembski 0:01f31e923fe2 513 BD[idx].stat = BD_DTS_MASK | BD_DATA01_MASK;
Pawel Zarembski 0:01f31e923fe2 514 BD[idx].stat |= BD_OWN_MASK;
Pawel Zarembski 0:01f31e923fe2 515 } else {
Pawel Zarembski 0:01f31e923fe2 516 BD[idx].stat = BD_DTS_MASK;
Pawel Zarembski 0:01f31e923fe2 517 BD[idx].stat |= BD_OWN_MASK;
Pawel Zarembski 0:01f31e923fe2 518 }
Pawel Zarembski 0:01f31e923fe2 519
Pawel Zarembski 0:01f31e923fe2 520 return (sz);
Pawel Zarembski 0:01f31e923fe2 521 }
Pawel Zarembski 0:01f31e923fe2 522
Pawel Zarembski 0:01f31e923fe2 523
Pawel Zarembski 0:01f31e923fe2 524 /*
Pawel Zarembski 0:01f31e923fe2 525 * Write USB Device Endpoint Data
Pawel Zarembski 0:01f31e923fe2 526 * Parameters: EPNum: Device Endpoint Number
Pawel Zarembski 0:01f31e923fe2 527 * EPNum.0..3: Address
Pawel Zarembski 0:01f31e923fe2 528 * EPNum.7: Dir
Pawel Zarembski 0:01f31e923fe2 529 * pData: Pointer to Data Buffer
Pawel Zarembski 0:01f31e923fe2 530 * cnt: Number of bytes to write
Pawel Zarembski 0:01f31e923fe2 531 * Return Value: Number of bytes written
Pawel Zarembski 0:01f31e923fe2 532 */
Pawel Zarembski 0:01f31e923fe2 533
Pawel Zarembski 0:01f31e923fe2 534 uint32_t USBD_WriteEP(uint32_t EPNum, uint8_t *pData, uint32_t cnt)
Pawel Zarembski 0:01f31e923fe2 535 {
Pawel Zarembski 0:01f31e923fe2 536 uint32_t idx, n;
Pawel Zarembski 0:01f31e923fe2 537 EPNum &= 0x0F;
Pawel Zarembski 0:01f31e923fe2 538 idx = IDX(EPNum, TX, 0);
Pawel Zarembski 0:01f31e923fe2 539 BD[idx].bc = cnt;
Pawel Zarembski 0:01f31e923fe2 540
Pawel Zarembski 0:01f31e923fe2 541 for (n = 0; n < cnt; n++) {
Pawel Zarembski 0:01f31e923fe2 542 EPBuf[idx][n] = pData[n];
Pawel Zarembski 0:01f31e923fe2 543 }
Pawel Zarembski 0:01f31e923fe2 544
Pawel Zarembski 0:01f31e923fe2 545 if ((Data1 >> (idx / 2)) & 1) {
Pawel Zarembski 0:01f31e923fe2 546 BD[idx].stat = BD_OWN_MASK | BD_DTS_MASK;
Pawel Zarembski 0:01f31e923fe2 547 } else {
Pawel Zarembski 0:01f31e923fe2 548 BD[idx].stat = BD_OWN_MASK | BD_DTS_MASK | BD_DATA01_MASK;
Pawel Zarembski 0:01f31e923fe2 549 }
Pawel Zarembski 0:01f31e923fe2 550
Pawel Zarembski 0:01f31e923fe2 551 protected_xor(&Data1, (1 << (idx / 2)));
Pawel Zarembski 0:01f31e923fe2 552 return (cnt);
Pawel Zarembski 0:01f31e923fe2 553 }
Pawel Zarembski 0:01f31e923fe2 554
Pawel Zarembski 0:01f31e923fe2 555 /*
Pawel Zarembski 0:01f31e923fe2 556 * Get USB Device Last Frame Number
Pawel Zarembski 0:01f31e923fe2 557 * Parameters: None
Pawel Zarembski 0:01f31e923fe2 558 * Return Value: Frame Number
Pawel Zarembski 0:01f31e923fe2 559 */
Pawel Zarembski 0:01f31e923fe2 560
Pawel Zarembski 0:01f31e923fe2 561 uint32_t USBD_GetFrame(void)
Pawel Zarembski 0:01f31e923fe2 562 {
Pawel Zarembski 0:01f31e923fe2 563 return ((USB0->FRMNUML | (USB0->FRMNUMH << 8) & 0x07FF));
Pawel Zarembski 0:01f31e923fe2 564 }
Pawel Zarembski 0:01f31e923fe2 565
Pawel Zarembski 0:01f31e923fe2 566 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 567 U32 LastError; /* Last Error */
Pawel Zarembski 0:01f31e923fe2 568
Pawel Zarembski 0:01f31e923fe2 569 /*
Pawel Zarembski 0:01f31e923fe2 570 * Get USB Device Last Error Code
Pawel Zarembski 0:01f31e923fe2 571 * Parameters: None
Pawel Zarembski 0:01f31e923fe2 572 * Return Value: Error Code
Pawel Zarembski 0:01f31e923fe2 573 */
Pawel Zarembski 0:01f31e923fe2 574
Pawel Zarembski 0:01f31e923fe2 575 U32 USBD_GetError(void)
Pawel Zarembski 0:01f31e923fe2 576 {
Pawel Zarembski 0:01f31e923fe2 577 return (LastError);
Pawel Zarembski 0:01f31e923fe2 578 }
Pawel Zarembski 0:01f31e923fe2 579 #endif
Pawel Zarembski 0:01f31e923fe2 580
Pawel Zarembski 0:01f31e923fe2 581
Pawel Zarembski 0:01f31e923fe2 582 /*
Pawel Zarembski 0:01f31e923fe2 583 * USB Device Interrupt Service Routine
Pawel Zarembski 0:01f31e923fe2 584 */
Pawel Zarembski 0:01f31e923fe2 585 void USB0_IRQHandler(void)
Pawel Zarembski 0:01f31e923fe2 586 {
Pawel Zarembski 0:01f31e923fe2 587 uint32_t istat, num, dir, ev_odd;
Pawel Zarembski 0:01f31e923fe2 588 uint32_t new_istat;
Pawel Zarembski 0:01f31e923fe2 589 uint8_t suspended = 0;
Pawel Zarembski 0:01f31e923fe2 590
Pawel Zarembski 0:01f31e923fe2 591 new_istat = istat = USB0->ISTAT;
Pawel Zarembski 0:01f31e923fe2 592
Pawel Zarembski 0:01f31e923fe2 593 // Read all tokens
Pawel Zarembski 0:01f31e923fe2 594 if (istat & USB_ISTAT_TOKDNE_MASK) {
Pawel Zarembski 0:01f31e923fe2 595 while (istat & USB_ISTAT_TOKDNE_MASK) {
Pawel Zarembski 0:01f31e923fe2 596 uint8_t stat = USB0->STAT;
Pawel Zarembski 0:01f31e923fe2 597 num = (stat >> 4) & 0x0F;
Pawel Zarembski 0:01f31e923fe2 598 dir = (stat >> 3) & 0x01;
Pawel Zarembski 0:01f31e923fe2 599 ev_odd = (stat >> 2) & 0x01;
Pawel Zarembski 0:01f31e923fe2 600
Pawel Zarembski 0:01f31e923fe2 601 // Consume all zero length OUT packets on endpoint 0 to prevent
Pawel Zarembski 0:01f31e923fe2 602 // a subsequent SETUP packet from being dropped
Pawel Zarembski 0:01f31e923fe2 603 if ((0 == num) && (RX == dir)) {
Pawel Zarembski 0:01f31e923fe2 604 uint32_t idx;
Pawel Zarembski 0:01f31e923fe2 605 idx = IDX(num, dir, ev_odd);
Pawel Zarembski 0:01f31e923fe2 606 if ((TOK_PID(idx) == OUT_TOKEN) && (BD[idx].bc == 0)) {
Pawel Zarembski 0:01f31e923fe2 607 BD[idx].bc = OutEpSize[num];
Pawel Zarembski 0:01f31e923fe2 608 if (BD[idx].stat & BD_DATA01_MASK) {
Pawel Zarembski 0:01f31e923fe2 609 BD[idx].stat = BD_OWN_MASK | BD_DTS_MASK;
Pawel Zarembski 0:01f31e923fe2 610 } else {
Pawel Zarembski 0:01f31e923fe2 611 BD[idx].stat = BD_OWN_MASK | BD_DTS_MASK | BD_DATA01_MASK;
Pawel Zarembski 0:01f31e923fe2 612 }
Pawel Zarembski 0:01f31e923fe2 613 stat |= 1 << 0;
Pawel Zarembski 0:01f31e923fe2 614 }
Pawel Zarembski 0:01f31e923fe2 615 }
Pawel Zarembski 0:01f31e923fe2 616
Pawel Zarembski 0:01f31e923fe2 617 stat_enque(stat);
Pawel Zarembski 0:01f31e923fe2 618 USB0->ISTAT = USB_ISTAT_TOKDNE_MASK;
Pawel Zarembski 0:01f31e923fe2 619
Pawel Zarembski 0:01f31e923fe2 620 // Check if USB is suspending before checking istat
Pawel Zarembski 0:01f31e923fe2 621 suspended = suspended || USB0->CTL & USB_CTL_TXSUSPENDTOKENBUSY_MASK;
Pawel Zarembski 0:01f31e923fe2 622 istat = USB0->ISTAT;
Pawel Zarembski 0:01f31e923fe2 623 }
Pawel Zarembski 0:01f31e923fe2 624 }
Pawel Zarembski 0:01f31e923fe2 625
Pawel Zarembski 0:01f31e923fe2 626 // Set global istat and suspended flags
Pawel Zarembski 0:01f31e923fe2 627 new_istat |= istat;
Pawel Zarembski 0:01f31e923fe2 628 protected_or(&LastIstat, new_istat);
Pawel Zarembski 0:01f31e923fe2 629 UsbSuspended |= suspended ? 1 : 0;
Pawel Zarembski 0:01f31e923fe2 630 USB0->ISTAT = istat;
Pawel Zarembski 0:01f31e923fe2 631
Pawel Zarembski 0:01f31e923fe2 632 USBD_SignalHandler();
Pawel Zarembski 0:01f31e923fe2 633 }
Pawel Zarembski 0:01f31e923fe2 634
Pawel Zarembski 0:01f31e923fe2 635 /*
Pawel Zarembski 0:01f31e923fe2 636 * USB Device Service Routine
Pawel Zarembski 0:01f31e923fe2 637 */
Pawel Zarembski 0:01f31e923fe2 638
Pawel Zarembski 0:01f31e923fe2 639 void USBD_Handler(void)
Pawel Zarembski 0:01f31e923fe2 640 {
Pawel Zarembski 0:01f31e923fe2 641 uint32_t istr, num, dir, ev_odd;
Pawel Zarembski 0:01f31e923fe2 642 cortex_int_state_t state;
Pawel Zarembski 0:01f31e923fe2 643 uint8_t suspended = 0;
Pawel Zarembski 0:01f31e923fe2 644
Pawel Zarembski 0:01f31e923fe2 645 // Get ISTAT
Pawel Zarembski 0:01f31e923fe2 646 state = cortex_int_get_and_disable();
Pawel Zarembski 0:01f31e923fe2 647 istr = LastIstat;
Pawel Zarembski 0:01f31e923fe2 648 LastIstat = 0;
Pawel Zarembski 0:01f31e923fe2 649 suspended = UsbSuspended;
Pawel Zarembski 0:01f31e923fe2 650 UsbSuspended = 0;
Pawel Zarembski 0:01f31e923fe2 651 cortex_int_restore(state);
Pawel Zarembski 0:01f31e923fe2 652
Pawel Zarembski 0:01f31e923fe2 653
Pawel Zarembski 0:01f31e923fe2 654 /* reset interrupt */
Pawel Zarembski 0:01f31e923fe2 655 if (istr & USB_ISTAT_USBRST_MASK) {
Pawel Zarembski 0:01f31e923fe2 656 USBD_Reset();
Pawel Zarembski 0:01f31e923fe2 657 usbd_reset_core();
Pawel Zarembski 0:01f31e923fe2 658 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 659
Pawel Zarembski 0:01f31e923fe2 660 if (USBD_RTX_DevTask) {
Pawel Zarembski 0:01f31e923fe2 661 isr_evt_set(USBD_EVT_RESET, USBD_RTX_DevTask);
Pawel Zarembski 0:01f31e923fe2 662 }
Pawel Zarembski 0:01f31e923fe2 663
Pawel Zarembski 0:01f31e923fe2 664 #else
Pawel Zarembski 0:01f31e923fe2 665
Pawel Zarembski 0:01f31e923fe2 666 if (USBD_P_Reset_Event) {
Pawel Zarembski 0:01f31e923fe2 667 USBD_P_Reset_Event();
Pawel Zarembski 0:01f31e923fe2 668 }
Pawel Zarembski 0:01f31e923fe2 669
Pawel Zarembski 0:01f31e923fe2 670 #endif
Pawel Zarembski 0:01f31e923fe2 671 }
Pawel Zarembski 0:01f31e923fe2 672
Pawel Zarembski 0:01f31e923fe2 673 /* suspend interrupt */
Pawel Zarembski 0:01f31e923fe2 674 if (istr & USB_ISTAT_SLEEP_MASK) {
Pawel Zarembski 0:01f31e923fe2 675 USBD_Suspend();
Pawel Zarembski 0:01f31e923fe2 676 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 677
Pawel Zarembski 0:01f31e923fe2 678 if (USBD_RTX_DevTask) {
Pawel Zarembski 0:01f31e923fe2 679 isr_evt_set(USBD_EVT_SUSPEND, USBD_RTX_DevTask);
Pawel Zarembski 0:01f31e923fe2 680 }
Pawel Zarembski 0:01f31e923fe2 681
Pawel Zarembski 0:01f31e923fe2 682 #else
Pawel Zarembski 0:01f31e923fe2 683
Pawel Zarembski 0:01f31e923fe2 684 if (USBD_P_Suspend_Event) {
Pawel Zarembski 0:01f31e923fe2 685 USBD_P_Suspend_Event();
Pawel Zarembski 0:01f31e923fe2 686 }
Pawel Zarembski 0:01f31e923fe2 687
Pawel Zarembski 0:01f31e923fe2 688 #endif
Pawel Zarembski 0:01f31e923fe2 689 }
Pawel Zarembski 0:01f31e923fe2 690
Pawel Zarembski 0:01f31e923fe2 691 /* resume interrupt */
Pawel Zarembski 0:01f31e923fe2 692 if (istr & USB_ISTAT_RESUME_MASK) {
Pawel Zarembski 0:01f31e923fe2 693 USBD_Resume();
Pawel Zarembski 0:01f31e923fe2 694 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 695
Pawel Zarembski 0:01f31e923fe2 696 if (USBD_RTX_DevTask) {
Pawel Zarembski 0:01f31e923fe2 697 isr_evt_set(USBD_EVT_RESUME, USBD_RTX_DevTask);
Pawel Zarembski 0:01f31e923fe2 698 }
Pawel Zarembski 0:01f31e923fe2 699
Pawel Zarembski 0:01f31e923fe2 700 #else
Pawel Zarembski 0:01f31e923fe2 701
Pawel Zarembski 0:01f31e923fe2 702 if (USBD_P_Resume_Event) {
Pawel Zarembski 0:01f31e923fe2 703 USBD_P_Resume_Event();
Pawel Zarembski 0:01f31e923fe2 704 }
Pawel Zarembski 0:01f31e923fe2 705
Pawel Zarembski 0:01f31e923fe2 706 #endif
Pawel Zarembski 0:01f31e923fe2 707 }
Pawel Zarembski 0:01f31e923fe2 708
Pawel Zarembski 0:01f31e923fe2 709 /* Start Of Frame */
Pawel Zarembski 0:01f31e923fe2 710 if (istr & USB_ISTAT_SOFTOK_MASK) {
Pawel Zarembski 0:01f31e923fe2 711 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 712
Pawel Zarembski 0:01f31e923fe2 713 if (USBD_RTX_DevTask) {
Pawel Zarembski 0:01f31e923fe2 714 isr_evt_set(USBD_EVT_SOF, USBD_RTX_DevTask);
Pawel Zarembski 0:01f31e923fe2 715 }
Pawel Zarembski 0:01f31e923fe2 716
Pawel Zarembski 0:01f31e923fe2 717 #else
Pawel Zarembski 0:01f31e923fe2 718
Pawel Zarembski 0:01f31e923fe2 719 if (USBD_P_SOF_Event) {
Pawel Zarembski 0:01f31e923fe2 720 USBD_P_SOF_Event();
Pawel Zarembski 0:01f31e923fe2 721 }
Pawel Zarembski 0:01f31e923fe2 722
Pawel Zarembski 0:01f31e923fe2 723 #endif
Pawel Zarembski 0:01f31e923fe2 724 }
Pawel Zarembski 0:01f31e923fe2 725
Pawel Zarembski 0:01f31e923fe2 726 /* Error interrupt */
Pawel Zarembski 0:01f31e923fe2 727 if (istr == USB_ISTAT_ERROR_MASK) {
Pawel Zarembski 0:01f31e923fe2 728 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 729 LastError = USB0->ERRSTAT;
Pawel Zarembski 0:01f31e923fe2 730
Pawel Zarembski 0:01f31e923fe2 731 if (USBD_RTX_DevTask) {
Pawel Zarembski 0:01f31e923fe2 732 isr_evt_set(USBD_EVT_ERROR, USBD_RTX_DevTask);
Pawel Zarembski 0:01f31e923fe2 733 }
Pawel Zarembski 0:01f31e923fe2 734
Pawel Zarembski 0:01f31e923fe2 735 #else
Pawel Zarembski 0:01f31e923fe2 736
Pawel Zarembski 0:01f31e923fe2 737 if (USBD_P_Error_Event) {
Pawel Zarembski 0:01f31e923fe2 738 USBD_P_Error_Event(USB0->ERRSTAT);
Pawel Zarembski 0:01f31e923fe2 739 }
Pawel Zarembski 0:01f31e923fe2 740
Pawel Zarembski 0:01f31e923fe2 741 #endif
Pawel Zarembski 0:01f31e923fe2 742 USB0->ERRSTAT = 0xFF;
Pawel Zarembski 0:01f31e923fe2 743 }
Pawel Zarembski 0:01f31e923fe2 744
Pawel Zarembski 0:01f31e923fe2 745 /* token interrupt */
Pawel Zarembski 0:01f31e923fe2 746 if (istr & USB_ISTAT_TOKDNE_MASK) {
Pawel Zarembski 0:01f31e923fe2 747 while (!stat_is_empty()) {
Pawel Zarembski 0:01f31e923fe2 748 uint32_t stat;
Pawel Zarembski 0:01f31e923fe2 749
Pawel Zarembski 0:01f31e923fe2 750 stat = stat_deque();
Pawel Zarembski 0:01f31e923fe2 751 num = (stat >> 4) & 0x0F;
Pawel Zarembski 0:01f31e923fe2 752 dir = (stat >> 3) & 0x01;
Pawel Zarembski 0:01f31e923fe2 753 ev_odd = (stat >> 2) & 0x01;
Pawel Zarembski 0:01f31e923fe2 754
Pawel Zarembski 0:01f31e923fe2 755 /* setup packet */
Pawel Zarembski 0:01f31e923fe2 756 if ((num == 0) && (TOK_PID((IDX(num, dir, ev_odd))) == SETUP_TOKEN)) {
Pawel Zarembski 0:01f31e923fe2 757 Data1 &= ~0x02;
Pawel Zarembski 0:01f31e923fe2 758 BD[IDX(0, TX, EVEN)].stat &= ~BD_OWN_MASK;
Pawel Zarembski 0:01f31e923fe2 759 BD[IDX(0, TX, ODD)].stat &= ~BD_OWN_MASK;
Pawel Zarembski 0:01f31e923fe2 760 Ep0ZlpOut = 0;
Pawel Zarembski 0:01f31e923fe2 761 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 762
Pawel Zarembski 0:01f31e923fe2 763 if (USBD_RTX_EPTask[num]) {
Pawel Zarembski 0:01f31e923fe2 764 isr_evt_set(USBD_EVT_SETUP, USBD_RTX_EPTask[num]);
Pawel Zarembski 0:01f31e923fe2 765 }
Pawel Zarembski 0:01f31e923fe2 766
Pawel Zarembski 0:01f31e923fe2 767 #else
Pawel Zarembski 0:01f31e923fe2 768
Pawel Zarembski 0:01f31e923fe2 769 if (USBD_P_EP[num]) {
Pawel Zarembski 0:01f31e923fe2 770 USBD_P_EP[num](USBD_EVT_SETUP);
Pawel Zarembski 0:01f31e923fe2 771 }
Pawel Zarembski 0:01f31e923fe2 772
Pawel Zarembski 0:01f31e923fe2 773 #endif
Pawel Zarembski 0:01f31e923fe2 774
Pawel Zarembski 0:01f31e923fe2 775 } else {
Pawel Zarembski 0:01f31e923fe2 776 /* OUT packet */
Pawel Zarembski 0:01f31e923fe2 777 if (TOK_PID((IDX(num, dir, ev_odd))) == OUT_TOKEN) {
Pawel Zarembski 0:01f31e923fe2 778 if (0 == num) {
Pawel Zarembski 0:01f31e923fe2 779 Ep0ZlpOut = stat & (1 << 0);
Pawel Zarembski 0:01f31e923fe2 780 }
Pawel Zarembski 0:01f31e923fe2 781 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 782
Pawel Zarembski 0:01f31e923fe2 783 if (USBD_RTX_EPTask[num]) {
Pawel Zarembski 0:01f31e923fe2 784 isr_evt_set(USBD_EVT_OUT, USBD_RTX_EPTask[num]);
Pawel Zarembski 0:01f31e923fe2 785 }
Pawel Zarembski 0:01f31e923fe2 786
Pawel Zarembski 0:01f31e923fe2 787 #else
Pawel Zarembski 0:01f31e923fe2 788
Pawel Zarembski 0:01f31e923fe2 789 if (USBD_P_EP[num]) {
Pawel Zarembski 0:01f31e923fe2 790 USBD_P_EP[num](USBD_EVT_OUT);
Pawel Zarembski 0:01f31e923fe2 791 }
Pawel Zarembski 0:01f31e923fe2 792
Pawel Zarembski 0:01f31e923fe2 793 #endif
Pawel Zarembski 0:01f31e923fe2 794 }
Pawel Zarembski 0:01f31e923fe2 795
Pawel Zarembski 0:01f31e923fe2 796 /* IN packet */
Pawel Zarembski 0:01f31e923fe2 797 if (TOK_PID((IDX(num, dir, ev_odd))) == IN_TOKEN) {
Pawel Zarembski 0:01f31e923fe2 798 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 799
Pawel Zarembski 0:01f31e923fe2 800 if (USBD_RTX_EPTask[num]) {
Pawel Zarembski 0:01f31e923fe2 801 isr_evt_set(USBD_EVT_IN, USBD_RTX_EPTask[num]);
Pawel Zarembski 0:01f31e923fe2 802 }
Pawel Zarembski 0:01f31e923fe2 803
Pawel Zarembski 0:01f31e923fe2 804 #else
Pawel Zarembski 0:01f31e923fe2 805
Pawel Zarembski 0:01f31e923fe2 806 if (USBD_P_EP[num]) {
Pawel Zarembski 0:01f31e923fe2 807 USBD_P_EP[num](USBD_EVT_IN);
Pawel Zarembski 0:01f31e923fe2 808 }
Pawel Zarembski 0:01f31e923fe2 809
Pawel Zarembski 0:01f31e923fe2 810 #endif
Pawel Zarembski 0:01f31e923fe2 811 }
Pawel Zarembski 0:01f31e923fe2 812 }
Pawel Zarembski 0:01f31e923fe2 813 }
Pawel Zarembski 0:01f31e923fe2 814 }
Pawel Zarembski 0:01f31e923fe2 815
Pawel Zarembski 0:01f31e923fe2 816 if (suspended) {
Pawel Zarembski 0:01f31e923fe2 817 USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK;
Pawel Zarembski 0:01f31e923fe2 818 }
Pawel Zarembski 0:01f31e923fe2 819 }