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_ATSAM3U2C.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 "sam3u.h"
Pawel Zarembski 0:01f31e923fe2 24 #include "util.h"
Pawel Zarembski 0:01f31e923fe2 25
Pawel Zarembski 0:01f31e923fe2 26 #define __NO_USB_LIB_C
Pawel Zarembski 0:01f31e923fe2 27 #include "usb_config.c"
Pawel Zarembski 0:01f31e923fe2 28
Pawel Zarembski 0:01f31e923fe2 29 #define UDPHS_EPTFIFO_BASE (0x20180000) /* (UDPHS_EPTFIFO) Base Address */
Pawel Zarembski 0:01f31e923fe2 30 uint32_t eptsta_copy[USBD_EP_NUM + 1];
Pawel Zarembski 0:01f31e923fe2 31
Pawel Zarembski 0:01f31e923fe2 32 /*
Pawel Zarembski 0:01f31e923fe2 33 * Calculate EP size code Function
Pawel Zarembski 0:01f31e923fe2 34 * Called during EndPoint configuration
Pawel Zarembski 0:01f31e923fe2 35 * Return Value: EP size code for given EP size
Pawel Zarembski 0:01f31e923fe2 36 */
Pawel Zarembski 0:01f31e923fe2 37
Pawel Zarembski 0:01f31e923fe2 38 static int USBD_CalcSizeEP(uint32_t size)
Pawel Zarembski 0:01f31e923fe2 39 {
Pawel Zarembski 0:01f31e923fe2 40 if (size <= 8) {
Pawel Zarembski 0:01f31e923fe2 41 return (0);
Pawel Zarembski 0:01f31e923fe2 42 } else if (size <= 16) {
Pawel Zarembski 0:01f31e923fe2 43 return (1);
Pawel Zarembski 0:01f31e923fe2 44 } else if (size <= 32) {
Pawel Zarembski 0:01f31e923fe2 45 return (2);
Pawel Zarembski 0:01f31e923fe2 46 } else if (size <= 64) {
Pawel Zarembski 0:01f31e923fe2 47 return (3);
Pawel Zarembski 0:01f31e923fe2 48 } else if (size <= 128) {
Pawel Zarembski 0:01f31e923fe2 49 return (4);
Pawel Zarembski 0:01f31e923fe2 50 } else if (size <= 256) {
Pawel Zarembski 0:01f31e923fe2 51 return (5);
Pawel Zarembski 0:01f31e923fe2 52 } else if (size <= 512) {
Pawel Zarembski 0:01f31e923fe2 53 return (6);
Pawel Zarembski 0:01f31e923fe2 54 } else if (size <= 1024) {
Pawel Zarembski 0:01f31e923fe2 55 return (7);
Pawel Zarembski 0:01f31e923fe2 56 }
Pawel Zarembski 0:01f31e923fe2 57
Pawel Zarembski 0:01f31e923fe2 58 return (0);
Pawel Zarembski 0:01f31e923fe2 59 }
Pawel Zarembski 0:01f31e923fe2 60
Pawel Zarembski 0:01f31e923fe2 61
Pawel Zarembski 0:01f31e923fe2 62 /*
Pawel Zarembski 0:01f31e923fe2 63 * Retrieve maximum EP size Function
Pawel Zarembski 0:01f31e923fe2 64 * Called during EndPoint configuration
Pawel Zarembski 0:01f31e923fe2 65 * Return Value: maximum size for given EP
Pawel Zarembski 0:01f31e923fe2 66 */
Pawel Zarembski 0:01f31e923fe2 67
Pawel Zarembski 0:01f31e923fe2 68 static int USBD_GetSizeEP(uint32_t EPNum)
Pawel Zarembski 0:01f31e923fe2 69 {
Pawel Zarembski 0:01f31e923fe2 70 switch (EPNum & 0x0F) {
Pawel Zarembski 0:01f31e923fe2 71 case 0:
Pawel Zarembski 0:01f31e923fe2 72 return (64); /* Maximum size is 64 bytes */
Pawel Zarembski 0:01f31e923fe2 73
Pawel Zarembski 0:01f31e923fe2 74 case 1:
Pawel Zarembski 0:01f31e923fe2 75 case 2:
Pawel Zarembski 0:01f31e923fe2 76 return (512); /* Maximum size is 512 bytes */
Pawel Zarembski 0:01f31e923fe2 77
Pawel Zarembski 0:01f31e923fe2 78 case 3:
Pawel Zarembski 0:01f31e923fe2 79 case 4:
Pawel Zarembski 0:01f31e923fe2 80 return (64); /* Maximum size is 64 bytes */
Pawel Zarembski 0:01f31e923fe2 81
Pawel Zarembski 0:01f31e923fe2 82 case 5:
Pawel Zarembski 0:01f31e923fe2 83 case 6:
Pawel Zarembski 0:01f31e923fe2 84 return (1024); /* Maximum size is 1024 bytes */
Pawel Zarembski 0:01f31e923fe2 85
Pawel Zarembski 0:01f31e923fe2 86 default:
Pawel Zarembski 0:01f31e923fe2 87 return (0); /* Non existant endpoint */
Pawel Zarembski 0:01f31e923fe2 88 }
Pawel Zarembski 0:01f31e923fe2 89 }
Pawel Zarembski 0:01f31e923fe2 90
Pawel Zarembski 0:01f31e923fe2 91
Pawel Zarembski 0:01f31e923fe2 92 /*
Pawel Zarembski 0:01f31e923fe2 93 * USB Device Interrupt enable
Pawel Zarembski 0:01f31e923fe2 94 * Called by USBD_Init to enable the USB Interrupt
Pawel Zarembski 0:01f31e923fe2 95 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 96 */
Pawel Zarembski 0:01f31e923fe2 97
Pawel Zarembski 0:01f31e923fe2 98 void USBD_IntrEna(void)
Pawel Zarembski 0:01f31e923fe2 99 {
Pawel Zarembski 0:01f31e923fe2 100 NVIC_EnableIRQ(UDPHS_IRQn); /* Enable USB interrupt */
Pawel Zarembski 0:01f31e923fe2 101 }
Pawel Zarembski 0:01f31e923fe2 102
Pawel Zarembski 0:01f31e923fe2 103
Pawel Zarembski 0:01f31e923fe2 104 /*
Pawel Zarembski 0:01f31e923fe2 105 * USB Device Initialize Function
Pawel Zarembski 0:01f31e923fe2 106 * Called by the User to initialize USB Device
Pawel Zarembski 0:01f31e923fe2 107 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 108 */
Pawel Zarembski 0:01f31e923fe2 109
Pawel Zarembski 0:01f31e923fe2 110 void USBD_Init(void)
Pawel Zarembski 0:01f31e923fe2 111 {
Pawel Zarembski 0:01f31e923fe2 112 uint32_t n;
Pawel Zarembski 0:01f31e923fe2 113 /* Enables the 48MHz USB Clock UDPCK and System Peripheral USB Clock */
Pawel Zarembski 0:01f31e923fe2 114 PMC->PMC_WPMR = 0x504D4300; /* Disable write protect */
Pawel Zarembski 0:01f31e923fe2 115 PMC->PMC_PCER0 = (1 << ID_UDPHS); /* enable clock for UPDHS */
Pawel Zarembski 0:01f31e923fe2 116 PMC->CKGR_UCKR = (CKGR_UCKR_UPLLCOUNT(15) | CKGR_UCKR_UPLLEN);
Pawel Zarembski 0:01f31e923fe2 117
Pawel Zarembski 0:01f31e923fe2 118 while (!(PMC->PMC_SR & PMC_SR_LOCKU)); /* wait until PLL is locked */
Pawel Zarembski 0:01f31e923fe2 119
Pawel Zarembski 0:01f31e923fe2 120 PMC->PMC_WPMR = 0x504D4301; /* Enable write protect */
Pawel Zarembski 0:01f31e923fe2 121 /* Configure the pull-up on D+ and disconnect it */
Pawel Zarembski 0:01f31e923fe2 122 UDPHS->UDPHS_CTRL |= UDPHS_CTRL_DETACH; /* Detach */
Pawel Zarembski 0:01f31e923fe2 123 UDPHS->UDPHS_CTRL |= UDPHS_CTRL_PULLD_DIS; /* Disable Pull Down */
Pawel Zarembski 0:01f31e923fe2 124 /* Reset IP UDPHS */
Pawel Zarembski 0:01f31e923fe2 125 UDPHS->UDPHS_CTRL &= ~UDPHS_CTRL_EN_UDPHS;
Pawel Zarembski 0:01f31e923fe2 126 UDPHS->UDPHS_CTRL |= UDPHS_CTRL_EN_UDPHS;
Pawel Zarembski 0:01f31e923fe2 127 #if (!USBD_HS_ENABLE) /* If HS disabled */
Pawel Zarembski 0:01f31e923fe2 128 UDPHS->UDPHS_TST |= (3 & UDPHS_TST_SPEED_CFG_Msk);
Pawel Zarembski 0:01f31e923fe2 129 #endif
Pawel Zarembski 0:01f31e923fe2 130
Pawel Zarembski 0:01f31e923fe2 131 /* Disable DMA for UDPHS */
Pawel Zarembski 0:01f31e923fe2 132 for (n = 1; n < (UDPHSDMA_NUMBER); n++) {
Pawel Zarembski 0:01f31e923fe2 133 /* RESET endpoint canal DMA: */
Pawel Zarembski 0:01f31e923fe2 134 UDPHS->UDPHS_DMA[n].UDPHS_DMACONTROL = 0; /* STOP command */
Pawel Zarembski 0:01f31e923fe2 135 /* Disable endpoint */
Pawel Zarembski 0:01f31e923fe2 136 UDPHS->UDPHS_EPT[n].UDPHS_EPTCTLDIS = 0xFFFFFFFF;
Pawel Zarembski 0:01f31e923fe2 137 /* Clear status endpoint */
Pawel Zarembski 0:01f31e923fe2 138 UDPHS->UDPHS_EPT[n].UDPHS_EPTCLRSTA = 0xFFFFFFFF;
Pawel Zarembski 0:01f31e923fe2 139 /* Reset endpoint config */
Pawel Zarembski 0:01f31e923fe2 140 UDPHS->UDPHS_EPT[n].UDPHS_EPTCTLENB = 0;
Pawel Zarembski 0:01f31e923fe2 141 /* Reset DMA channel (Buff count and Control field) */
Pawel Zarembski 0:01f31e923fe2 142 UDPHS->UDPHS_DMA[n].UDPHS_DMACONTROL = (0x1 << 1); /* NON STOP command */
Pawel Zarembski 0:01f31e923fe2 143 /* Reset DMA channel 0 (STOP) */
Pawel Zarembski 0:01f31e923fe2 144 UDPHS->UDPHS_DMA[n].UDPHS_DMACONTROL = 0; /* STOP command */
Pawel Zarembski 0:01f31e923fe2 145 /* Clear DMA channel status (read the register for clear it) */
Pawel Zarembski 0:01f31e923fe2 146 UDPHS->UDPHS_DMA[n].UDPHS_DMASTATUS = UDPHS->UDPHS_DMA[n].UDPHS_DMASTATUS;
Pawel Zarembski 0:01f31e923fe2 147 }
Pawel Zarembski 0:01f31e923fe2 148
Pawel Zarembski 0:01f31e923fe2 149 UDPHS->UDPHS_IEN = 0;
Pawel Zarembski 0:01f31e923fe2 150 UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_UPSTR_RES |
Pawel Zarembski 0:01f31e923fe2 151 UDPHS_CLRINT_ENDOFRSM |
Pawel Zarembski 0:01f31e923fe2 152 UDPHS_CLRINT_WAKE_UP |
Pawel Zarembski 0:01f31e923fe2 153 UDPHS_CLRINT_ENDRESET |
Pawel Zarembski 0:01f31e923fe2 154 UDPHS_CLRINT_INT_SOF |
Pawel Zarembski 0:01f31e923fe2 155 UDPHS_CLRINT_MICRO_SOF |
Pawel Zarembski 0:01f31e923fe2 156 UDPHS_CLRINT_DET_SUSPD;
Pawel Zarembski 0:01f31e923fe2 157 USBD_IntrEna(); /* Enable USB interrupt */
Pawel Zarembski 0:01f31e923fe2 158 }
Pawel Zarembski 0:01f31e923fe2 159
Pawel Zarembski 0:01f31e923fe2 160
Pawel Zarembski 0:01f31e923fe2 161 /*
Pawel Zarembski 0:01f31e923fe2 162 * USB Device Connect Function
Pawel Zarembski 0:01f31e923fe2 163 * Called by the User to Connect/Disconnect USB Device
Pawel Zarembski 0:01f31e923fe2 164 * Parameters: con: Connect/Disconnect
Pawel Zarembski 0:01f31e923fe2 165 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 166 */
Pawel Zarembski 0:01f31e923fe2 167
Pawel Zarembski 0:01f31e923fe2 168 void USBD_Connect(BOOL con)
Pawel Zarembski 0:01f31e923fe2 169 {
Pawel Zarembski 0:01f31e923fe2 170 if (con) {
Pawel Zarembski 0:01f31e923fe2 171 UDPHS->UDPHS_CTRL &= ~UDPHS_CTRL_DETACH; /* Pull Up on DP */
Pawel Zarembski 0:01f31e923fe2 172 UDPHS->UDPHS_CTRL |= UDPHS_CTRL_PULLD_DIS; /* Disable Pull Down */
Pawel Zarembski 0:01f31e923fe2 173 } else {
Pawel Zarembski 0:01f31e923fe2 174 UDPHS->UDPHS_CTRL |= UDPHS_CTRL_DETACH; /* Detach */
Pawel Zarembski 0:01f31e923fe2 175 UDPHS->UDPHS_CTRL &= ~UDPHS_CTRL_PULLD_DIS; /* Enable Pull Down */
Pawel Zarembski 0:01f31e923fe2 176 }
Pawel Zarembski 0:01f31e923fe2 177 }
Pawel Zarembski 0:01f31e923fe2 178
Pawel Zarembski 0:01f31e923fe2 179 /*
Pawel Zarembski 0:01f31e923fe2 180 * USB Device Reset Function
Pawel Zarembski 0:01f31e923fe2 181 * Called automatically on USB Device Reset
Pawel Zarembski 0:01f31e923fe2 182 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 183 */
Pawel Zarembski 0:01f31e923fe2 184 extern U8 USBD_ConfigDescriptor_HS[];
Pawel Zarembski 0:01f31e923fe2 185 extern U8 USBD_ConfigDescriptor[];
Pawel Zarembski 0:01f31e923fe2 186 void USBD_Reset(void)
Pawel Zarembski 0:01f31e923fe2 187 {
Pawel Zarembski 0:01f31e923fe2 188 uint32_t ep, EPMask;
Pawel Zarembski 0:01f31e923fe2 189 EPMask = ((1 << (USBD_EP_NUM + 1)) - 1);
Pawel Zarembski 0:01f31e923fe2 190
Pawel Zarembski 0:01f31e923fe2 191 /* Reset & Disable USB Endpoints */
Pawel Zarembski 0:01f31e923fe2 192 for (ep = 0; ep <= USBD_EP_NUM; ep++) {
Pawel Zarembski 0:01f31e923fe2 193 UDPHS->UDPHS_EPT[ep].UDPHS_EPTCFG = 0;
Pawel Zarembski 0:01f31e923fe2 194 UDPHS->UDPHS_EPT[ep].UDPHS_EPTCTLDIS = (0x1 << 0); /* Disable EP */
Pawel Zarembski 0:01f31e923fe2 195 eptsta_copy[ep] = 0;
Pawel Zarembski 0:01f31e923fe2 196 }
Pawel Zarembski 0:01f31e923fe2 197
Pawel Zarembski 0:01f31e923fe2 198 UDPHS->UDPHS_EPTRST = EPMask; /* Reset EPs */
Pawel Zarembski 0:01f31e923fe2 199 UDPHS->UDPHS_EPTRST = 0;
Pawel Zarembski 0:01f31e923fe2 200 /* Setup USB Interrupts */ /* note: Micro_SOF not yet handled */
Pawel Zarembski 0:01f31e923fe2 201 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 202 UDPHS->UDPHS_IEN = ((USBD_RTX_DevTask != 0) ? UDPHS_IEN_DET_SUSPD : 0) |
Pawel Zarembski 0:01f31e923fe2 203 ((USBD_RTX_DevTask != 0) ? UDPHS_IEN_MICRO_SOF : 0) |
Pawel Zarembski 0:01f31e923fe2 204 ((USBD_RTX_DevTask != 0) ? UDPHS_IEN_INT_SOF : 0) |
Pawel Zarembski 0:01f31e923fe2 205 ((USBD_RTX_DevTask != 0) ? UDPHS_IEN_ENDRESET : 0) |
Pawel Zarembski 0:01f31e923fe2 206 // ((USBD_RTX_DevTask != 0) ? UDPHS_IEN_WAKE_UP : 0) |
Pawel Zarembski 0:01f31e923fe2 207 // ((USBD_RTX_DevTask != 0) ? UDPHS_IEN_UPSTR_RES : 0) |
Pawel Zarembski 0:01f31e923fe2 208 #else
Pawel Zarembski 0:01f31e923fe2 209 UDPHS->UDPHS_IEN = ((USBD_P_Suspend_Event != 0) ? UDPHS_IEN_DET_SUSPD : 0) |
Pawel Zarembski 0:01f31e923fe2 210 ((USBD_P_SOF_Event != 0) ? UDPHS_IEN_MICRO_SOF : 0) |
Pawel Zarembski 0:01f31e923fe2 211 ((USBD_P_SOF_Event != 0) ? UDPHS_IEN_INT_SOF : 0) |
Pawel Zarembski 0:01f31e923fe2 212 ((USBD_P_Reset_Event != 0) ? UDPHS_IEN_ENDRESET : 0) |
Pawel Zarembski 0:01f31e923fe2 213 // ((USBD_P_WakeUp_Event != 0) ? UDPHS_IEN_WAKE_UP : 0) |
Pawel Zarembski 0:01f31e923fe2 214 // ((USBD_P_Resume_Event != 0) ? UDPHS_IEN_UPSTR_RES : 0) |
Pawel Zarembski 0:01f31e923fe2 215 #endif
Pawel Zarembski 0:01f31e923fe2 216 (EPMask << 8);
Pawel Zarembski 0:01f31e923fe2 217 /* Setup Control Endpoint 0 */
Pawel Zarembski 0:01f31e923fe2 218 UDPHS->UDPHS_EPT[0].UDPHS_EPTCFG = UDPHS_EPTCFG_BK_NUMBER_1 |
Pawel Zarembski 0:01f31e923fe2 219 UDPHS_EPTCFG_EPT_TYPE_CTRL8 |
Pawel Zarembski 0:01f31e923fe2 220 USBD_CalcSizeEP(USBD_MAX_PACKET0) ;
Pawel Zarembski 0:01f31e923fe2 221 UDPHS->UDPHS_EPT[0].UDPHS_EPTCTLENB = UDPHS_EPTCTLENB_RXRDY_TXKL |
Pawel Zarembski 0:01f31e923fe2 222 UDPHS_EPTCTLENB_TX_COMPLT |
Pawel Zarembski 0:01f31e923fe2 223 UDPHS_EPTCTLENB_RX_SETUP |
Pawel Zarembski 0:01f31e923fe2 224 UDPHS_EPTCTLENB_STALL_SNT |
Pawel Zarembski 0:01f31e923fe2 225 UDPHS_EPTCTLENB_NYET_DIS |
Pawel Zarembski 0:01f31e923fe2 226 UDPHS_EPTCTLENB_EPT_ENABL;
Pawel Zarembski 0:01f31e923fe2 227
Pawel Zarembski 0:01f31e923fe2 228
Pawel Zarembski 0:01f31e923fe2 229 #if (USBD_HS_ENABLE == 1)
Pawel Zarembski 0:01f31e923fe2 230 U8 * config_desc = USBD_ConfigDescriptor_HS;
Pawel Zarembski 0:01f31e923fe2 231 #else
Pawel Zarembski 0:01f31e923fe2 232 U8 * config_desc = USBD_ConfigDescriptor;
Pawel Zarembski 0:01f31e923fe2 233 #endif
Pawel Zarembski 0:01f31e923fe2 234
Pawel Zarembski 0:01f31e923fe2 235 while (((USB_ENDPOINT_DESCRIPTOR *)config_desc)->bLength > 0) {
Pawel Zarembski 0:01f31e923fe2 236 if (((USB_ENDPOINT_DESCRIPTOR *)config_desc)->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE) {
Pawel Zarembski 0:01f31e923fe2 237 uint32_t num, type, dir, size, banks, interval;
Pawel Zarembski 0:01f31e923fe2 238 USB_ENDPOINT_DESCRIPTOR *pEPD = (USB_ENDPOINT_DESCRIPTOR *)config_desc;
Pawel Zarembski 0:01f31e923fe2 239 num = pEPD->bEndpointAddress & 0x0F;
Pawel Zarembski 0:01f31e923fe2 240 type = pEPD->bmAttributes & USB_ENDPOINT_TYPE_MASK;
Pawel Zarembski 0:01f31e923fe2 241 dir = pEPD->bEndpointAddress >> 7;
Pawel Zarembski 0:01f31e923fe2 242 interval = pEPD->bInterval;
Pawel Zarembski 0:01f31e923fe2 243 size = USBD_CalcSizeEP(pEPD->wMaxPacketSize);
Pawel Zarembski 0:01f31e923fe2 244 banks = 1;
Pawel Zarembski 0:01f31e923fe2 245 UDPHS->UDPHS_EPT[num].UDPHS_EPTCFG = (interval << 8) |
Pawel Zarembski 0:01f31e923fe2 246 (banks << 6) |
Pawel Zarembski 0:01f31e923fe2 247 (type << 4) |
Pawel Zarembski 0:01f31e923fe2 248 (dir << 3) |
Pawel Zarembski 0:01f31e923fe2 249 (size << 0) ;
Pawel Zarembski 0:01f31e923fe2 250 }
Pawel Zarembski 0:01f31e923fe2 251 config_desc += ((USB_ENDPOINT_DESCRIPTOR *)config_desc)->bLength;
Pawel Zarembski 0:01f31e923fe2 252 }
Pawel Zarembski 0:01f31e923fe2 253 }
Pawel Zarembski 0:01f31e923fe2 254
Pawel Zarembski 0:01f31e923fe2 255
Pawel Zarembski 0:01f31e923fe2 256 /*
Pawel Zarembski 0:01f31e923fe2 257 * USB Device Suspend Function
Pawel Zarembski 0:01f31e923fe2 258 * Called automatically on USB Device Suspend
Pawel Zarembski 0:01f31e923fe2 259 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 260 */
Pawel Zarembski 0:01f31e923fe2 261
Pawel Zarembski 0:01f31e923fe2 262 void USBD_Suspend(void)
Pawel Zarembski 0:01f31e923fe2 263 {
Pawel Zarembski 0:01f31e923fe2 264 UDPHS->UDPHS_IEN &= ~UDPHS_IEN_DET_SUSPD;
Pawel Zarembski 0:01f31e923fe2 265 UDPHS->UDPHS_IEN |= UDPHS_IEN_WAKE_UP;
Pawel Zarembski 0:01f31e923fe2 266 }
Pawel Zarembski 0:01f31e923fe2 267
Pawel Zarembski 0:01f31e923fe2 268
Pawel Zarembski 0:01f31e923fe2 269 /*
Pawel Zarembski 0:01f31e923fe2 270 * USB Device Resume Function
Pawel Zarembski 0:01f31e923fe2 271 * Called automatically on USB Device Resume
Pawel Zarembski 0:01f31e923fe2 272 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 273 */
Pawel Zarembski 0:01f31e923fe2 274
Pawel Zarembski 0:01f31e923fe2 275 void USBD_Resume(void)
Pawel Zarembski 0:01f31e923fe2 276 {
Pawel Zarembski 0:01f31e923fe2 277 UDPHS->UDPHS_IEN &= ~UDPHS_IEN_WAKE_UP;
Pawel Zarembski 0:01f31e923fe2 278 UDPHS->UDPHS_IEN |= UDPHS_IEN_DET_SUSPD;
Pawel Zarembski 0:01f31e923fe2 279 }
Pawel Zarembski 0:01f31e923fe2 280
Pawel Zarembski 0:01f31e923fe2 281
Pawel Zarembski 0:01f31e923fe2 282 /*
Pawel Zarembski 0:01f31e923fe2 283 * USB Device Remote Wakeup Function
Pawel Zarembski 0:01f31e923fe2 284 * Called automatically on USB Device Remote Wakeup
Pawel Zarembski 0:01f31e923fe2 285 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 286 */
Pawel Zarembski 0:01f31e923fe2 287
Pawel Zarembski 0:01f31e923fe2 288 void USBD_WakeUp(void)
Pawel Zarembski 0:01f31e923fe2 289 {
Pawel Zarembski 0:01f31e923fe2 290 UDPHS->UDPHS_IEN |= UDPHS_IEN_UPSTR_RES;
Pawel Zarembski 0:01f31e923fe2 291 UDPHS->UDPHS_CTRL |= UDPHS_CTRL_REWAKEUP;
Pawel Zarembski 0:01f31e923fe2 292 }
Pawel Zarembski 0:01f31e923fe2 293
Pawel Zarembski 0:01f31e923fe2 294
Pawel Zarembski 0:01f31e923fe2 295 /*
Pawel Zarembski 0:01f31e923fe2 296 * USB Device Remote Wakeup Configuration Function
Pawel Zarembski 0:01f31e923fe2 297 * Parameters: cfg: Device Enable/Disable
Pawel Zarembski 0:01f31e923fe2 298 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 299 */
Pawel Zarembski 0:01f31e923fe2 300
Pawel Zarembski 0:01f31e923fe2 301 void USBD_WakeUpCfg(BOOL cfg)
Pawel Zarembski 0:01f31e923fe2 302 {
Pawel Zarembski 0:01f31e923fe2 303 if (cfg) {
Pawel Zarembski 0:01f31e923fe2 304 /* Enable wakeup mechanism */
Pawel Zarembski 0:01f31e923fe2 305 } else {
Pawel Zarembski 0:01f31e923fe2 306 UDPHS->UDPHS_CTRL &= ~UDPHS_CTRL_REWAKEUP;
Pawel Zarembski 0:01f31e923fe2 307 UDPHS->UDPHS_IEN &= ~UDPHS_IEN_UPSTR_RES;
Pawel Zarembski 0:01f31e923fe2 308 }
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 * USB Device Set Address Function
Pawel Zarembski 0:01f31e923fe2 314 * Parameters: adr: USB Device Address
Pawel Zarembski 0:01f31e923fe2 315 * setup: Called in setup stage (!=0), else after status stage
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_SetAddress(uint32_t adr, uint32_t setup)
Pawel Zarembski 0:01f31e923fe2 320 {
Pawel Zarembski 0:01f31e923fe2 321 if (setup) {
Pawel Zarembski 0:01f31e923fe2 322 return;
Pawel Zarembski 0:01f31e923fe2 323 }
Pawel Zarembski 0:01f31e923fe2 324
Pawel Zarembski 0:01f31e923fe2 325 if (adr) {
Pawel Zarembski 0:01f31e923fe2 326 UDPHS->UDPHS_CTRL |= (UDPHS_CTRL_FADDR_EN | adr);
Pawel Zarembski 0:01f31e923fe2 327 } else {
Pawel Zarembski 0:01f31e923fe2 328 UDPHS->UDPHS_CTRL &= ~(UDPHS_CTRL_FADDR_EN | UDPHS_CTRL_DEV_ADDR_Msk);
Pawel Zarembski 0:01f31e923fe2 329 }
Pawel Zarembski 0:01f31e923fe2 330 }
Pawel Zarembski 0:01f31e923fe2 331
Pawel Zarembski 0:01f31e923fe2 332
Pawel Zarembski 0:01f31e923fe2 333 /*
Pawel Zarembski 0:01f31e923fe2 334 * USB Device Configure Function
Pawel Zarembski 0:01f31e923fe2 335 * Parameters: cfg: Device Configure/Deconfigure
Pawel Zarembski 0:01f31e923fe2 336 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 337 */
Pawel Zarembski 0:01f31e923fe2 338
Pawel Zarembski 0:01f31e923fe2 339 void USBD_Configure(BOOL cfg)
Pawel Zarembski 0:01f31e923fe2 340 {
Pawel Zarembski 0:01f31e923fe2 341 /* Performed by Hardware */
Pawel Zarembski 0:01f31e923fe2 342 }
Pawel Zarembski 0:01f31e923fe2 343
Pawel Zarembski 0:01f31e923fe2 344
Pawel Zarembski 0:01f31e923fe2 345 /*
Pawel Zarembski 0:01f31e923fe2 346 * Configure USB Device Endpoint according to Descriptor
Pawel Zarembski 0:01f31e923fe2 347 * Parameters: pEPD: Pointer to Device Endpoint Descriptor
Pawel Zarembski 0:01f31e923fe2 348 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 349 */
Pawel Zarembski 0:01f31e923fe2 350
Pawel Zarembski 0:01f31e923fe2 351 void USBD_ConfigEP(USB_ENDPOINT_DESCRIPTOR *pEPD)
Pawel Zarembski 0:01f31e923fe2 352 {
Pawel Zarembski 0:01f31e923fe2 353 uint32_t num;//, type, dir, size, banks, interval;
Pawel Zarembski 0:01f31e923fe2 354 num = pEPD->bEndpointAddress & 0x0F;
Pawel Zarembski 0:01f31e923fe2 355 /*type = pEPD->bmAttributes & USB_ENDPOINT_TYPE_MASK;
Pawel Zarembski 0:01f31e923fe2 356 dir = pEPD->bEndpointAddress >> 7;
Pawel Zarembski 0:01f31e923fe2 357 interval = pEPD->bInterval;
Pawel Zarembski 0:01f31e923fe2 358 size = USBD_CalcSizeEP(pEPD->wMaxPacketSize);
Pawel Zarembski 0:01f31e923fe2 359 banks = 1;
Pawel Zarembski 0:01f31e923fe2 360 */
Pawel Zarembski 0:01f31e923fe2 361 /* Check if MaxPacketSize fits for EndPoint */
Pawel Zarembski 0:01f31e923fe2 362 if (pEPD->wMaxPacketSize <= USBD_GetSizeEP(num)) {
Pawel Zarembski 0:01f31e923fe2 363 /*UDPHS->UDPHS_EPT[num].UDPHS_EPTCFG = (interval << 8) |
Pawel Zarembski 0:01f31e923fe2 364 (banks << 6) |
Pawel Zarembski 0:01f31e923fe2 365 (type << 4) |
Pawel Zarembski 0:01f31e923fe2 366 (dir << 3) |
Pawel Zarembski 0:01f31e923fe2 367 //(size << 0) ;
Pawel Zarembski 0:01f31e923fe2 368 6;*/
Pawel Zarembski 0:01f31e923fe2 369 UDPHS->UDPHS_EPT[num].UDPHS_EPTCTLENB =
Pawel Zarembski 0:01f31e923fe2 370 (0x1 << 9) | /* Received OUT Data Interrupt Enable */
Pawel Zarembski 0:01f31e923fe2 371 (0x1 << 10) | /* Transmitted IN Data Complete Interrupt Enable */
Pawel Zarembski 0:01f31e923fe2 372 (0x0 << 4) | /* NYET Disable (Only for High Speed Bulk OUT endpoints) */
Pawel Zarembski 0:01f31e923fe2 373 (0x1 << 13) ; /* Stall Sent /ISO CRC Error/Number of Transaction Error */
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 /*
Pawel Zarembski 0:01f31e923fe2 379 * Set Direction for USB Device Control Endpoint
Pawel Zarembski 0:01f31e923fe2 380 * Parameters: dir: Out (dir == 0), In (dir <> 0)
Pawel Zarembski 0:01f31e923fe2 381 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 382 */
Pawel Zarembski 0:01f31e923fe2 383
Pawel Zarembski 0:01f31e923fe2 384 void USBD_DirCtrlEP(uint32_t dir)
Pawel Zarembski 0:01f31e923fe2 385 {
Pawel Zarembski 0:01f31e923fe2 386 /* Performed by Hardware */
Pawel Zarembski 0:01f31e923fe2 387 }
Pawel Zarembski 0:01f31e923fe2 388
Pawel Zarembski 0:01f31e923fe2 389
Pawel Zarembski 0:01f31e923fe2 390 /*
Pawel Zarembski 0:01f31e923fe2 391 * Enable USB Device Endpoint
Pawel Zarembski 0:01f31e923fe2 392 * Parameters: EPNum: Device Endpoint Number
Pawel Zarembski 0:01f31e923fe2 393 * EPNum.0..3: Address
Pawel Zarembski 0:01f31e923fe2 394 * EPNum.7: Dir
Pawel Zarembski 0:01f31e923fe2 395 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 396 */
Pawel Zarembski 0:01f31e923fe2 397
Pawel Zarembski 0:01f31e923fe2 398 void USBD_EnableEP(uint32_t EPNum)
Pawel Zarembski 0:01f31e923fe2 399 {
Pawel Zarembski 0:01f31e923fe2 400 UDPHS->UDPHS_EPT[EPNum & 0x0F].UDPHS_EPTCTLENB = (0x1 << 0); /* EP Enable */
Pawel Zarembski 0:01f31e923fe2 401 eptsta_copy[EPNum & 0x0F] = UDPHS->UDPHS_EPT[EPNum].UDPHS_EPTSETSTA;
Pawel Zarembski 0:01f31e923fe2 402 }
Pawel Zarembski 0:01f31e923fe2 403
Pawel Zarembski 0:01f31e923fe2 404
Pawel Zarembski 0:01f31e923fe2 405 /*
Pawel Zarembski 0:01f31e923fe2 406 * Disable USB Device Endpoint
Pawel Zarembski 0:01f31e923fe2 407 * Parameters: EPNum: Device Endpoint Number
Pawel Zarembski 0:01f31e923fe2 408 * EPNum.0..3: Address
Pawel Zarembski 0:01f31e923fe2 409 * EPNum.7: Dir
Pawel Zarembski 0:01f31e923fe2 410 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 411 */
Pawel Zarembski 0:01f31e923fe2 412
Pawel Zarembski 0:01f31e923fe2 413 void USBD_DisableEP(uint32_t EPNum)
Pawel Zarembski 0:01f31e923fe2 414 {
Pawel Zarembski 0:01f31e923fe2 415 UDPHS->UDPHS_EPT[EPNum & 0x0F].UDPHS_EPTCTLDIS = (0x1 << 0); /* EP Disable */
Pawel Zarembski 0:01f31e923fe2 416 eptsta_copy[EPNum & 0x0F] = UDPHS->UDPHS_EPT[EPNum].UDPHS_EPTSETSTA;
Pawel Zarembski 0:01f31e923fe2 417 }
Pawel Zarembski 0:01f31e923fe2 418
Pawel Zarembski 0:01f31e923fe2 419
Pawel Zarembski 0:01f31e923fe2 420 /*
Pawel Zarembski 0:01f31e923fe2 421 * Reset USB Device Endpoint
Pawel Zarembski 0:01f31e923fe2 422 * Parameters: EPNum: Device Endpoint Number
Pawel Zarembski 0:01f31e923fe2 423 * EPNum.0..3: Address
Pawel Zarembski 0:01f31e923fe2 424 * EPNum.7: Dir
Pawel Zarembski 0:01f31e923fe2 425 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 426 */
Pawel Zarembski 0:01f31e923fe2 427
Pawel Zarembski 0:01f31e923fe2 428 void USBD_ResetEP(uint32_t EPNum)
Pawel Zarembski 0:01f31e923fe2 429 {
Pawel Zarembski 0:01f31e923fe2 430 EPNum &= 0x0F;
Pawel Zarembski 0:01f31e923fe2 431 UDPHS->UDPHS_EPT[EPNum].UDPHS_EPTCLRSTA = (0x1 << 6) | /* Data Toggle Clear*/
Pawel Zarembski 0:01f31e923fe2 432 (0x1 << 5); /* Stall Req Set */
Pawel Zarembski 0:01f31e923fe2 433 UDPHS->UDPHS_EPTRST |= (1 << EPNum); /* Reset endpoint */
Pawel Zarembski 0:01f31e923fe2 434 UDPHS->UDPHS_EPTRST &= ~(1 << EPNum);
Pawel Zarembski 0:01f31e923fe2 435 eptsta_copy[EPNum] = UDPHS->UDPHS_EPT[EPNum].UDPHS_EPTSETSTA;
Pawel Zarembski 0:01f31e923fe2 436 }
Pawel Zarembski 0:01f31e923fe2 437
Pawel Zarembski 0:01f31e923fe2 438
Pawel Zarembski 0:01f31e923fe2 439 /*
Pawel Zarembski 0:01f31e923fe2 440 * Set Stall for USB Device Endpoint
Pawel Zarembski 0:01f31e923fe2 441 * Parameters: EPNum: Device Endpoint Number
Pawel Zarembski 0:01f31e923fe2 442 * EPNum.0..3: Address
Pawel Zarembski 0:01f31e923fe2 443 * EPNum.7: Dir
Pawel Zarembski 0:01f31e923fe2 444 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 445 */
Pawel Zarembski 0:01f31e923fe2 446
Pawel Zarembski 0:01f31e923fe2 447 void USBD_SetStallEP(uint32_t EPNum)
Pawel Zarembski 0:01f31e923fe2 448 {
Pawel Zarembski 0:01f31e923fe2 449 UDPHS->UDPHS_EPT[EPNum & 0x0F].UDPHS_EPTSETSTA = (0x1 << 5); /* Stall Set */
Pawel Zarembski 0:01f31e923fe2 450 eptsta_copy[EPNum & 0x0F] |= 0x1 << 5;
Pawel Zarembski 0:01f31e923fe2 451 }
Pawel Zarembski 0:01f31e923fe2 452
Pawel Zarembski 0:01f31e923fe2 453
Pawel Zarembski 0:01f31e923fe2 454 /*
Pawel Zarembski 0:01f31e923fe2 455 * Clear Stall for USB Device Endpoint
Pawel Zarembski 0:01f31e923fe2 456 * Parameters: EPNum: Device Endpoint Number
Pawel Zarembski 0:01f31e923fe2 457 * EPNum.0..3: Address
Pawel Zarembski 0:01f31e923fe2 458 * EPNum.7: Dir
Pawel Zarembski 0:01f31e923fe2 459 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 460 */
Pawel Zarembski 0:01f31e923fe2 461
Pawel Zarembski 0:01f31e923fe2 462 void USBD_ClrStallEP(uint32_t EPNum)
Pawel Zarembski 0:01f31e923fe2 463 {
Pawel Zarembski 0:01f31e923fe2 464 UDPHS->UDPHS_EPT[EPNum & 0x0F].UDPHS_EPTCLRSTA = (0x1 << 6) | /* Clr Toggle */
Pawel Zarembski 0:01f31e923fe2 465 (0x1 << 5); /* Stall Clear*/
Pawel Zarembski 0:01f31e923fe2 466 eptsta_copy[EPNum & 0x0F] &= ~(0x1 << 5);
Pawel Zarembski 0:01f31e923fe2 467 }
Pawel Zarembski 0:01f31e923fe2 468
Pawel Zarembski 0:01f31e923fe2 469
Pawel Zarembski 0:01f31e923fe2 470 /*
Pawel Zarembski 0:01f31e923fe2 471 * Read USB Device Endpoint Data
Pawel Zarembski 0:01f31e923fe2 472 * Parameters: EPNum: Device Endpoint Number
Pawel Zarembski 0:01f31e923fe2 473 * EPNum.0..3: Address
Pawel Zarembski 0:01f31e923fe2 474 * EPNum.7: Dir
Pawel Zarembski 0:01f31e923fe2 475 * pData: Pointer to Data Buffer
Pawel Zarembski 0:01f31e923fe2 476 * Return Value: Number of bytes read
Pawel Zarembski 0:01f31e923fe2 477 */
Pawel Zarembski 0:01f31e923fe2 478
Pawel Zarembski 0:01f31e923fe2 479 uint32_t USBD_ReadEP(uint32_t EPNum, uint8_t *pData, uint32_t size)
Pawel Zarembski 0:01f31e923fe2 480 {
Pawel Zarembski 0:01f31e923fe2 481 uint32_t cnt, n, copy_sz;
Pawel Zarembski 0:01f31e923fe2 482 uint8_t *pEPFIFO; /* Pointer to EP FIFO */
Pawel Zarembski 0:01f31e923fe2 483 uint32_t eptsta;
Pawel Zarembski 0:01f31e923fe2 484 EPNum &= 0x0F;
Pawel Zarembski 0:01f31e923fe2 485 eptsta = eptsta_copy[EPNum];
Pawel Zarembski 0:01f31e923fe2 486 pEPFIFO = (uint8_t *)((uint32_t *)UDPHS_EPTFIFO_BASE + (16384 * EPNum));
Pawel Zarembski 0:01f31e923fe2 487 cnt = (eptsta >> 20) & 0x07FF; /* Get by */
Pawel Zarembski 0:01f31e923fe2 488 copy_sz = cnt > size ? size : cnt;
Pawel Zarembski 0:01f31e923fe2 489
Pawel Zarembski 0:01f31e923fe2 490 for (n = 0; n < copy_sz; n++) {
Pawel Zarembski 0:01f31e923fe2 491 *pData++ = *pEPFIFO++;
Pawel Zarembski 0:01f31e923fe2 492 }
Pawel Zarembski 0:01f31e923fe2 493
Pawel Zarembski 0:01f31e923fe2 494 util_assert(cnt == copy_sz);
Pawel Zarembski 0:01f31e923fe2 495
Pawel Zarembski 0:01f31e923fe2 496 if ((cnt == copy_sz) && (eptsta & (0x1 << 9))) {
Pawel Zarembski 0:01f31e923fe2 497 UDPHS->UDPHS_EPT[EPNum].UDPHS_EPTCLRSTA = (0x1 << 9); /* Rece OUT Clear */
Pawel Zarembski 0:01f31e923fe2 498 }
Pawel Zarembski 0:01f31e923fe2 499
Pawel Zarembski 0:01f31e923fe2 500 /* RX_Setup must be cleared after Setup packet is read */
Pawel Zarembski 0:01f31e923fe2 501 if (eptsta & (0x1 << 12)) {
Pawel Zarembski 0:01f31e923fe2 502 UDPHS->UDPHS_EPT[EPNum].UDPHS_EPTCLRSTA = (0x1 << 12); /* Rece SETUP Clear */
Pawel Zarembski 0:01f31e923fe2 503 }
Pawel Zarembski 0:01f31e923fe2 504 UDPHS->UDPHS_IEN |= (1 << (EPNum + 8)); /* Enable EP int after data read*/
Pawel Zarembski 0:01f31e923fe2 505 return (cnt);
Pawel Zarembski 0:01f31e923fe2 506 }
Pawel Zarembski 0:01f31e923fe2 507
Pawel Zarembski 0:01f31e923fe2 508
Pawel Zarembski 0:01f31e923fe2 509 /*
Pawel Zarembski 0:01f31e923fe2 510 * Write USB Device Endpoint Data
Pawel Zarembski 0:01f31e923fe2 511 * Parameters: EPNum: Device Endpoint Number
Pawel Zarembski 0:01f31e923fe2 512 * EPNum.0..3: Address
Pawel Zarembski 0:01f31e923fe2 513 * EPNum.7: Dir
Pawel Zarembski 0:01f31e923fe2 514 * pData: Pointer to Data Buffer
Pawel Zarembski 0:01f31e923fe2 515 * cnt: Number of bytes to write
Pawel Zarembski 0:01f31e923fe2 516 * Return Value: Number of bytes written
Pawel Zarembski 0:01f31e923fe2 517 */
Pawel Zarembski 0:01f31e923fe2 518
Pawel Zarembski 0:01f31e923fe2 519 uint32_t USBD_WriteEP(uint32_t EPNum, uint8_t *pData, uint32_t cnt)
Pawel Zarembski 0:01f31e923fe2 520 {
Pawel Zarembski 0:01f31e923fe2 521 uint32_t n;
Pawel Zarembski 0:01f31e923fe2 522 uint8_t *pEPFIFO; /* Pointer to the endpoint FIFO */
Pawel Zarembski 0:01f31e923fe2 523 uint32_t eptsta;
Pawel Zarembski 0:01f31e923fe2 524 EPNum &= 0x0F;
Pawel Zarembski 0:01f31e923fe2 525 eptsta = eptsta_copy[EPNum];
Pawel Zarembski 0:01f31e923fe2 526
Pawel Zarembski 0:01f31e923fe2 527 // Cached value should match the real value
Pawel Zarembski 0:01f31e923fe2 528 util_assert((UDPHS->UDPHS_EPT[EPNum].UDPHS_EPTSTA & (0x1 << 5)) == (eptsta & (0x1 << 5)));
Pawel Zarembski 0:01f31e923fe2 529 if (eptsta & (0x1 << 5)) { /* If EP is stall */
Pawel Zarembski 0:01f31e923fe2 530 return (cnt);
Pawel Zarembski 0:01f31e923fe2 531 }
Pawel Zarembski 0:01f31e923fe2 532
Pawel Zarembski 0:01f31e923fe2 533 // Both register and cached value should indicate that the bank is ready (bit 11 clear)
Pawel Zarembski 0:01f31e923fe2 534 util_assert(!(UDPHS->UDPHS_EPT[EPNum].UDPHS_EPTSTA & (0x1 << 11)));
Pawel Zarembski 0:01f31e923fe2 535 util_assert(!(eptsta & (0x1 << 11)));
Pawel Zarembski 0:01f31e923fe2 536
Pawel Zarembski 0:01f31e923fe2 537 pEPFIFO = (uint8_t *)((uint32_t *)UDPHS_EPTFIFO_BASE + (16384 * EPNum));
Pawel Zarembski 0:01f31e923fe2 538
Pawel Zarembski 0:01f31e923fe2 539 for (n = 0; n < cnt; n++) {
Pawel Zarembski 0:01f31e923fe2 540 *pEPFIFO++ = *pData++; /* Write data to FIFO */
Pawel Zarembski 0:01f31e923fe2 541 }
Pawel Zarembski 0:01f31e923fe2 542
Pawel Zarembski 0:01f31e923fe2 543 UDPHS->UDPHS_EPT[EPNum].UDPHS_EPTSETSTA = (0x1 << 11); /* Set packet ready */
Pawel Zarembski 0:01f31e923fe2 544 return (cnt);
Pawel Zarembski 0:01f31e923fe2 545 }
Pawel Zarembski 0:01f31e923fe2 546
Pawel Zarembski 0:01f31e923fe2 547
Pawel Zarembski 0:01f31e923fe2 548 /*
Pawel Zarembski 0:01f31e923fe2 549 * Get USB Device Last Frame Number
Pawel Zarembski 0:01f31e923fe2 550 * Parameters: None
Pawel Zarembski 0:01f31e923fe2 551 * Return Value: Frame Number
Pawel Zarembski 0:01f31e923fe2 552 */
Pawel Zarembski 0:01f31e923fe2 553
Pawel Zarembski 0:01f31e923fe2 554 uint32_t USBD_GetFrame(void)
Pawel Zarembski 0:01f31e923fe2 555 {
Pawel Zarembski 0:01f31e923fe2 556 uint32_t val;
Pawel Zarembski 0:01f31e923fe2 557
Pawel Zarembski 0:01f31e923fe2 558 if ((UDPHS->UDPHS_FNUM & (1UL << 31)) == 0) {
Pawel Zarembski 0:01f31e923fe2 559 if (USBD_HighSpeed) {
Pawel Zarembski 0:01f31e923fe2 560 val = UDPHS->UDPHS_FNUM & 0x7FFFFFFF;
Pawel Zarembski 0:01f31e923fe2 561 } else {
Pawel Zarembski 0:01f31e923fe2 562 val = (UDPHS->UDPHS_FNUM & UDPHS_FNUM_FRAME_NUMBER_Msk) >> 3;
Pawel Zarembski 0:01f31e923fe2 563 }
Pawel Zarembski 0:01f31e923fe2 564 } else {
Pawel Zarembski 0:01f31e923fe2 565 val = 0xFFFFFFFF;
Pawel Zarembski 0:01f31e923fe2 566 }
Pawel Zarembski 0:01f31e923fe2 567
Pawel Zarembski 0:01f31e923fe2 568 return (val);
Pawel Zarembski 0:01f31e923fe2 569 }
Pawel Zarembski 0:01f31e923fe2 570
Pawel Zarembski 0:01f31e923fe2 571
Pawel Zarembski 0:01f31e923fe2 572 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 573 uint32_t LastError; /* Last Error */
Pawel Zarembski 0:01f31e923fe2 574
Pawel Zarembski 0:01f31e923fe2 575 /*
Pawel Zarembski 0:01f31e923fe2 576 * Get USB Device Last Error Code
Pawel Zarembski 0:01f31e923fe2 577 * Parameters: None
Pawel Zarembski 0:01f31e923fe2 578 * Return Value: Error Code
Pawel Zarembski 0:01f31e923fe2 579 */
Pawel Zarembski 0:01f31e923fe2 580
Pawel Zarembski 0:01f31e923fe2 581 uint32_t USBD_GetError(void)
Pawel Zarembski 0:01f31e923fe2 582 {
Pawel Zarembski 0:01f31e923fe2 583 return (LastError);
Pawel Zarembski 0:01f31e923fe2 584 }
Pawel Zarembski 0:01f31e923fe2 585 #endif
Pawel Zarembski 0:01f31e923fe2 586
Pawel Zarembski 0:01f31e923fe2 587
Pawel Zarembski 0:01f31e923fe2 588 /*
Pawel Zarembski 0:01f31e923fe2 589 * USB Device Interrupt Service Routine
Pawel Zarembski 0:01f31e923fe2 590 */
Pawel Zarembski 0:01f31e923fe2 591
Pawel Zarembski 0:01f31e923fe2 592 void UDPHS_IRQHandler(void)
Pawel Zarembski 0:01f31e923fe2 593 {
Pawel Zarembski 0:01f31e923fe2 594 NVIC_DisableIRQ(UDPHS_IRQn);
Pawel Zarembski 0:01f31e923fe2 595 USBD_SignalHandler();
Pawel Zarembski 0:01f31e923fe2 596 }
Pawel Zarembski 0:01f31e923fe2 597
Pawel Zarembski 0:01f31e923fe2 598 /*
Pawel Zarembski 0:01f31e923fe2 599 * USB Device Service Routine
Pawel Zarembski 0:01f31e923fe2 600 */
Pawel Zarembski 0:01f31e923fe2 601
Pawel Zarembski 0:01f31e923fe2 602 void USBD_Handler(void)
Pawel Zarembski 0:01f31e923fe2 603 {
Pawel Zarembski 0:01f31e923fe2 604 uint32_t intsta, eptsta, n;
Pawel Zarembski 0:01f31e923fe2 605 intsta = UDPHS->UDPHS_INTSTA & UDPHS->UDPHS_IEN;
Pawel Zarembski 0:01f31e923fe2 606
Pawel Zarembski 0:01f31e923fe2 607 /* End of Bus Reset Interrupt */
Pawel Zarembski 0:01f31e923fe2 608 if (intsta & UDPHS_INTSTA_ENDRESET) {
Pawel Zarembski 0:01f31e923fe2 609 /* Get used speed (HighSpeed or FullSpeed) */
Pawel Zarembski 0:01f31e923fe2 610 USBD_HighSpeed = (UDPHS->UDPHS_INTSTA & UDPHS_INTSTA_SPEED) ? 1 : 0;
Pawel Zarembski 0:01f31e923fe2 611 USBD_Reset();
Pawel Zarembski 0:01f31e923fe2 612 usbd_reset_core();
Pawel Zarembski 0:01f31e923fe2 613 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 614 UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_ENDRESET;
Pawel Zarembski 0:01f31e923fe2 615
Pawel Zarembski 0:01f31e923fe2 616 if (USBD_RTX_DevTask) {
Pawel Zarembski 0:01f31e923fe2 617 isr_evt_set(USBD_EVT_RESET, USBD_RTX_DevTask);
Pawel Zarembski 0:01f31e923fe2 618 }
Pawel Zarembski 0:01f31e923fe2 619
Pawel Zarembski 0:01f31e923fe2 620 #else
Pawel Zarembski 0:01f31e923fe2 621
Pawel Zarembski 0:01f31e923fe2 622 if (USBD_P_Reset_Event) {
Pawel Zarembski 0:01f31e923fe2 623 USBD_P_Reset_Event();
Pawel Zarembski 0:01f31e923fe2 624 }
Pawel Zarembski 0:01f31e923fe2 625
Pawel Zarembski 0:01f31e923fe2 626 UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_ENDRESET;
Pawel Zarembski 0:01f31e923fe2 627 #endif
Pawel Zarembski 0:01f31e923fe2 628 }
Pawel Zarembski 0:01f31e923fe2 629
Pawel Zarembski 0:01f31e923fe2 630 /* USB Suspend Interrupt */
Pawel Zarembski 0:01f31e923fe2 631 if (intsta & UDPHS_INTSTA_DET_SUSPD) {
Pawel Zarembski 0:01f31e923fe2 632 USBD_Suspend();
Pawel Zarembski 0:01f31e923fe2 633 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 634 UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_DET_SUSPD;
Pawel Zarembski 0:01f31e923fe2 635
Pawel Zarembski 0:01f31e923fe2 636 if (USBD_RTX_DevTask) {
Pawel Zarembski 0:01f31e923fe2 637 isr_evt_set(USBD_EVT_SUSPEND, USBD_RTX_DevTask);
Pawel Zarembski 0:01f31e923fe2 638 }
Pawel Zarembski 0:01f31e923fe2 639
Pawel Zarembski 0:01f31e923fe2 640 #else
Pawel Zarembski 0:01f31e923fe2 641
Pawel Zarembski 0:01f31e923fe2 642 if (USBD_P_Suspend_Event) {
Pawel Zarembski 0:01f31e923fe2 643 USBD_P_Suspend_Event();
Pawel Zarembski 0:01f31e923fe2 644 }
Pawel Zarembski 0:01f31e923fe2 645
Pawel Zarembski 0:01f31e923fe2 646 UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_DET_SUSPD;
Pawel Zarembski 0:01f31e923fe2 647 #endif
Pawel Zarembski 0:01f31e923fe2 648 }
Pawel Zarembski 0:01f31e923fe2 649
Pawel Zarembski 0:01f31e923fe2 650 /* USB Resume Interrupt */
Pawel Zarembski 0:01f31e923fe2 651 if (intsta & UDPHS_INTSTA_WAKE_UP) {
Pawel Zarembski 0:01f31e923fe2 652 USBD_Resume();
Pawel Zarembski 0:01f31e923fe2 653 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 654 UDPHS->UDPHS_CLRINT = UDPHS_INTSTA_WAKE_UP;
Pawel Zarembski 0:01f31e923fe2 655
Pawel Zarembski 0:01f31e923fe2 656 if (USBD_RTX_DevTask) {
Pawel Zarembski 0:01f31e923fe2 657 isr_evt_set(USBD_EVT_RESUME, USBD_RTX_DevTask);
Pawel Zarembski 0:01f31e923fe2 658 }
Pawel Zarembski 0:01f31e923fe2 659
Pawel Zarembski 0:01f31e923fe2 660 #else
Pawel Zarembski 0:01f31e923fe2 661
Pawel Zarembski 0:01f31e923fe2 662 if (USBD_P_Resume_Event) {
Pawel Zarembski 0:01f31e923fe2 663 USBD_P_Resume_Event();
Pawel Zarembski 0:01f31e923fe2 664 }
Pawel Zarembski 0:01f31e923fe2 665
Pawel Zarembski 0:01f31e923fe2 666 UDPHS->UDPHS_CLRINT = UDPHS_INTSTA_WAKE_UP;
Pawel Zarembski 0:01f31e923fe2 667 #endif
Pawel Zarembski 0:01f31e923fe2 668 }
Pawel Zarembski 0:01f31e923fe2 669
Pawel Zarembski 0:01f31e923fe2 670 /* USB Remote Wakeup Interrupt */
Pawel Zarembski 0:01f31e923fe2 671 if (intsta & UDPHS_INTSTA_UPSTR_RES) {
Pawel Zarembski 0:01f31e923fe2 672 UDPHS->UDPHS_CLRINT = UDPHS_INTSTA_UPSTR_RES;
Pawel Zarembski 0:01f31e923fe2 673 }
Pawel Zarembski 0:01f31e923fe2 674
Pawel Zarembski 0:01f31e923fe2 675 /* Start of Frame Interrupt */
Pawel Zarembski 0:01f31e923fe2 676 if (intsta & UDPHS_INTSTA_INT_SOF) {
Pawel Zarembski 0:01f31e923fe2 677 /* Process the SOF interrupt even in high speed mode.
Pawel Zarembski 0:01f31e923fe2 678 The SOF and MICRO_SOF interrupt are never generated at the same
Pawel Zarembski 0:01f31e923fe2 679 time. Instead, when in high speed mode there is 1 SOF
Pawel Zarembski 0:01f31e923fe2 680 interrupt and 7 MICRO_SOF interrupts every 1ms. */
Pawel Zarembski 0:01f31e923fe2 681
Pawel Zarembski 0:01f31e923fe2 682 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 683 UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_INT_SOF;
Pawel Zarembski 0:01f31e923fe2 684
Pawel Zarembski 0:01f31e923fe2 685 if (USBD_RTX_DevTask) {
Pawel Zarembski 0:01f31e923fe2 686 isr_evt_set(USBD_EVT_SOF, USBD_RTX_DevTask);
Pawel Zarembski 0:01f31e923fe2 687 }
Pawel Zarembski 0:01f31e923fe2 688
Pawel Zarembski 0:01f31e923fe2 689 #else
Pawel Zarembski 0:01f31e923fe2 690
Pawel Zarembski 0:01f31e923fe2 691 if (USBD_P_SOF_Event) {
Pawel Zarembski 0:01f31e923fe2 692 USBD_P_SOF_Event();
Pawel Zarembski 0:01f31e923fe2 693 }
Pawel Zarembski 0:01f31e923fe2 694
Pawel Zarembski 0:01f31e923fe2 695 UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_INT_SOF;
Pawel Zarembski 0:01f31e923fe2 696 #endif
Pawel Zarembski 0:01f31e923fe2 697 }
Pawel Zarembski 0:01f31e923fe2 698
Pawel Zarembski 0:01f31e923fe2 699 /* Micro Frame Interrupt */
Pawel Zarembski 0:01f31e923fe2 700 if (intsta & UDPHS_INTSTA_MICRO_SOF) {
Pawel Zarembski 0:01f31e923fe2 701 if (USBD_HighSpeed == 1) {
Pawel Zarembski 0:01f31e923fe2 702 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 703 UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_MICRO_SOF;
Pawel Zarembski 0:01f31e923fe2 704
Pawel Zarembski 0:01f31e923fe2 705 if (USBD_RTX_DevTask) {
Pawel Zarembski 0:01f31e923fe2 706 isr_evt_set(USBD_EVT_SOF, USBD_RTX_DevTask);
Pawel Zarembski 0:01f31e923fe2 707 }
Pawel Zarembski 0:01f31e923fe2 708
Pawel Zarembski 0:01f31e923fe2 709 #else
Pawel Zarembski 0:01f31e923fe2 710
Pawel Zarembski 0:01f31e923fe2 711 if (USBD_P_SOF_Event) {
Pawel Zarembski 0:01f31e923fe2 712 USBD_P_SOF_Event();
Pawel Zarembski 0:01f31e923fe2 713 }
Pawel Zarembski 0:01f31e923fe2 714
Pawel Zarembski 0:01f31e923fe2 715 UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_MICRO_SOF;
Pawel Zarembski 0:01f31e923fe2 716 #endif
Pawel Zarembski 0:01f31e923fe2 717
Pawel Zarembski 0:01f31e923fe2 718 } else {
Pawel Zarembski 0:01f31e923fe2 719 UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_MICRO_SOF;
Pawel Zarembski 0:01f31e923fe2 720 }
Pawel Zarembski 0:01f31e923fe2 721 }
Pawel Zarembski 0:01f31e923fe2 722
Pawel Zarembski 0:01f31e923fe2 723 /* Endpoint Interrupts */
Pawel Zarembski 0:01f31e923fe2 724 for (n = 0; n <= USBD_EP_NUM; n++) {
Pawel Zarembski 0:01f31e923fe2 725 if (intsta & (1 << (n + 8))) {
Pawel Zarembski 0:01f31e923fe2 726 eptsta = UDPHS->UDPHS_EPT[n].UDPHS_EPTSTA; /* Read EP status */
Pawel Zarembski 0:01f31e923fe2 727 eptsta_copy[n] = eptsta;
Pawel Zarembski 0:01f31e923fe2 728
Pawel Zarembski 0:01f31e923fe2 729 /* Data Packet Sent Interrupt */
Pawel Zarembski 0:01f31e923fe2 730 if (eptsta & (1 << 10)) { /* Transmitted IN Data Complete Int */
Pawel Zarembski 0:01f31e923fe2 731 UDPHS->UDPHS_EPT[n].UDPHS_EPTCLRSTA = (1 << 10); /* Tx IN Clear */
Pawel Zarembski 0:01f31e923fe2 732 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 733
Pawel Zarembski 0:01f31e923fe2 734 if (USBD_RTX_EPTask[n]) { /* IN Packet */
Pawel Zarembski 0:01f31e923fe2 735 isr_evt_set(USBD_EVT_IN, USBD_RTX_EPTask[n]);
Pawel Zarembski 0:01f31e923fe2 736 }
Pawel Zarembski 0:01f31e923fe2 737
Pawel Zarembski 0:01f31e923fe2 738 #else
Pawel Zarembski 0:01f31e923fe2 739
Pawel Zarembski 0:01f31e923fe2 740 if (USBD_P_EP[n]) {
Pawel Zarembski 0:01f31e923fe2 741 USBD_P_EP[n](USBD_EVT_IN);
Pawel Zarembski 0:01f31e923fe2 742 }
Pawel Zarembski 0:01f31e923fe2 743
Pawel Zarembski 0:01f31e923fe2 744 #endif
Pawel Zarembski 0:01f31e923fe2 745 }
Pawel Zarembski 0:01f31e923fe2 746
Pawel Zarembski 0:01f31e923fe2 747 /* Data Packet Received Interrupt */
Pawel Zarembski 0:01f31e923fe2 748 if (eptsta & (1 << 9)) { /* Received OUT Data Interrupt */
Pawel Zarembski 0:01f31e923fe2 749 UDPHS->UDPHS_IEN &= ~(1 << (n + 8)); /* Disable EP int until read*/
Pawel Zarembski 0:01f31e923fe2 750 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 751
Pawel Zarembski 0:01f31e923fe2 752 if (USBD_RTX_EPTask[n]) { /* OUT Packet */
Pawel Zarembski 0:01f31e923fe2 753 isr_evt_set(USBD_EVT_OUT, USBD_RTX_EPTask[n]);
Pawel Zarembski 0:01f31e923fe2 754 }
Pawel Zarembski 0:01f31e923fe2 755
Pawel Zarembski 0:01f31e923fe2 756 #else
Pawel Zarembski 0:01f31e923fe2 757
Pawel Zarembski 0:01f31e923fe2 758 if (USBD_P_EP[n]) {
Pawel Zarembski 0:01f31e923fe2 759 USBD_P_EP[n](USBD_EVT_OUT);
Pawel Zarembski 0:01f31e923fe2 760 }
Pawel Zarembski 0:01f31e923fe2 761
Pawel Zarembski 0:01f31e923fe2 762 #endif
Pawel Zarembski 0:01f31e923fe2 763 }
Pawel Zarembski 0:01f31e923fe2 764
Pawel Zarembski 0:01f31e923fe2 765 /* STALL Packet Sent Interrupt */
Pawel Zarembski 0:01f31e923fe2 766 if (eptsta & (0x1 << 13)) { /* Stall Sent */
Pawel Zarembski 0:01f31e923fe2 767 if ((UDPHS->UDPHS_EPT[n].UDPHS_EPTCFG & UDPHS_EPTCFG_EPT_TYPE_Msk) == UDPHS_EPTCFG_EPT_TYPE_CTRL8) {
Pawel Zarembski 0:01f31e923fe2 768 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 769
Pawel Zarembski 0:01f31e923fe2 770 if (USBD_RTX_EPTask[n]) {
Pawel Zarembski 0:01f31e923fe2 771 isr_evt_set(USBD_EVT_IN_STALL, USBD_RTX_EPTask[n]);
Pawel Zarembski 0:01f31e923fe2 772 }
Pawel Zarembski 0:01f31e923fe2 773
Pawel Zarembski 0:01f31e923fe2 774 #else
Pawel Zarembski 0:01f31e923fe2 775
Pawel Zarembski 0:01f31e923fe2 776 if (USBD_P_EP[n]) {
Pawel Zarembski 0:01f31e923fe2 777 USBD_P_EP[n](USBD_EVT_IN_STALL);
Pawel Zarembski 0:01f31e923fe2 778 }
Pawel Zarembski 0:01f31e923fe2 779
Pawel Zarembski 0:01f31e923fe2 780 #endif
Pawel Zarembski 0:01f31e923fe2 781 }
Pawel Zarembski 0:01f31e923fe2 782
Pawel Zarembski 0:01f31e923fe2 783 UDPHS->UDPHS_EPT[n].UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_STALL_SNT;
Pawel Zarembski 0:01f31e923fe2 784 }
Pawel Zarembski 0:01f31e923fe2 785
Pawel Zarembski 0:01f31e923fe2 786 /* Setup Packet Received Interrupt */
Pawel Zarembski 0:01f31e923fe2 787 if (eptsta & (0x1 << 12)) { /* Received SETUP Interrupt */
Pawel Zarembski 0:01f31e923fe2 788 UDPHS->UDPHS_IEN &= ~(1 << (n + 8)); /* Disable EP int until read*/
Pawel Zarembski 0:01f31e923fe2 789 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 790
Pawel Zarembski 0:01f31e923fe2 791 if (USBD_RTX_EPTask[n]) { /* SETUP Packet */
Pawel Zarembski 0:01f31e923fe2 792 isr_evt_set(USBD_EVT_SETUP, USBD_RTX_EPTask[n]);
Pawel Zarembski 0:01f31e923fe2 793 }
Pawel Zarembski 0:01f31e923fe2 794
Pawel Zarembski 0:01f31e923fe2 795 #else
Pawel Zarembski 0:01f31e923fe2 796
Pawel Zarembski 0:01f31e923fe2 797 if (USBD_P_EP[n]) {
Pawel Zarembski 0:01f31e923fe2 798 USBD_P_EP[n](USBD_EVT_SETUP);
Pawel Zarembski 0:01f31e923fe2 799 }
Pawel Zarembski 0:01f31e923fe2 800
Pawel Zarembski 0:01f31e923fe2 801 #endif
Pawel Zarembski 0:01f31e923fe2 802 }
Pawel Zarembski 0:01f31e923fe2 803 }
Pawel Zarembski 0:01f31e923fe2 804 }
Pawel Zarembski 0:01f31e923fe2 805
Pawel Zarembski 0:01f31e923fe2 806 NVIC_EnableIRQ(UDPHS_IRQn);
Pawel Zarembski 0:01f31e923fe2 807 }