@@ -92,7 +92,7 @@ CFG_TUH_MEM_SECTION TU_ATTR_ALIGNED(4096) static ehci_data_t ehci_data;
92
92
//--------------------------------------------------------------------+
93
93
// Debug
94
94
//--------------------------------------------------------------------+
95
- #if CFG_TUSB_DEBUG >= EHCI_DBG
95
+ #if CFG_TUSB_DEBUG >= ( EHCI_DBG + 1 )
96
96
static inline void print_portsc (ehci_registers_t * regs ) {
97
97
TU_LOG_HEX (EHCI_DBG , regs -> portsc );
98
98
TU_LOG (EHCI_DBG , " Connect Status : %u\r\n" , regs -> portsc_bm .current_connect_status );
@@ -159,7 +159,7 @@ static inline ehci_qtd_t* qtd_find_free (void);
159
159
static inline ehci_qtd_t * qtd_next (ehci_qtd_t const * p_qtd );
160
160
static inline void qtd_insert_to_qhd (ehci_qhd_t * p_qhd , ehci_qtd_t * p_qtd_new );
161
161
static inline void qtd_remove_1st_from_qhd (ehci_qhd_t * p_qhd );
162
- static void qtd_init (ehci_qtd_t * p_qtd , void const * buffer , uint16_t total_bytes );
162
+ static void qtd_init (ehci_qtd_t * qtd , void const * buffer , uint16_t total_bytes );
163
163
164
164
static inline void list_insert (ehci_link_t * current , ehci_link_t * new , uint8_t new_type );
165
165
static inline ehci_link_t * list_next (ehci_link_t * p_link_pointer );
@@ -325,28 +325,27 @@ bool ehci_init(uint8_t rhport, uint32_t capability_reg, uint32_t operatial_reg)
325
325
// 3 --> period_head_arr[3] (8ms)
326
326
327
327
// TODO EHCI_FRAMELIST_SIZE with other size than 8
328
- for (uint32_t i = 0 ; i < FRAMELIST_SIZE ; i ++ )
329
- {
328
+ for (uint32_t i = 0 ; i < FRAMELIST_SIZE ; i ++ ) {
330
329
framelist [i ].address = (uint32_t ) period_1ms ;
331
- framelist [i ].type = EHCI_QTYPE_QHD ;
330
+ framelist [i ].type = EHCI_QTYPE_QHD ;
332
331
}
333
332
334
- for (uint32_t i = 0 ; i < FRAMELIST_SIZE ; i += 2 )
335
- {
333
+ for (uint32_t i = 0 ; i < FRAMELIST_SIZE ; i += 2 ) {
336
334
list_insert (framelist + i , get_period_head (rhport , 2u ), EHCI_QTYPE_QHD );
337
335
}
338
336
339
- for (uint32_t i = 1 ; i < FRAMELIST_SIZE ; i += 4 )
340
- {
337
+ for (uint32_t i = 1 ; i < FRAMELIST_SIZE ; i += 4 ) {
341
338
list_insert (framelist + i , get_period_head (rhport , 4u ), EHCI_QTYPE_QHD );
342
339
}
343
-
344
- list_insert (framelist + 3 , get_period_head (rhport , 8u ), EHCI_QTYPE_QHD );
345
-
340
+ list_insert (framelist + 3 , get_period_head (rhport , 8u ), EHCI_QTYPE_QHD );
346
341
period_1ms -> terminate = 1 ;
347
342
348
343
regs -> periodic_list_base = (uint32_t ) framelist ;
349
344
345
+ if (hcd_dcache_clean ) {
346
+ hcd_dcache_clean (& ehci_data , sizeof (ehci_data_t ));
347
+ }
348
+
350
349
//------------- TT Control (NXP only) -------------//
351
350
regs -> nxp_tt_control = 0 ;
352
351
@@ -430,6 +429,11 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const
430
429
// TODO might need to disable async/period list
431
430
list_insert (list_head , (ehci_link_t * ) p_qhd , EHCI_QTYPE_QHD );
432
431
432
+ if (hcd_dcache_clean ) {
433
+ hcd_dcache_clean (p_qhd , sizeof (ehci_qhd_t ));
434
+ hcd_dcache_clean (list_head , sizeof (ehci_link_t ));
435
+ }
436
+
433
437
return true;
434
438
}
435
439
@@ -441,9 +445,12 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet
441
445
ehci_qtd_t * td = & ehci_data .control [dev_addr ].qtd ;
442
446
443
447
qtd_init (td , setup_packet , 8 );
444
- td -> pid = EHCI_PID_SETUP ;
445
- td -> int_on_complete = 1 ;
446
- td -> next .terminate = 1 ;
448
+ td -> pid = EHCI_PID_SETUP ;
449
+
450
+ if (hcd_dcache_clean && hcd_dcache_clean_invalidate ) {
451
+ hcd_dcache_clean ((void * ) setup_packet , 8 );
452
+ hcd_dcache_clean_invalidate (td , sizeof (ehci_qtd_t ));
453
+ }
447
454
448
455
// sw region
449
456
qhd -> p_qtd_list_head = td ;
@@ -452,6 +459,10 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet
452
459
// attach TD
453
460
qhd -> qtd_overlay .next .address = (uint32_t ) td ;
454
461
462
+ if (hcd_dcache_clean_invalidate ) {
463
+ hcd_dcache_clean_invalidate (qhd , sizeof (ehci_qhd_t ));
464
+ }
465
+
455
466
return true;
456
467
}
457
468
@@ -462,41 +473,48 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *
462
473
uint8_t const epnum = tu_edpt_number (ep_addr );
463
474
uint8_t const dir = tu_edpt_dir (ep_addr );
464
475
476
+ ehci_qhd_t * qhd ;
477
+ ehci_qtd_t * qtd ;
478
+
465
479
if ( epnum == 0 )
466
480
{
467
- ehci_qhd_t * qhd = qhd_control (dev_addr );
468
- ehci_qtd_t * qtd = qtd_control (dev_addr );
481
+ qhd = qhd_control (dev_addr );
482
+ qtd = qtd_control (dev_addr );
469
483
470
484
qtd_init (qtd , buffer , buflen );
471
485
472
486
// first first data toggle is always 1 (data & setup stage)
473
487
qtd -> data_toggle = 1 ;
474
488
qtd -> pid = dir ? EHCI_PID_IN : EHCI_PID_OUT ;
475
- qtd -> int_on_complete = 1 ;
476
- qtd -> next .terminate = 1 ;
477
-
478
- // sw region
479
- qhd -> p_qtd_list_head = qtd ;
480
- qhd -> p_qtd_list_tail = qtd ;
481
-
482
- // attach TD
483
- qhd -> qtd_overlay .next .address = (uint32_t ) qtd ;
484
489
}else
485
490
{
486
- ehci_qhd_t * p_qhd = qhd_get_from_addr (dev_addr , ep_addr );
487
- ehci_qtd_t * p_qtd = qtd_find_free ();
488
- TU_ASSERT (p_qtd );
491
+ qhd = qhd_get_from_addr (dev_addr , ep_addr );
492
+ qtd = qtd_find_free ();
493
+ TU_ASSERT (qtd );
494
+
495
+ qtd_init (qtd , buffer , buflen );
496
+ qtd -> pid = qhd -> pid ;
497
+ }
489
498
490
- qtd_init (p_qtd , buffer , buflen );
491
- p_qtd -> pid = p_qhd -> pid ;
499
+ if (hcd_dcache_clean && hcd_dcache_clean_invalidate ) {
500
+ // IN transfer: invalidate buffer, OUT transfer: clean buffer
501
+ if (dir ) {
502
+ hcd_dcache_invalidate (buffer , buflen );
503
+ }else {
504
+ hcd_dcache_clean (buffer , buflen );
505
+ }
506
+ hcd_dcache_clean_invalidate (qtd , sizeof (ehci_qtd_t ));
507
+ }
492
508
493
- // Insert TD to QH
494
- qtd_insert_to_qhd (p_qhd , p_qtd );
509
+ // Software: assign TD to QHD
510
+ qhd -> p_qtd_list_head = qtd ;
511
+ qhd -> p_qtd_list_tail = qtd ;
495
512
496
- p_qhd -> p_qtd_list_tail -> int_on_complete = 1 ;
513
+ // attach TD to QHD start transferring
514
+ qhd -> qtd_overlay .next .address = (uint32_t ) qtd ;
497
515
498
- // attach head QTD to QHD start transferring
499
- p_qhd -> qtd_overlay . next . address = ( uint32_t ) p_qhd -> p_qtd_list_head ;
516
+ if ( hcd_dcache_clean_invalidate ) {
517
+ hcd_dcache_clean_invalidate ( qhd , sizeof ( ehci_qhd_t )) ;
500
518
}
501
519
502
520
return true;
@@ -551,6 +569,11 @@ static void qhd_xfer_complete_isr(ehci_qhd_t * p_qhd)
551
569
while (p_qhd -> p_qtd_list_head != NULL && !p_qhd -> p_qtd_list_head -> active )
552
570
{
553
571
ehci_qtd_t * volatile qtd = (ehci_qtd_t * volatile ) p_qhd -> p_qtd_list_head ;
572
+
573
+ if (hcd_dcache_invalidate ) {
574
+ hcd_dcache_invalidate (qtd , sizeof (ehci_qtd_t ));
575
+ }
576
+
554
577
bool const is_ioc = (qtd -> int_on_complete != 0 );
555
578
uint8_t const ep_addr = tu_edpt_addr (p_qhd -> ep_number , qtd -> pid == EHCI_PID_IN ? 1 : 0 );
556
579
@@ -573,8 +596,12 @@ static void async_list_xfer_complete_isr(ehci_qhd_t * const async_head)
573
596
ehci_qhd_t * p_qhd = async_head ;
574
597
do
575
598
{
576
- if ( !p_qhd -> qtd_overlay .halted ) // halted or error is processed in error isr
577
- {
599
+ if (hcd_dcache_invalidate ) {
600
+ hcd_dcache_invalidate (p_qhd , sizeof (ehci_qhd_t ));
601
+ }
602
+
603
+ // halted or error is processed in error isr
604
+ if ( !p_qhd -> qtd_overlay .halted ) {
578
605
qhd_xfer_complete_isr (p_qhd );
579
606
}
580
607
p_qhd = qhd_next (p_qhd );
@@ -640,8 +667,8 @@ static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd)
640
667
// while(1){}
641
668
// }
642
669
643
- // No TD, probably an signal noise ?
644
- TU_VERIFY (p_qhd -> p_qtd_list_head , );
670
+ // No TD yet, it is probably the probably an signal noise ?
671
+ TU_ASSERT (p_qhd -> p_qtd_list_head , );
645
672
646
673
p_qhd -> p_qtd_list_head -> used = 0 ; // free QTD
647
674
qtd_remove_1st_from_qhd (p_qhd );
@@ -714,17 +741,19 @@ static void xfer_error_isr(uint8_t hostid)
714
741
void hcd_int_handler (uint8_t rhport )
715
742
{
716
743
ehci_registers_t * regs = ehci_data .regs ;
744
+ uint32_t const int_status = regs -> status ;
717
745
718
- uint32_t int_status = regs -> status ;
719
- int_status &= regs -> inten ;
720
-
721
- regs -> status = int_status ; // Acknowledge handled interrupt
722
-
723
- if ( int_status == 0 ) return ;
746
+ if ( int_status & EHCI_INT_MASK_HC_HALTED ) {
747
+ // something seriously wrong, maybe forget to flush/invalidate cache
748
+ TU_BREAKPOINT ();
749
+ TU_LOG1 ( " HC halted\n" );
750
+ return ;
751
+ }
724
752
725
753
if (int_status & EHCI_INT_MASK_FRAMELIST_ROLLOVER )
726
754
{
727
755
ehci_data .uframe_number += (FRAMELIST_SIZE << 3 );
756
+ regs -> status = EHCI_INT_MASK_FRAMELIST_ROLLOVER ; // Acknowledge
728
757
}
729
758
730
759
if (int_status & EHCI_INT_MASK_PORT_CHANGE )
@@ -739,31 +768,41 @@ void hcd_int_handler(uint8_t rhport)
739
768
}
740
769
741
770
regs -> portsc |= port_status ; // Acknowledge change bits in portsc
771
+ regs -> status = EHCI_INT_MASK_PORT_CHANGE ; // Acknowledge
742
772
}
743
773
744
774
if (int_status & EHCI_INT_MASK_ERROR )
745
775
{
746
776
xfer_error_isr (rhport );
777
+ regs -> status = EHCI_INT_MASK_ERROR ; // Acknowledge
747
778
}
748
779
749
780
//------------- some QTD/SITD/ITD with IOC set is completed -------------//
750
781
if (int_status & EHCI_INT_MASK_NXP_ASYNC )
751
782
{
752
- async_list_xfer_complete_isr ( qhd_async_head (rhport ) );
783
+ async_list_xfer_complete_isr (qhd_async_head (rhport ));
784
+ regs -> status = EHCI_INT_MASK_NXP_ASYNC ; // Acknowledge
753
785
}
754
786
755
787
if (int_status & EHCI_INT_MASK_NXP_PERIODIC )
756
788
{
757
789
for (uint32_t i = 1 ; i <= FRAMELIST_SIZE ; i *= 2 )
758
790
{
759
- period_list_xfer_complete_isr ( rhport , i );
791
+ period_list_xfer_complete_isr (rhport , i );
760
792
}
793
+ regs -> status = EHCI_INT_MASK_NXP_PERIODIC ; // Acknowledge
794
+ }
795
+
796
+ if (int_status & EHCI_INT_MASK_USB ) {
797
+ // TODO standard EHCI xfer complete
798
+ regs -> status = EHCI_INT_MASK_USB ; // Acknowledge
761
799
}
762
800
763
801
//------------- There is some removed async previously -------------//
764
- if ( int_status & EHCI_INT_MASK_ASYNC_ADVANCE ) // need to place after EHCI_INT_MASK_NXP_ASYNC
765
- {
802
+ // need to place after EHCI_INT_MASK_NXP_ASYNC
803
+ if ( int_status & EHCI_INT_MASK_ASYNC_ADVANCE ) {
766
804
async_advance_isr (rhport );
805
+ regs -> status = EHCI_INT_MASK_ASYNC_ADVANCE ; // Acknowledge
767
806
}
768
807
}
769
808
@@ -918,28 +957,30 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c
918
957
}
919
958
}
920
959
921
- static void qtd_init (ehci_qtd_t * p_qtd , void const * buffer , uint16_t total_bytes )
960
+ static void qtd_init (ehci_qtd_t * qtd , void const * buffer , uint16_t total_bytes )
922
961
{
923
- tu_memclr (p_qtd , sizeof (ehci_qtd_t ));
962
+ tu_memclr (qtd , sizeof (ehci_qtd_t ));
963
+ qtd -> used = 1 ;
924
964
925
- p_qtd -> used = 1 ;
965
+ qtd -> next .terminate = 1 ; // init to null
966
+ qtd -> alternate .terminate = 1 ; // not used, always set to terminated
967
+ qtd -> active = 1 ;
968
+ qtd -> err_count = 3 ; // TODO 3 consecutive errors tolerance
969
+ qtd -> data_toggle = 0 ;
970
+ qtd -> int_on_complete = 1 ;
971
+ qtd -> total_bytes = total_bytes ;
972
+ qtd -> expected_bytes = total_bytes ;
926
973
927
- p_qtd -> next .terminate = 1 ; // init to null
928
- p_qtd -> alternate .terminate = 1 ; // not used, always set to terminated
929
- p_qtd -> active = 1 ;
930
- p_qtd -> err_count = 3 ; // TODO 3 consecutive errors tolerance
931
- p_qtd -> data_toggle = 0 ;
932
- p_qtd -> total_bytes = total_bytes ;
933
- p_qtd -> expected_bytes = total_bytes ;
934
-
935
- p_qtd -> buffer [0 ] = (uint32_t ) buffer ;
974
+ qtd -> buffer [0 ] = (uint32_t ) buffer ;
936
975
for (uint8_t i = 1 ; i < 5 ; i ++ )
937
976
{
938
- p_qtd -> buffer [i ] |= tu_align4k ( p_qtd -> buffer [i - 1 ] ) + 4096 ;
977
+ qtd -> buffer [i ] |= tu_align4k (qtd -> buffer [i - 1 ] ) + 4096 ;
939
978
}
940
979
}
941
980
942
981
//------------- List Managing Helper -------------//
982
+
983
+ // insert at head
943
984
static inline void list_insert (ehci_link_t * current , ehci_link_t * new , uint8_t new_type )
944
985
{
945
986
new -> address = current -> address ;
0 commit comments