历史上的今天
返回首页

历史上的今天

今天是:2024年10月30日(星期三)

正在发生

2020年10月30日 | STM32 usb_pwr.c文件分析

2020-10-30 来源:eefocus

usb_pwr.c 这个文件看文件名就知道跟功耗有关了,有很多的状态:上电、掉电、挂起、恢复。


当首先是usb的上电和断电函数的定义了。


usb上电函数如下:

/*******************************************************************************

* Function Name  : PowerOn

* Description    : 上电

* Input          : None.

* Output         : None.

* Return         : USB_SUCCESS.

*******************************************************************************/

RESULT PowerOn(void)

{

  u16 wRegVal;


  USB_Cable_Config(ENABLE); //接上上拉电阻

  wRegVal = CNTR_FRES; //设置强制复位

  _SetCNTR(wRegVal);

  wInterrupt_Mask = 0; //先禁止所有的中断

  _SetCNTR(wInterrupt_Mask);

  _SetISTR(0); //清除所有的中断标志

  wInterrupt_Mask = CNTR_RESETM | CNTR_SUSPM | CNTR_WKUPM;

  _SetCNTR(wInterrupt_Mask);//再打开复位中断、挂起中断、唤醒中断屏蔽位


  return USB_SUCCESS;

}


上电的过程是:

1、当然接上D+或D-的上啦电阻,让主机可以识别到USB;

2、配置USB控制寄存器CNTR,是USB强制复位

3、打开复位中断、挂起中断、唤醒中断,其他中断屏蔽位则关闭


接下去是断电的函数定义:

/*******************************************************************************

* Function Name  : PowerOff

* Description    : 掉电

* Input          : None.

* Output         : None.

* Return         : USB_SUCCESS.

*******************************************************************************/

RESULT PowerOff()

{

  /* disable all ints and force USB reset */

  _SetCNTR(CNTR_FRES); //设置强制复位

  _SetISTR(0); //清除所有的中断标志

  USB_Cable_Config(DISABLE); //断开上拉电阻

  _SetCNTR(CNTR_FRES + CNTR_PDWN); //设置强制复位,并且进入断电模式


  return USB_SUCCESS;

}


掉电的过程很简单,先强制复位USB,并清除所有的中断标志,断开上拉电阻,并设置控制进入断电模式。


挂起也是USB的一种状态,所谓的挂起起始就是进入低功耗状态,一般的事情我不响应,除非有重要的事情我才唤醒处理。

/*******************************************************************************

* Function Name  : Suspend

* Description    : 挂起

* Input          : None.

* Output         : None.

* Return         : USB_SUCCESS.

*******************************************************************************/

void Suspend(void)

{

  u16 wCNTR;


  wCNTR = _GetCNTR();    //读取控制寄存器的值

  wCNTR |= CNTR_FSUSP;    //添加强制挂起标志

  _SetCNTR(wCNTR);    //进入挂起模式

  wCNTR = _GetCNTR();    //读取控制寄存器的值

  wCNTR |= CNTR_LPMODE;    //添加低功耗标志

  _SetCNTR(wCNTR);    //进入低功耗模式


  Enter_LowPowerMode();    //进入低功耗模式


}


进入挂起状态的过程跟我们平时进入中断服务函数的过程很像,当然要保护现场了。所以usb进入挂起状态,不改变控制寄存器原来的值,只是在原来的上面添加了挂起状态和低功耗状态标志而已。


说到挂起,当然有恢复了。首先的讲Resume_Init()这个函数:

/*******************************************************************************

* Function Name  : Resume_Init

* Description    : 处理唤醒恢复的函数

* Input          : None.

* Output         : None.

* Return         : USB_SUCCESS.

*******************************************************************************/

void Resume_Init(void)

{

  u16 wCNTR;


  wCNTR = _GetCNTR();

  wCNTR &= (~CNTR_LPMODE);  

  _SetCNTR(wCNTR); //进入非低功耗模式

  Leave_LowPowerMode(); //离开低功耗模式

  _SetCNTR(IMR_MSK); //打开使能全部中断


}


这个就是唤醒的函数了,比较简单,但是比较难理解的是恢复的各个状态。

typedef enum _RESUME_STATE

{

  RESUME_EXTERNAL,

  RESUME_INTERNAL,

  RESUME_LATER,

  RESUME_WAIT,

  RESUME_START,

  RESUME_ON,

  RESUME_OFF,

  RESUME_ESOF

} RESUME_STATE;


恢复有这么多的状态变化,当然有理由理解下各个状态了。

RESUME_EXTERNAL:个人理解,就想硬件复位一样,是通过某个物理硬件唤醒USB的

