2 * @brief USB Endpoint definitions for the LPC17xx microcontrollers
\r
5 * Copyright(C) NXP Semiconductors, 2012
\r
6 * All rights reserved.
\r
9 * Software that is described herein is for illustrative purposes only
\r
10 * which provides customers with programming information regarding the
\r
11 * LPC products. This software is supplied "AS IS" without any warranties of
\r
12 * any kind, and NXP Semiconductors and its licensor disclaim any and
\r
13 * all warranties, express or implied, including all implied warranties of
\r
14 * merchantability, fitness for a particular purpose and non-infringement of
\r
15 * intellectual property rights. NXP Semiconductors assumes no responsibility
\r
16 * or liability for the use of the software, conveys no license or rights under any
\r
17 * patent, copyright, mask work right, or any other intellectual property rights in
\r
18 * or to any products. NXP Semiconductors reserves the right to make changes
\r
19 * in the software without notification. NXP Semiconductors also makes no
\r
20 * representation or warranty that such application will be suitable for the
\r
21 * specified use without further testing or modification.
\r
24 * Permission to use, copy, modify, and distribute this software and its
\r
25 * documentation is hereby granted, under NXP Semiconductors' and its
\r
26 * licensor's relevant copyrights in the software, without fee, provided that it
\r
27 * is used in conjunction with NXP Semiconductors microcontrollers. This
\r
28 * copyright, permission, and disclaimer notice must appear in all copies of
\r
32 #define __INCLUDE_FROM_USB_DRIVER
\r
33 #include "../../USBMode.h"
\r
35 #if (defined(__LPC175X_6X__) || defined(__LPC177X_8X__) || defined(__LPC407X_8X__)) && defined(USB_CAN_BE_DEVICE)
\r
36 #include "../../Endpoint.h"
\r
38 #define IsOutEndpoint(PhysicalEP) (!((PhysicalEP) & 1) )
\r
40 volatile bool SETUPReceived;
\r
41 volatile bool isOutReceived;
\r
42 volatile bool isInReady;
\r
45 uint32_t UDCA[32] __BSS(USBRAM_SECTION) ATTR_ALIGNED(128);
\r
46 DMADescriptor dmaDescriptor[USED_PHYSICAL_ENDPOINTS] __BSS(USBRAM_SECTION);
\r
47 static uint8_t SetupPackage[8] __BSS(USBRAM_SECTION);
\r
48 uint32_t DataInRemainCount, DataInRemainOffset;
\r
49 bool IsConfigured, shortpacket;
\r
50 uint8_t *ISO_Address;
\r
52 uint8_t iso_buffer[512] ATTR_ALIGNED(4) __BSS(USBRAM_SECTION);
\r
53 PRAGMA_WEAK(CALLBACK_HAL_GetISOBufferAddress, Dummy_EPGetISOAddress)
\r
54 uint32_t CALLBACK_HAL_GetISOBufferAddress(const uint32_t EPNum, uint32_t *last_packet_size) ATTR_WEAK ATTR_ALIAS(
\r
55 Dummy_EPGetISOAddress);
\r
57 uint32_t BufferAddressIso[32] __BSS(USBRAM_SECTION);
\r
58 uint32_t SizeAudioTransfer;
\r
60 void SIE_WriteCommand(uint32_t cmd) {
\r
62 USB_REG(0)->DevIntClr = CCEMTY_INT;
\r
63 USB_REG(0)->CmdCode = cmd;
\r
64 while ((USB_REG(0)->DevIntSt & CCEMTY_INT) == 0) ;
\r
67 void SIE_WriteCommandData(uint32_t cmd, uint32_t val) {
\r
69 USB_REG(0)->DevIntClr = CCEMTY_INT;
\r
70 USB_REG(0)->CmdCode = cmd;
\r
71 while ((USB_REG(0)->DevIntSt & CCEMTY_INT) == 0) ;
\r
72 USB_REG(0)->DevIntClr = CCEMTY_INT;
\r
73 USB_REG(0)->CmdCode = val;
\r
74 while ((USB_REG(0)->DevIntSt & CCEMTY_INT) == 0) ;
\r
77 uint32_t SIE_ReadCommandData(uint32_t cmd) {
\r
79 USB_REG(0)->DevIntClr = CCEMTY_INT | CDFULL_INT;
\r
80 USB_REG(0)->CmdCode = cmd;
\r
81 while ((USB_REG(0)->DevIntSt & CDFULL_INT) == 0) ;
\r
82 return USB_REG(0)->CmdData;
\r
85 void HAL_Reset(uint8_t corenum)
\r
89 USB_REG(corenum)->EpInd = 0;
\r
90 USB_REG(corenum)->MaxPSize = USB_Device_ControlEndpointSize;
\r
91 USB_REG(corenum)->EpInd = 1;
\r
92 USB_REG(corenum)->MaxPSize = USB_Device_ControlEndpointSize;
\r
93 while ((USB_REG(corenum)->DevIntSt & EP_RLZED_INT) == 0) ;
\r
95 /* Slave Register */
\r
96 USB_REG(corenum)->EpIntEn = 0;
\r
97 USB_REG(corenum)->DevIntEn = (DEV_STAT_INT | EP_SLOW_INT | ERR_INT);
\r
99 USB_REG(corenum)->EpIntClr = 0xFFFFFFFF;
\r
100 USB_REG(corenum)->DevIntClr = 0xFFFFFFFF;
\r
101 USB_REG(corenum)->EpIntPri = 0;
\r
103 /* DMA registers */
\r
104 USB_REG(corenum)->EpDMADis = 0xFFFFFFFF;
\r
105 USB_REG(corenum)->DMARClr = 0xFFFFFFFF;
\r
106 USB_REG(corenum)->EoTIntClr = 0xFFFFFFFF;
\r
107 USB_REG(corenum)->NDDRIntClr = 0xFFFFFFFF;
\r
108 USB_REG(corenum)->SysErrIntClr = 0xFFFFFFFF;
\r
110 USB_REG(corenum)->DMAIntEn = (EOT_INT | NDD_REQ_INT | SYS_ERR_INT );
\r
111 USB_REG(corenum)->UDCAH = (uint32_t) UDCA;
\r
112 for (n = 0; n < USED_PHYSICAL_ENDPOINTS; n++)
\r
114 IsConfigured = false;
\r
115 isOutReceived = false;
\r
117 usb_data_buffer_size[corenum] = 0;
\r
118 usb_data_buffer_index[corenum] = 0;
\r
120 usb_data_buffer_OUT_size[corenum] = 0;
\r
121 usb_data_buffer_OUT_index[corenum] = 0;
\r
122 // uint32_t usb_data_buffer_IN_size = 0;
\r
123 usb_data_buffer_IN_index[corenum] = 0;
\r
124 // SIE_WriteCommandData(CMD_SET_MODE, DAT_WR_BYTE(0) );
\r
125 // SIE_WriteCommandData(CMD_SET_MODE, DAT_WR_BYTE(INAK_IO | INAK_BO) ); /* Disable INAK_IO, INAK_BO */
\r
128 void Endpoint_StallTransaction(uint8_t corenum)
\r
130 if (endpointselected[corenum] == ENDPOINT_CONTROLEP) {
\r
131 SIE_WriteCommandData(CMD_SET_EP_STAT(endpointhandle(corenum)[endpointselected[corenum]]), DAT_WR_BYTE(EP_STAT_CND_ST) );
\r
134 SIE_WriteCommandData(CMD_SET_EP_STAT(endpointhandle(corenum)[endpointselected[corenum]]), DAT_WR_BYTE(EP_STAT_ST) );
\r
138 bool Endpoint_ConfigureEndpoint(uint8_t corenum, const uint8_t Number, const uint8_t Type,
\r
139 const uint8_t Direction, const uint16_t Size, const uint8_t Banks)
\r
141 uint32_t PhyEP = 2 * Number + (Direction == ENDPOINT_DIR_OUT ? 0 : 1);
\r
143 if ((!IsConfigured) && (PhyEP > 1)) {
\r
144 IsConfigured = true;
\r
145 SIE_WriteCommandData(CMD_CFG_DEV, DAT_WR_BYTE(CONF_DVICE));
\r
148 USB_REG(corenum)->ReEp |= (1 << PhyEP); /* Realize endpoint */
\r
150 USB_REG(corenum)->EpInd = PhyEP; /* Endpoint Index */
\r
151 USB_REG(corenum)->MaxPSize = Size & 0x3ff; /* Max Packet Size */
\r
153 while ((USB_REG(corenum)->DevIntSt & EP_RLZED_INT) == 0) ; /* TODO shouldd we wait for this */
\r
154 USB_REG(corenum)->DevIntClr = EP_RLZED_INT;
\r
156 if (Number == ENDPOINT_CONTROLEP) { /* Control endpoints have to uses slave mode */
\r
157 USB_REG(corenum)->EpIntEn |= _BIT(PhyEP);
\r
158 DataInRemainCount = 0;
\r
159 DataInRemainOffset = 0;
\r
161 else { /* all other endpoints use DMA mode */
\r
162 memset(&dmaDescriptor[PhyEP], 0, sizeof(DMADescriptor));
\r
163 dmaDescriptor[PhyEP].Isochronous = (Type == EP_TYPE_ISOCHRONOUS ? 1 : 0 );
\r
164 dmaDescriptor[PhyEP].MaxPacketSize = Size;
\r
165 dmaDescriptor[PhyEP].Retired = 1; /* inactive DD */
\r
167 USB_REG(corenum)->EpDMAEn = _BIT(PhyEP);
\r
170 SIE_WriteCommandData(CMD_SET_EP_STAT(PhyEP), DAT_WR_BYTE(0)); /*enable endpoint*/
\r
171 SIE_WriteCommandData(CMD_SET_EP_STAT(PhyEP), DAT_WR_BYTE(0)); /* Reset Endpoint */
\r
173 endpointhandle(corenum)[Number] = (Number == ENDPOINT_CONTROLEP) ? ENDPOINT_CONTROLEP : PhyEP;
\r
177 void ReadControlEndpoint(uint8_t *pData)
\r
181 USB_REG(0)->Ctrl = CTRL_RD_EN;
\r
184 cnt = USB_REG(0)->RxPLen;
\r
185 } while ((cnt & PKT_RDY) == 0);
\r
186 cnt &= PKT_LNGTH_MASK;
\r
188 for (n = 0; n < (cnt + 3) / 4; n++) {
\r
189 *((uint32_t *) pData) = USB_REG(0)->RxData;
\r
192 USB_REG(0)->Ctrl = 0;
\r
194 if ((cnt > 0) && (SETUPReceived == false)) {
\r
195 isOutReceived = true;
\r
197 usb_data_buffer_size[0] = cnt;
\r
199 // SIE_WriteCommamd(CMD_SEL_EP(ENDPOINT_CONTROLEP));
\r
200 // SIE_WriteCommamd(CMD_CLR_BUF);
\r
203 void WriteControlEndpoint(uint8_t *pData, uint32_t cnt)
\r
209 if (cnt >= USB_Device_ControlEndpointSize) {
\r
210 if (cnt == USB_Device_ControlEndpointSize) {
\r
211 shortpacket = true;
\r
213 count = USB_Device_ControlEndpointSize;
\r
214 DataInRemainCount = cnt - USB_Device_ControlEndpointSize;
\r
215 DataInRemainOffset += count;
\r
219 DataInRemainCount = 0;
\r
220 DataInRemainOffset = 0;
\r
222 USB_REG(0)->Ctrl = CTRL_WR_EN;
\r
223 USB_REG(0)->TxPLen = count;
\r
225 for (n = 0; n < (count + 3) / 4; n++) {
\r
226 USB_REG(0)->TxData = *((uint32_t *) pData);
\r
230 USB_REG(0)->Ctrl = 0;
\r
232 SIE_WriteCommand(CMD_SEL_EP(ENDPOINT_CONTROLEP + 1));
\r
233 SIE_WriteCommand(CMD_VALID_BUF);
\r
236 void HAL17XX_SetDeviceAddress(uint8_t Address)
\r
238 SIE_WriteCommandData(CMD_SET_ADDR, DAT_WR_BYTE(DEV_EN | Address)); /* Don't wait for next */
\r
239 SIE_WriteCommandData(CMD_SET_ADDR, DAT_WR_BYTE(DEV_EN | Address)); /* Setup Status Phase */
\r
242 void HAL17XX_USBConnect(uint32_t con)
\r
244 SIE_WriteCommandData(CMD_SET_DEV_STAT, DAT_WR_BYTE(con ? DEV_CON : 0));
\r
247 void Endpoint_GetSetupPackage(uint8_t corenum, uint8_t *pData)
\r
249 memcpy(pData, SetupPackage, 8);
\r
252 void SlaveEndpointISR()
\r
255 for (PhyEP = 0; PhyEP < 2; PhyEP++) /* Check Control Endpoints */
\r
256 if (USB_REG(0)->EpIntSt & _BIT(PhyEP)) {
\r
257 USB_REG(0)->EpIntClr = _BIT(PhyEP); /*-- Clear Interrupt Endpoint --*/
\r
259 if (PhyEP == ENDPOINT_CONTROLEP) { /* Control OUT Endpoint */
\r
260 uint32_t SIEEndpointStatus;
\r
262 while ((USB_REG(0)->DevIntSt & CDFULL_INT) == 0) ;
\r
263 SIEEndpointStatus = USB_REG(0)->CmdData;
\r
265 if (SIEEndpointStatus & EP_SEL_STP) { /* Setup Packet */
\r
266 SETUPReceived = true;
\r
267 ReadControlEndpoint(SetupPackage);
\r
270 ReadControlEndpoint(usb_data_buffer[0]);
\r
273 else { /* IN Endpoint */
\r
275 if (DataInRemainCount) {
\r
276 WriteControlEndpoint((uint8_t *) (usb_data_buffer[0] + DataInRemainOffset), DataInRemainCount);
\r
280 shortpacket = false;
\r
281 WriteControlEndpoint((uint8_t *) (usb_data_buffer[0] + DataInRemainOffset), DataInRemainCount);
\r
282 DataInRemainOffset = 0;
\r
289 void Endpoint_Streaming(uint8_t corenum, uint8_t *buffer, uint16_t packetsize,
\r
290 uint16_t totalpackets, uint16_t dummypackets)
\r
292 uint8_t PhyEP = endpointhandle(corenum)[endpointselected[corenum]];
\r
294 dummypackets = dummypackets;
\r
296 for (i = 0; i < totalpackets; i++) {
\r
297 while (!Endpoint_IsReadWriteAllowed(corenum)) ;
\r
298 Endpoint_Write_Stream_LE(corenum, (void *) (buffer + i * packetsize), packetsize, NULL);
\r
299 Endpoint_ClearIN(corenum);
\r
303 for (i = 0; i < totalpackets; i++) {
\r
304 DcdDataTransfer(PhyEP, usb_data_buffer_OUT[corenum], packetsize);
\r
305 Endpoint_ClearOUT(corenum);
\r
306 while (!Endpoint_IsReadWriteAllowed(corenum)) ;
\r
307 Endpoint_Read_Stream_LE(corenum, (void *) (buffer + i * packetsize), packetsize, NULL);
\r
312 void DcdDataTransfer(uint8_t PhyEP, uint8_t *pData, uint32_t cnt)
\r
314 dmaDescriptor[PhyEP].BufferStartAddr = pData;
\r
315 if (dmaDescriptor[PhyEP].Isochronous == 1) {// iso endpoint
\r
316 if (PhyEP & 1) {// IN DIRECTION
\r
317 uint8_t BufferCount;
\r
318 for (BufferCount = 0; BufferCount < cnt / 0xFF; BufferCount++)
\r
319 BufferAddressIso[BufferCount] = 0xFF;
\r
320 BufferAddressIso[BufferCount] = (cnt % 0xFF);
\r
321 if (cnt % 0xFF != 0) {
\r
322 dmaDescriptor[PhyEP].BufferLength = cnt / 0xFF + 1;
\r
325 dmaDescriptor[PhyEP].BufferLength = cnt / 0xFF;
\r
328 else { // OUT DIRECTION
\r
329 dmaDescriptor[PhyEP].BufferLength = 1;
\r
331 dmaDescriptor[PhyEP].IsoBufferAddr = (uint32_t) BufferAddressIso;
\r
332 dmaDescriptor[PhyEP].Isochronous = 1;
\r
333 dmaDescriptor[PhyEP].MaxPacketSize = 0;
\r
336 dmaDescriptor[PhyEP].BufferLength = cnt;
\r
338 dmaDescriptor[PhyEP].Retired = 0;
\r
339 dmaDescriptor[PhyEP].Status = 0;
\r
340 dmaDescriptor[PhyEP].IsoPacketValid = 0;
\r
341 dmaDescriptor[PhyEP].LSByteExtracted = 0;
\r
342 dmaDescriptor[PhyEP].MSByteExtracted = 0;
\r
343 dmaDescriptor[PhyEP].PresentCount = 0;
\r
345 UDCA[PhyEP] = (uint32_t) &dmaDescriptor[PhyEP];
\r
346 USB_REG(0)->EpDMAEn = _BIT(PhyEP);
\r
349 void DMAEndTransferISR()
\r
352 uint32_t EoTIntSt = USB_REG(0)->EoTIntSt;
\r
354 for (PhyEP = 2; PhyEP < USED_PHYSICAL_ENDPOINTS; PhyEP++) /* Check All Endpoints */
\r
355 if ( EoTIntSt & _BIT(PhyEP) ) {
\r
356 if ( IsOutEndpoint(PhyEP) ) { /* OUT Endpoint */
\r
357 uint32_t tem = usb_data_buffer_OUT_index[0]; //just to clear warning
\r
358 if (dmaDescriptor[PhyEP].Isochronous == 1) {// iso endpoint
\r
359 SizeAudioTransfer = (BufferAddressIso[0]) & 0xFFFF;
\r
360 ISO_Address = (uint8_t *) CALLBACK_HAL_GetISOBufferAddress(PhyEP / 2, &SizeAudioTransfer);
\r
361 DcdDataTransfer(PhyEP, ISO_Address, 512);
\r
363 usb_data_buffer_OUT_size[0] += dmaDescriptor[PhyEP].PresentCount;
\r
364 if ((usb_data_buffer_OUT_size[0] + tem + dmaDescriptor[PhyEP].MaxPacketSize) > 512) {
\r
365 USB_REG(0)->DMAIntEn &= ~(1 << 1);
\r
368 else { /* IN Endpoint */
\r
369 /* Should be left blank */
\r
372 USB_REG(0)->EoTIntClr = EoTIntSt;
\r
375 void DMANewTransferRequestISR()
\r
378 uint32_t NDDRIntSt = USB_REG(0)->NDDRIntSt;
\r
380 for (PhyEP = 2; PhyEP < USED_PHYSICAL_ENDPOINTS; PhyEP++) /* Check All Endpoints */
\r
381 if ( NDDRIntSt & _BIT(PhyEP) ) {
\r
382 if ( IsOutEndpoint(PhyEP) ) { /* OUT Endpoint */
\r
383 if (dmaDescriptor[PhyEP].Isochronous == 1) {// iso endpoint
\r
384 DcdDataTransfer(PhyEP, ISO_Address, 512);
\r
387 uint16_t MaxPS = dmaDescriptor[PhyEP].MaxPacketSize;
\r
388 if (usb_data_buffer_OUT_size[0] == 0) {
\r
389 usb_data_buffer_OUT_index[0] = 0;
\r
390 DcdDataTransfer(PhyEP, usb_data_buffer_OUT[0], MaxPS);
\r
394 uint32_t tem = usb_data_buffer_OUT_index[0]; //just to clear warning
\r
395 DcdDataTransfer(PhyEP, &usb_data_buffer_OUT[0][usb_data_buffer_OUT_size[0] + tem], MaxPS);
\r
399 else { /* IN Endpoint */
\r
400 if (dmaDescriptor[PhyEP].Isochronous == 1) {
\r
401 ISO_Address = (uint8_t *) CALLBACK_HAL_GetISOBufferAddress(PhyEP / 2, &SizeAudioTransfer);
\r
402 if (SizeAudioTransfer > 0) {
\r
403 DcdDataTransfer(PhyEP, ISO_Address, SizeAudioTransfer);
\r
406 DcdDataTransfer(PhyEP, ISO_Address, 512);
\r
411 USB_REG(0)->NDDRIntClr = NDDRIntSt;
\r
414 // void DMASysErrISR()
\r
417 // uint32_t SysErrIntSt = LPC_USB->USBSysErrIntSt;
\r
418 // for (PhyEP = 2; PhyEP < USED_PHYSICAL_ENDPOINTS; PhyEP++) /* Check All Endpoints */
\r
420 // if ( SysErrIntSt & _BIT(PhyEP) )
\r
422 // if ( IsOutEndpoint(PhyEP) ) /* OUT Endpoint */
\r
425 // else /* IN Endpoint */
\r
430 // LPC_USB->USBSysErrIntClr = SysErrIntSt;
\r
433 void DcdIrqHandler(uint8_t DeviceID)
\r
435 uint32_t DevIntSt, DMAIntSt;
\r
437 DevIntSt = USB_REG(DeviceID)->DevIntEn; /* Device Interrupt Status */
\r
438 DevIntSt &= USB_REG(DeviceID)->DevIntEn;
\r
440 USB_REG(DeviceID)->DevIntClr = DevIntSt;
\r
442 /* Device Status Interrupt (Reset, Connect change, Suspend/Resume) */
\r
443 if (DevIntSt & DEV_STAT_INT) {
\r
444 uint32_t SIEDeviceStatus;
\r
445 SIE_WriteCommand(CMD_GET_DEV_STAT);
\r
446 SIEDeviceStatus = SIE_ReadCommandData(DAT_GET_DEV_STAT); /* Device Status */
\r
447 if (SIEDeviceStatus & DEV_RST) { /* Reset */
\r
448 HAL_Reset(DeviceID);
\r
449 USB_DeviceState[DeviceID] = DEVICE_STATE_Default;
\r
450 Endpoint_ConfigureEndpoint(DeviceID, ENDPOINT_CONTROLEP, 0, ENDPOINT_DIR_OUT, USB_Device_ControlEndpointSize, 0);
\r
451 Endpoint_ConfigureEndpoint(DeviceID, ENDPOINT_CONTROLEP, 0, ENDPOINT_DIR_IN, USB_Device_ControlEndpointSize, 0);
\r
453 if (SIEDeviceStatus & DEV_CON_CH) { /* Connect change */
\r
455 if (SIEDeviceStatus & DEV_SUS_CH) { /* Suspend/Resume */
\r
456 if (SIEDeviceStatus & DEV_SUS) { /* Suspend */
\r
458 else { /* Resume */
\r
463 if (DevIntSt & FRAME_INT) {}
\r
465 if (DevIntSt & ERR_INT) {
\r
466 volatile uint32_t SIEErrorStatus;
\r
467 SIE_WriteCommand(CMD_RD_ERR_STAT);
\r
468 SIEErrorStatus = SIE_ReadCommandData(DAT_RD_ERR_STAT);
\r
471 /* SLAVE mode : Endpoint's Slow Interrupt */
\r
472 if ( (DevIntSt & EP_SLOW_INT) || (DevIntSt & EP_FAST_INT) ) {
\r
473 SlaveEndpointISR();
\r
477 DMAIntSt = LPC_USB->DMAIntSt;
\r
478 DMAIntSt &= USB_REG(DeviceID)->DMAIntEn;
\r
480 if (DMAIntSt & EOT_INT) { /* End of Transfer Interrupt */
\r
481 DMAEndTransferISR();
\r
484 if (DMAIntSt & NDD_REQ_INT) { /* New DD Request Interrupt */
\r
485 DMANewTransferRequestISR();
\r
489 if (DMAIntSt & SYS_ERR_INT) { /* System Error Interrupt */
\r
491 USB_REG(DeviceID)->SysErrIntClr = USB_REG(DeviceID)->SysErrIntSt;
\r
495 uint32_t Dummy_EPGetISOAddress(uint32_t EPNum, uint32_t *last_packet_size)
\r
497 return (uint32_t) iso_buffer;
\r
500 #endif /*__LPC17XX__ || __LPC40XX__*/
\r