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 /** @ingroup Group_EndpointRW
\r
33 * @defgroup Group_EndpointRW_LPC17xx Endpoint Data Reading and Writing (LPC17xx)
\r
34 * @brief Endpoint data read/write definitions for the LPC architecture.
\r
36 * Functions, macros, variables, enums and types related to data reading and writing from and to endpoints.
\r
39 /** @ingroup Group_EndpointPrimitiveRW
\r
40 * @defgroup Group_EndpointPrimitiveRW_LPC17xx Read/Write of Primitive Data Types (LPC17xx)
\r
41 * @brief Endpoint primitive read/write definitions for the LPC17xx architecture.
\r
43 * Functions, macros, variables, enums and types related to data reading and writing of primitive data types
\r
44 * from and to endpoints.
\r
47 /** @ingroup Group_EndpointPacketManagement
\r
48 * @defgroup Group_EndpointPacketManagement_LPC17xx Endpoint Packet Management (LPC17xx)
\r
49 * @brief Endpoint packet management definitions for the NXP LPC17xx architecture.
\r
51 * Functions, macros, variables, enums and types related to packet management of endpoints.
\r
54 /** @ingroup Group_EndpointManagement
\r
55 * @defgroup Group_EndpointManagement_LPC17xx Endpoint Management (LPC17xx)
\r
56 * @brief Endpoint management definitions for the LPC17xx architecture.
\r
58 * Functions, macros and enums related to endpoint management when in USB Device mode. This
\r
59 * module contains the endpoint management macros, as well as endpoint interrupt and data
\r
60 * send/receive functions for various data types.
\r
65 #ifndef __ENDPOINT_LPC17XX_H__
\r
66 #define __ENDPOINT_LPC17XX_H__
\r
68 #include "../EndpointCommon.h"
\r
70 #if defined(__cplusplus)
\r
74 #if !defined(__INCLUDE_FROM_USB_DRIVER)
\r
75 #error Do not include this file directly. Include lpcroot/libraries/LPCUSBlib/Drivers/USB/USB.h instead.
\r
78 #if !defined(__DOXYGEN__)
\r
80 #define ENDPOINT_DETAILS_MAXEP 6 /* Maximum of supported endpoint */
\r
81 #define USED_PHYSICAL_ENDPOINTS (ENDPOINT_DETAILS_MAXEP * 2) /* This macro effect memory size of the DCD */
\r
82 #define ENDPOINT_DETAILS_MAXEP0 ENDPOINT_DETAILS_MAXEP
\r
83 #define ENDPOINT_DETAILS_MAXEP1 ENDPOINT_DETAILS_MAXEP
\r
85 extern volatile bool SETUPReceived;
\r
86 extern DMADescriptor dmaDescriptor[USED_PHYSICAL_ENDPOINTS];
\r
88 void SIE_WriteCommandData (uint32_t cmd, uint32_t val);
\r
90 void SIE_WriteCommand (uint32_t cmd);
\r
92 extern volatile bool isOutReceived;
\r
93 extern volatile bool isInReady;
\r
95 void WriteControlEndpoint(uint8_t *pData, uint32_t cnt);
\r
97 void ReadControlEndpoint(uint8_t *pData);
\r
99 void DcdDataTransfer(uint8_t PhyEP, uint8_t *pData, uint32_t cnt);
\r
101 void Endpoint_Streaming(uint8_t corenum, uint8_t *buffer, uint16_t packetsize,
\r
102 uint16_t totalpackets, uint16_t dummypackets);
\r
104 void Endpoint_ClearEndpoints(uint8_t corenum);
\r
106 bool Endpoint_ConfigureEndpoint_Prv(uint8_t corenum,
\r
107 const uint8_t Number,
\r
108 const uint8_t UECFG0XData,
\r
109 const uint8_t UECFG1XData);
\r
113 * @brief Configures the specified endpoint number with the given endpoint type, direction, bank size
\r
114 * and banking mode. Once configured, the endpoint may be read from or written to, depending
\r
115 * on its direction.
\r
117 * @param corenum : ID Number of USB Core to be processed.
\r
118 * @param Number : Endpoint number to configure. This must be more than 0 and less than
\r
119 * @ref ENDPOINT_TOTAL_ENDPOINTS.
\r
121 * @param Type : Type of endpoint to configure, a \c EP_TYPE_* mask. Not all endpoint types
\r
122 * are available on Low Speed USB devices - refer to the USB 2.0 specification.
\r
124 * @param Direction : Endpoint data direction, either @ref ENDPOINT_DIR_OUT or @ref ENDPOINT_DIR_IN.
\r
125 * All endpoints (except Control type) are unidirectional - data may only be read
\r
126 * from or written to the endpoint bank based on its direction, not both.
\r
128 * @param Size : Size of the endpoint's bank, where packets are stored before they are transmitted
\r
129 * to the USB host, or after they have been received from the USB host (depending on
\r
130 * the endpoint's data direction). The bank size must indicate the maximum packet size
\r
131 * that the endpoint can handle.
\r
133 * @param Banks : Number of banks to use for the endpoint being configured, an \c ENDPOINT_BANK_* mask.
\r
134 * More banks uses more USB DPRAM, but offers better performance. Isochronous type
\r
135 * endpoints <b>must</b> have at least two banks.
\r
136 * @return Boolean \c true if the configuration succeeded, \c false otherwise.
\r
138 /*static inline */ bool Endpoint_ConfigureEndpoint(uint8_t corenum,
\r
139 const uint8_t Number,
\r
140 const uint8_t Type,
\r
141 const uint8_t Direction,
\r
142 const uint16_t Size,
\r
143 const uint8_t Banks) /*ATTR_ALWAYS_INLINE*/;
\r
145 static inline uint16_t USB_Device_GetFrameNumber(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
\r
147 static inline uint16_t USB_Device_GetFrameNumber(void)
\r
151 SIE_WriteCommand(CMD_RD_FRAME);
\r
152 val = SIE_ReadCommandData(DAT_RD_FRAME);
\r
153 val = val | (SIE_ReadCommandData(DAT_RD_FRAME) << 8);
\r
158 static inline void USB_Device_SetDeviceAddress(uint8_t corenum, const uint8_t Address) ATTR_ALWAYS_INLINE;
\r
160 static inline void USB_Device_SetDeviceAddress(uint8_t corenum, const uint8_t Address)
\r
162 SIE_WriteCommandData(CMD_SET_ADDR, DAT_WR_BYTE(DEV_EN | Address));
\r
163 SIE_WriteCommandData(CMD_SET_ADDR, DAT_WR_BYTE(DEV_EN | Address));
\r
167 * @brief Resets the endpoint bank FIFO. This clears all the endpoint banks and resets the USB controller's
\r
168 * data In and Out pointers to the bank's contents.
\r
170 * @param EndpointNumber : Endpoint number whose FIFO buffers are to be reset.
\r
173 static inline void Endpoint_ResetEndpoint(const uint8_t EndpointNumber) ATTR_ALWAYS_INLINE;
\r
175 static inline void Endpoint_ResetEndpoint(const uint8_t EndpointNumber)
\r
179 * @brief Enables the currently selected endpoint so that data can be sent and received through it to
\r
182 * @note Endpoints must first be configured properly via @ref Endpoint_ConfigureEndpoint().
\r
185 static inline void Endpoint_EnableEndpoint(void) ATTR_ALWAYS_INLINE;
\r
187 static inline void Endpoint_EnableEndpoint(void)
\r
191 * @brief Disables the currently selected endpoint so that data cannot be sent and received through it
\r
192 * to and from a host.
\r
195 static inline void Endpoint_DisableEndpoint(void) ATTR_ALWAYS_INLINE;
\r
197 static inline void Endpoint_DisableEndpoint(void)
\r
201 * @brief Determines if the currently selected endpoint is enabled, but not necessarily configured
\r
202 * @return Boolean \c true if the currently selected endpoint is enabled, \c false otherwise.
\r
204 static inline bool Endpoint_IsEnabled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
\r
206 static inline bool Endpoint_IsEnabled(void)
\r
212 * @brief Retrieves the number of busy banks in the currently selected endpoint, which have been queued for
\r
213 * transmission via the @ref Endpoint_ClearIN() command, or are awaiting acknowledgement via the
\r
214 * @ref Endpoint_ClearOUT() command.
\r
216 * @ingroup Group_EndpointPacketManagement_LPC18xx
\r
218 * @return Total number of busy banks in the selected endpoint.
\r
220 static inline uint8_t Endpoint_GetBusyBanks(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
\r
222 static inline uint8_t Endpoint_GetBusyBanks(void)
\r
227 /** @brief Aborts all pending IN transactions on the currently selected endpoint, once the bank
\r
228 * has been queued for transmission to the host via @ref Endpoint_ClearIN(). This function
\r
229 * will terminate all queued transactions, resetting the endpoint banks ready for a new
\r
232 * @ingroup Group_EndpointPacketManagement_LPC18xx
\r
235 static inline void Endpoint_AbortPendingIN(void)
\r
239 * @brief Determines if the currently selected endpoint is configured.
\r
241 * @return Boolean \c true if the currently selected endpoint has been configured, \c false otherwise.
\r
243 static inline bool Endpoint_IsConfigured(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
\r
245 static inline bool Endpoint_IsConfigured(void)
\r
251 * @brief Returns a mask indicating which INTERRUPT type endpoints have interrupted - i.e. their
\r
252 * interrupt duration has elapsed. Which endpoints have interrupted can be determined by
\r
253 * masking the return value against <tt>(1 << <i>{Endpoint Number}</i>)</tt>.
\r
255 * @return Mask whose bits indicate which endpoints have interrupted.
\r
257 static inline uint8_t Endpoint_GetEndpointInterrupts(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
\r
259 static inline uint8_t Endpoint_GetEndpointInterrupts(void)
\r
265 * @brief Determines if the specified endpoint number has interrupted (valid only for INTERRUPT type
\r
267 * @param EndpointNumber : Index of the endpoint whose interrupt flag should be tested
\r
268 * @return Boolean \c true if the specified endpoint has interrupted, \c false otherwise.
\r
270 static inline bool Endpoint_HasEndpointInterrupted(const uint8_t EndpointNumber) ATTR_WARN_UNUSED_RESULT
\r
271 ATTR_ALWAYS_INLINE;
\r
273 static inline bool Endpoint_HasEndpointInterrupted(const uint8_t EndpointNumber)
\r
275 return (Endpoint_GetEndpointInterrupts() & (1 << EndpointNumber)) ? true : false;
\r
279 * @brief Indicates the number of bytes currently stored in the current endpoint's selected bank.
\r
281 * @note The return width of this function may differ, depending on the maximum endpoint bank size
\r
282 * of the selected LPC model.
\r
283 * @ingroup Group_EndpointRW_LPC17xx
\r
284 * @param corenum : ID Number of USB Core to be processed.
\r
285 * @return Total number of bytes in the currently selected Endpoint's FIFO buffer
\r
287 static inline uint16_t Endpoint_BytesInEndpoint(uint8_t corenum) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
\r
289 static inline uint16_t Endpoint_BytesInEndpoint(uint8_t corenum)
\r
291 if (endpointselected == ENDPOINT_CONTROLEP) {
\r
292 return usb_data_buffer_size[corenum];
\r
295 // return (dmaDescriptor[ endpointhandle[endpointselected] ].PresentCount);
\r
296 return usb_data_buffer_OUT_size[corenum];
\r
301 * @brief Determines if the selected IN endpoint is ready for a new packet to be sent to the host.
\r
303 * @ingroup Group_EndpointPacketManagement_LPC17xx
\r
305 * @param corenum : ID Number of USB Core to be processed.
\r
306 * @return Boolean \c true if the current endpoint is ready for an IN packet, \c false otherwise.
\r
308 static inline bool Endpoint_IsINReady(uint8_t corenum) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
\r
310 static inline bool Endpoint_IsINReady(uint8_t corenum)
\r
312 if (endpointselected[corenum] == ENDPOINT_CONTROLEP) {
\r
317 uint8_t SelEP_Data;
\r
318 if (dmaDescriptor[endpointhandle(corenum)[endpointselected[corenum]]].Retired == true) {
\r
319 SIE_WriteCommand(CMD_SEL_EP(endpointhandle(corenum)[endpointselected[corenum]]) );
\r
320 SelEP_Data = SIE_ReadCommandData(DAT_SEL_EP(endpointhandle(corenum)[endpointselected[corenum]]) );
\r
321 if ((SelEP_Data & 1) == 0) {
\r
331 * @brief Determines if the selected OUT endpoint has received new packet from the host.
\r
333 * @ingroup Group_EndpointPacketManagement_LPC17xx
\r
335 * @param corenum : ID Number of USB Core to be processed.
\r
336 * @return Boolean \c true if current endpoint is has received an OUT packet, \c false otherwise.
\r
338 static inline bool Endpoint_IsOUTReceived(uint8_t corenum) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
\r
340 static inline bool Endpoint_IsOUTReceived(uint8_t corenum)
\r
342 if (endpointselected[corenum] == ENDPOINT_CONTROLEP) {
\r
344 return isOutReceived;
\r
347 return (dmaDescriptor[endpointhandle(corenum)[endpointselected[corenum]]].Retired &&
\r
348 (dmaDescriptor[endpointhandle(corenum)[endpointselected[corenum]]].Status == 2 ||
\r
349 dmaDescriptor[endpointhandle(corenum)[endpointselected[corenum]]].Status == 3)
\r
355 * @brief Determines if the current CONTROL type endpoint has received a SETUP packet.
\r
357 * @ingroup Group_EndpointPacketManagement_LPC17xx
\r
359 * @param corenum : ID Number of USB Core to be processed.
\r
360 * @return Boolean \c true if the selected endpoint has received a SETUP packet, \c false otherwise.
\r
362 static inline bool Endpoint_IsSETUPReceived(uint8_t corenum) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
\r
364 static inline bool Endpoint_IsSETUPReceived(uint8_t corenum)
\r
366 return SETUPReceived;
\r
370 * @brief Clears a received SETUP packet on the currently selected CONTROL type endpoint, freeing up the
\r
371 * endpoint for the next packet.
\r
373 * @ingroup Group_EndpointPacketManagement_LPC17xx
\r
375 * @param corenum : ID Number of USB Core to be processed.
\r
377 * @note This is not applicable for non CONTROL type endpoints.
\r
379 static inline void Endpoint_ClearSETUP(uint8_t corenum) ATTR_ALWAYS_INLINE;
\r
381 static inline void Endpoint_ClearSETUP(uint8_t corenum)
\r
383 SETUPReceived = FALSE;
\r
384 usb_data_buffer_index[corenum] = 0;
\r
385 usb_data_buffer_size[corenum] = 0;
\r
386 SIE_WriteCommand(CMD_SEL_EP(ENDPOINT_CONTROLEP));
\r
387 SIE_WriteCommand(CMD_CLR_BUF);
\r
391 * @brief Sends an IN packet to the host on the currently selected endpoint, freeing up the endpoint for the
\r
392 * next packet and switching to the alternative endpoint bank if double banked.
\r
394 * @ingroup Group_EndpointPacketManagement_LPC17xx
\r
395 * @param corenum : ID Number of USB Core to be processed.
\r
398 static inline void Endpoint_ClearIN(uint8_t corenum) ATTR_ALWAYS_INLINE;
\r
400 static inline void Endpoint_ClearIN(uint8_t corenum)
\r
402 uint8_t PhyEP = (endpointselected[corenum] == ENDPOINT_CONTROLEP ? 1 : endpointhandle(corenum)[endpointselected[corenum]]);
\r
404 if (endpointselected[corenum] == ENDPOINT_CONTROLEP) {
\r
405 WriteControlEndpoint(usb_data_buffer[corenum], usb_data_buffer_index[corenum]);
\r
406 usb_data_buffer_index[corenum] = 0;
\r
407 usb_data_buffer_size[corenum] = 0;
\r
410 DcdDataTransfer(PhyEP, usb_data_buffer_IN[corenum], usb_data_buffer_IN_index[corenum]);
\r
411 LPC_USB->DMARSet = _BIT(PhyEP);
\r
412 usb_data_buffer_IN_index[corenum] = 0;
\r
417 * @brief Acknowledges an OUT packet to the host on the currently selected endpoint, freeing up the endpoint
\r
418 * for the next packet and switching to the alternative endpoint bank if double banked.
\r
420 * @ingroup Group_EndpointPacketManagement_LPC17xx
\r
421 * @param corenum : ID Number of USB Core to be processed.
\r
424 static inline void Endpoint_ClearOUT(uint8_t corenum) ATTR_ALWAYS_INLINE;
\r
426 static inline void Endpoint_ClearOUT(uint8_t corenum)
\r
428 usb_data_buffer_index[corenum] = 0;
\r
429 if (endpointselected[corenum] == ENDPOINT_CONTROLEP) { /* Control only */
\r
430 SIE_WriteCommand(CMD_SEL_EP(ENDPOINT_CONTROLEP));
\r
431 SIE_WriteCommand(CMD_CLR_BUF);
\r
432 isOutReceived = false;
\r
435 usb_data_buffer_OUT_index[corenum] = 0;
\r
436 usb_data_buffer_OUT_size[corenum] = 0;
\r
437 dmaDescriptor[endpointhandle(corenum)[endpointselected[corenum]]].Status = 0;
\r
438 LPC_USB->DMAIntEn |= (1 << 1);
\r
443 * @brief Stalls the current endpoint, indicating to the host that a logical problem occurred with the
\r
444 * indicated endpoint and that the current transfer sequence should be aborted. This provides a
\r
445 * way for devices to indicate invalid commands to the host so that the current transfer can be
\r
446 * aborted and the host can begin its own recovery sequence.
\r
448 * The currently selected endpoint remains stalled until either the @ref Endpoint_ClearStall() macro
\r
449 * is called, or the host issues a CLEAR FEATURE request to the device for the currently selected
\r
452 * @ingroup Group_EndpointPacketManagement_LPC17xx
\r
453 * @param corenum : ID Number of USB Core to be processed.
\r
456 // static inline void Endpoint_StallTransaction(void) ATTR_ALWAYS_INLINE;
\r
457 void Endpoint_StallTransaction(uint8_t corenum);
\r
460 * @brief Clears the STALL condition on the currently selected endpoint.
\r
462 * @ingroup Group_EndpointPacketManagement_LPC17xx
\r
463 * @param corenum : ID Number of USB Core to be processed.
\r
466 static inline void Endpoint_ClearStall(uint8_t corenum) ATTR_ALWAYS_INLINE;
\r
468 static inline void Endpoint_ClearStall(uint8_t corenum)
\r
470 uint8_t PhysicalEp = endpointhandle(corenum)[endpointselected[corenum]] + (endpointselected[corenum] == ENDPOINT_CONTROLEP ? 1 : 0);
\r
472 HAL_DisableUSBInterrupt(corenum);
\r
473 SIE_WriteCommandData(CMD_SET_EP_STAT(PhysicalEp), DAT_WR_BYTE(0));
\r
474 HAL_EnableUSBInterrupt(corenum);
\r
478 * @brief Determines if the currently selected endpoint is stalled, false otherwise.
\r
480 * @ingroup Group_EndpointPacketManagement_LPC17xx
\r
482 * @param corenum : ID Number of USB Core to be processed.
\r
483 * @return Boolean \c true if the currently selected endpoint is stalled, \c false otherwise.
\r
485 static inline bool Endpoint_IsStalled(uint8_t corenum) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
\r
487 static inline bool Endpoint_IsStalled(uint8_t corenum)
\r
491 HAL_DisableUSBInterrupt(corenum);
\r
492 SIE_WriteCommand(CMD_SEL_EP(endpointhandle(corenum)[endpointselected[corenum]]) );
\r
493 isStalled = SIE_ReadCommandData(DAT_SEL_EP(endpointhandle(corenum)[endpointselected[corenum]]) ) & EP_SEL_ST ? true : false;
\r
494 HAL_EnableUSBInterrupt(corenum);
\r
496 return isStalled; /* Device Status */
\r
499 /** Resets the data toggle of the currently selected endpoint. */
\r
500 static inline void Endpoint_ResetDataToggle(uint8_t corenum) ATTR_ALWAYS_INLINE;
\r
502 static inline void Endpoint_ResetDataToggle(uint8_t corenum)
\r
505 #if (!defined(FIXED_CONTROL_ENDPOINT_SIZE) || defined(__DOXYGEN__))
\r
506 extern uint8_t USB_Device_ControlEndpointSize;
\r
508 #define USB_Device_ControlEndpointSize FIXED_CONTROL_ENDPOINT_SIZE
\r
512 * @brief Completes the status stage of a control transfer on a CONTROL type endpoint automatically,
\r
513 * with respect to the data direction. This is a convenience function which can be used to
\r
514 * simplify user control request handling.
\r
515 * @param corenum : ID Number of USB Core to be processed.
\r
518 void Endpoint_ClearStatusStage(uint8_t corenum);
\r
520 uint8_t Endpoint_WaitUntilReady(void);
\r
522 #if defined(__cplusplus)
\r