ehci struct rename

This commit is contained in:
hathach 2018-12-11 12:57:30 +07:00
parent b0717275c8
commit b8c63ff624
No known key found for this signature in database
GPG Key ID: 2FA891220FBFD581
2 changed files with 191 additions and 200 deletions

View File

@ -118,24 +118,24 @@ void hcd_port_reset(uint8_t hostid)
{
ehci_registers_t* regs = ehci_data.regs;
regs->portsc_bit.port_enable = 0; // disable port before reset
regs->portsc_bit.port_reset = 1;
regs->portsc_bm.port_enabled = 0; // disable port before reset
regs->portsc_bm.port_reset = 1;
}
bool hcd_port_connect_status(uint8_t hostid)
{
return ehci_data.regs->portsc_bit.current_connect_status;
return ehci_data.regs->portsc_bm.current_connect_status;
}
tusb_speed_t hcd_port_speed_get(uint8_t hostid)
{
return (tusb_speed_t) ehci_data.regs->portsc_bit.nxp_port_speed; // NXP specific port speed
return (tusb_speed_t) ehci_data.regs->portsc_bm.nxp_port_speed; // NXP specific port speed
}
// TODO refractor abtract later
void hcd_device_remove(uint8_t rhport, uint8_t dev_addr)
{
ehci_data.regs->usb_cmd_bit.advance_async = 1; // Async doorbell check EHCI 4.8.2 for operational details
ehci_data.regs->command_bm.async_adv_doorbell = 1; // Async doorbell check EHCI 4.8.2 for operational details
}
//--------------------------------------------------------------------+
@ -149,10 +149,10 @@ static bool ehci_init(uint8_t hostid)
//------------- CTRLDSSEGMENT Register (skip) -------------//
//------------- USB INT Register -------------//
regs->usb_int_enable = 0; // 1. disable all the interrupt
regs->usb_sts = EHCI_INT_MASK_ALL; // 2. clear all status
regs->inten = 0; // 1. disable all the interrupt
regs->status = EHCI_INT_MASK_ALL; // 2. clear all status
regs->usb_int_enable = EHCI_INT_MASK_ERROR | EHCI_INT_MASK_PORT_CHANGE |
regs->inten = EHCI_INT_MASK_ERROR | EHCI_INT_MASK_PORT_CHANGE |
EHCI_INT_MASK_NXP_PERIODIC |
EHCI_INT_MASK_ASYNC_ADVANCE | EHCI_INT_MASK_NXP_ASYNC;
@ -166,14 +166,14 @@ static bool ehci_init(uint8_t hostid)
async_head->qtd_overlay.halted = 1; // inactive most of time
async_head->qtd_overlay.next.terminate = 1; // TODO removed if verified
regs->async_list_base = (uint32_t) async_head;
regs->async_list_addr = (uint32_t) async_head;
//------------- Periodic List -------------//
// Build the polling interval tree with 1 ms, 2 ms, 4 ms and 8 ms (framesize) only
for(uint32_t i=0; i<4; i++)
{
ehci_data.period_head_arr[i].interrupt_smask = 1; // queue head in period list must have smask non-zero
ehci_data.period_head_arr[i].int_smask = 1; // queue head in period list must have smask non-zero
ehci_data.period_head_arr[i].qtd_overlay.halted = 1; // dummy node, always inactive
}
@ -208,16 +208,16 @@ static bool ehci_init(uint8_t hostid)
regs->periodic_list_base = (uint32_t) framelist;
//------------- TT Control (NXP only) -------------//
regs->tt_control = 0;
regs->nxp_tt_control = 0;
//------------- USB CMD Register -------------//
regs->usb_cmd |= BIT_(EHCI_USBCMD_POS_RUN_STOP) | BIT_(EHCI_USBCMD_POS_ASYNC_ENABLE)
regs->command |= BIT_(EHCI_USBCMD_POS_RUN_STOP) | BIT_(EHCI_USBCMD_POS_ASYNC_ENABLE)
| BIT_(EHCI_USBCMD_POS_PERIOD_ENABLE) // TODO enable period list only there is int/iso endpoint
| ((EHCI_CFG_FRAMELIST_SIZE_BITS & BIN8(011)) << EHCI_USBCMD_POS_FRAMELIST_SZIE)
| ((EHCI_CFG_FRAMELIST_SIZE_BITS >> 2) << EHCI_USBCMD_POS_NXP_FRAMELIST_SIZE_MSB);
//------------- ConfigFlag Register (skip) -------------//
regs->portsc_bit.port_power = 1; // enable port power
regs->portsc_bm.port_power = 1; // enable port power
return true;
}
@ -226,11 +226,11 @@ static tusb_error_t hcd_controller_stop(uint8_t hostid)
{
ehci_registers_t* regs = ehci_data.regs;
regs->usb_cmd_bit.run_stop = 0;
regs->command_bm.run_stop = 0;
tu_timeout_t timeout;
tu_timeout_set(&timeout, 2); // USB Spec: controller has to stop within 16 uframe = 2 frames
while( regs->usb_sts_bit.hc_halted == 0 && !tu_timeout_expired(&timeout)) {}
while( regs->status_bm.hc_halted == 0 && !tu_timeout_expired(&timeout)) {}
return tu_timeout_expired(&timeout) ? TUSB_ERROR_OSAL_TIMEOUT : TUSB_ERROR_NONE;
}
@ -530,7 +530,7 @@ static void async_advance_isr(ehci_qhd_t * const async_head)
for (uint8_t i=0; i<HCD_MAX_ENDPOINT; i++) // free all qhd
{
if (ehci_data.qhd_pool[i].device_address == dev_addr)
if (ehci_data.qhd_pool[i].dev_addr == dev_addr)
{
ehci_data.qhd_pool[i].used = 0;
ehci_data.qhd_pool[i].is_removing = 0;
@ -549,7 +549,7 @@ static void async_advance_isr(ehci_qhd_t * const async_head)
static void port_connect_status_change_isr(uint8_t hostid)
{
// NOTE There is an sequence plug->unplug->…..-> plug if device is powering with pre-plugged device
if (ehci_data.regs->portsc_bit.current_connect_status)
if (ehci_data.regs->portsc_bm.current_connect_status)
{
hcd_port_reset(hostid);
hcd_event_device_attach(hostid);
@ -575,7 +575,7 @@ static void qhd_xfer_complete_isr(ehci_qhd_t * p_qhd)
{
// end of request
// call USBH callback
hcd_event_xfer_complete(p_qhd->device_address, edpt_addr(p_qhd->endpoint_number, p_qhd->pid_non_control == EHCI_PID_IN ? 1 : 0), XFER_RESULT_SUCCESS, p_qhd->total_xferred_bytes);
hcd_event_xfer_complete(p_qhd->dev_addr, edpt_addr(p_qhd->ep_number, p_qhd->pid_non_control == EHCI_PID_IN ? 1 : 0), XFER_RESULT_SUCCESS, p_qhd->total_xferred_bytes);
p_qhd->total_xferred_bytes = 0;
}
}
@ -634,7 +634,7 @@ static void period_list_xfer_complete_isr(uint8_t hostid, uint8_t interval_ms)
static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd)
{
if ( (p_qhd->device_address != 0 && p_qhd->qtd_overlay.halted) || // addr0 cannot be protocol STALL
if ( (p_qhd->dev_addr != 0 && p_qhd->qtd_overlay.halted) || // addr0 cannot be protocol STALL
qhd_has_xact_error(p_qhd) )
{ // current qhd has error in transaction
tusb_xfer_type_t const xfer_type = qhd_get_xfer_type(p_qhd);
@ -650,7 +650,7 @@ static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd)
p_qhd->p_qtd_list_head->used = 0; // free QTD
qtd_remove_1st_from_qhd(p_qhd);
if ( 0 == p_qhd->endpoint_number )
if ( 0 == p_qhd->ep_number )
{
// control cannot be halted --> clear all qtd list
p_qhd->p_qtd_list_head = NULL;
@ -660,12 +660,12 @@ static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd)
p_qhd->qtd_overlay.alternate.terminate = 1;
p_qhd->qtd_overlay.halted = 0;
ehci_qtd_t *p_setup = get_control_qtds(p_qhd->device_address);
ehci_qtd_t *p_setup = get_control_qtds(p_qhd->dev_addr);
p_setup->used = 0;
}
// call USBH callback
hcd_event_xfer_complete(p_qhd->device_address, edpt_addr(p_qhd->endpoint_number, p_qhd->pid_non_control == EHCI_PID_IN ? 1 : 0), error_event, p_qhd->total_xferred_bytes);
hcd_event_xfer_complete(p_qhd->dev_addr, edpt_addr(p_qhd->ep_number, p_qhd->pid_non_control == EHCI_PID_IN ? 1 : 0), error_event, p_qhd->total_xferred_bytes);
p_qhd->total_xferred_bytes = 0;
}
@ -723,10 +723,10 @@ void hal_hcd_isr(uint8_t hostid)
{
ehci_registers_t* regs = ehci_data.regs;
uint32_t int_status = regs->usb_sts;
int_status &= regs->usb_int_enable;
uint32_t int_status = regs->status;
int_status &= regs->inten;
regs->usb_sts |= int_status; // Acknowledge handled interrupt
regs->status |= int_status; // Acknowledge handled interrupt
if (int_status == 0) return;
@ -734,7 +734,7 @@ void hal_hcd_isr(uint8_t hostid)
{
uint32_t port_status = regs->portsc & EHCI_PORTSC_MASK_ALL;
if (regs->portsc_bit.connect_status_change)
if (regs->portsc_bm.connect_status_change)
{
port_connect_status_change_isr(hostid);
}
@ -808,8 +808,8 @@ static inline ehci_qhd_t* qhd_find_free (void)
static inline tusb_xfer_type_t qhd_get_xfer_type(ehci_qhd_t const * p_qhd)
{
return ( p_qhd->endpoint_number == 0 ) ? TUSB_XFER_CONTROL :
( p_qhd->interrupt_smask != 0 ) ? TUSB_XFER_INTERRUPT : TUSB_XFER_BULK;
return ( p_qhd->ep_number == 0 ) ? TUSB_XFER_CONTROL :
( p_qhd->int_smask != 0 ) ? TUSB_XFER_INTERRUPT : TUSB_XFER_BULK;
}
static inline ehci_qhd_t* qhd_next(ehci_qhd_t const * p_qhd)
@ -823,8 +823,8 @@ static inline ehci_qhd_t* qhd_get_from_addr(uint8_t dev_addr, uint8_t ep_addr)
for(uint32_t i=0; i<HCD_MAX_ENDPOINT; i++)
{
if ( (qhd_pool[i].device_address == dev_addr) &&
ep_addr == edpt_addr(qhd_pool[i].endpoint_number, qhd_pool[i].pid_non_control) )
if ( (qhd_pool[i].dev_addr == dev_addr) &&
ep_addr == edpt_addr(qhd_pool[i].ep_number, qhd_pool[i].pid_non_control) )
{
return &qhd_pool[i];
}
@ -883,49 +883,49 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c
uint8_t const xfer_type = ep_desc->bmAttributes.xfer;
uint8_t const interval = ep_desc->bInterval;
p_qhd->device_address = dev_addr;
p_qhd->non_hs_period_inactive_next_xact = 0;
p_qhd->endpoint_number = edpt_number(ep_desc->bEndpointAddress);
p_qhd->endpoint_speed = _usbh_devices[dev_addr].speed;
p_qhd->data_toggle_control = (xfer_type == TUSB_XFER_CONTROL) ? 1 : 0;
p_qhd->head_list_flag = (dev_addr == 0) ? 1 : 0; // addr0's endpoint is the static asyn list head
p_qhd->max_package_size = ep_desc->wMaxPacketSize.size;
p_qhd->non_hs_control_endpoint = ((xfer_type == TUSB_XFER_CONTROL) && (p_qhd->endpoint_speed != TUSB_SPEED_HIGH)) ? 1 : 0;
p_qhd->nak_count_reload = 0;
p_qhd->dev_addr = dev_addr;
p_qhd->inactive_next_xact = 0;
p_qhd->ep_number = edpt_number(ep_desc->bEndpointAddress);
p_qhd->ep_speed = _usbh_devices[dev_addr].speed;
p_qhd->data_toggle = (xfer_type == TUSB_XFER_CONTROL) ? 1 : 0;
p_qhd->head_list_flag = (dev_addr == 0) ? 1 : 0; // addr0's endpoint is the static asyn list head
p_qhd->max_packet_size = ep_desc->wMaxPacketSize.size;
p_qhd->fl_ctrl_ep_flag = ((xfer_type == TUSB_XFER_CONTROL) && (p_qhd->ep_speed != TUSB_SPEED_HIGH)) ? 1 : 0;
p_qhd->nak_reload = 0;
// Bulk/Control -> smask = cmask = 0
// TODO Isochronous
if (TUSB_XFER_INTERRUPT == xfer_type)
{
if (TUSB_SPEED_HIGH == p_qhd->endpoint_speed)
if (TUSB_SPEED_HIGH == p_qhd->ep_speed)
{
TU_ASSERT( interval <= 16, );
if ( interval < 4) // sub milisecond interval
{
p_qhd->interval_ms = 0;
p_qhd->interrupt_smask = (interval == 1) ? BIN8(11111111) :
(interval == 2) ? BIN8(10101010) : BIN8(01000100);
p_qhd->interval_ms = 0;
p_qhd->int_smask = (interval == 1) ? BIN8(11111111) :
(interval == 2) ? BIN8(10101010) : BIN8(01000100);
}else
{
p_qhd->interval_ms = (uint8_t) tu_min16( 1 << (interval-4), 255 );
p_qhd->interrupt_smask = BIT_(interval % 8);
p_qhd->interval_ms = (uint8_t) tu_min16( 1 << (interval-4), 255 );
p_qhd->int_smask = BIT_(interval % 8);
}
}else
{
TU_ASSERT( 0 != interval, );
// Full/Low: 4.12.2.1 (EHCI) case 1 schedule start split at 1 us & complete split at 2,3,4 uframes
p_qhd->interrupt_smask = 0x01;
p_qhd->non_hs_interrupt_cmask = BIN8(11100);
p_qhd->interval_ms = interval;
p_qhd->int_smask = 0x01;
p_qhd->fl_int_cmask = BIN8(11100);
p_qhd->interval_ms = interval;
}
}else
{
p_qhd->interrupt_smask = p_qhd->non_hs_interrupt_cmask = 0;
p_qhd->int_smask = p_qhd->fl_int_cmask = 0;
}
p_qhd->hub_address = _usbh_devices[dev_addr].hub_addr;
p_qhd->hub_port = _usbh_devices[dev_addr].hub_port;
p_qhd->mult = 1; // TODO not use high bandwidth/park mode yet
p_qhd->fl_hub_addr = _usbh_devices[dev_addr].hub_addr;
p_qhd->fl_hub_port = _usbh_devices[dev_addr].hub_port;
p_qhd->mult = 1; // TODO not use high bandwidth/park mode yet
//------------- HCD Management Data -------------//
p_qhd->used = 1;
@ -939,9 +939,9 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c
p_qhd->qtd_overlay.halted = 0;
p_qhd->qtd_overlay.next.terminate = 1;
p_qhd->qtd_overlay.alternate.terminate = 1;
if (TUSB_XFER_BULK == xfer_type && p_qhd->endpoint_speed == TUSB_SPEED_HIGH && p_qhd->pid_non_control == EHCI_PID_OUT)
if (TUSB_XFER_BULK == xfer_type && p_qhd->ep_speed == TUSB_SPEED_HIGH && p_qhd->pid_non_control == EHCI_PID_OUT)
{
p_qhd->qtd_overlay.pingstate_err = 1; // do PING for Highspeed Bulk OUT, EHCI section 4.11
p_qhd->qtd_overlay.ping_err = 1; // do PING for Highspeed Bulk OUT, EHCI section 4.11
}
}
@ -954,12 +954,12 @@ static void qtd_init(ehci_qtd_t* p_qtd, uint32_t data_ptr, uint16_t total_bytes)
p_qtd->next.terminate = 1; // init to null
p_qtd->alternate.terminate = 1; // not used, always set to terminated
p_qtd->active = 1;
p_qtd->cerr = 3; // TODO 3 consecutive errors tolerance
p_qtd->err_count = 3; // TODO 3 consecutive errors tolerance
p_qtd->data_toggle = 0;
p_qtd->total_bytes = total_bytes;
p_qtd->expected_bytes = total_bytes;
p_qtd->buffer[0] = data_ptr;
p_qtd->buffer[0] = data_ptr;
for(uint8_t i=1; i<5; i++)
{
p_qtd->buffer[i] |= tu_align4k( p_qtd->buffer[i-1] ) + 4096;

View File

@ -57,8 +57,6 @@
* SITD: Split ISO Transfer Descriptor for full-speed
* SMASK: Start Split mask for Slipt Transaction
* CMASK: Complete Split mask for Slipt Transaction
* RO: Read Only
* R/WC: Read, Write to Clear
*/
#ifdef __cplusplus
@ -106,13 +104,14 @@ typedef union {
};
}ehci_link_t;
/// Queue Element Transfer Descriptor (section 3.5)
typedef struct {
/// Word 0: Next QTD Pointer
/// Queue Element Transfer Descriptor
/// Qtd is used to declare overlay in ehci_qhd_t -> cannot be declared with ATTR_ALIGNED(32)
typedef struct
{
// Word 0: Next QTD Pointer
ehci_link_t next;
/// Word 1: Alternate Next QTD Pointer (not used)
// Word 1: Alternate Next QTD Pointer (not used)
union{
ehci_link_t alternate;
struct {
@ -123,63 +122,58 @@ typedef struct {
};
};
/// Word 2: qTQ Token
volatile uint32_t pingstate_err : 1 ; ///< If the QH.EPSfield indicates a High-speed device and the PID_Codeindicates an OUT endpoint, then this is the state bit for the Ping protocol. 0b=OUT 1b=PING
volatile uint32_t non_hs_split_state : 1 ; ///< This bit is ignored by the host controller unless the QH.EPSfield indicates a full- or low-speed endpoint. When a Full- or Low-speed device, the host controller uses this bit to track the state of the split-transaction. The functional requirements of the host controller for managing this state bit and the split transaction protocol depends on whether the endpoint is in the periodic or asynchronous schedule. 0b=Start Split 1b=Complete Split
volatile uint32_t non_hs_period_missed_uframe : 1 ; ///< This bit is ignored unless the QH.EPSfield indicates a full- or low-speed endpoint and the queue head is in the periodic list. This bit is set when the host controller detected that a host-induced hold-off caused the host controller to miss a required complete-split transaction. If the host controller sets this bit to a one, then it remains a one for the duration of the transfer.
volatile uint32_t xact_err : 1 ; ///< Set to a one by the Host Controller during status update in the case where the host did not receive a valid response from the device (Timeout, CRC, Bad PID, etc.)
volatile uint32_t babble_err : 1 ; ///< Set to a 1 by the Host Controller during status update when a babble is detected during the transaction. In addition to setting this bit, the Host Controller also sets the Haltedbit to a 1
volatile uint32_t buffer_err : 1 ; ///< Set to a 1 by the Host Controller during status update to indicate that the Host Controller is unable to keep up with the reception of incoming data (overrun) or is unable to supply data fast enough during transmission (underrun)
volatile uint32_t halted : 1 ; ///< Set to a 1 by the Host Controller during status updates to indicate that a serious error has occurred at the device/endpoint addressed by this qTD. This can be caused by babble, the error counter counting down to zero, or reception of the STALL handshake from the device during a transaction. Any time that a transaction results in the Halted bit being set to a one, the Active bit is also set to 0
volatile uint32_t active : 1 ; ///< Set to 1 by software to enable the execution of transactions by the Host Controller
// Word 2: qTQ Token
volatile uint32_t ping_err : 1 ; ///< For Highspeed: 0 Out, 1 Ping. Full/Slow used as error indicator
volatile uint32_t non_hs_split_state : 1 ; ///< Used by HC to track the state of slipt transaction
volatile uint32_t non_hs_missed_uframe : 1 ; ///< HC misses a complete slip transaction
volatile uint32_t xact_err : 1 ; ///< Error (Timeout, CRC, Bad PID ... )
volatile uint32_t babble_err : 1 ; ///< Babble detected, also set Halted bit to 1
volatile uint32_t buffer_err : 1 ; ///< Data overrun/underrun error
volatile uint32_t halted : 1 ; ///< Serious error or STALL received
volatile uint32_t active : 1 ; ///< Start transfer, clear by HC when complete
uint32_t pid : 2 ; ///< This field is an encoding of the token which should be used for transactions associated with this transfer descriptor. 00=OUT 01=IN 10=SETUP
volatile uint32_t cerr : 2 ; ///< Error Counter, This field is a 2-bit down counter that keeps track of the number of consecutive Errors detected while executing this qTD
volatile uint32_t current_page : 3 ; ///< This field is used as an index into the qTD buffer pointer list
uint32_t int_on_complete : 1 ; ///< If this bit is set to a one, it specifies that when this qTD is completed, the Host Controller should issue an interrupt at the next interrupt threshold
uint32_t pid : 2 ; ///< 0: OUT, 1: IN, 2 Setup
volatile uint32_t err_count : 2 ; ///< Error Counter of consecutive errors
volatile uint32_t current_page : 3 ; ///< Index into the qTD buffer pointer list
uint32_t int_on_complete : 1 ; ///< Interrupt on complete
volatile uint32_t total_bytes : 15 ; ///< Transfer bytes, decreased during transaction
volatile uint32_t data_toggle : 1 ; ///< Data Toogle bit
volatile uint32_t total_bytes : 15 ; ///< This field specifies the total number of bytes to be moved with this transfer descriptor
volatile uint32_t data_toggle : 1 ; ///< This is the data toggle sequence bit
uint32_t : 0 ; // padding to the end of current storage unit
// End of Word 2
/// Buffer Page Pointer List, Each element in the list is a 4K page aligned, physical memory address. The lower 12 bits in each pointer are reserved (except for the first one) as each memory pointer must reference the start of a 4K page
uint32_t buffer[5];
} ehci_qtd_t; // XXX qtd is used to declare overlay in ehci_qhd_t -> cannot be declared with ATTR_ALIGNED(32)
} ehci_qtd_t;
TU_VERIFY_STATIC( sizeof(ehci_qtd_t) == 32, "size is not correct" );
/// Queue Head (section 3.6)
typedef struct ATTR_ALIGNED(32) {
/// Word 0: Queue Head Horizontal Link Pointer
/// Queue Head
typedef struct ATTR_ALIGNED(32)
{
// Word 0: Next QHD
ehci_link_t next;
/// Word 1 : Endpoint Characteristics
uint32_t device_address : 7 ; ///< This field selects the specific device serving as the data source or sink
uint32_t non_hs_period_inactive_next_xact : 1 ; ///< This bit is used by system software to request that the host controller set the Active bit to zero. See Section 4.12.2.5 for full operational details
uint32_t endpoint_number : 4 ; ///< This 4-bit field selects the particular endpoint number on the device serving as the data source or sink.
uint32_t endpoint_speed : 2 ; ///< This is the speed of the associated endpoint 00b=Full 01b=Low 10b=High 11b=Reserved
uint32_t data_toggle_control : 1 ; ///< This bit specifies where the host controller should get the initial data toggle on an overlay transition. 0b=Ignore DT bit of qTD, 1b=Use DT bit of qTD
uint32_t head_list_flag : 1 ; ///< This bit is set by System Software to mark a queue head as being the head of the reclamation list. See Section 4.8 for operational model
uint32_t max_package_size : 11 ; ///< This directly corresponds to the maximum packet size of the associated endpoint (wMaxPacketSize)
uint32_t non_hs_control_endpoint : 1 ; ///< If the QH.EPSfield indicates the endpoint is not a high-speed device, and the endpoint is an control endpoint, then software must set this bit to a one. Otherwise it should always set this bit to a zero.
uint32_t nak_count_reload : 4 ; ///< This field contains a value, which is used by the host controller to reload the Nak Counter field.
uint32_t : 0 ; // padding to the end of current storage unit
// End of Word 1
// Word 1: Endpoint Characteristics
uint32_t dev_addr : 7 ; ///< device address
uint32_t inactive_next_xact : 1 ; ///< request HC to set the Active bit to zero (only valid for Periodic with Full/Slow speed)
uint32_t ep_number : 4 ; ///< EP number
uint32_t ep_speed : 2 ; ///< 0: Full, 1: Low, 2: High
uint32_t data_toggle : 1 ; ///< 0: use DT in qHD, 1: use DT in qTD
uint32_t head_list_flag : 1 ; ///< Head of the queue
uint32_t max_packet_size : 11 ; ///< Max packet size
uint32_t fl_ctrl_ep_flag : 1 ; ///< 1 if is Full/Low speed control endpoint
uint32_t nak_reload : 4 ; ///< Used by HC
/// Word 2 : Endpoint Capabilities
uint32_t interrupt_smask : 8 ; ///< This field is used for all endpoint speeds. Software should set this field to a zero when the queue head is on the asynchronous schedule. A non-zero value in this field indicates an interrupt endpoint
uint32_t non_hs_interrupt_cmask : 8 ; ///< This field is ignored by the host controller unless the EPSfield indicates this device is a low- or full-speed device and this queue head is in the periodic list. This field (along with the Activeand SplitX-statefields) is used to determine during which micro-frames the host controller should execute a complete-split transaction
uint32_t hub_address : 7 ; ///< This field is ignored by the host controller unless the EPSfield indicates a full- or low-speed device. The value is the USB device address of the USB 2.0 Hub below which the full- or low-speed device associated with this endpoint is attached. This field is used in the split-transaction protocol. See Section 4.12.
uint32_t hub_port : 7 ; ///< This field is ignored by the host controller unless the EPSfield indicates a full- or low-speed device. The value is the port number identifier on the USB 2.0 Hub (for hub at device address Hub Addrbelow), below which the full- or low-speed device associated with this endpoint is attached. This information is used in the split-transaction protocol. See Section 4.12.
uint32_t mult : 2 ; ///< This field is a multiplier used to key the host controller as the number of successive packets the host controller may submit to the endpoint in the current execution. 00b=Reserved 01b,10b,11b= 1 (2, 3) Transaction for this endpoint/micro frame
uint32_t : 0 ; // padding to the end of current storage unit
// End of Word 2
// Word 2: Endpoint Capabilities
uint32_t int_smask : 8 ; ///< Interrupt Schedule Mask
uint32_t fl_int_cmask : 8 ; ///< Split Completion Mask for Full/Slow speed
uint32_t fl_hub_addr : 7 ; ///< Hub Address for Full/Slow speed
uint32_t fl_hub_port : 7 ; ///< Hub Port for Full/Slow speed
uint32_t mult : 2 ; ///< Transaction per micro frame
/// Word 3: Current qTD Pointer
// Word 3: Current qTD Pointer
volatile uint32_t qtd_addr;
/// Word 4-11: Transfer Overlay
// Word 4-11: Transfer Overlay
volatile ehci_qtd_t qtd_overlay;
//--------------------------------------------------------------------+
@ -203,10 +197,10 @@ TU_VERIFY_STATIC( sizeof(ehci_qhd_t) == 64, "size is not correct" );
/// Highspeed Isochronous Transfer Descriptor (section 3.3)
typedef struct ATTR_ALIGNED(32) {
/// Word 0: Next Link Pointer
// Word 0: Next Link Pointer
ehci_link_t next;
/// Word 1-8: iTD Transaction Status and Control List
// Word 1-8: iTD Transaction Status and Control List
struct {
// iTD Control
volatile uint32_t offset : 12 ; ///< This field is a value that is an offset, expressed in bytes, from the beginning of a buffer.
@ -221,7 +215,7 @@ typedef struct ATTR_ALIGNED(32) {
volatile uint32_t active : 1 ; ///< Set to 1 by software to enable the execution of an isochronous transaction by the Host Controller
} xact[8];
///Word 9-15 Buffer Page Pointer List (Plus)
// Word 9-15 Buffer Page Pointer List (Plus)
uint32_t BufferPointer[7];
// // FIXME: Store meta data into buffer pointer reserved for saving memory
@ -235,28 +229,26 @@ TU_VERIFY_STATIC( sizeof(ehci_itd_t) == 64, "size is not correct" );
/// Split (Full-Speed) Isochronous Transfer Descriptor
typedef struct ATTR_ALIGNED(32) {
/// Word 0: Next Link Pointer
// Word 0: Next Link Pointer
ehci_link_t next;
/// Word 1: siTD Endpoint Characteristics
uint32_t device_address : 7; ///< This field selects the specific device serving as the data source or sink.
uint32_t : 1; ///< reserved
uint32_t endpoint_number : 4; ///< This 4-bit field selects the particular endpoint number on the device serving as the data source or sink.
uint32_t : 4; ///< This field is reserved and should be set to zero.
uint32_t hub_address : 7; ///< This field holds the device address of the transaction translators hub.
uint32_t : 1; ///< reserved
uint32_t port_number : 7; ///< This field is the port number of the recipient transaction translator.
uint32_t direction : 1; ///< 0 = OUT; 1 = IN. This field encodes whether the full-speed transaction should be an IN or OUT.
uint32_t : 0; // padding to the end of current storage unit
// End of Word 1
// Word 1: siTD Endpoint Characteristics
uint32_t dev_addr : 7; ///< This field selects the specific device serving as the data source or sink.
uint32_t : 1; ///< reserved
uint32_t ep_number : 4; ///< This 4-bit field selects the particular endpoint number on the device serving as the data source or sink.
uint32_t : 4; ///< This field is reserved and should be set to zero.
uint32_t hub_addr : 7; ///< This field holds the device address of the transaction translators hub.
uint32_t : 1; ///< reserved
uint32_t port_number : 7; ///< This field is the port number of the recipient transaction translator.
uint32_t direction : 1; ///< 0 = OUT; 1 = IN. This field encodes whether the full-speed transaction should be an IN or OUT.
uint32_t : 0; // padding to the end of current storage unit
/// Word 2: Micro-frame Schedule Control
uint8_t interrupt_smask ; ///< This field (along with the Activeand SplitX-statefields in the Statusbyte) are used to determine during which micro-frames the host controller should execute complete-split transactions
uint8_t non_hs_interrupt_cmask ; ///< This field (along with the Activeand SplitX-statefields in the Statusbyte) are used to determine during which micro-frames the host controller should execute start-split transactions.
// Word 2: Micro-frame Schedule Control
uint8_t int_smask ; ///< This field (along with the Activeand SplitX-statefields in the Statusbyte) are used to determine during which micro-frames the host controller should execute complete-split transactions
uint8_t fl_int_cmask; ///< This field (along with the Activeand SplitX-statefields in the Statusbyte) are used to determine during which micro-frames the host controller should execute start-split transactions.
uint16_t reserved ; ///< reserved
// End of Word 2
/// Word 3: siTD Transfer Status and Control
// Word 3: siTD Transfer Status and Control
// Status [7:0] TODO indentical to qTD Token'status --> refractor later
volatile uint32_t : 1 ; // reserved
volatile uint32_t split_state : 1 ;
@ -273,7 +265,6 @@ typedef struct ATTR_ALIGNED(32) {
volatile uint32_t page_select : 1 ; ///< Used to indicate which data page pointer should be concatenated with the CurrentOffsetfield to construct a data buffer pointer
uint32_t int_on_complete : 1 ; ///< Do not interrupt when transaction is complete. 1 = Do interrupt when transaction is complete
uint32_t : 0 ; // padding to the end of current storage unit
// End of Word 3
/// Word 4-5: Buffer Pointer List
uint32_t buffer[2]; // buffer[1] TP: Transaction Position - T-Count: Transaction Count
@ -342,103 +333,103 @@ enum ehci_portsc_change_mask_{
typedef volatile struct {
union {
uint32_t usb_cmd ; ///< The Command Register indicates the command to be executed by the serial bus host controller. Writing to the register causes a command to be executed
uint32_t command;
struct {
uint32_t run_stop : 1 ; ///< Default 0b. 1=Run. 0=Stop. When set to a 1, the Host Controller proceeds with execution of the schedule. The Host Controller continues execution as long as this bit is set to a 1. When this bit is set to 0, the Host Controller completes the current and any actively pipelined transactions on the USB and then halts. The Host Controller must halt within 16 micro-frames after software clears the Run bit. The HC Halted bit in the status register indicates when the Host Controller has finished its pending pipelined transactions and has entered the stopped state. Software must not write a one to this field unless the host controller is in the Halted state (i.e. HCHaltedin the USBSTS register is a one). Doing so will yield undefined results.
uint32_t reset : 1 ; ///< his control bit is used by software to reset the host controller. The effects of this on Root Hub registers are similar to a Chip Hardware Reset. When software writes a one to this bit, the Host Controller resets its internal pipelines, timers, counters, state machines, etc. to their initial value. Any transaction currently in progress on USB is immediately terminated. A USB reset is not driven on downstream ports.This bit is set to zero by the Host Controller when the reset process is complete. Software cannot terminate the reset process early by writing a zero to this register. Software should not set this bit to a one when the HCHaltedbit in the USBSTS register is a zero. Attempting to reset an actively running host controller will result in undefined behavior.
uint32_t framelist_size : 2 ; ///< This field is R/W only if Programmable Frame List Flagin the HCCPARAMS registers is set to a one. This field specifies the size of the frame list.00b 1024 elements (4096 bytes) Default value 01b 512 elements (2048 bytes) 10b 256 elements (1024 bytes)
uint32_t run_stop : 1 ; ///< 1=Run. 0=Stop
uint32_t reset : 1 ; ///< SW write 1 to reset HC, clear by HC when complete
uint32_t framelist_size : 2 ; ///< Frame List size 0: 1024, 1: 512, 2: 256
uint32_t periodic_enable : 1 ; ///< This bit controls whether the host controller skips processing the Periodic Schedule. Values mean: 0b Do not process the Periodic Schedule 1b Use the PERIODICLISTBASE register to access the Periodic Schedule.
uint32_t async_enable : 1 ; ///< This bit controls whether the host controller skips processing the Asynchronous Schedule. Values mean: 0b Do not process the Asynchronous Schedule 1b Use the ASYNCLISTADDR register to access the Asynchronous Schedule.
uint32_t advance_async : 1 ; ///< This bit is used as a doorbell by software to tell the host controller to issue an interrupt the next time it advances asynchronous schedule. Software must write a 1 to this bit to ringthe doorbell. When the host controller has evicted all appropriate cached schedule state, it sets the Interrupt on Async Advancestatus bit in the USBSTS register. If the Interrupt on Async Advance Enablebit in the USBINTR register is a one then the host controller will assert an interrupt at the next interrupt threshold. See Section 4.8.2 for operational details. The host controller sets this bit to a zero after it has set the Interrupt on Async Advance status bit in the USBSTS register to a one. Software should not write a one to this bit when the asynchronous schedule is disabled. Doing so will yield undefined results.
uint32_t light_reset : 1 ; ///< This control bit is not required. If implemented, it allows the driver to reset the EHCI controller without affecting the state of the ports or the relationship to the companion host controllers. For example, the PORSTC registers should not be reset to their default values and the CF bit setting should not go to zero (retaining port ownership relationships). A host software read of this bit as zero indicates the Light Host Controller Reset has completed and it is safe for host software to re-initialize the host controller. A host software read of this bit as a one indicates the Light Host Controller Reset has not yet completed.
uint32_t async_park : 2 ; ///< It contains a count of the number of successive transactions the host controller is allowed to execute from a high-speed queue head on the Asynchronous schedule before continuing traversal of the Asynchronous schedule. See Section 4.10.3.2 for full operational details. Valid values are 1h to 3h. Software must not write a zero to this bit when Park Mode Enableis a one as this will result in undefined behavior.
uint32_t : 1 ; ///< reserved
uint32_t async_park_enable : 1 ; ///< Software uses this bit to enable or disable Park mode. When this bit is one, Park mode is enabled. When this bit is a zero, Park mode is disabled.
uint32_t : 3 ; ///< reserved
uint32_t async_adv_doorbell : 1 ; ///< Tell HC to interrupt next time it advances async list. Clear by HC
uint32_t light_reset : 1 ; ///< Reset HC without affecting ports state
uint32_t async_park_count : 2 ; ///< not used by tinyusb
uint32_t : 1 ;
uint32_t async_park_enable : 1 ; ///< Enable park mode, not used by tinyusb
uint32_t : 3 ;
uint32_t nxp_framelist_size_msb : 1 ; ///< NXP customized : Bit 2 of the Frame List Size bits \n 011b: 128 elements \n 100b: 64 elements \n 101b: 32 elements \n 110b: 16 elements \n 111b: 8 elements
uint32_t int_threshold : 8 ; ///< Default 08h. This field is used by system software to select the maximum rate at which the host controller will issue interrupts. The only valid values are defined below. If software writes an invalid value to this register, the results are undefined. Value Maximum Interrupt Interval 00h Reserved 01h 1 micro-frame 02h 2 micro-frames 04h 4 micro-frames 08h 8 micro-frames (default, equates to 1 ms) 10h 16 micro-frames (2 ms) 20h 32 micro-frames (4 ms) 40h 64 micro-frames (8 ms) Refer to Section 4.15 for interrupts affected by this register. Any other value in this register yields undefined results. Software modifications to this bit while HCHalted bit is equal to zero results in undefined behavior.
uint32_t : 0 ; // padding to the boundary of storage unit
}usb_cmd_bit;
uint32_t int_threshold : 8 ; ///< Default 08h. Interrupt rate in unit of micro frame
}command_bm;
};
union {
uint32_t usb_sts ; ///< This register indicates pending interrupts and various states of the Host Controller. The status resulting from a transaction on the serial bus is not indicated in this register. Software sets a bit to 0 in this register by writing a 1 to it. See Section 4.15 for additional information concerning USB interrupt conditions.
uint32_t status;
struct {
uint32_t usb : 1 ; ///< R/WC The Host Controller sets this bit to 1 on the completion of a USB transaction, which results in the retirement of a Transfer Descriptor that had its IOC bit set. \n The Host Controller also sets this bit to 1 when a short packet is detected (actual number of bytes received was less than the expected number of bytes).
uint32_t usb_error : 1 ; ///< R/WC The Host Controller sets this bit to 1 when completion of a USB transaction results in an error condition (e.g., error counter underflow). If the TD on which the error interrupt occurred also had its IOC bit set, both this bit and USBINT bit are set. See Section 4.15.1 for a list of the USB errors that will result in this bit being set to a one.
uint32_t port_change_detect : 1 ; ///< R/WC The Host Controller sets this bit to a one when any port for which the Port Ownerbit is set to zero (see Section 2.3.9) has a change bit transition from a zero to a one or a Force Port Resumebit transition from a zero to a one as a result of a J-K transition detected on a suspended port.
uint32_t framelist_rollover : 1 ; ///< R/WC The Host Controller sets this bit to a one when the Frame List Index(see Section 2.3.4) rolls over from its maximum value to zero. The exact value at which the rollover occurs depends on the frame list size. For example, if the frame list size (as programmed in the Frame List Sizefield of the USBCMD register) is 1024, the Frame Index Registerrolls over every time FRINDEX[13] toggles. Similarly, if the size is 512, the Host Controller sets this bit to a one every time FRINDEX[12] toggles.
uint32_t pci_host_system_error : 1 ; ///< R/WC (not used by NXP) The Host Controller sets this bit to 1 when a serious error occurs during a host system access involving the Host Controller module. In a PCI system, conditions that set this bit to 1 include PCI Parity error, PCI Master Abort, and PCI Target Abort. When this error occurs, the Host Controller clears the Run/Stop bit in the Command register to prevent further execution of the scheduled TDs.
uint32_t async_advance : 1 ; ///< R/WC 0=Default. System software can force the host controller to issue an interrupt the next time the host controller advances the asynchronous schedule by writing a one to the Interrupt on Async Advance Doorbell bit in the USBCMD register. This status bit indicates the assertion of that interrupt source.
uint32_t : 1 ; ///< These bits are reserved and should be set to zero.
uint32_t nxp_int_sof : 1 ; ///< R/WC NXP customized: this bit will be set every 125us and can be used by host controller driver as a time base.
uint32_t : 4 ; ///< These bits are reserved and should be set to zero.
uint32_t hc_halted : 1 ; ///< Read-Only 1=Default. This bit is a zero whenever the Run/Stop bit is a one. The Host Controller sets this bit to one after it has stopped executing as a result of the Run/Stop bit being set to 0, either by software or by the Host Controller hardware (e.g. internal error).
uint32_t reclamation : 1 ; ///< Read-Only 0=Default. This is a read-only status bit, which is used to detect an empty asynchronous schedule. The operational model of empty schedule detection is described in Section 4.8.3. The valid transitions for this bit are described in Section 4.8.6.
uint32_t period_schedule_status : 1 ; ///< Read-Only The bit reports the current real status of the Periodic Schedule. If this bit is a zero then the status of the Periodic Schedule is disabled. If this bit is a one then the status of the Periodic Schedule is enabled
uint32_t async_schedule_status : 1 ; ///< Read-Only 0=Default. The bit reports the current real status of the Asynchronous Schedule. If this bit is a zero then the status of the Asynchronous Schedule is disabled. If this bit is a one then the status of the Asynchronous Schedule is enabled.
uint32_t : 2 ; ///< reseved
uint32_t nxp_int_async : 1 ; ///< R/WC NXP customized: This bit is set by the Host Controller when the cause of an interrupt is a completion of a USB transaction where the Transfer Descriptor (TD) has an interrupt on complete (IOC) bit set andthe TD was from the asynchronous schedule. This bit is also set by the Host when a short packet is detected andthe packet is on the asynchronous schedule.
uint32_t nxp_int_period : 1 ; ///< R/WC NXP customized: This bit is set by the Host Controller when the cause of an interrupt is a completion of a USB transaction where the Transfer Descriptor (TD) has an interrupt on complete (IOC) bit set andthe TD was from the periodic schedule.
uint32_t : 12 ; ///< reserved
uint32_t : 0 ; // padding to the boundary of storage unit
}usb_sts_bit;
uint32_t usb : 1 ; ///< qTD with IOC is retired
uint32_t usb_error : 1 ; ///< qTD retired due to error
uint32_t port_change_detect : 1 ; ///< Set when PortOwner or ForcePortResume change from 0 -> 1
uint32_t framelist_rollover : 1 ; ///< R/WC The Host Controller sets this bit to a one when the Frame List Index(see Section 2.3.4) rolls over from its maximum value to zero. The exact value at which the rollover occurs depends on the frame list size. For example, if the frame list size (as programmed in the Frame List Sizefield of the USBCMD register) is 1024, the Frame Index Registerrolls over every time FRINDEX[13] toggles. Similarly, if the size is 512, the Host Controller sets this bit to a one every time FRINDEX[12] toggles.
uint32_t pci_host_system_error : 1 ; ///< R/WC (not used by NXP) The Host Controller sets this bit to 1 when a serious error occurs during a host system access involving the Host Controller module. In a PCI system, conditions that set this bit to 1 include PCI Parity error, PCI Master Abort, and PCI Target Abort. When this error occurs, the Host Controller clears the Run/Stop bit in the Command register to prevent further execution of the scheduled TDs.
uint32_t async_adv : 1 ; ///< Async Advance interrupt
uint32_t : 1 ;
uint32_t nxp_int_sof : 1 ; ///< NXP customized: this bit will be set every 125us and can be used by host controller driver as a time base.
uint32_t : 4 ;
uint32_t hc_halted : 1 ; ///< Opposite value to run_stop bit.
uint32_t reclamation : 1 ; ///< Used to detect empty async shecudle
uint32_t periodic_status : 1 ; ///< Periodic schedule status
uint32_t async_status : 1 ; ///< Async schedule status
uint32_t : 2 ;
uint32_t nxp_int_async : 1 ; ///< NXP customized: This bit is set by the Host Controller when the cause of an interrupt is a completion of a USB transaction where the Transfer Descriptor (TD) has an interrupt on complete (IOC) bit set andthe TD was from the asynchronous schedule. This bit is also set by the Host when a short packet is detected andthe packet is on the asynchronous schedule.
uint32_t nxp_int_period : 1 ; ///< NXP customized: This bit is set by the Host Controller when the cause of an interrupt is a completion of a USB transaction where the Transfer Descriptor (TD) has an interrupt on complete (IOC) bit set andthe TD was from the periodic schedule.
uint32_t : 12 ;
}status_bm;
};
union{
uint32_t usb_int_enable ; ///< This register enables and disables reporting of the corresponding interrupt to the software. When a bit is set and the corresponding interrupt is active, an interrupt is generated to the host. Interrupt sources that are disabled in this register still appear in the USBSTS to allow the software to poll for events.
uint32_t inten;
struct {
uint32_t usb : 1 ; ///< When this bit is a one, and the USBINT bit in the USBSTS register is a one, the host controller will issue an interrupt at the next interrupt threshold. The interrupt is acknowledged by software clearing the USBINTbit.
uint32_t usb_error : 1 ; ///< When this bit is a one, and the USBERRINT bit in the USBSTS register is a one, the host controller will issue an interrupt at the next interrupt threshold. The interrupt is acknowledged by software clearing the USBERRINTbit.
uint32_t port_change_detect : 1 ; ///< When this bit is a one, and the Port Change Detect bit in the USBSTS register is a one, the host controller will issue an interrupt. The interrupt is acknowledged by software clearing the Port Change Detectbit.
uint32_t framelist_rollover : 1 ; ///< When this bit is a one, and the Frame List Rolloverbit in the USBSTS register is a one, the host controller will issue an interrupt. The interrupt is acknowledged by software clearing the Frame List Rollover bit.
uint32_t pci_host_system_error : 1 ; ///< (not used by NXP) When this bit is a one, and the Host System Error Statusbit in the USBSTS register is a one, the host controller will issue an interrupt. The interrupt is acknowledged by software clearing the Host System Error bit.
uint32_t async_advance : 1 ; ///< When this bit is a one, and the Interrupt on Async Advancebit in the USBSTS register is a one, the host controller will issue an interrupt at the next interrupt threshold. The interrupt is acknowledged by software clearing the Interrupt on Async Advancebit.
uint32_t : 1 ; ///< reserved
uint32_t nxp_int_sof : 1 ; ///< NXP customized: if this bit is one and the SRI bit in the USBSTS register is one, the host controller will issue an interrupt. In host mode, the SRI bit will be set every 125 micro sec and can be used by the host controller as a time base. The interrupt is acknowledged by software clearing the SRI bit in the USBSTS register.
uint32_t : 10 ; ///< reserved
uint32_t nxp_int_async : 1 ; ///< NXP customized: When this bit is a one, and the USBHSTASYNCINT bit in the USBSTS register is a one, the host controller will issue an interrupt at the next interrupt threshold. The interrupt is acknowledged by software clearing the USBHSTASYNCINT bit.
uint32_t nxp_int_period : 1 ; ///< NXP customized: When this bit is a one, and the USBHSTPERINT bit in the USBSTS register is a one, the host controller will issue an interrupt at the next interrupt threshold. The interrupt is acknowledged by software clearing the USBHSTPERINT bit.
uint32_t : 12 ; ///< reserved
uint32_t : 0 ; // padding to the boundary of storage unit
}usb_int_enable_bit;
uint32_t usb : 1 ;
uint32_t usb_error : 1 ;
uint32_t port_change_detect : 1 ;
uint32_t framelist_rollover : 1 ;
uint32_t pci_host_system_error : 1 ;
uint32_t async_adv : 1 ;
uint32_t : 1 ;
uint32_t nxp_int_sof : 1 ;
uint32_t : 10 ;
uint32_t nxp_int_async : 1 ;
uint32_t nxp_int_period : 1 ;
uint32_t : 12 ;
}inten_bm;
};
uint32_t frame_index ; ///< This register is used by the host controller to index into the periodic frame list. The register updates every 125 microseconds (once each micro-frame). Bits [N:3] are used to select a particular entry in the Periodic Frame List during periodic schedule execution. The number of bits used for the index depends on the size of the frame list as set by system software in the Frame List Sizefield in the USBCMD register
uint32_t ctrl_ds_seg ; ///< (not used by NXP) This 32-bit register corresponds to the most significant address bits [63:32] for all EHCI data structures. If the 64-bit Addressing Capabilityfield in HCCPARAMS is a zero, then this register is not used
uint32_t periodic_list_base ; ///< This 32-bit register contains the beginning address of the Periodic Frame List in the system memory. System software loads this register prior to starting the schedule execution by the Host Controller (see 4.1). The memory structure referenced by this physical memory pointer is assumed to be 4-Kbyte aligned. The contents of this register are combined with the Frame Index Register (FRINDEX) to enable the Host Controller to step through the Periodic Frame List in sequence.
uint32_t async_list_base ; ///< This 32-bit register contains the address of the next asynchronous queue head to be executed. Bits [4:0] of this register cannot be modified by system software and will always return a zero when read. The memory structure referenced by this physical memory pointer is assumed to be 32-byte (cache line) aligned
uint32_t tt_control ; ///< nxp embedded transaction translator (reserved by EHCI specs)
uint32_t reserved[8] ; ///< reserved by EHCI specs
uint32_t config_flag ; ///< (not used by NXP) configured flag register
uint32_t frame_index ; ///< Micro frame counter
uint32_t ctrl_ds_seg ; ///< Control Data Structure Segment
uint32_t periodic_list_base ; ///< Beginning address of perodic frame list
uint32_t async_list_addr ; ///< Address of next async QHD to be executed
uint32_t nxp_tt_control ; ///< nxp embedded transaction translator (reserved by EHCI specs)
uint32_t reserved[8] ;
uint32_t config_flag ; ///< not used by NXP
union {
uint32_t portsc ; ///< port status and control
struct {
uint32_t current_connect_status : 1; ///< RO 1=Device is present on port. 0=No device is present. Default = 0. This value reflects the current state of the port, and may not correspond directly to the event that caused the Connect Status Change bit (Bit 1) to be set. This field is zero if Port Power is zero.
uint32_t connect_status_change : 1; ///< R/WC 1=Change in Current Connect Status. 0=No change. Default = 0. Indicates a change has occurred in the port's Current Connect Status. The host controller sets this bit for all changes to the port device connect status, even if system software has not cleared an existing connect status change. For example, the insertion status changes twice before system software has cleared the changed condition, hub hardware will be "setting" an already-set bit (i.e., the bit will remain set). Software sets this bit to 0 by writing a 1 to it. This field is zero if Port Power is zero.
uint32_t port_enable : 1; ///< 1=Enable. 0=Disable. Default = 0. Ports can only be enabled by the host controller as a part of the reset and enable. Software cannot enable a port by writing a one to this field. The host controller will only set this bit to a one when the reset sequence determines that the attached device is a high-speed device. Ports can be disabled by either a fault condition (disconnect event or other fault condition) or by host software. Note that the bit status does not change until the port state actually changes.
uint32_t port_enable_change : 1; ///< R/WC 1=Port enabled/disabled status has changed. 0=No change. Default = 0. For the root hub, this bit gets set to a one only when a port is disabled due to the appropriate conditions existing at the EOF2 point (See Chapter 11 of the USB Specification for the definition of a Port Error). Software clears this bit by writing a 1 to it. This field is zero if Port Power is zero.
uint32_t over_current_active : 1; ///< RO Default = 0. 1=This port currently has an over-current condition. 0=This port does not have an over-current condition. This bit will automatically transition from a one to a zero when the over current condition is removed.
uint32_t over_current_change : 1; ///< R/WC Default = 0. 1=This bit gets set to a one when there is a change to Over-current Active. Software clears this bit by writing a one to this bit position.
uint32_t force_port_resume : 1; ///< 1= Resume detected/driven on port. 0=No resume (K-state) detected/driven on port. Default = 0. This functionality defined for manipulating this bit depends on the value of the Suspendbit. For example, if the port is not suspended (Suspendand Enabledbits are a one) and software transitions this bit to a one, then the effects on the bus are undefined. Software sets this bit to a 1 to drive resume signaling. The Host Controller sets this bit to a 1 if a J-to-K transition is detected while the port is in the Suspend state. When this bit transitions to a one because a J-to-K transition is detected, the Port Change Detectbit in the USBSTS register is also set to a one. If software sets this bit to a one, the host controller must not set the Port Change Detectbit.
uint32_t suspend : 1; ///< 1=Port in suspend state. 0=Port not in suspend state. Default = 0. Port Enabled Bit and Suspend bit of this register define the port states as follows: Bits [Port Enabled, Suspend] Port State 0X Disable 10 Enable 11 Suspend When in suspend state, downstream propagation of data is blocked on this port, except for port reset. The blocking occurs at the end of the current transaction, if a transaction was in progress when this bit was written to 1. In the suspend state, the port is sensitive to resume detection. Note that the bit status does not change until the port is suspended and that there may be a delay in suspending a port if there is a transaction currently in progress on the USB. A write of zero to this bit is ignored by the host controller. The host controller will unconditionally set this bit to a zero when: •Software sets the Force Port Resumebit to a zero (from a one). •Software sets the Port Resetbit to a one (from a zero).
uint32_t port_reset : 1; ///< 1=Port is in Reset. 0=Port is not in Reset. Default = 0. When software writes a one to this bit (from a zero)
uint32_t current_connect_status : 1; ///< 0: No device, 1: Device is present on port
uint32_t connect_status_change : 1; ///< Change in Current Connect Status
uint32_t port_enabled : 1; ///< Ports can only be enabled by HC as a part of the reset and enable. SW can write 0 to disable
uint32_t port_enable_change : 1; ///< Port Enabled has changed
uint32_t over_current_active : 1; ///< Port has an over-current condition
uint32_t over_current_change : 1; ///< Change to Over-current Active
uint32_t force_port_resume : 1; ///< Resume detected/driven on port. This functionality defined for manipulating this bit depends on the value of the Suspend bit.
uint32_t suspend : 1; ///< Port in suspend state
uint32_t port_reset : 1; ///< 1=Port is in Reset. 0=Port is not in Reset
uint32_t nxp_highspeed_status : 1; ///< NXP customized: 0=connected to the port is not in High-speed mode, 1=connected to the port is in High-speed mode
uint32_t line_status : 2; ///< hese bits reflect the current logical levels of the D+ (bit 11) and D- (bit 10) signal lines. These bits are used for detection of low-speed USB devices prior to the port reset and enable sequence. This field is valid only when the port enable bit is zero and the current connect status bit is set to a one. The encoding of the bits are: 00b SE0, 10b J-state, 01b K-state, 11b undefined
uint32_t port_power : 1; ///< 0= power off, 1= power on, Host/OTG controller requires port power control switches. This bit represents the current setting of the switch (0=off, 1=on). When power is not available on a port (i.e. PP equals a 0), the port is non-functional and will not report attaches, detaches, etc. When an over-current condition is detected on a powered port and PPC is a one, the PP bit in each affected port may be transitioned by the host controller driver from a one to a zero (removing power from the port).
uint32_t port_owner : 1; ///< (not used by NXP)
uint32_t port_indicator_control : 2; ///< Writing to this field effects the value of the pins USB0_IND1 and USB0_IND0. 00b: Port indication is off, 01b: Amber, 10b: green, 11b: undefined
uint32_t port_test_control : 4; ///< When this field is zero, the port is NOT operating in a test mode. A non-zero value indicates that it is operating in test mode
uint32_t wake_on_connect_enable : 1; ///< Default = 0b. Writing this bit to a one enables the port to be sensitive to device connects as wake-up events. See Section 4.3 for effects of this bit on resume event behavior. Refer to Section 4.3.1 for operational model.
uint32_t wake_on_disconnect_enable : 1; ///< Default = 0b. Writing this bit to a one enables the port to be sensitive to device disconnects as wake-up events. See Section 4.3 for effects of this bit on resume event behavior. Refer to Section 4.3.1 for operational model.
uint32_t wake_on_over_current_enable : 1; ///< Default = 0b. Writing this bit to a one enables the port to be sensitive to over-current conditions as wake-up events. See Section 4.3 for effects of this bit on resume event behavior. Refer to Section 4.3.1 for operational model.
uint32_t line_status : 2; ///< D+/D- state: 00: SE0, 10: J-state, 01: K-state
uint32_t port_power : 1; ///< 0= power off, 1= power on
uint32_t port_owner : 1; ///< not used by NXP
uint32_t port_indicator_control : 2; ///< 00b: off, 01b: Amber, 10b: green, 11b: undefined
uint32_t port_test_control : 4; ///< Port test mode, not used by tinyusb
uint32_t wake_on_connect_enable : 1; ///< Enables device connects as wake-up events
uint32_t wake_on_disconnect_enable : 1; ///< Enables device disconnects as wake-up events
uint32_t wake_on_over_current_enable : 1; ///< Enables over-current conditions as wake-up events
uint32_t nxp_phy_clock_disable : 1; ///< NXP customized: the PHY can be put into Low Power Suspend Clock Disable when the downstream device has been put into suspend mode or when no downstream device is connected. Low power suspend is completely under the control of software. 0: enable PHY clock, 1: disable PHY clock
uint32_t nxp_port_force_fullspeed : 1; ///< NXP customized: Writing this bit to a 1 will force the port to only connect at Full Speed. It disables the chirp sequence that allowsthe port to identify itself as High Speed. This is useful for testing FS configurations with a HS host, hub or device.
uint32_t : 1;
uint32_t nxp_port_speed : 2; ///< NXP customized: This register field indicates the speed atwhich the port is operating. For HS mode operation in the host controllerand HS/FS operation in the device controller the port routing steers data to the Protocol engine. For FS and LS mode operation in the host controller, the port routing steers data to the Protocol Engine w/ Embedded Transaction Translator. 0x0: Fullspeed, 0x1: Lowspeed, 0x2: Highspeed
uint32_t : 0; // padding to the boundary of storage unit
}portsc_bit;
}portsc_bm;
};
}ehci_registers_t;