Skip to content

Commit 27acaa0

Browse files
committed
refactor ehci, since usbh only queue 1 TD per queue head
1 parent 49e2aab commit 27acaa0

File tree

2 files changed

+37
-92
lines changed

2 files changed

+37
-92
lines changed

src/portable/ehci/ehci.c

Lines changed: 34 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,6 @@ static inline ehci_qhd_t* qhd_get_from_addr (uint8_t dev_addr, uint8_t ep_addr);
156156
static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc);
157157

158158
static inline ehci_qtd_t* qtd_find_free (void);
159-
static inline ehci_qtd_t* qtd_next (ehci_qtd_t const * p_qtd);
160-
static inline void qtd_insert_to_qhd (ehci_qhd_t *p_qhd, ehci_qtd_t *p_qtd_new);
161-
static inline void qtd_remove_1st_from_qhd (ehci_qhd_t *p_qhd);
162159
static void qtd_init (ehci_qtd_t* qtd, void const* buffer, uint16_t total_bytes);
163160

164161
static inline void list_insert (ehci_link_t *current, ehci_link_t *new, uint8_t new_type);
@@ -473,11 +470,8 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet
473470
hcd_dcache_clean((void *) setup_packet, 8);
474471
hcd_dcache_clean_invalidate(td, sizeof(ehci_qtd_t));
475472

476-
// sw region
477-
qhd->p_qtd_list_head = td;
478-
qhd->p_qtd_list_tail = td;
479-
480473
// attach TD
474+
qhd->p_attached_qtd = td; // software management
481475
qhd->qtd_overlay.next.address = (uint32_t) td;
482476

483477
hcd_dcache_clean_invalidate(qhd, sizeof(ehci_qhd_t));
@@ -501,7 +495,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *
501495

502496
qtd_init(qtd, buffer, buflen);
503497

504-
// first first data toggle is always 1 (data & setup stage)
498+
// first data toggle is always 1 (data & setup stage)
505499
qtd->data_toggle = 1;
506500
qtd->pid = dir ? EHCI_PID_IN : EHCI_PID_OUT;
507501
} else {
@@ -521,11 +515,8 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *
521515
}
522516
hcd_dcache_clean_invalidate(qtd, sizeof(ehci_qtd_t));
523517

524-
// Software: assign TD to QHD
525-
qhd->p_qtd_list_head = qtd;
526-
qhd->p_qtd_list_tail = qtd;
527-
528518
// attach TD to QHD start transferring
519+
qhd->p_attached_qtd = qtd; // software management
529520
qhd->qtd_overlay.next.address = (uint32_t) qtd;
530521

531522
hcd_dcache_clean_invalidate(qhd, sizeof(ehci_qhd_t));
@@ -580,27 +571,25 @@ void port_connect_status_change_isr(uint8_t rhport)
580571
TU_ATTR_ALWAYS_INLINE static inline
581572
void qhd_xfer_complete_isr(ehci_qhd_t * p_qhd)
582573
{
583-
// free all TDs from the head td to the first active TD
584-
while(p_qhd->p_qtd_list_head != NULL && !p_qhd->p_qtd_list_head->active)
585-
{
586-
ehci_qtd_t * volatile qtd = (ehci_qtd_t * volatile) p_qhd->p_qtd_list_head;
587-
hcd_dcache_invalidate(qtd, sizeof(ehci_qtd_t));
574+
// examine TD attached to queue head
575+
ehci_qtd_t * volatile qtd = (ehci_qtd_t * volatile) p_qhd->p_attached_qtd;
576+
if (qtd == NULL) return; // no TD attached
577+
hcd_dcache_invalidate(qtd, sizeof(ehci_qtd_t));
588578

589-
bool const is_ioc = (qtd->int_on_complete != 0);
590-
uint8_t const ep_addr = tu_edpt_addr(p_qhd->ep_number, qtd->pid == EHCI_PID_IN ? 1 : 0);
579+
// TD is still active, no need to process
580+
if (qtd->active) {
581+
return;
582+
}
591583

592-
p_qhd->total_xferred_bytes += qtd->expected_bytes - qtd->total_bytes;
584+
uint32_t const xferred_bytes = qtd->expected_bytes - qtd->total_bytes;
585+
uint8_t const ep_addr = tu_edpt_addr(p_qhd->ep_number, qtd->pid == EHCI_PID_IN ? 1 : 0);
593586

594-
// TD need to be freed and removed from qhd, before invoking callback
595-
qtd->used = 0; // free QTD
596-
qtd_remove_1st_from_qhd(p_qhd);
587+
// remove and free TD before invoking callback
588+
p_qhd->p_attached_qtd = NULL;
589+
qtd->used = 0; // free QTD
597590

598-
if (is_ioc)
599-
{
600-
hcd_event_xfer_complete(p_qhd->dev_addr, ep_addr, p_qhd->total_xferred_bytes, XFER_RESULT_SUCCESS, true);
601-
p_qhd->total_xferred_bytes = 0;
602-
}
603-
}
591+
// IOC is always set
592+
hcd_event_xfer_complete(p_qhd->dev_addr, ep_addr, xferred_bytes, XFER_RESULT_SUCCESS, true);
604593
}
605594