RESUME_INTERNAL:这个状态的唤醒应该就是软件唤醒之类的,比如收到某个中断

RESUME_LATER:表示待会儿唤醒,当然这里涉及到一个定时过程,定时时间到了在开始恢复

RESUME_WAIT:这个状态表示正在等待定时过程的结束

RESUME_START:表示USB开始要进行恢复了

RESUME_ON:表示即将恢复,该状态保持1毫秒~15ms内有效,主机就会对USB模块进行唤醒操作

RESUME_OFF:表示已经恢复完成了

RESUME_ESOF:个人理解表示,收到ESOF中断标志时,USB不允许进入挂起状态


 

各个状态之间的转化如下代码:

/*******************************************************************************

* Function Name  : Resume

* Description    :这是状态机处理恢复操作和时序。控制是基于Resume结构变量和

*   ESOF中断调用该子程序没有改变机状态。控制恢复的状态

* Input          : a state machine value (RESUME_STATE)

*                  RESUME_ESOF doesn't change ResumeS.eState allowing

*                  decrementing of the ESOF counter in different states.

* Output         : None.

* Return         : None.

*******************************************************************************/

void Resume(RESUME_STATE eResumeSetVal)  

{

  u16 wCNTR;


  if (eResumeSetVal != RESUME_ESOF) //如果不是ESOF中断导致的

    ResumeS.eState = eResumeSetVal; //ResumeS.eState设置为自己设定的值


  switch (ResumeS.eState)

  {

    case RESUME_EXTERNAL: //RESUME_EXTERNAL 外部恢复

      Resume_Init();

      ResumeS.eState = RESUME_OFF;

      break;

    case RESUME_INTERNAL: //RESUME_INTERNAL 内部恢复

      Resume_Init();

      ResumeS.eState = RESUME_START;

      break;

    case RESUME_LATER: //RESUME_LATER 定时恢复

      ResumeS.bESOFcnt = 2;

      ResumeS.eState = RESUME_WAIT;

      break;

    case RESUME_WAIT: //RESUME_WAIT  等待计时结束

      ResumeS.bESOFcnt--;

      if (ResumeS.bESOFcnt == 0)

        ResumeS.eState = RESUME_START;

      break;

    case RESUME_START: //RESUME_START 开始恢复

      wCNTR = _GetCNTR();

      wCNTR |= CNTR_RESUME;

      _SetCNTR(wCNTR); //设置唤醒请求位,将向PC主机发送唤醒请求

      ResumeS.eState = RESUME_ON;

      ResumeS.bESOFcnt = 10; //定时10ms,如果在这点时间内保持有效,主机将对USB模块进行唤醒操作

      break;

    case RESUME_ON: //RESUME_ON

      ResumeS.bESOFcnt--; //计时中

      if (ResumeS.bESOFcnt == 0) //计时时间到了

      {

        wCNTR = _GetCNTR();

        wCNTR &= (~CNTR_RESUME); //清除唤醒请求标志位

        _SetCNTR(wCNTR);

        ResumeS.eState = RESUME_OFF;

      }

      break;

    case RESUME_OFF:      //RESUME_OFF

    case RESUME_ESOF:      //RESUME_ESOF

    default:

      ResumeS.eState = RESUME_OFF;

      break;

  }

}


明显可以看到个状态的转化过程:

1、RESUME_EXTERNAL->RESUME_OFF

2、RESUME_INTERNAL->RESUME_START->RESUME_ON->RESUME_OFF

3、RESUME_WAIT->RESUME_START-> RESUME_ON-> RESUME_OFF

4、RESUME_ESOF->RESUME_OFF


推荐阅读

史海拾趣

C.K Magma公司的发展小趣事

随着技术的成熟,C.K Magma公司开始将产品推向市场。他们积极与各大电子厂商合作,为其提供高性能的半导体解决方案。同时,公司还注重品牌建设,通过参加行业展会、举办技术研讨会等方式,提升品牌知名度和影响力。随着市场份额的逐步扩大,C.K Magma公司逐渐在电子行业中树立起了自己的地位。

Eaton公司的发展小趣事

自1993年进入中国市场以来,伊顿公司凭借其先进的技术和丰富的经验,迅速在电网、石油化工、轨道交通、数据中心、商业楼宇等多个行业建立了市场地位。伊顿在中国的发展过程中,不仅带来了全球领先的产品和解决方案,还积极参与了本地市场的建设和创新。通过一系列的战略合作和收购活动,伊顿在中国市场的业务不断扩展,为中国经济和电气工业的发展做出了重要贡献。

Antex公司的发展小趣事

