USB做主机获取125us sof间隔方法
当MCU作为USB主机获取125微秒的SOF(Start Of Frame)间隔时,其主要作用是为高速(High-Speed)USB通信提供一个精确的时间基准和同步信号。这个基准主要用于保证实时性数据的同步传输、精准的带宽控制以及防止设备进入休眠状态。下表总结了它的几个核心应用场景:
| 应用场景 | 核心目的 | 关键机制 | 典型应用 |
|---|---|---|---|
| 精确的时间同步 | 让多个USB设备或MCU内部任务基于统一时钟工作 | 125µs SOF信号作为高精度“心跳” | 多声道音频同步采集/播放、多传感器数据融合 |
| 实时控制与定时 | 实现微秒级的精确周期性任务触发 | 利用SOF中断作为稳定的定时器源 | 电机控制、高频数据采集、实时控制系统 |
| 功耗管理(防止挂起) | 维持USB总线活跃,防止设备因无通信进入低功耗挂起状态 | 主机定期发送SOF包(即使无数据传输) | 需要随时唤醒的设备(如HID)、维持长连接的低功耗设备 |
| 传输调度与带宽控制 | 确保时间敏感型数据传输的实时性 | 主机在一个微帧(125µs)内规划并完成所有事务 | USB音频(同步传输)、视频(同步/批量传输) |
| 调试与时间标记 | 为总线事件提供精确的时间戳,便于分析 | 每个SOF包携带一个11位的帧编号,可用于标记事件发生的时刻 | USB协议分析、系统调试、性能优化 |
USBHOST主机的时基处理采取的是定时器125us区计时适配中断端点的binterval轮询,但是125us定时器计时开始时,与USB SOF包同步慢,有时候客户需要传输调度与带宽控制(此次传输时间大于下一个sof包的时间此次传输会被控制器放弃)。主机控制器可以在sof开始的时候然后做标记,开始做125us内会打断USB传输的操作,或者安排几次端点轮循访问。最大限度利用USB带宽并防止总线被打断。
方法一:开启USB SOF中断
配置:
void USBHS_Host_Init( FunctionalState sta )
{
if( sta )
{
/* Reset USB module */
USBHSH->CONTROL = USBHS_UC_CLR_ALL | USBHS_UC_RESET_SIE;
Delay_Us( 10 );
USBHSH->CONTROL = 0;
/* Initialize USB host configuration */
USBHSH->CONTROL = USBHS_UC_HOST_MODE | USBHS_UC_SPEED_HIGH | USBHS_UC_INT_BUSY | USBHS_UC_DMA_EN;
USBHSH->HOST_EP_CONFIG = USBHS_UH_EP_TX_EN | USBHS_UH_EP_RX_EN;
USBHSH->HOST_RX_DMA = (uint32_t)USBHS_RX_Buf;
USBHSH->HOST_TX_DMA = (uint32_t)USBHS_TX_Buf;
USBHSH->HOST_CTRL = USBHS_UH_PHY_SUSPENDM;
USBHSH->HOST_RX_MAX_LEN = USBHS_MAX_PACKET_SIZE;
USBHSD->INT_EN = USBHS_UIE_SOF_ACT;
NVIC_EnableIRQ( USBHS_IRQn );
}
else
{
USBHSH->CONTROL = USBHS_UC_CLR_ALL | USBHS_UC_RESET_SIE;
Delay_Us( 10 );
USBHSH->CONTROL = 0;
}
}
void USBHS_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void USBHS_IRQHandler( void )
{
uint8_t intflag, intst;
static uint16_t len;
intflag = USBHSD->INT_FG;
intst = USBHSD->INT_ST;
if( intflag & USBHS_UIF_HST_SOF )
{
len++;
USBHSD->INT_FG = USBHS_UIF_HST_SOF;
if(len==8000)
{
len=0;
printf("1stimeout\r\n");
}
}
USBHSD->INT_FG = intflag;
}

方法二:使用USB_FRAME_NO寄存器,非中断模式


while( 1 )
{
USBH_MainDeal( );
// if( RootHubDev[0].bStatus == ROOT_DEV_CONNECTED)
// {
// printf("1stimeout\r\n");
USB_FRAME_NO= (USBHSH->FRAME_NO>>13)&0x07;
if(LAST_USB_FRAME_NO-USB_FRAME_NO)
{
cunt++;
if(cunt==8000)
{
printf("1stimeout%d\r\n",(int8_t)(USB_FRAME_NO-LAST_USB_FRAME_NO));
cunt=0;
}
}
LAST_USB_FRAME_NO=USB_FRAME_NO;
// }
}
}
浙公网安备 33010602011771号