4646/*------------------------------------------------------------------*/
4747/* Low level controller
4848 *------------------------------------------------------------------*/
49-
5049// Init these in dcd_init
5150static uint8_t * next_buffer_ptr ;
5251
@@ -66,58 +65,31 @@ TU_ATTR_ALWAYS_INLINE static inline struct hw_endpoint* hw_endpoint_get_by_addr(
6665 return hw_endpoint_get_by_num (num , dir );
6766}
6867
69- static void _hw_endpoint_alloc (struct hw_endpoint * ep , uint8_t transfer_type ) {
70- // size must be multiple of 64
71- uint size = tu_div_ceil (ep -> wMaxPacketSize , 64 ) * 64u ;
68+ // Allocate from the USB buffer space (max 3840 bytes)
69+ static void hw_endpoint_alloc (struct hw_endpoint * ep , size_t size ) {
70+ // round up size to multiple of 64
71+ size = tu_round_up (ep -> wMaxPacketSize , 64 );
7272
7373 // double buffered Bulk endpoint
74- if (transfer_type == TUSB_XFER_BULK ) {
74+ if (ep -> transfer_type == TUSB_XFER_BULK ) {
7575 size *= 2u ;
7676 }
7777
78+ // assign buffer
7879 ep -> hw_data_buf = next_buffer_ptr ;
7980 next_buffer_ptr += size ;
8081
81- assert (((uintptr_t ) next_buffer_ptr & 0b111111u ) == 0 );
82- uint dpram_offset = hw_data_offset (ep -> hw_data_buf );
83- hard_assert (hw_data_offset (next_buffer_ptr ) <= USB_DPRAM_MAX );
84-
85- pico_info (" Allocated %d bytes at offset 0x%x (0x%p)\r\n" , size , dpram_offset , ep -> hw_data_buf );
86-
87- // Fill in endpoint control register with buffer offset
88- uint32_t const reg = EP_CTRL_ENABLE_BITS | ((uint ) transfer_type << EP_CTRL_BUFFER_TYPE_LSB ) | dpram_offset ;
89-
90- * ep -> endpoint_control = reg ;
91- }
92-
93- static void _hw_endpoint_close (struct hw_endpoint * ep ) {
94- // Clear hardware registers and then zero the struct
95- // Clears endpoint enable
96- * ep -> endpoint_control = 0 ;
97- // Clears buffer available, etc
98- * ep -> buffer_control = 0 ;
99- // Clear any endpoint state
100- memset (ep , 0 , sizeof (struct hw_endpoint ));
101-
102- // Reclaim buffer space if all endpoints are closed
103- bool reclaim_buffers = true;
104- for (uint8_t i = 1 ; i < USB_MAX_ENDPOINTS ; i ++ ) {
105- if (hw_endpoint_get_by_num (i , TUSB_DIR_OUT )-> hw_data_buf != NULL ||
106- hw_endpoint_get_by_num (i , TUSB_DIR_IN )-> hw_data_buf != NULL ) {
107- reclaim_buffers = false;
108- break ;
109- }
110- }
111- if (reclaim_buffers ) {
112- next_buffer_ptr = & usb_dpram -> epx_data [0 ];
113- }
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 );
11484}
11585
116- static void hw_endpoint_close (uint8_t ep_addr ) {
117- struct hw_endpoint * ep = hw_endpoint_get_by_addr (ep_addr );
118- _hw_endpoint_close (ep );
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 );
89+ * ep -> endpoint_control = reg ;
11990}
12091
92+ // main processing for dcd_edpt_iso_activate
12193static void hw_endpoint_init (uint8_t ep_addr , uint16_t wMaxPacketSize , uint8_t transfer_type ) {
12294 struct hw_endpoint * ep = hw_endpoint_get_by_addr (ep_addr );
12395
@@ -156,9 +128,18 @@ static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t t
156128 } else {
157129 ep -> endpoint_control = & usb_dpram -> ep_ctrl [num - 1 ].out ;
158130 }
131+ }
132+ }
159133
160- // alloc a buffer and fill in endpoint control register
161- _hw_endpoint_alloc (ep , transfer_type );
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 );
162143 }
163144}
164145
@@ -387,8 +368,8 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
387368
388369 // Init control endpoints
389370 tu_memclr (hw_endpoints [0 ], 2 * sizeof (hw_endpoint_t ));
390- hw_endpoint_init (0x0 , 64 , TUSB_XFER_CONTROL );
391- hw_endpoint_init (0x80 , 64 , TUSB_XFER_CONTROL );
371+ hw_endpoint_open (0x0 , 64 , TUSB_XFER_CONTROL );
372+ hw_endpoint_open (0x80 , 64 , TUSB_XFER_CONTROL );
392373
393374 // Init non-control endpoints
394375 reset_non_control_endpoints ();
@@ -493,9 +474,34 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const* req
493474 }
494475}
495476
496- bool dcd_edpt_open (__unused uint8_t rhport , tusb_desc_endpoint_t const * desc_edpt ) {
497- assert (rhport == 0 );
498- hw_endpoint_init (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 );
499505 return true;
500506}
501507
@@ -540,12 +546,6 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) {
540546 }
541547}
542548
543- void dcd_edpt_close (uint8_t rhport , uint8_t ep_addr ) {
544- (void ) rhport ;
545- pico_trace ("dcd_edpt_close %02x\r\n" , ep_addr );
546- hw_endpoint_close (ep_addr );
547- }
548-
549549void __tusb_irq_path_func (dcd_int_handler )(uint8_t rhport ) {
550550 (void ) rhport ;
551551 dcd_rp2040_irq ();
0 commit comments