USB中的SOF(Start Of Frame)包是USB开发中,经常接触也是很简单的一个概念: SOF由USB主机每1ms定时发出(FS),作用很多,相当于是一个时钟节拍基准,如果暂时用不到,就忽略也没有关系。 LPC5528的USB模块中,有一个FRAME_INT中断描述如下:
这个中断 ”感觉好像就是SOF中断”,似乎只是名字换成了FRAME_INT,在手册中的描述也和SOF中断几乎一样,但是手册里就是没有说它就是SOF中断。
经过小编实测和向同事确认,发现这个中断实际上并不完全等同于SOF中断,两者还是有一定区别的。本文就来探讨一下这个问题:
事情是这样的: 小编最近支持一个客户,客户的代码中涉及低功耗按键唤醒,USB Remote wakeup, 也需要用到SOF中断做为定时器来驱动上层app事件。
客户发现:当PC关机的时候,LPC5528被按键唤醒,唤醒后执行Remote Wakeup(实际就是MCU将USB总线设置为K states),因为这时候主机Host已经关机,USB总线上没有任何信号,永远维持的K states上,但是MCU却莫名其妙的进入了FRAME_INT中断,而且还是1ms的周期!
测试使用一个GPIO引脚——GPIO_SOF_EVT,每当进入FRAME_INT中断后,Toggle一次;测试波形如下图:
这有点奇怪了。。。USB总线上没有任何包发过来,但是还是会进FRAME_INT中断!难道FRAME_INT中断不是SOF中断?
结果确实是这样。。经过和同事确认,FRAME_INT中断确实不是SOF中断,它只是和SOF中断有点像而已。当VBUS没有掉电且MCU执行Remote wakeup(Resume)的时候, FEAME_INT还是会”如期而至”。。他和SOF包没有必然联系。。。 疑惑中
那么如果想用SOF中断咋办呢?有一个简单的办法:USB->INFO寄存器中的前11位为FRAME_NR,它记录了正确解码SOF的帧号,每当收到一个真正的SOF帧,FRAME_NR都会自加,所以在FRAME_INT中断中可以读入FRAME_NR来辅助判断,这次FRAME_INT到底是不是真正的SOF包到来:
代码如下所示:
补充:
小编同时也测试了HS-USB的FRAME_INT中断,其结论和FS是一样的,只不过HS的FRAME_INT中断是微帧,125us一次。
FRAME_INT中断在SDK中默认是关闭的,需要在INTEN寄存器中打开对应的标志位才可以使用。
到此为止,有必要进一步地思考一下,为什么这个USB的内部模块中,没有专门的SOF中断,却出现了这个与SOF有关,又不来源于SOF的FRAME_INT中断。
尽管没有与芯片设计人员沟通,但可以合理地推论,这个FRAME_INT中断是为SOF相关应用而设计的,之所以没有直接使用SOF作为触发源,是因为在USB主机休眠时,不再有SOF信号,而对于在主机休眠时仍需要周期中断源的USB应用而言,则需要使用其它定时器资源来实现相应功能,这样就会占用其它片上资源,又会增加软件调度的负担。
而在片内USB模块中,设计这样的机制,即可以在没有外部SOF信号时,继续维持周期性的中断,也可以在SOF信号恢复后,保持这个周期中断与SOF同步,即实现了SOF中断的功能,又兼顾了软件的实现与层次划分。
最后,这样的设计并不增加硬件的成本。
相关文章