66
66
* - STALL handled, but not tested.
67
67
* - Does it work? No clue.
68
68
* - All EP BTABLE buffers are created based on max packet size of first EP opened with that address.
69
- * - Endpoint index is the ID of the endpoint
70
- * - This means that priority is given to endpoints with lower ID numbers
71
- * - Manual override of this mapping is possible through callback
72
69
* - Packet buffer memory is copied in the interrupt.
73
70
* - This is better for performance, but means interrupts are disabled for longer
74
71
* - DMA may be the best choice, but it could also be pushed to the USBD task.
@@ -186,6 +183,16 @@ TU_ATTR_ALWAYS_INLINE static inline xfer_ctl_t* xfer_ctl_ptr(uint32_t ep_addr)
186
183
return & xfer_status [epnum ][dir ];
187
184
}
188
185
186
+ // EP allocator
187
+ typedef struct
188
+ {
189
+ uint8_t ep_num ;
190
+ uint8_t ep_type ;
191
+ bool allocated [2 ];
192
+ } ep_alloc_t ;
193
+
194
+ static ep_alloc_t ep_alloc_status [STFSDEV_EP_COUNT ];
195
+
189
196
static TU_ATTR_ALIGNED (4 ) uint32_t _setup_packet [6 ];
190
197
191
198
static uint8_t remoteWakeCountdown ; // When wake is requested
@@ -201,6 +208,8 @@ static uint16_t ep_buf_ptr; ///< Points to first free memory location
201
208
static void dcd_pma_alloc_reset (void );
202
209
static uint16_t dcd_pma_alloc (uint8_t ep_addr , size_t length );
203
210
static void dcd_pma_free (uint8_t ep_addr );
211
+ static void dcd_ep_free (uint8_t ep_addr );
212
+ static uint8_t dcd_ep_alloc (tusb_desc_endpoint_t const * p_endpoint_desc );
204
213
static bool dcd_write_packet_memory (uint16_t dst , const void * __restrict src , size_t wNBytes );
205
214
static bool dcd_read_packet_memory (void * __restrict dst , uint16_t src , size_t wNBytes );
206
215
@@ -458,10 +467,17 @@ static void dcd_handle_bus_reset(void)
458
467
//__IO uint16_t * const epreg = &(EPREG(0));
459
468
USB -> DADDR = 0u ; // disable USB peripheral by clearing the EF flag
460
469
461
- // Clear all EPREG (or maybe this is automatic? I'm not sure)
470
+
462
471
for (uint32_t i = 0 ; i < STFSDEV_EP_COUNT ; i ++ )
463
472
{
473
+ // Clear all EPREG (or maybe this is automatic? I'm not sure)
464
474
pcd_set_endpoint (USB ,i ,0u );
475
+
476
+ // Clear EP allocation status
477
+ ep_alloc_status [i ].ep_num = 0xFF ;
478
+ ep_alloc_status [i ].ep_type = 0xFF ;
479
+ ep_alloc_status [i ].allocated [0 ] = false;
480
+ ep_alloc_status [i ].allocated [1 ] = false;
465
481
}
466
482
467
483
dcd_pma_alloc_reset ();
@@ -783,20 +799,85 @@ static void dcd_pma_free(uint8_t ep_addr)
783
799
}
784
800
}
785
801
802
+ /***
803
+ * Allocate hardware endpoint
804
+ */
805
+ static uint8_t dcd_ep_alloc (tusb_desc_endpoint_t const * p_endpoint_desc )
806
+ {
807
+ uint8_t const epnum = tu_edpt_number (p_endpoint_desc -> bEndpointAddress );
808
+ uint8_t const dir = tu_edpt_dir (p_endpoint_desc -> bEndpointAddress );
809
+ uint8_t const eptype = p_endpoint_desc -> bmAttributes .xfer ;
810
+
811
+ for (uint8_t i = 0 ; i < STFSDEV_EP_COUNT ; i ++ )
812
+ {
813
+ // If EP of current direction is not allocated
814
+ // Except for ISO endpoint, both direction should be free
815
+ if (!ep_alloc_status [i ].allocated [dir ] &&
816
+ (eptype != TUSB_XFER_ISOCHRONOUS || !ep_alloc_status [i ].allocated [dir ^ 1 ]))
817
+ {
818
+ // Check if EP number is the same
819
+ if (ep_alloc_status [i ].ep_num == 0xFF ||
820
+ ep_alloc_status [i ].ep_num == epnum )
821
+ {
822
+ // One EP pair has to be the same type
823
+ if (ep_alloc_status [i ].ep_type == 0xFF ||
824
+ ep_alloc_status [i ].ep_type == eptype )
825
+ {
826
+ ep_alloc_status [i ].ep_num = epnum ;
827
+ ep_alloc_status [i ].ep_type = eptype ;
828
+ ep_alloc_status [i ].allocated [dir ] = true;
829
+
830
+ return i ;
831
+ }
832
+ }
833
+ }
834
+ }
835
+
836
+ // Allocation failed
837
+ TU_ASSERT (0 );
838
+ }
839
+
840
+ /***
841
+ * Free hardware endpoint
842
+ */
843
+ static void dcd_ep_free (uint8_t ep_addr )
844
+ {
845
+ uint8_t const epnum = tu_edpt_number (ep_addr );
846
+ uint8_t const dir = tu_edpt_dir (ep_addr );
847
+
848
+ for (uint8_t i = 0 ; i < STFSDEV_EP_COUNT ; i ++ )
849
+ {
850
+ // Check if EP number & dir are the same
851
+ if (ep_alloc_status [i ].ep_num == epnum &&
852
+ ep_alloc_status [i ].allocated [dir ] == dir )
853
+ {
854
+ ep_alloc_status [i ].allocated [dir ] = false;
855
+ // Reset entry if ISO endpoint or both direction are free
856
+ if (ep_alloc_status [i ].ep_type == TUSB_XFER_ISOCHRONOUS ||
857
+ !ep_alloc_status [i ].allocated [dir ^ 1 ])
858
+ {
859
+ ep_alloc_status [i ].ep_num = 0xFF ;
860
+ ep_alloc_status [i ].ep_type = 0xFF ;
861
+
862
+ return ;
863
+ }
864
+ }
865
+ }
866
+ }
867
+
786
868
// The STM32F0 doesn't seem to like |= or &= to manipulate the EP#R registers,
787
869
// so I'm using the #define from HAL here, instead.
788
870
789
871
bool dcd_edpt_open (uint8_t rhport , tusb_desc_endpoint_t const * p_endpoint_desc )
790
872
{
791
873
(void )rhport ;
792
- /* TODO: This hardware endpoint allocation could be more sensible. For now, simple allocation or manual allocation using callback */
793
- uint8_t const epnum = tu_stm32_edpt_number_cb ? tu_stm32_edpt_number_cb (p_endpoint_desc -> bEndpointAddress ) : tu_edpt_number (p_endpoint_desc -> bEndpointAddress );
874
+ uint8_t const epnum = dcd_ep_alloc (p_endpoint_desc );
794
875
uint8_t const dir = tu_edpt_dir (p_endpoint_desc -> bEndpointAddress );
795
876
const uint16_t buffer_size = pcd_aligned_buffer_size (tu_edpt_packet_size (p_endpoint_desc ));
796
877
uint16_t pma_addr ;
797
878
uint32_t wType ;
798
879
799
- TU_ASSERT (epnum < MAX_EP_COUNT );
880
+ TU_ASSERT (epnum < STFSDEV_EP_COUNT );
800
881
TU_ASSERT (buffer_size <= 1024 );
801
882
802
883
// Set type
@@ -906,6 +987,8 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr)
906
987
pcd_set_ep_rx_status (USB , epnum , USB_EP_RX_DIS );
907
988
}
908
989
990
+ dcd_ep_free (ep_addr );
991
+
909
992
dcd_pma_free (ep_addr );
910
993
}
911
994
0 commit comments