merge EHCI_MAX_QHD/QTD and OHCI_MAX_QHD/QTD to HCD_MAX_ENDPOINT/XFER and scale with number of enabled classes.
default config to support up to 5 device (hub + 4 others)
This commit is contained in:
		@@ -52,7 +52,7 @@
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
// HOST CONFIGURATION
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
#define TUSB_CFG_HOST_DEVICE_MAX                3 // TODO be a part of HUB config
 | 
			
		||||
#define TUSB_CFG_HOST_DEVICE_MAX                5 // TODO be a part of HUB config
 | 
			
		||||
 | 
			
		||||
//------------- CLASS -------------//
 | 
			
		||||
#define TUSB_CFG_HOST_HUB                       1
 | 
			
		||||
 
 | 
			
		||||
@@ -38,4 +38,5 @@ In order to build and run application demo, you would need
 | 
			
		||||
- A supported toolchain: LPCXpresso, Keil, IAR.
 | 
			
		||||
 | 
			
		||||
\subpage md_boards_readme
 | 
			
		||||
\subpage md_doxygen_started_build
 | 
			
		||||
\subpage md_doxygen_started_build_demo
 | 
			
		||||
\subpage md_doxygen_started_run_demo
 | 
			
		||||
@@ -523,12 +523,12 @@ static void async_advance_isr(ehci_qhd_t * const async_head)
 | 
			
		||||
      // Host Controller has cleaned up its cached data for this device, set state to unplug
 | 
			
		||||
      usbh_devices[relative_dev_addr+1].state = TUSB_DEVICE_STATE_UNPLUG;
 | 
			
		||||
 | 
			
		||||
      for (uint8_t i=0; i<EHCI_MAX_QHD; i++) // free all qhd
 | 
			
		||||
      for (uint8_t i=0; i<HCD_MAX_ENDPOINT; i++) // free all qhd
 | 
			
		||||
      {
 | 
			
		||||
        ehci_data.device[relative_dev_addr].qhd[i].used        = 0;
 | 
			
		||||
        ehci_data.device[relative_dev_addr].qhd[i].is_removing = 0;
 | 
			
		||||
      }
 | 
			
		||||
      for (uint8_t i=0; i<EHCI_MAX_QTD; i++) // free all qtd
 | 
			
		||||
      for (uint8_t i=0; i<HCD_MAX_XFER; i++) // free all qtd
 | 
			
		||||
      {
 | 
			
		||||
        ehci_data.device[relative_dev_addr].qtd[i].used = 0;
 | 
			
		||||
      }
 | 
			
		||||
@@ -560,7 +560,7 @@ static void qhd_xfer_complete_isr(ehci_qhd_t * p_qhd)
 | 
			
		||||
 | 
			
		||||
  // free all TDs from the head td to the first active TD
 | 
			
		||||
  while(p_qhd->p_qtd_list_head != NULL && !p_qhd->p_qtd_list_head->active
 | 
			
		||||
      && max_loop < EHCI_MAX_QTD)
 | 
			
		||||
      && max_loop < HCD_MAX_XFER)
 | 
			
		||||
  {
 | 
			
		||||
    // TD need to be freed and removed from qhd, before invoking callback
 | 
			
		||||
    bool is_ioc = (p_qhd->p_qtd_list_head->int_on_complete != 0);
 | 
			
		||||
@@ -593,7 +593,7 @@ static void async_list_xfer_complete_isr(ehci_qhd_t * const async_head)
 | 
			
		||||
    }
 | 
			
		||||
    p_qhd = qhd_next(p_qhd);
 | 
			
		||||
    max_loop++;
 | 
			
		||||
  }while(p_qhd != async_head && max_loop < EHCI_MAX_QHD); // async list traversal, stop if loop around
 | 
			
		||||
  }while(p_qhd != async_head && max_loop < HCD_MAX_ENDPOINT); // async list traversal, stop if loop around
 | 
			
		||||
  // TODO abstract max loop guard for async
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -607,7 +607,7 @@ static void period_list_xfer_complete_isr(uint8_t hostid, uint8_t interval_ms)
 | 
			
		||||
  // TODO abstract max loop guard for period
 | 
			
		||||
  while( !next_item.terminate &&
 | 
			
		||||
      !(interval_ms > 1 && period_1ms_addr == align32(next_item.address)) &&
 | 
			
		||||
      max_loop < (EHCI_MAX_QHD + EHCI_MAX_ITD + EHCI_MAX_SITD))
 | 
			
		||||
      max_loop < (HCD_MAX_ENDPOINT + EHCI_MAX_ITD + EHCI_MAX_SITD))
 | 
			
		||||
  {
 | 
			
		||||
    switch ( next_item.type )
 | 
			
		||||
    {
 | 
			
		||||
@@ -692,7 +692,7 @@ static void xfer_error_isr(uint8_t hostid)
 | 
			
		||||
    qhd_xfer_error_isr( p_qhd );
 | 
			
		||||
    p_qhd = qhd_next(p_qhd);
 | 
			
		||||
    max_loop++;
 | 
			
		||||
  }while(p_qhd != async_head && max_loop < EHCI_MAX_QHD); // async list traversal, stop if loop around
 | 
			
		||||
  }while(p_qhd != async_head && max_loop < HCD_MAX_ENDPOINT); // async list traversal, stop if loop around
 | 
			
		||||
 | 
			
		||||
  #if EHCI_PERIODIC_LIST
 | 
			
		||||
  //------------- TODO refractor period list -------------//
 | 
			
		||||
