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 |
|
---|