| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Endpoint_LPC17xx.c
Go to the documentation of this file.
1 /*
2 * @brief USB Endpoint definitions for the LPC17xx microcontrollers
3 *
4 * @note
5 * Copyright(C) NXP Semiconductors, 2012
6 * All rights reserved.
7 *
8 * @par
9 * Software that is described herein is for illustrative purposes only
10 * which provides customers with programming information regarding the
11 * LPC products. This software is supplied "AS IS" without any warranties of
12 * any kind, and NXP Semiconductors and its licensor disclaim any and
13 * all warranties, express or implied, including all implied warranties of
14 * merchantability, fitness for a particular purpose and non-infringement of
15 * intellectual property rights. NXP Semiconductors assumes no responsibility
16 * or liability for the use of the software, conveys no license or rights under any
17 * patent, copyright, mask work right, or any other intellectual property rights in
18 * or to any products. NXP Semiconductors reserves the right to make changes
19 * in the software without notification. NXP Semiconductors also makes no
20 * representation or warranty that such application will be suitable for the
21 * specified use without further testing or modification.
22 *
23 * @par
24 * Permission to use, copy, modify, and distribute this software and its
25 * documentation is hereby granted, under NXP Semiconductors' and its
26 * licensor's relevant copyrights in the software, without fee, provided that it
27 * is used in conjunction with NXP Semiconductors microcontrollers. This
28 * copyright, permission, and disclaimer notice must appear in all copies of
29 * this code.
30 */
31
32 #define __INCLUDE_FROM_USB_DRIVER
33 #include "../../USBMode.h"
34
35 #if (defined(__LPC175X_6X__) || defined(__LPC177X_8X__) || defined(__LPC407X_8X__)) && defined(USB_CAN_BE_DEVICE)
36 #include "../../Endpoint.h"
37
38 #define IsOutEndpoint(PhysicalEP) (!((PhysicalEP) & 1) )
39
40 volatile bool SETUPReceived;
41 volatile bool isOutReceived;
42 volatile bool isInReady;
43
44 PRAGMA_ALIGN_128
45 uint32_t UDCA[32] __BSS(USBRAM_SECTION) ATTR_ALIGNED(128);
46 DMADescriptor dmaDescriptor[USED_PHYSICAL_ENDPOINTS] __BSS(USBRAM_SECTION);
47 static uint8_t SetupPackage[8] __BSS(USBRAM_SECTION);
48 uint32_t DataInRemainCount, DataInRemainOffset;
49 bool IsConfigured, shortpacket;
50 uint8_t *ISO_Address;
51 PRAGMA_ALIGN_4
52 uint8_t iso_buffer[512] ATTR_ALIGNED(4) __BSS(USBRAM_SECTION);
53 PRAGMA_WEAK(CALLBACK_HAL_GetISOBufferAddress, Dummy_EPGetISOAddress)
54 uint32_t CALLBACK_HAL_GetISOBufferAddress(const uint32_t EPNum, uint32_t *last_packet_size) ATTR_WEAK ATTR_ALIAS(
55 Dummy_EPGetISOAddress);
56
57 uint32_t BufferAddressIso[32] __BSS(USBRAM_SECTION);
58 uint32_t SizeAudioTransfer;
59
60 void SIE_WriteCommand(uint32_t cmd) {
61
62 USB_REG(0)->DevIntClr = CCEMTY_INT;
63 USB_REG(0)->CmdCode = cmd;
64 while ((USB_REG(0)->DevIntSt & CCEMTY_INT) == 0) ;
65 }
66
67 void SIE_WriteCommandData(uint32_t cmd, uint32_t val) {
68
69 USB_REG(0)->DevIntClr = CCEMTY_INT;
70 USB_REG(0)->CmdCode = cmd;
71 while ((USB_REG(0)->DevIntSt & CCEMTY_INT) == 0) ;
72 USB_REG(0)->DevIntClr = CCEMTY_INT;
73 USB_REG(0)->CmdCode = val;
74 while ((USB_REG(0)->DevIntSt & CCEMTY_INT) == 0) ;
75 }
76
77 uint32_t SIE_ReadCommandData(uint32_t cmd) {
78
79 USB_REG(0)->DevIntClr = CCEMTY_INT | CDFULL_INT;
80 USB_REG(0)->CmdCode = cmd;
81 while ((USB_REG(0)->DevIntSt & CDFULL_INT) == 0) ;
82 return USB_REG(0)->CmdData;
83 }
84
85 void HAL_Reset(uint8_t corenum)
86 {
87 uint32_t n;
88
89 USB_REG(corenum)->EpInd = 0;
90 USB_REG(corenum)->MaxPSize = USB_Device_ControlEndpointSize;
91 USB_REG(corenum)->EpInd = 1;
92 USB_REG(corenum)->MaxPSize = USB_Device_ControlEndpointSize;
93 while ((USB_REG(corenum)->DevIntSt & EP_RLZED_INT) == 0) ;
94
95 /* Slave Register */
96 USB_REG(corenum)->EpIntEn = 0;
97 USB_REG(corenum)->DevIntEn = (DEV_STAT_INT | EP_SLOW_INT | ERR_INT);
98
99 USB_REG(corenum)->EpIntClr = 0xFFFFFFFF;
100 USB_REG(corenum)->DevIntClr = 0xFFFFFFFF;
101 USB_REG(corenum)->EpIntPri = 0;
102
103 /* DMA registers */
104 USB_REG(corenum)->EpDMADis = 0xFFFFFFFF;
105 USB_REG(corenum)->DMARClr = 0xFFFFFFFF;
106 USB_REG(corenum)->EoTIntClr = 0xFFFFFFFF;
107 USB_REG(corenum)->NDDRIntClr = 0xFFFFFFFF;
108 USB_REG(corenum)->SysErrIntClr = 0xFFFFFFFF;
109
110 USB_REG(corenum)->DMAIntEn = (EOT_INT | NDD_REQ_INT | SYS_ERR_INT );
111 USB_REG(corenum)->UDCAH = (uint32_t) UDCA;
112 for (n = 0; n < USED_PHYSICAL_ENDPOINTS; n++)
113 UDCA[n] = 0;
114 IsConfigured = false;
115 isOutReceived = false;
116 isInReady = true;
117 usb_data_buffer_size[corenum] = 0;
118 usb_data_buffer_index[corenum] = 0;
119
120 usb_data_buffer_OUT_size[corenum] = 0;
121 usb_data_buffer_OUT_index[corenum] = 0;
122 // uint32_t usb_data_buffer_IN_size = 0;
123 usb_data_buffer_IN_index[corenum] = 0;
124 // SIE_WriteCommandData(CMD_SET_MODE, DAT_WR_BYTE(0) );
125 // SIE_WriteCommandData(CMD_SET_MODE, DAT_WR_BYTE(INAK_IO | INAK_BO) ); /* Disable INAK_IO, INAK_BO */
126 }
127
128 void Endpoint_StallTransaction(uint8_t corenum)
129 {
130 if (endpointselected[corenum] == ENDPOINT_CONTROLEP) {
131 SIE_WriteCommandData(CMD_SET_EP_STAT(endpointhandle(corenum)[endpointselected[corenum]]), DAT_WR_BYTE(EP_STAT_CND_ST) );
132 }
133 else {
134 SIE_WriteCommandData(CMD_SET_EP_STAT(endpointhandle(corenum)[endpointselected[corenum]]), DAT_WR_BYTE(EP_STAT_ST) );
135 }
136 }
137
138 bool Endpoint_ConfigureEndpoint(uint8_t corenum, const uint8_t Number, const uint8_t Type,
139 const uint8_t Direction, const uint16_t Size, const uint8_t Banks)
140 {
141 uint32_t PhyEP = 2 * Number + (Direction == ENDPOINT_DIR_OUT ? 0 : 1);
142
143 if ((!IsConfigured) && (PhyEP > 1)) {
144 IsConfigured = true;
145 SIE_WriteCommandData(CMD_CFG_DEV, DAT_WR_BYTE(CONF_DVICE));
146 }
147
148 USB_REG(corenum)->ReEp |= (1 << PhyEP); /* Realize endpoint */
149
150 USB_REG(corenum)->EpInd = PhyEP; /* Endpoint Index */
151 USB_REG(corenum)->MaxPSize = Size & 0x3ff; /* Max Packet Size */
152
153 while ((USB_REG(corenum)->DevIntSt & EP_RLZED_INT) == 0) ; /* TODO shouldd we wait for this */
154 USB_REG(corenum)->DevIntClr = EP_RLZED_INT;
155
156 if (Number == ENDPOINT_CONTROLEP) { /* Control endpoints have to uses slave mode */
157 USB_REG(corenum)->EpIntEn |= _BIT(PhyEP);
158 DataInRemainCount = 0;
159 DataInRemainOffset = 0;
160 }
161 else { /* all other endpoints use DMA mode */
162 memset(&dmaDescriptor[PhyEP], 0, sizeof(DMADescriptor));
163 dmaDescriptor[PhyEP].Isochronous = (Type == EP_TYPE_ISOCHRONOUS ? 1 : 0 );
164 dmaDescriptor[PhyEP].MaxPacketSize = Size;
165 dmaDescriptor[PhyEP].Retired = 1; /* inactive DD */
166
167 USB_REG(corenum)->EpDMAEn = _BIT(PhyEP);
168 }
169
170 SIE_WriteCommandData(CMD_SET_EP_STAT(PhyEP), DAT_WR_BYTE(0)); /*enable endpoint*/
171 SIE_WriteCommandData(CMD_SET_EP_STAT(PhyEP), DAT_WR_BYTE(0)); /* Reset Endpoint */
172
173 endpointhandle(corenum)[Number] = (Number == ENDPOINT_CONTROLEP) ? ENDPOINT_CONTROLEP : PhyEP;
174 return true;
175 }
176
177 void ReadControlEndpoint(uint8_t *pData)
178 {
179 uint32_t cnt, n;
180
181 USB_REG(0)->Ctrl = CTRL_RD_EN;
182
183 do {
184 cnt = USB_REG(0)->RxPLen;
185 } while ((cnt & PKT_RDY) == 0);
186 cnt &= PKT_LNGTH_MASK;
187
188 for (n = 0; n < (cnt + 3) / 4; n++) {
189 *((uint32_t *) pData) = USB_REG(0)->RxData;
190 pData += 4;
191 }
192 USB_REG(0)->Ctrl = 0;
193
194 if ((cnt > 0) && (SETUPReceived == false)) {
195 isOutReceived = true;
196 }
197 usb_data_buffer_size[0] = cnt;
198
199 // SIE_WriteCommamd(CMD_SEL_EP(ENDPOINT_CONTROLEP));
200 // SIE_WriteCommamd(CMD_CLR_BUF);
201 }
202
203 void WriteControlEndpoint(uint8_t *pData, uint32_t cnt)
204 {
205 uint32_t n;
206 uint32_t count;
207
208 isInReady = false;
209 if (cnt >= USB_Device_ControlEndpointSize) {
210 if (cnt == USB_Device_ControlEndpointSize) {
211 shortpacket = true;
212 }
213 count = USB_Device_ControlEndpointSize;
214 DataInRemainCount = cnt - USB_Device_ControlEndpointSize;
215 DataInRemainOffset += count;
216 }
217 else {
218 count = cnt;
219 DataInRemainCount = 0;
220 DataInRemainOffset = 0;
221 }
222 USB_REG(0)->Ctrl = CTRL_WR_EN;
223 USB_REG(0)->TxPLen = count;
224
225 for (n = 0; n < (count + 3) / 4; n++) {
226 USB_REG(0)->TxData = *((uint32_t *) pData);
227 pData += 4;
228 }
229
230 USB_REG(0)->Ctrl = 0;
231
232 SIE_WriteCommand(CMD_SEL_EP(ENDPOINT_CONTROLEP + 1));
233 SIE_WriteCommand(CMD_VALID_BUF);
234 }
235
236 void HAL17XX_SetDeviceAddress(uint8_t Address)
237 {
238 SIE_WriteCommandData(CMD_SET_ADDR, DAT_WR_BYTE(DEV_EN | Address)); /* Don't wait for next */
239 SIE_WriteCommandData(CMD_SET_ADDR, DAT_WR_BYTE(DEV_EN | Address)); /* Setup Status Phase */
240 }
241
242 void HAL17XX_USBConnect(uint32_t con)
243 {
244 SIE_WriteCommandData(CMD_SET_DEV_STAT, DAT_WR_BYTE(con ? DEV_CON : 0));
245 }
246
247 void Endpoint_GetSetupPackage(uint8_t corenum, uint8_t *pData)
248 {
249 memcpy(pData, SetupPackage, 8);
250 }
251
252 void SlaveEndpointISR()
253 {
254 uint32_t PhyEP;
255 for (PhyEP = 0; PhyEP < 2; PhyEP++) /* Check Control Endpoints */
256 if (USB_REG(0)->EpIntSt & _BIT(PhyEP)) {
257 USB_REG(0)->EpIntClr = _BIT(PhyEP); /*-- Clear Interrupt Endpoint --*/
258
259 if (PhyEP == ENDPOINT_CONTROLEP) { /* Control OUT Endpoint */
260 uint32_t SIEEndpointStatus;
261
262 while ((USB_REG(0)->DevIntSt & CDFULL_INT) == 0) ;
263 SIEEndpointStatus = USB_REG(0)->CmdData;
264
265 if (SIEEndpointStatus & EP_SEL_STP) { /* Setup Packet */
266 SETUPReceived = true;
267 ReadControlEndpoint(SetupPackage);
268 }
269 else {
270 ReadControlEndpoint(usb_data_buffer[0]);
271 }
272 }
273 else { /* IN Endpoint */
274 isInReady = true;
275 if (DataInRemainCount) {
276 WriteControlEndpoint((uint8_t *) (usb_data_buffer[0] + DataInRemainOffset), DataInRemainCount);
277 }
278 else {
279 if (shortpacket) {
280 shortpacket = false;
281 WriteControlEndpoint((uint8_t *) (usb_data_buffer[0] + DataInRemainOffset), DataInRemainCount);
282 DataInRemainOffset = 0;
283 }
284 }
285 }
286 }
287 }
288
289 void Endpoint_Streaming(uint8_t corenum, uint8_t *buffer, uint16_t packetsize,
290 uint16_t totalpackets, uint16_t dummypackets)
291 {
292 uint8_t PhyEP = endpointhandle(corenum)[endpointselected[corenum]];
293 uint16_t i;
294 dummypackets = dummypackets;
295 if (PhyEP & 1) {
296 for (i = 0; i < totalpackets; i++) {
297 while (!Endpoint_IsReadWriteAllowed(corenum)) ;
298 Endpoint_Write_Stream_LE(corenum, (void *) (buffer + i * packetsize), packetsize, NULL);
299 Endpoint_ClearIN(corenum);
300 }
301 }
302 else {
303 for (i = 0; i < totalpackets; i++) {
304 DcdDataTransfer(PhyEP, usb_data_buffer_OUT[corenum], packetsize);
305 Endpoint_ClearOUT(corenum);
306 while (!Endpoint_IsReadWriteAllowed(corenum)) ;
307 Endpoint_Read_Stream_LE(corenum, (void *) (buffer + i * packetsize), packetsize, NULL);
308 }
309 }
310 }
311
312 void DcdDataTransfer(uint8_t PhyEP, uint8_t *pData, uint32_t cnt)
313 {
314 dmaDescriptor[PhyEP].BufferStartAddr = pData;
315 if (dmaDescriptor[PhyEP].Isochronous == 1) {// iso endpoint
316 if (PhyEP & 1) {// IN DIRECTION
317 uint8_t BufferCount;
318 for (BufferCount = 0; BufferCount < cnt / 0xFF; BufferCount++)
319 BufferAddressIso[BufferCount] = 0xFF;
320 BufferAddressIso[BufferCount] = (cnt % 0xFF);
321 if (cnt % 0xFF != 0) {
322 dmaDescriptor[PhyEP].BufferLength = cnt / 0xFF + 1;
323 }
324 else {
325 dmaDescriptor[PhyEP].BufferLength = cnt / 0xFF;
326 }
327 }
328 else { // OUT DIRECTION
329 dmaDescriptor[PhyEP].BufferLength = 1;
330 }
331 dmaDescriptor[PhyEP].IsoBufferAddr = (uint32_t) BufferAddressIso;
332 dmaDescriptor[PhyEP].Isochronous = 1;
333 dmaDescriptor[PhyEP].MaxPacketSize = 0;
334 }
335 else {
336 dmaDescriptor[PhyEP].BufferLength = cnt;
337 }
338 dmaDescriptor[PhyEP].Retired = 0;
339 dmaDescriptor[PhyEP].Status = 0;
340 dmaDescriptor[PhyEP].IsoPacketValid = 0;
341 dmaDescriptor[PhyEP].LSByteExtracted = 0;
342 dmaDescriptor[PhyEP].MSByteExtracted = 0;
343 dmaDescriptor[PhyEP].PresentCount = 0;
344
345 UDCA[PhyEP] = (uint32_t) &dmaDescriptor[PhyEP];
346 USB_REG(0)->EpDMAEn = _BIT(PhyEP);
347 }
348
349 void DMAEndTransferISR()
350 {
351 uint32_t PhyEP;
352 uint32_t EoTIntSt = USB_REG(0)->EoTIntSt;
353
354 for (PhyEP = 2; PhyEP < USED_PHYSICAL_ENDPOINTS; PhyEP++) /* Check All Endpoints */
355 if ( EoTIntSt & _BIT(PhyEP) ) {
356 if ( IsOutEndpoint(PhyEP) ) { /* OUT Endpoint */
357 uint32_t tem = usb_data_buffer_OUT_index[0]; //just to clear warning
358 if (dmaDescriptor[PhyEP].Isochronous == 1) {// iso endpoint
359 SizeAudioTransfer = (BufferAddressIso[0]) & 0xFFFF;
360 ISO_Address = (uint8_t *) CALLBACK_HAL_GetISOBufferAddress(PhyEP / 2, &SizeAudioTransfer);
361 DcdDataTransfer(PhyEP, ISO_Address, 512);
362 }
363 usb_data_buffer_OUT_size[0] += dmaDescriptor[PhyEP].PresentCount;
364 if ((usb_data_buffer_OUT_size[0] + tem + dmaDescriptor[PhyEP].MaxPacketSize) > 512) {
365 USB_REG(0)->DMAIntEn &= ~(1 << 1);
366 }
367 }
368 else { /* IN Endpoint */
369 /* Should be left blank */
370 }
371 }
372 USB_REG(0)->EoTIntClr = EoTIntSt;
373 }
374
375 void DMANewTransferRequestISR()
376 {
377 uint32_t PhyEP;
378 uint32_t NDDRIntSt = USB_REG(0)->NDDRIntSt;
379
380 for (PhyEP = 2; PhyEP < USED_PHYSICAL_ENDPOINTS; PhyEP++) /* Check All Endpoints */
381 if ( NDDRIntSt & _BIT(PhyEP) ) {
382 if ( IsOutEndpoint(PhyEP) ) { /* OUT Endpoint */
383 if (dmaDescriptor[PhyEP].Isochronous == 1) {// iso endpoint
384 DcdDataTransfer(PhyEP, ISO_Address, 512);
385 }
386 else {
387 uint16_t MaxPS = dmaDescriptor[PhyEP].MaxPacketSize;
388 if (usb_data_buffer_OUT_size[0] == 0) {
389 usb_data_buffer_OUT_index[0] = 0;
390 DcdDataTransfer(PhyEP, usb_data_buffer_OUT[0], MaxPS);
391
392 }
393 else {
394 uint32_t tem = usb_data_buffer_OUT_index[0]; //just to clear warning
395 DcdDataTransfer(PhyEP, &usb_data_buffer_OUT[0][usb_data_buffer_OUT_size[0] + tem], MaxPS);
396 }
397 }
398 }
399 else { /* IN Endpoint */
400 if (dmaDescriptor[PhyEP].Isochronous == 1) {
401 ISO_Address = (uint8_t *) CALLBACK_HAL_GetISOBufferAddress(PhyEP / 2, &SizeAudioTransfer);
402 if (SizeAudioTransfer > 0) {
403 DcdDataTransfer(PhyEP, ISO_Address, SizeAudioTransfer);
404 }
405 else {
406 DcdDataTransfer(PhyEP, ISO_Address, 512);
407 }
408 }
409 }
410 }
411 USB_REG(0)->NDDRIntClr = NDDRIntSt;
412 }
413
414 // void DMASysErrISR()
415 // {
416 // uint32_t PhyEP;
417 // uint32_t SysErrIntSt = LPC_USB->USBSysErrIntSt;
418 // for (PhyEP = 2; PhyEP < USED_PHYSICAL_ENDPOINTS; PhyEP++) /* Check All Endpoints */
419 // {
420 // if ( SysErrIntSt & _BIT(PhyEP) )
421 // {
422 // if ( IsOutEndpoint(PhyEP) ) /* OUT Endpoint */
423 // {
424 // }
425 // else /* IN Endpoint */
426 // {
427 // }
428 // }
429 // }
430 // LPC_USB->USBSysErrIntClr = SysErrIntSt;
431 // }
432
433 void DcdIrqHandler(uint8_t DeviceID)
434 {
435 uint32_t DevIntSt, DMAIntSt;
436
437 DevIntSt = USB_REG(DeviceID)->DevIntEn; /* Device Interrupt Status */
438 DevIntSt &= USB_REG(DeviceID)->DevIntEn;
439
440 USB_REG(DeviceID)->DevIntClr = DevIntSt;
441
442 /* Device Status Interrupt (Reset, Connect change, Suspend/Resume) */
443 if (DevIntSt & DEV_STAT_INT) {
444 uint32_t SIEDeviceStatus;
445 SIE_WriteCommand(CMD_GET_DEV_STAT);
446 SIEDeviceStatus = SIE_ReadCommandData(DAT_GET_DEV_STAT); /* Device Status */
447 if (SIEDeviceStatus & DEV_RST) { /* Reset */
448 HAL_Reset(DeviceID);
449 USB_DeviceState[DeviceID] = DEVICE_STATE_Default;
450 Endpoint_ConfigureEndpoint(DeviceID, ENDPOINT_CONTROLEP, 0, ENDPOINT_DIR_OUT, USB_Device_ControlEndpointSize, 0);
451 Endpoint_ConfigureEndpoint(DeviceID, ENDPOINT_CONTROLEP, 0, ENDPOINT_DIR_IN, USB_Device_ControlEndpointSize, 0);
452 }
453 if (SIEDeviceStatus & DEV_CON_CH) { /* Connect change */
454 }
455 if (SIEDeviceStatus & DEV_SUS_CH) { /* Suspend/Resume */
456 if (SIEDeviceStatus & DEV_SUS) { /* Suspend */
457 }
458 else { /* Resume */
459 }
460 }
461 }
462
463 if (DevIntSt & FRAME_INT) {}
464
465 if (DevIntSt & ERR_INT) {
466 volatile uint32_t SIEErrorStatus;
467 SIE_WriteCommand(CMD_RD_ERR_STAT);
468 SIEErrorStatus = SIE_ReadCommandData(DAT_RD_ERR_STAT);
469 }
470
471 /* SLAVE mode : Endpoint's Slow Interrupt */
472 if ( (DevIntSt & EP_SLOW_INT) || (DevIntSt & EP_FAST_INT) ) {
473 SlaveEndpointISR();
474 }
475
476 /* DMA mode */
477 DMAIntSt = LPC_USB->DMAIntSt;
478 DMAIntSt &= USB_REG(DeviceID)->DMAIntEn;
479
480 if (DMAIntSt & EOT_INT) { /* End of Transfer Interrupt */
481 DMAEndTransferISR();
482 }
483
484 if (DMAIntSt & NDD_REQ_INT) { /* New DD Request Interrupt */
485 DMANewTransferRequestISR();
486
487 }
488
489 if (DMAIntSt & SYS_ERR_INT) { /* System Error Interrupt */
490 // DMASysErrISR();
491 USB_REG(DeviceID)->SysErrIntClr = USB_REG(DeviceID)->SysErrIntSt;
492 }
493 }
494
495 uint32_t Dummy_EPGetISOAddress(uint32_t EPNum, uint32_t *last_packet_size)
496 {
497 return (uint32_t) iso_buffer;
498 }
499
500 #endif /*__LPC17XX__ || __LPC40XX__*/