@@ -705,7 +705,7 @@ static void xfer_error_isr(uint8_t hostid)
 | 
			
		||||
    // TODO abstract max loop guard for period
 | 
			
		||||
    while( !next_item.terminate &&
 | 
			
		||||
        !(interval_ms > 1 && period_1ms_addr == align32(next_item.address)) &&
 | 
			
		||||
        period_max_loop < (EHCI_MAX_QHD + EHCI_MAX_ITD + EHCI_MAX_SITD))
 | 
			
		||||
        period_max_loop < (HCD_MAX_ENDPOINT + EHCI_MAX_ITD + EHCI_MAX_SITD))
 | 
			
		||||
    {
 | 
			
		||||
      switch ( next_item.type )
 | 
			
		||||
      {
 | 
			
		||||
@@ -852,11 +852,11 @@ static inline ehci_qhd_t* qhd_find_free (uint8_t dev_addr)
 | 
			
		||||
{
 | 
			
		||||
  uint8_t relative_address = dev_addr-1;
 | 
			
		||||
  uint8_t index=0;
 | 
			
		||||
  while( index<EHCI_MAX_QHD && ehci_data.device[relative_address].qhd[index].used )
 | 
			
		||||
  while( index<HCD_MAX_ENDPOINT && ehci_data.device[relative_address].qhd[index].used )
 | 
			
		||||
  {
 | 
			
		||||
    index++;
 | 
			
		||||
  }
 | 
			
		||||
  return (index < EHCI_MAX_QHD) ? &ehci_data.device[relative_address].qhd[index] : NULL;
 | 
			
		||||
  return (index < HCD_MAX_ENDPOINT) ? &ehci_data.device[relative_address].qhd[index] : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline uint8_t qhd_get_index(ehci_qhd_t const * p_qhd)
 | 
			
		||||
@@ -899,12 +899,12 @@ static inline pipe_handle_t qhd_create_pipe_handle(ehci_qhd_t const * p_qhd, tus
 | 
			
		||||
STATIC_ INLINE_ ehci_qtd_t* qtd_find_free(uint8_t dev_addr)
 | 
			
		||||
{
 | 
			
		||||
  uint8_t index=0;
 | 
			
		||||
  while( index<EHCI_MAX_QTD && ehci_data.device[dev_addr-1].qtd[index].used )
 | 
			
		||||
  while( index<HCD_MAX_XFER && ehci_data.device[dev_addr-1].qtd[index].used )
 | 
			
		||||
  {
 | 
			
		||||
    index++;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (index < EHCI_MAX_QTD) ? &ehci_data.device[dev_addr-1].qtd[index] : NULL;
 | 
			
		||||
  return (index < HCD_MAX_XFER) ? &ehci_data.device[dev_addr-1].qtd[index] : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline ehci_qtd_t* qtd_next(ehci_qtd_t const * p_qtd )
 | 
			
		||||
@@ -1044,7 +1044,7 @@ static ehci_link_t* list_find_previous_item(ehci_link_t* p_head, ehci_link_t* p_
 | 
			
		||||
  while( (align32(p_prev->address) != (uint32_t) p_head)    && // not loop around
 | 
			
		||||
         (align32(p_prev->address) != (uint32_t) p_current) && // not found yet
 | 
			
		||||
         !p_prev->terminate                                 && // not advanceable
 | 
			
		||||
         max_loop < EHCI_MAX_QHD)
 | 
			
		||||
         max_loop < HCD_MAX_ENDPOINT)
 | 
			
		||||
  {
 | 
			
		||||
    p_prev = list_next(p_prev);
 | 
			
		||||
    max_loop++;
 | 
			
		||||
 
 | 
			
		||||
@@ -71,19 +71,17 @@
 | 
			
		||||
#define HOST_HCD_XFER_INTERRUPT // TODO interrupt is used widely, should always be enalbed
 | 
			
		||||
#define EHCI_PERIODIC_LIST (defined HOST_HCD_XFER_INTERRUPT || defined HOST_HCD_XFER_ISOCHRONOUS)
 | 
			
		||||
 | 
			
		||||
// TODO merge OHCI with EHCI
 | 
			
		||||
#define EHCI_MAX_QHD  8
 | 
			
		||||
#define EHCI_MAX_QTD  20
 | 
			
		||||
#define EHCI_MAX_ITD  4
 | 
			
		||||
#define EHCI_MAX_SITD 16
 | 
			
		||||
 | 
			
		||||
#define	EHCI_CFG_FRAMELIST_SIZE_BITS			7			/// Framelist Size (NXP specific) (0:1024) - (1:512) - (2:256) - (3:128) - (4:64) - (5:32) - (6:16) - (7:8)
 | 
			
		||||
#define EHCI_FRAMELIST_SIZE  (1024 >> EHCI_CFG_FRAMELIST_SIZE_BITS)
 | 
			
		||||
 | 
			
		||||
// TODO merge OHCI with EHCI
 | 
			
		||||
enum {
 | 
			
		||||
  EHCI_MAX_ITD  = 4,
 | 
			
		||||
  EHCI_MAX_SITD = 16
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//------------- Validation -------------//
 | 
			
		||||
#if EHCI_CFG_FRAMELIST_SIZE_BITS > 7
 | 
			
		||||
 #error EHCI_CFG_FRAMELIST_SIZE_BITS must be from 0-7
 | 
			
		||||
#endif
 | 
			
		||||
STATIC_ASSERT(EHCI_CFG_FRAMELIST_SIZE_BITS <= 7, "incorrect value");
 | 
			
		||||
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
// EHCI Data Structure
 | 
			
		||||
@@ -469,8 +467,8 @@ typedef struct {
 | 
			
		||||
      ehci_qtd_t qtd[3];
 | 
			
		||||
    }control;
 | 
			
		||||
 | 
			
		||||
    ehci_qhd_t  qhd[EHCI_MAX_QHD]                  ; ///< Queue Head Pool
 | 
			
		||||
    ehci_qtd_t  qtd[EHCI_MAX_QTD] ATTR_ALIGNED(32) ; ///< Queue Element Transfer Pool
 | 
			
		||||
    ehci_qhd_t  qhd[HCD_MAX_ENDPOINT]                  ; ///< Queue Head Pool
 | 
			
		||||
    ehci_qtd_t  qtd[HCD_MAX_XFER] ATTR_ALIGNED(32) ; ///< Queue Element Transfer Pool
 | 
			
		||||
//  ehci_itd_t  itd[EHCI_MAX_ITD]                  ; ///< Iso Transfer Pool
 | 
			
		||||
//  ehci_sitd_t sitd[EHCI_MAX_SITD]                ; ///< Split (FS) Isochronous Transfer Pool
 | 
			
		||||
  }device[TUSB_CFG_HOST_DEVICE_MAX];
 | 
			
		||||
 
 | 
			
		||||
@@ -43,12 +43,20 @@
 | 
			
		||||
#ifndef _TUSB_HCD_H_
 | 
			
		||||
#define _TUSB_HCD_H_
 | 
			
		||||
 | 
			
		||||
#include "common/common.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
 extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "common/common.h"
 | 
			
		||||
 | 
			
		||||
// Max number of endpoints per device
 | 
			
		||||
enum {
 | 
			
		||||
  HCD_MAX_ENDPOINT = TUSB_CFG_HOST_HUB + TUSB_CFG_HOST_HID_KEYBOARD + TUSB_CFG_HOST_HID_MOUSE + TUSB_CFG_HOST_HID_GENERIC +
 | 
			
		||||
                     TUSB_CFG_HOST_MSC*2 + TUSB_CFG_HOST_CDC*3,
 | 
			
		||||
 | 
			
		||||
  HCD_MAX_XFER     = HCD_MAX_ENDPOINT*2,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
// MACRO CONSTANT TYPEDEF
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
 
 | 
			
		||||
@@ -371,7 +371,7 @@ static inline ohci_ed_t * ed_from_pipe_handle(pipe_handle_t pipe_hdl)
 | 
			
		||||
static inline ohci_ed_t * ed_find_free(uint8_t dev_addr) ATTR_PURE ATTR_ALWAYS_INLINE;
 | 
			
		||||
static inline ohci_ed_t * ed_find_free(uint8_t dev_addr)
 | 
			
		||||
{
 | 
			
		||||
  for(uint8_t i = 0; i < OHCI_MAX_QHD; i++)
 | 
			
		||||
  for(uint8_t i = 0; i < HCD_MAX_ENDPOINT; i++)
 | 
			
		||||
  {
 | 
			
		||||
    if ( !ohci_data.device[dev_addr-1].ed[i].used )
 | 
			
		||||
    {
 | 
			
		||||
@@ -384,7 +384,7 @@ static inline ohci_ed_t * ed_find_free(uint8_t dev_addr)
 | 
			
		||||
 | 
			
		||||
static ohci_ed_t * ed_list_find_previous(ohci_ed_t const * p_head, ohci_ed_t const * p_ed)
 | 
			
		||||
{
 | 
			
		||||
  uint32_t max_loop = OHCI_MAX_QHD;
 | 
			
		||||
  uint32_t max_loop = HCD_MAX_ENDPOINT;
 | 
			
		||||
 | 
			
		||||
  ohci_ed_t const * p_prev = p_head;
 | 
			
		||||
 | 
			
		||||
@@ -444,7 +444,7 @@ pipe_handle_t hcd_pipe_open(uint8_t dev_addr, tusb_descriptor_endpoint_t const *
 | 
			
		||||
 | 
			
		||||
static ohci_gtd_t * gtd_find_free(uint8_t dev_addr)
 | 
			
		||||
{
 | 
			
		||||
  for(uint8_t i=0; i < OHCI_MAX_QTD; i++)
 | 
			
		||||
  for(uint8_t i=0; i < HCD_MAX_XFER; i++)
 | 
			
		||||
  {
 | 
			
		||||
    if (!ohci_data.device[dev_addr-1].gtd[i].used)
 | 
			
		||||
    {
 | 
			
		||||
@@ -608,7 +608,7 @@ static inline uint32_t gtd_xfer_byte_left(uint32_t buffer_end, uint32_t current_
 | 
			
		||||
 | 
			
		||||
static void done_queue_isr(uint8_t hostid)
 | 
			
		||||
{
 | 
			
		||||
  uint8_t max_loop = (TUSB_CFG_HOST_DEVICE_MAX+1)*(OHCI_MAX_QTD+OHCI_MAX_ITD);
 | 
			
		||||
  uint8_t max_loop = (TUSB_CFG_HOST_DEVICE_MAX+1)*(HCD_MAX_XFER+OHCI_MAX_ITD);
 | 
			
		||||
 | 
			
		||||
  // done head is written in reversed order of completion --> need to reverse the done queue first
 | 
			
		||||
  ohci_td_item_t* td_head = list_reverse ( (ohci_td_item_t*) align16(ohci_data.hcca.done_head) );
 | 
			
		||||
 
 | 
			
		||||
@@ -58,9 +58,9 @@
 | 
			
		||||
#define OHCI_PERIODIC_LIST (defined HOST_HCD_XFER_INTERRUPT || defined HOST_HCD_XFER_ISOCHRONOUS)
 | 
			
		||||
 | 
			
		||||
// TODO merge OHCI with EHCI
 | 
			
		||||
#define OHCI_MAX_QHD  8
 | 
			
		||||
#define OHCI_MAX_QTD  20
 | 
			
		||||
#define OHCI_MAX_ITD  4
 | 
			
		||||
enum {
 | 
			
		||||
  OHCI_MAX_ITD = 4
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
  OHCI_PID_SETUP = 0,
 | 
			
		||||
@@ -195,8 +195,8 @@ typedef struct ATTR_ALIGNED(256) {
 | 
			
		||||
 | 
			
		||||
  struct {
 | 
			
		||||
    //  ochi_itd_t itd[OHCI_MAX_ITD]; // itd requires alignment of 32
 | 
			
		||||
    ohci_ed_t ed[OHCI_MAX_QHD];
 | 
			
		||||
    ohci_gtd_t gtd[OHCI_MAX_QTD];
 | 
			
		||||
    ohci_ed_t ed[HCD_MAX_ENDPOINT];
 | 
			
		||||
    ohci_gtd_t gtd[HCD_MAX_XFER];
 | 
			
		||||
  }device[TUSB_CFG_HOST_DEVICE_MAX];
 | 
			
		||||
 | 
			
		||||
} ohci_data_t;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user