1 | /*
|
---|
2 | Copyright (c) 2014 Arduino LLC. All right reserved.
|
---|
3 |
|
---|
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 |
|
---|
24 | #include <stdio.h>
|
---|
25 | #include <stdint.h>
|
---|
26 | #include <string.h>
|
---|
27 |
|
---|
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 |
|
---|
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 |
|
---|
46 | __attribute__((__aligned__(4))) volatile UsbHostDescriptor usb_pipe_table[USB_EPT_NUM];
|
---|
47 |
|
---|
48 | extern void (*gpf_isr)(void);
|
---|
49 |
|
---|
50 |
|
---|
51 | // NVM Software Calibration Area Mapping
|
---|
52 | // USB TRANSN calibration value. Should be written to the USB PADCAL register.
|
---|
53 | #define NVM_USB_PAD_TRANSN_POS 45
|
---|
54 | #define NVM_USB_PAD_TRANSN_SIZE 5
|
---|
55 | // USB TRANSP calibration value. Should be written to the USB PADCAL register.
|
---|
56 | #define NVM_USB_PAD_TRANSP_POS 50
|
---|
57 | #define NVM_USB_PAD_TRANSP_SIZE 5
|
---|
58 | // USB TRIM calibration value. Should be written to the USB PADCAL register.
|
---|
59 | #define NVM_USB_PAD_TRIM_POS 55
|
---|
60 | #define NVM_USB_PAD_TRIM_SIZE 3
|
---|
61 |
|
---|
62 | static void UHD_ISR(void);
|
---|
63 |
|
---|
64 | /**
|
---|
65 | * \brief Initialize the SAMD21 host driver.
|
---|
66 | */
|
---|
67 | void UHD_Init(void)
|
---|
68 | {
|
---|
69 | uint32_t pad_transn;
|
---|
70 | uint32_t pad_transp;
|
---|
71 | uint32_t pad_trim;
|
---|
72 | uint32_t i;
|
---|
73 |
|
---|
74 | // USB_SetHandler(&USB_Handler);
|
---|
75 | USB_SetHandler(&UHD_ISR);
|
---|
76 |
|
---|
77 | /* Enable USB clock */
|
---|
78 | PM->APBBMASK.reg |= PM_APBBMASK_USB;
|
---|
79 |
|
---|
80 | /* Set up the USB DP/DM pins */
|
---|
81 | pinPeripheral( 33ul, PIO_COM );
|
---|
82 | pinPeripheral( 34ul, PIO_COM );
|
---|
83 |
|
---|
84 | /* ----------------------------------------------------------------------------------------------
|
---|
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;
|
---|
90 |
|
---|
91 | while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY)
|
---|
92 | {
|
---|
93 | /* Wait for synchronization */
|
---|
94 | }
|
---|
95 |
|
---|
96 | /* Reset */
|
---|
97 | USB->HOST.CTRLA.bit.SWRST = 1;
|
---|
98 | while (USB->HOST.SYNCBUSY.bit.SWRST)
|
---|
99 | {
|
---|
100 | /* Sync wait */
|
---|
101 | }
|
---|
102 |
|
---|
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);
|
---|
107 |
|
---|
108 | /* Load Pad Calibration */
|
---|
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);
|
---|
113 |
|
---|
114 | if (pad_transn == 0x1F) // maximum value (31)
|
---|
115 | {
|
---|
116 | pad_transn = 5;
|
---|
117 | }
|
---|
118 |
|
---|
119 | USB->HOST.PADCAL.bit.TRANSN = pad_transn;
|
---|
120 |
|
---|
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);
|
---|
125 |
|
---|
126 | if (pad_transp == 0x1F) // maximum value (31)
|
---|
127 | {
|
---|
128 | pad_transp = 29;
|
---|
129 | }
|
---|
130 |
|
---|
131 | USB->HOST.PADCAL.bit.TRANSP = pad_transp;
|
---|
132 |
|
---|
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);
|
---|
137 |
|
---|
138 | if (pad_trim == 0x7) // maximum value (7)
|
---|
139 | {
|
---|
140 | pad_trim = 3;
|
---|
141 | }
|
---|
142 |
|
---|
143 | USB->HOST.PADCAL.bit.TRIM = pad_trim;
|
---|
144 |
|
---|
145 |
|
---|
146 | /* Set the configuration */
|
---|
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 | }
|
---|
156 |
|
---|
157 | uhd_state = UHD_STATE_NO_VBUS;
|
---|
158 |
|
---|
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 |
|
---|
169 | USB->HOST.CTRLB.bit.VBUSOK = 1;
|
---|
170 |
|
---|
171 | // Configure interrupts
|
---|
172 | NVIC_SetPriority((IRQn_Type)USB_IRQn, 0UL);
|
---|
173 | NVIC_EnableIRQ((IRQn_Type)USB_IRQn);
|
---|
174 | }
|
---|
175 |
|
---|
176 |
|
---|
177 | static void UHD_ISR(void)
|
---|
178 | //void USB_Handler(void)
|
---|
179 | {
|
---|
180 | uint16_t flags;
|
---|
181 |
|
---|
182 | if (USB->HOST.CTRLA.bit.MODE) {
|
---|
183 | /*host mode ISR */
|
---|
184 |
|
---|
185 | /* get interrupt flags */
|
---|
186 | flags = USB->HOST.INTFLAG.reg;
|
---|
187 |
|
---|
188 | /* host SOF interrupt */
|
---|
189 | if (flags & USB_HOST_INTFLAG_HSOF)
|
---|
190 | {
|
---|
191 | /* clear the flag */
|
---|
192 | USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_HSOF;
|
---|
193 | uhd_state = UHD_STATE_CONNECTED;
|
---|
194 | return;
|
---|
195 | }
|
---|
196 |
|
---|
197 | /* host reset interrupt */
|
---|
198 | if (flags & USB_HOST_INTFLAG_RST)
|
---|
199 | {
|
---|
200 | /* clear the flag */
|
---|
201 | USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_RST;
|
---|
202 | uhd_state = UHD_STATE_DISCONNECTED; //UHD_STATE_ERROR;
|
---|
203 | return;
|
---|
204 | }
|
---|
205 |
|
---|
206 | /* host upstream resume interrupts */
|
---|
207 | if (flags & USB_HOST_INTFLAG_UPRSM)
|
---|
208 | {
|
---|
209 | /* clear the flags */
|
---|
210 | USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_UPRSM;
|
---|
211 | uhd_state = UHD_STATE_DISCONNECTED; //UHD_STATE_ERROR;
|
---|
212 | return;
|
---|
213 | }
|
---|
214 |
|
---|
215 | /* host downstream resume interrupts */
|
---|
216 | if (flags & USB_HOST_INTFLAG_DNRSM)
|
---|
217 | {
|
---|
218 | /* clear the flags */
|
---|
219 | USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_DNRSM;
|
---|
220 | uhd_state = UHD_STATE_DISCONNECTED; //UHD_STATE_ERROR;
|
---|
221 | return;
|
---|
222 | }
|
---|
223 |
|
---|
224 | /* host wakeup interrupts */
|
---|
225 | if (flags & USB_HOST_INTFLAG_WAKEUP)
|
---|
226 | {
|
---|
227 | /* clear the flags */
|
---|
228 | USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_WAKEUP;
|
---|
229 | uhd_state = UHD_STATE_CONNECTED; //UHD_STATE_ERROR;
|
---|
230 | return;
|
---|
231 | }
|
---|
232 |
|
---|
233 | /* host ram access interrupt */
|
---|
234 | if (flags & USB_HOST_INTFLAG_RAMACER)
|
---|
235 | {
|
---|
236 | /* clear the flag */
|
---|
237 | USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_RAMACER;
|
---|
238 | uhd_state = UHD_STATE_DISCONNECTED; //UHD_STATE_ERROR;
|
---|
239 | return;
|
---|
240 | }
|
---|
241 |
|
---|
242 | /* host connect interrupt */
|
---|
243 | if (flags & USB_HOST_INTFLAG_DCONN)
|
---|
244 | {
|
---|
245 | TRACE_UOTGHS_HOST(printf(">>> UHD_ISR : Connection INT\r\n");
|
---|
246 | )
|
---|
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 |
|
---|
257 | /* host disconnect interrupt */
|
---|
258 | if (flags & USB_HOST_INTFLAG_DDISC)
|
---|
259 | {
|
---|
260 | TRACE_UOTGHS_HOST(printf(">>> UHD_ISR : Disconnection INT\r\n");
|
---|
261 | )
|
---|
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 | }
|
---|
275 | else {
|
---|
276 | while(1);
|
---|
277 | }
|
---|
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 | {
|
---|
289 | return uhd_state;
|
---|
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 | */
|
---|
302 | uint32_t UHD_Pipe0_Alloc(uint32_t ul_add , uint32_t ul_ep_size)
|
---|
303 | {
|
---|
304 | (void)(ul_add); // Unused argument
|
---|
305 |
|
---|
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
|
---|
310 |
|
---|
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;
|
---|
314 |
|
---|
315 | return 0;
|
---|
316 | }
|
---|
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 */
|
---|
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;
|
---|
348 |
|
---|
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
|
---|
362 | else
|
---|
363 | ul_maxsize = USB_PCKSIZE_SIZE_64_BYTES; // Full Speed
|
---|
364 |
|
---|
365 | memset((uint8_t *)&usb_pipe_table[ul_dev_ep], 0, sizeof(usb_pipe_table[ul_dev_ep]));
|
---|
366 |
|
---|
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;
|
---|
370 |
|
---|
371 | return 1;
|
---|
372 | }
|
---|
373 |
|
---|
374 |
|
---|
375 | void UHD_Pipe_CountZero(uint32_t ul_pipe)
|
---|
376 | {
|
---|
377 | usb_pipe_table[ul_pipe].HostDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0;
|
---|
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 | {
|
---|
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;
|
---|
389 | }
|
---|
390 |
|
---|
391 |
|
---|
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 | */
|
---|
401 | uint32_t UHD_Pipe_Read(uint32_t pipe_num, uint32_t buf_size, uint8_t *buf)
|
---|
402 | {
|
---|
403 | if (USB->HOST.HostPipe[pipe_num].PCFG.bit.PTYPE == USB_HOST_PTYPE_DIS)
|
---|
404 | {
|
---|
405 | return 0;
|
---|
406 | }
|
---|
407 |
|
---|
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;
|
---|
413 |
|
---|
414 | /* Start transfer */
|
---|
415 | USB->HOST.HostPipe[pipe_num].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_BK0RDY;
|
---|
416 |
|
---|
417 | // Unfreeze pipe
|
---|
418 | USB->HOST.HostPipe[pipe_num].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_PFREEZE;
|
---|
419 |
|
---|
420 | return buf_size;
|
---|
421 | }
|
---|
422 |
|
---|
423 |
|
---|
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 | */
|
---|
431 | void UHD_Pipe_Write(uint32_t ul_pipe, uint32_t ul_size, uint8_t *buf)
|
---|
432 | {
|
---|
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;
|
---|
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 | USB->HOST.HostPipe[ul_pipe].PCFG.bit.PTOKEN = ul_token_type;
|
---|
448 |
|
---|
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 |
|
---|
465 | // Unfreeze pipe
|
---|
466 | uhd_unfreeze_pipe(ul_pipe);
|
---|
467 | }
|
---|
468 |
|
---|
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 |
|
---|
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 | {
|
---|
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;
|
---|
495 |
|
---|
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;
|
---|
519 | }
|
---|
520 |
|
---|
521 | #endif // HOST_DEFINED
|
---|