CH592_Makefile_Template/sdk/StdPeriphDriver/CH59x_usbhostBase.c
2023-12-21 22:44:09 +07:00

696 lines
22 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/********************************** (C) COPYRIGHT *******************************
* File Name : CH59x_usbhost.c
* Author : WCH
* Version : V1.2
* Date : 2021/11/17
* Description
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include "CH59x_common.h"
#if DISK_LIB_ENABLE
#include "CHRV3UFI.H"
#endif
uint8_t UsbDevEndp0Size; // USB设备的端点0的最大包尺寸
uint8_t FoundNewDev;
_RootHubDev ThisUsbDev; //ROOT口
_DevOnHubPort DevOnHubPort[HUB_MAX_PORTS]; // 假定:不超过1个外部HUB,每个外部HUB不超过HUB_MAX_PORTS个端口(多了不管)
uint8_t *pHOST_RX_RAM_Addr;
uint8_t *pHOST_TX_RAM_Addr;
/*获取设备描述符*/
__attribute__((aligned(4))) const uint8_t SetupGetDevDescr[] = {USB_REQ_TYP_IN, USB_GET_DESCRIPTOR, 0x00,
USB_DESCR_TYP_DEVICE, 0x00, 0x00, sizeof(USB_DEV_DESCR), 0x00};
/*获取配置描述符*/
__attribute__((aligned(4))) const uint8_t SetupGetCfgDescr[] = {USB_REQ_TYP_IN, USB_GET_DESCRIPTOR, 0x00,
USB_DESCR_TYP_CONFIG, 0x00, 0x00, 0x04, 0x00};
/*设置USB地址*/
__attribute__((aligned(4))) const uint8_t SetupSetUsbAddr[] = {USB_REQ_TYP_OUT, USB_SET_ADDRESS, USB_DEVICE_ADDR, 0x00,
0x00, 0x00, 0x00, 0x00};
/*设置USB配置*/
__attribute__((aligned(4))) const uint8_t SetupSetUsbConfig[] = {USB_REQ_TYP_OUT, USB_SET_CONFIGURATION, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00};
/*设置USB接口配置*/
__attribute__((aligned(4))) const uint8_t SetupSetUsbInterface[] = {USB_REQ_RECIP_INTERF, USB_SET_INTERFACE, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00};
/*清除端点STALL*/
__attribute__((aligned(4))) const uint8_t SetupClrEndpStall[] = {USB_REQ_TYP_OUT | USB_REQ_RECIP_ENDP, USB_CLEAR_FEATURE,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
/*********************************************************************
* @fn DisableRootHubPort
*
* @brief 关闭ROOT-HUB端口,实际上硬件已经自动关闭,此处只是清除一些结构状态
*
* @param none
*
* @return none
*/
void DisableRootHubPort(void)
{
#ifdef FOR_ROOT_UDISK_ONLY
CHRV3DiskStatus = DISK_DISCONNECT;
#endif
#ifndef DISK_BASE_BUF_LEN
ThisUsbDev.DeviceStatus = ROOT_DEV_DISCONNECT;
ThisUsbDev.DeviceAddress = 0x00;
#endif
}
/*********************************************************************
* @fn AnalyzeRootHub
*
* @brief 分析ROOT-HUB状态,处理ROOT-HUB端口的设备插拔事件
* 如果设备拔出,函数中调用DisableRootHubPort()函数,将端口关闭,插入事件,置相应端口的状态位
*
* @param none
*
* @return 返回ERR_SUCCESS为没有情况,返回ERR_USB_CONNECT为检测到新连接,返回ERR_USB_DISCON为检测到断开
*/
uint8_t AnalyzeRootHub(void)
{
uint8_t s;
s = ERR_SUCCESS;
if(R8_USB_MIS_ST & RB_UMS_DEV_ATTACH)
{ // 设备存在
#ifdef DISK_BASE_BUF_LEN
if(CHRV3DiskStatus == DISK_DISCONNECT
#else
if(ThisUsbDev.DeviceStatus == ROOT_DEV_DISCONNECT // 检测到有设备插入
#endif
|| (R8_UHOST_CTRL & RB_UH_PORT_EN) == 0x00)
{ // 检测到有设备插入,但尚未允许,说明是刚插入
DisableRootHubPort(); // 关闭端口
#ifdef DISK_BASE_BUF_LEN
CHRV3DiskStatus = DISK_CONNECT;
#else
ThisUsbDev.DeviceSpeed = R8_USB_MIS_ST & RB_UMS_DM_LEVEL ? 0 : 1;
ThisUsbDev.DeviceStatus = ROOT_DEV_CONNECTED; //置连接标志
#endif
PRINT("USB dev in\n");
s = ERR_USB_CONNECT;
}
}
#ifdef DISK_BASE_BUF_LEN
else if(CHRV3DiskStatus >= DISK_CONNECT)
{
#else
else if(ThisUsbDev.DeviceStatus >= ROOT_DEV_CONNECTED)
{ //检测到设备拔出
#endif
DisableRootHubPort(); // 关闭端口
PRINT("USB dev out\n");
if(s == ERR_SUCCESS)
{
s = ERR_USB_DISCON;
}
}
// R8_USB_INT_FG = RB_UIF_DETECT; // 清中断标志
return (s);
}
/*********************************************************************
* @fn SetHostUsbAddr
*
* @brief 设置USB主机当前操作的USB设备地址
*
* @param addr - USB设备地址
*
* @return none
*/
void SetHostUsbAddr(uint8_t addr)
{
R8_USB_DEV_AD = (R8_USB_DEV_AD & RB_UDA_GP_BIT) | (addr & MASK_USB_ADDR);
}
/*********************************************************************
* @fn SetUsbSpeed
*
* @brief 设置当前USB速度
*
* @param FullSpeed - USB速度
*
* @return none
*/
void SetUsbSpeed(uint8_t FullSpeed)
{
#ifndef DISK_BASE_BUF_LEN
if(FullSpeed) // 全速
{
R8_USB_CTRL &= ~RB_UC_LOW_SPEED; // 全速
R8_UH_SETUP &= ~RB_UH_PRE_PID_EN; // 禁止PRE PID
}
else
{
R8_USB_CTRL |= RB_UC_LOW_SPEED; // 低速
}
#endif
(void)FullSpeed;
}
/*********************************************************************
* @fn ResetRootHubPort
*
* @brief 检测到设备后,复位总线,为枚举设备准备,设置为默认为全速
*
* @param none
*
* @return none
*/
void ResetRootHubPort(void)
{
UsbDevEndp0Size = DEFAULT_ENDP0_SIZE; //USB设备的端点0的最大包尺寸
SetHostUsbAddr(0x00);
R8_UHOST_CTRL &= ~RB_UH_PORT_EN; // 关掉端口
SetUsbSpeed(1); // 默认为全速
R8_UHOST_CTRL = (R8_UHOST_CTRL & ~RB_UH_LOW_SPEED) | RB_UH_BUS_RESET; // 默认为全速,开始复位
mDelaymS(15); // 复位时间10mS到20mS
R8_UHOST_CTRL = R8_UHOST_CTRL & ~RB_UH_BUS_RESET; // 结束复位
mDelayuS(250);
R8_USB_INT_FG = RB_UIF_DETECT; // 清中断标志
}
/*********************************************************************
* @fn EnableRootHubPort
*
* @brief 使能ROOT-HUB端口,相应的bUH_PORT_EN置1开启端口,设备断开可能导致返回失败
*
* @param none
*
* @return 返回ERR_SUCCESS为检测到新连接,返回ERR_USB_DISCON为无连接
*/
uint8_t EnableRootHubPort(void)
{
#ifdef DISK_BASE_BUF_LEN
if(CHRV3DiskStatus < DISK_CONNECT)
CHRV3DiskStatus = DISK_CONNECT;
#else
if(ThisUsbDev.DeviceStatus < ROOT_DEV_CONNECTED)
ThisUsbDev.DeviceStatus = ROOT_DEV_CONNECTED;
#endif
if(R8_USB_MIS_ST & RB_UMS_DEV_ATTACH)
{ // 有设备
#ifndef DISK_BASE_BUF_LEN
if((R8_UHOST_CTRL & RB_UH_PORT_EN) == 0x00)
{ // 尚未使能
ThisUsbDev.DeviceSpeed = (R8_USB_MIS_ST & RB_UMS_DM_LEVEL) ? 0 : 1;
if(ThisUsbDev.DeviceSpeed == 0)
{
R8_UHOST_CTRL |= RB_UH_LOW_SPEED; // 低速
}
}
#endif
R8_UHOST_CTRL |= RB_UH_PORT_EN; //使能HUB端口
return (ERR_SUCCESS);
}
return (ERR_USB_DISCON);
}
#ifndef DISK_BASE_BUF_LEN
/*********************************************************************
* @fn SelectHubPort
*
* @brief 选定需要操作的HUB口
*
* @param HubPortIndex - 选择操作指定的ROOT-HUB端口的外部HUB的指定端口
*
* @return None
*/
void SelectHubPort(uint8_t HubPortIndex)
{
if(HubPortIndex) // 选择操作指定的ROOT-HUB端口的外部HUB的指定端口
{
SetHostUsbAddr(DevOnHubPort[HubPortIndex - 1].DeviceAddress); // 设置USB主机当前操作的USB设备地址
SetUsbSpeed(DevOnHubPort[HubPortIndex - 1].DeviceSpeed); // 设置当前USB速度
if(DevOnHubPort[HubPortIndex - 1].DeviceSpeed == 0) // 通过外部HUB与低速USB设备通讯需要前置ID
{
R8_UEP1_CTRL |= RB_UH_PRE_PID_EN; // 启用PRE PID
mDelayuS(100);
}
}
else
{
SetHostUsbAddr(ThisUsbDev.DeviceAddress); // 设置USB主机当前操作的USB设备地址
SetUsbSpeed(ThisUsbDev.DeviceSpeed); // 设置USB设备的速度
}
}
#endif
/*********************************************************************
* @fn WaitUSB_Interrupt
*
* @brief 等待USB中断
*
* @param none
*
* @return 返回ERR_SUCCESS 数据接收或者发送成功,返回ERR_USB_UNKNOWN 数据接收或者发送失败
*/
uint8_t WaitUSB_Interrupt(void)
{
uint16_t i;
for(i = WAIT_USB_TOUT_200US; i != 0 && (R8_USB_INT_FG & RB_UIF_TRANSFER) == 0; i--)
{
;
}
return ((R8_USB_INT_FG & RB_UIF_TRANSFER) ? ERR_SUCCESS : ERR_USB_UNKNOWN);
}
/*********************************************************************
* @fn USBHostTransact
*
* @brief 传输事务,输入目的端点地址/PID令牌,同步标志,以20uS为单位的NAK重试总时间(0则不重试,0xFFFF无限重试),返回0成功,超时/出错重试
* 本子程序着重于易理解,而在实际应用中,为了提供运行速度,应该对本子程序代码进行优化
*
* @param endp_pid - 令牌和地址, 高4位是token_pid令牌, 低4位是端点地址
* @param tog - 同步标志
* @param timeout - 超时时间
*
* @return ERR_USB_UNKNOWN 超时,可能硬件异常
* ERR_USB_DISCON 设备断开
* ERR_USB_CONNECT 设备连接
* ERR_SUCCESS 传输完成
*/
uint8_t USBHostTransact(uint8_t endp_pid, uint8_t tog, uint32_t timeout)
{
uint8_t TransRetry;
uint8_t s, r;
uint16_t i;
R8_UH_RX_CTRL = R8_UH_TX_CTRL = tog;
TransRetry = 0;
do
{
R8_UH_EP_PID = endp_pid; // 指定令牌PID和目的端点号
R8_USB_INT_FG = RB_UIF_TRANSFER;
for(i = WAIT_USB_TOUT_200US; i != 0 && (R8_USB_INT_FG & RB_UIF_TRANSFER) == 0; i--)
{
;
}
R8_UH_EP_PID = 0x00; // 停止USB传输
if((R8_USB_INT_FG & RB_UIF_TRANSFER) == 0)
{
return (ERR_USB_UNKNOWN);
}
if(R8_USB_INT_FG & RB_UIF_DETECT)
{ // USB设备插拔事件
// mDelayuS( 200 ); // 等待传输完成
R8_USB_INT_FG = RB_UIF_DETECT;
s = AnalyzeRootHub(); // 分析ROOT-HUB状态
if(s == ERR_USB_CONNECT)
FoundNewDev = 1;
#ifdef DISK_BASE_BUF_LEN
if(CHRV3DiskStatus == DISK_DISCONNECT)
{
return (ERR_USB_DISCON);
} // USB设备断开事件
if(CHRV3DiskStatus == DISK_CONNECT)
{
return (ERR_USB_CONNECT);
} // USB设备连接事件
#else
if(ThisUsbDev.DeviceStatus == ROOT_DEV_DISCONNECT)
{
return (ERR_USB_DISCON);
} // USB设备断开事件
if(ThisUsbDev.DeviceStatus == ROOT_DEV_CONNECTED)
{
return (ERR_USB_CONNECT);
} // USB设备连接事件
#endif
mDelayuS(200); // 等待传输完成
}
if(R8_USB_INT_FG & RB_UIF_TRANSFER) // 传输完成事件
{
if(R8_USB_INT_ST & RB_UIS_TOG_OK)
{
return (ERR_SUCCESS);
}
r = R8_USB_INT_ST & MASK_UIS_H_RES; // USB设备应答状态
if(r == USB_PID_STALL)
{
return (r | ERR_USB_TRANSFER);
}
if(r == USB_PID_NAK)
{
if(timeout == 0)
{
return (r | ERR_USB_TRANSFER);
}
if(timeout < 0xFFFFFFFF)
{
timeout--;
}
--TransRetry;
}
else
switch(endp_pid >> 4)
{
case USB_PID_SETUP:
case USB_PID_OUT:
if(r)
{
return (r | ERR_USB_TRANSFER);
} // 不是超时/出错,意外应答
break; // 超时重试
case USB_PID_IN:
if(r == USB_PID_DATA0 || r == USB_PID_DATA1)
{ // 不同步则需丢弃后重试
} // 不同步重试
else if(r)
{
return (r | ERR_USB_TRANSFER);
} // 不是超时/出错,意外应答
break; // 超时重试
default:
return (ERR_USB_UNKNOWN); // 不可能的情况
break;
}
}
else
{ // 其它中断,不应该发生的情况
R8_USB_INT_FG = 0xFF; /* 清中断标志 */
}
mDelayuS(15);
} while(++TransRetry < 3);
return (ERR_USB_TRANSFER); // 应答超时
}
/*********************************************************************
* @fn HostCtrlTransfer
*
* @brief 执行控制传输,8字节请求码在pSetupReq中,DataBuf为可选的收发缓冲区
*
* @param DataBuf - 如果需要接收和发送数据,那么DataBuf需指向有效缓冲区用于存放后续数据
* @param RetLen - 实际成功收发的总长度保存在RetLen指向的字节变量中
*
* @return ERR_USB_BUF_OVER IN状态阶段出错
* ERR_SUCCESS 数据交换成功
*/
uint8_t HostCtrlTransfer(uint8_t *DataBuf, uint8_t *RetLen)
{
uint16_t RemLen = 0;
uint8_t s, RxLen, RxCnt, TxCnt;
uint8_t *pBuf;
uint8_t *pLen;
pBuf = DataBuf;
pLen = RetLen;
mDelayuS(200);
if(pLen)
{
*pLen = 0; // 实际成功收发的总长度
}
R8_UH_TX_LEN = sizeof(USB_SETUP_REQ);
s = USBHostTransact(USB_PID_SETUP << 4 | 0x00, 0x00, 200000 / 20); // SETUP阶段,200mS超时
if(s != ERR_SUCCESS)
{
return (s);
}
R8_UH_RX_CTRL = R8_UH_TX_CTRL = RB_UH_R_TOG | RB_UH_R_AUTO_TOG | RB_UH_T_TOG | RB_UH_T_AUTO_TOG; // 默认DATA1
R8_UH_TX_LEN = 0x01; // 默认无数据故状态阶段为IN
RemLen = pSetupReq->wLength;
PRINT("wLength: %x\n", RemLen);
if(RemLen && pBuf) // 需要收发数据
{
PRINT("bRequestType: %x\n", pSetupReq->bRequestType);
if(pSetupReq->bRequestType & USB_REQ_TYP_IN) // 收
{
while(RemLen)
{
mDelayuS(200);
s = USBHostTransact(USB_PID_IN << 4 | 0x00, R8_UH_RX_CTRL, 200000 / 20); // IN数据
if(s != ERR_SUCCESS)
{
return (s);
}
RxLen = R8_USB_RX_LEN < RemLen ? R8_USB_RX_LEN : RemLen;
RemLen -= RxLen;
if(pLen)
{
*pLen += RxLen; // 实际成功收发的总长度
}
for(RxCnt = 0; RxCnt != RxLen; RxCnt++)
{
*pBuf = pHOST_RX_RAM_Addr[RxCnt];
pBuf++;
}
if(R8_USB_RX_LEN == 0 || (R8_USB_RX_LEN & (UsbDevEndp0Size - 1)))
{
break; // 短包
}
}
R8_UH_TX_LEN = 0x00; // 状态阶段为OUT
}
else // 发
{
while(RemLen)
{
mDelayuS(200);
R8_UH_TX_LEN = RemLen >= UsbDevEndp0Size ? UsbDevEndp0Size : RemLen;
for(TxCnt = 0; TxCnt != R8_UH_TX_LEN; TxCnt++)
{
pHOST_TX_RAM_Addr[TxCnt] = *pBuf;
pBuf++;
}
s = USBHostTransact(USB_PID_OUT << 4 | 0x00, R8_UH_TX_CTRL, 200000 / 20); // OUT数据
if(s != ERR_SUCCESS)
{
return (s);
}
RemLen -= R8_UH_TX_LEN;
if(pLen)
{
*pLen += R8_UH_TX_LEN; // 实际成功收发的总长度
}
}
PRINT("Send: %d\n", *pLen);
// R8_UH_TX_LEN = 0x01; // 状态阶段为IN
}
}
mDelayuS(200);
s = USBHostTransact((R8_UH_TX_LEN ? USB_PID_IN << 4 | 0x00 : USB_PID_OUT << 4 | 0x00), RB_UH_R_TOG | RB_UH_T_TOG, 200000 / 20); // STATUS阶段
if(s != ERR_SUCCESS)
{
return (s);
}
if(R8_UH_TX_LEN == 0)
{
return (ERR_SUCCESS); // 状态OUT
}
if(R8_USB_RX_LEN == 0)
{
return (ERR_SUCCESS); // 状态IN,检查IN状态返回数据长度
}
return (ERR_USB_BUF_OVER); // IN状态阶段错误
}
/*********************************************************************
* @fn CopySetupReqPkg
*
* @brief 复制控制传输的请求包
*
* @param pReqPkt - 控制请求包地址
*
* @return none
*/
void CopySetupReqPkg(const uint8_t *pReqPkt) // 复制控制传输的请求包
{
uint8_t i;
for(i = 0; i != sizeof(USB_SETUP_REQ); i++)
{
((uint8_t *)pSetupReq)[i] = *pReqPkt;
pReqPkt++;
}
}
/*********************************************************************
* @fn CtrlGetDeviceDescr
*
* @brief 获取设备描述符,返回在 pHOST_TX_RAM_Addr 中
*
* @param none
*
* @return ERR_USB_BUF_OVER 描述符长度错误
* ERR_SUCCESS 成功
*/
uint8_t CtrlGetDeviceDescr(void)
{
uint8_t s;
uint8_t len;
UsbDevEndp0Size = DEFAULT_ENDP0_SIZE;
CopySetupReqPkg(SetupGetDevDescr);
s = HostCtrlTransfer(Com_Buffer, &len); // 执行控制传输
if(s != ERR_SUCCESS)
{
return (s);
}
UsbDevEndp0Size = ((PUSB_DEV_DESCR)Com_Buffer)->bMaxPacketSize0; // 端点0最大包长度,这是简化处理,正常应该先获取前8字节后立即更新UsbDevEndp0Size再继续
if(len < ((PUSB_SETUP_REQ)SetupGetDevDescr)->wLength)
{
return (ERR_USB_BUF_OVER); // 描述符长度错误
}
return (ERR_SUCCESS);
}
/*********************************************************************
* @fn CtrlGetConfigDescr
*
* @brief 获取配置描述符,返回在 pHOST_TX_RAM_Addr 中
*
* @param none
*
* @return ERR_USB_BUF_OVER 描述符长度错误
* ERR_SUCCESS 成功
*/
uint8_t CtrlGetConfigDescr(void)
{
uint8_t s;
uint8_t len;
CopySetupReqPkg(SetupGetCfgDescr);
s = HostCtrlTransfer(Com_Buffer, &len); // 执行控制传输
if(s != ERR_SUCCESS)
{
return (s);
}
if(len < ((PUSB_SETUP_REQ)SetupGetCfgDescr)->wLength)
{
return (ERR_USB_BUF_OVER); // 返回长度错误
}
len = ((PUSB_CFG_DESCR)Com_Buffer)->wTotalLength;
CopySetupReqPkg(SetupGetCfgDescr);
pSetupReq->wLength = len; // 完整配置描述符的总长度
s = HostCtrlTransfer(Com_Buffer, &len); // 执行控制传输
if(s != ERR_SUCCESS)
{
return (s);
}
#ifdef DISK_BASE_BUF_LEN
if(len > 64)
len = 64;
memcpy(TxBuffer, Com_Buffer, len); //U盘操作时需要拷贝到TxBuffer
#endif
return (ERR_SUCCESS);
}
/*********************************************************************
* @fn CtrlSetUsbAddress
*
* @brief 设置USB设备地址
*
* @param addr - 设备地址
*
* @return ERR_SUCCESS 成功
*/
uint8_t CtrlSetUsbAddress(uint8_t addr)
{
uint8_t s;
CopySetupReqPkg(SetupSetUsbAddr);
pSetupReq->wValue = addr; // USB设备地址
s = HostCtrlTransfer(NULL, NULL); // 执行控制传输
if(s != ERR_SUCCESS)
{
return (s);
}
SetHostUsbAddr(addr); // 设置USB主机当前操作的USB设备地址
mDelaymS(10); // 等待USB设备完成操作
return (ERR_SUCCESS);
}
/*********************************************************************
* @fn CtrlSetUsbConfig
*
* @brief 设置USB设备配置
*
* @param cfg - 配置值
*
* @return ERR_SUCCESS 成功
*/
uint8_t CtrlSetUsbConfig(uint8_t cfg)
{
CopySetupReqPkg(SetupSetUsbConfig);
pSetupReq->wValue = cfg; // USB设备配置
return (HostCtrlTransfer(NULL, NULL)); // 执行控制传输
}
/*********************************************************************
* @fn CtrlClearEndpStall
*
* @brief 清除端点STALL
*
* @param endp - 端点地址
*
* @return ERR_SUCCESS 成功
*/
uint8_t CtrlClearEndpStall(uint8_t endp)
{
CopySetupReqPkg(SetupClrEndpStall); // 清除端点的错误
pSetupReq->wIndex = endp; // 端点地址
return (HostCtrlTransfer(NULL, NULL)); // 执行控制传输
}
/*********************************************************************
* @fn CtrlSetUsbIntercace
*
* @brief 设置USB设备接口
*
* @param cfg - 配置值
*
* @return ERR_SUCCESS 成功
*/
uint8_t CtrlSetUsbIntercace(uint8_t cfg)
{
CopySetupReqPkg(SetupSetUsbInterface);
pSetupReq->wValue = cfg; // USB设备配置
return (HostCtrlTransfer(NULL, NULL)); // 执行控制传输
}
/*********************************************************************
* @fn USB_HostInit
*
* @brief USB主机功能初始化
*
* @param none
*
* @return none
*/
void USB_HostInit(void)
{
R8_USB_CTRL = RB_UC_HOST_MODE;
R8_UHOST_CTRL = 0;
R8_USB_DEV_AD = 0x00;
R8_UH_EP_MOD = RB_UH_EP_TX_EN | RB_UH_EP_RX_EN;
R16_UH_RX_DMA = (uint16_t)(uint32_t)pHOST_RX_RAM_Addr;
R16_UH_TX_DMA = (uint16_t)(uint32_t)pHOST_TX_RAM_Addr;
R8_UH_RX_CTRL = 0x00;
R8_UH_TX_CTRL = 0x00;
R8_USB_CTRL = RB_UC_HOST_MODE | RB_UC_INT_BUSY | RB_UC_DMA_EN;
R8_UH_SETUP = RB_UH_SOF_EN;
R8_USB_INT_FG = 0xFF;
DisableRootHubPort();
R8_USB_INT_EN = RB_UIE_TRANSFER | RB_UIE_DETECT;
FoundNewDev = 0;
}