tinyusb  0.4
Click here to lend your support to tinyusb donation and make a donation at pledgie.com
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
dcd_lpc175x_6x.h
Go to the documentation of this file.
1 /**************************************************************************/
37 /**************************************************************************/
38 
43 #ifndef _TUSB_DCD_LPC175X_6X_H_
44 #define _TUSB_DCD_LPC175X_6X_H_
45 
46 #include "common/common.h"
47 
48 #ifdef __cplusplus
49  extern "C" {
50 #endif
51 
52 
53 typedef struct ATTR_ALIGNED(4)
54 {
55  //------------- Word 0 -------------//
56  uint32_t next;
57 
58  //------------- Word 1 -------------//
59  uint16_t mode : 2; // either 00 normal or 01 ATLE(auto length extraction)
60  uint16_t is_next_valid : 1;
61  uint16_t int_on_complete : 1;
62  uint16_t is_isochronous : 1; // is an iso endpoint
63  uint16_t max_packet_size : 11;
64  volatile uint16_t buffer_length;
65 
66  //------------- Word 2 -------------//
67  volatile uint32_t buffer_addr;
68 
69  //------------- Word 3 -------------//
70  volatile uint16_t is_retired : 1; // initialized to zero
71  volatile uint16_t status : 4;
72  volatile uint16_t iso_last_packet_valid : 1;
73  volatile uint16_t atle_is_lsb_extracted : 1; // used in ATLE mode
74  volatile uint16_t atle_is_msb_extracted : 1; // used in ATLE mode
75  volatile uint16_t atle_message_length_position : 6; // used in ATLE mode
76  uint16_t : 2;
77  volatile uint16_t present_count; // The number of bytes transferred by the DMA engine. The DMA engine updates this field after completing each packet transfer.
78 
79  //------------- Word 4 -------------//
80 // uint32_t iso_packet_size_addr; // iso only, can be omitted for non-iso
82 
83 STATIC_ASSERT( sizeof(dcd_dma_descriptor_t) == 16, "size is not correct"); // TODO not support ISO for now
84 
85 
86 //--------------------------------------------------------------------+
87 // Register Interface
88 //--------------------------------------------------------------------+
89 
90 //------------- USB Interrupt USBIntSt -------------//
91 //enum {
92 // DCD_USB_REQ_LOW_PRIO_MASK = BIT_(0),
93 // DCD_USB_REQ_HIGH_PRIO_MASK = BIT_(1),
94 // DCD_USB_REQ_DMA_MASK = BIT_(2),
95 // DCD_USB_REQ_NEED_CLOCK_MASK = BIT_(8),
96 // DCD_USB_REQ_ENABLE_MASK = BIT_(31)
97 //};
98 
99 //------------- Device Interrupt USBDevInt -------------//
100 enum {
101  DEV_INT_FRAME_MASK = BIT_(0),
102  DEV_INT_ENDPOINT_FAST_MASK = BIT_(1),
103  DEV_INT_ENDPOINT_SLOW_MASK = BIT_(2),
104  DEV_INT_DEVICE_STATUS_MASK = BIT_(3),
105  DEV_INT_COMMAND_CODE_EMPTY_MASK = BIT_(4),
106  DEV_INT_COMMAND_DATA_FULL_MASK = BIT_(5),
107  DEV_INT_RX_ENDPOINT_PACKET_MASK = BIT_(6),
108  DEV_INT_TX_ENDPOINT_PACKET_MASK = BIT_(7),
109  DEV_INT_ENDPOINT_REALIZED_MASK = BIT_(8),
110  DEV_INT_ERROR_MASK = BIT_(9)
111 };
112 
113 //------------- DMA Interrupt USBDMAInt-------------//
114 enum {
115  DMA_INT_END_OF_XFER_MASK = BIT_(0),
116  DMA_INT_NEW_DD_REQUEST_MASK = BIT_(1),
117  DMA_INT_ERROR_MASK = BIT_(2)
118 };
119 
120 //------------- USBCtrl -------------//
121 enum {
122  USBCTRL_READ_ENABLE_MASK = BIT_(0),
123  USBCTRL_WRITE_ENABLE_MASK = BIT_(1),
124 };
125 
126 //------------- USBRxPLen -------------//
127 enum {
128  USBRXPLEN_PACKET_LENGTH_MASK = (BIT_(10)-1),
129  USBRXPLEN_DATA_VALID_MASK = BIT_(10),
130  USBRXPLEN_PACKET_READY_MASK = BIT_(11),
131 };
132 
133 //------------- SIE Command Code -------------//
134 typedef enum {
135  SIE_CMDPHASE_WRITE = 1,
136  SIE_CMDPHASE_READ = 2,
137  SIE_CMDPHASE_COMMAND = 5
138 } sie_cmdphase_t;
139 
140 enum {
141  // device commands
142  SIE_CMDCODE_SET_ADDRESS = 0xd0,
143  SIE_CMDCODE_CONFIGURE_DEVICE = 0xd8,
144  SIE_CMDCODE_SET_MODE = 0xf3,
145  SIE_CMDCODE_READ_FRAME_NUMBER = 0xf5,
146  SIE_CMDCODE_READ_TEST_REGISTER = 0xfd,
147  SIE_CMDCODE_DEVICE_STATUS = 0xfe,
148  SIE_CMDCODE_GET_ERROR = 0xff,
149  SIE_CMDCODE_READ_ERROR_STATUS = 0xfb,
150 
151  // endpoint commands
152  SIE_CMDCODE_ENDPOINT_SELECT = 0x00, // + endpoint index
153  SIE_CMDCODE_ENDPOINT_SELECT_CLEAR_INTERRUPT = 0x40, // + endpoint index, should use USBEpIntClr instead
154  SIE_CMDCODE_ENDPOINT_SET_STATUS = 0x40, // + endpoint index
155  SIE_CMDCODE_BUFFER_CLEAR = 0xf2,
156  SIE_CMDCODE_BUFFER_VALIDATE = 0xfa
157 };
158 
159 //------------- SIE Device Status (get/set from SIE_CMDCODE_DEVICE_STATUS) -------------//
160 enum {
161  SIE_DEV_STATUS_CONNECT_STATUS_MASK = BIT_(0),
162  SIE_DEV_STATUS_CONNECT_CHANGE_MASK = BIT_(1),
163  SIE_DEV_STATUS_SUSPEND_MASK = BIT_(2),
164  SIE_DEV_STATUS_SUSPEND_CHANGE_MASK = BIT_(3),
165  SIE_DEV_STATUS_RESET_MASK = BIT_(4)
166 };
167 
168 //------------- SIE Select Endpoint Command -------------//
169 enum {
170  SIE_SELECT_ENDPOINT_FULL_EMPTY_MASK = BIT_(0), // 0: empty, 1 full. IN endpoint checks empty, OUT endpoint check full
171  SIE_SELECT_ENDPOINT_STALL_MASK = BIT_(1),
172  SIE_SELECT_ENDPOINT_SETUP_RECEIVED_MASK = BIT_(2), // clear by SIE_CMDCODE_ENDPOINT_SELECT_CLEAR_INTERRUPT
173  SIE_SELECT_ENDPOINT_PACKET_OVERWRITTEN_MASK = BIT_(3), // previous packet is overwritten by a SETUP packet
174  SIE_SELECT_ENDPOINT_NAK_MASK = BIT_(4), // last packet response is NAK (auto clear by an ACK)
175  SIE_SELECT_ENDPOINT_BUFFER1_FULL_MASK = BIT_(5),
176  SIE_SELECT_ENDPOINT_BUFFER2_FULL_MASK = BIT_(6)
177 };
178 
179 typedef enum {
180  SIE_SET_ENDPOINT_STALLED_MASK = BIT_(0),
181  SIE_SET_ENDPOINT_DISABLED_MASK = BIT_(5),
182  SIE_SET_ENDPOINT_RATE_FEEDBACK_MASK = BIT_(6),
183  SIE_SET_ENDPOINT_CONDITION_STALLED_MASK = BIT_(7),
184 }sie_endpoint_set_status_mask_t;
185 
186 //------------- DMA Descriptor Status -------------//
187 enum {
188  DD_STATUS_NOT_SERVICED = 0,
189  DD_STATUS_BEING_SERVICED,
190  DD_STATUS_NORMAL,
191  DD_STATUS_DATA_UNDERUN, // short packet
192  DD_STATUS_DATA_OVERRUN,
193  DD_STATUS_SYSTEM_ERROR
194 };
195 
196 //--------------------------------------------------------------------+
197 // SIE Command
198 //--------------------------------------------------------------------+
199 static inline void sie_cmd_code (sie_cmdphase_t phase, uint8_t code_data) ATTR_ALWAYS_INLINE;
200 static inline void sie_cmd_code (sie_cmdphase_t phase, uint8_t code_data)
201 {
202  LPC_USB->USBDevIntClr = (DEV_INT_COMMAND_CODE_EMPTY_MASK | DEV_INT_COMMAND_DATA_FULL_MASK);
203  LPC_USB->USBCmdCode = (phase << 8) | (code_data << 16);
204 
205  uint32_t const wait_flag = (phase == SIE_CMDPHASE_READ) ? DEV_INT_COMMAND_DATA_FULL_MASK : DEV_INT_COMMAND_CODE_EMPTY_MASK;
206 #ifndef _TEST_
207  while ((LPC_USB->USBDevIntSt & wait_flag) == 0); // TODO blocking forever potential
208 #endif
209  LPC_USB->USBDevIntClr = wait_flag;
210 }
211 
212 static inline void sie_write (uint8_t cmd_code, uint8_t data_len, uint8_t data) ATTR_ALWAYS_INLINE;
213 static inline void sie_write (uint8_t cmd_code, uint8_t data_len, uint8_t data)
214 {
215  sie_cmd_code(SIE_CMDPHASE_COMMAND, cmd_code);
216 
217  if (data_len)
218  {
219  sie_cmd_code(SIE_CMDPHASE_WRITE, data);
220  }
221 }
222 
223 static inline uint32_t sie_read (uint8_t cmd_code, uint8_t data_len) ATTR_ALWAYS_INLINE;
224 static inline uint32_t sie_read (uint8_t cmd_code, uint8_t data_len)
225 {
226  // TODO multiple read
227  sie_cmd_code(SIE_CMDPHASE_COMMAND , cmd_code);
228  sie_cmd_code(SIE_CMDPHASE_READ , cmd_code);
229  return LPC_USB->USBCmdData;
230 }
231 
232 #ifdef __cplusplus
233  }
234 #endif
235 
236 #endif /* _TUSB_DCD_LPC175X_6X_H_ */
237 
#define BIT_(n)
n-th Bit
Definition: binary.h:54
#define ATTR_ALIGNED(Bytes)
This attribute specifies a minimum alignment for the variable or structure field, measured in bytes...
Definition: compiler_gcc.h:72
#define ATTR_ALWAYS_INLINE
Generally, functions are not inlined unless optimization is specified. For functions declared inline...
Definition: compiler_gcc.h:89