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