LPCOpen Platform
LPCOpen Platform for NXP LPC Microcontrollers
 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(__LPC17XX__) || defined(__LPC177X_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 
45 uint32_t UDCA[32] __DATA(USBRAM_SECTION) ATTR_ALIGNED(128);
47 static uint8_t SetupPackage[8] __DATA(USBRAM_SECTION);
48 uint32_t DataInRemainCount, DataInRemainOffset;
49 bool IsConfigured, shortpacket;
50 uint8_t *ISO_Address;
52 uint8_t iso_buffer[512] ATTR_ALIGNED(4) __DATA(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] __DATA(USBRAM_SECTION);
58 uint32_t SizeAudioTransfer;
59 
60 void SIE_WriteCommamd(uint32_t cmd) {
61 
62  LPC_USB->USBDevIntClr = CCEMTY_INT;
63  LPC_USB->USBCmdCode = cmd;
64  while ((LPC_USB->USBDevIntSt & CCEMTY_INT) == 0) ;
65 }
66 
67 void SIE_WriteCommandData(uint32_t cmd, uint32_t val) {
68 
69  LPC_USB->USBDevIntClr = CCEMTY_INT;
70  LPC_USB->USBCmdCode = cmd;
71  while ((LPC_USB->USBDevIntSt & CCEMTY_INT) == 0) ;
72  LPC_USB->USBDevIntClr = CCEMTY_INT;
73  LPC_USB->USBCmdCode = val;
74  while ((LPC_USB->USBDevIntSt & CCEMTY_INT) == 0) ;
75 }
76 
78 
79  LPC_USB->USBDevIntClr = CCEMTY_INT | CDFULL_INT;
80  LPC_USB->USBCmdCode = cmd;
81  while ((LPC_USB->USBDevIntSt & CDFULL_INT) == 0) ;
82  return LPC_USB->USBCmdData;
83 }
84 
85 void HAL_Reset(void)
86 {
87  uint32_t n;
88 
89  LPC_USB->USBEpInd = 0;
90  LPC_USB->USBMaxPSize = USB_Device_ControlEndpointSize;
91  LPC_USB->USBEpInd = 1;
92  LPC_USB->USBMaxPSize = USB_Device_ControlEndpointSize;
93  while ((LPC_USB->USBDevIntSt & EP_RLZED_INT) == 0) ;
94 
95  /* Slave Register */
96  LPC_USB->USBEpIntEn = 0;
97  LPC_USB->USBDevIntEn = (DEV_STAT_INT | EP_SLOW_INT | ERR_INT);
98 
99  LPC_USB->USBEpIntClr = 0xFFFFFFFF;
100  LPC_USB->USBDevIntClr = 0xFFFFFFFF;
101  LPC_USB->USBEpIntPri = 0;
102 
103  /* DMA registers */
104  LPC_USB->USBEpDMADis = 0xFFFFFFFF;
105  LPC_USB->USBDMARClr = 0xFFFFFFFF;
106  LPC_USB->USBEoTIntClr = 0xFFFFFFFF;
107  LPC_USB->USBNDDRIntClr = 0xFFFFFFFF;
108  LPC_USB->USBSysErrIntClr = 0xFFFFFFFF;
109 
110  LPC_USB->USBDMAIntEn = (EOT_INT | NDD_REQ_INT | SYS_ERR_INT );
111  LPC_USB->USBUDCAH = (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;
119 
122  // uint32_t usb_data_buffer_IN_size = 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(void)
129 {
132  }
133  else {
135  }
136 }
137 
138 bool Endpoint_ConfigureEndpoint(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  LPC_USB->USBReEp |= (1 << PhyEP); /* Realize endpoint */
149 
150  LPC_USB->USBEpInd = PhyEP; /* Endpoint Index */
151  LPC_USB->USBMaxPSize = Size & 0x3ff; /* Max Packet Size */
152 
153  while ((LPC_USB->USBDevIntSt & EP_RLZED_INT) == 0) ; /* TODO shouldd we wait for this */
154  LPC_USB->USBDevIntClr = EP_RLZED_INT;
155 
156  if (Number == ENDPOINT_CONTROLEP) { /* Control endpoints have to uses slave mode */
157  LPC_USB->USBEpIntEn |= _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  LPC_USB->USBEpDMAEn = _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[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  LPC_USB->USBCtrl = CTRL_RD_EN;
182 
183  do {
184  cnt = LPC_USB->USBRxPLen;
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) = LPC_USB->USBRxData;
190  pData += 4;
191  }
192  LPC_USB->USBCtrl = 0;
193 
194  if ((cnt > 0) && (SETUPReceived == false)) {
195  isOutReceived = true;
196  }
197  usb_data_buffer_size = 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  }
214  DataInRemainCount = cnt - USB_Device_ControlEndpointSize;
215  DataInRemainOffset += count;
216  }
217  else {
218  count = cnt;
219  DataInRemainCount = 0;
220  DataInRemainOffset = 0;
221  }
222  LPC_USB->USBCtrl = CTRL_WR_EN;
223  LPC_USB->USBTxPLen = count;
224 
225  for (n = 0; n < (count + 3) / 4; n++) {
226  LPC_USB->USBTxData = *((uint32_t *) pData);
227  pData += 4;
228  }
229 
230  LPC_USB->USBCtrl = 0;
231 
232  SIE_WriteCommamd(CMD_SEL_EP(ENDPOINT_CONTROLEP + 1));
233  SIE_WriteCommamd(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 
243 {
244  SIE_WriteCommandData(CMD_SET_DEV_STAT, DAT_WR_BYTE(con ? DEV_CON : 0));
245 }
246 
247 void Endpoint_GetSetupPackage(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 (LPC_USB->USBEpIntSt & _BIT(PhyEP)) {
257  LPC_USB->USBEpIntClr = _BIT(PhyEP); /*-- Clear Interrupt Endpoint --*/
258 
259  if (PhyEP == ENDPOINT_CONTROLEP) { /* Control OUT Endpoint */
260  uint32_t SIEEndpointStatus;
261 
262  while ((LPC_USB->USBDevIntSt & CDFULL_INT) == 0) ;
263  SIEEndpointStatus = LPC_USB->USBCmdData;
264 
265  if (SIEEndpointStatus & EP_SEL_STP) { /* Setup Packet */
266  SETUPReceived = true;
267  ReadControlEndpoint(SetupPackage);
268  }
269  else {
270  ReadControlEndpoint(usb_data_buffer);
271  }
272  }
273  else { /* IN Endpoint */
274  isInReady = true;
275  if (DataInRemainCount) {
276  WriteControlEndpoint((uint8_t *) (usb_data_buffer + DataInRemainOffset), DataInRemainCount);
277  }
278  else {
279  if (shortpacket) {
280  shortpacket = false;
281  WriteControlEndpoint((uint8_t *) (usb_data_buffer + DataInRemainOffset), DataInRemainCount);
282  DataInRemainOffset = 0;
283  }
284  }
285  }
286  }
287 }
288 
289 void Endpoint_Streaming(uint8_t *buffer, uint16_t packetsize,
290  uint16_t totalpackets, uint16_t dummypackets)
291 {
292  uint8_t PhyEP = endpointhandle[endpointselected];
293  uint16_t i;
294  dummypackets = dummypackets;
295  if (PhyEP & 1) {
296  for (i = 0; i < totalpackets; i++) {
297  while (!Endpoint_IsReadWriteAllowed()) ;
298  Endpoint_Write_Stream_LE((void *) (buffer + i * packetsize), packetsize, NULL);
300  }
301  }
302  else {
303  for (i = 0; i < totalpackets; i++) {
304  DcdDataTransfer(PhyEP, usb_data_buffer_OUT, packetsize);
306  while (!Endpoint_IsReadWriteAllowed()) ;
307  Endpoint_Read_Stream_LE((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  LPC_USB->USBEpDMAEn = _BIT(PhyEP);
347 }
348 
349 void DMAEndTransferISR()
350 {
351  uint32_t PhyEP;
352  uint32_t EoTIntSt = LPC_USB->USBEoTIntSt;
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  if (dmaDescriptor[PhyEP].Isochronous == 1) {// iso endpoint
358  SizeAudioTransfer = (BufferAddressIso[0]) & 0xFFFF;
359  ISO_Address = (uint8_t *) CALLBACK_HAL_GetISOBufferAddress(PhyEP / 2, &SizeAudioTransfer);
360  DcdDataTransfer(PhyEP, ISO_Address, 512);
361  }
362  usb_data_buffer_OUT_size += dmaDescriptor[PhyEP].PresentCount;
364  dmaDescriptor[PhyEP].MaxPacketSize) > 512) {
365  LPC_USB->USBDMAIntEn &= ~(1 << 1);
366  }
367  }
368  else { /* IN Endpoint */
369  /* Should be left blank */
370  }
371  }
372  LPC_USB->USBEoTIntClr = EoTIntSt;
373 }
374 
375 void DMANewTransferRequestISR()
376 {
377  uint32_t PhyEP;
378  uint32_t NDDRIntSt = LPC_USB->USBNDDRIntSt;
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) {
390  DcdDataTransfer(PhyEP, usb_data_buffer_OUT, MaxPS);
391 
392  }
393  else {
394  DcdDataTransfer(PhyEP,
396  MaxPS);
397  }
398  }
399  }
400  else { /* IN Endpoint */
401  if (dmaDescriptor[PhyEP].Isochronous == 1) {
402  ISO_Address = (uint8_t *) CALLBACK_HAL_GetISOBufferAddress(PhyEP / 2, &SizeAudioTransfer);
403  if (SizeAudioTransfer > 0) {
404  DcdDataTransfer(PhyEP, ISO_Address, SizeAudioTransfer);
405  }
406  else {
407  DcdDataTransfer(PhyEP, ISO_Address, 512);
408  }
409  }
410  }
411  }
412  LPC_USB->USBNDDRIntClr = NDDRIntSt;
413 }
414 
415 // void DMASysErrISR()
416 // {
417 // uint32_t PhyEP;
418 // uint32_t SysErrIntSt = LPC_USB->USBSysErrIntSt;
419 // for (PhyEP = 2; PhyEP < USED_PHYSICAL_ENDPOINTS; PhyEP++) /* Check All Endpoints */
420 // {
421 // if ( SysErrIntSt & _BIT(PhyEP) )
422 // {
423 // if ( IsOutEndpoint(PhyEP) ) /* OUT Endpoint */
424 // {
425 // }
426 // else /* IN Endpoint */
427 // {
428 // }
429 // }
430 // }
431 // LPC_USB->USBSysErrIntClr = SysErrIntSt;
432 // }
433 
434 void DcdIrqHandler(uint8_t DeviceID)
435 {
436  uint32_t DevIntSt, DMAIntSt;
437 
438  DevIntSt = LPC_USB->USBDevIntSt & LPC_USB->USBDevIntEn; /* Device Interrupt Status */
439  LPC_USB->USBDevIntClr = DevIntSt;
440 
441  /* Device Status Interrupt (Reset, Connect change, Suspend/Resume) */
442  if (DevIntSt & DEV_STAT_INT) {
443  uint32_t SIEDeviceStatus;
444  SIE_WriteCommamd(CMD_GET_DEV_STAT);
445  SIEDeviceStatus = SIE_ReadCommandData(DAT_GET_DEV_STAT); /* Device Status */
446  if (SIEDeviceStatus & DEV_RST) { /* Reset */
447  HAL_Reset();
451  }
452  if (SIEDeviceStatus & DEV_CON_CH) { /* Connect change */
453  }
454  if (SIEDeviceStatus & DEV_SUS_CH) { /* Suspend/Resume */
455  if (SIEDeviceStatus & DEV_SUS) { /* Suspend */
456  }
457  else { /* Resume */
458  }
459  }
460  }
461 
462  if (DevIntSt & FRAME_INT) {}
463 
464  if (DevIntSt & ERR_INT) {
465  volatile uint32_t SIEErrorStatus;
466  SIE_WriteCommamd(CMD_RD_ERR_STAT);
467  SIEErrorStatus = SIE_ReadCommandData(DAT_RD_ERR_STAT);
468  }
469 
470  /* SLAVE mode : Endpoint's Slow Interrupt */
471  if ( (DevIntSt & EP_SLOW_INT) || (DevIntSt & EP_FAST_INT) ) {
472  SlaveEndpointISR();
473  }
474 
475  /* DMA mode */
476  DMAIntSt = LPC_USB->USBDMAIntSt & LPC_USB->USBDMAIntEn;
477 
478  if (DMAIntSt & EOT_INT) { /* End of Transfer Interrupt */
479  DMAEndTransferISR();
480 
481  }
482 
483  if (DMAIntSt & NDD_REQ_INT) { /* New DD Request Interrupt */
484  DMANewTransferRequestISR();
485 
486  }
487 
488  if (DMAIntSt & SYS_ERR_INT) { /* System Error Interrupt */
489  // DMASysErrISR();
490  LPC_USB->USBSysErrIntClr = LPC_USB->USBSysErrIntSt;
491  }
492 }
493 
494 uint32_t Dummy_EPGetISOAddress(uint32_t EPNum, uint32_t *last_packet_size)
495 {
496  return (uint32_t) iso_buffer;
497 }
498 
499 #endif /*__LPC17XX__*/