[224] | 1 | /*
|
---|
| 2 | Copyright (c) 2014 Arduino LLC. All right reserved.
|
---|
[136] | 3 |
|
---|
[224] | 4 | This library is free software; you can redistribute it and/or
|
---|
| 5 | modify it under the terms of the GNU Lesser General Public
|
---|
| 6 | License as published by the Free Software Foundation; either
|
---|
| 7 | version 2.1 of the License, or (at your option) any later version.
|
---|
| 8 |
|
---|
| 9 | This library is distributed in the hope that it will be useful,
|
---|
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
---|
| 12 | See the GNU Lesser General Public License for more details.
|
---|
| 13 |
|
---|
| 14 | You should have received a copy of the GNU Lesser General Public
|
---|
| 15 | License along with this library; if not, write to the Free Software
|
---|
| 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
---|
| 17 | */
|
---|
| 18 | /*
|
---|
| 19 | ** Modified 04/04/2016 by Arduino.org development team
|
---|
| 20 | */
|
---|
| 21 |
|
---|
| 22 |
|
---|
| 23 |
|
---|
[136] | 24 | #include <stdio.h>
|
---|
[224] | 25 | #include <stdint.h>
|
---|
| 26 | #include <string.h>
|
---|
[136] | 27 |
|
---|
[224] | 28 | #include "../Arduino.h"
|
---|
| 29 | #include "variant.h"
|
---|
| 30 | #include "USB_host.h"
|
---|
| 31 | #include "samd21_host.h"
|
---|
| 32 | #include "sam.h"
|
---|
| 33 | #include "wiring_digital.h"
|
---|
| 34 | #include "wiring_private.h"
|
---|
| 35 |
|
---|
| 36 | #define HOST_DEFINED
|
---|
| 37 |
|
---|
[136] | 38 | #ifdef HOST_DEFINED
|
---|
| 39 |
|
---|
| 40 | //#define TRACE_UOTGHS_HOST(x) x
|
---|
| 41 | #define TRACE_UOTGHS_HOST(x)
|
---|
| 42 |
|
---|
| 43 | // Handle UOTGHS Host driver state
|
---|
| 44 | static uhd_vbus_state_t uhd_state = UHD_STATE_NO_VBUS;
|
---|
| 45 |
|
---|
[224] | 46 | __attribute__((__aligned__(4))) volatile UsbHostDescriptor usb_pipe_table[USB_EPT_NUM];
|
---|
[136] | 47 |
|
---|
[224] | 48 | extern void (*gpf_isr)(void);
|
---|
[136] | 49 |
|
---|
[224] | 50 |
|
---|
[136] | 51 | // NVM Software Calibration Area Mapping
|
---|
| 52 | // USB TRANSN calibration value. Should be written to the USB PADCAL register.
|
---|
[224] | 53 | #define NVM_USB_PAD_TRANSN_POS 45
|
---|
| 54 | #define NVM_USB_PAD_TRANSN_SIZE 5
|
---|
[136] | 55 | // USB TRANSP calibration value. Should be written to the USB PADCAL register.
|
---|
[224] | 56 | #define NVM_USB_PAD_TRANSP_POS 50
|
---|
| 57 | #define NVM_USB_PAD_TRANSP_SIZE 5
|
---|
[136] | 58 | // USB TRIM calibration value. Should be written to the USB PADCAL register.
|
---|
[224] | 59 | #define NVM_USB_PAD_TRIM_POS 55
|
---|
| 60 | #define NVM_USB_PAD_TRIM_SIZE 3
|
---|
[136] | 61 |
|
---|
[224] | 62 | static void UHD_ISR(void);
|
---|
| 63 |
|
---|
[136] | 64 | /**
|
---|
| 65 | * \brief Initialize the SAMD21 host driver.
|
---|
| 66 | */
|
---|
| 67 | void UHD_Init(void)
|
---|
| 68 | {
|
---|
| 69 | uint32_t pad_transn;
|
---|
[224] | 70 | uint32_t pad_transp;
|
---|
| 71 | uint32_t pad_trim;
|
---|
| 72 | uint32_t i;
|
---|
[136] | 73 |
|
---|
[224] | 74 | // USB_SetHandler(&USB_Handler);
|
---|
| 75 | USB_SetHandler(&UHD_ISR);
|
---|
| 76 |
|
---|
[136] | 77 | /* Enable USB clock */
|
---|
| 78 | PM->APBBMASK.reg |= PM_APBBMASK_USB;
|
---|
| 79 |
|
---|
[224] | 80 | /* Set up the USB DP/DM pins */
|
---|
| 81 | pinPeripheral( 33ul, PIO_COM );
|
---|
| 82 | pinPeripheral( 34ul, PIO_COM );
|
---|
[136] | 83 |
|
---|
| 84 | /* ----------------------------------------------------------------------------------------------
|
---|
[224] | 85 | * Put Generic Clock Generator 0 as source for Generic Clock Multiplexer 6 (USB reference)
|
---|
| 86 | */
|
---|
| 87 | GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(6) | // Generic Clock Multiplexer 6
|
---|
| 88 | GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
|
---|
| 89 | GCLK_CLKCTRL_CLKEN;
|
---|
[136] | 90 |
|
---|
[224] | 91 | while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY)
|
---|
[136] | 92 | {
|
---|
[224] | 93 | /* Wait for synchronization */
|
---|
[136] | 94 | }
|
---|
| 95 |
|
---|
| 96 | /* Reset */
|
---|
| 97 | USB->HOST.CTRLA.bit.SWRST = 1;
|
---|
[224] | 98 | while (USB->HOST.SYNCBUSY.bit.SWRST)
|
---|
| 99 | {
|
---|
[136] | 100 | /* Sync wait */
|
---|
| 101 | }
|
---|
| 102 |
|
---|
[224] | 103 | // uhd_enable();
|
---|
| 104 | USB->DEVICE.CTRLA.reg |= USB_CTRLA_ENABLE | USB_CTRLA_MODE;
|
---|
| 105 | uhd_force_host_mode();
|
---|
| 106 | while (USB->HOST.SYNCBUSY.reg == USB_SYNCBUSY_ENABLE);
|
---|
[136] | 107 |
|
---|
| 108 | /* Load Pad Calibration */
|
---|
[224] | 109 | pad_transn = (*((uint32_t *)(NVMCTRL_OTP4) // Non-Volatile Memory Controller
|
---|
| 110 | + (NVM_USB_PAD_TRANSN_POS / 32))
|
---|
| 111 | >> (NVM_USB_PAD_TRANSN_POS % 32))
|
---|
| 112 | & ((1 << NVM_USB_PAD_TRANSN_SIZE) - 1);
|
---|
[136] | 113 |
|
---|
[224] | 114 | if (pad_transn == 0x1F) // maximum value (31)
|
---|
| 115 | {
|
---|
[136] | 116 | pad_transn = 5;
|
---|
| 117 | }
|
---|
| 118 |
|
---|
| 119 | USB->HOST.PADCAL.bit.TRANSN = pad_transn;
|
---|
| 120 |
|
---|
[224] | 121 | pad_transp = (*((uint32_t *)(NVMCTRL_OTP4)
|
---|
| 122 | + (NVM_USB_PAD_TRANSP_POS / 32))
|
---|
| 123 | >> (NVM_USB_PAD_TRANSP_POS % 32))
|
---|
| 124 | & ((1 << NVM_USB_PAD_TRANSP_SIZE) - 1);
|
---|
[136] | 125 |
|
---|
[224] | 126 | if (pad_transp == 0x1F) // maximum value (31)
|
---|
| 127 | {
|
---|
[136] | 128 | pad_transp = 29;
|
---|
| 129 | }
|
---|
| 130 |
|
---|
| 131 | USB->HOST.PADCAL.bit.TRANSP = pad_transp;
|
---|
| 132 |
|
---|
[224] | 133 | pad_trim = (*((uint32_t *)(NVMCTRL_OTP4)
|
---|
| 134 | + (NVM_USB_PAD_TRIM_POS / 32))
|
---|
| 135 | >> (NVM_USB_PAD_TRIM_POS % 32))
|
---|
| 136 | & ((1 << NVM_USB_PAD_TRIM_SIZE) - 1);
|
---|
[136] | 137 |
|
---|
[224] | 138 | if (pad_trim == 0x7) // maximum value (7)
|
---|
| 139 | {
|
---|
[136] | 140 | pad_trim = 3;
|
---|
| 141 | }
|
---|
| 142 |
|
---|
| 143 | USB->HOST.PADCAL.bit.TRIM = pad_trim;
|
---|
| 144 |
|
---|
[224] | 145 |
|
---|
[136] | 146 | /* Set the configuration */
|
---|
[224] | 147 | uhd_run_in_standby();
|
---|
| 148 | // Set address of USB SRAM
|
---|
| 149 | USB->HOST.DESCADD.reg = (uint32_t)(&usb_pipe_table[0]);
|
---|
| 150 | // For USB_SPEED_FULL
|
---|
| 151 | uhd_force_full_speed();
|
---|
| 152 | for (i = 0; i < sizeof(usb_pipe_table); i++)
|
---|
| 153 | {
|
---|
| 154 | (*(uint32_t *)(&usb_pipe_table[0] + i)) = 0;
|
---|
| 155 | }
|
---|
[136] | 156 |
|
---|
| 157 | uhd_state = UHD_STATE_NO_VBUS;
|
---|
| 158 |
|
---|
[224] | 159 | // Put VBUS on USB port
|
---|
| 160 | pinMode( 32ul, OUTPUT );
|
---|
| 161 | digitalWrite( 32ul, HIGH );
|
---|
| 162 |
|
---|
| 163 | uhd_enable_connection_int();
|
---|
| 164 |
|
---|
| 165 | USB->HOST.INTENSET.reg = USB_HOST_INTENSET_DCONN;
|
---|
| 166 | USB->HOST.INTENSET.reg = USB_HOST_INTENSET_WAKEUP;
|
---|
| 167 | USB->HOST.INTENSET.reg = USB_HOST_INTENSET_DDISC;
|
---|
| 168 |
|
---|
[136] | 169 | USB->HOST.CTRLB.bit.VBUSOK = 1;
|
---|
| 170 |
|
---|
| 171 | // Configure interrupts
|
---|
[224] | 172 | NVIC_SetPriority((IRQn_Type)USB_IRQn, 0UL);
|
---|
| 173 | NVIC_EnableIRQ((IRQn_Type)USB_IRQn);
|
---|
[136] | 174 | }
|
---|
| 175 |
|
---|
[224] | 176 |
|
---|
| 177 | static void UHD_ISR(void)
|
---|
| 178 | //void USB_Handler(void)
|
---|
[136] | 179 | {
|
---|
[224] | 180 | uint16_t flags;
|
---|
[136] | 181 |
|
---|
[224] | 182 | if (USB->HOST.CTRLA.bit.MODE) {
|
---|
| 183 | /*host mode ISR */
|
---|
[136] | 184 |
|
---|
| 185 | /* get interrupt flags */
|
---|
| 186 | flags = USB->HOST.INTFLAG.reg;
|
---|
| 187 |
|
---|
| 188 | /* host SOF interrupt */
|
---|
[224] | 189 | if (flags & USB_HOST_INTFLAG_HSOF)
|
---|
| 190 | {
|
---|
[136] | 191 | /* clear the flag */
|
---|
| 192 | USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_HSOF;
|
---|
[224] | 193 | uhd_state = UHD_STATE_CONNECTED;
|
---|
[136] | 194 | return;
|
---|
| 195 | }
|
---|
| 196 |
|
---|
| 197 | /* host reset interrupt */
|
---|
[224] | 198 | if (flags & USB_HOST_INTFLAG_RST)
|
---|
| 199 | {
|
---|
[136] | 200 | /* clear the flag */
|
---|
| 201 | USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_RST;
|
---|
[224] | 202 | uhd_state = UHD_STATE_DISCONNECTED; //UHD_STATE_ERROR;
|
---|
[136] | 203 | return;
|
---|
| 204 | }
|
---|
| 205 |
|
---|
| 206 | /* host upstream resume interrupts */
|
---|
[224] | 207 | if (flags & USB_HOST_INTFLAG_UPRSM)
|
---|
| 208 | {
|
---|
[136] | 209 | /* clear the flags */
|
---|
| 210 | USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_UPRSM;
|
---|
[224] | 211 | uhd_state = UHD_STATE_DISCONNECTED; //UHD_STATE_ERROR;
|
---|
[136] | 212 | return;
|
---|
| 213 | }
|
---|
| 214 |
|
---|
| 215 | /* host downstream resume interrupts */
|
---|
[224] | 216 | if (flags & USB_HOST_INTFLAG_DNRSM)
|
---|
| 217 | {
|
---|
[136] | 218 | /* clear the flags */
|
---|
| 219 | USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_DNRSM;
|
---|
[224] | 220 | uhd_state = UHD_STATE_DISCONNECTED; //UHD_STATE_ERROR;
|
---|
[136] | 221 | return;
|
---|
| 222 | }
|
---|
| 223 |
|
---|
| 224 | /* host wakeup interrupts */
|
---|
[224] | 225 | if (flags & USB_HOST_INTFLAG_WAKEUP)
|
---|
| 226 | {
|
---|
[136] | 227 | /* clear the flags */
|
---|
| 228 | USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_WAKEUP;
|
---|
[224] | 229 | uhd_state = UHD_STATE_CONNECTED; //UHD_STATE_ERROR;
|
---|
[136] | 230 | return;
|
---|
| 231 | }
|
---|
| 232 |
|
---|
| 233 | /* host ram access interrupt */
|
---|
[224] | 234 | if (flags & USB_HOST_INTFLAG_RAMACER)
|
---|
| 235 | {
|
---|
[136] | 236 | /* clear the flag */
|
---|
| 237 | USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_RAMACER;
|
---|
[224] | 238 | uhd_state = UHD_STATE_DISCONNECTED; //UHD_STATE_ERROR;
|
---|
[136] | 239 | return;
|
---|
| 240 | }
|
---|
| 241 |
|
---|
| 242 | /* host connect interrupt */
|
---|
[224] | 243 | if (flags & USB_HOST_INTFLAG_DCONN)
|
---|
| 244 | {
|
---|
| 245 | TRACE_UOTGHS_HOST(printf(">>> UHD_ISR : Connection INT\r\n");
|
---|
| 246 | )
|
---|
[136] | 247 | /* clear the flag */
|
---|
| 248 | uhd_ack_connection();
|
---|
| 249 | uhd_disable_connection_int();
|
---|
| 250 | uhd_ack_disconnection();
|
---|
| 251 | uhd_enable_disconnection_int();
|
---|
| 252 | //uhd_enable_sof();
|
---|
| 253 | uhd_state = UHD_STATE_CONNECTED;
|
---|
| 254 | return;
|
---|
| 255 | }
|
---|
| 256 |
|
---|
[224] | 257 | /* host disconnect interrupt */
|
---|
| 258 | if (flags & USB_HOST_INTFLAG_DDISC)
|
---|
| 259 | {
|
---|
| 260 | TRACE_UOTGHS_HOST(printf(">>> UHD_ISR : Disconnection INT\r\n");
|
---|
| 261 | )
|
---|
[136] | 262 | /* clear the flag */
|
---|
| 263 | uhd_ack_disconnection();
|
---|
| 264 | uhd_disable_disconnection_int();
|
---|
| 265 | // Stop reset signal, in case of disconnection during reset
|
---|
| 266 | uhd_stop_reset();
|
---|
| 267 | // Disable wakeup/resumes interrupts,
|
---|
| 268 | // in case of disconnection during suspend mode
|
---|
| 269 | uhd_ack_connection();
|
---|
| 270 | uhd_enable_connection_int();
|
---|
| 271 | uhd_state = UHD_STATE_DISCONNECTED;
|
---|
| 272 | return;
|
---|
| 273 | }
|
---|
| 274 | }
|
---|
[224] | 275 | else {
|
---|
| 276 | while(1);
|
---|
| 277 | }
|
---|
[136] | 278 | }
|
---|
| 279 |
|
---|
| 280 |
|
---|
| 281 |
|
---|
| 282 | /**
|
---|
| 283 | * \brief Get VBUS state.
|
---|
| 284 | *
|
---|
| 285 | * \return VBUS status.
|
---|
| 286 | */
|
---|
| 287 | uhd_vbus_state_t UHD_GetVBUSState(void)
|
---|
| 288 | {
|
---|
[224] | 289 | return uhd_state;
|
---|
[136] | 290 | }
|
---|
| 291 |
|
---|
| 292 |
|
---|
| 293 | /**
|
---|
| 294 | * \brief Allocate FIFO for pipe 0.
|
---|
| 295 | *
|
---|
| 296 | * \param ul_add Address of remote device for pipe 0.
|
---|
| 297 | * \param ul_ep_size Actual size of the FIFO in bytes.
|
---|
| 298 | *
|
---|
| 299 | * \retval 0 success.
|
---|
| 300 | * \retval 1 error.
|
---|
| 301 | */
|
---|
[224] | 302 | uint32_t UHD_Pipe0_Alloc(uint32_t ul_add , uint32_t ul_ep_size)
|
---|
[136] | 303 | {
|
---|
[224] | 304 | (void)(ul_add); // Unused argument
|
---|
[136] | 305 |
|
---|
[224] | 306 | if( USB->HOST.STATUS.reg & USB_HOST_STATUS_SPEED(1) )
|
---|
| 307 | ul_ep_size = USB_PCKSIZE_SIZE_8_BYTES; // Low Speed
|
---|
| 308 | else
|
---|
| 309 | ul_ep_size = USB_PCKSIZE_SIZE_64_BYTES; // Full Speed
|
---|
[136] | 310 |
|
---|
[224] | 311 | USB->HOST.HostPipe[0].PCFG.bit.PTYPE = 1; //USB_HOST_PCFG_PTYPE_CTRL;
|
---|
| 312 | usb_pipe_table[0].HostDescBank[0].CTRL_PIPE.bit.PEPNUM = 0;
|
---|
| 313 | usb_pipe_table[0].HostDescBank[0].PCKSIZE.bit.SIZE = ul_ep_size;
|
---|
[136] | 314 |
|
---|
[224] | 315 | return 0;
|
---|
| 316 | }
|
---|
[136] | 317 |
|
---|
| 318 |
|
---|
| 319 | /**
|
---|
| 320 | * \brief Allocate a new pipe.
|
---|
| 321 | *
|
---|
| 322 | * \note UOTGHS maximum pipe number is limited to 10, meaning that only a limited
|
---|
| 323 | * amount of devices can be connected. Unfortunately, using only one pipe shared accross
|
---|
| 324 | * various endpoints and devices is not possible because the UOTGHS IP does not allow to
|
---|
| 325 | * change the data toggle value through register interface.
|
---|
| 326 | *
|
---|
| 327 | * \param ul_dev_addr Address of remote device.
|
---|
| 328 | * \param ul_dev_ep Targeted endpoint of remote device.
|
---|
| 329 | * \param ul_type Pipe type.
|
---|
| 330 | * \param ul_dir Pipe direction.
|
---|
| 331 | * \param ul_maxsize Pipe size.
|
---|
| 332 | * \param ul_interval Polling interval (if applicable to pipe type).
|
---|
| 333 | * \param ul_nb_bank Number of banks associated with this pipe.
|
---|
| 334 | *
|
---|
| 335 | * \return the newly allocated pipe number on success, 0 otherwise.
|
---|
| 336 | */
|
---|
| 337 |
|
---|
| 338 | // 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);
|
---|
| 339 |
|
---|
| 340 | 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)
|
---|
| 341 | //bool uhd_ep_alloc(usb_add_t add, usb_ep_desc_t *ep_desc)
|
---|
| 342 | {
|
---|
| 343 | /* set pipe config */
|
---|
[224] | 344 | USB->HOST.HostPipe[ul_dev_ep].PCFG.bit.BK = ul_nb_bank;
|
---|
| 345 | USB->HOST.HostPipe[ul_dev_ep].PCFG.reg &= ~USB_HOST_PCFG_MASK; // USB->HOST.HostPipe[0].PCFG.bit.PTYPE = 1; //USB_HOST_PCFG_PTYPE_CTRL;
|
---|
| 346 | USB->HOST.HostPipe[ul_dev_ep].PCFG.reg |= ul_type;
|
---|
| 347 | USB->HOST.HostPipe[ul_dev_ep].BINTERVAL.reg = ul_interval;
|
---|
[136] | 348 |
|
---|
[224] | 349 | if (ul_dir & USB_EP_DIR_IN)
|
---|
| 350 | {
|
---|
| 351 | USB->HOST.HostPipe[ul_dev_ep].PCFG.bit.PTOKEN = USB_HOST_PCFG_PTOKEN_IN;
|
---|
| 352 | USB->HOST.HostPipe[ul_dev_ep].PSTATUSSET.reg = USB_HOST_PSTATUSSET_BK0RDY;
|
---|
| 353 | }
|
---|
| 354 | else
|
---|
| 355 | {
|
---|
| 356 | USB->HOST.HostPipe[ul_dev_ep].PCFG.bit.PTOKEN = USB_HOST_PCFG_PTOKEN_OUT;
|
---|
| 357 | USB->HOST.HostPipe[ul_dev_ep].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_BK0RDY;
|
---|
| 358 | }
|
---|
| 359 |
|
---|
| 360 | if( USB->HOST.STATUS.reg & USB_HOST_STATUS_SPEED(1) )
|
---|
| 361 | ul_maxsize = USB_PCKSIZE_SIZE_8_BYTES; // Low Speed
|
---|
[136] | 362 | else
|
---|
[224] | 363 | ul_maxsize = USB_PCKSIZE_SIZE_64_BYTES; // Full Speed
|
---|
[136] | 364 |
|
---|
[224] | 365 | memset((uint8_t *)&usb_pipe_table[ul_dev_ep], 0, sizeof(usb_pipe_table[ul_dev_ep]));
|
---|
[136] | 366 |
|
---|
[224] | 367 | usb_pipe_table[ul_dev_ep].HostDescBank[0].CTRL_PIPE.bit.PDADDR = ul_dev_addr;
|
---|
| 368 | usb_pipe_table[ul_dev_ep].HostDescBank[0].CTRL_PIPE.bit.PEPNUM = ul_dev_ep;
|
---|
| 369 | usb_pipe_table[ul_dev_ep].HostDescBank[0].PCKSIZE.bit.SIZE = ul_maxsize;
|
---|
[136] | 370 |
|
---|
[224] | 371 | return 1;
|
---|
| 372 | }
|
---|
[136] | 373 |
|
---|
[224] | 374 |
|
---|
| 375 | void UHD_Pipe_CountZero(uint32_t ul_pipe)
|
---|
| 376 | {
|
---|
| 377 | usb_pipe_table[ul_pipe].HostDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0;
|
---|
[136] | 378 | }
|
---|
| 379 |
|
---|
| 380 | /**
|
---|
| 381 | * \brief Free a pipe.
|
---|
| 382 | *
|
---|
| 383 | * \param ul_pipe Pipe number to free.
|
---|
| 384 | */
|
---|
| 385 | void UHD_Pipe_Free(uint32_t ul_pipe)
|
---|
| 386 | {
|
---|
[224] | 387 | // The Pipe is frozen and no additional requests will be sent to the device on this pipe address.
|
---|
| 388 | USB->HOST.HostPipe[ul_pipe].PSTATUSSET.reg = USB_HOST_PSTATUSSET_PFREEZE;
|
---|
[136] | 389 | }
|
---|
| 390 |
|
---|
[224] | 391 |
|
---|
[136] | 392 | /**
|
---|
| 393 | * \brief Read from a pipe.
|
---|
| 394 | *
|
---|
| 395 | * \param ul_pipe Pipe number.
|
---|
| 396 | * \param ul_size Maximum number of data to read.
|
---|
| 397 | * \param data Buffer to store the data.
|
---|
| 398 | *
|
---|
| 399 | * \return number of data read.
|
---|
| 400 | */
|
---|
[224] | 401 | uint32_t UHD_Pipe_Read(uint32_t pipe_num, uint32_t buf_size, uint8_t *buf)
|
---|
[136] | 402 | {
|
---|
[224] | 403 | if (USB->HOST.HostPipe[pipe_num].PCFG.bit.PTYPE == USB_HOST_PTYPE_DIS)
|
---|
| 404 | {
|
---|
| 405 | return 0;
|
---|
| 406 | }
|
---|
[136] | 407 |
|
---|
[224] | 408 | /* get pipe config from setting register */
|
---|
| 409 | usb_pipe_table[pipe_num].HostDescBank[0].ADDR.reg = (uint32_t)buf;
|
---|
| 410 | usb_pipe_table[pipe_num].HostDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0;
|
---|
| 411 | usb_pipe_table[pipe_num].HostDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = buf_size;
|
---|
| 412 | USB->HOST.HostPipe[pipe_num].PCFG.bit.PTOKEN = USB_HOST_PCFG_PTOKEN_IN;
|
---|
[136] | 413 |
|
---|
[224] | 414 | /* Start transfer */
|
---|
| 415 | USB->HOST.HostPipe[pipe_num].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_BK0RDY;
|
---|
[136] | 416 |
|
---|
[224] | 417 | // Unfreeze pipe
|
---|
| 418 | USB->HOST.HostPipe[pipe_num].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_PFREEZE;
|
---|
[136] | 419 |
|
---|
[224] | 420 | return buf_size;
|
---|
[136] | 421 | }
|
---|
| 422 |
|
---|
[224] | 423 |
|
---|
[136] | 424 | /**
|
---|
| 425 | * \brief Write into a pipe.
|
---|
| 426 | *
|
---|
| 427 | * \param ul_pipe Pipe number.
|
---|
| 428 | * \param ul_size Maximum number of data to read.
|
---|
| 429 | * \param data Buffer containing data to write.
|
---|
| 430 | */
|
---|
[224] | 431 | void UHD_Pipe_Write(uint32_t ul_pipe, uint32_t ul_size, uint8_t *buf)
|
---|
[136] | 432 | {
|
---|
[224] | 433 | /* get pipe config from setting register */
|
---|
| 434 | usb_pipe_table[ul_pipe].HostDescBank[0].ADDR.reg = (uint32_t)buf;
|
---|
| 435 | usb_pipe_table[ul_pipe].HostDescBank[0].PCKSIZE.bit.BYTE_COUNT = ul_size;
|
---|
| 436 | usb_pipe_table[ul_pipe].HostDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = 0;
|
---|
[136] | 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 | {
|
---|
[224] | 447 | USB->HOST.HostPipe[ul_pipe].PCFG.bit.PTOKEN = ul_token_type;
|
---|
[136] | 448 |
|
---|
[224] | 449 | /* Start transfer */
|
---|
| 450 | if(ul_token_type == USB_HOST_PCFG_PTOKEN_SETUP )
|
---|
| 451 | {
|
---|
| 452 | USB->HOST.HostPipe[ul_pipe].PINTFLAG.reg = USB_HOST_PINTFLAG_TXSTP;
|
---|
| 453 | USB->HOST.HostPipe[ul_pipe].PSTATUSSET.reg = USB_HOST_PSTATUSSET_BK0RDY;
|
---|
| 454 | }
|
---|
| 455 | else if(ul_token_type == USB_HOST_PCFG_PTOKEN_IN )
|
---|
| 456 | {
|
---|
| 457 | USB->HOST.HostPipe[ul_pipe].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_BK0RDY;
|
---|
| 458 | }
|
---|
| 459 | else
|
---|
| 460 | {
|
---|
| 461 | USB->HOST.HostPipe[ul_pipe].PINTFLAG.reg = USB_HOST_PINTFLAG_TRCPT(1); // Transfer Complete 0
|
---|
| 462 | USB->HOST.HostPipe[ul_pipe].PSTATUSSET.reg = USB_HOST_PSTATUSSET_BK0RDY;
|
---|
| 463 | }
|
---|
| 464 |
|
---|
[136] | 465 | // Unfreeze pipe
|
---|
[224] | 466 | uhd_unfreeze_pipe(ul_pipe);
|
---|
[136] | 467 | }
|
---|
| 468 |
|
---|
[224] | 469 | #define USB_HOST_PINTFLAG_TRCPT_Pos 0 /**< \brief (USB_HOST_PINTFLAG) Transfer Complete 0/1 Interrupt Flag */
|
---|
| 470 | #define USB_HOST_PINTFLAG_TRCPT_Msk (0x3u << USB_HOST_PINTFLAG_TRCPT_Pos)
|
---|
| 471 | #define USB_HOST_PINTFLAG_TRCPT(value) ((USB_HOST_PINTFLAG_TRCPT_Msk & ((value) << USB_HOST_PINTFLAG_TRCPT_Pos)))
|
---|
| 472 |
|
---|
[136] | 473 | /**
|
---|
| 474 | * \brief Check for pipe transfer completion.
|
---|
| 475 | *
|
---|
| 476 | * \param ul_pipe Pipe number.
|
---|
| 477 | * \param ul_token_type Token type.
|
---|
| 478 | *
|
---|
| 479 | * \retval 0 transfer is not complete.
|
---|
| 480 | * \retval 1 transfer is complete.
|
---|
| 481 | */
|
---|
| 482 | uint32_t UHD_Pipe_Is_Transfer_Complete(uint32_t ul_pipe, uint32_t ul_token_type)
|
---|
| 483 | {
|
---|
[224] | 484 | // Check for transfer completion depending on token type
|
---|
| 485 | switch (ul_token_type)
|
---|
| 486 | {
|
---|
| 487 | case USB_HOST_PCFG_PTOKEN_SETUP:
|
---|
| 488 | if (Is_uhd_setup_ready(ul_pipe))
|
---|
| 489 | {
|
---|
| 490 | uhd_ack_setup_ready(ul_pipe);
|
---|
| 491 | uhd_freeze_pipe(ul_pipe);
|
---|
| 492 | return 1;
|
---|
| 493 | }
|
---|
| 494 | break;
|
---|
[136] | 495 |
|
---|
[224] | 496 | case USB_HOST_PCFG_PTOKEN_IN:
|
---|
| 497 | if (Is_uhd_in_received(ul_pipe))
|
---|
| 498 | {
|
---|
| 499 | // IN packet received
|
---|
| 500 | uhd_ack_in_received(ul_pipe);
|
---|
| 501 | // Freeze will stop after the transfer
|
---|
| 502 | uhd_freeze_pipe(ul_pipe);
|
---|
| 503 | return 1;
|
---|
| 504 | }
|
---|
| 505 | break;
|
---|
| 506 |
|
---|
| 507 | case USB_HOST_PCFG_PTOKEN_OUT:
|
---|
| 508 | if (Is_uhd_out_ready(ul_pipe))
|
---|
| 509 | {
|
---|
| 510 | // OUT packet sent
|
---|
| 511 | uhd_ack_out_ready(ul_pipe);
|
---|
| 512 | uhd_freeze_pipe(ul_pipe);
|
---|
| 513 | return 1;
|
---|
| 514 | }
|
---|
| 515 | break;
|
---|
| 516 | }
|
---|
| 517 |
|
---|
| 518 | return 0;
|
---|
[136] | 519 | }
|
---|
| 520 |
|
---|
[224] | 521 | #endif // HOST_DEFINED
|
---|