606595
TU_ATTR_ALWAYS_INLINE static inline
@@ -685,20 +674,17 @@ void qhd_xfer_error_isr(ehci_qhd_t * p_qhd)
685674
// while(1){}
686675
// }
687676

688-
ehci_qtd_t * volatile qtd = (ehci_qtd_t * volatile) p_qhd->p_qtd_list_head;
677+
ehci_qtd_t * volatile qtd = (ehci_qtd_t * volatile) p_qhd->p_attached_qtd;
689678
TU_ASSERT(qtd, ); // No TD yet, probably a race condition or cache issue !?
690679

691680
hcd_dcache_invalidate(qtd, sizeof(ehci_qtd_t));
692-
p_qhd->total_xferred_bytes += qtd->expected_bytes - qtd->total_bytes;
681+
uint32_t const xferred_bytes = qtd->expected_bytes - qtd->total_bytes;
693682

683+
p_qhd->p_attached_qtd = NULL;
694684
qtd->used = 0; // free QTD
695-
qtd_remove_1st_from_qhd(p_qhd);
696685

697686
if ( 0 == p_qhd->ep_number ) {
698-
// control cannot be halted --> clear all qtd list
699-
p_qhd->p_qtd_list_head = NULL;
700-
p_qhd->p_qtd_list_tail = NULL;
701-
687+
// control cannot be halted
702688
p_qhd->qtd_overlay.next.terminate = 1;
703689
p_qhd->qtd_overlay.alternate.terminate = 1;
704690
p_qhd->qtd_overlay.halted = 0;
@@ -707,19 +693,17 @@ void qhd_xfer_error_isr(ehci_qhd_t * p_qhd)
707693
p_setup->used = 0;
708694
}
709695

710-
// call USBH callback
696+
// notify usbh
711697
uint8_t const ep_addr = tu_edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0);
712-
hcd_event_xfer_complete(p_qhd->dev_addr, ep_addr, p_qhd->total_xferred_bytes, xfer_result, true);
713-
714-
p_qhd->total_xferred_bytes = 0;
698+
hcd_event_xfer_complete(p_qhd->dev_addr, ep_addr, xferred_bytes, xfer_result, true);
715699
}
716700
}
717701

