[136] | 1 | /* ----------------------------------------------------------------------------
|
---|
| 2 | * SAM Software Package License
|
---|
| 3 | * ----------------------------------------------------------------------------
|
---|
| 4 | * Copyright (c) 2011-2012, Atmel Corporation
|
---|
| 5 | *
|
---|
| 6 | * All rights reserved.
|
---|
| 7 | *
|
---|
| 8 | * Redistribution and use in source and binary forms, with or without
|
---|
| 9 | * modification, are permitted provided that the following condition is met:
|
---|
| 10 | *
|
---|
| 11 | * - Redistributions of source code must retain the above copyright notice,
|
---|
| 12 | * this list of conditions and the disclaimer below.
|
---|
| 13 | *
|
---|
| 14 | * Atmel's name may not be used to endorse or promote products derived from
|
---|
| 15 | * this software without specific prior written permission.
|
---|
| 16 | *
|
---|
| 17 | * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
---|
| 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
---|
| 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
---|
| 20 | * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
---|
| 21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
---|
| 22 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
---|
| 23 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
---|
| 24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
---|
| 25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
---|
| 26 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
---|
| 27 | * ----------------------------------------------------------------------------
|
---|
| 28 | */
|
---|
| 29 |
|
---|
| 30 | #include <stdio.h>
|
---|
| 31 |
|
---|
| 32 | #ifdef HOST_DEFINED
|
---|
| 33 |
|
---|
| 34 | //#define TRACE_UOTGHS_HOST(x) x
|
---|
| 35 | #define TRACE_UOTGHS_HOST(x)
|
---|
| 36 |
|
---|
| 37 | //extern void (*gpf_isr)(void);
|
---|
| 38 |
|
---|
| 39 | // Handle UOTGHS Host driver state
|
---|
| 40 | static uhd_vbus_state_t uhd_state = UHD_STATE_NO_VBUS;
|
---|
| 41 |
|
---|
| 42 | __attribute__((__aligned__(4))) UsbHostDescriptor usb_pipe_table[USB_EPT_NUM];
|
---|
| 43 |
|
---|
| 44 |
|
---|
| 45 | // NVM Software Calibration Area Mapping
|
---|
| 46 | // USB TRANSN calibration value. Should be written to the USB PADCAL register.
|
---|
| 47 | #define NVM_USB_PAD_TRANSN_POS 45
|
---|
| 48 | #define NVM_USB_PAD_TRANSN_SIZE 5
|
---|
| 49 | // USB TRANSP calibration value. Should be written to the USB PADCAL register.
|
---|
| 50 | #define NVM_USB_PAD_TRANSP_POS 50
|
---|
| 51 | #define NVM_USB_PAD_TRANSP_SIZE 5
|
---|
| 52 | // USB TRIM calibration value. Should be written to the USB PADCAL register.
|
---|
| 53 | #define NVM_USB_PAD_TRIM_POS 55
|
---|
| 54 | #define NVM_USB_PAD_TRIM_SIZE 3
|
---|
| 55 |
|
---|
| 56 | /**
|
---|
| 57 | * \brief Initialize the SAMD21 host driver.
|
---|
| 58 | */
|
---|
| 59 | void UHD_Init(void)
|
---|
| 60 | {
|
---|
| 61 | uint32_t pad_transn;
|
---|
| 62 | uint32_t pad_transp;
|
---|
| 63 | uint32_t pad_trim;
|
---|
| 64 |
|
---|
| 65 | /* Enable USB clock */
|
---|
| 66 | PM->APBBMASK.reg |= PM_APBBMASK_USB;
|
---|
| 67 |
|
---|
| 68 | /* Set up the USB DP/DN pins */
|
---|
| 69 | PORT->Group[0].PINCFG[PIN_PA24G_USB_DM].bit.PMUXEN = 1;
|
---|
| 70 | PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg &= ~(0xF << (4 * (PIN_PA24G_USB_DM & 0x01u)));
|
---|
| 71 | PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg |= MUX_PA24G_USB_DM << (4 * (PIN_PA24G_USB_DM & 0x01u));
|
---|
| 72 | PORT->Group[0].PINCFG[PIN_PA25G_USB_DP].bit.PMUXEN = 1;
|
---|
| 73 | PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg &= ~(0xF << (4 * (PIN_PA25G_USB_DP & 0x01u)));
|
---|
| 74 | PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg |= MUX_PA25G_USB_DP << (4 * (PIN_PA25G_USB_DP & 0x01u));
|
---|
| 75 |
|
---|
| 76 | /* ----------------------------------------------------------------------------------------------
|
---|
| 77 | * Put Generic Clock Generator 0 as source for Generic Clock Multiplexer 6 (USB reference)
|
---|
| 78 | */
|
---|
| 79 | GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( 6 ) | // Generic Clock Multiplexer 6
|
---|
| 80 | GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
|
---|
| 81 | GCLK_CLKCTRL_CLKEN ;
|
---|
| 82 |
|
---|
| 83 | while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
|
---|
| 84 | {
|
---|
| 85 | /* Wait for synchronization */
|
---|
| 86 | }
|
---|
| 87 |
|
---|
| 88 | /* Reset */
|
---|
| 89 | USB->HOST.CTRLA.bit.SWRST = 1;
|
---|
| 90 | while (USB->HOST.SYNCBUSY.bit.SWRST) {
|
---|
| 91 | /* Sync wait */
|
---|
| 92 | }
|
---|
| 93 |
|
---|
| 94 | udd_enable();
|
---|
| 95 |
|
---|
| 96 | /* Load Pad Calibration */
|
---|
| 97 | pad_transn =( *((uint32_t *)(NVMCTRL_OTP4) // Non-Volatile Memory Controller
|
---|
| 98 | + (NVM_USB_PAD_TRANSN_POS / 32))
|
---|
| 99 | >> (NVM_USB_PAD_TRANSN_POS % 32))
|
---|
| 100 | & ((1 << NVM_USB_PAD_TRANSN_SIZE) - 1);
|
---|
| 101 |
|
---|
| 102 | if (pad_transn == 0x1F) { // maximum value (31)
|
---|
| 103 | pad_transn = 5;
|
---|
| 104 | }
|
---|
| 105 |
|
---|
| 106 | USB->HOST.PADCAL.bit.TRANSN = pad_transn;
|
---|
| 107 |
|
---|
| 108 | pad_transp =( *((uint32_t *)(NVMCTRL_OTP4)
|
---|
| 109 | + (NVM_USB_PAD_TRANSP_POS / 32))
|
---|
| 110 | >> (NVM_USB_PAD_TRANSP_POS % 32))
|
---|
| 111 | & ((1 << NVM_USB_PAD_TRANSP_SIZE) - 1);
|
---|
| 112 |
|
---|
| 113 | if (pad_transp == 0x1F) { // maximum value (31)
|
---|
| 114 | pad_transp = 29;
|
---|
| 115 | }
|
---|
| 116 |
|
---|
| 117 | USB->HOST.PADCAL.bit.TRANSP = pad_transp;
|
---|
| 118 |
|
---|
| 119 | pad_trim =( *((uint32_t *)(NVMCTRL_OTP4)
|
---|
| 120 | + (NVM_USB_PAD_TRIM_POS / 32))
|
---|
| 121 | >> (NVM_USB_PAD_TRIM_POS % 32))
|
---|
| 122 | & ((1 << NVM_USB_PAD_TRIM_SIZE) - 1);
|
---|
| 123 |
|
---|
| 124 | if (pad_trim == 0x7) { // maximum value (7)
|
---|
| 125 | pad_trim = 3;
|
---|
| 126 | }
|
---|
| 127 |
|
---|
| 128 | USB->HOST.PADCAL.bit.TRIM = pad_trim;
|
---|
| 129 |
|
---|
| 130 | /* Set the configuration */
|
---|
| 131 | udd_force_host_mode();
|
---|
| 132 | udd_device_run_in_standby();
|
---|
| 133 | // Set address of USB SRAM
|
---|
| 134 | USB->HOST.DESCADD.reg = (uint32_t)(&usb_endpoint_table[0]);
|
---|
| 135 | // For USB_SPEED_FULL
|
---|
| 136 | udd_force_full_speed();
|
---|
| 137 | for (uint32_t i = 0; i < sizeof(usb_endpoint_table); i++) {
|
---|
| 138 | (*(uint32_t *)(&usb_endpoint_table[0]+i)) = 0;
|
---|
| 139 | }
|
---|
| 140 |
|
---|
| 141 | uhd_state = UHD_STATE_NO_VBUS;
|
---|
| 142 |
|
---|
| 143 | USB->HOST.CTRLB.bit.VBUSOK = 1;
|
---|
| 144 |
|
---|
| 145 | // Configure interrupts
|
---|
| 146 | NVIC_SetPriority((IRQn_Type) USB_IRQn, 0UL);
|
---|
| 147 | NVIC_EnableIRQ((IRQn_Type) USB_IRQn);
|
---|
| 148 | }
|
---|
| 149 |
|
---|
| 150 | //static void UHD_ISR(void)
|
---|
| 151 | void USB_Handler(void)
|
---|
| 152 | {
|
---|
| 153 | uint16_t flags;
|
---|
| 154 | uint8_t i;
|
---|
| 155 | uint8_t ept_int;
|
---|
| 156 |
|
---|
| 157 | ept_int = udd_endpoint_interrupt();
|
---|
| 158 |
|
---|
| 159 | /* Not endpoint interrupt */
|
---|
| 160 | if (0 == ept_int)
|
---|
| 161 | {
|
---|
| 162 |
|
---|
| 163 |
|
---|
| 164 | }
|
---|
| 165 | else
|
---|
| 166 | {
|
---|
| 167 | /* host interrupts */
|
---|
| 168 |
|
---|
| 169 | /* get interrupt flags */
|
---|
| 170 | flags = USB->HOST.INTFLAG.reg;
|
---|
| 171 |
|
---|
| 172 | /* host SOF interrupt */
|
---|
| 173 | if (flags & USB_HOST_INTFLAG_HSOF) {
|
---|
| 174 | /* clear the flag */
|
---|
| 175 | USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_HSOF;
|
---|
| 176 | uhd_state = UHD_STATE_CONNECTED;
|
---|
| 177 | return;
|
---|
| 178 | }
|
---|
| 179 |
|
---|
| 180 | /* host reset interrupt */
|
---|
| 181 | if (flags & USB_HOST_INTFLAG_RST) {
|
---|
| 182 | /* clear the flag */
|
---|
| 183 | USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_RST;
|
---|
| 184 | uhd_state = UHD_STATE_DISCONNECTED; //UHD_STATE_ERROR;
|
---|
| 185 | return;
|
---|
| 186 | }
|
---|
| 187 |
|
---|
| 188 | /* host upstream resume interrupts */
|
---|
| 189 | if (flags & USB_HOST_INTFLAG_UPRSM) {
|
---|
| 190 | /* clear the flags */
|
---|
| 191 | USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_UPRSM;
|
---|
| 192 | uhd_state = UHD_STATE_DISCONNECTED; //UHD_STATE_ERROR;
|
---|
| 193 | return;
|
---|
| 194 | }
|
---|
| 195 |
|
---|
| 196 | /* host downstream resume interrupts */
|
---|
| 197 | if (flags & USB_HOST_INTFLAG_DNRSM) {
|
---|
| 198 | /* clear the flags */
|
---|
| 199 | USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_DNRSM;
|
---|
| 200 | uhd_state = UHD_STATE_DISCONNECTED; //UHD_STATE_ERROR;
|
---|
| 201 | return;
|
---|
| 202 | }
|
---|
| 203 |
|
---|
| 204 | /* host wakeup interrupts */
|
---|
| 205 | if (flags & USB_HOST_INTFLAG_WAKEUP) {
|
---|
| 206 | /* clear the flags */
|
---|
| 207 | USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_WAKEUP;
|
---|
| 208 | uhd_state = UHD_STATE_CONNECTED; //UHD_STATE_ERROR;
|
---|
| 209 | return;
|
---|
| 210 | }
|
---|
| 211 |
|
---|
| 212 | /* host ram access interrupt */
|
---|
| 213 | if (flags & USB_HOST_INTFLAG_RAMACER) {
|
---|
| 214 | /* clear the flag */
|
---|
| 215 | USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_RAMACER;
|
---|
| 216 | uhd_state = UHD_STATE_DISCONNECTED; //UHD_STATE_ERROR;
|
---|
| 217 | return;
|
---|
| 218 | }
|
---|
| 219 |
|
---|
| 220 | /* host connect interrupt */
|
---|
| 221 | if (flags & USB_HOST_INTFLAG_DCONN) {
|
---|
| 222 | TRACE_UOTGHS_HOST(printf(">>> UHD_ISR : Connection INT\r\n");)
|
---|
| 223 | /* clear the flag */
|
---|
| 224 | uhd_ack_connection();
|
---|
| 225 | uhd_disable_connection_int();
|
---|
| 226 | uhd_ack_disconnection();
|
---|
| 227 | uhd_enable_disconnection_int();
|
---|
| 228 | //uhd_enable_sof();
|
---|
| 229 | uhd_state = UHD_STATE_CONNECTED;
|
---|
| 230 | return;
|
---|
| 231 | }
|
---|
| 232 |
|
---|
| 233 | /* host disconnect interrupt */
|
---|
| 234 | if (flags & USB_HOST_INTFLAG_DDISC) {
|
---|
| 235 | TRACE_UOTGHS_HOST(printf(">>> UHD_ISR : Disconnection INT\r\n");)
|
---|
| 236 | /* clear the flag */
|
---|
| 237 | uhd_ack_disconnection();
|
---|
| 238 | uhd_disable_disconnection_int();
|
---|
| 239 | // Stop reset signal, in case of disconnection during reset
|
---|
| 240 | uhd_stop_reset();
|
---|
| 241 | // Disable wakeup/resumes interrupts,
|
---|
| 242 | // in case of disconnection during suspend mode
|
---|
| 243 | uhd_ack_connection();
|
---|
| 244 | uhd_enable_connection_int();
|
---|
| 245 | uhd_state = UHD_STATE_DISCONNECTED;
|
---|
| 246 | return;
|
---|
| 247 | }
|
---|
| 248 |
|
---|
| 249 | }
|
---|
| 250 |
|
---|
| 251 | }
|
---|
| 252 |
|
---|
| 253 |
|
---|
| 254 |
|
---|
| 255 |
|
---|
| 256 | /**
|
---|
| 257 | * \brief Trigger a USB bus reset.
|
---|
| 258 | */
|
---|
| 259 | void UHD_BusReset(void)
|
---|
| 260 | {
|
---|
| 261 | USB->HOST.CTRLB.bit.BUSRESET = 1;;
|
---|
| 262 | }
|
---|
| 263 |
|
---|
| 264 | /**
|
---|
| 265 | * \brief Get VBUS state.
|
---|
| 266 | *
|
---|
| 267 | * \return VBUS status.
|
---|
| 268 | */
|
---|
| 269 | uhd_vbus_state_t UHD_GetVBUSState(void)
|
---|
| 270 | {
|
---|
| 271 | return uhd_state;
|
---|
| 272 | }
|
---|
| 273 |
|
---|
| 274 |
|
---|
| 275 |
|
---|
| 276 | /**
|
---|
| 277 | * \brief Allocate FIFO for pipe 0.
|
---|
| 278 | *
|
---|
| 279 | * \param ul_add Address of remote device for pipe 0.
|
---|
| 280 | * \param ul_ep_size Actual size of the FIFO in bytes.
|
---|
| 281 | *
|
---|
| 282 | * \retval 0 success.
|
---|
| 283 | * \retval 1 error.
|
---|
| 284 | */
|
---|
| 285 | uint32_t UHD_Pipe0_Alloc(uint32_t ul_add, uint32_t ul_ep_size)
|
---|
| 286 | {
|
---|
| 287 | struct usb_host_pipe_config cfg;
|
---|
| 288 |
|
---|
| 289 | if (ep_size < 8)
|
---|
| 290 | {
|
---|
| 291 | return 0;
|
---|
| 292 | }
|
---|
| 293 |
|
---|
| 294 | /* set pipe config */
|
---|
| 295 | USB->HOST.HostPipe[0].PCFG.bit.BK = 0;
|
---|
| 296 | USB->HOST.HostPipe[0].PCFG.bit.PTYPE = USB_HOST_PIPE_TYPE_CONTROL;
|
---|
| 297 | USB->HOST.HostPipe[0].BINTERVAL.reg = 0;
|
---|
| 298 | USB->HOST.HostPipe[0].PCFG.bit.PTOKEN = USB_HOST_PIPE_TOKEN_SETUP;
|
---|
| 299 |
|
---|
| 300 | memset((uint8_t *)&usb_pipe_table[pipe_num], 0, sizeof(usb_pipe_table[0]));
|
---|
| 301 | usb_pipe_table[pipe_num].HostDescBank[0].CTRL_PIPE.bit.PDADDR = 0;
|
---|
| 302 | usb_pipe_table[pipe_num].HostDescBank[0].CTRL_PIPE.bit.PEPNUM = 0;
|
---|
| 303 | usb_pipe_table[pipe_num].HostDescBank[0].PCKSIZE.bit.SIZE = 0x03; // 64 bytes
|
---|
| 304 |
|
---|
| 305 | USB->HOST.HostPipe[pipe_num].PINTENSET.reg = USB_HOST_PINTENSET_TRCPT_Msk;
|
---|
| 306 | USB->HOST.HostPipe[pipe_num].PINTENSET.reg = USB_HOST_PINTENSET_TRFAIL | USB_HOST_PINTENSET_PERR;
|
---|
| 307 | USB->HOST.HostPipe[pipe_num].PINTENSET.reg = USB_HOST_PINTENSET_TXSTP;
|
---|
| 308 | USB->HOST.HostPipe[pipe_num].PINTENSET.reg = USB_HOST_PINTENSET_STALL;
|
---|
| 309 |
|
---|
| 310 | return 1;
|
---|
| 311 | }
|
---|
| 312 |
|
---|
| 313 | /**
|
---|
| 314 | * \brief Allocate a new pipe.
|
---|
| 315 | *
|
---|
| 316 | * \note UOTGHS maximum pipe number is limited to 10, meaning that only a limited
|
---|
| 317 | * amount of devices can be connected. Unfortunately, using only one pipe shared accross
|
---|
| 318 | * various endpoints and devices is not possible because the UOTGHS IP does not allow to
|
---|
| 319 | * change the data toggle value through register interface.
|
---|
| 320 | *
|
---|
| 321 | * \param ul_dev_addr Address of remote device.
|
---|
| 322 | * \param ul_dev_ep Targeted endpoint of remote device.
|
---|
| 323 | * \param ul_type Pipe type.
|
---|
| 324 | * \param ul_dir Pipe direction.
|
---|
| 325 | * \param ul_maxsize Pipe size.
|
---|
| 326 | * \param ul_interval Polling interval (if applicable to pipe type).
|
---|
| 327 | * \param ul_nb_bank Number of banks associated with this pipe.
|
---|
| 328 | *
|
---|
| 329 | * \return the newly allocated pipe number on success, 0 otherwise.
|
---|
| 330 | */
|
---|
| 331 |
|
---|
| 332 | // pipe = UHD_Pipe_Alloc(bAddress, epInfo[index].deviceEpNum, UOTGHS_HSTPIPCFG_PTYPE_BLK, UOTGHS_HSTPIPCFG_PTOKEN_IN, epInfo[index].maxPktSize, 0, UOTGHS_HSTPIPCFG_PBK_1_BANK);
|
---|
| 333 |
|
---|
| 334 | uint32_t UHD_Pipe_Alloc(uint32_t ul_dev_addr, uint32_t ul_dev_ep, uint32_t ul_type, uint32_t ul_dir, uint32_t ul_maxsize, uint32_t ul_interval, uint32_t ul_nb_bank)
|
---|
| 335 | //bool uhd_ep_alloc(usb_add_t add, usb_ep_desc_t *ep_desc)
|
---|
| 336 | {
|
---|
| 337 | /* set pipe config */
|
---|
| 338 | USB->HOST.HostPipe[ul_dev_ep].PCFG.bit.BK = ul_nb_bank;
|
---|
| 339 | USB->HOST.HostPipe[ul_dev_ep].PCFG.bit.PTYPE = ul_type;
|
---|
| 340 | USB->HOST.HostPipe[ul_dev_ep].BINTERVAL.reg = ul_interval;
|
---|
| 341 |
|
---|
| 342 | if (ul_dir & USB_EP_DIR_IN)
|
---|
| 343 | {
|
---|
| 344 | USB->HOST.HostPipe[ul_dev_ep].PCFG.bit.PTOKEN = USB_HOST_PIPE_TOKEN_IN;
|
---|
| 345 | USB->HOST.HostPipe[ul_dev_ep].PSTATUSSET.reg = USB_HOST_PSTATUSSET_BK0RDY;
|
---|
| 346 | }
|
---|
| 347 | else
|
---|
| 348 | {
|
---|
| 349 | USB->HOST.HostPipe[ul_dev_ep].PCFG.bit.PTOKEN = USB_HOST_PIPE_TOKEN_OUT;
|
---|
| 350 | USB->HOST.HostPipe[ul_dev_ep].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_BK0RDY;
|
---|
| 351 | }
|
---|
| 352 |
|
---|
| 353 | memset((uint8_t *)&usb_descriptor_table.usb_pipe_table[ul_dev_ep], 0, sizeof(usb_pipe_table[ul_dev_ep]));
|
---|
| 354 |
|
---|
| 355 | usb_descriptor_table.usb_pipe_table[ul_dev_ep].HostDescBank[0].CTRL_PIPE.bit.PDADDR = ul_dev_addr;
|
---|
| 356 | usb_descriptor_table.usb_pipe_table[ul_dev_ep].HostDescBank[0].CTRL_PIPE.bit.PEPNUM = ul_dev_ep;
|
---|
| 357 | usb_descriptor_table.usb_pipe_table[ul_dev_ep].HostDescBank[0].PCKSIZE.bit.SIZE = 0x03; // 64 bytes
|
---|
| 358 |
|
---|
| 359 | USB->HOST.HostPipe[pipe_num].PINTENSET.reg = USB_HOST_PINTENSET_TRCPT_Msk;
|
---|
| 360 | USB->HOST.HostPipe[pipe_num].PINTENSET.reg = USB_HOST_PINTENSET_TRFAIL | USB_HOST_PINTENSET_PERR;
|
---|
| 361 | USB->HOST.HostPipe[pipe_num].PINTENSET.reg = USB_HOST_PINTENSET_STALL;
|
---|
| 362 |
|
---|
| 363 | return 1;
|
---|
| 364 | }
|
---|
| 365 |
|
---|
| 366 |
|
---|
| 367 | /**
|
---|
| 368 | * \brief Free a pipe.
|
---|
| 369 | *
|
---|
| 370 | * \param ul_pipe Pipe number to free.
|
---|
| 371 | */
|
---|
| 372 | void UHD_Pipe_Free(uint32_t ul_pipe)
|
---|
| 373 | {
|
---|
| 374 | // Unalloc pipe
|
---|
| 375 | uhd_disable_pipe(ul_pipe);
|
---|
| 376 | uhd_unallocate_memory(ul_pipe);
|
---|
| 377 | uhd_reset_pipe(ul_pipe);
|
---|
| 378 |
|
---|
| 379 | // The Pipe is frozen and no additional requests will be sent to the device on this pipe address.
|
---|
| 380 | USB->HOST.HostPipe[pipe_num].PSTATUSSET.reg = USB_HOST_PSTATUSSET_PFREEZE;
|
---|
| 381 | }
|
---|
| 382 |
|
---|
| 383 | /**
|
---|
| 384 | * \brief Read from a pipe.
|
---|
| 385 | *
|
---|
| 386 | * \param ul_pipe Pipe number.
|
---|
| 387 | * \param ul_size Maximum number of data to read.
|
---|
| 388 | * \param data Buffer to store the data.
|
---|
| 389 | *
|
---|
| 390 | * \return number of data read.
|
---|
| 391 | */
|
---|
| 392 | uint32_t UHD_Pipe_Read(uint32_t pipe_num, uint32_t buf_size, uint8_t* buf)
|
---|
| 393 | {
|
---|
| 394 | if (USB->HOST.HostPipe[pipe_num].PCFG.bit.PTYPE == USB_HOST_PIPE_TYPE_DISABLE)
|
---|
| 395 | {
|
---|
| 396 | return 0;
|
---|
| 397 | }
|
---|
| 398 |
|
---|
| 399 | /* get pipe config from setting register */
|
---|
| 400 | usb_descriptor_table.usb_pipe_table[pipe_num].HostDescBank[0].ADDR.reg = (uint32_t)buf;
|
---|
| 401 | usb_descriptor_table.usb_pipe_table[pipe_num].HostDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0;
|
---|
| 402 | usb_descriptor_table.usb_pipe_table[pipe_num].HostDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = buf_size;
|
---|
| 403 | USB->HOST.HostPipe[pipe_num].PCFG.bit.PTOKEN = USB_HOST_PIPE_TOKEN_IN;
|
---|
| 404 |
|
---|
| 405 | /* Start transfer */
|
---|
| 406 | USB->HOST.HostPipe[pipe_num].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_BK0RDY;
|
---|
| 407 |
|
---|
| 408 | // Unfreeze pipe
|
---|
| 409 | USB->HOST.HostPipe[pipe_num].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_PFREEZE;
|
---|
| 410 |
|
---|
| 411 | return buf_size;
|
---|
| 412 | }
|
---|
| 413 |
|
---|
| 414 | /**
|
---|
| 415 | * \brief Write into a pipe.
|
---|
| 416 | *
|
---|
| 417 | * \param ul_pipe Pipe number.
|
---|
| 418 | * \param ul_size Maximum number of data to read.
|
---|
| 419 | * \param data Buffer containing data to write.
|
---|
| 420 | */
|
---|
| 421 | void UHD_Pipe_Write(uint32_t ul_pipe, uint32_t ul_size, uint8_t* data)
|
---|
| 422 | {
|
---|
| 423 |
|
---|
| 424 | if (USB->HOST.HostPipe[pipe_num].PCFG.bit.PTYPE == USB_HOST_PIPE_TYPE_DISABLE)
|
---|
| 425 | {
|
---|
| 426 | return 0;
|
---|
| 427 | }
|
---|
| 428 |
|
---|
| 429 | /* get pipe config from setting register */
|
---|
| 430 | usb_descriptor_table.usb_pipe_table[pipe_num].HostDescBank[0].ADDR.reg = (uint32_t)buf;
|
---|
| 431 | usb_descriptor_table.usb_pipe_table[pipe_num].HostDescBank[0].PCKSIZE.bit.BYTE_COUNT = buf_size;
|
---|
| 432 | usb_descriptor_table.usb_pipe_table[pipe_num].HostDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = 0;
|
---|
| 433 | USB->HOST.HostPipe[pipe_num].PCFG.bit.PTOKEN = USB_HOST_PIPE_TOKEN_OUT;
|
---|
| 434 |
|
---|
| 435 |
|
---|
| 436 | return 1;
|
---|
| 437 | }
|
---|
| 438 |
|
---|
| 439 | /**
|
---|
| 440 | * \brief Send a pipe content.
|
---|
| 441 | *
|
---|
| 442 | * \param ul_pipe Pipe number.
|
---|
| 443 | * \param ul_token_type Token type.
|
---|
| 444 | */
|
---|
| 445 | void UHD_Pipe_Send(uint32_t ul_pipe, uint32_t ul_token_type)
|
---|
| 446 | {
|
---|
| 447 | /* Start transfer */
|
---|
| 448 | USB->HOST.HostPipe[pipe_num].PSTATUSSET.reg = USB_HOST_PSTATUSSET_BK0RDY;
|
---|
| 449 |
|
---|
| 450 | // Unfreeze pipe
|
---|
| 451 | USB->HOST.HostPipe[pipe_num].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_PFREEZE;
|
---|
| 452 | }
|
---|
| 453 |
|
---|
| 454 | /**
|
---|
| 455 | * \brief Check for pipe transfer completion.
|
---|
| 456 | *
|
---|
| 457 | * \param ul_pipe Pipe number.
|
---|
| 458 | * \param ul_token_type Token type.
|
---|
| 459 | *
|
---|
| 460 | * \retval 0 transfer is not complete.
|
---|
| 461 | * \retval 1 transfer is complete.
|
---|
| 462 | */
|
---|
| 463 | uint32_t UHD_Pipe_Is_Transfer_Complete(uint32_t ul_pipe, uint32_t ul_token_type)
|
---|
| 464 | {
|
---|
| 465 |
|
---|
| 466 | // Freeze pipe
|
---|
| 467 | USB->HOST.HostPipe[pipe_num].PSTATUSSET.reg = USB_HOST_PSTATUSSET_PFREEZE;
|
---|
| 468 | switch(uhd_ctrl_request_phase) {
|
---|
| 469 | case UHD_CTRL_REQ_PHASE_DATA_IN:
|
---|
| 470 | _uhd_ctrl_phase_data_in(p_callback_para->transfered_size);
|
---|
| 471 | break;
|
---|
| 472 | case UHD_CTRL_REQ_PHASE_ZLP_IN:
|
---|
| 473 | _uhd_ctrl_request_end(UHD_TRANS_NOERROR);
|
---|
| 474 | break;
|
---|
| 475 | case UHD_CTRL_REQ_PHASE_DATA_OUT:
|
---|
| 476 | _uhd_ctrl_phase_data_out();
|
---|
| 477 | break;
|
---|
| 478 | case UHD_CTRL_REQ_PHASE_ZLP_OUT:
|
---|
| 479 | _uhd_ctrl_request_end(UHD_TRANS_NOERROR);
|
---|
| 480 | break;
|
---|
| 481 | }
|
---|
| 482 | return 0;
|
---|
| 483 | }
|
---|
| 484 |
|
---|
| 485 | #endif
|
---|
| 486 |
|
---|