4646/*------------------------------------------------------------------*/
4747/* Low level controller
4848 *------------------------------------------------------------------*/
49- static void hw_endpoint_init (uint8_t ep_addr , uint16_t wMaxPacketSize , uint8_t transfer_type );
50- static void hw_set_endpoint_control_reg (struct hw_endpoint * ep , uint dpram_offset );
51-
5249// Init these in dcd_init
53- static uint8_t * next_buffer_ptr = NULL ;
50+ static uint8_t * next_buffer_ptr ;
5451
5552// USB_MAX_ENDPOINTS Endpoints, direction TUSB_DIR_OUT for out and TUSB_DIR_IN for in.
5653static struct hw_endpoint hw_endpoints [USB_MAX_ENDPOINTS ][2 ];
@@ -70,115 +67,28 @@ TU_ATTR_ALWAYS_INLINE static inline struct hw_endpoint* hw_endpoint_get_by_addr(
7067
7168// Allocate from the USB buffer space (max 3840 bytes)
7269static void hw_endpoint_alloc (struct hw_endpoint * ep , size_t size ) {
73- static uint8_t * end ;
74- // determine buffer end
75- if (end == NULL ){
76- end = & usb_dpram -> epx_data [0 ] + 0xF00 ;
77- }
78- // determine first next_buffer_ptr if necessary
79- if (next_buffer_ptr == NULL ){
80- next_buffer_ptr = & usb_dpram -> epx_data [0 ];
81- }
82- // assign buffer
83- ep -> hw_data_buf = next_buffer_ptr ;
84- next_buffer_ptr += size ;
85-
86- hard_assert (next_buffer_ptr < end );
87-
88- pico_info (" Allocated %d bytes (0x%p)\r\n" , size , ep -> hw_data_buf );
89- }
70+ // round up size to multiple of 64
71+ size = tu_round_up (ep -> wMaxPacketSize , 64 );
9072
91- // allocate endpoint and fill endpoint control registers
92- static void hw_endpoint_alloc_and_control (struct hw_endpoint * ep , uint8_t transfer_type ) {
93- // size must be multiple of 64
94- uint size = tu_div_ceil (ep -> wMaxPacketSize , 64 ) * 64u ;
9573 // double buffered Bulk endpoint
96- if (transfer_type == TUSB_XFER_BULK ) {
74+ if (ep -> transfer_type == TUSB_XFER_BULK ) {
9775 size *= 2u ;
9876 }
99- ep -> transfer_type = transfer_type ;
100- hw_endpoint_alloc (ep , size );
10177
102- uint dpram_offset = hw_data_offset (ep -> hw_data_buf );
103- pico_info (" Allocated %d bytes at offset 0x%x (0x%p)\r\n" , size , dpram_offset , ep -> hw_data_buf );
78+ // assign buffer
79+ ep -> hw_data_buf = next_buffer_ptr ;
80+ next_buffer_ptr += size ;
10481
105- hw_set_endpoint_control_reg (ep , dpram_offset );
82+ hard_assert (next_buffer_ptr < usb_dpram -> epx_data + sizeof (usb_dpram -> epx_data ));
83+ pico_info (" Allocated %d bytes (0x%p)\r\n" , size , ep -> hw_data_buf );
10684}
10785
108- static void hw_set_endpoint_control_reg ( struct hw_endpoint * ep , uint dpram_offset ) {
109- // Fill in endpoint control register with buffer offset
110- uint32_t const reg = EP_CTRL_ENABLE_BITS | ((uint ) ep -> transfer_type << EP_CTRL_BUFFER_TYPE_LSB ) | dpram_offset ;
86+ // Enable endpoint
87+ TU_ATTR_ALWAYS_INLINE static inline void hw_endpoint_enable ( struct hw_endpoint * ep ) {
88+ uint32_t const reg = EP_CTRL_ENABLE_BITS | ((uint ) ep -> transfer_type << EP_CTRL_BUFFER_TYPE_LSB ) | hw_data_offset ( ep -> hw_data_buf ) ;
11189 * ep -> endpoint_control = reg ;
11290}
11391
114- // New API: Allocate packet buffer used by ISO endpoints
115- // Some MCU need manual packet buffer allocation, we allocate the largest size to avoid clustering
116- bool dcd_edpt_iso_alloc (uint8_t rhport , uint8_t ep_addr , uint16_t largest_packet_size ) {
117- (void ) rhport ;
118- assert (rhport == 0 );
119- struct hw_endpoint * ep = hw_endpoint_get_by_addr (ep_addr );
120- // size must be multiple of 64
121- uint16_t size = (uint16_t )tu_div_ceil (largest_packet_size , 64 ) * 64u ;
122- ep -> wMaxPacketSize = size ;
123- hw_endpoint_alloc (ep , size );
124- return true;
125- }
126-
127- // New API: Configure and enable an ISO endpoint according to descriptor
128- bool dcd_edpt_iso_activate (uint8_t rhport , tusb_desc_endpoint_t const * ep_desc ) {
129- (void ) rhport ;
130- assert (rhport == 0 );
131- const uint8_t ep_addr = ep_desc -> bEndpointAddress ;
132- const uint16_t mps = ep_desc -> wMaxPacketSize ;
133- uint16_t size = (uint16_t )tu_div_ceil (mps , 64 ) * 64u ;
134-
135- // init w/o allocate
136- hw_endpoint_init (ep_addr , size , TUSB_XFER_ISOCHRONOUS );
137-
138- // Fill in endpoint control register with buffer offset
139- struct hw_endpoint * ep = hw_endpoint_get_by_addr (ep_addr );
140- uint dpram_offset = hw_data_offset (ep -> hw_data_buf );
141- hw_set_endpoint_control_reg (ep , dpram_offset );
142- return true;
143- }
144-
145- static void hw_endpoint_close (uint8_t ep_addr ) {
146- struct hw_endpoint * ep = hw_endpoint_get_by_addr (ep_addr );
147- // Clear hardware registers and then zero the struct
148- // Clears endpoint enable
149- * ep -> endpoint_control = 0 ;
150- // Clears buffer available, etc
151- * ep -> buffer_control = 0 ;
152- // Clear any endpoint state
153- memset (ep , 0 , sizeof (struct hw_endpoint ));
154-
155- // Reclaim buffer space if all endpoints are closed
156- bool reclaim_buffers = true;
157- for (uint8_t i = 1 ; i < USB_MAX_ENDPOINTS ; i ++ ) {
158- if (hw_endpoint_get_by_num (i , TUSB_DIR_OUT )-> hw_data_buf != NULL ||
159- hw_endpoint_get_by_num (i , TUSB_DIR_IN )-> hw_data_buf != NULL ) {
160- reclaim_buffers = false;
161- break ;
162- }
163- }
164- if (reclaim_buffers ) {
165- next_buffer_ptr = & usb_dpram -> epx_data [0 ];
166- }
167- }
168-
169- // Legacy init called by dcd_init (which does allocation)
170- static void hw_endpoint_init_and_alloc (uint8_t ep_addr , uint16_t wMaxPacketSize , uint8_t transfer_type ) {
171- struct hw_endpoint * ep = hw_endpoint_get_by_addr (ep_addr );
172- uint16_t size = (uint16_t ) tu_div_ceil (wMaxPacketSize , 64 ) * 64u ;
173- // size must be multiple of 64
174- hw_endpoint_init (ep_addr , size , transfer_type );
175- const uint8_t num = tu_edpt_number (ep_addr );
176- if (num != 0 ) {
177- // alloc a buffer and fill in endpoint control register
178- hw_endpoint_alloc_and_control (ep , transfer_type );
179- }
180- }
181-
18292// main processing for dcd_edpt_iso_activate
18393static void hw_endpoint_init (uint8_t ep_addr , uint16_t wMaxPacketSize , uint8_t transfer_type ) {
18494 struct hw_endpoint * ep = hw_endpoint_get_by_addr (ep_addr );
@@ -221,6 +131,18 @@ static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t t
221131 }
222132}
223133
134+ // Init, allocate buffer and enable endpoint
135+ static void hw_endpoint_open (uint8_t ep_addr , uint16_t wMaxPacketSize , uint8_t transfer_type ) {
136+ struct hw_endpoint * ep = hw_endpoint_get_by_addr (ep_addr );
137+ hw_endpoint_init (ep_addr , wMaxPacketSize , transfer_type );
138+ const uint8_t num = tu_edpt_number (ep_addr );
139+ if (num != 0 ) {
140+ // EP0 is already enabled
141+ hw_endpoint_alloc (ep , ep -> wMaxPacketSize );
142+ hw_endpoint_enable (ep );
143+ }
144+ }
145+
224146static void hw_endpoint_xfer (uint8_t ep_addr , uint8_t * buffer , uint16_t total_bytes ) {
225147 struct hw_endpoint * ep = hw_endpoint_get_by_addr (ep_addr );
226148 hw_endpoint_xfer_start (ep , buffer , total_bytes );
@@ -446,8 +368,8 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
446368
447369 // Init control endpoints
448370 tu_memclr (hw_endpoints [0 ], 2 * sizeof (hw_endpoint_t ));
449- hw_endpoint_init_and_alloc (0x0 , 64 , TUSB_XFER_CONTROL );
450- hw_endpoint_init_and_alloc (0x80 , 64 , TUSB_XFER_CONTROL );
371+ hw_endpoint_open (0x0 , 64 , TUSB_XFER_CONTROL );
372+ hw_endpoint_open (0x80 , 64 , TUSB_XFER_CONTROL );
451373
452374 // Init non-control endpoints
453375 reset_non_control_endpoints ();
@@ -552,9 +474,34 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const* req
552474 }
553475}
554476
555- bool dcd_edpt_open (__unused uint8_t rhport , tusb_desc_endpoint_t const * desc_edpt ) {
556- assert (rhport == 0 );
557- hw_endpoint_init_and_alloc (desc_edpt -> bEndpointAddress , tu_edpt_packet_size (desc_edpt ), desc_edpt -> bmAttributes .xfer );
477+ bool dcd_edpt_open (uint8_t rhport , tusb_desc_endpoint_t const * desc_edpt ) {
478+ (void ) rhport ;
479+ const uint8_t xfer_type = desc_edpt -> bmAttributes .xfer ;
480+ TU_VERIFY (xfer_type != TUSB_XFER_ISOCHRONOUS );
481+ hw_endpoint_open (desc_edpt -> bEndpointAddress , tu_edpt_packet_size (desc_edpt ), xfer_type );
482+ return true;
483+ }
484+
485+ // New API: Allocate packet buffer used by ISO endpoints
486+ // Some MCU need manual packet buffer allocation, we allocate the largest size to avoid clustering
487+ bool dcd_edpt_iso_alloc (uint8_t rhport , uint8_t ep_addr , uint16_t largest_packet_size ) {
488+ (void ) rhport ;
489+ struct hw_endpoint * ep = hw_endpoint_get_by_addr (ep_addr );
490+ hw_endpoint_init (ep_addr , largest_packet_size , TUSB_XFER_ISOCHRONOUS );
491+ hw_endpoint_alloc (ep , largest_packet_size );
492+ return true;
493+ }
494+
495+ // New API: Configure and enable an ISO endpoint according to descriptor
496+ bool dcd_edpt_iso_activate (uint8_t rhport , tusb_desc_endpoint_t const * ep_desc ) {
497+ (void ) rhport ;
498+ const uint8_t ep_addr = ep_desc -> bEndpointAddress ;
499+ // Fill in endpoint control register with buffer offset
500+ struct hw_endpoint * ep = hw_endpoint_get_by_addr (ep_addr );
501+ TU_ASSERT (ep -> hw_data_buf != NULL ); // must be inited and buffer allocated
502+ ep -> wMaxPacketSize = ep_desc -> wMaxPacketSize ;
503+
504+ hw_endpoint_enable (ep );
558505 return true;
559506}
560507
@@ -599,12 +546,6 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) {
599546 }
600547}
601548
602- void dcd_edpt_close (uint8_t rhport , uint8_t ep_addr ) {
603- (void ) rhport ;
604- pico_trace ("dcd_edpt_close %02x\r\n" , ep_addr );
605- hw_endpoint_close (ep_addr );
606- }
607-
608549void __tusb_irq_path_func (dcd_int_handler )(uint8_t rhport ) {
609550 (void ) rhport ;
610551 dcd_rp2040_irq ();
0 commit comments