718702
TU_ATTR_ALWAYS_INLINE static inline
719-
void xfer_error_isr(uint8_t hostid)
703+
void xfer_error_isr(uint8_t rhport)
720704
{
721705
//------------- async list -------------//
722-
ehci_qhd_t * const async_head = qhd_async_head(hostid);
706+
ehci_qhd_t * const async_head = qhd_async_head(rhport);
723707
ehci_qhd_t *p_qhd = async_head;
724708
do
725709
{
@@ -729,10 +713,10 @@ void xfer_error_isr(uint8_t hostid)
729713
}while(p_qhd != async_head); // async list traversal, stop if loop around
730714

731715
//------------- TODO refractor period list -------------//
732-
uint32_t const period_1ms_addr = (uint32_t) get_period_head(hostid, 1u);
716+
uint32_t const period_1ms_addr = (uint32_t) get_period_head(rhport, 1u);
733717
for (uint32_t interval_ms=1; interval_ms <= FRAMELIST_SIZE; interval_ms *= 2)
734718
{
735-
ehci_link_t next_item = * get_period_head(hostid, interval_ms);
719+
ehci_link_t next_item = * get_period_head(rhport, interval_ms);
736720

737721
// TODO abstract max loop guard for period
738722
while( !next_item.terminate &&
@@ -873,34 +857,6 @@ static inline ehci_qtd_t* qtd_find_free(void)
873857
return NULL;
874858
}
875859

876-
static inline ehci_qtd_t* qtd_next(ehci_qtd_t const * p_qtd )
877-
{
878-
return (ehci_qtd_t*) tu_align32(p_qtd->next.address);
879-
}
880-
881-
static inline void qtd_remove_1st_from_qhd(ehci_qhd_t *p_qhd)
882-
{
883-
if (p_qhd->p_qtd_list_head == p_qhd->p_qtd_list_tail) // last TD --> make it NULL
884-
{
885-
p_qhd->p_qtd_list_head = p_qhd->p_qtd_list_tail = NULL;
886-
}else
887-
{
888-
p_qhd->p_qtd_list_head = qtd_next( p_qhd->p_qtd_list_head );
889-
}
890-
}
891-
892-
static inline void qtd_insert_to_qhd(ehci_qhd_t *p_qhd, ehci_qtd_t *p_qtd_new)
893-
{
894-
if (p_qhd->p_qtd_list_head == NULL) // empty list
895-
{
896-
p_qhd->p_qtd_list_head = p_qhd->p_qtd_list_tail = p_qtd_new;
897-
}else
898-
{
899-
p_qhd->p_qtd_list_tail->next.address = (uint32_t) p_qtd_new;
900-
p_qhd->p_qtd_list_tail = p_qtd_new;
901-
}
902-
}
903-
904860
static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc)
905861
{
906862
// address 0 is used as async head, which always on the list --> cannot be cleared (ehci halted otherwise)
@@ -955,15 +911,14 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c
955911
p_qhd->int_smask = p_qhd->fl_int_cmask = 0;
956912
}
957913

958-
p_qhd->fl_hub_addr = devtree_info.hub_addr;
959-
p_qhd->fl_hub_port = devtree_info.hub_port;
960-
p_qhd->mult = 1; // TODO not use high bandwidth/park mode yet
914+
p_qhd->fl_hub_addr = devtree_info.hub_addr;
915+
p_qhd->fl_hub_port = devtree_info.hub_port;
916+
p_qhd->mult = 1; // TODO not use high bandwidth/park mode yet
961917

962918
//------------- HCD Management Data -------------//
963-
p_qhd->used = 1;
964-
p_qhd->removing = 0;
965-
p_qhd->p_qtd_list_head = NULL;
966-
p_qhd->p_qtd_list_tail = NULL;
919+
p_qhd->used = 1;
920+
p_qhd->removing = 0;
921+
p_qhd->p_attached_qtd = NULL;
967922
p_qhd->pid = tu_edpt_dir(ep_desc->bEndpointAddress) ? EHCI_PID_IN : EHCI_PID_OUT; // PID for TD under this endpoint
968923

969924
//------------- active, but no TD list -------------//

src/portable/ehci/ehci.h

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -164,12 +164,10 @@ typedef struct TU_ATTR_ALIGNED(32)
164164
uint8_t pid;
165165
uint8_t interval_ms; // polling interval in frames (or millisecond)
166166

167-
uint16_t total_xferred_bytes; // number of bytes xferred until a qtd with ioc bit set
168-
uint8_t reserved2[2];
167+
uint8_t TU_RESERVED[8];
169168

170-
// TODO USBH will only queue 1 TD per QHD, thus we can remove the list
171-
ehci_qtd_t * volatile p_qtd_list_head; // head of the scheduled TD list
172-
ehci_qtd_t * volatile p_qtd_list_tail; // tail of the scheduled TD list
169+
// usbh will only queue 1 TD per QHD
170+
ehci_qtd_t * volatile p_attached_qtd;
173171
} ehci_qhd_t;
174172

175173
TU_VERIFY_STATIC( sizeof(ehci_qhd_t) == 64, "size is not correct" );
@@ -248,14 +246,6 @@ typedef struct TU_ATTR_ALIGNED(32)
248246
/// Word 4-5: Buffer Pointer List
249247
uint32_t buffer[2]; // buffer[1] TP: Transaction Position - T-Count: Transaction Count
250248

251-
// union{
252-
// uint32_t BufferPointer1;
253-
// struct {
254-
// volatile uint32_t TCount : 3;
255-
// volatile uint32_t TPosition : 2;
256-
// };
257-
// };
258-
259249
/*---------- Word 6 ----------*/
260250
ehci_link_t back;
261251

0 commit comments

Comments
 (0)