@@ -126,53 +126,29 @@ static inline void print_intr(uint32_t intr) {
126
126
//--------------------------------------------------------------------+
127
127
// PROTOTYPE
128
128
//--------------------------------------------------------------------+
129
- static inline ehci_link_t * get_period_head (uint8_t rhport , uint32_t interval_ms )
130
- {
131
- (void ) rhport ;
132
- return (ehci_link_t * ) & ehci_data .period_head_arr [ tu_log2 ( tu_min32 (FRAMELIST_SIZE , interval_ms ) ) ];
133
- }
134
-
135
- static inline ehci_qhd_t * qhd_control (uint8_t dev_addr )
136
- {
137
- return & ehci_data .control [dev_addr ].qhd ;
138
- }
139
-
140
- static inline ehci_qhd_t * qhd_async_head (uint8_t rhport )
141
- {
142
- (void ) rhport ;
143
- // control qhd of dev0 is used as async head
144
- return qhd_control (0 );
145
- }
146
129
147
- static inline ehci_qtd_t * qtd_control ( uint8_t dev_addr )
148
- {
149
- return & ehci_data . control [ dev_addr ]. qtd ;
150
- }
130
+ // weak dcache for non-cacheable MCU
131
+ TU_ATTR_WEAK void hcd_dcache_clean ( void const * addr , uint32_t data_size ) { ( void ) addr ; ( void ) data_size ; }
132
+ TU_ATTR_WEAK void hcd_dcache_invalidate ( void const * addr , uint32_t data_size ) { ( void ) addr ; ( void ) data_size ; }
133
+ TU_ATTR_WEAK void hcd_dcache_clean_invalidate ( void const * addr , uint32_t data_size ) { ( void ) addr ; ( void ) data_size ; }
151
134
135
+ TU_ATTR_ALWAYS_INLINE static inline ehci_link_t * list_get_period_head (uint8_t rhport , uint32_t interval_ms );
136
+ TU_ATTR_ALWAYS_INLINE static inline ehci_qhd_t * list_get_async_head (uint8_t rhport );
152
137
153
- static inline ehci_qhd_t * qhd_next (ehci_qhd_t const * p_qhd );
154
- static inline ehci_qhd_t * qhd_find_free (void );
155
- static inline ehci_qhd_t * qhd_get_from_addr (uint8_t dev_addr , uint8_t ep_addr );
138
+ TU_ATTR_ALWAYS_INLINE static inline ehci_qhd_t * qhd_control (uint8_t dev_addr );
139
+ TU_ATTR_ALWAYS_INLINE static inline ehci_qhd_t * qhd_next (ehci_qhd_t const * p_qhd );
140
+ TU_ATTR_ALWAYS_INLINE static inline ehci_qhd_t * qhd_find_free (void );
141
+ static ehci_qhd_t * qhd_get_from_addr (uint8_t dev_addr , uint8_t ep_addr );
156
142
static void qhd_init (ehci_qhd_t * p_qhd , uint8_t dev_addr , tusb_desc_endpoint_t const * ep_desc );
157
143
static void qhd_attach_qtd (ehci_qhd_t * qhd , ehci_qtd_t * qtd );
158
144
159
- static inline ehci_qtd_t * qtd_find_free (void );
145
+ TU_ATTR_ALWAYS_INLINE static inline ehci_qtd_t * qtd_control (uint8_t dev_addr );
146
+ TU_ATTR_ALWAYS_INLINE static inline ehci_qtd_t * qtd_find_free (void );
160
147
static void qtd_init (ehci_qtd_t * qtd , void const * buffer , uint16_t total_bytes );
161
148
162
149
static inline void list_insert (ehci_link_t * current , ehci_link_t * new , uint8_t new_type );
163
150
static inline ehci_link_t * list_next (ehci_link_t const * p_link );
164
-
165
- TU_ATTR_WEAK void hcd_dcache_clean (void const * addr , uint32_t data_size ) {
166
- (void ) addr ; (void ) data_size ;
167
- }
168
-
169
- TU_ATTR_WEAK void hcd_dcache_invalidate (void const * addr , uint32_t data_size ) {
170
- (void ) addr ; (void ) data_size ;
171
- }
172
-
173
- TU_ATTR_WEAK void hcd_dcache_clean_invalidate (void const * addr , uint32_t data_size ) {
174
- (void ) addr ; (void ) data_size ;
175
- }
151
+ static void list_remove_qhd_by_daddr (ehci_link_t * list_head , uint8_t dev_addr );
176
152
177
153
//--------------------------------------------------------------------+
178
154
// HCD API
@@ -274,7 +250,7 @@ void hcd_device_close(uint8_t rhport, uint8_t daddr)
274
250
}
275
251
276
252
// Remove from async list
277
- list_remove_qhd_by_daddr ((ehci_link_t * ) qhd_async_head (rhport ), daddr );
253
+ list_remove_qhd_by_daddr ((ehci_link_t * ) list_get_async_head (rhport ), daddr );
278
254
279
255
// Remove from all interval period list
280
256
for (uint8_t i = 0 ; i < TU_ARRAY_SIZE (ehci_data .period_head_arr ); i ++ ) {
@@ -286,37 +262,42 @@ void hcd_device_close(uint8_t rhport, uint8_t daddr)
286
262
}
287
263
288
264
static void init_periodic_list (uint8_t rhport ) {
265
+ (void ) rhport ;
266
+
289
267
// Build the polling interval tree with 1 ms, 2 ms, 4 ms and 8 ms (framesize) only
290
268
for ( uint32_t i = 0 ; i < TU_ARRAY_SIZE (ehci_data .period_head_arr ); i ++ ) {
291
269
ehci_data .period_head_arr [i ].int_smask = 1 ; // queue head in period list must have smask non-zero
292
270
ehci_data .period_head_arr [i ].qtd_overlay .halted = 1 ; // dummy node, always inactive
293
271
}
294
272
295
- ehci_link_t * const framelist = ehci_data .period_framelist ;
296
- ehci_link_t * const period_1ms = get_period_head (rhport , 1u );
297
-
273
+ // TODO EHCI_FRAMELIST_SIZE with other size than 8
298
274
// all links --> period_head_arr[0] (1ms)
299
275
// 0, 2, 4, 6 etc --> period_head_arr[1] (2ms)
300
276
// 1, 5 --> period_head_arr[2] (4ms)
301
277
// 3 --> period_head_arr[3] (8ms)
302
278
303
- // TODO EHCI_FRAMELIST_SIZE with other size than 8
279
+ ehci_link_t * const framelist = ehci_data .period_framelist ;
280
+ ehci_link_t * const head_1ms = (ehci_link_t * ) & ehci_data .period_head_arr [0 ];
281
+ ehci_link_t * const head_2ms = (ehci_link_t * ) & ehci_data .period_head_arr [1 ];
282
+ ehci_link_t * const head_4ms = (ehci_link_t * ) & ehci_data .period_head_arr [2 ];
283
+ ehci_link_t * const head_8ms = (ehci_link_t * ) & ehci_data .period_head_arr [3 ];
284
+
304
285
for (uint32_t i = 0 ; i < FRAMELIST_SIZE ; i ++ ) {
305
- framelist [i ].address = (uint32_t ) period_1ms ;
286
+ framelist [i ].address = (uint32_t ) head_1ms ;
306
287
framelist [i ].type = EHCI_QTYPE_QHD ;
307
288
}
308
289
309
290
for (uint32_t i = 0 ; i < FRAMELIST_SIZE ; i += 2 ) {
310
- list_insert (framelist + i , get_period_head ( rhport , 2u ) , EHCI_QTYPE_QHD );
291
+ list_insert (framelist + i , head_2ms , EHCI_QTYPE_QHD );
311
292
}
312
293
313
294
for (uint32_t i = 1 ; i < FRAMELIST_SIZE ; i += 4 ) {
314
- list_insert (framelist + i , get_period_head ( rhport , 4u ) , EHCI_QTYPE_QHD );
295
+ list_insert (framelist + i , head_4ms , EHCI_QTYPE_QHD );
315
296
}
316
297
317
- list_insert (framelist + 3 , get_period_head ( rhport , 8u ) , EHCI_QTYPE_QHD );
298
+ list_insert (framelist + 3 , head_8ms , EHCI_QTYPE_QHD );
318
299
319
- period_1ms -> terminate = 1 ;
300
+ head_1ms -> terminate = 1 ;
320
301
}
321
302
322
303
bool ehci_init (uint8_t rhport , uint32_t capability_reg , uint32_t operatial_reg )
@@ -345,7 +326,7 @@ bool ehci_init(uint8_t rhport, uint32_t capability_reg, uint32_t operatial_reg)
345
326
EHCI_INT_MASK_NXP_PERIODIC | EHCI_INT_MASK_NXP_ASYNC | EHCI_INT_MASK_FRAMELIST_ROLLOVER ;
346
327
347
328
//------------- Asynchronous List -------------//
348
- ehci_qhd_t * const async_head = qhd_async_head (rhport );
329
+ ehci_qhd_t * const async_head = list_get_async_head (rhport );
349
330
tu_memclr (async_head , sizeof (ehci_qhd_t ));
350
331
351
332
async_head -> next .address = (uint32_t ) async_head ; // circular list, next is itself
@@ -426,11 +407,11 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const
426
407
{
427
408
case TUSB_XFER_CONTROL :
428
409
case TUSB_XFER_BULK :
429
- list_head = (ehci_link_t * ) qhd_async_head (rhport );
410
+ list_head = (ehci_link_t * ) list_get_async_head (rhport );
430
411
break ;
431
412
432
413
case TUSB_XFER_INTERRUPT :
433
- list_head = get_period_head (rhport , p_qhd -> interval_ms );
414
+ list_head = list_get_period_head (rhport , p_qhd -> interval_ms );
434
415
break ;
435
416
436
417
case TUSB_XFER_ISOCHRONOUS :
@@ -439,10 +420,8 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const
439
420
440
421
default : break ;
441
422
}
442
-
443
423
TU_ASSERT (list_head );
444
424
445
- // TODO might need to disable async/period list
446
425
list_insert (list_head , (ehci_link_t * ) p_qhd , EHCI_QTYPE_QHD );
447
426
448
427
hcd_dcache_clean (p_qhd , sizeof (ehci_qhd_t ));
@@ -622,8 +601,8 @@ void async_list_xfer_complete_isr(ehci_qhd_t * const async_head)
622
601
TU_ATTR_ALWAYS_INLINE static inline
623
602
void period_list_xfer_complete_isr (uint8_t rhport , uint32_t interval_ms )
624
603
{
625
- uint32_t const period_1ms_addr = (uint32_t ) get_period_head (rhport , 1u );
626
- ehci_link_t next_link = * get_period_head (rhport , interval_ms );
604
+ uint32_t const period_1ms_addr = (uint32_t ) list_get_period_head (rhport , 1u );
605
+ ehci_link_t next_link = * list_get_period_head (rhport , interval_ms );
627
606
628
607
while (!next_link .terminate ) {
629
608
if (interval_ms > 1 && period_1ms_addr == tu_align32 (next_link .address )) {
@@ -721,7 +700,7 @@ TU_ATTR_ALWAYS_INLINE static inline
721
700
void xfer_error_isr (uint8_t rhport )
722
701
{
723
702
//------------- async list -------------//
724
- ehci_qhd_t * const async_head = qhd_async_head (rhport );
703
+ ehci_qhd_t * const async_head = list_get_async_head (rhport );
725
704
ehci_qhd_t * p_qhd = async_head ;
726
705
do
727
706
{
@@ -731,10 +710,10 @@ void xfer_error_isr(uint8_t rhport)
731
710
}while (p_qhd != async_head ); // async list traversal, stop if loop around
732
711
733
712
//------------- TODO refractor period list -------------//
734
- uint32_t const period_1ms_addr = (uint32_t ) get_period_head (rhport , 1u );
713
+ uint32_t const period_1ms_addr = (uint32_t ) list_get_period_head (rhport , 1u );
735
714
for (uint32_t interval_ms = 1 ; interval_ms <= FRAMELIST_SIZE ; interval_ms *= 2 )
736
715
{
737
- ehci_link_t next_item = * get_period_head (rhport , interval_ms );
716
+ ehci_link_t next_item = * list_get_period_head (rhport , interval_ms );
738
717
739
718
// TODO abstract max loop guard for period
740
719
while ( !next_item .terminate &&
@@ -801,7 +780,7 @@ void hcd_int_handler(uint8_t rhport)
801
780
802
781
//------------- some QTD/SITD/ITD with IOC set is completed -------------//
803
782
if (int_status & EHCI_INT_MASK_NXP_ASYNC ) {
804
- async_list_xfer_complete_isr (qhd_async_head (rhport ));
783
+ async_list_xfer_complete_isr (list_get_async_head (rhport ));
805
784
regs -> status = EHCI_INT_MASK_NXP_ASYNC ; // Acknowledge
806
785
}
807
786
@@ -828,42 +807,70 @@ void hcd_int_handler(uint8_t rhport)
828
807
}
829
808
830
809
//--------------------------------------------------------------------+
831
- // HELPER
810
+ // List Managing Helper
832
811
//--------------------------------------------------------------------+
833
812
813
+ // Get head of periodic list
814
+ TU_ATTR_ALWAYS_INLINE static inline ehci_link_t * list_get_period_head (uint8_t rhport , uint32_t interval_ms ) {
815
+ (void ) rhport ;
816
+ return (ehci_link_t * ) & ehci_data .period_head_arr [ tu_log2 ( tu_min32 (FRAMELIST_SIZE , interval_ms ) ) ];
817
+ }
834
818
835
- //------------- queue head helper -------------//
836
- static inline ehci_qhd_t * qhd_find_free (void )
819
+ // Get head of async list
820
+ TU_ATTR_ALWAYS_INLINE static inline ehci_qhd_t * list_get_async_head (uint8_t rhport ) {
821
+ (void ) rhport ;
822
+ return qhd_control (0 ); // control qhd of dev0 is used as async head
823
+ }
824
+
825
+ // insert at head
826
+ static inline void list_insert (ehci_link_t * current , ehci_link_t * new , uint8_t new_type )
837
827
{
838
- for (uint32_t i = 0 ; i < QHD_MAX ; i ++ )
839
- {
828
+ new -> address = current -> address ;
829
+ current -> address = ((uint32_t ) new ) | (new_type << 1 );
830
+ }
831
+
832
+ static inline ehci_link_t * list_next (ehci_link_t const * p_link )
833
+ {
834
+ return (ehci_link_t * ) tu_align32 (p_link -> address );
835
+ }
836
+
837
+ //--------------------------------------------------------------------+
838
+ // Queue Header helper
839
+ //--------------------------------------------------------------------+
840
+
841
+ // Get queue head for control transfer (always available)
842
+ TU_ATTR_ALWAYS_INLINE static inline ehci_qhd_t * qhd_control (uint8_t dev_addr ) {
843
+ return & ehci_data .control [dev_addr ].qhd ;
844
+ }
845
+
846
+ // Find a free queue head
847
+ TU_ATTR_ALWAYS_INLINE static inline ehci_qhd_t * qhd_find_free (void ) {
848
+ for ( uint32_t i = 0 ; i < QHD_MAX ; i ++ ) {
840
849
if ( !ehci_data .qhd_pool [i ].used ) return & ehci_data .qhd_pool [i ];
841
850
}
842
-
843
851
return NULL ;
844
852
}
845
853
846
- static inline ehci_qhd_t * qhd_next ( ehci_qhd_t const * p_qhd )
847
- {
848
- return (ehci_qhd_t * ) tu_align32 (p_qhd -> next .address );
854
+ // Next queue head link
855
+ TU_ATTR_ALWAYS_INLINE static inline ehci_qhd_t * qhd_next ( ehci_qhd_t const * p_qhd ) {
856
+ return (ehci_qhd_t * ) tu_align32 (p_qhd -> next .address );
849
857
}
850
858
851
- static inline ehci_qhd_t * qhd_get_from_addr ( uint8_t dev_addr , uint8_t ep_addr )
852
- {
853
- ehci_qhd_t * qhd_pool = ehci_data .qhd_pool ;
859
+ // Get queue head from address
860
+ static ehci_qhd_t * qhd_get_from_addr ( uint8_t dev_addr , uint8_t ep_addr ) {
861
+ ehci_qhd_t * qhd_pool = ehci_data .qhd_pool ;
854
862
855
- for (uint32_t i = 0 ; i < QHD_MAX ; i ++ )
856
- {
863
+ for ( uint32_t i = 0 ; i < QHD_MAX ; i ++ ) {
857
864
if ( (qhd_pool [i ].dev_addr == dev_addr ) &&
858
- ep_addr == tu_edpt_addr (qhd_pool [i ].ep_number , qhd_pool [i ].pid ) )
859
- {
865
+ ep_addr == tu_edpt_addr (qhd_pool [i ].ep_number , qhd_pool [i ].pid ) ) {
860
866
return & qhd_pool [i ];
861
867
}
862
868
}
863
869
864
870
return NULL ;
865
871
}
866
872
873
+ // Init queue head with endpoint descriptor
867
874
static void qhd_init (ehci_qhd_t * p_qhd , uint8_t dev_addr , tusb_desc_endpoint_t const * ep_desc )
868
875
{
869
876
// address 0 is used as async head, which always on the list --> cannot be cleared (ehci halted otherwise)
@@ -938,6 +945,7 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c
938
945
}
939
946
}
940
947
948
+ // Attach a TD to queue head
941
949
static void qhd_attach_qtd (ehci_qhd_t * qhd , ehci_qtd_t * qtd ) {
942
950
qhd -> attached_qtd = qtd ;
943
951
qhd -> attached_buffer = qtd -> buffer [0 ];
@@ -949,9 +957,16 @@ static void qhd_attach_qtd(ehci_qhd_t *qhd, ehci_qtd_t *qtd) {
949
957
hcd_dcache_clean_invalidate (qhd , sizeof (ehci_qhd_t ));
950
958
}
951
959
960
+ //--------------------------------------------------------------------+
961
+ // Queue TD helper
962
+ //--------------------------------------------------------------------+
963
+
964
+ // Get TD for control transfer (always available)
965
+ TU_ATTR_ALWAYS_INLINE static inline ehci_qtd_t * qtd_control (uint8_t dev_addr ) {
966
+ return & ehci_data .control [dev_addr ].qtd ;
967
+ }
952
968
953
- //------------- TD helper -------------//
954
- static inline ehci_qtd_t * qtd_find_free (void ) {
969
+ TU_ATTR_ALWAYS_INLINE static inline ehci_qtd_t * qtd_find_free (void ) {
955
970
for (uint32_t i = 0 ; i < QTD_MAX ; i ++ ) {
956
971
if (!ehci_data .qtd_pool [i ].used ) return & ehci_data .qtd_pool [i ];
957
972
}
@@ -979,18 +994,4 @@ static void qtd_init(ehci_qtd_t* qtd, void const* buffer, uint16_t total_bytes)
979
994
}
980
995
}
981
996
982
- //------------- List Managing Helper -------------//
983
-
984
- // insert at head
985
- static inline void list_insert (ehci_link_t * current , ehci_link_t * new , uint8_t new_type )
986
- {
987
- new -> address = current -> address ;
988
- current -> address = ((uint32_t ) new ) | (new_type << 1 );
989
- }
990
-
991
- static inline ehci_link_t * list_next (ehci_link_t const * p_link )
992
- {
993
- return (ehci_link_t * ) tu_align32 (p_link -> address );
994
- }
995
-
996
997
#endif
0 commit comments