📄 usb20hw.c
字号:
break;
/* Clear all the interrupts that occured. */
usb_opreg->USB_STS = status;
/*
* Only process interrupt bits if we have not already invoked
* the reset task, otherwise let it proceed without interference.
*/
if (!USB_ForceReset && usb_state.USB_STATE != USB_STATE_POWER_ON) {
/* Process reset. */
if (status & VUSB_STS_RESET) {
#if RESET_PWR_CYCLE
if (usb_state.USB_STATE == USB_STATE_CONFIG)
USB_Hard_Reset = TRUE;
#endif
/* Deconfigure interface before reset. */
USB_deconfigure_current_interface();
/*
* Only reset in Interrupt Service Routine if deconfigure
* went OK.
*/
if (!USB_ForceReset)
USB_ISR_process_reset();
}
/* Process change of speed (if not also reset). */
else if (status & VUSB_STS_PORT_CHANGE) {
if (usb_opreg->PORTSCX[0] & VUSB_PORTSCX_PORT_HIGH_SPEED)
new_speed = USB_DEV_HIGH_SPEED;
else
new_speed = USB_DEV_FULL_SPEED;
if (usb_state.SPEED != new_speed) {
usb_state.SPEED = new_speed;
usb_state.USB_STATE = USB_STATE_DEFAULT;
USB_speed_change();
}
}
/* Error count not currently used for anything. */
if (status & VUSB_STS_ERR)
usb_state.ERRORS++;
/* I/O transfer complete. */
if (status & VUSB_STS_INT)
USB_ISR_process_tr_complete();
/* Monitor change of suspend/resume. */
if (usb_state.USB_SUSPEND != (status & VUSB_STS_SUSPEND)) {
usb_state.USB_SUSPEND = status & VUSB_STS_SUSPEND;
/*
* Call to "suspend/resume" routine can go here.
*/
}
/* Start of USB frame: not currently enabled in VUSB_INTERRUPT_BITS */
if (status & VUSB_STS_SOF) {
/*
* Call to "Start of Frame" routine can go here; frame
* number is in "usb_opreg->USB_FRINDEX".
*/
}
}
}
/*
* Wake up USB reset/1248.4 task if appropriate.
*/
if (USB_ForceReset)
USB_WakeUpUSB_Task();
*(unsigned long *)EXMSK1A |= 2;
/* Clear bit in exception register. */
*(Uint32 *)EXCLRA = (1 << USB_INTERRUPT_BIT);
}
extern tsSemaphore USBSemaphore;
void USB_WakeUpUSB_Task(void)
{
Sint32 status;
status = TaskSemSignal(USBSemaphore);
USB_ASSERT(status >= 0);
}
#endif
/**************************************************************************
*
* Function Name : USB_ISR_io_request
* Returned Value : None
* Comments :
* Sends or receives data on a specified endpoint.
*
**************************************************************************/
void USB_ISR_io_request(Uint16 ep_index, Uint8 *buff_ptr, Uint16 size)
{
dDT_STRUCT *dTD;
dQH_STRUCT *ep_queue_head_ptr;
/*
* Endpoint must have been initialized already. If no request pending,
* endpoint must not be primed!
*/
USB_ASSERT(size <= VUSB_EP_MAX_LENGTH_TRANSFER);
USB_ASSERT(usb_state.EP_INIT[ep_index]);
USB_ASSERT(usb_state.EP_DTD_HEADS[ep_index]||ENDPOINT_NOT_PRIMED(ep_index));
/* Fatal error if the pool has no more descriptors left. */
if (!usb_state.DTD_POOL) {
USB_ForceReset = RESET_HW;
return;
}
/* Allocate a transfer descriptor for this I/O request. */
dTD = usb_state.DTD_POOL;
if (!dTD) {
USB_ForceReset = RESET_HW;
USB_ForceReset = RESET_HW;
USB_INTS_ON;
return;
}
usb_state.DTD_POOL = (dDT_STRUCT *)dTD->NEXT;
/* Initialize the new transfer descriptor. */
dTD->LENGTH = size;
dTD->NEXT = DTD_TERM_BIT;
dTD->SIZE_IOC_STS = (size << 16) | DTD_IOC | DTD_STATUS_ACTIVE;
/* Buffer page pointers are spaced 4K apart. */
dTD->BUFF_PTR0 = (Uint32)buff_ptr;
dTD->BUFF_PTR1 = (dTD->BUFF_PTR0 + 4096);
dTD->BUFF_PTR2 = (dTD->BUFF_PTR1 + 4096);
dTD->BUFF_PTR3 = (dTD->BUFF_PTR2 + 4096);
dTD->BUFF_PTR4 = (dTD->BUFF_PTR3 + 4096);
/*
* If there was already and active request, its now safe to link this
* new request onto the chain. If none, make this one the new HEAD.
* New dTD always becomes the new TAIL.
*/
if (usb_state.EP_DTD_HEADS[ep_index])
usb_state.EP_DTD_TAILS[ep_index]->NEXT = (Uint32)dTD;
else
usb_state.EP_DTD_HEADS[ep_index] = dTD;
usb_state.EP_DTD_TAILS[ep_index] = dTD;
/* Check if the endpoint is not primed and has no bit set in ENDPTSTAT. */
if (ENDPOINT_NOT_PRIMED(ep_index)) {
int i;
ep_queue_head_ptr = usb_state.EP_QUEUE_HEAD_PTR + ep_index;
/* Give the hardware time to settle before giving up */
for (i = 0; i < HW_LOOP_CNT; i++) {
/* Check if no other transfers queued, i.e., this is first. */
if ((volatile)(ep_queue_head_ptr->NEXT_DTD_PTR) & DTD_TERM_BIT) {
/*
* Make certain that the Endpoint Queue Head total-bytes
* count is accurate in the Transfer Overlay region. That
* is where we will monitor the progress of the packet
* reads and we don't want to think that data has been
* received when looking at leftover info from the last
* transfer.
*/
ep_queue_head_ptr->SIZE_IOC_INT_STS = size << 16;
ep_queue_head_ptr->CURR_DTD_PTR = 0;
ep_queue_head_ptr->NEXT_DTD_PTR = (Uint32)dTD;
/* Prime the Endpoint and return if it worked. */
usb_opreg->ENDPTPRIME = EP_REGBIT(ep_index);
if (ENDPOINT_PRIMED(ep_index))
return;
}
}
/*
* Prime didn't seem to work (Hardware bug?). Keep trying.
*/
for (i = 0; i < 6; i++) {
Uint32 t0;
/* OK if request finished right away */
if ((volatile)(ep_queue_head_ptr->NEXT_DTD_PTR) & DTD_TERM_BIT)
return;
/* Prime the Endpoint again. */
usb_opreg->ENDPTPRIME = EP_REGBIT(ep_index);
/* Hang for up to 30 usecs. to avoid messing up scanner endpoint */
t0 = *(unsigned volatile int *)HRTCNTL0;
while (*(unsigned volatile int *)HRTCNTL0 - t0 < 5*133)
;
/* Return if it worked this time */
if (ENDPOINT_PRIMED(ep_index))
return;
}
/*
* If the endpoint is not primed but the next-dTD pointer is
* not terminal, then we have hardware problems.
*/
USB_ForceReset = RESET_HW;
}
}
/**************************************************************************
*
* Function Name : USB_task_io_request
* Returned Value : USB_OK or error code
* Comments :
* Sends or receives data on a specified endpoint.
*
**************************************************************************/
Uint8 USB_task_io_request(Uint16 ep_index, Uint8 *buff_ptr, Uint16 size)
{
dDT_STRUCT *dTD;
dQH_STRUCT *ep_queue_head_ptr;
/*
* Endpoint 0 should never issue request from task level and only EP0
* is allowed to have a null buffer and zero size.
*/
USB_ASSERT(ep_index >= 2 && buff_ptr && size);
USB_ASSERT(size <= VUSB_EP_MAX_LENGTH_TRANSFER);
/*
* Disable interrupts from USB so we won't conflict with ISR io requests;
* check if endpoint initialized.
*/
USB_INTS_OFF;
if (!usb_state.EP_INIT[ep_index]) {
USB_INTS_ON;
return USBERR_EP_CLOSED;
}
/*
* Now that we are assured that the ISR can not interrupt,
* causing a reentrancy problem, issue the I/O request. This is
* a copy of USB_ISR_io_request(), but for task calls.
*/
/* If no request pending, endpoint must not be primed! */
USB_ASSERT(usb_state.EP_DTD_HEADS[ep_index] ||
ENDPOINT_NOT_PRIMED(ep_index));
/*
* Allocate a transfer descriptor for this I/O request. Fatal
* error if the pool has no more descriptors left.
*/
ARM_INTS_OFF;
dTD = usb_state.DTD_POOL;
if (!dTD) {
USB_ForceReset = RESET_HW;
USB_INTS_ON;
return USBERR_EP_CLOSED;
}
usb_state.DTD_POOL = (dDT_STRUCT *)dTD->NEXT;
ARM_INTS_ON;
/* Initialize the new transfer descriptor. */
dTD->LENGTH = size;
dTD->NEXT = DTD_TERM_BIT;
dTD->SIZE_IOC_STS = (size << 16) | DTD_IOC | DTD_STATUS_ACTIVE;
/* Buffer page pointers are spaced 4K apart. */
dTD->BUFF_PTR0 = (Uint32)buff_ptr;
dTD->BUFF_PTR1 = (dTD->BUFF_PTR0 + 4096);
dTD->BUFF_PTR2 = (dTD->BUFF_PTR1 + 4096);
dTD->BUFF_PTR3 = (dTD->BUFF_PTR2 + 4096);
dTD->BUFF_PTR4 = (dTD->BUFF_PTR3 + 4096);
/*
* If there was already and active request, its now safe to link this
* new request onto the chain. If none, make this one the new HEAD.
* New dTD always becomes the new TAIL.
*/
if (usb_state.EP_DTD_HEADS[ep_index])
usb_state.EP_DTD_TAILS[ep_index]->NEXT = (Uint32)dTD;
else
usb_state.EP_DTD_HEADS[ep_index] = dTD;
usb_state.EP_DTD_TAILS[ep_index] = dTD;
/* Check if the endpoint is not primed and has no bit set in ENDPTSTAT. */
if (ENDPOINT_NOT_PRIMED(ep_index)) {
int i;
ep_queue_head_ptr = usb_state.EP_QUEUE_HEAD_PTR + ep_index;
/* Give the hardware time to settle before giving up */
for (i = 0; i < HW_LOOP_CNT; i++) {
/* Check if no other transfers queued, i.e., this is first. */
if ((volatile)(ep_queue_head_ptr->NEXT_DTD_PTR) & DTD_TERM_BIT) {
/*
* Make certain that the Endpoint Queue Head total-bytes
* count is accurate in the Transfer Overlay region. That
* is where we will monitor the progress of the packet
* reads and we don't want to think that data has been
* received when looking at leftover info from the last
* transfer.
*/
ep_queue_head_ptr->SIZE_IOC_INT_STS = size << 16;
ep_queue_head_ptr->CURR_DTD_PTR = 0;
ep_queue_head_ptr->NEXT_DTD_PTR = (Uint32)dTD;
/* Prime the Endpoint and return if it worked. */
usb_opreg->ENDPTPRIME = EP_REGBIT(ep_index);
if (ENDPOINT_PRIMED(ep_index)) {
USB_INTS_ON;
return USB_OK;
}
}
}
/*
* Prime didn't seem to work (Hardware bug?). Keep trying.
*/
for (i = 0; i < 6; i++) {
Uint32 t0;
/* OK if request finished right away */
if ((volatile)(ep_queue_head_ptr->NEXT_DTD_PTR) & DTD_TERM_BIT) {
USB_INTS_ON;
return USB_OK;
}
/* Prime the Endpoint again. */
usb_opreg->ENDPTPRIME = EP_REGBIT(ep_index);
/* Hang for up to 30 usecs. to avoid messing up scanner endpoint */
t0 = *(unsigned volatile int *)HRTCNTL0;
while (*(unsigned volatile int *)HRTCNTL0 - t0 < 5*133)
;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -