1 |
/*---------------------------------------------------------------------------- |
---|
2 |
* U S B - K e r n e l |
---|
3 |
*---------------------------------------------------------------------------- |
---|
4 |
* Name: USBHW.C |
---|
5 |
* Purpose: USB Hardware Layer Module for Philips LPC214x/LPC318x/23xx/24xx |
---|
6 |
* Version: V1.10 |
---|
7 |
*---------------------------------------------------------------------------- |
---|
8 |
* This file is part of the uVision/ARM development tools. |
---|
9 |
* This software may only be used under the terms of a valid, current, |
---|
10 |
* end user licence from KEIL for a compatible version of KEIL software |
---|
11 |
* development tools. Nothing else gives you the right to use it. |
---|
12 |
* |
---|
13 |
* Copyright (c) 2005-2007 Keil Software. |
---|
14 |
*---------------------------------------------------------------------------*/ |
---|
15 |
|
---|
16 |
#include <LPC23xx.H> /* LPC23xx definitions */ |
---|
17 |
|
---|
18 |
#include "type.h" |
---|
19 |
|
---|
20 |
#include "usb.h" |
---|
21 |
#include "usbcfg.h" |
---|
22 |
#include "usbreg.h" |
---|
23 |
#include "usbhw.h" |
---|
24 |
#include "usbcore.h" |
---|
25 |
#include "usbuser.h" |
---|
26 |
|
---|
27 |
|
---|
28 |
#pragma diag_suppress 1441 |
---|
29 |
|
---|
30 |
|
---|
31 |
#define EP_MSK_CTRL 0x0001 /* Control Endpoint Logical Address Mask */ |
---|
32 |
#define EP_MSK_BULK 0xC924 /* Bulk Endpoint Logical Address Mask */ |
---|
33 |
#define EP_MSK_INT 0x4492 /* Interrupt Endpoint Logical Address Mask */ |
---|
34 |
#define EP_MSK_ISO 0x1248 /* Isochronous Endpoint Logical Address Mask */ |
---|
35 |
|
---|
36 |
|
---|
37 |
#if USB_DMA |
---|
38 |
|
---|
39 |
#pragma arm section zidata = "USB_RAM" |
---|
40 |
DWORD UDCA[USB_EP_NUM]; /* UDCA in USB RAM */ |
---|
41 |
DWORD DD_NISO_Mem[4*DD_NISO_CNT]; /* Non-Iso DMA Descriptor Memory */ |
---|
42 |
DWORD DD_ISO_Mem [5*DD_ISO_CNT]; /* Iso DMA Descriptor Memory */ |
---|
43 |
#pragma arm section zidata |
---|
44 |
DWORD udca[USB_EP_NUM]; /* UDCA saved values */ |
---|
45 |
|
---|
46 |
DWORD DDMemMap[2]; /* DMA Descriptor Memory Usage */ |
---|
47 |
|
---|
48 |
#endif |
---|
49 |
|
---|
50 |
|
---|
51 |
/* |
---|
52 |
* Get Endpoint Physical Address |
---|
53 |
* Parameters: EPNum: Endpoint Number |
---|
54 |
* EPNum.0..3: Address |
---|
55 |
* EPNum.7: Dir |
---|
56 |
* Return Value: Endpoint Physical Address |
---|
57 |
*/ |
---|
58 |
|
---|
59 |
DWORD EPAdr (DWORD EPNum) { |
---|
60 |
DWORD val; |
---|
61 |
|
---|
62 |
val = (EPNum & 0x0F) << 1; |
---|
63 |
if (EPNum & 0x80) { |
---|
64 |
val += 1; |
---|
65 |
} |
---|
66 |
return (val); |
---|
67 |
} |
---|
68 |
|
---|
69 |
|
---|
70 |
/* |
---|
71 |
* Write Command |
---|
72 |
* Parameters: cmd: Command |
---|
73 |
* Return Value: None |
---|
74 |
*/ |
---|
75 |
|
---|
76 |
void WrCmd (DWORD cmd) { |
---|
77 |
|
---|
78 |
DEV_INT_CLR = CCEMTY_INT; |
---|
79 |
CMD_CODE = cmd; |
---|
80 |
while ((DEV_INT_STAT & CCEMTY_INT) == 0); |
---|
81 |
} |
---|
82 |
|
---|
83 |
|
---|
84 |
/* |
---|
85 |
* Write Command Data |
---|
86 |
* Parameters: cmd: Command |
---|
87 |
* val: Data |
---|
88 |
* Return Value: None |
---|
89 |
*/ |
---|
90 |
|
---|
91 |
void WrCmdDat (DWORD cmd, DWORD val) { |
---|
92 |
|
---|
93 |
DEV_INT_CLR = CCEMTY_INT; |
---|
94 |
CMD_CODE = cmd; |
---|
95 |
while ((DEV_INT_STAT & CCEMTY_INT) == 0); |
---|
96 |
DEV_INT_CLR = CCEMTY_INT; |
---|
97 |
CMD_CODE = val; |
---|
98 |
while ((DEV_INT_STAT & CCEMTY_INT) == 0); |
---|
99 |
} |
---|
100 |
|
---|
101 |
|
---|
102 |
/* |
---|
103 |
* Read Command Data |
---|
104 |
* Parameters: cmd: Command |
---|
105 |
* Return Value: Data Value |
---|
106 |
*/ |
---|
107 |
|
---|
108 |
DWORD RdCmdDat (DWORD cmd) { |
---|
109 |
|
---|
110 |
DEV_INT_CLR = CCEMTY_INT | CDFULL_INT; |
---|
111 |
CMD_CODE = cmd; |
---|
112 |
while ((DEV_INT_STAT & CDFULL_INT) == 0); |
---|
113 |
return (CMD_DATA); |
---|
114 |
} |
---|
115 |
|
---|
116 |
|
---|
117 |
/* |
---|
118 |
* USB Initialize Function |
---|
119 |
* Called by the User to initialize USB |
---|
120 |
* Return Value: None |
---|
121 |
*/ |
---|
122 |
|
---|
123 |
void USB_Init (void) { |
---|
124 |
|
---|
125 |
PINSEL1 &= ~0x3C000000; /* P0.29 USB1_D+, P0.30 USB1_D- */ |
---|
126 |
PINSEL1 |= 0x14000000; /* PINSEL1 26.27, 28.29 */ |
---|
127 |
|
---|
128 |
PINSEL3 &= ~0x30000030; /* P1.18 GoodLink, P1.30 VBus */ |
---|
129 |
PINSEL3 |= 0x20000010; /* PINSEL3 4.5, 28.29 */ |
---|
130 |
|
---|
131 |
/* The SoftConnect pin for LPC2300 on USB_U1 doesn't work for now, |
---|
132 |
make it GPIO and make it low to turn on pull-up on D+. |
---|
133 |
Once it's fixed, make #if 1 and set it as SoftConn Pin. */ |
---|
134 |
#if 0 |
---|
135 |
PINSEL4 &= ~0x000C0000; /* P2.9 USB1 SoftConnect */ |
---|
136 |
PINSEL4 |= 0x000040000; /* PINSEl4 18.19 */ |
---|
137 |
#else |
---|
138 |
PINSEL4 &= ~0x000C0000; |
---|
139 |
FIO2DIR |= (1 << 9); |
---|
140 |
FIO2CLR = (1 << 9); |
---|
141 |
#endif |
---|
142 |
|
---|
143 |
PCONP |= 0x80000000; /* USB PCLK -> enable USB Per. */ |
---|
144 |
|
---|
145 |
OTG_CLK_CTRL = 0x12; /* Dev clock, AHB clock enable */ |
---|
146 |
while ((OTG_CLK_STAT & 0x12) != 0x12); |
---|
147 |
|
---|
148 |
VICVectAddr22 = (unsigned long)USB_ISR; /* USB Interrupt -> Vector 22 */ |
---|
149 |
VICVectCntl22 = 0x01; /* USB Interrupt -> Priority 1 */ |
---|
150 |
VICIntEnable = 1 << 22; /* Enable USB Interrupt */ |
---|
151 |
|
---|
152 |
// DEV_INT_EN = DEV_STAT_INT; /* Enable Device Status Interrupt */ |
---|
153 |
|
---|
154 |
#if 1 /* Partial Manual Reset since Automatic Bus Reset is not working */ |
---|
155 |
USB_Reset(); |
---|
156 |
USB_SetAddress(0); |
---|
157 |
#endif |
---|
158 |
} |
---|
159 |
|
---|
160 |
|
---|
161 |
/* |
---|
162 |
* USB Connect Function |
---|
163 |
* Called by the User to Connect/Disconnect USB |
---|
164 |
* Parameters: con: Connect/Disconnect |
---|
165 |
* Return Value: None |
---|
166 |
*/ |
---|
167 |
|
---|
168 |
void USB_Connect (BOOL con) { |
---|
169 |
WrCmdDat(CMD_SET_DEV_STAT, DAT_WR_BYTE(con ? DEV_CON : 0)); |
---|
170 |
} |
---|
171 |
|
---|
172 |
|
---|
173 |
/* |
---|
174 |
* USB Reset Function |
---|
175 |
* Called automatically on USB Reset |
---|
176 |
* Return Value: None |
---|
177 |
*/ |
---|
178 |
|
---|
179 |
void USB_Reset (void) { |
---|
180 |
#if USB_DMA |
---|
181 |
DWORD n; |
---|
182 |
#endif |
---|
183 |
|
---|
184 |
EP_INDEX = 0; |
---|
185 |
MAXPACKET_SIZE = USB_MAX_PACKET0; |
---|
186 |
EP_INDEX = 1; |
---|
187 |
MAXPACKET_SIZE = USB_MAX_PACKET0; |
---|
188 |
while ((DEV_INT_STAT & EP_RLZED_INT) == 0); |
---|
189 |
|
---|
190 |
EP_INT_CLR = 0xFFFFFFFF; |
---|
191 |
EP_INT_EN = 0xFFFFFFFF ^ USB_DMA_EP; |
---|
192 |
DEV_INT_CLR = 0xFFFFFFFF; |
---|
193 |
DEV_INT_EN = DEV_STAT_INT | EP_SLOW_INT | |
---|
194 |
(USB_SOF_EVENT ? FRAME_INT : 0) | |
---|
195 |
(USB_ERROR_EVENT ? ERR_INT : 0); |
---|
196 |
|
---|
197 |
#if USB_DMA |
---|
198 |
UDCA_HEAD = USB_RAM_ADR; |
---|
199 |
DMA_REQ_CLR = 0xFFFFFFFF; |
---|
200 |
EP_DMA_DIS = 0xFFFFFFFF; |
---|
201 |
EP_DMA_EN = USB_DMA_EP; |
---|
202 |
EOT_INT_CLR = 0xFFFFFFFF; |
---|
203 |
NDD_REQ_INT_CLR = 0xFFFFFFFF; |
---|
204 |
SYS_ERR_INT_CLR = 0xFFFFFFFF; |
---|
205 |
DMA_INT_EN = 0x00000007; |
---|
206 |
DDMemMap[0] = 0x00000000; |
---|
207 |
DDMemMap[1] = 0x00000000; |
---|
208 |
for (n = 0; n < USB_EP_NUM; n++) { |
---|
209 |
udca[n] = 0; |
---|
210 |
UDCA[n] = 0; |
---|
211 |
} |
---|
212 |
#endif |
---|
213 |
} |
---|
214 |
|
---|
215 |
|
---|
216 |
/* |
---|
217 |
* USB Suspend Function |
---|
218 |
* Called automatically on USB Suspend |
---|
219 |
* Return Value: None |
---|
220 |
*/ |
---|
221 |
|
---|
222 |
void USB_Suspend (void) { |
---|
223 |
/* Performed by Hardware */ |
---|
224 |
} |
---|
225 |
|
---|
226 |
|
---|
227 |
/* |
---|
228 |
* USB Resume Function |
---|
229 |
* Called automatically on USB Resume |
---|
230 |
* Return Value: None |
---|
231 |
*/ |
---|
232 |
|
---|
233 |
void USB_Resume (void) { |
---|
234 |
/* Performed by Hardware */ |
---|
235 |
} |
---|
236 |
|
---|
237 |
|
---|
238 |
/* |
---|
239 |
* USB Remote Wakeup Function |
---|
240 |
* Called automatically on USB Remote Wakeup |
---|
241 |
* Return Value: None |
---|
242 |
*/ |
---|
243 |
|
---|
244 |
void USB_WakeUp (void) { |
---|
245 |
|
---|
246 |
if (USB_DeviceStatus & USB_GETSTATUS_REMOTE_WAKEUP) { |
---|
247 |
WrCmdDat(CMD_SET_DEV_STAT, DAT_WR_BYTE(DEV_CON)); |
---|
248 |
} |
---|
249 |
} |
---|
250 |
|
---|
251 |
|
---|
252 |
/* |
---|
253 |
* USB Remote Wakeup Configuration Function |
---|
254 |
* Parameters: cfg: Enable/Disable |
---|
255 |
* Return Value: None |
---|
256 |
*/ |
---|
257 |
|
---|
258 |
void USB_WakeUpCfg (BOOL cfg) { |
---|
259 |
/* Not needed */ |
---|
260 |
} |
---|
261 |
|
---|
262 |
|
---|
263 |
/* |
---|
264 |
* USB Set Address Function |
---|
265 |
* Parameters: adr: USB Address |
---|
266 |
* Return Value: None |
---|
267 |
*/ |
---|
268 |
|
---|
269 |
void USB_SetAddress (DWORD adr) { |
---|
270 |
WrCmdDat(CMD_SET_ADDR, DAT_WR_BYTE(DEV_EN | adr)); /* Don't wait for next */ |
---|
271 |
WrCmdDat(CMD_SET_ADDR, DAT_WR_BYTE(DEV_EN | adr)); /* Setup Status Phase */ |
---|
272 |
} |
---|
273 |
|
---|
274 |
|
---|
275 |
/* |
---|
276 |
* USB Configure Function |
---|
277 |
* Parameters: cfg: Configure/Deconfigure |
---|
278 |
* Return Value: None |
---|
279 |
*/ |
---|
280 |
|
---|
281 |
void USB_Configure (BOOL cfg) { |
---|
282 |
|
---|
283 |
WrCmdDat(CMD_CFG_DEV, DAT_WR_BYTE(cfg ? CONF_DVICE : 0)); |
---|
284 |
|
---|
285 |
REALIZE_EP = 0x00000003; |
---|
286 |
while ((DEV_INT_STAT & EP_RLZED_INT) == 0); |
---|
287 |
DEV_INT_CLR = EP_RLZED_INT; |
---|
288 |
} |
---|
289 |
|
---|
290 |
|
---|
291 |
/* |
---|
292 |
* Configure USB Endpoint according to Descriptor |
---|
293 |
* Parameters: pEPD: Pointer to Endpoint Descriptor |
---|
294 |
* Return Value: None |
---|
295 |
*/ |
---|
296 |
|
---|
297 |
void USB_ConfigEP (USB_ENDPOINT_DESCRIPTOR *pEPD) { |
---|
298 |
DWORD num; |
---|
299 |
|
---|
300 |
num = EPAdr(pEPD->bEndpointAddress); |
---|
301 |
REALIZE_EP |= (1 << num); |
---|
302 |
EP_INDEX = num; |
---|
303 |
MAXPACKET_SIZE = pEPD->wMaxPacketSize; |
---|
304 |
while ((DEV_INT_STAT & EP_RLZED_INT) == 0); |
---|
305 |
DEV_INT_CLR = EP_RLZED_INT; |
---|
306 |
} |
---|
307 |
|
---|
308 |
|
---|
309 |
/* |
---|
310 |
* Set Direction for USB Control Endpoint |
---|
311 |
* Parameters: dir: Out (dir == 0), In (dir <> 0) |
---|
312 |
* Return Value: None |
---|
313 |
*/ |
---|
314 |
|
---|
315 |
void USB_DirCtrlEP (DWORD dir) { |
---|
316 |
/* Not needed */ |
---|
317 |
} |
---|
318 |
|
---|
319 |
|
---|
320 |
/* |
---|
321 |
* Enable USB Endpoint |
---|
322 |
* Parameters: EPNum: Endpoint Number |
---|
323 |
* EPNum.0..3: Address |
---|
324 |
* EPNum.7: Dir |
---|
325 |
* Return Value: None |
---|
326 |
*/ |
---|
327 |
|
---|
328 |
void USB_EnableEP (DWORD EPNum) { |
---|
329 |
WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(0)); |
---|
330 |
} |
---|
331 |
|
---|
332 |
|
---|
333 |
/* |
---|
334 |
* Disable USB Endpoint |
---|
335 |
* Parameters: EPNum: Endpoint Number |
---|
336 |
* EPNum.0..3: Address |
---|
337 |
* EPNum.7: Dir |
---|
338 |
* Return Value: None |
---|
339 |
*/ |
---|
340 |
|
---|
341 |
void USB_DisableEP (DWORD EPNum) { |
---|
342 |
WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(EP_STAT_DA)); |
---|
343 |
} |
---|
344 |
|
---|
345 |
|
---|
346 |
/* |
---|
347 |
* Reset USB Endpoint |
---|
348 |
* Parameters: EPNum: Endpoint Number |
---|
349 |
* EPNum.0..3: Address |
---|
350 |
* EPNum.7: Dir |
---|
351 |
* Return Value: None |
---|
352 |
*/ |
---|
353 |
|
---|
354 |
void USB_ResetEP (DWORD EPNum) { |
---|
355 |
WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(0)); |
---|
356 |
} |
---|
357 |
|
---|
358 |
|
---|
359 |
/* |
---|
360 |
* Set Stall for USB Endpoint |
---|
361 |
* Parameters: EPNum: Endpoint Number |
---|
362 |
* EPNum.0..3: Address |
---|
363 |
* EPNum.7: Dir |
---|
364 |
* Return Value: None |
---|
365 |
*/ |
---|
366 |
|
---|
367 |
void USB_SetStallEP (DWORD EPNum) { |
---|
368 |
WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(EP_STAT_ST)); |
---|
369 |
} |
---|
370 |
|
---|
371 |
|
---|
372 |
/* |
---|
373 |
* Clear Stall for USB Endpoint |
---|
374 |
* Parameters: EPNum: Endpoint Number |
---|
375 |
* EPNum.0..3: Address |
---|
376 |
* EPNum.7: Dir |
---|
377 |
* Return Value: None |
---|
378 |
*/ |
---|
379 |
|
---|
380 |
void USB_ClrStallEP (DWORD EPNum) { |
---|
381 |
WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(0)); |
---|
382 |
} |
---|
383 |
|
---|
384 |
|
---|
385 |
/* |
---|
386 |
* Read USB Endpoint Data |
---|
387 |
* Parameters: EPNum: Endpoint Number |
---|
388 |
* EPNum.0..3: Address |
---|
389 |
* EPNum.7: Dir |
---|
390 |
* pData: Pointer to Data Buffer |
---|
391 |
* Return Value: Number of bytes read |
---|
392 |
*/ |
---|
393 |
|
---|
394 |
DWORD USB_ReadEP (DWORD EPNum, BYTE *pData) { |
---|
395 |
DWORD cnt, n; |
---|
396 |
|
---|
397 |
USB_CTRL = ((EPNum & 0x0F) << 2) | CTRL_RD_EN; |
---|
398 |
|
---|
399 |
do { |
---|
400 |
cnt = RX_PLENGTH; |
---|
401 |
} while ((cnt & PKT_RDY) == 0); |
---|
402 |
cnt &= PKT_LNGTH_MASK; |
---|
403 |
|
---|
404 |
for (n = 0; n < (cnt + 3) / 4; n++) { |
---|
405 |
*((__packed DWORD *)pData) = RX_DATA; |
---|
406 |
pData += 4; |
---|
407 |
} |
---|
408 |
|
---|
409 |
USB_CTRL = 0; |
---|
410 |
|
---|
411 |
if (((EP_MSK_ISO >> EPNum) & 1) == 0) { /* Non-Isochronous Endpoint */ |
---|
412 |
WrCmd(CMD_SEL_EP(EPAdr(EPNum))); |
---|
413 |
WrCmd(CMD_CLR_BUF); |
---|
414 |
} |
---|
415 |
|
---|
416 |
return (cnt); |
---|
417 |
} |
---|
418 |
|
---|
419 |
|
---|
420 |
/* |
---|
421 |
* Write USB Endpoint Data |
---|
422 |
* Parameters: EPNum: Endpoint Number |
---|
423 |
* EPNum.0..3: Address |
---|
424 |
* EPNum.7: Dir |
---|
425 |
* pData: Pointer to Data Buffer |
---|
426 |
* cnt: Number of bytes to write |
---|
427 |
* Return Value: Number of bytes written |
---|
428 |
*/ |
---|
429 |
|
---|
430 |
DWORD USB_WriteEP (DWORD EPNum, BYTE *pData, DWORD cnt) { |
---|
431 |
DWORD n; |
---|
432 |
|
---|
433 |
USB_CTRL = ((EPNum & 0x0F) << 2) | CTRL_WR_EN; |
---|
434 |
|
---|
435 |
TX_PLENGTH = cnt; |
---|
436 |
|
---|
437 |
for (n = 0; n < (cnt + 3) / 4; n++) { |
---|
438 |
TX_DATA = *((__packed DWORD *)pData); |
---|
439 |
pData += 4; |
---|
440 |
} |
---|
441 |
|
---|
442 |
USB_CTRL = 0; |
---|
443 |
|
---|
444 |
WrCmd(CMD_SEL_EP(EPAdr(EPNum))); |
---|
445 |
WrCmd(CMD_VALID_BUF); |
---|
446 |
|
---|
447 |
return (cnt); |
---|
448 |
} |
---|
449 |
|
---|
450 |
|
---|
451 |
#if USB_DMA |
---|
452 |
|
---|
453 |
|
---|
454 |
/* DMA Descriptor Memory Layout */ |
---|
455 |
const DWORD DDAdr[2] = { DD_NISO_ADR, DD_ISO_ADR }; |
---|
456 |
const DWORD DDSz [2] = { 16, 20 }; |
---|
457 |
|
---|
458 |
|
---|
459 |
/* |
---|
460 |
* Setup USB DMA Transfer for selected Endpoint |
---|
461 |
* Parameters: EPNum: Endpoint Number |
---|
462 |
* pDD: Pointer to DMA Descriptor |
---|
463 |
* Return Value: TRUE - Success, FALSE - Error |
---|
464 |
*/ |
---|
465 |
|
---|
466 |
BOOL USB_DMA_Setup(DWORD EPNum, USB_DMA_DESCRIPTOR *pDD) { |
---|
467 |
DWORD num, ptr, nxt, iso, n; |
---|
468 |
|
---|
469 |
iso = pDD->Cfg.Type.IsoEP; /* Iso or Non-Iso Descriptor */ |
---|
470 |
num = EPAdr(EPNum); /* Endpoint's Physical Address */ |
---|
471 |
|
---|
472 |
ptr = 0; /* Current Descriptor */ |
---|
473 |
nxt = udca[num]; /* Initial Descriptor */ |
---|
474 |
while (nxt) { /* Go through Descriptor List */ |
---|
475 |
ptr = nxt; /* Current Descriptor */ |
---|
476 |
if (!pDD->Cfg.Type.Link) { /* Check for Linked Descriptors */ |
---|
477 |
n = (ptr - DDAdr[iso]) / DDSz[iso]; /* Descriptor Index */ |
---|
478 |
DDMemMap[iso] &= ~(1 << n); /* Unmark Memory Usage */ |
---|
479 |
} |
---|
480 |
nxt = *((DWORD *)ptr); /* Next Descriptor */ |
---|
481 |
} |
---|
482 |
|
---|
483 |
for (n = 0; n < 32; n++) { /* Search for available Memory */ |
---|
484 |
if ((DDMemMap[iso] & (1 << n)) == 0) { |
---|
485 |
break; /* Memory found */ |
---|
486 |
} |
---|
487 |
} |
---|
488 |
if (n == 32) return (FALSE); /* Memory not available */ |
---|
489 |
|
---|
490 |
DDMemMap[iso] |= 1 << n; /* Mark Memory Usage */ |
---|
491 |
nxt = DDAdr[iso] + n * DDSz[iso]; /* Next Descriptor */ |
---|
492 |
|
---|
493 |
if (ptr && pDD->Cfg.Type.Link) { |
---|
494 |
*((DWORD *)(ptr + 0)) = nxt; /* Link in new Descriptor */ |
---|
495 |
*((DWORD *)(ptr + 4)) |= 0x00000004; /* Next DD is Valid */ |
---|
496 |
} else { |
---|
497 |
udca[num] = nxt; /* Save new Descriptor */ |
---|
498 |
UDCA[num] = nxt; /* Update UDCA in USB */ |
---|
499 |
} |
---|
500 |
|
---|
501 |
/* Fill in DMA Descriptor */ |
---|
502 |
*(((DWORD *)nxt)++) = 0; /* Next DD Pointer */ |
---|
503 |
*(((DWORD *)nxt)++) = pDD->Cfg.Type.ATLE | |
---|
504 |
(pDD->Cfg.Type.IsoEP << 4) | |
---|
505 |
(pDD->MaxSize << 5) | |
---|
506 |
(pDD->BufLen << 16); |
---|
507 |
*(((DWORD *)nxt)++) = pDD->BufAdr; |
---|
508 |
*(((DWORD *)nxt)++) = pDD->Cfg.Type.LenPos << 8; |
---|
509 |
if (iso) { |
---|
510 |
*((DWORD *)nxt) = pDD->InfoAdr; |
---|
511 |
} |
---|
512 |
|
---|
513 |
return (TRUE); /* Success */ |
---|
514 |
} |
---|
515 |
|
---|
516 |
|
---|
517 |
/* |
---|
518 |
* Enable USB DMA Endpoint |
---|
519 |
* Parameters: EPNum: Endpoint Number |
---|
520 |
* EPNum.0..3: Address |
---|
521 |
* EPNum.7: Dir |
---|
522 |
* Return Value: None |
---|
523 |
*/ |
---|
524 |
|
---|
525 |
void USB_DMA_Enable (DWORD EPNum) { |
---|
526 |
EP_DMA_EN = 1 << EPAdr(EPNum); |
---|
527 |
} |
---|
528 |
|
---|
529 |
|
---|
530 |
/* |
---|
531 |
* Disable USB DMA Endpoint |
---|
532 |
* Parameters: EPNum: Endpoint Number |
---|
533 |
* EPNum.0..3: Address |
---|
534 |
* EPNum.7: Dir |
---|
535 |
* Return Value: None |
---|
536 |
*/ |
---|
537 |
|
---|
538 |
void USB_DMA_Disable (DWORD EPNum) { |
---|
539 |
EP_DMA_DIS = 1 << EPAdr(EPNum); |
---|
540 |
} |
---|
541 |
|
---|
542 |
|
---|
543 |
/* |
---|
544 |
* Get USB DMA Endpoint Status |
---|
545 |
* Parameters: EPNum: Endpoint Number |
---|
546 |
* EPNum.0..3: Address |
---|
547 |
* EPNum.7: Dir |
---|
548 |
* Return Value: DMA Status |
---|
549 |
*/ |
---|
550 |
|
---|
551 |
DWORD USB_DMA_Status (DWORD EPNum) { |
---|
552 |
DWORD ptr, val; |
---|
553 |
|
---|
554 |
ptr = UDCA[EPAdr(EPNum)]; /* Current Descriptor */ |
---|
555 |
if (ptr == 0) return (USB_DMA_INVALID); |
---|
556 |
|
---|
557 |
val = *((DWORD *)(ptr + 3*4)); /* Status Information */ |
---|
558 |
switch ((val >> 1) & 0x0F) { |
---|
559 |
case 0x00: /* Not serviced */ |
---|
560 |
return (USB_DMA_IDLE); |
---|
561 |
case 0x01: /* Being serviced */ |
---|
562 |
return (USB_DMA_BUSY); |
---|
563 |
case 0x02: /* Normal Completition */ |
---|
564 |
return (USB_DMA_DONE); |
---|
565 |
case 0x03: /* Data Under Run */ |
---|
566 |
return (USB_DMA_UNDER_RUN); |
---|
567 |
case 0x08: /* Data Over Run */ |
---|
568 |
return (USB_DMA_OVER_RUN); |
---|
569 |
case 0x09: /* System Error */ |
---|
570 |
return (USB_DMA_ERROR); |
---|
571 |
} |
---|
572 |
|
---|
573 |
return (USB_DMA_UNKNOWN); |
---|
574 |
} |
---|
575 |
|
---|
576 |
|
---|
577 |
/* |
---|
578 |
* Get USB DMA Endpoint Current Buffer Address |
---|
579 |
* Parameters: EPNum: Endpoint Number |
---|
580 |
* EPNum.0..3: Address |
---|
581 |
* EPNum.7: Dir |
---|
582 |
* Return Value: DMA Address (or -1 when DMA is Invalid) |
---|
583 |
*/ |
---|
584 |
|
---|
585 |
DWORD USB_DMA_BufAdr (DWORD EPNum) { |
---|
586 |
DWORD ptr, val; |
---|
587 |
|
---|
588 |
ptr = UDCA[EPAdr(EPNum)]; /* Current Descriptor */ |
---|
589 |
if (ptr == 0) return ((DWORD)(-1)); /* DMA Invalid */ |
---|
590 |
|
---|
591 |
val = *((DWORD *)(ptr + 2*4)); /* Buffer Address */ |
---|
592 |
|
---|
593 |
return (val); /* Current Address */ |
---|
594 |
} |
---|
595 |
|
---|
596 |
|
---|
597 |
/* |
---|
598 |
* Get USB DMA Endpoint Current Buffer Count |
---|
599 |
* Number of transfered Bytes or Iso Packets |
---|
600 |
* Parameters: EPNum: Endpoint Number |
---|
601 |
* EPNum.0..3: Address |
---|
602 |
* EPNum.7: Dir |
---|
603 |
* Return Value: DMA Count (or -1 when DMA is Invalid) |
---|
604 |
*/ |
---|
605 |
|
---|
606 |
DWORD USB_DMA_BufCnt (DWORD EPNum) { |
---|
607 |
DWORD ptr, val; |
---|
608 |
|
---|
609 |
ptr = UDCA[EPAdr(EPNum)]; /* Current Descriptor */ |
---|
610 |
if (ptr == 0) return ((DWORD)(-1)); /* DMA Invalid */ |
---|
611 |
|
---|
612 |
val = *((DWORD *)(ptr + 3*4)); /* Status Information */ |
---|
613 |
|
---|
614 |
return (val >> 16); /* Current Count */ |
---|
615 |
} |
---|
616 |
|
---|
617 |
|
---|
618 |
#endif /* USB_DMA */ |
---|
619 |
|
---|
620 |
|
---|
621 |
/* |
---|
622 |
* Get USB Last Frame Number |
---|
623 |
* Parameters: None |
---|
624 |
* Return Value: Frame Number |
---|
625 |
*/ |
---|
626 |
|
---|
627 |
DWORD USB_GetFrame (void) { |
---|
628 |
DWORD val; |
---|
629 |
|
---|
630 |
WrCmd(CMD_RD_FRAME); |
---|
631 |
val = RdCmdDat(DAT_RD_FRAME); |
---|
632 |
val = val | (RdCmdDat(DAT_RD_FRAME) << 8); |
---|
633 |
|
---|
634 |
return (val); |
---|
635 |
} |
---|
636 |
|
---|
637 |
|
---|
638 |
/* |
---|
639 |
* USB Interrupt Service Routine |
---|
640 |
*/ |
---|
641 |
|
---|
642 |
void USB_ISR (void) __irq { |
---|
643 |
DWORD disr, val, n, m; |
---|
644 |
|
---|
645 |
disr = DEV_INT_STAT; /* Device Interrupt Status */ |
---|
646 |
DEV_INT_CLR = disr; /* A known issue on LPC214x */ |
---|
647 |
|
---|
648 |
/* Device Status Interrupt (Reset, Connect change, Suspend/Resume) */ |
---|
649 |
if (disr & DEV_STAT_INT) { |
---|
650 |
WrCmd(CMD_GET_DEV_STAT); |
---|
651 |
val = RdCmdDat(DAT_GET_DEV_STAT); /* Device Status */ |
---|
652 |
if (val & DEV_RST) { /* Reset */ |
---|
653 |
USB_Reset(); |
---|
654 |
#if USB_RESET_EVENT |
---|
655 |
USB_Reset_Event(); |
---|
656 |
#endif |
---|
657 |
goto isr_end; |
---|
658 |
} |
---|
659 |
if (val & DEV_CON_CH) { /* Connect change */ |
---|
660 |
#if USB_POWER_EVENT |
---|
661 |
USB_Power_Event(val & DEV_CON); |
---|
662 |
#endif |
---|
663 |
goto isr_end; |
---|
664 |
} |
---|
665 |
if (val & DEV_SUS_CH) { /* Suspend/Resume */ |
---|
666 |
if (val & DEV_SUS) { /* Suspend */ |
---|
667 |
USB_Suspend(); |
---|
668 |
#if USB_SUSPEND_EVENT |
---|
669 |
USB_Suspend_Event(); |
---|
670 |
#endif |
---|
671 |
} else { /* Resume */ |
---|
672 |
USB_Resume(); |
---|
673 |
#if USB_RESUME_EVENT |
---|
674 |
USB_Resume_Event(); |
---|
675 |
#endif |
---|
676 |
} |
---|
677 |
goto isr_end; |
---|
678 |
} |
---|
679 |
} |
---|
680 |
|
---|
681 |
#if USB_SOF_EVENT |
---|
682 |
/* Start of Frame Interrupt */ |
---|
683 |
if (disr & FRAME_INT) { |
---|
684 |
USB_SOF_Event(); |
---|
685 |
} |
---|
686 |
#endif |
---|
687 |
|
---|
688 |
#if USB_ERROR_EVENT |
---|
689 |
/* Error Interrupt */ |
---|
690 |
if (disr & ERR_INT) { |
---|
691 |
WrCmd(CMD_RD_ERR_STAT); |
---|
692 |
val = RdCmdDat(DAT_RD_ERR_STAT); |
---|
693 |
USB_Error_Event(val); |
---|
694 |
} |
---|
695 |
#endif |
---|
696 |
|
---|
697 |
/* Endpoint's Slow Interrupt */ |
---|
698 |
if (disr & EP_SLOW_INT) { |
---|
699 |
|
---|
700 |
while (EP_INT_STAT) { /* Endpoint Interrupt Status */ |
---|
701 |
|
---|
702 |
for (n = 0; n < USB_EP_NUM; n++) { /* Check All Endpoints */ |
---|
703 |
if (EP_INT_STAT & (1 << n)) { |
---|
704 |
m = n >> 1; |
---|
705 |
|
---|
706 |
EP_INT_CLR = 1 << n; |
---|
707 |
while ((DEV_INT_STAT & CDFULL_INT) == 0); |
---|
708 |
val = CMD_DATA; |
---|
709 |
|
---|
710 |
if ((n & 1) == 0) { /* OUT Endpoint */ |
---|
711 |
if (n == 0) { /* Control OUT Endpoint */ |
---|
712 |
if (val & EP_SEL_STP) { /* Setup Packet */ |
---|
713 |
if (USB_P_EP[0]) { |
---|
714 |
USB_P_EP[0](USB_EVT_SETUP); |
---|
715 |
continue; |
---|
716 |
} |
---|
717 |
} |
---|
718 |
} |
---|
719 |
if (USB_P_EP[m]) { |
---|
720 |
USB_P_EP[m](USB_EVT_OUT); |
---|
721 |
} |
---|
722 |
} else { /* IN Endpoint */ |
---|
723 |
if (USB_P_EP[m]) { |
---|
724 |
USB_P_EP[m](USB_EVT_IN); |
---|
725 |
} |
---|
726 |
} |
---|
727 |
} |
---|
728 |
} |
---|
729 |
} |
---|
730 |
} |
---|
731 |
|
---|
732 |
#if USB_DMA |
---|
733 |
|
---|
734 |
if (DMA_INT_STAT & 0x00000001) { /* End of Transfer Interrupt */ |
---|
735 |
val = EOT_INT_STAT; |
---|
736 |
for (n = 2; n < USB_EP_NUM; n++) { /* Check All Endpoints */ |
---|
737 |
if (val & (1 << n)) { |
---|
738 |
m = n >> 1; |
---|
739 |
if ((n & 1) == 0) { /* OUT Endpoint */ |
---|
740 |
if (USB_P_EP[m]) { |
---|
741 |
USB_P_EP[m](USB_EVT_OUT_DMA_EOT); |
---|
742 |
} |
---|
743 |
} else { /* IN Endpoint */ |
---|
744 |
if (USB_P_EP[m]) { |
---|
745 |
USB_P_EP[m](USB_EVT_IN_DMA_EOT); |
---|
746 |
} |
---|
747 |
} |
---|
748 |
} |
---|
749 |
} |
---|
750 |
EOT_INT_CLR = val; |
---|
751 |
} |
---|
752 |
|
---|
753 |
if (DMA_INT_STAT & 0x00000002) { /* New DD Request Interrupt */ |
---|
754 |
val = NDD_REQ_INT_STAT; |
---|
755 |
for (n = 2; n < USB_EP_NUM; n++) { /* Check All Endpoints */ |
---|
756 |
if (val & (1 << n)) { |
---|
757 |
m = n >> 1; |
---|
758 |
if ((n & 1) == 0) { /* OUT Endpoint */ |
---|
759 |
if (USB_P_EP[m]) { |
---|
760 |
USB_P_EP[m](USB_EVT_OUT_DMA_NDR); |
---|
761 |
} |
---|
762 |
} else { /* IN Endpoint */ |
---|
763 |
if (USB_P_EP[m]) { |
---|
764 |
USB_P_EP[m](USB_EVT_IN_DMA_NDR); |
---|
765 |
} |
---|
766 |
} |
---|
767 |
} |
---|
768 |
} |
---|
769 |
NDD_REQ_INT_CLR = val; |
---|
770 |
} |
---|
771 |
|
---|
772 |
if (DMA_INT_STAT & 0x00000004) { /* System Error Interrupt */ |
---|
773 |
val = SYS_ERR_INT_STAT; |
---|
774 |
for (n = 2; n < USB_EP_NUM; n++) { /* Check All Endpoints */ |
---|
775 |
if (val & (1 << n)) { |
---|
776 |
m = n >> 1; |
---|
777 |
if ((n & 1) == 0) { /* OUT Endpoint */ |
---|
778 |
if (USB_P_EP[m]) { |
---|
779 |
USB_P_EP[m](USB_EVT_OUT_DMA_ERR); |
---|
780 |
} |
---|
781 |
} else { /* IN Endpoint */ |
---|
782 |
if (USB_P_EP[m]) { |
---|
783 |
USB_P_EP[m](USB_EVT_IN_DMA_ERR); |
---|
784 |
} |
---|
785 |
} |
---|
786 |
} |
---|
787 |
} |
---|
788 |
SYS_ERR_INT_CLR = val; |
---|
789 |
} |
---|
790 |
|
---|
791 |
#endif /* USB_DMA */ |
---|
792 |
|
---|
793 |
isr_end: |
---|
794 |
// DEV_INT_CLR = disr; |
---|
795 |
VICVectAddr = 0; /* Acknowledge Interrupt */ |
---|
796 |
} |
---|