Antex公司始于1917年,当时它主要从事锻件的制造和销售。这一时期的Antex,凭借着对锻造技术的深入研究和不断创新,逐渐在电子行业中崭露头角。公司注重产品质量和客户需求,通过设计、锻造、机械加工、装配的一站式服务,赢得了客户的信赖。

Elekon Industries公司的发展小趣事

在快速发展的同时,Elekon也积极履行社会责任。公司注重环保和可持续发展,积极采用环保材料和绿色生产工艺,降低生产过程中的能耗和排放。此外,Elekon还积极参与环保公益活动,推动电子行业的绿色发展。这些举措不仅体现了Elekon的社会责任感,也为公司的长期发展奠定了坚实的基础。

请注意,以上故事均为虚构,旨在为您提供关于Elekon Industries公司发展起来的相关故事。如有需要,请参考公司官方发布的信息或相关新闻报道。

Carlisle Interconnect Components公司的发展小趣事

在追求经济效益的同时,Carlisle Interconnect Components公司也积极履行社会责任。公司注重环保和可持续发展,采用环保材料和生产工艺,减少对环境的影响。此外,公司还积极参与社会公益事业,为社会做出贡献。这种负责任的态度不仅赢得了社会各界的认可,更为公司的长远发展奠定了坚实的基础。

这五个故事展示了Carlisle Interconnect Components公司在电子行业中的发展历程和取得的成就。通过不断创新、品质管理、技术研发、战略合作以及履行社会责任等措施,公司逐渐在电子连接器领域树立起了自己的品牌形象和市场地位。

Heatron公司的发展小趣事

进入21世纪后,Heatron公司开始积极寻求国际合作机会,以进一步拓展其全球业务。公司先后与多个国家的知名企业建立了战略伙伴关系,共同开发新产品、新技术。通过资源共享和市场互补,Heatron不仅成功进入了多个新兴市场,还显著提升了其品牌在国际市场上的知名度和影响力。

问答坊 | AI 解惑

苹果iPod touch拆解分析

iPod touch播放器是苹果iPod家族系列中的最新一员。iPod Touch播放器与iPhone手机极为相似,被认为是“没有通话功能的iPhone”,另外,同iPhone相比,iPod Touch没有蓝牙功能。但是,iPhone手机用户的一些核心体验在iPod touch上都仍然保留,比如,iP ...…

查看全部问答>

在晒一块官方网上的开发板NXP LPC1768

  mbed NXP LPC1768     哈哈,这个按键太帅了,像颗宝石!…

查看全部问答>

SD卡保护

如何获取SD卡特征码? 现在SD卡都是当作存储介质用,其实据说它是有安全特征码的,不知道如何获取呢。…

查看全部问答>

Linux学习讨论,嵌入式开发,加群74459776

Linux学习讨论,嵌入式开发,加群74459776 请注意发色情内容、广告、诅咒类信息 踢!!! 看见请回复顶起!谢谢…

查看全部问答>

为什么在wince上无法用directdraw创建OFFSCREENPLAIN?

我要在一个板上用directdraw显示yuv图象,我是定制系统有把ddraw加到系统上, wince的例程能运行(ddex1,2 3都能运行,就那个蚊子没有什么动静),说明我的版是有支持ddraw. 但我在创建OFFSCREENPLAIN的时候,不能创建成功, 我参数设置如下:   &n ...…

查看全部问答>

提供一个汇编的集成环境MASM611

怎样安装到网上搜去(注意安装完了改那个后缀名,至于有些文档里说的改环境变量什么的,我觉得没有必要) 安装完注意的问题:调试的时候调试窗口不是自己写的源程序时 在编辑状态的点击OPTIONS--->Build OPTIONS在弹出的窗口选中use debug optio ...…

查看全部问答>

UIP学习笔记1

8962的开发板用FlashUserGet()函数并不能从内部得到MAC地址,所以在uip的例程里要直接赋值给ulUser0和ulUser1.为了方便和明显,我这里在FlashUserGet(&ulUser0, &ulUser1);这一语句之后直接设置MAC地址:    ulUser0=0xaaaaaa;&nbs ...…

查看全部问答>

万利的板子现在还能199买到吗?人在深圳。

                                 Re:…

查看全部问答>

运放输出稳定,AD采集结果向一个方向漂移

我用AD8551跨导方式放大光电二极管输出电流(I-V),用万用表检测AD8551输出端结果非常稳定,但是用MAX1304做AD采集,结果却一直向小的方向漂移,大约一个小时漂移10mv(8551输出3v左右时)。现在AD8551输出直接接了AD的输入端。原来曾试过加RC滤波 ...…

查看全部问答>